]> Dogcows Code - chaz/yoink/blobdiff - src/stlplus/portability/inf.cpp
import stlplus 3.7
[chaz/yoink] / src / stlplus / portability / inf.cpp
index d70ab76453f40454f25043c39540ec2b6b3f15c6..19e87baa82c86198f9b5a1a60590e2e88689ed30 100644 (file)
-////////////////////////////////////////////////////////////////////////////////
-
-//   Author:    Andy Rushton
-//   Copyright: (c) Southampton University 1999-2004
-//              (c) Andy Rushton           2004-2009
-//   License:   BSD License, see ../docs/license.html
-
-//   The integer is represented as a sequence of bytes. They are stored such that
-//   element 0 is the lsB, which makes sense when seen as an integer offset but
-//   is counter-intuitive when you think that a string is usually read from left
-//   to right, 0 to size-1, in which case the lsB is on the *left*.
-
-//   This solution is compatible with 32-bit and 64-bit machines with either
-//   little-endian or big-endian representations of integers.
-
-//   Problem: I'm using std::string, which is an array of char. However, char is
-//   not well-defined - it could be signed or unsigned.
-
-//   In fact, there's no requirement for a char to even be one byte - it can be
-//   any size of one byte or more. However, it's just impossible to make any
-//   progress with that naffness (thanks to the C non-standardisation committee)
-//   and the practice is that char on every platform/compiler I've ever come
-//   across is that char = byte.
-
-//   The algorithms here use unsigned char to represent bit-patterns so I have to
-//   be careful to type-cast from char to unsigned char a lot. I use a typedef to
-//   make life easier.
-
-////////////////////////////////////////////////////////////////////////////////
-#include "inf.hpp"
-#include <ctype.h>
-////////////////////////////////////////////////////////////////////////////////
-
-namespace stlplus
-{
-
-  ////////////////////////////////////////////////////////////////////////////////
-  // choose a sensible C type for a byte
-
-  typedef unsigned char byte;
-
-  ////////////////////////////////////////////////////////////////////////////////
-  // local functions
-
-  // removes leading bytes that don't contribute to the value to create the minimum string representation
-  static void reduce_string(std::string& data)
-  {
-    while(data.size() > 1 && 
-          ((byte(data[data.size()-1]) == byte(0) && byte(data[data.size()-2]) < byte(128)) ||
-           (byte(data[data.size()-1]) == byte(255) && byte(data[data.size()-2]) >= byte(128))))
-    {
-      data.erase(data.end()-1);
-    }
-  }
-
-  // generic implementations of type conversions from integer type to internal representation
-  // data: integer value for conversion
-  // result: internal representation
-
-  template <typename T>
-  static void convert_from_signed(const T& data, std::string& result)
-  {
-    result.erase();
-    bool lsb_first = little_endian();
-    byte* address = (byte*)&data;
-    for (size_t i = 0; i < sizeof(T); i++)
-    {
-      size_t offset = (lsb_first ? i : (sizeof(T) - i - 1));
-      result.append(1,address[offset]);
-    }
-    reduce_string(result);
-  }
-
-  template <typename T>
-  static void convert_from_unsigned(const T& data, std::string& result)
-  {
-    result.erase();
-    bool lsb_first = little_endian();
-    byte* address = (byte*)&data;
-    for (size_t i = 0; i < sizeof(T); i++)
-    {
-      size_t offset = (lsb_first ? i : (sizeof(T) - i - 1));
-      result.append(1,address[offset]);
-    }
-    // inf is signed - so there is a possible extra sign bit to add
-    result.append(1,std::string::value_type(0));
-    reduce_string(result);
-  }
-
-  // generic implementations of type conversions from internal representation to an integer type
-  // data : string representation of integer
-  // result: integer result of conversion
-  // return: flag indicating success - false = overflow
-
-  template <class T>
-  bool convert_to_signed(const std::string& data, T& result)
-  {
-    bool lsb_first = little_endian();
-    byte* address = (byte*)&result;
-    for (size_t i = 0; i < sizeof(T); i++)
-    {
-      size_t offset = lsb_first ? i : (sizeof(T) - i - 1);
-      if (i < data.size())
-        address[offset] = byte(data[i]);
-      else if (data.empty() || (byte(data[data.size()-1]) < byte(128)))
-        address[offset] = byte(0);
-      else
-        address[offset] = byte(255);
-    }
-    return data.size() <= sizeof(T);
-  }
-
-  template <class T>
-  bool convert_to_unsigned(const std::string& data, T& result)
-  {
-    bool lsb_first = little_endian();
-    byte* address = (byte*)&result;
-    for (size_t i = 0; i < sizeof(T); i++)
-    {
-      size_t offset = lsb_first ? i : (sizeof(T) - i - 1);
-      if (i < data.size())
-        address[offset] = byte(data[i]);
-      else
-        address[offset] = byte(0);
-    }
-    return data.size() <= sizeof(T);
-  }
-
-  ////////////////////////////////////////////////////////////////////////////////
-  // Conversions to string
-
-  static char to_char [] = "0123456789abcdefghijklmnopqrstuvwxyz";
-  static int from_char [] = 
-  {
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
-    -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
-    25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
-    -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
-    25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
-  };
-
-  static void convert_to_string(const stlplus::inf& data, std::string& result, unsigned radix = 10)
-    throw(std::invalid_argument)
-  {
-    // only support the C-style radixes plus 0b for binary
-    if (radix != 2 && radix != 8 && radix != 10 && radix != 16)
-      throw std::invalid_argument("invalid radix value");
-    inf local_i = data;
-    // untangle all the options
-    bool binary = radix == 2;
-    bool octal = radix == 8;
-    bool hex = radix == 16;
-    // the C representations for binary, octal and hex use 2's-complement representation
-    // all other represenations use sign-magnitude
-    if (hex || octal || binary)
-    {
-      // bit-pattern representation
-      // this is the binary representation optionally shown in octal or hex
-      // first generate the binary by masking the bits
-      for (unsigned j = local_i.bits(); j--; )
-        result += (local_i.bit(j) ? '1' : '0');
-      // the result is now the full width of the type - e.g. int will give a 32-bit result
-      // now interpret this as either binary, octal or hex and add the prefix
-      if (binary)
-      {
-        // trim down to the smallest string that preserves the value
-        while (true)
-        {
-          // do not trim to less than 1 bit (sign only)
-          if (result.size() <= 1) break;
-          // only trim if it doesn't change the sign and therefore the value
-          if (result[0] != result[1]) break;
-          result.erase(0,1);
-        }
-        // add the prefix
-        result.insert((std::string::size_type)0, "0b");
-      }
-      else if (octal)
-      {
-        // the result is currently binary
-        // trim down to the smallest string that preserves the value
-        while (true)
-        {
-          // do not trim to less than 2 bits (sign plus 1-bit magnitude)
-          if (result.size() <= 2) break;
-          // only trim if it doesn't change the sign and therefore the value
-          if (result[0] != result[1]) break;
-          result.erase(0,1);
-        }
-        // also ensure that the binary is a multiple of 3 bits to make the conversion to octal easier
-        while (result.size() % 3 != 0)
-          result.insert((std::string::size_type)0, 1, result[0]);
-        // now convert to octal
-        std::string octal_result;
-        for (unsigned i = 0; i < result.size()/3; i++)
-        {
-          // yuck - ugly or what?
-          if (result[i*3] == '0')
-          {
-            if (result[i*3+1] == '0')
-            {
-              if (result[i*3+2] == '0')
-                octal_result += '0';
-              else
-                octal_result += '1';
-            }
-            else
-            {
-              if (result[i*3+2] == '0')
-                octal_result += '2';
-              else
-                octal_result += '3';
-            }
-          }
-          else
-          {
-            if (result[i*3+1] == '0')
-            {
-              if (result[i*3+2] == '0')
-                octal_result += '4';
-              else
-                octal_result += '5';
-            }
-            else
-            {
-              if (result[i*3+2] == '0')
-                octal_result += '6';
-              else
-                octal_result += '7';
-            }
-          }
-        }
-        result = octal_result;
-        // add the prefix
-        result.insert((std::string::size_type)0, "0");
-      }
-      else
-      {
-        // similar to octal
-        while (true)
-        {
-          // do not trim to less than 2 bits (sign plus 1-bit magnitude)
-          if (result.size() <= 2) break;
-          // only trim if it doesn't change the sign and therefore the value
-          if (result[0] != result[1]) break;
-          result.erase(0,1);
-        }
-        // pad to a multiple of 4 characters
-        while (result.size() % 4 != 0)
-          result.insert((std::string::size_type)0, 1, result[0]);
-        // now convert to hex
-        std::string hex_result;
-        for (unsigned i = 0; i < result.size()/4; i++)
-        {
-          // yuck - ugly or what?
-          if (result[i*4] == '0')
-          {
-            if (result[i*4+1] == '0')
-            {
-              if (result[i*4+2] == '0')
-              {
-                if (result[i*4+3] == '0')
-                  hex_result += '0';
-                else
-                  hex_result += '1';
-              }
-              else
-              {
-                if (result[i*4+3] == '0')
-                  hex_result += '2';
-                else
-                  hex_result += '3';
-              }
-            }
-            else
-            {
-              if (result[i*4+2] == '0')
-              {
-                if (result[i*4+3] == '0')
-                  hex_result += '4';
-                else
-                  hex_result += '5';
-              }
-              else
-              {
-                if (result[i*4+3] == '0')
-                  hex_result += '6';
-                else
-                  hex_result += '7';
-              }
-            }
-          }
-          else
-          {
-            if (result[i*4+1] == '0')
-            {
-              if (result[i*4+2] == '0')
-              {
-                if (result[i*4+3] == '0')
-                  hex_result += '8';
-                else
-                  hex_result += '9';
-              }
-              else
-              {
-                if (result[i*4+3] == '0')
-                  hex_result += 'a';
-                else
-                  hex_result += 'b';
-              }
-            }
-            else
-            {
-              if (result[i*4+2] == '0')
-              {
-                if (result[i*4+3] == '0')
-                  hex_result += 'c';
-                else
-                  hex_result += 'd';
-              }
-              else
-              {
-                if (result[i*4+3] == '0')
-                  hex_result += 'e';
-                else
-                  hex_result += 'f';
-              }
-            }
-          }
-        }
-        result = hex_result;
-        // add the prefix
-        result.insert((std::string::size_type)0, "0x");
-      }
-    }
-    else
-    {
-      // convert to sign-magnitude
-      // the representation is:
-      // [sign]magnitude
-      bool negative = local_i.negative();
-      local_i.abs();
-      // create a representation of the magnitude by successive division
-      inf inf_radix(radix);
-      do
-      {
-        std::pair<inf,inf> divided = local_i.divide(inf_radix);
-        unsigned remainder = divided.second.to_unsigned();
-        char digit = to_char[remainder];
-        result.insert((std::string::size_type)0, 1, digit);
-        local_i = divided.first;
-      }
-      while(!local_i.zero());
-      // add the prefixes
-      // add a sign only for negative values
-      if (negative)
-        result.insert((std::string::size_type)0, 1, '-');
-    }
-  }
-
-  ////////////////////////////////////////////////////////////////////////////////
-  // Conversions FROM string
-
-  void convert_from_string(const std::string& str, inf& result, unsigned radix = 10) throw(std::invalid_argument)
-  {
-    result = 0;
-    // only support the C-style radixes plus 0b for binary
-    // a radix of 0 means deduce the radix from the input - assume 10
-    if (radix != 0 && radix != 2 && radix != 8 && radix != 10 && radix != 16)
-      throw std::invalid_argument("invalid radix value");
-    unsigned i = 0;
-    // the radix passed as a parameter is just the default - it can be
-    // overridden by the C prefix
-    // Note: a leading zero is the C-style prefix for octal - I only make this
-    // override the default when the default radix is not specified
-    // first check for a C-style prefix
-    bool c_style = false;
-    if (i < str.size() && str[i] == '0')
-    {
-      // binary or hex
-      if (i+1 < str.size() && tolower(str[i+1]) == 'x')
-      {
-        c_style = true;
-        radix = 16;
-        i += 2;
-      }
-      else if (i+1 < str.size() && tolower(str[i+1]) == 'b')
-      {
-        c_style = true;
-        radix = 2;
-        i += 2;
-      }
-      else if (radix == 0)
-      {
-        c_style = true;
-        radix = 8;
-        i += 1;
-      }
-    }
-    if (radix == 0)
-      radix = 10;
-    if (c_style)
-    {
-      // the C style formats are bit patterns not integer values - these need
-      // to be sign-extended to get the right value
-      std::string binary;
-      if (radix == 2)
-      {
-        for (unsigned j = i; j < str.size(); j++)
-        {
-          switch(str[j])
-          {
-          case '0':
-            binary += '0';
-            break;
-          case '1':
-            binary += '1';
-            break;
-          default:
-            throw std::invalid_argument("invalid binary character in string " + str);
-          }
-        }
-      }
-      else if (radix == 8)
-      {
-        for (unsigned j = i; j < str.size(); j++)
-        {
-          switch(str[j])
-          {
-          case '0':
-            binary += "000";
-            break;
-          case '1':
-            binary += "001";
-            break;
-          case '2':
-            binary += "010";
-            break;
-          case '3':
-            binary += "011";
-            break;
-          case '4':
-            binary += "100";
-            break;
-          case '5':
-            binary += "101";
-            break;
-          case '6':
-            binary += "110";
-            break;
-          case '7':
-            binary += "111";
-            break;
-          default:
-            throw std::invalid_argument("invalid octal character in string " + str);
-          }
-        }
-      }
-      else
-      {
-        for (unsigned j = i; j < str.size(); j++)
-        {
-          switch(tolower(str[j]))
-          {
-          case '0':
-            binary += "0000";
-            break;
-          case '1':
-            binary += "0001";
-            break;
-          case '2':
-            binary += "0010";
-            break;
-          case '3':
-            binary += "0011";
-            break;
-          case '4':
-            binary += "0100";
-            break;
-          case '5':
-            binary += "0101";
-            break;
-          case '6':
-            binary += "0110";
-            break;
-          case '7':
-            binary += "0111";
-            break;
-          case '8':
-            binary += "1000";
-            break;
-          case '9':
-            binary += "1001";
-            break;
-          case 'a':
-            binary += "1010";
-            break;
-          case 'b':
-            binary += "1011";
-            break;
-          case 'c':
-            binary += "1100";
-            break;
-          case 'd':
-            binary += "1101";
-            break;
-          case 'e':
-            binary += "1110";
-            break;
-          case 'f':
-            binary += "1111";
-            break;
-          default:
-            throw std::invalid_argument("invalid hex character in string " + str);
-          }
-        }
-      }
-      // now convert the value
-      result.resize(binary.size());
-      for (unsigned j = 0; j < binary.size(); j++)
-        result.preset(binary.size() - j - 1, binary[j] == '1');
-    }
-    else
-    {
-      // sign-magnitude representation
-      // now scan for a sign and find whether this is a negative number
-      bool negative = false;
-      if (i < str.size())
-      {
-        switch (str[i])
-        {
-        case '-':
-          negative = true;
-          i++;
-          break;
-        case '+':
-          i++;
-          break;
-        }
-      }
-      for (; i < str.size(); i++)
-      {
-        result *= inf(radix);
-        unsigned char ascii = (unsigned char)str[i];
-        int ch = from_char[ascii] ;
-        if (ch == -1)
-          throw std::invalid_argument("invalid decimal character in string " + str);
-        result += inf(ch);
-      }
-      if (negative)
-        result.negate();
-    }
-  }
-
-  ////////////////////////////////////////////////////////////////////////////////
-  // constructors - mostly implemented in terms of the assignment operators
-
-  inf::inf(void)
-  {
-    // void constructor initialises to zero - represented as a single-byte value containing zero
-    m_data.append(1,std::string::value_type(0));
-  }
-
-  inf::inf(short r)
-  {
-    operator=(r);
-  }
-
-  inf::inf(unsigned short r)
-  {
-    operator=(r);
-  }
-
-  inf::inf(int r)
-  {
-    operator=(r);
-  }
-
-  inf::inf(unsigned r)
-  {
-    operator=(r);
-  }
-
-  inf::inf(long r)
-  {
-    operator=(r);
-  }
-
-  inf::inf(unsigned long r)
-  {
-    operator=(r);
-  }
-
-  inf::inf (const std::string& r) throw(std::invalid_argument)
-  {
-    operator=(r);
-  }
-
-  inf::inf(const inf& r)
-  {
-#ifdef __BORLANDC__
-    // work round bug in Borland compiler - copy constructor fails if string
-    // contains null characters, so do my own copy
-    for (unsigned i = 0; i < r.m_data.size(); i++)
-      m_data += r.m_data[i];
-#else
-    m_data = r.m_data;
-#endif
-  }
-
-  ////////////////////////////////////////////////////////////////////////////////
-
-  inf::~inf(void)
-  {
-  }
-
-  ////////////////////////////////////////////////////////////////////////////////
-  // assignments convert from iteger types to internal representation
-
-  inf& inf::operator = (short r)
-  {
-    convert_from_signed(r, m_data);
-    return *this;
-  }
-
-  inf& inf::operator = (unsigned short r)
-  {
-    convert_from_unsigned(r, m_data);
-    return *this;
-  }
-
-  inf& inf::operator = (int r)
-  {
-    convert_from_signed(r, m_data);
-    return *this;
-  }
-
-  inf& inf::operator = (unsigned r)
-  {
-    convert_from_unsigned(r, m_data);
-    return *this;
-  }
-
-  inf& inf::operator = (long r)
-  {
-    convert_from_signed(r, m_data);
-    return *this;
-  }
-
-  inf& inf::operator = (unsigned long r)
-  {
-    convert_from_unsigned(r, m_data);
-    return *this;
-  }
-
-  inf& inf::operator = (const std::string& r) throw(std::invalid_argument)
-  {
-    convert_from_string(r, *this);
-    return *this;
-  }
-
-  inf& inf::operator = (const inf& r)
-  {
-    m_data = r.m_data;
-    return *this;
-  }
-
-  ////////////////////////////////////////////////////////////////////////////////
-
-  short inf::to_short(bool truncate) const throw(std::overflow_error)
-  {
-    short result = 0;
-    if (!convert_to_signed(m_data, result))
-      if (!truncate)
-        throw std::overflow_error("stlplus::inf::to_short");
-    return result;
-  }
-
-  unsigned short inf::to_unsigned_short(bool truncate) const throw(std::overflow_error)
-  {
-    unsigned short result = 0;
-    if (!convert_to_unsigned(m_data, result))
-      if (!truncate)
-        throw std::overflow_error("stlplus::inf::to_unsigned_short");
-    return result;
-  }
-
-  int inf::to_int(bool truncate) const throw(std::overflow_error)
-  {
-    int result = 0;
-    if (!convert_to_signed(m_data, result))
-      if (!truncate)
-        throw std::overflow_error("stlplus::inf::to_int");
-    return result;
-  }
-
-  unsigned inf::to_unsigned(bool truncate) const throw(std::overflow_error)
-  {
-    unsigned result = 0;
-    if (!convert_to_unsigned(m_data, result))
-      if (!truncate)
-        throw std::overflow_error("stlplus::inf::to_unsigned");
-    return result;
-  }
-
-  long inf::to_long(bool truncate) const throw(std::overflow_error)
-  {
-    long result = 0;
-    if (!convert_to_signed(m_data, result))
-      if (!truncate)
-        throw std::overflow_error("stlplus::inf::to_long");
-    return result;
-  }
-
-  unsigned long inf::to_unsigned_long(bool truncate) const throw(std::overflow_error)
-  {
-    unsigned long result = 0;
-    if (!convert_to_unsigned(m_data, result))
-      if (!truncate)
-        throw std::overflow_error("stlplus::inf::to_unsigned_long");
-    return result;
-  }
-
-  ////////////////////////////////////////////////////////////////////////////////
-  // resize the inf regardless of the data
-
-  void inf::resize(unsigned bits)
-  {
-    if (bits == 0) bits = 1;
-    unsigned bytes = (bits+7)/8;
-    byte extend = negative() ? byte(255) : byte (0);
-    while(bytes > m_data.size())
-      m_data.append(1,extend);
-  }
-
-  // reduce the bit count to the minimum needed to preserve the value
-
-  void inf::reduce(void)
-  {
-    reduce_string(m_data);
-  }
-
-  ////////////////////////////////////////////////////////////////////////////////
-  // the number of significant bits in the number
-
-  unsigned inf::bits (void) const
-  {
-    // The number of significant bits in the integer value - this is the number
-    // of indexable bits less any redundant sign bits at the msb
-    // This does not assume that the inf has been reduced to its minimum form
-    unsigned result = indexable_bits();
-    bool sign = bit(result-1);
-    while (result > 1 && (sign == bit(result-2)))
-      result--;
-    return result;
-  }
-
-  unsigned inf::size(void) const
-  {
-    return bits();
-  }
-
-  unsigned inf::indexable_bits (void) const
-  {
-    return 8 * unsigned(m_data.size());
-  }
-
-  ////////////////////////////////////////////////////////////////////////////////
-  // bitwise operations
-
-  bool inf::bit (unsigned index) const throw(std::out_of_range)
-  {
-    if (index >= indexable_bits())
-      throw std::out_of_range(std::string("stlplus::inf::bit"));
-    // first split the offset into byte offset and bit offset
-    unsigned byte_offset = index/8;
-    unsigned bit_offset = index%8;
-    return (byte(m_data[byte_offset]) & (byte(1) << bit_offset)) != 0;
-  }
-
-  bool inf::operator [] (unsigned index) const throw(std::out_of_range)
-  {
-    return bit(index);
-  }
-
-  void inf::set (unsigned index)  throw(std::out_of_range)
-  {
-    if (index >= indexable_bits())
-      throw std::out_of_range(std::string("stlplus::inf::set"));
-    // first split the offset into byte offset and bit offset
-    unsigned byte_offset = index/8;
-    unsigned bit_offset = index%8;
-    m_data[byte_offset] |= (byte(1) << bit_offset);
-  }
-
-  void inf::clear (unsigned index)  throw(std::out_of_range)
-  {
-    if (index >= indexable_bits())
-      throw std::out_of_range(std::string("stlplus::inf::clear"));
-    // first split the offset into byte offset and bit offset
-    unsigned byte_offset = index/8;
-    unsigned bit_offset = index%8;
-    m_data[byte_offset] &= (~(byte(1) << bit_offset));
-  }
-
-  void inf::preset (unsigned index, bool value)  throw(std::out_of_range)
-  {
-    if (value)
-      set(index);
-    else
-      clear(index);
-  }
-
-  inf inf::slice(unsigned low, unsigned high) const throw(std::out_of_range)
-  {
-    if (low >= indexable_bits())
-      throw std::out_of_range(std::string("stlplus::inf::slice: low index"));
-    if (high >= indexable_bits())
-      throw std::out_of_range(std::string("stlplus::inf::slice: high index"));
-    inf result;
-    if (high >= low)
-    {
-      // create a result the right size and filled with sign bits
-      std::string::size_type result_size = (high-low+1+7)/8;
-      result.m_data.erase();
-      byte extend = bit(high) ? byte(255) : byte (0);
-      while (result.m_data.size() < result_size)
-        result.m_data.append(1,extend);
-      // now set the relevant bits
-      for (unsigned i = low; i <= high; i++)
-        result.preset(i-low, bit(i));
-    }
-    return result;
-  }
-
-  ////////////////////////////////////////////////////////////////////////////////
-  // testing operations
-
-  bool inf::negative (void) const
-  {
-    return bit(indexable_bits()-1);
-  }
-
-  bool inf::natural (void) const
-  {
-    return !negative();
-  }
-
-  bool inf::positive (void) const
-  {
-    return natural() && !zero();
-  }
-
-  bool inf::zero (void) const
-  {
-    for (std::string::size_type i = 0; i < m_data.size(); i++)
-      if (m_data[i] != 0)
-        return false;
-    return true;
-  }
-
-  bool inf::non_zero (void) const
-  {
-    return !zero();
-  }
-
-  bool inf::operator ! (void) const
-  {
-    return zero();
-  }
-
-  ////////////////////////////////////////////////////////////////////////////////
-  // comparison operators
-
-  bool inf::operator == (const inf& r) const
-  {
-    // Two infs are equal if they are numerically equal, even if they are
-    // different sizes (i.e. they could be non-reduced values).
-    // This makes life a little more complicated than if I could assume that values were reduced.
-    byte l_extend = negative() ? byte(255) : byte (0);
-    byte r_extend = r.negative() ? byte(255) : byte (0);
-    std::string::size_type bytes = maximum(m_data.size(),r.m_data.size());
-    for (std::string::size_type i = bytes; i--; )
-    {
-      byte l_byte = (i < m_data.size() ? byte(m_data[i]) : l_extend);
-      byte r_byte = (i < r.m_data.size() ? byte(r.m_data[i]) : r_extend);
-      if (l_byte != r_byte)
-        return false;
-    }
-    return true;
-  }
-
-  bool inf::operator != (const inf& r) const
-  {
-    return !operator==(r);
-  }
-
-  bool inf::operator < (const inf& r) const
-  {
-    // This could be implemented in terms of subtraction. However, it can be
-    // simplified since there is no need to calculate the accurate difference,
-    // just the direction of the difference. I compare from msB down and as
-    // soon as a byte difference is found, that defines the ordering. The
-    // problem is that in 2's-complement, all negative values are greater than
-    // all natural values if you just do a straight unsigned comparison. I
-    // handle this by doing a preliminary test for different signs.
-
-    // For example, a 3-bit signed type has the coding:
-    // 000 = 0
-    // ...
-    // 011 = 3
-    // 100 = -4
-    // ...
-    // 111 = -1
-
-    // So, for natural values, the ordering of the integer values is the
-    // ordering of the bit patterns. Similarly, for negative values, the
-    // ordering of the integer values is the ordering of the bit patterns
-    // However, the bit patterns for the negative values are *greater than*
-    // the natural values. This is a side-effect of the naffness of
-    // 2's-complement representation
-
-    // first handle the case of comparing two values with different signs
-    bool l_sign = negative();
-    bool r_sign = r.negative();
-    if (l_sign != r_sign)
-    {
-      // one argument must be negative and the other natural
-      // the left is less if it is the negative one
-      return l_sign;
-    }
-    // the arguments are the same sign
-    // so the ordering is a simple unsigned byte-by-byte comparison
-    // However, this is complicated by the possibility that the values could be different lengths
-    byte l_extend = l_sign ? byte(255) : byte (0);
-    byte r_extend = r_sign ? byte(255) : byte (0);
-    std::string::size_type bytes = maximum(m_data.size(),r.m_data.size());
-    for (std::string::size_type i = bytes; i--; )
-    {
-      byte l_byte = (i < m_data.size() ? byte(m_data[i]) : l_extend);
-      byte r_byte = (i < r.m_data.size() ? byte(r.m_data[i]) : r_extend);
-      if (l_byte != r_byte)
-        return l_byte < r_byte;
-    }
-    // if I get here, the two are equal, so that is not less-than
-    return false;
-  }
-
-  bool inf::operator <= (const inf& r) const
-  {
-    return !(r < *this);
-  }
-
-  bool inf::operator > (const inf& r) const
-  {
-    return r < *this;
-  }
-
-  bool inf::operator >= (const inf& r) const
-  {
-    return !(*this < r);
-  }
-
-  ////////////////////////////////////////////////////////////////////////////////
-  // logical operators
-
-  inf& inf::invert (void)
-  {
-    for (std::string::size_type i = 0; i < m_data.size(); i++)
-      m_data[i] = ~m_data[i];
-    return *this;
-  }
-
-  inf inf::operator ~ (void) const
-  {
-    inf result(*this);
-    result.invert();
-    return result;
-  }
-
-  inf& inf::operator &= (const inf& r)
-  {
-    // bitwise AND is extended to the length of the largest argument
-    byte l_extend = negative() ? byte(255) : byte (0);
-    byte r_extend = r.negative() ? byte(255) : byte (0);
-    std::string::size_type bytes = maximum(m_data.size(),r.m_data.size());
-    for (std::string::size_type i = 0; i < bytes; i++)
-    {
-      byte l_byte = (i < m_data.size() ? byte(m_data[i]) : l_extend);
-      byte r_byte = (i < r.m_data.size() ? byte(r.m_data[i]) : r_extend);
-      byte result = l_byte & r_byte;
-      if (i < m_data.size())
-        m_data[i] = result;
-      else
-        m_data.append(1,result);
-    }
-    // now reduce the result
-    reduce();
-    return *this;
-  }
-
-  inf inf::operator & (const inf& r) const
-  {
-    inf result(*this);
-    result &= r;
-    return result;
-  }
-
-  inf& inf::operator |= (const inf& r)
-  {
-    // bitwise OR is extended to the length of the largest argument
-    byte l_extend = negative() ? byte(255) : byte (0);
-    byte r_extend = r.negative() ? byte(255) : byte (0);
-    std::string::size_type bytes = maximum(m_data.size(),r.m_data.size());
-    for (std::string::size_type i = 0; i < bytes; i++)
-    {
-      byte l_byte = (i < m_data.size() ? byte(m_data[i]) : l_extend);
-      byte r_byte = (i < r.m_data.size() ? byte(r.m_data[i]) : r_extend);
-      byte result = l_byte | r_byte;
-      if (i < m_data.size())
-        m_data[i] = result;
-      else
-        m_data.append(1,result);
-    }
-    // now reduce the result
-    reduce();
-    return *this;
-  }
-
-  inf inf::operator | (const inf& r) const
-  {
-    inf result(*this);
-    result |= r;
-    return result;
-  }
-
-  inf& inf::operator ^= (const inf& r)
-  {
-    // bitwise XOR is extended to the length of the largest argument
-    byte l_extend = negative() ? byte(255) : byte (0);
-    byte r_extend = r.negative() ? byte(255) : byte (0);
-    std::string::size_type bytes = maximum(m_data.size(),r.m_data.size());
-    for (std::string::size_type i = 0; i < bytes; i++)
-    {
-      byte l_byte = (i < m_data.size() ? byte(m_data[i]) : l_extend);
-      byte r_byte = (i < r.m_data.size() ? byte(r.m_data[i]) : r_extend);
-      byte result = l_byte ^ r_byte;
-      if (i < m_data.size())
-        m_data[i] = result;
-      else
-        m_data.append(1,result);
-    }
-    // now reduce the result
-    reduce();
-    return *this;
-  }
-
-  inf inf::operator ^ (const inf& r) const
-  {
-    inf result(*this);
-    result ^= r;
-    return result;
-  }
-
-  ////////////////////////////////////////////////////////////////////////////////
-  // shift operators all preserve the value by increasing the word size
-
-  inf& inf::operator <<= (unsigned shift)
-  {
-    // left shift is a shift towards the msb, with 0s being shifted in at the lsb
-    // split this into a byte shift followed by a bit shift
-
-    // first expand the value to be big enough for the result
-    std::string::size_type new_size = (indexable_bits() + shift + 7) / 8;
-    byte extend = negative() ? byte(255) : byte (0);
-    while (m_data.size() < new_size)
-      m_data.append(1,extend);
-    // now do the byte shift
-    unsigned byte_shift = shift/8;
-    if (byte_shift > 0)
-    {
-      for (std::string::size_type b = new_size; b--; )
-        m_data[b] = (b >= byte_shift) ? m_data[b-byte_shift] : byte(0);
-    }
-    // and finally the bit shift
-    unsigned bit_shift = shift%8;
-    if (bit_shift > 0)
-    {
-      for (std::string::size_type b = new_size; b--; )
-      {
-        byte current = byte(m_data[b]);
-        byte previous = b > 0 ? m_data[b-1] : byte(0);
-        m_data[b] = (current << bit_shift) | (previous >> (8 - bit_shift));
-      }
-    }
-    // now reduce the result
-    reduce();
-    return *this;
-  }
-
-  inf inf::operator << (unsigned shift) const
-  {
-    inf result(*this);
-    result <<= shift;
-    return result;
-  }
-
-  inf& inf::operator >>= (unsigned shift)
-  {
-    // right shift is a shift towards the lsb, with sign bits being shifted in at the msb
-    // split this into a byte shift followed by a bit shift
-
-    // a byte of sign bits
-    byte extend = negative() ? byte(255) : byte (0);
-    // do the byte shift
-    unsigned byte_shift = shift/8;
-    if (byte_shift > 0)
-    {
-      for (std::string::size_type b = 0; b < m_data.size(); b++)
-        m_data[b] = (b + byte_shift < m_data.size()) ? m_data[b+byte_shift] : extend;
-    }
-    // and finally the bit shift
-    unsigned bit_shift = shift%8;
-    if (bit_shift > 0)
-    {
-      for (std::string::size_type b = 0; b < m_data.size(); b++)
-      {
-        byte current = byte(m_data[b]);
-        byte next = ((b+1) < m_data.size()) ? m_data[b+1] : extend;
-        byte shifted = (current >> bit_shift) | (next << (8 - bit_shift));
-        m_data[b] = shifted;
-      }
-    }
-    // now reduce the result
-    reduce();
-    return *this;
-  }
-
-  inf inf::operator >> (unsigned shift) const
-  {
-    inf result(*this);
-    result >>= shift;
-    return result;
-  }
-
-  ////////////////////////////////////////////////////////////////////////////////
-  // negation operators
-
-  inf& inf::negate (void)
-  {
-    // do 2's-complement negation
-    // equivalent to inversion plus one
-    invert();
-    operator += (inf(1));
-    return *this;
-  }
-
-  inf inf::operator - (void) const
-  {
-    inf result(*this);
-    result.negate();
-    return result;
-  }
-
-  inf& inf::abs(void)
-  {
-    if (negative()) negate();
-    return *this;
-  }
-
-  inf abs(const inf& i)
-  {
-    inf result = i;
-    result.abs();
-    return result;
-  }
-
-  ////////////////////////////////////////////////////////////////////////////////
-  // addition operators
-
-  inf& inf::operator += (const inf& r)
-  {
-    // do 2's-complement addition
-    // Note that the addition can give a result that is larger than either argument
-    byte carry = 0;
-    std::string::size_type max_size = maximum(m_data.size(),r.m_data.size());
-    byte l_extend = negative() ? byte(255) : byte (0);
-    byte r_extend = r.negative() ? byte(255) : byte (0);
-    for (std::string::size_type i = 0; i < max_size; i++)
-    {
-      byte l_byte = (i < m_data.size() ? byte(m_data[i]) : l_extend);
-      byte r_byte = (i < r.m_data.size() ? byte(r.m_data[i]) : r_extend);
-      // calculate the addition in a type that is bigger than a byte in order to catch the carry-out
-      unsigned short result = ((unsigned short)(l_byte)) + ((unsigned short)(r_byte)) + carry;
-      // now truncate the result to get the lsB
-      if (i < m_data.size())
-        m_data[i] = byte(result);
-      else
-        m_data.append(1,byte(result));
-      // and capture the carry out by grabbing the second byte of the result
-      carry = byte(result >> 8);
-    }
-    // if the result overflowed or underflowed, add an extra byte to catch it
-    unsigned short result = ((unsigned short)(l_extend)) + ((unsigned short)(r_extend)) + carry;
-    if (byte(result) != (negative() ? byte(255) : byte(0)))
-      m_data.append(1,byte(result));
-    // now reduce the result
-    reduce();
-    return *this;
-  }
-
-  inf inf::operator + (const inf& r) const
-  {
-    inf result(*this);
-    result += r;
-    return result;
-  }
-
-  ////////////////////////////////////////////////////////////////////////////////
-  // subtraction operators
-
-  inf& inf::operator -= (const inf& r)
-  {
-    // subtraction is defined in terms of negation and addition
-    inf negated = -r;
-    operator += (negated);
-    return *this;
-  }
-
-  inf inf::operator - (const inf& r) const
-  {
-    inf result(*this);
-    result -= r;
-    return result;
-  }
-
-  ////////////////////////////////////////////////////////////////////////////////
-  // multiplication operators
-
-  inf& inf::operator *= (const inf& r)
-  {
-    // 2's complement multiplication
-    // one day I'll do a more efficient version than this based on the underlying representation
-    inf left(*this);
-    inf right = r;
-    // make the right value natural but preserve its sign for later
-    bool right_negative = right.negative();
-    right.abs();
-    // implemented as a series of conditional additions
-    operator = (0);
-    //  left.resize(right.bits() + left.bits() - 1);
-    left <<= right.bits()-1;
-    for (unsigned i = right.bits(); i--; )
-    {
-      if (right[i]) 
-        operator += (left);
-      left >>= 1;
-    }
-    if (right_negative)
-      negate();
-    // now reduce the result
-    reduce();
-    return *this;
-  }
-
-  inf inf::operator * (const inf& r) const
-  {
-    inf result(*this);
-    result *= r;
-    return result;
-  }
-
-  ////////////////////////////////////////////////////////////////////////////////
-  // division and remainder operators
-
-  std::pair<inf,inf> inf::divide(const inf& right) const throw(divide_by_zero)
-  {
-    if (right.zero())
-      throw divide_by_zero("stlplus::inf::divide");
-    inf numerator(*this);
-    inf denominator = right;
-    // make the numerator natural but preserve the sign for later
-    bool numerator_negative = numerator.negative();
-    numerator.abs();
-    // same with the denominator
-    bool denominator_negative = denominator.negative();
-    denominator.abs();
-    // the quotient and remainder will form the result
-    // start with the quotiont zero and the remainder equal to the whole of the
-    // numerator, then do trial subtraction from this
-    inf quotient;
-    inf remainder = numerator;
-    // there's nothing more to do if the numerator is smaller than the denominator
-    // but otherwise do the division
-    if (numerator.bits() >= denominator.bits())
-    {
-      // make the quotient big enough to take the result
-      quotient.resize(numerator.bits());
-      // start with the numerator shifted to the far left
-      unsigned shift = numerator.bits() - denominator.bits();
-      denominator <<= shift;
-      // do the division by repeated subtraction, 
-      for (unsigned i = shift+1; i--; )
-      {
-        if (remainder >= denominator)
-        {
-          remainder -= denominator;
-          quotient.set(i);
-        }
-        denominator >>= 1;
-      }
-    }
-    // now adjust the signs 
-    // x/(-y) == (-x)/y == -(x/y)
-    if (numerator_negative != denominator_negative)
-      quotient.negate();
-    quotient.reduce();
-    // x%(-y) == x%y and (-x)%y == -(x%y)
-    if (numerator_negative)
-      remainder.negate();
-    remainder.reduce();
-    return std::pair<inf,inf>(quotient,remainder);
-  }
-
-  inf& inf::operator /= (const inf& r) throw(divide_by_zero)
-  {
-    std::pair<inf,inf> result = divide(r);
-    operator=(result.first);
-    return *this;
-  }
-
-  inf inf::operator / (const inf& r) const throw(divide_by_zero)
-  {
-    std::pair<inf,inf> result = divide(r);
-    return result.first;
-  }
-
-  inf& inf::operator %= (const inf& r) throw(divide_by_zero)
-  {
-    std::pair<inf,inf> result = divide(r);
-    operator=(result.second);
-    return *this;
-  }
-
-  inf inf::operator % (const inf& r) const throw(divide_by_zero)
-  {
-    std::pair<inf,inf> result = divide(r);
-    return result.second;
-  }
-
-  ////////////////////////////////////////////////////////////////////////////////
-  // prefix (void) and postfix (int) operators
-
-  inf& inf::operator ++ (void)
-  {
-    operator += (inf(1));
-    return *this;
-  }
-
-  inf inf::operator ++ (int)
-  {
-    inf old(*this);
-    operator += (inf(1));
-    return old;
-  }
-
-  inf& inf::operator -- (void)
-  {
-    operator -= (inf(1));
-    return *this;
-  }
-
-  inf inf::operator -- (int)
-  {
-    inf old(*this);
-    operator -= (inf(1));
-    return old;
-  }
-
-  ////////////////////////////////////////////////////////////////////////////////
-  // string representation and I/O routines
-
-  std::string inf::to_string(unsigned radix) const
-    throw(std::invalid_argument)
-  {
-    std::string result;
-    convert_to_string(*this, result, radix);
-    return result;
-  }
-
-  inf& inf::from_string(const std::string& value, unsigned radix)
-    throw(std::invalid_argument)
-  {
-    convert_from_string(value, *this, radix);
-    return *this;
-  }
-
-  std::ostream& operator << (std::ostream& str, const inf& i)
-  {
-    try
-    {
-      // get radix
-      unsigned radix = 10;
-      if (str.flags() & std::ios_base::oct)
-        radix = 8;
-      if (str.flags() & std::ios_base::hex)
-        radix = 16;
-      // the field width is handled by iostream, so I don't need to handle it as well
-      // generate the string representation then print it
-      str << i.to_string(radix);
-    }
-    catch(const std::invalid_argument)
-    {
-      str.setstate(std::ios_base::badbit);
-    }
-    return str;
-  }
-
-  std::istream& operator >> (std::istream& str, inf& i)
-  {
-    try
-    {
-      // get radix
-      unsigned radix = 10;
-      if (str.flags() & std::ios_base::oct)
-        radix = 8;
-      if (str.flags() & std::ios_base::hex)
-        radix = 16;
-      // now get the string image of the value
-      std::string image;
-      str >> image;
-      // and convert to inf
-      i.from_string(image, radix);
-    }
-    catch(const std::invalid_argument)
-    {
-      str.setstate(std::ios_base::badbit);
-    }
-    return str;
-  }
-
-  ////////////////////////////////////////////////////////////////////////////////
-  // diagnostic dump
-  // just convert to hex
-
-  std::string inf::image_debug(void) const
-  {
-    // create this dump in the human-readable form, i.e. msB to the left
-    std::string result = "0x";
-    for (std::string::size_type i = m_data.size(); i--; )
-    {
-      byte current = m_data[i];
-      byte msB = (current & byte(0xf0)) >> 4;
-      result += to_char[msB];
-      byte lsB = (current & byte(0x0f));
-      result += to_char[lsB];
-    }
-    return result;
-  }
-
-  const std::string& inf::get_bytes(void) const
-  {
-    return m_data;
-  }
-
-  void inf::set_bytes(const std::string& data)
-  {
-    m_data = data;
-  }
-
-} // end namespace stlplus
+////////////////////////////////////////////////////////////////////////////////\r
+\r
+//   Author:    Andy Rushton\r
+//   Copyright: (c) Southampton University 1999-2004\r
+//              (c) Andy Rushton           2004 onwards\r
+//   License:   BSD License, see ../docs/license.html\r
+\r
+//   The integer is represented as a sequence of bytes. They are stored such that\r
+//   element 0 is the lsB, which makes sense when seen as an integer offset but\r
+//   is counter-intuitive when you think that a string is usually read from left\r
+//   to right, 0 to size-1, in which case the lsB is on the *left*.\r
+\r
+//   This solution is compatible with 32-bit and 64-bit machines with either\r
+//   little-endian or big-endian representations of integers.\r
+\r
+//   Problem: I'm using std::string, which is an array of char. However, char is\r
+//   not well-defined - it could be signed or unsigned.\r
+\r
+//   In fact, there's no requirement for a char to even be one byte - it can be\r
+//   any size of one byte or more. However, it's just impossible to make any\r
+//   progress with that naffness (thanks to the C non-standardisation committee)\r
+//   and the practice is that char on every platform/compiler I've ever come\r
+//   across is that char = byte.\r
+\r
+//   The algorithms here use unsigned char to represent bit-patterns so I have to\r
+//   be careful to type-cast from char to unsigned char a lot. I use a typedef to\r
+//   make life easier.\r
+\r
+////////////////////////////////////////////////////////////////////////////////\r
+#include "inf.hpp"\r
+#include <ctype.h>\r
+////////////////////////////////////////////////////////////////////////////////\r
+\r
+namespace stlplus\r
+{\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // choose a sensible C type for a byte\r
+\r
+  typedef unsigned char byte;\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // local functions\r
+\r
+  // removes leading bytes that don't contribute to the value to create the minimum string representation\r
+  static void reduce_string(std::string& data)\r
+  {\r
+    while(data.size() > 1 && \r
+          ((byte(data[data.size()-1]) == byte(0) && byte(data[data.size()-2]) < byte(128)) ||\r
+           (byte(data[data.size()-1]) == byte(255) && byte(data[data.size()-2]) >= byte(128))))\r
+    {\r
+      data.erase(data.end()-1);\r
+    }\r
+  }\r
+\r
+  // generic implementations of type conversions from integer type to internal representation\r
+  // data: integer value for conversion\r
+  // result: internal representation\r
+\r
+  template <typename T>\r
+  static void convert_from_signed(const T& data, std::string& result)\r
+  {\r
+    result.erase();\r
+    bool lsb_first = little_endian();\r
+    byte* address = (byte*)&data;\r
+    for (size_t i = 0; i < sizeof(T); i++)\r
+    {\r
+      size_t offset = (lsb_first ? i : (sizeof(T) - i - 1));\r
+      result.append(1,address[offset]);\r
+    }\r
+    reduce_string(result);\r
+  }\r
+\r
+  template <typename T>\r
+  static void convert_from_unsigned(const T& data, std::string& result)\r
+  {\r
+    result.erase();\r
+    bool lsb_first = little_endian();\r
+    byte* address = (byte*)&data;\r
+    for (size_t i = 0; i < sizeof(T); i++)\r
+    {\r
+      size_t offset = (lsb_first ? i : (sizeof(T) - i - 1));\r
+      result.append(1,address[offset]);\r
+    }\r
+    // inf is signed - so there is a possible extra sign bit to add\r
+    result.append(1,std::string::value_type(0));\r
+    reduce_string(result);\r
+  }\r
+\r
+  // generic implementations of type conversions from internal representation to an integer type\r
+  // data : string representation of integer\r
+  // result: integer result of conversion\r
+  // return: flag indicating success - false = overflow\r
+\r
+  template <class T>\r
+  bool convert_to_signed(const std::string& data, T& result)\r
+  {\r
+    bool lsb_first = little_endian();\r
+    byte* address = (byte*)&result;\r
+    for (size_t i = 0; i < sizeof(T); i++)\r
+    {\r
+      size_t offset = lsb_first ? i : (sizeof(T) - i - 1);\r
+      if (i < data.size())\r
+        address[offset] = byte(data[i]);\r
+      else if (data.empty() || (byte(data[data.size()-1]) < byte(128)))\r
+        address[offset] = byte(0);\r
+      else\r
+        address[offset] = byte(255);\r
+    }\r
+    return data.size() <= sizeof(T);\r
+  }\r
+\r
+  template <class T>\r
+  bool convert_to_unsigned(const std::string& data, T& result)\r
+  {\r
+    bool lsb_first = little_endian();\r
+    byte* address = (byte*)&result;\r
+    for (size_t i = 0; i < sizeof(T); i++)\r
+    {\r
+      size_t offset = lsb_first ? i : (sizeof(T) - i - 1);\r
+      if (i < data.size())\r
+        address[offset] = byte(data[i]);\r
+      else\r
+        address[offset] = byte(0);\r
+    }\r
+    return data.size() <= sizeof(T);\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // Conversions to string\r
+\r
+  static char to_char [] = "0123456789abcdefghijklmnopqrstuvwxyz";\r
+  static int from_char [] = \r
+  {\r
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
+    0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,\r
+    -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\r
+    25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,\r
+    -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\r
+    25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,\r
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1\r
+  };\r
+\r
+  static void convert_to_string(const stlplus::inf& data, std::string& result, unsigned radix = 10)\r
+    throw(std::invalid_argument)\r
+  {\r
+    // only support the C-style radixes plus 0b for binary\r
+    if (radix != 2 && radix != 8 && radix != 10 && radix != 16)\r
+      throw std::invalid_argument("invalid radix value");\r
+    inf local_i = data;\r
+    // untangle all the options\r
+    bool binary = radix == 2;\r
+    bool octal = radix == 8;\r
+    bool hex = radix == 16;\r
+    // the C representations for binary, octal and hex use 2's-complement representation\r
+    // all other represenations use sign-magnitude\r
+    if (hex || octal || binary)\r
+    {\r
+      // bit-pattern representation\r
+      // this is the binary representation optionally shown in octal or hex\r
+      // first generate the binary by masking the bits\r
+      for (unsigned j = local_i.bits(); j--; )\r
+        result += (local_i.bit(j) ? '1' : '0');\r
+      // the result is now the full width of the type - e.g. int will give a 32-bit result\r
+      // now interpret this as either binary, octal or hex and add the prefix\r
+      if (binary)\r
+      {\r
+        // trim down to the smallest string that preserves the value\r
+        while (true)\r
+        {\r
+          // do not trim to less than 1 bit (sign only)\r
+          if (result.size() <= 1) break;\r
+          // only trim if it doesn't change the sign and therefore the value\r
+          if (result[0] != result[1]) break;\r
+          result.erase(0,1);\r
+        }\r
+        // add the prefix\r
+        result.insert((std::string::size_type)0, "0b");\r
+      }\r
+      else if (octal)\r
+      {\r
+        // the result is currently binary\r
+        // trim down to the smallest string that preserves the value\r
+        while (true)\r
+        {\r
+          // do not trim to less than 2 bits (sign plus 1-bit magnitude)\r
+          if (result.size() <= 2) break;\r
+          // only trim if it doesn't change the sign and therefore the value\r
+          if (result[0] != result[1]) break;\r
+          result.erase(0,1);\r
+        }\r
+        // also ensure that the binary is a multiple of 3 bits to make the conversion to octal easier\r
+        while (result.size() % 3 != 0)\r
+          result.insert((std::string::size_type)0, 1, result[0]);\r
+        // now convert to octal\r
+        std::string octal_result;\r
+        for (unsigned i = 0; i < result.size()/3; i++)\r
+        {\r
+          // yuck - ugly or what?\r
+          if (result[i*3] == '0')\r
+          {\r
+            if (result[i*3+1] == '0')\r
+            {\r
+              if (result[i*3+2] == '0')\r
+                octal_result += '0';\r
+              else\r
+                octal_result += '1';\r
+            }\r
+            else\r
+            {\r
+              if (result[i*3+2] == '0')\r
+                octal_result += '2';\r
+              else\r
+                octal_result += '3';\r
+            }\r
+          }\r
+          else\r
+          {\r
+            if (result[i*3+1] == '0')\r
+            {\r
+              if (result[i*3+2] == '0')\r
+                octal_result += '4';\r
+              else\r
+                octal_result += '5';\r
+            }\r
+            else\r
+            {\r
+              if (result[i*3+2] == '0')\r
+                octal_result += '6';\r
+              else\r
+                octal_result += '7';\r
+            }\r
+          }\r
+        }\r
+        result = octal_result;\r
+        // add the prefix\r
+        result.insert((std::string::size_type)0, "0");\r
+      }\r
+      else\r
+      {\r
+        // similar to octal\r
+        while (true)\r
+        {\r
+          // do not trim to less than 2 bits (sign plus 1-bit magnitude)\r
+          if (result.size() <= 2) break;\r
+          // only trim if it doesn't change the sign and therefore the value\r
+          if (result[0] != result[1]) break;\r
+          result.erase(0,1);\r
+        }\r
+        // pad to a multiple of 4 characters\r
+        while (result.size() % 4 != 0)\r
+          result.insert((std::string::size_type)0, 1, result[0]);\r
+        // now convert to hex\r
+        std::string hex_result;\r
+        for (unsigned i = 0; i < result.size()/4; i++)\r
+        {\r
+          // yuck - ugly or what?\r
+          if (result[i*4] == '0')\r
+          {\r
+            if (result[i*4+1] == '0')\r
+            {\r
+              if (result[i*4+2] == '0')\r
+              {\r
+                if (result[i*4+3] == '0')\r
+                  hex_result += '0';\r
+                else\r
+                  hex_result += '1';\r
+              }\r
+              else\r
+              {\r
+                if (result[i*4+3] == '0')\r
+                  hex_result += '2';\r
+                else\r
+                  hex_result += '3';\r
+              }\r
+            }\r
+            else\r
+            {\r
+              if (result[i*4+2] == '0')\r
+              {\r
+                if (result[i*4+3] == '0')\r
+                  hex_result += '4';\r
+                else\r
+                  hex_result += '5';\r
+              }\r
+              else\r
+              {\r
+                if (result[i*4+3] == '0')\r
+                  hex_result += '6';\r
+                else\r
+                  hex_result += '7';\r
+              }\r
+            }\r
+          }\r
+          else\r
+          {\r
+            if (result[i*4+1] == '0')\r
+            {\r
+              if (result[i*4+2] == '0')\r
+              {\r
+                if (result[i*4+3] == '0')\r
+                  hex_result += '8';\r
+                else\r
+                  hex_result += '9';\r
+              }\r
+              else\r
+              {\r
+                if (result[i*4+3] == '0')\r
+                  hex_result += 'a';\r
+                else\r
+                  hex_result += 'b';\r
+              }\r
+            }\r
+            else\r
+            {\r
+              if (result[i*4+2] == '0')\r
+              {\r
+                if (result[i*4+3] == '0')\r
+                  hex_result += 'c';\r
+                else\r
+                  hex_result += 'd';\r
+              }\r
+              else\r
+              {\r
+                if (result[i*4+3] == '0')\r
+                  hex_result += 'e';\r
+                else\r
+                  hex_result += 'f';\r
+              }\r
+            }\r
+          }\r
+        }\r
+        result = hex_result;\r
+        // add the prefix\r
+        result.insert((std::string::size_type)0, "0x");\r
+      }\r
+    }\r
+    else\r
+    {\r
+      // convert to sign-magnitude\r
+      // the representation is:\r
+      // [sign]magnitude\r
+      bool negative = local_i.negative();\r
+      local_i.abs();\r
+      // create a representation of the magnitude by successive division\r
+      inf inf_radix(radix);\r
+      do\r
+      {\r
+        std::pair<inf,inf> divided = local_i.divide(inf_radix);\r
+        unsigned remainder = divided.second.to_unsigned();\r
+        char digit = to_char[remainder];\r
+        result.insert((std::string::size_type)0, 1, digit);\r
+        local_i = divided.first;\r
+      }\r
+      while(!local_i.zero());\r
+      // add the prefixes\r
+      // add a sign only for negative values\r
+      if (negative)\r
+        result.insert((std::string::size_type)0, 1, '-');\r
+    }\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // Conversions FROM string\r
+\r
+  void convert_from_string(const std::string& str, inf& result, unsigned radix = 10) throw(std::invalid_argument)\r
+  {\r
+    result = 0;\r
+    // only support the C-style radixes plus 0b for binary\r
+    // a radix of 0 means deduce the radix from the input - assume 10\r
+    if (radix != 0 && radix != 2 && radix != 8 && radix != 10 && radix != 16)\r
+      throw std::invalid_argument("invalid radix value");\r
+    unsigned i = 0;\r
+    // the radix passed as a parameter is just the default - it can be\r
+    // overridden by the C prefix\r
+    // Note: a leading zero is the C-style prefix for octal - I only make this\r
+    // override the default when the default radix is not specified\r
+    // first check for a C-style prefix\r
+    bool c_style = false;\r
+    if (i < str.size() && str[i] == '0')\r
+    {\r
+      // binary or hex\r
+      if (i+1 < str.size() && tolower(str[i+1]) == 'x')\r
+      {\r
+        c_style = true;\r
+        radix = 16;\r
+        i += 2;\r
+      }\r
+      else if (i+1 < str.size() && tolower(str[i+1]) == 'b')\r
+      {\r
+        c_style = true;\r
+        radix = 2;\r
+        i += 2;\r
+      }\r
+      else if (radix == 0)\r
+      {\r
+        c_style = true;\r
+        radix = 8;\r
+        i += 1;\r
+      }\r
+    }\r
+    if (radix == 0)\r
+      radix = 10;\r
+    if (c_style)\r
+    {\r
+      // the C style formats are bit patterns not integer values - these need\r
+      // to be sign-extended to get the right value\r
+      std::string binary;\r
+      if (radix == 2)\r
+      {\r
+        for (unsigned j = i; j < str.size(); j++)\r
+        {\r
+          switch(str[j])\r
+          {\r
+          case '0':\r
+            binary += '0';\r
+            break;\r
+          case '1':\r
+            binary += '1';\r
+            break;\r
+          default:\r
+            throw std::invalid_argument("invalid binary character in string " + str);\r
+          }\r
+        }\r
+      }\r
+      else if (radix == 8)\r
+      {\r
+        for (unsigned j = i; j < str.size(); j++)\r
+        {\r
+          switch(str[j])\r
+          {\r
+          case '0':\r
+            binary += "000";\r
+            break;\r
+          case '1':\r
+            binary += "001";\r
+            break;\r
+          case '2':\r
+            binary += "010";\r
+            break;\r
+          case '3':\r
+            binary += "011";\r
+            break;\r
+          case '4':\r
+            binary += "100";\r
+            break;\r
+          case '5':\r
+            binary += "101";\r
+            break;\r
+          case '6':\r
+            binary += "110";\r
+            break;\r
+          case '7':\r
+            binary += "111";\r
+            break;\r
+          default:\r
+            throw std::invalid_argument("invalid octal character in string " + str);\r
+          }\r
+        }\r
+      }\r
+      else\r
+      {\r
+        for (unsigned j = i; j < str.size(); j++)\r
+        {\r
+          switch(tolower(str[j]))\r
+          {\r
+          case '0':\r
+            binary += "0000";\r
+            break;\r
+          case '1':\r
+            binary += "0001";\r
+            break;\r
+          case '2':\r
+            binary += "0010";\r
+            break;\r
+          case '3':\r
+            binary += "0011";\r
+            break;\r
+          case '4':\r
+            binary += "0100";\r
+            break;\r
+          case '5':\r
+            binary += "0101";\r
+            break;\r
+          case '6':\r
+            binary += "0110";\r
+            break;\r
+          case '7':\r
+            binary += "0111";\r
+            break;\r
+          case '8':\r
+            binary += "1000";\r
+            break;\r
+          case '9':\r
+            binary += "1001";\r
+            break;\r
+          case 'a':\r
+            binary += "1010";\r
+            break;\r
+          case 'b':\r
+            binary += "1011";\r
+            break;\r
+          case 'c':\r
+            binary += "1100";\r
+            break;\r
+          case 'd':\r
+            binary += "1101";\r
+            break;\r
+          case 'e':\r
+            binary += "1110";\r
+            break;\r
+          case 'f':\r
+            binary += "1111";\r
+            break;\r
+          default:\r
+            throw std::invalid_argument("invalid hex character in string " + str);\r
+          }\r
+        }\r
+      }\r
+      // now convert the value\r
+      result.resize(binary.size());\r
+      for (unsigned j = 0; j < binary.size(); j++)\r
+        result.preset(binary.size() - j - 1, binary[j] == '1');\r
+    }\r
+    else\r
+    {\r
+      // sign-magnitude representation\r
+      // now scan for a sign and find whether this is a negative number\r
+      bool negative = false;\r
+      if (i < str.size())\r
+      {\r
+        switch (str[i])\r
+        {\r
+        case '-':\r
+          negative = true;\r
+          i++;\r
+          break;\r
+        case '+':\r
+          i++;\r
+          break;\r
+        }\r
+      }\r
+      for (; i < str.size(); i++)\r
+      {\r
+        result *= inf(radix);\r
+        unsigned char ascii = (unsigned char)str[i];\r
+        int ch = from_char[ascii] ;\r
+        if (ch == -1)\r
+          throw std::invalid_argument("invalid decimal character in string " + str);\r
+        result += inf(ch);\r
+      }\r
+      if (negative)\r
+        result.negate();\r
+    }\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // constructors - mostly implemented in terms of the assignment operators\r
+\r
+  inf::inf(void)\r
+  {\r
+    // void constructor initialises to zero - represented as a single-byte value containing zero\r
+    m_data.append(1,std::string::value_type(0));\r
+  }\r
+\r
+  inf::inf(short r)\r
+  {\r
+    operator=(r);\r
+  }\r
+\r
+  inf::inf(unsigned short r)\r
+  {\r
+    operator=(r);\r
+  }\r
+\r
+  inf::inf(int r)\r
+  {\r
+    operator=(r);\r
+  }\r
+\r
+  inf::inf(unsigned r)\r
+  {\r
+    operator=(r);\r
+  }\r
+\r
+  inf::inf(long r)\r
+  {\r
+    operator=(r);\r
+  }\r
+\r
+  inf::inf(unsigned long r)\r
+  {\r
+    operator=(r);\r
+  }\r
+\r
+  inf::inf (const std::string& r) throw(std::invalid_argument)\r
+  {\r
+    operator=(r);\r
+  }\r
+\r
+  inf::inf(const inf& r)\r
+  {\r
+#ifdef __BORLANDC__\r
+    // work round bug in Borland compiler - copy constructor fails if string\r
+    // contains null characters, so do my own copy\r
+    for (unsigned i = 0; i < r.m_data.size(); i++)\r
+      m_data += r.m_data[i];\r
+#else\r
+    m_data = r.m_data;\r
+#endif\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+\r
+  inf::~inf(void)\r
+  {\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // assignments convert from iteger types to internal representation\r
+\r
+  inf& inf::operator = (short r)\r
+  {\r
+    convert_from_signed(r, m_data);\r
+    return *this;\r
+  }\r
+\r
+  inf& inf::operator = (unsigned short r)\r
+  {\r
+    convert_from_unsigned(r, m_data);\r
+    return *this;\r
+  }\r
+\r
+  inf& inf::operator = (int r)\r
+  {\r
+    convert_from_signed(r, m_data);\r
+    return *this;\r
+  }\r
+\r
+  inf& inf::operator = (unsigned r)\r
+  {\r
+    convert_from_unsigned(r, m_data);\r
+    return *this;\r
+  }\r
+\r
+  inf& inf::operator = (long r)\r
+  {\r
+    convert_from_signed(r, m_data);\r
+    return *this;\r
+  }\r
+\r
+  inf& inf::operator = (unsigned long r)\r
+  {\r
+    convert_from_unsigned(r, m_data);\r
+    return *this;\r
+  }\r
+\r
+  inf& inf::operator = (const std::string& r) throw(std::invalid_argument)\r
+  {\r
+    convert_from_string(r, *this);\r
+    return *this;\r
+  }\r
+\r
+  inf& inf::operator = (const inf& r)\r
+  {\r
+    m_data = r.m_data;\r
+    return *this;\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+\r
+  short inf::to_short(bool truncate) const throw(std::overflow_error)\r
+  {\r
+    short result = 0;\r
+    if (!convert_to_signed(m_data, result))\r
+      if (!truncate)\r
+        throw std::overflow_error("stlplus::inf::to_short");\r
+    return result;\r
+  }\r
+\r
+  unsigned short inf::to_unsigned_short(bool truncate) const throw(std::overflow_error)\r
+  {\r
+    unsigned short result = 0;\r
+    if (!convert_to_unsigned(m_data, result))\r
+      if (!truncate)\r
+        throw std::overflow_error("stlplus::inf::to_unsigned_short");\r
+    return result;\r
+  }\r
+\r
+  int inf::to_int(bool truncate) const throw(std::overflow_error)\r
+  {\r
+    int result = 0;\r
+    if (!convert_to_signed(m_data, result))\r
+      if (!truncate)\r
+        throw std::overflow_error("stlplus::inf::to_int");\r
+    return result;\r
+  }\r
+\r
+  unsigned inf::to_unsigned(bool truncate) const throw(std::overflow_error)\r
+  {\r
+    unsigned result = 0;\r
+    if (!convert_to_unsigned(m_data, result))\r
+      if (!truncate)\r
+        throw std::overflow_error("stlplus::inf::to_unsigned");\r
+    return result;\r
+  }\r
+\r
+  long inf::to_long(bool truncate) const throw(std::overflow_error)\r
+  {\r
+    long result = 0;\r
+    if (!convert_to_signed(m_data, result))\r
+      if (!truncate)\r
+        throw std::overflow_error("stlplus::inf::to_long");\r
+    return result;\r
+  }\r
+\r
+  unsigned long inf::to_unsigned_long(bool truncate) const throw(std::overflow_error)\r
+  {\r
+    unsigned long result = 0;\r
+    if (!convert_to_unsigned(m_data, result))\r
+      if (!truncate)\r
+        throw std::overflow_error("stlplus::inf::to_unsigned_long");\r
+    return result;\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // resize the inf regardless of the data\r
+\r
+  void inf::resize(unsigned bits)\r
+  {\r
+    if (bits == 0) bits = 1;\r
+    unsigned bytes = (bits+7)/8;\r
+    byte extend = negative() ? byte(255) : byte (0);\r
+    while(bytes > m_data.size())\r
+      m_data.append(1,extend);\r
+  }\r
+\r
+  // reduce the bit count to the minimum needed to preserve the value\r
+\r
+  void inf::reduce(void)\r
+  {\r
+    reduce_string(m_data);\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // the number of significant bits in the number\r
+\r
+  unsigned inf::bits (void) const\r
+  {\r
+    // The number of significant bits in the integer value - this is the number\r
+    // of indexable bits less any redundant sign bits at the msb\r
+    // This does not assume that the inf has been reduced to its minimum form\r
+    unsigned result = indexable_bits();\r
+    bool sign = bit(result-1);\r
+    while (result > 1 && (sign == bit(result-2)))\r
+      result--;\r
+    return result;\r
+  }\r
+\r
+  unsigned inf::size(void) const\r
+  {\r
+    return bits();\r
+  }\r
+\r
+  unsigned inf::indexable_bits (void) const\r
+  {\r
+    return 8 * unsigned(m_data.size());\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // bitwise operations\r
+\r
+  bool inf::bit (unsigned index) const throw(std::out_of_range)\r
+  {\r
+    if (index >= indexable_bits())\r
+      throw std::out_of_range(std::string("stlplus::inf::bit"));\r
+    // first split the offset into byte offset and bit offset\r
+    unsigned byte_offset = index/8;\r
+    unsigned bit_offset = index%8;\r
+    return (byte(m_data[byte_offset]) & (byte(1) << bit_offset)) != 0;\r
+  }\r
+\r
+  bool inf::operator [] (unsigned index) const throw(std::out_of_range)\r
+  {\r
+    return bit(index);\r
+  }\r
+\r
+  void inf::set (unsigned index)  throw(std::out_of_range)\r
+  {\r
+    if (index >= indexable_bits())\r
+      throw std::out_of_range(std::string("stlplus::inf::set"));\r
+    // first split the offset into byte offset and bit offset\r
+    unsigned byte_offset = index/8;\r
+    unsigned bit_offset = index%8;\r
+    m_data[byte_offset] |= (byte(1) << bit_offset);\r
+  }\r
+\r
+  void inf::clear (unsigned index)  throw(std::out_of_range)\r
+  {\r
+    if (index >= indexable_bits())\r
+      throw std::out_of_range(std::string("stlplus::inf::clear"));\r
+    // first split the offset into byte offset and bit offset\r
+    unsigned byte_offset = index/8;\r
+    unsigned bit_offset = index%8;\r
+    m_data[byte_offset] &= (~(byte(1) << bit_offset));\r
+  }\r
+\r
+  void inf::preset (unsigned index, bool value)  throw(std::out_of_range)\r
+  {\r
+    if (value)\r
+      set(index);\r
+    else\r
+      clear(index);\r
+  }\r
+\r
+  inf inf::slice(unsigned low, unsigned high) const throw(std::out_of_range)\r
+  {\r
+    if (low >= indexable_bits())\r
+      throw std::out_of_range(std::string("stlplus::inf::slice: low index"));\r
+    if (high >= indexable_bits())\r
+      throw std::out_of_range(std::string("stlplus::inf::slice: high index"));\r
+    inf result;\r
+    if (high >= low)\r
+    {\r
+      // create a result the right size and filled with sign bits\r
+      std::string::size_type result_size = (high-low+1+7)/8;\r
+      result.m_data.erase();\r
+      byte extend = bit(high) ? byte(255) : byte (0);\r
+      while (result.m_data.size() < result_size)\r
+        result.m_data.append(1,extend);\r
+      // now set the relevant bits\r
+      for (unsigned i = low; i <= high; i++)\r
+        result.preset(i-low, bit(i));\r
+    }\r
+    return result;\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // testing operations\r
+\r
+  bool inf::negative (void) const\r
+  {\r
+    return bit(indexable_bits()-1);\r
+  }\r
+\r
+  bool inf::natural (void) const\r
+  {\r
+    return !negative();\r
+  }\r
+\r
+  bool inf::positive (void) const\r
+  {\r
+    return natural() && !zero();\r
+  }\r
+\r
+  bool inf::zero (void) const\r
+  {\r
+    for (std::string::size_type i = 0; i < m_data.size(); i++)\r
+      if (m_data[i] != 0)\r
+        return false;\r
+    return true;\r
+  }\r
+\r
+  bool inf::non_zero (void) const\r
+  {\r
+    return !zero();\r
+  }\r
+\r
+  bool inf::operator ! (void) const\r
+  {\r
+    return zero();\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // comparison operators\r
+\r
+  bool inf::operator == (const inf& r) const\r
+  {\r
+    // Two infs are equal if they are numerically equal, even if they are\r
+    // different sizes (i.e. they could be non-reduced values).\r
+    // This makes life a little more complicated than if I could assume that values were reduced.\r
+    byte l_extend = negative() ? byte(255) : byte (0);\r
+    byte r_extend = r.negative() ? byte(255) : byte (0);\r
+    std::string::size_type bytes = maximum(m_data.size(),r.m_data.size());\r
+    for (std::string::size_type i = bytes; i--; )\r
+    {\r
+      byte l_byte = (i < m_data.size() ? byte(m_data[i]) : l_extend);\r
+      byte r_byte = (i < r.m_data.size() ? byte(r.m_data[i]) : r_extend);\r
+      if (l_byte != r_byte)\r
+        return false;\r
+    }\r
+    return true;\r
+  }\r
+\r
+  bool inf::operator != (const inf& r) const\r
+  {\r
+    return !operator==(r);\r
+  }\r
+\r
+  bool inf::operator < (const inf& r) const\r
+  {\r
+    // This could be implemented in terms of subtraction. However, it can be\r
+    // simplified since there is no need to calculate the accurate difference,\r
+    // just the direction of the difference. I compare from msB down and as\r
+    // soon as a byte difference is found, that defines the ordering. The\r
+    // problem is that in 2's-complement, all negative values are greater than\r
+    // all natural values if you just do a straight unsigned comparison. I\r
+    // handle this by doing a preliminary test for different signs.\r
+\r
+    // For example, a 3-bit signed type has the coding:\r
+    // 000 = 0\r
+    // ...\r
+    // 011 = 3\r
+    // 100 = -4\r
+    // ...\r
+    // 111 = -1\r
+\r
+    // So, for natural values, the ordering of the integer values is the\r
+    // ordering of the bit patterns. Similarly, for negative values, the\r
+    // ordering of the integer values is the ordering of the bit patterns\r
+    // However, the bit patterns for the negative values are *greater than*\r
+    // the natural values. This is a side-effect of the naffness of\r
+    // 2's-complement representation\r
+\r
+    // first handle the case of comparing two values with different signs\r
+    bool l_sign = negative();\r
+    bool r_sign = r.negative();\r
+    if (l_sign != r_sign)\r
+    {\r
+      // one argument must be negative and the other natural\r
+      // the left is less if it is the negative one\r
+      return l_sign;\r
+    }\r
+    // the arguments are the same sign\r
+    // so the ordering is a simple unsigned byte-by-byte comparison\r
+    // However, this is complicated by the possibility that the values could be different lengths\r
+    byte l_extend = l_sign ? byte(255) : byte (0);\r
+    byte r_extend = r_sign ? byte(255) : byte (0);\r
+    std::string::size_type bytes = maximum(m_data.size(),r.m_data.size());\r
+    for (std::string::size_type i = bytes; i--; )\r
+    {\r
+      byte l_byte = (i < m_data.size() ? byte(m_data[i]) : l_extend);\r
+      byte r_byte = (i < r.m_data.size() ? byte(r.m_data[i]) : r_extend);\r
+      if (l_byte != r_byte)\r
+        return l_byte < r_byte;\r
+    }\r
+    // if I get here, the two are equal, so that is not less-than\r
+    return false;\r
+  }\r
+\r
+  bool inf::operator <= (const inf& r) const\r
+  {\r
+    return !(r < *this);\r
+  }\r
+\r
+  bool inf::operator > (const inf& r) const\r
+  {\r
+    return r < *this;\r
+  }\r
+\r
+  bool inf::operator >= (const inf& r) const\r
+  {\r
+    return !(*this < r);\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // logical operators\r
+\r
+  inf& inf::invert (void)\r
+  {\r
+    for (std::string::size_type i = 0; i < m_data.size(); i++)\r
+      m_data[i] = ~m_data[i];\r
+    return *this;\r
+  }\r
+\r
+  inf inf::operator ~ (void) const\r
+  {\r
+    inf result(*this);\r
+    result.invert();\r
+    return result;\r
+  }\r
+\r
+  inf& inf::operator &= (const inf& r)\r
+  {\r
+    // bitwise AND is extended to the length of the largest argument\r
+    byte l_extend = negative() ? byte(255) : byte (0);\r
+    byte r_extend = r.negative() ? byte(255) : byte (0);\r
+    std::string::size_type bytes = maximum(m_data.size(),r.m_data.size());\r
+    for (std::string::size_type i = 0; i < bytes; i++)\r
+    {\r
+      byte l_byte = (i < m_data.size() ? byte(m_data[i]) : l_extend);\r
+      byte r_byte = (i < r.m_data.size() ? byte(r.m_data[i]) : r_extend);\r
+      byte result = l_byte & r_byte;\r
+      if (i < m_data.size())\r
+        m_data[i] = result;\r
+      else\r
+        m_data.append(1,result);\r
+    }\r
+    // now reduce the result\r
+    reduce();\r
+    return *this;\r
+  }\r
+\r
+  inf inf::operator & (const inf& r) const\r
+  {\r
+    inf result(*this);\r
+    result &= r;\r
+    return result;\r
+  }\r
+\r
+  inf& inf::operator |= (const inf& r)\r
+  {\r
+    // bitwise OR is extended to the length of the largest argument\r
+    byte l_extend = negative() ? byte(255) : byte (0);\r
+    byte r_extend = r.negative() ? byte(255) : byte (0);\r
+    std::string::size_type bytes = maximum(m_data.size(),r.m_data.size());\r
+    for (std::string::size_type i = 0; i < bytes; i++)\r
+    {\r
+      byte l_byte = (i < m_data.size() ? byte(m_data[i]) : l_extend);\r
+      byte r_byte = (i < r.m_data.size() ? byte(r.m_data[i]) : r_extend);\r
+      byte result = l_byte | r_byte;\r
+      if (i < m_data.size())\r
+        m_data[i] = result;\r
+      else\r
+        m_data.append(1,result);\r
+    }\r
+    // now reduce the result\r
+    reduce();\r
+    return *this;\r
+  }\r
+\r
+  inf inf::operator | (const inf& r) const\r
+  {\r
+    inf result(*this);\r
+    result |= r;\r
+    return result;\r
+  }\r
+\r
+  inf& inf::operator ^= (const inf& r)\r
+  {\r
+    // bitwise XOR is extended to the length of the largest argument\r
+    byte l_extend = negative() ? byte(255) : byte (0);\r
+    byte r_extend = r.negative() ? byte(255) : byte (0);\r
+    std::string::size_type bytes = maximum(m_data.size(),r.m_data.size());\r
+    for (std::string::size_type i = 0; i < bytes; i++)\r
+    {\r
+      byte l_byte = (i < m_data.size() ? byte(m_data[i]) : l_extend);\r
+      byte r_byte = (i < r.m_data.size() ? byte(r.m_data[i]) : r_extend);\r
+      byte result = l_byte ^ r_byte;\r
+      if (i < m_data.size())\r
+        m_data[i] = result;\r
+      else\r
+        m_data.append(1,result);\r
+    }\r
+    // now reduce the result\r
+    reduce();\r
+    return *this;\r
+  }\r
+\r
+  inf inf::operator ^ (const inf& r) const\r
+  {\r
+    inf result(*this);\r
+    result ^= r;\r
+    return result;\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // shift operators all preserve the value by increasing the word size\r
+\r
+  inf& inf::operator <<= (unsigned shift)\r
+  {\r
+    // left shift is a shift towards the msb, with 0s being shifted in at the lsb\r
+    // split this into a byte shift followed by a bit shift\r
+\r
+    // first expand the value to be big enough for the result\r
+    std::string::size_type new_size = (indexable_bits() + shift + 7) / 8;\r
+    byte extend = negative() ? byte(255) : byte (0);\r
+    while (m_data.size() < new_size)\r
+      m_data.append(1,extend);\r
+    // now do the byte shift\r
+    unsigned byte_shift = shift/8;\r
+    if (byte_shift > 0)\r
+    {\r
+      for (std::string::size_type b = new_size; b--; )\r
+        m_data[b] = (b >= byte_shift) ? m_data[b-byte_shift] : byte(0);\r
+    }\r
+    // and finally the bit shift\r
+    unsigned bit_shift = shift%8;\r
+    if (bit_shift > 0)\r
+    {\r
+      for (std::string::size_type b = new_size; b--; )\r
+      {\r
+        byte current = byte(m_data[b]);\r
+        byte previous = b > 0 ? m_data[b-1] : byte(0);\r
+        m_data[b] = (current << bit_shift) | (previous >> (8 - bit_shift));\r
+      }\r
+    }\r
+    // now reduce the result\r
+    reduce();\r
+    return *this;\r
+  }\r
+\r
+  inf inf::operator << (unsigned shift) const\r
+  {\r
+    inf result(*this);\r
+    result <<= shift;\r
+    return result;\r
+  }\r
+\r
+  inf& inf::operator >>= (unsigned shift)\r
+  {\r
+    // right shift is a shift towards the lsb, with sign bits being shifted in at the msb\r
+    // split this into a byte shift followed by a bit shift\r
+\r
+    // a byte of sign bits\r
+    byte extend = negative() ? byte(255) : byte (0);\r
+    // do the byte shift\r
+    unsigned byte_shift = shift/8;\r
+    if (byte_shift > 0)\r
+    {\r
+      for (std::string::size_type b = 0; b < m_data.size(); b++)\r
+        m_data[b] = (b + byte_shift < m_data.size()) ? m_data[b+byte_shift] : extend;\r
+    }\r
+    // and finally the bit shift\r
+    unsigned bit_shift = shift%8;\r
+    if (bit_shift > 0)\r
+    {\r
+      for (std::string::size_type b = 0; b < m_data.size(); b++)\r
+      {\r
+        byte current = byte(m_data[b]);\r
+        byte next = ((b+1) < m_data.size()) ? m_data[b+1] : extend;\r
+        byte shifted = (current >> bit_shift) | (next << (8 - bit_shift));\r
+        m_data[b] = shifted;\r
+      }\r
+    }\r
+    // now reduce the result\r
+    reduce();\r
+    return *this;\r
+  }\r
+\r
+  inf inf::operator >> (unsigned shift) const\r
+  {\r
+    inf result(*this);\r
+    result >>= shift;\r
+    return result;\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // negation operators\r
+\r
+  inf& inf::negate (void)\r
+  {\r
+    // do 2's-complement negation\r
+    // equivalent to inversion plus one\r
+    invert();\r
+    operator += (inf(1));\r
+    return *this;\r
+  }\r
+\r
+  inf inf::operator - (void) const\r
+  {\r
+    inf result(*this);\r
+    result.negate();\r
+    return result;\r
+  }\r
+\r
+  inf& inf::abs(void)\r
+  {\r
+    if (negative()) negate();\r
+    return *this;\r
+  }\r
+\r
+  inf abs(const inf& i)\r
+  {\r
+    inf result = i;\r
+    result.abs();\r
+    return result;\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // addition operators\r
+\r
+  inf& inf::operator += (const inf& r)\r
+  {\r
+    // do 2's-complement addition\r
+    // Note that the addition can give a result that is larger than either argument\r
+    byte carry = 0;\r
+    std::string::size_type max_size = maximum(m_data.size(),r.m_data.size());\r
+    byte l_extend = negative() ? byte(255) : byte (0);\r
+    byte r_extend = r.negative() ? byte(255) : byte (0);\r
+    for (std::string::size_type i = 0; i < max_size; i++)\r
+    {\r
+      byte l_byte = (i < m_data.size() ? byte(m_data[i]) : l_extend);\r
+      byte r_byte = (i < r.m_data.size() ? byte(r.m_data[i]) : r_extend);\r
+      // calculate the addition in a type that is bigger than a byte in order to catch the carry-out\r
+      unsigned short result = ((unsigned short)(l_byte)) + ((unsigned short)(r_byte)) + carry;\r
+      // now truncate the result to get the lsB\r
+      if (i < m_data.size())\r
+        m_data[i] = byte(result);\r
+      else\r
+        m_data.append(1,byte(result));\r
+      // and capture the carry out by grabbing the second byte of the result\r
+      carry = byte(result >> 8);\r
+    }\r
+    // if the result overflowed or underflowed, add an extra byte to catch it\r
+    unsigned short result = ((unsigned short)(l_extend)) + ((unsigned short)(r_extend)) + carry;\r
+    if (byte(result) != (negative() ? byte(255) : byte(0)))\r
+      m_data.append(1,byte(result));\r
+    // now reduce the result\r
+    reduce();\r
+    return *this;\r
+  }\r
+\r
+  inf inf::operator + (const inf& r) const\r
+  {\r
+    inf result(*this);\r
+    result += r;\r
+    return result;\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // subtraction operators\r
+\r
+  inf& inf::operator -= (const inf& r)\r
+  {\r
+    // subtraction is defined in terms of negation and addition\r
+    inf negated = -r;\r
+    operator += (negated);\r
+    return *this;\r
+  }\r
+\r
+  inf inf::operator - (const inf& r) const\r
+  {\r
+    inf result(*this);\r
+    result -= r;\r
+    return result;\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // multiplication operators\r
+\r
+  inf& inf::operator *= (const inf& r)\r
+  {\r
+    // 2's complement multiplication\r
+    // one day I'll do a more efficient version than this based on the underlying representation\r
+    inf left(*this);\r
+    inf right = r;\r
+    // make the right value natural but preserve its sign for later\r
+    bool right_negative = right.negative();\r
+    right.abs();\r
+    // implemented as a series of conditional additions\r
+    operator = (0);\r
+    //  left.resize(right.bits() + left.bits() - 1);\r
+    left <<= right.bits()-1;\r
+    for (unsigned i = right.bits(); i--; )\r
+    {\r
+      if (right[i]) \r
+        operator += (left);\r
+      left >>= 1;\r
+    }\r
+    if (right_negative)\r
+      negate();\r
+    // now reduce the result\r
+    reduce();\r
+    return *this;\r
+  }\r
+\r
+  inf inf::operator * (const inf& r) const\r
+  {\r
+    inf result(*this);\r
+    result *= r;\r
+    return result;\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // division and remainder operators\r
+\r
+  std::pair<inf,inf> inf::divide(const inf& right) const throw(divide_by_zero)\r
+  {\r
+    if (right.zero())\r
+      throw divide_by_zero("stlplus::inf::divide");\r
+    inf numerator(*this);\r
+    inf denominator = right;\r
+    // make the numerator natural but preserve the sign for later\r
+    bool numerator_negative = numerator.negative();\r
+    numerator.abs();\r
+    // same with the denominator\r
+    bool denominator_negative = denominator.negative();\r
+    denominator.abs();\r
+    // the quotient and remainder will form the result\r
+    // start with the quotiont zero and the remainder equal to the whole of the\r
+    // numerator, then do trial subtraction from this\r
+    inf quotient;\r
+    inf remainder = numerator;\r
+    // there's nothing more to do if the numerator is smaller than the denominator\r
+    // but otherwise do the division\r
+    if (numerator.bits() >= denominator.bits())\r
+    {\r
+      // make the quotient big enough to take the result\r
+      quotient.resize(numerator.bits());\r
+      // start with the numerator shifted to the far left\r
+      unsigned shift = numerator.bits() - denominator.bits();\r
+      denominator <<= shift;\r
+      // do the division by repeated subtraction, \r
+      for (unsigned i = shift+1; i--; )\r
+      {\r
+        if (remainder >= denominator)\r
+        {\r
+          remainder -= denominator;\r
+          quotient.set(i);\r
+        }\r
+        denominator >>= 1;\r
+      }\r
+    }\r
+    // now adjust the signs \r
+    // x/(-y) == (-x)/y == -(x/y)\r
+    if (numerator_negative != denominator_negative)\r
+      quotient.negate();\r
+    quotient.reduce();\r
+    // x%(-y) == x%y and (-x)%y == -(x%y)\r
+    if (numerator_negative)\r
+      remainder.negate();\r
+    remainder.reduce();\r
+    return std::pair<inf,inf>(quotient,remainder);\r
+  }\r
+\r
+  inf& inf::operator /= (const inf& r) throw(divide_by_zero)\r
+  {\r
+    std::pair<inf,inf> result = divide(r);\r
+    operator=(result.first);\r
+    return *this;\r
+  }\r
+\r
+  inf inf::operator / (const inf& r) const throw(divide_by_zero)\r
+  {\r
+    std::pair<inf,inf> result = divide(r);\r
+    return result.first;\r
+  }\r
+\r
+  inf& inf::operator %= (const inf& r) throw(divide_by_zero)\r
+  {\r
+    std::pair<inf,inf> result = divide(r);\r
+    operator=(result.second);\r
+    return *this;\r
+  }\r
+\r
+  inf inf::operator % (const inf& r) const throw(divide_by_zero)\r
+  {\r
+    std::pair<inf,inf> result = divide(r);\r
+    return result.second;\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // prefix (void) and postfix (int) operators\r
+\r
+  inf& inf::operator ++ (void)\r
+  {\r
+    operator += (inf(1));\r
+    return *this;\r
+  }\r
+\r
+  inf inf::operator ++ (int)\r
+  {\r
+    inf old(*this);\r
+    operator += (inf(1));\r
+    return old;\r
+  }\r
+\r
+  inf& inf::operator -- (void)\r
+  {\r
+    operator -= (inf(1));\r
+    return *this;\r
+  }\r
+\r
+  inf inf::operator -- (int)\r
+  {\r
+    inf old(*this);\r
+    operator -= (inf(1));\r
+    return old;\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // string representation and I/O routines\r
+\r
+  std::string inf::to_string(unsigned radix) const\r
+    throw(std::invalid_argument)\r
+  {\r
+    std::string result;\r
+    convert_to_string(*this, result, radix);\r
+    return result;\r
+  }\r
+\r
+  inf& inf::from_string(const std::string& value, unsigned radix)\r
+    throw(std::invalid_argument)\r
+  {\r
+    convert_from_string(value, *this, radix);\r
+    return *this;\r
+  }\r
+\r
+  std::ostream& operator << (std::ostream& str, const inf& i)\r
+  {\r
+    try\r
+    {\r
+      // get radix\r
+      unsigned radix = 10;\r
+      if (str.flags() & std::ios_base::oct)\r
+        radix = 8;\r
+      if (str.flags() & std::ios_base::hex)\r
+        radix = 16;\r
+      // the field width is handled by iostream, so I don't need to handle it as well\r
+      // generate the string representation then print it\r
+      str << i.to_string(radix);\r
+    }\r
+    catch(const std::invalid_argument)\r
+    {\r
+      str.setstate(std::ios_base::badbit);\r
+    }\r
+    return str;\r
+  }\r
+\r
+  std::istream& operator >> (std::istream& str, inf& i)\r
+  {\r
+    try\r
+    {\r
+      // get radix\r
+      unsigned radix = 10;\r
+      if (str.flags() & std::ios_base::oct)\r
+        radix = 8;\r
+      if (str.flags() & std::ios_base::hex)\r
+        radix = 16;\r
+      // now get the string image of the value\r
+      std::string image;\r
+      str >> image;\r
+      // and convert to inf\r
+      i.from_string(image, radix);\r
+    }\r
+    catch(const std::invalid_argument)\r
+    {\r
+      str.setstate(std::ios_base::badbit);\r
+    }\r
+    return str;\r
+  }\r
+\r
+  ////////////////////////////////////////////////////////////////////////////////\r
+  // diagnostic dump\r
+  // just convert to hex\r
+\r
+  std::string inf::image_debug(void) const\r
+  {\r
+    // create this dump in the human-readable form, i.e. msB to the left\r
+    std::string result = "0x";\r
+    for (std::string::size_type i = m_data.size(); i--; )\r
+    {\r
+      byte current = m_data[i];\r
+      byte msB = (current & byte(0xf0)) >> 4;\r
+      result += to_char[msB];\r
+      byte lsB = (current & byte(0x0f));\r
+      result += to_char[lsB];\r
+    }\r
+    return result;\r
+  }\r
+\r
+  const std::string& inf::get_bytes(void) const\r
+  {\r
+    return m_data;\r
+  }\r
+\r
+  void inf::set_bytes(const std::string& data)\r
+  {\r
+    m_data = data;\r
+  }\r
+\r
+} // end namespace stlplus\r
This page took 0.139289 seconds and 4 git commands to generate.