inf.hpp

    1: #ifndef INF_HPP
    2: #define INF_HPP
    3: /*------------------------------------------------------------------------------
    4: 
    5:   Author:    Andy Rushton
    6:   Copyright: (c) Andy Rushton, 2004
    7:   License:   BSD License, see ../docs/license.html
    8: 
    9:   An infinite-precision integer class
   10: 
   11:   ------------------------------------------------------------------------------*/
   12: #include "os_fixes.hpp"
   13: #include <string>
   14: #include <stdexcept>
   15: #include "textio.hpp"
   16: #include "string_utilities.hpp"
   17: #include "persistent.hpp"
   18: 
   19: ////////////////////////////////////////////////////////////////////////////////
   20: 
   21: class inf
   22: {
   23: public:
   24:   // this class can throw the following exceptions:
   25:   //   std::out_of_range
   26:   //   std::overflow_error
   27:   //   std::invalid_argument
   28:   //   inf::divide_by_zero    // why doesn't std have this?
   29:   // all of these are derivations of the baseclass:
   30:   //   std::logic_error
   31:   // So you can catch all of them by catching the baseclass
   32:   class divide_by_zero : public std::logic_error {
   33:   public:
   34:     divide_by_zero (const std::string& what_arg): std::logic_error (what_arg) { }
   35:   };
   36: 
   37:   //////////////////////////////////////////////////////////////////////////////
   38:   // constructors and assignments initialise the inf
   39:   // the void constructor initialises to zero, the others initialise to the value of the C integer type
   40:   // see also the section on string representations
   41: 
   42:   inf(void);
   43:   explicit inf(short);
   44:   explicit inf(unsigned short);
   45:   explicit inf(int);
   46:   explicit inf(unsigned);
   47:   explicit inf(long);
   48:   explicit inf(unsigned long);
   49:   explicit inf(const std::string&) throw(std::invalid_argument);
   50:   inf(const inf&);
   51: 
   52:   ~inf(void);
   53: 
   54:   inf& operator = (short);
   55:   inf& operator = (unsigned short);
   56:   inf& operator = (int);
   57:   inf& operator = (unsigned);
   58:   inf& operator = (long);
   59:   inf& operator = (unsigned long);
   60:   inf& operator = (const std::string&) throw(std::invalid_argument);
   61:   inf& operator = (const inf&);
   62: 
   63:   //////////////////////////////////////////////////////////////////////////////
   64:   // conversions back to the C types - note that the inf must be in range for this to be legal
   65: 
   66:   short to_short(void) const throw(std::overflow_error);
   67:   unsigned short to_ushort(void) const throw(std::overflow_error);
   68:   int to_int(void) const throw(std::overflow_error);
   69:   unsigned to_unsigned(void) const throw(std::overflow_error);
   70:   unsigned to_uint(void) const throw(std::overflow_error);
   71:   long to_long(void) const throw(std::overflow_error);
   72:   unsigned long to_ulong(void) const throw(std::overflow_error);
   73: 
   74:   //////////////////////////////////////////////////////////////////////////////
   75:   // bitwise manipulation
   76: 
   77:   void resize(unsigned bits);
   78:   void reduce(void);
   79: 
   80:   // the number of significant bits in the value
   81:   unsigned bits (void) const;
   82:   unsigned size (void) const;
   83: 
   84:   // the number of bits that can be accessed by the bit() method (=bits() rounded up to the next byte)
   85:   unsigned indexable_bits(void) const;
   86: 
   87:   bool bit (unsigned index) const throw(std::out_of_range);
   88:   bool operator [] (unsigned index) const throw(std::out_of_range);
   89: 
   90:   void set (unsigned index) throw(std::out_of_range);
   91:   void clear (unsigned index) throw(std::out_of_range);
   92:   void preset (unsigned index, bool value) throw(std::out_of_range);
   93: 
   94:   inf slice(unsigned low, unsigned high) const throw(std::out_of_range);
   95: 
   96:   //////////////////////////////////////////////////////////////////////////////
   97:   // tests for common values or ranges
   98: 
   99:   bool negative (void) const;
  100:   bool natural (void) const;
  101:   bool positive (void) const;
  102:   bool zero (void) const;
  103:   bool non_zero (void) const;
  104: 
  105:   // tests used in if(i) and if(!i)
  106: //  operator bool (void) const;
  107:   bool operator ! (void) const;
  108: 
  109:   //////////////////////////////////////////////////////////////////////////////
  110:   // comparisons
  111: 
  112:   friend bool operator == (const inf&, const inf&);
  113:   friend bool operator != (const inf&, const inf&);
  114:   friend bool operator < (const inf&, const inf&);
  115:   friend bool operator <= (const inf&, const inf&);
  116:   friend bool operator > (const inf&, const inf&);
  117:   friend bool operator >= (const inf&, const inf&);
  118: 
  119:   //////////////////////////////////////////////////////////////////////////////
  120:   // bitwise logic operations
  121: 
  122:   inf& invert (void);
  123:   friend inf operator ~ (const inf&);
  124: 
  125:   inf& operator &= (const inf&);
  126:   friend inf operator & (const inf&, const inf&);
  127: 
  128:   inf& operator |= (const inf&);
  129:   friend inf operator | (const inf&, const inf&);
  130: 
  131:   inf& operator ^= (const inf&);
  132:   friend inf operator ^ (const inf&, const inf&);
  133: 
  134:   inf& operator <<= (unsigned shift);
  135:   friend inf operator << (const inf&, unsigned shift);
  136: 
  137:   inf& operator >>= (unsigned shift);
  138:   friend inf operator >> (const inf&,unsigned shift);
  139: 
  140:   //////////////////////////////////////////////////////////////////////////////
  141:   // arithmetic operations
  142: 
  143:   inf& negate (void);
  144:   friend inf operator - (const inf&);
  145: 
  146:   inf& abs(void);
  147:   friend inf abs(const inf&);
  148: 
  149:   inf& operator += (const inf&);
  150:   friend inf operator + (const inf&, const inf&);
  151: 
  152:   inf& operator -= (const inf&);
  153:   friend inf operator - (const inf&, const inf&);
  154: 
  155:   inf& operator *= (const inf&);
  156:   friend inf operator * (const inf&, const inf&);
  157: 
  158:   inf& operator /= (const inf&) throw(divide_by_zero);
  159:   friend inf operator / (const inf&, const inf&) throw(divide_by_zero);
  160:   inf& operator %= (const inf&) throw(divide_by_zero);
  161:   friend inf operator % (const inf&, const inf&) throw(divide_by_zero);
  162: 
  163:   // combined division operator - returns the result pair(quotient,remainder) in one go
  164:   friend std::pair<inf,inf> divide(const inf&, const inf&) throw(divide_by_zero);
  165: 
  166:   //////////////////////////////////////////////////////////////////////////////
  167:   // pre- and post- increment and decrement
  168: 
  169:   inf& operator ++ (void);
  170:   inf operator ++ (int);
  171:   inf& operator -- (void);
  172:   inf operator -- (int);
  173: 
  174:   //////////////////////////////////////////////////////////////////////////////
  175:   // string representation and I/O
  176: 
  177:   std::string image_debug(void) const;
  178: 
  179:   // conversion to a string representation - see string_utilities for an explanation of the arguments
  180:   // provided as a method and a friend
  181: 
  182:   std::string to_string(unsigned radix = 10, radix_display_t display = radix_c_style_or_hash, unsigned width = 0) const
  183:     throw(std::invalid_argument);
  184: 
  185:   friend std::string to_string(const inf& i,
  186:                                unsigned radix = 10, radix_display_t display = radix_c_style_or_hash, unsigned width = 0)
  187:     throw(std::invalid_argument);
  188: 
  189:   friend inf to_inf(const std::string&, unsigned radix = 0)
  190:     throw(std::invalid_argument);
  191: 
  192:   friend otext& operator << (otext&, const inf&);
  193:   friend itext& operator >> (itext&, inf&);
  194: 
  195:   //////////////////////////////////////////////////////////////////////////////
  196:   // persistence
  197: 
  198:   void dump(dump_context&) const throw(persistent_dump_failed);
  199:   void restore(restore_context&) throw(persistent_restore_failed);
  200: 
  201:   friend void dump(dump_context& str, const inf& data) throw(persistent_dump_failed);
  202:   friend void restore(restore_context& str, inf& data) throw(persistent_restore_failed);
  203: 
  204:   //////////////////////////////////////////////////////////////////////////////
  205: private:
  206:   std::string m_data;
  207: 
  208:   void set_head(void);
  209: };
  210: 
  211: // redefine friends for gcc v4.1
  212: bool operator == (const inf&, const inf&);
  213: bool operator != (const inf&, const inf&);
  214: bool operator < (const inf&, const inf&);
  215: bool operator <= (const inf&, const inf&);
  216: bool operator > (const inf&, const inf&);
  217: bool operator >= (const inf&, const inf&);
  218: inf operator ~ (const inf&);
  219: inf operator & (const inf&, const inf&);
  220: inf operator | (const inf&, const inf&);
  221: inf operator ^ (const inf&, const inf&);
  222: inf operator << (const inf&, unsigned shift);
  223: inf operator >> (const inf&,unsigned shift);
  224: inf operator - (const inf&);
  225: inf abs(const inf&);
  226: inf operator + (const inf&, const inf&);
  227: inf operator - (const inf&, const inf&);
  228: inf operator * (const inf&, const inf&);
  229: inf operator / (const inf&, const inf&) throw(inf::divide_by_zero);
  230: inf operator % (const inf&, const inf&) throw(inf::divide_by_zero);
  231: std::pair<inf,inf> divide(const inf&, const inf&) throw(inf::divide_by_zero);
  232: std::string to_string(const inf& i, unsigned radix, radix_display_t display, unsigned width) throw(std::invalid_argument);
  233: inf to_inf(const std::string&, unsigned radix) throw(std::invalid_argument);
  234: otext& operator << (otext&, const inf&);
  235: itext& operator >> (itext&, inf&);
  236: void dump(dump_context& str, const inf& data) throw(persistent_dump_failed);
  237: void restore(restore_context& str, inf& data) throw(persistent_restore_failed);
  238: 
  239: ////////////////////////////////////////////////////////////////////////////////
  240: #endif