From 58ee1d5b8171c43c6b0231911e54aaacd7ba6a6e Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Mon, 26 Sep 2011 23:20:47 +0000 Subject: [PATCH] core: add operators +=, *= etc. to the real class, and refactor the print() method so that it displays decimal values. --- src/real.cpp | 107 ++++++++++++++++++++++++++++++++++++++++++++------- src/real.h | 11 ++++++ 2 files changed, 104 insertions(+), 14 deletions(-) diff --git a/src/real.cpp b/src/real.cpp index c5fa419d..aedcf632 100644 --- a/src/real.cpp +++ b/src/real.cpp @@ -22,10 +22,9 @@ using namespace std; namespace lol { -real::real(float f) -{ - new(this) real((double)f); -} +real::real(float f) { *this = (double)f; } +real::real(int i) { *this = (double)i; } +real::real(unsigned int i) { *this = (double)i; } real::real(double d) { @@ -54,10 +53,9 @@ real::real(double d) memset(m_mantissa + 4, 0, sizeof(m_mantissa) - 4 * sizeof(m_mantissa[0])); } -real::operator float() const -{ - return (float)(double)(*this); -} +real::operator float() const { return (float)(double)(*this); } +real::operator int() const { return (int)(double)(*this); } +real::operator unsigned int() const { return (unsigned int)(double)(*this); } real::operator double() const { @@ -315,6 +313,43 @@ real real::operator /(real const &x) const return *this * fres(x); } +real &real::operator +=(real const &x) +{ + real tmp = *this; + return *this = tmp + x; +} + +real &real::operator -=(real const &x) +{ + real tmp = *this; + return *this = tmp - x; +} + +real &real::operator *=(real const &x) +{ + real tmp = *this; + return *this = tmp * x; +} + +real &real::operator /=(real const &x) +{ + real tmp = *this; + return *this = tmp / x; +} + +bool real::operator ==(real const &x) const +{ + if (m_signexp != x.m_signexp) + return false; + + return memcmp(m_mantissa, x.m_mantissa, sizeof(m_mantissa)) == 0; +} + +bool real::operator !=(real const &x) const +{ + return !(*this == x); +} + bool real::operator <(real const &x) const { /* Ensure both numbers are positive */ @@ -384,8 +419,6 @@ real fres(real const &x) real ret; ret.m_mantissa[0] = (v.x >> 7) & 0xffffu; ret.m_mantissa[1] = (v.x << 9) & 0xffffu; - /* Better convergence with the mantissa zeroed. */ - memset(ret.m_mantissa + 2, 0, (real::BIGITS - 2) * sizeof(uint16_t)); uint32_t sign = x.m_signexp & 0x80000000u; ret.m_signexp = sign; @@ -395,7 +428,7 @@ real fres(real const &x) ret.m_signexp |= (exponent - 1) & 0x7fffffffu; /* Five steps of Newton-Raphson seems enough for 32-bigit reals. */ - real two(2.0f); + real two = 2; ret = ret * (two - ret * x); ret = ret * (two - ret * x); ret = ret * (two - ret * x); @@ -407,9 +440,55 @@ real fres(real const &x) void real::print() const { - printf("%x %08x ", m_signexp >> 31, (m_signexp << 1) >> 1); - for (int i = 0; i < BIGITS; i++) - printf("%04x ", m_mantissa[i]); + real const r1 = 1, r10 = 10; + real x = *this; + + if (x.m_signexp >> 31) + { + printf("-"); + x = -x; + } + + /* Normalise x so that mantissa is in [1..9.999] */ + int exponent = 0; + for (real div = r1, newdiv; true; div = newdiv) + { + newdiv = div * r10; + if (x < newdiv) + { + x /= div; + break; + } + exponent++; + } + for (real mul = 1, newx; true; mul *= r10) + { + newx = x * mul; + if (newx >= r1) + { + x = newx; + break; + } + exponent--; + } + + /* Print digits */ + for (int i = 0; i < 150; i++) + { + int digit = (int)x; + printf("%i", digit); + if (i == 0) + printf("."); + x -= real(digit); + x *= r10; + } + + /* Print exponent information */ + if (exponent < 0) + printf("e-%i", -exponent); + else if (exponent > 0) + printf("e+%i", exponent); + printf("\n"); } diff --git a/src/real.h b/src/real.h index 8e029c78..1f377d28 100644 --- a/src/real.h +++ b/src/real.h @@ -27,18 +27,29 @@ class real public: inline real() { } + real(float f); real(double f); + real(int i); + real(unsigned int i); operator float() const; operator double() const; + operator int() const; + operator unsigned int() const; real operator -() const; real operator +(real const &x) const; real operator -(real const &x) const; real operator *(real const &x) const; real operator /(real const &x) const; + real &operator +=(real const &x); + real &operator -=(real const &x); + real &operator *=(real const &x); + real &operator /=(real const &x); + bool operator ==(real const &x) const; + bool operator !=(real const &x) const; bool operator <(real const &x) const; bool operator >(real const &x) const; bool operator <=(real const &x) const;