PageRenderTime 56ms CodeModel.GetById 44ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 0ms

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