rtlbcdtest.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include "platform.h"
  14. #include "jlog.hpp"
  15. #include "rtlbcd.hpp"
  16. #include "nbcd.hpp"
  17. #define _elements_in(a) (sizeof(a)/sizeof((a)[0]))
  18. const char * hex = "0123456789ABCDEF";
  19. #ifdef _USE_CPPUNIT
  20. #include <cppunit/extensions/HelperMacros.h>
  21. // Usage: success &= check(statement, "error: foo bar %d", variable);
  22. static bool check(bool condition, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
  23. static bool check(bool condition, const char *fmt, ...)
  24. {
  25. if (!condition)
  26. {
  27. va_list args;
  28. va_start(args, fmt);
  29. VALOG(MCdebugInfo, unknownJob, fmt, args);
  30. va_end(args);
  31. }
  32. return condition;
  33. }
  34. // Usage: cppunit_assert(statement, "error: foo bar %d", variable));
  35. static void cppunit_assert(bool condition, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
  36. static void cppunit_assert(bool condition, const char *fmt, ...)
  37. {
  38. if (!condition)
  39. {
  40. va_list args;
  41. va_start(args, fmt);
  42. VALOG(MCdebugInfo, unknownJob, fmt, args);
  43. va_end(args);
  44. CPPUNIT_ASSERT(!"Please refer to the errors above");
  45. }
  46. }
  47. // Do not use: cppunit_cppunit_assert(condition, "string")), as that will print the string twice
  48. class NBcdTest : public CppUnit::TestFixture
  49. {
  50. CPPUNIT_TEST_SUITE(NBcdTest);
  51. CPPUNIT_TEST(testBcdUninitialized);
  52. CPPUNIT_TEST(testBcdCString);
  53. CPPUNIT_TEST(testBcdRoundTruncate);
  54. CPPUNIT_TEST(testBcdDecimal);
  55. CPPUNIT_TEST(testBcdInt);
  56. CPPUNIT_TEST(testBcdMultiply);
  57. CPPUNIT_TEST(testBcdDivideModulus);
  58. CPPUNIT_TEST(testBcdCompare);
  59. // Failing tests (due to precision)
  60. CPPUNIT_TEST(testBcdRandom);
  61. CPPUNIT_TEST(testBcdPower);
  62. CPPUNIT_TEST(testBcdPrecision);
  63. CPPUNIT_TEST_SUITE_END();
  64. protected:
  65. static void expandHex(const void * bytes, unsigned size, char * target)
  66. {
  67. byte * src = (byte *)bytes;
  68. while (size--)
  69. {
  70. *target++ = hex[*src>>4];
  71. *target++ = hex[*src&15];
  72. src++;
  73. }
  74. *target=0;
  75. }
  76. void testMultiply(const char * left, const char * right, const char * expected)
  77. {
  78. if (!right) right = left;
  79. char temp[80];
  80. Decimal a = left;
  81. Decimal b = right;
  82. a.multiply(b);
  83. a.getCString(sizeof(temp), temp);
  84. cppunit_assert(strcmp(expected, temp) == 0, "ERROR: testMultiply/getCString: expected '%s', got '%s'", expected, temp);
  85. DecPushCString(left);
  86. DecPushCString(right);
  87. DecMul();
  88. DecPopCString(sizeof(temp),temp);
  89. cppunit_assert(strcmp(expected, temp) == 0, "ERROR: testMultiply/DecMul: expected '%s', got '%s'", expected, temp);
  90. }
  91. void testDivide(const char * left, const char * right, const char * expected)
  92. {
  93. char temp[80];
  94. Decimal a = left;
  95. Decimal b = right;
  96. a.divide(b);
  97. a.getCString(sizeof(temp), temp);
  98. cppunit_assert(strcmp(expected, temp) == 0, "ERROR: testDivide/getCString: expected '%s', got '%s'", expected, temp);
  99. DecPushCString(left);
  100. DecPushCString(right);
  101. DecDivide(DBZzero);
  102. DecPopCString(sizeof(temp),temp);
  103. cppunit_assert(strcmp(expected, temp) == 0, "ERROR: testDivide/DecDivide: expected '%s', got '%s'", expected, temp);
  104. }
  105. void testCompare(const char * left, const char * right, int expected)
  106. {
  107. Decimal a = left;
  108. Decimal b = right;
  109. int temp = a.compare(b);
  110. cppunit_assert(temp == expected, "ERROR: testCompare/positive: expected '%d', got '%d'", expected, temp);
  111. temp = b.compare(a);
  112. cppunit_assert(temp == -expected, "ERROR: testCompare/negative: expected '%d', got '%d'", expected, temp);
  113. DecPushCString(left);
  114. DecPushCString(right);
  115. temp = DecDistinct();
  116. cppunit_assert(expected == temp, "ERROR: testCompare/DecDistinct: expected '%d', got '%d'", expected, temp);
  117. }
  118. void testModulus(const char * left, const char * right, const char * expected)
  119. {
  120. char temp[80];
  121. Decimal a = left;
  122. Decimal b = right;
  123. a.modulus(b);
  124. a.getCString(sizeof(temp), temp);
  125. cppunit_assert(strcmp(expected, temp) == 0, "ERROR: testModulus: expected '%s', got '%s'", expected, temp);
  126. }
  127. void checkDecimal(const Decimal & value, const char * expected)
  128. {
  129. char temp[80];
  130. value.getCString(sizeof(temp), temp);
  131. const char * unknown = strchr(expected, 'x');
  132. if (unknown && temp[unknown-expected])
  133. temp[unknown-expected] = 'x';
  134. cppunit_assert(strcmp(expected, temp) == 0, "ERROR: checkDecimal/char: expected '%s', got '%s'", expected, temp);
  135. }
  136. void checkDecimal(const Decimal & value, unsigned __int64 expected)
  137. {
  138. unsigned __int64 temp = value.getUInt64();
  139. cppunit_assert(expected == temp, "ERROR: checkDecimal/uint64: expected '%" I64F "d', got '%" I64F "d'", expected, temp);
  140. }
  141. void checkDecimal(const Decimal & value, __int64 expected)
  142. {
  143. __int64 temp = value.getInt64();
  144. cppunit_assert(expected == temp, "ERROR: checkDecimal/int64: expected '%" I64F "d', got '%" I64F "d'", expected, temp);
  145. }
  146. void checkBuffer(const void * buffer, const char * expected)
  147. {
  148. char temp[40];
  149. expandHex(buffer, strlen(expected)/2, temp);
  150. cppunit_assert(strcmp(expected, temp) == 0, "ERROR: checkBuffer: expected '%s', got '%s'", expected, temp);
  151. }
  152. // ========================================================= UNIT TESTS BELOW
  153. void testBcdRandom()
  154. {
  155. for (int i = 0; i < 1000; i++)
  156. {
  157. // 14-digit numbers, multiplications can't pass 28 digits (32 max)
  158. unsigned __int64 val1 = ((__int64) rand() << 16) | rand();
  159. unsigned __int64 val2 = ((__int64) rand() << 16) | rand();
  160. unsigned __int64 val3 = ((__int64) rand() << 16) | rand();
  161. unsigned __int64 val4 = ((__int64) rand() << 16) | rand();
  162. for (int i = 0; i < 2; i++)
  163. {
  164. Decimal d1 = val1;
  165. Decimal d2 = val2;
  166. Decimal d3 = val3;
  167. Decimal d4 = val4;
  168. d1.multiply(d2);
  169. d3.multiply(d4);
  170. checkDecimal(d1, val1*val2);
  171. checkDecimal(d3, val3*val4);
  172. d2.set(d1);
  173. d1.subtract(d3);
  174. d2.add(d3);
  175. checkDecimal(d1, (__int64)(val1*val2-val3*val4));
  176. checkDecimal(d2, (val1*val2+val3*val4));
  177. }
  178. }
  179. }
  180. void testBcdUninitialized()
  181. {
  182. // Test uninitialised
  183. Decimal zero, one=1, two(2);
  184. checkDecimal(zero, 0ULL);
  185. checkDecimal(one, 1ULL);
  186. checkDecimal(two, 2ULL);
  187. zero.add(one);
  188. checkDecimal(zero, 1ULL);
  189. zero.multiply(two);
  190. checkDecimal(zero, 2ULL);
  191. }
  192. void testBcdCString()
  193. {
  194. Decimal a,b,c;
  195. a.setString(10,"1234.56789"); // 1234.56789
  196. b.setString(8," 123456.88"); // 123456
  197. c.setString(6," 0.123 ");
  198. char temp[80];
  199. a.getCString(sizeof(temp), temp);
  200. check(strcmp("1234.56789", temp) == 0, "ERROR: testBcdCString/a: expected '1234.56789', got '%s'", temp);
  201. b.getCString(sizeof(temp), temp);
  202. check(strcmp("123456", temp) == 0, "ERROR: testBcdCString/b: expected '123456', got '%s'", temp);
  203. c.getCString(sizeof(temp), temp);
  204. check(strcmp("0.123", temp) == 0, "ERROR: testBcdCString/c: expected '0.123', got '%s'", temp);
  205. a.add(b);
  206. a.getCString(sizeof(temp), temp);
  207. check(strcmp("124690.56789", temp) == 0, "ERROR: testBcdCString/a+b: expected '124690.56789', got '%s'", temp);
  208. b.subtract(a);
  209. b.getCString(sizeof(temp), temp);
  210. check(strcmp("-1234.56789", temp) == 0, "ERROR: testBcdCString/-a: expected '-1234.56789', got '%s'", temp);
  211. }
  212. void testBcdRoundTruncate()
  213. {
  214. char temp[80];
  215. Decimal c = "9.53456";
  216. checkDecimal(c, "9.53456");
  217. c.round(4);
  218. checkDecimal(c,"9.5346");
  219. c.round(8);
  220. checkDecimal(c, "9.5346");
  221. c.round(2);
  222. checkDecimal(c, "9.53");
  223. c.round();
  224. checkDecimal(c, "10");
  225. c = 1234567.8901;
  226. checkDecimal(c, "1234567.8901");
  227. c.round(-3);
  228. checkDecimal(c, "1235000");
  229. c = "9.53456";
  230. c.truncate(4);
  231. checkDecimal(c, "9.5345");
  232. c.truncate(8);
  233. checkDecimal(c, "9.5345");
  234. c.truncate(2);
  235. checkDecimal(c, "9.53");
  236. c.truncate();
  237. checkDecimal(c, "9");
  238. Decimal x1 = 1;
  239. x1.round(-3);
  240. checkDecimal(x1, (__int64)0);
  241. Decimal x2 = 100;
  242. x2.round(-3);
  243. checkDecimal(x2, (__int64)0);
  244. Decimal x3 = 499;
  245. x3.round(-3);
  246. checkDecimal(x3, (__int64)0);
  247. Decimal x4 = 500;
  248. x4.round(-3);
  249. checkDecimal(x4, (__int64)1000);
  250. Decimal x5 = 1000;
  251. x5.round(-3);
  252. checkDecimal(x5, (__int64)1000);
  253. Decimal x6 = 1499;
  254. x6.round(-3);
  255. checkDecimal(x6, (__int64)1000);
  256. Decimal x7 = 1500;
  257. x7.round(-3);
  258. checkDecimal(x7, (__int64)2000);
  259. Decimal x8 = 10000;
  260. x8.round(-3);
  261. checkDecimal(x8, (__int64)10000);
  262. Decimal x9 = 10499;
  263. x9.round(-3);
  264. checkDecimal(x9, (__int64)10000);
  265. Decimal x10 = 10500;
  266. x10.round(-3);
  267. checkDecimal(x10, (__int64)11000);
  268. Decimal x11 = -10500;
  269. x11.round(-3);
  270. checkDecimal(x11, (__int64)-11000);
  271. c = 1234567.8901234567; // Expect rounding of the last digit
  272. c.getCString(sizeof(temp), temp);
  273. cppunit_assert(strcmp("1234567.890123457", temp) == 0, "ERROR: testBcdRoundTruncate/cstr: expected '1234567.890123457', got '%s'", temp);
  274. cppunit_assert(c.getReal() == 1234567.890123457, "ERROR: testBcdRoundTruncate/real: expected '1234567.890123457', got '%.8f'", c.getReal());
  275. }
  276. void testBcdDecimal()
  277. {
  278. Decimal a = "123.2345";
  279. unsigned decBufferSize=5;
  280. char decBuffer[7];
  281. char * decBufferPtr = decBuffer+1;
  282. decBuffer[0]=(char)0xCC;
  283. decBuffer[6]=(char)0xCC;
  284. a.getUDecimal(decBufferSize, 4, decBufferPtr);
  285. checkBuffer(decBuffer, "CC0001232345CC");
  286. a.getUDecimal(decBufferSize, 3, decBufferPtr);
  287. checkBuffer(decBuffer, "CC0000123234CC");
  288. a.getUDecimal(decBufferSize, 2, decBufferPtr);
  289. checkBuffer(decBuffer, "CC0000012323CC");
  290. a.getUDecimal(decBufferSize, 6, decBufferPtr);
  291. checkBuffer(decBuffer, "CC0123234500CC");
  292. a.getUDecimal(decBufferSize, 7, decBufferPtr);
  293. checkBuffer(decBuffer, "CC1232345000CC");
  294. a.getUDecimal(decBufferSize, 8, decBufferPtr);
  295. checkBuffer(decBuffer, "CC2323450000CC");
  296. a = "0.0001";
  297. a.getUDecimal(decBufferSize, 4, decBufferPtr);
  298. checkBuffer(decBuffer, "CC0000000001CC");
  299. a.getUDecimal(decBufferSize, 3, decBufferPtr);
  300. checkBuffer(decBuffer, "CC0000000000CC");
  301. a = "123.2345";
  302. a.getDecimal(decBufferSize, 4, decBufferPtr);
  303. checkBuffer(decBuffer, "CC001232345FCC");
  304. a.getDecimal(decBufferSize, 3, decBufferPtr);
  305. checkBuffer(decBuffer, "CC000123234FCC");
  306. a.getDecimal(decBufferSize, 2, decBufferPtr);
  307. checkBuffer(decBuffer, "CC000012323FCC");
  308. a.getDecimal(decBufferSize, 5, decBufferPtr);
  309. checkBuffer(decBuffer, "CC012323450FCC");
  310. a.getDecimal(decBufferSize, 6, decBufferPtr);
  311. checkBuffer(decBuffer, "CC123234500FCC");
  312. a.getDecimal(decBufferSize, 7, decBufferPtr);
  313. checkBuffer(decBuffer, "CC232345000FCC");
  314. a.getDecimal(decBufferSize, 5, decBufferPtr, 0xEB);
  315. checkBuffer(decBuffer, "CC012323450ECC");
  316. a = "0.0001";
  317. a.getDecimal(decBufferSize, 4, decBufferPtr);
  318. checkBuffer(decBuffer, "CC000000001FCC");
  319. a.getDecimal(decBufferSize, 3, decBufferPtr);
  320. checkBuffer(decBuffer, "CC000000000FCC");
  321. a = "-123.2345";
  322. a.getDecimal(decBufferSize, 4, decBufferPtr);
  323. checkBuffer(decBuffer, "CC001232345DCC");
  324. a.getDecimal(decBufferSize, 3, decBufferPtr, 0xFB);
  325. checkBuffer(decBuffer, "CC000123234BCC");
  326. memcpy(decBufferPtr, "\x00\x12\x34\x56\x78", 5);
  327. a.setUDecimal(5, 4, decBufferPtr);
  328. checkDecimal(a, "1234.5678");
  329. a.setUDecimal(5, 3, decBufferPtr);
  330. checkDecimal(a,"12345.678");
  331. a.setUDecimal(5, 0, decBufferPtr);
  332. checkDecimal(a, "12345678");
  333. a.setUDecimal(5, 9, decBufferPtr);
  334. checkDecimal(a, "0.012345678");
  335. memcpy(decBufferPtr, "\x00\x12\x34\x56\x7D", 5);
  336. a.setDecimal(5, 4, decBufferPtr);
  337. checkDecimal(a, "-123.4567");
  338. a.setDecimal(5, 3, decBufferPtr);
  339. checkDecimal(a, "-1234.567");
  340. a.setDecimal(5, 0, decBufferPtr);
  341. checkDecimal(a, "-1234567");
  342. a.setDecimal(5, 8, decBufferPtr);
  343. checkDecimal(a,"-0.01234567");
  344. memcpy(decBufferPtr, "\x00\x12\x34\x56\x7F", 5);
  345. a.setDecimal(5, 4, decBufferPtr);
  346. checkDecimal(a, "123.4567");
  347. a.setDecimal(5, 3, decBufferPtr);
  348. checkDecimal(a, "1234.567");
  349. a.setDecimal(5, 0, decBufferPtr);
  350. checkDecimal(a, "1234567");
  351. a.setDecimal(5, 8, decBufferPtr);
  352. checkDecimal(a, "0.01234567");
  353. }
  354. void testBcdInt()
  355. {
  356. Decimal a, b;
  357. for (unsigned i1 = 0; i1 <= 1000; i1++)
  358. {
  359. a = i1;
  360. cppunit_assert(a.getUInt() == i1, "ERROR: testBcdInt/getUInt: expected '%d', got '%d'", i1, a.getUInt());
  361. }
  362. for (unsigned i3 = 0; i3 <= 100; i3++)
  363. {
  364. a = i3;
  365. b = 10;
  366. a.multiply(b);
  367. cppunit_assert(a.getUInt() == i3*10, "ERROR: testBcdInt/getUInt*3: expected '%d', got '%d'", i3*10, a.getUInt());
  368. }
  369. for (unsigned i2 = 0; i2 <= 100; i2++)
  370. {
  371. Decimal x = i2;
  372. Decimal y = 100;
  373. y.multiply(x);
  374. cppunit_assert(100*i2 == (unsigned)y.getInt(), "ERROR: testBcdInt/getInt*100: expected '%d', got '%d'", 100*i2, y.getInt());
  375. x.multiply(x);
  376. cppunit_assert(i2*i2 == (unsigned)x.getInt(), "ERROR: testBcdInt/getInt*getInt: expected '%d', got '%d'", i2*i2, x.getInt());
  377. }
  378. }
  379. void testBcdMultiply()
  380. {
  381. testMultiply("-1","0","0");
  382. testMultiply("-1","2","-2");
  383. testMultiply("-1","-2","2");
  384. testMultiply("1","-2","-2");
  385. testMultiply("9","9","81");
  386. testMultiply("99","99","9801");
  387. testMultiply("999","999","998001");
  388. testMultiply("9999","9999","99980001");
  389. testMultiply("99.999999999",NULL,"9999.999999800000000001");
  390. testMultiply("9999.999999999",NULL,"99999999.999980000000000001");
  391. testMultiply("0.0000000000000001",NULL,"0.00000000000000000000000000000001");
  392. testMultiply("0.0000000000000009",NULL,"0.00000000000000000000000000000081");
  393. testMultiply("0.00000000000000001",NULL,"0");
  394. testMultiply("0.00000000000000009","0.0000000000000009","0.00000000000000000000000000000008");
  395. testMultiply("9999999999999999","10000000000000001","99999999999999999999999999999999");
  396. testMultiply("101","99009901","10000000001");
  397. testMultiply("0.000000000000000101","0.0000000000000000099009901","0");
  398. testMultiply("0.000000000000000101","0.000000000000000099009901","0.00000000000000000000000000000001");
  399. testMultiply("109", "9174311926605504587155963302.75229357798165137614678899082568", "999999999999999999999999999999.99999999999999999999999999999912");
  400. testMultiply("109", "9174311926605504587155963302.75229357798165137614678899082569", "1000000000000000000000000000000.00000000000000000000000000000021");
  401. testMultiply("9999999999.999999999999999999999999999999","9999999999.999999999999999999999999999999","99999999999999999999.99999999999999999998"); // actually 99999999999999999999.999999999999999999980000000000000000000000000000000000000001
  402. Decimal a = "9999999999999999";
  403. Decimal b = "10000000000000002";
  404. char temp[80];
  405. a.multiply(b);
  406. a.getCString(sizeof(temp), temp);
  407. cppunit_assert(strcmp("9999999999999998", temp) == 0, "ERROR: testBcdMultiply/overflow: expected '9999999999999998', got '%s'", temp);
  408. }
  409. void testBcdDivideModulus()
  410. {
  411. //Divide
  412. testDivide("1","1","1");
  413. testDivide("125","5","25");
  414. testDivide("99980001","9999","9999");
  415. testDivide("0.1234","10000000000000000000000000000000","0.00000000000000000000000000000001");
  416. testDivide("0.1234","20000000000000000000000000000000","0.00000000000000000000000000000001");
  417. testDivide("0.1234","30000000000000000000000000000000","0");
  418. testDivide("1","0.00000000000000000000000000000002", "50000000000000000000000000000000");
  419. testDivide("1","3", "0.33333333333333333333333333333333");
  420. testDivide("1000000000000000000000000000000","109", "9174311926605504587155963302.75229357798165137614678899082569");
  421. testModulus("1000000000000000000000000000000","109", "82");
  422. testModulus("10","5","0");
  423. testModulus("10","6","4");
  424. testModulus("10","-6","4");
  425. testModulus("-10","6","-4");
  426. testModulus("-10","-6","-4");
  427. }
  428. void testBcdCompare()
  429. {
  430. testCompare("1","1.0000",0);
  431. testCompare("-1","1.0000",-1);
  432. testCompare("1","-1.0000",+1);
  433. testCompare("-1","-1.0000",0);
  434. testCompare("1","2.0000",-1);
  435. testCompare("-1","2.0000",-1);
  436. testCompare("1","-2.0000",+1);
  437. testCompare("-1","-2.0000",+1);
  438. testCompare("100","2.0000",+1);
  439. testCompare("-100","2.0000",-1);
  440. testCompare("100","-2.0000",+1);
  441. testCompare("-100","-2.0000",-1);
  442. testCompare("0","1",-1);
  443. testCompare("0","-1",+1);
  444. testCompare("0","0",0);
  445. testCompare("1234","1230",+1);
  446. testCompare("1234.0001","1230.99",+1);
  447. testCompare("1234.999","1234.99",+1);
  448. testCompare("1234.989","1234.99",-1);
  449. testCompare("-1234","-1230",-1);
  450. testCompare("-1234.0001","-1230.99",-1);
  451. testCompare("-1234.999","-1234.99",-1);
  452. testCompare("-1234.989","-1234.99",+1);
  453. }
  454. void testBcdPower()
  455. {
  456. //MORE: Test power functions...
  457. const char * values[] = { "10000", "-1", "-10", "1.0001", "9.99" };
  458. Decimal one(1);
  459. for (unsigned idx = 0; idx < _elements_in(values); idx++)
  460. {
  461. Decimal value = values[idx];
  462. Decimal sofar1 = 1;
  463. Decimal sofar2 = 1;
  464. bool success=true;
  465. for (int power = 0; power < 10; power++)
  466. {
  467. Decimal powerValue1 = values[idx];
  468. Decimal powerValue2 = values[idx];
  469. powerValue1.power(power);
  470. powerValue2.power(-power);
  471. char temp1[80], temp2[80], temp3[80];
  472. if (sofar1.compare(powerValue1) != 0)
  473. {
  474. Decimal diff = powerValue1;
  475. diff.subtract(sofar1);
  476. sofar1.getCString(sizeof(temp1), temp1);
  477. powerValue1.getCString(sizeof(temp2), temp2);
  478. diff.getCString(sizeof(temp3), temp3);
  479. success &= check(false, "ERROR: %s^%d=%s (expected %s) diff %s", values[idx], power, temp2, temp1, temp3);
  480. }
  481. if (sofar2.compare(powerValue2) != 0)
  482. {
  483. Decimal diff = powerValue2;
  484. diff.subtract(sofar2);
  485. sofar2.getCString(sizeof(temp1), temp1);
  486. powerValue2.getCString(sizeof(temp2), temp2);
  487. diff.getCString(sizeof(temp3), temp3);
  488. success &= check(false, "ERROR: %s^%d=%s (expected %s) diff %s", values[idx], -power, temp2, temp1, temp3);
  489. }
  490. //internal consistency test, but liable to rounding errors....
  491. Decimal product(powerValue1);
  492. product.multiply(powerValue2);
  493. if (power && (product.compareNull() != 0) && (product.compare(one) != 0))
  494. {
  495. char temp4[80];
  496. char temp5[80];
  497. Decimal diff = product;
  498. diff.subtract(one);
  499. one.getCString(sizeof(temp1), temp1);
  500. product.getCString(sizeof(temp2), temp2);
  501. diff.getCString(sizeof(temp3), temp3);
  502. powerValue1.getCString(sizeof(temp4), temp4);
  503. powerValue2.getCString(sizeof(temp5), temp5);
  504. //Report rounding errors, but don't trigger a failure
  505. check(false, "ERROR: %s^%d^-%d=%s (expected %s) diff %s [%s*%s]", values[idx], power, power, temp2, temp1, temp3, temp4, temp5);
  506. }
  507. sofar1.multiply(value);
  508. sofar2.divide(value);
  509. }
  510. cppunit_assert(success, "ERROR: testBcdPower: one or more errors detected above.");
  511. }
  512. }
  513. void testBcdPrecision()
  514. {
  515. //check rounding is done correctly to number of significant digits
  516. checkDecimal(9999999.12, "9999999.12");
  517. checkDecimal(-9999999.12, "-9999999.12");
  518. checkDecimal(9999999.12345678, "9999999.12345678");
  519. checkDecimal(-9999999.12345678, "-9999999.12345678");
  520. checkDecimal(9999999.123456789, "9999999.123456789");
  521. checkDecimal(-9999999.123456789, "-9999999.123456789");
  522. //MORE: The exact values are out of our control.
  523. //Real->decimal extracts 16 decimal digits, but only 15.9 are significant, so the last digit cannot be guaranteed.
  524. checkDecimal(91999991234567800.00, "919999912345678x0");
  525. checkDecimal(-91999991234567800.00, "-919999912345678x0");
  526. checkDecimal(91999991234567123.00, "919999912345671x0");
  527. // in vc++ these real constants seem to only have 14 significant digits
  528. // checkDecimal(0.99999991234567800, "0.999999912345678");
  529. // checkDecimal(0.99999991234567890, "0.999999912345679");
  530. // checkDecimal(0.099999991234567800, "0.0999999912345678");
  531. // checkDecimal(0.099999991234567890, "0.0999999912345679");
  532. }
  533. };
  534. CPPUNIT_TEST_SUITE_REGISTRATION( NBcdTest );
  535. CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( NBcdTest, "NBcdTest" );
  536. #endif