mirror of
https://github.com/Microsoft/calculator.git
synced 2025-08-22 14:13:30 -07:00
Stack-allocate all _numbers internally
This commit is contained in:
parent
4053620e3e
commit
ceb4b3c9b9
16 changed files with 505 additions and 585 deletions
|
@ -17,22 +17,22 @@ namespace CalcEngine
|
|||
m_mantissa{ mantissa }
|
||||
{}
|
||||
|
||||
Number::Number(PNUMBER p) noexcept :
|
||||
m_sign{ p->sign },
|
||||
m_exp{ p->exp },
|
||||
Number::Number(NUMBER p) noexcept :
|
||||
m_sign{ p.sign },
|
||||
m_exp{ p.exp },
|
||||
m_mantissa{}
|
||||
{
|
||||
m_mantissa.reserve(p->cdigit);
|
||||
copy(p->mant.begin(), p->mant.begin() + p->cdigit, back_inserter(m_mantissa));
|
||||
m_mantissa.reserve(p.cdigit);
|
||||
copy(p.mant.begin(), p.mant.begin() + p.cdigit, back_inserter(m_mantissa));
|
||||
}
|
||||
|
||||
PNUMBER Number::ToPNUMBER() const
|
||||
NUMBER Number::ToNUMBER() const
|
||||
{
|
||||
PNUMBER ret = _createnum(static_cast<uint32_t>(this->Mantissa().size()) + 1);
|
||||
ret->sign = this->Sign();
|
||||
ret->exp = this->Exp();
|
||||
ret->cdigit = static_cast<int32_t>(this->Mantissa().size());
|
||||
ret->mant = this->Mantissa();
|
||||
NUMBER ret = _createnum(static_cast<uint32_t>(this->Mantissa().size()) + 1);
|
||||
ret.sign = this->Sign();
|
||||
ret.exp = this->Exp();
|
||||
ret.cdigit = static_cast<int32_t>(this->Mantissa().size());
|
||||
ret.mant = this->Mantissa();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -69,8 +69,8 @@ namespace CalcEngine
|
|||
{
|
||||
PRAT ret = _createrat();
|
||||
|
||||
ret->pp = this->P().ToPNUMBER();
|
||||
ret->pq = this->Q().ToPNUMBER();
|
||||
ret->pp = this->P().ToNUMBER();
|
||||
ret->pq = this->Q().ToNUMBER();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@ namespace CalcEngine
|
|||
Number() noexcept;
|
||||
Number(int32_t sign, int32_t exp, std::vector<uint32_t> const& mantissa) noexcept;
|
||||
|
||||
explicit Number(PNUMBER p) noexcept;
|
||||
PNUMBER ToPNUMBER() const;
|
||||
explicit Number(NUMBER p) noexcept;
|
||||
NUMBER ToNUMBER() const;
|
||||
|
||||
int32_t const& Sign() const;
|
||||
int32_t const& Exp() const;
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
void _mulnumx( PNUMBER *pa, PNUMBER b );
|
||||
void _mulnumx( NUMBER *pa, NUMBER b );
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
|
@ -36,13 +36,13 @@ void _mulnumx( PNUMBER *pa, PNUMBER b );
|
|||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void __inline mulnumx( PNUMBER *pa, PNUMBER b )
|
||||
void __inline mulnumx( NUMBER *pa, NUMBER b )
|
||||
|
||||
{
|
||||
if ( b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0 )
|
||||
if ( b.cdigit > 1 || b.mant[0] != 1 || b.exp != 0 )
|
||||
{
|
||||
// If b is not one we multiply
|
||||
if ( (*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0 )
|
||||
if ( (*pa).cdigit > 1 || (*pa).mant[0] != 1 || (*pa).exp != 0 )
|
||||
{
|
||||
// pa and b are both non-one.
|
||||
_mulnumx( pa, b );
|
||||
|
@ -50,15 +50,15 @@ void __inline mulnumx( PNUMBER *pa, PNUMBER b )
|
|||
else
|
||||
{
|
||||
// if pa is one and b isn't just copy b. and adjust the sign.
|
||||
int32_t sign = (*pa)->sign;
|
||||
int32_t sign = (*pa).sign;
|
||||
DUPNUM(*pa,b);
|
||||
(*pa)->sign *= sign;
|
||||
(*pa).sign *= sign;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// B is +/- 1, But we do have to set the sign.
|
||||
(*pa)->sign *= b->sign;
|
||||
(*pa).sign *= b.sign;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,11 +78,11 @@ void __inline mulnumx( PNUMBER *pa, PNUMBER b )
|
|||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void _mulnumx( PNUMBER *pa, PNUMBER b )
|
||||
void _mulnumx( NUMBER *pa, NUMBER b )
|
||||
|
||||
{
|
||||
PNUMBER c= nullptr; // c will contain the result.
|
||||
PNUMBER a= nullptr; // a is the dereferenced number pointer from *pa
|
||||
NUMBER c; // c will contain the result.
|
||||
NUMBER a; // a is the dereferenced number pointer from *pa
|
||||
vector<MANTTYPE>::iterator ptra; // ptra is an iterator pointing to the mantissa of a.
|
||||
vector<MANTTYPE>::iterator ptrb; // ptrb is an iterator pointing to the mantissa of b.
|
||||
vector<MANTTYPE>::iterator ptrc; // ptrc is an iterator pointing to the mantissa of c.
|
||||
|
@ -99,24 +99,24 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
|
|||
|
||||
a=*pa;
|
||||
|
||||
ibdigit = a->cdigit + b->cdigit - 1;
|
||||
ibdigit = a.cdigit + b.cdigit - 1;
|
||||
createnum( c, ibdigit + 1 );
|
||||
c->cdigit = ibdigit;
|
||||
c->sign = a->sign * b->sign;
|
||||
c.cdigit = ibdigit;
|
||||
c.sign = a.sign * b.sign;
|
||||
|
||||
c->exp = a->exp + b->exp;
|
||||
ptra = a->mant.begin();
|
||||
ptrcoffset = c->mant.begin();
|
||||
c.exp = a.exp + b.exp;
|
||||
ptra = a.mant.begin();
|
||||
ptrcoffset = c.mant.begin();
|
||||
|
||||
for ( iadigit = a->cdigit; iadigit > 0; iadigit-- )
|
||||
for ( iadigit = a.cdigit; iadigit > 0; iadigit-- )
|
||||
{
|
||||
da = *ptra++;
|
||||
ptrb = b->mant.begin();
|
||||
ptrb = b.mant.begin();
|
||||
|
||||
// Shift ptrc, and ptrcoffset, one for each digit
|
||||
ptrc = ptrcoffset++;
|
||||
|
||||
for ( ibdigit = b->cdigit; ibdigit > 0; ibdigit-- )
|
||||
for ( ibdigit = b.cdigit; ibdigit > 0; ibdigit-- )
|
||||
{
|
||||
cy = 0;
|
||||
mcy = (uint64_t)da * (*ptrb);
|
||||
|
@ -125,7 +125,7 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
|
|||
icdigit = 0;
|
||||
if ( ibdigit == 1 && iadigit == 1 )
|
||||
{
|
||||
c->cdigit++;
|
||||
c.cdigit++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,12 +152,11 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
|
|||
|
||||
// prevent different kinds of zeros, by stripping leading duplicate zeros.
|
||||
// digits are in order of increasing significance.
|
||||
while ( c->cdigit > 1 && c->mant[c->cdigit-1] == 0 )
|
||||
while ( c.cdigit > 1 && c.mant[c.cdigit-1] == 0 )
|
||||
{
|
||||
c->cdigit--;
|
||||
c.cdigit--;
|
||||
}
|
||||
|
||||
destroynum( *pa );
|
||||
*pa=c;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -176,10 +175,10 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void numpowi32x( _Inout_ PNUMBER *proot, _In_ int32_t power )
|
||||
void numpowi32x( _Inout_ NUMBER *proot, _In_ int32_t power )
|
||||
|
||||
{
|
||||
PNUMBER lret = i32tonum( 1, BASEX );
|
||||
NUMBER lret = i32tonum( 1, BASEX );
|
||||
|
||||
// Once the power remaining is zero we are done.
|
||||
while ( power > 0 )
|
||||
|
@ -198,12 +197,11 @@ void numpowi32x( _Inout_ PNUMBER *proot, _In_ int32_t power )
|
|||
// move the next bit of the power into place.
|
||||
power >>= 1;
|
||||
}
|
||||
destroynum( *proot );
|
||||
*proot=lret;
|
||||
|
||||
}
|
||||
|
||||
void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision);
|
||||
void _divnumx( NUMBER *pa, NUMBER b, int32_t precision);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
|
@ -220,13 +218,13 @@ void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision);
|
|||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void __inline divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
|
||||
void __inline divnumx( NUMBER *pa, NUMBER b, int32_t precision)
|
||||
|
||||
{
|
||||
if ( b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0 )
|
||||
if ( b.cdigit > 1 || b.mant[0] != 1 || b.exp != 0 )
|
||||
{
|
||||
// b is not one.
|
||||
if ( (*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0 )
|
||||
if ( (*pa).cdigit > 1 || (*pa).mant[0] != 1 || (*pa).exp != 0 )
|
||||
{
|
||||
// pa and b are both not one.
|
||||
_divnumx( pa, b, precision);
|
||||
|
@ -234,15 +232,15 @@ void __inline divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
|
|||
else
|
||||
{
|
||||
// if pa is one and b is not one, just copy b, and adjust the sign.
|
||||
int32_t sign = (*pa)->sign;
|
||||
int32_t sign = (*pa).sign;
|
||||
DUPNUM(*pa,b);
|
||||
(*pa)->sign *= sign;
|
||||
(*pa).sign *= sign;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// b is one so don't divide, but set the sign.
|
||||
(*pa)->sign *= b->sign;
|
||||
(*pa).sign *= b.sign;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -259,15 +257,15 @@ void __inline divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
|
|||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
|
||||
void _divnumx( NUMBER *pa, NUMBER b, int32_t precision)
|
||||
|
||||
{
|
||||
PNUMBER a= nullptr; // a is the dereferenced number pointer from *pa
|
||||
PNUMBER c= nullptr; // c will contain the result.
|
||||
PNUMBER lasttmp = nullptr; // lasttmp allows a backup when the algorithm
|
||||
NUMBER a; // a is the dereferenced number pointer from *pa
|
||||
NUMBER c; // c will contain the result.
|
||||
NUMBER lasttmp; // lasttmp allows a backup when the algorithm
|
||||
// guesses one bit too far.
|
||||
PNUMBER tmp = nullptr; // current guess being worked on for divide.
|
||||
PNUMBER rem = nullptr; // remainder after applying guess.
|
||||
NUMBER tmp; // current guess being worked on for divide.
|
||||
NUMBER rem; // remainder after applying guess.
|
||||
int32_t cdigits; // count of digits for answer.
|
||||
vector<MANTTYPE>::iterator ptrc; // ptrc is an iterator pointing to the mantissa of c.
|
||||
|
||||
|
@ -275,31 +273,31 @@ void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
|
|||
// to shoot for in the divide.
|
||||
|
||||
a=*pa;
|
||||
if ( thismax < a->cdigit )
|
||||
if ( thismax < a.cdigit )
|
||||
{
|
||||
// a has more digits than precision specified, bump up digits to shoot
|
||||
// for.
|
||||
thismax = a->cdigit;
|
||||
thismax = a.cdigit;
|
||||
}
|
||||
|
||||
if ( thismax < b->cdigit )
|
||||
if ( thismax < b.cdigit )
|
||||
{
|
||||
// b has more digits than precision specified, bump up digits to shoot
|
||||
// for.
|
||||
thismax = b->cdigit;
|
||||
thismax = b.cdigit;
|
||||
}
|
||||
|
||||
// Create c (the divide answer) and set up exponent and sign.
|
||||
createnum( c, thismax + 1 );
|
||||
c->exp = (a->cdigit+a->exp) - (b->cdigit+b->exp) + 1;
|
||||
c->sign = a->sign * b->sign;
|
||||
c.exp = (a.cdigit+a.exp) - (b.cdigit+b.exp) + 1;
|
||||
c.sign = a.sign * b.sign;
|
||||
|
||||
ptrc = c->mant.begin() + thismax;
|
||||
ptrc = c.mant.begin() + thismax;
|
||||
cdigits = 0;
|
||||
|
||||
DUPNUM( rem, a );
|
||||
rem->sign = b->sign;
|
||||
rem->exp = b->cdigit + b->exp - rem->cdigit;
|
||||
rem.sign = b.sign;
|
||||
rem.exp = b.cdigit + b.exp - rem.cdigit;
|
||||
|
||||
while ( cdigits++ < thismax && !zernum(rem) )
|
||||
{
|
||||
|
@ -309,11 +307,9 @@ void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
|
|||
{
|
||||
digit = 1;
|
||||
DUPNUM( tmp, b );
|
||||
destroynum( lasttmp );
|
||||
lasttmp=i32tonum( 0, BASEX );
|
||||
while ( lessnum( tmp, rem ) )
|
||||
{
|
||||
destroynum( lasttmp );
|
||||
DUPNUM(lasttmp,tmp);
|
||||
addnum( &tmp, tmp, BASEX );
|
||||
digit *= 2;
|
||||
|
@ -321,48 +317,43 @@ void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
|
|||
if ( lessnum( rem, tmp ) )
|
||||
{
|
||||
// too far, back up...
|
||||
destroynum( tmp );
|
||||
digit /= 2;
|
||||
tmp=lasttmp;
|
||||
lasttmp= nullptr;
|
||||
}
|
||||
|
||||
tmp->sign *= -1;
|
||||
tmp.sign *= -1;
|
||||
addnum( &rem, tmp, BASEX );
|
||||
destroynum( tmp );
|
||||
destroynum( lasttmp );
|
||||
*ptrc |= digit;
|
||||
}
|
||||
rem->exp++;
|
||||
rem.exp++;
|
||||
ptrc--;
|
||||
}
|
||||
cdigits--;
|
||||
if ( c->mant.begin() != ++ptrc )
|
||||
if ( c.mant.begin() != ++ptrc )
|
||||
{
|
||||
copy(ptrc, ptrc + cdigits, c->mant.begin());
|
||||
copy(ptrc, ptrc + cdigits, c.mant.begin());
|
||||
}
|
||||
|
||||
if ( !cdigits )
|
||||
{
|
||||
// A zero, make sure no weird exponents creep in
|
||||
c->exp = 0;
|
||||
c->cdigit = 1;
|
||||
c.exp = 0;
|
||||
c.cdigit = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
c->cdigit = cdigits;
|
||||
c->exp -= cdigits;
|
||||
c.cdigit = cdigits;
|
||||
c.exp -= cdigits;
|
||||
// prevent different kinds of zeros, by stripping leading duplicate
|
||||
// zeros. digits are in order of increasing significance.
|
||||
while ( c->cdigit > 1 && c->mant[c->cdigit-1] == 0 )
|
||||
while ( c.cdigit > 1 && c.mant[c.cdigit-1] == 0 )
|
||||
{
|
||||
c->cdigit--;
|
||||
c.cdigit--;
|
||||
}
|
||||
}
|
||||
|
||||
destroynum( rem );
|
||||
|
||||
destroynum( *pa );
|
||||
*pa=c;
|
||||
}
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ namespace {
|
|||
}
|
||||
|
||||
// Used to strip trailing zeros, and prevent combinatorial explosions
|
||||
bool stripzeroesnum(_Inout_ PNUMBER pnum, int32_t starting);
|
||||
bool stripzeroesnum(_Inout_ NUMBER pnum, int32_t starting);
|
||||
|
||||
void SetDecimalSeparator(wchar_t decimalSeparator)
|
||||
{
|
||||
|
@ -136,33 +136,12 @@ void* zmalloc(size_t a)
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void _dupnum(_In_ PNUMBER dest, _In_ const NUMBER * const src)
|
||||
void _dupnum(_In_ NUMBER dest, _In_ const NUMBER * const src)
|
||||
{
|
||||
dest->sign = src->sign;
|
||||
dest->exp = src->exp;
|
||||
dest->cdigit = src->cdigit;
|
||||
dest->mant = src->mant;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: _destroynum
|
||||
//
|
||||
// ARGUMENTS: pointer to a number
|
||||
//
|
||||
// RETURN: None
|
||||
//
|
||||
// DESCRIPTION: Deletes the number and associated allocation
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void _destroynum( _In_ PNUMBER pnum )
|
||||
|
||||
{
|
||||
if ( pnum != nullptr)
|
||||
{
|
||||
delete pnum;
|
||||
}
|
||||
dest.sign = src->sign;
|
||||
dest.exp = src->exp;
|
||||
dest.cdigit = src->cdigit;
|
||||
dest.mant = src->mant;
|
||||
}
|
||||
|
||||
|
||||
|
@ -184,8 +163,6 @@ void _destroyrat( _In_ PRAT prat )
|
|||
{
|
||||
if ( prat != nullptr)
|
||||
{
|
||||
destroynum( prat->pp );
|
||||
destroynum( prat->pq );
|
||||
delete prat;
|
||||
}
|
||||
}
|
||||
|
@ -197,27 +174,19 @@ void _destroyrat( _In_ PRAT prat )
|
|||
//
|
||||
// ARGUMENTS: size of number in 'digits'
|
||||
//
|
||||
// RETURN: pointer to a number
|
||||
// RETURN: a number
|
||||
//
|
||||
// DESCRIPTION: allocates and zeros out number type.
|
||||
// DESCRIPTION: initializes and zeros out number type.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
PNUMBER _createnum( _In_ uint32_t size )
|
||||
NUMBER _createnum( _In_ uint32_t size )
|
||||
|
||||
{
|
||||
PNUMBER pnumret= nullptr;
|
||||
try
|
||||
{
|
||||
pnumret = new NUMBER();
|
||||
}
|
||||
catch (const bad_alloc&)
|
||||
{
|
||||
throw( CALC_E_OUTOFMEMORY );
|
||||
}
|
||||
NUMBER num = NUMBER();
|
||||
// Fill mantissa vector with zeros
|
||||
pnumret->mant.insert(pnumret->mant.end(), size, 0);
|
||||
return( pnumret );
|
||||
num.mant.insert(num.mant.end(), size, 0);
|
||||
return( num );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -247,8 +216,6 @@ PRAT _createrat( void )
|
|||
{
|
||||
throw( CALC_E_OUTOFMEMORY );
|
||||
}
|
||||
prat->pp = nullptr;
|
||||
prat->pq = nullptr;
|
||||
return( prat );
|
||||
}
|
||||
|
||||
|
@ -269,19 +236,19 @@ PRAT _createrat( void )
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
PRAT numtorat( _In_ PNUMBER pin, uint32_t radix)
|
||||
PRAT numtorat( _In_ NUMBER pin, uint32_t radix)
|
||||
|
||||
{
|
||||
PNUMBER pnRadixn= nullptr;
|
||||
NUMBER pnRadixn;
|
||||
DUPNUM( pnRadixn, pin );
|
||||
|
||||
PNUMBER qnRadixn=i32tonum( 1, radix);
|
||||
NUMBER qnRadixn=i32tonum( 1, radix);
|
||||
|
||||
// Ensure p and q start out as integers.
|
||||
if ( pnRadixn->exp < 0 )
|
||||
if ( pnRadixn.exp < 0 )
|
||||
{
|
||||
qnRadixn->exp -= pnRadixn->exp;
|
||||
pnRadixn->exp = 0;
|
||||
qnRadixn.exp -= pnRadixn.exp;
|
||||
pnRadixn.exp = 0;
|
||||
}
|
||||
|
||||
PRAT pout= nullptr;
|
||||
|
@ -292,8 +259,6 @@ PRAT numtorat( _In_ PNUMBER pin, uint32_t radix)
|
|||
pout->pq = numtonRadixx(qnRadixn, radix);
|
||||
|
||||
|
||||
destroynum( pnRadixn );
|
||||
destroynum( qnRadixn );
|
||||
|
||||
return( pout );
|
||||
}
|
||||
|
@ -314,30 +279,30 @@ PRAT numtorat( _In_ PNUMBER pin, uint32_t radix)
|
|||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
PNUMBER nRadixxtonum( _In_ PNUMBER a, uint32_t radix, int32_t precision)
|
||||
NUMBER nRadixxtonum( _In_ NUMBER a, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
uint32_t bitmask;
|
||||
uint32_t cdigits;
|
||||
MANTTYPE *ptr;
|
||||
|
||||
PNUMBER sum = i32tonum( 0, radix );
|
||||
PNUMBER powofnRadix = i32tonum( BASEX, radix );
|
||||
NUMBER sum = i32tonum( 0, radix );
|
||||
NUMBER powofnRadix = i32tonum( BASEX, radix );
|
||||
|
||||
// A large penalty is paid for conversion of digits no one will see anyway.
|
||||
// limit the digits to the minimum of the existing precision or the
|
||||
// requested precision.
|
||||
cdigits = precision + 1;
|
||||
if ( cdigits > (uint32_t)a->cdigit )
|
||||
if ( cdigits > (uint32_t)a.cdigit )
|
||||
{
|
||||
cdigits = (uint32_t)a->cdigit;
|
||||
cdigits = (uint32_t)a.cdigit;
|
||||
}
|
||||
|
||||
// scale by the internal base to the internal exponent offset of the LSD
|
||||
numpowi32( &powofnRadix, a->exp + (a->cdigit - cdigits), radix, precision);
|
||||
numpowi32( &powofnRadix, a.exp + (a.cdigit - cdigits), radix, precision);
|
||||
|
||||
// Loop over all the relative digits from MSD to LSD
|
||||
for ( ptr = &(a->mant[a->cdigit-1]); cdigits > 0;
|
||||
for ( ptr = &(a.mant[a.cdigit-1]); cdigits > 0;
|
||||
ptr--, cdigits-- )
|
||||
{
|
||||
// Loop over all the bits from MSB to LSB
|
||||
|
@ -346,7 +311,7 @@ PNUMBER nRadixxtonum( _In_ PNUMBER a, uint32_t radix, int32_t precision)
|
|||
addnum( &sum, sum, radix );
|
||||
if ( *ptr & bitmask )
|
||||
{
|
||||
sum->mant[0] |= 1;
|
||||
sum.mant[0] |= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -354,8 +319,7 @@ PNUMBER nRadixxtonum( _In_ PNUMBER a, uint32_t radix, int32_t precision)
|
|||
// Scale answer by power of internal exponent.
|
||||
mulnum( &sum, powofnRadix, radix );
|
||||
|
||||
destroynum( powofnRadix );
|
||||
sum->sign = a->sign;
|
||||
sum.sign = a.sign;
|
||||
return( sum );
|
||||
}
|
||||
|
||||
|
@ -373,18 +337,18 @@ PNUMBER nRadixxtonum( _In_ PNUMBER a, uint32_t radix, int32_t precision)
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
PNUMBER numtonRadixx(_In_ PNUMBER a, uint32_t radix)
|
||||
NUMBER numtonRadixx(_In_ NUMBER a, uint32_t radix)
|
||||
{
|
||||
PNUMBER pnumret = i32tonum(0, BASEX); // pnumret is the number in internal form.
|
||||
PNUMBER num_radix = i32tonum(radix, BASEX);
|
||||
NUMBER pnumret = i32tonum(0, BASEX); // pnumret is the number in internal form.
|
||||
NUMBER num_radix = i32tonum(radix, BASEX);
|
||||
|
||||
// Digits are in reverse order, back over them LSD first.
|
||||
vector<MANTTYPE>::iterator ptrdigit = a->mant.begin() + a->cdigit; // iterator pointing to digit being worked on.
|
||||
vector<MANTTYPE>::iterator ptrdigit = a.mant.begin() + a.cdigit; // iterator pointing to digit being worked on.
|
||||
|
||||
PNUMBER thisdigit = nullptr; // thisdigit holds the current digit of a
|
||||
NUMBER thisdigit; // thisdigit holds the current digit of a
|
||||
// being summed into result.
|
||||
int32_t idigit; // idigit is the iterate of digits in a.
|
||||
for ( idigit = 0; idigit < a->cdigit; idigit++ )
|
||||
for ( idigit = 0; idigit < a.cdigit; idigit++ )
|
||||
{
|
||||
mulnumx( &pnumret, num_radix);
|
||||
// WARNING:
|
||||
|
@ -392,19 +356,17 @@ PNUMBER numtonRadixx(_In_ PNUMBER a, uint32_t radix)
|
|||
// and not do the overhead of recreating the number type each time.
|
||||
thisdigit = i32tonum( *(--ptrdigit), BASEX );
|
||||
addnum( &pnumret, thisdigit, BASEX );
|
||||
destroynum( thisdigit );
|
||||
}
|
||||
|
||||
// Calculate the exponent of the external base for scaling.
|
||||
numpowi32x( &num_radix, a->exp );
|
||||
numpowi32x( &num_radix, a.exp );
|
||||
|
||||
// ... and scale the result.
|
||||
mulnumx( &pnumret, num_radix);
|
||||
|
||||
destroynum(num_radix);
|
||||
|
||||
// And propagate the sign.
|
||||
pnumret->sign = a->sign;
|
||||
pnumret.sign = a.sign;
|
||||
|
||||
return( pnumret );
|
||||
}
|
||||
|
@ -450,7 +412,7 @@ PRAT StringToRat(bool mantissaIsNegative, wstring_view mantissa, bool exponentIs
|
|||
else
|
||||
{
|
||||
// Mantissa specified, convert to number form.
|
||||
PNUMBER pnummant = StringToNumber(mantissa, radix, precision);
|
||||
NUMBER pnummant = StringToNumber(mantissa, radix, precision);
|
||||
if (pnummant == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
|
@ -458,7 +420,6 @@ PRAT StringToRat(bool mantissaIsNegative, wstring_view mantissa, bool exponentIs
|
|||
|
||||
resultRat = numtorat(pnummant, radix);
|
||||
// convert to rational form, and cleanup.
|
||||
destroynum(pnummant);
|
||||
}
|
||||
|
||||
// Deal with exponent
|
||||
|
@ -468,7 +429,7 @@ PRAT StringToRat(bool mantissaIsNegative, wstring_view mantissa, bool exponentIs
|
|||
// Exponent specified, convert to number form.
|
||||
// Don't use native stuff, as it is restricted in the bases it can
|
||||
// handle.
|
||||
PNUMBER numExp = StringToNumber(exponent, radix, precision);
|
||||
NUMBER numExp = StringToNumber(exponent, radix, precision);
|
||||
if (numExp == nullptr)
|
||||
{
|
||||
return nullptr;
|
||||
|
@ -476,18 +437,16 @@ PRAT StringToRat(bool mantissaIsNegative, wstring_view mantissa, bool exponentIs
|
|||
|
||||
// Convert exponent number form to native integral form, and cleanup.
|
||||
expt = numtoi32(numExp, radix);
|
||||
destroynum(numExp);
|
||||
}
|
||||
|
||||
// Convert native integral exponent form to rational multiplier form.
|
||||
PNUMBER pnumexp = i32tonum(radix, BASEX);
|
||||
NUMBER pnumexp = i32tonum(radix, BASEX);
|
||||
numpowi32x(&pnumexp, abs(expt));
|
||||
|
||||
PRAT pratexp = nullptr;
|
||||
createrat(pratexp);
|
||||
DUPNUM(pratexp->pp, pnumexp);
|
||||
pratexp->pq = i32tonum(1, BASEX);
|
||||
destroynum(pnumexp);
|
||||
|
||||
if (exponentIsNegative)
|
||||
{
|
||||
|
@ -506,7 +465,7 @@ PRAT StringToRat(bool mantissaIsNegative, wstring_view mantissa, bool exponentIs
|
|||
if (mantissaIsNegative)
|
||||
{
|
||||
// A negative number was used, adjust the sign.
|
||||
resultRat->pp->sign *= -1;
|
||||
resultRat->pp.sign *= -1;
|
||||
}
|
||||
|
||||
return resultRat;
|
||||
|
@ -643,16 +602,16 @@ wchar_t NormalizeCharDigit(wchar_t c, uint32_t radix)
|
|||
return c;
|
||||
}
|
||||
|
||||
PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precision)
|
||||
NUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precision)
|
||||
{
|
||||
int32_t expSign = 1L; // expSign is exponent sign ( +/- 1 )
|
||||
int32_t expValue = 0L; // expValue is exponent mantissa, should be unsigned
|
||||
|
||||
PNUMBER pnumret = nullptr;
|
||||
NUMBER pnumret;
|
||||
createnum(pnumret, static_cast<uint32_t>(numberString.length()));
|
||||
pnumret->sign = 1L;
|
||||
pnumret->cdigit = 0;
|
||||
pnumret->exp = 0;
|
||||
pnumret.sign = 1L;
|
||||
pnumret.cdigit = 0;
|
||||
pnumret.exp = 0;
|
||||
int32_t imant = static_cast<int32_t>(numberString.length() - 1);
|
||||
|
||||
uint8_t state = START; // state is the state of the input state machine.
|
||||
|
@ -693,7 +652,7 @@ PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precis
|
|||
switch (state)
|
||||
{
|
||||
case MANTS:
|
||||
pnumret->sign = (curChar == L'-') ? -1 : 1;
|
||||
pnumret.sign = (curChar == L'-') ? -1 : 1;
|
||||
break;
|
||||
case EXPSZ:
|
||||
case EXPS:
|
||||
|
@ -717,7 +676,7 @@ PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precis
|
|||
}
|
||||
break;
|
||||
case LD:
|
||||
pnumret->exp++;
|
||||
pnumret.exp++;
|
||||
[[fallthrough]];
|
||||
case DD:
|
||||
{
|
||||
|
@ -726,9 +685,9 @@ PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precis
|
|||
size_t pos = DIGITS.find(curChar);
|
||||
if (pos != wstring_view::npos && pos < static_cast<size_t>(radix))
|
||||
{
|
||||
pnumret->mant[imant--] = static_cast<MANTTYPE>(pos);
|
||||
pnumret->exp--;
|
||||
pnumret->cdigit++;
|
||||
pnumret.mant[imant--] = static_cast<MANTTYPE>(pos);
|
||||
pnumret.exp--;
|
||||
pnumret.cdigit++;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -737,7 +696,7 @@ PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precis
|
|||
}
|
||||
break;
|
||||
case DZ:
|
||||
pnumret->exp--;
|
||||
pnumret.exp--;
|
||||
break;
|
||||
case LZ:
|
||||
case LZDP:
|
||||
|
@ -748,25 +707,24 @@ PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precis
|
|||
|
||||
if (state == DZ || state == EXPDZ)
|
||||
{
|
||||
pnumret->cdigit = 1;
|
||||
pnumret->exp = 0;
|
||||
pnumret->sign = 1;
|
||||
pnumret.cdigit = 1;
|
||||
pnumret.exp = 0;
|
||||
pnumret.sign = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (pnumret->cdigit < static_cast<int32_t>(numberString.length()))
|
||||
while (pnumret.cdigit < static_cast<int32_t>(numberString.length()))
|
||||
{
|
||||
pnumret->cdigit++;
|
||||
pnumret->exp--;
|
||||
pnumret.cdigit++;
|
||||
pnumret.exp--;
|
||||
}
|
||||
|
||||
pnumret->exp += expSign * expValue;
|
||||
pnumret.exp += expSign * expValue;
|
||||
}
|
||||
|
||||
// If we don't have a number, clear our result.
|
||||
if (pnumret->cdigit == 0)
|
||||
if (pnumret.cdigit == 0)
|
||||
{
|
||||
destroynum(pnumret);
|
||||
pnumret = nullptr;
|
||||
}
|
||||
|
||||
|
@ -835,31 +793,31 @@ PRAT Ui32torat( _In_ uint32_t inui32 )
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
PNUMBER i32tonum( int32_t ini32, uint32_t radix)
|
||||
NUMBER i32tonum( int32_t ini32, uint32_t radix)
|
||||
|
||||
{
|
||||
vector<MANTTYPE>::iterator pmant;
|
||||
PNUMBER pnumret= nullptr;
|
||||
NUMBER pnumret;
|
||||
|
||||
createnum( pnumret, MAX_LONG_SIZE );
|
||||
pmant = pnumret->mant.begin();
|
||||
pnumret->cdigit = 0;
|
||||
pnumret->exp = 0;
|
||||
pmant = pnumret.mant.begin();
|
||||
pnumret.cdigit = 0;
|
||||
pnumret.exp = 0;
|
||||
if ( ini32 < 0 )
|
||||
{
|
||||
pnumret->sign = -1;
|
||||
pnumret.sign = -1;
|
||||
ini32 *= -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pnumret->sign = 1;
|
||||
pnumret.sign = 1;
|
||||
}
|
||||
|
||||
do {
|
||||
*pmant = (MANTTYPE)(ini32 % radix);
|
||||
++pmant;
|
||||
ini32 /= radix;
|
||||
pnumret->cdigit++;
|
||||
pnumret.cdigit++;
|
||||
} while ( ini32 );
|
||||
|
||||
return( pnumret );
|
||||
|
@ -880,21 +838,21 @@ PNUMBER i32tonum( int32_t ini32, uint32_t radix)
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
PNUMBER Ui32tonum(uint32_t ini32, uint32_t radix)
|
||||
NUMBER Ui32tonum(uint32_t ini32, uint32_t radix)
|
||||
{
|
||||
vector<MANTTYPE>::iterator pmant;
|
||||
PNUMBER pnumret= nullptr;
|
||||
NUMBER pnumret;
|
||||
|
||||
createnum( pnumret, MAX_LONG_SIZE );
|
||||
pmant = pnumret->mant.begin();
|
||||
pnumret->cdigit = 0;
|
||||
pnumret->exp = 0;
|
||||
pnumret->sign = 1;
|
||||
pmant = pnumret.mant.begin();
|
||||
pnumret.cdigit = 0;
|
||||
pnumret.exp = 0;
|
||||
pnumret.sign = 1;
|
||||
|
||||
do {
|
||||
*pmant++ = (MANTTYPE)(ini32 % radix);
|
||||
ini32 /= radix;
|
||||
pnumret->cdigit++;
|
||||
pnumret.cdigit++;
|
||||
} while ( ini32 );
|
||||
|
||||
return( pnumret );
|
||||
|
@ -1023,24 +981,24 @@ uint64_t rattoUi64( _In_ PRAT prat, uint32_t radix, int32_t precision)
|
|||
// base claimed.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
int32_t numtoi32( _In_ PNUMBER pnum, uint32_t radix )
|
||||
int32_t numtoi32( _In_ NUMBER pnum, uint32_t radix )
|
||||
{
|
||||
int32_t lret = 0;
|
||||
|
||||
int32_t imant = pnum->cdigit - 1;
|
||||
int32_t imant = pnum.cdigit - 1;
|
||||
|
||||
int32_t expt = pnum->exp;
|
||||
for (int32_t length = pnum->cdigit; length > 0 && length + expt > 0; length--)
|
||||
int32_t expt = pnum.exp;
|
||||
for (int32_t length = pnum.cdigit; length > 0 && length + expt > 0; length--)
|
||||
{
|
||||
lret *= radix;
|
||||
lret += pnum->mant[imant--];
|
||||
lret += pnum.mant[imant--];
|
||||
}
|
||||
|
||||
while (expt-- > 0)
|
||||
{
|
||||
lret *= radix;
|
||||
}
|
||||
lret *= pnum->sign;
|
||||
lret *= pnum.sign;
|
||||
|
||||
return lret;
|
||||
}
|
||||
|
@ -1057,15 +1015,15 @@ int32_t numtoi32( _In_ PNUMBER pnum, uint32_t radix )
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool stripzeroesnum(_Inout_ PNUMBER pnum, int32_t starting)
|
||||
bool stripzeroesnum(_Inout_ NUMBER pnum, int32_t starting)
|
||||
{
|
||||
vector<MANTTYPE>::iterator pmant;
|
||||
int32_t cdigits;
|
||||
bool fstrip = false;
|
||||
|
||||
// point pmant to the LeastCalculatedDigit
|
||||
pmant=pnum->mant.begin();
|
||||
cdigits=pnum->cdigit;
|
||||
pmant=pnum.mant.begin();
|
||||
cdigits=pnum.cdigit;
|
||||
// point pmant to the LSD
|
||||
if ( cdigits > starting )
|
||||
{
|
||||
|
@ -1087,10 +1045,10 @@ bool stripzeroesnum(_Inout_ PNUMBER pnum, int32_t starting)
|
|||
if ( fstrip )
|
||||
{
|
||||
// Remove them.
|
||||
copy(pmant, pmant + cdigits, pnum->mant.begin());
|
||||
copy(pmant, pmant + cdigits, pnum.mant.begin());
|
||||
// And adjust exponent and digit count accordingly.
|
||||
pnum->exp += ( pnum->cdigit - cdigits );
|
||||
pnum->cdigit = cdigits;
|
||||
pnum.exp += ( pnum.cdigit - cdigits );
|
||||
pnum.cdigit = cdigits;
|
||||
}
|
||||
return( fstrip );
|
||||
}
|
||||
|
@ -1110,11 +1068,11 @@ bool stripzeroesnum(_Inout_ PNUMBER pnum, int32_t starting)
|
|||
// representation.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_t precision)
|
||||
wstring NumberToString(_Inout_ NUMBER& pnum, int format, uint32_t radix, int32_t precision)
|
||||
{
|
||||
stripzeroesnum(pnum, precision + 2);
|
||||
int32_t length = pnum->cdigit;
|
||||
int32_t exponent = pnum->exp + length; // Actual number of digits to the left of decimal
|
||||
int32_t length = pnum.cdigit;
|
||||
int32_t exponent = pnum.exp + length; // Actual number of digits to the left of decimal
|
||||
|
||||
int32_t oldFormat = format;
|
||||
if (exponent > precision && format == FMT_FLOAT)
|
||||
|
@ -1132,8 +1090,8 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
|
|||
// If there is a chance a round has to occur, round.
|
||||
// - if number is zero no rounding
|
||||
// - if number of digits is less than the maximum output no rounding
|
||||
PNUMBER round = nullptr;
|
||||
if (!zernum(pnum) && (pnum->cdigit >= precision || (length - exponent > precision && exponent >= -MAX_ZEROS_AFTER_DECIMAL)))
|
||||
NUMBER round;
|
||||
if (!zernum(pnum) && (pnum.cdigit >= precision || (length - exponent > precision && exponent >= -MAX_ZEROS_AFTER_DECIMAL)))
|
||||
{
|
||||
// Otherwise round.
|
||||
round = i32tonum(radix, radix);
|
||||
|
@ -1142,15 +1100,15 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
|
|||
// Make round number exponent one below the LSD for the number.
|
||||
if (exponent > 0 || format == FMT_FLOAT)
|
||||
{
|
||||
round->exp = pnum->exp + pnum->cdigit - round->cdigit - precision;
|
||||
round.exp = pnum.exp + pnum.cdigit - round.cdigit - precision;
|
||||
}
|
||||
else
|
||||
{
|
||||
round->exp = pnum->exp + pnum->cdigit - round->cdigit - precision - exponent;
|
||||
round.exp = pnum.exp + pnum.cdigit - round.cdigit - precision - exponent;
|
||||
length = precision + exponent;
|
||||
}
|
||||
|
||||
round->sign = pnum->sign;
|
||||
round.sign = pnum.sign;
|
||||
}
|
||||
|
||||
if (format == FMT_FLOAT)
|
||||
|
@ -1160,7 +1118,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
|
|||
{
|
||||
if (exponent >= -MAX_ZEROS_AFTER_DECIMAL)
|
||||
{
|
||||
round->exp -= exponent;
|
||||
round.exp -= exponent;
|
||||
length = precision + exponent;
|
||||
}
|
||||
else
|
||||
|
@ -1174,15 +1132,14 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
|
|||
{
|
||||
// Minimum loss of precision occurs with listing leading zeros
|
||||
// if we need to make room for zeros sacrifice some digits.
|
||||
round->exp -= exponent;
|
||||
round.exp -= exponent;
|
||||
}
|
||||
}
|
||||
|
||||
if (round != nullptr)
|
||||
{
|
||||
addnum(&pnum, round, radix);
|
||||
int32_t offset = (pnum->cdigit + pnum->exp) - (round->cdigit + round->exp);
|
||||
destroynum(round);
|
||||
int32_t offset = (pnum.cdigit + pnum.exp) - (round.cdigit + round.exp);
|
||||
if (stripzeroesnum(pnum, offset))
|
||||
{
|
||||
// WARNING: nesting/recursion, too much has been changed, need to
|
||||
|
@ -1198,7 +1155,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
|
|||
// Set up all the post rounding stuff.
|
||||
bool useSciForm = false;
|
||||
int32_t eout = exponent - 1; // Displayed exponent.
|
||||
int32_t imant = pnum->cdigit - 1;
|
||||
int32_t imant = pnum.cdigit - 1;
|
||||
// Case where too many digits are to the left of the decimal or
|
||||
// FMT_SCIENTIFIC or FMT_ENGINEERING was specified.
|
||||
if ((format == FMT_SCIENTIFIC) || (format == FMT_ENGINEERING))
|
||||
|
@ -1234,7 +1191,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
|
|||
wstringstream resultStream{};
|
||||
|
||||
// Make sure negative zeros aren't allowed.
|
||||
if ((pnum->sign == -1) && (length > 0))
|
||||
if ((pnum.sign == -1) && (length > 0))
|
||||
{
|
||||
resultStream << L'-';
|
||||
}
|
||||
|
@ -1255,7 +1212,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
|
|||
while (length > 0)
|
||||
{
|
||||
exponent--;
|
||||
resultStream << DIGITS[pnum->mant[imant--]];
|
||||
resultStream << DIGITS[pnum.mant[imant--]];
|
||||
length--;
|
||||
|
||||
// Be more regular in using a decimal point.
|
||||
|
@ -1327,46 +1284,43 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
|
|||
//-----------------------------------------------------------------------------
|
||||
wstring RatToString(_Inout_ PRAT& prat, int format, uint32_t radix, int32_t precision)
|
||||
{
|
||||
PNUMBER p = RatToNumber(prat, radix, precision);
|
||||
NUMBER p = RatToNumber(prat, radix, precision);
|
||||
|
||||
wstring result = NumberToString(p, format, radix, precision);
|
||||
destroynum(p);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PNUMBER RatToNumber(_In_ PRAT prat, uint32_t radix, int32_t precision)
|
||||
NUMBER RatToNumber(_In_ PRAT prat, uint32_t radix, int32_t precision)
|
||||
{
|
||||
PRAT temprat = nullptr;
|
||||
DUPRAT(temprat, prat);
|
||||
// Convert p and q of rational form from internal base to requested base.
|
||||
// Scale by largest power of BASEX possible.
|
||||
int32_t scaleby = min(temprat->pp->exp, temprat->pq->exp);
|
||||
int32_t scaleby = min(temprat->pp.exp, temprat->pq.exp);
|
||||
scaleby = max<int32_t>(scaleby, 0);
|
||||
|
||||
temprat->pp->exp -= scaleby;
|
||||
temprat->pq->exp -= scaleby;
|
||||
temprat->pp.exp -= scaleby;
|
||||
temprat->pq.exp -= scaleby;
|
||||
|
||||
PNUMBER p = nRadixxtonum(temprat->pp, radix, precision);
|
||||
PNUMBER q = nRadixxtonum(temprat->pq, radix, precision);
|
||||
NUMBER p = nRadixxtonum(temprat->pp, radix, precision);
|
||||
NUMBER q = nRadixxtonum(temprat->pq, radix, precision);
|
||||
|
||||
destroyrat(temprat);
|
||||
|
||||
// finally take the time hit to actually divide.
|
||||
divnum(&p, q, radix, precision);
|
||||
destroynum(q);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
// Converts a PRAT to a PNUMBER and back to a PRAT, flattening/simplifying the rational in the process
|
||||
// Converts a PRAT to a NUMBER and back to a PRAT, flattening/simplifying the rational in the process
|
||||
void flatrat(_Inout_ PRAT& prat, uint32_t radix, int32_t precision)
|
||||
{
|
||||
PNUMBER pnum = RatToNumber(prat, radix, precision);
|
||||
NUMBER pnum = RatToNumber(prat, radix, precision);
|
||||
|
||||
destroyrat(prat);
|
||||
prat = numtorat(pnum, radix);
|
||||
destroynum(pnum);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -1374,11 +1328,11 @@ void flatrat(_Inout_ PRAT& prat, uint32_t radix, int32_t precision)
|
|||
// FUNCTION: gcd
|
||||
//
|
||||
// ARGUMENTS:
|
||||
// PNUMBER representation of a number.
|
||||
// PNUMBER representation of a number.
|
||||
// NUMBER representation of a number.
|
||||
// NUMBER representation of a number.
|
||||
// int for Radix
|
||||
//
|
||||
// RETURN: Greatest common divisor in internal BASEX PNUMBER form.
|
||||
// RETURN: Greatest common divisor in internal BASEX NUMBER form.
|
||||
//
|
||||
// DESCRIPTION: gcd uses remainders to find the greatest common divisor.
|
||||
//
|
||||
|
@ -1390,11 +1344,11 @@ void flatrat(_Inout_ PRAT& prat, uint32_t radix, int32_t precision)
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
PNUMBER gcd( _In_ PNUMBER a, _In_ PNUMBER b)
|
||||
NUMBER gcd( _In_ NUMBER a, _In_ NUMBER b)
|
||||
{
|
||||
PNUMBER r= nullptr;
|
||||
PNUMBER larger= nullptr;
|
||||
PNUMBER smaller= nullptr;
|
||||
NUMBER r;
|
||||
NUMBER larger;
|
||||
NUMBER smaller;
|
||||
|
||||
if (zernum(a))
|
||||
{
|
||||
|
@ -1424,7 +1378,6 @@ PNUMBER gcd( _In_ PNUMBER a, _In_ PNUMBER b)
|
|||
larger = smaller;
|
||||
smaller = r;
|
||||
}
|
||||
destroynum(smaller);
|
||||
return larger;
|
||||
}
|
||||
|
||||
|
@ -1437,17 +1390,17 @@ PNUMBER gcd( _In_ PNUMBER a, _In_ PNUMBER b)
|
|||
// int32_t integer representing base of answer.
|
||||
// uint32_t integer for radix
|
||||
//
|
||||
// RETURN: Factorial of input in radix PNUMBER form.
|
||||
// RETURN: Factorial of input in radix NUMBER form.
|
||||
//
|
||||
// NOTE: Not currently used.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
PNUMBER i32factnum(int32_t ini32, uint32_t radix)
|
||||
NUMBER i32factnum(int32_t ini32, uint32_t radix)
|
||||
|
||||
{
|
||||
PNUMBER lret= nullptr;
|
||||
PNUMBER tmp= nullptr;
|
||||
NUMBER lret;
|
||||
NUMBER tmp;
|
||||
|
||||
lret = i32tonum( 1, radix);
|
||||
|
||||
|
@ -1455,7 +1408,6 @@ PNUMBER i32factnum(int32_t ini32, uint32_t radix)
|
|||
{
|
||||
tmp = i32tonum( ini32--, radix);
|
||||
mulnum( &lret, tmp, radix);
|
||||
destroynum( tmp );
|
||||
}
|
||||
return( lret );
|
||||
}
|
||||
|
@ -1469,15 +1421,15 @@ PNUMBER i32factnum(int32_t ini32, uint32_t radix)
|
|||
// int32_t integer representing base of answer.
|
||||
// uint32_t integer for radix
|
||||
//
|
||||
// RETURN: Factorial of input in base PNUMBER form.
|
||||
// RETURN: Factorial of input in base NUMBER form.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
PNUMBER i32prodnum(int32_t start, int32_t stop, uint32_t radix)
|
||||
NUMBER i32prodnum(int32_t start, int32_t stop, uint32_t radix)
|
||||
|
||||
{
|
||||
PNUMBER lret= nullptr;
|
||||
PNUMBER tmp= nullptr;
|
||||
NUMBER lret;
|
||||
NUMBER tmp;
|
||||
|
||||
lret = i32tonum( 1, radix);
|
||||
|
||||
|
@ -1487,7 +1439,6 @@ PNUMBER i32prodnum(int32_t start, int32_t stop, uint32_t radix)
|
|||
{
|
||||
tmp = i32tonum( start, radix);
|
||||
mulnum( &lret, tmp, radix);
|
||||
destroynum( tmp );
|
||||
}
|
||||
start++;
|
||||
}
|
||||
|
@ -1508,9 +1459,9 @@ PNUMBER i32prodnum(int32_t start, int32_t stop, uint32_t radix)
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void numpowi32( _Inout_ PNUMBER *proot, int32_t power, uint32_t radix, int32_t precision)
|
||||
void numpowi32( _Inout_ NUMBER *proot, int32_t power, uint32_t radix, int32_t precision)
|
||||
{
|
||||
PNUMBER lret = i32tonum( 1, radix );
|
||||
NUMBER lret = i32tonum( 1, radix );
|
||||
|
||||
while ( power > 0 )
|
||||
{
|
||||
|
@ -1522,7 +1473,6 @@ void numpowi32( _Inout_ PNUMBER *proot, int32_t power, uint32_t radix, int32_t p
|
|||
TRIMNUM(*proot, precision);
|
||||
power >>= 1;
|
||||
}
|
||||
destroynum( *proot );
|
||||
*proot=lret;
|
||||
|
||||
}
|
||||
|
@ -1546,7 +1496,7 @@ void ratpowi32( _Inout_ PRAT *proot, int32_t power, int32_t precision)
|
|||
if ( power < 0 )
|
||||
{
|
||||
// Take the positive power and invert answer.
|
||||
PNUMBER pnumtemp = nullptr;
|
||||
NUMBER pnumtemp;
|
||||
ratpowi32( proot, -power, precision);
|
||||
pnumtemp = (*proot)->pp;
|
||||
(*proot)->pp = (*proot)->pq;
|
||||
|
|
|
@ -133,15 +133,15 @@ void _lograt( PRAT *px, int32_t precision)
|
|||
createrat(thisterm);
|
||||
|
||||
// sub one from x
|
||||
(*px)->pq->sign *= -1;
|
||||
(*px)->pq.sign *= -1;
|
||||
addnum(&((*px)->pp),(*px)->pq, BASEX);
|
||||
(*px)->pq->sign *= -1;
|
||||
(*px)->pq.sign *= -1;
|
||||
|
||||
DUPRAT(pret,*px);
|
||||
DUPRAT(thisterm,*px);
|
||||
|
||||
n2=i32tonum(1L, BASEX);
|
||||
(*px)->pp->sign *= -1;
|
||||
(*px)->pp.sign *= -1;
|
||||
|
||||
do {
|
||||
NEXTTERM(*px, MULNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
|
@ -171,7 +171,7 @@ void lograt( PRAT *px, int32_t precision)
|
|||
if ( fneglog )
|
||||
{
|
||||
// WARNING: This is equivalent to doing *px = 1 / *px
|
||||
PNUMBER pnumtemp= nullptr;
|
||||
NUMBER pnumtemp;
|
||||
pnumtemp = (*px)->pp;
|
||||
(*px)->pp = (*px)->pq;
|
||||
(*px)->pq = pnumtemp;
|
||||
|
@ -185,7 +185,7 @@ void lograt( PRAT *px, int32_t precision)
|
|||
// a reasonable range.
|
||||
int32_t intpwr;
|
||||
intpwr=LOGRAT2(*px)-1;
|
||||
(*px)->pq->exp += intpwr;
|
||||
(*px)->pq.exp += intpwr;
|
||||
pwr=i32torat(intpwr*BASEXPWR);
|
||||
mulrat(&pwr, ln_two, precision);
|
||||
// ln(x+e)-ln(x) looks close to e when x is close to one using some
|
||||
|
@ -220,7 +220,7 @@ void lograt( PRAT *px, int32_t precision)
|
|||
// If number started out < 1 rescale answer to negative.
|
||||
if ( fneglog )
|
||||
{
|
||||
(*px)->pp->sign *= -1;
|
||||
(*px)->pp.sign *= -1;
|
||||
}
|
||||
|
||||
destroyrat(offset);
|
||||
|
@ -347,7 +347,7 @@ void powratNumeratorDenominator(PRAT *px, PRAT y, uint32_t radix, int32_t precis
|
|||
// ##################################
|
||||
PRAT roundedResult = nullptr;
|
||||
DUPRAT(roundedResult, originalResult);
|
||||
if (roundedResult->pp->sign == -1)
|
||||
if (roundedResult->pp.sign == -1)
|
||||
{
|
||||
subrat(&roundedResult, rat_half, precision);
|
||||
}
|
||||
|
@ -408,11 +408,11 @@ void powratNumeratorDenominator(PRAT *px, PRAT y, uint32_t radix, int32_t precis
|
|||
//---------------------------------------------------------------------------
|
||||
void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
|
||||
{
|
||||
int32_t sign = ((*px)->pp->sign * (*px)->pq->sign);
|
||||
int32_t sign = ((*px)->pp.sign * (*px)->pq.sign);
|
||||
|
||||
// Take the absolute value
|
||||
(*px)->pp->sign = 1;
|
||||
(*px)->pq->sign = 1;
|
||||
(*px)->pp.sign = 1;
|
||||
(*px)->pq.sign = 1;
|
||||
|
||||
if ( zerrat( *px ) )
|
||||
{
|
||||
|
@ -497,9 +497,9 @@ void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
|
|||
DUPRAT(pDenominator, rat_zero); // pDenominator->pq is 1 one
|
||||
|
||||
DUPNUM(pNumerator->pp, y->pp);
|
||||
pNumerator->pp->sign = 1;
|
||||
pNumerator->pp.sign = 1;
|
||||
DUPNUM(pDenominator->pp, y->pq);
|
||||
pDenominator->pp->sign = 1;
|
||||
pDenominator->pp.sign = 1;
|
||||
|
||||
while (IsEven(pNumerator, radix, precision) && IsEven(pDenominator, radix, precision)) // both Numerator & denominator is even
|
||||
{
|
||||
|
@ -536,5 +536,5 @@ void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
|
|||
}
|
||||
destroyrat(pxint);
|
||||
}
|
||||
(*px)->pp->sign *= sign;
|
||||
(*px)->pp.sign *= sign;
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
#include "ratpak.h"
|
||||
|
||||
|
||||
#define ABSRAT(x) (((x)->pp->sign=1),((x)->pq->sign=1))
|
||||
#define NEGATE(x) ((x)->pp->sign *= -1)
|
||||
#define ABSRAT(x) (((x)->pp.sign=1),((x)->pq.sign=1))
|
||||
#define NEGATE(x) ((x)->pp.sign *= -1)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
|
@ -61,7 +61,7 @@ void _gamma( PRAT *pn, uint32_t radix, int32_t precision)
|
|||
|
||||
{
|
||||
PRAT factorial= nullptr;
|
||||
PNUMBER count= nullptr;
|
||||
NUMBER count;
|
||||
PRAT tmp= nullptr;
|
||||
PRAT one_pt_five= nullptr;
|
||||
PRAT a= nullptr;
|
||||
|
@ -185,7 +185,6 @@ void _gamma( PRAT *pn, uint32_t radix, int32_t precision)
|
|||
destroyrat(tmp);
|
||||
destroyrat(one_pt_five);
|
||||
|
||||
destroynum(count);
|
||||
|
||||
destroyrat(factorial);
|
||||
destroyrat(*pn);
|
||||
|
@ -209,14 +208,14 @@ void factrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
DUPRAT(fact,rat_one);
|
||||
|
||||
DUPRAT(neg_rat_one,rat_one);
|
||||
neg_rat_one->pp->sign *= -1;
|
||||
neg_rat_one->pp.sign *= -1;
|
||||
|
||||
DUPRAT( frac, *px );
|
||||
fracrat( &frac, radix, precision);
|
||||
|
||||
// Check for negative integers and throw an error.
|
||||
if ( ( zerrat(frac) || ( LOGRATRADIX(frac) <= -precision) ) &&
|
||||
( (*px)->pp->sign * (*px)->pq->sign == -1 ) )
|
||||
( (*px)->pp.sign * (*px)->pq.sign == -1 ) )
|
||||
{
|
||||
throw CALC_E_DOMAIN;
|
||||
}
|
||||
|
|
|
@ -96,10 +96,10 @@ void asinrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
PRAT pret= nullptr;
|
||||
PRAT phack= nullptr;
|
||||
|
||||
sgn = (*px)->pp->sign* (*px)->pq->sign;
|
||||
sgn = (*px)->pp.sign* (*px)->pq.sign;
|
||||
|
||||
(*px)->pp->sign = 1;
|
||||
(*px)->pq->sign = 1;
|
||||
(*px)->pp.sign = 1;
|
||||
(*px)->pq.sign = 1;
|
||||
|
||||
// Avoid the really bad part of the asin curve near +/-1.
|
||||
DUPRAT(phack,*px);
|
||||
|
@ -129,11 +129,11 @@ void asinrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
}
|
||||
DUPRAT(pret,*px);
|
||||
mulrat( px, pret, precision);
|
||||
(*px)->pp->sign *= -1;
|
||||
(*px)->pp.sign *= -1;
|
||||
addrat( px, rat_one, precision);
|
||||
rootrat( px, rat_two, radix, precision);
|
||||
_asinrat( px, precision);
|
||||
(*px)->pp->sign *= -1;
|
||||
(*px)->pp.sign *= -1;
|
||||
addrat( px, pi_over_two, precision);
|
||||
destroyrat(pret);
|
||||
}
|
||||
|
@ -142,8 +142,8 @@ void asinrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
_asinrat( px, precision);
|
||||
}
|
||||
}
|
||||
(*px)->pp->sign = sgn;
|
||||
(*px)->pq->sign = 1;
|
||||
(*px)->pp.sign = sgn;
|
||||
(*px)->pq.sign = 1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -206,10 +206,10 @@ void acosrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
{
|
||||
int32_t sgn;
|
||||
|
||||
sgn = (*px)->pp->sign*(*px)->pq->sign;
|
||||
sgn = (*px)->pp.sign*(*px)->pq.sign;
|
||||
|
||||
(*px)->pp->sign = 1;
|
||||
(*px)->pq->sign = 1;
|
||||
(*px)->pp.sign = 1;
|
||||
(*px)->pq.sign = 1;
|
||||
|
||||
if ( rat_equ( *px, rat_one, precision) )
|
||||
{
|
||||
|
@ -224,9 +224,9 @@ void acosrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
}
|
||||
else
|
||||
{
|
||||
(*px)->pp->sign = sgn;
|
||||
(*px)->pp.sign = sgn;
|
||||
asinrat( px, radix, precision);
|
||||
(*px)->pp->sign *= -1;
|
||||
(*px)->pp.sign *= -1;
|
||||
addrat(px, pi_over_two, precision);
|
||||
}
|
||||
}
|
||||
|
@ -279,7 +279,7 @@ void _atanrat( PRAT *px, int32_t precision)
|
|||
|
||||
DUPNUM(n2,num_one);
|
||||
|
||||
xx->pp->sign *= -1;
|
||||
xx->pp.sign *= -1;
|
||||
|
||||
do {
|
||||
NEXTTERM(xx,MULNUM(n2) INC(n2) INC(n2) DIVNUM(n2), precision);
|
||||
|
@ -294,29 +294,29 @@ void atanrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
int32_t sgn;
|
||||
PRAT tmpx= nullptr;
|
||||
|
||||
sgn = (*px)->pp->sign * (*px)->pq->sign;
|
||||
sgn = (*px)->pp.sign * (*px)->pq.sign;
|
||||
|
||||
(*px)->pp->sign = 1;
|
||||
(*px)->pq->sign = 1;
|
||||
(*px)->pp.sign = 1;
|
||||
(*px)->pq.sign = 1;
|
||||
|
||||
if ( rat_gt( (*px), pt_eight_five, precision) )
|
||||
{
|
||||
if ( rat_gt( (*px), rat_two, precision) )
|
||||
{
|
||||
(*px)->pp->sign = sgn;
|
||||
(*px)->pq->sign = 1;
|
||||
(*px)->pp.sign = sgn;
|
||||
(*px)->pq.sign = 1;
|
||||
DUPRAT(tmpx,rat_one);
|
||||
divrat(&tmpx, (*px), precision);
|
||||
_atanrat(&tmpx, precision);
|
||||
tmpx->pp->sign = sgn;
|
||||
tmpx->pq->sign = 1;
|
||||
tmpx->pp.sign = sgn;
|
||||
tmpx->pq.sign = 1;
|
||||
DUPRAT(*px,pi_over_two);
|
||||
subrat(px, tmpx, precision);
|
||||
destroyrat( tmpx );
|
||||
}
|
||||
else
|
||||
{
|
||||
(*px)->pp->sign = sgn;
|
||||
(*px)->pp.sign = sgn;
|
||||
DUPRAT(tmpx,*px);
|
||||
mulrat( &tmpx, *px, precision);
|
||||
addrat( &tmpx, rat_one, precision);
|
||||
|
@ -324,14 +324,14 @@ void atanrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
divrat( px, tmpx, precision);
|
||||
destroyrat( tmpx );
|
||||
asinrat( px, radix, precision);
|
||||
(*px)->pp->sign = sgn;
|
||||
(*px)->pq->sign = 1;
|
||||
(*px)->pp.sign = sgn;
|
||||
(*px)->pq.sign = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
(*px)->pp->sign = sgn;
|
||||
(*px)->pq->sign = 1;
|
||||
(*px)->pp.sign = sgn;
|
||||
(*px)->pq.sign = 1;
|
||||
_atanrat( px, precision);
|
||||
}
|
||||
if ( rat_gt( *px, pi_over_two, precision) )
|
||||
|
|
|
@ -56,7 +56,7 @@ void asinhrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
PRAT neg_pt_eight_five = nullptr;
|
||||
|
||||
DUPRAT(neg_pt_eight_five,pt_eight_five);
|
||||
neg_pt_eight_five->pp->sign *= -1;
|
||||
neg_pt_eight_five->pp.sign *= -1;
|
||||
if ( rat_gt( *px, pt_eight_five, precision) || rat_lt( *px, neg_pt_eight_five, precision) )
|
||||
{
|
||||
PRAT ptmp = nullptr;
|
||||
|
@ -71,7 +71,7 @@ void asinhrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
else
|
||||
{
|
||||
CREATETAYLOR();
|
||||
xx->pp->sign *= -1;
|
||||
xx->pp.sign *= -1;
|
||||
|
||||
DUPRAT(pret,(*px));
|
||||
DUPRAT(thisterm,(*px));
|
||||
|
@ -152,7 +152,7 @@ void atanhrat( PRAT *px, int32_t precision)
|
|||
subrat(&ptmp, rat_one, precision);
|
||||
addrat(px, rat_one, precision);
|
||||
divrat(px, ptmp, precision);
|
||||
(*px)->pp->sign *= -1;
|
||||
(*px)->pp.sign *= -1;
|
||||
lograt(px, precision);
|
||||
divrat(px, rat_two, precision);
|
||||
destroyrat(ptmp);
|
||||
|
|
|
@ -65,7 +65,7 @@ void rshrat( PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
|
|||
}
|
||||
|
||||
void boolrat( PRAT *pa, PRAT b, int func, uint32_t radix, int32_t precision);
|
||||
void boolnum( PNUMBER *pa, PNUMBER b, int func );
|
||||
void boolnum( NUMBER *pa, NUMBER b, int func );
|
||||
|
||||
|
||||
enum {
|
||||
|
@ -130,11 +130,11 @@ void boolrat( PRAT *pa, PRAT b, int func, uint32_t radix, int32_t precision)
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void boolnum( PNUMBER *pa, PNUMBER b, int func )
|
||||
void boolnum( NUMBER *pa, NUMBER b, int func )
|
||||
|
||||
{
|
||||
PNUMBER c= nullptr;
|
||||
PNUMBER a= nullptr;
|
||||
NUMBER c;
|
||||
NUMBER a;
|
||||
vector<MANTTYPE>::iterator pcha;
|
||||
vector<MANTTYPE>::iterator pchb;
|
||||
vector<MANTTYPE>::iterator pchc;
|
||||
|
@ -144,22 +144,22 @@ void boolnum( PNUMBER *pa, PNUMBER b, int func )
|
|||
MANTTYPE db;
|
||||
|
||||
a=*pa;
|
||||
cdigits = max( a->cdigit+a->exp, b->cdigit+b->exp ) -
|
||||
min( a->exp, b->exp );
|
||||
cdigits = max( a.cdigit+a.exp, b.cdigit+b.exp ) -
|
||||
min( a.exp, b.exp );
|
||||
createnum( c, cdigits );
|
||||
c->exp = min( a->exp, b->exp );
|
||||
mexp = c->exp;
|
||||
c->cdigit = cdigits;
|
||||
pcha = a->mant.begin();
|
||||
pchb = b->mant.begin();
|
||||
pchc = c->mant.begin();
|
||||
c.exp = min( a.exp, b.exp );
|
||||
mexp = c.exp;
|
||||
c.cdigit = cdigits;
|
||||
pcha = a.mant.begin();
|
||||
pchb = b.mant.begin();
|
||||
pchc = c.mant.begin();
|
||||
for ( ;cdigits > 0; cdigits--, mexp++ )
|
||||
{
|
||||
da = ( ( ( mexp >= a->exp ) && ( cdigits + a->exp - c->exp >
|
||||
(c->cdigit - a->cdigit) ) ) ?
|
||||
da = ( ( ( mexp >= a.exp ) && ( cdigits + a.exp - c.exp >
|
||||
(c.cdigit - a.cdigit) ) ) ?
|
||||
*pcha++ : 0 );
|
||||
db = ( ( ( mexp >= b->exp ) && ( cdigits + b->exp - c->exp >
|
||||
(c->cdigit - b->cdigit) ) ) ?
|
||||
db = ( ( ( mexp >= b.exp ) && ( cdigits + b.exp - c.exp >
|
||||
(c.cdigit - b.cdigit) ) ) ?
|
||||
*pchb++ : 0 );
|
||||
switch ( func )
|
||||
{
|
||||
|
@ -174,12 +174,11 @@ void boolnum( PNUMBER *pa, PNUMBER b, int func )
|
|||
break;
|
||||
}
|
||||
}
|
||||
c->sign = a->sign;
|
||||
while ( c->cdigit > 1 && *(--pchc) == 0 )
|
||||
c.sign = a.sign;
|
||||
while ( c.cdigit > 1 && *(--pchc) == 0 )
|
||||
{
|
||||
c->cdigit--;
|
||||
c.cdigit--;
|
||||
}
|
||||
destroynum( *pa );
|
||||
*pa=c;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,14 +40,14 @@ using namespace std;
|
|||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix);
|
||||
void _addnum( NUMBER *pa, NUMBER b, uint32_t radix);
|
||||
|
||||
void __inline addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
||||
void __inline addnum( NUMBER *pa, NUMBER b, uint32_t radix)
|
||||
|
||||
{
|
||||
if ( b->cdigit > 1 || b->mant[0] != 0 )
|
||||
if ( b.cdigit > 1 || b.mant[0] != 0 )
|
||||
{ // If b is zero we are done.
|
||||
if ( (*pa)->cdigit > 1 || (*pa)->mant[0] != 0 )
|
||||
if ( (*pa).cdigit > 1 || (*pa).mant[0] != 0 )
|
||||
{ // pa and b are both nonzero.
|
||||
_addnum( pa, b, radix);
|
||||
}
|
||||
|
@ -58,11 +58,11 @@ void __inline addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
}
|
||||
}
|
||||
|
||||
void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
||||
void _addnum( NUMBER *pa, NUMBER b, uint32_t radix)
|
||||
|
||||
{
|
||||
PNUMBER c= nullptr; // c will contain the result.
|
||||
PNUMBER a= nullptr; // a is the dereferenced number pointer from *pa
|
||||
NUMBER c; // c will contain the result.
|
||||
NUMBER a; // a is the dereferenced number pointer from *pa
|
||||
vector<MANTTYPE>::iterator pcha; // pcha is an iterator pointing to the mantissa of a.
|
||||
vector<MANTTYPE>::iterator pchb; // pchb is an iterator pointing to the mantissa of b.
|
||||
vector<MANTTYPE>::iterator pchc; // pchc is an iterator pointing to the mantissa of c.
|
||||
|
@ -80,23 +80,23 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
|
||||
// Calculate the overlap of the numbers after alignment, this includes
|
||||
// necessary padding 0's
|
||||
cdigits = max( a->cdigit+a->exp, b->cdigit+b->exp ) -
|
||||
min( a->exp, b->exp );
|
||||
cdigits = max( a.cdigit+a.exp, b.cdigit+b.exp ) -
|
||||
min( a.exp, b.exp );
|
||||
|
||||
createnum( c, cdigits + 1 );
|
||||
c->exp = min( a->exp, b->exp );
|
||||
mexp = c->exp;
|
||||
c->cdigit = cdigits;
|
||||
pcha = a->mant.begin();
|
||||
pchb = b->mant.begin();
|
||||
pchc = c->mant.begin();
|
||||
c.exp = min( a.exp, b.exp );
|
||||
mexp = c.exp;
|
||||
c.cdigit = cdigits;
|
||||
pcha = a.mant.begin();
|
||||
pchb = b.mant.begin();
|
||||
pchc = c.mant.begin();
|
||||
|
||||
// Figure out the sign of the numbers
|
||||
if ( a->sign != b->sign )
|
||||
if ( a.sign != b.sign )
|
||||
{
|
||||
cy = 1;
|
||||
fcompla = ( a->sign == -1 );
|
||||
fcomplb = ( b->sign == -1 );
|
||||
fcompla = ( a.sign == -1 );
|
||||
fcomplb = ( b.sign == -1 );
|
||||
}
|
||||
|
||||
// Loop over all the digits, real and 0 padded. Here we know a and b are
|
||||
|
@ -105,12 +105,12 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
{
|
||||
|
||||
// Get digit from a, taking padding into account.
|
||||
da = ( ( ( mexp >= a->exp ) && ( cdigits + a->exp - c->exp >
|
||||
(c->cdigit - a->cdigit) ) ) ?
|
||||
da = ( ( ( mexp >= a.exp ) && ( cdigits + a.exp - c.exp >
|
||||
(c.cdigit - a.cdigit) ) ) ?
|
||||
*pcha++ : 0 );
|
||||
// Get digit from b, taking padding into account.
|
||||
db = ( ( ( mexp >= b->exp ) && ( cdigits + b->exp - c->exp >
|
||||
(c->cdigit - b->cdigit) ) ) ?
|
||||
db = ( ( ( mexp >= b.exp ) && ( cdigits + b.exp - c.exp >
|
||||
(c.cdigit - b.cdigit) ) ) ?
|
||||
*pchb++ : 0 );
|
||||
|
||||
// Handle complementing for a and b digit. Might be a better way, but
|
||||
|
@ -134,19 +134,19 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
if ( cy && !(fcompla || fcomplb) )
|
||||
{
|
||||
*pchc++ = cy;
|
||||
c->cdigit++;
|
||||
c.cdigit++;
|
||||
}
|
||||
|
||||
// Compute sign of result
|
||||
if ( !(fcompla || fcomplb) )
|
||||
{
|
||||
c->sign = a->sign;
|
||||
c.sign = a.sign;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( cy )
|
||||
{
|
||||
c->sign = 1;
|
||||
c.sign = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -154,9 +154,9 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
// and all the digits need to be complemented, at one time an
|
||||
// attempt to handle this above was made, it turned out to be much
|
||||
// slower on average.
|
||||
c->sign = -1;
|
||||
c.sign = -1;
|
||||
cy = 1;
|
||||
for ( ( cdigits = c->cdigit ), (pchc = c->mant.begin());
|
||||
for ( ( cdigits = c.cdigit ), (pchc = c.mant.begin());
|
||||
cdigits > 0;
|
||||
cdigits-- )
|
||||
{
|
||||
|
@ -169,11 +169,10 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
|
||||
// Remove leading zeros, remember digits are in order of
|
||||
// increasing significance. i.e. 100 would be 0,0,1
|
||||
while ( c->cdigit > 1 && *(--pchc) == 0 )
|
||||
while ( c.cdigit > 1 && *(--pchc) == 0 )
|
||||
{
|
||||
c->cdigit--;
|
||||
c.cdigit--;
|
||||
}
|
||||
destroynum( *pa );
|
||||
*pa=c;
|
||||
}
|
||||
|
||||
|
@ -192,35 +191,35 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix);
|
||||
void _mulnum( NUMBER *pa, NUMBER b, uint32_t radix);
|
||||
|
||||
void __inline mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
||||
void __inline mulnum( NUMBER *pa, NUMBER b, uint32_t radix)
|
||||
|
||||
{
|
||||
if ( b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0 )
|
||||
if ( b.cdigit > 1 || b.mant[0] != 1 || b.exp != 0 )
|
||||
{ // If b is one we don't multiply exactly.
|
||||
if ( (*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0 )
|
||||
if ( (*pa).cdigit > 1 || (*pa).mant[0] != 1 || (*pa).exp != 0 )
|
||||
{ // pa and b are both non-one.
|
||||
_mulnum( pa, b, radix);
|
||||
}
|
||||
else
|
||||
{ // if pa is one and b isn't just copy b, and adjust the sign.
|
||||
int32_t sign = (*pa)->sign;
|
||||
int32_t sign = (*pa).sign;
|
||||
DUPNUM(*pa,b);
|
||||
(*pa)->sign *= sign;
|
||||
(*pa).sign *= sign;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // But we do have to set the sign.
|
||||
(*pa)->sign *= b->sign;
|
||||
(*pa).sign *= b.sign;
|
||||
}
|
||||
}
|
||||
|
||||
void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
||||
void _mulnum( NUMBER *pa, NUMBER b, uint32_t radix)
|
||||
|
||||
{
|
||||
PNUMBER c= nullptr; // c will contain the result.
|
||||
PNUMBER a= nullptr; // a is the dereferenced number pointer from *pa
|
||||
NUMBER c; // c will contain the result.
|
||||
NUMBER a; // a is the dereferenced number pointer from *pa
|
||||
vector<MANTTYPE>::iterator pcha; // pcha is an iterator pointing to the mantissa of a.
|
||||
vector<MANTTYPE>::iterator pchb; // pchb is an iterator pointing to the mantissa of b.
|
||||
vector<MANTTYPE>::iterator pchc; // pchc is an iterator pointing to the mantissa of c.
|
||||
|
@ -236,24 +235,24 @@ void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
int32_t icdigit = 0; // Index of digit being calculated in final result.
|
||||
|
||||
a=*pa;
|
||||
ibdigit = a->cdigit + b->cdigit - 1;
|
||||
ibdigit = a.cdigit + b.cdigit - 1;
|
||||
createnum( c, ibdigit + 1 );
|
||||
c->cdigit = ibdigit;
|
||||
c->sign = a->sign * b->sign;
|
||||
c.cdigit = ibdigit;
|
||||
c.sign = a.sign * b.sign;
|
||||
|
||||
c->exp = a->exp + b->exp;
|
||||
pcha = a->mant.begin();
|
||||
pchcoffset = c->mant.begin();
|
||||
c.exp = a.exp + b.exp;
|
||||
pcha = a.mant.begin();
|
||||
pchcoffset = c.mant.begin();
|
||||
|
||||
for ( iadigit = a->cdigit; iadigit > 0; iadigit-- )
|
||||
for ( iadigit = a.cdigit; iadigit > 0; iadigit-- )
|
||||
{
|
||||
da = *pcha++;
|
||||
pchb = b->mant.begin();
|
||||
pchb = b.mant.begin();
|
||||
|
||||
// Shift pchc, and pchcoffset, one for each digit
|
||||
pchc = pchcoffset++;
|
||||
|
||||
for ( ibdigit = b->cdigit; ibdigit > 0; ibdigit-- )
|
||||
for ( ibdigit = b.cdigit; ibdigit > 0; ibdigit-- )
|
||||
{
|
||||
cy = 0;
|
||||
mcy = (TWO_MANTTYPE)da * *pchb;
|
||||
|
@ -262,7 +261,7 @@ void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
icdigit = 0;
|
||||
if ( ibdigit == 1 && iadigit == 1 )
|
||||
{
|
||||
c->cdigit++;
|
||||
c.cdigit++;
|
||||
}
|
||||
}
|
||||
// If result is nonzero, or while result of carry is nonzero...
|
||||
|
@ -287,12 +286,11 @@ void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
|
||||
// prevent different kinds of zeros, by stripping leading duplicate zeros.
|
||||
// digits are in order of increasing significance.
|
||||
while ( c->cdigit > 1 && c->mant[c->cdigit-1] == 0 )
|
||||
while ( c.cdigit > 1 && c.mant[c.cdigit-1] == 0 )
|
||||
{
|
||||
c->cdigit--;
|
||||
c.cdigit--;
|
||||
}
|
||||
|
||||
destroynum( *pa );
|
||||
*pa=c;
|
||||
}
|
||||
|
||||
|
@ -312,11 +310,11 @@ void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void remnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
||||
void remnum( NUMBER *pa, NUMBER b, uint32_t radix)
|
||||
|
||||
{
|
||||
PNUMBER tmp = nullptr; // tmp is the working remainder.
|
||||
PNUMBER lasttmp = nullptr; // lasttmp is the last remainder which worked.
|
||||
NUMBER tmp; // tmp is the working remainder.
|
||||
NUMBER lasttmp; // lasttmp is the last remainder which worked.
|
||||
|
||||
// Once *pa is less than b, *pa is the remainder.
|
||||
while ( !lessnum( *pa, b ) )
|
||||
|
@ -325,15 +323,14 @@ void remnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
if ( lessnum( tmp, *pa ) )
|
||||
{
|
||||
// Start off close to the right answer for subtraction.
|
||||
tmp->exp = (*pa)->cdigit+(*pa)->exp - tmp->cdigit;
|
||||
tmp.exp = (*pa).cdigit+(*pa).exp - tmp.cdigit;
|
||||
if ( MSD(*pa) <= MSD(tmp) )
|
||||
{
|
||||
// Don't take the chance that the numbers are equal.
|
||||
tmp->exp--;
|
||||
tmp.exp--;
|
||||
}
|
||||
}
|
||||
|
||||
destroynum( lasttmp );
|
||||
lasttmp=i32tonum( 0, radix);
|
||||
|
||||
while ( lessnum( tmp, *pa ) )
|
||||
|
@ -345,17 +342,14 @@ void remnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
if ( lessnum( *pa, tmp ) )
|
||||
{
|
||||
// too far, back up...
|
||||
destroynum( tmp );
|
||||
tmp=lasttmp;
|
||||
lasttmp= nullptr;
|
||||
}
|
||||
|
||||
// Subtract the working remainder from the remainder holder.
|
||||
tmp->sign = -1*(*pa)->sign;
|
||||
tmp.sign = -1*(*pa).sign;
|
||||
addnum( pa, tmp, radix);
|
||||
|
||||
destroynum( tmp );
|
||||
destroynum( lasttmp );
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -375,68 +369,67 @@ void remnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision);
|
||||
void _divnum( NUMBER *pa, NUMBER b, uint32_t radix, int32_t precision);
|
||||
|
||||
void __inline divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
|
||||
void __inline divnum( NUMBER *pa, NUMBER b, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
if ( b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0 )
|
||||
if ( b.cdigit > 1 || b.mant[0] != 1 || b.exp != 0 )
|
||||
{
|
||||
// b is not one
|
||||
_divnum( pa, b, radix, precision);
|
||||
}
|
||||
else
|
||||
{ // But we do have to set the sign.
|
||||
(*pa)->sign *= b->sign;
|
||||
(*pa).sign *= b.sign;
|
||||
}
|
||||
}
|
||||
|
||||
void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
|
||||
void _divnum( NUMBER *pa, NUMBER b, uint32_t radix, int32_t precision)
|
||||
{
|
||||
PNUMBER a = *pa;
|
||||
NUMBER a = *pa;
|
||||
int32_t thismax = precision + 2;
|
||||
if (thismax < a->cdigit)
|
||||
if (thismax < a.cdigit)
|
||||
{
|
||||
thismax = a->cdigit;
|
||||
thismax = a.cdigit;
|
||||
}
|
||||
|
||||
if (thismax < b->cdigit)
|
||||
if (thismax < b.cdigit)
|
||||
{
|
||||
thismax = b->cdigit;
|
||||
thismax = b.cdigit;
|
||||
}
|
||||
|
||||
PNUMBER c = nullptr;
|
||||
NUMBER c;
|
||||
createnum(c, thismax + 1);
|
||||
c->exp = (a->cdigit + a->exp) - (b->cdigit + b->exp) + 1;
|
||||
c->sign = a->sign * b->sign;
|
||||
c.exp = (a.cdigit + a.exp) - (b.cdigit + b.exp) + 1;
|
||||
c.sign = a.sign * b.sign;
|
||||
|
||||
vector<MANTTYPE>::iterator ptrc = c->mant.begin() + thismax;
|
||||
PNUMBER rem = nullptr;
|
||||
PNUMBER tmp = nullptr;
|
||||
vector<MANTTYPE>::iterator ptrc = c.mant.begin() + thismax;
|
||||
NUMBER rem;
|
||||
NUMBER tmp;
|
||||
DUPNUM(rem, a);
|
||||
DUPNUM(tmp, b);
|
||||
tmp->sign = a->sign;
|
||||
rem->exp = b->cdigit + b->exp - rem->cdigit;
|
||||
tmp.sign = a.sign;
|
||||
rem.exp = b.cdigit + b.exp - rem.cdigit;
|
||||
|
||||
// Build a table of multiplications of the divisor, this is quicker for
|
||||
// more than radix 'digits'
|
||||
list<PNUMBER> numberList{ i32tonum(0L, radix) };
|
||||
list<NUMBER> numberList{ i32tonum(0L, radix) };
|
||||
for (uint32_t i = 1; i < radix; i++)
|
||||
{
|
||||
PNUMBER newValue = nullptr;
|
||||
NUMBER newValue;
|
||||
DUPNUM(newValue, numberList.front());
|
||||
addnum(&newValue, tmp, radix);
|
||||
|
||||
numberList.emplace_front(newValue);
|
||||
}
|
||||
destroynum(tmp);
|
||||
|
||||
int32_t digit;
|
||||
int32_t cdigits = 0;
|
||||
while (cdigits++ < thismax && !zernum(rem))
|
||||
{
|
||||
digit = radix - 1;
|
||||
PNUMBER multiple = nullptr;
|
||||
NUMBER multiple;
|
||||
for (const auto& num : numberList)
|
||||
{
|
||||
if (!lessnum(rem, num) || !--digit)
|
||||
|
@ -448,43 +441,40 @@ void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
|
|||
|
||||
if (digit)
|
||||
{
|
||||
multiple->sign *= -1;
|
||||
multiple.sign *= -1;
|
||||
addnum(&rem, multiple, radix);
|
||||
multiple->sign *= -1;
|
||||
multiple.sign *= -1;
|
||||
}
|
||||
rem->exp++;
|
||||
rem.exp++;
|
||||
*ptrc-- = (MANTTYPE)digit;
|
||||
}
|
||||
cdigits--;
|
||||
|
||||
if (c->mant.begin() != ++ptrc)
|
||||
if (c.mant.begin() != ++ptrc)
|
||||
{
|
||||
copy(ptrc, ptrc + cdigits, c->mant.begin());
|
||||
copy(ptrc, ptrc + cdigits, c.mant.begin());
|
||||
}
|
||||
|
||||
// Cleanup table structure
|
||||
for (auto& num : numberList)
|
||||
{
|
||||
destroynum(num);
|
||||
}
|
||||
|
||||
if (!cdigits)
|
||||
{
|
||||
c->cdigit = 1;
|
||||
c->exp = 0;
|
||||
c.cdigit = 1;
|
||||
c.exp = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
c->cdigit = cdigits;
|
||||
c->exp -= cdigits;
|
||||
while (c->cdigit > 1 && c->mant[c->cdigit - 1] == 0)
|
||||
c.cdigit = cdigits;
|
||||
c.exp -= cdigits;
|
||||
while (c.cdigit > 1 && c.mant[c.cdigit - 1] == 0)
|
||||
{
|
||||
c->cdigit--;
|
||||
c.cdigit--;
|
||||
}
|
||||
}
|
||||
destroynum(rem);
|
||||
|
||||
destroynum(*pa);
|
||||
*pa = c;
|
||||
}
|
||||
|
||||
|
@ -502,7 +492,7 @@ void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool equnum( PNUMBER a, PNUMBER b )
|
||||
bool equnum( NUMBER a, NUMBER b )
|
||||
|
||||
{
|
||||
int32_t diff;
|
||||
|
@ -513,7 +503,7 @@ bool equnum( PNUMBER a, PNUMBER b )
|
|||
MANTTYPE da;
|
||||
MANTTYPE db;
|
||||
|
||||
diff = ( a->cdigit + a->exp ) - ( b->cdigit + b->exp );
|
||||
diff = ( a.cdigit + a.exp ) - ( b.cdigit + b.exp );
|
||||
if ( diff < 0 )
|
||||
{
|
||||
// If the exponents are different, these are different numbers.
|
||||
|
@ -529,19 +519,19 @@ bool equnum( PNUMBER a, PNUMBER b )
|
|||
else
|
||||
{
|
||||
// OK the exponents match.
|
||||
ia = a->cdigit - 1;
|
||||
ib = b->cdigit - 1;
|
||||
cdigits = max( a->cdigit, b->cdigit );
|
||||
ia = a.cdigit - 1;
|
||||
ib = b.cdigit - 1;
|
||||
cdigits = max( a.cdigit, b.cdigit );
|
||||
ccdigits = cdigits;
|
||||
|
||||
// Loop over all digits until we run out of digits or there is a
|
||||
// difference in the digits.
|
||||
for ( ;cdigits > 0; cdigits-- )
|
||||
{
|
||||
da = ( (cdigits > (ccdigits - a->cdigit) ) ?
|
||||
a->mant[ia--] : 0 );
|
||||
db = ( (cdigits > (ccdigits - b->cdigit) ) ?
|
||||
b->mant[ib--] : 0 );
|
||||
da = ( (cdigits > (ccdigits - a.cdigit) ) ?
|
||||
a.mant[ia--] : 0 );
|
||||
db = ( (cdigits > (ccdigits - b.cdigit) ) ?
|
||||
b.mant[ib--] : 0 );
|
||||
if ( da != db )
|
||||
{
|
||||
return false;
|
||||
|
@ -568,7 +558,7 @@ bool equnum( PNUMBER a, PNUMBER b )
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool lessnum( PNUMBER a, PNUMBER b )
|
||||
bool lessnum( NUMBER a, NUMBER b )
|
||||
|
||||
{
|
||||
int32_t diff;
|
||||
|
@ -580,7 +570,7 @@ bool lessnum( PNUMBER a, PNUMBER b )
|
|||
MANTTYPE db;
|
||||
|
||||
|
||||
diff = ( a->cdigit + a->exp ) - ( b->cdigit + b->exp );
|
||||
diff = ( a.cdigit + a.exp ) - ( b.cdigit + b.exp );
|
||||
if ( diff < 0 )
|
||||
{
|
||||
// The exponent of a is less than b
|
||||
|
@ -594,16 +584,16 @@ bool lessnum( PNUMBER a, PNUMBER b )
|
|||
}
|
||||
else
|
||||
{
|
||||
ia = a->cdigit - 1;
|
||||
ib = b->cdigit - 1;
|
||||
cdigits = max( a->cdigit, b->cdigit );
|
||||
ia = a.cdigit - 1;
|
||||
ib = b.cdigit - 1;
|
||||
cdigits = max( a.cdigit, b.cdigit );
|
||||
ccdigits = cdigits;
|
||||
for ( ;cdigits > 0; cdigits-- )
|
||||
{
|
||||
da = ( (cdigits > (ccdigits - a->cdigit) ) ?
|
||||
a->mant[ia--] : 0 );
|
||||
db = ( (cdigits > (ccdigits - b->cdigit) ) ?
|
||||
b->mant[ib--] : 0 );
|
||||
da = ( (cdigits > (ccdigits - a.cdigit) ) ?
|
||||
a.mant[ia--] : 0 );
|
||||
db = ( (cdigits > (ccdigits - b.cdigit) ) ?
|
||||
b.mant[ib--] : 0 );
|
||||
diff = da-db;
|
||||
if ( diff )
|
||||
{
|
||||
|
@ -628,17 +618,17 @@ bool lessnum( PNUMBER a, PNUMBER b )
|
|||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
bool zernum( PNUMBER a )
|
||||
bool zernum( NUMBER a )
|
||||
|
||||
{
|
||||
int32_t length = a->cdigit;
|
||||
int32_t length = a.cdigit;
|
||||
int32_t index = 0;
|
||||
|
||||
// loop over all the digits until you find a nonzero or until you run
|
||||
// out of digits
|
||||
while ( length-- > 0 )
|
||||
{
|
||||
if ( a->mant[index++] )
|
||||
if ( a.mant[index++] )
|
||||
{
|
||||
// One of the digits isn't zero, therefore the number isn't zero
|
||||
return false;
|
||||
|
|
|
@ -41,7 +41,7 @@ using namespace std;
|
|||
void gcdrat( PRAT *pa, int32_t precision)
|
||||
|
||||
{
|
||||
PNUMBER pgcd= nullptr;
|
||||
NUMBER pgcd;
|
||||
PRAT a= nullptr;
|
||||
|
||||
a=*pa;
|
||||
|
@ -53,7 +53,6 @@ void gcdrat( PRAT *pa, int32_t precision)
|
|||
divnumx( &(a->pq), pgcd, precision);
|
||||
}
|
||||
|
||||
destroynum( pgcd );
|
||||
*pa=a;
|
||||
|
||||
RENORMALIZE(*pa);
|
||||
|
@ -190,9 +189,9 @@ void divrat( PRAT *pa, PRAT b, int32_t precision)
|
|||
void subrat( PRAT *pa, PRAT b, int32_t precision)
|
||||
|
||||
{
|
||||
b->pp->sign *= -1;
|
||||
b->pp.sign *= -1;
|
||||
addrat( pa, b, precision);
|
||||
b->pp->sign *= -1;
|
||||
b->pp.sign *= -1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -211,7 +210,7 @@ void subrat( PRAT *pa, PRAT b, int32_t precision)
|
|||
void addrat( PRAT *pa, PRAT b, int32_t precision)
|
||||
|
||||
{
|
||||
PNUMBER bot= nullptr;
|
||||
NUMBER bot;
|
||||
|
||||
if ( equnum( (*pa)->pq, b->pq ) )
|
||||
{
|
||||
|
@ -219,10 +218,10 @@ void addrat( PRAT *pa, PRAT b, int32_t precision)
|
|||
// make sure signs are involved in the calculation
|
||||
// we have to do this since the optimization here is only
|
||||
// working with the top half of the rationals.
|
||||
(*pa)->pp->sign *= (*pa)->pq->sign;
|
||||
(*pa)->pq->sign = 1;
|
||||
b->pp->sign *= b->pq->sign;
|
||||
b->pq->sign = 1;
|
||||
(*pa)->pp.sign *= (*pa)->pq.sign;
|
||||
(*pa)->pq.sign = 1;
|
||||
b->pp.sign *= b->pq.sign;
|
||||
b->pq.sign = 1;
|
||||
addnum( &((*pa)->pp), b->pp, BASEX );
|
||||
}
|
||||
else
|
||||
|
@ -233,13 +232,12 @@ void addrat( PRAT *pa, PRAT b, int32_t precision)
|
|||
mulnumx( &((*pa)->pp), b->pq );
|
||||
mulnumx( &((*pa)->pq), b->pp );
|
||||
addnum( &((*pa)->pp), (*pa)->pq, BASEX );
|
||||
destroynum( (*pa)->pq );
|
||||
(*pa)->pq = bot;
|
||||
trimit(pa, precision);
|
||||
|
||||
// Get rid of negative zeros here.
|
||||
(*pa)->pp->sign *= (*pa)->pq->sign;
|
||||
(*pa)->pq->sign = 1;
|
||||
(*pa)->pp.sign *= (*pa)->pq.sign;
|
||||
(*pa)->pq.sign = 1;
|
||||
}
|
||||
|
||||
#ifdef ADDGCD
|
||||
|
|
|
@ -62,7 +62,7 @@ typedef struct _number
|
|||
int32_t exp; // The offset of digits from the radix point
|
||||
// (decimal point in radix 10)
|
||||
std::vector<MANTTYPE> mant;
|
||||
} NUMBER, *PNUMBER, **PPNUMBER;
|
||||
} NUMBER;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -74,8 +74,8 @@ typedef struct _number
|
|||
|
||||
typedef struct _rat
|
||||
{
|
||||
PNUMBER pp;
|
||||
PNUMBER pq;
|
||||
NUMBER pp;
|
||||
NUMBER pq;
|
||||
} RAT, *PRAT;
|
||||
|
||||
static constexpr uint32_t MAX_LONG_SIZE = 33; // Base 2 requires 32 'digits'
|
||||
|
@ -87,11 +87,11 @@ static constexpr uint32_t MAX_LONG_SIZE = 33; // Base 2 requires 32 'digits'
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
extern PNUMBER num_one;
|
||||
extern PNUMBER num_two;
|
||||
extern PNUMBER num_five;
|
||||
extern PNUMBER num_six;
|
||||
extern PNUMBER num_ten;
|
||||
extern NUMBER num_one;
|
||||
extern NUMBER num_two;
|
||||
extern NUMBER num_five;
|
||||
extern NUMBER num_six;
|
||||
extern NUMBER num_ten;
|
||||
|
||||
extern PRAT ln_ten;
|
||||
extern PRAT ln_two;
|
||||
|
@ -130,7 +130,7 @@ extern PRAT rat_max_i32;
|
|||
extern PRAT rat_min_i32;
|
||||
|
||||
// DUPNUM Duplicates a number taking care of allocation and internals
|
||||
#define DUPNUM(a,b) destroynum(a);createnum( a, (b)->cdigit );_dupnum(a, b);
|
||||
#define DUPNUM(a,b) createnum( a, (b).cdigit );_dupnum(a, &b);
|
||||
|
||||
// DUPRAT Duplicates a rational taking care of allocation and internals
|
||||
#define DUPRAT(a,b) destroyrat(a);createrat(a);DUPNUM((a)->pp,(b)->pp);DUPNUM((a)->pq,(b)->pq);
|
||||
|
@ -138,13 +138,13 @@ extern PRAT rat_min_i32;
|
|||
// LOG*RADIX calculates the integral portion of the log of a number in
|
||||
// the base currently being used, only accurate to within g_ratio
|
||||
|
||||
#define LOGNUMRADIX(pnum) (((pnum)->cdigit+(pnum)->exp)*g_ratio)
|
||||
#define LOGNUMRADIX(pnum) (((pnum).cdigit+(pnum).exp)*g_ratio)
|
||||
#define LOGRATRADIX(prat) (LOGNUMRADIX((prat)->pp)-LOGNUMRADIX((prat)->pq))
|
||||
|
||||
// LOG*2 calculates the integral portion of the log of a number in
|
||||
// the internal base being used, only accurate to within g_ratio
|
||||
|
||||
#define LOGNUM2(pnum) ((pnum)->cdigit+(pnum)->exp)
|
||||
#define LOGNUM2(pnum) ((pnum).cdigit+(pnum).exp)
|
||||
#define LOGRAT2(prat) (LOGNUM2((prat)->pp)-LOGNUM2((prat)->pq))
|
||||
|
||||
#if defined( DEBUG_RATPAK )
|
||||
|
@ -174,18 +174,14 @@ _destroyrat(x),(x)=nullptr
|
|||
outputString << "createnum " << y << " " << # y << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
|
||||
OutputDebugString(outputString.str().c_str()); \
|
||||
}
|
||||
#define destroynum(x) \
|
||||
{ \
|
||||
std::wstringstream outputString; \
|
||||
outputString << "destroynum " << x << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
|
||||
OutputDebugString(outputString.str().c_str()); \
|
||||
} \
|
||||
_destroynum(x),(x)=nullptr
|
||||
}
|
||||
#else
|
||||
#define createrat(y) (y)=_createrat()
|
||||
#define destroyrat(x) _destroyrat(x),(x)=nullptr
|
||||
#define createnum(y,x) (y)=_createnum(x)
|
||||
#define destroynum(x) _destroynum(x),(x)=nullptr
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -196,40 +192,40 @@ _destroynum(x),(x)=nullptr
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
// RENORMALIZE, gets the exponents non-negative.
|
||||
#define RENORMALIZE(x) if ( (x)->pp->exp < 0 ) { \
|
||||
(x)->pq->exp -= (x)->pp->exp; \
|
||||
(x)->pp->exp = 0; \
|
||||
#define RENORMALIZE(x) if ( (x)->pp.exp < 0 ) { \
|
||||
(x)->pq.exp -= (x)->pp.exp; \
|
||||
(x)->pp.exp = 0; \
|
||||
} \
|
||||
if ( (x)->pq->exp < 0 ) { \
|
||||
(x)->pp->exp -= (x)->pq->exp; \
|
||||
(x)->pq->exp = 0; \
|
||||
if ( (x)->pq.exp < 0 ) { \
|
||||
(x)->pp.exp -= (x)->pq.exp; \
|
||||
(x)->pq.exp = 0; \
|
||||
}
|
||||
|
||||
// TRIMNUM ASSUMES the number is in radix form NOT INTERNAL BASEX!!!
|
||||
#define TRIMNUM(x, precision) if ( !g_ftrueinfinite ) { \
|
||||
int32_t trim = (x)->cdigit - precision-g_ratio;\
|
||||
int32_t trim = (x).cdigit - precision-g_ratio;\
|
||||
if ( trim > 1 ) \
|
||||
{ \
|
||||
std::copy((x)->mant.begin() + trim, (x)->mant.begin() + (x)->cdigit, (x)->mant.begin());\
|
||||
(x)->cdigit -= trim; \
|
||||
(x)->exp += trim; \
|
||||
std::copy((x).mant.begin() + trim, (x).mant.begin() + (x).cdigit, (x).mant.begin());\
|
||||
(x).cdigit -= trim; \
|
||||
(x).exp += trim; \
|
||||
} \
|
||||
}
|
||||
// TRIMTOP ASSUMES the number is in INTERNAL BASEX!!!
|
||||
#define TRIMTOP(x, precision) if ( !g_ftrueinfinite ) { \
|
||||
int32_t trim = (x)->pp->cdigit - (precision/g_ratio) - 2;\
|
||||
int32_t trim = (x)->pp.cdigit - (precision/g_ratio) - 2;\
|
||||
if ( trim > 1 ) \
|
||||
{ \
|
||||
std::copy((x)->pp->mant.begin() + trim, (x)->pp->mant.begin() + (x)->pp->cdigit, (x)->pp->mant.begin()); \
|
||||
(x)->pp->cdigit -= trim; \
|
||||
(x)->pp->exp += trim; \
|
||||
std::copy((x)->pp.mant.begin() + trim, (x)->pp.mant.begin() + (x)->pp.cdigit, (x)->pp.mant.begin()); \
|
||||
(x)->pp.cdigit -= trim; \
|
||||
(x)->pp.exp += trim; \
|
||||
} \
|
||||
trim = std::min((x)->pp->exp,(x)->pq->exp);\
|
||||
(x)->pp->exp -= trim;\
|
||||
(x)->pq->exp -= trim;\
|
||||
trim = std::min((x)->pp.exp,(x)->pq.exp);\
|
||||
(x)->pp.exp -= trim;\
|
||||
(x)->pq.exp -= trim;\
|
||||
}
|
||||
|
||||
#define SMALL_ENOUGH_RAT(a, precision) (zernum((a)->pp) || ( ( ( (a)->pq->cdigit + (a)->pq->exp ) - ( (a)->pp->cdigit + (a)->pp->exp ) - 1 ) * g_ratio > precision ) )
|
||||
#define SMALL_ENOUGH_RAT(a, precision) (zernum((a)->pp) || ( ( ( (a)->pq.cdigit + (a)->pq.exp ) - ( (a)->pp.cdigit + (a)->pp.exp ) - 1 ) * g_ratio > precision ) )
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
|
@ -239,7 +235,7 @@ std::copy((x)->pp->mant.begin() + trim, (x)->pp->mant.begin() + (x)->pp->cdigit,
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define CREATETAYLOR() PRAT xx=nullptr;\
|
||||
PNUMBER n2=nullptr; \
|
||||
NUMBER n2; \
|
||||
PRAT pret=nullptr; \
|
||||
PRAT thisterm=nullptr; \
|
||||
DUPRAT(xx,*px); \
|
||||
|
@ -257,16 +253,16 @@ std::copy((x)->pp->mant.begin() + trim, (x)->pp->mant.begin() + (x)->pp->cdigit,
|
|||
|
||||
// INC(a) is the rational equivalent of a++
|
||||
// Check to see if we can avoid doing this the hard way.
|
||||
#define INC(a) if ( (a)->mant[0] < BASEX - 1 ) \
|
||||
#define INC(a) if ( (a).mant[0] < BASEX - 1 ) \
|
||||
{ \
|
||||
(a)->mant[0]++; \
|
||||
(a).mant[0]++; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
addnum( &(a), num_one, BASEX); \
|
||||
}
|
||||
|
||||
#define MSD(x) ((x)->mant[(x)->cdigit-1])
|
||||
#define MSD(x) ((x).mant[(x).cdigit-1])
|
||||
// MULNUM(b) is the rational equivalent of thisterm *= b where thisterm is
|
||||
// a rational and b is a number, NOTE this is a mixed type operation for
|
||||
// efficiency reasons.
|
||||
|
@ -307,35 +303,35 @@ extern void SetDecimalSeparator(wchar_t decimalSeparator);
|
|||
// Call whenever either radix or precision changes, is smarter about recalculating constants.
|
||||
extern void ChangeConstants(uint32_t radix, int32_t precision);
|
||||
|
||||
extern bool equnum(_In_ PNUMBER a, _In_ PNUMBER b ); // returns true of a == b
|
||||
extern bool lessnum(_In_ PNUMBER a, _In_ PNUMBER b ); // returns true of a < b
|
||||
extern bool zernum(_In_ PNUMBER a ); // returns true of a == 0
|
||||
extern bool equnum(_In_ NUMBER a, _In_ NUMBER b ); // returns true of a == b
|
||||
extern bool lessnum(_In_ NUMBER a, _In_ NUMBER b ); // returns true of a < b
|
||||
extern bool zernum(_In_ NUMBER a ); // returns true of a == 0
|
||||
extern bool zerrat(_In_ PRAT a ); // returns true if a == 0/q
|
||||
extern std::wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_t precision);
|
||||
extern std::wstring NumberToString(_Inout_ NUMBER& pnum, int format, uint32_t radix, int32_t precision);
|
||||
|
||||
// returns a text representation of a PRAT
|
||||
extern std::wstring RatToString(_Inout_ PRAT& prat, int format, uint32_t radix, int32_t precision);
|
||||
// converts a PRAT into a PNUMBER
|
||||
extern PNUMBER RatToNumber(_In_ PRAT prat, uint32_t radix, int32_t precision);
|
||||
// flattens a PRAT by converting it to a PNUMBER and back to a PRAT
|
||||
// converts a PRAT into a NUMBER
|
||||
extern NUMBER RatToNumber(_In_ PRAT prat, uint32_t radix, int32_t precision);
|
||||
// flattens a PRAT by converting it to a NUMBER and back to a PRAT
|
||||
extern void flatrat(_Inout_ PRAT& prat, uint32_t radix, int32_t precision);
|
||||
|
||||
extern int32_t numtoi32(_In_ PNUMBER pnum, uint32_t radix );
|
||||
extern int32_t numtoi32(_In_ NUMBER pnum, uint32_t radix );
|
||||
extern int32_t rattoi32(_In_ PRAT prat, uint32_t radix, int32_t precision);
|
||||
uint64_t rattoUi64(_In_ PRAT prat, uint32_t radix, int32_t precision);
|
||||
extern PNUMBER _createnum(_In_ uint32_t size ); // returns an empty number structure with size digits
|
||||
extern PNUMBER nRadixxtonum(_In_ PNUMBER a, uint32_t radix, int32_t precision);
|
||||
extern PNUMBER gcd(_In_ PNUMBER a, _In_ PNUMBER b );
|
||||
extern PNUMBER StringToNumber(std::wstring_view numberString, uint32_t radix, int32_t precision); // takes a text representation of a number and returns a number.
|
||||
extern NUMBER _createnum(_In_ uint32_t size ); // returns an empty number structure with size digits
|
||||
extern NUMBER nRadixxtonum(_In_ NUMBER a, uint32_t radix, int32_t precision);
|
||||
extern NUMBER gcd(_In_ NUMBER a, _In_ NUMBER b );
|
||||
extern NUMBER StringToNumber(std::wstring_view numberString, uint32_t radix, int32_t precision); // takes a text representation of a number and returns a number.
|
||||
|
||||
// takes a text representation of a number as a mantissa with sign and an exponent with sign.
|
||||
extern PRAT StringToRat(bool mantissaIsNegative, std::wstring_view mantissa, bool exponentIsNegative, std::wstring_view exponent, uint32_t radix, int32_t precision);
|
||||
|
||||
extern PNUMBER i32factnum(int32_t ini32, uint32_t radix);
|
||||
extern PNUMBER i32prodnum(int32_t start, int32_t stop, uint32_t radix);
|
||||
extern PNUMBER i32tonum(int32_t ini32, uint32_t radix);
|
||||
extern PNUMBER Ui32tonum(uint32_t ini32, uint32_t radix);
|
||||
extern PNUMBER numtonRadixx(PNUMBER a, uint32_t radix);
|
||||
extern NUMBER i32factnum(int32_t ini32, uint32_t radix);
|
||||
extern NUMBER i32prodnum(int32_t start, int32_t stop, uint32_t radix);
|
||||
extern NUMBER i32tonum(int32_t ini32, uint32_t radix);
|
||||
extern NUMBER Ui32tonum(uint32_t ini32, uint32_t radix);
|
||||
extern NUMBER numtonRadixx(NUMBER a, uint32_t radix);
|
||||
|
||||
// creates a empty/undefined rational representation (p/q)
|
||||
extern PRAT _createrat( void );
|
||||
|
@ -394,7 +390,7 @@ extern void lograt( _Inout_ PRAT *px, int32_t precision);
|
|||
|
||||
extern PRAT i32torat( int32_t ini32 );
|
||||
extern PRAT Ui32torat( uint32_t inui32 );
|
||||
extern PRAT numtorat( _In_ PNUMBER pin, uint32_t radix);
|
||||
extern PRAT numtorat( _In_ NUMBER pin, uint32_t radix);
|
||||
|
||||
extern void sinhrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
|
||||
extern void sinrat( _Inout_ PRAT *px );
|
||||
|
@ -410,32 +406,31 @@ extern void tanrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
|
|||
// angle type
|
||||
extern void tananglerat( _Inout_ PRAT *px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
||||
|
||||
extern void _dupnum(_In_ PNUMBER dest, _In_ const NUMBER * const src);
|
||||
extern void _dupnum(_In_ NUMBER dest, _In_ const NUMBER * const src);
|
||||
|
||||
extern void _destroynum( _In_ PNUMBER pnum );
|
||||
extern void _destroyrat( _In_ PRAT prat );
|
||||
extern void addnum( _Inout_ PNUMBER *pa, _In_ PNUMBER b, uint32_t radix);
|
||||
extern void addnum( _Inout_ NUMBER *pa, _In_ NUMBER b, uint32_t radix);
|
||||
extern void addrat( _Inout_ PRAT *pa, _In_ PRAT b, int32_t precision);
|
||||
extern void andrat( _Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
||||
extern void divnum( _Inout_ PNUMBER *pa, _In_ PNUMBER b, uint32_t radix, int32_t precision);
|
||||
extern void divnumx( _Inout_ PNUMBER *pa, _In_ PNUMBER b, int32_t precision);
|
||||
extern void divnum( _Inout_ NUMBER *pa, _In_ NUMBER b, uint32_t radix, int32_t precision);
|
||||
extern void divnumx( _Inout_ NUMBER *pa, _In_ NUMBER b, int32_t precision);
|
||||
extern void divrat( _Inout_ PRAT *pa, _In_ PRAT b, int32_t precision);
|
||||
extern void fracrat( _Inout_ PRAT *pa , uint32_t radix, int32_t precision);
|
||||
extern void factrat( _Inout_ PRAT *pa, uint32_t radix, int32_t precision);
|
||||
extern void modrat( _Inout_ PRAT *pa, _In_ PRAT b );
|
||||
extern void gcdrat( _Inout_ PRAT *pa, int32_t precision);
|
||||
extern void intrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
|
||||
extern void mulnum( _Inout_ PNUMBER *pa, _In_ PNUMBER b, uint32_t radix);
|
||||
extern void mulnumx( _Inout_ PNUMBER *pa, _In_ PNUMBER b );
|
||||
extern void mulnum( _Inout_ NUMBER *pa, _In_ NUMBER b, uint32_t radix);
|
||||
extern void mulnumx( _Inout_ NUMBER *pa, _In_ NUMBER b );
|
||||
extern void mulrat( _Inout_ PRAT *pa, _In_ PRAT b, int32_t precision);
|
||||
extern void numpowi32( _Inout_ PNUMBER *proot, int32_t power, uint32_t radix, int32_t precision);
|
||||
extern void numpowi32x( _Inout_ PNUMBER *proot, int32_t power );
|
||||
extern void numpowi32( _Inout_ NUMBER *proot, int32_t power, uint32_t radix, int32_t precision);
|
||||
extern void numpowi32x( _Inout_ NUMBER *proot, int32_t power );
|
||||
extern void orrat( _Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
||||
extern void powrat( _Inout_ PRAT *pa, _In_ PRAT b , uint32_t radix, int32_t precision);
|
||||
extern void powratNumeratorDenominator(_Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
||||
extern void powratcomp(_Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
||||
extern void ratpowi32( _Inout_ PRAT *proot, int32_t power, int32_t precision);
|
||||
extern void remnum( _Inout_ PNUMBER *pa, _In_ PNUMBER b, uint32_t radix);
|
||||
extern void remnum( _Inout_ NUMBER *pa, _In_ NUMBER b, uint32_t radix);
|
||||
extern void rootrat( _Inout_ PRAT *pa, _In_ PRAT b , uint32_t radix, int32_t precision);
|
||||
extern void scale2pi( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
|
||||
extern void scale( _Inout_ PRAT *px, _In_ PRAT scalefact, uint32_t radix, int32_t precision);
|
||||
|
@ -452,4 +447,4 @@ extern bool rat_le( _In_ PRAT a, _In_ PRAT b, int32_t precision);
|
|||
extern void inbetween( _In_ PRAT *px, _In_ PRAT range, int32_t precision);
|
||||
extern void trimit( _Inout_ PRAT *px, int32_t precision);
|
||||
extern void _dumprawrat(_In_ const wchar_t *varname, _In_ PRAT rat, std::wostream& out);
|
||||
extern void _dumprawnum(_In_ const wchar_t *varname, _In_ PNUMBER num, std::wostream& out);
|
||||
extern void _dumprawnum(_In_ const wchar_t *varname, _In_ NUMBER num, std::wostream& out);
|
||||
|
|
|
@ -62,11 +62,11 @@ bool g_ftrueinfinite = false; // Set to true if you don't want
|
|||
// chopping internally
|
||||
// precision used internally
|
||||
|
||||
PNUMBER num_one= nullptr;
|
||||
PNUMBER num_two= nullptr;
|
||||
PNUMBER num_five= nullptr;
|
||||
PNUMBER num_six= nullptr;
|
||||
PNUMBER num_ten= nullptr;
|
||||
NUMBER num_one;
|
||||
NUMBER num_two;
|
||||
NUMBER num_five;
|
||||
NUMBER num_six;
|
||||
NUMBER num_ten;
|
||||
|
||||
PRAT ln_ten= nullptr;
|
||||
PRAT ln_two= nullptr;
|
||||
|
@ -168,7 +168,7 @@ void ChangeConstants(uint32_t radix, int32_t precision)
|
|||
DUPRAT(rat_smallest, rat_nRadix);
|
||||
ratpowi32(&rat_smallest, -precision, precision);
|
||||
DUPRAT(rat_negsmallest, rat_smallest);
|
||||
rat_negsmallest->pp->sign = -1;
|
||||
rat_negsmallest->pp.sign = -1;
|
||||
DUMPRAWRAT(rat_smallest);
|
||||
DUMPRAWRAT(rat_negsmallest);
|
||||
|
||||
|
@ -204,11 +204,11 @@ void ChangeConstants(uint32_t radix, int32_t precision)
|
|||
subrat(&rat_max_i32, rat_one, precision); // rat_max_i32 = 2^31 -1
|
||||
DUMPRAWRAT(rat_max_i32);
|
||||
|
||||
rat_min_i32->pp->sign *= -1; // rat_min_i32 = -2^31
|
||||
rat_min_i32->pp.sign *= -1; // rat_min_i32 = -2^31
|
||||
DUMPRAWRAT(rat_min_i32);
|
||||
|
||||
DUPRAT(rat_min_exp, rat_max_exp);
|
||||
rat_min_exp->pp->sign *= -1;
|
||||
rat_min_exp->pp.sign *= -1;
|
||||
DUMPRAWRAT(rat_min_exp);
|
||||
|
||||
cbitsofprecision = g_ratio * radix * precision;
|
||||
|
@ -269,7 +269,7 @@ void ChangeConstants(uint32_t radix, int32_t precision)
|
|||
DUPRAT(rat_smallest, rat_nRadix);
|
||||
ratpowi32(&rat_smallest, -precision, precision);
|
||||
DUPRAT(rat_negsmallest, rat_smallest);
|
||||
rat_negsmallest->pp->sign = -1;
|
||||
rat_negsmallest->pp.sign = -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -322,7 +322,7 @@ bool rat_equ( PRAT a, PRAT b, int32_t precision)
|
|||
{
|
||||
PRAT rattmp= nullptr;
|
||||
DUPRAT(rattmp,a);
|
||||
rattmp->pp->sign *= -1;
|
||||
rattmp->pp.sign *= -1;
|
||||
addrat( &rattmp, b, precision);
|
||||
bool bret = zernum( rattmp->pp );
|
||||
destroyrat( rattmp );
|
||||
|
@ -345,11 +345,11 @@ bool rat_ge( PRAT a, PRAT b, int32_t precision)
|
|||
{
|
||||
PRAT rattmp= nullptr;
|
||||
DUPRAT(rattmp,a);
|
||||
b->pp->sign *= -1;
|
||||
b->pp.sign *= -1;
|
||||
addrat( &rattmp, b, precision);
|
||||
b->pp->sign *= -1;
|
||||
b->pp.sign *= -1;
|
||||
bool bret = ( zernum( rattmp->pp ) ||
|
||||
rattmp->pp->sign * rattmp->pq->sign == 1 );
|
||||
rattmp->pp.sign * rattmp->pq.sign == 1 );
|
||||
destroyrat( rattmp );
|
||||
return( bret );
|
||||
}
|
||||
|
@ -371,11 +371,11 @@ bool rat_gt( PRAT a, PRAT b, int32_t precision)
|
|||
{
|
||||
PRAT rattmp= nullptr;
|
||||
DUPRAT(rattmp,a);
|
||||
b->pp->sign *= -1;
|
||||
b->pp.sign *= -1;
|
||||
addrat( &rattmp, b, precision);
|
||||
b->pp->sign *= -1;
|
||||
b->pp.sign *= -1;
|
||||
bool bret = ( !zernum( rattmp->pp ) &&
|
||||
rattmp->pp->sign * rattmp->pq->sign == 1 );
|
||||
rattmp->pp.sign * rattmp->pq.sign == 1 );
|
||||
destroyrat( rattmp );
|
||||
return( bret );
|
||||
}
|
||||
|
@ -397,11 +397,11 @@ bool rat_le( PRAT a, PRAT b, int32_t precision)
|
|||
|
||||
PRAT rattmp= nullptr;
|
||||
DUPRAT(rattmp,a);
|
||||
b->pp->sign *= -1;
|
||||
b->pp.sign *= -1;
|
||||
addrat( &rattmp, b, precision);
|
||||
b->pp->sign *= -1;
|
||||
b->pp.sign *= -1;
|
||||
bool bret = ( zernum( rattmp->pp ) ||
|
||||
rattmp->pp->sign * rattmp->pq->sign == -1 );
|
||||
rattmp->pp.sign * rattmp->pq.sign == -1 );
|
||||
destroyrat( rattmp );
|
||||
return( bret );
|
||||
}
|
||||
|
@ -423,11 +423,11 @@ bool rat_lt( PRAT a, PRAT b, int32_t precision)
|
|||
{
|
||||
PRAT rattmp= nullptr;
|
||||
DUPRAT(rattmp,a);
|
||||
b->pp->sign *= -1;
|
||||
b->pp.sign *= -1;
|
||||
addrat( &rattmp, b, precision);
|
||||
b->pp->sign *= -1;
|
||||
b->pp.sign *= -1;
|
||||
bool bret = ( !zernum( rattmp->pp ) &&
|
||||
rattmp->pp->sign * rattmp->pq->sign == -1 );
|
||||
rattmp->pp.sign * rattmp->pq.sign == -1 );
|
||||
destroyrat( rattmp );
|
||||
return( bret );
|
||||
}
|
||||
|
@ -450,7 +450,7 @@ bool rat_neq( PRAT a, PRAT b, int32_t precision)
|
|||
{
|
||||
PRAT rattmp= nullptr;
|
||||
DUPRAT(rattmp,a);
|
||||
rattmp->pp->sign *= -1;
|
||||
rattmp->pp.sign *= -1;
|
||||
addrat( &rattmp, b, precision);
|
||||
bool bret = !( zernum( rattmp->pp ) );
|
||||
destroyrat( rattmp );
|
||||
|
@ -475,8 +475,8 @@ void scale( PRAT *px, PRAT scalefact, uint32_t radix, int32_t precision )
|
|||
|
||||
// Logscale is a quick way to tell how much extra precision is needed for
|
||||
// scaling by scalefact.
|
||||
int32_t logscale = g_ratio * ( (pret->pp->cdigit+pret->pp->exp) -
|
||||
(pret->pq->cdigit+pret->pq->exp) );
|
||||
int32_t logscale = g_ratio * ( (pret->pp.cdigit+pret->pp.exp) -
|
||||
(pret->pq.cdigit+pret->pq.exp) );
|
||||
if ( logscale > 0 )
|
||||
{
|
||||
precision += logscale;
|
||||
|
@ -485,7 +485,7 @@ void scale( PRAT *px, PRAT scalefact, uint32_t radix, int32_t precision )
|
|||
divrat( &pret, scalefact, precision);
|
||||
intrat(&pret, radix, precision);
|
||||
mulrat( &pret, scalefact, precision);
|
||||
pret->pp->sign *= -1;
|
||||
pret->pp.sign *= -1;
|
||||
addrat( px, pret, precision);
|
||||
|
||||
destroyrat( pret );
|
||||
|
@ -510,8 +510,8 @@ void scale2pi( PRAT *px, uint32_t radix, int32_t precision )
|
|||
|
||||
// Logscale is a quick way to tell how much extra precision is needed for
|
||||
// scaling by 2 pi.
|
||||
int32_t logscale = g_ratio * ( (pret->pp->cdigit+pret->pp->exp) -
|
||||
(pret->pq->cdigit+pret->pq->exp) );
|
||||
int32_t logscale = g_ratio * ( (pret->pp.cdigit+pret->pp.exp) -
|
||||
(pret->pq.cdigit+pret->pq.exp) );
|
||||
if ( logscale > 0 )
|
||||
{
|
||||
precision += logscale;
|
||||
|
@ -529,7 +529,7 @@ void scale2pi( PRAT *px, uint32_t radix, int32_t precision )
|
|||
divrat( &pret, my_two_pi, precision);
|
||||
intrat(&pret, radix, precision);
|
||||
mulrat( &pret, my_two_pi, precision);
|
||||
pret->pp->sign *= -1;
|
||||
pret->pp.sign *= -1;
|
||||
addrat( px, pret, precision);
|
||||
|
||||
destroyrat( my_two_pi );
|
||||
|
@ -555,12 +555,12 @@ void inbetween( PRAT *px, PRAT range, int32_t precision)
|
|||
}
|
||||
else
|
||||
{
|
||||
range->pp->sign *= -1;
|
||||
range->pp.sign *= -1;
|
||||
if ( rat_lt(*px, range, precision) )
|
||||
{
|
||||
DUPRAT(*px,range);
|
||||
}
|
||||
range->pp->sign *= -1;
|
||||
range->pp.sign *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -586,27 +586,27 @@ void _dumprawrat( const wchar_t *varname, PRAT rat, wostream& out)
|
|||
//
|
||||
// FUNCTION: _dumprawnum
|
||||
//
|
||||
// ARGUMENTS: const wchar *name of variable, PNUMBER num, output stream out
|
||||
// ARGUMENTS: const wchar *name of variable, NUMBER num, output stream out
|
||||
//
|
||||
// RETURN: none, prints the results of a dump of the internal structures
|
||||
// of a PNUMBER, suitable for READRAWNUM to stderr.
|
||||
// of a NUMBER, suitable for READRAWNUM to stderr.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void _dumprawnum(const wchar_t *varname, PNUMBER num, wostream& out)
|
||||
void _dumprawnum(const wchar_t *varname, NUMBER num, wostream& out)
|
||||
|
||||
{
|
||||
int i;
|
||||
|
||||
out << L"NUMBER " << varname << L" = {\n";
|
||||
out << L"\t"<< num->sign << L",\n";
|
||||
out << L"\t" << num->cdigit << L",\n";
|
||||
out << L"\t" << num->exp << L",\n";
|
||||
out << L"\t"<< num.sign << L",\n";
|
||||
out << L"\t" << num.cdigit << L",\n";
|
||||
out << L"\t" << num.exp << L",\n";
|
||||
out << L"\t{ ";
|
||||
|
||||
for ( i = 0; i < num->cdigit; i++ )
|
||||
for ( i = 0; i < num.cdigit; i++ )
|
||||
{
|
||||
out << L" "<< num->mant[i] << L",";
|
||||
out << L" "<< num.mant[i] << L",";
|
||||
}
|
||||
out << L"}\n";
|
||||
out << L"};\n";
|
||||
|
@ -682,37 +682,37 @@ void trimit( PRAT *px, int32_t precision)
|
|||
if ( !g_ftrueinfinite )
|
||||
{
|
||||
int32_t trim;
|
||||
PNUMBER pp=(*px)->pp;
|
||||
PNUMBER pq=(*px)->pq;
|
||||
trim = g_ratio * (min((pp->cdigit+pp->exp),(pq->cdigit+pq->exp))-1) - precision;
|
||||
NUMBER pp=(*px)->pp;
|
||||
NUMBER pq=(*px)->pq;
|
||||
trim = g_ratio * (min((pp.cdigit+pp.exp),(pq.cdigit+pq.exp))-1) - precision;
|
||||
if ( trim > g_ratio )
|
||||
{
|
||||
trim /= g_ratio;
|
||||
|
||||
if ( trim <= pp->exp )
|
||||
if ( trim <= pp.exp )
|
||||
{
|
||||
pp->exp -= trim;
|
||||
pp.exp -= trim;
|
||||
}
|
||||
else
|
||||
{
|
||||
copy(pp->mant.begin() + (trim-pp->exp), pp->mant.begin() + pp->cdigit, pp->mant.begin());
|
||||
pp->cdigit -= trim-pp->exp;
|
||||
pp->exp = 0;
|
||||
copy(pp.mant.begin() + (trim-pp.exp), pp.mant.begin() + pp.cdigit, pp.mant.begin());
|
||||
pp.cdigit -= trim-pp.exp;
|
||||
pp.exp = 0;
|
||||
}
|
||||
|
||||
if ( trim <= pq->exp )
|
||||
if ( trim <= pq.exp )
|
||||
{
|
||||
pq->exp -= trim;
|
||||
pq.exp -= trim;
|
||||
}
|
||||
else
|
||||
{
|
||||
copy(pq->mant.begin() + (trim-pq->exp), pq->mant.begin() + pq->cdigit, pq->mant.begin());
|
||||
pq->cdigit -= trim-pq->exp;
|
||||
pq->exp = 0;
|
||||
copy(pq.mant.begin() + (trim-pq.exp), pq.mant.begin() + pq.cdigit, pq.mant.begin());
|
||||
pq.cdigit -= trim-pq.exp;
|
||||
pq.exp = 0;
|
||||
}
|
||||
}
|
||||
trim = min(pp->exp,pq->exp);
|
||||
pp->exp -= trim;
|
||||
pq->exp -= trim;
|
||||
trim = min(pp.exp,pq.exp);
|
||||
pp.exp -= trim;
|
||||
pq.exp -= trim;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ void _sinrat( PRAT *px, int32_t precision)
|
|||
DUPRAT(thisterm,*px);
|
||||
|
||||
DUPNUM(n2,num_one);
|
||||
xx->pp->sign *= -1;
|
||||
xx->pp.sign *= -1;
|
||||
|
||||
do {
|
||||
NEXTTERM(xx,INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
|
@ -165,8 +165,6 @@ void _cosrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
{
|
||||
CREATETAYLOR();
|
||||
|
||||
destroynum(pret->pp);
|
||||
destroynum(pret->pq);
|
||||
|
||||
pret->pp=i32tonum( 1L, radix);
|
||||
pret->pq=i32tonum( 1L, radix);
|
||||
|
@ -174,7 +172,7 @@ void _cosrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
DUPRAT(thisterm,pret)
|
||||
|
||||
n2=i32tonum(0L, radix);
|
||||
xx->pp->sign *= -1;
|
||||
xx->pp.sign *= -1;
|
||||
|
||||
do {
|
||||
NEXTTERM(xx,INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
|
|
|
@ -101,7 +101,7 @@ void sinhrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
{
|
||||
DUPRAT(tmpx,*px);
|
||||
exprat(px, radix, precision);
|
||||
tmpx->pp->sign *= -1;
|
||||
tmpx->pp.sign *= -1;
|
||||
exprat(&tmpx, radix, precision);
|
||||
subrat( px, tmpx, precision);
|
||||
divrat( px, rat_two, precision);
|
||||
|
@ -178,13 +178,13 @@ void coshrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
{
|
||||
PRAT tmpx= nullptr;
|
||||
|
||||
(*px)->pp->sign = 1;
|
||||
(*px)->pq->sign = 1;
|
||||
(*px)->pp.sign = 1;
|
||||
(*px)->pq.sign = 1;
|
||||
if ( rat_ge( *px, rat_one, precision) )
|
||||
{
|
||||
DUPRAT(tmpx,*px);
|
||||
exprat(px, radix, precision);
|
||||
tmpx->pp->sign *= -1;
|
||||
tmpx->pp.sign *= -1;
|
||||
exprat(&tmpx, radix, precision);
|
||||
addrat( px, tmpx, precision);
|
||||
divrat( px, rat_two, precision);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue