- Format conversion code more nicely.
* negative BigInteger instead of an exception. */
// Done longhand to let us use initialization.
-BigInteger::BigInteger(unsigned long x) : mag(x) {
- sign = mag.isZero() ? zero : positive;
-}
-BigInteger::BigInteger(unsigned int x) : mag(x) {
- sign = mag.isZero() ? zero : positive;
-}
-BigInteger::BigInteger(unsigned short x) : mag(x) {
- sign = mag.isZero() ? zero : positive;
-}
+BigInteger::BigInteger(unsigned long x) : mag(x) { sign = mag.isZero() ? zero : positive; }
+BigInteger::BigInteger(unsigned int x) : mag(x) { sign = mag.isZero() ? zero : positive; }
+BigInteger::BigInteger(unsigned short x) : mag(x) { sign = mag.isZero() ? zero : positive; }
// For signed input, determine the desired magnitude and sign separately.
}
}
-BigInteger::BigInteger(long x) : sign(signOf(x)),
- mag(magOf<long, unsigned long>(x)) {}
-BigInteger::BigInteger(int x) : sign(signOf(x)),
- mag(magOf<int, unsigned int>(x)) {}
-BigInteger::BigInteger(short x) : sign(signOf(x)),
- mag(magOf<short, unsigned short>(x)) {}
+BigInteger::BigInteger(long x) : sign(signOf(x)), mag(magOf<long , unsigned long >(x)) {}
+BigInteger::BigInteger(int x) : sign(signOf(x)), mag(magOf<int , unsigned int >(x)) {}
+BigInteger::BigInteger(short x) : sign(signOf(x)), mag(magOf<short, unsigned short>(x)) {}
// CONVERSION TO PRIMITIVE INTEGERS
"Value is too big to fit in the requested type";
}
-unsigned long BigInteger::toUnsignedLong() const {
- return convertToUnsignedPrimitive<unsigned long>();
-}
-unsigned int BigInteger::toUnsignedInt() const {
- return convertToUnsignedPrimitive<unsigned int>();
-}
-unsigned short BigInteger::toUnsignedShort() const {
- return convertToUnsignedPrimitive<unsigned short>();
-}
-long BigInteger::toLong() const {
- return convertToSignedPrimitive<long, unsigned long>();
-}
-int BigInteger::toInt() const {
- return convertToSignedPrimitive<int, unsigned int>();
-}
-short BigInteger::toShort() const {
- return convertToSignedPrimitive<short, unsigned short>();
-}
+unsigned long BigInteger::toUnsignedLong () const { return convertToUnsignedPrimitive<unsigned long > (); }
+unsigned int BigInteger::toUnsignedInt () const { return convertToUnsignedPrimitive<unsigned int > (); }
+unsigned short BigInteger::toUnsignedShort() const { return convertToUnsignedPrimitive<unsigned short> (); }
+long BigInteger::toLong () const { return convertToSignedPrimitive <long , unsigned long> (); }
+int BigInteger::toInt () const { return convertToSignedPrimitive <int , unsigned int> (); }
+short BigInteger::toShort () const { return convertToSignedPrimitive <short, unsigned short>(); }
// COMPARISON
BigInteger::CmpRes BigInteger::compareTo(const BigInteger &x) const {
// Memory management definitions have moved to the bottom of NumberlikeArray.hh.
-// CONSTRUCTION FROM PRIMITIVE INTEGERS
-
-/* Initialize this BigUnsigned from the given primitive integer. The same
- * pattern works for all primitive integer types, so I put it into a template to
- * reduce code duplication. (Don't worry: this is protected and we instantiate
- * it only with primitive integer types.) Type X could be signed, but x is
- * known to be nonnegative. */
-template <class X>
-void BigUnsigned::initFromPrimitive(X x) {
- if (x == 0)
- ; // NumberlikeArray already initialized us to zero.
- else {
- // Create a single block. blk is NULL; no need to delete it.
- cap = 1;
- blk = new Blk[1];
- len = 1;
- blk[0] = Blk(x);
- }
-}
-
-/* Ditto, but first check that x is nonnegative. I could have put the check in
- * initFromPrimitive and let the compiler optimize it out for unsigned-type
- * instantiations, but I wanted to avoid the warning stupidly issued by g++ for
- * a condition that is constant in *any* instantiation, even if not in all. */
-template <class X>
-void BigUnsigned::initFromSignedPrimitive(X x) {
- if (x < 0)
- throw "BigUnsigned constructor: "
- "Cannot construct a BigUnsigned from a negative number";
- else
- initFromPrimitive(x);
-}
+// The templates used by these constructors and converters are at the bottom of
+// BigUnsigned.hh.
BigUnsigned::BigUnsigned(unsigned long x) { initFromPrimitive (x); }
BigUnsigned::BigUnsigned(unsigned int x) { initFromPrimitive (x); }
BigUnsigned::BigUnsigned( int x) { initFromSignedPrimitive(x); }
BigUnsigned::BigUnsigned( short x) { initFromSignedPrimitive(x); }
-// CONVERSION TO PRIMITIVE INTEGERS
-
-/* Template with the same idea as initFromPrimitive. This might be slightly
- * slower than the previous version with the masks, but it's much shorter and
- * clearer, which is the library's stated goal. */
-template <class X>
-X BigUnsigned::convertToPrimitive() const {
- if (len == 0)
- // The number is zero; return zero.
- return 0;
- else if (len == 1) {
- // The single block might fit in an X. Try the conversion.
- X x = X(blk[0]);
- // Make sure the result accurately represents the block.
- if (Blk(x) == blk[0])
- // Successful conversion.
- return x;
- // Otherwise fall through.
- }
- throw "BigUnsigned::to<Primitive>: "
- "Value is too big to fit in the requested type";
-}
-
-/* Wrap the above in an x >= 0 test to make sure we got a nonnegative result,
- * not a negative one that happened to convert back into the correct nonnegative
- * one. (E.g., catch incorrect conversion of 2^31 to the long -2^31.) Again,
- * separated to avoid a g++ warning. */
-template <class X>
-X BigUnsigned::convertToSignedPrimitive() const {
- X x = convertToPrimitive<X>();
- if (x >= 0)
- return x;
- else
- throw "BigUnsigned::to(Primitive): "
- "Value is too big to fit in the requested type";
-}
-
-unsigned long BigUnsigned::toUnsignedLong() const {
- return convertToPrimitive<unsigned long>();
-}
-unsigned int BigUnsigned::toUnsignedInt() const {
- return convertToPrimitive<unsigned int>();
-}
-unsigned short BigUnsigned::toUnsignedShort() const {
- return convertToPrimitive<unsigned short>();
-}
-long BigUnsigned::toLong() const {
- return convertToSignedPrimitive<long>();
-}
-int BigUnsigned::toInt() const {
- return convertToSignedPrimitive<int>();
-}
-short BigUnsigned::toShort() const {
- return convertToSignedPrimitive<short>();
-}
+unsigned long BigUnsigned::toUnsignedLong () const { return convertToPrimitive <unsigned long >(); }
+unsigned int BigUnsigned::toUnsignedInt () const { return convertToPrimitive <unsigned int >(); }
+unsigned short BigUnsigned::toUnsignedShort() const { return convertToPrimitive <unsigned short>(); }
+long BigUnsigned::toLong () const { return convertToSignedPrimitive< long >(); }
+int BigUnsigned::toInt () const { return convertToSignedPrimitive< int >(); }
+short BigUnsigned::toShort () const { return convertToSignedPrimitive< short>(); }
// COMPARISON
BigUnsigned::CmpRes BigUnsigned::compareTo(const BigUnsigned &x) const {
BigUnsigned( short x);
protected:
// Helpers
- template <class X> void initFromPrimitive(X x);
+ template <class X> void initFromPrimitive (X x);
template <class X> void initFromSignedPrimitive(X x);
public:
protected:
// Helpers
template <class X> X convertToSignedPrimitive() const;
- template <class X> X convertToPrimitive() const;
+ template <class X> X convertToPrimitive () const;
public:
// ACCESSORS
bitShiftRight(*this, b);
}
+/* Templates for conversions of BigUnsigned to and from primitive integers.
+ * BigInteger.cc needs to instantiate convertToPrimitive, and the uses in
+ * BigUnsigned.cc didn't do the trick; I think gcc inlined convertToPrimitive
+ * instead of generating linkable instantiations. So for consistency, I put
+ * all the templates here. */
+
+// CONSTRUCTION FROM PRIMITIVE INTEGERS
+
+/* Initialize this BigUnsigned from the given primitive integer. The same
+ * pattern works for all primitive integer types, so I put it into a template to
+ * reduce code duplication. (Don't worry: this is protected and we instantiate
+ * it only with primitive integer types.) Type X could be signed, but x is
+ * known to be nonnegative. */
+template <class X>
+void BigUnsigned::initFromPrimitive(X x) {
+ if (x == 0)
+ ; // NumberlikeArray already initialized us to zero.
+ else {
+ // Create a single block. blk is NULL; no need to delete it.
+ cap = 1;
+ blk = new Blk[1];
+ len = 1;
+ blk[0] = Blk(x);
+ }
+}
+
+/* Ditto, but first check that x is nonnegative. I could have put the check in
+ * initFromPrimitive and let the compiler optimize it out for unsigned-type
+ * instantiations, but I wanted to avoid the warning stupidly issued by g++ for
+ * a condition that is constant in *any* instantiation, even if not in all. */
+template <class X>
+void BigUnsigned::initFromSignedPrimitive(X x) {
+ if (x < 0)
+ throw "BigUnsigned constructor: "
+ "Cannot construct a BigUnsigned from a negative number";
+ else
+ initFromPrimitive(x);
+}
+
+// CONVERSION TO PRIMITIVE INTEGERS
+
+/* Template with the same idea as initFromPrimitive. This might be slightly
+ * slower than the previous version with the masks, but it's much shorter and
+ * clearer, which is the library's stated goal. */
+template <class X>
+X BigUnsigned::convertToPrimitive() const {
+ if (len == 0)
+ // The number is zero; return zero.
+ return 0;
+ else if (len == 1) {
+ // The single block might fit in an X. Try the conversion.
+ X x = X(blk[0]);
+ // Make sure the result accurately represents the block.
+ if (Blk(x) == blk[0])
+ // Successful conversion.
+ return x;
+ // Otherwise fall through.
+ }
+ throw "BigUnsigned::to<Primitive>: "
+ "Value is too big to fit in the requested type";
+}
+
+/* Wrap the above in an x >= 0 test to make sure we got a nonnegative result,
+ * not a negative one that happened to convert back into the correct nonnegative
+ * one. (E.g., catch incorrect conversion of 2^31 to the long -2^31.) Again,
+ * separated to avoid a g++ warning. */
+template <class X>
+X BigUnsigned::convertToSignedPrimitive() const {
+ X x = convertToPrimitive<X>();
+ if (x >= 0)
+ return x;
+ else
+ throw "BigUnsigned::to(Primitive): "
+ "Value is too big to fit in the requested type";
+}
+
#endif