1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.hipparchus.dfp;
24
25 import java.util.Arrays;
26
27 import org.hipparchus.CalculusFieldElement;
28 import org.hipparchus.exception.MathIllegalArgumentException;
29 import org.hipparchus.exception.MathRuntimeException;
30 import org.hipparchus.util.FastMath;
31 import org.hipparchus.util.FieldSinhCosh;
32 import org.hipparchus.util.MathUtils;
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104 public class Dfp implements CalculusFieldElement<Dfp> {
105
106
107 public static final int RADIX = 10000;
108
109
110
111 public static final int MIN_EXP = -32767;
112
113
114
115 public static final int MAX_EXP = 32768;
116
117
118 public static final int ERR_SCALE = 32760;
119
120
121 public static final byte FINITE = 0;
122
123
124 public static final byte INFINITE = 1;
125
126
127 public static final byte SNAN = 2;
128
129
130 public static final byte QNAN = 3;
131
132
133 private static final String NAN_STRING = "NaN";
134
135
136 private static final String POS_INFINITY_STRING = "Infinity";
137
138
139 private static final String NEG_INFINITY_STRING = "-Infinity";
140
141
142 private static final String ADD_TRAP = "add";
143
144
145 private static final String MULTIPLY_TRAP = "multiply";
146
147
148 private static final String DIVIDE_TRAP = "divide";
149
150
151 private static final String SQRT_TRAP = "sqrt";
152
153
154 private static final String ALIGN_TRAP = "align";
155
156
157 private static final String TRUNC_TRAP = "trunc";
158
159
160 private static final String NEXT_AFTER_TRAP = "nextAfter";
161
162
163 private static final String LESS_THAN_TRAP = "lessThan";
164
165
166 private static final String GREATER_THAN_TRAP = "greaterThan";
167
168
169 private static final String NEW_INSTANCE_TRAP = "newInstance";
170
171
172 private static final int LINEAR_COMBINATION_DIGITS_FACTOR = 2;
173
174
175 protected int[] mant;
176
177
178 protected byte sign;
179
180
181 protected int exp;
182
183
184 protected byte nans;
185
186
187 private final DfpField field;
188
189
190
191
192 protected Dfp(final DfpField field) {
193 mant = new int[field.getRadixDigits()];
194 sign = 1;
195 exp = 0;
196 nans = FINITE;
197 this.field = field;
198 }
199
200
201
202
203
204 protected Dfp(final DfpField field, byte x) {
205 this(field, (long) x);
206 }
207
208
209
210
211
212 protected Dfp(final DfpField field, int x) {
213 this(field, (long) x);
214 }
215
216
217
218
219
220 protected Dfp(final DfpField field, long x) {
221
222
223 mant = new int[field.getRadixDigits()];
224 nans = FINITE;
225 this.field = field;
226
227 boolean isLongMin = false;
228 if (x == Long.MIN_VALUE) {
229
230
231 isLongMin = true;
232 ++x;
233 }
234
235
236 if (x < 0) {
237 sign = -1;
238 x = -x;
239 } else {
240 sign = 1;
241 }
242
243 exp = 0;
244 while (x != 0) {
245 System.arraycopy(mant, mant.length - exp, mant, mant.length - 1 - exp, exp);
246 mant[mant.length - 1] = (int) (x % RADIX);
247 x /= RADIX;
248 exp++;
249 }
250
251 if (isLongMin) {
252
253
254 for (int i = 0; i < mant.length - 1; i++) {
255 if (mant[i] != 0) {
256 mant[i]++;
257 break;
258 }
259 }
260 }
261 }
262
263
264
265
266
267 protected Dfp(final DfpField field, double x) {
268
269
270 mant = new int[field.getRadixDigits()];
271 this.field = field;
272
273 long bits = Double.doubleToLongBits(x);
274 long mantissa = bits & 0x000fffffffffffffL;
275 int exponent = (int) ((bits & 0x7ff0000000000000L) >> 52) - 1023;
276
277 if (exponent == -1023) {
278
279 if (x == 0) {
280
281 if ((bits & 0x8000000000000000L) != 0) {
282 sign = -1;
283 } else {
284 sign = 1;
285 }
286 return;
287 }
288
289 exponent++;
290
291
292 while ( (mantissa & 0x0010000000000000L) == 0) {
293 exponent--;
294 mantissa <<= 1;
295 }
296 mantissa &= 0x000fffffffffffffL;
297 }
298
299 if (exponent == 1024) {
300
301 if (x != x) {
302 sign = (byte) 1;
303 nans = QNAN;
304 } else if (x < 0) {
305 sign = (byte) -1;
306 nans = INFINITE;
307 } else {
308 sign = (byte) 1;
309 nans = INFINITE;
310 }
311 return;
312 }
313
314 Dfp xdfp = new Dfp(field, mantissa);
315 xdfp = xdfp.divide(new Dfp(field, 4503599627370496l)).add(field.getOne());
316 xdfp = xdfp.multiply(DfpMath.pow(field.getTwo(), exponent));
317
318 if ((bits & 0x8000000000000000L) != 0) {
319 xdfp = xdfp.negate();
320 }
321
322 System.arraycopy(xdfp.mant, 0, mant, 0, mant.length);
323 sign = xdfp.sign;
324 exp = xdfp.exp;
325 nans = xdfp.nans;
326
327 }
328
329
330
331
332 public Dfp(final Dfp d) {
333 mant = d.mant.clone();
334 sign = d.sign;
335 exp = d.exp;
336 nans = d.nans;
337 field = d.field;
338 }
339
340
341
342
343
344 protected Dfp(final DfpField field, final String s) {
345
346
347 mant = new int[field.getRadixDigits()];
348 sign = 1;
349 nans = FINITE;
350 this.field = field;
351
352 boolean decimalFound = false;
353 final int rsize = 4;
354 final int offset = 4;
355 final char[] striped = new char[getRadixDigits() * rsize + offset * 2];
356
357
358 if (POS_INFINITY_STRING.equals(s)) {
359 sign = (byte) 1;
360 nans = INFINITE;
361 return;
362 }
363
364 if (NEG_INFINITY_STRING.equals(s)) {
365 sign = (byte) -1;
366 nans = INFINITE;
367 return;
368 }
369
370 if (NAN_STRING.equals(s)) {
371 sign = (byte) 1;
372 nans = QNAN;
373 return;
374 }
375
376
377 int p = s.indexOf('e');
378 if (p == -1) {
379 p = s.indexOf('E');
380 }
381
382 final String fpdecimal;
383 int sciexp = 0;
384 if (p != -1) {
385
386 fpdecimal = s.substring(0, p);
387 String fpexp = s.substring(p+1);
388 boolean negative = false;
389
390 for (int i=0; i<fpexp.length(); i++)
391 {
392 if (fpexp.charAt(i) == '-')
393 {
394 negative = true;
395 continue;
396 }
397 if (fpexp.charAt(i) >= '0' && fpexp.charAt(i) <= '9') {
398 sciexp = sciexp * 10 + fpexp.charAt(i) - '0';
399 }
400 }
401
402 if (negative) {
403 sciexp = -sciexp;
404 }
405 } else {
406
407 fpdecimal = s;
408 }
409
410
411 if (fpdecimal.indexOf('-') != -1) {
412 sign = -1;
413 }
414
415
416 p = 0;
417
418
419 int decimalPos = 0;
420 for (;;) {
421 if (fpdecimal.charAt(p) >= '1' && fpdecimal.charAt(p) <= '9') {
422 break;
423 }
424
425 if (decimalFound && fpdecimal.charAt(p) == '0') {
426 decimalPos--;
427 }
428
429 if (fpdecimal.charAt(p) == '.') {
430 decimalFound = true;
431 }
432
433 p++;
434
435 if (p == fpdecimal.length()) {
436 break;
437 }
438 }
439
440
441 int q = offset;
442 striped[0] = '0';
443 striped[1] = '0';
444 striped[2] = '0';
445 striped[3] = '0';
446 int significantDigits=0;
447 for(;;) {
448 if (p == (fpdecimal.length())) {
449 break;
450 }
451
452
453 if (q == mant.length*rsize+offset+1) {
454 break;
455 }
456
457 if (fpdecimal.charAt(p) == '.') {
458 decimalFound = true;
459 decimalPos = significantDigits;
460 p++;
461 continue;
462 }
463
464 if (fpdecimal.charAt(p) < '0' || fpdecimal.charAt(p) > '9') {
465 p++;
466 continue;
467 }
468
469 striped[q] = fpdecimal.charAt(p);
470 q++;
471 p++;
472 significantDigits++;
473 }
474
475
476
477 if (decimalFound && q != offset) {
478 for (;;) {
479 q--;
480 if (q == offset) {
481 break;
482 }
483 if (striped[q] == '0') {
484 significantDigits--;
485 } else {
486 break;
487 }
488 }
489 }
490
491
492 if (decimalFound && significantDigits == 0) {
493 decimalPos = 0;
494 }
495
496
497 if (!decimalFound) {
498 decimalPos = q-offset;
499 }
500
501
502 q = offset;
503 p = significantDigits-1+offset;
504
505 while (p > q) {
506 if (striped[p] != '0') {
507 break;
508 }
509 p--;
510 }
511
512
513 int i = ((rsize * 100) - decimalPos - sciexp % rsize) % rsize;
514 q -= i;
515 decimalPos += i;
516
517
518 while ((p - q) < (mant.length * rsize)) {
519 for (i = 0; i < rsize; i++) {
520 striped[++p] = '0';
521 }
522 }
523
524
525
526 for (i = mant.length - 1; i >= 0; i--) {
527 mant[i] = (striped[q] - '0') * 1000 +
528 (striped[q+1] - '0') * 100 +
529 (striped[q+2] - '0') * 10 +
530 (striped[q+3] - '0');
531 q += 4;
532 }
533
534 exp = (decimalPos+sciexp) / rsize;
535
536 if (q < striped.length) {
537
538 round((striped[q] - '0')*1000);
539 }
540
541 }
542
543
544
545
546
547
548
549 protected Dfp(final DfpField field, final byte sign, final byte nans) {
550 this.field = field;
551 this.mant = new int[field.getRadixDigits()];
552 this.sign = sign;
553 this.exp = 0;
554 this.nans = nans;
555 }
556
557
558
559
560
561 public Dfp newInstance() {
562 return new Dfp(getField());
563 }
564
565
566
567
568
569 public Dfp newInstance(final byte x) {
570 return new Dfp(getField(), x);
571 }
572
573
574
575
576
577 public Dfp newInstance(final int x) {
578 return new Dfp(getField(), x);
579 }
580
581
582
583
584
585 public Dfp newInstance(final long x) {
586 return new Dfp(getField(), x);
587 }
588
589
590 @Override
591 public Dfp newInstance(final double x) {
592 return new Dfp(getField(), x);
593 }
594
595
596
597
598
599
600 public Dfp newInstance(final Dfp d) {
601
602
603 if (field.getRadixDigits() != d.field.getRadixDigits()) {
604 field.setIEEEFlagsBits(DfpField.FLAG_INVALID);
605 final Dfp result = newInstance(getZero());
606 result.nans = QNAN;
607 return dotrap(DfpField.FLAG_INVALID, NEW_INSTANCE_TRAP, d, result);
608 }
609
610 return new Dfp(d);
611
612 }
613
614
615
616
617
618
619 public Dfp newInstance(final String s) {
620 return new Dfp(field, s);
621 }
622
623
624
625
626
627
628
629 public Dfp newInstance(final byte sig, final byte code) {
630 return field.newDfp(sig, code);
631 }
632
633
634
635
636
637
638
639
640
641
642
643
644 public Dfp newInstance(final DfpField targetField, final DfpField.RoundingMode rmode) {
645 final int deltaLength = targetField.getRadixDigits() - field.getRadixDigits();
646 if (deltaLength == 0) {
647
648
649 return this;
650
651 } else {
652
653
654 Dfp result = new Dfp(targetField);
655 result.sign = sign;
656 result.exp = exp;
657 result.nans = nans;
658 if (nans == 0) {
659
660 if (deltaLength < 0) {
661
662
663
664 System.arraycopy(mant, -deltaLength, result.mant, 0, result.mant.length);
665
666
667
668 final int last = -(deltaLength + 1);
669 boolean zeroLSB = true;
670 for (int i = 0; i < last; ++i) {
671 zeroLSB &= mant[i] == 0;
672 }
673
674 if (!(zeroLSB && mant[last] == 0)) {
675
676
677 if (shouldIncrement(rmode, zeroLSB, mant[last], result.mant[0], sign)) {
678
679 result.incrementMantissa();
680 }
681
682 targetField.setIEEEFlagsBits(DfpField.FLAG_INEXACT);
683 result = dotrap(DfpField.FLAG_INEXACT, TRUNC_TRAP, this, result);
684
685 }
686
687 } else {
688
689 System.arraycopy(mant, 0, result.mant, deltaLength, mant.length);
690 }
691
692 }
693
694 return result;
695
696 }
697 }
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713 private static boolean shouldIncrement(final DfpField.RoundingMode rmode,
714 final boolean zeroLSB, final int lastDiscarded,
715 final int firstNonDiscarded, final int sign) {
716 switch (rmode) {
717 case ROUND_DOWN :
718 return false;
719
720 case ROUND_UP :
721 return true;
722
723 case ROUND_HALF_UP :
724 return lastDiscarded >= 5000;
725
726 case ROUND_HALF_DOWN :
727 return isAboveHalfWay(zeroLSB, lastDiscarded);
728
729 case ROUND_HALF_EVEN :
730 return (isHalfWay(zeroLSB, lastDiscarded) && (firstNonDiscarded & 0x1) == 0x1) ||
731 isAboveHalfWay(zeroLSB, lastDiscarded);
732
733 case ROUND_HALF_ODD :
734 return (isHalfWay(zeroLSB, lastDiscarded) && (firstNonDiscarded & 0x1) == 0x0) ||
735 isAboveHalfWay(zeroLSB, lastDiscarded);
736
737 case ROUND_CEIL :
738 return sign > 0;
739
740 case ROUND_FLOOR :
741 return sign < 0;
742
743 default :
744
745 throw MathRuntimeException.createInternalError();
746 }
747 }
748
749
750
751
752 private void incrementMantissa() {
753 boolean carry = true;
754 for (int i = 0; carry && i < mant.length; ++i) {
755 ++mant[i];
756 if (mant[i] >= RADIX) {
757 mant[i] -= RADIX;
758 } else {
759 carry = false;
760 }
761 }
762 if (carry) {
763
764 for (int i = 0; i < mant.length - 1; i++) {
765 mant[i] = mant[i+1];
766 }
767 mant[mant.length - 1] = 1;
768 exp++;
769 }
770 }
771
772
773
774
775
776
777
778 private static boolean isHalfWay(final boolean zeroLSB, final int lastDiscarded) {
779 return lastDiscarded == 5000 && zeroLSB;
780 }
781
782
783
784
785
786
787
788 private static boolean isAboveHalfWay(final boolean zeroLSB, final int lastDiscarded) {
789 return (lastDiscarded > 5000) || (lastDiscarded == 5000 && !zeroLSB);
790 }
791
792
793
794
795
796
797
798
799 @Override
800 public DfpField getField() {
801 return field;
802 }
803
804
805
806
807 public int getRadixDigits() {
808 return field.getRadixDigits();
809 }
810
811
812
813
814 public Dfp getZero() {
815 return field.getZero();
816 }
817
818
819
820
821 public Dfp getOne() {
822 return field.getOne();
823 }
824
825
826
827
828 public Dfp getTwo() {
829 return field.getTwo();
830 }
831
832
833
834 protected void shiftLeft() {
835 for (int i = mant.length - 1; i > 0; i--) {
836 mant[i] = mant[i-1];
837 }
838 mant[0] = 0;
839 exp--;
840 }
841
842
843
844
845
846 protected void shiftRight() {
847 for (int i = 0; i < mant.length - 1; i++) {
848 mant[i] = mant[i+1];
849 }
850 mant[mant.length - 1] = 0;
851 exp++;
852 }
853
854
855
856
857
858
859
860
861
862 protected int align(int e) {
863 int lostdigit = 0;
864 boolean inexact = false;
865
866 int diff = exp - e;
867
868 int adiff = diff;
869 if (adiff < 0) {
870 adiff = -adiff;
871 }
872
873 if (diff == 0) {
874 return 0;
875 }
876
877 if (adiff > (mant.length + 1)) {
878
879 Arrays.fill(mant, 0);
880 exp = e;
881
882 field.setIEEEFlagsBits(DfpField.FLAG_INEXACT);
883 dotrap(DfpField.FLAG_INEXACT, ALIGN_TRAP, this, this);
884
885 return 0;
886 }
887
888 for (int i = 0; i < adiff; i++) {
889 if (diff < 0) {
890
891
892
893
894 if (lostdigit != 0) {
895 inexact = true;
896 }
897
898 lostdigit = mant[0];
899
900 shiftRight();
901 } else {
902 shiftLeft();
903 }
904 }
905
906 if (inexact) {
907 field.setIEEEFlagsBits(DfpField.FLAG_INEXACT);
908 dotrap(DfpField.FLAG_INEXACT, ALIGN_TRAP, this, this);
909 }
910
911 return lostdigit;
912
913 }
914
915
916
917
918
919 public boolean lessThan(final Dfp x) {
920
921
922 if (field.getRadixDigits() != x.field.getRadixDigits()) {
923 field.setIEEEFlagsBits(DfpField.FLAG_INVALID);
924 final Dfp result = newInstance(getZero());
925 result.nans = QNAN;
926 dotrap(DfpField.FLAG_INVALID, LESS_THAN_TRAP, x, result);
927 return false;
928 }
929
930
931 if (isNaN() || x.isNaN()) {
932 field.setIEEEFlagsBits(DfpField.FLAG_INVALID);
933 dotrap(DfpField.FLAG_INVALID, LESS_THAN_TRAP, x, newInstance(getZero()));
934 return false;
935 }
936
937 return compare(this, x) < 0;
938 }
939
940
941
942
943
944 public boolean greaterThan(final Dfp x) {
945
946
947 if (field.getRadixDigits() != x.field.getRadixDigits()) {
948 field.setIEEEFlagsBits(DfpField.FLAG_INVALID);
949 final Dfp result = newInstance(getZero());
950 result.nans = QNAN;
951 dotrap(DfpField.FLAG_INVALID, GREATER_THAN_TRAP, x, result);
952 return false;
953 }
954
955
956 if (isNaN() || x.isNaN()) {
957 field.setIEEEFlagsBits(DfpField.FLAG_INVALID);
958 dotrap(DfpField.FLAG_INVALID, GREATER_THAN_TRAP, x, newInstance(getZero()));
959 return false;
960 }
961
962 return compare(this, x) > 0;
963 }
964
965
966
967
968 public boolean negativeOrNull() {
969
970 if (isNaN()) {
971 field.setIEEEFlagsBits(DfpField.FLAG_INVALID);
972 dotrap(DfpField.FLAG_INVALID, LESS_THAN_TRAP, this, newInstance(getZero()));
973 return false;
974 }
975
976 return (sign < 0) || ((mant[mant.length - 1] == 0) && !isInfinite());
977
978 }
979
980
981
982
983 public boolean strictlyNegative() {
984
985 if (isNaN()) {
986 field.setIEEEFlagsBits(DfpField.FLAG_INVALID);
987 dotrap(DfpField.FLAG_INVALID, LESS_THAN_TRAP, this, newInstance(getZero()));
988 return false;
989 }
990
991 return (sign < 0) && ((mant[mant.length - 1] != 0) || isInfinite());
992
993 }
994
995
996
997
998 public boolean positiveOrNull() {
999
1000 if (isNaN()) {
1001 field.setIEEEFlagsBits(DfpField.FLAG_INVALID);
1002 dotrap(DfpField.FLAG_INVALID, LESS_THAN_TRAP, this, newInstance(getZero()));
1003 return false;
1004 }
1005
1006 return (sign > 0) || ((mant[mant.length - 1] == 0) && !isInfinite());
1007
1008 }
1009
1010
1011
1012
1013 public boolean strictlyPositive() {
1014
1015 if (isNaN()) {
1016 field.setIEEEFlagsBits(DfpField.FLAG_INVALID);
1017 dotrap(DfpField.FLAG_INVALID, LESS_THAN_TRAP, this, newInstance(getZero()));
1018 return false;
1019 }
1020
1021 return (sign > 0) && ((mant[mant.length - 1] != 0) || isInfinite());
1022
1023 }
1024
1025
1026 @Override
1027 public Dfp abs() {
1028 Dfp result = newInstance(this);
1029 result.sign = 1;
1030 return result;
1031 }
1032
1033
1034 @Override
1035 public boolean isInfinite() {
1036 return nans == INFINITE;
1037 }
1038
1039
1040 @Override
1041 public boolean isNaN() {
1042 return (nans == QNAN) || (nans == SNAN);
1043 }
1044
1045
1046
1047
1048 @Override
1049 public boolean isZero() {
1050
1051 if (isNaN()) {
1052 field.setIEEEFlagsBits(DfpField.FLAG_INVALID);
1053 dotrap(DfpField.FLAG_INVALID, LESS_THAN_TRAP, this, newInstance(getZero()));
1054 return false;
1055 }
1056
1057 return (mant[mant.length - 1] == 0) && !isInfinite();
1058
1059 }
1060
1061
1062
1063
1064
1065 @Override
1066 public boolean equals(final Object other) {
1067
1068 if (other instanceof Dfp) {
1069 final Dfp x = (Dfp) other;
1070 if (isNaN() || x.isNaN() || field.getRadixDigits() != x.field.getRadixDigits()) {
1071 return false;
1072 }
1073
1074 return compare(this, x) == 0;
1075 }
1076
1077 return false;
1078
1079 }
1080
1081
1082
1083
1084
1085 @Override
1086 public int hashCode() {
1087 return 17 + (isZero() ? 0 : (sign << 8)) + (nans << 16) + exp + Arrays.hashCode(mant);
1088 }
1089
1090
1091
1092
1093
1094 public boolean unequal(final Dfp x) {
1095 if (isNaN() || x.isNaN() || field.getRadixDigits() != x.field.getRadixDigits()) {
1096 return false;
1097 }
1098
1099 return greaterThan(x) || lessThan(x);
1100 }
1101
1102
1103
1104
1105
1106
1107
1108 private static int compare(final Dfp a, final Dfp b) {
1109
1110 if (a.mant[a.mant.length - 1] == 0 && b.mant[b.mant.length - 1] == 0 &&
1111 a.nans == FINITE && b.nans == FINITE) {
1112 return 0;
1113 }
1114
1115 if (a.sign != b.sign) {
1116 if (a.sign == -1) {
1117 return -1;
1118 } else {
1119 return 1;
1120 }
1121 }
1122
1123
1124 if (a.nans == INFINITE && b.nans == FINITE) {
1125 return a.sign;
1126 }
1127
1128 if (a.nans == FINITE && b.nans == INFINITE) {
1129 return -b.sign;
1130 }
1131
1132 if (a.nans == INFINITE && b.nans == INFINITE) {
1133 return 0;
1134 }
1135
1136
1137 if (b.mant[b.mant.length-1] != 0 && a.mant[b.mant.length-1] != 0) {
1138 if (a.exp < b.exp) {
1139 return -a.sign;
1140 }
1141
1142 if (a.exp > b.exp) {
1143 return a.sign;
1144 }
1145 }
1146
1147
1148 for (int i = a.mant.length - 1; i >= 0; i--) {
1149 if (a.mant[i] > b.mant[i]) {
1150 return a.sign;
1151 }
1152
1153 if (a.mant[i] < b.mant[i]) {
1154 return -a.sign;
1155 }
1156 }
1157
1158 return 0;
1159
1160 }
1161
1162
1163
1164
1165
1166
1167 @Override
1168 public Dfp rint() {
1169 return trunc(DfpField.RoundingMode.ROUND_HALF_EVEN);
1170 }
1171
1172
1173
1174
1175
1176 @Override
1177 public Dfp floor() {
1178 return trunc(DfpField.RoundingMode.ROUND_FLOOR);
1179 }
1180
1181
1182
1183
1184
1185 @Override
1186 public Dfp ceil() {
1187 return trunc(DfpField.RoundingMode.ROUND_CEIL);
1188 }
1189
1190
1191
1192
1193
1194 @Override
1195 public Dfp remainder(final Dfp d) {
1196
1197 final Dfp result = this.subtract(this.divide(d).rint().multiply(d));
1198
1199
1200 if (result.mant[mant.length-1] == 0) {
1201 result.sign = sign;
1202 }
1203
1204 return result;
1205
1206 }
1207
1208
1209
1210
1211
1212 protected Dfp trunc(final DfpField.RoundingMode rmode) {
1213 boolean changed = false;
1214
1215 if (isNaN()) {
1216 return newInstance(this);
1217 }
1218
1219 if (nans == INFINITE) {
1220 return newInstance(this);
1221 }
1222
1223 if (mant[mant.length-1] == 0) {
1224
1225 return newInstance(this);
1226 }
1227
1228
1229
1230 if (exp < 0) {
1231 field.setIEEEFlagsBits(DfpField.FLAG_INEXACT);
1232 final Dfp result;
1233 if (sign == -1 && rmode == DfpField.RoundingMode.ROUND_FLOOR) {
1234 result = newInstance(-1);
1235 } else if (sign == +1 && rmode == DfpField.RoundingMode.ROUND_CEIL) {
1236 result = newInstance(+1);
1237 } else {
1238
1239 result = newInstance(0);
1240 }
1241 return dotrap(DfpField.FLAG_INEXACT, TRUNC_TRAP, this, result);
1242 }
1243
1244
1245
1246
1247
1248 if (exp >= mant.length) {
1249 return newInstance(this);
1250 }
1251
1252
1253
1254
1255 Dfp result = newInstance(this);
1256 for (int i = 0; i < mant.length-result.exp; i++) {
1257 changed |= result.mant[i] != 0;
1258 result.mant[i] = 0;
1259 }
1260
1261 if (changed) {
1262 switch (rmode) {
1263 case ROUND_FLOOR:
1264 if (result.sign == -1) {
1265
1266 result = result.add(newInstance(-1));
1267 }
1268 break;
1269
1270 case ROUND_CEIL:
1271 if (result.sign == 1) {
1272
1273 result = result.add(getOne());
1274 }
1275 break;
1276
1277 case ROUND_HALF_EVEN:
1278 default:
1279 final Dfp half = newInstance("0.5");
1280 Dfp a = subtract(result);
1281 a.sign = 1;
1282 if (a.greaterThan(half)) {
1283 a = newInstance(getOne());
1284 a.sign = sign;
1285 result = result.add(a);
1286 }
1287
1288
1289 if (a.equals(half) && result.exp > 0 && (result.mant[mant.length-result.exp]&1) != 0) {
1290 a = newInstance(getOne());
1291 a.sign = sign;
1292 result = result.add(a);
1293 }
1294 break;
1295 }
1296
1297 field.setIEEEFlagsBits(DfpField.FLAG_INEXACT);
1298 result = dotrap(DfpField.FLAG_INEXACT, TRUNC_TRAP, this, result);
1299 return result;
1300 }
1301
1302 return result;
1303 }
1304
1305
1306
1307
1308
1309 public int intValue() {
1310 Dfp rounded;
1311 int result = 0;
1312
1313 rounded = rint();
1314
1315 if (rounded.greaterThan(newInstance(2147483647))) {
1316 return 2147483647;
1317 }
1318
1319 if (rounded.lessThan(newInstance(-2147483648))) {
1320 return -2147483648;
1321 }
1322
1323 for (int i = mant.length - 1; i >= mant.length - rounded.exp; i--) {
1324 result = result * RADIX + rounded.mant[i];
1325 }
1326
1327 if (rounded.sign == -1) {
1328 result = -result;
1329 }
1330
1331 return result;
1332 }
1333
1334
1335
1336
1337
1338
1339 public int log10K() {
1340 return exp - 1;
1341 }
1342
1343
1344
1345
1346
1347 public Dfp power10K(final int e) {
1348 Dfp d = newInstance(getOne());
1349 d.exp = e + 1;
1350 return d;
1351 }
1352
1353
1354
1355
1356 public int intLog10() {
1357 if (mant[mant.length-1] > 1000) {
1358 return exp * 4 - 1;
1359 }
1360 if (mant[mant.length-1] > 100) {
1361 return exp * 4 - 2;
1362 }
1363 if (mant[mant.length-1] > 10) {
1364 return exp * 4 - 3;
1365 }
1366 return exp * 4 - 4;
1367 }
1368
1369
1370
1371
1372
1373 public Dfp power10(final int e) {
1374 Dfp d = newInstance(getOne());
1375
1376 if (e >= 0) {
1377 d.exp = e / 4 + 1;
1378 } else {
1379 d.exp = (e + 1) / 4;
1380 }
1381
1382 switch ((e % 4 + 4) % 4) {
1383 case 0:
1384 break;
1385 case 1:
1386 d = d.multiply(10);
1387 break;
1388 case 2:
1389 d = d.multiply(100);
1390 break;
1391 default:
1392 d = d.multiply(1000);
1393 break;
1394 }
1395
1396 return d;
1397 }
1398
1399
1400
1401
1402
1403
1404
1405 protected int complement(int extra) {
1406
1407 extra = RADIX-extra;
1408 for (int i = 0; i < mant.length; i++) {
1409 mant[i] = RADIX-mant[i]-1;
1410 }
1411
1412 int rh = extra / RADIX;
1413 extra -= rh * RADIX;
1414 for (int i = 0; i < mant.length; i++) {
1415 final int r = mant[i] + rh;
1416 rh = r / RADIX;
1417 mant[i] = r - rh * RADIX;
1418 }
1419
1420 return extra;
1421 }
1422
1423
1424
1425
1426
1427 @Override
1428 public Dfp add(final Dfp x) {
1429
1430
1431 if (field.getRadixDigits() != x.field.getRadixDigits()) {
1432 field.setIEEEFlagsBits(DfpField.FLAG_INVALID);
1433 final Dfp result = newInstance(getZero());
1434 result.nans = QNAN;
1435 return dotrap(DfpField.FLAG_INVALID, ADD_TRAP, x, result);
1436 }
1437
1438
1439 if (nans != FINITE || x.nans != FINITE) {
1440 if (isNaN()) {
1441 return this;
1442 }
1443
1444 if (x.isNaN()) {
1445 return x;
1446 }
1447
1448 if (nans == INFINITE && x.nans == FINITE) {
1449 return this;
1450 }
1451
1452 if (x.nans == INFINITE && nans == FINITE) {
1453 return x;
1454 }
1455
1456 if (x.nans == INFINITE && nans == INFINITE && sign == x.sign) {
1457 return x;
1458 }
1459
1460 if (x.nans == INFINITE && nans == INFINITE && sign != x.sign) {
1461 field.setIEEEFlagsBits(DfpField.FLAG_INVALID);
1462 Dfp result = newInstance(getZero());
1463 result.nans = QNAN;
1464 result = dotrap(DfpField.FLAG_INVALID, ADD_TRAP, x, result);
1465 return result;
1466 }
1467 }
1468
1469
1470 Dfp a = newInstance(this);
1471 Dfp b = newInstance(x);
1472
1473
1474 Dfp result = newInstance(getZero());
1475
1476
1477 final byte asign = a.sign;
1478 final byte bsign = b.sign;
1479
1480 a.sign = 1;
1481 b.sign = 1;
1482
1483
1484 byte rsign = bsign;
1485 if (compare(a, b) > 0) {
1486 rsign = asign;
1487 }
1488
1489
1490
1491
1492 if (b.mant[mant.length-1] == 0) {
1493 b.exp = a.exp;
1494 }
1495
1496 if (a.mant[mant.length-1] == 0) {
1497 a.exp = b.exp;
1498 }
1499
1500
1501 int aextradigit = 0;
1502 int bextradigit = 0;
1503 if (a.exp < b.exp) {
1504 aextradigit = a.align(b.exp);
1505 } else {
1506 bextradigit = b.align(a.exp);
1507 }
1508
1509
1510 if (asign != bsign) {
1511 if (asign == rsign) {
1512 bextradigit = b.complement(bextradigit);
1513 } else {
1514 aextradigit = a.complement(aextradigit);
1515 }
1516 }
1517
1518
1519 int rh = 0;
1520 for (int i = 0; i < mant.length; i++) {
1521 final int r = a.mant[i]+b.mant[i]+rh;
1522 rh = r / RADIX;
1523 result.mant[i] = r - rh * RADIX;
1524 }
1525 result.exp = a.exp;
1526 result.sign = rsign;
1527
1528
1529
1530
1531 if (rh != 0 && (asign == bsign)) {
1532 final int lostdigit = result.mant[0];
1533 result.shiftRight();
1534 result.mant[mant.length-1] = rh;
1535 final int excp = result.round(lostdigit);
1536 if (excp != 0) {
1537 result = dotrap(excp, ADD_TRAP, x, result);
1538 }
1539 }
1540
1541
1542 for (int i = 0; i < mant.length; i++) {
1543 if (result.mant[mant.length-1] != 0) {
1544 break;
1545 }
1546 result.shiftLeft();
1547 if (i == 0) {
1548 result.mant[0] = aextradigit+bextradigit;
1549 aextradigit = 0;
1550 bextradigit = 0;
1551 }
1552 }
1553
1554
1555 if (result.mant[mant.length-1] == 0) {
1556 result.exp = 0;
1557
1558 if (asign != bsign) {
1559
1560 result.sign = 1;
1561 }
1562 }
1563
1564
1565 final int excp = result.round(aextradigit + bextradigit);
1566 if (excp != 0) {
1567 result = dotrap(excp, ADD_TRAP, x, result);
1568 }
1569
1570 return result;
1571 }
1572
1573
1574
1575
1576 @Override
1577 public Dfp negate() {
1578 Dfp result = newInstance(this);
1579 result.sign = (byte) - result.sign;
1580 return result;
1581 }
1582
1583
1584
1585
1586
1587 @Override
1588 public Dfp subtract(final Dfp x) {
1589 return add(x.negate());
1590 }
1591
1592
1593
1594
1595
1596 protected int round(int n) {
1597 boolean inc = false;
1598 switch (field.getRoundingMode()) {
1599 case ROUND_DOWN:
1600 inc = false;
1601 break;
1602
1603 case ROUND_UP:
1604 inc = n != 0;
1605 break;
1606
1607 case ROUND_HALF_UP:
1608 inc = n >= 5000;
1609 break;
1610
1611 case ROUND_HALF_DOWN:
1612 inc = n > 5000;
1613 break;
1614
1615 case ROUND_HALF_EVEN:
1616 inc = n > 5000 || (n == 5000 && (mant[0] & 1) == 1);
1617 break;
1618
1619 case ROUND_HALF_ODD:
1620 inc = n > 5000 || (n == 5000 && (mant[0] & 1) == 0);
1621 break;
1622
1623 case ROUND_CEIL:
1624 inc = sign == 1 && n != 0;
1625 break;
1626
1627 case ROUND_FLOOR:
1628 default:
1629 inc = sign == -1 && n != 0;
1630 break;
1631 }
1632
1633 if (inc) {
1634
1635 int rh = 1;
1636 for (int i = 0; i < mant.length; i++) {
1637 final int r = mant[i] + rh;
1638 rh = r / RADIX;
1639 mant[i] = r - rh * RADIX;
1640 }
1641
1642 if (rh != 0) {
1643 shiftRight();
1644 mant[mant.length-1] = rh;
1645 }
1646 }
1647
1648
1649 if (exp < MIN_EXP) {
1650
1651 field.setIEEEFlagsBits(DfpField.FLAG_UNDERFLOW);
1652 return DfpField.FLAG_UNDERFLOW;
1653 }
1654
1655 if (exp > MAX_EXP) {
1656
1657 field.setIEEEFlagsBits(DfpField.FLAG_OVERFLOW);
1658 return DfpField.FLAG_OVERFLOW;
1659 }
1660
1661 if (n != 0) {
1662
1663 field.setIEEEFlagsBits(DfpField.FLAG_INEXACT);
1664 return DfpField.FLAG_INEXACT;
1665 }
1666
1667 return 0;
1668
1669 }
1670
1671
1672
1673
1674
1675 @Override
1676 public Dfp multiply(final Dfp x) {
1677
1678
1679 if (field.getRadixDigits() != x.field.getRadixDigits()) {
1680 field.setIEEEFlagsBits(DfpField.FLAG_INVALID);
1681 final Dfp result = newInstance(getZero());
1682 result.nans = QNAN;
1683 return dotrap(DfpField.FLAG_INVALID, MULTIPLY_TRAP, x, result);
1684 }
1685
1686 Dfp result = newInstance(getZero());
1687
1688
1689 if (nans != FINITE || x.nans != FINITE) {
1690 if (isNaN()) {
1691 return this;
1692 }
1693
1694 if (x.isNaN()) {
1695 return x;
1696 }
1697
1698 if (nans == INFINITE && x.nans == FINITE && x.mant[mant.length-1] != 0) {
1699 result = newInstance(this);
1700 result.sign = (byte) (sign * x.sign);
1701 return result;
1702 }
1703
1704 if (x.nans == INFINITE && nans == FINITE && mant[mant.length-1] != 0) {
1705 result = newInstance(x);
1706 result.sign = (byte) (sign * x.sign);
1707 return result;
1708 }
1709
1710 if (x.nans == INFINITE && nans == INFINITE) {
1711 result = newInstance(this);
1712 result.sign = (byte) (sign * x.sign);
1713 return result;
1714 }
1715
1716 if ( (x.nans == INFINITE && nans == FINITE && mant[mant.length-1] == 0) ||
1717 (nans == INFINITE && x.nans == FINITE && x.mant[mant.length-1] == 0) ) {
1718 field.setIEEEFlagsBits(DfpField.FLAG_INVALID);
1719 result = newInstance(getZero());
1720 result.nans = QNAN;
1721 result = dotrap(DfpField.FLAG_INVALID, MULTIPLY_TRAP, x, result);
1722 return result;
1723 }
1724 }
1725
1726 int[] product = new int[mant.length*2];
1727
1728 for (int i = 0; i < mant.length; i++) {
1729 int rh = 0;
1730 for (int j=0; j<mant.length; j++) {
1731 int r = mant[i] * x.mant[j];
1732 r += product[i+j] + rh;
1733
1734 rh = r / RADIX;
1735 product[i+j] = r - rh * RADIX;
1736 }
1737 product[i+mant.length] = rh;
1738 }
1739
1740
1741 int md = mant.length * 2 - 1;
1742 for (int i = mant.length * 2 - 1; i >= 0; i--) {
1743 if (product[i] != 0) {
1744 md = i;
1745 break;
1746 }
1747 }
1748
1749
1750 for (int i = 0; i < mant.length; i++) {
1751 result.mant[mant.length - i - 1] = product[md - i];
1752 }
1753
1754
1755 result.exp = exp + x.exp + md - 2 * mant.length + 1;
1756 result.sign = (byte)((sign == x.sign)?1:-1);
1757
1758 if (result.mant[mant.length-1] == 0) {
1759
1760 result.exp = 0;
1761 }
1762
1763 final int excp;
1764 if (md > (mant.length-1)) {
1765 excp = result.round(product[md-mant.length]);
1766 } else {
1767 excp = result.round(0);
1768 }
1769
1770 if (excp != 0) {
1771 result = dotrap(excp, MULTIPLY_TRAP, x, result);
1772 }
1773
1774 return result;
1775
1776 }
1777
1778
1779
1780
1781
1782 @Override
1783 public Dfp multiply(final int x) {
1784 if (x >= 0 && x < RADIX) {
1785 return multiplyFast(x);
1786 } else {
1787 return multiply(newInstance(x));
1788 }
1789 }
1790
1791
1792
1793
1794
1795
1796 private Dfp multiplyFast(final int x) {
1797 Dfp result = newInstance(this);
1798
1799
1800 if (nans != FINITE) {
1801 if (isNaN()) {
1802 return this;
1803 }
1804
1805 if (nans == INFINITE && x != 0) {
1806 result = newInstance(this);
1807 return result;
1808 }
1809
1810 if (nans == INFINITE && x == 0) {
1811 field.setIEEEFlagsBits(DfpField.FLAG_INVALID);
1812 result = newInstance(getZero());
1813 result.nans = QNAN;
1814 result = dotrap(DfpField.FLAG_INVALID, MULTIPLY_TRAP, newInstance(getZero()), result);
1815 return result;
1816 }
1817 }
1818
1819
1820 if (x < 0 || x >= RADIX) {
1821 field.setIEEEFlagsBits(DfpField.FLAG_INVALID);
1822 result = newInstance(getZero());
1823 result.nans = QNAN;
1824 result = dotrap(DfpField.FLAG_INVALID, MULTIPLY_TRAP, result, result);
1825 return result;
1826 }
1827
1828 int rh = 0;
1829 for (int i = 0; i < mant.length; i++) {
1830 final int r = mant[i] * x + rh;
1831 rh = r / RADIX;
1832 result.mant[i] = r - rh * RADIX;
1833 }
1834
1835 int lostdigit = 0;
1836 if (rh != 0) {
1837 lostdigit = result.mant[0];
1838 result.shiftRight();
1839 result.mant[mant.length-1] = rh;
1840 }
1841
1842 if (result.mant[mant.length-1] == 0) {
1843 result.exp = 0;
1844 }
1845
1846 final int excp = result.round(lostdigit);
1847 if (excp != 0) {
1848 result = dotrap(excp, MULTIPLY_TRAP, result, result);
1849 }
1850
1851 return result;
1852 }
1853
1854
1855 @Override
1856 public Dfp square() {
1857 return multiply(this);
1858 }
1859
1860
1861
1862
1863
1864 @Override
1865 public Dfp divide(Dfp divisor) {
1866 int[] dividend;
1867 int[] quotient;
1868 int[] remainder;
1869 int qd;
1870 int nsqd;
1871 int trial=0;
1872 int minadj;
1873 boolean trialgood;
1874 int md;
1875 int excp;
1876
1877
1878 if (field.getRadixDigits() != divisor.field.getRadixDigits()) {
1879 field.setIEEEFlagsBits(DfpField.FLAG_INVALID);
1880 final Dfp result = newInstance(getZero());
1881 result.nans = QNAN;
1882 return dotrap(DfpField.FLAG_INVALID, DIVIDE_TRAP, divisor, result);
1883 }
1884
1885 Dfp result = newInstance(getZero());
1886
1887
1888 if (nans != FINITE || divisor.nans != FINITE) {
1889 if (isNaN()) {
1890 return this;
1891 }
1892
1893 if (divisor.isNaN()) {
1894 return divisor;
1895 }
1896
1897 if (nans == INFINITE && divisor.nans == FINITE) {
1898 result = newInstance(this);
1899 result.sign = (byte) (sign * divisor.sign);
1900 return result;
1901 }
1902
1903 if (divisor.nans == INFINITE && nans == FINITE) {
1904 result = newInstance(getZero());
1905 result.sign = (byte) (sign * divisor.sign);
1906 return result;
1907 }
1908
1909 if (divisor.nans == INFINITE && nans == INFINITE) {
1910 field.setIEEEFlagsBits(DfpField.FLAG_INVALID);
1911 result = newInstance(getZero());
1912 result.nans = QNAN;
1913 result = dotrap(DfpField.FLAG_INVALID, DIVIDE_TRAP, divisor, result);
1914 return result;
1915 }
1916 }
1917
1918
1919 if (divisor.mant[mant.length-1] == 0) {
1920 field.setIEEEFlagsBits(DfpField.FLAG_DIV_ZERO);
1921 result = newInstance(getZero());
1922 result.sign = (byte) (sign * divisor.sign);
1923 result.nans = INFINITE;
1924 result = dotrap(DfpField.FLAG_DIV_ZERO, DIVIDE_TRAP, divisor, result);
1925 return result;
1926 }
1927
1928 dividend = new int[mant.length+1];
1929 quotient = new int[mant.length+2];
1930 remainder = new int[mant.length+1];
1931
1932
1933
1934 dividend[mant.length] = 0;
1935 quotient[mant.length] = 0;
1936 quotient[mant.length+1] = 0;
1937 remainder[mant.length] = 0;
1938
1939
1940
1941
1942 for (int i = 0; i < mant.length; i++) {
1943 dividend[i] = mant[i];
1944 quotient[i] = 0;
1945 remainder[i] = 0;
1946 }
1947
1948
1949 nsqd = 0;
1950 for (qd = mant.length+1; qd >= 0; qd--) {
1951
1952
1953
1954 final int divMsb = dividend[mant.length]*RADIX+dividend[mant.length-1];
1955 int min = divMsb / (divisor.mant[mant.length-1]+1);
1956 int max = (divMsb + 1) / divisor.mant[mant.length-1];
1957
1958 trialgood = false;
1959 while (!trialgood) {
1960
1961 trial = (min+max)/2;
1962
1963
1964 int rh = 0;
1965 for (int i = 0; i < mant.length + 1; i++) {
1966 int dm = (i<mant.length)?divisor.mant[i]:0;
1967 final int r = (dm * trial) + rh;
1968 rh = r / RADIX;
1969 remainder[i] = r - rh * RADIX;
1970 }
1971
1972
1973 rh = 1;
1974 for (int i = 0; i < mant.length + 1; i++) {
1975 final int r = ((RADIX-1) - remainder[i]) + dividend[i] + rh;
1976 rh = r / RADIX;
1977 remainder[i] = r - rh * RADIX;
1978 }
1979
1980
1981 if (rh == 0) {
1982
1983 max = trial-1;
1984 continue;
1985 }
1986
1987
1988 minadj = (remainder[mant.length] * RADIX)+remainder[mant.length-1];
1989 minadj /= divisor.mant[mant.length-1] + 1;
1990
1991 if (minadj >= 2) {
1992 min = trial+minadj;
1993 continue;
1994 }
1995
1996
1997
1998 trialgood = false;
1999 for (int i = mant.length - 1; i >= 0; i--) {
2000 if (divisor.mant[i] > remainder[i]) {
2001 trialgood = true;
2002 }
2003 if (divisor.mant[i] < remainder[i]) {
2004 break;
2005 }
2006 }
2007
2008 if (remainder[mant.length] != 0) {
2009 trialgood = false;
2010 }
2011
2012 if (!trialgood) {
2013 min = trial+1;
2014 }
2015 }
2016
2017
2018 quotient[qd] = trial;
2019 if (trial != 0 || nsqd != 0) {
2020 nsqd++;
2021 }
2022
2023 if (field.getRoundingMode() == DfpField.RoundingMode.ROUND_DOWN && nsqd == mant.length) {
2024
2025 break;
2026 }
2027
2028 if (nsqd > mant.length) {
2029
2030 break;
2031 }
2032
2033
2034 dividend[0] = 0;
2035 for (int i = 0; i < mant.length; i++) {
2036 dividend[i + 1] = remainder[i];
2037 }
2038 }
2039
2040
2041 md = mant.length;
2042 for (int i = mant.length + 1; i >= 0; i--) {
2043 if (quotient[i] != 0) {
2044 md = i;
2045 break;
2046 }
2047 }
2048
2049
2050 for (int i=0; i<mant.length; i++) {
2051 result.mant[mant.length-i-1] = quotient[md-i];
2052 }
2053
2054
2055 result.exp = exp - divisor.exp + md - mant.length;
2056 result.sign = (byte) ((sign == divisor.sign) ? 1 : -1);
2057
2058 if (result.mant[mant.length-1] == 0) {
2059 result.exp = 0;
2060 }
2061
2062 if (md > (mant.length-1)) {
2063 excp = result.round(quotient[md-mant.length]);
2064 } else {
2065 excp = result.round(0);
2066 }
2067
2068 if (excp != 0) {
2069 result = dotrap(excp, DIVIDE_TRAP, divisor, result);
2070 }
2071
2072 return result;
2073 }
2074
2075
2076
2077
2078
2079
2080 public Dfp divide(int divisor) {
2081
2082
2083 if (nans != FINITE) {
2084 if (isNaN()) {
2085 return this;
2086 }
2087
2088 if (nans == INFINITE) {
2089 return newInstance(this);
2090 }
2091 }
2092
2093
2094 if (divisor == 0) {
2095 field.setIEEEFlagsBits(DfpField.FLAG_DIV_ZERO);
2096 Dfp result = newInstance(getZero());
2097 result.sign = sign;
2098 result.nans = INFINITE;
2099 result = dotrap(DfpField.FLAG_DIV_ZERO, DIVIDE_TRAP, getZero(), result);
2100 return result;
2101 }
2102
2103
2104 if (divisor < 0 || divisor >= RADIX) {
2105 field.setIEEEFlagsBits(DfpField.FLAG_INVALID);
2106 Dfp result = newInstance(getZero());
2107 result.nans = QNAN;
2108 result = dotrap(DfpField.FLAG_INVALID, DIVIDE_TRAP, result, result);
2109 return result;
2110 }
2111
2112 Dfp result = newInstance(this);
2113
2114 int rl = 0;
2115 for (int i = mant.length-1; i >= 0; i--) {
2116 final int r = rl*RADIX + result.mant[i];
2117 final int rh = r / divisor;
2118 rl = r - rh * divisor;
2119 result.mant[i] = rh;
2120 }
2121
2122 if (result.mant[mant.length-1] == 0) {
2123
2124 result.shiftLeft();
2125 final int r = rl * RADIX;
2126 final int rh = r / divisor;
2127 rl = r - rh * divisor;
2128 result.mant[0] = rh;
2129 }
2130
2131 final int excp = result.round(rl * RADIX / divisor);
2132 if (excp != 0) {
2133 result = dotrap(excp, DIVIDE_TRAP, result, result);
2134 }
2135
2136 return result;
2137
2138 }
2139
2140
2141 @Override
2142 public Dfp reciprocal() {
2143 return field.getOne().divide(this);
2144 }
2145
2146
2147
2148
2149 @Override
2150 public Dfp sqrt() {
2151
2152
2153 if (nans == FINITE && mant[mant.length-1] == 0) {
2154
2155 return newInstance(this);
2156 }
2157
2158 if (nans != FINITE) {
2159 if (nans == INFINITE && sign == 1) {
2160
2161 return newInstance(this);
2162 }
2163
2164 if (nans == QNAN) {
2165 return newInstance(this);
2166 }
2167
2168 if (nans == SNAN) {
2169 Dfp result;
2170
2171 field.setIEEEFlagsBits(DfpField.FLAG_INVALID);
2172 result = newInstance(this);
2173 result = dotrap(DfpField.FLAG_INVALID, SQRT_TRAP, null, result);
2174 return result;
2175 }
2176 }
2177
2178 if (sign == -1) {
2179
2180 Dfp result;
2181
2182 field.setIEEEFlagsBits(DfpField.FLAG_INVALID);
2183 result = newInstance(this);
2184 result.nans = QNAN;
2185 result = dotrap(DfpField.FLAG_INVALID, SQRT_TRAP, null, result);
2186 return result;
2187 }
2188
2189 Dfp x = newInstance(this);
2190
2191
2192 if (x.exp < -1 || x.exp > 1) {
2193 x.exp = this.exp / 2;
2194 }
2195
2196
2197 switch (x.mant[mant.length-1] / 2000) {
2198 case 0:
2199 x.mant[mant.length-1] = x.mant[mant.length-1]/2+1;
2200 break;
2201 case 2:
2202 x.mant[mant.length-1] = 1500;
2203 break;
2204 case 3:
2205 x.mant[mant.length-1] = 2200;
2206 break;
2207 default:
2208 x.mant[mant.length-1] = 3000;
2209 break;
2210 }
2211
2212
2213
2214
2215 Dfp dx;
2216 Dfp px = getZero();
2217 Dfp ppx;
2218 while (x.unequal(px)) {
2219 dx = newInstance(x);
2220 dx.sign = -1;
2221 dx = dx.add(this.divide(x));
2222 dx = dx.divide(2);
2223 ppx = px;
2224 px = x;
2225 x = x.add(dx);
2226
2227 if (x.equals(ppx)) {
2228
2229 break;
2230 }
2231
2232
2233
2234 if (dx.mant[mant.length-1] == 0) {
2235 break;
2236 }
2237 }
2238
2239 return x;
2240
2241 }
2242
2243
2244
2245
2246 @Override
2247 public String toString() {
2248 if (nans != FINITE) {
2249
2250 if (nans == INFINITE) {
2251 return (sign < 0) ? NEG_INFINITY_STRING : POS_INFINITY_STRING;
2252 } else {
2253 return NAN_STRING;
2254 }
2255 }
2256
2257 if (exp > mant.length || exp < -1) {
2258 return dfp2sci();
2259 }
2260
2261 return dfp2string();
2262
2263 }
2264
2265
2266
2267
2268 protected String dfp2sci() {
2269 char[] rawdigits = new char[mant.length * 4];
2270 int p;
2271 int e;
2272 int ae;
2273 int shf;
2274
2275
2276 p = 0;
2277 for (int i = mant.length - 1; i >= 0; i--) {
2278 rawdigits[p++] = (char) ((mant[i] / 1000) + '0');
2279 rawdigits[p++] = (char) (((mant[i] / 100) %10) + '0');
2280 rawdigits[p++] = (char) (((mant[i] / 10) % 10) + '0');
2281 rawdigits[p++] = (char) (((mant[i]) % 10) + '0');
2282 }
2283
2284
2285 for (p = 0; p < rawdigits.length; p++) {
2286 if (rawdigits[p] != '0') {
2287 break;
2288 }
2289 }
2290 shf = p;
2291
2292
2293 StringBuilder builder = new StringBuilder();
2294 if (sign == -1) {
2295 builder.append('-');
2296 }
2297
2298 if (p != rawdigits.length) {
2299
2300 builder.append(rawdigits[p++]);
2301 builder.append('.');
2302
2303 while (p<rawdigits.length) {
2304 builder.append(rawdigits[p++]);
2305 }
2306 } else {
2307 builder.append("0.0e0");
2308 return builder.toString();
2309 }
2310
2311 builder.append('e');
2312
2313
2314
2315 e = exp * 4 - shf - 1;
2316 ae = e;
2317 if (e < 0) {
2318 ae = -e;
2319 }
2320
2321
2322 for (p = 1000000000; p > ae; p /= 10) {
2323
2324 }
2325
2326 if (e < 0) {
2327 builder.append('-');
2328 }
2329
2330 while (p > 0) {
2331 builder.append((char)(ae / p + '0'));
2332 ae %= p;
2333 p /= 10;
2334 }
2335
2336 return builder.toString();
2337
2338 }
2339
2340
2341
2342
2343 protected String dfp2string() {
2344 final String fourZero = "0000";
2345 int e = exp;
2346 boolean pointInserted = false;
2347
2348 StringBuilder builder = new StringBuilder();
2349
2350 if (e <= 0) {
2351 builder.append("0.");
2352 pointInserted = true;
2353 }
2354
2355 while (e < 0) {
2356 builder.append(fourZero);
2357 e++;
2358 }
2359
2360 for (int i = mant.length - 1; i >= 0; i--) {
2361 builder.append((char) ((mant[i] / 1000) + '0'));
2362 builder.append((char) (((mant[i] / 100) % 10) + '0'));
2363 builder.append((char) (((mant[i] / 10) % 10) + '0'));
2364 builder.append((char) (((mant[i]) % 10) + '0'));
2365 --e;
2366 if (e == 0) {
2367 builder.append('.');
2368 pointInserted = true;
2369 }
2370 }
2371
2372 while (e > 0) {
2373 builder.append(fourZero);
2374 e--;
2375 }
2376
2377 if (!pointInserted) {
2378
2379 builder.append('.');
2380 }
2381
2382
2383 while (builder.charAt(0) == '0') {
2384 builder.deleteCharAt(0);
2385 }
2386 if (builder.charAt(0) == '.') {
2387 builder.insert(0, '0');
2388 }
2389
2390
2391 while (builder.charAt(builder.length() - 1) == '0') {
2392 builder.deleteCharAt(builder.length() - 1);
2393 }
2394
2395
2396 if (sign < 0) {
2397 builder.insert(0, '-');
2398 }
2399
2400 return builder.toString();
2401
2402 }
2403
2404
2405
2406
2407
2408
2409
2410
2411 public Dfp dotrap(int type, String what, Dfp oper, Dfp result) {
2412 Dfp def = result;
2413
2414 switch (type) {
2415 case DfpField.FLAG_INVALID:
2416 def = newInstance(getZero());
2417 def.sign = result.sign;
2418 def.nans = QNAN;
2419 break;
2420
2421 case DfpField.FLAG_DIV_ZERO:
2422 if (nans == FINITE && mant[mant.length-1] != 0) {
2423
2424 def = newInstance(getZero());
2425 def.sign = (byte)(sign*oper.sign);
2426 def.nans = INFINITE;
2427 }
2428
2429 if (nans == FINITE && mant[mant.length-1] == 0) {
2430
2431 def = newInstance(getZero());
2432 def.nans = QNAN;
2433 }
2434
2435 if (nans == INFINITE || nans == QNAN) {
2436 def = newInstance(getZero());
2437 def.nans = QNAN;
2438 }
2439
2440 if (nans == INFINITE || nans == SNAN) {
2441 def = newInstance(getZero());
2442 def.nans = QNAN;
2443 }
2444 break;
2445
2446 case DfpField.FLAG_UNDERFLOW:
2447 if ( (result.exp+mant.length) < MIN_EXP) {
2448 def = newInstance(getZero());
2449 def.sign = result.sign;
2450 } else {
2451 def = newInstance(result);
2452 }
2453 result.exp += ERR_SCALE;
2454 break;
2455
2456 case DfpField.FLAG_OVERFLOW:
2457 result.exp -= ERR_SCALE;
2458 def = newInstance(getZero());
2459 def.sign = result.sign;
2460 def.nans = INFINITE;
2461 break;
2462
2463 default: def = result; break;
2464 }
2465
2466 return trap(type, what, oper, def, result);
2467
2468 }
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481 protected Dfp trap(int type, String what, Dfp oper, Dfp def, Dfp result) {
2482 return def;
2483 }
2484
2485
2486
2487
2488 public int classify() {
2489 return nans;
2490 }
2491
2492
2493
2494
2495
2496
2497
2498 public static Dfp copysign(final Dfp x, final Dfp y) {
2499 Dfp result = x.newInstance(x);
2500 result.sign = y.sign;
2501 return result;
2502 }
2503
2504
2505
2506
2507
2508
2509 public Dfp nextAfter(final Dfp x) {
2510
2511
2512 if (field.getRadixDigits() != x.field.getRadixDigits()) {
2513 field.setIEEEFlagsBits(DfpField.FLAG_INVALID);
2514 final Dfp result = newInstance(getZero());
2515 result.nans = QNAN;
2516 return dotrap(DfpField.FLAG_INVALID, NEXT_AFTER_TRAP, x, result);
2517 }
2518
2519
2520 boolean up = false;
2521 if (this.lessThan(x)) {
2522 up = true;
2523 }
2524
2525 if (compare(this, x) == 0) {
2526 return newInstance(x);
2527 }
2528
2529 if (lessThan(getZero())) {
2530 up = !up;
2531 }
2532
2533 final Dfp inc;
2534 Dfp result;
2535 if (up) {
2536 inc = newInstance(getOne());
2537 inc.exp = this.exp-mant.length+1;
2538 inc.sign = this.sign;
2539
2540 if (this.equals(getZero())) {
2541 inc.exp = MIN_EXP-mant.length;
2542 }
2543
2544 result = add(inc);
2545 } else {
2546 inc = newInstance(getOne());
2547 inc.exp = this.exp;
2548 inc.sign = this.sign;
2549
2550 if (this.equals(inc)) {
2551 inc.exp = this.exp-mant.length;
2552 } else {
2553 inc.exp = this.exp-mant.length+1;
2554 }
2555
2556 if (this.equals(getZero())) {
2557 inc.exp = MIN_EXP-mant.length;
2558 }
2559
2560 result = this.subtract(inc);
2561 }
2562
2563 if (result.classify() == INFINITE && this.classify() != INFINITE) {
2564 field.setIEEEFlagsBits(DfpField.FLAG_INEXACT);
2565 result = dotrap(DfpField.FLAG_INEXACT, NEXT_AFTER_TRAP, x, result);
2566 }
2567
2568 if (result.equals(getZero()) && !this.equals(getZero())) {
2569 field.setIEEEFlagsBits(DfpField.FLAG_INEXACT);
2570 result = dotrap(DfpField.FLAG_INEXACT, NEXT_AFTER_TRAP, x, result);
2571 }
2572
2573 return result;
2574
2575 }
2576
2577
2578
2579
2580
2581 public double toDouble() {
2582
2583 if (isInfinite()) {
2584 if (lessThan(getZero())) {
2585 return Double.NEGATIVE_INFINITY;
2586 } else {
2587 return Double.POSITIVE_INFINITY;
2588 }
2589 }
2590
2591 if (isNaN()) {
2592 return Double.NaN;
2593 }
2594
2595 Dfp y = this;
2596 boolean negate = false;
2597 int cmp0 = compare(this, getZero());
2598 if (cmp0 == 0) {
2599 return sign < 0 ? -0.0 : +0.0;
2600 } else if (cmp0 < 0) {
2601 y = negate();
2602 negate = true;
2603 }
2604
2605
2606
2607 int exponent = (int)(y.intLog10() * 3.32);
2608 if (exponent < 0) {
2609 exponent--;
2610 }
2611
2612 Dfp tempDfp = DfpMath.pow(getTwo(), exponent);
2613 while (tempDfp.lessThan(y) || tempDfp.equals(y)) {
2614 tempDfp = tempDfp.multiply(2);
2615 exponent++;
2616 }
2617 exponent--;
2618
2619
2620
2621 y = y.divide(DfpMath.pow(getTwo(), exponent));
2622 if (exponent > -1023) {
2623 y = y.subtract(getOne());
2624 }
2625
2626 if (exponent < -1074) {
2627 return 0;
2628 }
2629
2630 if (exponent > 1023) {
2631 return negate ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
2632 }
2633
2634
2635 y = y.multiply(newInstance(4503599627370496l)).rint();
2636 String str = y.toString();
2637 str = str.substring(0, str.length()-1);
2638 long mantissa = Long.parseLong(str);
2639
2640 if (mantissa == 4503599627370496L) {
2641
2642 mantissa = 0;
2643 exponent++;
2644 }
2645
2646
2647 if (exponent <= -1023) {
2648 exponent--;
2649 }
2650
2651 while (exponent < -1023) {
2652 exponent++;
2653 mantissa >>>= 1;
2654 }
2655
2656 long bits = mantissa | ((exponent + 1023L) << 52);
2657 double x = Double.longBitsToDouble(bits);
2658
2659 if (negate) {
2660 x = -x;
2661 }
2662
2663 return x;
2664
2665 }
2666
2667
2668
2669
2670
2671 public double[] toSplitDouble() {
2672 double[] split = new double[2];
2673 long mask = 0xffffffffc0000000L;
2674
2675 split[0] = Double.longBitsToDouble(Double.doubleToLongBits(toDouble()) & mask);
2676 split[1] = subtract(newInstance(split[0])).toDouble();
2677
2678 return split;
2679 }
2680
2681
2682
2683 @Override
2684 public double getReal() {
2685 return toDouble();
2686 }
2687
2688
2689
2690 @Override
2691 public Dfp remainder(final double a) {
2692 return remainder(newInstance(a));
2693 }
2694
2695
2696
2697 @Override
2698 public Dfp sign() {
2699 if (isNaN() || isZero()) {
2700 return this;
2701 } else {
2702 return newInstance(sign > 0 ? +1 : -1);
2703 }
2704 }
2705
2706
2707
2708 @Override
2709 public Dfp copySign(final Dfp s) {
2710 if ((sign >= 0 && s.sign >= 0) || (sign < 0 && s.sign < 0)) {
2711 return this;
2712 }
2713 return negate();
2714 }
2715
2716
2717
2718 @Override
2719 public Dfp copySign(final double s) {
2720 long sb = Double.doubleToLongBits(s);
2721 if ((sign >= 0 && sb >= 0) || (sign < 0 && sb < 0)) {
2722 return this;
2723 }
2724 return negate();
2725 }
2726
2727
2728
2729 @Override
2730 public int getExponent() {
2731
2732 if (nans != FINITE) {
2733
2734 return 435411;
2735 }
2736 if (isZero()) {
2737 return -435412;
2738 }
2739
2740 final Dfp abs = abs();
2741
2742
2743
2744 int p = FastMath.max(13301 * exp / 1001 - 15, -435411);
2745 Dfp twoP = DfpMath.pow(getTwo(), p);
2746 while (compare(abs, twoP) >= 0) {
2747 twoP = twoP.add(twoP);
2748 ++p;
2749 }
2750
2751 return p - 1;
2752
2753 }
2754
2755
2756
2757 @Override
2758 public Dfp scalb(final int n) {
2759 return multiply(DfpMath.pow(getTwo(), n));
2760 }
2761
2762
2763
2764 @Override
2765 public Dfp ulp() {
2766 final Dfp result = new Dfp(field);
2767 result.mant[result.mant.length - 1] = 1;
2768 result.exp = exp - (result.mant.length - 1);
2769 return result;
2770 }
2771
2772
2773
2774 @Override
2775 public Dfp hypot(final Dfp y) {
2776
2777 if (isInfinite() || y.isInfinite()) {
2778 return field.newDfp(Double.POSITIVE_INFINITY);
2779 } else if (isNaN() || y.isNaN()) {
2780 return field.newDfp(Double.NaN);
2781 } else {
2782
2783 final int scalingExp = (exp + y.exp) / 2;
2784
2785
2786 final Dfp scaledX = new Dfp(this);
2787 scaledX.exp -= scalingExp;
2788 final Dfp scaledY = new Dfp(y);
2789 scaledY.exp -= scalingExp;
2790
2791
2792 final Dfp h = scaledX.multiply(scaledX).add(scaledY.multiply(scaledY)).sqrt();
2793
2794
2795 h.exp += scalingExp;
2796
2797 return h;
2798 }
2799
2800 }
2801
2802
2803
2804 @Override
2805 public Dfp rootN(final int n) {
2806 return (sign >= 0) ?
2807 DfpMath.pow(this, getOne().divide(n)) :
2808 DfpMath.pow(negate(), getOne().divide(n)).negate();
2809 }
2810
2811
2812
2813 @Override
2814 public Dfp pow(final double p) {
2815 return DfpMath.pow(this, newInstance(p));
2816 }
2817
2818
2819
2820 @Override
2821 public Dfp pow(final int n) {
2822 return DfpMath.pow(this, n);
2823 }
2824
2825
2826
2827 @Override
2828 public Dfp pow(final Dfp e) {
2829 return DfpMath.pow(this, e);
2830 }
2831
2832
2833
2834 @Override
2835 public Dfp exp() {
2836 return DfpMath.exp(this);
2837 }
2838
2839
2840
2841 @Override
2842 public Dfp expm1() {
2843 return DfpMath.exp(this).subtract(getOne());
2844 }
2845
2846
2847
2848 @Override
2849 public Dfp log() {
2850 return DfpMath.log(this);
2851 }
2852
2853
2854
2855 @Override
2856 public Dfp log1p() {
2857 return DfpMath.log(this.add(getOne()));
2858 }
2859
2860
2861
2862 @Override
2863 public Dfp log10() {
2864 return DfpMath.log(this).divide(DfpMath.log(newInstance(10)));
2865 }
2866
2867
2868
2869 @Override
2870 public Dfp cos() {
2871 return DfpMath.cos(this);
2872 }
2873
2874
2875
2876 @Override
2877 public Dfp sin() {
2878 return DfpMath.sin(this);
2879 }
2880
2881
2882
2883 @Override
2884 public Dfp tan() {
2885 return DfpMath.tan(this);
2886 }
2887
2888
2889
2890 @Override
2891 public Dfp acos() {
2892 return DfpMath.acos(this);
2893 }
2894
2895
2896
2897 @Override
2898 public Dfp asin() {
2899 return DfpMath.asin(this);
2900 }
2901
2902
2903
2904 @Override
2905 public Dfp atan() {
2906 return DfpMath.atan(this);
2907 }
2908
2909
2910
2911 @Override
2912 public Dfp atan2(final Dfp x)
2913 throws MathIllegalArgumentException {
2914
2915
2916 final Dfp r = x.square().add(multiply(this)).sqrt();
2917 if (r.isZero()) {
2918
2919 if (x.sign >= 0) {
2920 return this;
2921 } else {
2922 return newInstance((sign <= 0) ? -FastMath.PI : FastMath.PI);
2923 }
2924 }
2925
2926 if (x.sign >= 0) {
2927
2928
2929 return getTwo().multiply(divide(r.add(x)).atan());
2930
2931 } else {
2932
2933
2934 final Dfp tmp = getTwo().multiply(divide(r.subtract(x)).atan());
2935 final Dfp pmPi = newInstance((tmp.sign <= 0) ? -FastMath.PI : FastMath.PI);
2936 return pmPi.subtract(tmp);
2937
2938 }
2939
2940 }
2941
2942
2943
2944 @Override
2945 public Dfp cosh() {
2946 return DfpMath.exp(this).add(DfpMath.exp(negate())).multiply(0.5);
2947 }
2948
2949
2950
2951 @Override
2952 public Dfp sinh() {
2953 return DfpMath.exp(this).subtract(DfpMath.exp(negate())).multiply(0.5);
2954 }
2955
2956
2957
2958 @Override
2959 public FieldSinhCosh<Dfp> sinhCosh() {
2960 final Dfp p = DfpMath.exp(this);
2961 final Dfp m = DfpMath.exp(negate());
2962 return new FieldSinhCosh<>(p.subtract(m).multiply(0.5), p.add(m).multiply(0.5));
2963 }
2964
2965
2966
2967 @Override
2968 public Dfp tanh() {
2969 final Dfp ePlus = DfpMath.exp(this);
2970 final Dfp eMinus = DfpMath.exp(negate());
2971 return ePlus.subtract(eMinus).divide(ePlus.add(eMinus));
2972 }
2973
2974
2975
2976 @Override
2977 public Dfp acosh() {
2978 return square().subtract(getOne()).sqrt().add(this).log();
2979 }
2980
2981
2982
2983 @Override
2984 public Dfp asinh() {
2985 return square().add(getOne()).sqrt().add(this).log();
2986 }
2987
2988
2989
2990 @Override
2991 public Dfp atanh() {
2992 return getOne().add(this).divide(getOne().subtract(this)).log().divide(2);
2993 }
2994
2995
2996 @Override
2997 public Dfp toDegrees() {
2998 return multiply(field.getRadToDeg());
2999 }
3000
3001
3002 @Override
3003 public Dfp toRadians() {
3004 return multiply(field.getDegToRad());
3005 }
3006
3007
3008
3009 @Override
3010 public Dfp linearCombination(final Dfp[] a, final Dfp[] b)
3011 throws MathIllegalArgumentException {
3012
3013 MathUtils.checkDimension(a.length, b.length);
3014
3015
3016 final DfpField extendedField = a[0].field.getExtendedField(LINEAR_COMBINATION_DIGITS_FACTOR, false);
3017 Dfp r = extendedField.getZero();
3018 for (int i = 0; i < a.length; ++i) {
3019 final Dfp aiExt = a[i].newInstance(extendedField, null);
3020 final Dfp biExt = b[i].newInstance(extendedField, null);
3021 r = r.add(aiExt.multiply(biExt));
3022 }
3023
3024
3025 return r.newInstance(a[0].field, DfpField.RoundingMode.ROUND_HALF_EVEN);
3026
3027 }
3028
3029
3030
3031 @Override
3032 public Dfp linearCombination(final double[] a, final Dfp[] b)
3033 throws MathIllegalArgumentException {
3034
3035 MathUtils.checkDimension(a.length, b.length);
3036
3037
3038 final DfpField extendedField = b[0].field.getExtendedField(LINEAR_COMBINATION_DIGITS_FACTOR, false);
3039 Dfp r = extendedField.getZero();
3040 for (int i = 0; i < a.length; ++i) {
3041 final Dfp biExt = b[i].newInstance(extendedField, null);
3042 r = r.add(biExt.multiply(a[i]));
3043 }
3044
3045
3046 return r.newInstance(b[0].field, DfpField.RoundingMode.ROUND_HALF_EVEN);
3047
3048 }
3049
3050
3051
3052 @Override
3053 public Dfp linearCombination(final Dfp a1, final Dfp b1, final Dfp a2, final Dfp b2) {
3054
3055
3056 final DfpField extendedField = a1.field.getExtendedField(LINEAR_COMBINATION_DIGITS_FACTOR, false);
3057 final Dfp a1Ext = a1.newInstance(extendedField, null);
3058 final Dfp b1Ext = b1.newInstance(extendedField, null);
3059 final Dfp a2Ext = a2.newInstance(extendedField, null);
3060 final Dfp b2Ext = b2.newInstance(extendedField, null);
3061
3062
3063 final Dfp resultExt = a1Ext.multiply(b1Ext).
3064 add(a2Ext.multiply(b2Ext));
3065
3066
3067 return resultExt.newInstance(a1.field, DfpField.RoundingMode.ROUND_HALF_EVEN);
3068
3069 }
3070
3071
3072
3073 @Override
3074 public Dfp linearCombination(final double a1, final Dfp b1, final double a2, final Dfp b2) {
3075
3076
3077 final DfpField extendedField = b1.field.getExtendedField(LINEAR_COMBINATION_DIGITS_FACTOR, false);
3078 final Dfp b1Ext = b1.newInstance(extendedField, null);
3079 final Dfp b2Ext = b2.newInstance(extendedField, null);
3080
3081
3082 final Dfp resultExt = b1Ext.multiply(a1).
3083 add(b2Ext.multiply(a2));
3084
3085
3086 return resultExt.newInstance(b1.field, DfpField.RoundingMode.ROUND_HALF_EVEN);
3087
3088 }
3089
3090
3091
3092 @Override
3093 public Dfp linearCombination(final Dfp a1, final Dfp b1,
3094 final Dfp a2, final Dfp b2,
3095 final Dfp a3, final Dfp b3) {
3096
3097
3098 final DfpField extendedField = a1.field.getExtendedField(LINEAR_COMBINATION_DIGITS_FACTOR, false);
3099 final Dfp a1Ext = a1.newInstance(extendedField, null);
3100 final Dfp b1Ext = b1.newInstance(extendedField, null);
3101 final Dfp a2Ext = a2.newInstance(extendedField, null);
3102 final Dfp b2Ext = b2.newInstance(extendedField, null);
3103 final Dfp a3Ext = a3.newInstance(extendedField, null);
3104 final Dfp b3Ext = b3.newInstance(extendedField, null);
3105
3106
3107 final Dfp resultExt = a1Ext.multiply(b1Ext).
3108 add(a2Ext.multiply(b2Ext)).
3109 add(a3Ext.multiply(b3Ext));
3110
3111
3112 return resultExt.newInstance(a1.field, DfpField.RoundingMode.ROUND_HALF_EVEN);
3113
3114 }
3115
3116
3117
3118 @Override
3119 public Dfp linearCombination(final double a1, final Dfp b1,
3120 final double a2, final Dfp b2,
3121 final double a3, final Dfp b3) {
3122
3123
3124 final DfpField extendedField = b1.field.getExtendedField(LINEAR_COMBINATION_DIGITS_FACTOR, false);
3125 final Dfp b1Ext = b1.newInstance(extendedField, null);
3126 final Dfp b2Ext = b2.newInstance(extendedField, null);
3127 final Dfp b3Ext = b3.newInstance(extendedField, null);
3128
3129
3130 final Dfp resultExt = b1Ext.multiply(a1).
3131 add(b2Ext.multiply(a2)).
3132 add(b3Ext.multiply(a3));
3133
3134
3135 return resultExt.newInstance(b1.field, DfpField.RoundingMode.ROUND_HALF_EVEN);
3136
3137 }
3138
3139
3140
3141 @Override
3142 public Dfp linearCombination(final Dfp a1, final Dfp b1, final Dfp a2, final Dfp b2,
3143 final Dfp a3, final Dfp b3, final Dfp a4, final Dfp b4) {
3144
3145
3146 final DfpField extendedField = a1.field.getExtendedField(LINEAR_COMBINATION_DIGITS_FACTOR, false);
3147 final Dfp a1Ext = a1.newInstance(extendedField, null);
3148 final Dfp b1Ext = b1.newInstance(extendedField, null);
3149 final Dfp a2Ext = a2.newInstance(extendedField, null);
3150 final Dfp b2Ext = b2.newInstance(extendedField, null);
3151 final Dfp a3Ext = a3.newInstance(extendedField, null);
3152 final Dfp b3Ext = b3.newInstance(extendedField, null);
3153 final Dfp a4Ext = a4.newInstance(extendedField, null);
3154 final Dfp b4Ext = b4.newInstance(extendedField, null);
3155
3156
3157 final Dfp resultExt = a1Ext.multiply(b1Ext).
3158 add(a2Ext.multiply(b2Ext)).
3159 add(a3Ext.multiply(b3Ext)).
3160 add(a4Ext.multiply(b4Ext));
3161
3162
3163 return resultExt.newInstance(a1.field, DfpField.RoundingMode.ROUND_HALF_EVEN);
3164
3165 }
3166
3167
3168
3169 @Override
3170 public Dfp linearCombination(final double a1, final Dfp b1, final double a2, final Dfp b2,
3171 final double a3, final Dfp b3, final double a4, final Dfp b4) {
3172
3173
3174 final DfpField extendedField = b1.field.getExtendedField(LINEAR_COMBINATION_DIGITS_FACTOR, false);
3175 final Dfp b1Ext = b1.newInstance(extendedField, null);
3176 final Dfp b2Ext = b2.newInstance(extendedField, null);
3177 final Dfp b3Ext = b3.newInstance(extendedField, null);
3178 final Dfp b4Ext = b4.newInstance(extendedField, null);
3179
3180
3181 final Dfp resultExt = b1Ext.multiply(a1).
3182 add(b2Ext.multiply(a2)).
3183 add(b3Ext.multiply(a3)).
3184 add(b4Ext.multiply(a4));
3185
3186
3187 return resultExt.newInstance(b1.field, DfpField.RoundingMode.ROUND_HALF_EVEN);
3188
3189 }
3190
3191
3192 @Override
3193 public Dfp getPi() {
3194 return field.getPi();
3195 }
3196
3197 }