Use std::optional for previously nullable types

This commit is contained in:
fwcd 2019-04-09 21:54:32 +02:00
commit d1ba3540e3
6 changed files with 89 additions and 115 deletions

View file

@ -262,9 +262,9 @@ void _divnumx( NUMBER *pa, NUMBER b, int32_t precision)
{
NUMBER a; // a is the dereferenced number pointer from *pa
NUMBER c; // c will contain the result.
NUMBER lasttmp; // lasttmp allows a backup when the algorithm
optional<NUMBER> lasttmp; // lasttmp allows a backup when the algorithm
// guesses one bit too far.
NUMBER tmp; // current guess being worked on for divide.
optional<NUMBER> tmp; // current guess being worked on for divide.
NUMBER rem; // remainder after applying guess.
int32_t cdigits; // count of digits for answer.
vector<MANTTYPE>::iterator ptrc; // ptrc is an iterator pointing to the mantissa of c.
@ -306,24 +306,22 @@ void _divnumx( NUMBER *pa, NUMBER b, int32_t precision)
while ( !lessnum( rem, b ) )
{
digit = 1;
DUPNUM( tmp, b );
lasttmp=i32tonum( 0, BASEX );
while ( lessnum( tmp, rem ) )
while ( lessnum( *tmp, rem ) )
{
DUPNUM(lasttmp,tmp);
addnum( &tmp, tmp, BASEX );
addnum( &*tmp, *tmp, BASEX );
digit *= 2;
}
if ( lessnum( rem, tmp ) )
if ( lessnum( rem, *tmp ) )
{
// too far, back up...
digit /= 2;
tmp=lasttmp;
lasttmp= nullptr;
lasttmp= optional<NUMBER>();
}
tmp.sign *= -1;
addnum( &rem, tmp, BASEX );
tmp->sign *= -1;
addnum( &rem, *tmp, BASEX );
*ptrc |= digit;
}
rem.exp++;

View file

@ -339,7 +339,7 @@ NUMBER nRadixxtonum( _In_ NUMBER a, uint32_t radix, int32_t precision)
NUMBER numtonRadixx(_In_ NUMBER a, uint32_t radix)
{
NUMBER pnumret = i32tonum(0, BASEX); // pnumret is the number in internal form.
NUMBER numret = i32tonum(0, BASEX); // numret is the number in internal form.
NUMBER num_radix = i32tonum(radix, BASEX);
// Digits are in reverse order, back over them LSD first.
@ -350,25 +350,25 @@ NUMBER numtonRadixx(_In_ NUMBER a, uint32_t radix)
int32_t idigit; // idigit is the iterate of digits in a.
for ( idigit = 0; idigit < a.cdigit; idigit++ )
{
mulnumx( &pnumret, num_radix);
mulnumx( &numret, num_radix);
// WARNING:
// This should just smack in each digit into a 'special' thisdigit.
// and not do the overhead of recreating the number type each time.
thisdigit = i32tonum( *(--ptrdigit), BASEX );
addnum( &pnumret, thisdigit, BASEX );
addnum( &numret, thisdigit, BASEX );
}
// Calculate the exponent of the external base for scaling.
numpowi32x( &num_radix, a.exp );
// ... and scale the result.
mulnumx( &pnumret, num_radix);
mulnumx( &numret, num_radix);
// And propagate the sign.
pnumret.sign = a.sign;
numret.sign = a.sign;
return( pnumret );
return( numret );
}
//-----------------------------------------------------------------------------
@ -412,13 +412,13 @@ PRAT StringToRat(bool mantissaIsNegative, wstring_view mantissa, bool exponentIs
else
{
// Mantissa specified, convert to number form.
NUMBER pnummant = StringToNumber(mantissa, radix, precision);
if (pnummant == nullptr)
optional<NUMBER> pnummant = StringToNumber(mantissa, radix, precision);
if (!pnummant.has_value())
{
return nullptr;
}
resultRat = numtorat(pnummant, radix);
resultRat = numtorat(*pnummant, radix);
// convert to rational form, and cleanup.
}
@ -429,14 +429,14 @@ PRAT StringToRat(bool mantissaIsNegative, wstring_view mantissa, bool exponentIs
// Exponent specified, convert to number form.
// Don't use native stuff, as it is restricted in the bases it can
// handle.
NUMBER numExp = StringToNumber(exponent, radix, precision);
if (numExp == nullptr)
optional<NUMBER> numExp = StringToNumber(exponent, radix, precision);
if (!numExp.has_value())
{
return nullptr;
}
// Convert exponent number form to native integral form, and cleanup.
expt = numtoi32(numExp, radix);
expt = numtoi32(*numExp, radix);
}
// Convert native integral exponent form to rational multiplier form.
@ -602,16 +602,16 @@ wchar_t NormalizeCharDigit(wchar_t c, uint32_t radix)
return c;
}
NUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precision)
optional<NUMBER> StringToNumber(wstring_view numberString, uint32_t radix, int32_t precision)
{
int32_t expSign = 1L; // expSign is exponent sign ( +/- 1 )
int32_t expValue = 0L; // expValue is exponent mantissa, should be unsigned
NUMBER pnumret;
createnum(pnumret, static_cast<uint32_t>(numberString.length()));
pnumret.sign = 1L;
pnumret.cdigit = 0;
pnumret.exp = 0;
NUMBER numret;
createnum(numret, static_cast<uint32_t>(numberString.length()));
numret.sign = 1L;
numret.cdigit = 0;
numret.exp = 0;
int32_t imant = static_cast<int32_t>(numberString.length() - 1);
uint8_t state = START; // state is the state of the input state machine.
@ -652,7 +652,7 @@ NUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precisi
switch (state)
{
case MANTS:
pnumret.sign = (curChar == L'-') ? -1 : 1;
numret.sign = (curChar == L'-') ? -1 : 1;
break;
case EXPSZ:
case EXPS:
@ -676,7 +676,7 @@ NUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precisi
}
break;
case LD:
pnumret.exp++;
numret.exp++;
[[fallthrough]];
case DD:
{
@ -685,9 +685,9 @@ NUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precisi
size_t pos = DIGITS.find(curChar);
if (pos != wstring_view::npos && pos < static_cast<size_t>(radix))
{
pnumret.mant[imant--] = static_cast<MANTTYPE>(pos);
pnumret.exp--;
pnumret.cdigit++;
numret.mant[imant--] = static_cast<MANTTYPE>(pos);
numret.exp--;
numret.cdigit++;
}
else
{
@ -696,7 +696,7 @@ NUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precisi
}
break;
case DZ:
pnumret.exp--;
numret.exp--;
break;
case LZ:
case LZDP:
@ -707,30 +707,33 @@ NUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precisi
if (state == DZ || state == EXPDZ)
{
pnumret.cdigit = 1;
pnumret.exp = 0;
pnumret.sign = 1;
numret.cdigit = 1;
numret.exp = 0;
numret.sign = 1;
}
else
{
while (pnumret.cdigit < static_cast<int32_t>(numberString.length()))
while (numret.cdigit < static_cast<int32_t>(numberString.length()))
{
pnumret.cdigit++;
pnumret.exp--;
numret.cdigit++;
numret.exp--;
}
pnumret.exp += expSign * expValue;
numret.exp += expSign * expValue;
}
optional<NUMBER> optnumret;
// If we don't have a number, clear our result.
if (pnumret.cdigit == 0)
if (numret.cdigit == 0)
{
pnumret = nullptr;
optnumret = {};
}
stripzeroesnum(pnumret, precision);
stripzeroesnum(numret, precision);
return pnumret;
optnumret = numret;
return optnumret;
}
//-----------------------------------------------------------------------------
@ -797,30 +800,30 @@ NUMBER i32tonum( int32_t ini32, uint32_t radix)
{
vector<MANTTYPE>::iterator pmant;
NUMBER pnumret;
NUMBER numret;
createnum( pnumret, MAX_LONG_SIZE );
pmant = pnumret.mant.begin();
pnumret.cdigit = 0;
pnumret.exp = 0;
createnum( numret, MAX_LONG_SIZE );
pmant = numret.mant.begin();
numret.cdigit = 0;
numret.exp = 0;
if ( ini32 < 0 )
{
pnumret.sign = -1;
numret.sign = -1;
ini32 *= -1;
}
else
{
pnumret.sign = 1;
numret.sign = 1;
}
do {
*pmant = (MANTTYPE)(ini32 % radix);
++pmant;
ini32 /= radix;
pnumret.cdigit++;
numret.cdigit++;
} while ( ini32 );
return( pnumret );
return( numret );
}
//-----------------------------------------------------------------------------
@ -841,21 +844,21 @@ NUMBER i32tonum( int32_t ini32, uint32_t radix)
NUMBER Ui32tonum(uint32_t ini32, uint32_t radix)
{
vector<MANTTYPE>::iterator pmant;
NUMBER pnumret;
NUMBER numret;
createnum( pnumret, MAX_LONG_SIZE );
pmant = pnumret.mant.begin();
pnumret.cdigit = 0;
pnumret.exp = 0;
pnumret.sign = 1;
createnum( numret, MAX_LONG_SIZE );
pmant = numret.mant.begin();
numret.cdigit = 0;
numret.exp = 0;
numret.sign = 1;
do {
*pmant++ = (MANTTYPE)(ini32 % radix);
ini32 /= radix;
pnumret.cdigit++;
numret.cdigit++;
} while ( ini32 );
return( pnumret );
return( numret );
}
@ -1090,25 +1093,25 @@ wstring NumberToString(_Inout_ NUMBER& pnum, int format, uint32_t radix, int32_t
// If there is a chance a round has to occur, round.
// - if number is zero no rounding
// - if number of digits is less than the maximum output no rounding
NUMBER round;
optional<NUMBER> round;
if (!zernum(pnum) && (pnum.cdigit >= precision || (length - exponent > precision && exponent >= -MAX_ZEROS_AFTER_DECIMAL)))
{
// Otherwise round.
round = i32tonum(radix, radix);
divnum(&round, num_two, radix, precision);
divnum(&*round, num_two, radix, precision);
// Make round number exponent one below the LSD for the number.
if (exponent > 0 || format == FMT_FLOAT)
{
round.exp = pnum.exp + pnum.cdigit - round.cdigit - precision;
round->exp = pnum.exp + pnum.cdigit - round->cdigit - precision;
}
else
{
round.exp = pnum.exp + pnum.cdigit - round.cdigit - precision - exponent;
round->exp = pnum.exp + pnum.cdigit - round->cdigit - precision - exponent;
length = precision + exponent;
}
round.sign = pnum.sign;
round->sign = pnum.sign;
}
if (format == FMT_FLOAT)
@ -1118,7 +1121,7 @@ wstring NumberToString(_Inout_ NUMBER& pnum, int format, uint32_t radix, int32_t
{
if (exponent >= -MAX_ZEROS_AFTER_DECIMAL)
{
round.exp -= exponent;
round->exp -= exponent;
length = precision + exponent;
}
else
@ -1132,14 +1135,14 @@ wstring NumberToString(_Inout_ NUMBER& pnum, int format, uint32_t radix, int32_t
{
// Minimum loss of precision occurs with listing leading zeros
// if we need to make room for zeros sacrifice some digits.
round.exp -= exponent;
round->exp -= exponent;
}
}
if (round != nullptr)
if (round.has_value())
{
addnum(&pnum, round, radix);
int32_t offset = (pnum.cdigit + pnum.exp) - (round.cdigit + round.exp);
addnum(&pnum, *round, radix);
int32_t offset = (pnum.cdigit + pnum.exp) - (round->cdigit + round->exp);
if (stripzeroesnum(pnum, offset))
{
// WARNING: nesting/recursion, too much has been changed, need to

View file

@ -313,42 +313,40 @@ void _mulnum( NUMBER *pa, NUMBER b, uint32_t radix)
void remnum( NUMBER *pa, NUMBER b, uint32_t radix)
{
NUMBER tmp; // tmp is the working remainder.
NUMBER lasttmp; // lasttmp is the last remainder which worked.
optional<NUMBER> tmp; // tmp is the working remainder.
optional<NUMBER> lasttmp; // lasttmp is the last remainder which worked.
// Once *pa is less than b, *pa is the remainder.
while ( !lessnum( *pa, b ) )
{
DUPNUM( tmp, b );
if ( lessnum( tmp, *pa ) )
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--;
tmp->exp--;
}
}
lasttmp=i32tonum( 0, radix);
while ( lessnum( tmp, *pa ) )
while ( lessnum( *tmp, *pa ) )
{
DUPNUM( lasttmp, tmp );
addnum( &tmp, tmp, radix);
addnum( &*tmp, *tmp, radix);
}
if ( lessnum( *pa, tmp ) )
if ( lessnum( *pa, *tmp ) )
{
// too far, back up...
tmp=lasttmp;
lasttmp= nullptr;
lasttmp= optional<NUMBER>();
}
// 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);
}

View file

@ -244,8 +244,7 @@ std::copy((x)->pp.mant.begin() + trim, (x)->pp.mant.begin() + (x)->pp.cdigit, (x
pret->pp=i32tonum( 0L, BASEX ); \
pret->pq=i32tonum( 0L, BASEX );
#define DESTROYTAYLOR() destroynum( n2 ); \
destroyrat( xx );\
#define DESTROYTAYLOR() destroyrat( xx );\
destroyrat( thisterm );\
destroyrat( *px );\
trimit(&pret, precision);\
@ -322,7 +321,7 @@ uint64_t rattoUi64(_In_ PRAT prat, uint32_t radix, int32_t precision);
extern NUMBER _createnum(_In_ uint32_t size ); // returns an empty number structure with size digits
extern NUMBER nRadixxtonum(_In_ NUMBER a, uint32_t radix, int32_t precision);
extern NUMBER gcd(_In_ NUMBER a, _In_ NUMBER b );
extern NUMBER StringToNumber(std::wstring_view numberString, uint32_t radix, int32_t precision); // takes a text representation of a number and returns a number.
extern std::optional<NUMBER> StringToNumber(std::wstring_view numberString, uint32_t radix, int32_t precision); // takes a text representation of a number and returns a number.
// takes a text representation of a number as a mantissa with sign and an exponent with sign.
extern PRAT StringToRat(bool mantissaIsNegative, std::wstring_view mantissa, bool exponentIsNegative, std::wstring_view exponent, uint32_t radix, int32_t precision);

View file

@ -41,8 +41,7 @@ static int cbitsofprecision = 0;
#define DUMPRAWRAT(v)
#define DUMPRAWNUM(v)
#define READRAWRAT(v) createrat(v); DUPNUM((v)->pp,(&(init_p_##v))); \
DUPNUM((v)->pq,(&(init_q_##v)));
#define READRAWRAT(v) createrat(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); }
@ -139,25 +138,6 @@ void ChangeConstants(uint32_t radix, int32_t precision)
{
g_ftrueinfinite = false;
INIT_AND_DUMP_RAW_NUM_IF_NULL(num_one, 1L);
INIT_AND_DUMP_RAW_NUM_IF_NULL(num_two, 2L);
INIT_AND_DUMP_RAW_NUM_IF_NULL(num_five, 5L);
INIT_AND_DUMP_RAW_NUM_IF_NULL(num_six, 6L);
INIT_AND_DUMP_RAW_NUM_IF_NULL(num_ten, 10L);
INIT_AND_DUMP_RAW_RAT_IF_NULL(rat_six, 6L);
INIT_AND_DUMP_RAW_RAT_IF_NULL(rat_two, 2L);
INIT_AND_DUMP_RAW_RAT_IF_NULL(rat_zero, 0L);
INIT_AND_DUMP_RAW_RAT_IF_NULL(rat_one, 1L);
INIT_AND_DUMP_RAW_RAT_IF_NULL(rat_neg_one, -1L);
INIT_AND_DUMP_RAW_RAT_IF_NULL(rat_ten, 10L);
INIT_AND_DUMP_RAW_RAT_IF_NULL(rat_word, 0xffff);
INIT_AND_DUMP_RAW_RAT_IF_NULL(rat_word, 0xff);
INIT_AND_DUMP_RAW_RAT_IF_NULL(rat_400, 400);
INIT_AND_DUMP_RAW_RAT_IF_NULL(rat_360, 360);
INIT_AND_DUMP_RAW_RAT_IF_NULL(rat_200, 200);
INIT_AND_DUMP_RAW_RAT_IF_NULL(rat_180, 180);
INIT_AND_DUMP_RAW_RAT_IF_NULL(rat_max_exp, 100000);
// 3248, is the max number for which calc is able to compute factorial, after that it is unable to compute due to overflow.
// Hence restricted factorial range as at most 3248.Beyond that calc will throw overflow error immediately.
INIT_AND_DUMP_RAW_RAT_IF_NULL(rat_max_fact, 3249);
@ -615,11 +595,6 @@ void _dumprawnum(const wchar_t *varname, NUMBER num, wostream& out)
void _readconstants( void )
{
READRAWNUM(num_one);
READRAWNUM(num_two);
READRAWNUM(num_five);
READRAWNUM(num_six);
READRAWNUM(num_ten);
READRAWRAT(pt_eight_five);
READRAWRAT(rat_six);
READRAWRAT(rat_two);

View file

@ -25,6 +25,7 @@
#include <array>
#include <string_view>
#include <future>
#include <optional>
#include "winerror_cross_platform.h"
#include "sal_cross_platform.h"