commit b9f341b63f4d19b5ad8d13aaa008393a0b51accc
Author: David Sorber <david.sorber@gmail.com>
Date:   Thu Mar 31 18:29:52 2022 -0400

    Adding fixed point type changes from a few weeks ago. This includes
    significantly expanded tests.

diff --git a/software/fixed/fixed.h b/software/fixed/fixed.h
index bb6c24a..9e275e8 100644
--- a/software/fixed/fixed.h
+++ b/software/fixed/fixed.h
@@ -27,6 +27,15 @@
 #define __likely(cond)   (cond)
 #endif
 
+// Defaults for compile time options
+#ifndef BEHAVIOR_PARSE_TRUNCATE
+#define BEHAVIOR_PARSE_TRUNCATE     0   // Default: disable
+#endif
+
+#ifndef SUPPORT_PARSE_EXPONENT
+#define SUPPORT_PARSE_EXPONENT      1   // Default: enable
+#endif
+
 template<typename T>
 constexpr T calculateMax(size_t decimal_digits)
 {
@@ -64,6 +73,8 @@ public:
         std::floor(std::log10(std::numeric_limits<IntegerType>::max()));
     static constexpr size_t fractional_decimal_digits =
         std::floor(std::log10(std::numeric_limits<FractionalType>::max()));
+    static constexpr size_t total_decimal_digits = integer_decimal_digits + 
+                                                   fractional_decimal_digits;
 
     static constexpr IntegerType MAX_INTEGER_VALUE = 
         (calculateMax<IntegerType>(integer_decimal_digits));
@@ -73,21 +84,23 @@ public:
         (calculateMax<FractionalType>(fractional_decimal_digits));
     static constexpr FractionalType MIN_FRACTIONAL_VALUE = 0;
 
+    static constexpr IntegerType NEGATIVE_ZERO = MAX_INTEGER_VALUE + 2;
+
     static const uint64_t SCALE_VALUES[20];
     static const std::map<uint64_t, uint32_t> DIGIT_LOOKUP_TABLE;
 
     // Constructors
-    fixed()
+    explicit fixed()
         : m_integer(0),
           m_fractional(0)
     {}
 
-    fixed(IntegerType integerVal)
+    explicit fixed(IntegerType integerVal)
         : m_integer(__checkIntOverflow(integerVal)),
           m_fractional(0)
     {}
 
-    fixed(IntegerType integerVal, FractionalType fractionalVal)
+    explicit fixed(IntegerType integerVal, FractionalType fractionalVal)
         : m_integer(__checkIntOverflow(integerVal)),
           m_fractional(__checkFracOverflow(fractionalVal))
     {
@@ -96,7 +109,7 @@ public:
                                            getFracScaleValue(m_fractional));
     }
     
-    fixed(IntegerType integerVal, FractionalType fractionalVal, uint32_t leadingZeros)
+    explicit fixed(IntegerType integerVal, FractionalType fractionalVal, uint32_t leadingZeros)
         : m_integer(__checkIntOverflow(integerVal)),
           m_fractional(__checkFracOverflow(fractionalVal))
     {
@@ -141,34 +154,225 @@ public:
         char* endPtr = nullptr;
         m_integer = __checkIntOverflow(strto_inttype(input, &endPtr, 10));
         m_fractional = 0;
+        bool negativeZeroFlag = false;
 
         if (std::isdigit(*endPtr))
         {
             throw std::out_of_range("Integer value is out of range.");
         }
+        
+        // Check for negative zero corner case with leading zero digit
+        if (__unlikely(m_integer == 0 && endPtr - input >= 2 && *(endPtr - 2) == '-'))
+        {
+            negativeZeroFlag = true;
+        }
 
         // If the ending char is a period we can now parse the fractional part
-        if (*endPtr == '.')
+        uint32_t fracLen = 0;        
+        if (*endPtr == '.'|| (endPtr[0] == '-' && endPtr[1] == '.'))
         {
+            // Check for negative zero corner case without leading zero digit
+            if (__unlikely(endPtr[0] == '-'))
+            {
+                ++endPtr;
+                negativeZeroFlag = true;
+            }
+            
             char* fracEndPtr = nullptr;
             FractionalType fracTemp =
                 __checkFracOverflow(strto_fractype(endPtr + 1, &fracEndPtr, 10));
                 
-            uint32_t fracLen = (fracEndPtr - endPtr) - 1;
-            fracLen = fractional_decimal_digits - fracLen;
-
-            m_fractional = __checkFracOverflow(fracTemp * SCALE_VALUES[fracLen]);
+            fracLen = (fracEndPtr - endPtr) - 1;
+            if (__unlikely(fracLen > fractional_decimal_digits))
+            {
+#if BEHAVIOR_PARSE_TRUNCATE
+                // Fractional length exceeds supported number of fractional
+                // decimal digits, downscale value to only include supported 
+                // number of digits
+                uint32_t idx = fracLen - fractional_decimal_digits;
+                m_fractional = fracTemp / SCALE_VALUES[idx];
+#else
+                throw std::out_of_range("Fractional length exceeds supported "
+                                        "number of fractional decimal digits.");
+#endif
+            }
+            else
+            {
+                uint32_t idx = fractional_decimal_digits - fracLen;
+                m_fractional = __checkFracOverflow(fracTemp * SCALE_VALUES[idx]);
+            }
             endPtr = fracEndPtr;
         }
         
+#if SUPPORT_PARSE_EXPONENT
+        // Attempt to parse exponent
+        if (*endPtr == 'e' || *endPtr == 'E')
+        {
+            // Set negative zero flag here if integer part is negative then
+            // clear below if final integer part after exponent adjustment is
+            // not zero
+            if (m_integer < 0)
+            {
+                negativeZeroFlag = true;
+            }
+            
+            char* expEndPtr = nullptr;
+            long exponent = strtol(++endPtr, &expEndPtr, 10);
+            uint32_t integerLen = 0;
+            if (m_integer != 0)
+            {
+                integerLen = DIGIT_LOOKUP_TABLE.upper_bound(std::abs(m_integer))->second;
+            }
+            uint32_t scaledFracLen = 
+                DIGIT_LOOKUP_TABLE.upper_bound(m_fractional)->second;
+            
+            if (exponent >= 0)
+            {
+                // Detect potential overflow based on the exponent
+                if ((m_integer != 0)  && 
+                    (integerLen + static_cast<size_t>(exponent)) > 
+                     integer_decimal_digits)
+                {
+                    throw std::out_of_range("Positive exponent exceeds maximum"
+                                            " decimal digit range.");
+                }
+                else if (scaledFracLen + static_cast<size_t>(exponent)
+                         > total_decimal_digits)
+                {
+                    throw std::out_of_range("Positive exponent exceeds maximum"
+                                            " decimal digit range (2).");
+                }
+                
+                long fracExponent = exponent;
+                if (static_cast<size_t>(fracExponent) > fractional_decimal_digits)
+                {
+                    fracExponent = fractional_decimal_digits;
+                }
+                
+                bool intZeroFlag = true;
+                if (m_integer != 0)
+                {
+                    // Rescale integer value if it is greater than zero
+                    intZeroFlag = false;
+                    m_integer *= static_cast<IntegerType>(SCALE_VALUES[exponent]);
+                }
+                
+                uint64_t scaler = SCALE_VALUES[fractional_decimal_digits - 
+                                               fracExponent];
+                IntegerType temp = m_fractional / scaler;
+                m_integer += temp;
+                m_fractional -= (temp * scaler);
+                m_fractional *= SCALE_VALUES[fracExponent];
+                
+                if (intZeroFlag)
+                {
+                    // Rescale integer value if it was zero
+                    m_integer *= SCALE_VALUES[exponent - fracExponent];
+                }
+            }
+            else
+            {
+                // Handle negative exponent
+                // Detect potential overflow based on the exponent
+                if (m_fractional != 0 && 
+                    (static_cast<size_t>(-exponent) > 
+                     (fractional_decimal_digits - fracLen)))
+                {
+                    throw std::out_of_range("Negative exponent exceeds maximum"
+                                            " decimal digit range.");
+                }
+                else if (static_cast<size_t>(-exponent) >= 
+                         (integerLen + fractional_decimal_digits))
+                {
+                    throw std::out_of_range("Negative exponent exceeds maximum"
+                                            " decimal digit range.");
+                }
+
+                FractionalType temp = 0;
+                if (m_fractional != 0)
+                {
+                    // CASE 1: fractional non-zero
+                    m_fractional /= SCALE_VALUES[-exponent];
+                    temp = std::abs(m_integer) % SCALE_VALUES[-exponent];
+                    temp *= SCALE_VALUES[fractional_decimal_digits + exponent];
+                    m_integer /= static_cast<IntegerType>(SCALE_VALUES[-exponent]);
+                    m_fractional += temp;
+                }
+                else
+                {
+                    // CASE 2: fractional zero
+                    long intExponent = std::abs(exponent);
+                    if (static_cast<size_t>(intExponent) > integer_decimal_digits)
+                    {
+                        intExponent = integer_decimal_digits;
+                    }
+                    
+                    temp = std::abs(m_integer) % SCALE_VALUES[intExponent];
+                    temp *= SCALE_VALUES[fractional_decimal_digits - intExponent];
+                    m_integer /= SCALE_VALUES[intExponent];
+                    m_fractional += temp;
+                    
+                    if (std::abs(exponent) > intExponent)
+                    {
+                        long fracExponent = std::abs(exponent) - intExponent;
+                        m_fractional /= SCALE_VALUES[fracExponent];
+                    }
+                }
+            }
+        
+            // Clear negative zero flag if final adjusted integer part is not
+            // zero. Flag will remain set iff initial integer part was negative
+            // and integer part after exponent adjustment is zero.
+            if (__likely(m_integer != 0))
+            {
+                negativeZeroFlag = false;
+            }
+        }
+
+#endif
+        if (__unlikely(negativeZeroFlag))
+        {
+            m_integer = NEGATIVE_ZERO;
+        }
+
         // Calculate and return overall length
         return (endPtr - input);
     }
 
-    void absval()
+    constexpr inline void absval()
     {
-        m_integer = abs(m_integer);
+        if (__unlikely(m_integer == NEGATIVE_ZERO))
+        {
+            m_integer = 0;
+        }
+        else
+        {
+            m_integer = std::abs(m_integer);
+        }
+    }
+    
+    // This is modeled after std::signbit() for floating point types
+    constexpr inline bool signbit() const
+    {
+        return (m_integer < 0 || m_integer == NEGATIVE_ZERO);
+    }
+    
+    constexpr inline void negate()
+    {
+        if (__unlikely(m_integer == 0))
+        {
+            m_integer = NEGATIVE_ZERO;
+        }
+        else
+        {
+            m_integer *= -1;
+        }
     }
+    
+    // Disallow conversion operators (for now)
+    explicit operator int() = delete;
+    explicit operator float() = delete;
+    explicit operator double() = delete;
 
     constexpr inline fixed operator-() const noexcept = delete;
     constexpr inline fixed operator!() const noexcept = delete;
@@ -206,7 +410,7 @@ public:
     // Divide by unsigned int
     template<typename I, typename F, typename STI, typename STF>
     friend constexpr inline fixed<I, F, STI, STF> operator/(
-        const fixed<I, F, STI, STF>& x, const uint64_t& y);
+        const fixed<I, F, STI, STF>& x, const int64_t& y);
 
     // Output stream operator
     template<typename I, typename F, typename STI, typename STF>
@@ -243,7 +447,6 @@ private:
         return fractionalVal;
     }
     
-public:
     // Helper function to get the approprate scale value for an unscaled input
     // value of the fractional type
     static inline FractionalType getFracScaleValue(
@@ -256,7 +459,6 @@ public:
         return SCALE_VALUES[index];
     }
 
-public:
     IntegerType m_integer;
     FractionalType m_fractional;
 };
@@ -366,15 +568,38 @@ template<typename I, typename F, typename STI, typename STF>
 constexpr inline bool operator<(
     const fixed<I, F, STI, STF>& x, const fixed<I, F, STI, STF>& y) noexcept
 {
-    if (x.m_integer == y.m_integer)
+    if (x.signbit() && (! y.signbit()))
     {
-        return (x.m_fractional < y.m_fractional);
+        return true;
+    }
+    else if ((! x.signbit()) && y.signbit())
+    {
+        return false;
     }
     else
     {
-        return (x.m_integer < y.m_integer);
+        I integerX = x.m_integer;
+        if (__unlikely((x.m_integer == fixed<I, F, STI, STF>::NEGATIVE_ZERO)))
+        {
+            integerX = 0;
+        }
+        
+        I integerY = y.m_integer;
+        if (__unlikely((y.m_integer == fixed<I, F, STI, STF>::NEGATIVE_ZERO)))
+        {
+            integerY = 0;
+        }
+        
+        if (integerX == integerY)
+        {
+            return (x.m_fractional < y.m_fractional);
+        }
+        else
+        {
+            return (integerX < integerY);
+        }
     }
-
+    
     return false;
 }
 
@@ -382,15 +607,38 @@ template<typename I, typename F, typename STI, typename STF>
 constexpr inline bool operator>(
     const fixed<I, F, STI, STF>& x, const fixed<I, F, STI, STF>& y) noexcept
 {
-    if (x.m_integer == y.m_integer)
+    if (x.signbit() && (! y.signbit()))
+    {
+        return false;
+    }
+    else if ((! x.signbit()) && y.signbit())
     {
-        return (x.m_fractional > y.m_fractional);
+        return true;
     }
     else
     {
-        return (x.m_integer > y.m_integer);
+        I integerX = x.m_integer;
+        if (__unlikely((x.m_integer == fixed<I, F, STI, STF>::NEGATIVE_ZERO)))
+        {
+            integerX = 0;
+        }
+        
+        I integerY = y.m_integer;
+        if (__unlikely((y.m_integer == fixed<I, F, STI, STF>::NEGATIVE_ZERO)))
+        {
+            integerY = 0;
+        }
+        
+        if (integerX == integerY)
+        {
+            return (x.m_fractional > y.m_fractional);
+        }
+        else
+        {
+            return (integerX > integerY);
+        }
     }
-
+    
     return false;
 }
 
@@ -398,32 +646,14 @@ template<typename I, typename F, typename STI, typename STF>
 constexpr inline bool operator<=(
     const fixed<I, F, STI, STF>& x, const fixed<I, F, STI, STF>& y) noexcept
 {
-    if (x.m_integer == y.m_integer)
-    {
-        return (x.m_fractional <= y.m_fractional);
-    }
-    else
-    {
-        return (x.m_integer < y.m_integer);
-    }
-
-    return false;
+    return (x == y || x < y);
 }
 
 template<typename I, typename F, typename STI, typename STF>
 constexpr inline bool operator>=(
     const fixed<I, F, STI, STF>& x, const fixed<I, F, STI, STF>& y) noexcept
 {
-    if (x.m_integer == y.m_integer)
-    {
-        return (x.m_fractional >= y.m_fractional);
-    }
-    else
-    {
-        return (x.m_integer > y.m_integer);
-    }
-
-    return false;
+    return (x == y || x > y);
 }
 
 // Addition -- not yet supported
@@ -449,15 +679,38 @@ constexpr inline fixed<I, F, STI, STF> operator/(
 // Division by unsigned int
 template<typename I, typename F, typename STI, typename STF>
 constexpr inline fixed<I, F, STI, STF> operator/(
-     const fixed<I, F, STI, STF>& x, const uint64_t& y)
+     const fixed<I, F, STI, STF>& x, const int64_t& y)
+{
+    fixed<I, F, STI, STF> newVal;
+    bool negativeDivisorFlag = (y < 0);
+    bool negativeDividendFlag = (x.m_integer < 0) || 
+                                (x.m_integer == fixed<I, F, STI, STF>::NEGATIVE_ZERO);
+    bool negativeZeroFlag = false;
+    I integerX = x.m_integer;
+    if (__unlikely((integerX == fixed<I, F, STI, STF>::NEGATIVE_ZERO)))
+    {
+        integerX = 0;
+        negativeZeroFlag = true;
+    }
+    
+    newVal.m_integer = integerX / y;
+    newVal.m_fractional = std::abs(integerX) % y;
+    newVal.m_fractional *= x.getFracScaleValue(newVal.m_fractional);
+    newVal.m_fractional += x.m_fractional / std::abs(y);
+    
+    // Ensure quotient has correct sign value
+    if (newVal.m_integer == 0 && negativeDividendFlag && negativeDivisorFlag)
+    {
+        newVal.m_integer = 0;
+    }
+    else if ((newVal.m_integer == 0 && (negativeDividendFlag || negativeDivisorFlag))
+              || __unlikely(negativeZeroFlag))
     {
-        fixed<I, F, STI, STF> newVal;
-        newVal.m_integer = x.m_integer / y;
-        newVal.m_fractional = x.m_integer % y;
-        newVal.m_fractional *= x.getFracScaleValue(newVal.m_fractional);
-        newVal.m_fractional += x.m_fractional / y;
-        return newVal;
+        newVal.m_integer = fixed<I, F, STI, STF>::NEGATIVE_ZERO;
     }
+    
+    return newVal;
+}
 
 // Stream output
 template<typename I, typename F, typename STI, typename STF>
@@ -485,17 +738,27 @@ inline std::ostream& operator<<(std::ostream& os, const fixed<I, F, STI, STF>& r
             break;
         }
     }
-    if (found)
+    if (found || idx == -1)
     {
         buffer[idx + 1] = '\0';
     }
     
-    uint32_t leadingZeros = 
+    uint32_t leadingZeros = (rhs.m_fractional == 0) ? 1 : 
         fixed<I, F, STI, STF>::fractional_decimal_digits - 
         fixed<I, F, STI, STF>::DIGIT_LOOKUP_TABLE.upper_bound(rhs.m_fractional)->second;
+        
+    // Handle special case of negative zero
+    os << std::fixed;
+    if (__unlikely((rhs.m_integer == fixed<I, F, STI, STF>::NEGATIVE_ZERO)))
+    {
+        os << "-0.";
+    }
+    else
+    {
+        os << rhs.m_integer << ".";
+    }
     
-    // Output any leading zeros
-    os << std::fixed << rhs.m_integer << ".";
+    // Output any fractional leading zeros
     for (uint32_t idx = 0; idx < leadingZeros; ++idx)
     {
         os << "0";
diff --git a/software/fixed/fixed_test.cc b/software/fixed/fixed_test.cc
index 103806d..90be60a 100644
--- a/software/fixed/fixed_test.cc
+++ b/software/fixed/fixed_test.cc
@@ -2,6 +2,7 @@
 #include <cstdint>
 #include <limits>
 #include <random>
+#include <stdexcept>
 #include <sstream>
 #include <string>
 #include <vector>
@@ -11,7 +12,32 @@
 
 #include "fixed.h"
 
-BOOST_AUTO_TEST_CASE(t0)
+// Helper macros
+#define VALUE_CHECK(val)                    \
+    output.str("");                         \
+    output << value;                        \
+    BOOST_CHECK(output.str() == val);
+
+#define PARSE_VALUE_CHECK(val)              \
+    value.parse(input);                     \
+    output.str("");                         \
+    output << value;                        \
+    BOOST_CHECK(output.str() == val);
+
+
+#define PARSE_EXCEPTION_CHECK               \
+    exception = false;                      \
+    try                                     \
+    {                                       \
+        value.parse(input);                 \
+    }                                       \
+    catch (const std::out_of_range& exp)    \
+    {                                       \
+        exception = true;                   \
+    }                                       \
+    BOOST_CHECK(exception);
+
+BOOST_AUTO_TEST_CASE(t000)
 {
     /* TEST CASE 0: Check storage sizes (in bytes) of all predefined fixed 
      * point types.
@@ -53,7 +79,7 @@ BOOST_AUTO_TEST_CASE(t0)
     BOOST_CHECK(sizeof(f_64_64) == 16);
 }
 
-BOOST_AUTO_TEST_CASE(t1)
+BOOST_AUTO_TEST_CASE(t001)
 {
     /* TEST CASE 1: Test basic comparisons
      */ 
@@ -77,7 +103,7 @@ BOOST_AUTO_TEST_CASE(t1)
     BOOST_CHECK(! (val1 <= val2));
 }
 
-BOOST_AUTO_TEST_CASE(t2)
+BOOST_AUTO_TEST_CASE(t002)
 {
     /* TEST CASE 2: Test parsing with leading zeros.
      */ 
@@ -180,7 +206,7 @@ BOOST_AUTO_TEST_CASE(t2)
     BOOST_CHECK(val1 == val2);
 }
 
-BOOST_AUTO_TEST_CASE(t3)
+BOOST_AUTO_TEST_CASE(t003)
 {
     /* TEST CASE 3: Test parsing and printing randomly generated values
      */ 
@@ -193,6 +219,7 @@ BOOST_AUTO_TEST_CASE(t3)
     std::mt19937 rng;
     rng.seed(SEED);
     
+    std::uniform_int_distribution<std::mt19937::result_type> negative(0, 1);
     std::uniform_int_distribution<std::mt19937::result_type> intDigits(1, theType::integer_decimal_digits);
     std::uniform_int_distribution<std::mt19937::result_type> fracDigits(1, theType::fractional_decimal_digits);
     std::uniform_int_distribution<std::mt19937::result_type> digits(0, 9);
@@ -202,6 +229,13 @@ BOOST_AUTO_TEST_CASE(t3)
     for (uint32_t idx = 0; idx < NUMBER; ++idx)
     {
         std::ostringstream output;
+        
+        // Decide if the number should be negative
+        if (negative(rng) == 1)
+        {
+            output << "-";
+        }
+        
         // Generate random integer number digits
         for (uint32_t integerIdx = 0; integerIdx < intDigits(rng); ++integerIdx)
         {
@@ -222,7 +256,7 @@ BOOST_AUTO_TEST_CASE(t3)
         output << ".";
         
         // Generate random fractional number digits
-        int numFracDigits = fracDigits(rng);
+        uint32_t numFracDigits = fracDigits(rng);
         for (uint32_t fracIdx = 0; fracIdx < numFracDigits; ++fracIdx)
         {
             int digit = digits(rng);
@@ -257,7 +291,7 @@ BOOST_AUTO_TEST_CASE(t3)
     }
 }
 
-BOOST_AUTO_TEST_CASE(t4)
+BOOST_AUTO_TEST_CASE(t004)
 {
     /* TEST CASE 4: Basic test division by unsigned integer
      */ 
@@ -268,4 +302,1510 @@ BOOST_AUTO_TEST_CASE(t4)
     BOOST_CHECK(answer == val2);
 }
 
+BOOST_AUTO_TEST_CASE(t005)
+{
+    /* TEST CASE 5: Test parsing a decimal number with a larger than supported
+     * fractional part.
+     */ 
+     
+    const char* input = ".00010102030508132134";
+
+    fixed_64_64 value;
+#if 0
+    value.parse(input);
+    
+    std::ostringstream output;
+    output << value;
+    
+    BOOST_CHECK(output.str() == "0.0001010203050813213");
+#else
+    bool exception = false;
+    try
+    {
+        value.parse(input);
+    }
+    catch (const std::out_of_range& exp)
+    {
+        exception = true;
+    }
+    BOOST_CHECK(exception);
+#endif
+}
+
+BOOST_AUTO_TEST_CASE(t006)
+{
+    /* TEST CASE 6: zero integer, positive exponent, walking one positive test 
+     * cases
+     */ 
+    fixed_64_64 value;
+    std::ostringstream output;
+     
+    const char* input = "0.0000000000000000001e36";
+    PARSE_VALUE_CHECK("100000000000000000.0");
+    
+    input = "0.0000000000000000001e35";
+    PARSE_VALUE_CHECK("10000000000000000.0");
+    
+    input = "0.0000000000000000001e34";
+    PARSE_VALUE_CHECK("1000000000000000.0");
+    
+    input = "0.0000000000000000001e33";
+    PARSE_VALUE_CHECK("100000000000000.0");
+    
+    input = "0.0000000000000000001e32";
+    PARSE_VALUE_CHECK("10000000000000.0");
+    
+    input = "0.0000000000000000001e31";
+    PARSE_VALUE_CHECK("1000000000000.0");
+    
+    input = "0.0000000000000000001e30";
+    PARSE_VALUE_CHECK("100000000000.0");
+    
+    input = "0.0000000000000000001e29";
+    PARSE_VALUE_CHECK("10000000000.0");
+    
+    input = "0.0000000000000000001e28";
+    PARSE_VALUE_CHECK("1000000000.0");
+    
+    input = "0.0000000000000000001e27";
+    PARSE_VALUE_CHECK("100000000.0");
+    
+    input = "0.0000000000000000001e26";
+    PARSE_VALUE_CHECK("10000000.0");
+    
+    input = "0.0000000000000000001e25";
+    PARSE_VALUE_CHECK("1000000.0");
+    
+    input = "0.0000000000000000001e24";
+    PARSE_VALUE_CHECK("100000.0");
+    
+    input = "0.0000000000000000001e23";
+    PARSE_VALUE_CHECK("10000.0");
+    
+    input = "0.0000000000000000001e22";
+    PARSE_VALUE_CHECK("1000.0");
+    
+    input = "0.0000000000000000001e21";
+    PARSE_VALUE_CHECK("100.0");
+    
+    input = "0.0000000000000000001e20";
+    PARSE_VALUE_CHECK("10.0");
+    
+    input = "0.0000000000000000001e19";
+    PARSE_VALUE_CHECK("1.0");
+    
+    // Cross over
+    input = "0.0000000000000000001e18";
+    PARSE_VALUE_CHECK("0.1");
+    
+    input = "0.0000000000000000001e17";
+    PARSE_VALUE_CHECK("0.01");
+    
+    input = "0.0000000000000000001e16";
+    PARSE_VALUE_CHECK("0.001");
+    
+    input = "0.0000000000000000001e15";
+    PARSE_VALUE_CHECK("0.0001");
+    
+    input = "0.0000000000000000001e14";
+    PARSE_VALUE_CHECK("0.00001");
+    
+    input = "0.0000000000000000001e13";
+    PARSE_VALUE_CHECK("0.000001");
+    
+    input = "0.0000000000000000001e12";
+    PARSE_VALUE_CHECK("0.0000001");
+    
+    input = "0.0000000000000000001e11";
+    PARSE_VALUE_CHECK("0.00000001");
+    
+    input = "0.0000000000000000001e10";
+    PARSE_VALUE_CHECK("0.000000001");
+    
+    input = "0.0000000000000000001e9";
+    PARSE_VALUE_CHECK("0.0000000001");
+    
+    input = "0.0000000000000000001e8";
+    PARSE_VALUE_CHECK("0.00000000001");
+    
+    input = "0.0000000000000000001e7";
+    PARSE_VALUE_CHECK("0.000000000001");
+    
+    input = "0.0000000000000000001e6";
+    PARSE_VALUE_CHECK("0.0000000000001");
+    
+    input = "0.0000000000000000001e5";
+    PARSE_VALUE_CHECK("0.00000000000001");
+    
+    input = "0.0000000000000000001e4";
+    PARSE_VALUE_CHECK("0.000000000000001");
+    
+    input = "0.0000000000000000001e3";
+    PARSE_VALUE_CHECK("0.0000000000000001");
+    
+    input = "0.0000000000000000001e2";
+    PARSE_VALUE_CHECK("0.00000000000000001");
+    
+    input = "0.0000000000000000001e1";
+    PARSE_VALUE_CHECK("0.000000000000000001");
+    
+    input = "0.0000000000000000001e0";
+    PARSE_VALUE_CHECK("0.0000000000000000001");
+}
+
+BOOST_AUTO_TEST_CASE(t007)
+{
+    /* TEST CASE 7: non-zero integer, positive exponent, walking value 
+     * positive+negative test cases
+     */ 
+    fixed_64_64 value;
+    std::ostringstream output;
+     
+    const char* input = "1.0000000000000000001e1";
+    PARSE_VALUE_CHECK("10.000000000000000001");
+    
+    input = "1.0000000000000000001e2";
+    PARSE_VALUE_CHECK("100.00000000000000001");
+    
+    input = "1.0000000000000000001e3";
+    PARSE_VALUE_CHECK("1000.0000000000000001");
+    
+    input = "1.0000000000000000001e4";
+    PARSE_VALUE_CHECK("10000.000000000000001");
+    
+    input = "1.0000000000000000001e5";
+    PARSE_VALUE_CHECK("100000.00000000000001");
+    
+    input = "1.0000000000000000001e6";
+    PARSE_VALUE_CHECK("1000000.0000000000001");
+    
+    input = "1.0000000000000000001e7";
+    PARSE_VALUE_CHECK("10000000.000000000001");
+    
+    input = "1.0000000000000000001e8";
+    PARSE_VALUE_CHECK("100000000.00000000001");
+    
+    input = "1.0000000000000000001e9";
+    PARSE_VALUE_CHECK("1000000000.0000000001");
+    
+    input = "1.0000000000000000001e10";
+    PARSE_VALUE_CHECK("10000000000.000000001");
+    
+    input = "1.0000000000000000001e11";
+    PARSE_VALUE_CHECK("100000000000.00000001");
+    
+    input = "1.0000000000000000001e12";
+    PARSE_VALUE_CHECK("1000000000000.0000001");
+    
+    input = "1.0000000000000000001e13";
+    PARSE_VALUE_CHECK("10000000000000.000001");
+    
+    input = "1.0000000000000000001e14";
+    PARSE_VALUE_CHECK("100000000000000.00001");
+    
+    input = "1.0000000000000000001e15";
+    PARSE_VALUE_CHECK("1000000000000000.0001");
+    
+    input = "1.0000000000000000001e16";
+    PARSE_VALUE_CHECK("10000000000000000.001");
+    
+    input = "1.0000000000000000001e17";
+    PARSE_VALUE_CHECK("100000000000000000.01");
+    
+    input = "1.0000000000000000001e18";
+    bool exception = false;
+    PARSE_EXCEPTION_CHECK
+}
+
+BOOST_AUTO_TEST_CASE(t008)
+{
+    /* TEST CASE 8: zero integer, positive exponent, walking one negative test 
+     * cases
+     */ 
+    fixed_64_64 value;
+    std::ostringstream output;
+     
+    const char* input = "0.0000000000000000001e37";
+    bool exception = false;
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.000000000000000001e38";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.00000000000000001e37";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.0000000000000001e36";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.0000000000000001e35";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.000000000000001e34";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.00000000000001e32";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.0000000000001e31";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.000000000001e30";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.00000000001e29";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.0000000001e28";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.000000001e27";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.00000001e26";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.0000001e25";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.000001e24";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.00001e23";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.0001e22";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.001e21";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.01e20";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.1e19";
+    PARSE_EXCEPTION_CHECK
+    
+    // Cross over
+    input = "1.0e18";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "10.0e17";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "100.0e16";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "1000.0e15";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "10000.0e14";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "100000.0e13";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "1000000.0e12";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "10000000.0e11";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "100000000.0e10";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "1000000000.0e9";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "10000000000.0e8";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "100000000000.0e7";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "1000000000000.0e6";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "10000000000000.0e5";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "100000000000000.0e4";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "1000000000000000.0e3";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "10000000000000000.0e2";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "100000000000000000.0e1";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "1000000000000000000.0e0";
+    PARSE_EXCEPTION_CHECK
+}
+
+BOOST_AUTO_TEST_CASE(t009)
+{
+    /* TEST CASE 9: zero factional, negative exponent, walking one positive test 
+     * cases
+     */ 
+    fixed_64_64 value;
+    std::ostringstream output;
+     
+    const char* input = "100000000000000000.0e-1";
+    PARSE_VALUE_CHECK("10000000000000000.0");
+    
+    input = "100000000000000000.0e-2";
+    PARSE_VALUE_CHECK("1000000000000000.0");
+    
+    input = "100000000000000000.0e-3";
+    PARSE_VALUE_CHECK("100000000000000.0");
+    
+    input = "100000000000000000.0e-4";
+    PARSE_VALUE_CHECK("10000000000000.0");
+    
+    input = "100000000000000000.0e-5";
+    PARSE_VALUE_CHECK("1000000000000.0");
+    
+    input = "100000000000000000.0e-6";
+    PARSE_VALUE_CHECK("100000000000.0");
+    
+    input = "100000000000000000.0e-7";
+    PARSE_VALUE_CHECK("10000000000.0");
+    
+    input = "100000000000000000.0e-8";
+    PARSE_VALUE_CHECK("1000000000.0");
+    
+    input = "100000000000000000.0e-9";
+    PARSE_VALUE_CHECK("100000000.0");
+    
+    input = "100000000000000000.0e-10";
+    PARSE_VALUE_CHECK("10000000.0");
+    
+    input = "100000000000000000.0e-11";
+    PARSE_VALUE_CHECK("1000000.0");
+    
+    input = "100000000000000000.0e-12";
+    PARSE_VALUE_CHECK("100000.0");
+    
+    input = "100000000000000000.0e-13";
+    PARSE_VALUE_CHECK("10000.0");
+    
+    input = "100000000000000000.0e-14";
+    PARSE_VALUE_CHECK("1000.0");
+    
+    input = "100000000000000000.0e-15";
+    PARSE_VALUE_CHECK("100.0");
+    
+    input = "100000000000000000.0e-16";
+    PARSE_VALUE_CHECK("10.0");
+    
+    input = "100000000000000000.0e-17";
+    PARSE_VALUE_CHECK("1.0");
+    
+    // Cross over
+    input = "100000000000000000.0e-18";
+    PARSE_VALUE_CHECK("0.1");
+    
+    input = "100000000000000000.0e-19";
+    PARSE_VALUE_CHECK("0.01");
+    
+    input = "100000000000000000.0e-20";
+    PARSE_VALUE_CHECK("0.001");
+    
+    input = "100000000000000000.0e-21";
+    PARSE_VALUE_CHECK("0.0001");
+    
+    input = "100000000000000000.0e-22";
+    PARSE_VALUE_CHECK("0.00001");
+    
+    input = "100000000000000000.0e-23";
+    PARSE_VALUE_CHECK("0.000001");
+    
+    input = "100000000000000000.0e-24";
+    PARSE_VALUE_CHECK("0.0000001");
+    
+    input = "100000000000000000.0e-25";
+    PARSE_VALUE_CHECK("0.00000001");
+    
+    input = "100000000000000000.0e-26";
+    PARSE_VALUE_CHECK("0.000000001");
+    
+    input = "100000000000000000.0e-27";
+    PARSE_VALUE_CHECK("0.0000000001");
+    
+    input = "100000000000000000.0e-28";
+    PARSE_VALUE_CHECK("0.00000000001");
+    
+    input = "100000000000000000.0e-29";
+    PARSE_VALUE_CHECK("0.000000000001");
+    
+    input = "100000000000000000.0e-30";
+    PARSE_VALUE_CHECK("0.0000000000001");
+    
+    input = "100000000000000000.0e-31";
+    PARSE_VALUE_CHECK("0.00000000000001");
+    
+    input = "100000000000000000.0e-32";
+    PARSE_VALUE_CHECK("0.000000000000001");
+    
+    input = "100000000000000000.0e-33";
+    PARSE_VALUE_CHECK("0.0000000000000001");
+    
+    input = "100000000000000000.0e-34";
+    PARSE_VALUE_CHECK("0.00000000000000001");
+    
+    input = "100000000000000000.0e-35";
+    PARSE_VALUE_CHECK("0.000000000000000001");
+    
+    input = "100000000000000000.0e-36";
+    PARSE_VALUE_CHECK("0.0000000000000000001");
+}
+
+BOOST_AUTO_TEST_CASE(t010)
+{
+    /* TEST CASE 10: non-zero factional, negative exponent, walking value 
+     * positive+negative test cases
+     */ 
+    fixed_64_64 value;
+    std::ostringstream output;
+     
+    const char* input = "100000000000000000.1e-1";
+    PARSE_VALUE_CHECK("10000000000000000.01");
+    
+    input = "100000000000000000.1e-2";
+    PARSE_VALUE_CHECK("1000000000000000.001");
+    
+    input = "100000000000000000.1e-3";
+    PARSE_VALUE_CHECK("100000000000000.0001");
+    
+    input = "100000000000000000.1e-4";
+    PARSE_VALUE_CHECK("10000000000000.00001");
+    
+    input = "100000000000000000.1e-5";
+    PARSE_VALUE_CHECK("1000000000000.000001");
+    
+    input = "100000000000000000.1e-6";
+    PARSE_VALUE_CHECK("100000000000.0000001");
+    
+    input = "100000000000000000.1e-7";
+    PARSE_VALUE_CHECK("10000000000.00000001");
+    
+    input = "100000000000000000.1e-8";
+    PARSE_VALUE_CHECK("1000000000.000000001");
+    
+    input = "100000000000000000.1e-9";
+    PARSE_VALUE_CHECK("100000000.0000000001");
+    
+    input = "100000000000000000.1e-10";
+    PARSE_VALUE_CHECK("10000000.00000000001");
+    
+    input = "100000000000000000.1e-11";
+    PARSE_VALUE_CHECK("1000000.000000000001");
+    
+    input = "100000000000000000.1e-12";
+    PARSE_VALUE_CHECK("100000.0000000000001");
+    
+    input = "100000000000000000.1e-13";
+    PARSE_VALUE_CHECK("10000.00000000000001");
+    
+    input = "100000000000000000.1e-14";
+    PARSE_VALUE_CHECK("1000.000000000000001");
+    
+    input = "100000000000000000.1e-15";
+    PARSE_VALUE_CHECK("100.0000000000000001");
+    
+    input = "100000000000000000.1e-16";
+    PARSE_VALUE_CHECK("10.00000000000000001");
+    
+    input = "100000000000000000.1e-17";
+    PARSE_VALUE_CHECK("1.000000000000000001");
+    
+    input = "100000000000000000.1e-18";
+    PARSE_VALUE_CHECK("0.1000000000000000001");
+    
+    input = "100000000000000000.1e-19";
+    bool exception = false;
+    PARSE_EXCEPTION_CHECK
+}
+
+BOOST_AUTO_TEST_CASE(t011)
+{
+    /* TEST CASE 11: zero factional, negative exponent, walking one negative test 
+     * cases
+     */ 
+    fixed_64_64 value;
+    std::ostringstream output;
+     
+    const char* input = "100000000000000000.0e-37";
+    bool exception = false;
+    PARSE_EXCEPTION_CHECK
+    
+    input = "10000000000000000.0e-36";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "1000000000000000.0e-35";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "100000000000000.0e-34";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "10000000000000.0e-33";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "1000000000000.0e-32";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "100000000000.0e-31";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "10000000000.0e-30";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "1000000000.0e-29";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "100000000.0e-28";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "10000000.0e-27";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "1000000.0e-26";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "100000.0e-25";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "10000.0e-24";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "1000.0e-23";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "100.0e-22";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "10.0e-21";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "1.0e-20";
+    PARSE_EXCEPTION_CHECK
+    
+    // Cross over
+    input = "0.1e-19";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.01e-18";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.001e-17";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.0001e-16";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.00001e-15";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.000001e-14";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.0000001e-13";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.00000001e-12";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.000000001e-11";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.0000000001e-10";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.00000000001e-9";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.000000000001e-8";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.0000000000001e-7";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.00000000000001e-6";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.000000000000001e-5";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.0000000000000001e-4";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.00000000000000001e-3";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.000000000000000001e-2";
+    PARSE_EXCEPTION_CHECK
+    
+    input = "0.0000000000000000001e-1";
+    PARSE_EXCEPTION_CHECK
+}
+
+BOOST_AUTO_TEST_CASE(t012)
+{
+    /* TEST CASE 12: non-zero negative integer, positive exponent, walking value 
+     * positive+negative test cases
+     */ 
+    fixed_64_64 value;
+    std::ostringstream output;
+     
+    const char* input = "-1.0000000000000000001e1";
+    PARSE_VALUE_CHECK("-10.000000000000000001");
+    
+    input = "-1.0000000000000000001e2";
+    PARSE_VALUE_CHECK("-100.00000000000000001");
+    
+    input = "-1.0000000000000000001e3";
+    PARSE_VALUE_CHECK("-1000.0000000000000001");
+    
+    input = "-1.0000000000000000001e4";
+    PARSE_VALUE_CHECK("-10000.000000000000001");
+    
+    input = "-1.0000000000000000001e5";
+    PARSE_VALUE_CHECK("-100000.00000000000001");
+    
+    input = "-1.0000000000000000001e6";
+    PARSE_VALUE_CHECK("-1000000.0000000000001");
+    
+    input = "-1.0000000000000000001e7";
+    PARSE_VALUE_CHECK("-10000000.000000000001");
+    
+    input = "-1.0000000000000000001e8";
+    PARSE_VALUE_CHECK("-100000000.00000000001");
+    
+    input = "-1.0000000000000000001e9";
+    PARSE_VALUE_CHECK("-1000000000.0000000001");
+    
+    input = "-1.0000000000000000001e10";
+    PARSE_VALUE_CHECK("-10000000000.000000001");
+    
+    input = "-1.0000000000000000001e11";
+    PARSE_VALUE_CHECK("-100000000000.00000001");
+    
+    input = "-1.0000000000000000001e12";
+    PARSE_VALUE_CHECK("-1000000000000.0000001");
+    
+    input = "-1.0000000000000000001e13";
+    PARSE_VALUE_CHECK("-10000000000000.000001");
+    
+    input = "-1.0000000000000000001e14";
+    PARSE_VALUE_CHECK("-100000000000000.00001");
+    
+    input = "-1.0000000000000000001e15";
+    PARSE_VALUE_CHECK("-1000000000000000.0001");
+    
+    input = "-1.0000000000000000001e16";
+    PARSE_VALUE_CHECK("-10000000000000000.001");
+    
+    input = "-1.0000000000000000001e17";
+    PARSE_VALUE_CHECK("-100000000000000000.01");
+    
+    input = "-1.0000000000000000001e18";
+    bool exception = false;
+    PARSE_EXCEPTION_CHECK
+}
+
+BOOST_AUTO_TEST_CASE(t013)
+{
+    /* TEST CASE 13: non-zero negative factional, negative exponent, walking
+     * value positive+negative test cases
+     */ 
+    fixed_64_64 value;
+    std::ostringstream output;
+     
+    const char* input = "-100000000000000000.1e-1";
+    PARSE_VALUE_CHECK("-10000000000000000.01");
+    
+    input = "-100000000000000000.1e-2";
+    PARSE_VALUE_CHECK("-1000000000000000.001");
+    
+    input = "-100000000000000000.1e-3";
+    PARSE_VALUE_CHECK("-100000000000000.0001");
+    
+    input = "-100000000000000000.1e-4";
+    PARSE_VALUE_CHECK("-10000000000000.00001");
+    
+    input = "-100000000000000000.1e-5";
+    PARSE_VALUE_CHECK("-1000000000000.000001");
+    
+    input = "-100000000000000000.1e-6";
+    PARSE_VALUE_CHECK("-100000000000.0000001");
+    
+    input = "-100000000000000000.1e-7";
+    PARSE_VALUE_CHECK("-10000000000.00000001");
+    
+    input = "-100000000000000000.1e-8";
+    PARSE_VALUE_CHECK("-1000000000.000000001");
+    
+    input = "-100000000000000000.1e-9";
+    PARSE_VALUE_CHECK("-100000000.0000000001");
+    
+    input = "-100000000000000000.1e-10";
+    PARSE_VALUE_CHECK("-10000000.00000000001");
+    
+    input = "-100000000000000000.1e-11";
+    PARSE_VALUE_CHECK("-1000000.000000000001");
+    
+    input = "-100000000000000000.1e-12";
+    PARSE_VALUE_CHECK("-100000.0000000000001");
+    
+    input = "-100000000000000000.1e-13";
+    PARSE_VALUE_CHECK("-10000.00000000000001");
+    
+    input = "-100000000000000000.1e-14";
+    PARSE_VALUE_CHECK("-1000.000000000000001");
+    
+    input = "-100000000000000000.1e-15";
+    PARSE_VALUE_CHECK("-100.0000000000000001");
+    
+    input = "-100000000000000000.1e-16";
+    PARSE_VALUE_CHECK("-10.00000000000000001");
+    
+    input = "-100000000000000000.1e-17";
+    PARSE_VALUE_CHECK("-1.000000000000000001");
+    
+    input = "-100000000000000000.1e-18";
+    PARSE_VALUE_CHECK("-0.1000000000000000001");
+    
+    input = "-100000000000000000.1e-19";
+    bool exception = false;
+    PARSE_EXCEPTION_CHECK
+}
+
+BOOST_AUTO_TEST_CASE(t014)
+{
+    /* TEST CASE 14: LEADING_ZERO=true; negative zero parse
+     */ 
+     
+    fixed_64_64 value;
+    std::ostringstream output;
+     
+    const char* input = "-0.9";
+    PARSE_VALUE_CHECK("-0.9");
+    
+    input = "-0.99";
+    PARSE_VALUE_CHECK("-0.99");
+
+    input = "-0.999";
+    PARSE_VALUE_CHECK("-0.999");
+
+    input = "-0.9999";
+    PARSE_VALUE_CHECK("-0.9999");
+
+    input = "-0.99999";
+    PARSE_VALUE_CHECK("-0.99999");
+
+    input = "-0.999999";
+    PARSE_VALUE_CHECK("-0.999999");
+
+    input = "-0.9999999";
+    PARSE_VALUE_CHECK("-0.9999999");
+
+    input = "-0.99999999";
+    PARSE_VALUE_CHECK("-0.99999999");
+
+    input = "-0.999999999";
+    PARSE_VALUE_CHECK("-0.999999999");
+
+    input = "-0.9999999999";
+    PARSE_VALUE_CHECK("-0.9999999999");
+
+    input = "-0.99999999999";
+    PARSE_VALUE_CHECK("-0.99999999999");
+
+    input = "-0.999999999999";
+    PARSE_VALUE_CHECK("-0.999999999999");
+
+    input = "-0.9999999999999";
+    PARSE_VALUE_CHECK("-0.9999999999999");
+
+    input = "-0.99999999999999";
+    PARSE_VALUE_CHECK("-0.99999999999999");
+
+    input = "-0.999999999999999";
+    PARSE_VALUE_CHECK("-0.999999999999999");
+
+    input = "-0.9999999999999999";
+    PARSE_VALUE_CHECK("-0.9999999999999999");
+
+    input = "-0.99999999999999999";
+    PARSE_VALUE_CHECK("-0.99999999999999999");
+
+    input = "-0.999999999999999999";
+    PARSE_VALUE_CHECK("-0.999999999999999999");
+
+    input = "-0.9999999999999999999";
+    PARSE_VALUE_CHECK("-0.9999999999999999999");
+}
+
+BOOST_AUTO_TEST_CASE(t015)
+{
+    /* TEST CASE 15: LEADING_ZERO=false; negative zero parse
+     */ 
+     
+    fixed_64_64 value;
+    std::ostringstream output;
+     
+    const char* input = "-.9";
+    PARSE_VALUE_CHECK("-0.9");
+    
+    input = "-.99";
+    PARSE_VALUE_CHECK("-0.99");
+
+    input = "-.999";
+    PARSE_VALUE_CHECK("-0.999");
+
+    input = "-.9999";
+    PARSE_VALUE_CHECK("-0.9999");
+
+    input = "-.99999";
+    PARSE_VALUE_CHECK("-0.99999");
+
+    input = "-.999999";
+    PARSE_VALUE_CHECK("-0.999999");
+
+    input = "-.9999999";
+    PARSE_VALUE_CHECK("-0.9999999");
+
+    input = "-.99999999";
+    PARSE_VALUE_CHECK("-0.99999999");
+
+    input = "-.999999999";
+    PARSE_VALUE_CHECK("-0.999999999");
+
+    input = "-.9999999999";
+    PARSE_VALUE_CHECK("-0.9999999999");
+
+    input = "-.99999999999";
+    PARSE_VALUE_CHECK("-0.99999999999");
+
+    input = "-.999999999999";
+    PARSE_VALUE_CHECK("-0.999999999999");
+
+    input = "-.9999999999999";
+    PARSE_VALUE_CHECK("-0.9999999999999");
+
+    input = "-.99999999999999";
+    PARSE_VALUE_CHECK("-0.99999999999999");
+
+    input = "-.999999999999999";
+    PARSE_VALUE_CHECK("-0.999999999999999");
+
+    input = "-.9999999999999999";
+    PARSE_VALUE_CHECK("-0.9999999999999999");
+
+    input = "-.99999999999999999";
+    PARSE_VALUE_CHECK("-0.99999999999999999");
+
+    input = "-.999999999999999999";
+    PARSE_VALUE_CHECK("-0.999999999999999999");
+
+    input = "-.9999999999999999999";
+    PARSE_VALUE_CHECK("-0.9999999999999999999");
+}
+
+BOOST_AUTO_TEST_CASE(t016)
+{
+    /* TEST CASE 16: negative zero comparison
+     */ 
+    fixed_64_64 val1;
+    val1.parse("-0.9");
+    
+    fixed_64_64 val2;
+    val2.parse("-0.9");
+    
+    //             -0.9 OP -0.9
+    BOOST_CHECK(  (val1 == val2));
+    BOOST_CHECK(! (val1 != val2));
+    BOOST_CHECK(! (val1 > val2));
+    BOOST_CHECK(! (val1 < val2));
+    BOOST_CHECK(  (val1 >= val2));
+    BOOST_CHECK(  (val1 <= val2));
+    
+    // 0.9
+    val2.assignUnscaledFrac(0, 9, 0);
+    
+    //             -0.9 OP 0.9
+    BOOST_CHECK(! (val1 == val2));
+    BOOST_CHECK(  (val1 != val2));
+    BOOST_CHECK(! (val1 > val2));
+    BOOST_CHECK(  (val1 < val2));
+    BOOST_CHECK(! (val1 >= val2));
+    BOOST_CHECK(  (val1 <= val2));
+}
+
+BOOST_AUTO_TEST_CASE(t017)
+{
+    /* TEST CASE 17: positive divide by positive integer
+     */ 
+     
+    fixed_64_64 value;
+    std::ostringstream output;
+     
+    const char* input = "900000000000000000.0";
+    value.parse(input);
+    value = value / 1;
+    VALUE_CHECK("900000000000000000.0");
+    
+    value = value / 10;
+    VALUE_CHECK("90000000000000000.0");
+    
+    value = value / 10;
+    VALUE_CHECK("9000000000000000.0");
+
+    value = value / 10;
+    VALUE_CHECK("900000000000000.0");
+
+    value = value / 10;
+    VALUE_CHECK("90000000000000.0");
+
+    value = value / 10;
+    VALUE_CHECK("9000000000000.0");
+
+    value = value / 10;
+    VALUE_CHECK("900000000000.0");
+
+    value = value / 10;
+    VALUE_CHECK("90000000000.0");
+
+    value = value / 10;
+    VALUE_CHECK("9000000000.0");
+
+    value = value / 10;
+    VALUE_CHECK("900000000.0");
+
+    value = value / 10;
+    VALUE_CHECK("90000000.0");
+
+    value = value / 10;
+    VALUE_CHECK("9000000.0");
+
+    value = value / 10;
+    VALUE_CHECK("900000.0");
+
+    value = value / 10;
+    VALUE_CHECK("90000.0");
+
+    value = value / 10;
+    VALUE_CHECK("9000.0");
+
+    value = value / 10;
+    VALUE_CHECK("900.0");
+
+    value = value / 10;
+    VALUE_CHECK("90.0");
+
+    value = value / 10;
+    VALUE_CHECK("9.0");
+
+    // Cross over
+    value = value / 10;
+    VALUE_CHECK("0.9");
+
+    value = value / 10;
+    VALUE_CHECK("0.09");
+
+    value = value / 10;
+    VALUE_CHECK("0.009");
+
+    value = value / 10;
+    VALUE_CHECK("0.0009");
+
+    value = value / 10;
+    VALUE_CHECK("0.00009");
+
+    value = value / 10;
+    VALUE_CHECK("0.000009");
+
+    value = value / 10;
+    VALUE_CHECK("0.0000009");
+
+    value = value / 10;
+    VALUE_CHECK("0.00000009");
+
+    value = value / 10;
+    VALUE_CHECK("0.000000009");
+
+    value = value / 10;
+    VALUE_CHECK("0.0000000009");
+
+    value = value / 10;
+    VALUE_CHECK("0.00000000009");
+
+    value = value / 10;
+    VALUE_CHECK("0.000000000009");
+
+    value = value / 10;
+    VALUE_CHECK("0.0000000000009");
+
+    value = value / 10;
+    VALUE_CHECK("0.00000000000009");
+
+    value = value / 10;
+    VALUE_CHECK("0.000000000000009");
+
+    value = value / 10;
+    VALUE_CHECK("0.0000000000000009");
+
+    value = value / 10;
+    VALUE_CHECK("0.00000000000000009");
 
+    value = value / 10;
+    VALUE_CHECK("0.000000000000000009");
+
+    value = value / 10;
+    VALUE_CHECK("0.0000000000000000009");
+}
+
+BOOST_AUTO_TEST_CASE(t018)
+{
+    /* TEST CASE 18: negative divide by positive integer
+     */ 
+     
+    fixed_64_64 value;
+    std::ostringstream output;
+     
+    const char* input = "-900000000000000000.0";
+    value.parse(input);
+    
+    value = value / 1;
+    VALUE_CHECK("-900000000000000000.0");
+    
+    value = value / 10;
+    VALUE_CHECK("-90000000000000000.0");
+
+    value = value / 10;
+    VALUE_CHECK("-9000000000000000.0");
+
+    value = value / 10;
+    VALUE_CHECK("-900000000000000.0");
+
+    value = value / 10;
+    VALUE_CHECK("-90000000000000.0");
+
+    value = value / 10;
+    VALUE_CHECK("-9000000000000.0");
+
+    value = value / 10;
+    VALUE_CHECK("-900000000000.0");
+
+    value = value / 10;
+    VALUE_CHECK("-90000000000.0");
+
+    value = value / 10;
+    VALUE_CHECK("-9000000000.0");
+
+    value = value / 10;
+    VALUE_CHECK("-900000000.0");
+
+    value = value / 10;
+    VALUE_CHECK("-90000000.0");
+
+    value = value / 10;
+    VALUE_CHECK("-9000000.0");
+
+    value = value / 10;
+    VALUE_CHECK("-900000.0");
+
+    value = value / 10;
+    VALUE_CHECK("-90000.0");
+
+    value = value / 10;
+    VALUE_CHECK("-9000.0");
+
+    value = value / 10;
+    VALUE_CHECK("-900.0");
+
+    value = value / 10;
+    VALUE_CHECK("-90.0");
+
+    value = value / 10;
+    VALUE_CHECK("-9.0");
+    
+    // Cross over
+    value = value / 10;
+    VALUE_CHECK("-0.9");
+
+    value = value / 10;
+    VALUE_CHECK("-0.09");
+
+    value = value / 10;
+    VALUE_CHECK("-0.009");
+
+    value = value / 10;
+    VALUE_CHECK("-0.0009");
+
+    value = value / 10;
+    VALUE_CHECK("-0.00009");
+
+    value = value / 10;
+    VALUE_CHECK("-0.000009");
+
+    value = value / 10;
+    VALUE_CHECK("-0.0000009");
+
+    value = value / 10;
+    VALUE_CHECK("-0.00000009");
+
+    value = value / 10;
+    VALUE_CHECK("-0.000000009");
+
+    value = value / 10;
+    VALUE_CHECK("-0.0000000009");
+
+    value = value / 10;
+    VALUE_CHECK("-0.00000000009");
+
+    value = value / 10;
+    VALUE_CHECK("-0.000000000009");
+
+    value = value / 10;
+    VALUE_CHECK("-0.0000000000009");
+
+    value = value / 10;
+    VALUE_CHECK("-0.00000000000009");
+
+    value = value / 10;
+    VALUE_CHECK("-0.000000000000009");
+
+    value = value / 10;
+    VALUE_CHECK("-0.0000000000000009");
+
+    value = value / 10;
+    VALUE_CHECK("-0.00000000000000009");
+
+    value = value / 10;
+    VALUE_CHECK("-0.000000000000000009");
+
+    value = value / 10;
+    VALUE_CHECK("-0.0000000000000000009");
+}
+
+BOOST_AUTO_TEST_CASE(t019)
+{
+    /* TEST CASE 19: positive divide by negative integer
+     */ 
+     
+    fixed_64_64 value;
+    std::ostringstream output;
+     
+    const char* input = "900000000000000000.0";
+    value.parse(input);
+    value = value / -1;
+    VALUE_CHECK("-900000000000000000.0");
+    
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-90000000000000000.0");
+    
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-9000000000000000.0");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-900000000000000.0");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-90000000000000.0");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-9000000000000.0");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-900000000000.0");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-90000000000.0");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-9000000000.0");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-900000000.0");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-90000000.0");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-9000000.0");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-900000.0");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-90000.0");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-9000.0");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-900.0");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-90.0");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-9.0");
+
+    // Cross over
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-0.9");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-0.09");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-0.009");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-0.0009");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-0.00009");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-0.000009");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-0.0000009");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-0.00000009");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-0.000000009");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-0.0000000009");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-0.00000000009");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-0.000000000009");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-0.0000000000009");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-0.00000000000009");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-0.000000000000009");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-0.0000000000000009");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-0.00000000000000009");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-0.000000000000000009");
+
+    value.absval();
+    value = value / -10;
+    VALUE_CHECK("-0.0000000000000000009");
+}
+
+BOOST_AUTO_TEST_CASE(t020)
+{
+    /* TEST CASE 20: hegative divide by negative integer
+     */ 
+     
+    fixed_64_64 value;
+    std::ostringstream output;
+     
+    const char* input = "-900000000000000000.0";
+    value.parse(input);
+    value = value / -1;
+    VALUE_CHECK("900000000000000000.0");
+    
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("90000000000000000.0");
+    
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("9000000000000000.0");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("900000000000000.0");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("90000000000000.0");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("9000000000000.0");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("900000000000.0");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("90000000000.0");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("9000000000.0");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("900000000.0");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("90000000.0");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("9000000.0");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("900000.0");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("90000.0");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("9000.0");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("900.0");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("90.0");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("9.0");
+
+    // Cross over
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("0.9");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("0.09");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("0.009");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("0.0009");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("0.00009");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("0.000009");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("0.0000009");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("0.00000009");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("0.000000009");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("0.0000000009");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("0.00000000009");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("0.000000000009");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("0.0000000000009");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("0.00000000000009");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("0.000000000000009");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("0.0000000000000009");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("0.00000000000000009");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("0.000000000000000009");
+
+    value.negate();
+    value = value / -10;
+    VALUE_CHECK("0.0000000000000000009");
+}
