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

View file

@ -313,42 +313,40 @@ void _mulnum( NUMBER *pa, NUMBER b, uint32_t radix)
void remnum( NUMBER *pa, NUMBER b, uint32_t radix) void remnum( NUMBER *pa, NUMBER b, uint32_t radix)
{ {
NUMBER tmp; // tmp is the working remainder. optional<NUMBER> tmp; // tmp is the working remainder.
NUMBER lasttmp; // lasttmp is the last remainder which worked. optional<NUMBER> lasttmp; // lasttmp is the last remainder which worked.
// Once *pa is less than b, *pa is the remainder. // Once *pa is less than b, *pa is the remainder.
while ( !lessnum( *pa, b ) ) while ( !lessnum( *pa, b ) )
{ {
DUPNUM( tmp, b ); if ( lessnum( *tmp, *pa ) )
if ( lessnum( tmp, *pa ) )
{ {
// Start off close to the right answer for subtraction. // Start off close to the right answer for subtraction.
tmp.exp = (*pa).cdigit+(*pa).exp - tmp.cdigit; tmp->exp = (*pa).cdigit+(*pa).exp - tmp->cdigit;
if ( MSD(*pa) <= MSD(tmp) ) if ( MSD(*pa) <= MSD(*tmp) )
{ {
// Don't take the chance that the numbers are equal. // Don't take the chance that the numbers are equal.
tmp.exp--; tmp->exp--;
} }
} }
lasttmp=i32tonum( 0, radix); 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... // too far, back up...
tmp=lasttmp; tmp=lasttmp;
lasttmp= nullptr; lasttmp= optional<NUMBER>();
} }
// Subtract the working remainder from the remainder holder. // Subtract the working remainder from the remainder holder.
tmp.sign = -1*(*pa).sign; tmp->sign = -1*(*pa).sign;
addnum( pa, tmp, radix); addnum( pa, *tmp, radix);
} }

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->pp=i32tonum( 0L, BASEX ); \
pret->pq=i32tonum( 0L, BASEX ); pret->pq=i32tonum( 0L, BASEX );
#define DESTROYTAYLOR() destroynum( n2 ); \ #define DESTROYTAYLOR() destroyrat( xx );\
destroyrat( xx );\
destroyrat( thisterm );\ destroyrat( thisterm );\
destroyrat( *px );\ destroyrat( *px );\
trimit(&pret, precision);\ 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 _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 nRadixxtonum(_In_ NUMBER a, uint32_t radix, int32_t precision);
extern NUMBER gcd(_In_ NUMBER a, _In_ NUMBER b ); 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. // 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);

View file

@ -41,8 +41,7 @@ static int cbitsofprecision = 0;
#define DUMPRAWRAT(v) #define DUMPRAWRAT(v)
#define DUMPRAWNUM(v) #define DUMPRAWNUM(v)
#define READRAWRAT(v) createrat(v); DUPNUM((v)->pp,(&(init_p_##v))); \ #define READRAWRAT(v) createrat(v);
DUPNUM((v)->pq,(&(init_q_##v)));
#define READRAWNUM(v) DUPNUM(v,(&(init_##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_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; 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. // 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. // 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); 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 ) void _readconstants( void )
{ {
READRAWNUM(num_one);
READRAWNUM(num_two);
READRAWNUM(num_five);
READRAWNUM(num_six);
READRAWNUM(num_ten);
READRAWRAT(pt_eight_five); READRAWRAT(pt_eight_five);
READRAWRAT(rat_six); READRAWRAT(rat_six);
READRAWRAT(rat_two); READRAWRAT(rat_two);

View file

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