diff --git a/CHANGES.md b/CHANGES.md
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,7 +1,126 @@
 * Hackage: <http://hackage.haskell.org/package/sbv>
 * GitHub:  <http://leventerkok.github.com/sbv/>
 
-* Latest Hackage released version: 4.4, 2015-04-13
+* Latest Hackage released version: 5.0, 2015-09-22
+
+### 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
 
diff --git a/Data/SBV.hs b/Data/SBV.hs
--- a/Data/SBV.hs
+++ b/Data/SBV.hs
@@ -105,11 +105,7 @@
 -- get in touch if there is a solver you'd like to see included.
 ---------------------------------------------------------------------------------
 
-{-# LANGUAGE CPP                  #-}
 {-# LANGUAGE FlexibleInstances    #-}
-#if __GLASGOW_HASKELL__ < 710
-{-# LANGUAGE OverlappingInstances #-}
-#endif
 
 module Data.SBV (
   -- * Programming with symbolic values
@@ -128,18 +124,14 @@
   , SInteger
   -- *** IEEE-floating point numbers
   -- $floatingPoints
-  , SFloat, SDouble, RoundingFloat(..), RoundingMode(..), SRoundingMode, nan, infinity, sNaN, sInfinity, fusedMA
+  , SFloat, SDouble, IEEEFloating(..), IEEEFloatConvertable(..), RoundingMode(..), SRoundingMode, nan, infinity, sNaN, sInfinity
   -- **** Rounding modes
-  , sRoundNearestTiesToEven, sRoundNearestTiesToAway, sRoundTowardPositive, sRoundTowardNegative, sRoundTowardZero
-  -- **** FP classifiers
-  , isNormalFP, isSubnormalFP, isZeroFP, isInfiniteFP, isNaNFP, isNegativeFP, isPositiveFP, isNegativeZeroFP, isPositiveZeroFP, isPointFP
-  -- **** Conversion to and from Word32, Word64
-  , sWord32ToSFloat, sWord64ToSDouble, sFloatToSWord32, sDoubleToSWord64
-  -- **** Blasting floats to sign, exponent, mantissa bits
-  , blastSFloat, blastSDouble
+  , 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, sIntegerToSReal, fpToSReal, sRealToSFloat, sRealToSDouble
+  , SReal, AlgReal, sIntegerToSReal
   -- ** Creating a symbolic variable
   -- $createSym
   , sBool, sWord8, sWord16, sWord32, sWord64, sInt8, sInt16, sInt32, sInt64, sInteger, sReal, sFloat, sDouble
@@ -154,7 +146,8 @@
   , STree, readSTree, writeSTree, mkSTree
   -- ** Operations on symbolic values
   -- *** Word level
-  , sbvTestBit, sbvPopCount, sbvShiftLeft, sbvShiftRight, sbvRotateLeft, sbvRotateRight, sbvSignedShiftArithRight, setBitTo, oneIf, lsb, msb
+  , 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
@@ -165,14 +158,10 @@
   , blastBE, blastLE, FromBits(..)
   -- *** Splitting, joining, and extending
   , Splittable(..)
-  -- *** Sign-casting
-  , SignCast(..)
   -- ** Polynomial arithmetic and CRCs
   , Polynomial(..), crcBV, crc
   -- ** Conditionals: Mergeable values
-  , Mergeable(..), ite, iteLazy, sBranch
-  -- ** Conditional symbolic simulation
-  , sAssert, sAssertCont
+  , Mergeable(..), ite, iteLazy
   -- ** Symbolic equality
   , EqSymbolic(..)
   -- ** Symbolic ordering
@@ -187,6 +176,8 @@
   , 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
@@ -214,10 +205,6 @@
   -- ** Checking constraint vacuity
   , isVacuous, isVacuousWith
 
-  -- * Checking safety
-  -- $safeIntro
-  , safe, safeWith, SExecutable(..)
-
   -- * Proving properties using multiple solvers
   -- $multiIntro
   , proveWithAll, proveWithAny, satWithAll, satWithAny, allSatWithAll, allSatWithAny
@@ -235,7 +222,7 @@
 
   -- ** Inspecting proof results
   -- $resultTypes
-  , ThmResult(..), SatResult(..), AllSatResult(..), SMTResult(..), SafeResult(..)
+  , ThmResult(..), SatResult(..), AllSatResult(..), SMTResult(..)
 
   -- ** Programmable model extraction
   -- $programmableExtraction
@@ -296,9 +283,8 @@
 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.Rounding
-import Data.SBV.BitVectors.SignCast
 import Data.SBV.BitVectors.Splittable
 import Data.SBV.BitVectors.STree
 import Data.SBV.Compilers.C
@@ -316,52 +302,11 @@
 
 -- | The currently active solver, obtained by importing "Data.SBV".
 -- To have other solvers /current/, import one of the bridge
--- modules "Data.SBV.Bridge.CVC4", "Data.SBV.Bridge.Yices", or
--- "Data.SBV.Bridge.Z3" directly.
+-- 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
 
--- | Is the floating-point number a normal value. (i.e., not denormalized.)
-isNormalFP :: (RealFloat a, SymWord a) => SBV a -> SBool
-isNormalFP = liftFPPredicate "fp.isNormal" isNormalized
-  where isNormalized x = not (isDenormalized x || isInfinite x || isNaN x)
-
--- | Is the floating-point number a subnormal value. (Also known as denormal.)
-isSubnormalFP :: (RealFloat a, SymWord a) => SBV a -> SBool
-isSubnormalFP = liftFPPredicate "fp.isSubnormal" isDenormalized
-
--- | Is the floating-point number 0? (Note that both +0 and -0 will satisfy this predicate.)
-isZeroFP :: (Floating a, SymWord a) => SBV a -> SBool
-isZeroFP = liftFPPredicate "fp.isZero" (== 0)
-
--- | Is the floating-point number infinity? (Note that both +oo and -oo will satisfy this predicate.)
-isInfiniteFP :: (RealFloat a, SymWord a) => SBV a -> SBool
-isInfiniteFP = liftFPPredicate "fp.isInfinite" isInfinite
-
--- | Is the floating-point number a NaN value?
-isNaNFP :: (RealFloat a, SymWord a) => SBV a -> SBool
-isNaNFP = liftFPPredicate "fp.isNaN" isNaN
-
--- | Is the floating-point number negative? Note that -0 satisfies this predicate but +0 does not.
-isNegativeFP :: (RealFloat a, SymWord a) => SBV a -> SBool
-isNegativeFP = liftFPPredicate "fp.isNegative" (\x -> x < 0 ||       isNegativeZero x)
-
--- | Is the floating-point number positive? Note that +0 satisfies this predicate but -0 does not.
-isPositiveFP :: (RealFloat a, SymWord a) => SBV a -> SBool
-isPositiveFP = liftFPPredicate "fp.isPositive" (\x -> x >= 0 && not (isNegativeZero x))
-
--- | Is the floating point number -0?
-isNegativeZeroFP :: (RealFloat a, SymWord a) => SBV a -> SBool
-isNegativeZeroFP x = isZeroFP x &&& isNegativeFP x
-
--- | Is the floating point number +0?
-isPositiveZeroFP :: (RealFloat a, SymWord a) => SBV a -> SBool
-isPositiveZeroFP x = isZeroFP x &&& isPositiveFP x
-
--- | Is the floating-point number a regular floating point, i.e., not NaN, nor +oo, nor -oo. Normals or denormals are allowed.
-isPointFP :: (RealFloat a, SymWord a) => SBV a -> SBool
-isPointFP x = bnot (isNaNFP x ||| isInfiniteFP x)
-
 -- | Form the symbolic conjunction of a given list of boolean conditions. Useful in expressing
 -- problems with constraints, like the following:
 --
@@ -443,96 +388,45 @@
 class Equality a where
   (===) :: a -> a -> IO ThmResult
 
-instance
-#if __GLASGOW_HASKELL__ >= 710
- {-# OVERLAPPABLE #-}
-#endif
- (SymWord a, EqSymbolic z) => Equality (SBV a -> z) where
+instance {-# OVERLAPPABLE #-} (SymWord a, EqSymbolic z) => Equality (SBV a -> z) where
   k === l = prove $ \a -> k a .== l a
 
-instance
-#if __GLASGOW_HASKELL__ >= 710
- {-# OVERLAPPABLE #-}
-#endif
-
- (SymWord a, SymWord b, EqSymbolic z) => Equality (SBV a -> SBV b -> z) where
+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
-#if __GLASGOW_HASKELL__ >= 710
-  {-# OVERLAPPABLE #-}
-#endif
- (SymWord a, SymWord b, EqSymbolic z) => Equality ((SBV a, SBV b) -> z) where
+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
-#if __GLASGOW_HASKELL__ >= 710
- {-# OVERLAPPABLE #-}
-#endif
- (SymWord a, SymWord b, SymWord c, EqSymbolic z) => Equality (SBV a -> SBV b -> SBV c -> z) where
+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
-#if __GLASGOW_HASKELL__ >= 710
- {-# OVERLAPPABLE #-}
-#endif
- (SymWord a, SymWord b, SymWord c, EqSymbolic z) => Equality ((SBV a, SBV b, SBV c) -> z) where
+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
-#if __GLASGOW_HASKELL__ >= 710
- {-# OVERLAPPABLE #-}
-#endif
- (SymWord a, SymWord b, SymWord c, SymWord d, EqSymbolic z) => Equality (SBV a -> SBV b -> SBV c -> SBV d -> z) where
+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
-#if __GLASGOW_HASKELL__ >= 710
- {-# OVERLAPPABLE #-}
-#endif
- (SymWord a, SymWord b, SymWord c, SymWord d, EqSymbolic z) => Equality ((SBV a, SBV b, SBV c, SBV d) -> z) where
+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
-#if __GLASGOW_HASKELL__ >= 710
- {-# OVERLAPPABLE #-}
-#endif
- (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
+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
-#if __GLASGOW_HASKELL__ >= 710
- {-# OVERLAPPABLE #-}
-#endif
- (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
+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
-#if __GLASGOW_HASKELL__ >= 710
- {-# OVERLAPPABLE #-}
-#endif
- (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
+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
-#if __GLASGOW_HASKELL__ >= 710
- {-# OVERLAPPABLE #-}
-#endif
+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
-#if __GLASGOW_HASKELL__ >= 710
- {-# OVERLAPPABLE #-}
-#endif
+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
-#if __GLASGOW_HASKELL__ >= 710
- {-# OVERLAPPABLE #-}
-#endif
- (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
+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
@@ -592,46 +486,6 @@
 used as the first argument to all these functions, if you simply want to try all available solvers on a machine.
 -}
 
-{- $safeIntro
-
-The 'sAssert' and 'sAssertCont' functions allow users to introduce invariants through-out their code 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 then 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 it's
-first argument to be larger than the second:
-
->>> let sub x y = sAssert "sub: x >= y must hold!" (x .>= y) (x - y)
-
-Clearly, this function is not safe, as there's nothing that ensures us to pass a larger second argument.
-If we try to prove a theorem regarding sub, we'll get an exception:
-
->>> prove $ \x y -> sub x y .>= (0 :: SInt16)
-*** Exception: Assertion failure: "sub: x >= y must hold!"
-  s0 = -32768 :: Int16
-  s1 = -32767 :: Int16
-
-Of course, we can use, 'safe' to statically see if such a violation is possible before we attempt a proof:
-
->>> safe (sub :: SInt8 -> SInt8 -> SInt8)
-Assertion failure: "sub: x >= y must hold!"
-  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) (sub y x)
-
-Clearly, 'safeSub' must be safe. And indeed, SBV can prove that:
-
->>> safe (safeSub :: SInt8 -> SInt8 -> SInt8)
-No safety 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.
--}
-
 {- $optimizeIntro
 Symbolic optimization. A call of the form:
 
@@ -653,14 +507,26 @@
 
 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))@
+   @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.) 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 find solutions where there is no global optimum value, while the iterative version would simply loop forever
-in such cases. On the other hand, the iterative version might be more suitable if the quantified version of the problem is too hard to deal with by the SMT solver.
+'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
@@ -851,19 +717,10 @@
 following example demonstrates:
 
   @
-     data B = B () deriving (Eq, Ord, Data, Typeable, Read, Show)
-     instance SymWord  B
-     instance HasKind  B
-     instance SatModel B  -- required only if 'getModel' etc. is used.
+     data B = B () deriving (Eq, Ord, Show, Read, Data, SymWord, HasKind, SatModel)
   @
 
-(Note that you'll also need to use the language pragma @DeriveDataTypeable@, and import @Data.Generics@ for the above to work.) 
-
-Once GHC implements derivable user classes (<http://hackage.haskell.org/trac/ghc/ticket/5462>), we will be able to simplify this to:
-
-  @
-     data B = B () deriving (Eq, Ord, Data, Typeable, Read, Show, SymWord, HasKind)
-  @
+(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.
@@ -877,10 +734,7 @@
 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, Data, Typeable, Read, Show)
-    instance SymWord X
-    instance HasKind X
-    instance SatModel X
+    data X = A | B | C deriving (Eq, Ord, Show, Read, Data, SymWord, HasKind, SatModel)
   @
 
 Now, the user can define
diff --git a/Data/SBV/BitVectors/AlgReals.hs b/Data/SBV/BitVectors/AlgReals.hs
--- a/Data/SBV/BitVectors/AlgReals.hs
+++ b/Data/SBV/BitVectors/AlgReals.hs
@@ -125,8 +125,10 @@
   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
-  (/)          = lift2 "/" (/)
+  (AlgRational True _) / (AlgRational True b) | b == 0 = 0
+  a                    / b                             = lift2 "/" (/) a b
   fromRational = AlgRational True
 
 instance Real AlgReal where
diff --git a/Data/SBV/BitVectors/Data.hs b/Data/SBV/BitVectors/Data.hs
--- a/Data/SBV/BitVectors/Data.hs
+++ b/Data/SBV/BitVectors/Data.hs
@@ -17,46 +17,43 @@
 {-# LANGUAGE PatternGuards         #-}
 {-# LANGUAGE DefaultSignatures     #-}
 {-# LANGUAGE NamedFieldPuns        #-}
-{-# LANGUAGE CPP                   #-}
 
 module Data.SBV.BitVectors.Data
  ( SBool, SWord8, SWord16, SWord32, SWord64
  , SInt8, SInt16, SInt32, SInt64, SInteger, SReal, SFloat, SDouble
- , nan, infinity, sNaN, sInfinity, RoundingMode(..), SRoundingMode, smtLibSquareRoot, smtLibFusedMA
+ , nan, infinity, sNaN, sInfinity, RoundingMode(..), SRoundingMode
  , sRoundNearestTiesToEven, sRoundNearestTiesToAway, sRoundTowardPositive, sRoundTowardNegative, sRoundTowardZero
+ , sRNE, sRNA, sRTP, sRTN, sRTZ
  , SymWord(..)
  , CW(..), CWVal(..), AlgReal(..), cwSameType, cwIsBit, cwToBool
  , mkConstCW ,liftCW2, mapCW, mapCW2
  , SW(..), trueSW, falseSW, trueCW, falseCW, normCW
  , SVal(..)
  , SBV(..), NodeId(..), mkSymSBV
- , ArrayContext(..), ArrayInfo, SymArray(..), SFunArray(..), mkSFunArray, SArray(..), arrayUIKind
+ , ArrayContext(..), ArrayInfo, SymArray(..), SFunArray(..), mkSFunArray, SArray(..)
  , sbvToSW, sbvToSymSW, forceSWArg
  , SBVExpr(..), newExpr
  , cache, Cached, uncache, uncacheAI, HasKind(..)
- , Op(..), NamedSymVar, UnintKind(..), getTableIndex, SBVPgm(..), Symbolic, SExecutable(..), runSymbolic, runSymbolic', State, getPathCondition, extendPathCondition
+ , Op(..), FPOp(..), NamedSymVar, getTableIndex
+ , SBVPgm(..), Symbolic, runSymbolic, runSymbolic', State, getPathCondition, extendPathCondition
  , inProofMode, SBVRunMode(..), Kind(..), Outputtable(..), Result(..)
  , Logic(..), SMTLibLogic(..)
  , getTraceInfo, getConstraints, addConstraint
- , SBVType(..), newUninterpreted, unintFnUIKind, addAxiom
+ , SBVType(..), newUninterpreted, addAxiom
  , Quantifier(..), needsExistentials
- , SMTLibPgm(..), SMTLibVersion(..)
+ , SMTLibPgm(..), SMTLibVersion(..), smtLibVersionExtension
  , SolverCapabilities(..)
  , extractSymbolicSimulationState
  , SMTScript(..), Solver(..), SMTSolver(..), SMTResult(..), SMTModel(..), SMTConfig(..), getSBranchRunConfig
  , declNewSArray, declNewSFunArray
  ) where
 
-#if __GLASGOW_HASKELL__ < 710
-import Control.Applicative  ((<$>))
-#endif
-
 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            (intercalate, elemIndex)
+import Data.List            (elemIndex)
 import Data.Maybe           (fromMaybe)
 
 import qualified Data.Generics as G    (Data(..))
@@ -239,6 +236,26 @@
 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
@@ -494,100 +511,3 @@
 
 instance NFData a => 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 NFData a => 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 (NFData a, SymWord a) => 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
new file mode 100644
--- /dev/null
+++ b/Data/SBV/BitVectors/Floating.hs
@@ -0,0 +1,416 @@
+-----------------------------------------------------------------------------
+-- |
+-- 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              = lift2  FP_Min             (Just fpMinH)             Nothing
+  fpMax              = lift2  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, Floating 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, Floating 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, Floating 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, Floating 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, Floating 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, Floating 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, Floating 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 a 2 arg FP-op, producing bool
+lift2B :: (SymWord a, Floating 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, Floating 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)
+
+-- | Relationally assert the equivalence between an 'SFloat' and an 'SWord32', when the bit-pattern
+-- is interpreted as either type. Useful when analyzing components of a floating point number. Note
+-- that this cannot be written as a function, since IEEE754 NaN values are not unique. That is,
+-- given a float, there isn't a unique sign/mantissa/exponent that we can match it to.
+--
+-- The use case would be code of the form:
+--
+-- @
+--     do w <- free_
+--        constrain $ sFloatToSWord32 f w
+--        ...
+-- @
+--
+-- At which point the variable @w@ can be used to access the bits of the float 'f'.
+sFloatAsSWord32 :: SFloat -> SWord32 -> SBool
+sFloatAsSWord32 fVal wVal
+  | Just f <- unliteral fVal, not (isNaN f) = wVal .== literal (DB.floatToWord f)
+  | True                                    = fVal `fpIsEqualObject` sWord32AsSFloat wVal
+
+-- | Relationally assert the equivalence between an 'SDouble' and an 'SWord64', when the bit-pattern
+-- is interpreted as either type. See the comments for 'sFloatToSWord32' for details.
+sDoubleAsSWord64 :: SDouble -> SWord64 -> SBool
+sDoubleAsSWord64 fVal wVal
+  | Just f <- unliteral fVal, not (isNaN f) = wVal .== literal (DB.doubleToWord f)
+  | True                                    = fVal `fpIsEqualObject` sWord64AsSDouble wVal
+
+-- | Relationally extract the sign\/exponent\/mantissa of a single-precision float. Due to the
+-- non-unique representation of NaN's, we have to do this relationally, much like
+-- 'sFloatAsSWord32'.
+blastSFloat :: SFloat -> (SBool, [SBool], [SBool]) -> SBool
+blastSFloat fVal (s, expt, mant)
+  | length expt /= 8 || length mant /= 23  = error "SBV.blastSFloat: Need 8-bit expt and 23 bit mantissa"
+  | True                                   = sFloatAsSWord32 fVal wVal
+ where bits = s : expt ++ mant
+       wVal = sum [ite b (2^c) 0 | (b, c) <- zip bits (reverse [(0::Word32) .. 31])]
+
+-- | Relationally extract the sign\/exponent\/mantissa of a double-precision float. Due to the
+-- non-unique representation of NaN's, we have to do this relationally, much like
+-- 'sDoubleAsSWord64'.
+blastSDouble :: SDouble -> (SBool, [SBool], [SBool]) -> SBool
+blastSDouble fVal (s, expt, mant)
+  | length expt /= 11 || length mant /= 52 = error "SBV.blastSDouble: Need 11-bit expt and 52 bit mantissa"
+  | True                                   = sDoubleAsSWord64 fVal wVal
+ where bits = s : expt ++ mant
+       wVal = sum [ite b (2^c) 0 | (b, c) <- zip bits (reverse [(0::Word64) .. 63])]
+
+-- | 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/Model.hs b/Data/SBV/BitVectors/Model.hs
--- a/Data/SBV/BitVectors/Model.hs
+++ b/Data/SBV/BitVectors/Model.hs
@@ -10,7 +10,6 @@
 -----------------------------------------------------------------------------
 
 {-# OPTIONS_GHC -fno-warn-orphans   #-}
-{-# LANGUAGE CPP                    #-}
 {-# LANGUAGE TypeSynonymInstances   #-}
 {-# LANGUAGE BangPatterns           #-}
 {-# LANGUAGE PatternGuards          #-}
@@ -22,23 +21,23 @@
 
 module Data.SBV.BitVectors.Model (
     Mergeable(..), EqSymbolic(..), OrdSymbolic(..), SDivisible(..), Uninterpreted(..), SIntegral
-  , ite, iteLazy, sBranch, sAssert, sAssertCont, sbvTestBit, sbvPopCount, setBitTo
-  , sbvShiftLeft, sbvShiftRight, sbvRotateLeft, sbvRotateRight, sbvSignedShiftArithRight, (.^)
+  , 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
-  , sIntegerToSReal, fpToSReal, sRealToSFloat, sRealToSDouble
-  , sWord32ToSFloat, sWord64ToSDouble, sFloatToSWord32, sDoubleToSWord64, blastSFloat, blastSDouble
-  , fusedMA, liftFPPredicate
+  , sIntegerToSReal, label
   , liftQRem, liftDMod, symbolicMergeWithKind
   , genLiteral, genFromCW, genMkSymVar
-  , reduceInPathCondition
+  , isSatisfiableInCurrentPath
   )
   where
 
-import Control.Monad   (when, liftM)
+import Control.Monad        (when, liftM)
+import Control.Monad.Reader (ask)
+import Control.Monad.Trans  (liftIO)
 
 import Data.Array      (Array, Ix, listArray, elems, bounds, rangeSize)
 import Data.Bits       (Bits(..))
@@ -47,12 +46,6 @@
 import Data.Maybe      (fromMaybe)
 import Data.Word       (Word8, Word16, Word32, Word64)
 
-import Data.Binary.IEEE754 (wordToFloat, wordToDouble, floatToWord, doubleToWord)
-
-import qualified Data.Map as M
-
-import qualified Control.Exception as C
-
 import Test.QuickCheck                           (Testable(..), Arbitrary(..))
 import qualified Test.QuickCheck         as QC   (whenFail)
 import qualified Test.QuickCheck.Monadic as QC   (monadicIO, run)
@@ -62,8 +55,8 @@
 import Data.SBV.BitVectors.Data
 import Data.SBV.Utils.Boolean
 
-import Data.SBV.Provers.Prover (isSBranchFeasibleInState, isConditionSatisfiable, isVacuous, prove, defaultSMTCfg)
-import Data.SBV.SMT.SMT (SafeResult(..), SatResult(..), ThmResult, getModelDictionary)
+import Data.SBV.Provers.Prover (isVacuous, prove, defaultSMTCfg, internalSATCheck)
+import Data.SBV.SMT.SMT        (ThmResult, SatResult(..))
 
 import Data.SBV.BitVectors.Symbolic
 import Data.SBV.BitVectors.Operations
@@ -72,11 +65,7 @@
 -- 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
-#if __GLASGOW_HASKELL__ >= 708
-ghcBitSize x = maybe (error "SBV.ghcBitSize: Unexpected non-finite usage!") id (bitSizeMaybe x)
-#else
-ghcBitSize = bitSize
-#endif
+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)
@@ -108,6 +97,10 @@
 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)
@@ -304,105 +297,17 @@
   | Just i <- unliteral x = literal $ fromInteger i
   | True                  = SBV (SVal KReal (Right (cache y)))
   where y st = do xsw <- sbvToSW st x
-                  newExpr st KReal (SBVApp (Uninterpreted "to_real") [xsw])
-
--- | Promote an SFloat/SDouble to an SReal
-fpToSReal :: (Real a, Floating a, SymWord a) => SBV a -> SReal
-fpToSReal x
-  | Just i <- unliteral x = literal $ fromRational $ toRational i
-  | True                  = SBV (SVal KReal (Right (cache y)))
-  where y st = do xsw <- sbvToSW st x
-                  newExpr st KReal (SBVApp (Uninterpreted "fp.to_real") [xsw])
-
--- | Promote (demote really) an SReal to an SFloat.
---
--- NB: This function doesn't work on concrete values at the Haskell
--- level since we have no easy way of honoring the rounding-mode given.
-sRealToSFloat :: SRoundingMode -> SReal -> SFloat
-sRealToSFloat rm x = SBV (SVal KFloat (Right (cache y)))
-  where y st = do swm <- sbvToSW st rm
-                  xsw <- sbvToSW st x
-                  newExpr st KFloat (SBVApp (FPRound "(_ to_fp 8 24)") [swm, xsw])
-
--- | Promote (demote really) an SReal to an SDouble.
---
--- NB: This function doesn't work on concrete values at the Haskell
--- level since we have no easy way of honoring the rounding-mode given.
-sRealToSDouble :: SRoundingMode -> SReal -> SFloat
-sRealToSDouble rm x = SBV (SVal KFloat (Right (cache y)))
-  where y st = do swm <- sbvToSW st rm
-                  xsw <- sbvToSW st x
-                  newExpr st KDouble (SBVApp (FPRound "(_ to_fp 11 53)") [swm, xsw])
-
--- | Reinterpret a 32-bit word as an 'SFloat'.
-sWord32ToSFloat :: SWord32 -> SFloat
-sWord32ToSFloat x
-    | Just w <- unliteral x = literal (wordToFloat w)
-    | True                  = SBV (SVal KFloat (Right (cache y)))
-   where y st = do xsw <- sbvToSW st x
-                   newExpr st KFloat (SBVApp (FPRound "(_ to_fp 8 24)") [xsw])
-
--- | Reinterpret a 64-bit word as an 'SDouble'. Note that this function does not
--- directly work on concrete values, since IEEE754 NaN values are not unique, and
--- thus do not directly map to SDouble
-sWord64ToSDouble :: SWord64 -> SDouble
-sWord64ToSDouble x
-    | Just w <- unliteral x = literal (wordToDouble w)
-    | True                  = SBV (SVal KDouble (Right (cache y)))
-   where y st = do xsw <- sbvToSW st x
-                   newExpr st KDouble (SBVApp (FPRound "(_ to_fp 11 53)") [xsw])
-
--- | Relationally assert the equivalence between an 'SFloat' and an 'SWord32', when the bit-pattern
--- is interpreted as either type. Useful when analyzing components of a floating point number. Note
--- that this cannot be written as a function, since IEEE754 NaN values are not unique. That is,
--- given a float, there isn't a unique sign/mantissa/exponent that we can match it to.
---
--- The use case would be code of the form:
---
--- @
---     do w <- free_
---        constrain $ sFloatToSWord32 f w
---        ...
--- @
---
--- At which point the variable @w@ can be used to access the bits of the float 'f'.
-sFloatToSWord32 :: SFloat -> SWord32 -> SBool
-sFloatToSWord32 fVal wVal
-  | Just f <- unliteral fVal, not (isNaN f) = wVal .== literal (floatToWord f)
-  | True                                    = result `is` fVal
- where result   = sWord32ToSFloat wVal
-       a `is` b = (checkNaN a &&& checkNaN b) ||| (a .== b)
-       checkNaN = liftFPPredicate "fp.isNaN" isNaN
-
--- | Relationally assert the equivalence between an 'SDouble' and an 'SWord64', when the bit-pattern
--- is interpreted as either type. See the comments for 'sFloatToSWord32' for details.
-sDoubleToSWord64 :: SDouble -> SWord64 -> SBool
-sDoubleToSWord64 fVal wVal
-  | Just f <- unliteral fVal, not (isNaN f) = wVal .== literal (doubleToWord f)
-  | True                                    = result `is` fVal
- where result   = sWord64ToSDouble wVal
-       a `is` b = (checkNaN a &&& checkNaN b) ||| (a .== b)
-       checkNaN = liftFPPredicate "fp.isNaN" isNaN
-
--- | Relationally extract the sign\/exponent\/mantissa of a single-precision float. Due to the
--- non-unique representation of NaN's, we have to do this function relationally, much like
--- 'sFloatToSWord32'.
-blastSFloat :: SFloat -> (SBool, [SBool], [SBool]) -> SBool
-blastSFloat fVal (s, expt, mant)
-  | length expt /= 8 || length mant /= 23  = error "SBV.blastSFloat: Need 8-bit expt and 23 bit mantissa"
-  | True                                   = sFloatToSWord32 fVal wVal
- where bits = s : expt ++ mant
-       wVal = sum [ite b (2^c) 0 | (b, c) <- zip bits (reverse [(0::Word32) .. 31])]
+                  newExpr st KReal (SBVApp (IntCast KUnbounded KReal) [xsw])
 
--- | Relationally extract the sign\/exponent\/mantissa of a double-precision float. Due to the
--- non-unique representation of NaN's, we have to do this function relationally, much like
--- 'sDoubleToSWord64'.
-blastSDouble :: SDouble -> (SBool, [SBool], [SBool]) -> SBool
-blastSDouble fVal (s, expt, mant)
-  | length expt /= 11 || length mant /= 52 = error "SBV.blastSDouble: Need 11-bit expt and 52 bit mantissa"
-  | True                                   = sDoubleToSWord64 fVal wVal
- where bits = s : expt ++ mant
-       wVal = sum [ite b (2^c) 0 | (b, c) <- zip bits (reverse [(0::Word64) .. 63])]
+-- | 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 :: (HasKind a, 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.
@@ -573,13 +478,13 @@
 
 -- | Returns (symbolic) true if all the elements of the given list are different.
 allDifferent :: EqSymbolic a => [a] -> SBool
-allDifferent (x:xs@(_:_)) = bAll (x ./=) xs &&& allDifferent xs
-allDifferent _            = true
+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 (x:xs@(_:_))     = bAll (x .==) xs
-allEqual _                = true
+allEqual []     = true
+allEqual (x:xs) = bAll (x .==) xs
 
 -- | Returns (symbolic) true if the argument is in range
 inRange :: OrdSymbolic a => a -> (a, a) -> SBool
@@ -615,12 +520,15 @@
   -- 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
-    | hasSign a = ite (a .<  z) (-i) (ite (a .== z) z i)
-    | True      = ite (a ./= z) i    z
+    -- 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
-  -- just cannot rely on its default definition; which would be 0-0, which is not -0!
+  -- 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.
@@ -633,8 +541,20 @@
                                         (iterate (\x -> x*x) b)
 
 instance (SymWord a, Fractional a) => Fractional (SBV a) where
-  fromRational = literal . fromRational
-  SBV x / SBV y = SBV (svDivide x y)
+  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.
@@ -643,7 +563,7 @@
     pi      = literal pi
     exp     = lift1FNS "exp"     exp
     log     = lift1FNS "log"     log
-    sqrt    = lift1F   sqrt      smtLibSquareRoot
+    sqrt    = lift1F   FP_Sqrt   sqrt
     sin     = lift1FNS "sin"     sin
     cos     = lift1FNS "cos"     cos
     tan     = lift1FNS "tan"     tan
@@ -659,36 +579,17 @@
     (**)    = lift2FNS "**"      (**)
     logBase = lift2FNS "logBase" logBase
 
--- | Lift an FP predicate as defined by SMT-Lib to the world of SFloat and SDoubles.
-liftFPPredicate :: (Floating a, SymWord a) => String -> (a -> Bool) -> SBV a -> SBool
-liftFPPredicate nm 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 (Uninterpreted nm) [swa])
-
--- | Fused-multiply add. @fusedMA a b c = a * b + c@, for double and floating point values.
--- Note that a 'fusedMA' call will *never* be concrete, even if all the arguments are constants; since
--- we cannot guarantee the precision requirements, which is the whole reason why 'fusedMA' exists in the
--- first place. (NB. 'fusedMA' only rounds once, even though it does two operations, and hence the extra
--- precision.)
-fusedMA :: (SymWord a, Floating a) => SBV a -> SBV a -> SBV a -> SBV a
-fusedMA a b c = 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
-                  newExpr st k (SBVApp smtLibFusedMA [swa, swb, swc])
-
--- | Lift a float/double unary function, using a corresponding function in SMT-lib. We piggy-back on the uninterpreted
--- function mechanism here, as it essentially is the same as introducing this as a new function.
-lift1F :: (SymWord a, Floating a) => (a -> a) -> Op -> SBV a -> SBV a
-lift1F f smtOp sv
-  | Just v <- unliteral sv = literal $ f v
-  | True                   = SBV $ SVal k $ Right $ cache c
-  where k = kindOf sv
-        c st = do swa <- sbvToSW st sv
-                  newExpr st k (SBVApp smtOp [swa])
+-- | Lift a 1 arg FP-op, using sRNE default
+lift1F :: (SymWord a, Floating 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
@@ -706,51 +607,57 @@
 -- 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)
+  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
-#if __GLASGOW_HASKELL__ >= 708
-  bitSizeMaybe x = Just $ intSizeOf x
-#endif
-  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)
+  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 sbvTestBit instead."
+    | 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 sbvPopCount instead."
+    | 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.
-sbvTestBit :: (Num a, Bits a, SymWord a) => SBV a -> Int -> SBool
-sbvTestBit (SBV x) i = SBV (svTestBit x i)
+sTestBit :: (Num a, Bits a, SymWord a) => SBV a -> Int -> SBool
+sTestBit (SBV x) i = SBV (svTestBit x i)
 
+-- | Variant of 'sTestBit', where we want to extract multiple bit positions.
+sExtractBits :: (Num a, Bits a, SymWord a) => 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 'sbvPopCount' for unbounded symbolic integers,
+-- 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.
-sbvPopCount :: (Num a, Bits a, SymWord a) => SBV a -> SWord8
-sbvPopCount x
-  | isReal x          = error "SBV.sbvPopCount: Called on a real value"
+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.sbvPopCount: Called on an infinite precision symbolic value"
+  | 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
@@ -762,12 +669,27 @@
 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, Bits a, SymWord a, HasKind b, Num b, Bits 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 (IntCast 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 shift amount must be an unsigned quantity.
-sbvShiftLeft :: (SIntegral a, SIntegral b) => SBV a -> SBV b -> SBV a
-sbvShiftLeft x i
-  | isSigned i = error "sbvShiftLeft: shift amount should be unsigned"
+sShiftLeft :: (SIntegral a, SIntegral b) => SBV a -> SBV b -> SBV a
+sShiftLeft x i
+  | isSigned i = error "sShiftLeft: shift amount should be unsigned"
   | True       = select [x `shiftL` k | k <- [0 .. ghcBitSize x - 1]] z i
   where z = genLiteral (kindOf x) (0::Integer)
 
@@ -776,33 +698,33 @@
 -- a symbolic amount to shift with. The shift amount must be an unsigned quantity.
 --
 -- NB. If the shiftee is signed, then this is an arithmetic shift; otherwise it's logical,
--- following the usual Haskell convention. See 'sbvSignedShiftArithRight' for a variant
+-- following the usual Haskell convention. See 'sSignedShiftArithRight' for a variant
 -- that explicitly uses the msb as the sign bit, even for unsigned underlying types.
-sbvShiftRight :: (SIntegral a, SIntegral b) => SBV a -> SBV b -> SBV a
-sbvShiftRight x i
-  | isSigned i = error "sbvShiftRight: shift amount should be unsigned"
+sShiftRight :: (SIntegral a, SIntegral b) => SBV a -> SBV b -> SBV a
+sShiftRight x i
+  | isSigned i = error "sShiftRight: shift amount should be unsigned"
   | True       = 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 'sbvShiftRight' when the argument is signed. However, if the argument is unsigned,
+-- 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.
-sbvSignedShiftArithRight:: (SIntegral a, SIntegral b) => SBV a -> SBV b -> SBV a
-sbvSignedShiftArithRight x i
-  | isSigned i = error "sbvSignedShiftArithRight: shift amount should be unsigned"
-  | isSigned x = sbvShiftRight x i
+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 (sbvShiftRight (complement x) i))
-                     (sbvShiftRight x i)
+                     (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 shift amount must be an unsigned quantity.
-sbvRotateLeft :: (SIntegral a, SIntegral b, SDivisible (SBV b)) => SBV a -> SBV b -> SBV a
-sbvRotateLeft x i
-  | isSigned i             = error "sbvRotateLeft: rotation amount should be unsigned"
+sRotateLeft :: (SIntegral a, SIntegral b, SDivisible (SBV b)) => SBV a -> SBV b -> SBV a
+sRotateLeft x i
+  | isSigned i             = error "sRotateLeft: rotation amount should be unsigned"
   | bit si <= toInteger sx = select [x `rotateL` k | k <- [0 .. bit si - 1]] z i         -- wrap-around not possible
   | True                   = select [x `rotateL` k | k <- [0 .. sx     - 1]] z (i `sRem` n)
     where sx = ghcBitSize x
@@ -813,9 +735,9 @@
 -- | 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 shift amount must be an unsigned quantity.
-sbvRotateRight :: (SIntegral a, SIntegral b, SDivisible (SBV b)) => SBV a -> SBV b -> SBV a
-sbvRotateRight x i
-  | isSigned i             = error "sbvRotateRight: rotation amount should be unsigned"
+sRotateRight :: (SIntegral a, SIntegral b, SDivisible (SBV b)) => SBV a -> SBV b -> SBV a
+sRotateRight x i
+  | isSigned i             = error "sRotateRight: rotation amount should be unsigned"
   | bit si <= toInteger sx = select [x `rotateR` k | k <- [0 .. bit si - 1]] z i         -- wrap-around not possible
   | True                   = select [x `rotateR` k | k <- [0 .. sx     - 1]] z (i `sRem` n)
     where sx = ghcBitSize x
@@ -857,7 +779,7 @@
 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 (sbvTestBit x) [0 .. intSizeOf x - 1]
+ | 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]
@@ -865,14 +787,14 @@
 
 -- | Least significant bit of a word, always stored at index 0.
 lsb :: (Num a, Bits a, SymWord a) => SBV a -> SBool
-lsb x = sbvTestBit x 0
+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              = sbvTestBit x (intSizeOf x - 1)
+ | 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
@@ -1074,7 +996,7 @@
                                    mkSymOp o st sgnsz sw1 sw2
         z = genLiteral (kindOf x) (0::Integer)
 
--- | Lift 'QMod' to symbolic words. Division by 0 is defined s.t. @x/0 = 0@; which
+-- | 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 a, SDivisible (SBV a)) => SBV a -> SBV a -> (SBV a, SBV a)
@@ -1174,56 +1096,6 @@
   | Just r <- unliteral t = if r then a else b
   | True                  = symbolicMerge False t a b
 
--- | Branch on a condition, much like 'ite'. The exception is that SBV will
--- check to make sure if the test condition is feasible by making an external
--- call to the SMT solver. Note that this can be expensive, thus we shall use
--- a time-out value ('sBranchTimeOut'). There might be zero, one, or two such
--- external calls per 'sBranch' call:
---
---    - If condition is statically known to be True/False: 0 calls
---           - In this case, we simply constant fold..
---
---    - If condition is determined to be unsatisfiable   : 1 call
---           - In this case, we know then-branch is infeasible, so just take the else-branch
---
---    - If condition is determined to be satisfable      : 2 calls
---           - In this case, we know then-branch is feasible, but we still have to check if the else-branch is
---
--- In summary, 'sBranch' calls can be expensive, but they can help with the so-called symbolic-termination
--- problem. See "Data.SBV.Examples.Misc.SBranch" for an example.
-sBranch :: Mergeable a => SBool -> a -> a -> a
-sBranch t a b
-  | Just r <- unliteral c = if r then a else b
-  | True                  = symbolicMerge False c a b
-  where c = reduceInPathCondition t
-
--- | Symbolic assert. Check that the given boolean condition is always true in the given path.
--- Otherwise symbolic simulation will stop with a run-time error.
-sAssert :: Mergeable a => String -> SBool -> a -> a
-sAssert msg = sAssertCont msg defCont
-  where defCont _   Nothing   = C.throw (SafeAlwaysFails  msg)
-        defCont cfg (Just md) = C.throw (SafeFailsInModel msg cfg (SMTModel (M.toList md) [] []))
-
--- | Symbolic assert with a programmable continuation. Check that the given boolean condition is always true in the given path.
--- Otherwise symbolic simulation will transfer the failing model to the given continuation. The
--- continuation takes the @SMTConfig@, and a possible model: If it receives @Nothing@, then it means that the condition
--- fails for all assignments to inputs. Otherwise, it'll receive @Just@ a dictionary that maps the
--- input variables to the appropriate @CW@ values that exhibit the failure. Note that the continuation
--- has no option but to display the result in some fashion and call error, due to its restricted type.
-sAssertCont :: Mergeable a => String -> (forall b. SMTConfig -> Maybe (M.Map String CW) -> b) -> SBool -> a -> a
-sAssertCont msg cont t a
-  | Just r <- unliteral t = if r then a else cont defaultSMTCfg Nothing
-  | True                  = symbolicMerge False cond a (die ["SBV.error: Internal-error, cannot happen: Reached false branch in checked s-Assert."])
-  where k     = kindOf t
-        cond  = SBV $ SVal k $ Right $ cache c
-        die m = error $ intercalate "\n" $ ("Assertion failure: " ++ show msg) : m
-        c st  = do let pc  = getPathCondition st
-                       chk = pc &&& bnot t
-                   mbModel <- isConditionSatisfiable st chk
-                   case mbModel of
-                     Just (r@(SatResult (Satisfiable cfg _))) -> cont cfg $ Just $ getModelDictionary r
-                     _                                        -> return trueSW
-
 -- | 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
@@ -1656,25 +1528,6 @@
 pConstrain :: Double -> SBool -> Symbolic ()
 pConstrain t c = addConstraint (Just t) c (bnot c)
 
--- | Boolean symbolic reduction. See if we can reduce a boolean condition to true/false
--- using the path context information, by making external calls to the SMT solvers. Used in the
--- implementation of 'sBranch'.
-reduceInPathCondition :: SBool -> SBool
-reduceInPathCondition b
-  | isConcrete b = b -- No reduction is needed, already a concrete value
-  | True         = SBV $ SVal k $ Right $ cache c
-  where k    = kindOf b
-        c st = do -- Now that we know our boolean is not obviously true/false. Need to make an external
-                  -- call to the SMT solver to see if we can prove it is necessarily one of those
-                  let pc = getPathCondition st
-                  satTrue <- isSBranchFeasibleInState st "then" (pc &&& b)
-                  if not satTrue
-                     then return falseSW          -- condition is not satisfiable; so it must be necessarily False.
-                     else do satFalse <- isSBranchFeasibleInState st "else" (pc &&& bnot b)
-                             if not satFalse      -- negation of the condition is not satisfiable; so it must be necessarily True.
-                                then return trueSW
-                                else sbvToSW st b -- condition is not necessarily always True/False. So, keep symbolic.
-
 -- Quickcheck interface on symbolic-booleans..
 instance Testable SBool where
   property (SBV (SVal _ (Left b))) = property (cwToBool b)
@@ -1700,6 +1553,14 @@
                   shN s = s ++ replicate (maxLen - length s) ' '
                   info (n, cw) = shN n ++ " = " ++ show cw
 
+-- 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 (svKind 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
@@ -1712,6 +1573,23 @@
                     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
diff --git a/Data/SBV/BitVectors/Operations.hs b/Data/SBV/BitVectors/Operations.hs
--- a/Data/SBV/BitVectors/Operations.hs
+++ b/Data/SBV/BitVectors/Operations.hs
@@ -148,13 +148,23 @@
     rem' a b | svKind 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 (eqOpt trueSW) Equal) rationalCheck (==) (==) (==) (==) (==)
+svEqual = liftSym2B (mkSymOpSC (eqOptBool Equal trueSW) Equal) rationalCheck (==) (==) (==) (==) (==)
 
 -- | Inequality.
 svNotEqual :: SVal -> SVal -> SVal
-svNotEqual = liftSym2B (mkSymOpSC (eqOpt falseSW) NotEqual) rationalCheck (/=) (/=) (/=) (/=) (/=)
+svNotEqual = liftSym2B (mkSymOpSC (eqOptBool NotEqual falseSW) NotEqual) rationalCheck (/=) (/=) (/=) (/=) (/=)
 
 -- | Less than.
 svLessThan :: SVal -> SVal -> SVal
@@ -500,7 +510,7 @@
 -- The shift amount must be an unsigned quantity.
 svShiftLeft :: SVal -> SVal -> SVal
 svShiftLeft x i
-  | svSigned i = error "sbvShiftLeft: shift amount should be unsigned"
+  | svSigned i = error "sShiftLeft: shift amount should be unsigned"
   | True       = svSelect [svShl x k | k <- [0 .. svBitSize x - 1]] z i
   where z = svInteger (svKind x) 0
 
@@ -511,7 +521,7 @@
 -- otherwise it's logical.
 svShiftRight :: SVal -> SVal -> SVal
 svShiftRight x i
-  | svSigned i = error "sbvShiftRight: shift amount should be unsigned"
+  | svSigned i = error "sShiftRight: shift amount should be unsigned"
   | True       = svSelect [svShr x k | k <- [0 .. svBitSize x - 1]] z i
   where z = svInteger (svKind x) 0
 
@@ -519,7 +529,7 @@
 -- The rotation amount must be an unsigned quantity.
 svRotateLeft :: SVal -> SVal -> SVal
 svRotateLeft x i
-  | svSigned i             = error "sbvRotateLeft: rotation amount should be unsigned"
+  | svSigned i             = error "sRotateLeft: rotation amount should be unsigned"
   | bit si <= toInteger sx = svSelect [x `svRol` k | k <- [0 .. bit si - 1]] z i         -- wrap-around not possible
   | True                   = svSelect [x `svRol` k | k <- [0 .. sx     - 1]] z (i `svRem` n)
     where sx = svBitSize x
@@ -531,7 +541,7 @@
 -- The rotation amount must be an unsigned quantity.
 svRotateRight :: SVal -> SVal -> SVal
 svRotateRight x i
-  | svSigned i             = error "sbvRotateRight: rotation amount should be unsigned"
+  | svSigned i             = error "sRotateRight: rotation amount should be unsigned"
   | bit si <= toInteger sx = svSelect [x `svRor` k | k <- [0 .. bit si - 1]] z i         -- wrap-around not possible
   | True                   = svSelect [x `svRor` k | k <- [0 .. sx     - 1]] z (i `svRem` n)
     where sx = svBitSize x
diff --git a/Data/SBV/BitVectors/PrettyNum.hs b/Data/SBV/BitVectors/PrettyNum.hs
--- a/Data/SBV/BitVectors/PrettyNum.hs
+++ b/Data/SBV/BitVectors/PrettyNum.hs
@@ -222,7 +222,7 @@
    | isInfinite f        = as "+oo"
    | isNegativeZero f    = "(fp.neg ((_ to_fp 8 24) " ++ smtRoundingMode rm ++ " (/ 0 1)))"
    | True                = "((_ to_fp 8 24) " ++ smtRoundingMode rm ++ " " ++ toSMTLibRational (toRational f) ++ ")"
-   where as s = "(as " ++ s ++ " (_ FloatingPoint 8 24))"
+   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
@@ -232,7 +232,7 @@
    | isInfinite d        = as "+oo"
    | isNegativeZero d    = "(fp.neg ((_ to_fp 11 53) " ++ smtRoundingMode rm ++ " (/ 0 1)))"
    | True                = "((_ to_fp 11 53) " ++ smtRoundingMode rm ++ " " ++ toSMTLibRational (toRational d) ++ ")"
-   where as s = "(as " ++ s ++ " (_ FloatingPoint 11 53))"
+   where as s = "(_ " ++ s ++ " 11 53)"
 
 -- | Show a rational in SMTLib format
 toSMTLibRational :: Rational -> String
diff --git a/Data/SBV/BitVectors/Rounding.hs b/Data/SBV/BitVectors/Rounding.hs
deleted file mode 100644
--- a/Data/SBV/BitVectors/Rounding.hs
+++ /dev/null
@@ -1,75 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.BitVectors.Rounding
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Implementation of floating-point operations that know about rounding-modes
------------------------------------------------------------------------------
-
-module Data.SBV.BitVectors.Rounding (RoundingFloat(..)) where
-
-import Data.SBV.BitVectors.Data
-import Data.SBV.BitVectors.Model ()  -- instances only
-
--- | A class of floating-point (IEEE754) operations that behave
--- differently based on rounding modes. Note that we will never
--- concretely evaluate these, but rather pass down to the SMT solver
--- even when we have a concrete rounding mode supported by Haskell.
--- (i.e., round-to-nearest even.) The extra complexity is just not
--- worth it to support constant folding in that rare case; and if
--- the rounding mode is already round-to-nearest-even then end-users simply
--- use the usual Num instances. (Except for FMA obviously, which has no
--- Haskell equivalent.)
-class (SymWord a, Floating a) => RoundingFloat a where
-  fpAdd  :: SRoundingMode -> SBV a -> SBV a -> SBV a
-  fpSub  :: SRoundingMode -> SBV a -> SBV a -> SBV a
-  fpMul  :: SRoundingMode -> SBV a -> SBV a -> SBV a
-  fpDiv  :: SRoundingMode -> SBV a -> SBV a -> SBV a
-  fpFMA  :: SRoundingMode -> SBV a -> SBV a -> SBV a -> SBV a
-  fpSqrt :: SRoundingMode -> SBV a -> SBV a
-
-  -- Default definitions simply piggy back onto FPRound
-  fpAdd  = lift2Rm "fp.add"
-  fpSub  = lift2Rm "fp.sub"
-  fpMul  = lift2Rm "fp.mul"
-  fpDiv  = lift2Rm "fp.div"
-  fpFMA  = lift3Rm "fp.fma"
-  fpSqrt = lift1Rm "fp.sqrt"
-
--- | Lift a 1 arg floating point UOP
-lift1Rm :: (SymWord a, Floating a) => String -> SRoundingMode -> SBV a -> SBV a
-lift1Rm w m a = SBV $ SVal k $ Right $ cache r
-  where k = kindOf a
-        r st = do swm <- sbvToSW st m
-                  swa <- sbvToSW st a
-                  newExpr st k (SBVApp (FPRound w) [swm, swa])
-
--- | Lift a 2 arg floating point UOP
-lift2Rm :: (SymWord a, Floating a) => String -> SRoundingMode -> SBV a -> SBV a -> SBV a
-lift2Rm w m a b = SBV $ SVal k $ Right $ cache r
-  where k = kindOf a
-        r st = do swm <- sbvToSW st m
-                  swa <- sbvToSW st a
-                  swb <- sbvToSW st b
-                  newExpr st k (SBVApp (FPRound w) [swm, swa, swb])
-
--- | Lift a 3 arg floating point UOP
-lift3Rm :: (SymWord a, Floating a) => String -> SRoundingMode -> SBV a -> SBV a -> SBV a -> SBV a
-lift3Rm w m a b c = SBV $ SVal k $ Right $ cache r
-  where k = kindOf a
-        r st = do swm <- sbvToSW st m
-                  swa <- sbvToSW st a
-                  swb <- sbvToSW st b
-                  swc <- sbvToSW st c
-                  newExpr st k (SBVApp (FPRound w) [swm, swa, swb, swc])
-
--- | SFloat instance
-instance RoundingFloat Float
-
--- | SDouble instance
-instance RoundingFloat Double
-
-{-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
diff --git a/Data/SBV/BitVectors/SignCast.hs b/Data/SBV/BitVectors/SignCast.hs
deleted file mode 100644
--- a/Data/SBV/BitVectors/SignCast.hs
+++ /dev/null
@@ -1,127 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.BitVectors.SignCast
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Implementation of casting between signed/unsigned variants of the
--- same type.
------------------------------------------------------------------------------
-
-{-# LANGUAGE MultiParamTypeClasses  #-}
-{-# LANGUAGE FunctionalDependencies #-}
-{-# LANGUAGE TypeSynonymInstances   #-}
-{-# LANGUAGE PatternGuards          #-}
-{-# LANGUAGE FlexibleInstances      #-}
-
-module Data.SBV.BitVectors.SignCast (SignCast(..)) where
-
-import Data.Word (Word8, Word16, Word32, Word64)
-import Data.Int  (Int8,  Int16,  Int32,  Int64)
-
-import Data.SBV.BitVectors.Data
-import Data.SBV.BitVectors.Model()  -- instances only
-
--- | Sign casting a value into another. This essentially
--- means forgetting the sign bit and reinterpreting the bits
--- accordingly when converting a signed value to an unsigned
--- one. Similarly, when an unsigned quantity is converted to
--- a signed one, the most significant bit is interpreted
--- as the sign. We only define instances when the source
--- and target types are precisely the same size.
--- The idea is that 'signCast' and 'unsignCast' must form
--- an isomorphism pair between the types @a@ and @b@, i.e., we
--- expect the following two properties to hold:
---
--- @
---    signCast . unsignCast = id
---    unsingCast . signCast = id
--- @
---
--- Note that one naive way to implement both these operations
--- is simply to compute @fromBitsLE . blastLE@, i.e., first
--- get all the bits of the word and then reconstruct in the target
--- type. While this is semantically correct, it generates a lot
--- of code (both during proofs via SMT-Lib, and when compiled to C).
--- The goal of this class is to avoid that cost, so these operations
--- can be compiled very efficiently, they will essentially become no-op's.
---
--- Minimal complete definition: All, no defaults.
-class SignCast a b | a -> b, b -> a where
-  -- | Interpret as a signed word
-  signCast   :: a -> b
-  -- | Interpret as an unsigned word
-  unsignCast :: b -> a
-
--- concrete instances
-instance SignCast Word64 Int64 where
-  signCast   = fromIntegral
-  unsignCast = fromIntegral
-
-instance SignCast Word32 Int32 where
-  signCast   = fromIntegral
-  unsignCast = fromIntegral
-
-instance SignCast Word16 Int16 where
-  signCast   = fromIntegral
-  unsignCast = fromIntegral
-
-instance SignCast Word8  Int8  where
-  signCast   = fromIntegral
-  unsignCast = fromIntegral
-
--- A generic implementation can be along the following lines:
---      fromBitsLE . blastLE
--- However, we prefer this version as the above will generate
--- a ton more code during compilation to SMT-Lib and C
-genericSign :: (Integral a, SymWord a, Num b, SymWord b) => SBV a -> SBV b
-genericSign x
-  | Just c <- unliteral x = literal $ fromIntegral c
-  | True                  = SBV (SVal k (Right (cache y)))
-     where k = case kindOf x of
-                 KBool            -> error "Data.SBV.SignCast.genericSign: Called on boolean value"
-                 KBounded False n -> KBounded True n
-                 KBounded True  _ -> error "Data.SBV.SignCast.genericSign: Called on signed value"
-                 KUnbounded       -> error "Data.SBV.SignCast.genericSign: Called on unbounded value"
-                 KReal            -> error "Data.SBV.SignCast.genericSign: Called on real value"
-                 KFloat           -> error "Data.SBV.SignCast.genericSign: Called on float value"
-                 KDouble          -> error "Data.SBV.SignCast.genericSign: Called on double value"
-                 KUserSort s _    -> error $ "Data.SBV.SignCast.genericSign: Called on unintepreted sort " ++ s
-           y st = do xsw <- sbvToSW st x
-                     newExpr st k (SBVApp (Extract (intSizeOf x-1) 0) [xsw])
-
--- Same comments as above, regarding the implementation.
-genericUnsign :: (Integral a, SymWord a, Num b, SymWord b) => SBV a -> SBV b
-genericUnsign x
-  | Just c <- unliteral x = literal $ fromIntegral c
-  | True                  = SBV (SVal k (Right (cache y)))
-     where k = case kindOf x of
-                 KBool            -> error "Data.SBV.SignCast.genericUnSign: Called on boolean value"
-                 KBounded True  n -> KBounded False n
-                 KBounded False _ -> error "Data.SBV.SignCast.genericUnSign: Called on unsigned value"
-                 KUnbounded       -> error "Data.SBV.SignCast.genericUnSign: Called on unbounded value"
-                 KReal            -> error "Data.SBV.SignCast.genericUnSign: Called on real value"
-                 KFloat           -> error "Data.SBV.SignCast.genericUnSign: Called on float value"
-                 KDouble          -> error "Data.SBV.SignCast.genericUnSign: Called on double value"
-                 KUserSort s _    -> error $ "Data.SBV.SignCast.genericUnSign: Called on unintepreted sort " ++ s
-           y st = do xsw <- sbvToSW st x
-                     newExpr st k (SBVApp (Extract (intSizeOf x-1) 0) [xsw])
-
--- symbolic instances
-instance SignCast SWord8 SInt8 where
-  signCast   = genericSign
-  unsignCast = genericUnsign
-
-instance SignCast SWord16 SInt16 where
-  signCast   = genericSign
-  unsignCast = genericUnsign
-
-instance SignCast SWord32 SInt32 where
-  signCast   = genericSign
-  unsignCast = genericUnsign
-
-instance SignCast SWord64 SInt64 where
-  signCast   = genericSign
-  unsignCast = genericUnsign
diff --git a/Data/SBV/BitVectors/Symbolic.hs b/Data/SBV/BitVectors/Symbolic.hs
--- a/Data/SBV/BitVectors/Symbolic.hs
+++ b/Data/SBV/BitVectors/Symbolic.hs
@@ -19,26 +19,24 @@
 {-# LANGUAGE    DefaultSignatures          #-}
 {-# LANGUAGE    NamedFieldPuns             #-}
 {-# LANGUAGE    DeriveDataTypeable         #-}
-{-# LANGUAGE    CPP                        #-}
 {-# OPTIONS_GHC -fno-warn-orphans          #-}
 
 module Data.SBV.BitVectors.Symbolic
   ( NodeId(..)
   , SW(..), swKind, trueSW, falseSW
-  , Op(..), smtLibSquareRoot, smtLibFusedMA
+  , Op(..), FPOp(..)
   , Quantifier(..), needsExistentials
   , RoundingMode(..)
-  , SBVType(..), newUninterpreted, unintFnUIKind, addAxiom
+  , SBVType(..), newUninterpreted, addAxiom
   , SVal(..), svKind
   , svBitSize, svSigned
   , svMkSymVar
-  , ArrayContext(..), ArrayInfo, arrayUIKind
+  , ArrayContext(..), ArrayInfo
   , svToSW, svToSymSW, forceSWArg
   , SBVExpr(..), newExpr
   , Cached, cache, uncache
   , ArrayIndex, uncacheAI
   , NamedSymVar
-  , UnintKind(..)
   , getSValPathCondition, extendSValPathCondition
   , getTableIndex
   , SBVPgm(..), Symbolic, runSymbolic, runSymbolic', State
@@ -46,19 +44,15 @@
   , Logic(..), SMTLibLogic(..)
   , getTraceInfo, getConstraints
   , addSValConstraint
-  , SMTLibPgm(..), SMTLibVersion(..)
+  , SMTLibPgm(..), SMTLibVersion(..), smtLibVersionExtension
   , SolverCapabilities(..)
   , extractSymbolicSimulationState
-  , SMTScript(..), Solver(..), SMTSolver(..), SMTResult(..), SMTModel(..), SMTConfig(..), getSBranchRunConfig
+  , SMTScript(..), Solver(..), SMTSolver(..), SMTResult(..), SMTModel(..), SMTConfig(..), SMTEngine, getSBranchRunConfig
   , outputSVal
   , mkSValUserSort
   , SArr(..), readSArr, resetSArr, writeSArr, mergeSArr, newSArr, eqSArr
   ) where
 
-#if __GLASGOW_HASKELL__ < 710
-import Control.Applicative  (Applicative)
-#endif
-
 import Control.DeepSeq      (NFData(..))
 import Control.Monad        (when, unless)
 import Control.Monad.Reader (MonadReader, ReaderT, ask, runReaderT)
@@ -69,14 +63,12 @@
 import Data.Maybe           (isJust, fromJust, fromMaybe)
 
 import qualified Data.Generics as G    (Data(..))
-import qualified Data.Typeable as T    (Typeable)
 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.Exit           (ExitCode(..))
 import System.Mem.StableName
 import System.Random
 
@@ -113,35 +105,93 @@
 trueSW  = SW KBool $ NodeId (-1)
 
 -- | Symbolic operations
-data Op = Plus | Times | Minus | UNeg | Abs
-        | Quot | Rem
-        | Equal | NotEqual
-        | LessThan | GreaterThan | LessEq | GreaterEq
+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
+        | 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
+        | ArrEq   Int Int                       -- Array equality
         | ArrRead Int
+        | IntCast Kind Kind
         | Uninterpreted String
-        -- Floating point uops with custom rounding-modes
-        | FPRound String
+        | Label String                          -- Essentially no-op; useful for code generation to emit comments.
+        | IEEEFP FPOp                           -- Floating-point ops, categorized separately
         deriving (Eq, Ord)
 
--- | SMT-Lib's square-root over floats/doubles. We piggy back on to the uninterpreted function mechanism
--- to implement these; which is not a terrible idea; although the use of the constructor 'Uninterpreted'
--- might be confusing. This function will *not* be uninterpreted in reality, as QF_FP will define it. It's
--- a bit of a shame, but much easier to implement it this way.
-smtLibSquareRoot :: Op
-smtLibSquareRoot = Uninterpreted "fp.sqrt"
+-- | 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)
 
--- | SMT-Lib's fusedMA over floats/doubles. Similar to the 'smtLibSquareRoot'. Note that we cannot implement
--- this function in Haskell as precision loss would be inevitable. Maybe Haskell will eventually add this op
--- to the Num class.
-smtLibFusedMA :: Op
-smtLibFusedMA = Uninterpreted "fp.fma"
+-- | 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.
@@ -154,10 +204,12 @@
   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 (ArrEq i j)       = "array_" ++ show i ++ " == array_" ++ show j
+  show (ArrRead i)       = "select array_" ++ show i
+  show (IntCast fr to)   = "cast_" ++ show fr ++ "_" ++ show to
   show (Uninterpreted i) = "[uninterpreted] " ++ i
-  show (FPRound w)       = w
+  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!"
@@ -185,10 +237,6 @@
 newtype SBVType = SBVType [Kind]
              deriving (Eq, Ord)
 
--- | how many arguments does the type take?
-typeArity :: SBVType -> Int
-typeArity (SBVType xs) = length xs - 1
-
 instance Show SBVType where
   show (SBVType []) = error "SBV: internal error, empty SBVType"
   show (SBVType xs) = intercalate " -> " $ map show xs
@@ -222,11 +270,6 @@
 -- | 'NamedSymVar' pairs symbolic words and user given/automatically generated names
 type NamedSymVar = (SW, String)
 
--- | 'UnintKind' pairs array names and uninterpreted constants with their "kinds"
--- used mainly for printing counterexamples
-data UnintKind = UFun Int String | UArr Int String      -- in each case, arity and the aliasing name
- deriving Show
-
 -- | Result of running a symbolic computation
 data Result = Result (Set.Set Kind)                -- kinds used in the program
                      [(String, CW)]                -- quick-check counter-example information (if any)
@@ -337,24 +380,10 @@
 -- | Cached values, implementing sharing
 type Cache a   = IMap.IntMap [(StableName (State -> IO a), a)]
 
--- | Convert an SBV-type to the kind-of uninterpreted value it represents
-unintFnUIKind :: (String, SBVType) -> (String, UnintKind)
-unintFnUIKind (s, t) = (s, UFun (typeArity t) s)
-
--- | Convert an array value type to the kind-of uninterpreted value it represents
-arrayUIKind :: (Int, ArrayInfo) -> Maybe (String, UnintKind)
-arrayUIKind (i, (nm, _, ctx))
-  | external ctx = Just ("array_" ++ show i, UArr 1 nm) -- arrays are always 1-dimensional in the SMT-land. (Unless encoded explicitly)
-  | True         = Nothing
-  where external (ArrayFree{})   = True
-        external (ArrayReset{})  = False
-        external (ArrayMutate{}) = False
-        external (ArrayMerge{})  = False
-
 -- | Different means of running a symbolic piece of code
-data SBVRunMode = Proof (Bool, Maybe SMTConfig) -- ^ Symbolic simulation mode, for proof purposes. Bool is True if it's a sat instance. SMTConfig is used for 'sBranch' calls.
-                | CodeGen                       -- ^ Code generation mode
-                | Concrete StdGen               -- ^ Concrete simulation mode. The StdGen is for the pConstrain acceptance in cross runs
+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 :: SBVRunMode -> Bool
@@ -363,25 +392,25 @@
 isConcreteMode CodeGen      = False
 
 -- | 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])]
-                    , rSWCache      :: IORef (Cache SW)
-                    , rAICache      :: IORef (Cache Int)
+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])]
+                    , rSWCache     :: IORef (Cache SW)
+                    , rAICache     :: IORef (Cache Int)
                     }
 
 -- | Get the current path condition
@@ -402,7 +431,7 @@
 -- | If in proof mode, get the underlying configuration (used for 'sBranch')
 getSBranchRunConfig :: State -> Maybe SMTConfig
 getSBranchRunConfig st = case runMode st of
-                           Proof (_, s)  -> s
+                           Proof (_, s)  -> Just s
                            _             -> Nothing
 
 -- | The "Symbolic" value. Either a constant (@Left@) or a symbolic
@@ -556,7 +585,7 @@
         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 (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
@@ -580,10 +609,10 @@
         liftIO $ registerKind st k
         let q = case (mbQ, runMode st) of
                   (Just x,  _)                -> x
-                  (Nothing, Proof (True, _))  -> EX
+                  (Nothing, Proof (True,  _)) -> EX
                   (Nothing, Proof (False, _)) -> ALL
-                  (Nothing, Concrete{})       -> error $ "SBV: Uninterpreted sort " ++ sortName ++ " can not be used in concrete simulation mode."
                   (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
@@ -602,8 +631,8 @@
 
 -- | 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, Maybe SMTConfig) -> Symbolic a -> IO Result
-runSymbolic b c = snd `fmap` runSymbolic' (Proof b) c
+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)
@@ -834,12 +863,16 @@
                         r `seq` modifyIORef rCache (IMap.insertWith (++) h [(sn, r)])
                         return r
 
--- | Representation of SMTLib Program versions, currently we only know of versions 1 and 2.
--- (NB. Eventually, we should just drop SMTLib1.)
-data SMTLibVersion = SMTLib1
-                   | SMTLib2
-                   deriving Eq
+-- | 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.
@@ -866,7 +899,6 @@
 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 UnintKind     where rnf a = seq a ()
 instance NFData a => NFData (Cached a) where
   rnf (Cached f) = f `seq` ()
 instance NFData SVal where
@@ -882,7 +914,7 @@
   rnf (TimeOut _)         = ()
 
 instance NFData SMTModel where
-  rnf (SMTModel assocs unints uarrs) = rnf assocs `seq` rnf unints `seq` rnf uarrs `seq` ()
+  rnf (SMTModel assocs) = rnf assocs `seq` ()
 
 instance NFData SMTScript where
   rnf (SMTScript b m) = rnf b `seq` rnf m `seq` ()
@@ -954,7 +986,7 @@
                   | 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, G.Data, T.Typeable, Read, Show, Bounded, Enum)
+                  deriving (Eq, Ord, Show, Read, G.Data, Bounded, Enum)
 
 -- | 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}@.)
@@ -973,19 +1005,19 @@
 -- 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         :: Bool             -- ^ 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.
-       , smtFile        :: Maybe FilePath   -- ^ If Just, the generated SMT script will be put in this file (for debugging purposes mostly)
-       , useSMTLib2     :: Bool             -- ^ If True, we'll treat the solver as using SMTLib2 input format. Otherwise, SMTLib1
-       , 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.
+         verbose        :: Bool           -- ^ Debug mode
+       , timing         :: Bool           -- ^ 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.
+       , 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
@@ -994,8 +1026,6 @@
 -- | A model, as returned by a solver
 data SMTModel = SMTModel {
         modelAssocs    :: [(String, CW)]        -- ^ Mapping of symbolic values to constants.
-     ,  modelArrays    :: [(String, [String])]  -- ^ Arrays, very crude; only works with Yices.
-     ,  modelUninterps :: [(String, [String])]  -- ^ Uninterpreted funcs; very crude; only works with Yices.
      }
      deriving Show
 
@@ -1017,7 +1047,7 @@
         }
 
 -- | An SMT engine
-type SMTEngine = SMTConfig -> Bool -> [(Quantifier, NamedSymVar)] -> [(String, UnintKind)] -> [Either SW (SW, [SW])] -> String -> IO SMTResult
+type SMTEngine = SMTConfig -> Bool -> [(Quantifier, NamedSymVar)] -> [Either SW (SW, [SW])] -> String -> IO SMTResult
 
 -- | Solvers that SBV is aware of
 data Solver = Z3
@@ -1030,13 +1060,14 @@
 
 -- | 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
-       , xformExitCode  :: ExitCode -> ExitCode -- ^ Should we re-interpret exit codes. Most solvers behave rationally, i.e., id will do. Some (like CVC4) don't.
-       , capabilities   :: SolverCapabilities   -- ^ Various capabilities of the solver
+         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
--- a/Data/SBV/Bridge/ABC.hs
+++ b/Data/SBV/Bridge/ABC.hs
@@ -24,14 +24,14 @@
 module Data.SBV.Bridge.ABC (
   -- * ABC specific interface
   sbvCurrentSolver
-  -- ** Proving, checking satisfiability, and safety
-  , prove, sat, safe, allSat, isVacuous, isTheorem, isSatisfiable
+  -- ** Proving, checking satisfiability
+  , prove, sat, 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)
+import Data.SBV hiding (prove, sat, allSat, isVacuous, isTheorem, isSatisfiable, optimize, minimize, maximize, sbvCurrentSolver)
 
 -- | Current solver instance, pointing to abc.
 sbvCurrentSolver :: SMTConfig
@@ -48,12 +48,6 @@
     => a                -- ^ Property to check
     -> IO SatResult     -- ^ Response of the SMT Solver, containing the model if found
 sat = satWith sbvCurrentSolver
-
--- | Check safety, i.e., prove that all 'sAssert' conditions are statically true in all paths
-safe :: SExecutable a
-     => a               -- ^ Program to check the safety of
-     -> IO SafeResult   -- ^ Response of the SMT solver, containing the unsafe model if found
-safe = safeWith sbvCurrentSolver
 
 -- | Find all satisfying solutions, using ABC
 allSat :: Provable a
diff --git a/Data/SBV/Bridge/Boolector.hs b/Data/SBV/Bridge/Boolector.hs
--- a/Data/SBV/Bridge/Boolector.hs
+++ b/Data/SBV/Bridge/Boolector.hs
@@ -24,8 +24,8 @@
 module Data.SBV.Bridge.Boolector (
   -- * Boolector specific interface
   sbvCurrentSolver
-  -- ** Proving, checking satisfiability, and safety
-  , prove, sat, safe, allSat, isVacuous, isTheorem, isSatisfiable
+  -- ** Proving, checking satisfiability
+  , prove, sat, allSat, isVacuous, isTheorem, isSatisfiable
   -- ** Optimization routines
   , optimize, minimize, maximize
   -- * Non-Boolector specific SBV interface
@@ -33,7 +33,7 @@
   , module Data.SBV
   ) where
 
-import Data.SBV hiding (prove, sat, safe, allSat, isVacuous, isTheorem, isSatisfiable, optimize, minimize, maximize, sbvCurrentSolver)
+import Data.SBV hiding (prove, sat, allSat, isVacuous, isTheorem, isSatisfiable, optimize, minimize, maximize, sbvCurrentSolver)
 
 -- | Current solver instance, pointing to cvc4.
 sbvCurrentSolver :: SMTConfig
@@ -50,12 +50,6 @@
     => a                -- ^ Property to check
     -> IO SatResult     -- ^ Response of the SMT Solver, containing the model if found
 sat = satWith sbvCurrentSolver
-
--- | Check safety, i.e., prove that all 'sAssert' conditions are statically true in all paths
-safe :: SExecutable a
-     => a               -- ^ Program to check the safety of
-     -> IO SafeResult   -- ^ Response of the SMT solver, containing the unsafe model if found
-safe = safeWith sbvCurrentSolver
 
 -- | Find all satisfying solutions, using the CVC4 SMT solver
 allSat :: Provable a
diff --git a/Data/SBV/Bridge/CVC4.hs b/Data/SBV/Bridge/CVC4.hs
--- a/Data/SBV/Bridge/CVC4.hs
+++ b/Data/SBV/Bridge/CVC4.hs
@@ -24,8 +24,8 @@
 module Data.SBV.Bridge.CVC4 (
   -- * CVC4 specific interface
   sbvCurrentSolver
-  -- ** Proving, checking satisfiability, and safety
-  , prove, sat, safe, allSat, isVacuous, isTheorem, isSatisfiable
+  -- ** Proving, checking satisfiability
+  , prove, sat, allSat, isVacuous, isTheorem, isSatisfiable
   -- ** Optimization routines
   , optimize, minimize, maximize
   -- * Non-CVC4 specific SBV interface
@@ -33,7 +33,7 @@
   , module Data.SBV
   ) where
 
-import Data.SBV hiding (prove, sat, safe, allSat, isVacuous, isTheorem, isSatisfiable, optimize, minimize, maximize, sbvCurrentSolver)
+import Data.SBV hiding (prove, sat, allSat, isVacuous, isTheorem, isSatisfiable, optimize, minimize, maximize, sbvCurrentSolver)
 
 -- | Current solver instance, pointing to cvc4.
 sbvCurrentSolver :: SMTConfig
@@ -50,12 +50,6 @@
     => a                -- ^ Property to check
     -> IO SatResult     -- ^ Response of the SMT Solver, containing the model if found
 sat = satWith sbvCurrentSolver
-
--- | Check safety, i.e., prove that all 'sAssert' conditions are statically true in all paths
-safe :: SExecutable a
-     => a               -- ^ Program to check the safety of
-     -> IO SafeResult   -- ^ Response of the SMT solver, containing the unsafe model if found
-safe = safeWith sbvCurrentSolver
 
 -- | Find all satisfying solutions, using the CVC4 SMT solver
 allSat :: Provable a
diff --git a/Data/SBV/Bridge/MathSAT.hs b/Data/SBV/Bridge/MathSAT.hs
--- a/Data/SBV/Bridge/MathSAT.hs
+++ b/Data/SBV/Bridge/MathSAT.hs
@@ -24,8 +24,8 @@
 module Data.SBV.Bridge.MathSAT (
   -- * MathSAT specific interface
   sbvCurrentSolver
-  -- ** Proving, checking satisfiability, and safety
-  , prove, sat, safe, allSat, isVacuous, isTheorem, isSatisfiable
+  -- ** Proving, checking satisfiability
+  , prove, sat, allSat, isVacuous, isTheorem, isSatisfiable
   -- ** Optimization routines
   , optimize, minimize, maximize
   -- * Non-MathSAT specific SBV interface
@@ -33,7 +33,7 @@
   , module Data.SBV
   ) where
 
-import Data.SBV hiding (prove, sat, safe, allSat, isVacuous, isTheorem, isSatisfiable, optimize, minimize, maximize, sbvCurrentSolver)
+import Data.SBV hiding (prove, sat, allSat, isVacuous, isTheorem, isSatisfiable, optimize, minimize, maximize, sbvCurrentSolver)
 
 -- | Current solver instance, pointing to cvc4.
 sbvCurrentSolver :: SMTConfig
@@ -50,12 +50,6 @@
     => a                -- ^ Property to check
     -> IO SatResult     -- ^ Response of the SMT Solver, containing the model if found
 sat = satWith sbvCurrentSolver
-
--- | Check safety, i.e., prove that all 'sAssert' conditions are statically true in all paths
-safe :: SExecutable a
-     => a               -- ^ Program to check the safety of
-     -> IO SafeResult   -- ^ Response of the SMT solver, containing the unsafe model if found
-safe = safeWith sbvCurrentSolver
 
 -- | Find all satisfying solutions, using the CVC4 SMT solver
 allSat :: Provable a
diff --git a/Data/SBV/Bridge/Yices.hs b/Data/SBV/Bridge/Yices.hs
--- a/Data/SBV/Bridge/Yices.hs
+++ b/Data/SBV/Bridge/Yices.hs
@@ -24,8 +24,8 @@
 module Data.SBV.Bridge.Yices (
   -- * Yices specific interface
   sbvCurrentSolver
-  -- ** Proving, checking satisfiability, and safety
-  , prove, sat, safe, allSat, isVacuous, isTheorem, isSatisfiable
+  -- ** Proving, checking satisfiability
+  , prove, sat, allSat, isVacuous, isTheorem, isSatisfiable
   -- ** Optimization routines
   , optimize, minimize, maximize
   -- * Non-Yices specific SBV interface
@@ -33,7 +33,7 @@
   , module Data.SBV
   ) where
 
-import Data.SBV hiding (prove, sat, safe, allSat, isVacuous, isTheorem, isSatisfiable, optimize, minimize, maximize, sbvCurrentSolver)
+import Data.SBV hiding (prove, sat, allSat, isVacuous, isTheorem, isSatisfiable, optimize, minimize, maximize, sbvCurrentSolver)
 
 -- | Current solver instance, pointing to yices.
 sbvCurrentSolver :: SMTConfig
@@ -50,12 +50,6 @@
     => a                -- ^ Property to check
     -> IO SatResult     -- ^ Response of the SMT Solver, containing the model if found
 sat = satWith sbvCurrentSolver
-
--- | Check safety, i.e., prove that all 'sAssert' conditions are statically true in all paths
-safe :: SExecutable a
-     => a               -- ^ Program to check the safety of
-     -> IO SafeResult   -- ^ Response of the SMT solver, containing the unsafe model if found
-safe = safeWith sbvCurrentSolver
 
 -- | Find all satisfying solutions, using the Yices SMT solver
 allSat :: Provable a
diff --git a/Data/SBV/Bridge/Z3.hs b/Data/SBV/Bridge/Z3.hs
--- a/Data/SBV/Bridge/Z3.hs
+++ b/Data/SBV/Bridge/Z3.hs
@@ -24,8 +24,8 @@
 module Data.SBV.Bridge.Z3 (
   -- * Z3 specific interface
   sbvCurrentSolver
-  -- ** Proving, checking satisfiability, and safety
-  , prove, sat, safe, allSat, isVacuous, isTheorem, isSatisfiable
+  -- ** Proving, checking satisfiability
+  , prove, sat, allSat, isVacuous, isTheorem, isSatisfiable
   -- ** Optimization routines
   , optimize, minimize, maximize
   -- * Non-Z3 specific SBV interface
@@ -33,7 +33,7 @@
   , module Data.SBV
   ) where
 
-import Data.SBV hiding (prove, sat, safe, allSat, isVacuous, isTheorem, isSatisfiable, optimize, minimize, maximize, sbvCurrentSolver)
+import Data.SBV hiding (prove, sat, allSat, isVacuous, isTheorem, isSatisfiable, optimize, minimize, maximize, sbvCurrentSolver)
 
 -- | Current solver instance, pointing to z3.
 sbvCurrentSolver :: SMTConfig
@@ -50,12 +50,6 @@
     => a                -- ^ Property to check
     -> IO SatResult     -- ^ Response of the SMT Solver, containing the model if found
 sat = satWith sbvCurrentSolver
-
--- | Check safety, i.e., prove that all 'sAssert' conditions are statically true in all paths
-safe :: SExecutable a
-     => a               -- ^ Program to check the safety of
-     -> IO SafeResult   -- ^ Response of the SMT solver, containing the unsafe model if found
-safe = safeWith sbvCurrentSolver
 
 -- | Find all satisfying solutions, using the Z3 SMT solver
 allSat :: Provable a
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
@@ -18,7 +18,7 @@
 import Data.List                      (nub, intercalate)
 import Data.Maybe                     (isJust, isNothing, fromJust)
 import qualified Data.Foldable as F   (toList)
-import qualified Data.Set      as Set (member, toList)
+import qualified Data.Set      as Set (member, union, unions, empty, toList, singleton, fromList)
 import System.FilePath                (takeBaseName, replaceExtension)
 import System.Random
 import Text.PrettyPrint.HughesPJ
@@ -118,7 +118,7 @@
                      xs -> vcat $ text "/* User given prototypes: */" : map text xs
         extDecls  = case cgDecls st of
                      [] -> empty
-                     xs -> vcat $ text "/* User given declarations: */" : map text xs ++ [text ""]
+                     xs -> vcat $ text "/* User given declarations: */" : map text xs
         flags    = cgLDFlags st
 
 -- | Pretty print a functions type. If there is only one output, we compile it
@@ -143,6 +143,11 @@
 declSW w sw = text "const" <+> pad (showCType sw) <+> text (show sw)
   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))
+  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
@@ -156,6 +161,7 @@
 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.
 showCType :: HasKind a => a -> String
 showCType i = case kindOf i of
                 KBounded False 1 -> "SBool"
@@ -183,15 +189,13 @@
         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 "%f"
-        specF CgDouble     = text "%f"
+        specF CgFloat      = text "%.6g"    -- float.h: __FLT_DIG__
+        specF CgDouble     = text "%.15g"   -- float.h: __DBL_DIG__
         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
---   8-bit or less constants using decimal; otherwise we use hex.
---   Note that this automatically takes care of the boolean (1-bit) value problem, since it
---   shows the result as an integer, which is OK as far as C is concerned.
+--   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))
   where sRealSuffix CgFloat      = text "F"
@@ -199,8 +203,9 @@
         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 KFloat (CWFloat f))             = text $ showCFloat f
-mkConst _   (CW KDouble (CWDouble d))           = text $ showCDouble d
+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
 
 showSizedConst :: Integer -> (Bool, Int) -> Doc
@@ -227,7 +232,7 @@
              , (True, text "# include any user-defined .mk file in the current directory.")
              , (True, text "-include *.mk")
              , (True, text "")
-             , (True, text "CC=gcc")
+             , (True, text "CC?=gcc")
              , (True, text "CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer")
              , (ifld, text "LDFLAGS?=" <> text (unwords ldFlags))
              , (True, text "")
@@ -268,6 +273,7 @@
   $$ text "#include <inttypes.h>"
   $$ text "#include <stdint.h>"
   $$ text "#include <stdbool.h>"
+  $$ text "#include <string.h>"
   $$ text "#include <math.h>"
   $$ text ""
   $$ text "/* The boolean type */"
@@ -324,10 +330,6 @@
  where pre    =  text "/* Example driver program for" <+> nm <> text ". */"
               $$ text "/* Automatically generated by SBV. Edit as you see fit! */"
               $$ text ""
-              $$ text "#include <inttypes.h>"
-              $$ text "#include <stdint.h>"
-              $$ text "#include <stdbool.h>"
-              $$ text "#include <math.h>"
               $$ text "#include <stdio.h>"
        header =  text "#include" <+> doubleQuotes (nm <> text ".h")
               $$ text ""
@@ -414,13 +416,9 @@
   = error "SBV->C: Cannot compile functions with existentially quantified variables."
   | True
   = [pre, header, post]
- where usorts = [s | KUserSort s _ <- Set.toList kindInfo]
+ where 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! */"
               $$ text ""
-              $$ text "#include <inttypes.h>"
-              $$ text "#include <stdint.h>"
-              $$ text "#include <stdbool.h>"
-              $$ text "#include <math.h>"
        header = text "#include" <+> doubleQuotes (nm <> text ".h")
        post   = text ""
              $$ vcat (map codeSeg cgs)
@@ -428,10 +426,10 @@
              $$ proto
              $$ text "{"
              $$ text ""
-             $$ nest 2 (   vcat (concatMap (genIO True) inVars)
+             $$ nest 2 (   vcat (concatMap (genIO True . (\v -> (isAlive v, v))) inVars)
                         $$ vcat (merge (map genTbl tbls) (map genAsgn assignments))
                         $$ sepIf (not (null assignments) || not (null tbls))
-                        $$ vcat (concatMap (genIO False) outVars)
+                        $$ vcat (concatMap (genIO False) (zip (repeat True) outVars))
                         $$ maybe empty mkRet mbRet
                        )
              $$ text "}"
@@ -441,7 +439,7 @@
        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]
+       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
@@ -455,10 +453,23 @@
                       getMax m (x:xs) = getMax (m `max` x) xs
        consts = (falseSW, falseCW) : (trueSW, trueCW) : preConsts
        isConst s = isJust (lookup s consts)
-       genIO :: Bool -> (String, CgVal) -> [Doc]
-       genIO True  (cNm, CgAtomic sw) = [declSW typeWidth sw  <+> text "=" <+> text cNm <> semi]
-       genIO False (cNm, CgAtomic sw) = [text "*" <> text cNm <+> text "=" <+> showSW cfg consts sw <> semi]
-       genIO isInp (cNm, CgArray sws) = zipWith genElt sws [(0::Int)..]
+       -- 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 (_, _)           = 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 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
@@ -473,7 +484,8 @@
        getNodeId s@(SW _ (NodeId n)) | isConst s = -1
                                      | True      = n
        genAsgn :: (SW, SBVExpr) -> (Int, Doc)
-       genAsgn (sw, n) = (getNodeId sw, declSW typeWidth sw <+> text "=" <+> ppExpr cfg consts n <> semi)
+       genAsgn (sw, n) = (getNodeId sw, ppExpr cfg consts n (declSW typeWidth sw) (declSWNoConst typeWidth sw) <> semi)
+
        -- merge tables intermixed with assignments, paying attention to putting tables as
        -- early as possible.. Note that the assignment list (second argument) is sorted on its order
        merge :: [(Int, Doc)] -> [(Int, Doc)] -> [Doc]
@@ -483,31 +495,117 @@
          | i < i'                                 = t : merge trest as
          | True                                   = a : merge ts arest
 
-ppExpr :: CgConfig -> [(SW, CW)] -> SBVExpr -> Doc
-ppExpr cfg consts (SBVApp op opArgs) = p op (map (showSW cfg consts) opArgs)
-  where rtc = cgRTC cfg
+handleIEEE :: FPOp -> [(SW, CW)] -> [(SW, 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 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)"
+                                     _                            -> 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
+        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_ObjEqual          = let mkIte   x y z = x <+> text "?" <+> y <+> text ":" <+> z
+                                       chkNaN  x     = text "isnan"   <> parens x
+                                       signbit x     = text "signbit" <> 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
+
+        -- 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
+
+        -- 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) = 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)
+
+        pickOp _          []             = die $ "Cannot determine float/double kind for op: " ++ show w
+        pickOp (fOp, dOp) args@((a,_):_) = case kindOf a of
+                                             KFloat  -> fOp KFloat  (map snd args)
+                                             KDouble -> dOp KDouble (map snd args)
+                                             k       -> die $ "handleIEEE: Expected double/float args, but got: " ++ show k ++ " for: " ++ show w
+
+        dispatch (fOp, dOp) = pickOp (fOp, dOp) fpArgs
+        cast f              = f (map snd fpArgs)
+
+        -- In SMT-Lib, fpMin/fpMax return +0 when given +0/-0 as the two arguments. (In any order.)
+        -- In C, the second argument is returned. So, wrap around an if-then-else to avoid discrepancy:
+        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
+
+ppExpr :: CgConfig -> [(SW, CW)] -> SBVExpr -> Doc -> (Doc, Doc) -> Doc
+ppExpr cfg consts (SBVApp op opArgs) lhs (typ, var)
+  | doNotAssign op
+  = typ <+> var <> 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)
+        rtc = cgRTC cfg
         cBinOps = [ (Plus, "+"),  (Times, "*"), (Minus, "-")
                   , (Equal, "=="), (NotEqual, "!="), (LessThan, "<"), (GreaterThan, ">"), (LessEq, "<="), (GreaterEq, ">=")
                   , (And, "&"), (Or, "|"), (XOr, "^")
                   ]
-        uninterpret "to_real" as
-          | [a] <- as            = text "(SReal)" <+> a
-        uninterpret "fp.sqrt" as = let f = case kindOf (head opArgs) of
-                                               KFloat  -> text "sqrtf"
-                                               KDouble -> text "sqrt"
-                                               k       -> die $ "squareRoot on unexpected kind: " ++ show k
-                                   in f <> parens (fsep (punctuate comma as))
-        uninterpret "fp.fma"  as = let f = case kindOf (head opArgs) of
-                                                KFloat  -> text "fmaf"
-                                                KDouble -> text "fma"
-                                                k       -> die $ "fusedMA on unexpected kind: " ++ show k
-                                   in f <> parens (fsep (punctuate comma as))
-        uninterpret s []         = text "/* Uninterpreted constant */" <+> text s
-        uninterpret s as         = text "/* Uninterpreted function */" <+> text s <> parens (fsep (punctuate comma as))
+        p :: Op -> [Doc] -> Doc
         p (ArrRead _)       _  = tbd "User specified arrays (ArrRead)"
         p (ArrEq _ _)       _  = tbd "User specified arrays (ArrEq)"
-        p (FPRound w)       _  = tbd $ "Floating point operations with custom rounding modes (" ++ w ++ ")"
-        p (Uninterpreted s) as = uninterpret s as
+        p (Label s)        [a] = a <+> text "/*" <+> text s <+> text "*/"
+        p (IEEEFP w)        as = handleIEEE w consts (zip opArgs as) var
+        p (IntCast _ 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 Join [a, b]          = join (let (s1 : s2 : _) = opArgs in (s1, s2, a, b))
         p (Rol i) [a]          = rotate True  i a (head opArgs)
@@ -546,18 +644,30 @@
         -- 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] = parens (b <+> text "== 0") <+> text "?" <+> text "0" <+> text ":" <+> parens (a <+> text "/" <+> b)
-        p Rem  [a, b] = parens (b <+> text "== 0") <+> text "?" <+>    a     <+> text ":" <+> parens (a <+> text "%" <+> b)
+        p Quot [a, b] = let k = kindOf (head opArgs)
+                            z = mkConst cfg $ mkConstCW k (0::Integer)
+                        in protectDiv0 k "/" z a b
+        p Rem  [a, b] = protectDiv0 (kindOf (head 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
+        -- 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 o [a, b]
           | Just co <- lookup o cBinOps
           = a <+> text co <+> b
         p o args = die $ "Received operator " ++ show o ++ " applied to " ++ show args
+        -- 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
+                                        KDouble -> res
+                                        _       -> 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
@@ -580,8 +690,8 @@
                         _                           -> tbd $ "Rotation for unbounded quantity: " ++ show (toLeft, i, s)
           where (cop, cop') | toLeft = ("<<", ">>")
                             | True   = (">>", "<<")
-        -- TBD: below we only support the values that SBV actually currently generates.
-        -- we would need to add new ones if we generate others. (Check instances in Data/SBV/BitVectors/Splittable.hs).
+        -- 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")
@@ -592,7 +702,6 @@
                               (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
-                              -- the followings are used by sign-conversions. (Check instances in Data/SBV/BitVectors/SignCast.hs).
                               (63,  0, KBounded False 64) -> text "(SInt64)"  <+> a
                               (63,  0, KBounded True  64) -> text "(SWord64)" <+> a
                               (31,  0, KBounded False 32) -> text "(SInt32)"  <+> a
@@ -664,11 +773,11 @@
              , (True,  text "# include any user-defined .mk file in the current directory.")
              , (True,  text "-include *.mk")
              , (True,  text "")
-             , (True,  text "CC=gcc")
+             , (True,  text "CC?=gcc")
              , (True,  text "CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer")
              , (ifld,  text "LDFLAGS?=" <> text (unwords ldFlags))
-             , (True,  text "AR=ar")
-             , (True,  text "ARFLAGS=cr")
+             , (True,  text "AR?=ar")
+             , (True,  text "ARFLAGS?=cr")
              , (True,  text "")
              , (not ifdr,  text ("all: " ++ liba))
              , (ifdr,      text ("all: " ++ unwords [liba, libd]))
@@ -703,10 +812,6 @@
   where pre =  text "/* Example driver program for" <+> text libName <> text ". */"
             $$ text "/* Automatically generated by SBV. Edit as you see fit! */"
             $$ text ""
-            $$ text "#include <inttypes.h>"
-            $$ text "#include <stdint.h>"
-            $$ text "#include <stdbool.h>"
-            $$ text "#include <math.h>"
             $$ text "#include <stdio.h>"
             $$ inc
         mkDFun (f, [_pre, _header, body, _post]) = [header, body, post]
@@ -730,3 +835,5 @@
                  ptag = "printf(\"" ++ tag ++ "\\n\");"
                  lsep = replicate (length tag) '='
                  psep = "printf(\"" ++ lsep ++ "\\n\");"
+
+{-# ANN module ("HLint: ignore Redundant lambda" :: String) #-}
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
@@ -11,14 +11,9 @@
 
 {-# LANGUAGE FlexibleInstances          #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE CPP                        #-}
 
 module Data.SBV.Compilers.CodeGen where
 
-#if __GLASGOW_HASKELL__ < 710
-import Control.Applicative  (Applicative)
-#endif
-
 import Control.Monad.Trans
 import Control.Monad.State.Lazy
 import Data.Char                 (toLower, isSpace)
@@ -151,9 +146,7 @@
 
 -- | Adds the given lines to the program file generated, useful for generating programs with uninterpreted functions.
 cgAddDecl :: [String] -> SBVCodeGen ()
-cgAddDecl ss = modify (\s -> let old = cgDecls s
-                                 new = if null old then ss else old ++ [""] ++ ss
-                             in s { cgDecls = new })
+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 ()
diff --git a/Data/SBV/Dynamic.hs b/Data/SBV/Dynamic.hs
--- a/Data/SBV/Dynamic.hs
+++ b/Data/SBV/Dynamic.hs
@@ -55,7 +55,7 @@
   , svRotateLeft, svRotateRight
   -- ** Conditionals: Mergeable values
   , svIte, svLazyIte, svSymbolicMerge
-  , svReduceInPathCondition
+  , svIsSatisfiableInCurrentPath
   -- * Uninterpreted sorts, constants, and functions
   , svUninterpreted
   -- * Properties, proofs, and satisfiability
@@ -68,7 +68,7 @@
   -- * Model extraction
 
   -- ** Inspecting proof results
-  , ThmResult(..), SatResult(..), AllSatResult(..), SMTResult(..), SafeResult(..)
+  , ThmResult(..), SatResult(..), AllSatResult(..), SMTResult(..)
 
   -- ** Programmable model extraction
   , genParse, getModel, getModelDictionary
@@ -121,50 +121,39 @@
   , cgAddPrototype, cgAddDecl, cgAddLDFlags
   , 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(..), AllSatResult(..), SafeResult(..), genParse )
-import Data.SBV.Tools.Optimize
-  ( OptimizeOpts(..) )
-import Data.SBV
-  ( sbvCurrentSolver, sbvCheckSolverInstallation, defaultSolverConfig, sbvAvailableSolvers )
+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(..), AllSatResult(..), genParse)
+import Data.SBV.Tools.Optimize (OptimizeOpts(..))
+import Data.SBV                (sbvCurrentSolver, sbvCheckSolverInstallation, defaultSolverConfig, sbvAvailableSolvers)
 
-import qualified Data.SBV as SBV
-  ( SBool, proveWithAll, proveWithAny, satWithAll, satWithAny, allSatWithAll, allSatWithAny )
-import qualified Data.SBV.BitVectors.Data as SBV
-  ( SBV(..) )
-import qualified Data.SBV.BitVectors.Model as SBV
-  ( reduceInPathCondition )
-import qualified Data.SBV.Provers.Prover as SBV
-  ( proveWith, satWith, compileToSMTLib, generateSMTBenchmarks )
-import qualified Data.SBV.SMT.SMT as SBV
-  ( Modelable(getModel, getModelDictionary) )
+import qualified Data.SBV                  as SBV (SBool, proveWithAll, proveWithAny, satWithAll, satWithAny, allSatWithAll, allSatWithAny)
+import qualified Data.SBV.BitVectors.Data  as SBV (SBV(..))
+import qualified Data.SBV.BitVectors.Model as SBV (isSatisfiableInCurrentPath)
+import qualified Data.SBV.Provers.Prover   as SBV (proveWith, satWith, compileToSMTLib, generateSMTBenchmarks)
+import qualified Data.SBV.SMT.SMT          as SBV (Modelable(getModel, getModelDictionary))
 
 -- | Reduce a condition (i.e., try to concretize it) under the given path
-svReduceInPathCondition :: SVal -> SVal
-svReduceInPathCondition t = c
-  where SBV.SBV c = SBV.reduceInPathCondition (SBV.SBV t)
+svIsSatisfiableInCurrentPath :: SVal -> Symbolic Bool
+svIsSatisfiableInCurrentPath = SBV.isSatisfiableInCurrentPath . toSBool
 
 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 booleans:
+-- supported out-of-the box by the SBV library. It takes two arguments:
 --
---    * smtLib2: If 'True', will generate SMT-Lib2 output, otherwise SMT-Lib1 output
+--    * 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 :: Bool   -- ^ 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.)
+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 smtLib2 isSat s = SBV.compileToSMTLib smtLib2 isSat (fmap toSBool s)
+compileToSMTLib version isSat s = SBV.compileToSMTLib version isSat (fmap 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
diff --git a/Data/SBV/Examples/BitPrecise/Legato.hs b/Data/SBV/Examples/BitPrecise/Legato.hs
--- a/Data/SBV/Examples/BitPrecise/Legato.hs
+++ b/Data/SBV/Examples/BitPrecise/Legato.hs
@@ -166,7 +166,7 @@
   where v  = peek a m
         c  = getFlag FlagC m
         v' = setBitTo (v `rotateR` 1) 7 c
-        c' = sbvTestBit v 0
+        c' = sTestBit v 0
 
 -- | ROR, register version: Same as 'rorM', except through register @r@.
 rorR :: Register -> Instruction
@@ -174,7 +174,7 @@
   where v  = getReg r m
         c  = getFlag FlagC m
         v' = setBitTo (v `rotateR` 1) 7 c
-        c' = sbvTestBit v 0
+        c' = sTestBit v 0
 
 -- | BCC: branch to label @l@ if the carry flag is false
 bcc :: Program -> Instruction
diff --git a/Data/SBV/Examples/BitPrecise/MultMask.hs b/Data/SBV/Examples/BitPrecise/MultMask.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Examples/BitPrecise/MultMask.hs
@@ -0,0 +1,50 @@
+-----------------------------------------------------------------------------
+-- |
+-- 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
--- a/Data/SBV/Examples/BitPrecise/PrefixSum.hs
+++ b/Data/SBV/Examples/BitPrecise/PrefixSum.hs
@@ -18,8 +18,7 @@
 module Data.SBV.Examples.BitPrecise.PrefixSum where
 
 import Data.SBV
-import qualified Data.SBV.Provers.Yices as Yices
-import Data.SBV.Internals(runSymbolic)
+import Data.SBV.Internals (runSymbolic)
 
 ----------------------------------------------------------------------
 -- * Formalizing power-lists
@@ -93,119 +92,6 @@
 thm2 = prove $ flIsCorrect 16 (0, smax)
 
 ----------------------------------------------------------------------
--- * Attempt at proving for arbitrary operators
-----------------------------------------------------------------------
--- | Try proving correctness for an arbitrary operator. This proof will /not/ go through since the
--- SMT solver does not know that the operator associative and has the given left-unit element. We have:
---
--- >>> thm3
--- Falsifiable. Counter-example:
---   s0 = 0 :: Word32
---   s1 = 0 :: Word32
---   s2 = 0 :: Word32
---   s3 = 0 :: Word32
---   s4 = 1073741824 :: Word32
---   s5 = 0 :: Word32
---   s6 = 0 :: Word32
---   s7 = 0 :: Word32
---   -- uninterpreted: u
---        u  = 0
---   -- uninterpreted: flOp
---        flOp 0          0          = 2147483648
---        flOp 0          1073741824 = 3221225472
---        flOp 2147483648 0          = 3221225472
---        flOp 2147483648 1073741824 = 1073741824
---        flOp _          _          = 0
---
--- You can verify that the function @flOp@ is indeed not associative:
---
--- @
---   ghci> flOp 3221225472 (flOp 2147483648 1073741824)
---   0
---   ghci> flOp (flOp 3221225472 2147483648) 1073741824
---   3221225472
--- @
---
--- Also, the unit @0@ is clearly not a left-unit for @flOp@, as the last
--- equation for @flOp@ will simply map many elements to @0@.
--- (NB. We need to use yices for this proof as the uninterpreted function
--- examples are only supported through the yices interface currently.)
-thm3 :: IO ThmResult
-thm3 = proveWith yicesSMT09 $ do args :: PowerList SWord32 <- mkForallVars 8
-                                 return $ ps (u, op) args .== lf (u, op) args
-  where op :: SWord32 -> SWord32 -> SWord32
-        op = uninterpret "flOp"
-        u :: SWord32
-        u = uninterpret "u"
-
-----------------------------------------------------------------------
--- * Proving for arbitrary operators using axioms
-----------------------------------------------------------------------
--- | Generate an instance of the prefix-sum problem for an arbitrary operator, by telling the SMT solver
--- the necessary axioms for associativity and left-unit. The first argument states how wide the power list should be.
-genPrefixSumInstance :: Int -> Symbolic SBool
-genPrefixSumInstance n = do
-     args :: PowerList SWord32 <- mkForallVars n
-     addAxiom "flOp is associative"     assocAxiom
-     addAxiom "u is left-unit for flOp" leftUnitAxiom
-     return $ ps (u, op) args .== lf (u, op) args
-  where op :: SWord32 -> SWord32 -> SWord32
-        op = uninterpret "flOp"
-        u  :: SWord32
-        u  = uninterpret "u"
-        -- axioms.. These are a bit brittle. Note that we have to
-        -- refer to the uninterpreted symbols with the prefix "uninterpreted_" when
-        -- used with the SMTLib1 interface to avoid any collision. This is admittedly
-        -- ugly, but it'll do till we get a sub-DSL for writing proper axioms (if ever)
-        assocAxiom :: [String]
-        assocAxiom = [
-             ":assumption (forall (?x BitVec[32]) (?y BitVec[32]) (?z BitVec[32])"
-           , "                    (= (uninterpreted_flOp ?x (uninterpreted_flOp ?y ?z))"
-           , "                       (uninterpreted_flOp (uninterpreted_flOp ?x ?y) ?z)"
-           , "                    )"
-           , "            )"
-          ]
-        leftUnitAxiom :: [String]
-        leftUnitAxiom = [
-            ":assumption (forall (?x BitVec[32]) (= (uninterpreted_flOp uninterpreted_u ?x) ?x))"
-          ]
-
--- | Prove the generic problem for powerlists of given sizes. Note that
--- this only works with Yices-1 currently.
---
--- We have:
---
--- >>> prefixSum 2
--- Q.E.D.
---
--- >>> prefixSum 4
--- Q.E.D.
---
--- Note that these proofs tend to run long. Also, Yices ran out of memory
--- and crashed on my box when I tried for size @8@, after running for about 2.5 minutes..
-prefixSum :: Int -> IO ThmResult
-prefixSum i
-  -- Fast way of checking whether a number is a power of two, see: <http://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2>
-  | i <= 1 || (i .&. (i-1)) /= 0
-  = error $ "prefixSum: input must be a power of 2 larger than 2, received: " ++ show i
-  | True
-  = proveWith yices1029 $ genPrefixSumInstance i
-
--- | Old version of Yices that supports quantified axioms in SMT-Lib1
-yices1029 :: SMTConfig
-yices1029 = yices {solver = yices'}
-  where yices' = Yices.yices { options    = ["-tc", "-smt", "-e"]
-                             , executable = "yices-1.0.29"
-                             }
-
--- | Another old version of yices, suitable for the non-axiom based problem
-yicesSMT09 :: SMTConfig
-yicesSMT09 = yices {solver = yices'}
-  where yices' = Yices.yices { options    = ["-m"]
-                             , executable = "yices-SMT09"
-                             }
-
-----------------------------------------------------------------------
 -- * Inspecting symbolic traces
 ----------------------------------------------------------------------
 
@@ -255,8 +141,8 @@
 --   s18
 ladnerFischerTrace :: Int -> IO ()
 ladnerFischerTrace n = gen >>= print
-  where gen = runSymbolic (True, Nothing) $ do args :: [SWord8] <- mkForallVars n
-                                               mapM_ output $ lf (0, (+)) args
+  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:
@@ -300,7 +186,7 @@
 --
 scanlTrace :: Int -> IO ()
 scanlTrace n = gen >>= print
-  where gen = runSymbolic (True, Nothing) $ do args :: [SWord8] <- mkForallVars n
-                                               mapM_ output $ ps (0, (+)) args
+  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
--- a/Data/SBV/Examples/CodeGeneration/AddSub.hs
+++ b/Data/SBV/Examples/CodeGeneration/AddSub.hs
@@ -26,7 +26,7 @@
 -- # include any user-defined .mk file in the current directory.
 -- -include *.mk
 -- <BLANKLINE>
--- CC=gcc
+-- CC?=gcc
 -- CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
 -- <BLANKLINE>
 -- all: addSub_driver
@@ -55,6 +55,7 @@
 -- #include <inttypes.h>
 -- #include <stdint.h>
 -- #include <stdbool.h>
+-- #include <string.h>
 -- #include <math.h>
 -- <BLANKLINE>
 -- /* The boolean type */
@@ -88,10 +89,6 @@
 -- /* Example driver program for addSub. */
 -- /* Automatically generated by SBV. Edit as you see fit! */
 -- <BLANKLINE>
--- #include <inttypes.h>
--- #include <stdint.h>
--- #include <stdbool.h>
--- #include <math.h>
 -- #include <stdio.h>
 -- #include "addSub.h"
 -- <BLANKLINE>
@@ -112,10 +109,6 @@
 -- == BEGIN: "addSub.c" ================
 -- /* File: "addSub.c". Automatically generated by SBV. Do not edit! */
 -- <BLANKLINE>
--- #include <inttypes.h>
--- #include <stdint.h>
--- #include <stdbool.h>
--- #include <math.h>
 -- #include "addSub.h"
 -- <BLANKLINE>
 -- void addSub(const SWord8 x, const SWord8 y, SWord8 *sum,
diff --git a/Data/SBV/Examples/CodeGeneration/PopulationCount.hs b/Data/SBV/Examples/CodeGeneration/PopulationCount.hs
--- a/Data/SBV/Examples/CodeGeneration/PopulationCount.hs
+++ b/Data/SBV/Examples/CodeGeneration/PopulationCount.hs
@@ -88,7 +88,7 @@
 -- # include any user-defined .mk file in the current directory.
 -- -include *.mk
 -- <BLANKLINE>
--- CC=gcc
+-- CC?=gcc
 -- CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
 -- <BLANKLINE>
 -- all: popCount_driver
@@ -117,6 +117,7 @@
 -- #include <inttypes.h>
 -- #include <stdint.h>
 -- #include <stdbool.h>
+-- #include <string.h>
 -- #include <math.h>
 -- <BLANKLINE>
 -- /* The boolean type */
@@ -149,10 +150,6 @@
 -- /* Example driver program for popCount. */
 -- /* Automatically generated by SBV. Edit as you see fit! */
 -- <BLANKLINE>
--- #include <inttypes.h>
--- #include <stdint.h>
--- #include <stdbool.h>
--- #include <math.h>
 -- #include <stdio.h>
 -- #include "popCount.h"
 -- <BLANKLINE>
@@ -168,10 +165,6 @@
 -- == BEGIN: "popCount.c" ================
 -- /* File: "popCount.c". Automatically generated by SBV. Do not edit! */
 -- <BLANKLINE>
--- #include <inttypes.h>
--- #include <stdint.h>
--- #include <stdbool.h>
--- #include <math.h>
 -- #include "popCount.h"
 -- <BLANKLINE>
 -- SWord8 popCount(const SWord64 x)
diff --git a/Data/SBV/Examples/CodeGeneration/Uninterpreted.hs b/Data/SBV/Examples/CodeGeneration/Uninterpreted.hs
--- a/Data/SBV/Examples/CodeGeneration/Uninterpreted.hs
+++ b/Data/SBV/Examples/CodeGeneration/Uninterpreted.hs
@@ -13,10 +13,9 @@
 -- purposes, such as efficiency, or reliability.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE CPP #-}
-
 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.
@@ -37,13 +36,7 @@
         -- 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)
-#if __GLASGOW_HASKELL__ >= 708
-        bs x = maybe (error "SBV.Example.CodeGeneration.Uninterpreted.shiftLeft: Unexpected non-finite usage!") id (bitSizeMaybe x)
-#else
-        bs = bitSize
-#endif
-
-
+        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,
diff --git a/Data/SBV/Examples/Existentials/CRCPolynomial.hs b/Data/SBV/Examples/Existentials/CRCPolynomial.hs
--- a/Data/SBV/Examples/Existentials/CRCPolynomial.hs
+++ b/Data/SBV/Examples/Existentials/CRCPolynomial.hs
@@ -71,7 +71,7 @@
                         -- 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 $ sbvTestBit p 0 &&& crcGood hd p s r
+                        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 ()
diff --git a/Data/SBV/Examples/Misc/Enumerate.hs b/Data/SBV/Examples/Misc/Enumerate.hs
--- a/Data/SBV/Examples/Misc/Enumerate.hs
+++ b/Data/SBV/Examples/Misc/Enumerate.hs
@@ -13,6 +13,7 @@
 -----------------------------------------------------------------------------
 
 {-# LANGUAGE DeriveDataTypeable  #-}
+{-# LANGUAGE DeriveAnyClass      #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 
 module Data.SBV.Examples.Misc.Enumerate where
@@ -23,27 +24,12 @@
 -- | 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 slew of classes we need: 'Eq', 'Ord', 'Data', 'Typeable', 'Read',
--- and 'Show'. For symbolic enumerated types, you should
--- always let GHC derive these instances. Aside from these, we also need
--- instances for 'SymWord', 'HasKind' and 'SatModel'. Again, the default definitions suffice
--- so the actual declarations are straightforward.
+-- 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@ set.
-data E = A | B | C
-       deriving (Eq, Ord, Data, Typeable, Read, Show)
-
--- | The 'SymWord' instance for 'E'. In GHC 7.10 and forward, we'll be able to add these to the @deriving@ clause as well.
-instance SymWord E
-
--- | The 'HasKind' instance for 'E'. In GHC 7.10 and forward, we'll be able to add these to the @deriving@ clause as well.
-instance HasKind E
-
--- | The 'SatModel' instance for 'E'. In GHC 7.10 and forward, we'll be able to add these to the @deriving@ clause as well.
--- Note that the 'SatModel' instance is only needed if you use 'getModel' and its friends; but it does not hurt to always
--- derive the default definitions.
-instance SatModel E
+-- 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
diff --git a/Data/SBV/Examples/Misc/Floating.hs b/Data/SBV/Examples/Misc/Floating.hs
--- a/Data/SBV/Examples/Misc/Floating.hs
+++ b/Data/SBV/Examples/Misc/Floating.hs
@@ -24,20 +24,20 @@
 -- * FP addition is not associative
 -----------------------------------------------------------------------------
 
--- | Prove that floating point addition is not associative. We have:
+-- | 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
+-- >>> prove $ assocPlus (0/0)
 -- Falsifiable. Counter-example:
---   s0 = -9.62965e-35 :: Float
---   s1 = Infinity :: Float
---   s2 = -Infinity :: Float
+--   s0 = 0.0 :: Float
+--   s1 = 0.0 :: Float
 --
 -- Indeed:
 --
--- >>> let i = 1/0 :: Float
--- >>> (-9.62965e-35 + (i + (-i)))
+-- >>> let i = 0/0 :: Float
+-- >>> i + (0.0 + 0.0)
 -- NaN
--- >>> ((-9.62965e-35 + i) + (-i))
+-- >>> ((i + 0.0) + 0.0)
 -- NaN
 --
 -- But keep in mind that @NaN@ does not equal itself in the floating point world! We have:
@@ -48,7 +48,7 @@
 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 'isPointFP', which is true of a floating point
+-- 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.)
 --
@@ -56,16 +56,16 @@
 --
 -- >>> assocPlusRegular
 -- Falsifiable. Counter-example:
---   x = -1.0491915e7 :: Float
---   y = 1967115.5 :: Float
---   z = 982003.94 :: Float
+--   x = -1.5991211e-2 :: Float
+--   y = 131071.99 :: Float
+--   z = -131069.99 :: Float
 --
 -- Indeed, we have:
 --
--- >>> ((-1.0491915e7) + (1967115.5 + 982003.94)) :: Float
--- -7542795.5
--- >>> (((-1.0491915e7) + 1967115.5) + 982003.94) :: Float
--- -7542796.0
+-- >>> ((-1.5991211e-2) + (131071.99 + (-131069.99))) :: Float
+-- 1.9840088
+-- >>> ((-1.5991211e-2) + 131071.99) + (-131069.99) :: Float
+-- 1.984375
 --
 -- Note the significant difference between two additions!
 assocPlusRegular :: IO ThmResult
@@ -73,8 +73,8 @@
                               let lhs = x+(y+z)
                                   rhs = (x+y)+z
                               -- make sure we do not overflow at the intermediate points
-                              constrain $ isPointFP lhs
-                              constrain $ isPointFP rhs
+                              constrain $ fpIsPoint lhs
+                              constrain $ fpIsPoint rhs
                               return $ lhs .== rhs
 
 -----------------------------------------------------------------------------
@@ -87,23 +87,23 @@
 --
 -- >>> nonZeroAddition
 -- Falsifiable. Counter-example:
---   a = -2.0 :: Float
---   b = -3.0e-45 :: Float
+--   a = 5.1705105e-26 :: Float
+--   b = -3.8518597e-34 :: Float
 --
 -- Indeed, we have:
 --
--- >>> (-2.0) + (-3.0e-45) == (-2.0 :: Float)
+-- >>> (5.1705105e-26 + (-3.8518597e-34)) == (5.1705105e-26 :: Float)
 -- True
 --
 -- But:
 --
--- >>> -3.0e-45 == (0::Float)
+-- >>> -3.8518597e-34 == (0::Float)
 -- False
 --
 nonZeroAddition :: IO ThmResult
 nonZeroAddition = prove $ do [a, b] <- sFloats ["a", "b"]
-                             constrain $ isPointFP a
-                             constrain $ isPointFP b
+                             constrain $ fpIsPoint a
+                             constrain $ fpIsPoint b
                              constrain $ a + b .== a
                              return $ b .== 0
 
@@ -118,17 +118,17 @@
 --
 -- >>> multInverse
 -- Falsifiable. Counter-example:
---   a = -2.0445642768532407e154 :: Double
+--   a = 1.1058928764217435e308 :: Double
 --
 -- Indeed, we have:
 --
--- >>> let a = -2.0445642768532407e154 :: Double
+-- >>> let a = 1.1058928764217435e308 :: Double
 -- >>> a * (1/a)
--- 0.9999999999999999
+-- 0.9999999999999998
 multInverse :: IO ThmResult
 multInverse = prove $ do a <- sDouble "a"
-                         constrain $ isPointFP a
-                         constrain $ isPointFP (1/a)
+                         constrain $ fpIsPoint a
+                         constrain $ fpIsPoint (1/a)
                          return $ a * (1/a) .== 1
 
 -----------------------------------------------------------------------------
@@ -145,22 +145,22 @@
 --
 -- >>> roundingAdd
 -- Satisfiable. Model:
---   rm = RoundTowardPositive :: RoundingMode
---   x = 246080.08 :: Float
---   y = 16255.999 :: Float
+--   rm = RoundNearestTiesToAway :: RoundingMode
+--   x = 2.0644195e19 :: Float
+--   y = -2.1974389e18 :: Float
 --
 -- Unfortunately we can't directly validate this result at the Haskell level, as Haskell only supports
 -- 'RoundNearestTiesToEven'. We have:
 --
--- >>> (246080.08 + 16255.999) :: Float
--- 262336.06
+-- >>> (2.0644195e19 + (-2.1974389e18)) :: Float
+-- 1.8446757e19
 --
--- While we cannot directly see the result when the mode is 'RoundTowardPositive' in Haskell, we can use
+-- While we cannot directly see the result when the mode is 'RoundNearestTiesToAway' in Haskell, we can use
 -- SBV to provide us with that result thusly:
 --
--- >>> sat $ \z -> z .== fpAdd sRoundTowardPositive 246080.08 (16255.999::SFloat)
+-- >>> sat $ \z -> z .== fpAdd sRoundNearestTiesToAway 2.0644195e19 (-2.1974389e18 :: SFloat)
 -- Satisfiable. Model:
---   s0 = 262336.1 :: Float
+--   s0 = 1.8446755e19 :: Float
 --
 -- We can see why these two resuls are indeed different. To see why, one would have to convert the
 -- individual numbers to Float's, which would induce rounding-errors, add them up, and round-back;
@@ -175,6 +175,6 @@
                        y <- sFloat "y"
                        let lhs = fpAdd m x y
                        let rhs = x + y
-                       constrain $ isPointFP lhs
-                       constrain $ isPointFP rhs
+                       constrain $ fpIsPoint lhs
+                       constrain $ fpIsPoint rhs
                        return $ lhs ./= rhs
diff --git a/Data/SBV/Examples/Misc/SBranch.hs b/Data/SBV/Examples/Misc/SBranch.hs
deleted file mode 100644
--- a/Data/SBV/Examples/Misc/SBranch.hs
+++ /dev/null
@@ -1,73 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.Examples.Misc.SBranch
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Illustrates the use of 'sBranch', as a means of dealing with certain cases
--- of the symbolic-termination problem.
------------------------------------------------------------------------------
-
-module Data.SBV.Examples.Misc.SBranch where
-
-import Data.SBV
-
--- | A fast implementation of population-count. Note that SBV already provides
--- this functionality via 'sbvPopCount', using simple expansion and counting
--- algorithm. 'sbvPopCount' is linear in the size of the input, i.e., a 32-bit
--- word would take 32 additions. This implementation here is /faster/ in the
--- sense that it takes as many additions as there are set-bits in the given word.
---
--- Of course, the issue is that this definition is recursive, and the usual
--- definition via 'ite' would never symbolically terminate: Recursion is done
--- on the input argument: In each recursive call, we /reduce/ the value @n@
--- to @n .&. (n-1)@. This eliminates one set-bit in the input. However, this
--- claim is far from obvious. By the use of 'sBranch' we tell SBV to call
--- the SMT solver in each test to ensure we only evaluate the branches we need,
--- thus avoiding the symbolic-termination issue. In a sense, the SMT solvers
--- proves that the implementation terminates for all valid inputs.
---
--- Note that replacing 'sBranch' in this implementation with 'ite' would cause
--- symbolic-termination to loop forever. Of course, this does /not/ mean that
--- 'sBranch' is fast: It is costly to make external calls to the solver for
--- each branch, so use with care.
-bitCount :: SWord32 -> SWord8
-bitCount = go 0
-  where go c n = sBranch (n .== 0) c (go (c+1) (n .&. (n-1)))
-
--- | Prove that the 'bitCount' function implemented here is equivalent to
--- the internal "slower" implementation. We have:
---
--- >>> prop
--- Q.E.D.
-prop :: IO ThmResult
-prop = prove $ \n -> bitCount n .== sbvPopCount n
-
--- | Illustrates the use of path-conditions in avoiding infeasible paths in symbolic
--- simulation. If we used 'ite' instead of 'sBranch' in the else-branch of the
--- implementation of 'path' symbolic simulation would have encountered the 'error' call, and
--- hence would have failed. But 'sBranch' keeps track of the path condition, and can
--- successfully determine that this path will never be taken, and hence avoids the problem.
--- Note that we can freely mix/match 'ite' and 'sBranch' calls; path conditions will be
--- tracked in both cases. In fact, use of 'ite' is advisable if we know for a fact that
--- both branches are feasible, as it avoids the external call. 'sBranch' will have the
--- same result, albeit it'll cost more.
-path :: SWord8 -> SWord8
-path x = ite (x .> 5)
-             10
-             (sBranch (x .> 10)
-                      (error "this case is not reachable!")  -- NB. x .> 5 fails, so can't be .> 10 here
-                      20)
-
--- | Prove that 'path' always produces either @10@ or @20@, i.e., symbolic simulation will
--- not fail due to the 'error' call. We have:
---
--- >>> pathCheck
--- Q.E.D.
---
--- Were we to use 'ite' instead of 'sBranch' in the implementation of 'path', this expression
--- would have caused an exception to be raised at symbolic simulation time.
-pathCheck :: IO ThmResult
-pathCheck = prove $ \n -> let pn = path n in pn .== 10 ||| pn .== 20
diff --git a/Data/SBV/Examples/Misc/Word4.hs b/Data/SBV/Examples/Misc/Word4.hs
--- a/Data/SBV/Examples/Misc/Word4.hs
+++ b/Data/SBV/Examples/Misc/Word4.hs
@@ -10,7 +10,6 @@
 -- used with SBV.
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE CPP                   #-}
 {-# LANGUAGE DeriveDataTypeable    #-}
 {-# LANGUAGE FlexibleInstances     #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
@@ -94,9 +93,7 @@
   Word4 x `rotate` i    = word4 (x `shiftL` k .|. x `shiftR` (4-k))
                             where k = i .&. 3
   bitSize _             = 4
-#if __GLASGOW_HASKELL__ >= 708
   bitSizeMaybe _        = Just 4
-#endif
   isSigned _            = False
   testBit (Word4 x)     = testBit x
   bit i                 = word4 (bit i)
diff --git a/Data/SBV/Examples/Puzzles/Birthday.hs b/Data/SBV/Examples/Puzzles/Birthday.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Examples/Puzzles/Birthday.hs
@@ -0,0 +1,145 @@
+-----------------------------------------------------------------------------
+-- |
+-- 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/Fish.hs b/Data/SBV/Examples/Puzzles/Fish.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Examples/Puzzles/Fish.hs
@@ -0,0 +1,108 @@
+-----------------------------------------------------------------------------
+-- |
+-- 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/SendMoreMoney.hs b/Data/SBV/Examples/Puzzles/SendMoreMoney.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Examples/Puzzles/SendMoreMoney.hs
@@ -0,0 +1,45 @@
+-----------------------------------------------------------------------------
+-- |
+-- 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/U2Bridge.hs b/Data/SBV/Examples/Puzzles/U2Bridge.hs
--- a/Data/SBV/Examples/Puzzles/U2Bridge.hs
+++ b/Data/SBV/Examples/Puzzles/U2Bridge.hs
@@ -9,9 +9,10 @@
 -- The famous U2 bridge crossing puzzle: <http://www.brainj.net/puzzle.php?id=u2>
 -----------------------------------------------------------------------------
 
+{-# LANGUAGE DeriveAnyClass       #-}
+{-# LANGUAGE DeriveDataTypeable   #-}
 {-# LANGUAGE FlexibleInstances    #-}
 {-# LANGUAGE TypeSynonymInstances #-}
-{-# LANGUAGE DeriveDataTypeable   #-}
 
 module Data.SBV.Examples.Puzzles.U2Bridge where
 
@@ -27,17 +28,7 @@
 
 -- | 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 (Data, Typeable, Ord, Eq, Read, Show)
-
--- | Make 'U2Member' a valid symbolic element. In GHC 7.10; we'll be able to derive this automatically.
-instance SymWord  U2Member
-
--- | Make 'U2Member' have a default kind. In GHC 7.10; we'll be able to derive this automatically.
-instance HasKind  U2Member
-
--- | Make 'U2Member' part of model-generation facilities. In GHC 7.10; we'll be able to derive this automatically.
-instance SatModel U2Member
+data U2Member = Bono | Edge | Adam | Larry deriving (Eq, Ord, Show, Read, Data, SymWord, HasKind, SatModel)
 
 -- | Symbolic shorthand for a 'U2Member'
 type SU2Member = SBV U2Member
@@ -67,17 +58,7 @@
                                   (literal (crossTime Larry)) -- Must be Larry
 
 -- | Location of the flash
-data Location = Here | There
-              deriving (Data, Typeable, Ord, Eq, Read, Show)
-
--- | Make 'Location' a valid symbolic element. In GHC 7.10; we'll be able to derive this automatically.
-instance SymWord  Location
-
--- | Make 'Location' have a default kind. In GHC 7.10; we'll be able to derive this automatically.
-instance HasKind  Location
-
--- | Make 'Location' part of model-generation facilities. In GHC 7.10; we'll be able to derive this automatically.
-instance SatModel Location
+data Location = Here | There deriving (Eq, Ord, Show, Read, Data, SymWord, HasKind, SatModel)
 
 -- | Symbolic variant of 'Location'
 type SLocation = SBV Location
@@ -260,16 +241,16 @@
 -- Checking for solutions with 5 moves.
 -- Solution #1: 
 --  0 --> Edge, Bono
---  2 <-- Bono
---  3 --> Larry, Adam
--- 13 <-- Edge
+--  2 <-- Edge
+--  4 --> Larry, Adam
+-- 14 <-- Bono
 -- 15 --> Edge, Bono
 -- Total time: 17
 -- Solution #2: 
 --  0 --> Edge, Bono
---  2 <-- Edge
---  4 --> Larry, Adam
--- 14 <-- Bono
+--  2 <-- Bono
+--  3 --> Larry, Adam
+-- 13 <-- Edge
 -- 15 --> Edge, Bono
 -- Total time: 17
 -- Found: 2 solutions with 5 moves.
diff --git a/Data/SBV/Examples/Uninterpreted/Deduce.hs b/Data/SBV/Examples/Uninterpreted/Deduce.hs
--- a/Data/SBV/Examples/Uninterpreted/Deduce.hs
+++ b/Data/SBV/Examples/Uninterpreted/Deduce.hs
@@ -11,6 +11,7 @@
 -- essentially showing how to show the required deduction using SBV.
 -----------------------------------------------------------------------------
 
+{-# LANGUAGE DeriveAnyClass     #-}
 {-# LANGUAGE DeriveDataTypeable #-}
 
 module Data.SBV.Examples.Uninterpreted.Deduce where
@@ -28,14 +29,7 @@
 
 -- | The uninterpreted sort 'B', corresponding to the carrier.
 -- To prevent SBV from translating it to an enumerated type, we simply attach an unused field
-data B = B ()
-        deriving (Eq, Ord, Data, Typeable, Read, Show)
-
--- | Default instance declaration for 'SymWord'
-instance SymWord  B
-
--- | Default instance declaration for 'HasKind'
-instance HasKind  B
+data B = B () deriving (Eq, Ord, Show, Read, Data, SymWord, HasKind)
 
 -- | Handy shortcut for the type of symbolic values over 'B'
 type SB = SBV B
diff --git a/Data/SBV/Examples/Uninterpreted/Function.hs b/Data/SBV/Examples/Uninterpreted/Function.hs
--- a/Data/SBV/Examples/Uninterpreted/Function.hs
+++ b/Data/SBV/Examples/Uninterpreted/Function.hs
@@ -12,7 +12,6 @@
 module Data.SBV.Examples.Uninterpreted.Function where
 
 import Data.SBV
-import qualified Data.SBV.Provers.Yices as Yices
 
 -- | An uninterpreted function
 f :: SWord8 -> SWord8 -> SWord16
@@ -24,35 +23,3 @@
 -- Q.E.D.
 thmGood :: SWord8 -> SWord8 -> SWord8 -> SBool
 thmGood x y z = x .== y+2 ==> f x z .== f (y + 2) z
-
--- | Asserts that @f@ is commutative; which is not necessarily true!
--- Indeed, the SMT solver returns a counter-example function that is
--- not commutative. (Note that we have to use Yices as Z3 function
--- counterexamples are not yet supported by sbv.) We have:
---
---
--- >>> proveWith yicesSMT09 $ forAll ["x", "y"] thmBad
--- Falsifiable. Counter-example:
---   x = 0 :: Word8
---   y = 128 :: Word8
---   -- uninterpreted: f
---        f 128 0 = 32768
---        f _   _ = 0
---
--- Note how the counterexample function @f@ returned by Yices violates commutativity;
--- thus providing evidence that the asserted theorem is not valid.
-thmBad :: SWord8 -> SWord8 -> SBool
-thmBad x y = f x y .== f y x
-
--- | Old version of Yices, which supports nice output for uninterpreted functions.
-yicesSMT09 :: SMTConfig
-yicesSMT09 = yices {solver = yices'}
-  where yices' = Yices.yices { options    = ["-m"]
-                             , executable = "yices-SMT09"
-                             }
-
-----------------------------------------------------------------------
--- * Inspecting symbolic traces
-----------------------------------------------------------------------
-
--- | A symbolic trace can help illustrate the action of Ladner-Fischer. This
diff --git a/Data/SBV/Examples/Uninterpreted/Sort.hs b/Data/SBV/Examples/Uninterpreted/Sort.hs
--- a/Data/SBV/Examples/Uninterpreted/Sort.hs
+++ b/Data/SBV/Examples/Uninterpreted/Sort.hs
@@ -9,6 +9,7 @@
 -- Demonstrates uninterpreted sorts, together with axioms.
 -----------------------------------------------------------------------------
 
+{-# LANGUAGE DeriveAnyClass     #-}
 {-# LANGUAGE DeriveDataTypeable #-}
 
 module Data.SBV.Examples.Uninterpreted.Sort where
@@ -20,16 +21,7 @@
 -- 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
-data Q = Q () deriving (Eq, Ord, Data, Typeable, Read, Show)
-
--- | We need 'SymWord' and 'HasKind' instances, but default definitions
--- are always sufficient for uninterpreted sorts, so all we do is to
--- declare them as such. Note that, starting with GHC 7.6.1, we will
--- be able to simply derive these classes as well. (See <http://hackage.haskell.org/trac/ghc/ticket/5462>.)
-instance SymWord Q
-
--- | 'HasKind' instance is again straightforward, no specific implementation needed.
-instance HasKind Q
+data Q = Q () deriving (Eq, Ord, Data, Read, Show, SymWord, HasKind)
 
 -- | Declare an uninterpreted function that works over Q's
 f :: SBV Q -> SBV Q
diff --git a/Data/SBV/Examples/Uninterpreted/UISortAllSat.hs b/Data/SBV/Examples/Uninterpreted/UISortAllSat.hs
--- a/Data/SBV/Examples/Uninterpreted/UISortAllSat.hs
+++ b/Data/SBV/Examples/Uninterpreted/UISortAllSat.hs
@@ -24,7 +24,7 @@
 -- constructors.
 data L = Nil
        | Cons Int L
-       deriving (Eq, Ord, Data, Typeable, Read, Show)
+       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.
diff --git a/Data/SBV/Internals.hs b/Data/SBV/Internals.hs
--- a/Data/SBV/Internals.hs
+++ b/Data/SBV/Internals.hs
@@ -13,7 +13,7 @@
 
 module Data.SBV.Internals (
   -- * Running symbolic programs /manually/
-  Result, SBVRunMode(..), runSymbolic, runSymbolic'
+  Result, SBVRunMode(..), Symbolic, runSymbolic, runSymbolic'
   -- * Other internal structures useful for low-level programming
   , SBV(..), slet, CW(..), Kind(..), CWVal(..), AlgReal(..), Quantifier(..), mkConstCW, genVar, genVar_
   , liftQRem, liftDMod, symbolicMergeWithKind
@@ -25,9 +25,11 @@
   , ites, mdp, addPoly
   -- * Compilation to C
   , compileToC', compileToCLib', CgPgmBundle(..), CgPgmKind(..)
+  -- * Various math utilities around floats
+  , module Data.SBV.Utils.Numeric
   ) where
 
-import Data.SBV.BitVectors.Data       (Result, SBVRunMode(..), runSymbolic, runSymbolic', SBV(..), CW(..), Kind(..), CWVal(..), AlgReal(..), Quantifier(..), mkConstCW)
+import Data.SBV.BitVectors.Data       (Result, Symbolic, SBVRunMode(..), runSymbolic, runSymbolic', SBV(..), CW(..), Kind(..), CWVal(..), AlgReal(..), Quantifier(..), mkConstCW)
 import Data.SBV.BitVectors.Data       (cache, sbvToSW, newExpr, normCW, SBVExpr(..), Op(..), SBVType(..), newUninterpreted, forceSWArg)
 import Data.SBV.BitVectors.Model      (genVar, genVar_, slet, liftQRem, liftDMod, symbolicMergeWithKind, genLiteral, genFromCW, genMkSymVar)
 import Data.SBV.BitVectors.Splittable (checkAndConvert)
@@ -35,3 +37,4 @@
 import Data.SBV.Compilers.CodeGen     (CgPgmBundle(..), CgPgmKind(..))
 import Data.SBV.SMT.SMT               (genParse)
 import Data.SBV.Tools.Polynomial      (ites, mdp, addPoly)
+import Data.SBV.Utils.Numeric
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
@@ -9,72 +9,33 @@
 -- The connection to the ABC verification and synthesis tool
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE ScopedTypeVariables #-}
-
 module Data.SBV.Provers.ABC(abc) where
 
-import qualified Control.Exception as C
-
-import Data.Function      (on)
-import Data.List          (intercalate, sortBy)
-import System.Environment (getEnv)
-
 import Data.SBV.BitVectors.Data
-import Data.SBV.BitVectors.PrettyNum (mkSkolemZero)
 import Data.SBV.SMT.SMT
-import Data.SBV.SMT.SMTLib
-import Data.SBV.Utils.Lib (splitArgs)
 
 -- | The description of abc. The default executable is @\"abc\"@,
 -- which must be in your path. You can use the @SBV_ABC@ environment
--- variable to point to the executable on your system.  There are no
--- default options. You can use the @SBV_ABC_OPTIONS@ environment
--- variable to override the options.
+-- variable to point to the executable on your system.  The default
+-- options are @-S \"%blast; &sweep -C 5000; &syn4; &cec -s -m -C 2000\"@.
+-- You can use the @SBV_ABC_OPTIONS@ environment variable to override the options.
 abc :: SMTSolver
 abc = SMTSolver {
-           name           = ABC
-         , executable     = "abc"
-         , options        = ["-S", "%blast; &sweep -C 5000; &syn4; &cec -s -m -C 2000"]
-         , engine         = \cfg isSat qinps modelMap skolemMap pgm -> do
-                                    execName <-                   getEnv "SBV_ABC"          `C.catch` (\(_ :: C.SomeException) -> return (executable (solver cfg)))
-                                    execOpts <- (splitArgs `fmap` getEnv "SBV_ABC_OPTIONS") `C.catch` (\(_ :: C.SomeException) -> return (options (solver cfg)))
-                                    let cfg' = cfg { solver = (solver cfg) {executable = execName, options = execOpts} }
-                                        tweaks = case solverTweaks cfg' of
-                                                   [] -> ""
-                                                   ts -> unlines $ "; --- user given solver tweaks ---" : ts ++ ["; --- end of user given tweaks ---"]
-                                        script = SMTScript {scriptBody = tweaks ++ pgm, scriptModel = Just (cont (roundingMode cfg) skolemMap)}
-                                    standardSolver cfg' script id (ProofError cfg') (interpretSolverOutput cfg' (extractMap isSat qinps modelMap))
-         , xformExitCode  = id
-         , capabilities   = SolverCapabilities {
-                                  capSolverName              = "ABC"
-                                , mbDefaultLogic             = Nothing
-                                , supportsMacros             = True
-                                , supportsProduceModels      = True
-                                , supportsQuantifiers        = False
-                                , supportsUninterpretedSorts = False
-                                , supportsUnboundedInts      = False
-                                , supportsReals              = False
-                                , supportsFloats             = False
-                                , supportsDoubles            = False
-                                }
+           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
+         , capabilities = SolverCapabilities {
+                                capSolverName              = "ABC"
+                              , mbDefaultLogic             = Nothing
+                              , supportsMacros             = True
+                              , supportsProduceModels      = True
+                              , supportsQuantifiers        = False
+                              , supportsUninterpretedSorts = False
+                              , supportsUnboundedInts      = False
+                              , supportsReals              = False
+                              , supportsFloats             = False
+                              , supportsDoubles            = False
+                              }
          }
- where cont rm skolemMap = intercalate "\n" $ map extract skolemMap
-        where extract (Left s)        = "(echo \"((" ++ show s ++ " " ++ mkSkolemZero rm (kindOf s) ++ "))\")"
-              extract (Right (s, [])) = "(get-value (" ++ show s ++ "))"
-              extract (Right (s, ss)) = "(get-value (" ++ show s ++ concat [' ' : mkSkolemZero rm (kindOf a) | a <- ss] ++ "))"
-
-extractMap :: Bool -> [(Quantifier, NamedSymVar)] -> [(String, UnintKind)] -> [String] -> SMTModel
-extractMap isSat qinps _modelMap solverLines =
-   SMTModel { modelAssocs    = map snd $ sortByNodeId $ concatMap (interpretSolverModelLine inps) solverLines
-            , modelUninterps = []
-            , modelArrays    = []
-            }
-  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
+  where addTimeOut _ _ = error "ABC: Timeout values are not supported"
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
@@ -9,75 +9,32 @@
 -- The connection to the Boolector SMT solver
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE ScopedTypeVariables #-}
-
 module Data.SBV.Provers.Boolector(boolector) where
 
-import qualified Control.Exception as C
-
-import Data.Function      (on)
-import Data.List          (sortBy, intercalate)
-import System.Environment (getEnv)
-import System.Exit        (ExitCode(..))
-
 import Data.SBV.BitVectors.Data
-import Data.SBV.BitVectors.PrettyNum (mkSkolemZero)
 import Data.SBV.SMT.SMT
-import Data.SBV.SMT.SMTLib
-import Data.SBV.Utils.Lib (splitArgs)
 
 -- | 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.
 boolector :: SMTSolver
 boolector = SMTSolver {
-           name           = Boolector
-         , executable     = "boolector"
-         , options        = ["--smt2", "--smt2-model"]
-         , engine         = \cfg _isSat qinps modelMap skolemMap pgm -> do
-                                    execName <-                   getEnv "SBV_BOOLECTOR"          `C.catch` (\(_ :: C.SomeException) -> return (executable (solver cfg)))
-                                    execOpts <- (splitArgs `fmap` getEnv "SBV_BOOLECTOR_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 ---"]
-                                        script = SMTScript {scriptBody = tweaks ++ pgm, scriptModel = Just (cont (roundingMode cfg) skolemMap)}
-                                    standardSolver cfg' script id (ProofError cfg') (interpretSolverOutput cfg' (extractMap (map snd qinps) modelMap))
-         , xformExitCode  = boolectorExitCode
-         , capabilities   = SolverCapabilities {
-                                  capSolverName              = "Boolector"
-                                , mbDefaultLogic             = Nothing
-                                , supportsMacros             = False
-                                , supportsProduceModels      = True
-                                , supportsQuantifiers        = False
-                                , supportsUninterpretedSorts = False
-                                , supportsUnboundedInts      = False
-                                , supportsReals              = False
-                                , supportsFloats             = False
-                                , supportsDoubles            = False
-                                }
+           name         = Boolector
+         , executable   = "boolector"
+         , options      = ["--smt2", "--smt2-model", "--no-exit-codes"]
+         , engine       = standardEngine "SBV_BOOLECTOR" "SBV_BOOLECTOR_OPTIONS" addTimeOut standardModel
+         , capabilities = SolverCapabilities {
+                                capSolverName              = "Boolector"
+                              , mbDefaultLogic             = Nothing
+                              , supportsMacros             = False
+                              , supportsProduceModels      = True
+                              , supportsQuantifiers        = False
+                              , supportsUninterpretedSorts = False
+                              , supportsUnboundedInts      = False
+                              , supportsReals              = False
+                              , supportsFloats             = False
+                              , supportsDoubles            = False
+                              }
          }
- where addTimeOut Nothing  o   = o
-       addTimeOut (Just i) o
-         | i < 0               = error $ "Boolector: Timeout value must be non-negative, received: " ++ show i
-         | True                = o ++ ["-t=" ++ show i]
-       cont rm skolemMap = intercalate "\n" $ map extract skolemMap
-        where extract (Left s)        = "(echo \"((" ++ show s ++ " " ++ mkSkolemZero rm (kindOf s) ++ "))\")"
-              extract (Right (s, [])) = "(get-value (" ++ show s ++ "))"
-              extract (Right (s, ss)) = "(get-value (" ++ show s ++ concat [' ' : mkSkolemZero rm (kindOf a) | a <- ss] ++ "))"
-
--- | Similar to CVC4, Boolector uses different exit codes to indicate its status.
--- NB. This is likely going to change with the next release of Boolector, so simplify the
--- code when it does happen.
-boolectorExitCode :: ExitCode -> ExitCode
-boolectorExitCode (ExitFailure n) | n `elem` [10, 20, 0] = ExitSuccess
-boolectorExitCode ec                                     = ec
-
-extractMap :: [NamedSymVar] -> [(String, UnintKind)] -> [String] -> SMTModel
-extractMap inps _modelMap solverLines =
-   SMTModel { modelAssocs    = map snd $ sortByNodeId $ concatMap (interpretSolverModelLine inps) solverLines
-            , modelUninterps = []
-            , modelArrays    = []
-            }
-  where sortByNodeId :: [(Int, a)] -> [(Int, a)]
-        sortByNodeId = sortBy (compare `on` fst)
+ 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
@@ -13,76 +13,30 @@
 
 module Data.SBV.Provers.CVC4(cvc4) where
 
-import qualified Control.Exception as C
-
-import Data.Char          (isSpace)
-import Data.Function      (on)
-import Data.List          (sortBy, intercalate)
-import System.Environment (getEnv)
-
 import Data.SBV.BitVectors.Data
-import Data.SBV.BitVectors.PrettyNum (mkSkolemZero)
 import Data.SBV.SMT.SMT
-import Data.SBV.SMT.SMTLib
-import Data.SBV.Utils.Lib (splitArgs)
 
 -- | 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.
 cvc4 :: SMTSolver
 cvc4 = SMTSolver {
-           name           = CVC4
-         , executable     = "cvc4"
-         , options        = ["--lang", "smt"]
-         , engine         = \cfg isSat qinps modelMap skolemMap pgm -> do
-                                    execName <-                   getEnv "SBV_CVC4"          `C.catch` (\(_ :: C.SomeException) -> return (executable (solver cfg)))
-                                    execOpts <- (splitArgs `fmap` getEnv "SBV_CVC4_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 ---"]
-                                        script = SMTScript {scriptBody = tweaks ++ pgm, scriptModel = Just (cont (roundingMode cfg) skolemMap)}
-                                    standardSolver cfg' script id (ProofError cfg') (interpretSolverOutput cfg' (extractMap isSat qinps modelMap))
-         , xformExitCode  = id
-         , capabilities   = SolverCapabilities {
-                                  capSolverName              = "CVC4"
-                                , mbDefaultLogic             = 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
-                                }
+           name         = CVC4
+         , executable   = "cvc4"
+         , options      = ["--lang", "smt"]
+         , engine       = standardEngine "SBV_CVC4" "SBV_CVC4_OPTIONS" addTimeOut standardModel
+         , capabilities = SolverCapabilities {
+                                capSolverName              = "CVC4"
+                              , mbDefaultLogic             = 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
+                              }
          }
- where cont rm skolemMap = intercalate "\n" $ map extract skolemMap
-        where extract (Left s)        = "(echo \"((" ++ show s ++ " " ++ mkSkolemZero rm (kindOf s) ++ "))\")"
-              extract (Right (s, [])) = "(get-value (" ++ show s ++ "))"
-              extract (Right (s, ss)) = "(get-value (" ++ show s ++ concat [' ' : mkSkolemZero rm (kindOf a) | a <- ss] ++ "))"
-       addTimeOut Nothing  o   = o
-       addTimeOut (Just i) o
-         | 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
-
-extractMap :: Bool -> [(Quantifier, NamedSymVar)] -> [(String, UnintKind)] -> [String] -> SMTModel
-extractMap isSat qinps _modelMap solverLines =
-   SMTModel { modelAssocs    = map snd $ sortByNodeId $ concatMap (interpretSolverModelLine inps . unstring) solverLines
-            , modelUninterps = []
-            , modelArrays    = []
-            }
-  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
-        -- CVC4 puts quotes around echo's, go figure. strip them here
-        unstring s' = case (s, head s, last s) of
-                        (_:tl@(_:_), '"', '"') -> init tl
-                        _                      -> s'
-          where s = reverse . dropWhile isSpace . reverse . dropWhile isSpace $ s'
+ 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
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
@@ -13,74 +13,29 @@
 
 module Data.SBV.Provers.MathSAT(mathSAT) where
 
-import qualified Control.Exception as C
-
-import Data.Function      (on)
-import Data.List          (sortBy, intercalate)
-import System.Environment (getEnv)
-
 import Data.SBV.BitVectors.Data
-import Data.SBV.BitVectors.PrettyNum (mkSkolemZero)
 import Data.SBV.SMT.SMT
-import Data.SBV.SMT.SMTLib
-import Data.SBV.Utils.Lib (splitArgs)
 
 -- | 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.
 mathSAT :: SMTSolver
 mathSAT = SMTSolver {
-           name           = MathSAT
-         , executable     = "mathsat"
-         , options        = ["-input=smt2"]
-         , engine         = \cfg _isSat qinps modelMap skolemMap pgm -> do
-                                    execName <-                   getEnv "SBV_MATHSAT"          `C.catch` (\(_ :: C.SomeException) -> return (executable (solver cfg)))
-                                    execOpts <- (splitArgs `fmap` getEnv "SBV_MATHSAT_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 ---"]
-                                        script = SMTScript {scriptBody = tweaks ++ pgm, scriptModel = Just (cont (roundingMode cfg) skolemMap)}
-                                    standardSolver cfg' script id (ProofError cfg') (interpretSolverOutput cfg' (extractMap (map snd qinps) modelMap))
-         , xformExitCode  = id
-         , capabilities   = SolverCapabilities {
-                                  capSolverName              = "MathSAT"
-                                , mbDefaultLogic             = Nothing
-                                , supportsMacros             = False
-                                , supportsProduceModels      = True
-                                , supportsQuantifiers        = True
-                                , supportsUninterpretedSorts = True
-                                , supportsUnboundedInts      = True
-                                , supportsReals              = True
-                                , supportsFloats             = False
-                                , supportsDoubles            = False
-                                }
+           name         = MathSAT
+         , executable   = "mathsat"
+         , options      = ["-input=smt2"]
+         , engine       = standardEngine "SBV_MATHSAT" "SBV_MATHSAT_OPTIONS" addTimeOut standardModel
+         , capabilities = SolverCapabilities {
+                                capSolverName              = "MathSAT"
+                              , mbDefaultLogic             = Nothing
+                              , supportsMacros             = False
+                              , supportsProduceModels      = True
+                              , supportsQuantifiers        = True
+                              , supportsUninterpretedSorts = True
+                              , supportsUnboundedInts      = True
+                              , supportsReals              = True
+                              , supportsFloats             = True
+                              , supportsDoubles            = 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, [])) = ["(get-value (" ++ show s ++ "))"]
-              extract (Right (s, ss)) = let g = "(get-value ((" ++ show s ++ concat [' ' : mkSkolemZero rm (kindOf a) | a <- ss] ++ ")))" in [g]
-       addTimeOut Nothing  o = o
-       addTimeOut (Just _) _ = error "MathSAT: Timeout values are not supported by MathSat"
-
-extractMap :: [NamedSymVar] -> [(String, UnintKind)] -> [String] -> SMTModel
-extractMap inps _modelMap solverLines =
-   SMTModel { modelAssocs    = map snd $ sortByNodeId $ concatMap (interpretSolverModelLine inps . cvt) solverLines
-            , modelUninterps = []
-            , modelArrays    = []
-            }
-  where sortByNodeId :: [(Int, a)] -> [(Int, a)]
-        sortByNodeId = sortBy (compare `on` fst)
-        cvt :: String -> String
-        cvt s = case words s of
-                  [var, val] -> "((" ++ var ++ " #b" ++ map tr val ++ "))"
-                  _          -> s -- good-luck..
-          where tr 'x' = '0'
-                tr x   = x
+ where addTimeOut _ _ = error "MathSAT: Timeout values are not supported"
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
@@ -9,90 +9,86 @@
 -- Provable abstraction and the connection to SMT solvers
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE TypeSynonymInstances #-}
-{-# LANGUAGE FlexibleInstances    #-}
 {-# LANGUAGE BangPatterns         #-}
+{-# LANGUAGE FlexibleInstances    #-}
+{-# LANGUAGE NamedFieldPuns       #-}
 {-# LANGUAGE ScopedTypeVariables  #-}
+{-# LANGUAGE TypeSynonymInstances #-}
 
 module Data.SBV.Provers.Prover (
          SMTSolver(..), SMTConfig(..), Predicate, Provable(..)
-       , ThmResult(..), SatResult(..), AllSatResult(..), SMTResult(..), SafeResult(..)
+       , ThmResult(..), SatResult(..), AllSatResult(..), SMTResult(..)
        , isSatisfiable, isSatisfiableWith, isTheorem, isTheoremWith
        , prove, proveWith
        , sat, satWith
-       , safe, safeWith
        , allSat, allSatWith
        , isVacuous, isVacuousWith
        , SatModel(..), Modelable(..), displayModels, extractModels
        , getModelDictionaries, getModelValues, getModelUninterpretedValues
        , boolector, cvc4, yices, z3, mathSAT, abc, defaultSMTCfg
        , compileToSMTLib, generateSMTBenchmarks
-       , isSBranchFeasibleInState
-       , isConditionSatisfiable
+       , internalSATCheck
        ) where
 
-import Control.Monad       (when, unless)
-import Control.Monad.Trans (liftIO)
-import Data.List           (intercalate)
-import Data.Maybe          (mapMaybe, fromMaybe, isJust)
-import System.FilePath     (addExtension, splitExtension)
-import System.Time         (getClockTime)
-import System.IO.Unsafe    (unsafeInterleaveIO)
+import Control.Monad    (when, unless)
+import Data.List        (intercalate)
+import System.FilePath  (addExtension, splitExtension)
+import System.Time      (getClockTime)
+import System.IO.Unsafe (unsafeInterleaveIO)
 
 import qualified Data.Set as Set (Set, toList)
 
-import qualified Control.Exception as C
-
 import Data.SBV.BitVectors.Data
 import Data.SBV.SMT.SMT
 import Data.SBV.SMT.SMTLib
+import Data.SBV.Utils.TDiff
+
 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
-import Data.SBV.Utils.TDiff
 
-mkConfig :: SMTSolver -> Bool -> [String] -> SMTConfig
-mkConfig s isSMTLib2 tweaks = SMTConfig { verbose        = False
-                                        , timing         = False
-                                        , sBranchTimeOut = Nothing
-                                        , timeOut        = Nothing
-                                        , printBase      = 10
-                                        , printRealPrec  = 16
-                                        , smtFile        = Nothing
-                                        , solver         = s
-                                        , solverTweaks   = tweaks
-                                        , useSMTLib2     = isSMTLib2
-                                        , satCmd         = "(check-sat)"
-                                        , roundingMode   = RoundNearestTiesToEven
-                                        , useLogic       = Nothing
-                                        }
+mkConfig :: SMTSolver -> SMTLibVersion -> [String] -> SMTConfig
+mkConfig s smtVersion tweaks = SMTConfig { verbose        = False
+                                         , timing         = False
+                                         , sBranchTimeOut = Nothing
+                                         , timeOut        = Nothing
+                                         , printBase      = 10
+                                         , printRealPrec  = 16
+                                         , smtFile        = Nothing
+                                         , solver         = s
+                                         , solverTweaks   = tweaks
+                                         , smtLibVersion  = smtVersion
+                                         , satCmd         = "(check-sat)"
+                                         , roundingMode   = RoundNearestTiesToEven
+                                         , useLogic       = Nothing
+                                         }
 
 -- | Default configuration for the Boolector SMT solver
 boolector :: SMTConfig
-boolector = mkConfig Boolector.boolector True []
+boolector = mkConfig Boolector.boolector SMTLib2 []
 
 -- | Default configuration for the CVC4 SMT Solver.
 cvc4 :: SMTConfig
-cvc4 = mkConfig CVC4.cvc4 True []
+cvc4 = mkConfig CVC4.cvc4 SMTLib2 []
 
 -- | Default configuration for the Yices SMT Solver.
 yices :: SMTConfig
-yices = mkConfig Yices.yices False []
+yices = mkConfig Yices.yices SMTLib2 []
 
 -- | Default configuration for the Z3 SMT solver
 z3 :: SMTConfig
-z3 = mkConfig Z3.z3 True ["(set-option :smt.mbqi true) ; use model based quantifier instantiation"]
+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 True []
+mathSAT = mkConfig MathSAT.mathSAT SMTLib2 []
 
 -- | Default configuration for the ABC synthesis and verification tool.
 abc :: SMTConfig
-abc = mkConfig ABC.abc True []
+abc = mkConfig ABC.abc SMTLib2 []
 
 -- | The default solver used by SBV. This is currently set to z3.
 defaultSMTCfg :: SMTConfig
@@ -249,10 +245,6 @@
 sat :: Provable a => a -> IO SatResult
 sat = satWith defaultSMTCfg
 
--- | Check if a given definition is safe; i.e., if all 'sAssert' conditions can be proven to hold.
-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.
@@ -303,72 +295,59 @@
 
 -- | 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 booleans:
+-- supported out-of-the box by the SBV library. It takes two arguments:
 --
---    * smtLib2: If 'True', will generate SMT-Lib2 output, otherwise SMT-Lib1 output
+--    * 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 => Bool   -- ^ 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.)
+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 smtLib2 isSat a = do
+compileToSMTLib version isSat a = do
         t <- getClockTime
         let comments = ["Created on " ++ show t]
-            cvt = if smtLib2 then toSMTLib2 else toSMTLib1
-        (_, _, _, _, smtLibPgm) <- simulate cvt defaultSMTCfg isSat comments a
+            cvt = case version of
+                    SMTLib2 -> toSMTLib2
+        (_, _, _, smtLibPgm) <- simulate cvt defaultSMTCfg isSat comments a
         let out = show smtLibPgm
-        return $ out ++ if smtLib2 -- append check-sat in case of smtLib2
-                        then "\n(check-sat)\n"
-                        else "\n"
+        return $ out ++ "\n(check-sat)\n"
 
--- | 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
+-- | 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 = gen False smt1 >> gen True smt2
-  where smt1     = addExtension f "smt1"
-        smt2     = addExtension f "smt2"
-        gen b fn = do s <- compileToSMTLib b isSat a
-                      writeFile fn s
-                      putStrLn $ "Generated SMT benchmark " ++ show fn ++ "."
+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 = if useSMTLib2 config then toSMTLib2 else toSMTLib1
+  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 = if useSMTLib2 config then toSMTLib2 else toSMTLib1
-
--- | Check if a given definition is safe using the given solver configuration; i.e., if all 'sAssert' conditions can be proven to hold.
-safeWith :: SExecutable a => SMTConfig -> a -> IO SafeResult
-safeWith config a = C.catchJust choose checkSafe return
-  where checkSafe = do let msg = when (verbose config) . putStrLn . ("** " ++)
-                           isTiming = timing config
-                       msg "Starting safety checking symbolic simulation.."
-                       res <- timeIf isTiming "problem construction" $ runSymbolic (False, Just config) $ sName_ a >>= output
-                       msg $ "Generated symbolic trace:\n" ++ show res
-                       return SafeNeverFails
-        choose e@(SafeNeverFails{})   = Just e
-        choose e@(SafeAlwaysFails{})  = Just e
-        choose e@(SafeFailsInModel{}) = Just e
+  where cvt = case smtLibVersion config of
+                SMTLib2 -> toSMTLib2
 
 -- | 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 _ <- runSymbolic (True, Just config) $ forAll_ a >>= output
+        Result ki tr uic is cs ts as uis ax asgn cstr _ <- 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 [trueSW]
-                        cvt  = if useSMTLib2 config then toSMTLib2 else toSMTLib1
+                        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!
@@ -380,9 +359,10 @@
 -- | Find all satisfying assignments using the given SMT-solver
 allSatWith :: Provable a => SMTConfig -> a -> IO AllSatResult
 allSatWith config p = do
-        let converter = if useSMTLib2 config then toSMTLib2 else toSMTLib1
+        let converter  = case smtLibVersion config of
+                           SMTLib2 -> toSMTLib2
         msg "Checking Satisfiability, all solutions.."
-        sbvPgm@(qinps, _, _, ki, _) <- simulate converter config True [] p
+        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
@@ -402,39 +382,38 @@
                     Just (SatResult r) -> let cont model = do rest <- unsafeInterleaveIO $ loop (n+1) (modelAssocs model : 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, modelMap, skolemMap, _, smtLibPgm) = do
+                                               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 modelMap skolemMap 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
-                  , [(String, UnintKind)]               -- model-map
                   , [Either SW (SW, [SW])]              -- skolem-map
                   , Set.Set Kind                        -- kinds used
                   , SMTLibPgm                           -- SMTLib representation
                   )
 
 callSolver :: Bool -> String -> (SMTResult -> b) -> SMTConfig -> SMTProblem -> IO b
-callSolver isSat checkMsg wrap config (qinps, modelMap, skolemMap, _, smtLibPgm) = do
+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 modelMap skolemMap finalPgm
+       smtAnswer <- engine (solver config) config isSat qinps skolemMap finalPgm
        msg "Done.."
        return $ wrap smtAnswer
 
@@ -443,7 +422,7 @@
         let msg = when (verbose config) . putStrLn . ("** " ++)
             isTiming = timing config
         msg "Starting symbolic simulation.."
-        res <- timeIf isTiming "problem construction" $ runSymbolic (isSat, Just config) $ (if isSat then forSome_ else forAll_) predicate >>= output
+        res <- timeIf isTiming "problem construction" $ 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
@@ -455,8 +434,7 @@
         in case res of
              Result ki _qcInfo _codeSegs is consts tbls arrs uis axs pgm cstrs [o@(SW KBool _)] ->
                timeIf isTiming "translation"
-                $ let uiMap     = mapMaybe arrayUIKind arrs ++ map unintFnUIKind uis
-                      skolemMap = skolemize (if isSat then is else map flipQ is)
+                $ 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])]
@@ -464,7 +442,7 @@
                                    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)
-                  in return (is, uiMap, skolemMap, ki, converter (roundingMode config) (useLogic config) solverCaps ki isSat comments is skolemMap consts tbls arrs uis axs pgm cstrs o)
+                  in return (is, skolemMap, ki, converter (roundingMode config) (useLogic config) solverCaps ki isSat comments is skolemMap consts tbls arrs uis axs pgm cstrs o)
              Result _kindInfo _qcInfo _codeSegs _is _consts _tbls _arrs _uis _axs _pgm _cstrs 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
@@ -473,43 +451,17 @@
                                        ++ "\nDetected while generating the trace:\n" ++ show res
                                        ++ "\n*** Check calls to \"output\", they are typically not needed!"
 
--- | Check if a branch condition is feasible in the current state
-isSBranchFeasibleInState :: State -> String -> SBool -> IO Bool
-isSBranchFeasibleInState st branch cond = do
-       let cfg = let pickedConfig = fromMaybe defaultSMTCfg (getSBranchRunConfig st)
-                 in pickedConfig { timeOut = sBranchTimeOut pickedConfig }
-           msg = when (verbose cfg) . putStrLn . ("** " ++)
-       check <- internalSATCheck cfg st cond ("sBranch: Checking " ++ show branch ++ " feasibility")
-       res <- case check of
-                SatResult (Unsatisfiable _) -> return False
-                _                           -> return True   -- No risks, even if it timed-our or anything else, we say it's feasible
-       msg $ "sBranch: Conclusion: " ++ if res then "Feasible" else "Unfeasible"
-       return res
-
--- | Check if a boolean condition is satisfiable in the current state. If so, it returns such a satisfying assignment
-isConditionSatisfiable :: State -> SBool -> IO (Maybe SatResult)
-isConditionSatisfiable st cond = do
-       let cfg  = fromMaybe defaultSMTCfg (getSBranchRunConfig st)
-           msg  = when (verbose cfg) . putStrLn . ("** " ++)
-       check <- internalSATCheck cfg st cond "sAssert: Checking satisfiability"
-       res <- case check of
-                r@(SatResult (Satisfiable{})) -> return $ Just r
-                SatResult (Unsatisfiable _)   -> return Nothing
-                _                             -> error $ "sAssert: Unexpected external result: " ++ show check
-       msg $ "sAssert: Conclusion: " ++ if isJust res then "Satisfiable" else "Unsatisfiable"
-       return res
-
--- | Check the boolean SAT of an internal condition in the current execution state
-internalSATCheck :: SMTConfig -> State -> SBool -> String -> IO SatResult
-internalSATCheck cfg st cond msg = do
-   sw <- sbvToSW st cond
+-- | 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 _ <- liftIO $ extractSymbolicSimulationState st
+   Result ki tr uic is cs ts as uis ax asgn cstr _ <- 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 [sw]
-       cvt = if useSMTLib2 cfg then toSMTLib2 else toSMTLib1
+       cvt = case smtLibVersion cfg of
+                SMTLib2 -> toSMTLib2
    runProofOn cvt cfg True [] pgm >>= callSolver True msg SatResult cfg
-
 {-# ANN module ("HLint: ignore Reduce duplication" :: String) #-}
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
@@ -9,152 +9,33 @@
 -- The connection to the Yices SMT solver
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE PatternGuards       #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 
 module Data.SBV.Provers.Yices(yices) where
 
-import qualified Control.Exception as C
-
-import Data.Char          (isDigit)
-import Data.List          (sortBy, isPrefixOf, intercalate, transpose, partition)
-import Data.Maybe         (mapMaybe, isNothing, fromJust)
-import System.Environment (getEnv)
-
 import Data.SBV.BitVectors.Data
-import Data.SBV.Provers.SExpr
 import Data.SBV.SMT.SMT
-import Data.SBV.SMT.SMTLib
-import Data.SBV.Utils.Lib (splitArgs)
 
 -- | The description of the Yices SMT solver
--- The default executable is @\"yices-smt\"@, which must be in your path. You can use the @SBV_YICES@ environment variable to point to the executable on your system.
--- The default options are @\"-m -f\"@, which is valid for Yices 2.1 series. You can use the @SBV_YICES_OPTIONS@ environment variable to override the options.
+-- 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.
 yices :: SMTSolver
 yices = SMTSolver {
-           name           = Yices
-         , executable     = "yices-smt"
-         -- , options        = ["-tc", "-smt", "-e"]   -- For Yices1
-         , options        = ["-m", "-f"]  -- For Yices2
-         , engine         = \cfg _isSat qinps modelMap _skolemMap pgm -> do
-                                    execName <-                    getEnv "SBV_YICES"          `C.catch` (\(_ :: C.SomeException) -> return (executable (solver cfg)))
-                                    execOpts <- (splitArgs `fmap`  getEnv "SBV_YICES_OPTIONS") `C.catch` (\(_ :: C.SomeException) -> return (options (solver cfg)))
-                                    let cfg'   = cfg {solver = (solver cfg) {executable = execName, options = addTimeOut (timeOut cfg) execOpts}}
-                                        script = SMTScript {scriptBody = unlines (solverTweaks cfg') ++ pgm, scriptModel = Nothing}
-                                    standardSolver cfg' script id (ProofError cfg') (interpretSolverOutput cfg' (extractMap (map snd qinps) modelMap))
-         , xformExitCode  = id
-         , capabilities   = SolverCapabilities {
-                                  capSolverName              = "Yices"
-                                , mbDefaultLogic             = Nothing
-                                , supportsMacros             = False
-                                , supportsProduceModels      = False
-                                , supportsQuantifiers        = False
-                                , supportsUninterpretedSorts = False
-                                , supportsUnboundedInts      = False
-                                , supportsReals              = False
-                                , supportsFloats             = False
-                                , supportsDoubles            = False
-                                }
+           name         = Yices
+         , executable   = "yices-smt2"
+         , options      = []
+         , engine       = standardEngine "SBV_YICES" "SBV_YICES_OPTIONS" addTimeOut standardModel
+         , capabilities = SolverCapabilities {
+                                capSolverName              = "Yices"
+                              , mbDefaultLogic             = Just "QF_AUFLIA"
+                              , supportsMacros             = True
+                              , supportsProduceModels      = True
+                              , supportsQuantifiers        = False
+                              , supportsUninterpretedSorts = True
+                              , supportsUnboundedInts      = True
+                              , supportsReals              = True
+                              , supportsFloats             = False
+                              , supportsDoubles            = False
+                              }
          }
-  where addTimeOut Nothing  o   = o
-        addTimeOut (Just i) o
-          | i < 0               = error $ "Yices: Timeout value must be non-negative, received: " ++ show i
-          | True                = o ++ ["-t", show i]
-
-sortByNodeId :: [(Int, a)] -> [(Int, a)]
-sortByNodeId = sortBy (\(x, _) (y, _) -> compare x y)
-
-extractMap :: [NamedSymVar] -> [(String, UnintKind)] -> [String] -> SMTModel
-extractMap inps modelMap solverLines =
-   SMTModel { modelAssocs    = map snd $ sortByNodeId $ concatMap (getCounterExample inps) modelLines
-            , modelUninterps = [(n, ls) | (UFun _ n, ls) <- uis]
-            , modelArrays    = [(n, ls) | (UArr _ n, ls) <- uis]
-            }
-  where (modelLines, unintLines) = moveConstUIs $ break ("--- " `isPrefixOf`) solverLines
-        uis = extractUnints modelMap unintLines
-
--- another crude hack
-moveConstUIs :: ([String], [String]) -> ([String], [String])
-moveConstUIs (pre, post) = (pre', concatMap mkDecl extras ++ post)
-  where (extras, pre') = partition ("(= uninterpreted_" `isPrefixOf`) pre
-        mkDecl s = ["--- " ++ takeWhile (/= ' ') (drop 3 s) ++ " ---", s]
-
-getCounterExample :: [NamedSymVar] -> String -> [(Int, (String, CW))]
-getCounterExample inps line = either err extract (parseSExpr line)
-  where err r =  error $  "*** Failed to parse Yices model output from: "
-                       ++ "*** " ++ show line ++ "\n"
-                       ++ "*** Reason: " ++ r ++ "\n"
-        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.Yices: Cannot uniquely identify value for "
-                                                  ++ 's':v ++ " in "  ++ show matches
-        isInput _       = Nothing
-        extract (EApp [ECon "=", ECon v, ENum i]) | Just (n, s, nm) <- isInput v = [(n, (nm, mkConstCW (kindOf s) (fst i)))]
-        extract (EApp [ECon "=", ENum i, ECon v]) | Just (n, s, nm) <- isInput v = [(n, (nm, mkConstCW (kindOf s) (fst i)))]
-        extract _                                                                = []
-
-extractUnints :: [(String, UnintKind)] -> [String] -> [(UnintKind, [String])]
-extractUnints modelMap = mapMaybe (extractUnint modelMap) . chunks
-  where chunks []     = []
-        chunks (x:xs) = let (f, r) = break ("---" `isPrefixOf`) xs in (x:f) : chunks r
-
--- Parsing the Yices output is done extremely crudely and designed
--- mostly by observation of Yices output. Likely to have bugs and
--- brittle as Yices evolves. We really need an SMT-Lib2 like interface.
-extractUnint :: [(String, UnintKind)] -> [String] -> Maybe (UnintKind, [String])
-extractUnint _    []           = Nothing
-extractUnint mmap (tag : rest)
-  | null tag'                  = Nothing
-  | isNothing mbKnd            = Nothing
-  | True                       = mapM (getUIVal knd) rest >>= \xs -> return (knd, format knd xs)
-  where mbKnd | "--- uninterpreted_" `isPrefixOf` tag = uf `lookup` mmap
-              | True                                  = af `lookup` mmap
-        knd = fromJust mbKnd
-        tag' = dropWhile (/= '_') tag
-        f    = takeWhile (/= ' ') (tail tag')
-        uf   = f
-        af   = "array_" ++ f
-
-getUIVal :: UnintKind -> String -> Maybe (String, [String], String)
-getUIVal knd s
-  | "default: " `isPrefixOf` s
-  = getDefaultVal knd (dropWhile (/= ' ') s)
-  | True
-  = case parseSExpr s of
-       Right (EApp [ECon "=", EApp (ECon _ : args), ENum i]) -> getCallVal knd args (fst i)
-       Right (EApp [ECon "=", ECon _, ENum i])               -> getCallVal knd []   (fst i)
-       _ -> Nothing
-
-getDefaultVal :: UnintKind -> String -> Maybe (String, [String], String)
-getDefaultVal knd n = case parseSExpr n of
-                        Right (ENum i) -> Just $ showDefault knd (show (fst i))
-                        _              -> Nothing
-
-getCallVal :: UnintKind -> [SExpr] -> Integer -> Maybe (String, [String], String)
-getCallVal knd args res = mapM getArg args >>= \as -> return (showCall knd as (show res))
-
-getArg :: SExpr -> Maybe String
-getArg (ENum i) = Just (show (fst i))
-getArg _        = Nothing
-
-showDefault :: UnintKind -> String -> (String, [String], String)
-showDefault (UFun cnt f) res = (f, replicate cnt "_", res)
-showDefault (UArr cnt f) res = (f, replicate cnt "_", res)
-
-showCall :: UnintKind -> [String] -> String -> (String, [String], String)
-showCall (UFun _ f) as res = (f, as, res)
-showCall (UArr _ f) as res = (f, as, res)
-
-format :: UnintKind -> [(String, [String], String)] -> [String]
-format (UFun{}) eqns = fmtFun eqns
-format (UArr{}) eqns = let fmt (f, as, r) = f ++ "[" ++ intercalate ", " as ++ "] = " ++ r in map fmt eqns
-
-fmtFun :: [(String, [String], String)] -> [String]
-fmtFun ls = map fmt ls
-  where fmt (f, as, r) = f ++ " " ++ unwords (zipWith align as (lens ++ repeat 0)) ++ " = " ++ r
-        lens           = map (maximum . (0:) . map length) $ transpose [as | (_, as, _) <- ls]
-        align s i      = take (i `max` length s) (s ++ repeat ' ')
+  where addTimeOut _ _ = error "Yices: Timeout values are not supported by Yices"
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
@@ -17,7 +17,7 @@
 
 import Data.Char          (toLower)
 import Data.Function      (on)
-import Data.List          (sortBy, intercalate, isPrefixOf, groupBy)
+import Data.List          (sortBy, intercalate, groupBy)
 import System.Environment (getEnv)
 import qualified System.Info as S(os)
 
@@ -42,8 +42,8 @@
 z3 = SMTSolver {
            name           = Z3
          , executable     = "z3"
-         , options        = map (optionPrefix:) ["in", "smt2"]
-         , engine         = \cfg isSat qinps modelMap skolemMap pgm -> do
+         , 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} }
@@ -53,10 +53,7 @@
                                         dlim = printRealPrec cfg'
                                         ppDecLim = "(set-option :pp.decimal_precision " ++ show dlim ++ ")\n"
                                         script = SMTScript {scriptBody = tweaks ++ ppDecLim ++ pgm, scriptModel = Just (cont (roundingMode cfg) skolemMap)}
-                                    if dlim < 1
-                                       then error $ "SBV.Z3: printRealPrec value should be at least 1, invalid value received: " ++ show dlim
-                                       else standardSolver cfg' script cleanErrs (ProofError cfg') (interpretSolverOutput cfg' (extractMap isSat qinps modelMap))
-         , xformExitCode  = id
+                                    standardSolver cfg' script id (ProofError cfg') (interpretSolverOutput cfg' (extractMap isSat qinps))
          , capabilities   = SolverCapabilities {
                                   capSolverName              = "Z3"
                                 , mbDefaultLogic             = Nothing
@@ -70,9 +67,7 @@
                                 , supportsDoubles            = True
                                 }
          }
- where cleanErrs = intercalate "\n" . filter (not . junk) . lines
-       junk = ("WARNING:" `isPrefixOf`)
-       cont rm skolemMap = intercalate "\n" $ concatMap extract skolemMap
+ 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.
@@ -89,12 +84,9 @@
          | i < 0               = error $ "Z3: Timeout value must be non-negative, received: " ++ show i
          | True                = o ++ [optionPrefix : "T:" ++ show i]
 
-extractMap :: Bool -> [(Quantifier, NamedSymVar)] -> [(String, UnintKind)] -> [String] -> SMTModel
-extractMap isSat qinps _modelMap solverLines =
-   SMTModel { modelAssocs    = map snd $ squashReals $ sortByNodeId $ concatMap (interpretSolverModelLine inps) solverLines
-            , modelUninterps = []
-            , modelArrays    = []
-            }
+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
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
@@ -10,7 +10,6 @@
 -----------------------------------------------------------------------------
 
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE DeriveDataTypeable  #-}
 {-# LANGUAGE DefaultSignatures   #-}
 
 module Data.SBV.SMT.SMT where
@@ -22,20 +21,23 @@
 import Control.Monad      (when, zipWithM)
 import Data.Char          (isSpace)
 import Data.Int           (Int8, Int16, Int32, Int64)
-import Data.List          (intercalate, isPrefixOf, isInfixOf)
+import Data.Function      (on)
+import Data.List          (intercalate, isPrefixOf, isInfixOf, sortBy)
 import Data.Word          (Word8, Word16, Word32, Word64)
 import System.Directory   (findExecutable)
-import System.Process     (runInteractiveProcess, waitForProcess, terminateProcess)
+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.Typeable
 
 import Data.SBV.BitVectors.AlgReals
 import Data.SBV.BitVectors.Data
 import Data.SBV.BitVectors.PrettyNum
-import Data.SBV.Utils.Lib (joinArgs)
+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
@@ -89,22 +91,6 @@
                            Satisfiable{} -> True
                            _             -> False
 
--- | The result of an 'sAssert' call
-data SafeResult = SafeNeverFails
-                | SafeAlwaysFails  String
-                | SafeFailsInModel String SMTConfig SMTModel
-                deriving Typeable
-
--- | The show instance for SafeResult. Note that this is for display purposes only,
--- user programs are likely to pattern match on the output and proceed accordingly.
-instance Show SafeResult where
-   show SafeNeverFails              = "No safety violations detected."
-   show (SafeAlwaysFails s)         = intercalate "\n" ["Assertion failure: " ++ show s, "*** Fails in all assignments to inputs"]
-   show (SafeFailsInModel s cfg md) = intercalate "\n" ["Assertion failure: " ++ show s, showModel cfg md]
-
--- | If a 'prove' or 'sat' call comes accross an 'sAssert' call that fails, they will throw a 'SafeResult' as an exception.
-instance C.Exception SafeResult
-
 -- | 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
@@ -337,23 +323,20 @@
 -- | 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"
+  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
 showModel :: SMTConfig -> SMTModel -> String
-showModel cfg m = intercalate "\n" (map shM assocs ++ concatMap shUI uninterps ++ concatMap shUA arrs)
-  where assocs     = modelAssocs m
-        uninterps  = modelUninterps m
-        arrs       = modelArrays m
-        shM (s, v) = "  " ++ s ++ " = " ++ shCW cfg v
+showModel cfg m = intercalate "\n" $ map shM $ modelAssocs m
+  where shM (s, v) = "  " ++ s ++ " = " ++ shCW cfg v
 
 -- | Show a constant value, in the user-specified base
 shCW :: SMTConfig -> CW -> String
@@ -389,7 +372,7 @@
                         Left s                          -> return $ Left s
                         Right (ec, contents, allErrors) ->
                           let errors = dropWhile isSpace (cleanErrs allErrors)
-                          in case (null errors, xformExitCode (solver cfg) ec) of
+                          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)
@@ -411,6 +394,47 @@
                                                                          ++ "\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.
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
@@ -9,13 +9,12 @@
 -- Conversion of symbolic programs to SMTLib format
 -----------------------------------------------------------------------------
 
-module Data.SBV.SMT.SMTLib(SMTLibPgm, SMTLibConverter, toSMTLib1, toSMTLib2, addNonEqConstraints, interpretSolverOutput, interpretSolverModelLine) where
+module Data.SBV.SMT.SMTLib(SMTLibPgm, SMTLibConverter, toSMTLib2, addNonEqConstraints, interpretSolverOutput, interpretSolverModelLine) where
 
 import Data.Char (isDigit)
 
 import Data.SBV.BitVectors.Data
 import Data.SBV.Provers.SExpr
-import qualified Data.SBV.SMT.SMTLib1 as SMT1
 import qualified Data.SBV.SMT.SMTLib2 as SMT2
 
 import qualified Data.Set as Set (Set, member, toList)
@@ -39,12 +38,9 @@
                      -> SW                          -- ^ output variable
                      -> SMTLibPgm
 
--- | Convert to SMTLib-1 format
-toSMTLib1 :: SMTLibConverter
-
 -- | Convert to SMTLib-2 format
 toSMTLib2 :: SMTLibConverter
-(toSMTLib1, toSMTLib2) = (cvt SMTLib1, cvt SMTLib2)
+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"
@@ -63,7 +59,8 @@
          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   = if v == SMTLib1 then SMT1.cvt else SMT2.cvt
+               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
@@ -74,7 +71,6 @@
 
 -- | 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 SMTLib1 _) = SMT1.addNonEqConstraints rm cs p
 addNonEqConstraints rm  qinps cs p@(SMTLibPgm SMTLib2 _) = SMT2.addNonEqConstraints rm qinps cs p
 
 -- | Interpret solver output based on SMT-Lib standard output responses
diff --git a/Data/SBV/SMT/SMTLib1.hs b/Data/SBV/SMT/SMTLib1.hs
deleted file mode 100644
--- a/Data/SBV/SMT/SMTLib1.hs
+++ /dev/null
@@ -1,296 +0,0 @@
------------------------------------------------------------------------------
--- |
--- Module      :  Data.SBV.SMT.SMTLib1
--- Copyright   :  (c) Levent Erkok
--- License     :  BSD3
--- Maintainer  :  erkokl@gmail.com
--- Stability   :  experimental
---
--- Conversion of symbolic programs to SMTLib format, Using v1 of the standard
------------------------------------------------------------------------------
-{-# LANGUAGE PatternGuards #-}
-
-module Data.SBV.SMT.SMTLib1(cvt, addNonEqConstraints) where
-
-import qualified Data.Foldable as F   (toList)
-import qualified Data.Set      as Set
-import Data.List  (intercalate)
-
-import Data.SBV.BitVectors.Data
-
--- | Add constraints to generate /new/ models. This function is used to query the SMT-solver, while
--- disallowing a previous model.
-addNonEqConstraints :: RoundingMode -> [[(String, CW)]] -> SMTLibPgm -> Maybe String
-addNonEqConstraints _rm nonEqConstraints (SMTLibPgm _ (aliasTable, pre, post)) = Just $ intercalate "\n" $
-     pre
-  ++ [ " ; --- refuted-models ---" ]
-  ++ concatMap (nonEqs . map intName) nonEqConstraints
-  ++ post
- where intName (s, c)
-          | Just sw <- s `lookup` aliasTable = (show sw, c)
-          | True                             = (s, c)
-
-nonEqs :: [(String, CW)] -> [String]
-nonEqs []     =  []
-nonEqs [sc]   =  [" :assumption " ++ nonEq sc]
-nonEqs (sc:r) =  [" :assumption (or " ++ nonEq sc]
-              ++ map (("                 " ++) . nonEq) r
-              ++ ["             )"]
-
-nonEq :: (String, CW) -> String
-nonEq (s, c) = "(not (= " ++ s ++ " " ++ cvtCW c ++ "))"
-
--- | Translate a problem into an SMTLib1 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 of the 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 _roundingMode smtLogic _solverCaps _kindInfo isSat comments qinps _skolemInps consts tbls arrs uis axs asgnsSeq cstrs out = (pre, post)
-  where logic
-         | Just l <- smtLogic                 = show l
-         | null tbls && null arrs && null uis = "QF_BV"
-         | True                               = "QF_AUFBV"
-        inps = map (fst . snd) qinps
-        pre =    [ "; Automatically generated by SBV. Do not edit." ]
-              ++ map ("; " ++) comments
-              ++ ["(benchmark sbv"
-                 , " :logic " ++ logic
-                 , " :status unknown"
-                 , " ; --- inputs ---"
-                 ]
-              ++ map decl inps
-              ++ [ " ; --- declarations ---" ]
-              ++ map (decl . fst) consts
-              ++ map (decl . fst) asgns
-              ++ [ " ; --- constants ---" ]
-              ++ map cvtCnst consts
-              ++ [ " ; --- tables ---" ]
-              ++ concatMap mkTable tbls
-              ++ [ " ; --- arrays ---" ]
-              ++ concatMap declArray arrs
-              ++ [ " ; --- uninterpreted constants ---" ]
-              ++ concatMap declUI uis
-              ++ [ " ; --- user given axioms ---" ]
-              ++ map declAx axs
-              ++ [ " ; --- assignments ---" ]
-              ++ map cvtAsgn asgns
-        post =    [ " ; --- constraints ---" ]
-               ++ map mkCstr cstrs
-               ++ [ " ; --- formula ---" ]
-               ++ [mkFormula isSat out]
-               ++ [")"]
-        asgns = F.toList (pgmAssignments asgnsSeq)
-        mkCstr s = " :assumption " ++ show s
-
--- TODO: Does this work for SMT-Lib when the index/element types are signed?
--- Currently we ignore the signedness of the arguments, as there appears to be no way
--- to capture that in SMT-Lib; and likely it does not matter. Would be good to check
--- explicitly though.
-mkTable :: ((Int, Kind, Kind), [SW]) -> [String]
-mkTable ((i, ak, rk), elts) = (" :extrafuns ((" ++ t ++ " Array[" ++ show at ++ ":" ++ show rt ++ "]))") : zipWith mkElt elts [(0::Int)..]
-  where t = "table" ++ show i
-        mkElt x k = " :assumption (= (select " ++ t ++ " bv" ++ show k ++ "[" ++ show at ++ "]) " ++ show x ++ ")"
-        (at, rt) = case (ak, rk) of
-                     (KBounded _ a, KBounded _ b) -> (a, b)
-                     _                            -> die $ "mkTable: Unbounded table component: " ++ show (ak, rk)
-
--- Unexpected input, or things we will probably never support
-die :: String -> a
-die msg = error $ "SBV->SMTLib1: Unexpected: " ++ msg
-
-declArray :: (Int, ArrayInfo) -> [String]
-declArray (i, (_, (ak, rk), ctx)) = adecl : ctxInfo
-  where nm = "array_" ++ show i
-        adecl = " :extrafuns ((" ++ nm ++ " Array[" ++ show at ++ ":" ++ show rt ++ "]))"
-        (at, rt) = case (ak, rk) of
-                     (KBounded _ a, KBounded _ b) -> (a, b)
-                     _                            -> die $ "declArray: Unbounded array component: " ++ show (ak, rk)
-        ctxInfo = case ctx of
-                    ArrayFree Nothing   -> []
-                    ArrayFree (Just sw) -> declA sw
-                    ArrayReset _ sw     -> declA sw
-                    ArrayMutate j a b -> [" :assumption (= " ++ nm ++ " (store array_" ++ show j ++ " " ++ show a ++ " " ++ show b ++ "))"]
-                    ArrayMerge  t j k -> [" :assumption (= " ++ nm ++ " (ite " ++ show t ++ " array_" ++ show j ++ " array_" ++ show k ++ "))"]
-        declA sw = let iv = nm ++ "_freeInitializer"
-                   in [ " :extrafuns ((" ++ iv ++ " " ++ kindType ak ++ "))"
-                      , " :assumption (= (select " ++ nm ++ " " ++ iv ++ ") " ++ show sw ++ ")"
-                      ]
-
-declAx :: (String, [String]) -> String
-declAx (nm, ls) = (" ;; -- user given axiom: " ++ nm ++ "\n   ") ++ intercalate "\n   " ls
-
-declUI :: (String, SBVType) -> [String]
-declUI (i, t) = [" :extrafuns ((uninterpreted_" ++ i ++ " " ++ cvtType t ++ "))"]
-
-mkFormula :: Bool -> SW -> String
-mkFormula isSat s
- | isSat = " :formula " ++ show s
- | True  = " :formula (not " ++ show s ++ ")"
-
--- SMTLib represents signed/unsigned quantities with the same type
-decl :: SW -> String
-decl s
- | isBoolean s = " :extrapreds ((" ++ show s ++ "))"
- | True        = " :extrafuns  ((" ++ show s ++ " " ++ kindType (kindOf s) ++ "))"
-
-cvtAsgn :: (SW, SBVExpr) -> String
-cvtAsgn (s, e) = " :assumption (= " ++ show s ++ " " ++ cvtExp e ++ ")"
-
-cvtCnst :: (SW, CW) -> String
-cvtCnst (s, c) = " :assumption (= " ++ show s ++ " " ++ cvtCW c ++ ")"
-
--- no need to worry about Int/Real here as we don't support them with the SMTLib1 interface..
-cvtCW :: CW -> String
-cvtCW (CW KBool (CWInteger v)) = if v == 0 then "false" else "true"
-cvtCW x@(CW _ (CWInteger v)) | not (hasSign x) = "bv" ++ show v ++ "[" ++ show (intSizeOf x) ++ "]"
--- 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
-cvtCW x@(CW _ (CWInteger v))  | v == least = mkMinBound (intSizeOf x)
-  where least = negate (2 ^ intSizeOf x)
-cvtCW x@(CW _ (CWInteger v)) = negIf (v < 0) $ "bv" ++ show (abs v) ++ "[" ++ show (intSizeOf x) ++ "]"
-cvtCW x = error $ "SBV.SMTLib1.cvtCW: Unexpected CW: " ++ show x -- unbounded/real, shouldn't reach here
-
-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 = "bv1" ++ replicate (i-1) '0' ++ "[" ++ show i ++ "]"
-
-rot :: String -> Int -> SW -> String
-rot o c x = "(" ++ o ++ "[" ++ show c ++ "] " ++ show x ++ ")"
-
--- only used for bounded SWs
-shft :: String -> String -> Int -> SW -> String
-shft oW oS c x = "(" ++ o ++ " " ++ show x ++ " " ++ cvtCW c' ++ ")"
-   where s  = hasSign x
-         c' = mkConstCW (kindOf x) c
-         o  = if s then oS else oW
-
-cvtExp :: SBVExpr -> String
-cvtExp (SBVApp Ite [a, b, c]) = "(ite " ++ show a ++ " " ++ show b ++ " " ++ show c ++ ")"
-cvtExp (SBVApp (Rol i) [a])   = rot "rotate_left"  i a
-cvtExp (SBVApp (Ror i) [a])   = rot "rotate_right" i a
-cvtExp (SBVApp (Shl i) [a])   = shft "bvshl"  "bvshl"  i a
-cvtExp (SBVApp (Shr i) [a])   = shft "bvlshr" "bvashr" i a
-cvtExp (SBVApp (FPRound w) _) = die $ "cvtExp: SMTLib1 backend does not support floating point operations with rounding modes: (" ++  w ++ ")"
-cvtExp (SBVApp (LkUp (t, ak, _, l) i e) [])
-  | needsCheck = "(ite " ++ cond ++ show e ++ " " ++ lkUp ++ ")"
-  | True       = lkUp
-  where at = case ak of
-              KBounded _ n -> n
-              _            -> die $ "cvtExp: Unbounded lookup component" ++ show ak
-        needsCheck = (2::Integer)^at > fromIntegral l
-        lkUp = "(select table" ++ show t ++ " " ++ show i ++ ")"
-        cond
-         | hasSign i = "(or " ++ le0 ++ " " ++ gtl ++ ") "
-         | True      = gtl ++ " "
-        (less, leq) = if hasSign i then ("bvslt", "bvsle") else ("bvult", "bvule")
-        mkCnst = cvtCW . mkConstCW (kindOf i)
-        le0  = "(" ++ less ++ " " ++ show i ++ " " ++ mkCnst 0 ++ ")"
-        gtl  = "(" ++ leq  ++ " " ++ mkCnst l ++ " " ++ show i ++ ")"
-cvtExp (SBVApp (Extract i j) [a]) = "(extract[" ++ show i ++ ":" ++ show j ++ "] " ++ show a ++ ")"
-cvtExp (SBVApp (ArrEq i j) []) = "(= array_" ++ show i ++ " array_" ++ show j ++")"
-cvtExp (SBVApp (ArrRead i) [a]) = "(select array_" ++ show i ++ " " ++ show a ++ ")"
-cvtExp (SBVApp Abs [a])
-   | hasSign a = "(ite " ++ ltz ++ " " ++ na ++ " " ++ sa ++ ")"
-   | True      = sa
-   where sa  = show a
-         na  = "(bvneg " ++ sa ++ ")"
-         z   = cvtCW (mkConstCW (kindOf a) (0::Integer))
-         ltz = "(bvslt " ++ sa ++ " " ++ z ++ ")"
-cvtExp (SBVApp (Uninterpreted nm) [])   = "uninterpreted_" ++ nm
-cvtExp (SBVApp (Uninterpreted nm) args) = "(uninterpreted_" ++ nm ++ " " ++ unwords (map show args) ++ ")"
-cvtExp inp@(SBVApp op args)
-  | allBools, Just f <- lookup op boolComps
-  = f (map show args)
-  | Just f <- lookup op smtOpTable
-  = f (any hasSign args) allBools (map show args)
-  | True
-  = error $ "SBV.SMT.SMTLib1.cvtExp: impossible happened; can't translate: " ++ show inp
-  where allBools = all isBoolean args
-        lift2  o _ _ [x, y] = "(" ++ o ++ " " ++ x ++ " " ++ y ++ ")"
-        lift2  o _ _ sbvs   = error $ "SBV.SMTLib1.cvtExp.lift2: Unexpected arguments: "   ++ show (o, sbvs)
-        lift2S oU oS sgn isB sbvs
-          | sgn
-          = lift2 oS sgn isB sbvs
-          | True
-          = lift2 oU sgn isB sbvs
-        lift1  o _ _ [x]    = "(" ++ o ++ " " ++ x ++ ")"
-        lift1  o _ _ sbvs   = error $ "SBV.SMT.SMTLib1.cvtExp.lift1: Unexpected arguments: "   ++ show (o, sbvs)
-        -- ops that distinguish 1-bit bitvectors (boolean) from others
-        lift2B bOp vOp sgn isB sbvs
-          | isB
-          = lift2 bOp sgn isB sbvs
-          | True
-          = lift2 vOp sgn isB sbvs
-        lift1B bOp vOp sgn isB sbvs
-          | isB
-          = lift1 bOp sgn isB sbvs
-          | True
-          = lift1 vOp sgn isB sbvs
-        eq sgn isB sbvs
-          | isB
-          = lift2 "=" sgn isB sbvs
-          | True
-          = "(= " ++ lift2 "bvcomp" sgn isB sbvs ++ " bv1[1])"
-        neq sgn isB sbvs = "(not " ++ eq sgn isB sbvs ++ ")"
-        -- 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.SMTLib1.boolComps.blt: Impossible happened, incorrect arity (expected 2): " ++ show xs
-                             blq [x, y] = "(or (not " ++ x ++ ") " ++ y ++ ")"
-                             blq xs     = error $ "SBV.SMT.SMTLib1.boolComps.blq: Impossible happened, incorrect arity (expected 2): " ++ show xs
-                             swp [x, y] = [y, x]
-                             swp xs     = error $ "SBV.SMT.SMTLib1.boolComps.swp: Impossible happened, incorrect arity (expected 2): " ++ show xs
-        smtOpTable = [ (Plus,          lift2   "bvadd")
-                     , (Minus,         lift2   "bvsub")
-                     , (Times,         lift2   "bvmul")
-                     , (Quot,          lift2S  "bvudiv" "bvsdiv")
-                     , (Rem,           lift2S  "bvurem" "bvsrem")
-                     , (Equal,         eq)
-                     , (NotEqual,      neq)
-                     , (LessThan,      lift2S  "bvult" "bvslt")
-                     , (GreaterThan,   lift2S  "bvugt" "bvsgt")
-                     , (LessEq,        lift2S  "bvule" "bvsle")
-                     , (GreaterEq,     lift2S  "bvuge" "bvsge")
-                     , (And,           lift2B  "and" "bvand")
-                     , (Or,            lift2B  "or"  "bvor")
-                     , (Not,           lift1B  "not" "bvnot")
-                     , (UNeg,          lift1B  "not" "bvneg")
-                     , (XOr,           lift2B  "xor" "bvxor")
-                     , (Join,          lift2   "concat")
-                     ]
-
-cvtType :: SBVType -> String
-cvtType (SBVType []) = error "SBV.SMT.SMTLib1.cvtType: internal: received an empty type!"
-cvtType (SBVType xs) = unwords $ map kindType xs
-
-kindType :: Kind -> String
-kindType KBool                = "Bool"
-kindType (KBounded _ s)       = "BitVec[" ++ show s ++ "]"
-kindType KUnbounded           = die "unbounded Integer"
-kindType KReal                = die "real value"
-kindType KFloat               = die "float value"
-kindType KDouble              = die "double value"
-kindType (KUserSort s _)      = die $ "user sort: " ++ s
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
@@ -78,7 +78,7 @@
 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
+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
@@ -186,7 +186,8 @@
           where mkConstTable (((t, _, _), _), _) = (t, "table" ++ show t)
                 mkSkTable    (((t, _, _), _), _) = (t, "table" ++ show t ++ forallArgs)
         asgns = F.toList asgnsSeq
-        mkLet (s, e) = "(let ((" ++ show s ++ " " ++ cvtExp rm skolemMap tableMap e ++ "))"
+        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 ++ ")"
@@ -396,14 +397,11 @@
                 mkCnst = cvtCW rm . mkConstCW (kindOf i)
                 le0  = "(" ++ less ++ " " ++ ssw i ++ " " ++ mkCnst 0 ++ ")"
                 gtl  = "(" ++ leq  ++ " " ++ mkCnst l ++ " " ++ ssw i ++ ")"
-        sh (SBVApp (ArrEq i j) []) = "(= array_" ++ show i ++ " array_" ++ show j ++")"
+        sh (SBVApp (IntCast f t) [a]) = handleIntCast 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) ++ ")"
-          where -- slight hack needed here to take advantage of custom floating-point functions.. sigh.
-                fpSpecials = ["fp.sqrt", "fp.fma"]
-                nm' | (floatOp || doubleOp) && (nm `elem` fpSpecials) = addRM nm
-                    | True                                            = 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
@@ -435,8 +433,9 @@
                                , (Not,  lift1B "not" "bvnot")
                                , (Join, lift2 "concat")
                                ]
-        sh (SBVApp (FPRound w) args)
-          = "(" ++ w ++ " " ++ unwords (map ssw args) ++ ")"
+        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)
@@ -508,6 +507,73 @@
                                      , (GreaterEq,   unintComp ">=")
                                      ]
 
+-----------------------------------------------------------------------------------------------
+-- Casts supported by SMTLib. (From: http://smtlib.cs.uiowa.edu/theories/FloatingPoint.smt2)
+--   ; 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 ++ ")"
 
@@ -516,3 +582,50 @@
    where s  = hasSign x
          c' = mkConstCW (kindOf x) c
          o  = if s then oS else oW
+
+-- Various integer casts
+handleIntCast :: Kind -> Kind -> String -> String
+handleIntCast 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
+                        _            -> noCast
+
+      KUnbounded   -> case kTo of
+                        KReal        -> "(to_real " ++ a ++ ")"
+                        KBounded _ n -> i2b n
+                        _            -> noCast
+
+      _            -> noCast
+
+  where noCast  = error $ "SBV.SMTLib2: Unexpected integer 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 ++ ")"
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
@@ -143,6 +143,7 @@
               , "#include <inttypes.h>"
               , "#include <stdint.h>"
               , "#include <stdbool.h>"
+              , "#include <string.h>"
               , "#include <math.h>"
               , ""
               , "/* The boolean type */"
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
@@ -9,7 +9,6 @@
 -- Implementation of polynomial arithmetic
 -----------------------------------------------------------------------------
 
-{-# LANGUAGE CPP                  #-}
 {-# LANGUAGE FlexibleContexts     #-}
 {-# LANGUAGE FlexibleInstances    #-}
 {-# LANGUAGE PatternGuards        #-}
@@ -19,7 +18,7 @@
 
 import Data.Bits  (Bits(..))
 import Data.List  (genericTake)
-import Data.Maybe (fromJust)
+import Data.Maybe (fromJust, fromMaybe)
 import Data.Word  (Word8, Word16, Word32, Word64)
 
 import Data.SBV.BitVectors.Data
@@ -101,11 +100,7 @@
  | True    = foldr (\x y -> sh x ++ " + " ++ y) (sh (last cs)) (init cs) ++ t
  where t | st   = " :: GF(2^" ++ show n ++ ")"
          | True = ""
-#if __GLASGOW_HASKELL__ >= 708
-       n  = maybe (error "SBV.Polynomial.sp: Unexpected non-finite usage!") id (bitSizeMaybe a)
-#else
-       n  = bitSize a
-#endif
+       n  = fromMaybe (error "SBV.Polynomial.sp: Unexpected non-finite usage!") (bitSizeMaybe a)
        is = [n-1, n-2 .. 0]
        cs = map fst $ filter snd $ zip is (map (testBit a) is)
        sh 0 = "1"
diff --git a/Data/SBV/Utils/Numeric.hs b/Data/SBV/Utils/Numeric.hs
new file mode 100644
--- /dev/null
+++ b/Data/SBV/Utils/Numeric.hs
@@ -0,0 +1,107 @@
+-----------------------------------------------------------------------------
+-- |
+-- 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
+
+-- | A variant of round; except defaulting to 0 when fed NaN or Infinity
+fpRound0 :: (RealFloat a, RealFrac a, Integral b) => a -> b
+fpRound0 x
+ | isNaN x || isInfinite x = 0
+ | True                    = round x
+
+-- | A variant of toRational; except defaulting to 0 when fed NaN or Infinity
+fpRatio0 :: (RealFloat a, RealFrac a) => a -> Rational
+fpRatio0 x
+ | isNaN x || isInfinite x = 0
+ | True                    = toRational x
+
+-- | The SMT-Lib (in particular Z3) implementation for min/max for floats does not agree with
+-- Haskell's; and also it does not agree with what the hardware does. Sigh.. See:
+--      <https://ghc.haskell.org/trac/ghc/ticket/10378>
+--      <https://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 returns +0
+fpMaxH :: RealFloat a => a -> a -> a
+fpMaxH x y
+   | isNaN x                              = y
+   | isNaN y                              = x
+   | isNegativeZero x && isNegativeZero y = -0.0
+   | (x == 0) && (y == 0)                 =  0.0   -- Corresponds to SMTLib. For x86 semantics, we'd return 'y' here. (Matters when x=+0, y=-0 or vice versa)
+   | x > y                                = x
+   | True                                 = y
+
+-- | SMTLib compliant definition for 'fpMin'. See the comments for 'fpMax'.
+fpMinH :: RealFloat a => a -> a -> a
+fpMinH x y
+   | isNaN x                              = y
+   | isNaN y                              = x
+   | isNegativeZero x && isNegativeZero y = -0.0
+   | (x == y) && (y == 0)                 =  0.0   -- Corresponds to SMTLib. For x86 semantics, we'd return 'y' here. (Matters when x=+0, y=-0 or vice versa)
+   | x < y                                = x
+   | True                                 = y
+
+-- | Convert double to float and back. Essentially @fromRational . toRational@
+-- 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
+ | 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.
+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))
+  where rx, ry, rd :: Rational
+        rx = toRational x
+        ry = toRational y
+        rd = rx / ry
+        d :: Integer
+        d | rd > 0 = floor   rd
+          | True   = ceiling rd
+        -- If the result is 0, make sure we preserve the sign of x
+        pSign r
+          | r == 0 = if x < 0 || isNegativeZero x then -0.0 else 0.0
+          | True   = r
+
+-- | Convert a float to the nearest integral representable in that type
+fpRoundToIntegralH :: RealFloat a => a -> a
+fpRoundToIntegralH x
+  | isNaN x      = x
+  | x == 0       = x
+  | isInfinite x = x
+  | i == 0       = if x < 0 || isNegativeZero x then -0.0 else 0.0
+  | True         = fromInteger i
+  where i :: Integer
+        i = round x
+
+-- | Check that two floats are the exact same values, i.e., +0/-0 does not
+-- compare equal, and NaN's compare equal to themselves.
+fpIsEqualObjectH :: RealFloat a => a -> a -> Bool
+fpIsEqualObjectH a b
+  | isNaN a          = isNaN b
+  | isNegativeZero a = isNegativeZero b
+  | isNegativeZero b = isNegativeZero a
+  | True             = a == 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)
diff --git a/SBVUnitTest/Examples/Basics/BasicTests.hs b/SBVUnitTest/Examples/Basics/BasicTests.hs
--- a/SBVUnitTest/Examples/Basics/BasicTests.hs
+++ b/SBVUnitTest/Examples/Basics/BasicTests.hs
@@ -16,27 +16,28 @@
 
 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 = runSymbolic (True, Nothing) $ do let x = literal (3 :: Word8)
-                                               y = literal (2 :: Word8)
-                                           output $ f x y
-test2 f = runSymbolic (True, Nothing) $ do let x = literal (3 :: Word8)
-                                           y :: SWord8 <- forall "y"
-                                           output $ f x y
-test3 f = runSymbolic (True, Nothing) $ do x :: SWord8 <- forall "x"
-                                           y :: SWord8 <- forall "y"
-                                           output $ f x y
-test4 f = runSymbolic (True, Nothing) $ do x :: SWord8 <- forall "x"
-                                           output $ f x x
-test5 f = runSymbolic (True, Nothing) $ do x :: SWord8 <- forall "x"
-                                           let r = f x x
-                                           q :: SWord8 <- forall "q"
-                                           _ <- output q
-                                           output r
+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)
diff --git a/SBVUnitTest/GoldFiles/U2Bridge.gold b/SBVUnitTest/GoldFiles/U2Bridge.gold
--- a/SBVUnitTest/GoldFiles/U2Bridge.gold
+++ b/SBVUnitTest/GoldFiles/U2Bridge.gold
@@ -3,13 +3,13 @@
   s1 = Edge :: U2Member
   s2 = Bono :: U2Member
   s3 = True
-  s4 = Bono :: U2Member
+  s4 = Edge :: U2Member
   s5 = Bono :: U2Member
   s6 = False
   s7 = Larry :: U2Member
   s8 = Adam :: U2Member
   s9 = True
-  s10 = Edge :: U2Member
+  s10 = Bono :: U2Member
   s11 = Bono :: U2Member
   s12 = False
   s13 = Edge :: U2Member
diff --git a/SBVUnitTest/GoldFiles/addSub.gold b/SBVUnitTest/GoldFiles/addSub.gold
--- a/SBVUnitTest/GoldFiles/addSub.gold
+++ b/SBVUnitTest/GoldFiles/addSub.gold
@@ -4,7 +4,7 @@
 # include any user-defined .mk file in the current directory.
 -include *.mk
 
-CC=gcc
+CC?=gcc
 CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
 
 all: addSub_driver
@@ -33,6 +33,7 @@
 #include <inttypes.h>
 #include <stdint.h>
 #include <stdbool.h>
+#include <string.h>
 #include <math.h>
 
 /* The boolean type */
@@ -66,10 +67,6 @@
 /* Example driver program for addSub. */
 /* Automatically generated by SBV. Edit as you see fit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include <stdio.h>
 #include "addSub.h"
 
@@ -90,10 +87,6 @@
 == BEGIN: "addSub.c" ================
 /* File: "addSub.c". Automatically generated by SBV. Do not edit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include "addSub.h"
 
 void addSub(const SWord8 x, const SWord8 y, SWord8 *sum,
diff --git a/SBVUnitTest/GoldFiles/aes128Dec.gold b/SBVUnitTest/GoldFiles/aes128Dec.gold
--- a/SBVUnitTest/GoldFiles/aes128Dec.gold
+++ b/SBVUnitTest/GoldFiles/aes128Dec.gold
@@ -4,7 +4,7 @@
 # include any user-defined .mk file in the current directory.
 -include *.mk
 
-CC=gcc
+CC?=gcc
 CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
 
 all: aes128Dec_driver
@@ -33,6 +33,7 @@
 #include <inttypes.h>
 #include <stdint.h>
 #include <stdbool.h>
+#include <string.h>
 #include <math.h>
 
 /* The boolean type */
@@ -65,10 +66,6 @@
 /* Example driver program for aes128Dec. */
 /* Automatically generated by SBV. Edit as you see fit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include <stdio.h>
 #include "aes128Dec.h"
 
@@ -107,10 +104,6 @@
 == BEGIN: "aes128Dec.c" ================
 /* File: "aes128Dec.c". Automatically generated by SBV. Do not edit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include "aes128Dec.h"
 
 void aes128Dec(const SWord32 *pt, const SWord32 *key, SWord32 *ct)
diff --git a/SBVUnitTest/GoldFiles/aes128Enc.gold b/SBVUnitTest/GoldFiles/aes128Enc.gold
--- a/SBVUnitTest/GoldFiles/aes128Enc.gold
+++ b/SBVUnitTest/GoldFiles/aes128Enc.gold
@@ -4,7 +4,7 @@
 # include any user-defined .mk file in the current directory.
 -include *.mk
 
-CC=gcc
+CC?=gcc
 CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
 
 all: aes128Enc_driver
@@ -33,6 +33,7 @@
 #include <inttypes.h>
 #include <stdint.h>
 #include <stdbool.h>
+#include <string.h>
 #include <math.h>
 
 /* The boolean type */
@@ -65,10 +66,6 @@
 /* Example driver program for aes128Enc. */
 /* Automatically generated by SBV. Edit as you see fit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include <stdio.h>
 #include "aes128Enc.h"
 
@@ -107,10 +104,6 @@
 == BEGIN: "aes128Enc.c" ================
 /* File: "aes128Enc.c". Automatically generated by SBV. Do not edit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include "aes128Enc.h"
 
 void aes128Enc(const SWord32 *pt, const SWord32 *key, SWord32 *ct)
diff --git a/SBVUnitTest/GoldFiles/aes128Lib.gold b/SBVUnitTest/GoldFiles/aes128Lib.gold
--- a/SBVUnitTest/GoldFiles/aes128Lib.gold
+++ b/SBVUnitTest/GoldFiles/aes128Lib.gold
@@ -1,10 +1,6 @@
 == BEGIN: "aes128KeySchedule.c" ================
 /* File: "aes128KeySchedule.c". Automatically generated by SBV. Do not edit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include "aes128Lib.h"
 
 void aes128KeySchedule(const SWord32 *key, SWord32 *encKS,
@@ -1740,10 +1736,6 @@
 == BEGIN: "aes128BlockEncrypt.c" ================
 /* File: "aes128BlockEncrypt.c". Automatically generated by SBV. Do not edit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include "aes128Lib.h"
 
 void aes128BlockEncrypt(const SWord32 *pt, const SWord32 *xkey,
@@ -2657,10 +2649,6 @@
 == BEGIN: "aes128BlockDecrypt.c" ================
 /* File: "aes128BlockDecrypt.c". Automatically generated by SBV. Do not edit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include "aes128Lib.h"
 
 void aes128BlockDecrypt(const SWord32 *ct, const SWord32 *xkey,
@@ -3580,6 +3568,7 @@
 #include <inttypes.h>
 #include <stdint.h>
 #include <stdbool.h>
+#include <string.h>
 #include <math.h>
 
 /* The boolean type */
@@ -3617,10 +3606,6 @@
 /* Example driver program for aes128Lib. */
 /* Automatically generated by SBV. Edit as you see fit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include <stdio.h>
 #include "aes128Lib.h"
 
@@ -3755,10 +3740,10 @@
 # include any user-defined .mk file in the current directory.
 -include *.mk
 
-CC=gcc
+CC?=gcc
 CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
-AR=ar
-ARFLAGS=cr
+AR?=ar
+ARFLAGS?=cr
 
 all: aes128Lib.a aes128Lib_driver
 
diff --git a/SBVUnitTest/GoldFiles/cgUninterpret.gold b/SBVUnitTest/GoldFiles/cgUninterpret.gold
--- a/SBVUnitTest/GoldFiles/cgUninterpret.gold
+++ b/SBVUnitTest/GoldFiles/cgUninterpret.gold
@@ -4,7 +4,7 @@
 # include any user-defined .mk file in the current directory.
 -include *.mk
 
-CC=gcc
+CC?=gcc
 CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
 
 all: tstShiftLeft_driver
@@ -33,6 +33,7 @@
 #include <inttypes.h>
 #include <stdint.h>
 #include <stdbool.h>
+#include <string.h>
 #include <math.h>
 
 /* The boolean type */
@@ -65,10 +66,6 @@
 /* Example driver program for tstShiftLeft. */
 /* Automatically generated by SBV. Edit as you see fit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include <stdio.h>
 #include "tstShiftLeft.h"
 
@@ -94,10 +91,6 @@
 == BEGIN: "tstShiftLeft.c" ================
 /* File: "tstShiftLeft.c". Automatically generated by SBV. Do not edit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include "tstShiftLeft.h"
 
 /* User specified custom code for "SBV_SHIFTLEFT" */
diff --git a/SBVUnitTest/GoldFiles/codeGen1.gold b/SBVUnitTest/GoldFiles/codeGen1.gold
--- a/SBVUnitTest/GoldFiles/codeGen1.gold
+++ b/SBVUnitTest/GoldFiles/codeGen1.gold
@@ -4,7 +4,7 @@
 # include any user-defined .mk file in the current directory.
 -include *.mk
 
-CC=gcc
+CC?=gcc
 CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
 
 all: foo_driver
@@ -33,6 +33,7 @@
 #include <inttypes.h>
 #include <stdint.h>
 #include <stdbool.h>
+#include <string.h>
 #include <math.h>
 
 /* The boolean type */
@@ -66,10 +67,6 @@
 /* Example driver program for foo. */
 /* Automatically generated by SBV. Edit as you see fit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include <stdio.h>
 #include "foo.h"
 
@@ -119,10 +116,6 @@
 == BEGIN: "foo.c" ================
 /* File: "foo.c". Automatically generated by SBV. Do not edit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include "foo.h"
 
 SInt16 foo(const SInt16 x, const SInt64 *xArr, SWord16 *z,
diff --git a/SBVUnitTest/GoldFiles/crcUSB5_1.gold b/SBVUnitTest/GoldFiles/crcUSB5_1.gold
--- a/SBVUnitTest/GoldFiles/crcUSB5_1.gold
+++ b/SBVUnitTest/GoldFiles/crcUSB5_1.gold
@@ -4,7 +4,7 @@
 # include any user-defined .mk file in the current directory.
 -include *.mk
 
-CC=gcc
+CC?=gcc
 CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
 
 all: crcUSB5_driver
@@ -33,6 +33,7 @@
 #include <inttypes.h>
 #include <stdint.h>
 #include <stdbool.h>
+#include <string.h>
 #include <math.h>
 
 /* The boolean type */
@@ -65,10 +66,6 @@
 /* Example driver program for crcUSB5. */
 /* Automatically generated by SBV. Edit as you see fit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include <stdio.h>
 #include "crcUSB5.h"
 
@@ -84,10 +81,6 @@
 == BEGIN: "crcUSB5.c" ================
 /* File: "crcUSB5.c". Automatically generated by SBV. Do not edit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include "crcUSB5.h"
 
 SWord16 crcUSB5(const SWord16 msg)
diff --git a/SBVUnitTest/GoldFiles/crcUSB5_2.gold b/SBVUnitTest/GoldFiles/crcUSB5_2.gold
--- a/SBVUnitTest/GoldFiles/crcUSB5_2.gold
+++ b/SBVUnitTest/GoldFiles/crcUSB5_2.gold
@@ -4,7 +4,7 @@
 # include any user-defined .mk file in the current directory.
 -include *.mk
 
-CC=gcc
+CC?=gcc
 CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
 
 all: crcUSB5_driver
@@ -33,6 +33,7 @@
 #include <inttypes.h>
 #include <stdint.h>
 #include <stdbool.h>
+#include <string.h>
 #include <math.h>
 
 /* The boolean type */
@@ -65,10 +66,6 @@
 /* Example driver program for crcUSB5. */
 /* Automatically generated by SBV. Edit as you see fit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include <stdio.h>
 #include "crcUSB5.h"
 
@@ -84,10 +81,6 @@
 == BEGIN: "crcUSB5.c" ================
 /* File: "crcUSB5.c". Automatically generated by SBV. Do not edit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include "crcUSB5.h"
 
 SWord16 crcUSB5(const SWord16 msg)
diff --git a/SBVUnitTest/GoldFiles/fib1.gold b/SBVUnitTest/GoldFiles/fib1.gold
--- a/SBVUnitTest/GoldFiles/fib1.gold
+++ b/SBVUnitTest/GoldFiles/fib1.gold
@@ -4,7 +4,7 @@
 # include any user-defined .mk file in the current directory.
 -include *.mk
 
-CC=gcc
+CC?=gcc
 CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
 
 all: fib1_driver
@@ -33,6 +33,7 @@
 #include <inttypes.h>
 #include <stdint.h>
 #include <stdbool.h>
+#include <string.h>
 #include <math.h>
 
 /* The boolean type */
@@ -65,10 +66,6 @@
 /* Example driver program for fib1. */
 /* Automatically generated by SBV. Edit as you see fit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include <stdio.h>
 #include "fib1.h"
 
@@ -84,10 +81,6 @@
 == BEGIN: "fib1.c" ================
 /* File: "fib1.c". Automatically generated by SBV. Do not edit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include "fib1.h"
 
 SWord64 fib1(const SWord64 n)
diff --git a/SBVUnitTest/GoldFiles/fib2.gold b/SBVUnitTest/GoldFiles/fib2.gold
--- a/SBVUnitTest/GoldFiles/fib2.gold
+++ b/SBVUnitTest/GoldFiles/fib2.gold
@@ -4,7 +4,7 @@
 # include any user-defined .mk file in the current directory.
 -include *.mk
 
-CC=gcc
+CC?=gcc
 CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
 
 all: fib2_driver
@@ -33,6 +33,7 @@
 #include <inttypes.h>
 #include <stdint.h>
 #include <stdbool.h>
+#include <string.h>
 #include <math.h>
 
 /* The boolean type */
@@ -65,10 +66,6 @@
 /* Example driver program for fib2. */
 /* Automatically generated by SBV. Edit as you see fit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include <stdio.h>
 #include "fib2.h"
 
@@ -84,10 +81,6 @@
 == BEGIN: "fib2.c" ================
 /* File: "fib2.c". Automatically generated by SBV. Do not edit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include "fib2.h"
 
 SWord64 fib2(const SWord64 n)
diff --git a/SBVUnitTest/GoldFiles/floats_cgen.gold b/SBVUnitTest/GoldFiles/floats_cgen.gold
new file mode 100644
--- /dev/null
+++ b/SBVUnitTest/GoldFiles/floats_cgen.gold
@@ -0,0 +1,2873 @@
+== 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"
+
+SBool fromFP_SFloat_SWord32(const SFloat a, const SWord32 b)
+{
+  const SFloat  s0 = a;
+  const SWord32 s1 = b;
+        SFloat  s2; memcpy(&s2, &s1, sizeof(SFloat));
+  const SBool   s3 = isnan(s0) ? isnan(s2) : (signbit(s0) && (s0 == 0)) ? (signbit(s2) && (s2 == 0)) : (signbit(s2) && (s2 == 0)) ? (signbit(s0) && (s0 == 0)) : (s0 == s2);
+
+  return s3;
+}
+== 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"
+
+SBool fromFP_SDouble_SWord64(const SDouble a, const SWord64 b)
+{
+  const SDouble s0 = a;
+  const SWord64 s1 = b;
+        SDouble s2; memcpy(&s2, &s1, sizeof(SDouble));
+  const SBool   s3 = isnan(s0) ? isnan(s2) : (signbit(s0) && (s0 == 0)) ? (signbit(s2) && (s2 == 0)) : (signbit(s2) && (s2 == 0)) ? (signbit(s0) && (s0 == 0)) : (s0 == s2);
+
+  return s3;
+}
+== 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 <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);
+SBool fromFP_SFloat_SWord32(const SFloat a, const SWord32 b);
+SBool fromFP_SDouble_SWord64(const SDouble a, const SWord64 b);
+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 SBool __result = fromFP_SFloat_SWord32(42.0F,
+                                               0x0000002bUL);
+
+  printf("fromFP_SFloat_SWord32(42.0F, 0x0000002bUL) = %d\n", __result);
+}
+
+void fromFP_SDouble_SWord64_driver(void)
+{
+  const SBool __result = fromFP_SDouble_SWord64(42.0,
+                                                0x000000000000002bULL);
+
+  printf("fromFP_SDouble_SWord64(42.0, 0x000000000000002bULL) = %d\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
--- a/SBVUnitTest/GoldFiles/gcd.gold
+++ b/SBVUnitTest/GoldFiles/gcd.gold
@@ -4,7 +4,7 @@
 # include any user-defined .mk file in the current directory.
 -include *.mk
 
-CC=gcc
+CC?=gcc
 CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
 
 all: sgcd_driver
@@ -33,6 +33,7 @@
 #include <inttypes.h>
 #include <stdint.h>
 #include <stdbool.h>
+#include <string.h>
 #include <math.h>
 
 /* The boolean type */
@@ -65,10 +66,6 @@
 /* Example driver program for sgcd. */
 /* Automatically generated by SBV. Edit as you see fit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include <stdio.h>
 #include "sgcd.h"
 
@@ -84,10 +81,6 @@
 == BEGIN: "sgcd.c" ================
 /* File: "sgcd.c". Automatically generated by SBV. Do not edit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include "sgcd.h"
 
 SWord8 sgcd(const SWord8 x, const SWord8 y)
diff --git a/SBVUnitTest/GoldFiles/legato_c.gold b/SBVUnitTest/GoldFiles/legato_c.gold
--- a/SBVUnitTest/GoldFiles/legato_c.gold
+++ b/SBVUnitTest/GoldFiles/legato_c.gold
@@ -4,7 +4,7 @@
 # include any user-defined .mk file in the current directory.
 -include *.mk
 
-CC=gcc
+CC?=gcc
 CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
 
 all: legatoMult_driver
@@ -33,6 +33,7 @@
 #include <inttypes.h>
 #include <stdint.h>
 #include <stdbool.h>
+#include <string.h>
 #include <math.h>
 
 /* The boolean type */
@@ -66,10 +67,6 @@
 /* Example driver program for legatoMult. */
 /* Automatically generated by SBV. Edit as you see fit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include <stdio.h>
 #include "legatoMult.h"
 
@@ -90,10 +87,6 @@
 == BEGIN: "legatoMult.c" ================
 /* File: "legatoMult.c". Automatically generated by SBV. Do not edit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include "legatoMult.h"
 
 void legatoMult(const SWord8 x, const SWord8 y, SWord8 *hi,
@@ -208,7 +201,7 @@
   const SWord8 s110 = s1 + s105;
   const SBool  s111 = s110 < s1;
   const SBool  s112 = s110 < s105;
-  const SBool  s113 = s111 | s112;
+  const SBool  s113 = s111 || s112;
   const SWord8 s114 = (s110 >> 1) | (s110 << 7);
   const SWord8 s115 = 128 | s114;
   const SWord8 s116 = 127 & s114;
@@ -217,7 +210,7 @@
   const SWord8 s119 = s1 + s101;
   const SBool  s120 = s119 < s1;
   const SBool  s121 = s119 < s101;
-  const SBool  s122 = s120 | s121;
+  const SBool  s122 = s120 || s121;
   const SWord8 s123 = (s119 >> 1) | (s119 << 7);
   const SWord8 s124 = 128 | s123;
   const SWord8 s125 = 127 & s123;
@@ -229,7 +222,7 @@
   const SWord8 s131 = s1 + s126;
   const SBool  s132 = s131 < s1;
   const SBool  s133 = s131 < s126;
-  const SBool  s134 = s132 | s133;
+  const SBool  s134 = s132 || s133;
   const SWord8 s135 = (s131 >> 1) | (s131 << 7);
   const SWord8 s136 = 128 | s135;
   const SWord8 s137 = 127 & s135;
@@ -239,7 +232,7 @@
   const SWord8 s141 = s1 + s97;
   const SBool  s142 = s141 < s1;
   const SBool  s143 = s141 < s97;
-  const SBool  s144 = s142 | s143;
+  const SBool  s144 = s142 || s143;
   const SWord8 s145 = (s141 >> 1) | (s141 << 7);
   const SWord8 s146 = 128 | s145;
   const SWord8 s147 = 127 & s145;
@@ -255,7 +248,7 @@
   const SWord8 s157 = s1 + s152;
   const SBool  s158 = s157 < s1;
   const SBool  s159 = s157 < s152;
-  const SBool  s160 = s158 | s159;
+  const SBool  s160 = s158 || s159;
   const SWord8 s161 = (s157 >> 1) | (s157 << 7);
   const SWord8 s162 = 128 | s161;
   const SWord8 s163 = 127 & s161;
@@ -264,7 +257,7 @@
   const SWord8 s166 = s1 + s148;
   const SBool  s167 = s166 < s1;
   const SBool  s168 = s166 < s148;
-  const SBool  s169 = s167 | s168;
+  const SBool  s169 = s167 || s168;
   const SWord8 s170 = (s166 >> 1) | (s166 << 7);
   const SWord8 s171 = 128 | s170;
   const SWord8 s172 = 127 & s170;
@@ -276,7 +269,7 @@
   const SWord8 s178 = s1 + s173;
   const SBool  s179 = s178 < s1;
   const SBool  s180 = s178 < s173;
-  const SBool  s181 = s179 | s180;
+  const SBool  s181 = s179 || s180;
   const SWord8 s182 = (s178 >> 1) | (s178 << 7);
   const SWord8 s183 = 128 | s182;
   const SWord8 s184 = 127 & s182;
@@ -296,7 +289,7 @@
   const SBool  s198 = false == s197;
   const SBool  s199 = s189 < s1;
   const SBool  s200 = s189 < s78;
-  const SBool  s201 = s199 | s200;
+  const SBool  s201 = s199 || s200;
   const SWord8 s202 = (s189 >> 1) | (s189 << 7);
   const SWord8 s203 = 128 | s202;
   const SWord8 s204 = 127 & s202;
@@ -316,7 +309,7 @@
   const SWord8 s218 = s1 + s213;
   const SBool  s219 = s218 < s1;
   const SBool  s220 = s218 < s213;
-  const SBool  s221 = s219 | s220;
+  const SBool  s221 = s219 || s220;
   const SWord8 s222 = (s218 >> 1) | (s218 << 7);
   const SWord8 s223 = 128 | s222;
   const SWord8 s224 = 127 & s222;
@@ -325,7 +318,7 @@
   const SWord8 s227 = s1 + s209;
   const SBool  s228 = s227 < s1;
   const SBool  s229 = s227 < s209;
-  const SBool  s230 = s228 | s229;
+  const SBool  s230 = s228 || s229;
   const SWord8 s231 = (s227 >> 1) | (s227 << 7);
   const SWord8 s232 = 128 | s231;
   const SWord8 s233 = 127 & s231;
@@ -337,7 +330,7 @@
   const SWord8 s239 = s1 + s234;
   const SBool  s240 = s239 < s1;
   const SBool  s241 = s239 < s234;
-  const SBool  s242 = s240 | s241;
+  const SBool  s242 = s240 || s241;
   const SWord8 s243 = (s239 >> 1) | (s239 << 7);
   const SWord8 s244 = 128 | s243;
   const SWord8 s245 = 127 & s243;
@@ -347,7 +340,7 @@
   const SWord8 s249 = s1 + s205;
   const SBool  s250 = s249 < s1;
   const SBool  s251 = s249 < s205;
-  const SBool  s252 = s250 | s251;
+  const SBool  s252 = s250 || s251;
   const SWord8 s253 = (s249 >> 1) | (s249 << 7);
   const SWord8 s254 = 128 | s253;
   const SWord8 s255 = 127 & s253;
@@ -363,7 +356,7 @@
   const SWord8 s265 = s1 + s260;
   const SBool  s266 = s265 < s1;
   const SBool  s267 = s265 < s260;
-  const SBool  s268 = s266 | s267;
+  const SBool  s268 = s266 || s267;
   const SWord8 s269 = (s265 >> 1) | (s265 << 7);
   const SWord8 s270 = 128 | s269;
   const SWord8 s271 = 127 & s269;
@@ -372,7 +365,7 @@
   const SWord8 s274 = s1 + s256;
   const SBool  s275 = s274 < s1;
   const SBool  s276 = s274 < s256;
-  const SBool  s277 = s275 | s276;
+  const SBool  s277 = s275 || s276;
   const SWord8 s278 = (s274 >> 1) | (s274 << 7);
   const SWord8 s279 = 128 | s278;
   const SWord8 s280 = 127 & s278;
@@ -384,7 +377,7 @@
   const SWord8 s286 = s1 + s281;
   const SBool  s287 = s286 < s1;
   const SBool  s288 = s286 < s281;
-  const SBool  s289 = s287 | s288;
+  const SBool  s289 = s287 || s288;
   const SWord8 s290 = (s286 >> 1) | (s286 << 7);
   const SWord8 s291 = 128 | s290;
   const SWord8 s292 = 127 & s290;
@@ -405,7 +398,7 @@
   const SBool  s307 = false == s306;
   const SBool  s308 = s298 < s1;
   const SBool  s309 = s298 < s59;
-  const SBool  s310 = s308 | s309;
+  const SBool  s310 = s308 || s309;
   const SWord8 s311 = (s298 >> 1) | (s298 << 7);
   const SWord8 s312 = 128 | s311;
   const SWord8 s313 = 127 & s311;
@@ -444,7 +437,7 @@
   const SWord8 s346 = s1 + s341;
   const SBool  s347 = s346 < s1;
   const SBool  s348 = s346 < s341;
-  const SBool  s349 = s347 | s348;
+  const SBool  s349 = s347 || s348;
   const SWord8 s350 = (s346 >> 1) | (s346 << 7);
   const SWord8 s351 = 128 | s350;
   const SWord8 s352 = 127 & s350;
@@ -453,7 +446,7 @@
   const SWord8 s355 = s1 + s337;
   const SBool  s356 = s355 < s1;
   const SBool  s357 = s355 < s337;
-  const SBool  s358 = s356 | s357;
+  const SBool  s358 = s356 || s357;
   const SWord8 s359 = (s355 >> 1) | (s355 << 7);
   const SWord8 s360 = 128 | s359;
   const SWord8 s361 = 127 & s359;
@@ -465,7 +458,7 @@
   const SWord8 s367 = s1 + s362;
   const SBool  s368 = s367 < s1;
   const SBool  s369 = s367 < s362;
-  const SBool  s370 = s368 | s369;
+  const SBool  s370 = s368 || s369;
   const SWord8 s371 = (s367 >> 1) | (s367 << 7);
   const SWord8 s372 = 128 | s371;
   const SWord8 s373 = 127 & s371;
@@ -475,7 +468,7 @@
   const SWord8 s377 = s1 + s333;
   const SBool  s378 = s377 < s1;
   const SBool  s379 = s377 < s333;
-  const SBool  s380 = s378 | s379;
+  const SBool  s380 = s378 || s379;
   const SWord8 s381 = (s377 >> 1) | (s377 << 7);
   const SWord8 s382 = 128 | s381;
   const SWord8 s383 = 127 & s381;
@@ -491,7 +484,7 @@
   const SWord8 s393 = s1 + s388;
   const SBool  s394 = s393 < s1;
   const SBool  s395 = s393 < s388;
-  const SBool  s396 = s394 | s395;
+  const SBool  s396 = s394 || s395;
   const SWord8 s397 = (s393 >> 1) | (s393 << 7);
   const SWord8 s398 = 128 | s397;
   const SWord8 s399 = 127 & s397;
@@ -500,7 +493,7 @@
   const SWord8 s402 = s1 + s384;
   const SBool  s403 = s402 < s1;
   const SBool  s404 = s402 < s384;
-  const SBool  s405 = s403 | s404;
+  const SBool  s405 = s403 || s404;
   const SWord8 s406 = (s402 >> 1) | (s402 << 7);
   const SWord8 s407 = 128 | s406;
   const SWord8 s408 = 127 & s406;
@@ -512,7 +505,7 @@
   const SWord8 s414 = s1 + s409;
   const SBool  s415 = s414 < s1;
   const SBool  s416 = s414 < s409;
-  const SBool  s417 = s415 | s416;
+  const SBool  s417 = s415 || s416;
   const SWord8 s418 = (s414 >> 1) | (s414 << 7);
   const SWord8 s419 = 128 | s418;
   const SWord8 s420 = 127 & s418;
@@ -532,7 +525,7 @@
   const SBool  s434 = false == s433;
   const SBool  s435 = s425 < s1;
   const SBool  s436 = s425 < s314;
-  const SBool  s437 = s435 | s436;
+  const SBool  s437 = s435 || s436;
   const SWord8 s438 = (s425 >> 1) | (s425 << 7);
   const SWord8 s439 = 128 | s438;
   const SWord8 s440 = 127 & s438;
@@ -552,7 +545,7 @@
   const SWord8 s454 = s1 + s449;
   const SBool  s455 = s454 < s1;
   const SBool  s456 = s454 < s449;
-  const SBool  s457 = s455 | s456;
+  const SBool  s457 = s455 || s456;
   const SWord8 s458 = (s454 >> 1) | (s454 << 7);
   const SWord8 s459 = 128 | s458;
   const SWord8 s460 = 127 & s458;
@@ -561,7 +554,7 @@
   const SWord8 s463 = s1 + s445;
   const SBool  s464 = s463 < s1;
   const SBool  s465 = s463 < s445;
-  const SBool  s466 = s464 | s465;
+  const SBool  s466 = s464 || s465;
   const SWord8 s467 = (s463 >> 1) | (s463 << 7);
   const SWord8 s468 = 128 | s467;
   const SWord8 s469 = 127 & s467;
@@ -573,7 +566,7 @@
   const SWord8 s475 = s1 + s470;
   const SBool  s476 = s475 < s1;
   const SBool  s477 = s475 < s470;
-  const SBool  s478 = s476 | s477;
+  const SBool  s478 = s476 || s477;
   const SWord8 s479 = (s475 >> 1) | (s475 << 7);
   const SWord8 s480 = 128 | s479;
   const SWord8 s481 = 127 & s479;
@@ -583,7 +576,7 @@
   const SWord8 s485 = s1 + s441;
   const SBool  s486 = s485 < s1;
   const SBool  s487 = s485 < s441;
-  const SBool  s488 = s486 | s487;
+  const SBool  s488 = s486 || s487;
   const SWord8 s489 = (s485 >> 1) | (s485 << 7);
   const SWord8 s490 = 128 | s489;
   const SWord8 s491 = 127 & s489;
@@ -599,7 +592,7 @@
   const SWord8 s501 = s1 + s496;
   const SBool  s502 = s501 < s1;
   const SBool  s503 = s501 < s496;
-  const SBool  s504 = s502 | s503;
+  const SBool  s504 = s502 || s503;
   const SWord8 s505 = (s501 >> 1) | (s501 << 7);
   const SWord8 s506 = 128 | s505;
   const SWord8 s507 = 127 & s505;
@@ -608,7 +601,7 @@
   const SWord8 s510 = s1 + s492;
   const SBool  s511 = s510 < s1;
   const SBool  s512 = s510 < s492;
-  const SBool  s513 = s511 | s512;
+  const SBool  s513 = s511 || s512;
   const SWord8 s514 = (s510 >> 1) | (s510 << 7);
   const SWord8 s515 = 128 | s514;
   const SWord8 s516 = 127 & s514;
@@ -620,7 +613,7 @@
   const SWord8 s522 = s1 + s517;
   const SBool  s523 = s522 < s1;
   const SBool  s524 = s522 < s517;
-  const SBool  s525 = s523 | s524;
+  const SBool  s525 = s523 || s524;
   const SWord8 s526 = (s522 >> 1) | (s522 << 7);
   const SWord8 s527 = 128 | s526;
   const SWord8 s528 = 127 & s526;
@@ -642,7 +635,7 @@
   const SBool  s544 = false == s543;
   const SBool  s545 = s535 < s1;
   const SBool  s546 = s535 < s40;
-  const SBool  s547 = s545 | s546;
+  const SBool  s547 = s545 || s546;
   const SWord8 s548 = (s535 >> 1) | (s535 << 7);
   const SWord8 s549 = 128 | s548;
   const SWord8 s550 = 127 & s548;
@@ -700,7 +693,7 @@
   const SWord8 s602 = s1 + s597;
   const SBool  s603 = s602 < s1;
   const SBool  s604 = s602 < s597;
-  const SBool  s605 = s603 | s604;
+  const SBool  s605 = s603 || s604;
   const SWord8 s606 = (s602 >> 1) | (s602 << 7);
   const SWord8 s607 = 128 | s606;
   const SWord8 s608 = 127 & s606;
@@ -709,7 +702,7 @@
   const SWord8 s611 = s1 + s593;
   const SBool  s612 = s611 < s1;
   const SBool  s613 = s611 < s593;
-  const SBool  s614 = s612 | s613;
+  const SBool  s614 = s612 || s613;
   const SWord8 s615 = (s611 >> 1) | (s611 << 7);
   const SWord8 s616 = 128 | s615;
   const SWord8 s617 = 127 & s615;
@@ -721,7 +714,7 @@
   const SWord8 s623 = s1 + s618;
   const SBool  s624 = s623 < s1;
   const SBool  s625 = s623 < s618;
-  const SBool  s626 = s624 | s625;
+  const SBool  s626 = s624 || s625;
   const SWord8 s627 = (s623 >> 1) | (s623 << 7);
   const SWord8 s628 = 128 | s627;
   const SWord8 s629 = 127 & s627;
@@ -731,7 +724,7 @@
   const SWord8 s633 = s1 + s589;
   const SBool  s634 = s633 < s1;
   const SBool  s635 = s633 < s589;
-  const SBool  s636 = s634 | s635;
+  const SBool  s636 = s634 || s635;
   const SWord8 s637 = (s633 >> 1) | (s633 << 7);
   const SWord8 s638 = 128 | s637;
   const SWord8 s639 = 127 & s637;
@@ -747,7 +740,7 @@
   const SWord8 s649 = s1 + s644;
   const SBool  s650 = s649 < s1;
   const SBool  s651 = s649 < s644;
-  const SBool  s652 = s650 | s651;
+  const SBool  s652 = s650 || s651;
   const SWord8 s653 = (s649 >> 1) | (s649 << 7);
   const SWord8 s654 = 128 | s653;
   const SWord8 s655 = 127 & s653;
@@ -756,7 +749,7 @@
   const SWord8 s658 = s1 + s640;
   const SBool  s659 = s658 < s1;
   const SBool  s660 = s658 < s640;
-  const SBool  s661 = s659 | s660;
+  const SBool  s661 = s659 || s660;
   const SWord8 s662 = (s658 >> 1) | (s658 << 7);
   const SWord8 s663 = 128 | s662;
   const SWord8 s664 = 127 & s662;
@@ -768,7 +761,7 @@
   const SWord8 s670 = s1 + s665;
   const SBool  s671 = s670 < s1;
   const SBool  s672 = s670 < s665;
-  const SBool  s673 = s671 | s672;
+  const SBool  s673 = s671 || s672;
   const SWord8 s674 = (s670 >> 1) | (s670 << 7);
   const SWord8 s675 = 128 | s674;
   const SWord8 s676 = 127 & s674;
@@ -788,7 +781,7 @@
   const SBool  s690 = false == s689;
   const SBool  s691 = s681 < s1;
   const SBool  s692 = s681 < s570;
-  const SBool  s693 = s691 | s692;
+  const SBool  s693 = s691 || s692;
   const SWord8 s694 = (s681 >> 1) | (s681 << 7);
   const SWord8 s695 = 128 | s694;
   const SWord8 s696 = 127 & s694;
@@ -808,7 +801,7 @@
   const SWord8 s710 = s1 + s705;
   const SBool  s711 = s710 < s1;
   const SBool  s712 = s710 < s705;
-  const SBool  s713 = s711 | s712;
+  const SBool  s713 = s711 || s712;
   const SWord8 s714 = (s710 >> 1) | (s710 << 7);
   const SWord8 s715 = 128 | s714;
   const SWord8 s716 = 127 & s714;
@@ -817,7 +810,7 @@
   const SWord8 s719 = s1 + s701;
   const SBool  s720 = s719 < s1;
   const SBool  s721 = s719 < s701;
-  const SBool  s722 = s720 | s721;
+  const SBool  s722 = s720 || s721;
   const SWord8 s723 = (s719 >> 1) | (s719 << 7);
   const SWord8 s724 = 128 | s723;
   const SWord8 s725 = 127 & s723;
@@ -829,7 +822,7 @@
   const SWord8 s731 = s1 + s726;
   const SBool  s732 = s731 < s1;
   const SBool  s733 = s731 < s726;
-  const SBool  s734 = s732 | s733;
+  const SBool  s734 = s732 || s733;
   const SWord8 s735 = (s731 >> 1) | (s731 << 7);
   const SWord8 s736 = 128 | s735;
   const SWord8 s737 = 127 & s735;
@@ -839,7 +832,7 @@
   const SWord8 s741 = s1 + s697;
   const SBool  s742 = s741 < s1;
   const SBool  s743 = s741 < s697;
-  const SBool  s744 = s742 | s743;
+  const SBool  s744 = s742 || s743;
   const SWord8 s745 = (s741 >> 1) | (s741 << 7);
   const SWord8 s746 = 128 | s745;
   const SWord8 s747 = 127 & s745;
@@ -855,7 +848,7 @@
   const SWord8 s757 = s1 + s752;
   const SBool  s758 = s757 < s1;
   const SBool  s759 = s757 < s752;
-  const SBool  s760 = s758 | s759;
+  const SBool  s760 = s758 || s759;
   const SWord8 s761 = (s757 >> 1) | (s757 << 7);
   const SWord8 s762 = 128 | s761;
   const SWord8 s763 = 127 & s761;
@@ -864,7 +857,7 @@
   const SWord8 s766 = s1 + s748;
   const SBool  s767 = s766 < s1;
   const SBool  s768 = s766 < s748;
-  const SBool  s769 = s767 | s768;
+  const SBool  s769 = s767 || s768;
   const SWord8 s770 = (s766 >> 1) | (s766 << 7);
   const SWord8 s771 = 128 | s770;
   const SWord8 s772 = 127 & s770;
@@ -876,7 +869,7 @@
   const SWord8 s778 = s1 + s773;
   const SBool  s779 = s778 < s1;
   const SBool  s780 = s778 < s773;
-  const SBool  s781 = s779 | s780;
+  const SBool  s781 = s779 || s780;
   const SWord8 s782 = (s778 >> 1) | (s778 << 7);
   const SWord8 s783 = 128 | s782;
   const SWord8 s784 = 127 & s782;
@@ -897,7 +890,7 @@
   const SBool  s799 = false == s798;
   const SBool  s800 = s790 < s1;
   const SBool  s801 = s790 < s551;
-  const SBool  s802 = s800 | s801;
+  const SBool  s802 = s800 || s801;
   const SWord8 s803 = (s790 >> 1) | (s790 << 7);
   const SWord8 s804 = 128 | s803;
   const SWord8 s805 = 127 & s803;
@@ -936,7 +929,7 @@
   const SWord8 s838 = s1 + s833;
   const SBool  s839 = s838 < s1;
   const SBool  s840 = s838 < s833;
-  const SBool  s841 = s839 | s840;
+  const SBool  s841 = s839 || s840;
   const SWord8 s842 = (s838 >> 1) | (s838 << 7);
   const SWord8 s843 = 128 | s842;
   const SWord8 s844 = 127 & s842;
@@ -945,7 +938,7 @@
   const SWord8 s847 = s1 + s829;
   const SBool  s848 = s847 < s1;
   const SBool  s849 = s847 < s829;
-  const SBool  s850 = s848 | s849;
+  const SBool  s850 = s848 || s849;
   const SWord8 s851 = (s847 >> 1) | (s847 << 7);
   const SWord8 s852 = 128 | s851;
   const SWord8 s853 = 127 & s851;
@@ -957,7 +950,7 @@
   const SWord8 s859 = s1 + s854;
   const SBool  s860 = s859 < s1;
   const SBool  s861 = s859 < s854;
-  const SBool  s862 = s860 | s861;
+  const SBool  s862 = s860 || s861;
   const SWord8 s863 = (s859 >> 1) | (s859 << 7);
   const SWord8 s864 = 128 | s863;
   const SWord8 s865 = 127 & s863;
@@ -967,7 +960,7 @@
   const SWord8 s869 = s1 + s825;
   const SBool  s870 = s869 < s1;
   const SBool  s871 = s869 < s825;
-  const SBool  s872 = s870 | s871;
+  const SBool  s872 = s870 || s871;
   const SWord8 s873 = (s869 >> 1) | (s869 << 7);
   const SWord8 s874 = 128 | s873;
   const SWord8 s875 = 127 & s873;
@@ -983,7 +976,7 @@
   const SWord8 s885 = s1 + s880;
   const SBool  s886 = s885 < s1;
   const SBool  s887 = s885 < s880;
-  const SBool  s888 = s886 | s887;
+  const SBool  s888 = s886 || s887;
   const SWord8 s889 = (s885 >> 1) | (s885 << 7);
   const SWord8 s890 = 128 | s889;
   const SWord8 s891 = 127 & s889;
@@ -992,7 +985,7 @@
   const SWord8 s894 = s1 + s876;
   const SBool  s895 = s894 < s1;
   const SBool  s896 = s894 < s876;
-  const SBool  s897 = s895 | s896;
+  const SBool  s897 = s895 || s896;
   const SWord8 s898 = (s894 >> 1) | (s894 << 7);
   const SWord8 s899 = 128 | s898;
   const SWord8 s900 = 127 & s898;
@@ -1004,7 +997,7 @@
   const SWord8 s906 = s1 + s901;
   const SBool  s907 = s906 < s1;
   const SBool  s908 = s906 < s901;
-  const SBool  s909 = s907 | s908;
+  const SBool  s909 = s907 || s908;
   const SWord8 s910 = (s906 >> 1) | (s906 << 7);
   const SWord8 s911 = 128 | s910;
   const SWord8 s912 = 127 & s910;
@@ -1024,7 +1017,7 @@
   const SBool  s926 = false == s925;
   const SBool  s927 = s917 < s1;
   const SBool  s928 = s917 < s806;
-  const SBool  s929 = s927 | s928;
+  const SBool  s929 = s927 || s928;
   const SWord8 s930 = (s917 >> 1) | (s917 << 7);
   const SWord8 s931 = 128 | s930;
   const SWord8 s932 = 127 & s930;
@@ -1044,7 +1037,7 @@
   const SWord8 s946 = s1 + s941;
   const SBool  s947 = s946 < s1;
   const SBool  s948 = s946 < s941;
-  const SBool  s949 = s947 | s948;
+  const SBool  s949 = s947 || s948;
   const SWord8 s950 = (s946 >> 1) | (s946 << 7);
   const SWord8 s951 = 128 | s950;
   const SWord8 s952 = 127 & s950;
@@ -1053,7 +1046,7 @@
   const SWord8 s955 = s1 + s937;
   const SBool  s956 = s955 < s1;
   const SBool  s957 = s955 < s937;
-  const SBool  s958 = s956 | s957;
+  const SBool  s958 = s956 || s957;
   const SWord8 s959 = (s955 >> 1) | (s955 << 7);
   const SWord8 s960 = 128 | s959;
   const SWord8 s961 = 127 & s959;
@@ -1065,7 +1058,7 @@
   const SWord8 s967 = s1 + s962;
   const SBool  s968 = s967 < s1;
   const SBool  s969 = s967 < s962;
-  const SBool  s970 = s968 | s969;
+  const SBool  s970 = s968 || s969;
   const SWord8 s971 = (s967 >> 1) | (s967 << 7);
   const SWord8 s972 = 128 | s971;
   const SWord8 s973 = 127 & s971;
@@ -1075,7 +1068,7 @@
   const SWord8 s977 = s1 + s933;
   const SBool  s978 = s977 < s1;
   const SBool  s979 = s977 < s933;
-  const SBool  s980 = s978 | s979;
+  const SBool  s980 = s978 || s979;
   const SWord8 s981 = (s977 >> 1) | (s977 << 7);
   const SWord8 s982 = 128 | s981;
   const SWord8 s983 = 127 & s981;
@@ -1091,7 +1084,7 @@
   const SWord8 s993 = s1 + s988;
   const SBool  s994 = s993 < s1;
   const SBool  s995 = s993 < s988;
-  const SBool  s996 = s994 | s995;
+  const SBool  s996 = s994 || s995;
   const SWord8 s997 = (s993 >> 1) | (s993 << 7);
   const SWord8 s998 = 128 | s997;
   const SWord8 s999 = 127 & s997;
@@ -1100,7 +1093,7 @@
   const SWord8 s1002 = s1 + s984;
   const SBool  s1003 = s1002 < s1;
   const SBool  s1004 = s1002 < s984;
-  const SBool  s1005 = s1003 | s1004;
+  const SBool  s1005 = s1003 || s1004;
   const SWord8 s1006 = (s1002 >> 1) | (s1002 << 7);
   const SWord8 s1007 = 128 | s1006;
   const SWord8 s1008 = 127 & s1006;
@@ -1112,7 +1105,7 @@
   const SWord8 s1014 = s1 + s1009;
   const SBool  s1015 = s1014 < s1;
   const SBool  s1016 = s1014 < s1009;
-  const SBool  s1017 = s1015 | s1016;
+  const SBool  s1017 = s1015 || s1016;
   const SWord8 s1018 = (s1014 >> 1) | (s1014 << 7);
   const SWord8 s1019 = 128 | s1018;
   const SWord8 s1020 = 127 & s1018;
@@ -1135,7 +1128,7 @@
   const SBool  s1037 = false == s1036;
   const SBool  s1038 = s1028 < s1;
   const SBool  s1039 = s1028 < s24;
-  const SBool  s1040 = s1038 | s1039;
+  const SBool  s1040 = s1038 || s1039;
   const SWord8 s1041 = (s1028 >> 1) | (s1028 << 7);
   const SWord8 s1042 = 128 | s1041;
   const SWord8 s1043 = 127 & s1041;
@@ -1212,7 +1205,7 @@
   const SWord8 s1114 = s1 + s1109;
   const SBool  s1115 = s1114 < s1;
   const SBool  s1116 = s1114 < s1109;
-  const SBool  s1117 = s1115 | s1116;
+  const SBool  s1117 = s1115 || s1116;
   const SWord8 s1118 = (s1114 >> 1) | (s1114 << 7);
   const SWord8 s1119 = 128 | s1118;
   const SWord8 s1120 = 127 & s1118;
@@ -1221,7 +1214,7 @@
   const SWord8 s1123 = s1 + s1105;
   const SBool  s1124 = s1123 < s1;
   const SBool  s1125 = s1123 < s1105;
-  const SBool  s1126 = s1124 | s1125;
+  const SBool  s1126 = s1124 || s1125;
   const SWord8 s1127 = (s1123 >> 1) | (s1123 << 7);
   const SWord8 s1128 = 128 | s1127;
   const SWord8 s1129 = 127 & s1127;
@@ -1233,7 +1226,7 @@
   const SWord8 s1135 = s1 + s1130;
   const SBool  s1136 = s1135 < s1;
   const SBool  s1137 = s1135 < s1130;
-  const SBool  s1138 = s1136 | s1137;
+  const SBool  s1138 = s1136 || s1137;
   const SWord8 s1139 = (s1135 >> 1) | (s1135 << 7);
   const SWord8 s1140 = 128 | s1139;
   const SWord8 s1141 = 127 & s1139;
@@ -1243,7 +1236,7 @@
   const SWord8 s1145 = s1 + s1101;
   const SBool  s1146 = s1145 < s1;
   const SBool  s1147 = s1145 < s1101;
-  const SBool  s1148 = s1146 | s1147;
+  const SBool  s1148 = s1146 || s1147;
   const SWord8 s1149 = (s1145 >> 1) | (s1145 << 7);
   const SWord8 s1150 = 128 | s1149;
   const SWord8 s1151 = 127 & s1149;
@@ -1259,7 +1252,7 @@
   const SWord8 s1161 = s1 + s1156;
   const SBool  s1162 = s1161 < s1;
   const SBool  s1163 = s1161 < s1156;
-  const SBool  s1164 = s1162 | s1163;
+  const SBool  s1164 = s1162 || s1163;
   const SWord8 s1165 = (s1161 >> 1) | (s1161 << 7);
   const SWord8 s1166 = 128 | s1165;
   const SWord8 s1167 = 127 & s1165;
@@ -1268,7 +1261,7 @@
   const SWord8 s1170 = s1 + s1152;
   const SBool  s1171 = s1170 < s1;
   const SBool  s1172 = s1170 < s1152;
-  const SBool  s1173 = s1171 | s1172;
+  const SBool  s1173 = s1171 || s1172;
   const SWord8 s1174 = (s1170 >> 1) | (s1170 << 7);
   const SWord8 s1175 = 128 | s1174;
   const SWord8 s1176 = 127 & s1174;
@@ -1280,7 +1273,7 @@
   const SWord8 s1182 = s1 + s1177;
   const SBool  s1183 = s1182 < s1;
   const SBool  s1184 = s1182 < s1177;
-  const SBool  s1185 = s1183 | s1184;
+  const SBool  s1185 = s1183 || s1184;
   const SWord8 s1186 = (s1182 >> 1) | (s1182 << 7);
   const SWord8 s1187 = 128 | s1186;
   const SWord8 s1188 = 127 & s1186;
@@ -1300,7 +1293,7 @@
   const SBool  s1202 = false == s1201;
   const SBool  s1203 = s1193 < s1;
   const SBool  s1204 = s1193 < s1082;
-  const SBool  s1205 = s1203 | s1204;
+  const SBool  s1205 = s1203 || s1204;
   const SWord8 s1206 = (s1193 >> 1) | (s1193 << 7);
   const SWord8 s1207 = 128 | s1206;
   const SWord8 s1208 = 127 & s1206;
@@ -1320,7 +1313,7 @@
   const SWord8 s1222 = s1 + s1217;
   const SBool  s1223 = s1222 < s1;
   const SBool  s1224 = s1222 < s1217;
-  const SBool  s1225 = s1223 | s1224;
+  const SBool  s1225 = s1223 || s1224;
   const SWord8 s1226 = (s1222 >> 1) | (s1222 << 7);
   const SWord8 s1227 = 128 | s1226;
   const SWord8 s1228 = 127 & s1226;
@@ -1329,7 +1322,7 @@
   const SWord8 s1231 = s1 + s1213;
   const SBool  s1232 = s1231 < s1;
   const SBool  s1233 = s1231 < s1213;
-  const SBool  s1234 = s1232 | s1233;
+  const SBool  s1234 = s1232 || s1233;
   const SWord8 s1235 = (s1231 >> 1) | (s1231 << 7);
   const SWord8 s1236 = 128 | s1235;
   const SWord8 s1237 = 127 & s1235;
@@ -1341,7 +1334,7 @@
   const SWord8 s1243 = s1 + s1238;
   const SBool  s1244 = s1243 < s1;
   const SBool  s1245 = s1243 < s1238;
-  const SBool  s1246 = s1244 | s1245;
+  const SBool  s1246 = s1244 || s1245;
   const SWord8 s1247 = (s1243 >> 1) | (s1243 << 7);
   const SWord8 s1248 = 128 | s1247;
   const SWord8 s1249 = 127 & s1247;
@@ -1351,7 +1344,7 @@
   const SWord8 s1253 = s1 + s1209;
   const SBool  s1254 = s1253 < s1;
   const SBool  s1255 = s1253 < s1209;
-  const SBool  s1256 = s1254 | s1255;
+  const SBool  s1256 = s1254 || s1255;
   const SWord8 s1257 = (s1253 >> 1) | (s1253 << 7);
   const SWord8 s1258 = 128 | s1257;
   const SWord8 s1259 = 127 & s1257;
@@ -1367,7 +1360,7 @@
   const SWord8 s1269 = s1 + s1264;
   const SBool  s1270 = s1269 < s1;
   const SBool  s1271 = s1269 < s1264;
-  const SBool  s1272 = s1270 | s1271;
+  const SBool  s1272 = s1270 || s1271;
   const SWord8 s1273 = (s1269 >> 1) | (s1269 << 7);
   const SWord8 s1274 = 128 | s1273;
   const SWord8 s1275 = 127 & s1273;
@@ -1376,7 +1369,7 @@
   const SWord8 s1278 = s1 + s1260;
   const SBool  s1279 = s1278 < s1;
   const SBool  s1280 = s1278 < s1260;
-  const SBool  s1281 = s1279 | s1280;
+  const SBool  s1281 = s1279 || s1280;
   const SWord8 s1282 = (s1278 >> 1) | (s1278 << 7);
   const SWord8 s1283 = 128 | s1282;
   const SWord8 s1284 = 127 & s1282;
@@ -1388,7 +1381,7 @@
   const SWord8 s1290 = s1 + s1285;
   const SBool  s1291 = s1290 < s1;
   const SBool  s1292 = s1290 < s1285;
-  const SBool  s1293 = s1291 | s1292;
+  const SBool  s1293 = s1291 || s1292;
   const SWord8 s1294 = (s1290 >> 1) | (s1290 << 7);
   const SWord8 s1295 = 128 | s1294;
   const SWord8 s1296 = 127 & s1294;
@@ -1409,7 +1402,7 @@
   const SBool  s1311 = false == s1310;
   const SBool  s1312 = s1302 < s1;
   const SBool  s1313 = s1302 < s1063;
-  const SBool  s1314 = s1312 | s1313;
+  const SBool  s1314 = s1312 || s1313;
   const SWord8 s1315 = (s1302 >> 1) | (s1302 << 7);
   const SWord8 s1316 = 128 | s1315;
   const SWord8 s1317 = 127 & s1315;
@@ -1448,7 +1441,7 @@
   const SWord8 s1350 = s1 + s1345;
   const SBool  s1351 = s1350 < s1;
   const SBool  s1352 = s1350 < s1345;
-  const SBool  s1353 = s1351 | s1352;
+  const SBool  s1353 = s1351 || s1352;
   const SWord8 s1354 = (s1350 >> 1) | (s1350 << 7);
   const SWord8 s1355 = 128 | s1354;
   const SWord8 s1356 = 127 & s1354;
@@ -1457,7 +1450,7 @@
   const SWord8 s1359 = s1 + s1341;
   const SBool  s1360 = s1359 < s1;
   const SBool  s1361 = s1359 < s1341;
-  const SBool  s1362 = s1360 | s1361;
+  const SBool  s1362 = s1360 || s1361;
   const SWord8 s1363 = (s1359 >> 1) | (s1359 << 7);
   const SWord8 s1364 = 128 | s1363;
   const SWord8 s1365 = 127 & s1363;
@@ -1469,7 +1462,7 @@
   const SWord8 s1371 = s1 + s1366;
   const SBool  s1372 = s1371 < s1;
   const SBool  s1373 = s1371 < s1366;
-  const SBool  s1374 = s1372 | s1373;
+  const SBool  s1374 = s1372 || s1373;
   const SWord8 s1375 = (s1371 >> 1) | (s1371 << 7);
   const SWord8 s1376 = 128 | s1375;
   const SWord8 s1377 = 127 & s1375;
@@ -1479,7 +1472,7 @@
   const SWord8 s1381 = s1 + s1337;
   const SBool  s1382 = s1381 < s1;
   const SBool  s1383 = s1381 < s1337;
-  const SBool  s1384 = s1382 | s1383;
+  const SBool  s1384 = s1382 || s1383;
   const SWord8 s1385 = (s1381 >> 1) | (s1381 << 7);
   const SWord8 s1386 = 128 | s1385;
   const SWord8 s1387 = 127 & s1385;
@@ -1495,7 +1488,7 @@
   const SWord8 s1397 = s1 + s1392;
   const SBool  s1398 = s1397 < s1;
   const SBool  s1399 = s1397 < s1392;
-  const SBool  s1400 = s1398 | s1399;
+  const SBool  s1400 = s1398 || s1399;
   const SWord8 s1401 = (s1397 >> 1) | (s1397 << 7);
   const SWord8 s1402 = 128 | s1401;
   const SWord8 s1403 = 127 & s1401;
@@ -1504,7 +1497,7 @@
   const SWord8 s1406 = s1 + s1388;
   const SBool  s1407 = s1406 < s1;
   const SBool  s1408 = s1406 < s1388;
-  const SBool  s1409 = s1407 | s1408;
+  const SBool  s1409 = s1407 || s1408;
   const SWord8 s1410 = (s1406 >> 1) | (s1406 << 7);
   const SWord8 s1411 = 128 | s1410;
   const SWord8 s1412 = 127 & s1410;
@@ -1516,7 +1509,7 @@
   const SWord8 s1418 = s1 + s1413;
   const SBool  s1419 = s1418 < s1;
   const SBool  s1420 = s1418 < s1413;
-  const SBool  s1421 = s1419 | s1420;
+  const SBool  s1421 = s1419 || s1420;
   const SWord8 s1422 = (s1418 >> 1) | (s1418 << 7);
   const SWord8 s1423 = 128 | s1422;
   const SWord8 s1424 = 127 & s1422;
@@ -1536,7 +1529,7 @@
   const SBool  s1438 = false == s1437;
   const SBool  s1439 = s1429 < s1;
   const SBool  s1440 = s1429 < s1318;
-  const SBool  s1441 = s1439 | s1440;
+  const SBool  s1441 = s1439 || s1440;
   const SWord8 s1442 = (s1429 >> 1) | (s1429 << 7);
   const SWord8 s1443 = 128 | s1442;
   const SWord8 s1444 = 127 & s1442;
@@ -1556,7 +1549,7 @@
   const SWord8 s1458 = s1 + s1453;
   const SBool  s1459 = s1458 < s1;
   const SBool  s1460 = s1458 < s1453;
-  const SBool  s1461 = s1459 | s1460;
+  const SBool  s1461 = s1459 || s1460;
   const SWord8 s1462 = (s1458 >> 1) | (s1458 << 7);
   const SWord8 s1463 = 128 | s1462;
   const SWord8 s1464 = 127 & s1462;
@@ -1565,7 +1558,7 @@
   const SWord8 s1467 = s1 + s1449;
   const SBool  s1468 = s1467 < s1;
   const SBool  s1469 = s1467 < s1449;
-  const SBool  s1470 = s1468 | s1469;
+  const SBool  s1470 = s1468 || s1469;
   const SWord8 s1471 = (s1467 >> 1) | (s1467 << 7);
   const SWord8 s1472 = 128 | s1471;
   const SWord8 s1473 = 127 & s1471;
@@ -1577,7 +1570,7 @@
   const SWord8 s1479 = s1 + s1474;
   const SBool  s1480 = s1479 < s1;
   const SBool  s1481 = s1479 < s1474;
-  const SBool  s1482 = s1480 | s1481;
+  const SBool  s1482 = s1480 || s1481;
   const SWord8 s1483 = (s1479 >> 1) | (s1479 << 7);
   const SWord8 s1484 = 128 | s1483;
   const SWord8 s1485 = 127 & s1483;
@@ -1587,7 +1580,7 @@
   const SWord8 s1489 = s1 + s1445;
   const SBool  s1490 = s1489 < s1;
   const SBool  s1491 = s1489 < s1445;
-  const SBool  s1492 = s1490 | s1491;
+  const SBool  s1492 = s1490 || s1491;
   const SWord8 s1493 = (s1489 >> 1) | (s1489 << 7);
   const SWord8 s1494 = 128 | s1493;
   const SWord8 s1495 = 127 & s1493;
@@ -1603,7 +1596,7 @@
   const SWord8 s1505 = s1 + s1500;
   const SBool  s1506 = s1505 < s1;
   const SBool  s1507 = s1505 < s1500;
-  const SBool  s1508 = s1506 | s1507;
+  const SBool  s1508 = s1506 || s1507;
   const SWord8 s1509 = (s1505 >> 1) | (s1505 << 7);
   const SWord8 s1510 = 128 | s1509;
   const SWord8 s1511 = 127 & s1509;
@@ -1612,7 +1605,7 @@
   const SWord8 s1514 = s1 + s1496;
   const SBool  s1515 = s1514 < s1;
   const SBool  s1516 = s1514 < s1496;
-  const SBool  s1517 = s1515 | s1516;
+  const SBool  s1517 = s1515 || s1516;
   const SWord8 s1518 = (s1514 >> 1) | (s1514 << 7);
   const SWord8 s1519 = 128 | s1518;
   const SWord8 s1520 = 127 & s1518;
@@ -1624,7 +1617,7 @@
   const SWord8 s1526 = s1 + s1521;
   const SBool  s1527 = s1526 < s1;
   const SBool  s1528 = s1526 < s1521;
-  const SBool  s1529 = s1527 | s1528;
+  const SBool  s1529 = s1527 || s1528;
   const SWord8 s1530 = (s1526 >> 1) | (s1526 << 7);
   const SWord8 s1531 = 128 | s1530;
   const SWord8 s1532 = 127 & s1530;
@@ -1646,7 +1639,7 @@
   const SBool  s1548 = false == s1547;
   const SBool  s1549 = s1539 < s1;
   const SBool  s1550 = s1539 < s1044;
-  const SBool  s1551 = s1549 | s1550;
+  const SBool  s1551 = s1549 || s1550;
   const SWord8 s1552 = (s1539 >> 1) | (s1539 << 7);
   const SWord8 s1553 = 128 | s1552;
   const SWord8 s1554 = 127 & s1552;
@@ -1704,7 +1697,7 @@
   const SWord8 s1606 = s1 + s1601;
   const SBool  s1607 = s1606 < s1;
   const SBool  s1608 = s1606 < s1601;
-  const SBool  s1609 = s1607 | s1608;
+  const SBool  s1609 = s1607 || s1608;
   const SWord8 s1610 = (s1606 >> 1) | (s1606 << 7);
   const SWord8 s1611 = 128 | s1610;
   const SWord8 s1612 = 127 & s1610;
@@ -1713,7 +1706,7 @@
   const SWord8 s1615 = s1 + s1597;
   const SBool  s1616 = s1615 < s1;
   const SBool  s1617 = s1615 < s1597;
-  const SBool  s1618 = s1616 | s1617;
+  const SBool  s1618 = s1616 || s1617;
   const SWord8 s1619 = (s1615 >> 1) | (s1615 << 7);
   const SWord8 s1620 = 128 | s1619;
   const SWord8 s1621 = 127 & s1619;
@@ -1725,7 +1718,7 @@
   const SWord8 s1627 = s1 + s1622;
   const SBool  s1628 = s1627 < s1;
   const SBool  s1629 = s1627 < s1622;
-  const SBool  s1630 = s1628 | s1629;
+  const SBool  s1630 = s1628 || s1629;
   const SWord8 s1631 = (s1627 >> 1) | (s1627 << 7);
   const SWord8 s1632 = 128 | s1631;
   const SWord8 s1633 = 127 & s1631;
@@ -1735,7 +1728,7 @@
   const SWord8 s1637 = s1 + s1593;
   const SBool  s1638 = s1637 < s1;
   const SBool  s1639 = s1637 < s1593;
-  const SBool  s1640 = s1638 | s1639;
+  const SBool  s1640 = s1638 || s1639;
   const SWord8 s1641 = (s1637 >> 1) | (s1637 << 7);
   const SWord8 s1642 = 128 | s1641;
   const SWord8 s1643 = 127 & s1641;
@@ -1751,7 +1744,7 @@
   const SWord8 s1653 = s1 + s1648;
   const SBool  s1654 = s1653 < s1;
   const SBool  s1655 = s1653 < s1648;
-  const SBool  s1656 = s1654 | s1655;
+  const SBool  s1656 = s1654 || s1655;
   const SWord8 s1657 = (s1653 >> 1) | (s1653 << 7);
   const SWord8 s1658 = 128 | s1657;
   const SWord8 s1659 = 127 & s1657;
@@ -1760,7 +1753,7 @@
   const SWord8 s1662 = s1 + s1644;
   const SBool  s1663 = s1662 < s1;
   const SBool  s1664 = s1662 < s1644;
-  const SBool  s1665 = s1663 | s1664;
+  const SBool  s1665 = s1663 || s1664;
   const SWord8 s1666 = (s1662 >> 1) | (s1662 << 7);
   const SWord8 s1667 = 128 | s1666;
   const SWord8 s1668 = 127 & s1666;
@@ -1772,7 +1765,7 @@
   const SWord8 s1674 = s1 + s1669;
   const SBool  s1675 = s1674 < s1;
   const SBool  s1676 = s1674 < s1669;
-  const SBool  s1677 = s1675 | s1676;
+  const SBool  s1677 = s1675 || s1676;
   const SWord8 s1678 = (s1674 >> 1) | (s1674 << 7);
   const SWord8 s1679 = 128 | s1678;
   const SWord8 s1680 = 127 & s1678;
@@ -1792,7 +1785,7 @@
   const SBool  s1694 = false == s1693;
   const SBool  s1695 = s1685 < s1;
   const SBool  s1696 = s1685 < s1574;
-  const SBool  s1697 = s1695 | s1696;
+  const SBool  s1697 = s1695 || s1696;
   const SWord8 s1698 = (s1685 >> 1) | (s1685 << 7);
   const SWord8 s1699 = 128 | s1698;
   const SWord8 s1700 = 127 & s1698;
@@ -1812,7 +1805,7 @@
   const SWord8 s1714 = s1 + s1709;
   const SBool  s1715 = s1714 < s1;
   const SBool  s1716 = s1714 < s1709;
-  const SBool  s1717 = s1715 | s1716;
+  const SBool  s1717 = s1715 || s1716;
   const SWord8 s1718 = (s1714 >> 1) | (s1714 << 7);
   const SWord8 s1719 = 128 | s1718;
   const SWord8 s1720 = 127 & s1718;
@@ -1821,7 +1814,7 @@
   const SWord8 s1723 = s1 + s1705;
   const SBool  s1724 = s1723 < s1;
   const SBool  s1725 = s1723 < s1705;
-  const SBool  s1726 = s1724 | s1725;
+  const SBool  s1726 = s1724 || s1725;
   const SWord8 s1727 = (s1723 >> 1) | (s1723 << 7);
   const SWord8 s1728 = 128 | s1727;
   const SWord8 s1729 = 127 & s1727;
@@ -1833,7 +1826,7 @@
   const SWord8 s1735 = s1 + s1730;
   const SBool  s1736 = s1735 < s1;
   const SBool  s1737 = s1735 < s1730;
-  const SBool  s1738 = s1736 | s1737;
+  const SBool  s1738 = s1736 || s1737;
   const SWord8 s1739 = (s1735 >> 1) | (s1735 << 7);
   const SWord8 s1740 = 128 | s1739;
   const SWord8 s1741 = 127 & s1739;
@@ -1843,7 +1836,7 @@
   const SWord8 s1745 = s1 + s1701;
   const SBool  s1746 = s1745 < s1;
   const SBool  s1747 = s1745 < s1701;
-  const SBool  s1748 = s1746 | s1747;
+  const SBool  s1748 = s1746 || s1747;
   const SWord8 s1749 = (s1745 >> 1) | (s1745 << 7);
   const SWord8 s1750 = 128 | s1749;
   const SWord8 s1751 = 127 & s1749;
@@ -1859,7 +1852,7 @@
   const SWord8 s1761 = s1 + s1756;
   const SBool  s1762 = s1761 < s1;
   const SBool  s1763 = s1761 < s1756;
-  const SBool  s1764 = s1762 | s1763;
+  const SBool  s1764 = s1762 || s1763;
   const SWord8 s1765 = (s1761 >> 1) | (s1761 << 7);
   const SWord8 s1766 = 128 | s1765;
   const SWord8 s1767 = 127 & s1765;
@@ -1868,7 +1861,7 @@
   const SWord8 s1770 = s1 + s1752;
   const SBool  s1771 = s1770 < s1;
   const SBool  s1772 = s1770 < s1752;
-  const SBool  s1773 = s1771 | s1772;
+  const SBool  s1773 = s1771 || s1772;
   const SWord8 s1774 = (s1770 >> 1) | (s1770 << 7);
   const SWord8 s1775 = 128 | s1774;
   const SWord8 s1776 = 127 & s1774;
@@ -1880,7 +1873,7 @@
   const SWord8 s1782 = s1 + s1777;
   const SBool  s1783 = s1782 < s1;
   const SBool  s1784 = s1782 < s1777;
-  const SBool  s1785 = s1783 | s1784;
+  const SBool  s1785 = s1783 || s1784;
   const SWord8 s1786 = (s1782 >> 1) | (s1782 << 7);
   const SWord8 s1787 = 128 | s1786;
   const SWord8 s1788 = 127 & s1786;
@@ -1901,7 +1894,7 @@
   const SBool  s1803 = false == s1802;
   const SBool  s1804 = s1794 < s1;
   const SBool  s1805 = s1794 < s1555;
-  const SBool  s1806 = s1804 | s1805;
+  const SBool  s1806 = s1804 || s1805;
   const SWord8 s1807 = (s1794 >> 1) | (s1794 << 7);
   const SWord8 s1808 = 128 | s1807;
   const SWord8 s1809 = 127 & s1807;
@@ -1940,7 +1933,7 @@
   const SWord8 s1842 = s1 + s1837;
   const SBool  s1843 = s1842 < s1;
   const SBool  s1844 = s1842 < s1837;
-  const SBool  s1845 = s1843 | s1844;
+  const SBool  s1845 = s1843 || s1844;
   const SWord8 s1846 = (s1842 >> 1) | (s1842 << 7);
   const SWord8 s1847 = 128 | s1846;
   const SWord8 s1848 = 127 & s1846;
@@ -1949,7 +1942,7 @@
   const SWord8 s1851 = s1 + s1833;
   const SBool  s1852 = s1851 < s1;
   const SBool  s1853 = s1851 < s1833;
-  const SBool  s1854 = s1852 | s1853;
+  const SBool  s1854 = s1852 || s1853;
   const SWord8 s1855 = (s1851 >> 1) | (s1851 << 7);
   const SWord8 s1856 = 128 | s1855;
   const SWord8 s1857 = 127 & s1855;
@@ -1961,7 +1954,7 @@
   const SWord8 s1863 = s1 + s1858;
   const SBool  s1864 = s1863 < s1;
   const SBool  s1865 = s1863 < s1858;
-  const SBool  s1866 = s1864 | s1865;
+  const SBool  s1866 = s1864 || s1865;
   const SWord8 s1867 = (s1863 >> 1) | (s1863 << 7);
   const SWord8 s1868 = 128 | s1867;
   const SWord8 s1869 = 127 & s1867;
@@ -1971,7 +1964,7 @@
   const SWord8 s1873 = s1 + s1829;
   const SBool  s1874 = s1873 < s1;
   const SBool  s1875 = s1873 < s1829;
-  const SBool  s1876 = s1874 | s1875;
+  const SBool  s1876 = s1874 || s1875;
   const SWord8 s1877 = (s1873 >> 1) | (s1873 << 7);
   const SWord8 s1878 = 128 | s1877;
   const SWord8 s1879 = 127 & s1877;
@@ -1987,7 +1980,7 @@
   const SWord8 s1889 = s1 + s1884;
   const SBool  s1890 = s1889 < s1;
   const SBool  s1891 = s1889 < s1884;
-  const SBool  s1892 = s1890 | s1891;
+  const SBool  s1892 = s1890 || s1891;
   const SWord8 s1893 = (s1889 >> 1) | (s1889 << 7);
   const SWord8 s1894 = 128 | s1893;
   const SWord8 s1895 = 127 & s1893;
@@ -1996,7 +1989,7 @@
   const SWord8 s1898 = s1 + s1880;
   const SBool  s1899 = s1898 < s1;
   const SBool  s1900 = s1898 < s1880;
-  const SBool  s1901 = s1899 | s1900;
+  const SBool  s1901 = s1899 || s1900;
   const SWord8 s1902 = (s1898 >> 1) | (s1898 << 7);
   const SWord8 s1903 = 128 | s1902;
   const SWord8 s1904 = 127 & s1902;
@@ -2008,7 +2001,7 @@
   const SWord8 s1910 = s1 + s1905;
   const SBool  s1911 = s1910 < s1;
   const SBool  s1912 = s1910 < s1905;
-  const SBool  s1913 = s1911 | s1912;
+  const SBool  s1913 = s1911 || s1912;
   const SWord8 s1914 = (s1910 >> 1) | (s1910 << 7);
   const SWord8 s1915 = 128 | s1914;
   const SWord8 s1916 = 127 & s1914;
@@ -2028,7 +2021,7 @@
   const SBool  s1930 = false == s1929;
   const SBool  s1931 = s1921 < s1;
   const SBool  s1932 = s1921 < s1810;
-  const SBool  s1933 = s1931 | s1932;
+  const SBool  s1933 = s1931 || s1932;
   const SWord8 s1934 = (s1921 >> 1) | (s1921 << 7);
   const SWord8 s1935 = 128 | s1934;
   const SWord8 s1936 = 127 & s1934;
@@ -2048,7 +2041,7 @@
   const SWord8 s1950 = s1 + s1945;
   const SBool  s1951 = s1950 < s1;
   const SBool  s1952 = s1950 < s1945;
-  const SBool  s1953 = s1951 | s1952;
+  const SBool  s1953 = s1951 || s1952;
   const SWord8 s1954 = (s1950 >> 1) | (s1950 << 7);
   const SWord8 s1955 = 128 | s1954;
   const SWord8 s1956 = 127 & s1954;
@@ -2057,7 +2050,7 @@
   const SWord8 s1959 = s1 + s1941;
   const SBool  s1960 = s1959 < s1;
   const SBool  s1961 = s1959 < s1941;
-  const SBool  s1962 = s1960 | s1961;
+  const SBool  s1962 = s1960 || s1961;
   const SWord8 s1963 = (s1959 >> 1) | (s1959 << 7);
   const SWord8 s1964 = 128 | s1963;
   const SWord8 s1965 = 127 & s1963;
@@ -2069,7 +2062,7 @@
   const SWord8 s1971 = s1 + s1966;
   const SBool  s1972 = s1971 < s1;
   const SBool  s1973 = s1971 < s1966;
-  const SBool  s1974 = s1972 | s1973;
+  const SBool  s1974 = s1972 || s1973;
   const SWord8 s1975 = (s1971 >> 1) | (s1971 << 7);
   const SWord8 s1976 = 128 | s1975;
   const SWord8 s1977 = 127 & s1975;
@@ -2079,7 +2072,7 @@
   const SWord8 s1981 = s1 + s1937;
   const SBool  s1982 = s1981 < s1;
   const SBool  s1983 = s1981 < s1937;
-  const SBool  s1984 = s1982 | s1983;
+  const SBool  s1984 = s1982 || s1983;
   const SWord8 s1985 = (s1981 >> 1) | (s1981 << 7);
   const SWord8 s1986 = 128 | s1985;
   const SWord8 s1987 = 127 & s1985;
@@ -2095,7 +2088,7 @@
   const SWord8 s1997 = s1 + s1992;
   const SBool  s1998 = s1997 < s1;
   const SBool  s1999 = s1997 < s1992;
-  const SBool  s2000 = s1998 | s1999;
+  const SBool  s2000 = s1998 || s1999;
   const SWord8 s2001 = (s1997 >> 1) | (s1997 << 7);
   const SWord8 s2002 = 128 | s2001;
   const SWord8 s2003 = 127 & s2001;
@@ -2104,7 +2097,7 @@
   const SWord8 s2006 = s1 + s1988;
   const SBool  s2007 = s2006 < s1;
   const SBool  s2008 = s2006 < s1988;
-  const SBool  s2009 = s2007 | s2008;
+  const SBool  s2009 = s2007 || s2008;
   const SWord8 s2010 = (s2006 >> 1) | (s2006 << 7);
   const SWord8 s2011 = 128 | s2010;
   const SWord8 s2012 = 127 & s2010;
@@ -2116,7 +2109,7 @@
   const SWord8 s2018 = s1 + s2013;
   const SBool  s2019 = s2018 < s1;
   const SBool  s2020 = s2018 < s2013;
-  const SBool  s2021 = s2019 | s2020;
+  const SBool  s2021 = s2019 || s2020;
   const SWord8 s2022 = (s2018 >> 1) | (s2018 << 7);
   const SWord8 s2023 = 128 | s2022;
   const SWord8 s2024 = 127 & s2022;
@@ -2231,7 +2224,7 @@
   const SWord8 s2133 = s1 + s2128;
   const SBool  s2134 = s2133 < s1;
   const SBool  s2135 = s2133 < s2128;
-  const SBool  s2136 = s2134 | s2135;
+  const SBool  s2136 = s2134 || s2135;
   const SWord8 s2137 = (s2133 >> 1) | (s2133 << 7);
   const SWord8 s2138 = 128 | s2137;
   const SWord8 s2139 = 127 & s2137;
@@ -2240,7 +2233,7 @@
   const SWord8 s2142 = s1 + s2124;
   const SBool  s2143 = s2142 < s1;
   const SBool  s2144 = s2142 < s2124;
-  const SBool  s2145 = s2143 | s2144;
+  const SBool  s2145 = s2143 || s2144;
   const SWord8 s2146 = (s2142 >> 1) | (s2142 << 7);
   const SWord8 s2147 = 128 | s2146;
   const SWord8 s2148 = 127 & s2146;
@@ -2252,7 +2245,7 @@
   const SWord8 s2154 = s1 + s2149;
   const SBool  s2155 = s2154 < s1;
   const SBool  s2156 = s2154 < s2149;
-  const SBool  s2157 = s2155 | s2156;
+  const SBool  s2157 = s2155 || s2156;
   const SWord8 s2158 = (s2154 >> 1) | (s2154 << 7);
   const SWord8 s2159 = 128 | s2158;
   const SWord8 s2160 = 127 & s2158;
@@ -2262,7 +2255,7 @@
   const SWord8 s2164 = s1 + s2120;
   const SBool  s2165 = s2164 < s1;
   const SBool  s2166 = s2164 < s2120;
-  const SBool  s2167 = s2165 | s2166;
+  const SBool  s2167 = s2165 || s2166;
   const SWord8 s2168 = (s2164 >> 1) | (s2164 << 7);
   const SWord8 s2169 = 128 | s2168;
   const SWord8 s2170 = 127 & s2168;
@@ -2278,7 +2271,7 @@
   const SWord8 s2180 = s1 + s2175;
   const SBool  s2181 = s2180 < s1;
   const SBool  s2182 = s2180 < s2175;
-  const SBool  s2183 = s2181 | s2182;
+  const SBool  s2183 = s2181 || s2182;
   const SWord8 s2184 = (s2180 >> 1) | (s2180 << 7);
   const SWord8 s2185 = 128 | s2184;
   const SWord8 s2186 = 127 & s2184;
@@ -2287,7 +2280,7 @@
   const SWord8 s2189 = s1 + s2171;
   const SBool  s2190 = s2189 < s1;
   const SBool  s2191 = s2189 < s2171;
-  const SBool  s2192 = s2190 | s2191;
+  const SBool  s2192 = s2190 || s2191;
   const SWord8 s2193 = (s2189 >> 1) | (s2189 << 7);
   const SWord8 s2194 = 128 | s2193;
   const SWord8 s2195 = 127 & s2193;
@@ -2299,7 +2292,7 @@
   const SWord8 s2201 = s1 + s2196;
   const SBool  s2202 = s2201 < s1;
   const SBool  s2203 = s2201 < s2196;
-  const SBool  s2204 = s2202 | s2203;
+  const SBool  s2204 = s2202 || s2203;
   const SWord8 s2205 = (s2201 >> 1) | (s2201 << 7);
   const SWord8 s2206 = 128 | s2205;
   const SWord8 s2207 = 127 & s2205;
@@ -2319,7 +2312,7 @@
   const SBool  s2221 = false == s2220;
   const SBool  s2222 = s2212 < s1;
   const SBool  s2223 = s2212 < s2101;
-  const SBool  s2224 = s2222 | s2223;
+  const SBool  s2224 = s2222 || s2223;
   const SWord8 s2225 = (s2212 >> 1) | (s2212 << 7);
   const SWord8 s2226 = 128 | s2225;
   const SWord8 s2227 = 127 & s2225;
@@ -2339,7 +2332,7 @@
   const SWord8 s2241 = s1 + s2236;
   const SBool  s2242 = s2241 < s1;
   const SBool  s2243 = s2241 < s2236;
-  const SBool  s2244 = s2242 | s2243;
+  const SBool  s2244 = s2242 || s2243;
   const SWord8 s2245 = (s2241 >> 1) | (s2241 << 7);
   const SWord8 s2246 = 128 | s2245;
   const SWord8 s2247 = 127 & s2245;
@@ -2348,7 +2341,7 @@
   const SWord8 s2250 = s1 + s2232;
   const SBool  s2251 = s2250 < s1;
   const SBool  s2252 = s2250 < s2232;
-  const SBool  s2253 = s2251 | s2252;
+  const SBool  s2253 = s2251 || s2252;
   const SWord8 s2254 = (s2250 >> 1) | (s2250 << 7);
   const SWord8 s2255 = 128 | s2254;
   const SWord8 s2256 = 127 & s2254;
@@ -2360,7 +2353,7 @@
   const SWord8 s2262 = s1 + s2257;
   const SBool  s2263 = s2262 < s1;
   const SBool  s2264 = s2262 < s2257;
-  const SBool  s2265 = s2263 | s2264;
+  const SBool  s2265 = s2263 || s2264;
   const SWord8 s2266 = (s2262 >> 1) | (s2262 << 7);
   const SWord8 s2267 = 128 | s2266;
   const SWord8 s2268 = 127 & s2266;
@@ -2370,7 +2363,7 @@
   const SWord8 s2272 = s1 + s2228;
   const SBool  s2273 = s2272 < s1;
   const SBool  s2274 = s2272 < s2228;
-  const SBool  s2275 = s2273 | s2274;
+  const SBool  s2275 = s2273 || s2274;
   const SWord8 s2276 = (s2272 >> 1) | (s2272 << 7);
   const SWord8 s2277 = 128 | s2276;
   const SWord8 s2278 = 127 & s2276;
@@ -2386,7 +2379,7 @@
   const SWord8 s2288 = s1 + s2283;
   const SBool  s2289 = s2288 < s1;
   const SBool  s2290 = s2288 < s2283;
-  const SBool  s2291 = s2289 | s2290;
+  const SBool  s2291 = s2289 || s2290;
   const SWord8 s2292 = (s2288 >> 1) | (s2288 << 7);
   const SWord8 s2293 = 128 | s2292;
   const SWord8 s2294 = 127 & s2292;
@@ -2395,7 +2388,7 @@
   const SWord8 s2297 = s1 + s2279;
   const SBool  s2298 = s2297 < s1;
   const SBool  s2299 = s2297 < s2279;
-  const SBool  s2300 = s2298 | s2299;
+  const SBool  s2300 = s2298 || s2299;
   const SWord8 s2301 = (s2297 >> 1) | (s2297 << 7);
   const SWord8 s2302 = 128 | s2301;
   const SWord8 s2303 = 127 & s2301;
@@ -2407,7 +2400,7 @@
   const SWord8 s2309 = s1 + s2304;
   const SBool  s2310 = s2309 < s1;
   const SBool  s2311 = s2309 < s2304;
-  const SBool  s2312 = s2310 | s2311;
+  const SBool  s2312 = s2310 || s2311;
   const SWord8 s2313 = (s2309 >> 1) | (s2309 << 7);
   const SWord8 s2314 = 128 | s2313;
   const SWord8 s2315 = 127 & s2313;
@@ -2428,7 +2421,7 @@
   const SBool  s2330 = false == s2329;
   const SBool  s2331 = s2321 < s1;
   const SBool  s2332 = s2321 < s2082;
-  const SBool  s2333 = s2331 | s2332;
+  const SBool  s2333 = s2331 || s2332;
   const SWord8 s2334 = (s2321 >> 1) | (s2321 << 7);
   const SWord8 s2335 = 128 | s2334;
   const SWord8 s2336 = 127 & s2334;
@@ -2467,7 +2460,7 @@
   const SWord8 s2369 = s1 + s2364;
   const SBool  s2370 = s2369 < s1;
   const SBool  s2371 = s2369 < s2364;
-  const SBool  s2372 = s2370 | s2371;
+  const SBool  s2372 = s2370 || s2371;
   const SWord8 s2373 = (s2369 >> 1) | (s2369 << 7);
   const SWord8 s2374 = 128 | s2373;
   const SWord8 s2375 = 127 & s2373;
@@ -2476,7 +2469,7 @@
   const SWord8 s2378 = s1 + s2360;
   const SBool  s2379 = s2378 < s1;
   const SBool  s2380 = s2378 < s2360;
-  const SBool  s2381 = s2379 | s2380;
+  const SBool  s2381 = s2379 || s2380;
   const SWord8 s2382 = (s2378 >> 1) | (s2378 << 7);
   const SWord8 s2383 = 128 | s2382;
   const SWord8 s2384 = 127 & s2382;
@@ -2488,7 +2481,7 @@
   const SWord8 s2390 = s1 + s2385;
   const SBool  s2391 = s2390 < s1;
   const SBool  s2392 = s2390 < s2385;
-  const SBool  s2393 = s2391 | s2392;
+  const SBool  s2393 = s2391 || s2392;
   const SWord8 s2394 = (s2390 >> 1) | (s2390 << 7);
   const SWord8 s2395 = 128 | s2394;
   const SWord8 s2396 = 127 & s2394;
@@ -2498,7 +2491,7 @@
   const SWord8 s2400 = s1 + s2356;
   const SBool  s2401 = s2400 < s1;
   const SBool  s2402 = s2400 < s2356;
-  const SBool  s2403 = s2401 | s2402;
+  const SBool  s2403 = s2401 || s2402;
   const SWord8 s2404 = (s2400 >> 1) | (s2400 << 7);
   const SWord8 s2405 = 128 | s2404;
   const SWord8 s2406 = 127 & s2404;
@@ -2514,7 +2507,7 @@
   const SWord8 s2416 = s1 + s2411;
   const SBool  s2417 = s2416 < s1;
   const SBool  s2418 = s2416 < s2411;
-  const SBool  s2419 = s2417 | s2418;
+  const SBool  s2419 = s2417 || s2418;
   const SWord8 s2420 = (s2416 >> 1) | (s2416 << 7);
   const SWord8 s2421 = 128 | s2420;
   const SWord8 s2422 = 127 & s2420;
@@ -2523,7 +2516,7 @@
   const SWord8 s2425 = s1 + s2407;
   const SBool  s2426 = s2425 < s1;
   const SBool  s2427 = s2425 < s2407;
-  const SBool  s2428 = s2426 | s2427;
+  const SBool  s2428 = s2426 || s2427;
   const SWord8 s2429 = (s2425 >> 1) | (s2425 << 7);
   const SWord8 s2430 = 128 | s2429;
   const SWord8 s2431 = 127 & s2429;
@@ -2535,7 +2528,7 @@
   const SWord8 s2437 = s1 + s2432;
   const SBool  s2438 = s2437 < s1;
   const SBool  s2439 = s2437 < s2432;
-  const SBool  s2440 = s2438 | s2439;
+  const SBool  s2440 = s2438 || s2439;
   const SWord8 s2441 = (s2437 >> 1) | (s2437 << 7);
   const SWord8 s2442 = 128 | s2441;
   const SWord8 s2443 = 127 & s2441;
@@ -2555,7 +2548,7 @@
   const SBool  s2457 = false == s2456;
   const SBool  s2458 = s2448 < s1;
   const SBool  s2459 = s2448 < s2337;
-  const SBool  s2460 = s2458 | s2459;
+  const SBool  s2460 = s2458 || s2459;
   const SWord8 s2461 = (s2448 >> 1) | (s2448 << 7);
   const SWord8 s2462 = 128 | s2461;
   const SWord8 s2463 = 127 & s2461;
@@ -2575,7 +2568,7 @@
   const SWord8 s2477 = s1 + s2472;
   const SBool  s2478 = s2477 < s1;
   const SBool  s2479 = s2477 < s2472;
-  const SBool  s2480 = s2478 | s2479;
+  const SBool  s2480 = s2478 || s2479;
   const SWord8 s2481 = (s2477 >> 1) | (s2477 << 7);
   const SWord8 s2482 = 128 | s2481;
   const SWord8 s2483 = 127 & s2481;
@@ -2584,7 +2577,7 @@
   const SWord8 s2486 = s1 + s2468;
   const SBool  s2487 = s2486 < s1;
   const SBool  s2488 = s2486 < s2468;
-  const SBool  s2489 = s2487 | s2488;
+  const SBool  s2489 = s2487 || s2488;
   const SWord8 s2490 = (s2486 >> 1) | (s2486 << 7);
   const SWord8 s2491 = 128 | s2490;
   const SWord8 s2492 = 127 & s2490;
@@ -2596,7 +2589,7 @@
   const SWord8 s2498 = s1 + s2493;
   const SBool  s2499 = s2498 < s1;
   const SBool  s2500 = s2498 < s2493;
-  const SBool  s2501 = s2499 | s2500;
+  const SBool  s2501 = s2499 || s2500;
   const SWord8 s2502 = (s2498 >> 1) | (s2498 << 7);
   const SWord8 s2503 = 128 | s2502;
   const SWord8 s2504 = 127 & s2502;
@@ -2606,7 +2599,7 @@
   const SWord8 s2508 = s1 + s2464;
   const SBool  s2509 = s2508 < s1;
   const SBool  s2510 = s2508 < s2464;
-  const SBool  s2511 = s2509 | s2510;
+  const SBool  s2511 = s2509 || s2510;
   const SWord8 s2512 = (s2508 >> 1) | (s2508 << 7);
   const SWord8 s2513 = 128 | s2512;
   const SWord8 s2514 = 127 & s2512;
@@ -2622,7 +2615,7 @@
   const SWord8 s2524 = s1 + s2519;
   const SBool  s2525 = s2524 < s1;
   const SBool  s2526 = s2524 < s2519;
-  const SBool  s2527 = s2525 | s2526;
+  const SBool  s2527 = s2525 || s2526;
   const SWord8 s2528 = (s2524 >> 1) | (s2524 << 7);
   const SWord8 s2529 = 128 | s2528;
   const SWord8 s2530 = 127 & s2528;
@@ -2631,7 +2624,7 @@
   const SWord8 s2533 = s1 + s2515;
   const SBool  s2534 = s2533 < s1;
   const SBool  s2535 = s2533 < s2515;
-  const SBool  s2536 = s2534 | s2535;
+  const SBool  s2536 = s2534 || s2535;
   const SWord8 s2537 = (s2533 >> 1) | (s2533 << 7);
   const SWord8 s2538 = 128 | s2537;
   const SWord8 s2539 = 127 & s2537;
@@ -2643,7 +2636,7 @@
   const SWord8 s2545 = s1 + s2540;
   const SBool  s2546 = s2545 < s1;
   const SBool  s2547 = s2545 < s2540;
-  const SBool  s2548 = s2546 | s2547;
+  const SBool  s2548 = s2546 || s2547;
   const SWord8 s2549 = (s2545 >> 1) | (s2545 << 7);
   const SWord8 s2550 = 128 | s2549;
   const SWord8 s2551 = 127 & s2549;
@@ -2665,7 +2658,7 @@
   const SBool  s2567 = false == s2566;
   const SBool  s2568 = s2558 < s1;
   const SBool  s2569 = s2558 < s2063;
-  const SBool  s2570 = s2568 | s2569;
+  const SBool  s2570 = s2568 || s2569;
   const SWord8 s2571 = (s2558 >> 1) | (s2558 << 7);
   const SWord8 s2572 = 128 | s2571;
   const SWord8 s2573 = 127 & s2571;
@@ -2723,7 +2716,7 @@
   const SWord8 s2625 = s1 + s2620;
   const SBool  s2626 = s2625 < s1;
   const SBool  s2627 = s2625 < s2620;
-  const SBool  s2628 = s2626 | s2627;
+  const SBool  s2628 = s2626 || s2627;
   const SWord8 s2629 = (s2625 >> 1) | (s2625 << 7);
   const SWord8 s2630 = 128 | s2629;
   const SWord8 s2631 = 127 & s2629;
@@ -2732,7 +2725,7 @@
   const SWord8 s2634 = s1 + s2616;
   const SBool  s2635 = s2634 < s1;
   const SBool  s2636 = s2634 < s2616;
-  const SBool  s2637 = s2635 | s2636;
+  const SBool  s2637 = s2635 || s2636;
   const SWord8 s2638 = (s2634 >> 1) | (s2634 << 7);
   const SWord8 s2639 = 128 | s2638;
   const SWord8 s2640 = 127 & s2638;
@@ -2744,7 +2737,7 @@
   const SWord8 s2646 = s1 + s2641;
   const SBool  s2647 = s2646 < s1;
   const SBool  s2648 = s2646 < s2641;
-  const SBool  s2649 = s2647 | s2648;
+  const SBool  s2649 = s2647 || s2648;
   const SWord8 s2650 = (s2646 >> 1) | (s2646 << 7);
   const SWord8 s2651 = 128 | s2650;
   const SWord8 s2652 = 127 & s2650;
@@ -2754,7 +2747,7 @@
   const SWord8 s2656 = s1 + s2612;
   const SBool  s2657 = s2656 < s1;
   const SBool  s2658 = s2656 < s2612;
-  const SBool  s2659 = s2657 | s2658;
+  const SBool  s2659 = s2657 || s2658;
   const SWord8 s2660 = (s2656 >> 1) | (s2656 << 7);
   const SWord8 s2661 = 128 | s2660;
   const SWord8 s2662 = 127 & s2660;
@@ -2770,7 +2763,7 @@
   const SWord8 s2672 = s1 + s2667;
   const SBool  s2673 = s2672 < s1;
   const SBool  s2674 = s2672 < s2667;
-  const SBool  s2675 = s2673 | s2674;
+  const SBool  s2675 = s2673 || s2674;
   const SWord8 s2676 = (s2672 >> 1) | (s2672 << 7);
   const SWord8 s2677 = 128 | s2676;
   const SWord8 s2678 = 127 & s2676;
@@ -2779,7 +2772,7 @@
   const SWord8 s2681 = s1 + s2663;
   const SBool  s2682 = s2681 < s1;
   const SBool  s2683 = s2681 < s2663;
-  const SBool  s2684 = s2682 | s2683;
+  const SBool  s2684 = s2682 || s2683;
   const SWord8 s2685 = (s2681 >> 1) | (s2681 << 7);
   const SWord8 s2686 = 128 | s2685;
   const SWord8 s2687 = 127 & s2685;
@@ -2791,7 +2784,7 @@
   const SWord8 s2693 = s1 + s2688;
   const SBool  s2694 = s2693 < s1;
   const SBool  s2695 = s2693 < s2688;
-  const SBool  s2696 = s2694 | s2695;
+  const SBool  s2696 = s2694 || s2695;
   const SWord8 s2697 = (s2693 >> 1) | (s2693 << 7);
   const SWord8 s2698 = 128 | s2697;
   const SWord8 s2699 = 127 & s2697;
@@ -2811,7 +2804,7 @@
   const SBool  s2713 = false == s2712;
   const SBool  s2714 = s2704 < s1;
   const SBool  s2715 = s2704 < s2593;
-  const SBool  s2716 = s2714 | s2715;
+  const SBool  s2716 = s2714 || s2715;
   const SWord8 s2717 = (s2704 >> 1) | (s2704 << 7);
   const SWord8 s2718 = 128 | s2717;
   const SWord8 s2719 = 127 & s2717;
@@ -2831,7 +2824,7 @@
   const SWord8 s2733 = s1 + s2728;
   const SBool  s2734 = s2733 < s1;
   const SBool  s2735 = s2733 < s2728;
-  const SBool  s2736 = s2734 | s2735;
+  const SBool  s2736 = s2734 || s2735;
   const SWord8 s2737 = (s2733 >> 1) | (s2733 << 7);
   const SWord8 s2738 = 128 | s2737;
   const SWord8 s2739 = 127 & s2737;
@@ -2840,7 +2833,7 @@
   const SWord8 s2742 = s1 + s2724;
   const SBool  s2743 = s2742 < s1;
   const SBool  s2744 = s2742 < s2724;
-  const SBool  s2745 = s2743 | s2744;
+  const SBool  s2745 = s2743 || s2744;
   const SWord8 s2746 = (s2742 >> 1) | (s2742 << 7);
   const SWord8 s2747 = 128 | s2746;
   const SWord8 s2748 = 127 & s2746;
@@ -2852,7 +2845,7 @@
   const SWord8 s2754 = s1 + s2749;
   const SBool  s2755 = s2754 < s1;
   const SBool  s2756 = s2754 < s2749;
-  const SBool  s2757 = s2755 | s2756;
+  const SBool  s2757 = s2755 || s2756;
   const SWord8 s2758 = (s2754 >> 1) | (s2754 << 7);
   const SWord8 s2759 = 128 | s2758;
   const SWord8 s2760 = 127 & s2758;
@@ -2862,7 +2855,7 @@
   const SWord8 s2764 = s1 + s2720;
   const SBool  s2765 = s2764 < s1;
   const SBool  s2766 = s2764 < s2720;
-  const SBool  s2767 = s2765 | s2766;
+  const SBool  s2767 = s2765 || s2766;
   const SWord8 s2768 = (s2764 >> 1) | (s2764 << 7);
   const SWord8 s2769 = 128 | s2768;
   const SWord8 s2770 = 127 & s2768;
@@ -2878,7 +2871,7 @@
   const SWord8 s2780 = s1 + s2775;
   const SBool  s2781 = s2780 < s1;
   const SBool  s2782 = s2780 < s2775;
-  const SBool  s2783 = s2781 | s2782;
+  const SBool  s2783 = s2781 || s2782;
   const SWord8 s2784 = (s2780 >> 1) | (s2780 << 7);
   const SWord8 s2785 = 128 | s2784;
   const SWord8 s2786 = 127 & s2784;
@@ -2887,7 +2880,7 @@
   const SWord8 s2789 = s1 + s2771;
   const SBool  s2790 = s2789 < s1;
   const SBool  s2791 = s2789 < s2771;
-  const SBool  s2792 = s2790 | s2791;
+  const SBool  s2792 = s2790 || s2791;
   const SWord8 s2793 = (s2789 >> 1) | (s2789 << 7);
   const SWord8 s2794 = 128 | s2793;
   const SWord8 s2795 = 127 & s2793;
@@ -2899,7 +2892,7 @@
   const SWord8 s2801 = s1 + s2796;
   const SBool  s2802 = s2801 < s1;
   const SBool  s2803 = s2801 < s2796;
-  const SBool  s2804 = s2802 | s2803;
+  const SBool  s2804 = s2802 || s2803;
   const SWord8 s2805 = (s2801 >> 1) | (s2801 << 7);
   const SWord8 s2806 = 128 | s2805;
   const SWord8 s2807 = 127 & s2805;
@@ -2920,7 +2913,7 @@
   const SBool  s2822 = false == s2821;
   const SBool  s2823 = s2813 < s1;
   const SBool  s2824 = s2813 < s2574;
-  const SBool  s2825 = s2823 | s2824;
+  const SBool  s2825 = s2823 || s2824;
   const SWord8 s2826 = (s2813 >> 1) | (s2813 << 7);
   const SWord8 s2827 = 128 | s2826;
   const SWord8 s2828 = 127 & s2826;
@@ -2959,7 +2952,7 @@
   const SWord8 s2861 = s1 + s2856;
   const SBool  s2862 = s2861 < s1;
   const SBool  s2863 = s2861 < s2856;
-  const SBool  s2864 = s2862 | s2863;
+  const SBool  s2864 = s2862 || s2863;
   const SWord8 s2865 = (s2861 >> 1) | (s2861 << 7);
   const SWord8 s2866 = 128 | s2865;
   const SWord8 s2867 = 127 & s2865;
@@ -2968,7 +2961,7 @@
   const SWord8 s2870 = s1 + s2852;
   const SBool  s2871 = s2870 < s1;
   const SBool  s2872 = s2870 < s2852;
-  const SBool  s2873 = s2871 | s2872;
+  const SBool  s2873 = s2871 || s2872;
   const SWord8 s2874 = (s2870 >> 1) | (s2870 << 7);
   const SWord8 s2875 = 128 | s2874;
   const SWord8 s2876 = 127 & s2874;
@@ -2980,7 +2973,7 @@
   const SWord8 s2882 = s1 + s2877;
   const SBool  s2883 = s2882 < s1;
   const SBool  s2884 = s2882 < s2877;
-  const SBool  s2885 = s2883 | s2884;
+  const SBool  s2885 = s2883 || s2884;
   const SWord8 s2886 = (s2882 >> 1) | (s2882 << 7);
   const SWord8 s2887 = 128 | s2886;
   const SWord8 s2888 = 127 & s2886;
@@ -2990,7 +2983,7 @@
   const SWord8 s2892 = s1 + s2848;
   const SBool  s2893 = s2892 < s1;
   const SBool  s2894 = s2892 < s2848;
-  const SBool  s2895 = s2893 | s2894;
+  const SBool  s2895 = s2893 || s2894;
   const SWord8 s2896 = (s2892 >> 1) | (s2892 << 7);
   const SWord8 s2897 = 128 | s2896;
   const SWord8 s2898 = 127 & s2896;
@@ -3006,7 +2999,7 @@
   const SWord8 s2908 = s1 + s2903;
   const SBool  s2909 = s2908 < s1;
   const SBool  s2910 = s2908 < s2903;
-  const SBool  s2911 = s2909 | s2910;
+  const SBool  s2911 = s2909 || s2910;
   const SWord8 s2912 = (s2908 >> 1) | (s2908 << 7);
   const SWord8 s2913 = 128 | s2912;
   const SWord8 s2914 = 127 & s2912;
@@ -3015,7 +3008,7 @@
   const SWord8 s2917 = s1 + s2899;
   const SBool  s2918 = s2917 < s1;
   const SBool  s2919 = s2917 < s2899;
-  const SBool  s2920 = s2918 | s2919;
+  const SBool  s2920 = s2918 || s2919;
   const SWord8 s2921 = (s2917 >> 1) | (s2917 << 7);
   const SWord8 s2922 = 128 | s2921;
   const SWord8 s2923 = 127 & s2921;
@@ -3027,7 +3020,7 @@
   const SWord8 s2929 = s1 + s2924;
   const SBool  s2930 = s2929 < s1;
   const SBool  s2931 = s2929 < s2924;
-  const SBool  s2932 = s2930 | s2931;
+  const SBool  s2932 = s2930 || s2931;
   const SWord8 s2933 = (s2929 >> 1) | (s2929 << 7);
   const SWord8 s2934 = 128 | s2933;
   const SWord8 s2935 = 127 & s2933;
@@ -3047,7 +3040,7 @@
   const SBool  s2949 = false == s2948;
   const SBool  s2950 = s2940 < s1;
   const SBool  s2951 = s2940 < s2829;
-  const SBool  s2952 = s2950 | s2951;
+  const SBool  s2952 = s2950 || s2951;
   const SWord8 s2953 = (s2940 >> 1) | (s2940 << 7);
   const SWord8 s2954 = 128 | s2953;
   const SWord8 s2955 = 127 & s2953;
@@ -3067,7 +3060,7 @@
   const SWord8 s2969 = s1 + s2964;
   const SBool  s2970 = s2969 < s1;
   const SBool  s2971 = s2969 < s2964;
-  const SBool  s2972 = s2970 | s2971;
+  const SBool  s2972 = s2970 || s2971;
   const SWord8 s2973 = (s2969 >> 1) | (s2969 << 7);
   const SWord8 s2974 = 128 | s2973;
   const SWord8 s2975 = 127 & s2973;
@@ -3076,7 +3069,7 @@
   const SWord8 s2978 = s1 + s2960;
   const SBool  s2979 = s2978 < s1;
   const SBool  s2980 = s2978 < s2960;
-  const SBool  s2981 = s2979 | s2980;
+  const SBool  s2981 = s2979 || s2980;
   const SWord8 s2982 = (s2978 >> 1) | (s2978 << 7);
   const SWord8 s2983 = 128 | s2982;
   const SWord8 s2984 = 127 & s2982;
@@ -3088,7 +3081,7 @@
   const SWord8 s2990 = s1 + s2985;
   const SBool  s2991 = s2990 < s1;
   const SBool  s2992 = s2990 < s2985;
-  const SBool  s2993 = s2991 | s2992;
+  const SBool  s2993 = s2991 || s2992;
   const SWord8 s2994 = (s2990 >> 1) | (s2990 << 7);
   const SWord8 s2995 = 128 | s2994;
   const SWord8 s2996 = 127 & s2994;
@@ -3098,7 +3091,7 @@
   const SWord8 s3000 = s1 + s2956;
   const SBool  s3001 = s3000 < s1;
   const SBool  s3002 = s3000 < s2956;
-  const SBool  s3003 = s3001 | s3002;
+  const SBool  s3003 = s3001 || s3002;
   const SWord8 s3004 = (s3000 >> 1) | (s3000 << 7);
   const SWord8 s3005 = 128 | s3004;
   const SWord8 s3006 = 127 & s3004;
@@ -3114,7 +3107,7 @@
   const SWord8 s3016 = s1 + s3011;
   const SBool  s3017 = s3016 < s1;
   const SBool  s3018 = s3016 < s3011;
-  const SBool  s3019 = s3017 | s3018;
+  const SBool  s3019 = s3017 || s3018;
   const SWord8 s3020 = (s3016 >> 1) | (s3016 << 7);
   const SWord8 s3021 = 128 | s3020;
   const SWord8 s3022 = 127 & s3020;
@@ -3123,7 +3116,7 @@
   const SWord8 s3025 = s1 + s3007;
   const SBool  s3026 = s3025 < s1;
   const SBool  s3027 = s3025 < s3007;
-  const SBool  s3028 = s3026 | s3027;
+  const SBool  s3028 = s3026 || s3027;
   const SWord8 s3029 = (s3025 >> 1) | (s3025 << 7);
   const SWord8 s3030 = 128 | s3029;
   const SWord8 s3031 = 127 & s3029;
@@ -3135,7 +3128,7 @@
   const SWord8 s3037 = s1 + s3032;
   const SBool  s3038 = s3037 < s1;
   const SBool  s3039 = s3037 < s3032;
-  const SBool  s3040 = s3038 | s3039;
+  const SBool  s3040 = s3038 || s3039;
   const SWord8 s3041 = (s3037 >> 1) | (s3037 << 7);
   const SWord8 s3042 = 128 | s3041;
   const SWord8 s3043 = 127 & s3041;
@@ -3158,7 +3151,7 @@
   const SBool  s3060 = false == s3059;
   const SBool  s3061 = s3051 < s1;
   const SBool  s3062 = s3051 < s2044;
-  const SBool  s3063 = s3061 | s3062;
+  const SBool  s3063 = s3061 || s3062;
   const SWord8 s3064 = (s3051 >> 1) | (s3051 << 7);
   const SWord8 s3065 = 128 | s3064;
   const SWord8 s3066 = 127 & s3064;
@@ -3235,7 +3228,7 @@
   const SWord8 s3137 = s1 + s3132;
   const SBool  s3138 = s3137 < s1;
   const SBool  s3139 = s3137 < s3132;
-  const SBool  s3140 = s3138 | s3139;
+  const SBool  s3140 = s3138 || s3139;
   const SWord8 s3141 = (s3137 >> 1) | (s3137 << 7);
   const SWord8 s3142 = 128 | s3141;
   const SWord8 s3143 = 127 & s3141;
@@ -3244,7 +3237,7 @@
   const SWord8 s3146 = s1 + s3128;
   const SBool  s3147 = s3146 < s1;
   const SBool  s3148 = s3146 < s3128;
-  const SBool  s3149 = s3147 | s3148;
+  const SBool  s3149 = s3147 || s3148;
   const SWord8 s3150 = (s3146 >> 1) | (s3146 << 7);
   const SWord8 s3151 = 128 | s3150;
   const SWord8 s3152 = 127 & s3150;
@@ -3256,7 +3249,7 @@
   const SWord8 s3158 = s1 + s3153;
   const SBool  s3159 = s3158 < s1;
   const SBool  s3160 = s3158 < s3153;
-  const SBool  s3161 = s3159 | s3160;
+  const SBool  s3161 = s3159 || s3160;
   const SWord8 s3162 = (s3158 >> 1) | (s3158 << 7);
   const SWord8 s3163 = 128 | s3162;
   const SWord8 s3164 = 127 & s3162;
@@ -3266,7 +3259,7 @@
   const SWord8 s3168 = s1 + s3124;
   const SBool  s3169 = s3168 < s1;
   const SBool  s3170 = s3168 < s3124;
-  const SBool  s3171 = s3169 | s3170;
+  const SBool  s3171 = s3169 || s3170;
   const SWord8 s3172 = (s3168 >> 1) | (s3168 << 7);
   const SWord8 s3173 = 128 | s3172;
   const SWord8 s3174 = 127 & s3172;
@@ -3282,7 +3275,7 @@
   const SWord8 s3184 = s1 + s3179;
   const SBool  s3185 = s3184 < s1;
   const SBool  s3186 = s3184 < s3179;
-  const SBool  s3187 = s3185 | s3186;
+  const SBool  s3187 = s3185 || s3186;
   const SWord8 s3188 = (s3184 >> 1) | (s3184 << 7);
   const SWord8 s3189 = 128 | s3188;
   const SWord8 s3190 = 127 & s3188;
@@ -3291,7 +3284,7 @@
   const SWord8 s3193 = s1 + s3175;
   const SBool  s3194 = s3193 < s1;
   const SBool  s3195 = s3193 < s3175;
-  const SBool  s3196 = s3194 | s3195;
+  const SBool  s3196 = s3194 || s3195;
   const SWord8 s3197 = (s3193 >> 1) | (s3193 << 7);
   const SWord8 s3198 = 128 | s3197;
   const SWord8 s3199 = 127 & s3197;
@@ -3303,7 +3296,7 @@
   const SWord8 s3205 = s1 + s3200;
   const SBool  s3206 = s3205 < s1;
   const SBool  s3207 = s3205 < s3200;
-  const SBool  s3208 = s3206 | s3207;
+  const SBool  s3208 = s3206 || s3207;
   const SWord8 s3209 = (s3205 >> 1) | (s3205 << 7);
   const SWord8 s3210 = 128 | s3209;
   const SWord8 s3211 = 127 & s3209;
@@ -3323,7 +3316,7 @@
   const SBool  s3225 = false == s3224;
   const SBool  s3226 = s3216 < s1;
   const SBool  s3227 = s3216 < s3105;
-  const SBool  s3228 = s3226 | s3227;
+  const SBool  s3228 = s3226 || s3227;
   const SWord8 s3229 = (s3216 >> 1) | (s3216 << 7);
   const SWord8 s3230 = 128 | s3229;
   const SWord8 s3231 = 127 & s3229;
@@ -3343,7 +3336,7 @@
   const SWord8 s3245 = s1 + s3240;
   const SBool  s3246 = s3245 < s1;
   const SBool  s3247 = s3245 < s3240;
-  const SBool  s3248 = s3246 | s3247;
+  const SBool  s3248 = s3246 || s3247;
   const SWord8 s3249 = (s3245 >> 1) | (s3245 << 7);
   const SWord8 s3250 = 128 | s3249;
   const SWord8 s3251 = 127 & s3249;
@@ -3352,7 +3345,7 @@
   const SWord8 s3254 = s1 + s3236;
   const SBool  s3255 = s3254 < s1;
   const SBool  s3256 = s3254 < s3236;
-  const SBool  s3257 = s3255 | s3256;
+  const SBool  s3257 = s3255 || s3256;
   const SWord8 s3258 = (s3254 >> 1) | (s3254 << 7);
   const SWord8 s3259 = 128 | s3258;
   const SWord8 s3260 = 127 & s3258;
@@ -3364,7 +3357,7 @@
   const SWord8 s3266 = s1 + s3261;
   const SBool  s3267 = s3266 < s1;
   const SBool  s3268 = s3266 < s3261;
-  const SBool  s3269 = s3267 | s3268;
+  const SBool  s3269 = s3267 || s3268;
   const SWord8 s3270 = (s3266 >> 1) | (s3266 << 7);
   const SWord8 s3271 = 128 | s3270;
   const SWord8 s3272 = 127 & s3270;
@@ -3374,7 +3367,7 @@
   const SWord8 s3276 = s1 + s3232;
   const SBool  s3277 = s3276 < s1;
   const SBool  s3278 = s3276 < s3232;
-  const SBool  s3279 = s3277 | s3278;
+  const SBool  s3279 = s3277 || s3278;
   const SWord8 s3280 = (s3276 >> 1) | (s3276 << 7);
   const SWord8 s3281 = 128 | s3280;
   const SWord8 s3282 = 127 & s3280;
@@ -3390,7 +3383,7 @@
   const SWord8 s3292 = s1 + s3287;
   const SBool  s3293 = s3292 < s1;
   const SBool  s3294 = s3292 < s3287;
-  const SBool  s3295 = s3293 | s3294;
+  const SBool  s3295 = s3293 || s3294;
   const SWord8 s3296 = (s3292 >> 1) | (s3292 << 7);
   const SWord8 s3297 = 128 | s3296;
   const SWord8 s3298 = 127 & s3296;
@@ -3399,7 +3392,7 @@
   const SWord8 s3301 = s1 + s3283;
   const SBool  s3302 = s3301 < s1;
   const SBool  s3303 = s3301 < s3283;
-  const SBool  s3304 = s3302 | s3303;
+  const SBool  s3304 = s3302 || s3303;
   const SWord8 s3305 = (s3301 >> 1) | (s3301 << 7);
   const SWord8 s3306 = 128 | s3305;
   const SWord8 s3307 = 127 & s3305;
@@ -3411,7 +3404,7 @@
   const SWord8 s3313 = s1 + s3308;
   const SBool  s3314 = s3313 < s1;
   const SBool  s3315 = s3313 < s3308;
-  const SBool  s3316 = s3314 | s3315;
+  const SBool  s3316 = s3314 || s3315;
   const SWord8 s3317 = (s3313 >> 1) | (s3313 << 7);
   const SWord8 s3318 = 128 | s3317;
   const SWord8 s3319 = 127 & s3317;
@@ -3432,7 +3425,7 @@
   const SBool  s3334 = false == s3333;
   const SBool  s3335 = s3325 < s1;
   const SBool  s3336 = s3325 < s3086;
-  const SBool  s3337 = s3335 | s3336;
+  const SBool  s3337 = s3335 || s3336;
   const SWord8 s3338 = (s3325 >> 1) | (s3325 << 7);
   const SWord8 s3339 = 128 | s3338;
   const SWord8 s3340 = 127 & s3338;
@@ -3471,7 +3464,7 @@
   const SWord8 s3373 = s1 + s3368;
   const SBool  s3374 = s3373 < s1;
   const SBool  s3375 = s3373 < s3368;
-  const SBool  s3376 = s3374 | s3375;
+  const SBool  s3376 = s3374 || s3375;
   const SWord8 s3377 = (s3373 >> 1) | (s3373 << 7);
   const SWord8 s3378 = 128 | s3377;
   const SWord8 s3379 = 127 & s3377;
@@ -3480,7 +3473,7 @@
   const SWord8 s3382 = s1 + s3364;
   const SBool  s3383 = s3382 < s1;
   const SBool  s3384 = s3382 < s3364;
-  const SBool  s3385 = s3383 | s3384;
+  const SBool  s3385 = s3383 || s3384;
   const SWord8 s3386 = (s3382 >> 1) | (s3382 << 7);
   const SWord8 s3387 = 128 | s3386;
   const SWord8 s3388 = 127 & s3386;
@@ -3492,7 +3485,7 @@
   const SWord8 s3394 = s1 + s3389;
   const SBool  s3395 = s3394 < s1;
   const SBool  s3396 = s3394 < s3389;
-  const SBool  s3397 = s3395 | s3396;
+  const SBool  s3397 = s3395 || s3396;
   const SWord8 s3398 = (s3394 >> 1) | (s3394 << 7);
   const SWord8 s3399 = 128 | s3398;
   const SWord8 s3400 = 127 & s3398;
@@ -3502,7 +3495,7 @@
   const SWord8 s3404 = s1 + s3360;
   const SBool  s3405 = s3404 < s1;
   const SBool  s3406 = s3404 < s3360;
-  const SBool  s3407 = s3405 | s3406;
+  const SBool  s3407 = s3405 || s3406;
   const SWord8 s3408 = (s3404 >> 1) | (s3404 << 7);
   const SWord8 s3409 = 128 | s3408;
   const SWord8 s3410 = 127 & s3408;
@@ -3518,7 +3511,7 @@
   const SWord8 s3420 = s1 + s3415;
   const SBool  s3421 = s3420 < s1;
   const SBool  s3422 = s3420 < s3415;
-  const SBool  s3423 = s3421 | s3422;
+  const SBool  s3423 = s3421 || s3422;
   const SWord8 s3424 = (s3420 >> 1) | (s3420 << 7);
   const SWord8 s3425 = 128 | s3424;
   const SWord8 s3426 = 127 & s3424;
@@ -3527,7 +3520,7 @@
   const SWord8 s3429 = s1 + s3411;
   const SBool  s3430 = s3429 < s1;
   const SBool  s3431 = s3429 < s3411;
-  const SBool  s3432 = s3430 | s3431;
+  const SBool  s3432 = s3430 || s3431;
   const SWord8 s3433 = (s3429 >> 1) | (s3429 << 7);
   const SWord8 s3434 = 128 | s3433;
   const SWord8 s3435 = 127 & s3433;
@@ -3539,7 +3532,7 @@
   const SWord8 s3441 = s1 + s3436;
   const SBool  s3442 = s3441 < s1;
   const SBool  s3443 = s3441 < s3436;
-  const SBool  s3444 = s3442 | s3443;
+  const SBool  s3444 = s3442 || s3443;
   const SWord8 s3445 = (s3441 >> 1) | (s3441 << 7);
   const SWord8 s3446 = 128 | s3445;
   const SWord8 s3447 = 127 & s3445;
@@ -3559,7 +3552,7 @@
   const SBool  s3461 = false == s3460;
   const SBool  s3462 = s3452 < s1;
   const SBool  s3463 = s3452 < s3341;
-  const SBool  s3464 = s3462 | s3463;
+  const SBool  s3464 = s3462 || s3463;
   const SWord8 s3465 = (s3452 >> 1) | (s3452 << 7);
   const SWord8 s3466 = 128 | s3465;
   const SWord8 s3467 = 127 & s3465;
@@ -3579,7 +3572,7 @@
   const SWord8 s3481 = s1 + s3476;
   const SBool  s3482 = s3481 < s1;
   const SBool  s3483 = s3481 < s3476;
-  const SBool  s3484 = s3482 | s3483;
+  const SBool  s3484 = s3482 || s3483;
   const SWord8 s3485 = (s3481 >> 1) | (s3481 << 7);
   const SWord8 s3486 = 128 | s3485;
   const SWord8 s3487 = 127 & s3485;
@@ -3588,7 +3581,7 @@
   const SWord8 s3490 = s1 + s3472;
   const SBool  s3491 = s3490 < s1;
   const SBool  s3492 = s3490 < s3472;
-  const SBool  s3493 = s3491 | s3492;
+  const SBool  s3493 = s3491 || s3492;
   const SWord8 s3494 = (s3490 >> 1) | (s3490 << 7);
   const SWord8 s3495 = 128 | s3494;
   const SWord8 s3496 = 127 & s3494;
@@ -3600,7 +3593,7 @@
   const SWord8 s3502 = s1 + s3497;
   const SBool  s3503 = s3502 < s1;
   const SBool  s3504 = s3502 < s3497;
-  const SBool  s3505 = s3503 | s3504;
+  const SBool  s3505 = s3503 || s3504;
   const SWord8 s3506 = (s3502 >> 1) | (s3502 << 7);
   const SWord8 s3507 = 128 | s3506;
   const SWord8 s3508 = 127 & s3506;
@@ -3610,7 +3603,7 @@
   const SWord8 s3512 = s1 + s3468;
   const SBool  s3513 = s3512 < s1;
   const SBool  s3514 = s3512 < s3468;
-  const SBool  s3515 = s3513 | s3514;
+  const SBool  s3515 = s3513 || s3514;
   const SWord8 s3516 = (s3512 >> 1) | (s3512 << 7);
   const SWord8 s3517 = 128 | s3516;
   const SWord8 s3518 = 127 & s3516;
@@ -3626,7 +3619,7 @@
   const SWord8 s3528 = s1 + s3523;
   const SBool  s3529 = s3528 < s1;
   const SBool  s3530 = s3528 < s3523;
-  const SBool  s3531 = s3529 | s3530;
+  const SBool  s3531 = s3529 || s3530;
   const SWord8 s3532 = (s3528 >> 1) | (s3528 << 7);
   const SWord8 s3533 = 128 | s3532;
   const SWord8 s3534 = 127 & s3532;
@@ -3635,7 +3628,7 @@
   const SWord8 s3537 = s1 + s3519;
   const SBool  s3538 = s3537 < s1;
   const SBool  s3539 = s3537 < s3519;
-  const SBool  s3540 = s3538 | s3539;
+  const SBool  s3540 = s3538 || s3539;
   const SWord8 s3541 = (s3537 >> 1) | (s3537 << 7);
   const SWord8 s3542 = 128 | s3541;
   const SWord8 s3543 = 127 & s3541;
@@ -3647,7 +3640,7 @@
   const SWord8 s3549 = s1 + s3544;
   const SBool  s3550 = s3549 < s1;
   const SBool  s3551 = s3549 < s3544;
-  const SBool  s3552 = s3550 | s3551;
+  const SBool  s3552 = s3550 || s3551;
   const SWord8 s3553 = (s3549 >> 1) | (s3549 << 7);
   const SWord8 s3554 = 128 | s3553;
   const SWord8 s3555 = 127 & s3553;
@@ -3669,7 +3662,7 @@
   const SBool  s3571 = false == s3570;
   const SBool  s3572 = s3562 < s1;
   const SBool  s3573 = s3562 < s3067;
-  const SBool  s3574 = s3572 | s3573;
+  const SBool  s3574 = s3572 || s3573;
   const SWord8 s3575 = (s3562 >> 1) | (s3562 << 7);
   const SWord8 s3576 = 128 | s3575;
   const SWord8 s3577 = 127 & s3575;
@@ -3727,7 +3720,7 @@
   const SWord8 s3629 = s1 + s3624;
   const SBool  s3630 = s3629 < s1;
   const SBool  s3631 = s3629 < s3624;
-  const SBool  s3632 = s3630 | s3631;
+  const SBool  s3632 = s3630 || s3631;
   const SWord8 s3633 = (s3629 >> 1) | (s3629 << 7);
   const SWord8 s3634 = 128 | s3633;
   const SWord8 s3635 = 127 & s3633;
@@ -3736,7 +3729,7 @@
   const SWord8 s3638 = s1 + s3620;
   const SBool  s3639 = s3638 < s1;
   const SBool  s3640 = s3638 < s3620;
-  const SBool  s3641 = s3639 | s3640;
+  const SBool  s3641 = s3639 || s3640;
   const SWord8 s3642 = (s3638 >> 1) | (s3638 << 7);
   const SWord8 s3643 = 128 | s3642;
   const SWord8 s3644 = 127 & s3642;
@@ -3748,7 +3741,7 @@
   const SWord8 s3650 = s1 + s3645;
   const SBool  s3651 = s3650 < s1;
   const SBool  s3652 = s3650 < s3645;
-  const SBool  s3653 = s3651 | s3652;
+  const SBool  s3653 = s3651 || s3652;
   const SWord8 s3654 = (s3650 >> 1) | (s3650 << 7);
   const SWord8 s3655 = 128 | s3654;
   const SWord8 s3656 = 127 & s3654;
@@ -3758,7 +3751,7 @@
   const SWord8 s3660 = s1 + s3616;
   const SBool  s3661 = s3660 < s1;
   const SBool  s3662 = s3660 < s3616;
-  const SBool  s3663 = s3661 | s3662;
+  const SBool  s3663 = s3661 || s3662;
   const SWord8 s3664 = (s3660 >> 1) | (s3660 << 7);
   const SWord8 s3665 = 128 | s3664;
   const SWord8 s3666 = 127 & s3664;
@@ -3774,7 +3767,7 @@
   const SWord8 s3676 = s1 + s3671;
   const SBool  s3677 = s3676 < s1;
   const SBool  s3678 = s3676 < s3671;
-  const SBool  s3679 = s3677 | s3678;
+  const SBool  s3679 = s3677 || s3678;
   const SWord8 s3680 = (s3676 >> 1) | (s3676 << 7);
   const SWord8 s3681 = 128 | s3680;
   const SWord8 s3682 = 127 & s3680;
@@ -3783,7 +3776,7 @@
   const SWord8 s3685 = s1 + s3667;
   const SBool  s3686 = s3685 < s1;
   const SBool  s3687 = s3685 < s3667;
-  const SBool  s3688 = s3686 | s3687;
+  const SBool  s3688 = s3686 || s3687;
   const SWord8 s3689 = (s3685 >> 1) | (s3685 << 7);
   const SWord8 s3690 = 128 | s3689;
   const SWord8 s3691 = 127 & s3689;
@@ -3795,7 +3788,7 @@
   const SWord8 s3697 = s1 + s3692;
   const SBool  s3698 = s3697 < s1;
   const SBool  s3699 = s3697 < s3692;
-  const SBool  s3700 = s3698 | s3699;
+  const SBool  s3700 = s3698 || s3699;
   const SWord8 s3701 = (s3697 >> 1) | (s3697 << 7);
   const SWord8 s3702 = 128 | s3701;
   const SWord8 s3703 = 127 & s3701;
@@ -3815,7 +3808,7 @@
   const SBool  s3717 = false == s3716;
   const SBool  s3718 = s3708 < s1;
   const SBool  s3719 = s3708 < s3597;
-  const SBool  s3720 = s3718 | s3719;
+  const SBool  s3720 = s3718 || s3719;
   const SWord8 s3721 = (s3708 >> 1) | (s3708 << 7);
   const SWord8 s3722 = 128 | s3721;
   const SWord8 s3723 = 127 & s3721;
@@ -3835,7 +3828,7 @@
   const SWord8 s3737 = s1 + s3732;
   const SBool  s3738 = s3737 < s1;
   const SBool  s3739 = s3737 < s3732;
-  const SBool  s3740 = s3738 | s3739;
+  const SBool  s3740 = s3738 || s3739;
   const SWord8 s3741 = (s3737 >> 1) | (s3737 << 7);
   const SWord8 s3742 = 128 | s3741;
   const SWord8 s3743 = 127 & s3741;
@@ -3844,7 +3837,7 @@
   const SWord8 s3746 = s1 + s3728;
   const SBool  s3747 = s3746 < s1;
   const SBool  s3748 = s3746 < s3728;
-  const SBool  s3749 = s3747 | s3748;
+  const SBool  s3749 = s3747 || s3748;
   const SWord8 s3750 = (s3746 >> 1) | (s3746 << 7);
   const SWord8 s3751 = 128 | s3750;
   const SWord8 s3752 = 127 & s3750;
@@ -3856,7 +3849,7 @@
   const SWord8 s3758 = s1 + s3753;
   const SBool  s3759 = s3758 < s1;
   const SBool  s3760 = s3758 < s3753;
-  const SBool  s3761 = s3759 | s3760;
+  const SBool  s3761 = s3759 || s3760;
   const SWord8 s3762 = (s3758 >> 1) | (s3758 << 7);
   const SWord8 s3763 = 128 | s3762;
   const SWord8 s3764 = 127 & s3762;
@@ -3866,7 +3859,7 @@
   const SWord8 s3768 = s1 + s3724;
   const SBool  s3769 = s3768 < s1;
   const SBool  s3770 = s3768 < s3724;
-  const SBool  s3771 = s3769 | s3770;
+  const SBool  s3771 = s3769 || s3770;
   const SWord8 s3772 = (s3768 >> 1) | (s3768 << 7);
   const SWord8 s3773 = 128 | s3772;
   const SWord8 s3774 = 127 & s3772;
@@ -3882,7 +3875,7 @@
   const SWord8 s3784 = s1 + s3779;
   const SBool  s3785 = s3784 < s1;
   const SBool  s3786 = s3784 < s3779;
-  const SBool  s3787 = s3785 | s3786;
+  const SBool  s3787 = s3785 || s3786;
   const SWord8 s3788 = (s3784 >> 1) | (s3784 << 7);
   const SWord8 s3789 = 128 | s3788;
   const SWord8 s3790 = 127 & s3788;
@@ -3891,7 +3884,7 @@
   const SWord8 s3793 = s1 + s3775;
   const SBool  s3794 = s3793 < s1;
   const SBool  s3795 = s3793 < s3775;
-  const SBool  s3796 = s3794 | s3795;
+  const SBool  s3796 = s3794 || s3795;
   const SWord8 s3797 = (s3793 >> 1) | (s3793 << 7);
   const SWord8 s3798 = 128 | s3797;
   const SWord8 s3799 = 127 & s3797;
@@ -3903,7 +3896,7 @@
   const SWord8 s3805 = s1 + s3800;
   const SBool  s3806 = s3805 < s1;
   const SBool  s3807 = s3805 < s3800;
-  const SBool  s3808 = s3806 | s3807;
+  const SBool  s3808 = s3806 || s3807;
   const SWord8 s3809 = (s3805 >> 1) | (s3805 << 7);
   const SWord8 s3810 = 128 | s3809;
   const SWord8 s3811 = 127 & s3809;
@@ -3924,7 +3917,7 @@
   const SBool  s3826 = false == s3825;
   const SBool  s3827 = s3817 < s1;
   const SBool  s3828 = s3817 < s3578;
-  const SBool  s3829 = s3827 | s3828;
+  const SBool  s3829 = s3827 || s3828;
   const SWord8 s3830 = (s3817 >> 1) | (s3817 << 7);
   const SWord8 s3831 = 128 | s3830;
   const SWord8 s3832 = 127 & s3830;
@@ -3963,7 +3956,7 @@
   const SWord8 s3865 = s1 + s3860;
   const SBool  s3866 = s3865 < s1;
   const SBool  s3867 = s3865 < s3860;
-  const SBool  s3868 = s3866 | s3867;
+  const SBool  s3868 = s3866 || s3867;
   const SWord8 s3869 = (s3865 >> 1) | (s3865 << 7);
   const SWord8 s3870 = 128 | s3869;
   const SWord8 s3871 = 127 & s3869;
@@ -3972,7 +3965,7 @@
   const SWord8 s3874 = s1 + s3856;
   const SBool  s3875 = s3874 < s1;
   const SBool  s3876 = s3874 < s3856;
-  const SBool  s3877 = s3875 | s3876;
+  const SBool  s3877 = s3875 || s3876;
   const SWord8 s3878 = (s3874 >> 1) | (s3874 << 7);
   const SWord8 s3879 = 128 | s3878;
   const SWord8 s3880 = 127 & s3878;
@@ -3984,7 +3977,7 @@
   const SWord8 s3886 = s1 + s3881;
   const SBool  s3887 = s3886 < s1;
   const SBool  s3888 = s3886 < s3881;
-  const SBool  s3889 = s3887 | s3888;
+  const SBool  s3889 = s3887 || s3888;
   const SWord8 s3890 = (s3886 >> 1) | (s3886 << 7);
   const SWord8 s3891 = 128 | s3890;
   const SWord8 s3892 = 127 & s3890;
@@ -3994,7 +3987,7 @@
   const SWord8 s3896 = s1 + s3852;
   const SBool  s3897 = s3896 < s1;
   const SBool  s3898 = s3896 < s3852;
-  const SBool  s3899 = s3897 | s3898;
+  const SBool  s3899 = s3897 || s3898;
   const SWord8 s3900 = (s3896 >> 1) | (s3896 << 7);
   const SWord8 s3901 = 128 | s3900;
   const SWord8 s3902 = 127 & s3900;
@@ -4010,7 +4003,7 @@
   const SWord8 s3912 = s1 + s3907;
   const SBool  s3913 = s3912 < s1;
   const SBool  s3914 = s3912 < s3907;
-  const SBool  s3915 = s3913 | s3914;
+  const SBool  s3915 = s3913 || s3914;
   const SWord8 s3916 = (s3912 >> 1) | (s3912 << 7);
   const SWord8 s3917 = 128 | s3916;
   const SWord8 s3918 = 127 & s3916;
@@ -4019,7 +4012,7 @@
   const SWord8 s3921 = s1 + s3903;
   const SBool  s3922 = s3921 < s1;
   const SBool  s3923 = s3921 < s3903;
-  const SBool  s3924 = s3922 | s3923;
+  const SBool  s3924 = s3922 || s3923;
   const SWord8 s3925 = (s3921 >> 1) | (s3921 << 7);
   const SWord8 s3926 = 128 | s3925;
   const SWord8 s3927 = 127 & s3925;
@@ -4031,7 +4024,7 @@
   const SWord8 s3933 = s1 + s3928;
   const SBool  s3934 = s3933 < s1;
   const SBool  s3935 = s3933 < s3928;
-  const SBool  s3936 = s3934 | s3935;
+  const SBool  s3936 = s3934 || s3935;
   const SWord8 s3937 = (s3933 >> 1) | (s3933 << 7);
   const SWord8 s3938 = 128 | s3937;
   const SWord8 s3939 = 127 & s3937;
@@ -4051,7 +4044,7 @@
   const SBool  s3953 = false == s3952;
   const SBool  s3954 = s3944 < s1;
   const SBool  s3955 = s3944 < s3833;
-  const SBool  s3956 = s3954 | s3955;
+  const SBool  s3956 = s3954 || s3955;
   const SWord8 s3957 = (s3944 >> 1) | (s3944 << 7);
   const SWord8 s3958 = 128 | s3957;
   const SWord8 s3959 = 127 & s3957;
@@ -4071,7 +4064,7 @@
   const SWord8 s3973 = s1 + s3968;
   const SBool  s3974 = s3973 < s1;
   const SBool  s3975 = s3973 < s3968;
-  const SBool  s3976 = s3974 | s3975;
+  const SBool  s3976 = s3974 || s3975;
   const SWord8 s3977 = (s3973 >> 1) | (s3973 << 7);
   const SWord8 s3978 = 128 | s3977;
   const SWord8 s3979 = 127 & s3977;
@@ -4080,7 +4073,7 @@
   const SWord8 s3982 = s1 + s3964;
   const SBool  s3983 = s3982 < s1;
   const SBool  s3984 = s3982 < s3964;
-  const SBool  s3985 = s3983 | s3984;
+  const SBool  s3985 = s3983 || s3984;
   const SWord8 s3986 = (s3982 >> 1) | (s3982 << 7);
   const SWord8 s3987 = 128 | s3986;
   const SWord8 s3988 = 127 & s3986;
@@ -4092,7 +4085,7 @@
   const SWord8 s3994 = s1 + s3989;
   const SBool  s3995 = s3994 < s1;
   const SBool  s3996 = s3994 < s3989;
-  const SBool  s3997 = s3995 | s3996;
+  const SBool  s3997 = s3995 || s3996;
   const SWord8 s3998 = (s3994 >> 1) | (s3994 << 7);
   const SWord8 s3999 = 128 | s3998;
   const SWord8 s4000 = 127 & s3998;
@@ -4102,7 +4095,7 @@
   const SWord8 s4004 = s1 + s3960;
   const SBool  s4005 = s4004 < s1;
   const SBool  s4006 = s4004 < s3960;
-  const SBool  s4007 = s4005 | s4006;
+  const SBool  s4007 = s4005 || s4006;
   const SWord8 s4008 = (s4004 >> 1) | (s4004 << 7);
   const SWord8 s4009 = 128 | s4008;
   const SWord8 s4010 = 127 & s4008;
@@ -4118,7 +4111,7 @@
   const SWord8 s4020 = s1 + s4015;
   const SBool  s4021 = s4020 < s1;
   const SBool  s4022 = s4020 < s4015;
-  const SBool  s4023 = s4021 | s4022;
+  const SBool  s4023 = s4021 || s4022;
   const SWord8 s4024 = (s4020 >> 1) | (s4020 << 7);
   const SWord8 s4025 = 128 | s4024;
   const SWord8 s4026 = 127 & s4024;
@@ -4127,7 +4120,7 @@
   const SWord8 s4029 = s1 + s4011;
   const SBool  s4030 = s4029 < s1;
   const SBool  s4031 = s4029 < s4011;
-  const SBool  s4032 = s4030 | s4031;
+  const SBool  s4032 = s4030 || s4031;
   const SWord8 s4033 = (s4029 >> 1) | (s4029 << 7);
   const SWord8 s4034 = 128 | s4033;
   const SWord8 s4035 = 127 & s4033;
@@ -4139,7 +4132,7 @@
   const SWord8 s4041 = s1 + s4036;
   const SBool  s4042 = s4041 < s1;
   const SBool  s4043 = s4041 < s4036;
-  const SBool  s4044 = s4042 | s4043;
+  const SBool  s4044 = s4042 || s4043;
   const SWord8 s4045 = (s4041 >> 1) | (s4041 << 7);
   const SWord8 s4046 = 128 | s4045;
   const SWord8 s4047 = 127 & s4045;
diff --git a/SBVUnitTest/GoldFiles/merge.gold b/SBVUnitTest/GoldFiles/merge.gold
--- a/SBVUnitTest/GoldFiles/merge.gold
+++ b/SBVUnitTest/GoldFiles/merge.gold
@@ -4,7 +4,7 @@
 # include any user-defined .mk file in the current directory.
 -include *.mk
 
-CC=gcc
+CC?=gcc
 CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
 
 all: merge_driver
@@ -33,6 +33,7 @@
 #include <inttypes.h>
 #include <stdint.h>
 #include <stdbool.h>
+#include <string.h>
 #include <math.h>
 
 /* The boolean type */
@@ -65,10 +66,6 @@
 /* Example driver program for merge. */
 /* Automatically generated by SBV. Edit as you see fit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include <stdio.h>
 #include "merge.h"
 
@@ -98,10 +95,6 @@
 == BEGIN: "merge.c" ================
 /* File: "merge.c". Automatically generated by SBV. Do not edit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include "merge.h"
 
 void merge(const SWord8 *xs, SWord8 *ys)
diff --git a/SBVUnitTest/GoldFiles/popCount1.gold b/SBVUnitTest/GoldFiles/popCount1.gold
--- a/SBVUnitTest/GoldFiles/popCount1.gold
+++ b/SBVUnitTest/GoldFiles/popCount1.gold
@@ -4,7 +4,7 @@
 # include any user-defined .mk file in the current directory.
 -include *.mk
 
-CC=gcc
+CC?=gcc
 CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
 
 all: popCount_driver
@@ -33,6 +33,7 @@
 #include <inttypes.h>
 #include <stdint.h>
 #include <stdbool.h>
+#include <string.h>
 #include <math.h>
 
 /* The boolean type */
@@ -65,10 +66,6 @@
 /* Example driver program for popCount. */
 /* Automatically generated by SBV. Edit as you see fit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include <stdio.h>
 #include "popCount.h"
 
@@ -84,10 +81,6 @@
 == BEGIN: "popCount.c" ================
 /* File: "popCount.c". Automatically generated by SBV. Do not edit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include "popCount.h"
 
 SWord8 popCount(const SWord64 x)
diff --git a/SBVUnitTest/GoldFiles/popCount2.gold b/SBVUnitTest/GoldFiles/popCount2.gold
--- a/SBVUnitTest/GoldFiles/popCount2.gold
+++ b/SBVUnitTest/GoldFiles/popCount2.gold
@@ -4,7 +4,7 @@
 # include any user-defined .mk file in the current directory.
 -include *.mk
 
-CC=gcc
+CC?=gcc
 CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
 
 all: popCount_driver
@@ -33,6 +33,7 @@
 #include <inttypes.h>
 #include <stdint.h>
 #include <stdbool.h>
+#include <string.h>
 #include <math.h>
 
 /* The boolean type */
@@ -65,10 +66,6 @@
 /* Example driver program for popCount. */
 /* Automatically generated by SBV. Edit as you see fit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include <stdio.h>
 #include "popCount.h"
 
@@ -84,10 +81,6 @@
 == BEGIN: "popCount.c" ================
 /* File: "popCount.c". Automatically generated by SBV. Do not edit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include "popCount.h"
 
 SWord8 popCount(const SWord64 x)
diff --git a/SBVUnitTest/GoldFiles/prefixSum_16.gold b/SBVUnitTest/GoldFiles/prefixSum_16.gold
deleted file mode 100644
--- a/SBVUnitTest/GoldFiles/prefixSum_16.gold
+++ /dev/null
@@ -1,115 +0,0 @@
-INPUTS
-  s0 :: SWord32
-  s1 :: SWord32
-  s2 :: SWord32
-  s3 :: SWord32
-  s4 :: SWord32
-  s5 :: SWord32
-  s6 :: SWord32
-  s7 :: SWord32
-  s8 :: SWord32
-  s9 :: SWord32
-  s10 :: SWord32
-  s11 :: SWord32
-  s12 :: SWord32
-  s13 :: SWord32
-  s14 :: SWord32
-  s15 :: SWord32
-CONSTANTS
-  s_2 = False
-  s_1 = True
-TABLES
-ARRAYS
-UNINTERPRETED CONSTANTS
-  [uninterpreted] flOp :: SWord32 -> SWord32 -> SWord32
-  [uninterpreted] u :: SWord32
-USER GIVEN CODE SEGMENTS
-AXIOMS
-  -- user defined axiom: flOp is associative
-  :assumption (forall (?x BitVec[32]) (?y BitVec[32]) (?z BitVec[32])
-                      (= (uninterpreted_flOp ?x (uninterpreted_flOp ?y ?z))
-                         (uninterpreted_flOp (uninterpreted_flOp ?x ?y) ?z)
-                      )
-              )
-  -- user defined axiom: u is left-unit for flOp
-  :assumption (forall (?x BitVec[32]) (= (uninterpreted_flOp uninterpreted_u ?x) ?x))
-DEFINE
-  s16 :: SWord32 = [uninterpreted] u
-  s17 :: SWord32 = s16 [uninterpreted] flOp s0
-  s18 :: SBool = s0 == s17
-  s19 :: SWord32 = s0 [uninterpreted] flOp s1
-  s20 :: SWord32 = s16 [uninterpreted] flOp s19
-  s21 :: SBool = s19 == s20
-  s22 :: SWord32 = s19 [uninterpreted] flOp s2
-  s23 :: SWord32 = s20 [uninterpreted] flOp s2
-  s24 :: SBool = s22 == s23
-  s25 :: SWord32 = s22 [uninterpreted] flOp s3
-  s26 :: SWord32 = s2 [uninterpreted] flOp s3
-  s27 :: SWord32 = s19 [uninterpreted] flOp s26
-  s28 :: SWord32 = s16 [uninterpreted] flOp s27
-  s29 :: SBool = s25 == s28
-  s30 :: SWord32 = s25 [uninterpreted] flOp s4
-  s31 :: SWord32 = s28 [uninterpreted] flOp s4
-  s32 :: SBool = s30 == s31
-  s33 :: SWord32 = s30 [uninterpreted] flOp s5
-  s34 :: SWord32 = s4 [uninterpreted] flOp s5
-  s35 :: SWord32 = s28 [uninterpreted] flOp s34
-  s36 :: SBool = s33 == s35
-  s37 :: SWord32 = s33 [uninterpreted] flOp s6
-  s38 :: SWord32 = s35 [uninterpreted] flOp s6
-  s39 :: SBool = s37 == s38
-  s40 :: SWord32 = s37 [uninterpreted] flOp s7
-  s41 :: SWord32 = s6 [uninterpreted] flOp s7
-  s42 :: SWord32 = s34 [uninterpreted] flOp s41
-  s43 :: SWord32 = s27 [uninterpreted] flOp s42
-  s44 :: SWord32 = s16 [uninterpreted] flOp s43
-  s45 :: SBool = s40 == s44
-  s46 :: SWord32 = s40 [uninterpreted] flOp s8
-  s47 :: SWord32 = s44 [uninterpreted] flOp s8
-  s48 :: SBool = s46 == s47
-  s49 :: SWord32 = s46 [uninterpreted] flOp s9
-  s50 :: SWord32 = s8 [uninterpreted] flOp s9
-  s51 :: SWord32 = s44 [uninterpreted] flOp s50
-  s52 :: SBool = s49 == s51
-  s53 :: SWord32 = s49 [uninterpreted] flOp s10
-  s54 :: SWord32 = s51 [uninterpreted] flOp s10
-  s55 :: SBool = s53 == s54
-  s56 :: SWord32 = s53 [uninterpreted] flOp s11
-  s57 :: SWord32 = s10 [uninterpreted] flOp s11
-  s58 :: SWord32 = s50 [uninterpreted] flOp s57
-  s59 :: SWord32 = s44 [uninterpreted] flOp s58
-  s60 :: SBool = s56 == s59
-  s61 :: SWord32 = s56 [uninterpreted] flOp s12
-  s62 :: SWord32 = s59 [uninterpreted] flOp s12
-  s63 :: SBool = s61 == s62
-  s64 :: SWord32 = s61 [uninterpreted] flOp s13
-  s65 :: SWord32 = s12 [uninterpreted] flOp s13
-  s66 :: SWord32 = s59 [uninterpreted] flOp s65
-  s67 :: SBool = s64 == s66
-  s68 :: SWord32 = s64 [uninterpreted] flOp s14
-  s69 :: SWord32 = s66 [uninterpreted] flOp s14
-  s70 :: SBool = s68 == s69
-  s71 :: SWord32 = s68 [uninterpreted] flOp s15
-  s72 :: SWord32 = s14 [uninterpreted] flOp s15
-  s73 :: SWord32 = s65 [uninterpreted] flOp s72
-  s74 :: SWord32 = s58 [uninterpreted] flOp s73
-  s75 :: SWord32 = s43 [uninterpreted] flOp s74
-  s76 :: SBool = s71 == s75
-  s77 :: SBool = s70 & s76
-  s78 :: SBool = s67 & s77
-  s79 :: SBool = s63 & s78
-  s80 :: SBool = s60 & s79
-  s81 :: SBool = s55 & s80
-  s82 :: SBool = s52 & s81
-  s83 :: SBool = s48 & s82
-  s84 :: SBool = s45 & s83
-  s85 :: SBool = s39 & s84
-  s86 :: SBool = s36 & s85
-  s87 :: SBool = s32 & s86
-  s88 :: SBool = s29 & s87
-  s89 :: SBool = s24 & s88
-  s90 :: SBool = s21 & s89
-  s91 :: SBool = s18 & s90
-CONSTRAINTS
-OUTPUTS
-  s91
diff --git a/SBVUnitTest/GoldFiles/selChecked.gold b/SBVUnitTest/GoldFiles/selChecked.gold
--- a/SBVUnitTest/GoldFiles/selChecked.gold
+++ b/SBVUnitTest/GoldFiles/selChecked.gold
@@ -4,7 +4,7 @@
 # include any user-defined .mk file in the current directory.
 -include *.mk
 
-CC=gcc
+CC?=gcc
 CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
 
 all: selChecked_driver
@@ -33,6 +33,7 @@
 #include <inttypes.h>
 #include <stdint.h>
 #include <stdbool.h>
+#include <string.h>
 #include <math.h>
 
 /* The boolean type */
@@ -65,10 +66,6 @@
 /* Example driver program for selChecked. */
 /* Automatically generated by SBV. Edit as you see fit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include <stdio.h>
 #include "selChecked.h"
 
@@ -84,10 +81,6 @@
 == BEGIN: "selChecked.c" ================
 /* File: "selChecked.c". Automatically generated by SBV. Do not edit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include "selChecked.h"
 
 SWord8 selChecked(const SWord8 x)
diff --git a/SBVUnitTest/GoldFiles/selUnchecked.gold b/SBVUnitTest/GoldFiles/selUnchecked.gold
--- a/SBVUnitTest/GoldFiles/selUnchecked.gold
+++ b/SBVUnitTest/GoldFiles/selUnchecked.gold
@@ -4,7 +4,7 @@
 # include any user-defined .mk file in the current directory.
 -include *.mk
 
-CC=gcc
+CC?=gcc
 CCFLAGS?=-Wall -O3 -DNDEBUG -fomit-frame-pointer
 
 all: selUnChecked_driver
@@ -33,6 +33,7 @@
 #include <inttypes.h>
 #include <stdint.h>
 #include <stdbool.h>
+#include <string.h>
 #include <math.h>
 
 /* The boolean type */
@@ -65,10 +66,6 @@
 /* Example driver program for selUnChecked. */
 /* Automatically generated by SBV. Edit as you see fit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include <stdio.h>
 #include "selUnChecked.h"
 
@@ -84,10 +81,6 @@
 == BEGIN: "selUnChecked.c" ================
 /* File: "selUnChecked.c". Automatically generated by SBV. Do not edit! */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <math.h>
 #include "selUnChecked.h"
 
 SWord8 selUnChecked(const SWord8 x)
diff --git a/SBVUnitTest/GoldFiles/temperature.gold b/SBVUnitTest/GoldFiles/temperature.gold
--- a/SBVUnitTest/GoldFiles/temperature.gold
+++ b/SBVUnitTest/GoldFiles/temperature.gold
@@ -1,5 +1,5 @@
 Solution #1:
-  s0 = 28 :: Integer
-Solution #2:
   s0 = 16 :: Integer
+Solution #2:
+  s0 = 28 :: Integer
 Found 2 different solutions.
diff --git a/SBVUnitTest/SBVTest.hs b/SBVUnitTest/SBVTest.hs
--- a/SBVUnitTest/SBVTest.hs
+++ b/SBVUnitTest/SBVTest.hs
@@ -10,13 +10,20 @@
 -----------------------------------------------------------------------------
 
 {-# LANGUAGE RankNTypes #-}
-module SBVTest(generateGoldCheck, showsAs, ioShowsAs, mkTestSuite, SBVTestSuite(..), module Test.HUnit, isThm, isSat, free, newArray, numberOfModels) where
+module SBVTest(
+          generateGoldCheck, showsAs, ioShowsAs, mkTestSuite, SBVTestSuite(..)
+        , isThm, isSat, runSAT, numberOfModels
+        , module Test.HUnit
+        , module Data.SBV
+        ) where
 
-import Data.SBV        (Provable(..), isTheorem, isSatisfiable, AllSatResult(..), allSat, SymWord(free), SymArray(newArray))
-import Data.Maybe      (fromJust)
-import System.FilePath ((</>))
-import Test.HUnit      (Test(..), Assertion, assert, (~:), test)
+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
 data SBVTestSuite = SBVTestSuite ((forall a. Show a => (IO a -> FilePath -> IO ())) -> Test)
 
@@ -57,3 +64,7 @@
 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
--- a/SBVUnitTest/SBVTestCollection.hs
+++ b/SBVUnitTest/SBVTestCollection.hs
@@ -36,9 +36,10 @@
 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.GCD             as T05_05(testSuite)
-import qualified TestSuite.CodeGeneration.PopulationCount as T05_06(testSuite)
-import qualified TestSuite.CodeGeneration.Uninterpreted   as T05_07(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)
@@ -87,9 +88,10 @@
      , ("cgtest",      False, T05_02.testSuite)
      , ("cgUSB5",      False, T05_03.testSuite)
      , ("fib",         False, T05_04.testSuite)
-     , ("gcd",         False, T05_05.testSuite)
-     , ("popCount",    False, T05_06.testSuite)
-     , ("cgUninterp",  False, T05_07.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)
diff --git a/SBVUnitTest/SBVUnitTest.hs b/SBVUnitTest/SBVUnitTest.hs
--- a/SBVUnitTest/SBVUnitTest.hs
+++ b/SBVUnitTest/SBVUnitTest.hs
@@ -12,6 +12,8 @@
 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(..))
@@ -30,12 +32,20 @@
           tgts <- getArgs
           case tgts of
             [x] | x `elem` ["-h", "--help", "-?"]
-                   -> putStrLn "Usage: SBVUnitTests [-l(ist)] [-s(kipCF)] [targets]" -- Not quite right, but sufficient
+                   -> 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 ts   False True ["SBVUnitTest/GoldFiles"]
-            ("-s":ts) -> run ts   True False []
-            _         -> run tgts False False []
+            ("-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
@@ -51,21 +61,33 @@
 showTargets = do putStrLn "Known test targets are:"
                  mapM_ (putStrLn . ("\t" ++))  allTargets
 
-run :: [String] -> Bool -> Bool -> [String] -> IO ()
-run targets skipCF shouldCreate [gd] =
+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 $ map mkTst [c | (tc, needsSolver, c) <- allTestCases, select needsSolver tc]
+           cts <- runTestTT $ TestList $ concatMap mkTst [c | (tc, needsSolver, c) <- allTestCases, select needsSolver tc]
            decide shouldCreate cts
-  where mkTst (SBVTestSuite f) = f $ generateGoldCheck gd shouldCreate
+  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 = null targets || tc `elem` targets
-        checkTgt t | t `elem` allTargets = return ()
+          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"]
diff --git a/SBVUnitTest/SBVUnitTestBuildTime.hs b/SBVUnitTest/SBVUnitTestBuildTime.hs
--- a/SBVUnitTest/SBVUnitTestBuildTime.hs
+++ b/SBVUnitTest/SBVUnitTestBuildTime.hs
@@ -2,4 +2,4 @@
 module SBVUnitTestBuildTime (buildTime) where
 
 buildTime :: String
-buildTime = "Sun Apr 12 21:51:24 PDT 2015"
+buildTime = "Mon Sep 21 22:01:46 PDT 2015"
diff --git a/SBVUnitTest/TestSuite/Basics/ArithNoSolver.hs b/SBVUnitTest/TestSuite/Basics/ArithNoSolver.hs
--- a/SBVUnitTest/TestSuite/Basics/ArithNoSolver.hs
+++ b/SBVUnitTest/TestSuite/Basics/ArithNoSolver.hs
@@ -12,20 +12,19 @@
 
 {-# LANGUAGE Rank2Types    #-}
 {-# LANGUAGE TupleSections #-}
-{-# LANGUAGE CPP           #-}
 
 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)
 
 ghcBitSize :: Bits a => a -> Int
-#if __GLASGOW_HASKELL__ >= 708
-ghcBitSize x = maybe (error "SBV.ghcBitSize: Unexpected non-finite usage!") id (bitSizeMaybe x)
-#else
-ghcBitSize = bitSize
-#endif
+ghcBitSize x = fromMaybe (error "SBV.ghcBitSize: Unexpected non-finite usage!") (bitSizeMaybe x)
 
 -- Test suite
 testSuite :: SBVTestSuite
@@ -61,7 +60,7 @@
      ++ genIntTestS "rotateL"          rotateL
      ++ genIntTestS "rotateR"          rotateR
      ++ genBlasts
-     ++ genCasts
+     ++ genIntCasts
 
 genBinTest :: String -> (forall a. (Num a, Bits a) => a -> a -> a) -> [Test]
 genBinTest nm op = map mkTest $
@@ -154,56 +153,57 @@
           ++ [(show x, fromBitsBE (blastBE x) .== x) | x <- si64s]
   where mkTest (x, r) = "blast-" ++ x ~: r `showsAs` "True"
 
-genCasts :: [Test]
-genCasts = map mkTest $
-            [(show x, unsignCast (signCast x) .== x) | x <- sw8s ]
-         ++ [(show x, unsignCast (signCast x) .== x) | x <- sw16s]
-         ++ [(show x, unsignCast (signCast x) .== x) | x <- sw32s]
-         ++ [(show x, unsignCast (signCast x) .== x) | x <- sw64s]
-         ++ [(show x, signCast (unsignCast x) .== x) | x <- si8s ]
-         ++ [(show x, signCast (unsignCast x) .== x) | x <- si16s]
-         ++ [(show x, signCast (unsignCast x) .== x) | x <- si8s ]
-         ++ [(show x, signCast (unsignCast x) .== x) | x <- si16s]
-         ++ [(show x, signCast (unsignCast x) .== x) | x <- si32s]
-         ++ [(show x, signCast (unsignCast x) .== x) | x <- si64s]
-         ++ [(show x, signCast x .== fromBitsLE (blastLE x))   | x <- sw8s ]
-         ++ [(show x, signCast x .== fromBitsLE (blastLE x))   | x <- sw16s]
-         ++ [(show x, signCast x .== fromBitsLE (blastLE x))   | x <- sw32s]
-         ++ [(show x, signCast x .== fromBitsLE (blastLE x))   | x <- sw64s]
-         ++ [(show x, unsignCast x .== fromBitsLE (blastLE x)) | x <- si8s ]
-         ++ [(show x, unsignCast x .== fromBitsLE (blastLE x)) | x <- si16s]
-         ++ [(show x, unsignCast x .== fromBitsLE (blastLE x)) | x <- si32s]
-         ++ [(show x, unsignCast x .== fromBitsLE (blastLE x)) | x <- si64s]
-  where mkTest (x, r) = "cast-" ++ 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, Bits 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 `divMod'`  y) | x <- w8s,  y <- w8s ]                 [x `sDivMod`  y | x <- sw8s,  y <- sw8s ]
-     ++ zipWith pair [("divMod",  show x, show y, x `divMod'`  y) | x <- w16s, y <- w16s]                 [x `sDivMod`  y | x <- sw16s, y <- sw16s]
-     ++ zipWith pair [("divMod",  show x, show y, x `divMod'`  y) | x <- w32s, y <- w32s]                 [x `sDivMod`  y | x <- sw32s, y <- sw32s]
-     ++ zipWith pair [("divMod",  show x, show y, x `divMod'`  y) | x <- w64s, y <- w64s]                 [x `sDivMod`  y | x <- sw64s, y <- sw64s]
-     ++ zipWith pair [("divMod",  show x, show y, x `divMod'`  y) | x <- i8s,  y <- i8s , noOverflow x y] [x `sDivMod`  y | x <- si8s,  y <- si8s , noOverflow x y]
-     ++ zipWith pair [("divMod",  show x, show y, x `divMod'`  y) | x <- i16s, y <- i16s, noOverflow x y] [x `sDivMod`  y | x <- si16s, y <- si16s, noOverflow x y]
-     ++ zipWith pair [("divMod",  show x, show y, x `divMod'`  y) | x <- i32s, y <- i32s, noOverflow x y] [x `sDivMod`  y | x <- si32s, y <- si32s, noOverflow x y]
-     ++ zipWith pair [("divMod",  show x, show y, x `divMod'`  y) | x <- i64s, y <- i64s, noOverflow x y] [x `sDivMod`  y | x <- si64s, y <- si64s, noOverflow x y]
-     ++ zipWith pair [("divMod",  show x, show y, x `divMod'`  y) | x <- iUBs, y <- iUBs]                 [x `sDivMod`  y | x <- siUBs, y <- siUBs]
-     ++ zipWith pair [("quotRem", show x, show y, x `quotRem'` y) | x <- w8s,  y <- w8s ]                 [x `sQuotRem` y | x <- sw8s,  y <- sw8s ]
-     ++ zipWith pair [("quotRem", show x, show y, x `quotRem'` y) | x <- w16s, y <- w16s]                 [x `sQuotRem` y | x <- sw16s, y <- sw16s]
-     ++ zipWith pair [("quotRem", show x, show y, x `quotRem'` y) | x <- w32s, y <- w32s]                 [x `sQuotRem` y | x <- sw32s, y <- sw32s]
-     ++ zipWith pair [("quotRem", show x, show y, x `quotRem'` y) | x <- w64s, y <- w64s]                 [x `sQuotRem` y | x <- sw64s, y <- sw64s]
-     ++ zipWith pair [("quotRem", show x, show y, x `quotRem'` y) | x <- i8s,  y <- i8s , noOverflow x y] [x `sQuotRem` y | x <- si8s,  y <- si8s , noOverflow x y]
-     ++ zipWith pair [("quotRem", show x, show y, x `quotRem'` y) | x <- i16s, y <- i16s, noOverflow x y] [x `sQuotRem` y | x <- si16s, y <- si16s, noOverflow x y]
-     ++ zipWith pair [("quotRem", show x, show y, x `quotRem'` y) | x <- i32s, y <- i32s, noOverflow x y] [x `sQuotRem` y | x <- si32s, y <- si32s, noOverflow x y]
-     ++ zipWith pair [("quotRem", show x, show y, x `quotRem'` y) | x <- i64s, y <- i64s, noOverflow x y] [x `sQuotRem` y | x <- si64s, y <- si64s, noOverflow x y]
-     ++ zipWith pair [("quotRem", show x, show y, x `quotRem'` y) | x <- iUBs, y <- iUBs]                 [x `sQuotRem` y | x <- siUBs, y <- siUBs]
-  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
-        pair (nm, x, y, (r1, r2)) (e1, e2)   = (nm, x, y, show (fromIntegral r1 `asTypeOf` e1, fromIntegral r2 `asTypeOf` e2) == show (e1, e2))
+        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 overflows if x == minBound and y == -1 for bounded signed types; so avoid that case
-        -- NB. There's a bug filed against this; so remove this when it gets fixed:
-        -- See: https://ghc.haskell.org/trac/ghc/ticket/8695
-        noOverflow x y = not (x == minBound && y == -1)
+        -- 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 $
@@ -221,61 +221,183 @@
         mkTest (nm, (x, y, s)) = "arithCF-" ++ nm ++ "." ++ x ++ "_" ++ y  ~: s `showsAs` "True"
 
 genFloats :: [Test]
-genFloats = bTests ++ uTests
-  where bTests = map mkTest2 $
-                   map ("+",)  (zipWith pair  [(show x, show y, x +  y) | x <- fs, y <- fs        ] [x +   y | x <- sfs,  y <- sfs                       ])
-                ++ map ("-",)  (zipWith pair  [(show x, show y, x -  y) | x <- fs, y <- fs        ] [x -   y | x <- sfs,  y <- sfs                       ])
-                ++ map ("*",)  (zipWith pair  [(show x, show y, x *  y) | x <- fs, y <- fs        ] [x *   y | x <- sfs,  y <- sfs                       ])
-                ++ map ("<",)  (zipWith pairB [(     x,      y, x <  y) | x <- fs, y <- fs        ] [x .<  y | x <- sfs,  y <- sfs                       ])
-                ++ map ("<=",) (zipWith pairB [(     x,      y, x <= y) | x <- fs, y <- fs        ] [x .<= y | x <- sfs,  y <- sfs                       ])
-                ++ map (">",)  (zipWith pairB [(     x,      y, x >  y) | x <- fs, y <- fs        ] [x .>  y | x <- sfs,  y <- sfs                       ])
-                ++ map (">=",) (zipWith pairB [(     x,      y, x >= y) | x <- fs, y <- fs        ] [x .>= y | x <- sfs,  y <- sfs                       ])
-                ++ map ("==",) (zipWith pairB [(     x,      y, x == y) | x <- fs, y <- fs        ] [x .== y | x <- sfs,  y <- sfs                       ])
-                ++ map ("/=",) (zipWith pairN [(     x,      y, x /= y) | x <- fs, y <- fs        ] [x ./= y | x <- sfs,  y <- sfs                       ])
-                ++ map ("/",)  (zipWith pair  [(show x, show y, x /  y) | x <- fs, y <- fs, y /= 0] [x / y   | x <- sfs,  y <- sfs, unliteral y /= Just 0])
-                ++ map ("+",)  (zipWith pair  [(show x, show y, x +  y) | x <- ds, y <- ds        ] [x +   y | x <- sds,  y <- sds                       ])
-                ++ map ("-",)  (zipWith pair  [(show x, show y, x -  y) | x <- ds, y <- ds        ] [x -   y | x <- sds,  y <- sds                       ])
-                ++ map ("*",)  (zipWith pair  [(show x, show y, x *  y) | x <- ds, y <- ds        ] [x *   y | x <- sds,  y <- sds                       ])
-                ++ map ("<",)  (zipWith pairB [(     x,      y, x <  y) | x <- ds, y <- ds        ] [x .<  y | x <- sds,  y <- sds                       ])
-                ++ map ("<=",) (zipWith pairB [(     x,      y, x <= y) | x <- ds, y <- ds        ] [x .<= y | x <- sds,  y <- sds                       ])
-                ++ map (">",)  (zipWith pairB [(     x,      y, x >  y) | x <- ds, y <- ds        ] [x .>  y | x <- sds,  y <- sds                       ])
-                ++ map (">=",) (zipWith pairB [(     x,      y, x >= y) | x <- ds, y <- ds        ] [x .>= y | x <- sds,  y <- sds                       ])
-                ++ map ("==",) (zipWith pairB [(     x,      y, x == y) | x <- ds, y <- ds        ] [x .== y | x <- sds,  y <- sds                       ])
-                ++ map ("/=",) (zipWith pairN [(     x,      y, x /= y) | x <- ds, y <- ds        ] [x ./= y | x <- sds,  y <- sds                       ])
-                ++ map ("/",)  (zipWith pair  [(show x, show y, x /  y) | x <- ds, y <- ds, y /= 0] [x / y   | x <- sds,  y <- sds, unliteral y /= Just 0])
+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
+
+                               ++ floatRun2   "fpMin"           fpMinH           fpMin           comb
+                               ++ doubleRun2  "fpMin"           fpMinH           fpMin           comb
+
+                               ++ floatRun2   "fpMax"           fpMaxH           fpMax           comb
+                               ++ doubleRun2  "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  (sWord32AsSFloat  (literal x)) (literal x), literal true) | x <- w32s]
+                 ++ map cvtTestI [("reinterp_Double_Word64", show x, sDoubleAsSWord64 (sWord64AsSDouble (literal x)) (literal x), literal true) | x <- w64s]
+
+        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]
         uTests = map mkTest1 $  concatMap (checkPred fs sfs) predicates
                              ++ concatMap (checkPred ds sds) predicates
-        pair (x, y, a) b = (x, y, same a (unliteral b))
-        same a (Just b) = (isNaN a &&& isNaN b) || (a == b)
-        same _ _        = False
-        pairB (x, y, a) b = (show x, show y, checkNaN f x y a (unliteral b)) where f v w = not (v || w)  -- Other comparison: Both should be False
-        pairN (x, y, a) b = (show x, show y, checkNaN f x y a (unliteral b)) where f v w =      v && w   -- /=: Both should be True
-        checkNaN f x y a (Just b)
+        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
-        checkNaN _ _ _ _ _     = False
-        mkTest1 (nm, x, s)      = "arithCF-" ++ nm ++ "." ++ x ~: s `showsAs` "True"
+        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, RealFloat a, Floating a, SymWord a) => [a] -> [SBV a] -> (String, SBV a -> SBool, a -> Bool) -> [(String, String, Bool)]
+        checkPred :: (Show a, RealFloat a, Floating a, SymWord 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
                   -- Work around GHC bug, see issue #138
                   -- Remove the following line when fixed.
-                  | nm == "isPositiveZeroFP" && isNegativeZero x = (nm, show x, True)
-                  | True                                         = (nm, show x, Just v == unliteral sv)
-        predicates :: (RealFloat a, Floating a, SymWord a) => [(String, SBV a -> SBool, a -> Bool)]
-        predicates = [ ("isNormalFP",       isNormalFP,        isNormalized)
-                     , ("isSubnormalFP",    isSubnormalFP,     isDenormalized)
-                     , ("isZeroFP",         isZeroFP,          (== 0))
-                     , ("isInfiniteFP",     isInfiniteFP,      isInfinite)
-                     , ("isNaNFP",          isNaNFP,           isNaN)
-                     , ("isNegativeFP",     isNegativeFP,      \x -> x < 0  ||      isNegativeZero x)
-                     , ("isPositiveFP",     isPositiveFP,      \x -> x >= 0 && not (isNegativeZero x))
-                     , ("isNegativeZeroFP", isNegativeZeroFP,  isNegativeZero)
-                     , ("isPositiveZeroFP", isPositiveZeroFP,  \x -> x == 0 && not (isNegativeZero x))
-                     , ("isPointFP",        isPointFP,         \x -> not (isNaN x || isInfinite x))
+                  | nm == "fpIsPositiveZero" && isNegativeZero x = (nm, (show x, True))
+                  | True                                         = (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))
                      ]
-            where isNormalized x = not (isDenormalized x || isInfinite x || isNaN x)
 
 -- Concrete test data
 xsSigned, xsUnsigned :: (Num a, Enum a, Bounded a) => [a]
@@ -345,15 +467,15 @@
 srs = map literal rs
 
 fs :: [Float]
-fs = xs ++ map (* (-1)) xs
+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)) xs
- where xs = [nan, infinity, 0, 0.5, 2.516632060108026e-2, 0.8601891300751106, 7.518897767550192e-2, 1.1656043286207285e-2, 1.0e-323]
+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
--- a/SBVUnitTest/TestSuite/Basics/ArithSolver.hs
+++ b/SBVUnitTest/TestSuite/Basics/ArithSolver.hs
@@ -13,20 +13,19 @@
 
 {-# LANGUAGE Rank2Types    #-}
 {-# LANGUAGE TupleSections #-}
-{-# LANGUAGE CPP           #-}
 
 module TestSuite.Basics.ArithSolver(testSuite) where
 
+import Data.Maybe (fromMaybe, fromJust)
+import qualified Data.Binary.IEEE754 as DB (wordToFloat, wordToDouble)
+
 import Data.SBV
+import Data.SBV.Internals
 
 import SBVTest
 
 ghcBitSize :: Bits a => a -> Int
-#if __GLASGOW_HASKELL__ >= 708
-ghcBitSize x = maybe (error "SBV.ghcBitSize: Unexpected non-finite usage!") id (bitSizeMaybe x)
-#else
-ghcBitSize = bitSize
-#endif
+ghcBitSize x = fromMaybe (error "SBV.ghcBitSize: Unexpected non-finite usage!") (bitSizeMaybe x)
 
 -- Test suite
 testSuite :: SBVTestSuite
@@ -63,8 +62,7 @@
      ++ genIntTestS True   "rotateL"          rotateL
      ++ genIntTestS True   "rotateR"          rotateR
      ++ genBlasts
-     ++ genCasts
-
+     ++ 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 ]
@@ -167,32 +165,25 @@
                                      constrain $ a .== literal v
                                      return $ a .== from (to a)
 
-genCasts :: [Test]
-genCasts = map mkTest $  [(show x, mkThm unsignCast signCast x) | x <- w8s ]
-                      ++ [(show x, mkThm unsignCast signCast x) | x <- w16s]
-                      ++ [(show x, mkThm unsignCast signCast x) | x <- w32s]
-                      ++ [(show x, mkThm unsignCast signCast x) | x <- w64s]
-                      ++ [(show x, mkThm signCast unsignCast x) | x <- i8s ]
-                      ++ [(show x, mkThm signCast unsignCast x) | x <- i16s]
-                      ++ [(show x, mkThm signCast unsignCast x) | x <- i8s ]
-                      ++ [(show x, mkThm signCast unsignCast x) | x <- i16s]
-                      ++ [(show x, mkThm signCast unsignCast x) | x <- i32s]
-                      ++ [(show x, mkThm signCast unsignCast x) | x <- i64s]
-                      ++ [(show x, mkFEq signCast   (fromBitsLE . blastLE) x) | x <- w8s ]
-                      ++ [(show x, mkFEq signCast   (fromBitsLE . blastLE) x) | x <- w16s]
-                      ++ [(show x, mkFEq signCast   (fromBitsLE . blastLE) x) | x <- w32s]
-                      ++ [(show x, mkFEq signCast   (fromBitsLE . blastLE) x) | x <- w64s]
-                      ++ [(show x, mkFEq unsignCast (fromBitsLE . blastLE) x) | x <- i8s ]
-                      ++ [(show x, mkFEq unsignCast (fromBitsLE . blastLE) x) | x <- i16s]
-                      ++ [(show x, mkFEq unsignCast (fromBitsLE . blastLE) x) | x <- i32s]
-                      ++ [(show x, mkFEq unsignCast (fromBitsLE . blastLE) x) | x <- i64s]
-  where mkTest (x, t) = "genCasts.cast-" ++ x ~: assert t
-        mkThm from to v = isThm $ do a <- free "x"
-                                     constrain $ a .== literal v
-                                     return $ a .== from (to a)
-        mkFEq f g v = isThm $ do a <- free "x"
-                                 constrain $ a .== literal v
-                                 return $ f a .== g 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, Bits 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        ]
@@ -217,68 +208,180 @@
 genDoubles :: [Test]
 genDoubles = genIEEE754 "genDoubles" ds
 
-genIEEE754 :: (RealFloat a, Show a, SymWord a, Ord a, Floating a) => String -> [a] -> [Test]
-genIEEE754 origin vs = map tst1 uns ++ map tst2 bins ++ map tst1 preds
-  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, not (isNaN x)]  -- TODO: Remove NaNs, skipping over NaN due to GHC bug. GitHub Issue #101.
-        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, y /= 0]
-               ++ [("<",      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        ]
+genIEEE754 :: (IEEEFloating a, Show a, Ord a) => String -> [a] -> [Test]
+genIEEE754 origin vs =  map tst1 [("fpCast_" ++ nm, x, y)    | (nm, x, y)    <- converts]
+                     ++ 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]
+               ++ [("fpMax",           show x, show y, mkThm2  fpMax            x y (fpMaxH           x y)) | x <- vs, y <- vs]
+               ++ [("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
+
+        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, mkIso sFloatAsSWord32  sWord32AsSFloat  x) | x <- w32s]
+                 ++  [("reinterp_Double_Word64", show x, mkIso sDoubleAsSWord64 sWord64AsSDouble x) | x <- w64s]
+
+        m f = f sRNE
+
         preds =   [(pn,       show x,         mkThmP        ps       x   (pc x))     | (pn, ps, pc) <- predicates, x <- vs
                                                                                      -- Work around GHC bug, see issue #138
                                                                                      -- Remove the following line when fixed.
-                                                                                     , not (pn == "isPositiveZeroFP" && isNegativeZero x)
+                                                                                     , not (pn == "fpIsPositiveZero" && isNegativeZero x)
                                                                                      ]
         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 $ isNaNFP v
-          | isNegativeZero val        = constrain $ isNegativeZeroFP v
-          | val == 0                  = constrain $ isPositiveZeroFP v
-          | isInfinite val && val > 0 = constrain $ isInfiniteFP v &&& isPositiveFP v
-          | isInfinite val && val < 0 = constrain $ isInfiniteFP v &&& isNegativeFP v
+          | 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
-        mkThmP op x r = isThm $ do a <- free "x"
+
+        -- 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
+
+        mkIso f g i = fpThm $ do a <- free "x"
+                                 constrain $ a .== literal i
+                                 return (f (g a) a :: SBool)
+
+        mkThmP op x r = fpThm $ do a <- free "x"
                                    eqF a x
                                    return $ literal r .== op a
-        mkThm1 op x r = isThm $ do a <- free "x"
+
+        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 $ if isNaN r
-                                            then isNaNFP (op a)
-                                            else literal r .== op a
-        mkThm2 op x y r = isThm $ do [a, b] <- mapM free ["x", "y"]
+                                   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
+
+        mkThm2 op x y r = fpThm $ do [a, b] <- mapM free ["x", "y"]
                                      eqF a x
                                      eqF b y
-                                     return $ if isNaN r
-                                              then isNaNFP (a `op` b)
-                                              else literal r .== a `op` b
-        mkThm2C neq op x y r = isThm $ do [a, b] <- mapM free ["x", "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 :: (RealFloat a, Floating a, SymWord a) => [(String, SBV a -> SBool, a -> Bool)]
-        predicates = [ ("isNormalFP",       isNormalFP,        isNormalized)
-                     , ("isSubnormalFP",    isSubnormalFP,     isDenormalized)
-                     , ("isZeroFP",         isZeroFP,          (== 0))
-                     , ("isInfiniteFP",     isInfiniteFP,      isInfinite)
-                     , ("isNaNFP",          isNaNFP,           isNaN)
-                     , ("isNegativeFP",     isNegativeFP,      \x -> x < 0  ||      isNegativeZero x)
-                     , ("isPositiveFP",     isPositiveFP,      \x -> x >= 0 && not (isNegativeZero x))
-                     , ("isNegativeZeroFP", isNegativeZeroFP,  isNegativeZero)
-                     , ("isPositiveZeroFP", isPositiveZeroFP,  \x -> x == 0 && not (isNegativeZero x))
-                     , ("isPointFP",        isPointFP,         \x -> not (isNaN x || isInfinite x))
+
+        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))
                      ]
-           where isNormalized x = not (isDenormalized x || isInfinite x || isNaN x)
 
 genQRems :: [Test]
 genQRems = map mkTest $  [("divMod",  show x, show y, mkThm2 sDivMod  x y (x `divMod'`  y)) | x <- w8s,  y <- w8s ]
@@ -311,8 +414,8 @@
 
 -- Concrete test data
 xsSigned, xsUnsigned :: (Num a, Enum a, Bounded a) => [a]
-xsUnsigned = [minBound, 0, maxBound]
-xsSigned   = xsUnsigned ++ [-1, 1]
+xsUnsigned = [0, 1, maxBound - 1, maxBound]
+xsSigned   = xsUnsigned ++ [minBound, minBound + 1, -1]
 
 w8s :: [Word8]
 w8s = xsUnsigned
@@ -348,11 +451,11 @@
 
 -- Admittedly paltry test-cases for float/double
 fs :: [Float]
-fs = xs ++ map (* (-1)) xs
- where xs = [nan, infinity, 0, 0.5, 0.68302244, 0.5268265, 0.10283524, 5.8336496e-2, 1.0e-45]
+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)) xs
- where xs = [nan, infinity, 0, 0.5, 2.516632060108026e-2, 0.8601891300751106, 7.518897767550192e-2, 1.1656043286207285e-2, 1.0e-323]
+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/IteTest.hs b/SBVUnitTest/TestSuite/Basics/IteTest.hs
--- a/SBVUnitTest/TestSuite/Basics/IteTest.hs
+++ b/SBVUnitTest/TestSuite/Basics/IteTest.hs
@@ -12,7 +12,6 @@
 module TestSuite.Basics.IteTest(testSuite)  where
 
 import Data.SBV
-import Data.SBV.Internals
 
 import SBVTest
 
@@ -34,8 +33,5 @@
  , "ite-4"  ~: assert =<< isThm (chk1 iteLazy)
  , "ite-5"  ~: assert =<< isThm (chk2 iteLazy)
  , "ite-6"  ~: assert =<< isThm (chk3 iteLazy)
- , "ite-7"  ~: assert =<< isThm (chk1 sBranch)
- , "ite-8"  ~: assert =<< isThm (chk2 sBranch)
- , "ite-9"  ~: assert =<< isThm (chk3 sBranch)
  ]
- where rs f = runSymbolic (True, Nothing) $ forAll ["x"] f
+ where rs f = runSAT $ forAll ["x"] f
diff --git a/SBVUnitTest/TestSuite/BitPrecise/Legato.hs b/SBVUnitTest/TestSuite/BitPrecise/Legato.hs
--- a/SBVUnitTest/TestSuite/BitPrecise/Legato.hs
+++ b/SBVUnitTest/TestSuite/BitPrecise/Legato.hs
@@ -23,7 +23,7 @@
    "legato-1" ~: legatoPgm `goldCheck` "legato.gold"
  , "legato-2" ~: legatoC `goldCheck` "legato_c.gold"
  ]
- where legatoPgm = runSymbolic (True, Nothing) $ do
+ where legatoPgm = runSAT $ do
                        mem     <- newArray "mem" Nothing
                        addrX   <- free "addrX"
                        x       <- free "x"
diff --git a/SBVUnitTest/TestSuite/BitPrecise/PrefixSum.hs b/SBVUnitTest/TestSuite/BitPrecise/PrefixSum.hs
--- a/SBVUnitTest/TestSuite/BitPrecise/PrefixSum.hs
+++ b/SBVUnitTest/TestSuite/BitPrecise/PrefixSum.hs
@@ -12,15 +12,13 @@
 module TestSuite.BitPrecise.PrefixSum(testSuite) where
 
 import Data.SBV
-import Data.SBV.Internals
 import Data.SBV.Examples.BitPrecise.PrefixSum
 
 import SBVTest
 
 -- Test suite
 testSuite :: SBVTestSuite
-testSuite = mkTestSuite $ \goldCheck -> test [
+testSuite = mkTestSuite $ \_ -> test [
     "prefixSum1" ~: assert =<< isThm (flIsCorrect  8 (0, (+)))
   , "prefixSum2" ~: assert =<< isThm (flIsCorrect 16 (0, smax))
-  , "prefixSum3" ~: runSymbolic (True, Nothing) (genPrefixSumInstance 16 >>= output) `goldCheck` "prefixSum_16.gold"
   ]
diff --git a/SBVUnitTest/TestSuite/CRC/CCITT.hs b/SBVUnitTest/TestSuite/CRC/CCITT.hs
--- a/SBVUnitTest/TestSuite/CRC/CCITT.hs
+++ b/SBVUnitTest/TestSuite/CRC/CCITT.hs
@@ -12,7 +12,6 @@
 module TestSuite.CRC.CCITT(testSuite) where
 
 import Data.SBV
-import Data.SBV.Internals
 
 import Examples.CRC.CCITT
 import SBVTest
@@ -22,4 +21,4 @@
 testSuite = mkTestSuite $ \goldCheck -> test [
   "ccitt" ~: crcPgm `goldCheck` "ccitt.gold"
  ]
- where crcPgm = runSymbolic (True, Nothing) $ forAll_ crcGood >>= output
+ where crcPgm = runSAT $ forAll_ crcGood >>= output
diff --git a/SBVUnitTest/TestSuite/CodeGeneration/Floats.hs b/SBVUnitTest/TestSuite/CodeGeneration/Floats.hs
new file mode 100644
--- /dev/null
+++ b/SBVUnitTest/TestSuite/CodeGeneration/Floats.hs
@@ -0,0 +1,164 @@
+-----------------------------------------------------------------------------
+-- |
+-- 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)
+          , test2 "fromFP_SFloat_SWord32"   (sFloatAsSWord32  :: SFloat  -> SWord32 -> SBool)
+          , test2 "fromFP_SDouble_SWord64"  (sDoubleAsSWord64 :: SDouble -> SWord64 -> SBool)
+
+          , 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/Existentials/CRCPolynomial.hs b/SBVUnitTest/TestSuite/Existentials/CRCPolynomial.hs
--- a/SBVUnitTest/TestSuite/Existentials/CRCPolynomial.hs
+++ b/SBVUnitTest/TestSuite/Existentials/CRCPolynomial.hs
@@ -12,7 +12,6 @@
 module TestSuite.Existentials.CRCPolynomial(testSuite) where
 
 import Data.SBV
-import Data.SBV.Internals
 import Data.SBV.Examples.Existentials.CRCPolynomial
 
 import SBVTest
@@ -22,7 +21,7 @@
 testSuite = mkTestSuite $ \goldCheck -> test [
   "crcPolyExist" ~: pgm `goldCheck` "crcPolyExist.gold"
  ]
- where pgm = runSymbolic (True, Nothing) $ do
+ where pgm = runSAT $ do
                 p <- exists "poly"
                 s <- do sh <- forall "sh"
                         sl <- forall "sl"
@@ -30,4 +29,4 @@
                 r <- do rh <- forall "rh"
                         rl <- forall "rl"
                         return (rh, rl)
-                output $ sbvTestBit p 0 &&& crcGood 4 p s r
+                output $ sTestBit p 0 &&& crcGood 4 p s r
diff --git a/SBVUnitTest/TestSuite/Puzzles/Coins.hs b/SBVUnitTest/TestSuite/Puzzles/Coins.hs
--- a/SBVUnitTest/TestSuite/Puzzles/Coins.hs
+++ b/SBVUnitTest/TestSuite/Puzzles/Coins.hs
@@ -12,7 +12,6 @@
 module TestSuite.Puzzles.Coins(testSuite) where
 
 import Data.SBV
-import Data.SBV.Internals
 import Data.SBV.Examples.Puzzles.Coins
 
 import SBVTest
@@ -22,8 +21,7 @@
 testSuite = mkTestSuite $ \goldCheck -> test [
   "coins" ~: coinsPgm `goldCheck` "coins.gold"
  ]
- where coinsPgm = runSymbolic (True, Nothing) $ 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
+ 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
--- a/SBVUnitTest/TestSuite/Puzzles/Counts.hs
+++ b/SBVUnitTest/TestSuite/Puzzles/Counts.hs
@@ -12,7 +12,6 @@
 module TestSuite.Puzzles.Counts(testSuite) where
 
 import Data.SBV
-import Data.SBV.Internals
 import Data.SBV.Examples.Puzzles.Counts
 
 import SBVTest
@@ -22,5 +21,5 @@
 testSuite = mkTestSuite $ \goldCheck -> test [
   "counts" ~: countPgm `goldCheck` "counts.gold"
  ]
- where countPgm = runSymbolic (True, Nothing) $ forAll_ puzzle' >>= output
+ 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/Uninterpreted/AUF.hs b/SBVUnitTest/TestSuite/Uninterpreted/AUF.hs
--- a/SBVUnitTest/TestSuite/Uninterpreted/AUF.hs
+++ b/SBVUnitTest/TestSuite/Uninterpreted/AUF.hs
@@ -12,7 +12,6 @@
 module TestSuite.Uninterpreted.AUF where
 
 import Data.SBV
-import Data.SBV.Internals
 import Data.SBV.Examples.Uninterpreted.AUF
 
 import SBVTest
@@ -24,7 +23,7 @@
  , "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 = runSymbolic (True, Nothing) $ do
+ where pgm = runSAT $ do
                 x <- free "x"
                 y <- free "y"
                 a <- newArray "a" Nothing
diff --git a/SBVUnitTest/TestSuite/Uninterpreted/Axioms.hs b/SBVUnitTest/TestSuite/Uninterpreted/Axioms.hs
--- a/SBVUnitTest/TestSuite/Uninterpreted/Axioms.hs
+++ b/SBVUnitTest/TestSuite/Uninterpreted/Axioms.hs
@@ -9,7 +9,9 @@
 -- Test suite for basic axioms and uninterpreted functions
 -----------------------------------------------------------------------------
 
+{-# LANGUAGE DeriveAnyClass     #-}
 {-# LANGUAGE DeriveDataTypeable #-}
+
 module TestSuite.Uninterpreted.Axioms(testSuite) where
 
 import Data.SBV
@@ -23,9 +25,7 @@
  ]
 
 -- Example provided by Thomas DuBuisson:
-data Bitstring = Bitstring () deriving (Eq, Ord, Data, Typeable, Read, Show)
-instance SymWord Bitstring
-instance HasKind Bitstring
+data Bitstring = Bitstring () deriving (Eq, Ord, Show, Read, Data, SymWord, HasKind)
 type SBitstring = SBV Bitstring
 
 a :: SBitstring -> SBool
diff --git a/SBVUnitTest/TestSuite/Uninterpreted/Function.hs b/SBVUnitTest/TestSuite/Uninterpreted/Function.hs
--- a/SBVUnitTest/TestSuite/Uninterpreted/Function.hs
+++ b/SBVUnitTest/TestSuite/Uninterpreted/Function.hs
@@ -18,6 +18,5 @@
 -- Test suite
 testSuite :: SBVTestSuite
 testSuite = mkTestSuite $ \_ -> test [
-   "aufunc-0" ~: assert       =<< isThm thmGood
- , "aufunc-1" ~: assert . not =<< isThm thmBad
+   "aufunc-0" ~: assert =<< isThm thmGood
  ]
diff --git a/SBVUnitTest/TestSuite/Uninterpreted/Sort.hs b/SBVUnitTest/TestSuite/Uninterpreted/Sort.hs
--- a/SBVUnitTest/TestSuite/Uninterpreted/Sort.hs
+++ b/SBVUnitTest/TestSuite/Uninterpreted/Sort.hs
@@ -11,6 +11,7 @@
 
 {-# LANGUAGE DeriveDataTypeable  #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+
 module TestSuite.Uninterpreted.Sort where
 
 import Data.SBV
@@ -23,7 +24,7 @@
   "unint-sort" ~: assert . (==4) . length . (extractModels :: AllSatResult -> [L]) =<< allSat p0
  ]
 
-data L = Nil | Cons Int L deriving (Eq, Ord, Data, Typeable, Read, Show)
+data L = Nil | Cons Int L deriving (Eq, Ord, Data, Read, Show)
 instance SymWord L
 instance HasKind L
 instance SatModel L where
diff --git a/sbv.cabal b/sbv.cabal
--- a/sbv.cabal
+++ b/sbv.cabal
@@ -1,5 +1,5 @@
 Name:          sbv
-Version:       4.4
+Version:       5.0
 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
@@ -30,6 +30,7 @@
   other-extensions: BangPatterns
                     DefaultSignatures
                     DeriveDataTypeable
+                    DeriveAnyClass
                     FlexibleContexts
                     FlexibleInstances
                     FunctionalDependencies
@@ -60,6 +61,7 @@
                   , 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
@@ -73,16 +75,18 @@
                   , Data.SBV.Examples.Existentials.Diophantine
                   , Data.SBV.Examples.Misc.Enumerate
                   , Data.SBV.Examples.Misc.Floating
-                  , Data.SBV.Examples.Misc.SBranch
                   , Data.SBV.Examples.Misc.ModelExtract
                   , 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
@@ -98,8 +102,7 @@
                   , Data.SBV.BitVectors.Model
                   , Data.SBV.BitVectors.Operations
                   , Data.SBV.BitVectors.PrettyNum
-                  , Data.SBV.BitVectors.Rounding
-                  , Data.SBV.BitVectors.SignCast
+                  , Data.SBV.BitVectors.Floating
                   , Data.SBV.BitVectors.Splittable
                   , Data.SBV.BitVectors.STree
                   , Data.SBV.BitVectors.Symbolic
@@ -107,7 +110,6 @@
                   , Data.SBV.Compilers.CodeGen
                   , Data.SBV.SMT.SMT
                   , Data.SBV.SMT.SMTLib
-                  , Data.SBV.SMT.SMTLib1
                   , Data.SBV.SMT.SMTLib2
                   , Data.SBV.Provers.Prover
                   , Data.SBV.Provers.SExpr
@@ -122,6 +124,7 @@
                   , Data.SBV.Tools.Optimize
                   , Data.SBV.Tools.Polynomial
                   , Data.SBV.Utils.Boolean
+                  , Data.SBV.Utils.Numeric
                   , Data.SBV.Utils.TDiff
                   , Data.SBV.Utils.Lib
 
@@ -133,7 +136,7 @@
                     ScopedTypeVariables
                     TupleSections
   Build-depends   : base  >= 4 && < 5
-                  , HUnit, directory, filepath, process, syb, sbv
+                  , HUnit, directory, filepath, process, syb, sbv, data-binary-ieee754
   Hs-Source-Dirs  : SBVUnitTest
   main-is         : SBVUnitTest.hs
   Other-modules   : SBVUnitTestBuildTime
@@ -170,6 +173,7 @@
                   , TestSuite.CodeGeneration.CgTests
                   , TestSuite.CodeGeneration.CRC_USB5
                   , TestSuite.CodeGeneration.Fibonacci
+                  , TestSuite.CodeGeneration.Floats
                   , TestSuite.CodeGeneration.GCD
                   , TestSuite.CodeGeneration.PopulationCount
                   , TestSuite.CodeGeneration.Uninterpreted
@@ -203,7 +207,7 @@
   default-language: Haskell2010
   ghc-options     : -Wall -with-rtsopts=-K64m
   Build-depends   : base >= 4 && < 5
-                  , HUnit, directory, filepath, syb, sbv
+                  , HUnit, directory, filepath, syb, sbv, data-binary-ieee754
   Hs-Source-Dirs  : SBVUnitTest
   main-is         : SBVBasicTests.hs
   Other-modules   : SBVBasicTests
