Fix the project code style, as it is not consistent. (#236)

Fixes #202
This PR fixes code style for the project files.

The Problem
Different files in the project use different code style. That is not consistent and leads to harder maintenance of the project.

Description of the changes:
Have investigated and determined the most used code style across the given codebase
Have configured IDE and applied code style to all project files.
Have crafted clang-formatter config.
see https://clang.llvm.org/docs/ClangFormat.html
https://clang.llvm.org/docs/ClangFormatStyleOptions.html
Some cases were fixed manually
How changes were validated:
manual/ad-hoc testing, automated testing

All tests pass as before because these are only code style changes.
Additional
Please review, and let me know if I have any mistake in the code style. In case of any mistake, I will change the configuration and re-apply it to the project.
This commit is contained in:
Oleg Abrazhaev
2019-05-02 20:59:19 +02:00
committed by Daniel Belcher
parent c77f1de84c
commit 2826d37056
237 changed files with 12824 additions and 11843 deletions

View File

@@ -41,46 +41,45 @@ typedef int32_t ResultCode;
// CALC_E_DIVIDEBYZERO
//
// The current operation would require a divide by zero to complete
#define CALC_E_DIVIDEBYZERO ((uint32_t)0x80000000)
#define CALC_E_DIVIDEBYZERO ((uint32_t)0x80000000)
// CALC_E_DOMAIN
//
// The given input is not within the domain of this function
#define CALC_E_DOMAIN ((uint32_t)0x80000001)
#define CALC_E_DOMAIN ((uint32_t)0x80000001)
// CALC_E_INDEFINITE
//
// The result of this function is undefined
#define CALC_E_INDEFINITE ((uint32_t)0x80000002)
#define CALC_E_INDEFINITE ((uint32_t)0x80000002)
// CALC_E_POSINFINITY
//
// The result of this function is Positive Infinity.
#define CALC_E_POSINFINITY ((uint32_t)0x80000003)
#define CALC_E_POSINFINITY ((uint32_t)0x80000003)
// CALC_E_NEGINFINITY
//
// The result of this function is Negative Infinity
#define CALC_E_NEGINFINITY ((uint32_t)0x80000004)
#define CALC_E_NEGINFINITY ((uint32_t)0x80000004)
// CALC_E_INVALIDRANGE
//
// The given input is within the domain of the function but is beyond
// the range for which calc can successfully compute the answer
#define CALC_E_INVALIDRANGE ((uint32_t)0x80000006)
#define CALC_E_INVALIDRANGE ((uint32_t)0x80000006)
// CALC_E_OUTOFMEMORY
//
// There is not enough free memory to complete the requested function
#define CALC_E_OUTOFMEMORY ((uint32_t)0x80000007)
#define CALC_E_OUTOFMEMORY ((uint32_t)0x80000007)
// CALC_E_OVERFLOW
//
// The result of this operation is an overflow
#define CALC_E_OVERFLOW ((uint32_t)0x80000008)
#define CALC_E_OVERFLOW ((uint32_t)0x80000008)
// CALC_E_NORESULT
//
// The result of this operation is undefined
#define CALC_E_NORESULT ((uint32_t)0x80000009)
#define CALC_E_NORESULT ((uint32_t)0x80000009)

View File

@@ -17,7 +17,7 @@
#include "ratpak.h"
#include <cstring> // for memmove
void _mulnumx( PNUMBER *pa, PNUMBER b );
void _mulnumx(PNUMBER* pa, PNUMBER b);
//----------------------------------------------------------------------------
//
@@ -34,30 +34,30 @@ void _mulnumx( PNUMBER *pa, PNUMBER b );
//
//----------------------------------------------------------------------------
void __inline mulnumx( PNUMBER *pa, PNUMBER b )
void __inline mulnumx(PNUMBER* pa, PNUMBER b)
{
if ( b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0 )
{
if (b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0)
{
// If b is not one we multiply
if ( (*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0 )
{
if ((*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0)
{
// pa and b are both non-one.
_mulnumx( pa, b );
}
_mulnumx(pa, b);
}
else
{
{
// if pa is one and b isn't just copy b. and adjust the sign.
int32_t sign = (*pa)->sign;
DUPNUM(*pa,b);
DUPNUM(*pa, b);
(*pa)->sign *= sign;
}
}
}
else
{
{
// B is +/- 1, But we do have to set the sign.
(*pa)->sign *= b->sign;
}
}
}
//----------------------------------------------------------------------------
@@ -76,29 +76,29 @@ void __inline mulnumx( PNUMBER *pa, PNUMBER b )
//
//----------------------------------------------------------------------------
void _mulnumx( PNUMBER *pa, PNUMBER b )
void _mulnumx(PNUMBER* pa, PNUMBER b)
{
PNUMBER c= nullptr; // c will contain the result.
PNUMBER a= nullptr; // a is the dereferenced number pointer from *pa
MANTTYPE *ptra; // ptra is a pointer to the mantissa of a.
MANTTYPE *ptrb; // ptrb is a pointer to the mantissa of b.
MANTTYPE *ptrc; // ptrc is a pointer to the mantissa of c.
MANTTYPE *ptrcoffset; // ptrcoffset, is the anchor location of the next
// single digit multiply partial result.
int32_t iadigit=0; // Index of digit being used in the first number.
int32_t ibdigit=0; // Index of digit being used in the second number.
MANTTYPE da=0; // da is the digit from the fist number.
TWO_MANTTYPE cy=0; // cy is the carry resulting from the addition of
// a multiplied row into the result.
TWO_MANTTYPE mcy=0; // mcy is the resultant from a single
// multiply, AND the carry of that multiply.
int32_t icdigit=0; // Index of digit being calculated in final result.
PNUMBER c = nullptr; // c will contain the result.
PNUMBER a = nullptr; // a is the dereferenced number pointer from *pa
MANTTYPE* ptra; // ptra is a pointer to the mantissa of a.
MANTTYPE* ptrb; // ptrb is a pointer to the mantissa of b.
MANTTYPE* ptrc; // ptrc is a pointer to the mantissa of c.
MANTTYPE* ptrcoffset; // ptrcoffset, is the anchor location of the next
// single digit multiply partial result.
int32_t iadigit = 0; // Index of digit being used in the first number.
int32_t ibdigit = 0; // Index of digit being used in the second number.
MANTTYPE da = 0; // da is the digit from the fist number.
TWO_MANTTYPE cy = 0; // cy is the carry resulting from the addition of
// a multiplied row into the result.
TWO_MANTTYPE mcy = 0; // mcy is the resultant from a single
// multiply, AND the carry of that multiply.
int32_t icdigit = 0; // Index of digit being calculated in final result.
a=*pa;
a = *pa;
ibdigit = a->cdigit + b->cdigit - 1;
createnum( c, ibdigit + 1 );
createnum(c, ibdigit + 1);
c->cdigit = ibdigit;
c->sign = a->sign * b->sign;
@@ -106,36 +106,35 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
ptra = a->mant;
ptrcoffset = c->mant;
for ( iadigit = a->cdigit; iadigit > 0; iadigit-- )
for (iadigit = a->cdigit; iadigit > 0; iadigit--)
{
da = *ptra++;
da = *ptra++;
ptrb = b->mant;
// Shift ptrc, and ptrcoffset, one for each digit
ptrc = ptrcoffset++;
for ( ibdigit = b->cdigit; ibdigit > 0; ibdigit-- )
for (ibdigit = b->cdigit; ibdigit > 0; ibdigit--)
{
cy = 0;
mcy = (uint64_t)da * (*ptrb);
if ( mcy )
if (mcy)
{
icdigit = 0;
if ( ibdigit == 1 && iadigit == 1 )
if (ibdigit == 1 && iadigit == 1)
{
c->cdigit++;
}
}
// If result is nonzero, or while result of carry is nonzero...
while ( mcy || cy )
while (mcy || cy)
{
// update carry from addition(s) and multiply.
cy += (TWO_MANTTYPE)ptrc[icdigit]+((uint32_t)mcy&((uint32_t)~BASEX));
cy += (TWO_MANTTYPE)ptrc[icdigit] + ((uint32_t)mcy & ((uint32_t)~BASEX));
// update result digit from
ptrc[icdigit++]=(MANTTYPE)((uint32_t)cy&((uint32_t)~BASEX));
ptrc[icdigit++] = (MANTTYPE)((uint32_t)cy & ((uint32_t)~BASEX));
// update carries from
mcy >>= BASEXPWR;
@@ -144,19 +143,18 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
ptrb++;
ptrc++;
}
}
// prevent different kinds of zeros, by stripping leading duplicate zeros.
// digits are in order of increasing significance.
while ( c->cdigit > 1 && c->mant[c->cdigit-1] == 0 )
{
while (c->cdigit > 1 && c->mant[c->cdigit - 1] == 0)
{
c->cdigit--;
}
}
destroynum( *pa );
*pa=c;
destroynum(*pa);
*pa = c;
}
//-----------------------------------------------------------------------------
//
@@ -174,34 +172,33 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
//
//-----------------------------------------------------------------------------
void numpowi32x( _Inout_ PNUMBER *proot, _In_ int32_t power )
void numpowi32x(_Inout_ PNUMBER* proot, _In_ int32_t power)
{
PNUMBER lret = i32tonum( 1, BASEX );
PNUMBER lret = i32tonum(1, BASEX);
// Once the power remaining is zero we are done.
while ( power > 0 )
{
while (power > 0)
{
// If this bit in the power decomposition is on, multiply the result
// by the root number.
if ( power & 1 )
{
mulnumx( &lret, *proot );
}
if (power & 1)
{
mulnumx(&lret, *proot);
}
// multiply the root number by itself to scale for the next bit (i.e.
// square it.
mulnumx( proot, *proot );
mulnumx(proot, *proot);
// move the next bit of the power into place.
power >>= 1;
}
destroynum( *proot );
*proot=lret;
}
destroynum(*proot);
*proot = lret;
}
void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision);
void _divnumx(PNUMBER* pa, PNUMBER b, int32_t precision);
//----------------------------------------------------------------------------
//
@@ -218,30 +215,30 @@ void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision);
//
//----------------------------------------------------------------------------
void __inline divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
void __inline divnumx(PNUMBER* pa, PNUMBER b, int32_t precision)
{
if ( b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0 )
{
if (b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0)
{
// b is not one.
if ( (*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0 )
{
if ((*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0)
{
// pa and b are both not one.
_divnumx( pa, b, precision);
}
_divnumx(pa, b, precision);
}
else
{
{
// if pa is one and b is not one, just copy b, and adjust the sign.
int32_t sign = (*pa)->sign;
DUPNUM(*pa,b);
DUPNUM(*pa, b);
(*pa)->sign *= sign;
}
}
}
else
{
{
// b is one so don't divide, but set the sign.
(*pa)->sign *= b->sign;
}
}
}
//----------------------------------------------------------------------------
@@ -257,111 +254,109 @@ void __inline divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
//
//----------------------------------------------------------------------------
void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
void _divnumx(PNUMBER* pa, PNUMBER b, int32_t precision)
{
PNUMBER a= nullptr; // a is the dereferenced number pointer from *pa
PNUMBER c= nullptr; // c will contain the result.
PNUMBER a = nullptr; // a is the dereferenced number pointer from *pa
PNUMBER c = nullptr; // c will contain the result.
PNUMBER lasttmp = nullptr; // lasttmp allows a backup when the algorithm
// guesses one bit too far.
// guesses one bit too far.
PNUMBER tmp = nullptr; // current guess being worked on for divide.
PNUMBER rem = nullptr; // remainder after applying guess.
int32_t cdigits; // count of digits for answer.
MANTTYPE *ptrc; // ptrc is a pointer to the mantissa of c.
MANTTYPE* ptrc; // ptrc is a pointer to the mantissa of c.
int32_t thismax = precision + g_ratio; // set a maximum number of internal digits
// to shoot for in the divide.
// to shoot for in the divide.
a=*pa;
if ( thismax < a->cdigit )
{
a = *pa;
if (thismax < a->cdigit)
{
// a has more digits than precision specified, bump up digits to shoot
// for.
thismax = a->cdigit;
}
}
if ( thismax < b->cdigit )
{
if (thismax < b->cdigit)
{
// b has more digits than precision specified, bump up digits to shoot
// for.
thismax = b->cdigit;
}
}
// Create c (the divide answer) and set up exponent and sign.
createnum( c, thismax + 1 );
c->exp = (a->cdigit+a->exp) - (b->cdigit+b->exp) + 1;
createnum(c, thismax + 1);
c->exp = (a->cdigit + a->exp) - (b->cdigit + b->exp) + 1;
c->sign = a->sign * b->sign;
ptrc = c->mant + thismax;
cdigits = 0;
DUPNUM( rem, a );
DUPNUM(rem, a);
rem->sign = b->sign;
rem->exp = b->cdigit + b->exp - rem->cdigit;
while ( cdigits++ < thismax && !zernum(rem) )
{
while (cdigits++ < thismax && !zernum(rem))
{
int32_t digit = 0;
*ptrc = 0;
while ( !lessnum( rem, b ) )
{
while (!lessnum(rem, b))
{
digit = 1;
DUPNUM( tmp, b );
destroynum( lasttmp );
lasttmp=i32tonum( 0, BASEX );
while ( lessnum( tmp, rem ) )
{
destroynum( lasttmp );
DUPNUM(lasttmp,tmp);
addnum( &tmp, tmp, BASEX );
DUPNUM(tmp, b);
destroynum(lasttmp);
lasttmp = i32tonum(0, BASEX);
while (lessnum(tmp, rem))
{
destroynum(lasttmp);
DUPNUM(lasttmp, tmp);
addnum(&tmp, tmp, BASEX);
digit *= 2;
}
if ( lessnum( rem, tmp ) )
{
}
if (lessnum(rem, tmp))
{
// too far, back up...
destroynum( tmp );
destroynum(tmp);
digit /= 2;
tmp=lasttmp;
lasttmp= nullptr;
}
tmp = lasttmp;
lasttmp = nullptr;
}
tmp->sign *= -1;
addnum( &rem, tmp, BASEX );
destroynum( tmp );
destroynum( lasttmp );
addnum(&rem, tmp, BASEX);
destroynum(tmp);
destroynum(lasttmp);
*ptrc |= digit;
}
}
rem->exp++;
ptrc--;
}
}
cdigits--;
if ( c->mant != ++ptrc )
{
memmove( c->mant, ptrc, (int)(cdigits*sizeof(MANTTYPE)) );
}
if (c->mant != ++ptrc)
{
memmove(c->mant, ptrc, (int)(cdigits * sizeof(MANTTYPE)));
}
if ( !cdigits )
{
if (!cdigits)
{
// A zero, make sure no weird exponents creep in
c->exp = 0;
c->cdigit = 1;
}
}
else
{
{
c->cdigit = cdigits;
c->exp -= cdigits;
// prevent different kinds of zeros, by stripping leading duplicate
// zeros. digits are in order of increasing significance.
while ( c->cdigit > 1 && c->mant[c->cdigit-1] == 0 )
{
while (c->cdigit > 1 && c->mant[c->cdigit - 1] == 0)
{
c->cdigit--;
}
}
}
destroynum( rem );
destroynum(rem);
destroynum( *pa );
*pa=c;
destroynum(*pa);
*pa = c;
}

File diff suppressed because it is too large Load Diff

View File

@@ -16,7 +16,6 @@
//-----------------------------------------------------------------------------
#include "ratpak.h"
//-----------------------------------------------------------------------------
//
// FUNCTION: exprat
@@ -40,63 +39,63 @@
//
//-----------------------------------------------------------------------------
void _exprat( PRAT *px, int32_t precision)
void _exprat(PRAT* px, int32_t precision)
{
CREATETAYLOR();
addnum(&(pret->pp),num_one, BASEX);
addnum(&(pret->pq),num_one, BASEX);
DUPRAT(thisterm,pret);
addnum(&(pret->pp), num_one, BASEX);
addnum(&(pret->pq), num_one, BASEX);
DUPRAT(thisterm, pret);
n2=i32tonum(0L, BASEX);
n2 = i32tonum(0L, BASEX);
do {
do
{
NEXTTERM(*px, INC(n2) DIVNUM(n2), precision);
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR();
}
void exprat( PRAT *px, uint32_t radix, int32_t precision)
void exprat(PRAT* px, uint32_t radix, int32_t precision)
{
PRAT pwr= nullptr;
PRAT pint= nullptr;
PRAT pwr = nullptr;
PRAT pint = nullptr;
int32_t intpwr;
if ( rat_gt( *px, rat_max_exp, precision) || rat_lt( *px, rat_min_exp, precision) )
{
if (rat_gt(*px, rat_max_exp, precision) || rat_lt(*px, rat_min_exp, precision))
{
// Don't attempt exp of anything large.
throw( CALC_E_DOMAIN );
}
throw(CALC_E_DOMAIN);
}
DUPRAT(pwr,rat_exp);
DUPRAT(pint,*px);
DUPRAT(pwr, rat_exp);
DUPRAT(pint, *px);
intrat(&pint, radix, precision);
intpwr = rattoi32(pint, radix, precision);
ratpowi32( &pwr, intpwr, precision);
ratpowi32(&pwr, intpwr, precision);
subrat(px, pint, precision);
// It just so happens to be an integral power of e.
if ( rat_gt( *px, rat_negsmallest, precision) && rat_lt( *px, rat_smallest, precision) )
{
DUPRAT(*px,pwr);
}
if (rat_gt(*px, rat_negsmallest, precision) && rat_lt(*px, rat_smallest, precision))
{
DUPRAT(*px, pwr);
}
else
{
{
_exprat(px, precision);
mulrat(px, pwr, precision);
}
}
destroyrat( pwr );
destroyrat( pint );
destroyrat(pwr);
destroyrat(pint);
}
//-----------------------------------------------------------------------------
//
// FUNCTION: lograt, _lograt
@@ -124,7 +123,7 @@ void exprat( PRAT *px, uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
void _lograt( PRAT *px, int32_t precision)
void _lograt(PRAT* px, int32_t precision)
{
CREATETAYLOR();
@@ -133,76 +132,75 @@ void _lograt( PRAT *px, int32_t precision)
// sub one from x
(*px)->pq->sign *= -1;
addnum(&((*px)->pp),(*px)->pq, BASEX);
addnum(&((*px)->pp), (*px)->pq, BASEX);
(*px)->pq->sign *= -1;
DUPRAT(pret,*px);
DUPRAT(thisterm,*px);
DUPRAT(pret, *px);
DUPRAT(thisterm, *px);
n2=i32tonum(1L, BASEX);
n2 = i32tonum(1L, BASEX);
(*px)->pp->sign *= -1;
do {
do
{
NEXTTERM(*px, MULNUM(n2) INC(n2) DIVNUM(n2), precision);
TRIMTOP(*px, precision);
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR();
}
void lograt( PRAT *px, int32_t precision)
void lograt(PRAT* px, int32_t precision)
{
bool fneglog;
PRAT pwr = nullptr; // pwr is the large scaling factor.
PRAT offset = nullptr; // offset is the incremental scaling factor.
PRAT pwr = nullptr; // pwr is the large scaling factor.
PRAT offset = nullptr; // offset is the incremental scaling factor.
// Check for someone taking the log of zero or a negative number.
if ( rat_le( *px, rat_zero, precision) )
{
throw( CALC_E_DOMAIN );
}
if (rat_le(*px, rat_zero, precision))
{
throw(CALC_E_DOMAIN);
}
// Get number > 1, for scaling
fneglog = rat_lt( *px, rat_one, precision);
if ( fneglog )
{
fneglog = rat_lt(*px, rat_one, precision);
if (fneglog)
{
// WARNING: This is equivalent to doing *px = 1 / *px
PNUMBER pnumtemp= nullptr;
PNUMBER pnumtemp = nullptr;
pnumtemp = (*px)->pp;
(*px)->pp = (*px)->pq;
(*px)->pq = pnumtemp;
}
}
// Scale the number within BASEX factor of 1, for the large scale.
// log(x*2^(BASEXPWR*k)) = BASEXPWR*k*log(2)+log(x)
if ( LOGRAT2(*px) > 1 )
{
if (LOGRAT2(*px) > 1)
{
// Take advantage of px's base BASEX to scale quickly down to
// a reasonable range.
int32_t intpwr;
intpwr=LOGRAT2(*px)-1;
intpwr = LOGRAT2(*px) - 1;
(*px)->pq->exp += intpwr;
pwr=i32torat(intpwr*BASEXPWR);
pwr = i32torat(intpwr * BASEXPWR);
mulrat(&pwr, ln_two, precision);
// ln(x+e)-ln(x) looks close to e when x is close to one using some
// expansions. This means we can trim past precision digits+1.
TRIMTOP(*px, precision);
}
}
else
{
DUPRAT(pwr,rat_zero);
}
{
DUPRAT(pwr, rat_zero);
}
DUPRAT(offset,rat_zero);
DUPRAT(offset, rat_zero);
// Scale the number between 1 and e_to_one_half, for the small scale.
while ( rat_gt( *px, e_to_one_half, precision) )
{
divrat( px, e_to_one_half, precision);
addrat( &offset, rat_one, precision);
}
while (rat_gt(*px, e_to_one_half, precision))
{
divrat(px, e_to_one_half, precision);
addrat(&offset, rat_one, precision);
}
_lograt(px, precision);
@@ -217,16 +215,16 @@ void lograt( PRAT *px, int32_t precision)
trimit(px, precision);
// If number started out < 1 rescale answer to negative.
if ( fneglog )
{
if (fneglog)
{
(*px)->pp->sign *= -1;
}
}
destroyrat(offset);
destroyrat(pwr);
}
void log10rat( PRAT *px, int32_t precision)
void log10rat(PRAT* px, int32_t precision)
{
lograt(px, precision);
@@ -246,7 +244,7 @@ bool IsEven(PRAT x, uint32_t radix, int32_t precision)
fracrat(&tmp, radix, precision);
addrat(&tmp, tmp, precision);
subrat(&tmp, rat_one, precision);
if ( rat_lt( tmp, rat_zero, precision))
if (rat_lt(tmp, rat_zero, precision))
{
bRet = true;
}
@@ -269,7 +267,7 @@ bool IsEven(PRAT x, uint32_t radix, int32_t precision)
//
//
//---------------------------------------------------------------------------
void powrat(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
void powrat(PRAT* px, PRAT y, uint32_t radix, int32_t precision)
{
// Handle cases where px or y is 0 by calling powratcomp directly
if (zerrat(*px) || zerrat(y))
@@ -296,12 +294,12 @@ void powrat(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
}
}
void powratNumeratorDenominator(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
void powratNumeratorDenominator(PRAT* px, PRAT y, uint32_t radix, int32_t precision)
{
// Prepare rationals
PRAT yNumerator = nullptr;
PRAT yDenominator = nullptr;
DUPRAT(yNumerator, rat_zero); // yNumerator->pq is 1 one
DUPRAT(yNumerator, rat_zero); // yNumerator->pq is 1 one
DUPRAT(yDenominator, rat_zero); // yDenominator->pq is 1 one
DUPNUM(yNumerator->pp, y->pp);
DUPNUM(yDenominator->pp, y->pq);
@@ -405,7 +403,7 @@ 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 = SIGN(*px);
@@ -413,76 +411,74 @@ void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
(*px)->pp->sign = 1;
(*px)->pq->sign = 1;
if ( zerrat( *px ) )
{
if (zerrat(*px))
{
// *px is zero.
if ( rat_lt( y, rat_zero, precision) )
{
throw( CALC_E_DOMAIN );
}
else if ( zerrat( y ) )
{
// *px and y are both zero, special case a 1 return.
DUPRAT(*px,rat_one);
// Ensure sign is positive.
sign = 1;
}
}
else
if (rat_lt(y, rat_zero, precision))
{
PRAT pxint= nullptr;
DUPRAT(pxint,*px);
subrat(&pxint, rat_one, precision);
if ( rat_gt( pxint, rat_negsmallest, precision) &&
rat_lt( pxint, rat_smallest, precision) && ( sign == 1 ) )
{
// *px is one, special case a 1 return.
DUPRAT(*px,rat_one);
throw(CALC_E_DOMAIN);
}
else if (zerrat(y))
{
// *px and y are both zero, special case a 1 return.
DUPRAT(*px, rat_one);
// Ensure sign is positive.
sign = 1;
}
}
}
else
{
PRAT pxint = nullptr;
DUPRAT(pxint, *px);
subrat(&pxint, rat_one, precision);
if (rat_gt(pxint, rat_negsmallest, precision) && rat_lt(pxint, rat_smallest, precision) && (sign == 1))
{
// *px is one, special case a 1 return.
DUPRAT(*px, rat_one);
// Ensure sign is positive.
sign = 1;
}
else
{
{
// Only do the exp if the number isn't zero or one
PRAT podd = nullptr;
DUPRAT(podd,y);
DUPRAT(podd, y);
fracrat(&podd, radix, precision);
if ( rat_gt( podd, rat_negsmallest, precision) && rat_lt( podd, rat_smallest, precision) )
{
if (rat_gt(podd, rat_negsmallest, precision) && rat_lt(podd, rat_smallest, precision))
{
// If power is an integer let ratpowi32 deal with it.
PRAT iy = nullptr;
int32_t inty;
DUPRAT(iy,y);
DUPRAT(iy, y);
subrat(&iy, podd, precision);
inty = rattoi32(iy, radix, precision);
PRAT plnx = nullptr;
DUPRAT(plnx,*px);
DUPRAT(plnx, *px);
lograt(&plnx, precision);
mulrat(&plnx, iy, precision);
if ( rat_gt( plnx, rat_max_exp, precision) || rat_lt( plnx, rat_min_exp, precision) )
{
if (rat_gt(plnx, rat_max_exp, precision) || rat_lt(plnx, rat_min_exp, precision))
{
// Don't attempt exp of anything large or small.A
destroyrat(plnx);
destroyrat(iy);
destroyrat(pxint);
destroyrat(podd);
throw( CALC_E_DOMAIN );
}
throw(CALC_E_DOMAIN);
}
destroyrat(plnx);
ratpowi32(px, inty, precision);
if ( ( inty & 1 ) == 0 )
{
sign=1;
}
destroyrat(iy);
}
else
if ((inty & 1) == 0)
{
sign = 1;
}
destroyrat(iy);
}
else
{
// power is a fraction
if ( sign == -1 )
{
if (sign == -1)
{
// Need to throw an error if the exponent has an even denominator.
// As a first step, the numerator and denominator must be divided by 2 as many times as
// possible, so that 2/6 is allowed.
@@ -492,7 +488,7 @@ void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
bool fBadExponent = false;
// Get the numbers in arbitrary precision rational number format
DUPRAT(pNumerator, rat_zero); // pNumerator->pq is 1 one
DUPRAT(pNumerator, rat_zero); // pNumerator->pq is 1 one
DUPRAT(pDenominator, rat_zero); // pDenominator->pq is 1 one
DUPNUM(pNumerator->pp, y->pp);
@@ -501,39 +497,39 @@ void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
pDenominator->pp->sign = 1;
while (IsEven(pNumerator, radix, precision) && IsEven(pDenominator, radix, precision)) // both Numerator & denominator is even
{
{
divrat(&pNumerator, rat_two, precision);
divrat(&pDenominator, rat_two, precision);
}
}
if (IsEven(pDenominator, radix, precision)) // denominator is still even
{
fBadExponent = true;
}
{
fBadExponent = true;
}
if (IsEven(pNumerator, radix, precision)) // numerator is still even
{
{
sign = 1;
}
}
destroyrat(pNumerator);
destroyrat(pDenominator);
if (fBadExponent)
{
throw( CALC_E_DOMAIN );
}
}
else
{
throw(CALC_E_DOMAIN);
}
}
else
{
// If the exponent is not odd disregard the sign.
sign = 1;
}
}
lograt(px, precision);
mulrat(px, y, precision);
exprat(px, radix, precision);
}
destroyrat(podd);
}
destroyrat(pxint);
}
destroyrat(podd);
}
destroyrat(pxint);
}
(*px)->pp->sign *= sign;
}

View File

@@ -15,8 +15,7 @@
//-----------------------------------------------------------------------------
#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)
//-----------------------------------------------------------------------------
@@ -55,37 +54,36 @@
//
//-----------------------------------------------------------------------------
void _gamma( PRAT *pn, uint32_t radix, int32_t precision)
void _gamma(PRAT* pn, uint32_t radix, int32_t precision)
{
PRAT factorial= nullptr;
PNUMBER count= nullptr;
PRAT tmp= nullptr;
PRAT one_pt_five= nullptr;
PRAT a= nullptr;
PRAT a2= nullptr;
PRAT term= nullptr;
PRAT sum= nullptr;
PRAT err= nullptr;
PRAT mpy= nullptr;
PRAT factorial = nullptr;
PNUMBER count = nullptr;
PRAT tmp = nullptr;
PRAT one_pt_five = nullptr;
PRAT a = nullptr;
PRAT a2 = nullptr;
PRAT term = nullptr;
PRAT sum = nullptr;
PRAT err = nullptr;
PRAT mpy = nullptr;
PRAT ratprec = nullptr;
PRAT ratRadix = nullptr;
int32_t oldprec;
// Set up constants and initial conditions
oldprec = precision;
ratprec = i32torat( oldprec );
ratprec = i32torat(oldprec);
// Find the best 'A' for convergence to the required precision.
a=i32torat( radix );
a = i32torat(radix);
lograt(&a, precision);
mulrat(&a, ratprec, precision);
// Really is -ln(n)+1, but -ln(n) will be < 1
// if we scale n between 0.5 and 1.5
addrat(&a, rat_two, precision);
DUPRAT(tmp,a);
DUPRAT(tmp, a);
lograt(&tmp, precision);
mulrat(&tmp, *pn, precision);
addrat(&a, tmp, precision);
@@ -94,85 +92,85 @@ void _gamma( PRAT *pn, uint32_t radix, int32_t precision)
// Calculate the necessary bump in precision and up the precision.
// The following code is equivalent to
// precision += ln(exp(a)*pow(a,n+1.5))-ln(radix));
DUPRAT(tmp,*pn);
one_pt_five=i32torat( 3L );
divrat( &one_pt_five, rat_two, precision);
addrat( &tmp, one_pt_five, precision);
DUPRAT(term,a);
powratcomp( &term, tmp, radix, precision);
DUPRAT( tmp, a );
exprat( &tmp, radix, precision);
mulrat( &term, tmp, precision);
lograt( &term, precision);
DUPRAT(tmp, *pn);
one_pt_five = i32torat(3L);
divrat(&one_pt_five, rat_two, precision);
addrat(&tmp, one_pt_five, precision);
DUPRAT(term, a);
powratcomp(&term, tmp, radix, precision);
DUPRAT(tmp, a);
exprat(&tmp, radix, precision);
mulrat(&term, tmp, precision);
lograt(&term, precision);
ratRadix = i32torat(radix);
DUPRAT(tmp,ratRadix);
lograt( &tmp, precision);
subrat( &term, tmp, precision);
precision += rattoi32( term, radix, precision);
DUPRAT(tmp, ratRadix);
lograt(&tmp, precision);
subrat(&term, tmp, precision);
precision += rattoi32(term, radix, precision);
// Set up initial terms for series, refer to series in above comment block.
DUPRAT(factorial,rat_one); // Start factorial out with one
count = i32tonum( 0L, BASEX );
DUPRAT(factorial, rat_one); // Start factorial out with one
count = i32tonum(0L, BASEX);
DUPRAT(mpy,a);
powratcomp(&mpy,*pn, radix, precision);
DUPRAT(mpy, a);
powratcomp(&mpy, *pn, radix, precision);
// a2=a^2
DUPRAT(a2,a);
DUPRAT(a2, a);
mulrat(&a2, a, precision);
// sum=(1/n)-(a/(n+1))
DUPRAT(sum,rat_one);
DUPRAT(sum, rat_one);
divrat(&sum, *pn, precision);
DUPRAT(tmp,*pn);
DUPRAT(tmp, *pn);
addrat(&tmp, rat_one, precision);
DUPRAT(term,a);
DUPRAT(term, a);
divrat(&term, tmp, precision);
subrat(&sum, term, precision);
DUPRAT(err,ratRadix);
DUPRAT(err, ratRadix);
NEGATE(ratprec);
powratcomp(&err,ratprec, radix, precision);
powratcomp(&err, ratprec, radix, precision);
divrat(&err, ratRadix, precision);
// Just get something not tiny in term
DUPRAT(term, rat_two );
DUPRAT(term, rat_two);
// Loop until precision is reached, or asked to halt.
while ( !zerrat( term ) && rat_gt( term, err, precision) )
{
while (!zerrat(term) && rat_gt(term, err, precision))
{
addrat(pn, rat_two, precision);
// WARNING: mixing numbers and rationals here.
// for speed and efficiency.
INC(count);
mulnumx(&(factorial->pp),count);
mulnumx(&(factorial->pp), count);
INC(count)
mulnumx(&(factorial->pp),count);
mulnumx(&(factorial->pp), count);
divrat(&factorial, a2, precision);
DUPRAT(tmp,*pn);
addrat( &tmp, rat_one, precision);
DUPRAT(tmp, *pn);
addrat(&tmp, rat_one, precision);
destroyrat(term);
createrat(term);
DUPNUM(term->pp,count);
DUPNUM(term->pq,num_one);
addrat( &term, rat_one, precision);
mulrat( &term, tmp, precision);
DUPRAT(tmp,a);
divrat( &tmp, term, precision);
DUPNUM(term->pp, count);
DUPNUM(term->pq, num_one);
addrat(&term, rat_one, precision);
mulrat(&term, tmp, precision);
DUPRAT(tmp, a);
divrat(&tmp, term, precision);
DUPRAT(term,rat_one);
divrat( &term, *pn, precision);
subrat( &term, tmp, precision);
DUPRAT(term, rat_one);
divrat(&term, *pn, precision);
subrat(&term, tmp, precision);
divrat (&term, factorial, precision);
addrat( &sum, term, precision);
divrat(&term, factorial, precision);
addrat(&sum, term, precision);
ABSRAT(term);
}
}
// Multiply by factor.
mulrat( &sum, mpy, precision);
mulrat(&sum, mpy, precision);
// And cleanup
precision = oldprec;
@@ -188,70 +186,67 @@ void _gamma( PRAT *pn, uint32_t radix, int32_t precision)
destroyrat(factorial);
destroyrat(*pn);
DUPRAT(*pn,sum);
DUPRAT(*pn, sum);
destroyrat(sum);
}
void factrat( PRAT *px, uint32_t radix, int32_t precision)
void factrat(PRAT* px, uint32_t radix, int32_t precision)
{
PRAT fact = nullptr;
PRAT frac = nullptr;
PRAT neg_rat_one = nullptr;
if ( rat_gt( *px, rat_max_fact, precision) || rat_lt( *px, rat_min_fact, precision) )
{
if (rat_gt(*px, rat_max_fact, precision) || rat_lt(*px, rat_min_fact, precision))
{
// Don't attempt factorial of anything too large or small.
throw CALC_E_OVERFLOW;
}
}
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;
DUPRAT( frac, *px );
fracrat( &frac, radix, precision);
DUPRAT(frac, *px);
fracrat(&frac, radix, precision);
// Check for negative integers and throw an error.
if ( ( zerrat(frac) || ( LOGRATRADIX(frac) <= -precision) ) &&
( SIGN(*px) == -1 ) )
{
if ((zerrat(frac) || (LOGRATRADIX(frac) <= -precision)) && (SIGN(*px) == -1))
{
throw CALC_E_DOMAIN;
}
while ( rat_gt( *px, rat_zero, precision) &&
( LOGRATRADIX(*px) > -precision) )
{
mulrat( &fact, *px, precision);
subrat( px, rat_one, precision);
}
}
while (rat_gt(*px, rat_zero, precision) && (LOGRATRADIX(*px) > -precision))
{
mulrat(&fact, *px, precision);
subrat(px, rat_one, precision);
}
// Added to make numbers 'close enough' to integers use integer factorial.
if ( LOGRATRADIX(*px) <= -precision)
{
DUPRAT((*px),rat_zero);
if (LOGRATRADIX(*px) <= -precision)
{
DUPRAT((*px), rat_zero);
intrat(&fact, radix, precision);
}
}
while ( rat_lt( *px, neg_rat_one, precision) )
{
addrat( px, rat_one, precision);
divrat( &fact, *px, precision);
}
while (rat_lt(*px, neg_rat_one, precision))
{
addrat(px, rat_one, precision);
divrat(&fact, *px, precision);
}
if ( rat_neq( *px, rat_zero, precision) )
{
addrat( px, rat_one, precision);
_gamma( px, radix, precision);
mulrat( px, fact, precision);
}
if (rat_neq(*px, rat_zero, precision))
{
addrat(px, rat_one, precision);
_gamma(px, radix, precision);
mulrat(px, fact, precision);
}
else
{
DUPRAT(*px,fact);
}
{
DUPRAT(*px, fact);
}
destroyrat(fact);
destroyrat(frac);
destroyrat(neg_rat_one);
}

View File

@@ -17,26 +17,23 @@
//-----------------------------------------------------------------------------
#include "ratpak.h"
void ascalerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, int32_t precision)
void ascalerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, int32_t precision)
{
switch ( angletype )
{
switch (angletype)
{
case ANGLE_RAD:
break;
case ANGLE_DEG:
divrat( pa, two_pi, precision);
mulrat( pa, rat_360, precision);
divrat(pa, two_pi, precision);
mulrat(pa, rat_360, precision);
break;
case ANGLE_GRAD:
divrat( pa, two_pi, precision);
mulrat( pa, rat_400, precision);
divrat(pa, two_pi, precision);
mulrat(pa, rat_400, precision);
break;
}
}
}
//-----------------------------------------------------------------------------
//
// FUNCTION: asinrat, _asinrat
@@ -64,86 +61,83 @@ void ascalerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, int32_t precision)
//
//-----------------------------------------------------------------------------
void _asinrat( PRAT *px, int32_t precision)
void _asinrat(PRAT* px, int32_t precision)
{
CREATETAYLOR();
DUPRAT(pret,*px);
DUPRAT(thisterm,*px);
DUPNUM(n2,num_one);
DUPRAT(pret, *px);
DUPRAT(thisterm, *px);
DUPNUM(n2, num_one);
do
{
NEXTTERM(xx,MULNUM(n2) MULNUM(n2)
INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
}
while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
{
NEXTTERM(xx, MULNUM(n2) MULNUM(n2) INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR();
}
void asinanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
void asinanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
{
asinrat( pa, radix, precision);
ascalerat( pa, angletype, precision);
asinrat(pa, radix, precision);
ascalerat(pa, angletype, precision);
}
void asinrat( PRAT *px, uint32_t radix, int32_t precision)
void asinrat(PRAT* px, uint32_t radix, int32_t precision)
{
PRAT pret= nullptr;
PRAT phack= nullptr;
PRAT pret = nullptr;
PRAT phack = nullptr;
int32_t sgn = SIGN(*px);
(*px)->pp->sign = 1;
(*px)->pq->sign = 1;
// Avoid the really bad part of the asin curve near +/-1.
DUPRAT(phack,*px);
DUPRAT(phack, *px);
subrat(&phack, rat_one, precision);
// Since *px might be epsilon near zero we must set it to zero.
if ( rat_le(phack, rat_smallest, precision) && rat_ge(phack, rat_negsmallest, precision) )
{
if (rat_le(phack, rat_smallest, precision) && rat_ge(phack, rat_negsmallest, precision))
{
destroyrat(phack);
DUPRAT( *px, pi_over_two );
}
DUPRAT(*px, pi_over_two);
}
else
{
{
destroyrat(phack);
if ( rat_gt( *px, pt_eight_five, precision) )
if (rat_gt(*px, pt_eight_five, precision))
{
if (rat_gt(*px, rat_one, precision))
{
if ( rat_gt( *px, rat_one, precision) )
subrat(px, rat_one, precision);
if (rat_gt(*px, rat_smallest, precision))
{
subrat( px, rat_one, precision);
if ( rat_gt( *px, rat_smallest, precision) )
{
throw( CALC_E_DOMAIN );
}
else
{
DUPRAT(*px,rat_one);
}
throw(CALC_E_DOMAIN);
}
DUPRAT(pret,*px);
mulrat( px, pret, precision);
else
{
DUPRAT(*px, rat_one);
}
}
DUPRAT(pret, *px);
mulrat(px, pret, precision);
(*px)->pp->sign *= -1;
addrat( px, rat_one, precision);
rootrat( px, rat_two, radix, precision);
_asinrat( px, precision);
addrat(px, rat_one, precision);
rootrat(px, rat_two, radix, precision);
_asinrat(px, precision);
(*px)->pp->sign *= -1;
addrat( px, pi_over_two, precision);
addrat(px, pi_over_two, precision);
destroyrat(pret);
}
else
{
_asinrat( px, precision);
}
}
else
{
_asinrat(px, precision);
}
}
(*px)->pp->sign = sgn;
(*px)->pq->sign = 1;
}
//-----------------------------------------------------------------------------
//
// FUNCTION: acosrat, _acosrat
@@ -170,35 +164,33 @@ void asinrat( PRAT *px, uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
void acosanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
void acosanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
{
acosrat( pa, radix, precision);
ascalerat( pa, angletype, precision);
acosrat(pa, radix, precision);
ascalerat(pa, angletype, precision);
}
void _acosrat( PRAT *px, int32_t precision)
void _acosrat(PRAT* px, int32_t precision)
{
CREATETAYLOR();
createrat(thisterm);
thisterm->pp=i32tonum( 1L, BASEX );
thisterm->pq=i32tonum( 1L, BASEX );
thisterm->pp = i32tonum(1L, BASEX);
thisterm->pq = i32tonum(1L, BASEX);
DUPNUM(n2,num_one);
DUPNUM(n2, num_one);
do
{
NEXTTERM(xx,MULNUM(n2) MULNUM(n2)
INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
}
while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
{
NEXTTERM(xx, MULNUM(n2) MULNUM(n2) INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR();
}
void acosrat( PRAT *px, uint32_t radix, int32_t precision)
void acosrat(PRAT* px, uint32_t radix, int32_t precision)
{
int32_t sgn = SIGN(*px);
@@ -206,24 +198,24 @@ void acosrat( PRAT *px, uint32_t radix, int32_t precision)
(*px)->pp->sign = 1;
(*px)->pq->sign = 1;
if ( rat_equ( *px, rat_one, precision) )
if (rat_equ(*px, rat_one, precision))
{
if (sgn == -1)
{
if ( sgn == -1 )
{
DUPRAT(*px,pi);
}
else
{
DUPRAT( *px, rat_zero );
}
DUPRAT(*px, pi);
}
else
else
{
DUPRAT(*px, rat_zero);
}
}
else
{
(*px)->pp->sign = sgn;
asinrat( px, radix, precision);
asinrat(px, radix, precision);
(*px)->pp->sign *= -1;
addrat(px, pi_over_two, precision);
}
}
}
//-----------------------------------------------------------------------------
@@ -257,79 +249,79 @@ void acosrat( PRAT *px, uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
void atananglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
void atananglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
{
atanrat( pa, radix, precision);
ascalerat( pa, angletype, precision);
atanrat(pa, radix, precision);
ascalerat(pa, angletype, precision);
}
void _atanrat( PRAT *px, int32_t precision)
void _atanrat(PRAT* px, int32_t precision)
{
CREATETAYLOR();
DUPRAT(pret,*px);
DUPRAT(thisterm,*px);
DUPRAT(pret, *px);
DUPRAT(thisterm, *px);
DUPNUM(n2,num_one);
DUPNUM(n2, num_one);
xx->pp->sign *= -1;
do {
NEXTTERM(xx,MULNUM(n2) INC(n2) INC(n2) DIVNUM(n2), precision);
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
do
{
NEXTTERM(xx, MULNUM(n2) INC(n2) INC(n2) DIVNUM(n2), precision);
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR();
}
void atanrat( PRAT *px, uint32_t radix, int32_t precision)
void atanrat(PRAT* px, uint32_t radix, int32_t precision)
{
PRAT tmpx= nullptr;
PRAT tmpx = nullptr;
int32_t sgn = SIGN(*px);
(*px)->pp->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)->pq->sign = 1;
DUPRAT(tmpx,rat_one);
DUPRAT(tmpx, rat_one);
divrat(&tmpx, (*px), precision);
_atanrat(&tmpx, precision);
tmpx->pp->sign = sgn;
tmpx->pq->sign = 1;
DUPRAT(*px,pi_over_two);
DUPRAT(*px, pi_over_two);
subrat(px, tmpx, precision);
destroyrat( tmpx );
}
destroyrat(tmpx);
}
else
{
{
(*px)->pp->sign = sgn;
DUPRAT(tmpx,*px);
mulrat( &tmpx, *px, precision);
addrat( &tmpx, rat_one, precision);
rootrat( &tmpx, rat_two, radix, precision);
divrat( px, tmpx, precision);
destroyrat( tmpx );
asinrat( px, radix, precision);
DUPRAT(tmpx, *px);
mulrat(&tmpx, *px, precision);
addrat(&tmpx, rat_one, precision);
rootrat(&tmpx, rat_two, radix, precision);
divrat(px, tmpx, precision);
destroyrat(tmpx);
asinrat(px, radix, precision);
(*px)->pp->sign = sgn;
(*px)->pq->sign = 1;
}
}
}
else
{
{
(*px)->pp->sign = sgn;
(*px)->pq->sign = 1;
_atanrat( px, precision);
}
if ( rat_gt( *px, pi_over_two, precision) )
{
subrat( px, pi, precision);
}
_atanrat(px, precision);
}
if (rat_gt(*px, pi_over_two, precision))
{
subrat(px, pi, precision);
}
}

View File

@@ -18,8 +18,6 @@
//-----------------------------------------------------------------------------
#include "ratpak.h"
//-----------------------------------------------------------------------------
//
// FUNCTION: asinhrat
@@ -49,47 +47,44 @@
//
//-----------------------------------------------------------------------------
void asinhrat( PRAT *px, uint32_t radix, int32_t precision)
void asinhrat(PRAT* px, uint32_t radix, int32_t precision)
{
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;
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;
DUPRAT(ptmp,(*px));
DUPRAT(ptmp, (*px));
mulrat(&ptmp, *px, precision);
addrat(&ptmp, rat_one, precision);
rootrat(&ptmp, rat_two, radix, precision);
addrat(px, ptmp, precision);
lograt(px, precision);
destroyrat(ptmp);
}
}
else
{
{
CREATETAYLOR();
xx->pp->sign *= -1;
DUPRAT(pret,(*px));
DUPRAT(thisterm,(*px));
DUPRAT(pret, (*px));
DUPRAT(thisterm, (*px));
DUPNUM(n2,num_one);
DUPNUM(n2, num_one);
do
{
NEXTTERM(xx,MULNUM(n2) MULNUM(n2)
INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
}
while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
{
NEXTTERM(xx, MULNUM(n2) MULNUM(n2) INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR();
}
}
destroyrat(neg_pt_eight_five);
}
//-----------------------------------------------------------------------------
//
// FUNCTION: acoshrat
@@ -106,24 +101,24 @@ void asinhrat( PRAT *px, uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
void acoshrat( PRAT *px, uint32_t radix, int32_t precision)
void acoshrat(PRAT* px, uint32_t radix, int32_t precision)
{
if ( rat_lt( *px, rat_one, precision) )
{
if (rat_lt(*px, rat_one, precision))
{
throw CALC_E_DOMAIN;
}
}
else
{
{
PRAT ptmp = nullptr;
DUPRAT(ptmp,(*px));
DUPRAT(ptmp, (*px));
mulrat(&ptmp, *px, precision);
subrat(&ptmp, rat_one, precision);
rootrat(&ptmp,rat_two, radix, precision);
rootrat(&ptmp, rat_two, radix, precision);
addrat(px, ptmp, precision);
lograt(px, precision);
destroyrat(ptmp);
}
}
}
//-----------------------------------------------------------------------------
@@ -143,11 +138,11 @@ void acoshrat( PRAT *px, uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
void atanhrat( PRAT *px, int32_t precision)
void atanhrat(PRAT* px, int32_t precision)
{
PRAT ptmp = nullptr;
DUPRAT(ptmp,(*px));
DUPRAT(ptmp, (*px));
subrat(&ptmp, rat_one, precision);
addrat(px, rat_one, precision);
divrat(px, ptmp, precision);
@@ -156,4 +151,3 @@ void atanhrat( PRAT *px, int32_t precision)
divrat(px, rat_two, precision);
destroyrat(ptmp);
}

View File

@@ -17,7 +17,7 @@
using namespace std;
void lshrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
void lshrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision)
{
PRAT pwr = nullptr;
@@ -40,7 +40,7 @@ void lshrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
}
}
void rshrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
void rshrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision)
{
PRAT pwr = nullptr;
@@ -63,29 +63,29 @@ void rshrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
}
}
void boolrat(PRAT *pa, PRAT b, int func, uint32_t radix, int32_t precision);
void boolnum(PNUMBER *pa, PNUMBER b, int func);
void boolrat(PRAT* pa, PRAT b, int func, uint32_t radix, int32_t precision);
void boolnum(PNUMBER* pa, PNUMBER b, int func);
enum {
enum
{
FUNC_AND,
FUNC_OR,
FUNC_XOR
} BOOL_FUNCS;
void andrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
void andrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision)
{
boolrat(pa, b, FUNC_AND, radix, precision);
}
void orrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
void orrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision)
{
boolrat(pa, b, FUNC_OR, radix, precision);
}
void xorrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
void xorrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision)
{
boolrat(pa, b, FUNC_XOR, radix, precision);
@@ -103,7 +103,7 @@ void xorrat(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)
{
PRAT tmp = nullptr;
@@ -129,22 +129,21 @@ void boolrat(PRAT *pa, PRAT b, int func, uint32_t radix, int32_t precision)
//
//---------------------------------------------------------------------------
void boolnum(PNUMBER *pa, PNUMBER b, int func)
void boolnum(PNUMBER* pa, PNUMBER b, int func)
{
PNUMBER c = nullptr;
PNUMBER a = nullptr;
MANTTYPE *pcha;
MANTTYPE *pchb;
MANTTYPE *pchc;
MANTTYPE* pcha;
MANTTYPE* pchb;
MANTTYPE* pchc;
int32_t cdigits;
int32_t mexp;
MANTTYPE da;
MANTTYPE db;
a = *pa;
cdigits = max(a->cdigit + a->exp, b->cdigit + b->exp) -
min(a->exp, b->exp);
cdigits = max(a->cdigit + a->exp, b->cdigit + b->exp) - min(a->exp, b->exp);
createnum(c, cdigits);
c->exp = min(a->exp, b->exp);
mexp = c->exp;
@@ -154,12 +153,8 @@ void boolnum(PNUMBER *pa, PNUMBER b, int func)
pchc = c->mant;
for (; cdigits > 0; cdigits--, mexp++)
{
da = (((mexp >= a->exp) && (cdigits + a->exp - c->exp >
(c->cdigit - a->cdigit))) ?
*pcha++ : 0);
db = (((mexp >= b->exp) && (cdigits + b->exp - c->exp >
(c->cdigit - b->cdigit))) ?
*pchb++ : 0);
da = (((mexp >= a->exp) && (cdigits + a->exp - c->exp > (c->cdigit - a->cdigit))) ? *pcha++ : 0);
db = (((mexp >= b->exp) && (cdigits + b->exp - c->exp > (c->cdigit - b->cdigit))) ? *pchb++ : 0);
switch (func)
{
case FUNC_AND:
@@ -196,7 +191,7 @@ void boolnum(PNUMBER *pa, PNUMBER b, int func)
//
//-----------------------------------------------------------------------------
void remrat(PRAT *pa, PRAT b)
void remrat(PRAT* pa, PRAT b)
{
if (zerrat(b))
@@ -227,15 +222,15 @@ void remrat(PRAT *pa, PRAT b)
// RETURN: None, changes pointer.
//
// DESCRIPTION: Calculate the remainder of *pa / b, with the sign of the result
// either zero or has the same sign as the divisor.
// either zero or has the same sign as the divisor.
// NOTE: When *pa or b are negative, the result won't be the same as
// the C/C++ operator %, use remrat if it's the behavior you expect.
// the C/C++ operator %, use remrat if it's the behavior you expect.
//
//-----------------------------------------------------------------------------
void modrat(PRAT *pa, PRAT b)
void modrat(PRAT* pa, PRAT b)
{
//contrary to remrat(X, 0) returning 0, modrat(X, 0) must return X
// contrary to remrat(X, 0) returning 0, modrat(X, 0) must return X
if (zerrat(b))
{
return;

View File

@@ -41,51 +41,49 @@ using namespace std;
//
//----------------------------------------------------------------------------
void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix);
void _addnum(PNUMBER* pa, PNUMBER b, uint32_t radix);
void __inline addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
void __inline addnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
{
if ( b->cdigit > 1 || b->mant[0] != 0 )
{ // If b is zero we are done.
if ( (*pa)->cdigit > 1 || (*pa)->mant[0] != 0 )
{ // pa and b are both nonzero.
_addnum( pa, b, radix);
}
else
{ // if pa is zero and b isn't just copy b.
DUPNUM(*pa,b);
}
if (b->cdigit > 1 || b->mant[0] != 0)
{ // If b is zero we are done.
if ((*pa)->cdigit > 1 || (*pa)->mant[0] != 0)
{ // pa and b are both nonzero.
_addnum(pa, b, radix);
}
else
{ // if pa is zero and b isn't just copy b.
DUPNUM(*pa, b);
}
}
}
void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
void _addnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
{
PNUMBER c= nullptr; // c will contain the result.
PNUMBER a= nullptr; // a is the dereferenced number pointer from *pa
MANTTYPE *pcha; // pcha is a pointer to the mantissa of a.
MANTTYPE *pchb; // pchb is a pointer to the mantissa of b.
MANTTYPE *pchc; // pchc is a pointer to the mantissa of c.
int32_t cdigits; // cdigits is the max count of the digits results
// used as a counter.
int32_t mexp; // mexp is the exponent of the result.
MANTTYPE da; // da is a single 'digit' after possible padding.
MANTTYPE db; // db is a single 'digit' after possible padding.
MANTTYPE cy=0; // cy is the value of a carry after adding two 'digits'
int32_t fcompla = 0; // fcompla is a flag to signal a is negative.
int32_t fcomplb = 0; // fcomplb is a flag to signal b is negative.
a=*pa;
PNUMBER c = nullptr; // c will contain the result.
PNUMBER a = nullptr; // a is the dereferenced number pointer from *pa
MANTTYPE* pcha; // pcha is a pointer to the mantissa of a.
MANTTYPE* pchb; // pchb is a pointer to the mantissa of b.
MANTTYPE* pchc; // pchc is a pointer to the mantissa of c.
int32_t cdigits; // cdigits is the max count of the digits results
// used as a counter.
int32_t mexp; // mexp is the exponent of the result.
MANTTYPE da; // da is a single 'digit' after possible padding.
MANTTYPE db; // db is a single 'digit' after possible padding.
MANTTYPE cy = 0; // cy is the value of a carry after adding two 'digits'
int32_t fcompla = 0; // fcompla is a flag to signal a is negative.
int32_t fcomplb = 0; // fcomplb is a flag to signal b is negative.
a = *pa;
// Calculate the overlap of the numbers after alignment, this includes
// necessary padding 0's
cdigits = max( a->cdigit+a->exp, b->cdigit+b->exp ) -
min( a->exp, b->exp );
cdigits = max(a->cdigit + a->exp, b->cdigit + b->exp) - min(a->exp, b->exp);
createnum( c, cdigits + 1 );
c->exp = min( a->exp, b->exp );
createnum(c, cdigits + 1);
c->exp = min(a->exp, b->exp);
mexp = c->exp;
c->cdigit = cdigits;
pcha = a->mant;
@@ -93,89 +91,82 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
pchc = c->mant;
// Figure out the sign of the numbers
if ( a->sign != b->sign )
{
if (a->sign != b->sign)
{
cy = 1;
fcompla = ( a->sign == -1 );
fcomplb = ( b->sign == -1 );
}
fcompla = (a->sign == -1);
fcomplb = (b->sign == -1);
}
// Loop over all the digits, real and 0 padded. Here we know a and b are
// aligned
for ( ;cdigits > 0; cdigits--, mexp++ )
{
for (; cdigits > 0; cdigits--, mexp++)
{
// Get digit from a, taking padding into account.
da = ( ( ( mexp >= a->exp ) && ( cdigits + a->exp - c->exp >
(c->cdigit - a->cdigit) ) ) ?
*pcha++ : 0 );
da = (((mexp >= a->exp) && (cdigits + a->exp - c->exp > (c->cdigit - a->cdigit))) ? *pcha++ : 0);
// Get digit from b, taking padding into account.
db = ( ( ( mexp >= b->exp ) && ( cdigits + b->exp - c->exp >
(c->cdigit - b->cdigit) ) ) ?
*pchb++ : 0 );
db = (((mexp >= b->exp) && (cdigits + b->exp - c->exp > (c->cdigit - b->cdigit))) ? *pchb++ : 0);
// Handle complementing for a and b digit. Might be a better way, but
// haven't found it yet.
if ( fcompla )
{
da = (MANTTYPE)(radix) - 1 - da;
}
if ( fcomplb )
{
db = (MANTTYPE)(radix) - 1 - db;
}
if (fcompla)
{
da = (MANTTYPE)(radix)-1 - da;
}
if (fcomplb)
{
db = (MANTTYPE)(radix)-1 - db;
}
// Update carry as necessary
cy = da + db + cy;
*pchc++ = (MANTTYPE)(cy % (MANTTYPE)radix);
cy /= (MANTTYPE)radix;
}
}
// Handle carry from last sum as extra digit
if ( cy && !(fcompla || fcomplb) )
{
if (cy && !(fcompla || fcomplb))
{
*pchc++ = cy;
c->cdigit++;
}
}
// Compute sign of result
if ( !(fcompla || fcomplb) )
{
if (!(fcompla || fcomplb))
{
c->sign = a->sign;
}
}
else
{
if (cy)
{
if ( cy )
{
c->sign = 1;
}
}
else
{
{
// In this particular case an overflow or underflow has occurred
// and all the digits need to be complemented, at one time an
// attempt to handle this above was made, it turned out to be much
// slower on average.
c->sign = -1;
cy = 1;
for ( ( cdigits = c->cdigit ), (pchc = c->mant);
cdigits > 0;
cdigits-- )
{
for ((cdigits = c->cdigit), (pchc = c->mant); cdigits > 0; cdigits--)
{
cy = (MANTTYPE)radix - (MANTTYPE)1 - *pchc + cy;
*pchc++ = (MANTTYPE)( cy % (MANTTYPE)radix);
*pchc++ = (MANTTYPE)(cy % (MANTTYPE)radix);
cy /= (MANTTYPE)radix;
}
}
}
}
// Remove leading zeros, remember digits are in order of
// increasing significance. i.e. 100 would be 0,0,1
while ( c->cdigit > 1 && *(--pchc) == 0 )
{
while (c->cdigit > 1 && *(--pchc) == 0)
{
c->cdigit--;
}
destroynum( *pa );
*pa=c;
}
destroynum(*pa);
*pa = c;
}
//----------------------------------------------------------------------------
@@ -193,52 +184,52 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
//
//----------------------------------------------------------------------------
void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix);
void _mulnum(PNUMBER* pa, PNUMBER b, uint32_t radix);
void __inline mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
void __inline mulnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
{
if ( b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0 )
{ // If b is one we don't multiply exactly.
if ( (*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0 )
{ // pa and b are both non-one.
_mulnum( pa, b, radix);
}
if (b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0)
{ // If b is one we don't multiply exactly.
if ((*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0)
{ // pa and b are both non-one.
_mulnum(pa, b, radix);
}
else
{ // if pa is one and b isn't just copy b, and adjust the sign.
{ // if pa is one and b isn't just copy b, and adjust the sign.
int32_t sign = (*pa)->sign;
DUPNUM(*pa,b);
DUPNUM(*pa, b);
(*pa)->sign *= sign;
}
}
}
else
{ // But we do have to set the sign.
{ // But we do have to set the sign.
(*pa)->sign *= b->sign;
}
}
}
void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
void _mulnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
{
PNUMBER c= nullptr; // c will contain the result.
PNUMBER a= nullptr; // a is the dereferenced number pointer from *pa
MANTTYPE *pcha; // pcha is a pointer to the mantissa of a.
MANTTYPE *pchb; // pchb is a pointer to the mantissa of b.
MANTTYPE *pchc; // pchc is a pointer to the mantissa of c.
MANTTYPE *pchcoffset; // pchcoffset, is the anchor location of the next
// single digit multiply partial result.
int32_t iadigit = 0; // Index of digit being used in the first number.
int32_t ibdigit = 0; // Index of digit being used in the second number.
MANTTYPE da = 0; // da is the digit from the fist number.
TWO_MANTTYPE cy = 0; // cy is the carry resulting from the addition of
// a multiplied row into the result.
TWO_MANTTYPE mcy = 0; // mcy is the resultant from a single
// multiply, AND the carry of that multiply.
int32_t icdigit = 0; // Index of digit being calculated in final result.
PNUMBER c = nullptr; // c will contain the result.
PNUMBER a = nullptr; // a is the dereferenced number pointer from *pa
MANTTYPE* pcha; // pcha is a pointer to the mantissa of a.
MANTTYPE* pchb; // pchb is a pointer to the mantissa of b.
MANTTYPE* pchc; // pchc is a pointer to the mantissa of c.
MANTTYPE* pchcoffset; // pchcoffset, is the anchor location of the next
// single digit multiply partial result.
int32_t iadigit = 0; // Index of digit being used in the first number.
int32_t ibdigit = 0; // Index of digit being used in the second number.
MANTTYPE da = 0; // da is the digit from the fist number.
TWO_MANTTYPE cy = 0; // cy is the carry resulting from the addition of
// a multiplied row into the result.
TWO_MANTTYPE mcy = 0; // mcy is the resultant from a single
// multiply, AND the carry of that multiply.
int32_t icdigit = 0; // Index of digit being calculated in final result.
a=*pa;
a = *pa;
ibdigit = a->cdigit + b->cdigit - 1;
createnum( c, ibdigit + 1 );
createnum(c, ibdigit + 1);
c->cdigit = ibdigit;
c->sign = a->sign * b->sign;
@@ -246,58 +237,56 @@ void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
pcha = a->mant;
pchcoffset = c->mant;
for ( iadigit = a->cdigit; iadigit > 0; iadigit-- )
{
da = *pcha++;
for (iadigit = a->cdigit; iadigit > 0; iadigit--)
{
da = *pcha++;
pchb = b->mant;
// Shift pchc, and pchcoffset, one for each digit
pchc = pchcoffset++;
for ( ibdigit = b->cdigit; ibdigit > 0; ibdigit-- )
{
for (ibdigit = b->cdigit; ibdigit > 0; ibdigit--)
{
cy = 0;
mcy = (TWO_MANTTYPE)da * *pchb;
if ( mcy )
{
if (mcy)
{
icdigit = 0;
if ( ibdigit == 1 && iadigit == 1 )
{
c->cdigit++;
}
}
// If result is nonzero, or while result of carry is nonzero...
while ( mcy || cy )
if (ibdigit == 1 && iadigit == 1)
{
c->cdigit++;
}
}
// If result is nonzero, or while result of carry is nonzero...
while (mcy || cy)
{
// update carry from addition(s) and multiply.
cy += (TWO_MANTTYPE)pchc[icdigit]+(mcy%(TWO_MANTTYPE)radix);
cy += (TWO_MANTTYPE)pchc[icdigit] + (mcy % (TWO_MANTTYPE)radix);
// update result digit from
pchc[icdigit++]=(MANTTYPE)(cy%(TWO_MANTTYPE)radix);
pchc[icdigit++] = (MANTTYPE)(cy % (TWO_MANTTYPE)radix);
// update carries from
mcy /= (TWO_MANTTYPE)radix;
cy /= (TWO_MANTTYPE)radix;
}
}
pchb++;
pchc++;
}
}
}
// prevent different kinds of zeros, by stripping leading duplicate zeros.
// digits are in order of increasing significance.
while ( c->cdigit > 1 && c->mant[c->cdigit-1] == 0 )
{
while (c->cdigit > 1 && c->mant[c->cdigit - 1] == 0)
{
c->cdigit--;
}
}
destroynum( *pa );
*pa=c;
destroynum(*pa);
*pa = c;
}
//----------------------------------------------------------------------------
//
// FUNCTION: remnum
@@ -313,55 +302,53 @@ void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
//
//----------------------------------------------------------------------------
void remnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
void remnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
{
PNUMBER tmp = nullptr; // tmp is the working remainder.
PNUMBER lasttmp = nullptr; // lasttmp is the last remainder which worked.
// Once *pa is less than b, *pa is the remainder.
while ( !lessnum( *pa, b ) )
while (!lessnum(*pa, b))
{
DUPNUM(tmp, b);
if (lessnum(tmp, *pa))
{
DUPNUM( tmp, b );
if ( lessnum( tmp, *pa ) )
{
// Start off close to the right answer for subtraction.
tmp->exp = (*pa)->cdigit+(*pa)->exp - tmp->cdigit;
if ( MSD(*pa) <= MSD(tmp) )
{
tmp->exp = (*pa)->cdigit + (*pa)->exp - tmp->cdigit;
if (MSD(*pa) <= MSD(tmp))
{
// Don't take the chance that the numbers are equal.
tmp->exp--;
}
}
}
destroynum( lasttmp );
lasttmp=i32tonum( 0, radix);
destroynum(lasttmp);
lasttmp = i32tonum(0, radix);
while ( lessnum( tmp, *pa ) )
{
DUPNUM( lasttmp, tmp );
addnum( &tmp, tmp, radix);
}
while (lessnum(tmp, *pa))
{
DUPNUM(lasttmp, tmp);
addnum(&tmp, tmp, radix);
}
if ( lessnum( *pa, tmp ) )
{
if (lessnum(*pa, tmp))
{
// too far, back up...
destroynum( tmp );
tmp=lasttmp;
lasttmp= nullptr;
}
destroynum(tmp);
tmp = lasttmp;
lasttmp = nullptr;
}
// Subtract the working remainder from the remainder holder.
tmp->sign = -1*(*pa)->sign;
addnum( pa, tmp, radix);
tmp->sign = -1 * (*pa)->sign;
addnum(pa, tmp, radix);
destroynum( tmp );
destroynum( lasttmp );
}
destroynum(tmp);
destroynum(lasttmp);
}
}
//---------------------------------------------------------------------------
//
// FUNCTION: divnum
@@ -376,23 +363,23 @@ void remnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
//
//---------------------------------------------------------------------------
void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision);
void _divnum(PNUMBER* pa, PNUMBER b, uint32_t radix, int32_t precision);
void __inline divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
void __inline divnum(PNUMBER* pa, PNUMBER b, uint32_t radix, int32_t precision)
{
if ( b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0 )
{
if (b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0)
{
// b is not one
_divnum( pa, b, radix, precision);
}
_divnum(pa, b, radix, precision);
}
else
{ // But we do have to set the sign.
{ // But we do have to set the sign.
(*pa)->sign *= b->sign;
}
}
}
void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
void _divnum(PNUMBER* pa, PNUMBER b, uint32_t radix, int32_t precision)
{
PNUMBER a = *pa;
int32_t thismax = precision + 2;
@@ -411,7 +398,7 @@ void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
c->exp = (a->cdigit + a->exp) - (b->cdigit + b->exp) + 1;
c->sign = a->sign * b->sign;
MANTTYPE *ptrc = c->mant + thismax;
MANTTYPE* ptrc = c->mant + thismax;
PNUMBER rem = nullptr;
PNUMBER tmp = nullptr;
DUPNUM(rem, a);
@@ -489,7 +476,6 @@ void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
*pa = c;
}
//---------------------------------------------------------------------------
//
// FUNCTION: equnum
@@ -503,58 +489,56 @@ void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
//
//---------------------------------------------------------------------------
bool equnum( PNUMBER a, PNUMBER b )
bool equnum(PNUMBER a, PNUMBER b)
{
int32_t diff;
MANTTYPE *pa;
MANTTYPE *pb;
MANTTYPE* pa;
MANTTYPE* pb;
int32_t cdigits;
int32_t ccdigits;
MANTTYPE da;
MANTTYPE db;
MANTTYPE da;
MANTTYPE db;
diff = ( a->cdigit + a->exp ) - ( b->cdigit + b->exp );
if ( diff < 0 )
{
diff = (a->cdigit + a->exp) - (b->cdigit + b->exp);
if (diff < 0)
{
// If the exponents are different, these are different numbers.
return false;
}
}
else
{
if (diff > 0)
{
if ( diff > 0 )
{
// If the exponents are different, these are different numbers.
return false;
}
}
else
{
{
// OK the exponents match.
pa = a->mant;
pb = b->mant;
pa += a->cdigit - 1;
pb += b->cdigit - 1;
cdigits = max( a->cdigit, b->cdigit );
cdigits = max(a->cdigit, b->cdigit);
ccdigits = cdigits;
// Loop over all digits until we run out of digits or there is a
// difference in the digits.
for ( ;cdigits > 0; cdigits-- )
for (; cdigits > 0; cdigits--)
{
da = ((cdigits > (ccdigits - a->cdigit)) ? *pa-- : 0);
db = ((cdigits > (ccdigits - b->cdigit)) ? *pb-- : 0);
if (da != db)
{
da = ( (cdigits > (ccdigits - a->cdigit) ) ?
*pa-- : 0 );
db = ( (cdigits > (ccdigits - b->cdigit) ) ?
*pb-- : 0 );
if ( da != db )
{
return false;
}
}
}
// In this case, they are equal.
return true;
}
}
}
}
//---------------------------------------------------------------------------
@@ -571,54 +555,51 @@ bool equnum( PNUMBER a, PNUMBER b )
//
//---------------------------------------------------------------------------
bool lessnum( PNUMBER a, PNUMBER b )
bool lessnum(PNUMBER a, PNUMBER b)
{
int32_t diff;
MANTTYPE *pa;
MANTTYPE *pb;
MANTTYPE* pa;
MANTTYPE* pb;
int32_t cdigits;
int32_t ccdigits;
MANTTYPE da;
MANTTYPE db;
MANTTYPE da;
MANTTYPE db;
diff = ( a->cdigit + a->exp ) - ( b->cdigit + b->exp );
if ( diff < 0 )
{
diff = (a->cdigit + a->exp) - (b->cdigit + b->exp);
if (diff < 0)
{
// The exponent of a is less than b
return true;
}
}
else
{
if (diff > 0)
{
if ( diff > 0 )
{
return false;
}
}
else
{
{
pa = a->mant;
pb = b->mant;
pa += a->cdigit - 1;
pb += b->cdigit - 1;
cdigits = max( a->cdigit, b->cdigit );
cdigits = max(a->cdigit, b->cdigit);
ccdigits = cdigits;
for ( ;cdigits > 0; cdigits-- )
for (; cdigits > 0; cdigits--)
{
da = ((cdigits > (ccdigits - a->cdigit)) ? *pa-- : 0);
db = ((cdigits > (ccdigits - b->cdigit)) ? *pb-- : 0);
diff = da - db;
if (diff)
{
da = ( (cdigits > (ccdigits - a->cdigit) ) ?
*pa-- : 0 );
db = ( (cdigits > (ccdigits - b->cdigit) ) ?
*pb-- : 0 );
diff = da-db;
if ( diff )
{
return( diff < 0 );
}
return (diff < 0);
}
}
// In this case, they are equal.
return false;
}
}
}
}
//----------------------------------------------------------------------------
@@ -633,24 +614,24 @@ bool lessnum( PNUMBER a, PNUMBER b )
//
//----------------------------------------------------------------------------
bool zernum( PNUMBER a )
bool zernum(PNUMBER a)
{
int32_t length;
MANTTYPE *pcha;
MANTTYPE* pcha;
length = a->cdigit;
pcha = a->mant;
// loop over all the digits until you find a nonzero or until you run
// out of digits
while ( length-- > 0 )
while (length-- > 0)
{
if (*pcha++)
{
if ( *pcha++ )
{
// One of the digits isn't zero, therefore the number isn't zero
return false;
}
}
}
// All of the digits are zero, therefore the number is zero
return true;
}

View File

@@ -37,23 +37,23 @@ using namespace std;
//
//-----------------------------------------------------------------------------
void gcdrat( PRAT *pa, int32_t precision)
void gcdrat(PRAT* pa, int32_t precision)
{
PNUMBER pgcd= nullptr;
PRAT a= nullptr;
PNUMBER pgcd = nullptr;
PRAT a = nullptr;
a=*pa;
pgcd = gcd( a->pp, a->pq );
a = *pa;
pgcd = gcd(a->pp, a->pq);
if ( !zernum( pgcd ) )
{
divnumx( &(a->pp), pgcd, precision);
divnumx( &(a->pq), pgcd, precision);
}
if (!zernum(pgcd))
{
divnumx(&(a->pp), pgcd, precision);
divnumx(&(a->pq), pgcd, precision);
}
destroynum( pgcd );
*pa=a;
destroynum(pgcd);
*pa = a;
RENORMALIZE(*pa);
}
@@ -70,16 +70,16 @@ void gcdrat( PRAT *pa, int32_t precision)
//
//-----------------------------------------------------------------------------
void fracrat( PRAT *pa , uint32_t radix, int32_t precision)
void fracrat(PRAT* pa, uint32_t radix, int32_t precision)
{
// Only do the flatrat operation if number is nonzero.
// and only if the bottom part is not one.
if ( !zernum( (*pa)->pp ) && !equnum( (*pa)->pq, num_one ) )
if (!zernum((*pa)->pp) && !equnum((*pa)->pq, num_one))
{
flatrat(*pa, radix, precision);
}
remnum( &((*pa)->pp), (*pa)->pq, BASEX );
remnum(&((*pa)->pp), (*pa)->pq, BASEX);
// Get *pa back in the integer over integer form.
RENORMALIZE(*pa);
@@ -98,26 +98,25 @@ void fracrat( PRAT *pa , uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
void mulrat( PRAT *pa, PRAT b, int32_t precision)
void mulrat(PRAT* pa, PRAT b, int32_t precision)
{
{
// Only do the multiply if it isn't zero.
if ( !zernum( (*pa)->pp ) )
{
mulnumx( &((*pa)->pp), b->pp );
mulnumx( &((*pa)->pq), b->pq );
if (!zernum((*pa)->pp))
{
mulnumx(&((*pa)->pp), b->pp);
mulnumx(&((*pa)->pq), b->pq);
trimit(pa, precision);
}
}
else
{
{
// If it is zero, blast a one in the denominator.
DUPNUM( ((*pa)->pq), num_one );
}
DUPNUM(((*pa)->pq), num_one);
}
#ifdef MULGCD
gcdrat( pa );
gcdrat(pa);
#endif
}
//-----------------------------------------------------------------------------
@@ -133,44 +132,41 @@ void mulrat( PRAT *pa, PRAT b, int32_t precision)
//
//-----------------------------------------------------------------------------
void divrat( PRAT *pa, PRAT b, int32_t precision)
void divrat(PRAT* pa, PRAT b, int32_t precision)
{
if ( !zernum( (*pa)->pp ) )
{
if (!zernum((*pa)->pp))
{
// Only do the divide if the top isn't zero.
mulnumx( &((*pa)->pp), b->pq );
mulnumx( &((*pa)->pq), b->pp );
mulnumx(&((*pa)->pp), b->pq);
mulnumx(&((*pa)->pq), b->pp);
if ( zernum( (*pa)->pq ) )
{
// raise an exception if the bottom is 0.
throw( CALC_E_DIVIDEBYZERO );
}
trimit(pa, precision);
}
else
if (zernum((*pa)->pq))
{
// raise an exception if the bottom is 0.
throw(CALC_E_DIVIDEBYZERO);
}
trimit(pa, precision);
}
else
{
// Top is zero.
if ( zerrat( b ) )
{
if (zerrat(b))
{
// If bottom is zero
// 0 / 0 is indefinite, raise an exception.
throw( CALC_E_INDEFINITE );
}
else
{
// 0/x make a unique 0.
DUPNUM( ((*pa)->pq), num_one );
}
throw(CALC_E_INDEFINITE);
}
else
{
// 0/x make a unique 0.
DUPNUM(((*pa)->pq), num_one);
}
}
#ifdef DIVGCD
gcdrat( pa );
gcdrat(pa);
#endif
}
//-----------------------------------------------------------------------------
@@ -186,11 +182,11 @@ 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;
addrat( pa, b, precision);
addrat(pa, b, precision);
b->pp->sign *= -1;
}
@@ -207,13 +203,13 @@ 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;
PNUMBER bot = nullptr;
if ( equnum( (*pa)->pq, b->pq ) )
{
if (equnum((*pa)->pq, b->pq))
{
// Very special case, q's match.,
// make sure signs are involved in the calculation
// we have to do this since the optimization here is only
@@ -222,33 +218,30 @@ void addrat( PRAT *pa, PRAT b, int32_t precision)
(*pa)->pq->sign = 1;
b->pp->sign *= b->pq->sign;
b->pq->sign = 1;
addnum( &((*pa)->pp), b->pp, BASEX );
}
addnum(&((*pa)->pp), b->pp, BASEX);
}
else
{
{
// Usual case q's aren't the same.
DUPNUM( bot, (*pa)->pq );
mulnumx( &bot, b->pq );
mulnumx( &((*pa)->pp), b->pq );
mulnumx( &((*pa)->pq), b->pp );
addnum( &((*pa)->pp), (*pa)->pq, BASEX );
destroynum( (*pa)->pq );
DUPNUM(bot, (*pa)->pq);
mulnumx(&bot, b->pq);
mulnumx(&((*pa)->pp), b->pq);
mulnumx(&((*pa)->pq), b->pp);
addnum(&((*pa)->pp), (*pa)->pq, BASEX);
destroynum((*pa)->pq);
(*pa)->pq = bot;
trimit(pa, precision);
// Get rid of negative zeros here.
(*pa)->pp->sign *= (*pa)->pq->sign;
(*pa)->pq->sign = 1;
}
}
#ifdef ADDGCD
gcdrat( pa );
gcdrat(pa);
#endif
}
//-----------------------------------------------------------------------------
//
// FUNCTION: rootrat
@@ -262,11 +255,11 @@ void addrat( PRAT *pa, PRAT b, int32_t precision)
//
//-----------------------------------------------------------------------------
void rootrat( PRAT *py, PRAT n, uint32_t radix, int32_t precision)
void rootrat(PRAT* py, PRAT n, uint32_t radix, int32_t precision)
{
// Initialize 1/n
PRAT oneovern= nullptr;
DUPRAT(oneovern,rat_one);
PRAT oneovern = nullptr;
DUPRAT(oneovern, rat_one);
divrat(&oneovern, n, precision);
powrat(py, oneovern, radix, precision);
@@ -274,7 +267,6 @@ void rootrat( PRAT *py, PRAT n, uint32_t radix, int32_t precision)
destroyrat(oneovern);
}
//-----------------------------------------------------------------------------
//
// FUNCTION: zerrat
@@ -288,10 +280,8 @@ void rootrat( PRAT *py, PRAT n, uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
bool zerrat( PRAT a )
bool zerrat(PRAT a)
{
return( zernum(a->pp) );
return (zernum(a->pp));
}

File diff suppressed because it is too large Load Diff

View File

@@ -21,27 +21,29 @@
#include <string>
#include "CalcErr.h"
#include <cstring> // for memmove
#include <sal.h> // for SAL
#include <sal.h> // for SAL
static constexpr uint32_t BASEXPWR = 31L;// Internal log2(BASEX)
static constexpr uint32_t BASEXPWR = 31L; // Internal log2(BASEX)
static constexpr uint32_t BASEX = 0x80000000; // Internal radix used in calculations, hope to raise
// this to 2^32 after solving scaling problems with
// overflow detection esp. in mul
// this to 2^32 after solving scaling problems with
// overflow detection esp. in mul
typedef uint32_t MANTTYPE;
typedef uint64_t TWO_MANTTYPE;
enum eNUMOBJ_FMT {
FMT_FLOAT, // returns floating point, or exponential if number is too big
FMT_SCIENTIFIC, // always returns scientific notation
FMT_ENGINEERING // always returns engineering notation such that exponent is a multiple of 3
enum eNUMOBJ_FMT
{
FMT_FLOAT, // returns floating point, or exponential if number is too big
FMT_SCIENTIFIC, // always returns scientific notation
FMT_ENGINEERING // always returns engineering notation such that exponent is a multiple of 3
};
enum eANGLE_TYPE {
ANGLE_DEG, // Calculate trig using 360 degrees per revolution
ANGLE_RAD, // Calculate trig using 2 pi radians per revolution
ANGLE_GRAD // Calculate trig using 400 gradients per revolution
enum eANGLE_TYPE
{
ANGLE_DEG, // Calculate trig using 360 degrees per revolution
ANGLE_RAD, // Calculate trig using 2 pi radians per revolution
ANGLE_GRAD // Calculate trig using 400 gradients per revolution
};
@@ -55,21 +57,20 @@ typedef enum eANGLE_TYPE ANGLE_TYPE;
//-----------------------------------------------------------------------------
#pragma warning(push)
#pragma warning(disable:4200) // nonstandard extension used : zero-sized array in struct/union
#pragma warning(disable : 4200) // nonstandard extension used : zero-sized array in struct/union
typedef struct _number
{
int32_t sign; // The sign of the mantissa, +1, or -1
int32_t cdigit; // The number of digits, or what passes for digits in the
int32_t sign; // The sign of the mantissa, +1, or -1
int32_t cdigit; // The number of digits, or what passes for digits in the
// radix being used.
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)
MANTTYPE mant[];
// This is actually allocated as a continuation of the
// NUMBER structure.
// This is actually allocated as a continuation of the
// NUMBER structure.
} NUMBER, *PNUMBER, **PPNUMBER;
#pragma warning(pop)
//-----------------------------------------------------------------------------
//
// RAT type is a representation radix on 2 NUMBER types.
@@ -78,10 +79,10 @@ typedef struct _number
//-----------------------------------------------------------------------------
typedef struct _rat
{
{
PNUMBER pp;
PNUMBER pq;
} RAT, *PRAT;
} RAT, *PRAT;
static constexpr uint32_t MAX_LONG_SIZE = 33; // Base 2 requires 32 'digits'
@@ -135,27 +136,34 @@ extern PRAT rat_max_i32;
extern PRAT rat_min_i32;
// DUPNUM Duplicates a number taking care of allocation and internals
#define DUPNUM(a,b) destroynum(a);createnum( a, (b)->cdigit );_dupnum(a, b);
#define DUPNUM(a, b) \
destroynum(a); \
createnum(a, (b)->cdigit); \
_dupnum(a, b);
// DUPRAT Duplicates a rational taking care of allocation and internals
#define DUPRAT(a,b) destroyrat(a);createrat(a);DUPNUM((a)->pp,(b)->pp);DUPNUM((a)->pq,(b)->pq);
#define DUPRAT(a, b) \
destroyrat(a); \
createrat(a); \
DUPNUM((a)->pp, (b)->pp); \
DUPNUM((a)->pq, (b)->pq);
// LOG*RADIX calculates the integral portion of the log of a number in
// the base currently being used, only accurate to within g_ratio
#define LOGNUMRADIX(pnum) (((pnum)->cdigit+(pnum)->exp)*g_ratio)
#define LOGRATRADIX(prat) (LOGNUMRADIX((prat)->pp)-LOGNUMRADIX((prat)->pq))
#define LOGNUMRADIX(pnum) (((pnum)->cdigit + (pnum)->exp) * g_ratio)
#define LOGRATRADIX(prat) (LOGNUMRADIX((prat)->pp) - LOGNUMRADIX((prat)->pq))
// LOG*2 calculates the integral portion of the log of a number in
// the internal base being used, only accurate to within g_ratio
#define LOGNUM2(pnum) ((pnum)->cdigit+(pnum)->exp)
#define LOGRAT2(prat) (LOGNUM2((prat)->pp)-LOGNUM2((prat)->pq))
#define LOGNUM2(pnum) ((pnum)->cdigit + (pnum)->exp)
#define LOGRAT2(prat) (LOGNUM2((prat)->pp) - LOGNUM2((prat)->pq))
// SIGN returns the sign of the rational
#define SIGN(prat) ((prat)->pp->sign*(prat)->pq->sign)
#define SIGN(prat) ((prat)->pp->sign * (prat)->pq->sign)
#if defined( DEBUG_RATPAK )
#if defined(DEBUG_RATPAK)
//-----------------------------------------------------------------------------
//
// Debug versions of rational number creation and destruction routines.
@@ -163,37 +171,39 @@ extern PRAT rat_min_i32;
//
//-----------------------------------------------------------------------------
#define createrat(y) (y)=_createrat(); \
{ \
std::wstringstream outputString; \
outputString << "createrat " << y << " " << # y << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
OutputDebugString(outputString.str().c_str()); \
}
#define destroyrat(x) \
{ \
std::wstringstream outputString; \
outputString << "destroyrat " << x << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
OutputDebugString(outputString.str().c_str()); \
} \
_destroyrat(x),(x)=nullptr
#define createnum(y,x) (y)=_createnum(x); \
{ \
std::wstringstream outputString; \
outputString << "createnum " << y << " " << # y << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
OutputDebugString(outputString.str().c_str()); \
}
#define destroynum(x) \
{ \
std::wstringstream outputString; \
outputString << "destroynum " << x << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
OutputDebugString(outputString.str().c_str()); \
} \
_destroynum(x),(x)=nullptr
#define createrat(y) \
(y) = _createrat(); \
{ \
std::wstringstream outputString; \
outputString << "createrat " << y << " " << #y << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
OutputDebugString(outputString.str().c_str()); \
}
#define destroyrat(x) \
{ \
std::wstringstream outputString; \
outputString << "destroyrat " << x << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
OutputDebugString(outputString.str().c_str()); \
} \
_destroyrat(x), (x) = nullptr
#define createnum(y, x) \
(y) = _createnum(x); \
{ \
std::wstringstream outputString; \
outputString << "createnum " << y << " " << #y << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
OutputDebugString(outputString.str().c_str()); \
}
#define destroynum(x) \
{ \
std::wstringstream outputString; \
outputString << "destroynum " << x << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
OutputDebugString(outputString.str().c_str()); \
} \
_destroynum(x), (x) = nullptr
#else
#define createrat(y) (y)=_createrat()
#define destroyrat(x) _destroyrat(x),(x)=nullptr
#define createnum(y,x) (y)=_createnum(x)
#define destroynum(x) _destroynum(x),(x)=nullptr
#define createrat(y) (y) = _createrat()
#define destroyrat(x) _destroyrat(x), (x) = nullptr
#define createnum(y, x) (y) = _createnum(x)
#define destroynum(x) _destroynum(x), (x) = nullptr
#endif
//-----------------------------------------------------------------------------
@@ -204,40 +214,47 @@ _destroynum(x),(x)=nullptr
//-----------------------------------------------------------------------------
// RENORMALIZE, gets the exponents non-negative.
#define RENORMALIZE(x) if ( (x)->pp->exp < 0 ) { \
(x)->pq->exp -= (x)->pp->exp; \
(x)->pp->exp = 0; \
} \
if ( (x)->pq->exp < 0 ) { \
(x)->pp->exp -= (x)->pq->exp; \
(x)->pq->exp = 0; \
#define RENORMALIZE(x) \
if ((x)->pp->exp < 0) \
{ \
(x)->pq->exp -= (x)->pp->exp; \
(x)->pp->exp = 0; \
} \
if ((x)->pq->exp < 0) \
{ \
(x)->pp->exp -= (x)->pq->exp; \
(x)->pq->exp = 0; \
}
// TRIMNUM ASSUMES the number is in radix form NOT INTERNAL BASEX!!!
#define TRIMNUM(x, precision) if ( !g_ftrueinfinite ) { \
int32_t trim = (x)->cdigit - precision-g_ratio;\
if ( trim > 1 ) \
{ \
memmove( (x)->mant, &((x)->mant[trim]), sizeof(MANTTYPE)*((x)->cdigit-trim) ); \
(x)->cdigit -= trim; \
(x)->exp += trim; \
} \
}
#define TRIMNUM(x, precision) \
if (!g_ftrueinfinite) \
{ \
int32_t trim = (x)->cdigit - precision - g_ratio; \
if (trim > 1) \
{ \
memmove((x)->mant, &((x)->mant[trim]), sizeof(MANTTYPE) * ((x)->cdigit - trim)); \
(x)->cdigit -= trim; \
(x)->exp += trim; \
} \
}
// TRIMTOP ASSUMES the number is in INTERNAL BASEX!!!
#define TRIMTOP(x, precision) if ( !g_ftrueinfinite ) { \
int32_t trim = (x)->pp->cdigit - (precision/g_ratio) - 2;\
if ( trim > 1 ) \
{ \
memmove( (x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE)*((x)->pp->cdigit-trim) ); \
(x)->pp->cdigit -= trim; \
(x)->pp->exp += trim; \
} \
trim = std::min((x)->pp->exp,(x)->pq->exp);\
(x)->pp->exp -= trim;\
(x)->pq->exp -= trim;\
}
#define TRIMTOP(x, precision) \
if (!g_ftrueinfinite) \
{ \
int32_t trim = (x)->pp->cdigit - (precision / g_ratio) - 2; \
if (trim > 1) \
{ \
memmove((x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE) * ((x)->pp->cdigit - trim)); \
(x)->pp->cdigit -= trim; \
(x)->pp->exp += trim; \
} \
trim = std::min((x)->pp->exp, (x)->pq->exp); \
(x)->pp->exp -= trim; \
(x)->pq->exp -= trim; \
}
#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))
//-----------------------------------------------------------------------------
//
@@ -246,50 +263,55 @@ memmove( (x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE)*((x)->pp->cdigi
//
//-----------------------------------------------------------------------------
#define CREATETAYLOR() PRAT xx=nullptr;\
PNUMBER n2=nullptr; \
PRAT pret=nullptr; \
PRAT thisterm=nullptr; \
DUPRAT(xx,*px); \
mulrat(&xx,*px, precision); \
createrat(pret); \
pret->pp=i32tonum( 0L, BASEX ); \
pret->pq=i32tonum( 0L, BASEX );
#define CREATETAYLOR() \
PRAT xx = nullptr; \
PNUMBER n2 = nullptr; \
PRAT pret = nullptr; \
PRAT thisterm = nullptr; \
DUPRAT(xx, *px); \
mulrat(&xx, *px, precision); \
createrat(pret); \
pret->pp = i32tonum(0L, BASEX); \
pret->pq = i32tonum(0L, BASEX);
#define DESTROYTAYLOR() destroynum( n2 ); \
destroyrat( xx );\
destroyrat( thisterm );\
destroyrat( *px );\
trimit(&pret, precision);\
*px=pret;
#define DESTROYTAYLOR() \
destroynum(n2); \
destroyrat(xx); \
destroyrat(thisterm); \
destroyrat(*px); \
trimit(&pret, precision); \
*px = pret;
// INC(a) is the rational equivalent of a++
// Check to see if we can avoid doing this the hard way.
#define INC(a) if ( (a)->mant[0] < BASEX - 1 ) \
{ \
(a)->mant[0]++; \
} \
else \
{ \
addnum( &(a), num_one, BASEX); \
#define INC(a) \
if ((a)->mant[0] < BASEX - 1) \
{ \
(a)->mant[0]++; \
} \
else \
{ \
addnum(&(a), num_one, BASEX); \
}
#define MSD(x) ((x)->mant[(x)->cdigit-1])
#define MSD(x) ((x)->mant[(x)->cdigit - 1])
// MULNUM(b) is the rational equivalent of thisterm *= b where thisterm is
// a rational and b is a number, NOTE this is a mixed type operation for
// efficiency reasons.
#define MULNUM(b) mulnumx( &(thisterm->pp), b);
#define MULNUM(b) mulnumx(&(thisterm->pp), b);
// DIVNUM(b) is the rational equivalent of thisterm /= b where thisterm is
// a rational and b is a number, NOTE this is a mixed type operation for
// efficiency reasons.
#define DIVNUM(b) mulnumx( &(thisterm->pq), b);
#define DIVNUM(b) mulnumx(&(thisterm->pq), b);
// NEXTTERM(p,d) is the rational equivalent of
// thisterm *= p
// d <d is usually an expansion of operations to get thisterm updated.>
// pret += thisterm
#define NEXTTERM(p,d,precision) mulrat(&thisterm,p,precision);d addrat( &pret, thisterm, precision )
#define NEXTTERM(p, d, precision) \
mulrat(&thisterm, p, precision); \
d addrat(&pret, thisterm, precision)
//-----------------------------------------------------------------------------
//
@@ -299,9 +321,9 @@ memmove( (x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE)*((x)->pp->cdigi
extern bool g_ftrueinfinite; // set to true to allow infinite precision
// don't use unless you know what you are doing
// used to help decide when to stop calculating.
// used to help decide when to stop calculating.
extern int32_t g_ratio; // Internally calculated ratio of internal radix
extern int32_t g_ratio; // Internally calculated ratio of internal radix
//-----------------------------------------------------------------------------
//
@@ -315,10 +337,10 @@ extern void SetDecimalSeparator(wchar_t decimalSeparator);
// Call whenever either radix or precision changes, is smarter about recalculating constants.
extern void ChangeConstants(uint32_t radix, int32_t precision);
extern bool equnum(_In_ PNUMBER a, _In_ PNUMBER b ); // returns true of a == b
extern bool lessnum(_In_ PNUMBER a, _In_ PNUMBER b ); // returns true of a < b
extern bool zernum(_In_ PNUMBER a ); // returns true of a == 0
extern bool zerrat(_In_ PRAT a ); // returns true if a == 0/q
extern bool equnum(_In_ PNUMBER a, _In_ PNUMBER b); // returns true of a == b
extern bool lessnum(_In_ PNUMBER a, _In_ PNUMBER b); // returns true of a < b
extern bool zernum(_In_ PNUMBER a); // returns true of a == 0
extern bool 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);
// returns a text representation of a PRAT
@@ -328,16 +350,18 @@ extern PNUMBER RatToNumber(_In_ PRAT prat, uint32_t radix, int32_t precision);
// flattens a PRAT by converting it to a PNUMBER and back to a PRAT
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_ PNUMBER pnum, uint32_t radix);
extern int32_t rattoi32(_In_ PRAT prat, uint32_t radix, int32_t precision);
uint64_t rattoUi64(_In_ PRAT prat, uint32_t radix, int32_t precision);
extern PNUMBER _createnum(_In_ uint32_t size ); // returns an empty number structure with size digits
extern PNUMBER _createnum(_In_ uint32_t size); // returns an empty number structure with size digits
extern PNUMBER nRadixxtonum(_In_ PNUMBER a, uint32_t radix, int32_t precision);
extern PNUMBER gcd(_In_ PNUMBER a, _In_ PNUMBER b );
extern PNUMBER StringToNumber(std::wstring_view numberString, uint32_t radix, int32_t precision); // takes a text representation of a number and returns a number.
extern PNUMBER gcd(_In_ PNUMBER a, _In_ PNUMBER b);
extern PNUMBER StringToNumber(std::wstring_view numberString, uint32_t radix,
int32_t precision); // takes a text representation of a number and returns a number.
// 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 PNUMBER i32prodnum(int32_t start, int32_t stop, uint32_t radix);
@@ -346,119 +370,119 @@ extern PNUMBER Ui32tonum(uint32_t ini32, uint32_t radix);
extern PNUMBER numtonRadixx(PNUMBER a, uint32_t radix);
// creates a empty/undefined rational representation (p/q)
extern PRAT _createrat( void );
extern PRAT _createrat(void);
// returns a new rat structure with the acos of x->p/x->q taking into account
// angle type
extern void acosanglerat( _Inout_ PRAT *px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
extern void acosanglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
// returns a new rat structure with the acosh of x->p/x->q
extern void acoshrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
extern void acoshrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the acos of x->p/x->q
extern void acosrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
extern void acosrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the asin of x->p/x->q taking into account
// angle type
extern void asinanglerat( _Inout_ PRAT *px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
extern void asinanglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
extern void asinhrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
extern void asinhrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the asinh of x->p/x->q
// returns a new rat structure with the asin of x->p/x->q
extern void asinrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
extern void asinrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the atan of x->p/x->q taking into account
// angle type
extern void atananglerat( _Inout_ PRAT *px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
extern void atananglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
// returns a new rat structure with the atanh of x->p/x->q
extern void atanhrat( _Inout_ PRAT *px, int32_t precision);
extern void atanhrat(_Inout_ PRAT* px, int32_t precision);
// returns a new rat structure with the atan of x->p/x->q
extern void atanrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
extern void atanrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the cosh of x->p/x->q
extern void coshrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
extern void coshrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the cos of x->p/x->q
extern void cosrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
extern void cosrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the cos of x->p/x->q taking into account
// angle type
extern void cosanglerat( _Inout_ PRAT *px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
extern void cosanglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
// returns a new rat structure with the exp of x->p/x->q this should not be called explicitly.
extern void _exprat( _Inout_ PRAT *px, int32_t precision);
extern void _exprat(_Inout_ PRAT* px, int32_t precision);
// returns a new rat structure with the exp of x->p/x->q
extern void exprat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
extern void exprat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the log base 10 of x->p/x->q
extern void log10rat( _Inout_ PRAT *px, int32_t precision);
extern void log10rat(_Inout_ PRAT* px, int32_t precision);
// returns a new rat structure with the natural log of x->p/x->q
extern void lograt( _Inout_ PRAT *px, int32_t precision);
extern void lograt(_Inout_ PRAT* px, int32_t precision);
extern PRAT i32torat( int32_t ini32 );
extern PRAT Ui32torat( uint32_t inui32 );
extern PRAT numtorat( _In_ PNUMBER pin, uint32_t radix);
extern PRAT i32torat(int32_t ini32);
extern PRAT Ui32torat(uint32_t inui32);
extern PRAT numtorat(_In_ PNUMBER pin, uint32_t radix);
extern void sinhrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
extern void sinrat( _Inout_ PRAT *px );
extern void sinhrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
extern void sinrat(_Inout_ PRAT* px);
// returns a new rat structure with the sin of x->p/x->q taking into account
// angle type
extern void sinanglerat( _Inout_ PRAT *px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
extern void sinanglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
extern void tanhrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
extern void tanrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
extern void tanhrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
extern void tanrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the tan of x->p/x->q taking into account
// 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_ PNUMBER dest, _In_ const NUMBER* const src);
extern void _destroynum( _In_ PNUMBER pnum );
extern void _destroyrat( _In_ PRAT prat );
extern void addnum( _Inout_ PNUMBER *pa, _In_ PNUMBER b, uint32_t radix);
extern void addrat( _Inout_ PRAT *pa, _In_ PRAT b, int32_t precision);
extern void andrat( _Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void divnum( _Inout_ PNUMBER *pa, _In_ PNUMBER b, uint32_t radix, int32_t precision);
extern void divnumx( _Inout_ PNUMBER *pa, _In_ PNUMBER b, int32_t precision);
extern void divrat( _Inout_ PRAT *pa, _In_ PRAT b, int32_t precision);
extern void fracrat( _Inout_ PRAT *pa , uint32_t radix, int32_t precision);
extern void factrat( _Inout_ PRAT *pa, uint32_t radix, int32_t precision);
extern void remrat(_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 intrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
extern void mulnum( _Inout_ PNUMBER *pa, _In_ PNUMBER b, uint32_t radix);
extern void mulnumx( _Inout_ PNUMBER *pa, _In_ PNUMBER b );
extern void mulrat( _Inout_ PRAT *pa, _In_ PRAT b, int32_t precision);
extern void numpowi32( _Inout_ PNUMBER *proot, int32_t power, uint32_t radix, int32_t precision);
extern void numpowi32x( _Inout_ PNUMBER *proot, int32_t power );
extern void orrat( _Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void powrat( _Inout_ PRAT *pa, _In_ PRAT b , uint32_t radix, int32_t precision);
extern void powratNumeratorDenominator(_Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void powratcomp(_Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void ratpowi32( _Inout_ PRAT *proot, int32_t power, int32_t precision);
extern void remnum( _Inout_ PNUMBER *pa, _In_ PNUMBER b, uint32_t radix);
extern void rootrat( _Inout_ PRAT *pa, _In_ PRAT b , uint32_t radix, int32_t precision);
extern void scale2pi( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
extern void scale( _Inout_ PRAT *px, _In_ PRAT scalefact, uint32_t radix, int32_t precision);
extern void subrat( _Inout_ PRAT *pa, _In_ PRAT b, int32_t precision);
extern void xorrat( _Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void lshrat( _Inout_ PRAT *pa, _In_ PRAT b , uint32_t radix, int32_t precision);
extern void rshrat( _Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern bool rat_equ( _In_ PRAT a, _In_ PRAT b, int32_t precision);
extern bool rat_neq( _In_ PRAT a, _In_ PRAT b, int32_t precision);
extern bool rat_gt( _In_ PRAT a, _In_ PRAT b, int32_t precision);
extern bool rat_ge( _In_ PRAT a, _In_ PRAT b, int32_t precision);
extern bool rat_lt( _In_ PRAT a, _In_ PRAT b, int32_t precision);
extern bool rat_le( _In_ PRAT a, _In_ PRAT b, int32_t precision);
extern void inbetween( _In_ PRAT *px, _In_ PRAT range, int32_t precision);
extern void trimit( _Inout_ PRAT *px, int32_t precision);
extern void _dumprawrat(_In_ const wchar_t *varname, _In_ PRAT rat, std::wostream& out);
extern void _dumprawnum(_In_ const wchar_t *varname, _In_ PNUMBER num, std::wostream& out);
extern void _destroynum(_In_ PNUMBER pnum);
extern void _destroyrat(_In_ PRAT prat);
extern void addnum(_Inout_ PNUMBER* pa, _In_ PNUMBER b, uint32_t radix);
extern void addrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision);
extern void andrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void divnum(_Inout_ PNUMBER* pa, _In_ PNUMBER b, uint32_t radix, int32_t precision);
extern void divnumx(_Inout_ PNUMBER* pa, _In_ PNUMBER b, int32_t precision);
extern void divrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision);
extern void fracrat(_Inout_ PRAT* pa, uint32_t radix, int32_t precision);
extern void factrat(_Inout_ PRAT* pa, uint32_t radix, int32_t precision);
extern void remrat(_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 intrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
extern void mulnum(_Inout_ PNUMBER* pa, _In_ PNUMBER b, uint32_t radix);
extern void mulnumx(_Inout_ PNUMBER* pa, _In_ PNUMBER b);
extern void mulrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision);
extern void numpowi32(_Inout_ PNUMBER* proot, int32_t power, uint32_t radix, int32_t precision);
extern void numpowi32x(_Inout_ PNUMBER* proot, int32_t power);
extern void orrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void powrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void powratNumeratorDenominator(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void powratcomp(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void ratpowi32(_Inout_ PRAT* proot, int32_t power, int32_t precision);
extern void remnum(_Inout_ PNUMBER* pa, _In_ PNUMBER b, uint32_t radix);
extern void rootrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void scale2pi(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
extern void scale(_Inout_ PRAT* px, _In_ PRAT scalefact, uint32_t radix, int32_t precision);
extern void subrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision);
extern void xorrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void lshrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void rshrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern bool rat_equ(_In_ PRAT a, _In_ PRAT b, int32_t precision);
extern bool rat_neq(_In_ PRAT a, _In_ PRAT b, int32_t precision);
extern bool rat_gt(_In_ PRAT a, _In_ PRAT b, int32_t precision);
extern bool rat_ge(_In_ PRAT a, _In_ PRAT b, int32_t precision);
extern bool rat_lt(_In_ PRAT a, _In_ PRAT b, int32_t precision);
extern bool rat_le(_In_ PRAT a, _In_ PRAT b, int32_t precision);
extern void inbetween(_In_ PRAT* px, _In_ PRAT range, int32_t precision);
extern void trimit(_Inout_ PRAT* px, int32_t precision);
extern void _dumprawrat(_In_ const wchar_t* varname, _In_ PRAT rat, std::wostream& out);
extern void _dumprawnum(_In_ const wchar_t* varname, _In_ PNUMBER num, std::wostream& out);

View File

@@ -19,36 +19,47 @@
//----------------------------------------------------------------------------
#include <string>
#include <cstring> // for memmove
#include <cstring> // for memmove
#include <iostream> // for wostream
#include "ratpak.h"
using namespace std;
void _readconstants( void );
void _readconstants(void);
#if defined( GEN_CONST )
#if defined(GEN_CONST)
static int cbitsofprecision = 0;
#define READRAWRAT(v)
#define READRAWNUM(v)
#define DUMPRAWRAT(v) _dumprawrat(#v,v, wcout)
#define DUMPRAWNUM(v) fprintf( stderr, \
"// Autogenerated by _dumprawrat in support.cpp\n" ); \
fprintf( stderr, "inline const NUMBER init_" #v "= {\n" ); \
_dumprawnum(v, wcout); \
fprintf( stderr, "};\n" )
#define DUMPRAWRAT(v) _dumprawrat(#v, v, wcout)
#define DUMPRAWNUM(v) \
fprintf(stderr, "// Autogenerated by _dumprawrat in support.cpp\n"); \
fprintf(stderr, "inline const NUMBER init_" #v "= {\n"); \
_dumprawnum(v, wcout); \
fprintf(stderr, "};\n")
#else
#define DUMPRAWRAT(v)
#define DUMPRAWNUM(v)
#define READRAWRAT(v) createrat(v); DUPNUM((v)->pp,(&(init_p_##v))); \
DUPNUM((v)->pq,(&(init_q_##v)));
#define READRAWNUM(v) DUPNUM(v,(&(init_##v)))
#define READRAWRAT(v) \
createrat(v); \
DUPNUM((v)->pp, (&(init_p_##v))); \
DUPNUM((v)->pq, (&(init_q_##v)));
#define READRAWNUM(v) DUPNUM(v, (&(init_##v)))
#define INIT_AND_DUMP_RAW_NUM_IF_NULL(r, v) if (r == nullptr) { r = i32tonum(v, BASEX); DUMPRAWNUM(v); }
#define INIT_AND_DUMP_RAW_RAT_IF_NULL(r, v) if (r == nullptr) { r = i32torat(v); DUMPRAWRAT(v); }
#define INIT_AND_DUMP_RAW_NUM_IF_NULL(r, v) \
if (r == nullptr) \
{ \
r = i32tonum(v, BASEX); \
DUMPRAWNUM(v); \
}
#define INIT_AND_DUMP_RAW_RAT_IF_NULL(r, v) \
if (r == nullptr) \
{ \
r = i32torat(v); \
DUMPRAWRAT(v); \
}
static constexpr int RATIO_FOR_DECIMAL = 9;
static constexpr int DECIMAL = 10;
@@ -60,51 +71,51 @@ static int cbitsofprecision = RATIO_FOR_DECIMAL * DECIMAL * CALC_DECIMAL_DIGITS_
#endif
bool g_ftrueinfinite = false; // Set to true if you don't want
// chopping internally
// precision used internally
bool g_ftrueinfinite = false; // Set to true if you don't want
// chopping internally
// precision used internally
PNUMBER num_one= nullptr;
PNUMBER num_two= nullptr;
PNUMBER num_five= nullptr;
PNUMBER num_six= nullptr;
PNUMBER num_ten= nullptr;
PNUMBER num_one = nullptr;
PNUMBER num_two = nullptr;
PNUMBER num_five = nullptr;
PNUMBER num_six = nullptr;
PNUMBER num_ten = nullptr;
PRAT ln_ten= nullptr;
PRAT ln_two= nullptr;
PRAT rat_zero= nullptr;
PRAT rat_one= nullptr;
PRAT rat_neg_one= nullptr;
PRAT rat_two= nullptr;
PRAT rat_six= nullptr;
PRAT rat_half= nullptr;
PRAT rat_ten= nullptr;
PRAT pt_eight_five= nullptr;
PRAT pi= nullptr;
PRAT pi_over_two= nullptr;
PRAT two_pi= nullptr;
PRAT one_pt_five_pi= nullptr;
PRAT e_to_one_half= nullptr;
PRAT rat_exp= nullptr;
PRAT rad_to_deg= nullptr;
PRAT rad_to_grad= nullptr;
PRAT rat_qword= nullptr;
PRAT rat_dword= nullptr; // unsigned max ui32
PRAT rat_word= nullptr;
PRAT rat_byte= nullptr;
PRAT rat_360= nullptr;
PRAT rat_400= nullptr;
PRAT rat_180= nullptr;
PRAT rat_200= nullptr;
PRAT rat_nRadix= nullptr;
PRAT rat_smallest= nullptr;
PRAT rat_negsmallest= nullptr;
PRAT rat_max_exp= nullptr;
PRAT rat_min_exp= nullptr;
PRAT ln_ten = nullptr;
PRAT ln_two = nullptr;
PRAT rat_zero = nullptr;
PRAT rat_one = nullptr;
PRAT rat_neg_one = nullptr;
PRAT rat_two = nullptr;
PRAT rat_six = nullptr;
PRAT rat_half = nullptr;
PRAT rat_ten = nullptr;
PRAT pt_eight_five = nullptr;
PRAT pi = nullptr;
PRAT pi_over_two = nullptr;
PRAT two_pi = nullptr;
PRAT one_pt_five_pi = nullptr;
PRAT e_to_one_half = nullptr;
PRAT rat_exp = nullptr;
PRAT rad_to_deg = nullptr;
PRAT rad_to_grad = nullptr;
PRAT rat_qword = nullptr;
PRAT rat_dword = nullptr; // unsigned max ui32
PRAT rat_word = nullptr;
PRAT rat_byte = nullptr;
PRAT rat_360 = nullptr;
PRAT rat_400 = nullptr;
PRAT rat_180 = nullptr;
PRAT rat_200 = nullptr;
PRAT rat_nRadix = nullptr;
PRAT rat_smallest = nullptr;
PRAT rat_negsmallest = nullptr;
PRAT rat_max_exp = nullptr;
PRAT rat_min_exp = nullptr;
PRAT rat_max_fact = nullptr;
PRAT rat_min_fact = nullptr;
PRAT rat_min_i32= nullptr; // min signed i32
PRAT rat_max_i32= nullptr; // max signed i32
PRAT rat_min_i32 = nullptr; // min signed i32
PRAT rat_max_i32 = nullptr; // max signed i32
//----------------------------------------------------------------------------
//
@@ -127,14 +138,14 @@ void ChangeConstants(uint32_t radix, int32_t precision)
uint64_t limit = static_cast<uint64_t>(BASEX) / static_cast<uint64_t>(radix);
g_ratio = 0;
for (uint32_t digit = 1; digit < limit; digit *= radix )
for (uint32_t digit = 1; digit < limit; digit *= radix)
{
g_ratio++;
}
g_ratio += !g_ratio;
destroyrat(rat_nRadix);
rat_nRadix=i32torat( radix );
rat_nRadix = i32torat(radix);
// Check to see what we have to recalculate and what we don't
if (cbitsofprecision < (g_ratio * static_cast<int32_t>(radix) * precision))
@@ -253,7 +264,6 @@ void ChangeConstants(uint32_t radix, int32_t precision)
lograt(&ln_two, extraPrecision);
DUMPRAWRAT(ln_two);
destroyrat(rad_to_deg);
rad_to_deg = i32torat(180L);
divrat(&rad_to_deg, pi, extraPrecision);
@@ -273,7 +283,6 @@ void ChangeConstants(uint32_t radix, int32_t precision)
DUPRAT(rat_negsmallest, rat_smallest);
rat_negsmallest->pp->sign = -1;
}
}
//----------------------------------------------------------------------------
@@ -287,21 +296,21 @@ void ChangeConstants(uint32_t radix, int32_t precision)
//
//----------------------------------------------------------------------------
void intrat( PRAT *px, uint32_t radix, int32_t precision)
void intrat(PRAT* px, uint32_t radix, int32_t precision)
{
// Only do the intrat operation if number is nonzero.
// and only if the bottom part is not one.
if ( !zernum( (*px)->pp ) && !equnum( (*px)->pq, num_one ) )
if (!zernum((*px)->pp) && !equnum((*px)->pq, num_one))
{
flatrat(*px, radix, precision);
// Subtract the fractional part of the rational
PRAT pret = nullptr;
DUPRAT(pret,*px);
remrat( &pret, rat_one );
DUPRAT(pret, *px);
remrat(&pret, rat_one);
subrat( px, pret, precision);
destroyrat( pret );
subrat(px, pret, precision);
destroyrat(pret);
// Simplify the value if possible to resolve rounding errors
flatrat(*px, radix, precision);
@@ -319,16 +328,16 @@ void intrat( PRAT *px, uint32_t radix, int32_t precision)
//
//---------------------------------------------------------------------------
bool rat_equ( PRAT a, PRAT b, int32_t precision)
bool rat_equ(PRAT a, PRAT b, int32_t precision)
{
PRAT rattmp= nullptr;
DUPRAT(rattmp,a);
PRAT rattmp = nullptr;
DUPRAT(rattmp, a);
rattmp->pp->sign *= -1;
addrat( &rattmp, b, precision);
bool bret = zernum( rattmp->pp );
destroyrat( rattmp );
return( bret );
addrat(&rattmp, b, precision);
bool bret = zernum(rattmp->pp);
destroyrat(rattmp);
return (bret);
}
//---------------------------------------------------------------------------
@@ -342,20 +351,19 @@ bool rat_equ( PRAT a, PRAT b, int32_t precision)
//
//---------------------------------------------------------------------------
bool rat_ge( PRAT a, PRAT b, int32_t precision)
bool rat_ge(PRAT a, PRAT b, int32_t precision)
{
PRAT rattmp= nullptr;
DUPRAT(rattmp,a);
PRAT rattmp = nullptr;
DUPRAT(rattmp, a);
b->pp->sign *= -1;
addrat( &rattmp, b, precision);
addrat(&rattmp, b, precision);
b->pp->sign *= -1;
bool bret = ( zernum( rattmp->pp ) || SIGN(rattmp) == 1 );
destroyrat( rattmp );
return( bret );
bool bret = (zernum(rattmp->pp) || SIGN(rattmp) == 1);
destroyrat(rattmp);
return (bret);
}
//---------------------------------------------------------------------------
//
// FUNCTION: rat_gt
@@ -367,17 +375,17 @@ bool rat_ge( PRAT a, PRAT b, int32_t precision)
//
//---------------------------------------------------------------------------
bool rat_gt( PRAT a, PRAT b, int32_t precision)
bool rat_gt(PRAT a, PRAT b, int32_t precision)
{
PRAT rattmp= nullptr;
DUPRAT(rattmp,a);
PRAT rattmp = nullptr;
DUPRAT(rattmp, a);
b->pp->sign *= -1;
addrat( &rattmp, b, precision);
addrat(&rattmp, b, precision);
b->pp->sign *= -1;
bool bret = ( !zernum( rattmp->pp ) && SIGN(rattmp) == 1 );
destroyrat( rattmp );
return( bret );
bool bret = (!zernum(rattmp->pp) && SIGN(rattmp) == 1);
destroyrat(rattmp);
return (bret);
}
//---------------------------------------------------------------------------
@@ -391,21 +399,19 @@ bool rat_gt( PRAT a, PRAT b, int32_t precision)
//
//---------------------------------------------------------------------------
bool rat_le( PRAT a, PRAT b, int32_t precision)
bool rat_le(PRAT a, PRAT b, int32_t precision)
{
PRAT rattmp= nullptr;
DUPRAT(rattmp,a);
PRAT rattmp = nullptr;
DUPRAT(rattmp, a);
b->pp->sign *= -1;
addrat( &rattmp, b, precision);
addrat(&rattmp, b, precision);
b->pp->sign *= -1;
bool bret = ( zernum( rattmp->pp ) || SIGN(rattmp) == -1 );
destroyrat( rattmp );
return( bret );
bool bret = (zernum(rattmp->pp) || SIGN(rattmp) == -1);
destroyrat(rattmp);
return (bret);
}
//---------------------------------------------------------------------------
//
// FUNCTION: rat_lt
@@ -417,20 +423,19 @@ bool rat_le( PRAT a, PRAT b, int32_t precision)
//
//---------------------------------------------------------------------------
bool rat_lt( PRAT a, PRAT b, int32_t precision)
bool rat_lt(PRAT a, PRAT b, int32_t precision)
{
PRAT rattmp= nullptr;
DUPRAT(rattmp,a);
PRAT rattmp = nullptr;
DUPRAT(rattmp, a);
b->pp->sign *= -1;
addrat( &rattmp, b, precision);
addrat(&rattmp, b, precision);
b->pp->sign *= -1;
bool bret = ( !zernum( rattmp->pp ) && SIGN(rattmp) == -1 );
destroyrat( rattmp );
return( bret );
bool bret = (!zernum(rattmp->pp) && SIGN(rattmp) == -1);
destroyrat(rattmp);
return (bret);
}
//---------------------------------------------------------------------------
//
// FUNCTION: rat_neq
@@ -442,17 +447,16 @@ bool rat_lt( PRAT a, PRAT b, int32_t precision)
//
//---------------------------------------------------------------------------
bool rat_neq( PRAT a, PRAT b, int32_t precision)
bool rat_neq(PRAT a, PRAT b, int32_t precision)
{
PRAT rattmp= nullptr;
DUPRAT(rattmp,a);
PRAT rattmp = nullptr;
DUPRAT(rattmp, a);
rattmp->pp->sign *= -1;
addrat( &rattmp, b, precision);
bool bret = !( zernum( rattmp->pp ) );
destroyrat( rattmp );
return( bret );
addrat(&rattmp, b, precision);
bool bret = !(zernum(rattmp->pp));
destroyrat(rattmp);
return (bret);
}
//---------------------------------------------------------------------------
@@ -466,27 +470,26 @@ bool rat_neq( PRAT a, PRAT b, int32_t precision)
//
//---------------------------------------------------------------------------
void scale( PRAT *px, PRAT scalefact, uint32_t radix, int32_t precision )
void scale(PRAT* px, PRAT scalefact, uint32_t radix, int32_t precision)
{
PRAT pret = nullptr;
DUPRAT(pret,*px);
DUPRAT(pret, *px);
// Logscale is a quick way to tell how much extra precision is needed for
// scaling by scalefact.
int32_t logscale = g_ratio * ( (pret->pp->cdigit+pret->pp->exp) -
(pret->pq->cdigit+pret->pq->exp) );
if ( logscale > 0 )
int32_t logscale = g_ratio * ((pret->pp->cdigit + pret->pp->exp) - (pret->pq->cdigit + pret->pq->exp));
if (logscale > 0)
{
precision += logscale;
}
divrat( &pret, scalefact, precision);
divrat(&pret, scalefact, precision);
intrat(&pret, radix, precision);
mulrat( &pret, scalefact, precision);
mulrat(&pret, scalefact, precision);
pret->pp->sign *= -1;
addrat( px, pret, precision);
addrat(px, pret, precision);
destroyrat( pret );
destroyrat(pret);
}
//---------------------------------------------------------------------------
@@ -500,38 +503,37 @@ void scale( PRAT *px, PRAT scalefact, uint32_t radix, int32_t precision )
//
//---------------------------------------------------------------------------
void scale2pi( PRAT *px, uint32_t radix, int32_t precision )
void scale2pi(PRAT* px, uint32_t radix, int32_t precision)
{
PRAT pret = nullptr;
PRAT my_two_pi = nullptr;
DUPRAT(pret,*px);
DUPRAT(pret, *px);
// Logscale is a quick way to tell how much extra precision is needed for
// scaling by 2 pi.
int32_t logscale = g_ratio * ( (pret->pp->cdigit+pret->pp->exp) -
(pret->pq->cdigit+pret->pq->exp) );
if ( logscale > 0 )
int32_t logscale = g_ratio * ((pret->pp->cdigit + pret->pp->exp) - (pret->pq->cdigit + pret->pq->exp));
if (logscale > 0)
{
precision += logscale;
DUPRAT(my_two_pi,rat_half);
asinrat( &my_two_pi, radix, precision);
mulrat( &my_two_pi, rat_six, precision);
mulrat( &my_two_pi, rat_two, precision);
DUPRAT(my_two_pi, rat_half);
asinrat(&my_two_pi, radix, precision);
mulrat(&my_two_pi, rat_six, precision);
mulrat(&my_two_pi, rat_two, precision);
}
else
{
DUPRAT(my_two_pi,two_pi);
DUPRAT(my_two_pi, two_pi);
logscale = 0;
}
divrat( &pret, my_two_pi, precision);
divrat(&pret, my_two_pi, precision);
intrat(&pret, radix, precision);
mulrat( &pret, my_two_pi, precision);
mulrat(&pret, my_two_pi, precision);
pret->pp->sign *= -1;
addrat( px, pret, precision);
addrat(px, pret, precision);
destroyrat( my_two_pi );
destroyrat( pret );
destroyrat(my_two_pi);
destroyrat(pret);
}
//---------------------------------------------------------------------------
@@ -544,22 +546,22 @@ void scale2pi( PRAT *px, uint32_t radix, int32_t precision )
//
//---------------------------------------------------------------------------
void inbetween( PRAT *px, PRAT range, int32_t precision)
void inbetween(PRAT* px, PRAT range, int32_t precision)
{
if ( rat_gt(*px,range, precision) )
{
DUPRAT(*px,range);
}
if (rat_gt(*px, range, precision))
{
DUPRAT(*px, range);
}
else
{
range->pp->sign *= -1;
if (rat_lt(*px, range, precision))
{
range->pp->sign *= -1;
if ( rat_lt(*px, range, precision) )
{
DUPRAT(*px,range);
}
range->pp->sign *= -1;
DUPRAT(*px, range);
}
range->pp->sign *= -1;
}
}
//---------------------------------------------------------------------------
@@ -573,11 +575,11 @@ void inbetween( PRAT *px, PRAT range, int32_t precision)
//
//---------------------------------------------------------------------------
void _dumprawrat( const wchar_t *varname, PRAT rat, wostream& out)
void _dumprawrat(const wchar_t* varname, PRAT rat, wostream& out)
{
_dumprawnum(varname, rat->pp, out );
_dumprawnum(varname, rat->pq, out );
_dumprawnum(varname, rat->pp, out);
_dumprawnum(varname, rat->pq, out);
}
//---------------------------------------------------------------------------
@@ -591,26 +593,26 @@ void _dumprawrat( const wchar_t *varname, PRAT rat, wostream& out)
//
//---------------------------------------------------------------------------
void _dumprawnum(const wchar_t *varname, PNUMBER num, wostream& out)
void _dumprawnum(const wchar_t* varname, PNUMBER num, wostream& out)
{
int i;
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->exp << L",\n";
out << L"\t{ ";
for ( i = 0; i < num->cdigit; i++ )
{
out << L" "<< num->mant[i] << L",";
}
for (i = 0; i < num->cdigit; i++)
{
out << L" " << num->mant[i] << L",";
}
out << L"}\n";
out << L"};\n";
}
void _readconstants( void )
void _readconstants(void)
{
READRAWNUM(num_one);
@@ -674,43 +676,43 @@ void _readconstants( void )
//
//---------------------------------------------------------------------------
void trimit( PRAT *px, int32_t precision)
void trimit(PRAT* px, int32_t precision)
{
if ( !g_ftrueinfinite )
{
if (!g_ftrueinfinite)
{
int32_t trim;
PNUMBER pp=(*px)->pp;
PNUMBER pq=(*px)->pq;
trim = g_ratio * (min((pp->cdigit+pp->exp),(pq->cdigit+pq->exp))-1) - precision;
if ( trim > g_ratio )
{
PNUMBER pp = (*px)->pp;
PNUMBER pq = (*px)->pq;
trim = g_ratio * (min((pp->cdigit + pp->exp), (pq->cdigit + pq->exp)) - 1) - precision;
if (trim > g_ratio)
{
trim /= g_ratio;
if ( trim <= pp->exp )
{
if (trim <= pp->exp)
{
pp->exp -= trim;
}
else
{
memmove( pp->mant, &(pp->mant[trim-pp->exp]), sizeof(MANTTYPE)*(pp->cdigit-trim+pp->exp) );
pp->cdigit -= trim-pp->exp;
pp->exp = 0;
}
if ( trim <= pq->exp )
{
pq->exp -= trim;
}
else
{
memmove( pq->mant, &(pq->mant[trim-pq->exp]), sizeof(MANTTYPE)*(pq->cdigit-trim+pq->exp) );
pq->cdigit -= trim-pq->exp;
pq->exp = 0;
}
}
trim = min(pp->exp,pq->exp);
else
{
memmove(pp->mant, &(pp->mant[trim - pp->exp]), sizeof(MANTTYPE) * (pp->cdigit - trim + pp->exp));
pp->cdigit -= trim - pp->exp;
pp->exp = 0;
}
if (trim <= pq->exp)
{
pq->exp -= trim;
}
else
{
memmove(pq->mant, &(pq->mant[trim - pq->exp]), sizeof(MANTTYPE) * (pq->cdigit - trim + pq->exp));
pq->cdigit -= trim - pq->exp;
pq->exp = 0;
}
}
trim = min(pp->exp, pq->exp);
pp->exp -= trim;
pq->exp -= trim;
}
}
}

View File

@@ -16,25 +16,22 @@
#include "ratpak.h"
void scalerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision )
void scalerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
{
switch ( angletype )
switch (angletype)
{
case ANGLE_RAD:
scale2pi( pa, radix, precision);
scale2pi(pa, radix, precision);
break;
case ANGLE_DEG:
scale( pa, rat_360, radix, precision);
scale(pa, rat_360, radix, precision);
break;
case ANGLE_GRAD:
scale( pa, rat_400, radix, precision);
scale(pa, rat_400, radix, precision);
break;
}
}
//-----------------------------------------------------------------------------
//
// FUNCTION: sinrat, _sinrat
@@ -66,21 +63,21 @@ void scalerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t p
//
//-----------------------------------------------------------------------------
void _sinrat( PRAT *px, int32_t precision)
void _sinrat(PRAT* px, int32_t precision)
{
CREATETAYLOR();
DUPRAT(pret,*px);
DUPRAT(thisterm,*px);
DUPRAT(pret, *px);
DUPRAT(thisterm, *px);
DUPNUM(n2,num_one);
DUPNUM(n2, num_one);
xx->pp->sign *= -1;
do {
NEXTTERM(xx,INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
do
{
NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR();
@@ -89,42 +86,42 @@ void _sinrat( PRAT *px, int32_t precision)
inbetween(px, rat_one, precision);
// Since *px might be epsilon near zero we must set it to zero.
if ( rat_le(*px, rat_smallest, precision) && rat_ge(*px, rat_negsmallest, precision) )
{
DUPRAT(*px,rat_zero);
}
if (rat_le(*px, rat_smallest, precision) && rat_ge(*px, rat_negsmallest, precision))
{
DUPRAT(*px, rat_zero);
}
}
void sinrat( PRAT *px, uint32_t radix, int32_t precision)
void sinrat(PRAT* px, uint32_t radix, int32_t precision)
{
scale2pi(px, radix, precision);
_sinrat(px, precision);
}
void sinanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
void sinanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
{
scalerat( pa, angletype, radix, precision);
switch ( angletype )
{
scalerat(pa, angletype, radix, precision);
switch (angletype)
{
case ANGLE_DEG:
if ( rat_gt( *pa, rat_180, precision) )
{
if (rat_gt(*pa, rat_180, precision))
{
subrat(pa, rat_360, precision);
}
divrat( pa, rat_180, precision);
mulrat( pa, pi, precision);
}
divrat(pa, rat_180, precision);
mulrat(pa, pi, precision);
break;
case ANGLE_GRAD:
if ( rat_gt( *pa, rat_200, precision) )
{
subrat(pa,rat_400, precision);
}
divrat( pa, rat_200, precision);
mulrat( pa, pi, precision);
break;
if (rat_gt(*pa, rat_200, precision))
{
subrat(pa, rat_400, precision);
}
_sinrat( pa, precision);
divrat(pa, rat_200, precision);
mulrat(pa, pi, precision);
break;
}
_sinrat(pa, precision);
}
//-----------------------------------------------------------------------------
@@ -158,8 +155,7 @@ void sinanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_
//
//-----------------------------------------------------------------------------
void _cosrat( PRAT *px, uint32_t radix, int32_t precision)
void _cosrat(PRAT* px, uint32_t radix, int32_t precision)
{
CREATETAYLOR();
@@ -167,67 +163,68 @@ void _cosrat( PRAT *px, uint32_t radix, int32_t precision)
destroynum(pret->pp);
destroynum(pret->pq);
pret->pp=i32tonum( 1L, radix);
pret->pq=i32tonum( 1L, radix);
pret->pp = i32tonum(1L, radix);
pret->pq = i32tonum(1L, radix);
DUPRAT(thisterm,pret)
DUPRAT(thisterm, pret)
n2=i32tonum(0L, radix);
n2 = i32tonum(0L, radix);
xx->pp->sign *= -1;
do {
NEXTTERM(xx,INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
do
{
NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR();
// Since *px might be epsilon above 1 or below -1, due to TRIMIT we need
// this trick here.
inbetween(px, rat_one, precision);
// Since *px might be epsilon near zero we must set it to zero.
if ( rat_le(*px, rat_smallest, precision) && rat_ge(*px, rat_negsmallest, precision) )
{
DUPRAT(*px,rat_zero);
}
if (rat_le(*px, rat_smallest, precision) && rat_ge(*px, rat_negsmallest, precision))
{
DUPRAT(*px, rat_zero);
}
}
void cosrat( PRAT *px, uint32_t radix, int32_t precision)
void cosrat(PRAT* px, uint32_t radix, int32_t precision)
{
scale2pi(px, radix, precision);
_cosrat(px, radix, precision);
}
void cosanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
void cosanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
{
scalerat( pa, angletype, radix, precision);
switch ( angletype )
{
scalerat(pa, angletype, radix, precision);
switch (angletype)
{
case ANGLE_DEG:
if ( rat_gt( *pa, rat_180, precision) )
{
PRAT ptmp= nullptr;
DUPRAT(ptmp,rat_360);
if (rat_gt(*pa, rat_180, precision))
{
PRAT ptmp = nullptr;
DUPRAT(ptmp, rat_360);
subrat(&ptmp, *pa, precision);
destroyrat(*pa);
*pa=ptmp;
}
divrat( pa, rat_180, precision);
mulrat( pa, pi, precision);
*pa = ptmp;
}
divrat(pa, rat_180, precision);
mulrat(pa, pi, precision);
break;
case ANGLE_GRAD:
if ( rat_gt( *pa, rat_200, precision) )
{
PRAT ptmp= nullptr;
DUPRAT(ptmp,rat_400);
if (rat_gt(*pa, rat_200, precision))
{
PRAT ptmp = nullptr;
DUPRAT(ptmp, rat_400);
subrat(&ptmp, *pa, precision);
destroyrat(*pa);
*pa=ptmp;
}
divrat( pa, rat_200, precision);
mulrat( pa, pi, precision);
break;
*pa = ptmp;
}
_cosrat( pa, radix, precision);
divrat(pa, rat_200, precision);
mulrat(pa, pi, precision);
break;
}
_cosrat(pa, radix, precision);
}
//-----------------------------------------------------------------------------
@@ -242,55 +239,52 @@ void cosanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_
//
//-----------------------------------------------------------------------------
void _tanrat( PRAT *px, uint32_t radix, int32_t precision)
void _tanrat(PRAT* px, uint32_t radix, int32_t precision)
{
PRAT ptmp= nullptr;
PRAT ptmp = nullptr;
DUPRAT(ptmp,*px);
DUPRAT(ptmp, *px);
_sinrat(px, precision);
_cosrat(&ptmp, radix, precision);
if ( zerrat( ptmp ) )
{
if (zerrat(ptmp))
{
destroyrat(ptmp);
throw( CALC_E_DOMAIN );
}
throw(CALC_E_DOMAIN);
}
divrat(px, ptmp, precision);
destroyrat(ptmp);
}
void tanrat( PRAT *px, uint32_t radix, int32_t precision)
void tanrat(PRAT* px, uint32_t radix, int32_t precision)
{
scale2pi(px, radix, precision);
_tanrat(px, radix, precision);
}
void tananglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
void tananglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
{
scalerat( pa, angletype, radix, precision);
switch ( angletype )
{
scalerat(pa, angletype, radix, precision);
switch (angletype)
{
case ANGLE_DEG:
if ( rat_gt( *pa, rat_180, precision) )
{
if (rat_gt(*pa, rat_180, precision))
{
subrat(pa, rat_180, precision);
}
divrat( pa, rat_180, precision);
mulrat( pa, pi, precision);
}
divrat(pa, rat_180, precision);
mulrat(pa, pi, precision);
break;
case ANGLE_GRAD:
if ( rat_gt( *pa, rat_200, precision) )
{
if (rat_gt(*pa, rat_200, precision))
{
subrat(pa, rat_200, precision);
}
divrat( pa, rat_200, precision);
mulrat( pa, pi, precision);
break;
}
_tanrat( pa, radix, precision);
divrat(pa, rat_200, precision);
mulrat(pa, pi, precision);
break;
}
_tanrat(pa, radix, precision);
}

View File

@@ -16,22 +16,19 @@
//-----------------------------------------------------------------------------
#include "ratpak.h"
bool IsValidForHypFunc(PRAT px, int32_t precision)
{
PRAT ptmp = nullptr;
bool bRet = true;
DUPRAT(ptmp,rat_min_exp);
DUPRAT(ptmp, rat_min_exp);
divrat(&ptmp, rat_ten, precision);
if ( rat_lt( px, ptmp, precision) )
if (rat_lt(px, ptmp, precision))
{
bRet = false;
}
destroyrat( ptmp );
destroyrat(ptmp);
return bRet;
}
//-----------------------------------------------------------------------------
@@ -67,49 +64,49 @@ bool IsValidForHypFunc(PRAT px, int32_t precision)
//
//-----------------------------------------------------------------------------
void _sinhrat( PRAT *px, int32_t precision)
void _sinhrat(PRAT* px, int32_t precision)
{
if ( !IsValidForHypFunc(*px, precision))
{
if (!IsValidForHypFunc(*px, precision))
{
// Don't attempt exp of anything large or small
throw( CALC_E_DOMAIN );
}
throw(CALC_E_DOMAIN);
}
CREATETAYLOR();
DUPRAT(pret,*px);
DUPRAT(thisterm,pret);
DUPRAT(pret, *px);
DUPRAT(thisterm, pret);
DUPNUM(n2,num_one);
DUPNUM(n2, num_one);
do {
NEXTTERM(xx,INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
do
{
NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR();
}
void sinhrat( PRAT *px, uint32_t radix, int32_t precision)
void sinhrat(PRAT* px, uint32_t radix, int32_t precision)
{
PRAT tmpx= nullptr;
PRAT tmpx = nullptr;
if ( rat_ge( *px, rat_one, precision) )
{
DUPRAT(tmpx,*px);
if (rat_ge(*px, rat_one, precision))
{
DUPRAT(tmpx, *px);
exprat(px, radix, precision);
tmpx->pp->sign *= -1;
exprat(&tmpx, radix, precision);
subrat( px, tmpx, precision);
divrat( px, rat_two, precision);
destroyrat( tmpx );
}
subrat(px, tmpx, precision);
divrat(px, rat_two, precision);
destroyrat(tmpx);
}
else
{
_sinhrat( px, precision);
}
{
_sinhrat(px, precision);
}
}
//-----------------------------------------------------------------------------
@@ -146,59 +143,59 @@ void sinhrat( PRAT *px, uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
void _coshrat( PRAT *px, uint32_t radix, int32_t precision)
void _coshrat(PRAT* px, uint32_t radix, int32_t precision)
{
if ( !IsValidForHypFunc(*px, precision))
{
if (!IsValidForHypFunc(*px, precision))
{
// Don't attempt exp of anything large or small
throw( CALC_E_DOMAIN );
}
throw(CALC_E_DOMAIN);
}
CREATETAYLOR();
pret->pp=i32tonum( 1L, radix);
pret->pq=i32tonum( 1L, radix);
pret->pp = i32tonum(1L, radix);
pret->pq = i32tonum(1L, radix);
DUPRAT(thisterm,pret)
DUPRAT(thisterm, pret)
n2=i32tonum(0L, radix);
n2 = i32tonum(0L, radix);
do {
NEXTTERM(xx,INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
do
{
NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR();
}
void coshrat( PRAT *px, uint32_t radix, int32_t precision)
void coshrat(PRAT* px, uint32_t radix, int32_t precision)
{
PRAT tmpx= nullptr;
PRAT tmpx = nullptr;
(*px)->pp->sign = 1;
(*px)->pq->sign = 1;
if ( rat_ge( *px, rat_one, precision) )
{
DUPRAT(tmpx,*px);
if (rat_ge(*px, rat_one, precision))
{
DUPRAT(tmpx, *px);
exprat(px, radix, precision);
tmpx->pp->sign *= -1;
exprat(&tmpx, radix, precision);
addrat( px, tmpx, precision);
divrat( px, rat_two, precision);
destroyrat( tmpx );
}
addrat(px, tmpx, precision);
divrat(px, rat_two, precision);
destroyrat(tmpx);
}
else
{
_coshrat( px, radix, precision);
}
{
_coshrat(px, radix, precision);
}
// Since *px might be epsilon below 1 due to TRIMIT
// we need this trick here.
if ( rat_lt(*px, rat_one, precision) )
{
DUPRAT(*px,rat_one);
}
if (rat_lt(*px, rat_one, precision))
{
DUPRAT(*px, rat_one);
}
}
//-----------------------------------------------------------------------------
@@ -214,17 +211,16 @@ void coshrat( PRAT *px, uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
void tanhrat( PRAT *px, uint32_t radix, int32_t precision)
void tanhrat(PRAT* px, uint32_t radix, int32_t precision)
{
PRAT ptmp= nullptr;
PRAT ptmp = nullptr;
DUPRAT(ptmp,*px);
DUPRAT(ptmp, *px);
sinhrat(px, radix, precision);
coshrat(&ptmp, radix, precision);
mulnumx(&((*px)->pp),ptmp->pq);
mulnumx(&((*px)->pq),ptmp->pp);
mulnumx(&((*px)->pp), ptmp->pq);
mulnumx(&((*px)->pq), ptmp->pp);
destroyrat(ptmp);
}