+}
+
+void TestAddSubIntegers(int max=100)
+{
+ Debug("Test add/sub integers 0 -> %i", max);
+ ParanoidNumber p;
+ double d(0);
+ for (int a = 0; a < max; ++a)
+ {
+ TestOp(p, d, ADD, a);
+ for (int b = 0; b < max; ++b)
+ {
+ TestOp(p, d, SUBTRACT, b);
+ }
+ for (int b = 0; b < max; ++b)
+ {
+ TestOp(p, d, ADD, b);
+ }
+ }
+ for (int a = 0; a < max; ++a)
+ {
+ TestOp(p, d, SUBTRACT, a);
+ for (int b = 0; b < max; ++b)
+ {
+ TestOp(p, d, ADD, b);
+ }
+ for (int b = 0; b < max; ++b)
+ {
+ TestOp(p, d, SUBTRACT, b);
+ }
+ }
+ Debug("PN Yields: %.40lf", p.ToDouble());
+ Debug("Doubles Yield: %.40lf", d);
+ Debug("Complete!");
+
+}
+
+void TestMulDivIntegers(int max=50)
+{
+ Debug("Test mul/div integers 1 -> %i", max);
+ ParanoidNumber p(1.0);
+ double d(1.0);
+ for (int a = 1; a < max; ++a)
+ {
+ TestOp(p, d, MULTIPLY, a);
+ for (int b = 1; b < max; ++b)
+ {
+ TestOp(p, d, DIVIDE, b);
+ }
+ for (int b = 1; b < max; ++b)
+ {
+ TestOp(p, d, MULTIPLY, b);
+ }
+ }
+ for (int a = 1; a < max; ++a)
+ {
+ TestOp(p, d, DIVIDE, a);
+ for (int b = 1; b < max; ++b)
+ {
+ TestOp(p, d, MULTIPLY, b);
+ }
+ for (int b = 1; b < max; ++b)
+ {
+ TestOp(p, d, DIVIDE, b);
+ }
+ }
+ Debug("PN Yields: %.40lf", p.ToDouble());
+ Debug("PN is: %s", p.Str().c_str());
+
+ Debug("Doubles Yield: %.40lf", d);
+ Debug("Complete!");
+
+}
+
+void TestRandomisedOps(int test_cases = 1000, int ops_per_case = 1, int max_digits = 4)
+{
+ Debug("Test %i*%i randomised ops (max digits = %i)", test_cases, ops_per_case, max_digits);
+ long double eps = 1; //* (1e4*ops_per_case);
+ for (int i = 0; i < test_cases; ++i)
+ {
+ string s = RandomNumberAsString(max_digits);
+ ParanoidNumber a(s);
+
+ double da(a.ToDouble());
+ for (int j = 1; j <= ops_per_case; ++j)
+ {
+ double da2(a.ToDouble());
+ s = RandomNumberAsString(max_digits);
+ ParanoidNumber b(s);
+ double db(b.ToDouble());
+
+
+
+ Optype op = Optype(rand() % 4);
+
+ ParanoidNumber a_before(a);
+
+
+ switch (op)
+ {
+ case ADD:
+ a += b;
+ da += db;
+ da2 += db;
+ break;
+ case SUBTRACT:
+ a -= b;
+ da -= db;
+ da2 -= db;
+ break;
+ case MULTIPLY:
+ a *= b;
+ da *= db;
+ da2 *= db;
+ break;
+ case DIVIDE:
+ if (db == 0)
+ {
+ --i;
+ }
+ else
+ {
+ a /= b;
+ da /= db;
+ da2 /= db;
+ }
+ break;
+ case NOP:
+ break;
+ }
+ if (!CloseEnough(da2, a, eps))
+ {
+ Error("{%s} %c= {%s}", a_before.Str().c_str(), OpChar(op), b.Str().c_str());
+ Error("{%s}", a.Str().c_str());
+ Error("double Yields: %.40lf", da);
+ Error("PN Yields: %.40lf", a.ToDouble());
+ Fatal("Failed on case %i", i*ops_per_case + j-1);
+ }
+ }
+ if (!CloseEnough(da, a, eps))
+ {
+ Warn("double Yields: %.40lf", da);
+ Warn("PN Yields: %.40lf", a.ToDouble());
+ }
+ if (i == test_cases - 1)
+ {
+ Debug("double: %.40lf", da);
+ Debug("PN: %.40lf", a.ToDouble());
+ }
+ }
+
+
+}
+
+#define TEST_CASES 1000
+
+int main(int argc, char ** argv)
+{
+ TestAddSubIntegers(100);
+ TestMulDivIntegers(100);
+ for (int i = 1; i <= 100; ++i)
+ TestRandomisedOps(1000, i);
+ return 0;
+ srand(0);//time(NULL)); //always test off same set