mirror of
https://github.com/Microsoft/calculator.git
synced 2025-08-22 14:13:30 -07:00
Use std::optional for previously nullable types
This commit is contained in:
parent
ceb4b3c9b9
commit
d1ba3540e3
6 changed files with 89 additions and 115 deletions
|
@ -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++;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <array>
|
||||
#include <string_view>
|
||||
#include <future>
|
||||
#include <optional>
|
||||
|
||||
#include "winerror_cross_platform.h"
|
||||
#include "sal_cross_platform.h"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue