BigNum.hxx

Go to the documentation of this file.
00001 #ifndef LIBSHERPA_BIGNUM_HXX
00002 #define LIBSHERPA_BIGNUM_HXX
00003 
00004 /**************************************************************************
00005  *
00006  * Copyright (C) 2007, The EROS Group, LLC.
00007  * All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or
00010  * without modification, are permitted provided that the following
00011  * conditions are met:
00012  *
00013  *   - Redistributions of source code must contain the above
00014  *     copyright notice, this list of conditions, and the following
00015  *     disclaimer.
00016  *
00017  *   - Redistributions in binary form must reproduce the above
00018  *     copyright notice, this list of conditions, and the following
00019  *     disclaimer in the documentation and/or other materials
00020  *     provided with the distribution.
00021  *
00022  *   - Neither the names of the copyright holders nor the names of any
00023  *     of any contributors may be used to endorse or promote products
00024  *     derived from this software without specific prior written
00025  *     permission.
00026  *
00027  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00028  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00029  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00030  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00031  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00032  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00033  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00034  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00035  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00036  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00037  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00038  *
00039  **************************************************************************/
00040 
00041 #include <stdint.h>
00042 #include <stdlib.h>
00043 #include <vector>
00044 #include <iostream>
00045 #include <sstream>
00046 
00047 namespace sherpa {
00048 
00049   class BigNum {
00050     friend struct nvec;
00051 
00052     bool negative;
00053     size_t nDigits;
00054 
00055     union {
00056       uint32_t oneDigit;        // when it fits
00057       uint32_t *digits;         // dynamically allocated
00058     };
00059 
00062     //    void normalize();
00063 
00064     uint64_t getDigit(size_t i) const
00065     {
00066       if (i >= nDigits)
00067         return 0;
00068       return (nDigits == 1) ? oneDigit :  digits[i];
00069     }
00070 
00071     uint32_t& theDigit(size_t i)
00072     {
00073       if (nDigits == 1)
00074         return oneDigit;
00075       return digits[i];
00076     }
00077 
00078     // Used internally.
00079     inline BigNum(size_t nDigits, uint32_t *digits, bool negative = false);
00080 
00081     BigNum rshift_digits(size_t nDigits) const;
00082     BigNum lshift_digits(size_t nDigits) const;
00083   public:
00084     ~BigNum();
00085     BigNum()
00086     {
00087       negative = false;
00088       nDigits = 1;
00089       oneDigit = 0;
00090     }
00091 
00092     inline BigNum(uint32_t u, bool neg)
00093     {
00094       negative = neg;
00095       nDigits = 1;
00096       oneDigit = u;
00097     }
00098 
00099     BigNum(uint64_t u, bool neg);
00100 
00101     // Ideally, we would just have a pair of constructors above with
00102     // an OPTIONAL boolean negation. Unfortunately, there are
00103     // compilers that will not resolve the overload correctly given
00104     //
00105     //   BigNum bn = (size_t) i;
00106     //
00107     // The following constructors exist so that this case will have an
00108     // exact match:
00109 
00110     inline BigNum(uint32_t u) {
00111       negative = false;
00112       nDigits = 1;
00113       oneDigit = u;
00114     }
00115     BigNum(uint64_t u);
00116 
00117     inline BigNum(int32_t i)
00118     {
00119       negative = (i < 0);
00120       nDigits = 1;
00121       oneDigit = (i < 0) ? -i : i;
00122     }
00123     BigNum(int64_t i);
00124 
00125     BigNum(const std::string& s, uint32_t radix = 0);
00126 
00127     BigNum(const BigNum&);
00128 
00129     BigNum operator+(const BigNum&) const;
00130     BigNum operator-(const BigNum&) const;
00131     BigNum operator*(const BigNum&) const;
00132     BigNum operator/(const BigNum&) const;
00133     BigNum operator%(const BigNum&) const;
00134 
00135     inline BigNum& operator+=(const BigNum& other)
00136     {
00137       BigNum tmp = *this + other;
00138       *this = tmp;
00139       return *this;
00140     }
00141     inline BigNum& operator-=(const BigNum& other)
00142     {
00143       BigNum tmp = *this - other;
00144       *this = tmp;
00145       return *this;
00146     }
00147     inline BigNum& operator*=(const BigNum& other)
00148     {
00149       BigNum tmp = *this * other;
00150       *this = tmp;
00151       return *this;
00152     }
00153     inline BigNum& operator/=(const BigNum& other)
00154     {
00155       BigNum tmp = *this / other;
00156       *this = tmp;
00157       return *this;
00158     }
00159     inline BigNum& operator%=(const BigNum& other)
00160     {
00161       BigNum tmp = *this % other;
00162       *this = tmp;
00163       return *this;
00164     }
00165 
00166     BigNum& operator=(const BigNum&);
00167 
00168     BigNum abs() const;
00169     BigNum neg() const;
00170 
00171     inline BigNum operator-() const     // unary minus
00172     {
00173       return this->neg();
00174     }
00175 
00176     int cmp(const BigNum& other) const;
00177 
00178     inline bool operator<(const BigNum& other) const
00179     {
00180       return cmp(other) < 0;
00181     }
00182 
00183     inline bool operator<=(const BigNum& other) const
00184     {
00185       return cmp(other) <= 0;
00186     }
00187     inline bool operator>(const BigNum& other) const
00188     {
00189       return cmp(other) > 0;
00190     }
00191 
00192     inline bool operator>=(const BigNum& other) const
00193     {
00194       return cmp(other) >= 0;
00195     }
00196 
00197     inline bool operator==(const BigNum& other) const
00198     {
00199       return cmp(other) == 0;
00200     }
00201 
00202     inline bool operator!=(const BigNum& other) const
00203     {
00204       return cmp(other) != 0;
00205     }
00206 
00207     BigNum operator<<(size_t n);
00208     BigNum operator>>(size_t n);
00209 
00210     inline BigNum& operator<<=(size_t n)
00211     {
00212       *this = *this << n;
00213       return *this;
00214     }
00215     inline BigNum& operator>>=(size_t n)
00216     {
00217       *this = *this >> n;
00218       return *this;
00219     }
00220 
00221     std::string asString(uint32_t radix = 10) const;
00222 
00223     void toStream(std::ostream& strm, uint32_t radix = 10) const;
00224     void fromStream(std::istream& strm, uint32_t radix = 10);
00225 
00226     inline uint32_t as_uint32() const
00227     {
00228       return getDigit(0);
00229     }
00230 
00231     inline uint64_t as_uint64() const
00232     {
00233       return (getDigit(1) << 32) | getDigit(0);
00234     }
00235   };
00236 
00237   // Curiously, if these are removed from the namespace then
00238   // overloadin creap in very quickly.
00239   inline
00240   std::ostream& operator<<(std::ostream& strm, const sherpa::BigNum& bn)
00241   {
00242     if (strm.flags() & strm.hex)
00243       bn.toStream(strm, 16);
00244     else if (strm.flags() & strm.oct)
00245       bn.toStream(strm, 8);
00246     else
00247       bn.toStream(strm, 10);
00248 
00249     return strm;
00250   }
00251 
00252   inline
00253   std::istream& operator>>(std::istream& strm, sherpa::BigNum& bn)
00254   {
00255     if (strm.flags() & strm.hex)
00256       bn.fromStream(strm, 16);
00257     else if (strm.flags() & strm.oct)
00258       bn.fromStream(strm, 8);
00259     else
00260       bn.fromStream(strm, 10);
00261 
00262     return strm;
00263   }
00264 } /* namespace sherpa */
00265 
00266 #endif /* LIBSHERPA_BIGNUM_HXX */

Generated on Sat Feb 4 23:59:28 2012 for BitC Compiler by  doxygen 1.4.7