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;
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 System.arraycopy(remainder, 0, dividend, 1, mant.length);
2036 }
2037
2038
2039 md = mant.length;
2040 for (int i = mant.length + 1; i >= 0; i--) {
2041 if (quotient[i] != 0) {
2042 md = i;
2043 break;
2044 }
2045 }
2046
2047
2048 for (int i=0; i<mant.length; i++) {
2049 result.mant[mant.length-i-1] = quotient[md-i];
2050 }
2051
2052
2053 result.exp = exp - divisor.exp + md - mant.length;
2054 result.sign = (byte) ((sign == divisor.sign) ? 1 : -1);
2055
2056 if (result.mant[mant.length-1] == 0) {
2057 result.exp = 0;
2058 }
2059
2060 if (md > (mant.length-1)) {
2061 excp = result.round(quotient[md-mant.length]);
2062 } else {
2063 excp = result.round(0);
2064 }
2065
2066 if (excp != 0) {
2067 result = dotrap(excp, DIVIDE_TRAP, divisor, result);
2068 }
2069
2070 return result;
2071 }
2072
2073
2074
2075
2076
2077
2078 public Dfp divide(int divisor) {
2079
2080
2081 if (nans != FINITE) {
2082 if (isNaN()) {
2083 return this;
2084 }
2085
2086 if (nans == INFINITE) {
2087 return newInstance(this);
2088 }
2089 }
2090
2091
2092 if (divisor == 0) {
2093 field.setIEEEFlagsBits(DfpField.FLAG_DIV_ZERO);
2094 Dfp result = newInstance(getZero());
2095 result.sign = sign;
2096 result.nans = INFINITE;
2097 result = dotrap(DfpField.FLAG_DIV_ZERO, DIVIDE_TRAP, getZero(), result);
2098 return result;
2099 }
2100
2101
2102 if (divisor < 0 || divisor >= RADIX) {
2103 field.setIEEEFlagsBits(DfpField.FLAG_INVALID);
2104 Dfp result = newInstance(getZero());
2105 result.nans = QNAN;
2106 result = dotrap(DfpField.FLAG_INVALID, DIVIDE_TRAP, result, result);
2107 return result;
2108 }
2109
2110 Dfp result = newInstance(this);
2111
2112 int rl = 0;
2113 for (int i = mant.length-1; i >= 0; i--) {
2114 final int r = rl*RADIX + result.mant[i];
2115 final int rh = r / divisor;
2116 rl = r - rh * divisor;
2117 result.mant[i] = rh;
2118 }
2119
2120 if (result.mant[mant.length-1] == 0) {
2121
2122 result.shiftLeft();
2123 final int r = rl * RADIX;
2124 final int rh = r / divisor;
2125 rl = r - rh * divisor;
2126 result.mant[0] = rh;
2127 }
2128
2129 final int excp = result.round(rl * RADIX / divisor);
2130 if (excp != 0) {
2131 result = dotrap(excp, DIVIDE_TRAP, result, result);
2132 }
2133
2134 return result;
2135
2136 }
2137
2138
2139 @Override
2140 public Dfp reciprocal() {
2141 return field.getOne().divide(this);
2142 }
2143
2144
2145
2146
2147 @Override
2148 public Dfp sqrt() {
2149
2150
2151 if (nans == FINITE && mant[mant.length-1] == 0) {
2152
2153 return newInstance(this);
2154 }
2155
2156 if (nans != FINITE) {
2157 if (nans == INFINITE && sign == 1) {
2158
2159 return newInstance(this);
2160 }
2161
2162 if (nans == QNAN) {
2163 return newInstance(this);
2164 }
2165
2166 if (nans == SNAN) {
2167 Dfp result;
2168
2169 field.setIEEEFlagsBits(DfpField.FLAG_INVALID);
2170 result = newInstance(this);
2171 result = dotrap(DfpField.FLAG_INVALID, SQRT_TRAP, null, result);
2172 return result;
2173 }
2174 }
2175
2176 if (sign == -1) {
2177
2178 Dfp result;
2179
2180 field.setIEEEFlagsBits(DfpField.FLAG_INVALID);
2181 result = newInstance(this);
2182 result.nans = QNAN;
2183 result = dotrap(DfpField.FLAG_INVALID, SQRT_TRAP, null, result);
2184 return result;
2185 }
2186
2187 Dfp x = newInstance(this);
2188
2189
2190 if (x.exp < -1 || x.exp > 1) {
2191 x.exp = this.exp / 2;
2192 }
2193
2194
2195 switch (x.mant[mant.length-1] / 2000) {
2196 case 0:
2197 x.mant[mant.length-1] = x.mant[mant.length-1]/2+1;
2198 break;
2199 case 2:
2200 x.mant[mant.length-1] = 1500;
2201 break;
2202 case 3:
2203 x.mant[mant.length-1] = 2200;
2204 break;
2205 default:
2206 x.mant[mant.length-1] = 3000;
2207 break;
2208 }
2209
2210
2211
2212
2213 Dfp dx;
2214 Dfp px = getZero();
2215 Dfp ppx;
2216 while (x.unequal(px)) {
2217 dx = newInstance(x);
2218 dx.sign = -1;
2219 dx = dx.add(this.divide(x));
2220 dx = dx.divide(2);
2221 ppx = px;
2222 px = x;
2223 x = x.add(dx);
2224
2225 if (x.equals(ppx)) {
2226
2227 break;
2228 }
2229
2230
2231
2232 if (dx.mant[mant.length-1] == 0) {
2233 break;
2234 }
2235 }
2236
2237 return x;
2238
2239 }
2240
2241
2242
2243
2244 @Override
2245 public String toString() {
2246 if (nans != FINITE) {
2247
2248 if (nans == INFINITE) {
2249 return (sign < 0) ? NEG_INFINITY_STRING : POS_INFINITY_STRING;
2250 } else {
2251 return NAN_STRING;
2252 }
2253 }
2254
2255 if (exp > mant.length || exp < -1) {
2256 return dfp2sci();
2257 }
2258
2259 return dfp2string();
2260
2261 }
2262
2263
2264
2265
2266 protected String dfp2sci() {
2267 char[] rawdigits = new char[mant.length * 4];
2268 int p;
2269 int e;
2270 int ae;
2271 int shf;
2272
2273
2274 p = 0;
2275 for (int i = mant.length - 1; i >= 0; i--) {
2276 rawdigits[p++] = (char) ((mant[i] / 1000) + '0');
2277 rawdigits[p++] = (char) (((mant[i] / 100) %10) + '0');
2278 rawdigits[p++] = (char) (((mant[i] / 10) % 10) + '0');
2279 rawdigits[p++] = (char) (((mant[i]) % 10) + '0');
2280 }
2281
2282
2283 for (p = 0; p < rawdigits.length; p++) {
2284 if (rawdigits[p] != '0') {
2285 break;
2286 }
2287 }
2288 shf = p;
2289
2290
2291 StringBuilder builder = new StringBuilder();
2292 if (sign == -1) {
2293 builder.append('-');
2294 }
2295
2296 if (p != rawdigits.length) {
2297
2298 builder.append(rawdigits[p++]).append('.');
2299
2300 while (p<rawdigits.length) {
2301 builder.append(rawdigits[p++]);
2302 }
2303 } else {
2304 builder.append("0.0e0");
2305 return builder.toString();
2306 }
2307
2308 builder.append('e');
2309
2310
2311
2312 e = exp * 4 - shf - 1;
2313 ae = e;
2314 if (e < 0) {
2315 ae = -e;
2316 }
2317
2318
2319 for (p = 1000000000; p > ae; p /= 10) {
2320
2321 }
2322
2323 if (e < 0) {
2324 builder.append('-');
2325 }
2326
2327 while (p > 0) {
2328 builder.append((char)(ae / p + '0'));
2329 ae %= p;
2330 p /= 10;
2331 }
2332
2333 return builder.toString();
2334
2335 }
2336
2337
2338
2339
2340 protected String dfp2string() {
2341 final String fourZero = "0000";
2342 int e = exp;
2343 boolean pointInserted = false;
2344
2345 StringBuilder builder = new StringBuilder(23);
2346
2347 if (e <= 0) {
2348 builder.append("0.");
2349 pointInserted = true;
2350 }
2351
2352 while (e < 0) {
2353 builder.append(fourZero);
2354 e++;
2355 }
2356
2357 for (int i = mant.length - 1; i >= 0; i--) {
2358 builder.
2359 append((char) ((mant[i] / 1000) + '0')).
2360 append((char) (((mant[i] / 100) % 10) + '0')).
2361 append((char) (((mant[i] / 10) % 10) + '0')).
2362 append((char) (((mant[i]) % 10) + '0'));
2363 --e;
2364 if (e == 0) {
2365 builder.append('.');
2366 pointInserted = true;
2367 }
2368 }
2369
2370 while (e > 0) {
2371 builder.append(fourZero);
2372 e--;
2373 }
2374
2375 if (!pointInserted) {
2376
2377 builder.append('.');
2378 }
2379
2380
2381 while (builder.charAt(0) == '0') {
2382 builder.deleteCharAt(0);
2383 }
2384 if (builder.charAt(0) == '.') {
2385 builder.insert(0, '0');
2386 }
2387
2388
2389 while (builder.charAt(builder.length() - 1) == '0') {
2390 builder.deleteCharAt(builder.length() - 1);
2391 }
2392
2393
2394 if (sign < 0) {
2395 builder.insert(0, '-');
2396 }
2397
2398 return builder.toString();
2399
2400 }
2401
2402
2403
2404
2405
2406
2407
2408
2409 public Dfp dotrap(int type, String what, Dfp oper, Dfp result) {
2410 Dfp def = result;
2411
2412 switch (type) {
2413 case DfpField.FLAG_INVALID:
2414 def = newInstance(getZero());
2415 def.sign = result.sign;
2416 def.nans = QNAN;
2417 break;
2418
2419 case DfpField.FLAG_DIV_ZERO:
2420 if (nans == FINITE && mant[mant.length-1] != 0) {
2421
2422 def = newInstance(getZero());
2423 def.sign = (byte)(sign*oper.sign);
2424 def.nans = INFINITE;
2425 }
2426
2427 if (nans == FINITE && mant[mant.length-1] == 0) {
2428
2429 def = newInstance(getZero());
2430 def.nans = QNAN;
2431 }
2432
2433 if (nans == INFINITE || nans == QNAN) {
2434 def = newInstance(getZero());
2435 def.nans = QNAN;
2436 }
2437
2438 if (nans == INFINITE || nans == SNAN) {
2439 def = newInstance(getZero());
2440 def.nans = QNAN;
2441 }
2442 break;
2443
2444 case DfpField.FLAG_UNDERFLOW:
2445 if ( (result.exp+mant.length) < MIN_EXP) {
2446 def = newInstance(getZero());
2447 def.sign = result.sign;
2448 } else {
2449 def = newInstance(result);
2450 }
2451 result.exp += ERR_SCALE;
2452 break;
2453
2454 case DfpField.FLAG_OVERFLOW:
2455 result.exp -= ERR_SCALE;
2456 def = newInstance(getZero());
2457 def.sign = result.sign;
2458 def.nans = INFINITE;
2459 break;
2460
2461 default: def = result; break;
2462 }
2463
2464 return trap(type, what, oper, def, result);
2465
2466 }
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479 protected Dfp trap(int type, String what, Dfp oper, Dfp def, Dfp result) {
2480 return def;
2481 }
2482
2483
2484
2485
2486 public int classify() {
2487 return nans;
2488 }
2489
2490
2491
2492
2493
2494
2495
2496 public static Dfp copysign(final Dfp x, final Dfp y) {
2497 Dfp result = x.newInstance(x);
2498 result.sign = y.sign;
2499 return result;
2500 }
2501
2502
2503
2504
2505
2506
2507 public Dfp nextAfter(final Dfp x) {
2508
2509
2510 if (field.getRadixDigits() != x.field.getRadixDigits()) {
2511 field.setIEEEFlagsBits(DfpField.FLAG_INVALID);
2512 final Dfp result = newInstance(getZero());
2513 result.nans = QNAN;
2514 return dotrap(DfpField.FLAG_INVALID, NEXT_AFTER_TRAP, x, result);
2515 }
2516
2517
2518 boolean up = false;
2519 if (this.lessThan(x)) {
2520 up = true;
2521 }
2522
2523 if (compare(this, x) == 0) {
2524 return newInstance(x);
2525 }
2526
2527 if (lessThan(getZero())) {
2528 up = !up;
2529 }
2530
2531 final Dfp inc;
2532 Dfp result;
2533 if (up) {
2534 inc = newInstance(getOne());
2535 inc.exp = this.exp-mant.length+1;
2536 inc.sign = this.sign;
2537
2538 if (this.equals(getZero())) {
2539 inc.exp = MIN_EXP-mant.length;
2540 }
2541
2542 result = add(inc);
2543 } else {
2544 inc = newInstance(getOne());
2545 inc.exp = this.exp;
2546 inc.sign = this.sign;
2547
2548 if (this.equals(inc)) {
2549 inc.exp = this.exp-mant.length;
2550 } else {
2551 inc.exp = this.exp-mant.length+1;
2552 }
2553
2554 if (this.equals(getZero())) {
2555 inc.exp = MIN_EXP-mant.length;
2556 }
2557
2558 result = this.subtract(inc);
2559 }
2560
2561 if (result.classify() == INFINITE && this.classify() != INFINITE) {
2562 field.setIEEEFlagsBits(DfpField.FLAG_INEXACT);
2563 result = dotrap(DfpField.FLAG_INEXACT, NEXT_AFTER_TRAP, x, result);
2564 }
2565
2566 if (result.equals(getZero()) && !this.equals(getZero())) {
2567 field.setIEEEFlagsBits(DfpField.FLAG_INEXACT);
2568 result = dotrap(DfpField.FLAG_INEXACT, NEXT_AFTER_TRAP, x, result);
2569 }
2570
2571 return result;
2572
2573 }
2574
2575
2576
2577
2578
2579 public double toDouble() {
2580
2581 if (isInfinite()) {
2582 if (lessThan(getZero())) {
2583 return Double.NEGATIVE_INFINITY;
2584 } else {
2585 return Double.POSITIVE_INFINITY;
2586 }
2587 }
2588
2589 if (isNaN()) {
2590 return Double.NaN;
2591 }
2592
2593 Dfp y = this;
2594 boolean negate = false;
2595 int cmp0 = compare(this, getZero());
2596 if (cmp0 == 0) {
2597 return sign < 0 ? -0.0 : +0.0;
2598 } else if (cmp0 < 0) {
2599 y = negate();
2600 negate = true;
2601 }
2602
2603
2604
2605 int exponent = (int)(y.intLog10() * 3.32);
2606 if (exponent < 0) {
2607 exponent--;
2608 }
2609
2610 Dfp tempDfp = DfpMath.pow(getTwo(), exponent);
2611 while (tempDfp.lessThan(y) || tempDfp.equals(y)) {
2612 tempDfp = tempDfp.multiply(2);
2613 exponent++;
2614 }
2615 exponent--;
2616
2617
2618
2619 y = y.divide(DfpMath.pow(getTwo(), exponent));
2620 if (exponent > -1023) {
2621 y = y.subtract(getOne());
2622 }
2623
2624 if (exponent < -1074) {
2625 return 0;
2626 }
2627
2628 if (exponent > 1023) {
2629 return negate ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
2630 }
2631
2632
2633 y = y.multiply(newInstance(4503599627370496L)).rint();
2634 String str = y.toString();
2635 str = str.substring(0, str.length()-1);
2636 long mantissa = Long.parseLong(str);
2637
2638 if (mantissa == 4503599627370496L) {
2639
2640 mantissa = 0;
2641 exponent++;
2642 }
2643
2644
2645 if (exponent <= -1023) {
2646 exponent--;
2647 }
2648
2649 while (exponent < -1023) {
2650 exponent++;
2651 mantissa >>>= 1;
2652 }
2653
2654 long bits = mantissa | ((exponent + 1023L) << 52);
2655 double x = Double.longBitsToDouble(bits);
2656
2657 if (negate) {
2658 x = -x;
2659 }
2660
2661 return x;
2662
2663 }
2664
2665
2666
2667
2668
2669 public double[] toSplitDouble() {
2670 double[] split = new double[2];
2671 long mask = 0xffffffffc0000000L;
2672
2673 split[0] = Double.longBitsToDouble(Double.doubleToLongBits(toDouble()) & mask);
2674 split[1] = subtract(newInstance(split[0])).toDouble();
2675
2676 return split;
2677 }
2678
2679
2680
2681 @Override
2682 public double getReal() {
2683 return toDouble();
2684 }
2685
2686
2687 @Override
2688 public Dfp getAddendum() {
2689 return isFinite() ? subtract(getReal()) : getZero();
2690 }
2691
2692
2693
2694 @Override
2695 public Dfp remainder(final double a) {
2696 return remainder(newInstance(a));
2697 }
2698
2699
2700
2701 @Override
2702 public Dfp sign() {
2703 if (isNaN() || isZero()) {
2704 return this;
2705 } else {
2706 return newInstance(sign > 0 ? +1 : -1);
2707 }
2708 }
2709
2710
2711
2712 @Override
2713 public Dfp copySign(final Dfp s) {
2714 if ((sign >= 0 && s.sign >= 0) || (sign < 0 && s.sign < 0)) {
2715 return this;
2716 }
2717 return negate();
2718 }
2719
2720
2721
2722 @Override
2723 public Dfp copySign(final double s) {
2724 long sb = Double.doubleToLongBits(s);
2725 if ((sign >= 0 && sb >= 0) || (sign < 0 && sb < 0)) {
2726 return this;
2727 }
2728 return negate();
2729 }
2730
2731
2732
2733 @Override
2734 public int getExponent() {
2735
2736 if (nans != FINITE) {
2737
2738 return 435411;
2739 }
2740 if (isZero()) {
2741 return -435412;
2742 }
2743
2744 final Dfp abs = abs();
2745
2746
2747
2748 int p = FastMath.max(13301 * exp / 1001 - 15, -435411);
2749 Dfp twoP = DfpMath.pow(getTwo(), p);
2750 while (compare(abs, twoP) >= 0) {
2751 twoP = twoP.add(twoP);
2752 ++p;
2753 }
2754
2755 return p - 1;
2756
2757 }
2758
2759
2760
2761 @Override
2762 public Dfp scalb(final int n) {
2763 return multiply(DfpMath.pow(getTwo(), n));
2764 }
2765
2766
2767
2768 @Override
2769 public Dfp ulp() {
2770 final Dfp result = new Dfp(field);
2771 result.mant[result.mant.length - 1] = 1;
2772 result.exp = exp - (result.mant.length - 1);
2773 return result;
2774 }
2775
2776
2777
2778 @Override
2779 public Dfp hypot(final Dfp y) {
2780
2781 if (isInfinite() || y.isInfinite()) {
2782 return field.newDfp(Double.POSITIVE_INFINITY);
2783 } else if (isNaN() || y.isNaN()) {
2784 return field.newDfp(Double.NaN);
2785 } else {
2786
2787 final int scalingExp = (exp + y.exp) / 2;
2788
2789
2790 final Dfp scaledX = new Dfp(this);
2791 scaledX.exp -= scalingExp;
2792 final Dfp scaledY = new Dfp(y);
2793 scaledY.exp -= scalingExp;
2794
2795
2796 final Dfp h = scaledX.multiply(scaledX).add(scaledY.multiply(scaledY)).sqrt();
2797
2798
2799 h.exp += scalingExp;
2800
2801 return h;
2802 }
2803
2804 }
2805
2806
2807
2808 @Override
2809 public Dfp rootN(final int n) {
2810 return (sign >= 0) ?
2811 DfpMath.pow(this, getOne().divide(n)) :
2812 DfpMath.pow(negate(), getOne().divide(n)).negate();
2813 }
2814
2815
2816
2817 @Override
2818 public Dfp pow(final double p) {
2819 return DfpMath.pow(this, newInstance(p));
2820 }
2821
2822
2823
2824 @Override
2825 public Dfp pow(final int n) {
2826 return DfpMath.pow(this, n);
2827 }
2828
2829
2830
2831 @Override
2832 public Dfp pow(final Dfp e) {
2833 return DfpMath.pow(this, e);
2834 }
2835
2836
2837
2838 @Override
2839 public Dfp exp() {
2840 return DfpMath.exp(this);
2841 }
2842
2843
2844
2845 @Override
2846 public Dfp expm1() {
2847 return DfpMath.exp(this).subtract(getOne());
2848 }
2849
2850
2851
2852 @Override
2853 public Dfp log() {
2854 return DfpMath.log(this);
2855 }
2856
2857
2858
2859 @Override
2860 public Dfp log1p() {
2861 return DfpMath.log(this.add(getOne()));
2862 }
2863
2864
2865
2866 @Override
2867 public Dfp log10() {
2868 return DfpMath.log(this).divide(DfpMath.log(newInstance(10)));
2869 }
2870
2871
2872
2873 @Override
2874 public Dfp cos() {
2875 return DfpMath.cos(this);
2876 }
2877
2878
2879
2880 @Override
2881 public Dfp sin() {
2882 return DfpMath.sin(this);
2883 }
2884
2885
2886
2887 @Override
2888 public Dfp tan() {
2889 return DfpMath.tan(this);
2890 }
2891
2892
2893
2894 @Override
2895 public Dfp acos() {
2896 return DfpMath.acos(this);
2897 }
2898
2899
2900
2901 @Override
2902 public Dfp asin() {
2903 return DfpMath.asin(this);
2904 }
2905
2906
2907
2908 @Override
2909 public Dfp atan() {
2910 return DfpMath.atan(this);
2911 }
2912
2913
2914
2915 @Override
2916 public Dfp atan2(final Dfp x)
2917 throws MathIllegalArgumentException {
2918
2919
2920 final Dfp r = x.square().add(multiply(this)).sqrt();
2921 if (r.isZero()) {
2922
2923 if (x.sign >= 0) {
2924 return this;
2925 } else {
2926 return newInstance((sign <= 0) ? -FastMath.PI : FastMath.PI);
2927 }
2928 }
2929
2930 if (x.sign >= 0) {
2931
2932
2933 return getTwo().multiply(divide(r.add(x)).atan());
2934
2935 } else {
2936
2937
2938 final Dfp tmp = getTwo().multiply(divide(r.subtract(x)).atan());
2939 final Dfp pmPi = newInstance((tmp.sign <= 0) ? -FastMath.PI : FastMath.PI);
2940 return pmPi.subtract(tmp);
2941
2942 }
2943
2944 }
2945
2946
2947
2948 @Override
2949 public Dfp cosh() {
2950 return DfpMath.exp(this).add(DfpMath.exp(negate())).multiply(0.5);
2951 }
2952
2953
2954
2955 @Override
2956 public Dfp sinh() {
2957 return DfpMath.exp(this).subtract(DfpMath.exp(negate())).multiply(0.5);
2958 }
2959
2960
2961
2962 @Override
2963 public FieldSinhCosh<Dfp> sinhCosh() {
2964 final Dfp p = DfpMath.exp(this);
2965 final Dfp m = DfpMath.exp(negate());
2966 return new FieldSinhCosh<>(p.subtract(m).multiply(0.5), p.add(m).multiply(0.5));
2967 }
2968
2969
2970
2971 @Override
2972 public Dfp tanh() {
2973 final Dfp ePlus = DfpMath.exp(this);
2974 final Dfp eMinus = DfpMath.exp(negate());
2975 return ePlus.subtract(eMinus).divide(ePlus.add(eMinus));
2976 }
2977
2978
2979
2980 @Override
2981 public Dfp acosh() {
2982 return square().subtract(getOne()).sqrt().add(this).log();
2983 }
2984
2985
2986
2987 @Override
2988 public Dfp asinh() {
2989 return square().add(getOne()).sqrt().add(this).log();
2990 }
2991
2992
2993
2994 @Override
2995 public Dfp atanh() {
2996 return getOne().add(this).divide(getOne().subtract(this)).log().divide(2);
2997 }
2998
2999
3000 @Override
3001 public Dfp toDegrees() {
3002 return multiply(field.getRadToDeg());
3003 }
3004
3005
3006 @Override
3007 public Dfp toRadians() {
3008 return multiply(field.getDegToRad());
3009 }
3010
3011
3012
3013 @Override
3014 public Dfp linearCombination(final Dfp[] a, final Dfp[] b)
3015 throws MathIllegalArgumentException {
3016
3017 MathUtils.checkDimension(a.length, b.length);
3018
3019
3020 final DfpField extendedField = a[0].field.getExtendedField(LINEAR_COMBINATION_DIGITS_FACTOR, false);
3021 Dfp r = extendedField.getZero();
3022 for (int i = 0; i < a.length; ++i) {
3023 final Dfp aiExt = a[i].newInstance(extendedField, null);
3024 final Dfp biExt = b[i].newInstance(extendedField, null);
3025 r = r.add(aiExt.multiply(biExt));
3026 }
3027
3028
3029 return r.newInstance(a[0].field, DfpField.RoundingMode.ROUND_HALF_EVEN);
3030
3031 }
3032
3033
3034
3035 @Override
3036 public Dfp linearCombination(final double[] a, final Dfp[] b)
3037 throws MathIllegalArgumentException {
3038
3039 MathUtils.checkDimension(a.length, b.length);
3040
3041
3042 final DfpField extendedField = b[0].field.getExtendedField(LINEAR_COMBINATION_DIGITS_FACTOR, false);
3043 Dfp r = extendedField.getZero();
3044 for (int i = 0; i < a.length; ++i) {
3045 final Dfp biExt = b[i].newInstance(extendedField, null);
3046 r = r.add(biExt.multiply(a[i]));
3047 }
3048
3049
3050 return r.newInstance(b[0].field, DfpField.RoundingMode.ROUND_HALF_EVEN);
3051
3052 }
3053
3054
3055
3056 @Override
3057 public Dfp linearCombination(final Dfp a1, final Dfp b1, final Dfp a2, final Dfp b2) {
3058
3059
3060 final DfpField extendedField = a1.field.getExtendedField(LINEAR_COMBINATION_DIGITS_FACTOR, false);
3061 final Dfp a1Ext = a1.newInstance(extendedField, null);
3062 final Dfp b1Ext = b1.newInstance(extendedField, null);
3063 final Dfp a2Ext = a2.newInstance(extendedField, null);
3064 final Dfp b2Ext = b2.newInstance(extendedField, null);
3065
3066
3067 final Dfp resultExt = a1Ext.multiply(b1Ext).
3068 add(a2Ext.multiply(b2Ext));
3069
3070
3071 return resultExt.newInstance(a1.field, DfpField.RoundingMode.ROUND_HALF_EVEN);
3072
3073 }
3074
3075
3076
3077 @Override
3078 public Dfp linearCombination(final double a1, final Dfp b1, final double a2, final Dfp b2) {
3079
3080
3081 final DfpField extendedField = b1.field.getExtendedField(LINEAR_COMBINATION_DIGITS_FACTOR, false);
3082 final Dfp b1Ext = b1.newInstance(extendedField, null);
3083 final Dfp b2Ext = b2.newInstance(extendedField, null);
3084
3085
3086 final Dfp resultExt = b1Ext.multiply(a1).
3087 add(b2Ext.multiply(a2));
3088
3089
3090 return resultExt.newInstance(b1.field, DfpField.RoundingMode.ROUND_HALF_EVEN);
3091
3092 }
3093
3094
3095
3096 @Override
3097 public Dfp linearCombination(final Dfp a1, final Dfp b1,
3098 final Dfp a2, final Dfp b2,
3099 final Dfp a3, final Dfp b3) {
3100
3101
3102 final DfpField extendedField = a1.field.getExtendedField(LINEAR_COMBINATION_DIGITS_FACTOR, false);
3103 final Dfp a1Ext = a1.newInstance(extendedField, null);
3104 final Dfp b1Ext = b1.newInstance(extendedField, null);
3105 final Dfp a2Ext = a2.newInstance(extendedField, null);
3106 final Dfp b2Ext = b2.newInstance(extendedField, null);
3107 final Dfp a3Ext = a3.newInstance(extendedField, null);
3108 final Dfp b3Ext = b3.newInstance(extendedField, null);
3109
3110
3111 final Dfp resultExt = a1Ext.multiply(b1Ext).
3112 add(a2Ext.multiply(b2Ext)).
3113 add(a3Ext.multiply(b3Ext));
3114
3115
3116 return resultExt.newInstance(a1.field, DfpField.RoundingMode.ROUND_HALF_EVEN);
3117
3118 }
3119
3120
3121
3122 @Override
3123 public Dfp linearCombination(final double a1, final Dfp b1,
3124 final double a2, final Dfp b2,
3125 final double a3, final Dfp b3) {
3126
3127
3128 final DfpField extendedField = b1.field.getExtendedField(LINEAR_COMBINATION_DIGITS_FACTOR, false);
3129 final Dfp b1Ext = b1.newInstance(extendedField, null);
3130 final Dfp b2Ext = b2.newInstance(extendedField, null);
3131 final Dfp b3Ext = b3.newInstance(extendedField, null);
3132
3133
3134 final Dfp resultExt = b1Ext.multiply(a1).
3135 add(b2Ext.multiply(a2)).
3136 add(b3Ext.multiply(a3));
3137
3138
3139 return resultExt.newInstance(b1.field, DfpField.RoundingMode.ROUND_HALF_EVEN);
3140
3141 }
3142
3143
3144
3145 @Override
3146 public Dfp linearCombination(final Dfp a1, final Dfp b1, final Dfp a2, final Dfp b2,
3147 final Dfp a3, final Dfp b3, final Dfp a4, final Dfp b4) {
3148
3149
3150 final DfpField extendedField = a1.field.getExtendedField(LINEAR_COMBINATION_DIGITS_FACTOR, false);
3151 final Dfp a1Ext = a1.newInstance(extendedField, null);
3152 final Dfp b1Ext = b1.newInstance(extendedField, null);
3153 final Dfp a2Ext = a2.newInstance(extendedField, null);
3154 final Dfp b2Ext = b2.newInstance(extendedField, null);
3155 final Dfp a3Ext = a3.newInstance(extendedField, null);
3156 final Dfp b3Ext = b3.newInstance(extendedField, null);
3157 final Dfp a4Ext = a4.newInstance(extendedField, null);
3158 final Dfp b4Ext = b4.newInstance(extendedField, null);
3159
3160
3161 final Dfp resultExt = a1Ext.multiply(b1Ext).
3162 add(a2Ext.multiply(b2Ext)).
3163 add(a3Ext.multiply(b3Ext)).
3164 add(a4Ext.multiply(b4Ext));
3165
3166
3167 return resultExt.newInstance(a1.field, DfpField.RoundingMode.ROUND_HALF_EVEN);
3168
3169 }
3170
3171
3172
3173 @Override
3174 public Dfp linearCombination(final double a1, final Dfp b1, final double a2, final Dfp b2,
3175 final double a3, final Dfp b3, final double a4, final Dfp b4) {
3176
3177
3178 final DfpField extendedField = b1.field.getExtendedField(LINEAR_COMBINATION_DIGITS_FACTOR, false);
3179 final Dfp b1Ext = b1.newInstance(extendedField, null);
3180 final Dfp b2Ext = b2.newInstance(extendedField, null);
3181 final Dfp b3Ext = b3.newInstance(extendedField, null);
3182 final Dfp b4Ext = b4.newInstance(extendedField, null);
3183
3184
3185 final Dfp resultExt = b1Ext.multiply(a1).
3186 add(b2Ext.multiply(a2)).
3187 add(b3Ext.multiply(a3)).
3188 add(b4Ext.multiply(a4));
3189
3190
3191 return resultExt.newInstance(b1.field, DfpField.RoundingMode.ROUND_HALF_EVEN);
3192
3193 }
3194
3195
3196 @Override
3197 public Dfp getPi() {
3198 return field.getPi();
3199 }
3200
3201 }