CalcEngine: Manage precision internally to Rational and convert functions to operator overrides (#35)
* Convert Rational::Negate to an operator override * Convert Rational::Add to + and += operator overrides. * Convert Rational::Sub to - and -= operator overrides. * Convert Rational::Div and ::Mul to use /, /=, *, *= operator overrides. * Convert Rational::Mod to use %= and % operator overrides * Convert Rational::Rsh and ::Lsh to use >>=, >>, <<=, << operator overrides * Convert Rational::And, ::Or, ::Xor to use &=, &, |=, |, ^=, ^ operator overrides * Convert Rational relational functions to operator overrides * Remove unnecessary precision arguments from Rational class and remove use of explicit Rational constructors in favor of implicit conversions for value types * Remove unnecessary precision variable from RationalMath operations * Replace unnecessary Rational::Not with Xor operation * Remove unnecessary Rational::IsZero() in favor of == 0 comparisons * Fix rounding issues in ratpak that result from using large precisions. * Move assignment stmt out of IsCurrentTooBigForTrig
This commit is contained in:
parent
424891516f
commit
0cb5e9bae0
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "Header Files/Rational.h"
|
#include "Header Files/Rational.h"
|
||||||
#include "Header Files/scimath.h"
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -50,12 +49,12 @@ namespace CalcEngine
|
|||||||
destroyrat(pr);
|
destroyrat(pr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational::Rational(uint64_t ui, int32_t precision)
|
Rational::Rational(uint64_t ui)
|
||||||
{
|
{
|
||||||
uint32_t hi = HIDWORD(ui);
|
uint32_t hi = HIDWORD(ui);
|
||||||
uint32_t lo = LODWORD(ui);
|
uint32_t lo = LODWORD(ui);
|
||||||
|
|
||||||
Rational temp = Rational{ hi }.Lsh(32, precision).Or(lo, precision);
|
Rational temp = (Rational{ hi } << 32) | lo;
|
||||||
|
|
||||||
m_p = Number{ temp.P() };
|
m_p = Number{ temp.P() };
|
||||||
m_q = Number{ temp.Q() };
|
m_q = Number{ temp.Q() };
|
||||||
@ -86,19 +85,19 @@ namespace CalcEngine
|
|||||||
return m_q;
|
return m_q;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational Rational::Negate() const
|
Rational Rational::operator-() const
|
||||||
{
|
{
|
||||||
return Rational{ Number{ -1 * m_p.Sign(), m_p.Exp(), m_p.Mantissa() }, m_q};
|
return Rational{ Number{ -1 * m_p.Sign(), m_p.Exp(), m_p.Mantissa() }, m_q };
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational Rational::Add(Rational const& rhs, int32_t precision) const
|
Rational& Rational::operator+=(Rational const& rhs)
|
||||||
{
|
{
|
||||||
PRAT lhsRat = this->ToPRAT();
|
PRAT lhsRat = this->ToPRAT();
|
||||||
PRAT rhsRat = rhs.ToPRAT();
|
PRAT rhsRat = rhs.ToPRAT();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
addrat(&lhsRat, rhsRat, precision);
|
addrat(&lhsRat, rhsRat, RATIONAL_PRECISION);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
@ -108,20 +107,20 @@ namespace CalcEngine
|
|||||||
throw(error);
|
throw(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational result = Rational{ lhsRat };
|
*this = Rational{ lhsRat };
|
||||||
destroyrat(lhsRat);
|
destroyrat(lhsRat);
|
||||||
|
|
||||||
return result;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational Rational::Sub(Rational const& rhs, int32_t precision) const
|
Rational& Rational::operator-=(Rational const& rhs)
|
||||||
{
|
{
|
||||||
PRAT lhsRat = this->ToPRAT();
|
PRAT lhsRat = this->ToPRAT();
|
||||||
PRAT rhsRat = rhs.ToPRAT();
|
PRAT rhsRat = rhs.ToPRAT();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
subrat(&lhsRat, rhsRat, precision);
|
subrat(&lhsRat, rhsRat, RATIONAL_PRECISION);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
@ -131,20 +130,20 @@ namespace CalcEngine
|
|||||||
throw(error);
|
throw(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational result = Rational{ lhsRat };
|
*this = Rational{ lhsRat };
|
||||||
destroyrat(lhsRat);
|
destroyrat(lhsRat);
|
||||||
|
|
||||||
return result;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational Rational::Mul(Rational const& rhs, int32_t precision) const
|
Rational& Rational::operator*=(Rational const& rhs)
|
||||||
{
|
{
|
||||||
PRAT lhsRat = this->ToPRAT();
|
PRAT lhsRat = this->ToPRAT();
|
||||||
PRAT rhsRat = rhs.ToPRAT();
|
PRAT rhsRat = rhs.ToPRAT();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
mulrat(&lhsRat, rhsRat, precision);
|
mulrat(&lhsRat, rhsRat, RATIONAL_PRECISION);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
@ -154,20 +153,20 @@ namespace CalcEngine
|
|||||||
throw(error);
|
throw(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational result = Rational{ lhsRat };
|
*this = Rational{ lhsRat };
|
||||||
destroyrat(lhsRat);
|
destroyrat(lhsRat);
|
||||||
|
|
||||||
return result;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational Rational::Div(Rational const& rhs, int32_t precision) const
|
Rational& Rational::operator/=(Rational const& rhs)
|
||||||
{
|
{
|
||||||
PRAT lhsRat = this->ToPRAT();
|
PRAT lhsRat = this->ToPRAT();
|
||||||
PRAT rhsRat = rhs.ToPRAT();
|
PRAT rhsRat = rhs.ToPRAT();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
divrat(&lhsRat, rhsRat, precision);
|
divrat(&lhsRat, rhsRat, RATIONAL_PRECISION);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
@ -177,13 +176,13 @@ namespace CalcEngine
|
|||||||
throw(error);
|
throw(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational result = Rational{ lhsRat };
|
*this = Rational{ lhsRat };
|
||||||
destroyrat(lhsRat);
|
destroyrat(lhsRat);
|
||||||
|
|
||||||
return result;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational Rational::Mod(Rational const& rhs) const
|
Rational& Rational::operator%=(Rational const& rhs)
|
||||||
{
|
{
|
||||||
PRAT lhsRat = this->ToPRAT();
|
PRAT lhsRat = this->ToPRAT();
|
||||||
PRAT rhsRat = rhs.ToPRAT();
|
PRAT rhsRat = rhs.ToPRAT();
|
||||||
@ -200,20 +199,20 @@ namespace CalcEngine
|
|||||||
throw(error);
|
throw(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational result = Rational{ lhsRat };
|
*this = Rational{ lhsRat };
|
||||||
destroyrat(lhsRat);
|
destroyrat(lhsRat);
|
||||||
|
|
||||||
return result;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational Rational::Lsh(Rational const& rhs, int32_t precision) const
|
Rational& Rational::operator<<=(Rational const& rhs)
|
||||||
{
|
{
|
||||||
PRAT lhsRat = this->ToPRAT();
|
PRAT lhsRat = this->ToPRAT();
|
||||||
PRAT rhsRat = rhs.ToPRAT();
|
PRAT rhsRat = rhs.ToPRAT();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
lshrat(&lhsRat, rhsRat, RATIONAL_BASE, precision);
|
lshrat(&lhsRat, rhsRat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
@ -223,20 +222,20 @@ namespace CalcEngine
|
|||||||
throw(error);
|
throw(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational result = Rational{ lhsRat };
|
*this = Rational{ lhsRat };
|
||||||
destroyrat(lhsRat);
|
destroyrat(lhsRat);
|
||||||
|
|
||||||
return result;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational Rational::Rsh(Rational const& rhs, int32_t precision) const
|
Rational& Rational::operator>>=(Rational const& rhs)
|
||||||
{
|
{
|
||||||
PRAT lhsRat = this->ToPRAT();
|
PRAT lhsRat = this->ToPRAT();
|
||||||
PRAT rhsRat = rhs.ToPRAT();
|
PRAT rhsRat = rhs.ToPRAT();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
rshrat(&lhsRat, rhsRat, RATIONAL_BASE, precision);
|
rshrat(&lhsRat, rhsRat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
@ -246,25 +245,20 @@ namespace CalcEngine
|
|||||||
throw(error);
|
throw(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational result = Rational{ lhsRat };
|
*this = Rational{ lhsRat };
|
||||||
destroyrat(lhsRat);
|
destroyrat(lhsRat);
|
||||||
|
|
||||||
return result;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational Rational::Not(Rational const& chopNum, int32_t precision) const
|
Rational& Rational::operator&=(Rational const& rhs)
|
||||||
{
|
|
||||||
return this->Xor(chopNum, precision);
|
|
||||||
}
|
|
||||||
|
|
||||||
Rational Rational::And(Rational const& rhs, int32_t precision) const
|
|
||||||
{
|
{
|
||||||
PRAT lhsRat = this->ToPRAT();
|
PRAT lhsRat = this->ToPRAT();
|
||||||
PRAT rhsRat = rhs.ToPRAT();
|
PRAT rhsRat = rhs.ToPRAT();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
andrat(&lhsRat, rhsRat, RATIONAL_BASE, precision);
|
andrat(&lhsRat, rhsRat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
@ -274,19 +268,19 @@ namespace CalcEngine
|
|||||||
throw(error);
|
throw(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational result = Rational{ lhsRat };
|
*this = Rational{ lhsRat };
|
||||||
destroyrat(lhsRat);
|
destroyrat(lhsRat);
|
||||||
|
|
||||||
return result;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational Rational::Or(Rational const& rhs, int32_t precision) const
|
Rational& Rational::operator|=(Rational const& rhs)
|
||||||
{
|
{
|
||||||
PRAT lhsRat = this->ToPRAT();
|
PRAT lhsRat = this->ToPRAT();
|
||||||
PRAT rhsRat = rhs.ToPRAT();
|
PRAT rhsRat = rhs.ToPRAT();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
orrat(&lhsRat, rhsRat, RATIONAL_BASE, precision);
|
orrat(&lhsRat, rhsRat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
@ -296,19 +290,19 @@ namespace CalcEngine
|
|||||||
throw(error);
|
throw(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational result = Rational{ lhsRat };
|
*this = Rational{ lhsRat };
|
||||||
destroyrat(lhsRat);
|
destroyrat(lhsRat);
|
||||||
|
|
||||||
return result;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational Rational::Xor(Rational const& rhs, int32_t precision) const
|
Rational& Rational::operator^=(Rational const& rhs)
|
||||||
{
|
{
|
||||||
PRAT lhsRat = this->ToPRAT();
|
PRAT lhsRat = this->ToPRAT();
|
||||||
PRAT rhsRat = rhs.ToPRAT();
|
PRAT rhsRat = rhs.ToPRAT();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
xorrat(&lhsRat, rhsRat, RATIONAL_BASE, precision);
|
xorrat(&lhsRat, rhsRat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
@ -318,107 +312,136 @@ namespace CalcEngine
|
|||||||
throw(error);
|
throw(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational result = Rational{ lhsRat };
|
*this = Rational{ lhsRat };
|
||||||
destroyrat(lhsRat);
|
destroyrat(lhsRat);
|
||||||
|
|
||||||
return result;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Rational::IsZero() const
|
Rational operator+(Rational lhs, Rational const& rhs)
|
||||||
{
|
{
|
||||||
return this->P().IsZero();
|
lhs += rhs;
|
||||||
|
return lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Rational::IsLess(Rational const& r, int32_t precision) const
|
Rational operator-(Rational lhs, Rational const& rhs)
|
||||||
{
|
{
|
||||||
PRAT thisRat = this->ToPRAT();
|
lhs -= rhs;
|
||||||
PRAT rRat = r.ToPRAT();
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational operator*(Rational lhs, Rational const& rhs)
|
||||||
|
{
|
||||||
|
lhs *= rhs;
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational operator/(Rational lhs, Rational const& rhs)
|
||||||
|
{
|
||||||
|
lhs /= rhs;
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational operator%(Rational lhs, Rational const& rhs)
|
||||||
|
{
|
||||||
|
lhs %= rhs;
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational operator<<(Rational lhs, Rational const& rhs)
|
||||||
|
{
|
||||||
|
lhs <<= rhs;
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational operator>>(Rational lhs, Rational const& rhs)
|
||||||
|
{
|
||||||
|
lhs >>= rhs;
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational operator&(Rational lhs, Rational const& rhs)
|
||||||
|
{
|
||||||
|
lhs &= rhs;
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational operator|(Rational lhs, Rational const& rhs)
|
||||||
|
{
|
||||||
|
lhs |= rhs;
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational operator^(Rational lhs, Rational const& rhs)
|
||||||
|
{
|
||||||
|
lhs ^= rhs;
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(Rational const& lhs, Rational const& rhs)
|
||||||
|
{
|
||||||
|
PRAT lhsRat = lhs.ToPRAT();
|
||||||
|
PRAT rhsRat = rhs.ToPRAT();
|
||||||
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
result = rat_lt(thisRat, rRat, precision);
|
result = rat_equ(lhsRat, rhsRat, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
{
|
{
|
||||||
destroyrat(thisRat);
|
destroyrat(lhsRat);
|
||||||
destroyrat(rRat);
|
destroyrat(rhsRat);
|
||||||
throw(error);
|
throw(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
destroyrat(thisRat);
|
destroyrat(lhsRat);
|
||||||
destroyrat(rRat);
|
destroyrat(rhsRat);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Rational::IsLessEq(Rational const& r, int32_t precision) const
|
bool operator!=(Rational const& lhs, Rational const& rhs)
|
||||||
{
|
{
|
||||||
PRAT thisRat = this->ToPRAT();
|
return !(lhs == rhs);
|
||||||
PRAT rRat = r.ToPRAT();
|
}
|
||||||
|
|
||||||
|
bool operator<(Rational const& lhs, Rational const& rhs)
|
||||||
|
{
|
||||||
|
PRAT lhsRat = lhs.ToPRAT();
|
||||||
|
PRAT rhsRat = rhs.ToPRAT();
|
||||||
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
result = rat_le(thisRat, rRat, precision);
|
result = rat_lt(lhsRat, rhsRat, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
{
|
{
|
||||||
destroyrat(thisRat);
|
destroyrat(lhsRat);
|
||||||
destroyrat(rRat);
|
destroyrat(rhsRat);
|
||||||
throw(error);
|
throw(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
destroyrat(thisRat);
|
destroyrat(lhsRat);
|
||||||
destroyrat(rRat);
|
destroyrat(rhsRat);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Rational::IsGreaterEq(Rational const& r, int32_t precision) const
|
bool operator>(Rational const& lhs, Rational const& rhs)
|
||||||
{
|
{
|
||||||
PRAT thisRat = this->ToPRAT();
|
return rhs < lhs;
|
||||||
PRAT rRat = r.ToPRAT();
|
|
||||||
|
|
||||||
bool result = false;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
result = rat_ge(thisRat, rRat, precision);
|
|
||||||
}
|
|
||||||
catch (DWORD error)
|
|
||||||
{
|
|
||||||
destroyrat(thisRat);
|
|
||||||
destroyrat(rRat);
|
|
||||||
throw(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
destroyrat(thisRat);
|
|
||||||
destroyrat(rRat);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Rational::IsEq(Rational const& r, int32_t precision) const
|
bool operator<=(Rational const& lhs, Rational const& rhs)
|
||||||
{
|
{
|
||||||
PRAT thisRat = this->ToPRAT();
|
return !(lhs > rhs);
|
||||||
PRAT rRat = r.ToPRAT();
|
}
|
||||||
|
|
||||||
bool result = false;
|
bool operator>=(Rational const& lhs, Rational const& rhs)
|
||||||
try
|
{
|
||||||
{
|
return !(lhs < rhs);
|
||||||
result = rat_equ(thisRat, rRat, precision);
|
|
||||||
}
|
|
||||||
catch (DWORD error)
|
|
||||||
{
|
|
||||||
destroyrat(thisRat);
|
|
||||||
destroyrat(rRat);
|
|
||||||
throw(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
destroyrat(thisRat);
|
|
||||||
destroyrat(rRat);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wstring Rational::ToString(uint32_t radix, NUMOBJ_FMT fmt, int32_t precision) const
|
wstring Rational::ToString(uint32_t radix, NUMOBJ_FMT fmt, int32_t precision) const
|
||||||
@ -441,13 +464,13 @@ namespace CalcEngine
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t Rational::ToUInt64_t(int32_t precision) const
|
uint64_t Rational::ToUInt64_t() const
|
||||||
{
|
{
|
||||||
PRAT rat = this->ToPRAT();
|
PRAT rat = this->ToPRAT();
|
||||||
uint64_t result;
|
uint64_t result;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
result = rattoUlonglong(rat, RATIONAL_BASE, precision);
|
result = rattoUlonglong(rat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
{
|
{
|
||||||
|
@ -95,7 +95,7 @@ CCalcEngine::CCalcEngine(bool fPrecedence, bool fIntegerMode, CalculationManager
|
|||||||
|
|
||||||
m_dwWordBitWidth = DwWordBitWidthFromeNumWidth(m_numwidth);
|
m_dwWordBitWidth = DwWordBitWidthFromeNumWidth(m_numwidth);
|
||||||
|
|
||||||
m_maxTrigonometricNum = RationalMath::Pow(10, 100, m_precision);
|
m_maxTrigonometricNum = RationalMath::Pow(10, 100);
|
||||||
|
|
||||||
SetRadixTypeAndNumWidth(DEC_RADIX, m_numwidth);
|
SetRadixTypeAndNumWidth(DEC_RADIX, m_numwidth);
|
||||||
SettingsChanged();
|
SettingsChanged();
|
||||||
@ -117,8 +117,8 @@ void CCalcEngine::InitChopNumbers()
|
|||||||
assert(m_chopNumbers.size() == m_maxDecimalValueStrings.size());
|
assert(m_chopNumbers.size() == m_maxDecimalValueStrings.size());
|
||||||
for (size_t i = 0; i < m_chopNumbers.size(); i++)
|
for (size_t i = 0; i < m_chopNumbers.size(); i++)
|
||||||
{
|
{
|
||||||
auto maxVal = m_chopNumbers[i].Div(2, m_precision);
|
auto maxVal = m_chopNumbers[i] / 2;
|
||||||
maxVal = RationalMath::Integer(maxVal, m_precision);
|
maxVal = RationalMath::Integer(maxVal);
|
||||||
|
|
||||||
m_maxDecimalValueStrings[i] = maxVal.ToString(10, FMT_FLOAT, m_precision);
|
m_maxDecimalValueStrings[i] = maxVal.ToString(10, FMT_FLOAT, m_precision);
|
||||||
}
|
}
|
||||||
|
@ -318,6 +318,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
|||||||
{
|
{
|
||||||
if (IsCurrentTooBigForTrig())
|
if (IsCurrentTooBigForTrig())
|
||||||
{
|
{
|
||||||
|
m_currentVal = 0;
|
||||||
DisplayError(CALC_E_DOMAIN);
|
DisplayError(CALC_E_DOMAIN);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -382,7 +383,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
|||||||
CheckAndAddLastBinOpToHistory(false);
|
CheckAndAddLastBinOpToHistory(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_lastVal = Rational{};
|
m_lastVal = 0;
|
||||||
|
|
||||||
m_bChangeOp = false;
|
m_bChangeOp = false;
|
||||||
m_precedenceOpCount = m_nTempCom = m_nLastCom = m_nOpCode = m_openParenCount = 0;
|
m_precedenceOpCount = m_nTempCom = m_nLastCom = m_nOpCode = m_openParenCount = 0;
|
||||||
@ -563,12 +564,12 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
|||||||
m_nPrecOp[m_precedenceOpCount++] = 0;
|
m_nPrecOp[m_precedenceOpCount++] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_lastVal = Rational{};
|
m_lastVal = 0;
|
||||||
if (IsBinOpCode(m_nLastCom))
|
if (IsBinOpCode(m_nLastCom))
|
||||||
{
|
{
|
||||||
// We want 1 + ( to start as 1 + (0. Any number you type replaces 0. But if it is 1 + 3 (, it is
|
// We want 1 + ( to start as 1 + (0. Any number you type replaces 0. But if it is 1 + 3 (, it is
|
||||||
// treated as 1 + (3
|
// treated as 1 + (3
|
||||||
m_currentVal = Rational{};
|
m_currentVal = 0;
|
||||||
}
|
}
|
||||||
m_nTempCom = 0;
|
m_nTempCom = 0;
|
||||||
m_nOpCode = 0;
|
m_nOpCode = 0;
|
||||||
@ -691,7 +692,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
|||||||
m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal);
|
m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_currentVal = m_currentVal.Negate();
|
m_currentVal = -(m_currentVal);
|
||||||
|
|
||||||
DisplayNum();
|
DisplayNum();
|
||||||
m_HistoryCollector.AddUnaryOpToHistory(IDC_SIGN, m_bInv, m_angletype);
|
m_HistoryCollector.AddUnaryOpToHistory(IDC_SIGN, m_bInv, m_angletype);
|
||||||
@ -708,7 +709,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Recall immediate memory value.
|
// Recall immediate memory value.
|
||||||
m_currentVal = Rational{ *m_memoryValue };
|
m_currentVal = *m_memoryValue;
|
||||||
}
|
}
|
||||||
CheckAndAddLastBinOpToHistory();
|
CheckAndAddLastBinOpToHistory();
|
||||||
DisplayNum();
|
DisplayNum();
|
||||||
@ -718,7 +719,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
|||||||
{
|
{
|
||||||
/* MPLUS adds m_currentVal to immediate memory and kills the "mem" */
|
/* MPLUS adds m_currentVal to immediate memory and kills the "mem" */
|
||||||
/* indicator if the result is zero. */
|
/* indicator if the result is zero. */
|
||||||
Rational result = m_memoryValue->Add(m_currentVal, m_precision);
|
Rational result = *m_memoryValue + m_currentVal;
|
||||||
m_memoryValue = make_unique<Rational>(TruncateNumForIntMath(result)); // Memory should follow the current int mode
|
m_memoryValue = make_unique<Rational>(TruncateNumForIntMath(result)); // Memory should follow the current int mode
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -727,14 +728,14 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
|||||||
{
|
{
|
||||||
/* MMINUS subtracts m_currentVal to immediate memory and kills the "mem" */
|
/* MMINUS subtracts m_currentVal to immediate memory and kills the "mem" */
|
||||||
/* indicator if the result is zero. */
|
/* indicator if the result is zero. */
|
||||||
Rational result = m_memoryValue->Sub(m_currentVal, m_precision);
|
Rational result = *m_memoryValue - m_currentVal;
|
||||||
m_memoryValue = make_unique<Rational>(TruncateNumForIntMath(result));
|
m_memoryValue = make_unique<Rational>(TruncateNumForIntMath(result));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IDC_STORE:
|
case IDC_STORE:
|
||||||
case IDC_MCLEAR:
|
case IDC_MCLEAR:
|
||||||
m_memoryValue = make_unique<Rational>(wParam == IDC_STORE ? TruncateNumForIntMath(m_currentVal) : Rational{});
|
m_memoryValue = make_unique<Rational>(wParam == IDC_STORE ? TruncateNumForIntMath(m_currentVal) : 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_PI:
|
case IDC_PI:
|
||||||
@ -1002,13 +1003,7 @@ int CCalcEngine::IdcSetAngleTypeDecMode(int idc)
|
|||||||
|
|
||||||
bool CCalcEngine::IsCurrentTooBigForTrig()
|
bool CCalcEngine::IsCurrentTooBigForTrig()
|
||||||
{
|
{
|
||||||
if (m_currentVal.IsGreaterEq(m_maxTrigonometricNum, m_precision))
|
return m_currentVal >= m_maxTrigonometricNum;
|
||||||
{
|
|
||||||
m_currentVal = Rational{};
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CCalcEngine::GetCurrentRadix()
|
int CCalcEngine::GetCurrentRadix()
|
||||||
@ -1048,14 +1043,12 @@ wstring CCalcEngine::GetStringForDisplay(Rational const& rat, uint32_t radix)
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
uint64_t w64Bits = tempRat.ToUInt64_t(m_precision);
|
uint64_t w64Bits = tempRat.ToUInt64_t();
|
||||||
bool fMsb = ((w64Bits >> (m_dwWordBitWidth - 1)) & 1);
|
bool fMsb = ((w64Bits >> (m_dwWordBitWidth - 1)) & 1);
|
||||||
if ((radix == 10) && fMsb)
|
if ((radix == 10) && fMsb)
|
||||||
{
|
{
|
||||||
// If high bit is set, then get the decimal number in negative 2's compl form.
|
// If high bit is set, then get the decimal number in negative 2's compl form.
|
||||||
tempRat = tempRat.Not(m_chopNumbers[m_numwidth], m_precision);
|
tempRat = -((tempRat ^ m_chopNumbers[m_numwidth]) + 1);
|
||||||
tempRat = tempRat.Add(1, m_precision);
|
|
||||||
tempRat = tempRat.Negate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = tempRat.ToString(radix, m_nFE, m_precision);
|
result = tempRat.ToString(radix, m_nFE, m_precision);
|
||||||
|
@ -57,19 +57,18 @@ CalcEngine::Rational CCalcEngine::TruncateNumForIntMath(CalcEngine::Rational con
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Truncate to an integer. Do not round here.
|
// Truncate to an integer. Do not round here.
|
||||||
auto result = RationalMath::Integer(rat, m_precision);
|
auto result = RationalMath::Integer(rat);
|
||||||
|
|
||||||
// Can be converting a dec negative number to Hex/Oct/Bin rep. Use 2's complement form
|
// Can be converting a dec negative number to Hex/Oct/Bin rep. Use 2's complement form
|
||||||
// Check the range.
|
// Check the range.
|
||||||
if (result.IsLess(0, m_precision))
|
if (result < 0)
|
||||||
{
|
{
|
||||||
// if negative make positive by doing a twos complement
|
// if negative make positive by doing a twos complement
|
||||||
result = result.Negate();
|
result = -(result) - 1;
|
||||||
result = result.Sub(1, m_precision);
|
result ^= m_chopNumbers[m_numwidth];
|
||||||
result = result.Not(m_chopNumbers[m_numwidth], m_precision);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = result.And(m_chopNumbers[m_numwidth], m_precision);
|
result &= m_chopNumbers[m_numwidth];
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -84,7 +83,7 @@ void CCalcEngine::DisplayNum(void)
|
|||||||
// called.
|
// called.
|
||||||
//
|
//
|
||||||
if (m_bRecord ||
|
if (m_bRecord ||
|
||||||
!gldPrevious.value.IsEq(m_currentVal, m_precision) ||
|
gldPrevious.value != m_currentVal ||
|
||||||
gldPrevious.precision != m_precision ||
|
gldPrevious.precision != m_precision ||
|
||||||
gldPrevious.radix != m_radix ||
|
gldPrevious.radix != m_radix ||
|
||||||
gldPrevious.nFE != (int)m_nFE ||
|
gldPrevious.nFE != (int)m_nFE ||
|
||||||
|
@ -32,20 +32,18 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
|
|||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
case IDC_CHOP:
|
case IDC_CHOP:
|
||||||
result = m_bInv ? Frac(rat, m_precision) : Integer(rat, m_precision);
|
result = m_bInv ? Frac(rat) : Integer(rat);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Return complement. */
|
/* Return complement. */
|
||||||
case IDC_COM:
|
case IDC_COM:
|
||||||
if (m_radix == 10 && !m_fIntegerMode)
|
if (m_radix == 10 && !m_fIntegerMode)
|
||||||
{
|
{
|
||||||
result = RationalMath::Integer(rat, m_precision);
|
result = -(RationalMath::Integer(rat) + 1);
|
||||||
result = result.Add(1, m_precision);
|
|
||||||
result = result.Negate();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = rat.Xor(m_chopNumbers[m_numwidth], m_precision);
|
result = rat ^ m_chopNumbers[m_numwidth];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -53,14 +51,14 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
|
|||||||
case IDC_ROL:
|
case IDC_ROL:
|
||||||
if (m_fIntegerMode)
|
if (m_fIntegerMode)
|
||||||
{
|
{
|
||||||
result = Integer(rat, m_precision);
|
result = Integer(rat);
|
||||||
|
|
||||||
uint64_t w64Bits = result.ToUInt64_t(m_precision);
|
uint64_t w64Bits = result.ToUInt64_t();
|
||||||
uint64_t msb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
|
uint64_t msb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
|
||||||
w64Bits <<= 1; // LShift by 1
|
w64Bits <<= 1; // LShift by 1
|
||||||
w64Bits |= msb; // Set the prev Msb as the current Lsb
|
w64Bits |= msb; // Set the prev Msb as the current Lsb
|
||||||
|
|
||||||
result = Rational{ w64Bits, m_precision };
|
result = w64Bits;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -68,14 +66,14 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
|
|||||||
case IDC_ROR:
|
case IDC_ROR:
|
||||||
if (m_fIntegerMode)
|
if (m_fIntegerMode)
|
||||||
{
|
{
|
||||||
result = Integer(rat, m_precision);
|
result = Integer(rat);
|
||||||
|
|
||||||
uint64_t w64Bits = result.ToUInt64_t(m_precision);
|
uint64_t w64Bits = result.ToUInt64_t();
|
||||||
uint64_t lsb = ((w64Bits & 0x01) == 1) ? 1 : 0;
|
uint64_t lsb = ((w64Bits & 0x01) == 1) ? 1 : 0;
|
||||||
w64Bits >>= 1; //RShift by 1
|
w64Bits >>= 1; //RShift by 1
|
||||||
w64Bits |= (lsb << (m_dwWordBitWidth - 1));
|
w64Bits |= (lsb << (m_dwWordBitWidth - 1));
|
||||||
|
|
||||||
result = Rational{ w64Bits, m_precision };
|
result = w64Bits;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -85,12 +83,11 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
|
|||||||
// Otherwise, we evaluate it as "X [op] (X * Y%)"
|
// Otherwise, we evaluate it as "X [op] (X * Y%)"
|
||||||
if (m_nOpCode == IDC_MUL || m_nOpCode == IDC_DIV)
|
if (m_nOpCode == IDC_MUL || m_nOpCode == IDC_DIV)
|
||||||
{
|
{
|
||||||
result = rat.Div(100, m_precision);
|
result = rat / 100;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = m_lastVal.Div(100, m_precision);
|
result = rat * (m_lastVal / 100);
|
||||||
result = rat.Mul(result, m_precision);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -98,76 +95,76 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
|
|||||||
case IDC_SIN: /* Sine; normal and arc */
|
case IDC_SIN: /* Sine; normal and arc */
|
||||||
if (!m_fIntegerMode)
|
if (!m_fIntegerMode)
|
||||||
{
|
{
|
||||||
result = m_bInv ? ASin(rat, m_angletype, m_precision) : Sin(rat, m_angletype, m_precision);
|
result = m_bInv ? ASin(rat, m_angletype) : Sin(rat, m_angletype);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_SINH: /* Sine- hyperbolic and archyperbolic */
|
case IDC_SINH: /* Sine- hyperbolic and archyperbolic */
|
||||||
if (!m_fIntegerMode)
|
if (!m_fIntegerMode)
|
||||||
{
|
{
|
||||||
result = m_bInv ? ASinh(rat, m_precision) : Sinh(rat, m_precision);
|
result = m_bInv ? ASinh(rat) : Sinh(rat);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_COS: /* Cosine, follows convention of sine function. */
|
case IDC_COS: /* Cosine, follows convention of sine function. */
|
||||||
if (!m_fIntegerMode)
|
if (!m_fIntegerMode)
|
||||||
{
|
{
|
||||||
result = m_bInv ? ACos(rat, m_angletype, m_precision) : Cos(rat, m_angletype, m_precision);
|
result = m_bInv ? ACos(rat, m_angletype) : Cos(rat, m_angletype);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_COSH: /* Cosine hyperbolic, follows convention of sine h function. */
|
case IDC_COSH: /* Cosine hyperbolic, follows convention of sine h function. */
|
||||||
if (!m_fIntegerMode)
|
if (!m_fIntegerMode)
|
||||||
{
|
{
|
||||||
result = m_bInv ? ACosh(rat, m_precision) : Cosh(rat, m_precision);
|
result = m_bInv ? ACosh(rat) : Cosh(rat);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_TAN: /* Same as sine and cosine. */
|
case IDC_TAN: /* Same as sine and cosine. */
|
||||||
if (!m_fIntegerMode)
|
if (!m_fIntegerMode)
|
||||||
{
|
{
|
||||||
result = m_bInv ? ATan(rat, m_angletype, m_precision) : Tan(rat, m_angletype, m_precision);
|
result = m_bInv ? ATan(rat, m_angletype) : Tan(rat, m_angletype);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_TANH: /* Same as sine h and cosine h. */
|
case IDC_TANH: /* Same as sine h and cosine h. */
|
||||||
if (!m_fIntegerMode)
|
if (!m_fIntegerMode)
|
||||||
{
|
{
|
||||||
result = m_bInv ? ATanh(rat, m_precision) : Tanh(rat, m_precision);
|
result = m_bInv ? ATanh(rat) : Tanh(rat);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_REC: /* Reciprocal. */
|
case IDC_REC: /* Reciprocal. */
|
||||||
result = Invert(rat, m_precision);
|
result = Invert(rat);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_SQR: /* Square */
|
case IDC_SQR: /* Square */
|
||||||
result = Pow(rat, 2, m_precision);
|
result = Pow(rat, 2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_SQRT: /* Square Root */
|
case IDC_SQRT: /* Square Root */
|
||||||
result = Root(rat, 2, m_precision);
|
result = Root(rat, 2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_CUBEROOT:
|
case IDC_CUBEROOT:
|
||||||
case IDC_CUB: /* Cubing and cube root functions. */
|
case IDC_CUB: /* Cubing and cube root functions. */
|
||||||
result = IDC_CUBEROOT == op ? Root(rat, 3, m_precision) : Pow(rat, 3, m_precision);
|
result = IDC_CUBEROOT == op ? Root(rat, 3) : Pow(rat, 3);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_LOG: /* Functions for common log. */
|
case IDC_LOG: /* Functions for common log. */
|
||||||
result = Log10(rat, m_precision);
|
result = Log10(rat);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_POW10:
|
case IDC_POW10:
|
||||||
result = Pow(10, rat, m_precision);
|
result = Pow(10, rat);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_LN: /* Functions for natural log. */
|
case IDC_LN: /* Functions for natural log. */
|
||||||
result = m_bInv ? Exp(rat, m_precision) : Log(rat, m_precision);
|
result = m_bInv ? Exp(rat) : Log(rat);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_FAC: /* Calculate factorial. Inverse is ineffective. */
|
case IDC_FAC: /* Calculate factorial. Inverse is ineffective. */
|
||||||
result = Fact(rat, m_precision);
|
result = Fact(rat);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_DEGREES:
|
case IDC_DEGREES:
|
||||||
@ -180,31 +177,28 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
|
|||||||
{
|
{
|
||||||
if (!m_fIntegerMode)
|
if (!m_fIntegerMode)
|
||||||
{
|
{
|
||||||
Rational shftRat{ m_bInv ? 100 : 60 };
|
auto shftRat{ m_bInv ? 100 : 60 };
|
||||||
|
|
||||||
Rational degreeRat = Integer(rat, m_precision);
|
Rational degreeRat = Integer(rat);
|
||||||
|
|
||||||
Rational minuteRat = rat.Sub(degreeRat, m_precision);
|
Rational minuteRat = (rat - degreeRat) * shftRat;
|
||||||
minuteRat = minuteRat.Mul(shftRat, m_precision);
|
|
||||||
|
|
||||||
Rational secondRat = minuteRat;
|
Rational secondRat = minuteRat;
|
||||||
|
|
||||||
minuteRat = Integer(minuteRat, m_precision);
|
minuteRat = Integer(minuteRat);
|
||||||
|
|
||||||
secondRat = secondRat.Sub(minuteRat, m_precision);
|
secondRat = (secondRat - minuteRat) * shftRat;
|
||||||
secondRat = secondRat.Mul(shftRat, m_precision);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// degreeRat == degrees, minuteRat == minutes, secondRat == seconds
|
// degreeRat == degrees, minuteRat == minutes, secondRat == seconds
|
||||||
//
|
//
|
||||||
|
|
||||||
shftRat = Rational{ m_bInv ? 60 : 100 };
|
shftRat = m_bInv ? 60 : 100;
|
||||||
secondRat = secondRat.Div(shftRat, m_precision);
|
secondRat /= shftRat;
|
||||||
|
|
||||||
minuteRat = minuteRat.Add(secondRat, m_precision);
|
minuteRat = (minuteRat + secondRat) / shftRat;
|
||||||
minuteRat = minuteRat.Div(shftRat, m_precision);
|
|
||||||
|
|
||||||
result = degreeRat.Add(minuteRat, m_precision);
|
result = degreeRat + minuteRat;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2,18 +2,17 @@
|
|||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "Header Files/CalcEngine.h"
|
#include "Header Files/scimath.h"
|
||||||
#include "Ratpack/ratpak.h"
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace CalcEngine;
|
using namespace CalcEngine;
|
||||||
|
|
||||||
Rational RationalMath::Frac(Rational const& rat, int32_t precision)
|
Rational RationalMath::Frac(Rational const& rat)
|
||||||
{
|
{
|
||||||
PRAT prat = rat.ToPRAT();
|
PRAT prat = rat.ToPRAT();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
fracrat(&prat, RATIONAL_BASE, precision);
|
fracrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
{
|
{
|
||||||
@ -27,12 +26,12 @@ Rational RationalMath::Frac(Rational const& rat, int32_t precision)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational RationalMath::Integer(Rational const& rat, int32_t precision)
|
Rational RationalMath::Integer(Rational const& rat)
|
||||||
{
|
{
|
||||||
PRAT prat = rat.ToPRAT();
|
PRAT prat = rat.ToPRAT();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
intrat(&prat, RATIONAL_BASE, precision);
|
intrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
{
|
{
|
||||||
@ -46,14 +45,14 @@ Rational RationalMath::Integer(Rational const& rat, int32_t precision)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational RationalMath::Pow(Rational const& base, Rational const& pow, int32_t precision)
|
Rational RationalMath::Pow(Rational const& base, Rational const& pow)
|
||||||
{
|
{
|
||||||
PRAT baseRat = base.ToPRAT();
|
PRAT baseRat = base.ToPRAT();
|
||||||
PRAT powRat = pow.ToPRAT();
|
PRAT powRat = pow.ToPRAT();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
powrat(&baseRat, powRat, RATIONAL_BASE, precision);
|
powrat(&baseRat, powRat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
destroyrat(powRat);
|
destroyrat(powRat);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
@ -69,18 +68,18 @@ Rational RationalMath::Pow(Rational const& base, Rational const& pow, int32_t pr
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational RationalMath::Root(Rational const& base, Rational const& root, int32_t precision)
|
Rational RationalMath::Root(Rational const& base, Rational const& root)
|
||||||
{
|
{
|
||||||
return Pow(base, Invert(root, precision), precision);
|
return Pow(base, Invert(root));
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational RationalMath::Fact(Rational const& rat, int32_t precision)
|
Rational RationalMath::Fact(Rational const& rat)
|
||||||
{
|
{
|
||||||
PRAT prat = rat.ToPRAT();
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
factrat(&prat, RATIONAL_BASE, precision);
|
factrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
{
|
{
|
||||||
@ -94,13 +93,13 @@ Rational RationalMath::Fact(Rational const& rat, int32_t precision)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational RationalMath::Exp(Rational const& rat, int32_t precision)
|
Rational RationalMath::Exp(Rational const& rat)
|
||||||
{
|
{
|
||||||
PRAT prat = rat.ToPRAT();
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
exprat(&prat, RATIONAL_BASE, precision);
|
exprat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
{
|
{
|
||||||
@ -114,13 +113,13 @@ Rational RationalMath::Exp(Rational const& rat, int32_t precision)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational RationalMath::Log(Rational const& rat, int32_t precision)
|
Rational RationalMath::Log(Rational const& rat)
|
||||||
{
|
{
|
||||||
PRAT prat = rat.ToPRAT();
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
lograt(&prat, precision);
|
lograt(&prat, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
{
|
{
|
||||||
@ -134,14 +133,14 @@ Rational RationalMath::Log(Rational const& rat, int32_t precision)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational RationalMath::Log10(Rational const& rat, int32_t precision)
|
Rational RationalMath::Log10(Rational const& rat)
|
||||||
{
|
{
|
||||||
return Log(rat, precision).Div(Rational{ ln_ten }, precision);
|
return Log(rat) / Rational{ ln_ten };
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational RationalMath::Invert(Rational const& rat, int32_t precision)
|
Rational RationalMath::Invert(Rational const& rat)
|
||||||
{
|
{
|
||||||
return Rational{ 1 }.Div(rat, precision);
|
return 1 / rat;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational RationalMath::Abs(Rational const& rat)
|
Rational RationalMath::Abs(Rational const& rat)
|
||||||
@ -149,13 +148,13 @@ Rational RationalMath::Abs(Rational const& rat)
|
|||||||
return Rational{ Number{ 1, rat.P().Exp(), rat.P().Mantissa() }, Number{ 1, rat.Q().Exp(), rat.Q().Mantissa() } };
|
return Rational{ Number{ 1, rat.P().Exp(), rat.P().Mantissa() }, Number{ 1, rat.Q().Exp(), rat.Q().Mantissa() } };
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational RationalMath::Sin(Rational const& rat, ANGLE_TYPE angletype, int32_t precision)
|
Rational RationalMath::Sin(Rational const& rat, ANGLE_TYPE angletype)
|
||||||
{
|
{
|
||||||
PRAT prat = rat.ToPRAT();
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
sinanglerat(&prat, angletype, RATIONAL_BASE, precision);
|
sinanglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
{
|
{
|
||||||
@ -169,13 +168,13 @@ Rational RationalMath::Sin(Rational const& rat, ANGLE_TYPE angletype, int32_t pr
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational RationalMath::Cos(Rational const& rat, ANGLE_TYPE angletype, int32_t precision)
|
Rational RationalMath::Cos(Rational const& rat, ANGLE_TYPE angletype)
|
||||||
{
|
{
|
||||||
PRAT prat = rat.ToPRAT();
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
cosanglerat(&prat, angletype, RATIONAL_BASE, precision);
|
cosanglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
{
|
{
|
||||||
@ -189,13 +188,13 @@ Rational RationalMath::Cos(Rational const& rat, ANGLE_TYPE angletype, int32_t pr
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational RationalMath::Tan(Rational const& rat, ANGLE_TYPE angletype, int32_t precision)
|
Rational RationalMath::Tan(Rational const& rat, ANGLE_TYPE angletype)
|
||||||
{
|
{
|
||||||
PRAT prat = rat.ToPRAT();
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
tananglerat(&prat, angletype, RATIONAL_BASE, precision);
|
tananglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
{
|
{
|
||||||
@ -209,13 +208,13 @@ Rational RationalMath::Tan(Rational const& rat, ANGLE_TYPE angletype, int32_t pr
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational RationalMath::ASin(Rational const& rat, ANGLE_TYPE angletype, int32_t precision)
|
Rational RationalMath::ASin(Rational const& rat, ANGLE_TYPE angletype)
|
||||||
{
|
{
|
||||||
PRAT prat = rat.ToPRAT();
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
asinanglerat(&prat, angletype, RATIONAL_BASE, precision);
|
asinanglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
{
|
{
|
||||||
@ -229,13 +228,13 @@ Rational RationalMath::ASin(Rational const& rat, ANGLE_TYPE angletype, int32_t p
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational RationalMath::ACos(Rational const& rat, ANGLE_TYPE angletype, int32_t precision)
|
Rational RationalMath::ACos(Rational const& rat, ANGLE_TYPE angletype)
|
||||||
{
|
{
|
||||||
PRAT prat = rat.ToPRAT();
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
acosanglerat(&prat, angletype, RATIONAL_BASE, precision);
|
acosanglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
{
|
{
|
||||||
@ -249,13 +248,13 @@ Rational RationalMath::ACos(Rational const& rat, ANGLE_TYPE angletype, int32_t p
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational RationalMath::ATan(Rational const& rat, ANGLE_TYPE angletype, int32_t precision)
|
Rational RationalMath::ATan(Rational const& rat, ANGLE_TYPE angletype)
|
||||||
{
|
{
|
||||||
PRAT prat = rat.ToPRAT();
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
atananglerat(&prat, angletype, RATIONAL_BASE, precision);
|
atananglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
{
|
{
|
||||||
@ -269,13 +268,13 @@ Rational RationalMath::ATan(Rational const& rat, ANGLE_TYPE angletype, int32_t p
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational RationalMath::Sinh(Rational const& rat, int32_t precision)
|
Rational RationalMath::Sinh(Rational const& rat)
|
||||||
{
|
{
|
||||||
PRAT prat = rat.ToPRAT();
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
sinhrat(&prat, RATIONAL_BASE, precision);
|
sinhrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
{
|
{
|
||||||
@ -289,13 +288,13 @@ Rational RationalMath::Sinh(Rational const& rat, int32_t precision)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational RationalMath::Cosh(Rational const& rat, int32_t precision)
|
Rational RationalMath::Cosh(Rational const& rat)
|
||||||
{
|
{
|
||||||
PRAT prat = rat.ToPRAT();
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
coshrat(&prat, RATIONAL_BASE, precision);
|
coshrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
{
|
{
|
||||||
@ -309,13 +308,13 @@ Rational RationalMath::Cosh(Rational const& rat, int32_t precision)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational RationalMath::Tanh(Rational const& rat, int32_t precision)
|
Rational RationalMath::Tanh(Rational const& rat)
|
||||||
{
|
{
|
||||||
PRAT prat = rat.ToPRAT();
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
tanhrat(&prat, RATIONAL_BASE, precision);
|
tanhrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
{
|
{
|
||||||
@ -329,13 +328,13 @@ Rational RationalMath::Tanh(Rational const& rat, int32_t precision)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational RationalMath::ASinh(Rational const& rat, int32_t precision)
|
Rational RationalMath::ASinh(Rational const& rat)
|
||||||
{
|
{
|
||||||
PRAT prat = rat.ToPRAT();
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
asinhrat(&prat, RATIONAL_BASE, precision);
|
asinhrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
{
|
{
|
||||||
@ -349,13 +348,13 @@ Rational RationalMath::ASinh(Rational const& rat, int32_t precision)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational RationalMath::ACosh(Rational const& rat, int32_t precision)
|
Rational RationalMath::ACosh(Rational const& rat)
|
||||||
{
|
{
|
||||||
PRAT prat = rat.ToPRAT();
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
acoshrat(&prat, RATIONAL_BASE, precision);
|
acoshrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
{
|
{
|
||||||
@ -369,13 +368,13 @@ Rational RationalMath::ACosh(Rational const& rat, int32_t precision)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational RationalMath::ATanh(Rational const& rat, int32_t precision)
|
Rational RationalMath::ATanh(Rational const& rat)
|
||||||
{
|
{
|
||||||
PRAT prat = rat.ToPRAT();
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
atanhrat(&prat, precision);
|
atanhrat(&prat, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (DWORD error)
|
||||||
{
|
{
|
||||||
|
@ -11,69 +11,68 @@ using namespace CalcEngine::RationalMath;
|
|||||||
CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rational const& lhs, CalcEngine::Rational const& rhs)
|
CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rational const& lhs, CalcEngine::Rational const& rhs)
|
||||||
{
|
{
|
||||||
// Remove any variance in how 0 could be represented in rat e.g. -0, 0/n, etc.
|
// Remove any variance in how 0 could be represented in rat e.g. -0, 0/n, etc.
|
||||||
auto result = (!lhs.IsZero() ? lhs : Rational{});
|
auto result = (lhs != 0 ? lhs : 0);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
switch (operation)
|
switch (operation)
|
||||||
{
|
{
|
||||||
case IDC_AND:
|
case IDC_AND:
|
||||||
result = result.And(rhs, m_precision);
|
result &= rhs;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_OR:
|
case IDC_OR:
|
||||||
result = result.Or(rhs, m_precision);
|
result |= rhs;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_XOR:
|
case IDC_XOR:
|
||||||
result = result.Xor(rhs, m_precision);
|
result ^= rhs;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_RSHF:
|
case IDC_RSHF:
|
||||||
{
|
{
|
||||||
if (m_fIntegerMode && result.IsGreaterEq(Rational{ m_dwWordBitWidth }, m_precision)) // Lsh/Rsh >= than current word size is always 0
|
if (m_fIntegerMode && result >= m_dwWordBitWidth) // Lsh/Rsh >= than current word size is always 0
|
||||||
{
|
{
|
||||||
throw CALC_E_NORESULT;
|
throw CALC_E_NORESULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t w64Bits = rhs.ToUInt64_t(m_precision);
|
uint64_t w64Bits = rhs.ToUInt64_t();
|
||||||
bool fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
|
bool fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
|
||||||
|
|
||||||
Rational holdVal = result;
|
Rational holdVal = result;
|
||||||
result = rhs.Rsh(holdVal, m_precision);
|
result = rhs >> holdVal;
|
||||||
|
|
||||||
if (fMsb)
|
if (fMsb)
|
||||||
{
|
{
|
||||||
result = Integer(result, m_precision);
|
result = Integer(result);
|
||||||
|
|
||||||
auto tempRat = m_chopNumbers[m_numwidth].Rsh(holdVal, m_precision);
|
auto tempRat = m_chopNumbers[m_numwidth] >> holdVal;
|
||||||
tempRat = Integer(tempRat, m_precision);
|
tempRat = Integer(tempRat);
|
||||||
|
|
||||||
tempRat = tempRat.Xor(m_chopNumbers[m_numwidth], m_precision);
|
result |= tempRat ^ m_chopNumbers[m_numwidth];
|
||||||
result = result.Or(tempRat, m_precision);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case IDC_LSHF:
|
case IDC_LSHF:
|
||||||
if (m_fIntegerMode && result.IsGreaterEq(Rational{ m_dwWordBitWidth }, m_precision)) // Lsh/Rsh >= than current word size is always 0
|
if (m_fIntegerMode && result >= m_dwWordBitWidth) // Lsh/Rsh >= than current word size is always 0
|
||||||
{
|
{
|
||||||
throw CALC_E_NORESULT;
|
throw CALC_E_NORESULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = rhs.Lsh(result, m_precision);
|
result = rhs << result;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_ADD:
|
case IDC_ADD:
|
||||||
result = result.Add(rhs, m_precision);
|
result += rhs;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_SUB:
|
case IDC_SUB:
|
||||||
result = rhs.Sub(result, m_precision);
|
result = rhs - result;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_MUL:
|
case IDC_MUL:
|
||||||
result = result.Mul(rhs, m_precision);
|
result *= rhs;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_DIV:
|
case IDC_DIV:
|
||||||
@ -85,24 +84,22 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
|
|||||||
|
|
||||||
if (m_fIntegerMode)
|
if (m_fIntegerMode)
|
||||||
{
|
{
|
||||||
uint64_t w64Bits = rhs.ToUInt64_t(m_precision);
|
uint64_t w64Bits = rhs.ToUInt64_t();
|
||||||
bool fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
|
bool fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
|
||||||
|
|
||||||
if (fMsb)
|
if (fMsb)
|
||||||
{
|
{
|
||||||
result = rhs.Not(m_chopNumbers[m_numwidth], m_precision);
|
result = (rhs ^ m_chopNumbers[m_numwidth]) + 1;
|
||||||
result = result.Add(1, m_precision);
|
|
||||||
|
|
||||||
iNumeratorSign = -1;
|
iNumeratorSign = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
w64Bits = temp.ToUInt64_t(m_precision);
|
w64Bits = temp.ToUInt64_t();
|
||||||
fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
|
fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
|
||||||
|
|
||||||
if (fMsb)
|
if (fMsb)
|
||||||
{
|
{
|
||||||
temp = temp.Not(m_chopNumbers[m_numwidth], m_precision);
|
temp = (temp ^ m_chopNumbers[m_numwidth]) + 1;
|
||||||
temp = temp.Add(1, m_precision);
|
|
||||||
|
|
||||||
iDenominatorSign = -1;
|
iDenominatorSign = -1;
|
||||||
}
|
}
|
||||||
@ -111,28 +108,28 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
|
|||||||
if (operation == IDC_DIV)
|
if (operation == IDC_DIV)
|
||||||
{
|
{
|
||||||
iFinalSign = iNumeratorSign * iDenominatorSign;
|
iFinalSign = iNumeratorSign * iDenominatorSign;
|
||||||
result = result.Div(temp, m_precision);
|
result /= temp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
iFinalSign = iNumeratorSign;
|
iFinalSign = iNumeratorSign;
|
||||||
result = result.Mod(temp);
|
result %= temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_fIntegerMode && iFinalSign == -1)
|
if (m_fIntegerMode && iFinalSign == -1)
|
||||||
{
|
{
|
||||||
result = Integer(result, m_precision).Negate();
|
result = -(Integer(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case IDC_PWR: // Calculates rhs to the result(th) power.
|
case IDC_PWR: // Calculates rhs to the result(th) power.
|
||||||
result = Pow(rhs, result, m_precision);
|
result = Pow(rhs, result);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_ROOT: // Calculates rhs to the result(th) root.
|
case IDC_ROOT: // Calculates rhs to the result(th) root.
|
||||||
result = Root(rhs, result, m_precision);
|
result = Root(rhs, result);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,16 +18,15 @@ void CCalcEngine::SetRadixTypeAndNumWidth(RADIX_TYPE radixtype, NUM_WIDTH numwid
|
|||||||
// back to 1111,1111,1000,0001 when in Word mode.
|
// back to 1111,1111,1000,0001 when in Word mode.
|
||||||
if (m_fIntegerMode)
|
if (m_fIntegerMode)
|
||||||
{
|
{
|
||||||
uint64_t w64Bits = m_currentVal.ToUInt64_t(m_precision);
|
uint64_t w64Bits = m_currentVal.ToUInt64_t();
|
||||||
bool fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1; // make sure you use the old width
|
bool fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1; // make sure you use the old width
|
||||||
|
|
||||||
if (fMsb)
|
if (fMsb)
|
||||||
{
|
{
|
||||||
// If high bit is set, then get the decimal number in -ve 2'scompl form.
|
// If high bit is set, then get the decimal number in -ve 2'scompl form.
|
||||||
auto tempResult = m_currentVal.Not(m_chopNumbers[m_numwidth], m_precision);
|
auto tempResult = m_currentVal ^ m_chopNumbers[m_numwidth];
|
||||||
tempResult = tempResult.Add(1, m_precision);
|
|
||||||
|
|
||||||
m_currentVal = tempResult.Negate();
|
m_currentVal = -(tempResult + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,16 +84,13 @@ bool CCalcEngine::TryToggleBit(CalcEngine::Rational& rat, DWORD wbitno)
|
|||||||
return false; // ignore error cant happen
|
return false; // ignore error cant happen
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational result = Integer(rat, m_precision);
|
Rational result = Integer(rat);
|
||||||
if (result.IsZero())
|
|
||||||
{
|
|
||||||
// This is the same work around happenning in SciCalcFunctions. Ought to move to intrat function itself.
|
|
||||||
// Basic bug is there which doesn't treat 0/ n as 0, or -0 as 0 etc.
|
|
||||||
result = Rational{};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto pow = Pow(2, static_cast<int32_t>(wbitno), m_precision);
|
// Remove any variance in how 0 could be represented in rat e.g. -0, 0/n, etc.
|
||||||
rat = result.Xor(pow, m_precision);
|
result = (result != 0 ? result : 0);
|
||||||
|
|
||||||
|
// XOR the result with 2^wbitno power
|
||||||
|
rat = result ^ Pow(2, static_cast<int32_t>(wbitno));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
*
|
*
|
||||||
\****************************************************************************/
|
\****************************************************************************/
|
||||||
|
|
||||||
#include "scimath.h"
|
|
||||||
#include "CCommand.h"
|
#include "CCommand.h"
|
||||||
#include "EngineStrings.h"
|
#include "EngineStrings.h"
|
||||||
#include "../Command.h"
|
#include "../Command.h"
|
||||||
@ -24,6 +23,7 @@
|
|||||||
#include "History.h" // for History Collector
|
#include "History.h" // for History Collector
|
||||||
#include "CalcInput.h"
|
#include "CalcInput.h"
|
||||||
#include "ICalcDisplay.h"
|
#include "ICalcDisplay.h"
|
||||||
|
#include "scimath.h"
|
||||||
#include "Rational.h"
|
#include "Rational.h"
|
||||||
|
|
||||||
// The following are NOT real exports of CalcEngine, but for forward declarations
|
// The following are NOT real exports of CalcEngine, but for forward declarations
|
||||||
|
@ -10,6 +10,9 @@ namespace CalcEngine
|
|||||||
// RatPack calculations currently support up to Base64.
|
// RatPack calculations currently support up to Base64.
|
||||||
inline constexpr uint32_t RATIONAL_BASE = 10;
|
inline constexpr uint32_t RATIONAL_BASE = 10;
|
||||||
|
|
||||||
|
// Default Precision to use for Rational calculations
|
||||||
|
inline constexpr int32_t RATIONAL_PRECISION = 128;
|
||||||
|
|
||||||
class Rational
|
class Rational
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -18,7 +21,7 @@ namespace CalcEngine
|
|||||||
Rational(Number const& p, Number const& q) noexcept;
|
Rational(Number const& p, Number const& q) noexcept;
|
||||||
Rational(int32_t i);
|
Rational(int32_t i);
|
||||||
Rational(uint32_t ui);
|
Rational(uint32_t ui);
|
||||||
Rational(uint64_t ui, int32_t precision);
|
Rational(uint64_t ui);
|
||||||
|
|
||||||
explicit Rational(PRAT prat) noexcept;
|
explicit Rational(PRAT prat) noexcept;
|
||||||
PRAT ToPRAT() const;
|
PRAT ToPRAT() const;
|
||||||
@ -26,29 +29,42 @@ namespace CalcEngine
|
|||||||
Number const& P() const;
|
Number const& P() const;
|
||||||
Number const& Q() const;
|
Number const& Q() const;
|
||||||
|
|
||||||
Rational Negate() const;
|
Rational operator-() const;
|
||||||
Rational Add(Rational const& rhs, int32_t precision) const;
|
Rational& operator+=(Rational const& rhs);
|
||||||
Rational Sub(Rational const& rhs, int32_t precision) const;
|
Rational& operator-=(Rational const& rhs);
|
||||||
Rational Mul(Rational const& rhs, int32_t precision) const;
|
Rational& operator*=(Rational const& rhs);
|
||||||
Rational Div(Rational const& rhs, int32_t precision) const;
|
Rational& operator/=(Rational const& rhs);
|
||||||
Rational Mod(Rational const& rhs) const;
|
Rational& operator%=(Rational const& rhs);
|
||||||
|
|
||||||
Rational Lsh(Rational const& r, int32_t precision) const;
|
Rational& operator<<=(Rational const& rhs);
|
||||||
Rational Rsh(Rational const& r, int32_t precision) const;
|
Rational& operator>>=(Rational const& rhs);
|
||||||
|
|
||||||
Rational Not(Rational const& chopNum, int32_t precision) const;
|
Rational& operator&=(Rational const& rhs);
|
||||||
Rational And(Rational const& r, int32_t precision) const;
|
Rational& operator|=(Rational const& rhs);
|
||||||
Rational Or(Rational const& r, int32_t precision) const;
|
Rational& operator^=(Rational const& rhs);
|
||||||
Rational Xor(Rational const& r, int32_t precision) const;
|
|
||||||
|
|
||||||
bool IsZero() const;
|
friend Rational operator+(Rational lhs, Rational const& rhs);
|
||||||
bool IsLess(Rational const& r, int32_t precision) const;
|
friend Rational operator-(Rational lhs, Rational const& rhs);
|
||||||
bool IsLessEq(Rational const& r, int32_t precision) const;
|
friend Rational operator*(Rational lhs, Rational const& rhs);
|
||||||
bool IsGreaterEq(Rational const& r, int32_t precision) const;
|
friend Rational operator/(Rational lhs, Rational const& rhs);
|
||||||
bool IsEq(Rational const& r, int32_t precision) const;
|
friend Rational operator%(Rational lhs, Rational const& rhs);
|
||||||
|
|
||||||
|
friend Rational operator<<(Rational lhs, Rational const& rhs);
|
||||||
|
friend Rational operator>>(Rational lhs, Rational const& rhs);
|
||||||
|
|
||||||
|
friend Rational operator&(Rational lhs, Rational const& rhs);
|
||||||
|
friend Rational operator|(Rational lhs, Rational const& rhs);
|
||||||
|
friend Rational operator^(Rational lhs, Rational const& rhs);
|
||||||
|
|
||||||
|
friend bool operator==(Rational const& lhs, Rational const& rhs);
|
||||||
|
friend bool operator!=(Rational const& lhs, Rational const& rhs);
|
||||||
|
friend bool operator<(Rational const& lhs, Rational const& rhs);
|
||||||
|
friend bool operator>(Rational const& lhs, Rational const& rhs);
|
||||||
|
friend bool operator<=(Rational const& lhs, Rational const& rhs);
|
||||||
|
friend bool operator>=(Rational const& lhs, Rational const& rhs);
|
||||||
|
|
||||||
std::wstring ToString(uint32_t radix, NUMOBJ_FMT format, int32_t precision) const;
|
std::wstring ToString(uint32_t radix, NUMOBJ_FMT format, int32_t precision) const;
|
||||||
uint64_t ToUInt64_t(int32_t precision) const;
|
uint64_t ToUInt64_t() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Number m_p;
|
Number m_p;
|
||||||
|
@ -5,31 +5,31 @@
|
|||||||
|
|
||||||
namespace CalcEngine::RationalMath
|
namespace CalcEngine::RationalMath
|
||||||
{
|
{
|
||||||
Rational Frac(Rational const& rat, int32_t precision);
|
Rational Frac(Rational const& rat);
|
||||||
Rational Integer(Rational const& rat, int32_t precision);
|
Rational Integer(Rational const& rat);
|
||||||
|
|
||||||
Rational Pow(Rational const& base, Rational const& pow, int32_t precision);
|
Rational Pow(Rational const& base, Rational const& pow);
|
||||||
Rational Root(Rational const& base, Rational const& root, int32_t precision);
|
Rational Root(Rational const& base, Rational const& root);
|
||||||
Rational Fact(Rational const& rat, int32_t precision);
|
Rational Fact(Rational const& rat);
|
||||||
|
|
||||||
Rational Exp(Rational const& rat, int32_t precision);
|
Rational Exp(Rational const& rat);
|
||||||
Rational Log(Rational const& rat, int32_t precision);
|
Rational Log(Rational const& rat);
|
||||||
Rational Log10(Rational const& rat, int32_t precision);
|
Rational Log10(Rational const& rat);
|
||||||
|
|
||||||
Rational Invert(Rational const& rat, int32_t precision);
|
Rational Invert(Rational const& rat);
|
||||||
Rational Abs(Rational const& rat);
|
Rational Abs(Rational const& rat);
|
||||||
|
|
||||||
Rational Sin(Rational const& rat, ANGLE_TYPE angletype, int32_t precision);
|
Rational Sin(Rational const& rat, ANGLE_TYPE angletype);
|
||||||
Rational Cos(Rational const& rat, ANGLE_TYPE angletype, int32_t precision);
|
Rational Cos(Rational const& rat, ANGLE_TYPE angletype);
|
||||||
Rational Tan(Rational const& rat, ANGLE_TYPE angletype, int32_t precision);
|
Rational Tan(Rational const& rat, ANGLE_TYPE angletype);
|
||||||
Rational ASin(Rational const& rat, ANGLE_TYPE angletype, int32_t precision);
|
Rational ASin(Rational const& rat, ANGLE_TYPE angletype);
|
||||||
Rational ACos(Rational const& rat, ANGLE_TYPE angletype, int32_t precision);
|
Rational ACos(Rational const& rat, ANGLE_TYPE angletype);
|
||||||
Rational ATan(Rational const& rat, ANGLE_TYPE angletype, int32_t precision);
|
Rational ATan(Rational const& rat, ANGLE_TYPE angletype);
|
||||||
|
|
||||||
Rational Sinh(Rational const& rat, int32_t precision);
|
Rational Sinh(Rational const& rat);
|
||||||
Rational Cosh(Rational const& rat, int32_t precision);
|
Rational Cosh(Rational const& rat);
|
||||||
Rational Tanh(Rational const& rat, int32_t precision);
|
Rational Tanh(Rational const& rat);
|
||||||
Rational ASinh(Rational const& rat, int32_t precision);
|
Rational ASinh(Rational const& rat);
|
||||||
Rational ACosh(Rational const& rat, int32_t precision);
|
Rational ACosh(Rational const& rat);
|
||||||
Rational ATanh(Rational const& rat, int32_t precision);
|
Rational ATanh(Rational const& rat);
|
||||||
}
|
}
|
||||||
|
@ -1259,20 +1259,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
wstring RatToString(_Inout_ PRAT& prat, int format, uint32_t radix, int32_t precision)
|
wstring RatToString(_Inout_ PRAT& prat, int format, uint32_t radix, int32_t precision)
|
||||||
{
|
{
|
||||||
// Convert p and q of rational form from internal base to requested base.
|
PNUMBER p = RatToNumber(prat, radix, precision);
|
||||||
// Scale by largest power of BASEX possible.
|
|
||||||
long scaleby = min(prat->pp->exp, prat->pq->exp);
|
|
||||||
scaleby = max(scaleby, 0);
|
|
||||||
|
|
||||||
prat->pp->exp -= scaleby;
|
|
||||||
prat->pq->exp -= scaleby;
|
|
||||||
|
|
||||||
PNUMBER p = nRadixxtonum(prat->pp, radix, precision);
|
|
||||||
PNUMBER q = nRadixxtonum(prat->pq, radix, precision);
|
|
||||||
|
|
||||||
// finally take the time hit to actually divide.
|
|
||||||
divnum(&p, q, radix, precision);
|
|
||||||
destroynum(q);
|
|
||||||
|
|
||||||
wstring result = NumberToString(p, format, radix, precision);
|
wstring result = NumberToString(p, format, radix, precision);
|
||||||
destroynum(p);
|
destroynum(p);
|
||||||
@ -1280,6 +1267,40 @@ wstring RatToString(_Inout_ PRAT& prat, int format, uint32_t radix, int32_t prec
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PNUMBER RatToNumber(_In_ PRAT prat, uint32_t radix, int32_t precision)
|
||||||
|
{
|
||||||
|
PRAT temprat = nullptr;
|
||||||
|
DUPRAT(temprat, prat);
|
||||||
|
// Convert p and q of rational form from internal base to requested base.
|
||||||
|
// Scale by largest power of BASEX possible.
|
||||||
|
long scaleby = min(temprat->pp->exp, temprat->pq->exp);
|
||||||
|
scaleby = max(scaleby, 0);
|
||||||
|
|
||||||
|
temprat->pp->exp -= scaleby;
|
||||||
|
temprat->pq->exp -= scaleby;
|
||||||
|
|
||||||
|
PNUMBER p = nRadixxtonum(temprat->pp, radix, precision);
|
||||||
|
PNUMBER q = nRadixxtonum(temprat->pq, radix, precision);
|
||||||
|
|
||||||
|
destroyrat(temprat);
|
||||||
|
|
||||||
|
// finally take the time hit to actually divide.
|
||||||
|
divnum(&p, q, radix, precision);
|
||||||
|
destroynum(q);
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converts a PRAT to a PNUMBER and back to a PRAT, flattening/simplifying the rational in the process
|
||||||
|
void flatrat(_Inout_ PRAT& prat, uint32_t radix, int32_t precision)
|
||||||
|
{
|
||||||
|
PNUMBER pnum = RatToNumber(prat, radix, precision);
|
||||||
|
|
||||||
|
destroyrat(prat);
|
||||||
|
prat = numtorat(pnum, radix);
|
||||||
|
destroynum(pnum);
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: gcd
|
// FUNCTION: gcd
|
||||||
|
@ -73,16 +73,11 @@ void gcdrat( PRAT *pa, uint32_t radix, 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 intrat operation if number is nonzero.
|
// Only do the flatrat operation if number is nonzero.
|
||||||
// and only if the bottom part is not one.
|
// 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 ) )
|
||||||
{
|
{
|
||||||
wstring ratStr = RatToString(*pa, FMT_FLOAT, radix, precision);
|
flatrat(*pa, radix, precision);
|
||||||
PNUMBER pnum = StringToNumber(ratStr, radix, precision);
|
|
||||||
|
|
||||||
destroyrat( *pa );
|
|
||||||
*pa = numtorat( pnum, radix);
|
|
||||||
destroynum( pnum );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
remnum( &((*pa)->pp), (*pa)->pq, BASEX );
|
remnum( &((*pa)->pp), (*pa)->pq, BASEX );
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -316,6 +316,10 @@ extern std::wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t r
|
|||||||
|
|
||||||
// returns a text representation of a PRAT
|
// returns a text representation of a PRAT
|
||||||
extern std::wstring RatToString(_Inout_ PRAT& prat, int format, uint32_t radix, int32_t precision);
|
extern std::wstring RatToString(_Inout_ PRAT& prat, int format, uint32_t radix, int32_t precision);
|
||||||
|
// converts a PRAT into a PNUMBER
|
||||||
|
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 long numtolong(_In_ PNUMBER pnum, uint32_t radix );
|
extern long numtolong(_In_ PNUMBER pnum, uint32_t radix );
|
||||||
extern long rattolong(_In_ PRAT prat, uint32_t radix, int32_t precision);
|
extern long rattolong(_In_ PRAT prat, uint32_t radix, int32_t precision);
|
||||||
|
@ -291,19 +291,18 @@ void intrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||||||
// and only if the bottom part is not one.
|
// 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 ) )
|
||||||
{
|
{
|
||||||
wstring ratStr = RatToString(*px, FMT_FLOAT, radix, precision);
|
flatrat(*px, radix, precision);
|
||||||
PNUMBER pnum = StringToNumber(ratStr, radix, precision);
|
|
||||||
|
|
||||||
destroyrat( *px );
|
|
||||||
*px = numtorat( pnum, radix);
|
|
||||||
destroynum( pnum );
|
|
||||||
|
|
||||||
|
// Subtract the fractional part of the rational
|
||||||
PRAT pret = nullptr;
|
PRAT pret = nullptr;
|
||||||
DUPRAT(pret,*px);
|
DUPRAT(pret,*px);
|
||||||
modrat( &pret, rat_one );
|
modrat( &pret, rat_one );
|
||||||
|
|
||||||
subrat( px, pret, precision);
|
subrat( px, pret, precision);
|
||||||
destroyrat( pret );
|
destroyrat( pret );
|
||||||
|
|
||||||
|
// Simplify the value if possible to resolve rounding errors
|
||||||
|
flatrat(*px, radix, precision);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user