/Tests/Foundation/CPDecimalTest.j

http://github.com/cacaodev/cappuccino · Unknown · 706 lines · 610 code · 96 blank · 0 comment · 0 complexity · 458cf1f6c8a3aa38abbda98b51fb0bed MD5 · raw file

  1. /*
  2. * CPDecimalTest.j
  3. * Foundation
  4. *
  5. * Created by Stephen Paul Ierodiaconou
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. @import <Foundation/CPString.j>
  22. @import <Foundation/CPDecimal.j>
  23. @implementation CPDecimalTest : OJTestCase
  24. - (void)testInitialisers
  25. {
  26. // max digits
  27. [self assertNotNull:CPDecimalMakeWithString(@"9999999999999999999999999999999999") message:"CPDecimalMakeWithString() Tmx1: max digits string"];
  28. [self assertNotNull:CPDecimalMakeWithString(@"-1111111111111111111111111111111111") message:"CPDecimalMakeWithString() Tmx2: negative max digits string"];
  29. // too big digit, round
  30. var dcm = CPDecimalMakeWithString(@"11111111111111111111111111111111111111111");
  31. [self assertNotNull:dcm message:"CPDecimalMakeWithString() Tb1: mantissa rounding string"];
  32. [self assert:3 equals:dcm._exponent message:"CPDecimalMakeWithString() Tb1: exponent"];
  33. [self assert:[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] equals:dcm._mantissa message:"CPDecimalMakeWithString() Tb1: mantissa"];
  34. [self assert:NO equals:dcm._isNegative message:"CPDecimalMakeWithString() Tb1: sign"];
  35. [self assert:NO equals:dcm._isNaN message:"CPDecimalMakeWithString() Tb1: NaN is incorrectly set"];
  36. // format tests
  37. dcm = CPDecimalMakeWithString(@"+0.01e+1");
  38. [self assertNotNull:dcm message:"CPDecimalMakeWithString() Tf1: mantissa rounding string"];
  39. [self assert:-1 equals:dcm._exponent message:"CPDecimalMakeWithString() Tf1: exponent"];
  40. [self assert:[1] equals:dcm._mantissa message:"CPDecimalMakeWithString() Tf1: mantissa"];
  41. [self assert:NO equals:dcm._isNegative message:"CPDecimalMakeWithString() Tf1: sign"];
  42. [self assert:NO equals:dcm._isNaN message:"CPDecimalMakeWithString() Tf1: NaN is incorrectly set"];
  43. dcm = CPDecimalMakeWithString(@"+99e-5");
  44. [self assertNotNull:dcm message:"CPDecimalMakeWithString() Tf2: mantissa rounding string"];
  45. [self assert:-5 equals:dcm._exponent message:"CPDecimalMakeWithString() Tf2: exponent"];
  46. [self assert:[9,9] equals:dcm._mantissa message:"CPDecimalMakeWithString() Tf2: mantissa"];
  47. [self assert:NO equals:dcm._isNegative message:"CPDecimalMakeWithString() Tf2: sign"];
  48. [self assert:NO equals:dcm._isNaN message:"CPDecimalMakeWithString() Tf2: NaN is incorrectly set"];
  49. dcm = CPDecimalMakeWithString(@"-1234.5678e100");
  50. [self assertNotNull:dcm message:"CPDecimalMakeWithString() Tf3: mantissa rounding string"];
  51. [self assert:96 equals:dcm._exponent message:"CPDecimalMakeWithString() Tf3: exponent"];
  52. [self assert:[1, 2, 3, 4, 5, 6, 7, 8] equals:dcm._mantissa message:"CPDecimalMakeWithString() Tf3: mantissa"];
  53. [self assert:YES equals:dcm._isNegative message:"CPDecimalMakeWithString() Tf3: sign"];
  54. [self assert:NO equals:dcm._isNaN message:"CPDecimalMakeWithString() Tf3: NaN is incorrectly set"];
  55. dcm = CPDecimalMakeWithString(@"0.00000000000000000000000001");
  56. [self assertNotNull:dcm message:"CPDecimalMakeWithString() Tf4: mantissa rounding string"];
  57. [self assert:-26 equals:dcm._exponent message:"CPDecimalMakeWithString() Tf4: exponent"];
  58. [self assert:[1] equals:dcm._mantissa message:"CPDecimalMakeWithString() Tf4: mantissa"];
  59. [self assert:NO equals:dcm._isNegative message:"CPDecimalMakeWithString() Tf4: sign"];
  60. [self assert:NO equals:dcm._isNaN message:"CPDecimalMakeWithString() Tf4: NaN is incorrectly set"];
  61. dcm = CPDecimalMakeWithString(@"000000000000000000");
  62. [self assertFalse:dcm._isNaN message:"CPDecimalMakeWithString() Tf5: Should be valid"];
  63. // too large return NaN
  64. dcm = CPDecimalMakeWithString(@"111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
  65. [self assertTrue:dcm._isNaN message:"CPDecimalMakeWithString() To1: number overflow handling. Should return NaN"];
  66. dcm = CPDecimalMakeWithString(@"-1e1000");
  67. [self assertTrue:dcm._isNaN message:"CPDecimalMakeWithString() To2: exponent overflow not caught. Should return NaN"];
  68. dcm = CPDecimalMakeWithString(@"-1e-2342");
  69. [self assertTrue:dcm._isNaN message:"CPDecimalMakeWithString() To3: exponent underflow not caught. Should return NaN"];
  70. // Tests for invalid strings
  71. dcm = CPDecimalMakeWithString(@"abc");
  72. [self assertTrue:dcm._isNaN message:"CPDecimalMakeWithString() Ti1: catch of invalid number string. Should return NaN"];
  73. dcm = CPDecimalMakeWithString(@"123a");
  74. [self assertTrue:dcm._isNaN message:"CPDecimalMakeWithString() Ti2: catch of invalid number string. Should return NaN"];
  75. dcm = CPDecimalMakeWithString(@"12.7e");
  76. [self assertTrue:dcm._isNaN message:"CPDecimalMakeWithString() Ti3: catch of invalid number string. Should return NaN"];
  77. dcm = CPDecimalMakeWithString(@"e");
  78. [self assertTrue:dcm._isNaN message:"CPDecimalMakeWithString() Ti4: catch of invalid number string. Should return NaN"];
  79. dcm = CPDecimalMakeWithString(@"12 ");
  80. [self assertTrue:dcm._isNaN message:"CPDecimalMakeWithString() Ti5: catch of invalid number string. Should return NaN"];
  81. dcm = CPDecimalMakeWithString(@"1 2 3");
  82. [self assertTrue:dcm._isNaN message:"CPDecimalMakeWithString() Ti6: catch of invalid number string. Should return NaN"];
  83. dcm = CPDecimalMakeWithString(@"e10");
  84. [self assertTrue:dcm._isNaN message:"CPDecimalMakeWithString() Ti7: catch of invalid number string. Should return NaN"];
  85. dcm = CPDecimalMakeWithString(@"123ee");
  86. [self assertTrue:dcm._isNaN message:"CPDecimalMakeWithString() Ti8: catch of invalid number string. Should return NaN"];
  87. // this behaviour has changed to match Cocoa. Making a decimal with a leading zero should return the decimal.
  88. dcm = CPDecimalMakeWithString(@"0001");
  89. [self assertFalse:dcm._isNaN message:"CPDecimalMakeWithString() Ti9: Numbers with leading zeros are valid numbers. Expected False when evaluating against NaN, got True."];
  90. dcm = CPDecimalMakeWithString(@"-0001");
  91. [self assertFalse:dcm._isNaN message:"CPDecimalMakeWithString() Ti10: Numbers with leading zeros are valid numbers. Expected False when evaluating against NaN, got True."];
  92. //test make with parts
  93. dcm = CPDecimalMakeWithParts(10127658, 2);
  94. [self assert:2 equals:dcm._exponent message:"CPDecimalMakeWithParts() Tmp1: exponent"];
  95. [self assert:[1, 0, 1, 2, 7, 6, 5, 8] equals:dcm._mantissa message:"CPDecimalMakeWithParts() Tmp1: mantissa"];
  96. [self assert:NO equals:dcm._isNegative message:"CPDecimalMakeWithParts() Tmp1: sign"];
  97. [self assert:NO equals:dcm._isNaN message:"CPDecimalMakeWithParts() Tmp1: NaN is incorrectly set"];
  98. dcm = CPDecimalMakeWithParts(-1000000, 0);
  99. [self assert:6 equals:dcm._exponent message:"CPDecimalMakeWithParts() Tmp2: exponent"];
  100. [self assert:[1] equals:dcm._mantissa message:"CPDecimalMakeWithParts() Tmp2: mantissa"];
  101. [self assert:YES equals:dcm._isNegative message:"CPDecimalMakeWithParts() Tmp2: sign"];
  102. [self assert:NO equals:dcm._isNaN message:"CPDecimalMakeWithParts() Tmp2: NaN is incorrectly set"];
  103. dcm = CPDecimalMakeWithParts(1, 10000);
  104. [self assertTrue:dcm._isNaN message:"CPDecimalMakeWithParts() Tmp3: exponent overflow not caught. Should return NaN"];
  105. dcm = CPDecimalMakeWithParts(-1, -1000);
  106. [self assertTrue:dcm._isNaN message:"CPDecimalMakeWithParts() Tmp4: exponent underflow not caught. Should return NaN"];
  107. }
  108. - (void)testZeros
  109. {
  110. var dcm = CPDecimalMakeWithString(@"0");
  111. [self assertTrue:CPDecimalIsZero(dcm) message:"CPDecimalMakeWithString(0) and CPDecimalIsZero()"];
  112. dcm = CPDecimalMakeWithString(@"-0.000000000000e-0");
  113. [self assertTrue:CPDecimalIsZero(dcm) message:"CPDecimalMakeWithString(0) and CPDecimalIsZero()"];
  114. dcm = CPDecimalMakeWithParts(0,0);
  115. [self assertTrue:CPDecimalIsZero(dcm) message:"CPDecimalMakeWithParts(0)"];
  116. dcm = CPDecimalMakeZero();
  117. [self assertTrue:CPDecimalIsZero(dcm) message:"CPDecimalMakeZero()"];
  118. }
  119. - (void)testOnes
  120. {
  121. var dcm = CPDecimalMakeOne();
  122. [self assertTrue:CPDecimalIsOne(dcm) message:"CPDecimalMakeOne() and CPDecimalIsOne()"];
  123. dcm = CPDecimalMakeWithString(@"1.00000e1");
  124. [self assertTrue:CPDecimalIsOne(dcm) message:"CPDecimalMakeWithString(1)"];
  125. dcm = CPDecimalMakeWithString(@"0.00100000e-3");
  126. [self assertTrue:CPDecimalIsOne(dcm) message:"CPDecimalMakeWithString(1)"];
  127. [self assert:1 equals:dcm._mantissa[0] message:"CPDecimalMakeWithString(1)"];
  128. }
  129. - (void)testNormalize
  130. {
  131. var dcm1 = CPDecimalMakeWithString( @"200" ),
  132. dcm2 = CPDecimalMakeWithString( @"2" );
  133. [self assert:0 equals:CPDecimalNormalize(dcm1,dcm2,CPRoundDown) message:"CPDecimalNormalise() Tn1:call" ];
  134. [self assert:[2,0,0] equals:dcm1._mantissa message:"CPDecimalNormalise() Tn1: mantissa"];
  135. [self assert:0 equals:dcm1._exponent message:"CPDecimalNormalise() Tn1: exponent"];
  136. [self assert:[2] equals:dcm2._mantissa message:"CPDecimalNormalise() Tn1: mantissa"];
  137. [self assert:0 equals:dcm2._exponent message:"CPDecimalNormalise() Tn1: exponent"];
  138. dcm1 = CPDecimalMakeWithString( @"0.001" );
  139. dcm2 = CPDecimalMakeWithString( @"123" );
  140. [self assert:0 equals:CPDecimalNormalize(dcm1,dcm2,CPRoundDown) message:"CPDecimalNormalise() Tn2:call" ];
  141. [self assert:[1] equals:dcm1._mantissa message:"CPDecimalNormalise() Tn2: mantissa"];
  142. [self assert:-3 equals:dcm1._exponent message:"CPDecimalNormalise() Tn2: exponent"];
  143. [self assert:[1,2,3,0,0,0] equals:dcm2._mantissa message:"CPDecimalNormalise() Tn2: mantissa"];
  144. [self assert:-3 equals:dcm2._exponent message:"CPDecimalNormalise() Tn2: exponent"];
  145. dcm1 = CPDecimalMakeWithString( @"123" );
  146. dcm2 = CPDecimalMakeWithString( @"0.001" );
  147. [self assert:0 equals:CPDecimalNormalize(dcm1,dcm2,CPRoundDown) message:"CPDecimalNormalise() Tn3:call" ];
  148. [self assert:[1] equals:dcm2._mantissa message:"CPDecimalNormalise() Tn3: mantissa"];
  149. [self assert:-3 equals:dcm2._exponent message:"CPDecimalNormalise() Tn3: exponent"];
  150. [self assert:[1,2,3,0,0,0] equals:dcm1._mantissa message:"CPDecimalNormalise() Tn3: mantissa"];
  151. [self assert:-3 equals:dcm1._exponent message:"CPDecimalNormalise() Tn3: exponent"];
  152. dcm1 = CPDecimalMakeWithString( @"-1e-7" );
  153. dcm2 = CPDecimalMakeWithString( @"-21e-8" );
  154. [self assert:0 equals:CPDecimalNormalize(dcm1,dcm2,CPRoundDown) message:"CPDecimalNormalise() Tn4:call" ];
  155. [self assert:[1,0] equals:dcm1._mantissa message:"CPDecimalNormalise() Tn4: mantissa"];
  156. [self assert:-8 equals:dcm1._exponent message:"CPDecimalNormalise() Tn4: exponent"];
  157. [self assert:[2, 1] equals:dcm2._mantissa message:"CPDecimalNormalise() Tn4: mantissa"];
  158. [self assert:-8 equals:dcm2._exponent message:"CPDecimalNormalise() Tn4: exponent"];
  159. // these will result in one number becoming zero.
  160. dcm1 = CPDecimalMakeWithString( @"1e0" );
  161. dcm2 = CPDecimalMakeWithString( @"10000000000000000000000000000000000001e2" );
  162. [self assert:CPCalculationLossOfPrecision equals:CPDecimalNormalize(dcm1,dcm2,CPRoundDown) message:"CPDecimalNormalise() Tnp1:call should ret LossOfPrecision" ];
  163. [self assert:[0] equals:dcm1._mantissa message:"CPDecimalNormalise() Tnp1: mantissa"];
  164. [self assert:0 equals:dcm1._exponent message:"CPDecimalNormalise() Tnp1: exponent"];
  165. [self assert:[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1] equals:dcm2._mantissa message:"CPDecimalNormalise() Tnp1: mantissa"];
  166. [self assert:2 equals:dcm2._exponent message:"CPDecimalNormalise() Tnp1: exponent"];
  167. dcm1 = CPDecimalMakeWithString( @"10000000000000000000000000000000000001e2" );
  168. dcm2 = CPDecimalMakeWithString( @"1e0" );
  169. [self assert:CPCalculationLossOfPrecision equals:CPDecimalNormalize(dcm1,dcm2,CPRoundDown) message:"CPDecimalNormalise() Tnp2:call should ret LossOfPrecision" ];
  170. [self assert:[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1] equals:dcm1._mantissa message:"CPDecimalNormalise() Tnp2: mantissa"];
  171. [self assert:2 equals:dcm1._exponent message:"CPDecimalNormalise() Tnp2:exponent"];
  172. [self assert:[0] equals:dcm2._mantissa message:"CPDecimalNormalise() Tnp2: mantissa"];
  173. [self assert:0 equals:dcm2._exponent message:"CPDecimalNormalise() Tnp2: exponent"];
  174. dcm1 = CPDecimalMakeWithString( @"10000000000000000000000000000000000001e127" );
  175. dcm2 = CPDecimalMakeWithString( @"1e0" );
  176. [self assert:CPCalculationLossOfPrecision equals:CPDecimalNormalize(dcm1,dcm2,CPRoundDown) message:"CPDecimalNormalise() Tnp3:call should ret LossOfPrecision" ];
  177. [self assert:[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1] equals:dcm1._mantissa message:"CPDecimalNormalise() Tnp3: mantissa"];
  178. [self assert:127 equals:dcm1._exponent message:"CPDecimalNormalise() Tnp3: exponent"];
  179. [self assert:[0] equals:dcm2._mantissa message:"CPDecimalNormalise() Tnp3: mantissa"];
  180. [self assert:0 equals:dcm2._exponent message:"CPDecimalNormalise() Tnp3: exponent"];
  181. dcm1 = CPDecimalMakeWithString( @"1e-3" );
  182. dcm2 = CPDecimalMakeWithString( @"1e36" );
  183. [self assert:CPCalculationLossOfPrecision equals:CPDecimalNormalize(dcm1,dcm2,CPRoundDown) message:"CPDecimalNormalise() Tnp4:call should ret LossOfPrecision" ];
  184. [self assert:[0] equals:dcm1._mantissa message:"CPDecimalNormalise() Tnp4: mantissa"];
  185. [self assert:0 equals:dcm1._exponent message:"CPDecimalNormalise() Tnp4: exponent"];
  186. [self assert:[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] equals:dcm2._mantissa message:"CPDecimalNormalise() Tnp4: mantissa"];
  187. [self assert:-1 equals:dcm2._exponent message:"CPDecimalNormalise() Tnp4: exponent"];
  188. }
  189. - (void)testRound
  190. {
  191. var dcm = CPDecimalMakeWithString(@"0.00123");
  192. CPDecimalRound(dcm,dcm,3,CPRoundUp);
  193. [self assert:[2] equals:dcm._mantissa message:"CPDecimalRound() Tr1: mantissa"];
  194. [self assert:-3 equals:dcm._exponent message:"CPDecimalRound() Tr1: exponent"];
  195. // plain
  196. var dcm1 = CPDecimalMakeZero();
  197. dcm = CPDecimalMakeWithString(@"123.456");
  198. CPDecimalRound(dcm1,dcm,0,CPRoundPlain);
  199. [self assert:[1,2,3] equals:dcm1._mantissa message:"CPDecimalRound() Tp1: mantissa"];
  200. [self assert:0 equals:dcm1._exponent message:"CPDecimalRound() Tp1: exponent"];
  201. CPDecimalRound(dcm1,dcm,2,CPRoundPlain);
  202. [self assert:[1,2,3,4,6] equals:dcm1._mantissa message:"CPDecimalRound() Tp2: mantissa"];
  203. [self assert:-2 equals:dcm1._exponent message:"CPDecimalRound() Tp2: exponent"];
  204. CPDecimalRound(dcm1,dcm,-2,CPRoundPlain);
  205. [self assert:[1] equals:dcm1._mantissa message:"CPDecimalRound() Tp3: mantissa"];
  206. [self assert:2 equals:dcm1._exponent message:"CPDecimalRound() Tp3: exponent"];
  207. CPDecimalRound(dcm1,dcm,-4,CPRoundPlain);
  208. [self assert:[0] equals:dcm1._mantissa message:"CPDecimalRound() Tp4: mantissa"];
  209. [self assert:0 equals:dcm1._exponent message:"CPDecimalRound() Tp4: exponent"];
  210. CPDecimalRound(dcm1,dcm,6,CPRoundPlain);
  211. [self assert:[1,2,3,4,5,6] equals:dcm1._mantissa message:"CPDecimalRound() Tp5: mantissa"];
  212. [self assert:-3 equals:dcm1._exponent message:"CPDecimalRound() Tp5: exponent"];
  213. // down
  214. CPDecimalRound(dcm1,dcm,0,CPRoundDown);
  215. [self assert:[1,2,3] equals:dcm1._mantissa message:"CPDecimalRound() Td1: mantissa"];
  216. [self assert:0 equals:dcm1._exponent message:"CPDecimalRound() Td1: exponent"];
  217. CPDecimalRound(dcm1,dcm,2,CPRoundDown);
  218. [self assert:[1,2,3,4,5] equals:dcm1._mantissa message:"CPDecimalRound() Td2: mantissa"];
  219. [self assert:-2 equals:dcm1._exponent message:"CPDecimalRound() Td2: exponent"];
  220. CPDecimalRound(dcm1,dcm,-2,CPRoundDown);
  221. [self assert:[1] equals:dcm1._mantissa message:"CPDecimalRound() Td3: mantissa"];
  222. [self assert:2 equals:dcm1._exponent message:"CPDecimalRound() Td3: exponent"];
  223. CPDecimalRound(dcm1,dcm,-4,CPRoundDown);
  224. [self assert:[0] equals:dcm1._mantissa message:"CPDecimalRound() Td4: mantissa"];
  225. [self assert:0 equals:dcm1._exponent message:"CPDecimalRound() Td4: exponent"];
  226. CPDecimalRound(dcm1,dcm,6,CPRoundDown);
  227. [self assert:[1,2,3,4,5,6] equals:dcm1._mantissa message:"CPDecimalRound() Td5: mantissa"];
  228. [self assert:-3 equals:dcm1._exponent message:"CPDecimalRound() Td5: exponent"];
  229. // up
  230. CPDecimalRound(dcm1,dcm,0,CPRoundUp);
  231. [self assert:[1,2,4] equals:dcm1._mantissa message:"CPDecimalRound() Tu1: mantissa"];
  232. [self assert:0 equals:dcm1._exponent message:"CPDecimalRound() Tu1: exponent"];
  233. CPDecimalRound(dcm1,dcm,2,CPRoundUp);
  234. [self assert:[1,2,3,4,6] equals:dcm1._mantissa message:"CPDecimalRound() Tu2: mantissa"];
  235. [self assert:-2 equals:dcm1._exponent message:"CPDecimalRound() Tu2: exponent"];
  236. CPDecimalRound(dcm1,dcm,-2,CPRoundUp);
  237. [self assert:[2] equals:dcm1._mantissa message:"CPDecimalRound() Tu3: mantissa"];
  238. [self assert:2 equals:dcm1._exponent message:"CPDecimalRound() Tu3: exponent"];
  239. CPDecimalRound(dcm1,dcm,-4,CPRoundUp);
  240. [self assert:[0] equals:dcm1._mantissa message:"CPDecimalRound() Tu4: mantissa"];
  241. [self assert:0 equals:dcm1._exponent message:"CPDecimalRound() Tu4: exponent"];
  242. CPDecimalRound(dcm1,dcm,6,CPRoundUp);
  243. [self assert:[1,2,3,4,5,6] equals:dcm1._mantissa message:"CPDecimalRound() Tu5: mantissa"];
  244. [self assert:-3 equals:dcm1._exponent message:"CPDecimalRound() Tu5: exponent"];
  245. // bankers
  246. CPDecimalRound(dcm1,dcm,0,CPRoundBankers);
  247. [self assert:[1,2,3] equals:dcm1._mantissa message:"CPDecimalRound() Tb1: mantissa"];
  248. [self assert:0 equals:dcm1._exponent message:"CPDecimalRound() Tb1: exponent"];
  249. CPDecimalRound(dcm1,dcm,2,CPRoundBankers);
  250. [self assert:[1,2,3,4,6] equals:dcm1._mantissa message:"CPDecimalRound() Tb2: mantissa"];
  251. [self assert:-2 equals:dcm1._exponent message:"CPDecimalRound() Tb2: exponent"];
  252. CPDecimalRound(dcm1,dcm,-2,CPRoundBankers);
  253. [self assert:[1] equals:dcm1._mantissa message:"CPDecimalRound() Tb3: mantissa"];
  254. [self assert:2 equals:dcm1._exponent message:"CPDecimalRound() Tb3: exponent"];
  255. CPDecimalRound(dcm1,dcm,-4,CPRoundBankers);
  256. [self assert:[0] equals:dcm1._mantissa message:"CPDecimalRound() Tb4: mantissa"];
  257. [self assert:0 equals:dcm1._exponent message:"CPDecimalRound() Tb4: exponent"];
  258. CPDecimalRound(dcm1,dcm,6,CPRoundBankers);
  259. [self assert:[1,2,3,4,5,6] equals:dcm1._mantissa message:"CPDecimalRound() Tb5: mantissa"];
  260. [self assert:-3 equals:dcm1._exponent message:"CPDecimalRound() Tb5: exponent"];
  261. // Noscale
  262. dcm1 = CPDecimalMakeZero();
  263. CPDecimalRound(dcm1,dcm,CPDecimalNoScale,CPRoundPlain);
  264. [self assert:[1,2,3,4,5,6] equals:dcm1._mantissa message:"CPDecimalRound() Tns1: mantissa"];
  265. [self assert:-3 equals:dcm1._exponent message:"CPDecimalRound() Tns1: exponent"];
  266. }
  267. - (void)testCompare
  268. {
  269. var dcm1 = CPDecimalMakeWithString(@"75836"),
  270. dcm = CPDecimalMakeWithString(@"75836"),
  271. c = CPDecimalCompare(dcm1,dcm);
  272. [self assert:CPOrderedSame equals:c message:"CPDecimalCompare() Tc1: should be same"];
  273. dcm1 = CPDecimalMakeWithString(@"75836");
  274. dcm = CPDecimalMakeWithString(@"75836e-9");
  275. c = CPDecimalCompare(dcm1,dcm);
  276. [self assert:CPOrderedDescending equals:c message:"CPDecimalCompare() Tc2: should be descending"];
  277. dcm1 = CPDecimalMakeWithString(@"823479");
  278. dcm = CPDecimalMakeWithString(@"7082371231252");
  279. c = CPDecimalCompare(dcm1,dcm);
  280. [self assert:CPOrderedAscending equals:c message:"CPDecimalCompare() Tc3: should be descending"];
  281. dcm1 = CPDecimalMakeWithString(@"0.00000000002");
  282. dcm = CPDecimalMakeWithString(@"-1e-9");
  283. c = CPDecimalCompare(dcm1,dcm);
  284. [self assert:CPOrderedDescending equals:c message:"CPDecimalCompare() Tc4: should be descending"];
  285. dcm1 = CPDecimalMakeWithString(@"-23412345123e12");
  286. dcm = CPDecimalMakeWithString(@"-1e100");
  287. c = CPDecimalCompare(dcm1,dcm);
  288. [self assert:CPOrderedDescending equals:c message:"CPDecimalCompare() Tc4: should be descending"];
  289. dcm1 = CPDecimalMakeWithString(@"0.0");
  290. dcm = CPDecimalMakeWithString(@"0.5");
  291. c = CPDecimalCompare(dcm1,dcm);
  292. [self assert:CPOrderedAscending equals:c message:"CPDecimalCompare() (0.0, 0.5) should be ascending"];
  293. dcm1 = CPDecimalMakeWithString(@"0.0");
  294. dcm = CPDecimalMakeWithString(@"-0.5");
  295. c = CPDecimalCompare(dcm1,dcm);
  296. [self assert:CPOrderedDescending equals:c message:"CPDecimalCompare() (0, -0.5) should be descending"];
  297. dcm1 = CPDecimalMakeZero();
  298. dcm = CPDecimalMakeZero();
  299. c = CPDecimalCompare(dcm1,dcm);
  300. [self assert:CPOrderedSame equals:c message:"CPDecimalCompare(): zeros should be same"];
  301. dcm1 = CPDecimalMakeWithString(@"0.0001");
  302. dcm = CPDecimalMakeZero();
  303. c = CPDecimalCompare(dcm1,dcm);
  304. [self assert:CPOrderedDescending equals:c message:"CPDecimalCompare(): (0.0001, 0) should be descending"];
  305. dcm1 = CPDecimalMakeZero();
  306. dcm = CPDecimalMakeWithString(@"0.0001");
  307. c = CPDecimalCompare(dcm1,dcm);
  308. [self assert:CPOrderedAscending equals:c message:"CPDecimalCompare(): (0, 0.0001) should be ascending"];
  309. dcm1 = CPDecimalMakeWithString(@"-0.0001");
  310. dcm = CPDecimalMakeZero();
  311. c = CPDecimalCompare(dcm1,dcm);
  312. [self assert:CPOrderedAscending equals:c message:"CPDecimalCompare(): (-0.0001, 0) should be ascending"];
  313. dcm1 = CPDecimalMakeZero();
  314. dcm = CPDecimalMakeWithString(@"-0.0001");
  315. c = CPDecimalCompare(dcm1,dcm);
  316. [self assert:CPOrderedDescending equals:c message:"CPDecimalCompare(): (0, -0.0001) should be descending"];
  317. }
  318. - (void)testCompact
  319. {
  320. var dcm = CPDecimalMakeZero();
  321. dcm._mantissa = [0,0,0,0, 1,0,0,0,0, 1];
  322. dcm._exponent = 2;
  323. CPDecimalCompact(dcm);
  324. [self assert:2 equals:dcm._exponent message:"CPDecimalCompact() Tcm1: exponent"];
  325. [self assert:[1,0,0,0,0, 1] equals:dcm._mantissa message:"CPDecimalCompact() Tcm1: mantissa"];
  326. dcm = CPDecimalMakeZero();
  327. dcm._mantissa = [0,0,0,0, 1,2,0,0,0,0];
  328. dcm._exponent = -4;
  329. dcm._isNegative = YES;
  330. CPDecimalCompact(dcm);
  331. [self assert:0 equals:dcm._exponent message:"CPDecimalCompact() Tcm2: exponent"];
  332. [self assert:[1,2] equals:dcm._mantissa message:"CPDecimalCompact() Tcm2: mantissa"];
  333. [self assert:YES equals:dcm._isNegative message:"CPDecimalCompact() Tcm2: sign"];
  334. dcm = CPDecimalMakeZero();
  335. dcm._mantissa = [1,2,0,0,0,0];
  336. dcm._exponent = -1;
  337. CPDecimalCompact(dcm);
  338. [self assert:3 equals:dcm._exponent message:"CPDecimalCompact() Tcm3: exponent"];
  339. [self assert:[1,2] equals:dcm._mantissa message:"CPDecimalCompact() Tcm3: mantissa"];
  340. [self assert:NO equals:dcm._isNegative message:"CPDecimalCompact() Tcm3: sign"];
  341. [self assert:NO equals:dcm._isNaN message:"CPDecimalCompact() Tcm3: NaN is incorrectly set"];
  342. dcm = CPDecimalMakeZero();
  343. dcm._mantissa = [8,9,0,0,0,0, 1,2,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
  344. dcm._exponent = -20;
  345. dcm._isNegative = YES;
  346. CPDecimalCompact(dcm);
  347. [self assert:-5 equals:dcm._exponent message:"CPDecimalCompact() Tcm4: exponent"];
  348. [self assert:[8,9,0,0,0,0, 1,2,3] equals:dcm._mantissa message:"CPDecimalCompact() Tcm4: mantissa"];
  349. [self assert:YES equals:dcm._isNegative message:"CPDecimalCompact() Tcm4: sign"];
  350. [self assert:NO equals:dcm._isNaN message:"CPDecimalCompact() Tcm4: NaN is incorrectly set"];
  351. }
  352. - (void)testAdd
  353. {
  354. // test addition of positives
  355. var d1 = CPDecimalMakeWithString(@"1"),
  356. d2 = CPDecimalMakeWithParts(1, 0),
  357. dcm = CPDecimalMakeZero(),
  358. i = 50;
  359. while (i--)
  360. [self assert:CPDecimalAdd(d1, d1, d2, CPRoundPlain) equals:CPCalculationNoError message:"CPDecimalAdd() Tap1: addition"];
  361. [self assert:0 equals:d1._exponent message:"CPDecimalAdd() Tap1: exponent"];
  362. [self assert:[5, 1] equals:d1._mantissa message:"CPDecimalAdd() Tap1: mantissa"];
  363. [self assert:NO equals:d1._isNegative message:"CPDecimalAdd() Tap1: sign"];
  364. [self assert:NO equals:d1._isNaN message:"CPDecimalAdd() Tap1: NaN is incorrectly set"];
  365. // test addition with negatives
  366. d1 = CPDecimalMakeWithString(@"-1");
  367. d2 = CPDecimalMakeWithString(@"-1e-10");
  368. [self assert:CPCalculationNoError equals:CPDecimalAdd(d1, d1, d2, CPRoundPlain) message:"CPDecimalAdd() Tan1: addition of 2 negatives"];
  369. [self assert:-10 equals:d1._exponent message:"CPDecimalAdd() Tan1: exponent"];
  370. [self assert:[1,0,0,0,0,0,0,0,0,0, 1] equals:d1._mantissa message:"CPDecimalAdd() Tan1: mantissa"];
  371. [self assert:YES equals:d1._isNegative message:"CPDecimalAdd() Tan1: sign"];
  372. [self assert:NO equals:d1._isNaN message:"CPDecimalAdd() Tan1: NaN is incorrectly set"];
  373. d1 = CPDecimalMakeWithString(@"-5");
  374. d2 = CPDecimalMakeWithString(@"11");
  375. [self assert:CPCalculationNoError equals:CPDecimalAdd(d1, d1, d2, CPRoundPlain) message:"CPDecimalAdd() Tan2: addition with negatives"];
  376. [self assert:0 equals:d1._exponent message:"CPDecimalAdd() Tan2: exponent"];
  377. [self assert:[6] equals:d1._mantissa message:"CPDecimalAdd() Tan2: mantissa"];
  378. [self assert:NO equals:d1._isNegative message:"CPDecimalAdd() Tan2: sign"];
  379. [self assert:NO equals:d1._isNaN message:"CPDecimalAdd() Tan2: NaN is incorrectly set"];
  380. d1 = CPDecimalMakeWithString(@"11");
  381. d2 = CPDecimalMakeWithString(@"-12");
  382. [self assert:CPCalculationNoError equals:CPDecimalAdd(d1, d1, d2, CPRoundPlain) message:"CPDecimalAdd() Tan3: addition with negatives"];
  383. [self assert:0 equals:d1._exponent message:"CPDecimalAdd() Tan3: exponent"];
  384. [self assert:[1] equals:d1._mantissa message:"CPDecimalAdd() Tan3: mantissa"];
  385. [self assert:YES equals:d1._isNegative message:"CPDecimalAdd() Tan3: sign"];
  386. [self assert:NO equals:d1._isNaN message:"CPDecimalAdd() Tan3: NaN is incorrectly set"];
  387. // FIXME: test mantissa overflow handling - is there a loss of precision?? not according to gnustep - check cocoa!!!! CPCalculationLossOfPrecision?
  388. d1 = CPDecimalMakeWithString(@"12345");
  389. d2 = CPDecimalMakeWithString(@"99999999999999999999999999999999999999");
  390. [self assert:0 equals:CPDecimalAdd(d1, d1, d2, CPRoundPlain) message:"CPDecimalAdd() Tapc1: addition with mantissa overflow and rounding"];
  391. [self assert:1 equals:d1._exponent message:"CPDecimalAdd() Tapc1: exponent"];
  392. [self assert:[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1,2,3,4] equals:d1._mantissa message:"CPDecimalAdd() Tapc1: mantissa"];
  393. [self assert:NO equals:d1._isNegative message:"CPDecimalAdd() Tapc1: sign"];
  394. [self assert:NO equals:d1._isNaN message:"CPDecimalAdd() Tapc1: NaN is incorrectly set"];
  395. d1 = CPDecimalMakeWithString(@"1e127");
  396. d2 = CPDecimalMakeWithString(@"99999999999999999999999999999999999999");
  397. [self assert:CPDecimalAdd(d1, d1, d2, CPRoundPlain) equals:CPCalculationLossOfPrecision message:"CPDecimalAdd() Tapc2: addition loss of precision"];
  398. // Overflow
  399. d1 = CPDecimalMakeWithString(@"1e127");
  400. d2 = CPDecimalMakeWithString(@"99999999999999999999999999999999999999e127");
  401. [self assert:CPDecimalAdd(d1, d1, d2, CPRoundPlain) equals:CPCalculationOverflow message:"CPDecimalAdd() Tao1: addition loss of precision"];
  402. }
  403. - (void)testSubtract
  404. {
  405. var d1 = CPDecimalMakeZero(),
  406. d2 = CPDecimalMakeWithString(@"0.875"),
  407. d3 = CPDecimalMakeWithString(@"12.67");
  408. [self assert:CPCalculationNoError equals:CPDecimalSubtract(d1,d2,d3,CPRoundPlain) message:"CPDecimalSubtract(): Ts1: Should succeed"];
  409. [self assert:-3 equals:d1._exponent message:"CPDecimalSubtract(): Ts1: exponent"];
  410. [self assert:[1, 1,7,9,5] equals:d1._mantissa message:"CPDecimalSubtract(): Ts1: mantissa"];
  411. [self assert:YES equals:d1._isNegative message:"CPDecimalSubtract(): Ts1: sign"];
  412. [self assert:NO equals:d1._isNaN message:"CPDecimalSubtract(): Ts1: NaN is incorrectly set"];
  413. d1 = CPDecimalMakeZero();
  414. d2 = CPDecimalMakeWithString(@"-0.875");
  415. d3 = CPDecimalMakeWithString(@"-12.67");
  416. [self assert:CPCalculationNoError equals:CPDecimalSubtract(d1,d2,d3,CPRoundPlain) message:"CPDecimalSubtract(): Ts2: Should succeed"];
  417. [self assert:-3 equals:d1._exponent message:"CPDecimalSubtract(): Ts2: exponent"];
  418. [self assert:[1, 1,7,9,5] equals:d1._mantissa message:"CPDecimalSubtract(): Ts2: mantissa"];
  419. [self assert:NO equals:d1._isNegative message:"CPDecimalSubtract(): Ts2: sign"];
  420. [self assert:NO equals:d1._isNaN message:"CPDecimalSubtract(): Ts2: NaN is incorrectly set"];
  421. d1 = CPDecimalMakeZero();
  422. d2 = CPDecimalMakeWithString(@"-0.875");
  423. d3 = CPDecimalMakeWithString(@"12.67e2");
  424. [self assert:CPCalculationNoError equals:CPDecimalSubtract(d1,d2,d3,CPRoundPlain) message:"CPDecimalSubtract(): Ts3: Should succeed"];
  425. [self assert:-3 equals:d1._exponent message:"CPDecimalSubtract(): Ts3: exponent"];
  426. [self assert:[1,2,6,7,8,7,5] equals:d1._mantissa message:"CPDecimalSubtract(): Ts3: mantissa"];
  427. [self assert:YES equals:d1._isNegative message:"CPDecimalSubtract(): Ts3: sign"];
  428. [self assert:NO equals:d1._isNaN message:"CPDecimalSubtract(): Ts3: NaN is incorrectly set"];
  429. d1 = CPDecimalMakeZero();
  430. d2 = CPDecimalMakeWithString(@"0.875");
  431. d3 = CPDecimalMakeWithString(@"-12.67");
  432. [self assert:CPCalculationNoError equals:CPDecimalSubtract(d1,d2,d3,CPRoundPlain) message:"CPDecimalSubtract(): Ts4: Should succeed"];
  433. [self assert:-3 equals:d1._exponent message:"CPDecimalSubtract(): Ts4: exponent"];
  434. [self assert:[1,3,5,4,5] equals:d1._mantissa message:"CPDecimalSubtract(): Ts4: mantissa"];
  435. [self assert:NO equals:d1._isNegative message:"CPDecimalSubtract(): Ts4: sign"];
  436. [self assert:NO equals:d1._isNaN message:"CPDecimalSubtract(): Ts4: NaN is incorrectly set"];
  437. // loss of precision
  438. d1 = CPDecimalMakeZero();
  439. d2 = CPDecimalMakeWithString(@"1e-128");
  440. d3 = CPDecimalMakeWithString(@"1");
  441. [self assert:CPCalculationLossOfPrecision equals:CPDecimalSubtract(d1,d2,d3,CPRoundPlain) message:"CPDecimalSubtract(): Tsp1: Should throw loss of precision"];
  442. [self assert:0 equals:d1._exponent message:"CPDecimalSubtract(): Tsp1: exponent"];
  443. [self assert:[1] equals:d1._mantissa message:"CPDecimalSubtract(): Tsp1: mantissa"];
  444. [self assert:YES equals:d1._isNegative message:"CPDecimalSubtract(): Tsp1: sign"];
  445. [self assert:NO equals:d1._isNaN message:"CPDecimalSubtract(): Tsp1: NaN is incorrectly set"];
  446. }
  447. - (void)testDivide
  448. {
  449. var d1 = CPDecimalMakeZero(),
  450. d2 = CPDecimalMakeWithString(@"55e12"),
  451. d3 = CPDecimalMakeWithString(@"-5e20");
  452. [self assert:CPCalculationNoError equals:CPDecimalDivide(d1,d2,d3,CPRoundPlain) message:"CPDecimalDivide(): Td1: Should succeed"];
  453. [self assert:-8 equals:d1._exponent message:"CPDecimalDivide(): Td1: exponent"];
  454. [self assert:[1, 1] equals:d1._mantissa message:"CPDecimalDivide(): Td1: mantissa"];
  455. [self assert:YES equals:d1._isNegative message:"CPDecimalDivide(): Td1: sign"];
  456. [self assert:NO equals:d1._isNaN message:"CPDecimalDivide(): Td1: NaN is incorrectly set"];
  457. d1 = CPDecimalMakeZero();
  458. d2 = CPDecimalMakeWithString(@"-1e12");
  459. d3 = CPDecimalMakeWithString(@"-1e6");
  460. [self assert:CPCalculationNoError equals:CPDecimalDivide(d1,d2,d3,CPRoundPlain) message:"CPDecimalDivide(): Td2: Should succeed"];
  461. [self assert:6 equals:d1._exponent message:"CPDecimalDivide(): Td2: exponent"];
  462. [self assert:[1] equals:d1._mantissa message:"CPDecimalDivide(): Td2: mantissa"];
  463. [self assert:NO equals:d1._isNegative message:"CPDecimalDivide(): Td2: sign"];
  464. [self assert:NO equals:d1._isNaN message:"CPDecimalDivide(): Td2: NaN is incorrectly set"];
  465. d1 = CPDecimalMakeZero();
  466. d2 = CPDecimalMakeWithString(@"1");
  467. d3 = CPDecimalMakeWithString(@"0.00001");
  468. [self assert:CPCalculationNoError equals:CPDecimalDivide(d1,d2,d3,CPRoundPlain) message:"CPDecimalDivide(): Td3: Should succeed"];
  469. [self assert:5 equals:d1._exponent message:"CPDecimalDivide(): Td3: exponent"];
  470. [self assert:[1] equals:d1._mantissa message:"CPDecimalDivide(): Td3: mantissa"];
  471. [self assert:NO equals:d1._isNegative message:"CPDecimalDivide(): Td3: sign"];
  472. [self assert:NO equals:d1._isNaN message:"CPDecimalDivide(): Td3: NaN is incorrectly set"];
  473. d1 = CPDecimalMakeZero();
  474. d2 = CPDecimalMakeWithString(@"1");
  475. d3 = CPDecimalMakeWithString(@"3");
  476. [self assert:CPCalculationLossOfPrecision equals:CPDecimalDivide(d1,d2,d3,CPRoundPlain) message:"CPDecimalDivide(): Tdp1: Should Loss of precision"];
  477. [self assert:-38 equals:d1._exponent message:"CPDecimalDivide(): Tdp1: exponent"];
  478. [self assert:[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3] equals:d1._mantissa message:"CPDecimalDivide(): Tdp1: mantissa"];
  479. [self assert:NO equals:d1._isNegative message:"CPDecimalDivide(): Tdp1: sign"];
  480. [self assert:NO equals:d1._isNaN message:"CPDecimalDivide(): Tdp1: NaN is incorrectly set"];
  481. // Why doesnt Cocoa round the final digit up?
  482. d1 = CPDecimalMakeZero();
  483. d2 = CPDecimalMakeWithString(@"-0.875");
  484. d3 = CPDecimalMakeWithString(@"12");
  485. [self assert:CPCalculationLossOfPrecision equals:CPDecimalDivide(d1,d2,d3,CPRoundUp) message:"CPDecimalDivide(): Tdp2: Should Loss of precision"];
  486. [self assert:-39 equals:d1._exponent message:"CPDecimalDivide(): Td2: exponent"];
  487. [self assert:[7,2,9, 1,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6] equals:d1._mantissa message:"CPDecimalDivide(): Td2: mantissa"];
  488. [self assert:YES equals:d1._isNegative message:"CPDecimalDivide(): Td2: sign"];
  489. [self assert:NO equals:d1._isNaN message:"CPDecimalDivide(): Td2: NaN is incorrectly set"];
  490. // div zero
  491. d1 = CPDecimalMakeZero();
  492. d2 = CPDecimalMakeWithString(@"-0.875");
  493. d3 = CPDecimalMakeWithString(@"0");
  494. [self assert:CPCalculationDivideByZero equals:CPDecimalDivide(d1,d2,d3,CPRoundUp) message:"CPDecimalDivide(): Tdp2: Should Loss of precision"];
  495. d1 = CPDecimalMakeZero();
  496. d2 = CPDecimalMakeWithString(@"11");
  497. d3 = CPDecimalMakeWithString(@"11");
  498. [self assert:CPCalculationNoError equals:CPDecimalDivide(d1, d2, d3, CPRoundPlain) message:"CPDecimalDivide(): Td4: Should succeed"];
  499. [self assert:0 equals:d1._exponent message:"CPDecimalDivide(): Td4: exponent"];
  500. [self assert:[1] equals:d1._mantissa message:"CPDecimalDivide(): Td4: mantissa"];
  501. [self assert:NO equals:d1._isNegative message:"CPDecimalDivide(): Td4: sign"];
  502. [self assert:NO equals:d1._isNaN message:"CPDecimalDivide(): Td4: NaN is incorrectly set"];
  503. }
  504. - (void)testMultiply
  505. {
  506. var d1 = CPDecimalMakeZero(),
  507. d2 = CPDecimalMakeWithString(@"12"),
  508. d3 = CPDecimalMakeWithString(@"-1441231251321235231");
  509. [self assert:CPCalculationNoError equals:CPDecimalMultiply(d1,d2,d3,CPRoundPlain) message:"CPDecimalMultiply(): Tm1: Should succeed"];
  510. [self assert:0 equals:d1._exponent message:"CPDecimalMultiply(): Tm1: exponent"];
  511. [self assert:[1,7,2,9,4,7,7,5,0, 1,5,8,5,4,8,2,2,7,7,2] equals:d1._mantissa message:"CPDecimalMultiply(): Tm1: mantissa"];
  512. [self assert:YES equals:d1._isNegative message:"CPDecimalMultiply(): Tm1: sign"];
  513. [self assert:NO equals:d1._isNaN message:"CPDecimalMultiply(): Tm1: NaN is incorrectly set"];
  514. d1 = CPDecimalMakeZero();
  515. d2 = CPDecimalMakeWithString(@"23e100");
  516. d3 = CPDecimalMakeWithString(@"-13e-76");
  517. [self assert:CPCalculationNoError equals:CPDecimalMultiply(d1,d2,d3,CPRoundPlain) message:"CPDecimalMultiply(): Tm2: Should succeed"];
  518. [self assert:24 equals:d1._exponent message:"CPDecimalMultiply(): Tm2: exponent"];
  519. [self assert:[2,9,9] equals:d1._mantissa message:"CPDecimalMultiply(): Tm2: mantissa"];
  520. [self assert:YES equals:d1._isNegative message:"CPDecimalMultiply(): Tm2: sign"];
  521. [self assert:NO equals:d1._isNaN message:"CPDecimalMultiply(): Tm2: NaN is incorrectly set"];
  522. d1 = CPDecimalMakeZero();
  523. d2 = CPDecimalMakeWithString(@"-0.8888");
  524. d3 = CPDecimalMakeWithString(@"8.88e2");
  525. [self assert:CPCalculationNoError equals:CPDecimalMultiply(d1,d2,d3,CPRoundPlain) message:"CPDecimalMultiply(): Tm3: Should succeed"];
  526. [self assert:-4 equals:d1._exponent message:"CPDecimalMultiply(): Tm3: exponent"];
  527. [self assert:[7,8,9,2,5,4,4] equals:d1._mantissa message:"CPDecimalMultiply(): Tm3: mantissa"];
  528. [self assert:YES equals:d1._isNegative message:"CPDecimalMultiply(): Tm3: sign"];
  529. [self assert:NO equals:d1._isNaN message:"CPDecimalMultiply(): Tm3: NaN is incorrectly set"];
  530. d1 = CPDecimalMakeZero();
  531. d2 = CPDecimalMakeWithString(@"-1e111");
  532. d3 = CPDecimalMakeWithString(@"-1e-120");
  533. [self assert:CPCalculationNoError equals:CPDecimalMultiply(d1,d2,d3,CPRoundPlain) message:"CPDecimalMultiply(): Tm4: Should succeed"];
  534. [self assert:-9 equals:d1._exponent message:"CPDecimalMultiply(): Tm4: exponent"];
  535. [self assert:[1] equals:d1._mantissa message:"CPDecimalMultiply(): Tm4: mantissa"];
  536. [self assert:NO equals:d1._isNegative message:"CPDecimalMultiply(): Tm4: sign"];
  537. [self assert:NO equals:d1._isNaN message:"CPDecimalMultiply(): Tm4: NaN is incorrectly set"];
  538. // loss of precision
  539. d1 = CPDecimalMakeZero();
  540. d2 = CPDecimalMakeWithString(@"212341251123892374823742638472481124");
  541. d3 = CPDecimalMakeWithString(@"127889465810478913");
  542. [self assert:CPCalculationLossOfPrecision equals:CPDecimalMultiply(d1,d2,d3,CPRoundDown) message:"CPDecimalMultiply(): Tmp1: Should throw loss of precision"];
  543. [self assert:15 equals:d1._exponent message:"CPDecimalMultiply(): Tmp1: exponent"]; // 69 diff
  544. [self assert:[2,7, 1,5,6,2,0,9, 1,7,5,7,6,3,3,5,0,9,2,9,7,4,0,2,3,5,6,0,8,0,6,9,5,2,8,3,9, 1] equals:d1._mantissa message:"CPDecimalMultiply(): Tmp1: mantissa"];
  545. [self assert:NO equals:d1._isNegative message:"CPDecimalMultiply(): Tmp1: sign"];
  546. [self assert:NO equals:d1._isNaN message:"CPDecimalMultiply(): Tmp1: NaN is incorrectly set"];
  547. // overflow
  548. d1 = CPDecimalMakeZero();
  549. d2 = CPDecimalMakeWithString(@"1e110");
  550. d3 = CPDecimalMakeWithString(@"1e111");
  551. [self assert:CPCalculationOverflow equals:CPDecimalMultiply(d1,d2,d3,CPRoundDown) message:"CPDecimalMultiply(): Tmo1: Should throw overflow"];
  552. [self assert:YES equals:d1._isNaN message:"CPDecimalMultiply(): Tmo1: NaN is incorrectly set"];
  553. }
  554. // Power is unsigned
  555. - (void)testPower
  556. {
  557. var d1 = CPDecimalMakeZero(),
  558. d2 = CPDecimalMakeWithString(@"123"),
  559. d3 = 12;
  560. [self assert:CPCalculationNoError equals:CPDecimalPower(d1,d2,d3,CPRoundPlain) message:"CPDecimalPower(): Tp1: Should succeed"];
  561. [self assert:0 equals:d1._exponent message:"CPDecimalPower(): Tp1: exponent"];
  562. [self assert:[1, 1,9,9, 1, 1,6,3,8,4,8,7, 1,6,9,0,6,2,9,7,0,7,2,7,2, 1] equals:d1._mantissa message:"CPDecimalPower(): Tp1: mantissa"];
  563. [self assert:NO equals:d1._isNegative message:"CPDecimalPower(): Tp1: sign"];
  564. [self assert:NO equals:d1._isNaN message:"CPDecimalPower(): Tp1: NaN is incorrectly set"];
  565. //0.00000 13893554059925661274821814636807535200 1 cocoa (39 digits)
  566. //0.00000 13893554059925661274821814636807535204 This , a few off
  567. d1 = CPDecimalMakeZero();
  568. d2 = CPDecimalMakeWithString(@"0.875");
  569. d3 = 101;
  570. [self assert:CPCalculationLossOfPrecision equals:CPDecimalPower(d1,d2,d3,CPRoundUp) message:"CPDecimalPower(): Tp2: Should throw Loss of precision"];
  571. [self assert:-43 equals:d1._exponent message:"CPDecimalPower(): Tp2: exponent"];
  572. [self assert:[1,3,8,9,3,5,5,4,0,5,9,9,2,5,6,6, 1,2,7,4,8,2, 1,8, 1,4,6,3,6,8,0,7,5,3,5,2,0,4] equals:d1._mantissa message:"CPDecimalPower(): Tp2: mantissa"];
  573. [self assert:NO equals:d1._isNegative message:"CPDecimalPower(): Tp2: sign"];
  574. [self assert:NO equals:d1._isNaN message:"CPDecimalPower(): Tp2: NaN is incorrectly set"];
  575. }
  576. - (void)testPower10
  577. {
  578. var d1 = CPDecimalMakeZero(),
  579. d2 = CPDecimalMakeWithString(@"-0.875"),
  580. d3 = 3;
  581. [self assert:CPCalculationNoError equals:CPDecimalMultiplyByPowerOf10(d1,d2,d3,CPRoundPlain) message:"CPDecimalMultiplyByPowerOf10(): Tpp1: Should succeed"];
  582. [self assert:0 equals:d1._exponent message:"CPDecimalMultiplyByPowerOf10(): Tpp1: exponent"];
  583. [self assert:[8,7,5] equals:d1._mantissa message:"CPDecimalMultiplyByPowerOf10(): Tpp1: mantissa"];
  584. [self assert:YES equals:d1._isNegative message:"CPDecimalMultiplyByPowerOf10(): Tpp1: sign"];
  585. [self assert:NO equals:d1._isNaN message:"CPDecimalMultiplyByPowerOf10(): Tpp1: NaN is incorrectly set"];
  586. d1 = CPDecimalMakeZero();
  587. d2 = CPDecimalMakeWithString(@"1e-120");
  588. d3 = 130;
  589. [self assert:CPCalculationNoError equals:CPDecimalMultiplyByPowerOf10(d1,d2,d3,CPRoundPlain) message:"CPDecimalMultiplyByPowerOf10(): Tpp2: Should succeed"];
  590. [self assert:10 equals:d1._exponent message:"CPDecimalMultiplyByPowerOf10(): Tpp2: exponent"];
  591. [self assert:[1] equals:d1._mantissa message:"CPDecimalMultiplyByPowerOf10(): Tpp2: mantissa"];
  592. [self assert:NO equals:d1._isNegative message:"CPDecimalMultiplyByPowerOf10(): Tpp2: sign"];
  593. [self assert:NO equals:d1._isNaN message:"CPDecimalMultiplyByPowerOf10(): Tpp2: NaN is incorrectly set"];
  594. }
  595. - (void)testString
  596. {
  597. var dcm = CPDecimalMakeWithString(@"0.00123");
  598. [self assert:"0.00123" equals:CPDecimalString(dcm,nil) message:"CPDecimalString() Ts1"];
  599. dcm = CPDecimalMakeWithString(@"2e3");
  600. [self assert:"2000" equals:CPDecimalString(dcm,nil) message:"CPDecimalString() Ts2"];
  601. dcm = CPDecimalMakeWithString(@"0.00876e-5");
  602. [self assert:"0.0000000876" equals:CPDecimalString(dcm,nil) message:"CPDecimalString() Ts3"];
  603. dcm = CPDecimalMakeWithString(@"98.56e10");
  604. [self assert:"985600000000" equals:CPDecimalString(dcm,nil) message:"CPDecimalString() Ts4"];
  605. dcm = CPDecimalMakeWithString(@"-1e-1");
  606. [self assert:"-0.1" equals:CPDecimalString(dcm,nil) message:"CPDecimalString() Ts5"];
  607. dcm = CPDecimalMakeWithString(@"-5e20");
  608. [self assert:"-500000000000000000000" equals:CPDecimalString(dcm,nil) message:"CPDecimalString() Ts6"];
  609. }
  610. @end