portability/inf.hpp

    1: #ifndef STLPLUS_INF
    2: #define STLPLUS_INF
    3: ////////////////////////////////////////////////////////////////////////////////
    4: 
    5: //   Author:    Andy Rushton
    6: //   Copyright: (c) Andy Rushton, 2007
    7: //   License:   BSD License, see ../docs/license.html
    8: 
    9: //   An infinite-precision integer class. This allows calculations on large
   10: //   integers to be performed without overflow.
   11: 
   12: //   this class can throw the following exceptions:
   13: //     std::out_of_range
   14: //     std::overflow_error
   15: //     std::invalid_argument
   16: //     stlplus::divide_by_zero    // why doesn't std have this?
   17: //   all of these are derivations of the baseclass:
   18: //     std::logic_error
   19: //   So you can catch all of them by catching the baseclass
   20: 
   21: //   Warning: inf was never intended to be fast, it is just for programs which
   22: //   need a bit of infinite-precision integer arithmetic. For high-performance
   23: //   processing, use the Gnu Multi-Precision (GMP) library. The inf type is just
   24: //   easier to integrate and is already ported to all platforms and compilers
   25: //   that STLplus is ported to.
   26: 
   27: ////////////////////////////////////////////////////////////////////////////////
   28: #include "portability_fixes.hpp"
   29: #include "portability_exceptions.hpp"
   30: #include <string>
   31: #include <iostream>
   32: 
   33: ////////////////////////////////////////////////////////////////////////////////
   34: 
   35: namespace stlplus
   36: {
   37: 
   38: ////////////////////////////////////////////////////////////////////////////////
   39: 
   40:   class inf
   41:   {
   42:   public:
   43: 
   44:     //////////////////////////////////////////////////////////////////////////////
   45:     // constructors and assignments initialise the inf
   46: 
   47:     // the void constructor initialises to zero, the others initialise to the
   48:     // value of the C integer type or the text value contained in the string
   49: 
   50:     inf(void);
   51:     explicit inf(short);
   52:     explicit inf(unsigned short);
   53:     explicit inf(int);
   54:     explicit inf(unsigned);
   55:     explicit inf(long);
   56:     explicit inf(unsigned long);
   57:     explicit inf(const std::string&) throw(std::invalid_argument);
   58:     inf(const inf&);
   59: 
   60:     ~inf(void);
   61: 
   62:     // assignments with equivalent behaviour to the constructors
   63: 
   64:     inf& operator = (short);
   65:     inf& operator = (unsigned short);
   66:     inf& operator = (int);
   67:     inf& operator = (unsigned);
   68:     inf& operator = (long);
   69:     inf& operator = (unsigned long);
   70:     inf& operator = (const std::string&) throw(std::invalid_argument);
   71:     inf& operator = (const inf&);
   72: 
   73:     //////////////////////////////////////////////////////////////////////////////
   74:     // conversions back to the C types
   75:     // truncate: controls the behaviour when the value is too long for the result
   76:     //           true: truncate the value
   77:     //           false: throw an exception
   78: 
   79:     short to_short(bool truncate = true) const throw(std::overflow_error);
   80:     unsigned short to_unsigned_short(bool truncate = true) const throw(std::overflow_error);
   81: 
   82:     int to_int(bool truncate = true) const throw(std::overflow_error);
   83:     unsigned to_unsigned(bool truncate = true) const throw(std::overflow_error);
   84: 
   85:     long to_long(bool truncate = true) const throw(std::overflow_error);
   86:     unsigned long to_unsigned_long(bool truncate = true) const throw(std::overflow_error);
   87: 
   88:     //////////////////////////////////////////////////////////////////////////////
   89:     // bitwise manipulation
   90: 
   91:     void resize(unsigned bits);
   92:     void reduce(void);
   93: 
   94:     // the number of significant bits in the value
   95:     unsigned bits (void) const;
   96:     unsigned size (void) const;
   97: 
   98:     // the number of bits that can be accessed by the bit() method (=bits() rounded up to the next byte)
   99:     unsigned indexable_bits(void) const;
  100: 
  101:     bool bit (unsigned index) const throw(std::out_of_range);
  102:     bool operator [] (unsigned index) const throw(std::out_of_range);
  103: 
  104:     void set (unsigned index) throw(std::out_of_range);
  105:     void clear (unsigned index) throw(std::out_of_range);
  106:     void preset (unsigned index, bool value) throw(std::out_of_range);
  107: 
  108:     inf slice(unsigned low, unsigned high) const throw(std::out_of_range);
  109: 
  110:     //////////////////////////////////////////////////////////////////////////////
  111:     // tests for common values or ranges
  112: 
  113:     bool negative (void) const;
  114:     bool natural (void) const;
  115:     bool positive (void) const;
  116:     bool zero (void) const;
  117:     bool non_zero (void) const;
  118: 
  119:     // tests used in if(i) and if(!i)
  120: //  operator bool (void) const;
  121:     bool operator ! (void) const;
  122: 
  123:     //////////////////////////////////////////////////////////////////////////////
  124:     // comparisons
  125: 
  126:     bool operator == (const inf&) const;
  127:     bool operator != (const inf&) const;
  128:     bool operator < (const inf&) const;
  129:     bool operator <= (const inf&) const;
  130:     bool operator > (const inf&) const;
  131:     bool operator >= (const inf&) const;
  132: 
  133:     //////////////////////////////////////////////////////////////////////////////
  134:     // bitwise logic operations
  135: 
  136:     inf& invert (void);
  137:     inf operator ~ (void) const;
  138: 
  139:     inf& operator &= (const inf&);
  140:     inf operator & (const inf&) const;
  141: 
  142:     inf& operator |= (const inf&);
  143:     inf operator | (const inf&) const;
  144: 
  145:     inf& operator ^= (const inf&);
  146:     inf operator ^ (const inf&) const;
  147: 
  148:     inf& operator <<= (unsigned shift);
  149:     inf operator << (unsigned shift) const;
  150: 
  151:     inf& operator >>= (unsigned shift);
  152:     inf operator >> (unsigned shift) const;
  153: 
  154:     //////////////////////////////////////////////////////////////////////////////
  155:     // arithmetic operations
  156: 
  157:     inf& negate (void);
  158:     inf operator - (void) const;
  159: 
  160:     inf& abs(void);
  161:     friend inf abs(const inf&);
  162: 
  163:     inf& operator += (const inf&);
  164:     inf operator + (const inf&) const;
  165: 
  166:     inf& operator -= (const inf&);
  167:     inf operator - (const inf&) const;
  168: 
  169:     inf& operator *= (const inf&);
  170:     inf operator * (const inf&) const;
  171: 
  172:     inf& operator /= (const inf&) throw(divide_by_zero);
  173:     inf operator / (const inf&) const throw(divide_by_zero);
  174: 
  175:     inf& operator %= (const inf&) throw(divide_by_zero);
  176:     inf operator % (const inf&) const throw(divide_by_zero);
  177: 
  178:     // combined division operator - returns the result pair(quotient,remainder) in one go
  179:     std::pair<inf,inf> divide(const inf&) const throw(divide_by_zero);
  180: 
  181:     //////////////////////////////////////////////////////////////////////////////
  182:     // pre- and post- increment and decrement
  183: 
  184:     inf& operator ++ (void);
  185:     inf operator ++ (int);
  186:     inf& operator -- (void);
  187:     inf operator -- (int);
  188: 
  189:     //////////////////////////////////////////////////////////////////////////////
  190:     // string representation and I/O
  191: 
  192:     std::string image_debug(void) const;
  193: 
  194:     // conversion to a string representation
  195:     // radix must be 10, 2, 8 or 16
  196:     std::string to_string(unsigned radix = 10) const
  197:       throw(std::invalid_argument);
  198: 
  199:     // conversion from a string
  200:     // radix == 0 - radix is deduced from the input - assumed 10 unless number is prefixed by 0b, 0 or 0x
  201:     // however, you can specify the radix to be 10, 2, 8 or 16 to force that interpretation
  202:     inf& from_string(const std::string&, unsigned radix = 0)
  203:       throw(std::invalid_argument);
  204: 
  205:     //////////////////////////////////////////////////////////////////////////////
  206:   private:
  207:     std::string m_data;
  208:   public:
  209:     const std::string& get_bytes(void) const;
  210:     void set_bytes(const std::string&);
  211:   };
  212: 
  213:   ////////////////////////////////////////////////////////////////////////////////
  214:   // redefine friends for gcc v4.1
  215: 
  216:   inf abs(const inf&);
  217: 
  218:   ////////////////////////////////////////////////////////////////////////////////
  219: 
  220:   std::ostream& operator << (std::ostream&, const inf&);
  221:   std::istream& operator >> (std::istream&, inf&);
  222: 
  223:   ////////////////////////////////////////////////////////////////////////////////
  224: 
  225: } // end namespace stlplus
  226: 
  227: #endif