#include "common.h"
#include <cmath>
#include <cassert>
+#include "arbint.h"
namespace IPDF
{
+
+template <class T> T Tabs(const T & a)
+{
+ return llabs(a);
+}
+
+
/* Recursive version of GCD
template <class T>
Rational(double d=0) : P(d*1e6), Q(1e6) // Possibly the worst thing ever...
{
Simplify();
- if (!CheckAccuracy(d, "Construct from double"))
+ //if (!CheckAccuracy(d, "Construct from double"))
{
//Fatal("Bwah bwah :(");
}
Q = T(1);
return;
}
- T g = gcd(T(llabs(P)),T(llabs(Q)));
+ T g = gcd(Tabs(P), Tabs(Q));
//Debug("Got gcd!");
P /= g;
Q /= g;
Rational operator+(const Rational & r) const
{
Rational result = (r.P == T(0)) ? Rational(P,Q) : Rational(P*r.Q + r.P*Q, Q*r.Q);
- if (!result.CheckAccuracy(ToDouble() * r.ToDouble(),"+"))
- {
- Debug("This is %s (%f) and r is %s (%f)", Str().c_str(), ToDouble(), r.Str().c_str(), r.ToDouble());
- }
+ //if (!result.CheckAccuracy(ToDouble() * r.ToDouble(),"+"))
+ //{
+ // Debug("This is %s (%f) and r is %s (%f)", Str().c_str(), ToDouble(), r.Str().c_str(), r.ToDouble());
+ //}
return result;
}
Rational operator-(const Rational & r) const
Rational operator*(const Rational & r) const
{
Rational result(P * r.P, Q * r.Q);
- if (!result.CheckAccuracy(ToDouble() * r.ToDouble(),"*"))
- {
- Debug("This is %s (%f) and r is %s (%f)", Str().c_str(), ToDouble(), r.Str().c_str(), r.ToDouble());
- }
+ //if (!result.CheckAccuracy(ToDouble() * r.ToDouble(),"*"))
+ //{
+ // Debug("This is %s (%f) and r is %s (%f)", Str().c_str(), ToDouble(), r.Str().c_str(), r.ToDouble());
+ //}
return result;
}
Rational operator/(const Rational & r) const
{
Rational result(P * r.Q, Q*r.P);
- if (!result.CheckAccuracy(ToDouble() / r.ToDouble(),"/"))
- {
- Debug("This is %s (%f) and r is %s (%f)", Str().c_str(), ToDouble(), r.Str().c_str(), r.ToDouble());
- }
+ //if (!result.CheckAccuracy(ToDouble() / r.ToDouble(),"/"))
+ //{
+ // Debug("This is %s (%f) and r is %s (%f)", Str().c_str(), ToDouble(), r.Str().c_str(), r.ToDouble());
+ //}
return result;
}
+
}
#endif //_RATIONAL_H
using namespace std;
using namespace IPDF;
+#define TEST_CASES 100
+
+bool NotEqual(double a, double b, double threshold=1e-4)
+{
+ return (fabs(a-b) > threshold);
+}
int main(int argc, char ** argv)
{
srand(time(NULL));
- Real a = Random(100);
- Real b = Random(100);
- Debug("a = %f", Float(a));
- Debug("b = %f", Float(b));
- Debug("a + b = %f", Float(a + b));
- Debug("a - b = %f", Float(a - b));
- Debug("a * b = %f", Float(a * b));
- Debug("a / b = %f", Float(a / b));
- Debug("a += b => %f", Float(a += b));
- Debug("a -= b => %f", Float(a -= b));
- Debug("a *= b => %f", Float(a *= b));
- Debug("a /= b => %f", Float(a /= b));
- Debug("a = %f", Float(a));
- Debug("b = %f", Float(b));
+
+ unsigned failures = 0;
+ for (unsigned i = 0; i < TEST_CASES; ++i)
+ {
+ double da = (double)(rand()) / (double)(rand());
+ double db = (double)(rand()) / (double)(rand());
+
+ Real a(da);
+ Real b(db);
+
+
+
+ if (NotEqual(Double(a), da))
+ {
+ failures++;
+ Warn("a != da; %f vs %f", Double(a), da);
+ }
+ if (NotEqual(Double(b), db))
+ {
+ failures++;
+ Warn("b != db; %f vs %f", Double(b), db);
+ }
+ if (NotEqual(Double(a+b), da+db))
+ {
+ failures++;
+ Warn("a + b = %f should be %f", Double(a+b), da+db);
+ }
+ if (NotEqual(Double(a-b), da-db))
+ {
+ failures++;
+ Warn("a - b = %f should be %f", Double(a-b), da-db);
+ }
+ if (NotEqual(Double(a*b), da*db))
+ {
+ failures++;
+ Warn("a * b = %f should be %f", Double(a*b), da*db);
+ }
+ if (NotEqual(Double(a/b), da/db))
+ {
+ failures++;
+ Warn("a / b = %f should be %f", Double(a/b), da/db);
+ }
+
+ if (NotEqual(Double(a), da))
+ {
+ failures++;
+ Warn("a has changed after +-*/ from %f to %f", da, Double(a));
+ }
+ if (NotEqual(Double(b), db))
+ {
+ failures++;
+ Warn("b has changed after +-*/ from %f to %f", db, Double(b));
+ }
+
+ if (NotEqual(Double(a+=b), da+=db))
+ {
+ failures++;
+ Warn("a += b = %f should be %f", Double(a), da);
+ }
+ if (NotEqual(Double(a-=b), da-=db))
+ {
+ failures++;
+ Warn("a -= b = %f should be %f", Double(a), da);
+ }
+ if (NotEqual(Double(a*=b), da*=db))
+ {
+ failures++;
+ Warn("a *= b = %f should be %f", Double(a), da);
+ }
+ if (NotEqual(Double(a/=b), da/=db))
+ {
+ failures++;
+ Warn("a /= b = %f should be %f", Double(a), da);
+ }
+ }
+ Debug("Completed %u test cases with total of %u operations, %u failures", TEST_CASES, 12*TEST_CASES, failures);
}