View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.math4.legacy.core.dfp;
19  
20  import org.junit.After;
21  import org.junit.Assert;
22  import org.junit.Before;
23  import org.junit.Test;
24  
25  public class DfpMathTest {
26  
27      private DfpField factory;
28      private Dfp pinf;
29      private Dfp ninf;
30      private Dfp nan;
31      private Dfp qnan;
32  
33      @Before
34      public void setUp() {
35          // Some basic setup.  Define some constants and clear the status flags
36          factory = new DfpField(20);
37          pinf = factory.newDfp("1").divide(factory.newDfp("0"));
38          ninf = factory.newDfp("-1").divide(factory.newDfp("0"));
39          nan = factory.newDfp("0").divide(factory.newDfp("0"));
40          qnan = factory.newDfp((byte)1, Dfp.QNAN);
41          ninf.getField().clearIEEEFlags();
42  
43          // force loading of dfpmath
44          Dfp pi = factory.getPi();
45          pi.getField().clearIEEEFlags();
46      }
47  
48      @After
49      public void tearDown() {
50          pinf = null;
51          ninf = null;
52          nan  = null;
53          qnan = null;
54      }
55  
56      // Generic test function.  Takes params x and y and tests them for
57      // equality.  Then checks the status flags against the flags argument.
58      // If the test fail, it prints the desc string
59      private void test(Dfp x, Dfp y, int flags, String desc) {
60          boolean b = x.equals(y);
61  
62          if (!x.equals(y) && !x.unequal(y)) { // NaNs involved
63              b = x.toString().equals(y.toString());
64          }
65  
66          if (x.equals(factory.newDfp("0"))) { // distinguish +/- zero
67              b = b && (x.toString().equals(y.toString()));
68          }
69  
70          b = b && x.getField().getIEEEFlags() == flags;
71  
72          if (!b) {
73              Assert.assertTrue(
74                  "assertion failed " + desc + " x = " + x.toString() + " flags = " + x.getField().getIEEEFlags(), b);
75          }
76  
77          x.getField().clearIEEEFlags();
78      }
79  
80      @Test
81      public void testPow() {
82          // Test special cases exponent of zero
83          test(DfpMath.pow(factory.newDfp("0"), factory.newDfp("0")),
84               factory.newDfp("1"),
85               0, "pow #1");
86  
87          test(DfpMath.pow(factory.newDfp("0"), factory.newDfp("-0")),
88               factory.newDfp("1"),
89               0, "pow #2");
90  
91          test(DfpMath.pow(factory.newDfp("2"), factory.newDfp("0")),
92               factory.newDfp("1"),
93               0, "pow #3");
94  
95          test(DfpMath.pow(factory.newDfp("-2"), factory.newDfp("-0")),
96               factory.newDfp("1"),
97               0, "pow #4");
98  
99          test(DfpMath.pow(pinf, factory.newDfp("-0")),
100              factory.newDfp("1"),
101              0, "pow #5");
102 
103         test(DfpMath.pow(pinf, factory.newDfp("0")),
104              factory.newDfp("1"),
105              0, "pow #6");
106 
107         test(DfpMath.pow(ninf, factory.newDfp("-0")),
108              factory.newDfp("1"),
109              0, "pow #7");
110 
111         test(DfpMath.pow(ninf, factory.newDfp("0")),
112              factory.newDfp("1"),
113              0, "pow #8");
114 
115         test(DfpMath.pow(qnan, factory.newDfp("0")),
116              factory.newDfp("1"),
117              0, "pow #8");
118 
119         // exponent of one
120         test(DfpMath.pow(factory.newDfp("0"), factory.newDfp("1")),
121              factory.newDfp("0"),
122              0, "pow #9");
123 
124         test(DfpMath.pow(factory.newDfp("-0"), factory.newDfp("1")),
125              factory.newDfp("-0"),
126              0, "pow #10");
127 
128         test(DfpMath.pow(factory.newDfp("2"), factory.newDfp("1")),
129              factory.newDfp("2"),
130              0, "pow #11");
131 
132         test(DfpMath.pow(factory.newDfp("-2"), factory.newDfp("1")),
133              factory.newDfp("-2"),
134              0, "pow #12");
135 
136         test(DfpMath.pow(pinf, factory.newDfp("1")),
137              pinf,
138              0, "pow #13");
139 
140         test(DfpMath.pow(ninf, factory.newDfp("1")),
141              ninf,
142              0, "pow #14");
143 
144         test(DfpMath.pow(qnan, factory.newDfp("1")),
145              qnan,
146              DfpField.FLAG_INVALID, "pow #14.1");
147 
148         // exponent of NaN
149         test(DfpMath.pow(factory.newDfp("0"), qnan),
150              qnan,
151              DfpField.FLAG_INVALID, "pow #15");
152 
153         test(DfpMath.pow(factory.newDfp("-0"), qnan),
154              qnan,
155              DfpField.FLAG_INVALID, "pow #16");
156 
157         test(DfpMath.pow(factory.newDfp("2"), qnan),
158              qnan,
159              DfpField.FLAG_INVALID, "pow #17");
160 
161         test(DfpMath.pow(factory.newDfp("-2"), qnan),
162              qnan,
163              DfpField.FLAG_INVALID, "pow #18");
164 
165         test(DfpMath.pow(pinf, qnan),
166              qnan,
167              DfpField.FLAG_INVALID, "pow #19");
168 
169         test(DfpMath.pow(ninf, qnan),
170              qnan,
171              DfpField.FLAG_INVALID, "pow #20");
172 
173         test(DfpMath.pow(qnan, qnan),
174              qnan,
175              DfpField.FLAG_INVALID, "pow #21");
176 
177         // radix of NaN
178         test(DfpMath.pow(qnan, factory.newDfp("1")),
179              qnan,
180              DfpField.FLAG_INVALID, "pow #22");
181 
182         test(DfpMath.pow(qnan, factory.newDfp("-1")),
183              qnan,
184              DfpField.FLAG_INVALID, "pow #23");
185 
186         test(DfpMath.pow(qnan, pinf),
187              qnan,
188              DfpField.FLAG_INVALID, "pow #24");
189 
190         test(DfpMath.pow(qnan, ninf),
191              qnan,
192              DfpField.FLAG_INVALID, "pow #25");
193 
194         test(DfpMath.pow(qnan, qnan),
195              qnan,
196              DfpField.FLAG_INVALID, "pow #26");
197 
198         // (x > 1) ^ pinf = pinf,    (x < -1) ^ pinf = pinf
199         test(DfpMath.pow(factory.newDfp("2"), pinf),
200              pinf,
201              0, "pow #27");
202 
203         test(DfpMath.pow(factory.newDfp("-2"), pinf),
204              pinf,
205              0, "pow #28");
206 
207         test(DfpMath.pow(pinf, pinf),
208              pinf,
209              0, "pow #29");
210 
211         test(DfpMath.pow(ninf, pinf),
212              pinf,
213              0, "pow #30");
214 
215         // (x > 1) ^ ninf = +0,    (x < -1) ^ ninf = +0
216         test(DfpMath.pow(factory.newDfp("2"), ninf),
217              factory.getZero(),
218              0, "pow #31");
219 
220         test(DfpMath.pow(factory.newDfp("-2"), ninf),
221              factory.getZero(),
222              0, "pow #32");
223 
224         test(DfpMath.pow(pinf, ninf),
225              factory.getZero(),
226              0, "pow #33");
227 
228         test(DfpMath.pow(ninf, ninf),
229              factory.getZero(),
230              0, "pow #34");
231 
232         // (-1 < x < 1) ^ pinf = 0
233         test(DfpMath.pow(factory.newDfp("0.5"), pinf),
234              factory.getZero(),
235              0, "pow #35");
236 
237         test(DfpMath.pow(factory.newDfp("-0.5"), pinf),
238              factory.getZero(),
239              0, "pow #36");
240 
241         // (-1 < x < 1) ^ ninf = pinf
242         test(DfpMath.pow(factory.newDfp("0.5"), ninf),
243              pinf,
244              0, "pow #37");
245 
246         test(DfpMath.pow(factory.newDfp("-0.5"), ninf),
247              pinf,
248              0, "pow #38");
249 
250         // +/- 1  ^ +/-inf  = NaN
251         test(DfpMath.pow(factory.getOne(), pinf),
252              qnan,
253              DfpField.FLAG_INVALID, "pow #39");
254 
255         test(DfpMath.pow(factory.getOne(), ninf),
256              qnan,
257              DfpField.FLAG_INVALID, "pow #40");
258 
259         test(DfpMath.pow(factory.newDfp("-1"), pinf),
260              qnan,
261              DfpField.FLAG_INVALID, "pow #41");
262 
263         test(DfpMath.pow(factory.getOne().negate(), ninf),
264              qnan,
265              DfpField.FLAG_INVALID, "pow #42");
266 
267         // +0  ^ +anything except 0, NAN  = +0
268 
269         test(DfpMath.pow(factory.newDfp("0"), factory.newDfp("1")),
270              factory.newDfp("0"),
271              0, "pow #43");
272 
273         test(DfpMath.pow(factory.newDfp("0"), factory.newDfp("1e30")),
274              factory.newDfp("0"),
275              0, "pow #44");
276 
277         test(DfpMath.pow(factory.newDfp("0"), factory.newDfp("1e-30")),
278              factory.newDfp("0"),
279              0, "pow #45");
280 
281         test(DfpMath.pow(factory.newDfp("0"), pinf),
282              factory.newDfp("0"),
283              0, "pow #46");
284 
285         // -0  ^ +anything except 0, NAN, odd integer  = +0
286 
287         test(DfpMath.pow(factory.newDfp("-0"), factory.newDfp("2")),
288              factory.newDfp("0"),
289              0, "pow #47");
290 
291         test(DfpMath.pow(factory.newDfp("-0"), factory.newDfp("1e30")),
292              factory.newDfp("0"),
293              0, "pow #48");
294 
295         test(DfpMath.pow(factory.newDfp("-0"), factory.newDfp("1e-30")),
296              factory.newDfp("0"),
297              DfpField.FLAG_INEXACT, "pow #49");
298 
299         test(DfpMath.pow(factory.newDfp("-0"), pinf),
300              factory.newDfp("0"),
301              0, "pow #50");
302 
303         // +0  ^ -anything except 0, NAN  = +INF
304 
305         test(DfpMath.pow(factory.newDfp("0"), factory.newDfp("-1")),
306              pinf,
307              0, "pow #51");
308 
309         test(DfpMath.pow(factory.newDfp("0"), factory.newDfp("-1e30")),
310              pinf,
311              0, "pow #52");
312 
313         test(DfpMath.pow(factory.newDfp("0"), factory.newDfp("-1e-30")),
314              pinf,
315              0, "pow #53");
316 
317         test(DfpMath.pow(factory.newDfp("0"), ninf),
318              pinf,
319              0, "pow #54");
320 
321         // -0  ^ -anything except 0, NAN, odd integer  = +INF
322 
323         test(DfpMath.pow(factory.newDfp("-0"), factory.newDfp("-2")),
324              pinf,
325              0, "pow #55");
326 
327         test(DfpMath.pow(factory.newDfp("-0"), factory.newDfp("-1e30")),
328              pinf,
329              0, "pow #56");
330 
331         test(DfpMath.pow(factory.newDfp("-0"), factory.newDfp("-1e-30")),
332              pinf,
333              DfpField.FLAG_INEXACT, "pow #57");
334 
335         test(DfpMath.pow(factory.newDfp("-0"), ninf),
336              pinf,
337              0, "pow #58");
338 
339         // -0  ^ -odd integer   =  -INF
340         test(DfpMath.pow(factory.newDfp("-0"), factory.newDfp("-1")),
341              ninf,
342              DfpField.FLAG_INEXACT, "pow #59");
343 
344         test(DfpMath.pow(factory.newDfp("-0"), factory.newDfp("-12345")),
345              ninf,
346              DfpField.FLAG_INEXACT, "pow #60");
347 
348         // -0  ^ +odd integer   =  -0
349         test(DfpMath.pow(factory.newDfp("-0"), factory.newDfp("3")),
350              factory.newDfp("-0"),
351              DfpField.FLAG_INEXACT, "pow #61");
352 
353         test(DfpMath.pow(factory.newDfp("-0"), factory.newDfp("12345")),
354              factory.newDfp("-0"),
355              DfpField.FLAG_INEXACT, "pow #62");
356 
357         // pinf  ^ +anything   = pinf
358         test(DfpMath.pow(pinf, factory.newDfp("3")),
359              pinf,
360              0, "pow #63");
361 
362         test(DfpMath.pow(pinf, factory.newDfp("1e30")),
363              pinf,
364              0, "pow #64");
365 
366         test(DfpMath.pow(pinf, factory.newDfp("1e-30")),
367              pinf,
368              0, "pow #65");
369 
370         test(DfpMath.pow(pinf, pinf),
371              pinf,
372              0, "pow #66");
373 
374         // pinf  ^ -anything   = +0
375 
376         test(DfpMath.pow(pinf, factory.newDfp("-3")),
377              factory.getZero(),
378              0, "pow #67");
379 
380         test(DfpMath.pow(pinf, factory.newDfp("-1e30")),
381              factory.getZero(),
382              0, "pow #68");
383 
384         test(DfpMath.pow(pinf, factory.newDfp("-1e-30")),
385              factory.getZero(),
386              0, "pow #69");
387 
388         test(DfpMath.pow(pinf, ninf),
389              factory.getZero(),
390              0, "pow #70");
391 
392         // ninf  ^ anything   = -0 ^ -anything
393         // ninf  ^ -anything except 0, NAN, odd integer  = +0
394 
395         test(DfpMath.pow(ninf, factory.newDfp("-2")),
396              factory.newDfp("0"),
397              0, "pow #71");
398 
399         test(DfpMath.pow(ninf, factory.newDfp("-1e30")),
400              factory.newDfp("0"),
401              0, "pow #72");
402 
403         test(DfpMath.pow(ninf, factory.newDfp("-1e-30")),
404              factory.newDfp("0"),
405              DfpField.FLAG_INEXACT, "pow #73");
406 
407         test(DfpMath.pow(ninf, ninf),
408              factory.newDfp("0"),
409              0, "pow #74");
410 
411         // ninf  ^ +anything except 0, NAN, odd integer  = +INF
412 
413         test(DfpMath.pow(ninf, factory.newDfp("2")),
414              pinf,
415              0, "pow #75");
416 
417         test(DfpMath.pow(ninf, factory.newDfp("1e30")),
418              pinf,
419              0, "pow #76");
420 
421         test(DfpMath.pow(ninf, factory.newDfp("1e-30")),
422              pinf,
423              DfpField.FLAG_INEXACT, "pow #77");
424 
425         test(DfpMath.pow(ninf, pinf),
426              pinf,
427              0, "pow #78");
428 
429         // ninf  ^ +odd integer   =  -INF
430         test(DfpMath.pow(ninf, factory.newDfp("3")),
431              ninf,
432              DfpField.FLAG_INEXACT, "pow #79");
433 
434         test(DfpMath.pow(ninf, factory.newDfp("12345")),
435              ninf,
436              DfpField.FLAG_INEXACT, "pow #80");
437 
438         // ninf  ^ -odd integer   =  -0
439         test(DfpMath.pow(ninf, factory.newDfp("-3")),
440              factory.newDfp("-0"),
441              DfpField.FLAG_INEXACT, "pow #81");
442 
443         test(DfpMath.pow(ninf, factory.newDfp("-12345")),
444              factory.newDfp("-0"),
445              DfpField.FLAG_INEXACT, "pow #82");
446 
447         // -anything ^ integer
448         test(DfpMath.pow(factory.newDfp("-2"), factory.newDfp("3")),
449              factory.newDfp("-8"),
450              DfpField.FLAG_INEXACT, "pow #83");
451 
452         test(DfpMath.pow(factory.newDfp("-2"), factory.newDfp("16")),
453              factory.newDfp("65536"),
454              0, "pow #84");
455 
456         test(DfpMath.pow(factory.newDfp("-2"), factory.newDfp("-3")),
457              factory.newDfp("-0.125"),
458              DfpField.FLAG_INEXACT, "pow #85");
459 
460         test(DfpMath.pow(factory.newDfp("-2"), factory.newDfp("-4")),
461              factory.newDfp("0.0625"),
462              0, "pow #86");
463 
464         // -anything ^ noninteger = NaN
465 
466         test(DfpMath.pow(factory.newDfp("-2"), factory.newDfp("-4.1")),
467              qnan,
468              DfpField.FLAG_INVALID | DfpField.FLAG_INEXACT, "pow #87");
469 
470         // Some fractional cases.
471         test(DfpMath.pow(factory.newDfp("2"), factory.newDfp("1.5")),
472              factory.newDfp("2.8284271247461901"),
473              DfpField.FLAG_INEXACT, "pow #88");
474     }
475 
476     @Test
477     public void testSin() {
478         test(DfpMath.sin(pinf),
479              nan,
480              DfpField.FLAG_INVALID | DfpField.FLAG_INEXACT, "sin #1");
481 
482         test(DfpMath.sin(nan),
483              nan,
484              DfpField.FLAG_INVALID | DfpField.FLAG_INEXACT, "sin #2");
485 
486         test(DfpMath.sin(factory.getZero()),
487              factory.getZero(),
488              DfpField.FLAG_INEXACT, "sin #3");
489 
490         test(DfpMath.sin(factory.getPi()),
491              factory.getZero(),
492              DfpField.FLAG_INEXACT, "sin #4");
493 
494         test(DfpMath.sin(factory.getPi().negate()),
495              factory.newDfp("-0"),
496              DfpField.FLAG_INEXACT, "sin #5");
497 
498         test(DfpMath.sin(factory.getPi().multiply(2)),
499              factory.getZero(),
500              DfpField.FLAG_INEXACT, "sin #6");
501 
502         test(DfpMath.sin(factory.getPi().divide(2)),
503              factory.getOne(),
504              DfpField.FLAG_INEXACT, "sin #7");
505 
506         test(DfpMath.sin(factory.getPi().divide(2).negate()),
507              factory.getOne().negate(),
508              DfpField.FLAG_INEXACT, "sin #8");
509 
510         test(DfpMath.sin(DfpMath.atan(factory.getOne())),  // pi/4
511              factory.newDfp("0.5").sqrt(),
512              DfpField.FLAG_INEXACT, "sin #9");
513 
514         test(DfpMath.sin(DfpMath.atan(factory.getOne())).negate(),  // -pi/4
515              factory.newDfp("0.5").sqrt().negate(),
516              DfpField.FLAG_INEXACT, "sin #10");
517 
518         test(DfpMath.sin(DfpMath.atan(factory.getOne())).negate(),  // -pi/4
519              factory.newDfp("0.5").sqrt().negate(),
520              DfpField.FLAG_INEXACT, "sin #11");
521 
522         test(DfpMath.sin(factory.newDfp("0.1")),
523              factory.newDfp("0.0998334166468281523"),
524              DfpField.FLAG_INEXACT, "sin #12");
525 
526         test(DfpMath.sin(factory.newDfp("0.2")),
527              factory.newDfp("0.19866933079506121546"),
528              DfpField.FLAG_INEXACT, "sin #13");
529 
530         test(DfpMath.sin(factory.newDfp("0.3")),
531              factory.newDfp("0.2955202066613395751"),
532              DfpField.FLAG_INEXACT, "sin #14");
533 
534         test(DfpMath.sin(factory.newDfp("0.4")),
535              factory.newDfp("0.38941834230865049166"),
536              DfpField.FLAG_INEXACT, "sin #15");
537 
538         test(DfpMath.sin(factory.newDfp("0.5")),
539              factory.newDfp("0.47942553860420300026"),  // off by one ULP
540              DfpField.FLAG_INEXACT, "sin #16");
541 
542         test(DfpMath.sin(factory.newDfp("0.6")),
543              factory.newDfp("0.56464247339503535721"),  // off by one ULP
544              DfpField.FLAG_INEXACT, "sin #17");
545 
546         test(DfpMath.sin(factory.newDfp("0.7")),
547              factory.newDfp("0.64421768723769105367"),
548              DfpField.FLAG_INEXACT, "sin #18");
549 
550         test(DfpMath.sin(factory.newDfp("0.8")),
551              factory.newDfp("0.71735609089952276163"),
552              DfpField.FLAG_INEXACT, "sin #19");
553 
554         test(DfpMath.sin(factory.newDfp("0.9")),        // off by one ULP
555              factory.newDfp("0.78332690962748338847"),
556              DfpField.FLAG_INEXACT, "sin #20");
557 
558         test(DfpMath.sin(factory.newDfp("1.0")),
559              factory.newDfp("0.84147098480789650666"),
560              DfpField.FLAG_INEXACT, "sin #21");
561 
562         test(DfpMath.sin(factory.newDfp("1.1")),
563              factory.newDfp("0.89120736006143533995"),
564              DfpField.FLAG_INEXACT, "sin #22");
565 
566         test(DfpMath.sin(factory.newDfp("1.2")),
567              factory.newDfp("0.93203908596722634968"),
568              DfpField.FLAG_INEXACT, "sin #23");
569 
570         test(DfpMath.sin(factory.newDfp("1.3")),
571              factory.newDfp("0.9635581854171929647"),
572              DfpField.FLAG_INEXACT, "sin #24");
573 
574         test(DfpMath.sin(factory.newDfp("1.4")),
575              factory.newDfp("0.98544972998846018066"),
576              DfpField.FLAG_INEXACT, "sin #25");
577 
578         test(DfpMath.sin(factory.newDfp("1.5")),
579              factory.newDfp("0.99749498660405443096"),
580              DfpField.FLAG_INEXACT, "sin #26");
581 
582         test(DfpMath.sin(factory.newDfp("1.6")),
583              factory.newDfp("0.99957360304150516323"),
584              DfpField.FLAG_INEXACT, "sin #27");
585     }
586 
587 }