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