bignum.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,299 行 · 第 1/4 页
C
1,299 行
// operator<< -- overload left shift operator for CoolBignums
// Inputs: reference to CoolBignum to be shifted, left shift amount
// Outputs: shifted CoolBignum
CoolBignumE operator<< (const CoolBignum& b1, long l) {
if (l == 0 || b1 == zero_s) { // if either arg is zero
CoolBignum b(b1); // copy b1
CoolBignumE& result = *((CoolBignumE*) &b); // same physical object
return result; // shallow swap on return
}
if (l < 0) // if shift amt is negative
return right_shift(b1,-l); // do an actual right shift
else // otherwise
return left_shift(b1,l); // do a left shift
}
// operator>> -- overload right shift operator for CoolBignums
// Inputs: reference to CoolBignum to be shifted, right shift amount
// Outputs: shifted CoolBignum
CoolBignumE operator>> (const CoolBignum& b1, long l) {
if (l == 0 || b1 == zero_s) { // if either arg is zero
CoolBignum b(b1); // copy b1
CoolBignumE& result = *((CoolBignumE*) &b); // same physical object
return result; // shallow swap on return
}
if (l < 0) // if shift amt is negative
return left_shift(b1,-l); // do an actual left shift
else // else
return right_shift(b1,l); // do a right shift
}
// operator== -- overload equality operator for CoolBignums
// Inputs: reference to CoolBignum to compare to
// Outputs: Boolean equality indicator
Boolean CoolBignum::operator== (const CoolBignum& b) const {
if (this->sign != b.sign) return FALSE; // Different sign implies !=
if (this->count != b.count) return FALSE; // Different size implies !=
for (Counter i = 0; i < this->count; i++) // Each data element the same?
if (this->data[i] != b.data[i]) return FALSE; // No. Return !=
return TRUE; // Yes. Return ==
}
// operator< -- overload less-than operator for CoolBignums
// Inputs: reference to CoolBignum to compare to
// Outputs: Boolean less-than indicator
Boolean CoolBignum::operator< (const CoolBignum& b) const {
if (this->sign < b.sign) return TRUE; // Different signs?
if (this->sign > b.sign) return FALSE;
if (this->sign == 1) // Both signs == 1
return (magnitude_cmp(*this,b) < 0 ? TRUE: FALSE); // this must be smaller
else // Both signs == -1
return (magnitude_cmp(*this,b) > 0 ? TRUE: FALSE); // this must be larger
}
// operator> -- overload greater-than operator for CoolBignums
// Inputs: reference to CoolBignum to compare to
// Outputs: Boolean greater-than indicator
Boolean CoolBignum::operator> (const CoolBignum& b) const {
if (this->sign > b.sign) return TRUE; // Different signs?
if (this->sign < b.sign) return FALSE;
if (this->sign == 1) // Both signs == 1
return (magnitude_cmp(*this,b) > 0 ? TRUE: FALSE); // this must be larger
else // Both signs == -1
return (magnitude_cmp(*this,b) < 0 ? TRUE: FALSE); // this must be smaller
}
// operator<< -- overload output operator for CoolBignums
// Inputs: reference to output stream and CoolBignum
// Outputs: reference to output stream
ostream& operator<< (ostream& os, const CoolBignum& b) {
CoolBignum d = b; // Copy the input CoolBignum
if (d.sign == -1) { // If it's negative
cout.put('-'); // Output leading minus sign
d.sign = 1; // Make d positive for divide
}
CoolBignum q,r; // Temp quotient and remainder
char *cbuf = new char[5 * b.count]; // Temp character buffer
Counter i = 0;
do { // repeat:
divide(d,ten_s,q,r); // Divide CoolBignum by ten
cbuf[i++] = char(long(r) + '0'); // Get one's digit
d = q; // Then discard one's digit
q = r = zero_s; // Prep for next divide
} while (d != zero_s); // until no more one's digits
do { // repeat;
os.put(cbuf[--i]); // output char buf in reverse
} while (i); // until no more chars
delete [] cbuf; // delete temp char buf
return os; // return output stream
}
// operator short - conversion operator from CoolBignum to short
// Inputs: none
// Outputs: CoolBignum converted to short
CoolBignum::operator short () const {
if (*this > max_short_s) { // If short overflow
overflow("operator short ()"); // raise exception
}
if (*this < -max_short_s) { // If short underflow
underflow("operator short ()"); // raise exception
}
short s = 0; // Default is zero conversion
for (Counter i = this->count; i > 0; i--)
s = short(s*radix_s + this->data[i - 1]);
return this->sign*s; // calculate sign
}
// operator int - conversion operator from CoolBignum to int
// Inputs: none
// Outputs: CoolBignum converted to int
CoolBignum::operator int () const {
if (*this > max_int_s) { // If int overflow
overflow("operator int ()"); // raise exception
}
if (*this < -max_int_s) { // If int underflow
underflow("operator int ()"); // raise exception
}
int j = 0; // Otherwise, do conversion
for (Counter i = this->count; i > 0; i--) // For each data element
j = int(j*radix_s + this->data[i - 1]); // stick it into j and shift
return this->sign*j; // Attach sign
}
// operator long - conversion operator from CoolBignum to long
// Inputs: none
// Outputs: CoolBignum converted to long
CoolBignum::operator long () const {
if (*this > max_long_s) { // If long overflow
overflow("operator long ()"); // raise exception
}
if (*this < -max_long_s) { // If long underflow
underflow("operator long ()"); // raise exception
}
long l = 0; // Otherwise, do conversion
for (Counter i = this->count; i > 0; i--) // For each data element
l = l*radix_s + this->data[i - 1]; // stick it into l and shift
return this->sign*l; // Attach sign
}
// operator float - conversion operator from CoolBignum to float
// Inputs: none
// Outputs: CoolBignum converted to float
CoolBignum::operator float () const {
if (*this > max_float_s) { // If float overflow
overflow("operator float ()"); // raise exception
}
if (*this < negmax_float_s) { // If float underflow
underflow("operator float ()"); // raise exception
}
float f = 0.0; // Otherwise, do conversion
for (Counter i = this->count; i > 0; i--) // For each data element
f = f*radix_s + this->data[i - 1]; // stick it into f and shift
return this->sign*f; // Attach sign
}
// operator double - conversion operator from CoolBignum to double
// Inputs: none
// Outputs: CoolBignum converted to double
CoolBignum::operator double () const {
if (*this > max_double_s) { // If double overflow
overflow("operator double ()"); // raise exception
}
if (*this < negmax_double_s) { // If double underflow
underflow("operator double ()"); // raise exception
}
double d = 0.0; // Otherwise, do conversion
for (Counter i = this->count; i > 0; i--) // For each data element
d = d*radix_s + this->data[i - 1]; // stick it into d and shift
return this->sign*d; // Attach sign
}
// print -- terse print function for CoolBignums
// Inputs: reference to output stream
// Outputs: none
void CoolBignum::print (ostream& os) {
os << "/* CoolBignum " << (long)this << " */";
}
// dump -- dump the contents of a CoolBignum to a stream
// Inputs: stream to dump to (default cout)
// Outputs: none
void CoolBignum::dump (ostream& os) {
os << "{count: " << this->count << // output count field
", sign: " << this->sign << // output sign field
", state: " << this->state << // output state field
", data: " << this->data << // output data pointer
", {";
#ifdef THE_OLD_WAY_USING_THAT_UGLY_FORM
// format string == "%04X%s" or "%02X%s", etc.
static char format_str[10] =
{'%','0',char(2*sizeof(Data) + '0'),'X','%','s'};
format_str[2] = char(2*sizeof(Data) + '0');
if (this->count > 0) { // output data array
for (Counter i = this->count; i > 1; i--)
os << form(format_str,this->data[i - 1],",");
os << form(format_str,this->data[0],"");
}
#else // the new and improved way which probably no two compilers get alike
if (this->count > 0) { // output data array
long save_flags = os.flags(); // save format state
char save_fill = os.fill('0'); // use fill character
int width = sizeof(Data)*CHAR_BIT/4; // max width of data in hex
for (Counter i = this->count; i > 1; i--)
os << setw(width) << hex << this->data[i - 1] << ",";
os << setw(width) << hex << this->data[0];
os.fill(save_fill); // reset fill character
os.flags(save_flags); // rest format state (eg, dec)
}
#endif
os << "}}"; // close brackets
}
// minus_infinity -- raise a minus infinity error exeption
// Inputs: name of function in which exception occurred
// Outputs: none
void CoolBignum::minus_infinity (const char* name) const {
//RAISE (Error, SYM(CoolBignum), SYM(Minus_Infinity),
printf ("CoolBignum::%s: Quotient is negative infinity.\n", name);
abort ();
}
// plus_infinity -- raise a plus infinity error exception
// Inputs: name of function in which exception occurred
// Outputs: none
void CoolBignum::plus_infinity (const char* name) const {
//RAISE (Error, SYM(CoolBignum), SYM(Plus_Infinity),
printf ("CoolBignum::%s: Quotient is positive infinity.\n", name);
abort ();
}
// divide_by_zero -- raise a division by zero error exception
// Inputs: name of function in which exception occurred
// Outputs: none
void CoolBignum::divide_by_zero (const char* name) const {
//RAISE (Error, SYM(CoolBignum), SYM(Divide_By_Zero),
printf ("CoolBignum::%s: Divide by zero.\n", name);
abort ();
}
// overflow -- raise an overflow exception
// Inputs: name of function in which exception occurred
// Outputs: none
void CoolBignum::overflow (const char* name) const {
//RAISE (Error, SYM(CoolBignum), SYM(Overflow),
printf ("CoolBignum::%s: Overflow occured during type conversion.\n", name);
abort ();
}
// underflow -- raise an underflow exception
// Inputs: name of function in which exception occurred
// Outputs: none
void CoolBignum::underflow (const char* name) const {
//RAISE (Error, SYM(CoolBignum), SYM(Underflow),
printf ("CoolBignum::%s: Underflow occured during type conversion.\n", name);
abort ();
}
// no_conversion -- raise a no conversion exception
// Inputs: name of function in which exception occurred
// Outputs: none
void CoolBignum::no_conversion (const char* name) const {
//RAISE(Error, SYM(CoolBignum), SYM(No_Conversion),
printf ("CoolBignum::%s: Can not convert input parameter to CoolBignum.\n", name);
abort ();
}
// end Bignum.C
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?