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 + -
显示快捷键?