// -------------------------------------------- compare // returns 1 if a > b, 0 if a == b and -1 otherwise. int compare (const Rational& a, const Rational &b) { if (isZero(a.num) && isZero(b.num)) return 0 ; if (isZero(a.num)) return -sign(b.num); if (isZero(b.num)) return sign(a.num); if (sign(a.num) != sign(b.num)) return (sign(a.num) == -1 ? -1 : 1 ) ; if (sign(a.num) > 0) return absCompare(a,b) ; else return -absCompare(a,b) ; }
BigInt& BigInt::operator -= (const BigInt &bi) { NumVec vec; if( m_sign ^ bi.m_sign ) { vec = BigInt::vecAdd(m_vec, bi.m_vec); } else { if( absCompare(bi) >= 0 ) { vec = BigInt::vecSub(m_vec, bi.m_vec); } else { vec = BigInt::vecSub(bi.m_vec, m_vec); m_sign = !bi.m_sign; } if( vec.size()==1 && vec[0] == 0) m_sign = false; } m_vec = std::move(vec); return *this; }
int32_t absCompare(const Integer &a, const int64_t b) { #if GMP_LIMB_BITS != 64 return absCompare( a, Integer(b)); #else return mpz_cmpabs_ui( (mpz_srcptr)&(a.gmp_rep), (uint64_t) std::abs(b)); #endif }
// -------------------------------------------- absCompare int absCompare (const Rational& a, const Rational& b) { int cnum = absCompare(a.num, b.num) ; int cden = absCompare(a.den, b.den) ; if ( (cnum == -1) && (cden == 1) ) return -1 ; if ( (cnum == 1) && (cden == -1) ) return 1 ; if (cnum == 0) return -cden ; if (cden == 0) return cnum ; Integer p1 = a.num * b.den; Integer p2 = a.den * b.num; return absCompare(p1,p2); }
BigInt& BigInt::operator /= (const BigInt &bi) { if( bi == 0 ) throw std::logic_error("can't div 0"); bool sign = m_sign; m_sign = false; BigInt res(0); BigInt divsor(bi), count(1); while( absCompare(divsor) >= 0 ) { divsor.selfLeftShift(10);//fast count.selfLeftShift(10); } while(absCompare(bi) >= 0) { while(absCompare(divsor) < 0) { divsor.selfRightShift(1);//slow count.selfRightShift(1); } res += count; (*this) -= divsor; } m_vec = std::move(res.m_vec); if( m_vec.size() == 1 && m_vec[0] == 0 ) m_sign = false; else m_sign = sign ^ bi.m_sign; return *this; }
bool BigInt::operator > (const BigInt &bi)const { if( m_sign != bi.m_sign ) return !m_sign; int ret = absCompare(bi); if( ret == 0 ) return false; //当同为正数时(m_sign为false),对于正数来说,直接判断ret是否大于0即可。 //此时异或的结果也是根据ret>0而确定的. //当同为负数时(m_sign为true),对于负数来说,结果要与ret>0取反, //而异或在m_sign为true时会自动与ret>0取反. return m_sign ^ (ret > 0); }
bool BigInt::operator < (const BigInt &bi)const { if( m_sign != bi.m_sign ) return m_sign; //same sign int ret = absCompare(bi); if( ret == 0 ) return false; /* if( m_sign )//negative return ret > 0; else //positive return ret < 0; */ return m_sign ^ (ret < 0); }