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