Skip to content

Commit

Permalink
preliminary numerics cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
grzegorzmazur committed Nov 20, 2017
1 parent a03e2ee commit 5abc060
Show file tree
Hide file tree
Showing 8 changed files with 584 additions and 844 deletions.
8 changes: 4 additions & 4 deletions cyacas/libyacas/include/yacas/anumber.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,16 @@ typedef signed long PlatSignedDoubleWord;
class ANumber : public std::vector<PlatWord>
{
public:
ANumber(const char* aString,int aPrecision,int aBase=10);
ANumber(int aPrecision);
ANumber(const std::string& aString,int aPrecision,int aBase=10);
explicit ANumber(int aPrecision);
//TODO the properties of this object are set in the member initialization list, but then immediately overwritten by the CopyFrom. We can make this slightly cleaner by only initializing once.
inline ANumber(const ANumber& aOther) : iExp(0),iNegative(false),iPrecision(0),iTensExp(0)
{
CopyFrom(aOther);
}
void CopyFrom(const ANumber& aOther);
bool ExactlyEqual(const ANumber& aOther);
void SetTo(const char* aString,int aBase=10);
void SetTo(const std::string& aString,int aBase=10);
int Precision() const;
void SetPrecision(int aPrecision) {iPrecision = aPrecision;}
void ChangePrecision(int aPrecision);
Expand Down Expand Up @@ -82,7 +82,7 @@ int WordDigits(int aPrecision, int aBase);

// Operations on ANumber.
void Negate(ANumber& aNumber);
void ANumberToString(LispString& aResult, ANumber& aNumber, int aBase, bool aForceFloat=false);
void ANumberToString(std::string& aResult, ANumber& aNumber, int aBase, bool aForceFloat=false);
void Add(ANumber& aResult, ANumber& a1, ANumber& a2);
void Subtract(ANumber& aResult, ANumber& a1, ANumber& a2);
void Multiply(ANumber& aResult, ANumber& a1, ANumber& a2);
Expand Down
85 changes: 14 additions & 71 deletions cyacas/libyacas/include/yacas/numbers.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,7 @@

#include "lispenvironment.h"

/// Whether the numeric library supports 1.0E-10 and such.
int NumericSupportForMantissa();

LispObject* GcdInteger(LispObject* int1, LispObject* int2, LispEnvironment& aEnvironment);

LispObject* SinFloat(LispObject* int1, LispEnvironment& aEnvironment,int aPrecision);
LispObject* CosFloat(LispObject* int1, LispEnvironment& aEnvironment,int aPrecision);
LispObject* TanFloat(LispObject* int1, LispEnvironment& aEnvironment,int aPrecision);
LispObject* ArcSinFloat(LispObject* int1, LispEnvironment& aEnvironment,int aPrecision);
LispObject* ExpFloat(LispObject* int1, LispEnvironment& aEnvironment,int aPrecision);
LispObject* LnFloat(LispObject* int1, LispEnvironment& aEnvironment,int aPrecision);

LispObject* SqrtFloat(LispObject* int1, LispEnvironment& aEnvironment,int aPrecision);
LispObject* ModFloat( LispObject* int1, LispObject* int2, LispEnvironment& aEnvironment,
int aPrecision);
Expand All @@ -25,64 +14,41 @@ LispObject* ShiftLeft( LispObject* int1, LispObject* int2, LispEnvironment& aEnv
LispObject* ShiftRight( LispObject* int1, LispObject* int2, LispEnvironment& aEnvironment,int aPrecision);
LispObject* LispFactorial(LispObject* int1, LispEnvironment& aEnvironment,int aPrecision);



// methods generally useful for all numeric libraries
const unsigned GUARD_BITS = 8; // we leave this many guard bits untruncated in various situations when we need to truncate precision by hand

const long DIST_BITS = 1; // at least this many bits of difference - used in precision tracking

/// DIST(x, y) returns 1 if abs(x-y) >= DIST_BITS. See documentation for precision tracking.
template<class T> inline T DIST(T x, T y) { return (x>=y+DIST_BITS || y>=x+DIST_BITS) ? 0 : 1; }


/** Base number class.
*/


class ANumber;



/// Main class for multiple-precision arithmetic.
/// All calculations are done at given precision. Integers grow as needed, floats don't grow beyond given precision.
class BigNumber {
public: //constructors
BigNumber(const char* aString,int aPrecision,int aBase=10);
BigNumber(const std::string& aString,int aPrecision,int aBase=10);
/// copy constructor
BigNumber(const BigNumber& aOther);
explicit BigNumber(const BigNumber& aOther);
// no constructors from int or double to avoid automatic conversions
BigNumber(int aPrecision = 20);
//explicit BigNumber(int aPrecision = 20);
~BigNumber();
// assign from another number
void SetTo(const BigNumber& aOther);
// assign from string, precision in base digits
void SetTo(const char* aString,int aPrecision,int aBase=10);
// assign from a platform type
void SetTo(long value);
inline void SetTo(int value) { SetTo(long(value)); };
void SetTo(double value);
public: // Convert back to other types

BigNumber& operator = (const BigNumber&);

/// ToString : return string representation of number in aResult to given precision (base digits)
void ToString(LispString& aResult, int aPrecision, int aBase=10) const;
void ToString(std::string& aResult, int aPrecision, int aBase=10) const;
/// Give approximate representation as a double number
double Double() const;

public://basic object manipulation
//basic object manipulation
bool Equals(const BigNumber& aOther) const;
bool IsInt() const;
bool IsIntValue() const;
bool IsSmall() const;
void BecomeInt();
void BecomeFloat(int aPrecision=0);
bool LessThan(const BigNumber& aOther) const;
public://arithmetic
//arithmetic
/// Multiply two numbers at given precision and put result in *this
void Multiply(const BigNumber& aX, const BigNumber& aY, int aPrecision);
/** Multiply two numbers, and add to *this (this is useful and generally efficient to implement).
* This is most likely going to be used by internal functions only, using aResult as an accumulator.
*/
void MultiplyAdd(const BigNumber& aX, const BigNumber& aY, int aPrecision);
/// Add two numbers at given precision and return result in *this
void Add(const BigNumber& aX, const BigNumber& aY, int aPrecision);
/// Negate the given number, return result in *this
Expand All @@ -96,13 +62,12 @@ class BigNumber {
/// For debugging purposes, dump internal state of this object into a string
void DumpDebugInfo(std::ostream&) const;

public:
/// assign self to Floor(aX) if possible
void Floor(const BigNumber& aX);
/// set precision (in bits)
void Precision(int aPrecision);

public:/// Bitwise operations, return result in *this.
/// Bitwise operations, return result in *this.
void ShiftLeft( const BigNumber& aX, int aNrToShift);
void ShiftRight( const BigNumber& aX, int aNrToShift);
void BitAnd(const BigNumber& aX, const BigNumber& aY);
Expand All @@ -116,25 +81,16 @@ class BigNumber {
/// Give sign (-1, 0, 1)
int Sign() const;

public:
inline int GetPrecision() const {return iPrecision;};

private:
BigNumber& operator=(const BigNumber& aOther)
{
// copy constructor not written yet, hence the assert
assert(0);
return *this;
}
public:
unsigned iReferenceCount;
private:
int iPrecision;

public:
/// Internal library wrapper starts here.
inline void SetIsInteger(bool aIsInteger) {iType = (aIsInteger ? KInt : KFloat);}
inline void SetIsInteger(bool aIsInteger) {iType = (aIsInteger ? KInt : KFloat);}

private:
int iPrecision;

enum ENumType
{
KInt = 0,
Expand Down Expand Up @@ -170,16 +126,3 @@ unsigned long bits_to_digits(unsigned long abits, unsigned aBase);


#endif













7 changes: 4 additions & 3 deletions cyacas/libyacas/src/anumber.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ ANumber::ANumber(int aPrecision) : iExp(0),iNegative(false),iPrecision(aPrecisio


/* ANumber: Constructor for an arbitrary precision number. */
ANumber::ANumber(const char* aString,int aPrecision,int aBase): iExp(0),iNegative(false),iPrecision(aPrecision),iTensExp(0)
ANumber::ANumber(const std::string& aString,int aPrecision,int aBase): iExp(0),iNegative(false),iPrecision(aPrecision),iTensExp(0)
{
SetPrecision(aPrecision);
SetTo(aString,aBase);
Expand Down Expand Up @@ -120,7 +120,7 @@ int WordDigits(int aPrecision, int aBase)
}


void ANumber::SetTo(const char* aString,int aBase)
void ANumber::SetTo(const std::string& str, int aBase)
{
clear();

Expand All @@ -130,6 +130,7 @@ void ANumber::SetTo(const char* aString,int aBase)
iExp = 0;
iTensExp = 0;

const char* aString = str.c_str();
const char* endptr = aString;

// Parse minus sign
Expand Down Expand Up @@ -538,7 +539,7 @@ bool LessThan(ANumber& a1, ANumber& a2)
}


void ANumberToString(LispString& aResult, ANumber& aNumber, int aBase, bool aForceFloat)
void ANumberToString(std::string& aResult, ANumber& aNumber, int aBase, bool aForceFloat)
{
while (aNumber.size() > 1 && aNumber.back() == 0)
aNumber.pop_back();
Expand Down
14 changes: 4 additions & 10 deletions cyacas/libyacas/src/lispatom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
/// construct an atom from a string representation.
LispObject* LispAtom::New(LispEnvironment& aEnvironment, const std::string& aString)
{
if (IsNumber(aString.c_str(),true)) // check if aString is a number (int or float)
if (IsNumber(aString, true)) // check if aString is a number (int or float)
return new LispNumber(new LispString(aString), aEnvironment.Precision());

return new LispAtom(aEnvironment.HashTable().LookUp(aString));
Expand Down Expand Up @@ -143,21 +143,15 @@ BigNumber* LispNumber::Number(int aBasePrecision)
RefPtr<LispString> str;
str = iString;
// aBasePrecision is in digits, not in bits, ok
iNumber = new BigNumber(str->c_str(), aBasePrecision, BASE10);
iNumber = new BigNumber(*str, aBasePrecision, BASE10);
}

// check if the BigNumber object has enough precision, if not, extend it
// (applies only to floats). Note that iNumber->GetPrecision() might be < 0
else if (!iNumber->IsInt() && iNumber->GetPrecision() < (int)digits_to_bits(aBasePrecision, BASE10))
{
if (iString)
{// have string representation, can extend precision
iNumber->SetTo(iString->c_str(),aBasePrecision, BASE10);
}
else
{
// do not have string representation, cannot extend precision!
}
if (iString) // have string representation, can extend precision
iNumber = new BigNumber(*iString,aBasePrecision, BASE10);
}
return iNumber;
}
Expand Down
4 changes: 2 additions & 2 deletions cyacas/libyacas/src/mathcommands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ static void InternalSetVar(LispEnvironment& aEnvironment, int aStackTop, bool aM
varstring = ARGUMENT(1)->String();
}
CheckArg(varstring, 1, aEnvironment, aStackTop);
CheckArg(!IsNumber(varstring->c_str(), true), 1, aEnvironment, aStackTop);
CheckArg(!IsNumber(*varstring, true), 1, aEnvironment, aStackTop);

LispPtr result;
InternalEval(aEnvironment, result, ARGUMENT(2));
Expand Down Expand Up @@ -1573,7 +1573,7 @@ void LispFindFile(LispEnvironment& aEnvironment,int aStackTop)
const std::string oper = InternalUnstringify(*orig);

const std::string path =
InternalFindFile(oper.c_str(), aEnvironment.iInputDirectories);
InternalFindFile(oper, aEnvironment.iInputDirectories);

RESULT = LispAtom::New(aEnvironment, stringify(path));
}
Expand Down
2 changes: 1 addition & 1 deletion cyacas/libyacas/src/mathcommands2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ void LispCharString(LispEnvironment& aEnvironment, int aStackTop)
{
const LispString* str = ARGUMENT(1)->String();
CheckArg(str, 2, aEnvironment, aStackTop);
CheckArg(IsNumber(str->c_str(), false), 2, aEnvironment, aStackTop);
CheckArg(IsNumber(*str, false), 2, aEnvironment, aStackTop);
int asciiCode = InternalAsciiToInt(*str);

char ascii[4];
Expand Down

0 comments on commit 5abc060

Please sign in to comment.