1 | /*
|
---|
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
|
---|
3 | * contributor license agreements. See the NOTICE file distributed with
|
---|
4 | * this work for additional information regarding copyright ownership.
|
---|
5 | * The ASF licenses this file to You under the Apache License, Version 2.0
|
---|
6 | * (the "License"); you may not use this file except in compliance with
|
---|
7 | * the License. You may obtain a copy of the License at
|
---|
8 | *
|
---|
9 | * http://www.apache.org/licenses/LICENSE-2.0
|
---|
10 | *
|
---|
11 | * Unless required by applicable law or agreed to in writing, software
|
---|
12 | * distributed under the License is distributed on an "AS IS" BASIS,
|
---|
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
---|
14 | * See the License for the specific language governing permissions and
|
---|
15 | * limitations under the License.
|
---|
16 | */
|
---|
17 |
|
---|
18 | package agents.org.apache.commons.math.dfp;
|
---|
19 |
|
---|
20 | import agents.org.apache.commons.math.Field;
|
---|
21 |
|
---|
22 | /** Field for Decimal floating point instances.
|
---|
23 | * @version $Revision: 995987 $ $Date: 2010-09-10 23:24:15 +0200 (ven. 10 sept. 2010) $
|
---|
24 | * @since 2.2
|
---|
25 | */
|
---|
26 | public class DfpField implements Field<Dfp> {
|
---|
27 |
|
---|
28 | /** Enumerate for rounding modes. */
|
---|
29 | public enum RoundingMode {
|
---|
30 |
|
---|
31 | /** Rounds toward zero (truncation). */
|
---|
32 | ROUND_DOWN,
|
---|
33 |
|
---|
34 | /** Rounds away from zero if discarded digit is non-zero. */
|
---|
35 | ROUND_UP,
|
---|
36 |
|
---|
37 | /** Rounds towards nearest unless both are equidistant in which case it rounds away from zero. */
|
---|
38 | ROUND_HALF_UP,
|
---|
39 |
|
---|
40 | /** Rounds towards nearest unless both are equidistant in which case it rounds toward zero. */
|
---|
41 | ROUND_HALF_DOWN,
|
---|
42 |
|
---|
43 | /** Rounds towards nearest unless both are equidistant in which case it rounds toward the even neighbor.
|
---|
44 | * This is the default as specified by IEEE 854-1987
|
---|
45 | */
|
---|
46 | ROUND_HALF_EVEN,
|
---|
47 |
|
---|
48 | /** Rounds towards nearest unless both are equidistant in which case it rounds toward the odd neighbor. */
|
---|
49 | ROUND_HALF_ODD,
|
---|
50 |
|
---|
51 | /** Rounds towards positive infinity. */
|
---|
52 | ROUND_CEIL,
|
---|
53 |
|
---|
54 | /** Rounds towards negative infinity. */
|
---|
55 | ROUND_FLOOR;
|
---|
56 |
|
---|
57 | }
|
---|
58 |
|
---|
59 | /** IEEE 854-1987 flag for invalid operation. */
|
---|
60 | public static final int FLAG_INVALID = 1;
|
---|
61 |
|
---|
62 | /** IEEE 854-1987 flag for division by zero. */
|
---|
63 | public static final int FLAG_DIV_ZERO = 2;
|
---|
64 |
|
---|
65 | /** IEEE 854-1987 flag for overflow. */
|
---|
66 | public static final int FLAG_OVERFLOW = 4;
|
---|
67 |
|
---|
68 | /** IEEE 854-1987 flag for underflow. */
|
---|
69 | public static final int FLAG_UNDERFLOW = 8;
|
---|
70 |
|
---|
71 | /** IEEE 854-1987 flag for inexact result. */
|
---|
72 | public static final int FLAG_INEXACT = 16;
|
---|
73 |
|
---|
74 | /** High precision string representation of √2. */
|
---|
75 | private static String sqr2String;
|
---|
76 |
|
---|
77 | /** High precision string representation of √2 / 2. */
|
---|
78 | private static String sqr2ReciprocalString;
|
---|
79 |
|
---|
80 | /** High precision string representation of √3. */
|
---|
81 | private static String sqr3String;
|
---|
82 |
|
---|
83 | /** High precision string representation of √3 / 3. */
|
---|
84 | private static String sqr3ReciprocalString;
|
---|
85 |
|
---|
86 | /** High precision string representation of π. */
|
---|
87 | private static String piString;
|
---|
88 |
|
---|
89 | /** High precision string representation of e. */
|
---|
90 | private static String eString;
|
---|
91 |
|
---|
92 | /** High precision string representation of ln(2). */
|
---|
93 | private static String ln2String;
|
---|
94 |
|
---|
95 | /** High precision string representation of ln(5). */
|
---|
96 | private static String ln5String;
|
---|
97 |
|
---|
98 | /** High precision string representation of ln(10). */
|
---|
99 | private static String ln10String;
|
---|
100 |
|
---|
101 | /** The number of radix digits.
|
---|
102 | * Note these depend on the radix which is 10000 digits,
|
---|
103 | * so each one is equivalent to 4 decimal digits.
|
---|
104 | */
|
---|
105 | private final int radixDigits;
|
---|
106 |
|
---|
107 | /** A {@link Dfp} with value 0. */
|
---|
108 | private final Dfp zero;
|
---|
109 |
|
---|
110 | /** A {@link Dfp} with value 1. */
|
---|
111 | private final Dfp one;
|
---|
112 |
|
---|
113 | /** A {@link Dfp} with value 2. */
|
---|
114 | private final Dfp two;
|
---|
115 |
|
---|
116 | /** A {@link Dfp} with value √2. */
|
---|
117 | private final Dfp sqr2;
|
---|
118 |
|
---|
119 | /** A two elements {@link Dfp} array with value √2 split in two pieces. */
|
---|
120 | private final Dfp[] sqr2Split;
|
---|
121 |
|
---|
122 | /** A {@link Dfp} with value √2 / 2. */
|
---|
123 | private final Dfp sqr2Reciprocal;
|
---|
124 |
|
---|
125 | /** A {@link Dfp} with value √3. */
|
---|
126 | private final Dfp sqr3;
|
---|
127 |
|
---|
128 | /** A {@link Dfp} with value √3 / 3. */
|
---|
129 | private final Dfp sqr3Reciprocal;
|
---|
130 |
|
---|
131 | /** A {@link Dfp} with value π. */
|
---|
132 | private final Dfp pi;
|
---|
133 |
|
---|
134 | /** A two elements {@link Dfp} array with value π split in two pieces. */
|
---|
135 | private final Dfp[] piSplit;
|
---|
136 |
|
---|
137 | /** A {@link Dfp} with value e. */
|
---|
138 | private final Dfp e;
|
---|
139 |
|
---|
140 | /** A two elements {@link Dfp} array with value e split in two pieces. */
|
---|
141 | private final Dfp[] eSplit;
|
---|
142 |
|
---|
143 | /** A {@link Dfp} with value ln(2). */
|
---|
144 | private final Dfp ln2;
|
---|
145 |
|
---|
146 | /** A two elements {@link Dfp} array with value ln(2) split in two pieces. */
|
---|
147 | private final Dfp[] ln2Split;
|
---|
148 |
|
---|
149 | /** A {@link Dfp} with value ln(5). */
|
---|
150 | private final Dfp ln5;
|
---|
151 |
|
---|
152 | /** A two elements {@link Dfp} array with value ln(5) split in two pieces. */
|
---|
153 | private final Dfp[] ln5Split;
|
---|
154 |
|
---|
155 | /** A {@link Dfp} with value ln(10). */
|
---|
156 | private final Dfp ln10;
|
---|
157 |
|
---|
158 | /** Current rounding mode. */
|
---|
159 | private RoundingMode rMode;
|
---|
160 |
|
---|
161 | /** IEEE 854-1987 signals. */
|
---|
162 | private int ieeeFlags;
|
---|
163 |
|
---|
164 | /** Create a factory for the specified number of radix digits.
|
---|
165 | * <p>
|
---|
166 | * Note that since the {@link Dfp} class uses 10000 as its radix, each radix
|
---|
167 | * digit is equivalent to 4 decimal digits. This implies that asking for
|
---|
168 | * 13, 14, 15 or 16 decimal digits will really lead to a 4 radix 10000 digits in
|
---|
169 | * all cases.
|
---|
170 | * </p>
|
---|
171 | * @param decimalDigits minimal number of decimal digits.
|
---|
172 | */
|
---|
173 | public DfpField(final int decimalDigits) {
|
---|
174 | this(decimalDigits, true);
|
---|
175 | }
|
---|
176 |
|
---|
177 | /** Create a factory for the specified number of radix digits.
|
---|
178 | * <p>
|
---|
179 | * Note that since the {@link Dfp} class uses 10000 as its radix, each radix
|
---|
180 | * digit is equivalent to 4 decimal digits. This implies that asking for
|
---|
181 | * 13, 14, 15 or 16 decimal digits will really lead to a 4 radix 10000 digits in
|
---|
182 | * all cases.
|
---|
183 | * </p>
|
---|
184 | * @param decimalDigits minimal number of decimal digits
|
---|
185 | * @param computeConstants if true, the transcendental constants for the given precision
|
---|
186 | * must be computed (setting this flag to false is RESERVED for the internal recursive call)
|
---|
187 | */
|
---|
188 | private DfpField(final int decimalDigits, final boolean computeConstants) {
|
---|
189 |
|
---|
190 | this.radixDigits = (decimalDigits < 13) ? 4 : (decimalDigits + 3) / 4;
|
---|
191 | this.rMode = RoundingMode.ROUND_HALF_EVEN;
|
---|
192 | this.ieeeFlags = 0;
|
---|
193 | this.zero = new Dfp(this, 0);
|
---|
194 | this.one = new Dfp(this, 1);
|
---|
195 | this.two = new Dfp(this, 2);
|
---|
196 |
|
---|
197 | if (computeConstants) {
|
---|
198 | // set up transcendental constants
|
---|
199 | synchronized (DfpField.class) {
|
---|
200 |
|
---|
201 | // as a heuristic to circumvent Table-Maker's Dilemma, we set the string
|
---|
202 | // representation of the constants to be at least 3 times larger than the
|
---|
203 | // number of decimal digits, also as an attempt to really compute these
|
---|
204 | // constants only once, we set a minimum number of digits
|
---|
205 | computeStringConstants((decimalDigits < 67) ? 200 : (3 * decimalDigits));
|
---|
206 |
|
---|
207 | // set up the constants at current field accuracy
|
---|
208 | sqr2 = new Dfp(this, sqr2String);
|
---|
209 | sqr2Split = split(sqr2String);
|
---|
210 | sqr2Reciprocal = new Dfp(this, sqr2ReciprocalString);
|
---|
211 | sqr3 = new Dfp(this, sqr3String);
|
---|
212 | sqr3Reciprocal = new Dfp(this, sqr3ReciprocalString);
|
---|
213 | pi = new Dfp(this, piString);
|
---|
214 | piSplit = split(piString);
|
---|
215 | e = new Dfp(this, eString);
|
---|
216 | eSplit = split(eString);
|
---|
217 | ln2 = new Dfp(this, ln2String);
|
---|
218 | ln2Split = split(ln2String);
|
---|
219 | ln5 = new Dfp(this, ln5String);
|
---|
220 | ln5Split = split(ln5String);
|
---|
221 | ln10 = new Dfp(this, ln10String);
|
---|
222 |
|
---|
223 | }
|
---|
224 | } else {
|
---|
225 | // dummy settings for unused constants
|
---|
226 | sqr2 = null;
|
---|
227 | sqr2Split = null;
|
---|
228 | sqr2Reciprocal = null;
|
---|
229 | sqr3 = null;
|
---|
230 | sqr3Reciprocal = null;
|
---|
231 | pi = null;
|
---|
232 | piSplit = null;
|
---|
233 | e = null;
|
---|
234 | eSplit = null;
|
---|
235 | ln2 = null;
|
---|
236 | ln2Split = null;
|
---|
237 | ln5 = null;
|
---|
238 | ln5Split = null;
|
---|
239 | ln10 = null;
|
---|
240 | }
|
---|
241 |
|
---|
242 | }
|
---|
243 |
|
---|
244 | /** Get the number of radix digits of the {@link Dfp} instances built by this factory.
|
---|
245 | * @return number of radix digits
|
---|
246 | */
|
---|
247 | public int getRadixDigits() {
|
---|
248 | return radixDigits;
|
---|
249 | }
|
---|
250 |
|
---|
251 | /** Set the rounding mode.
|
---|
252 | * If not set, the default value is {@link RoundingMode#ROUND_HALF_EVEN}.
|
---|
253 | * @param mode desired rounding mode
|
---|
254 | * Note that the rounding mode is common to all {@link Dfp} instances
|
---|
255 | * belonging to the current {@link DfpField} in the system and will
|
---|
256 | * affect all future calculations.
|
---|
257 | */
|
---|
258 | public void setRoundingMode(final RoundingMode mode) {
|
---|
259 | rMode = mode;
|
---|
260 | }
|
---|
261 |
|
---|
262 | /** Get the current rounding mode.
|
---|
263 | * @return current rounding mode
|
---|
264 | */
|
---|
265 | public RoundingMode getRoundingMode() {
|
---|
266 | return rMode;
|
---|
267 | }
|
---|
268 |
|
---|
269 | /** Get the IEEE 854 status flags.
|
---|
270 | * @return IEEE 854 status flags
|
---|
271 | * @see #clearIEEEFlags()
|
---|
272 | * @see #setIEEEFlags(int)
|
---|
273 | * @see #setIEEEFlagsBits(int)
|
---|
274 | * @see #FLAG_INVALID
|
---|
275 | * @see #FLAG_DIV_ZERO
|
---|
276 | * @see #FLAG_OVERFLOW
|
---|
277 | * @see #FLAG_UNDERFLOW
|
---|
278 | * @see #FLAG_INEXACT
|
---|
279 | */
|
---|
280 | public int getIEEEFlags() {
|
---|
281 | return ieeeFlags;
|
---|
282 | }
|
---|
283 |
|
---|
284 | /** Clears the IEEE 854 status flags.
|
---|
285 | * @see #getIEEEFlags()
|
---|
286 | * @see #setIEEEFlags(int)
|
---|
287 | * @see #setIEEEFlagsBits(int)
|
---|
288 | * @see #FLAG_INVALID
|
---|
289 | * @see #FLAG_DIV_ZERO
|
---|
290 | * @see #FLAG_OVERFLOW
|
---|
291 | * @see #FLAG_UNDERFLOW
|
---|
292 | * @see #FLAG_INEXACT
|
---|
293 | */
|
---|
294 | public void clearIEEEFlags() {
|
---|
295 | ieeeFlags = 0;
|
---|
296 | }
|
---|
297 |
|
---|
298 | /** Sets the IEEE 854 status flags.
|
---|
299 | * @param flags desired value for the flags
|
---|
300 | * @see #getIEEEFlags()
|
---|
301 | * @see #clearIEEEFlags()
|
---|
302 | * @see #setIEEEFlagsBits(int)
|
---|
303 | * @see #FLAG_INVALID
|
---|
304 | * @see #FLAG_DIV_ZERO
|
---|
305 | * @see #FLAG_OVERFLOW
|
---|
306 | * @see #FLAG_UNDERFLOW
|
---|
307 | * @see #FLAG_INEXACT
|
---|
308 | */
|
---|
309 | public void setIEEEFlags(final int flags) {
|
---|
310 | ieeeFlags = flags & (FLAG_INVALID | FLAG_DIV_ZERO | FLAG_OVERFLOW | FLAG_UNDERFLOW | FLAG_INEXACT);
|
---|
311 | }
|
---|
312 |
|
---|
313 | /** Sets some bits in the IEEE 854 status flags, without changing the already set bits.
|
---|
314 | * <p>
|
---|
315 | * Calling this method is equivalent to call {@code setIEEEFlags(getIEEEFlags() | bits)}
|
---|
316 | * </p>
|
---|
317 | * @param bits bits to set
|
---|
318 | * @see #getIEEEFlags()
|
---|
319 | * @see #clearIEEEFlags()
|
---|
320 | * @see #setIEEEFlags(int)
|
---|
321 | * @see #FLAG_INVALID
|
---|
322 | * @see #FLAG_DIV_ZERO
|
---|
323 | * @see #FLAG_OVERFLOW
|
---|
324 | * @see #FLAG_UNDERFLOW
|
---|
325 | * @see #FLAG_INEXACT
|
---|
326 | */
|
---|
327 | public void setIEEEFlagsBits(final int bits) {
|
---|
328 | ieeeFlags |= bits & (FLAG_INVALID | FLAG_DIV_ZERO | FLAG_OVERFLOW | FLAG_UNDERFLOW | FLAG_INEXACT);
|
---|
329 | }
|
---|
330 |
|
---|
331 | /** Makes a {@link Dfp} with a value of 0.
|
---|
332 | * @return a new {@link Dfp} with a value of 0
|
---|
333 | */
|
---|
334 | public Dfp newDfp() {
|
---|
335 | return new Dfp(this);
|
---|
336 | }
|
---|
337 |
|
---|
338 | /** Create an instance from a byte value.
|
---|
339 | * @param x value to convert to an instance
|
---|
340 | * @return a new {@link Dfp} with the same value as x
|
---|
341 | */
|
---|
342 | public Dfp newDfp(final byte x) {
|
---|
343 | return new Dfp(this, x);
|
---|
344 | }
|
---|
345 |
|
---|
346 | /** Create an instance from an int value.
|
---|
347 | * @param x value to convert to an instance
|
---|
348 | * @return a new {@link Dfp} with the same value as x
|
---|
349 | */
|
---|
350 | public Dfp newDfp(final int x) {
|
---|
351 | return new Dfp(this, x);
|
---|
352 | }
|
---|
353 |
|
---|
354 | /** Create an instance from a long value.
|
---|
355 | * @param x value to convert to an instance
|
---|
356 | * @return a new {@link Dfp} with the same value as x
|
---|
357 | */
|
---|
358 | public Dfp newDfp(final long x) {
|
---|
359 | return new Dfp(this, x);
|
---|
360 | }
|
---|
361 |
|
---|
362 | /** Create an instance from a double value.
|
---|
363 | * @param x value to convert to an instance
|
---|
364 | * @return a new {@link Dfp} with the same value as x
|
---|
365 | */
|
---|
366 | public Dfp newDfp(final double x) {
|
---|
367 | return new Dfp(this, x);
|
---|
368 | }
|
---|
369 |
|
---|
370 | /** Copy constructor.
|
---|
371 | * @param d instance to copy
|
---|
372 | * @return a new {@link Dfp} with the same value as d
|
---|
373 | */
|
---|
374 | public Dfp newDfp(Dfp d) {
|
---|
375 | return new Dfp(d);
|
---|
376 | }
|
---|
377 |
|
---|
378 | /** Create a {@link Dfp} given a String representation.
|
---|
379 | * @param s string representation of the instance
|
---|
380 | * @return a new {@link Dfp} parsed from specified string
|
---|
381 | */
|
---|
382 | public Dfp newDfp(final String s) {
|
---|
383 | return new Dfp(this, s);
|
---|
384 | }
|
---|
385 |
|
---|
386 | /** Creates a {@link Dfp} with a non-finite value.
|
---|
387 | * @param sign sign of the Dfp to create
|
---|
388 | * @param nans code of the value, must be one of {@link Dfp#INFINITE},
|
---|
389 | * {@link Dfp#SNAN}, {@link Dfp#QNAN}
|
---|
390 | * @return a new {@link Dfp} with a non-finite value
|
---|
391 | */
|
---|
392 | public Dfp newDfp(final byte sign, final byte nans) {
|
---|
393 | return new Dfp(this, sign, nans);
|
---|
394 | }
|
---|
395 |
|
---|
396 | /** Get the constant 0.
|
---|
397 | * @return a {@link Dfp} with value 0
|
---|
398 | */
|
---|
399 | public Dfp getZero() {
|
---|
400 | return zero;
|
---|
401 | }
|
---|
402 |
|
---|
403 | /** Get the constant 1.
|
---|
404 | * @return a {@link Dfp} with value 1
|
---|
405 | */
|
---|
406 | public Dfp getOne() {
|
---|
407 | return one;
|
---|
408 | }
|
---|
409 |
|
---|
410 | /** Get the constant 2.
|
---|
411 | * @return a {@link Dfp} with value 2
|
---|
412 | */
|
---|
413 | public Dfp getTwo() {
|
---|
414 | return two;
|
---|
415 | }
|
---|
416 |
|
---|
417 | /** Get the constant √2.
|
---|
418 | * @return a {@link Dfp} with value √2
|
---|
419 | */
|
---|
420 | public Dfp getSqr2() {
|
---|
421 | return sqr2;
|
---|
422 | }
|
---|
423 |
|
---|
424 | /** Get the constant √2 split in two pieces.
|
---|
425 | * @return a {@link Dfp} with value √2 split in two pieces
|
---|
426 | */
|
---|
427 | public Dfp[] getSqr2Split() {
|
---|
428 | return sqr2Split.clone();
|
---|
429 | }
|
---|
430 |
|
---|
431 | /** Get the constant √2 / 2.
|
---|
432 | * @return a {@link Dfp} with value √2 / 2
|
---|
433 | */
|
---|
434 | public Dfp getSqr2Reciprocal() {
|
---|
435 | return sqr2Reciprocal;
|
---|
436 | }
|
---|
437 |
|
---|
438 | /** Get the constant √3.
|
---|
439 | * @return a {@link Dfp} with value √3
|
---|
440 | */
|
---|
441 | public Dfp getSqr3() {
|
---|
442 | return sqr3;
|
---|
443 | }
|
---|
444 |
|
---|
445 | /** Get the constant √3 / 3.
|
---|
446 | * @return a {@link Dfp} with value √3 / 3
|
---|
447 | */
|
---|
448 | public Dfp getSqr3Reciprocal() {
|
---|
449 | return sqr3Reciprocal;
|
---|
450 | }
|
---|
451 |
|
---|
452 | /** Get the constant π.
|
---|
453 | * @return a {@link Dfp} with value π
|
---|
454 | */
|
---|
455 | public Dfp getPi() {
|
---|
456 | return pi;
|
---|
457 | }
|
---|
458 |
|
---|
459 | /** Get the constant π split in two pieces.
|
---|
460 | * @return a {@link Dfp} with value π split in two pieces
|
---|
461 | */
|
---|
462 | public Dfp[] getPiSplit() {
|
---|
463 | return piSplit.clone();
|
---|
464 | }
|
---|
465 |
|
---|
466 | /** Get the constant e.
|
---|
467 | * @return a {@link Dfp} with value e
|
---|
468 | */
|
---|
469 | public Dfp getE() {
|
---|
470 | return e;
|
---|
471 | }
|
---|
472 |
|
---|
473 | /** Get the constant e split in two pieces.
|
---|
474 | * @return a {@link Dfp} with value e split in two pieces
|
---|
475 | */
|
---|
476 | public Dfp[] getESplit() {
|
---|
477 | return eSplit.clone();
|
---|
478 | }
|
---|
479 |
|
---|
480 | /** Get the constant ln(2).
|
---|
481 | * @return a {@link Dfp} with value ln(2)
|
---|
482 | */
|
---|
483 | public Dfp getLn2() {
|
---|
484 | return ln2;
|
---|
485 | }
|
---|
486 |
|
---|
487 | /** Get the constant ln(2) split in two pieces.
|
---|
488 | * @return a {@link Dfp} with value ln(2) split in two pieces
|
---|
489 | */
|
---|
490 | public Dfp[] getLn2Split() {
|
---|
491 | return ln2Split.clone();
|
---|
492 | }
|
---|
493 |
|
---|
494 | /** Get the constant ln(5).
|
---|
495 | * @return a {@link Dfp} with value ln(5)
|
---|
496 | */
|
---|
497 | public Dfp getLn5() {
|
---|
498 | return ln5;
|
---|
499 | }
|
---|
500 |
|
---|
501 | /** Get the constant ln(5) split in two pieces.
|
---|
502 | * @return a {@link Dfp} with value ln(5) split in two pieces
|
---|
503 | */
|
---|
504 | public Dfp[] getLn5Split() {
|
---|
505 | return ln5Split.clone();
|
---|
506 | }
|
---|
507 |
|
---|
508 | /** Get the constant ln(10).
|
---|
509 | * @return a {@link Dfp} with value ln(10)
|
---|
510 | */
|
---|
511 | public Dfp getLn10() {
|
---|
512 | return ln10;
|
---|
513 | }
|
---|
514 |
|
---|
515 | /** Breaks a string representation up into two {@link Dfp}'s.
|
---|
516 | * The split is such that the sum of them is equivalent to the input string,
|
---|
517 | * but has higher precision than using a single Dfp.
|
---|
518 | * @param a string representation of the number to split
|
---|
519 | * @return an array of two {@link Dfp Dfp} instances which sum equals a
|
---|
520 | */
|
---|
521 | private Dfp[] split(final String a) {
|
---|
522 | Dfp result[] = new Dfp[2];
|
---|
523 | boolean leading = true;
|
---|
524 | int sp = 0;
|
---|
525 | int sig = 0;
|
---|
526 |
|
---|
527 | char[] buf = new char[a.length()];
|
---|
528 |
|
---|
529 | for (int i = 0; i < buf.length; i++) {
|
---|
530 | buf[i] = a.charAt(i);
|
---|
531 |
|
---|
532 | if (buf[i] >= '1' && buf[i] <= '9') {
|
---|
533 | leading = false;
|
---|
534 | }
|
---|
535 |
|
---|
536 | if (buf[i] == '.') {
|
---|
537 | sig += (400 - sig) % 4;
|
---|
538 | leading = false;
|
---|
539 | }
|
---|
540 |
|
---|
541 | if (sig == (radixDigits / 2) * 4) {
|
---|
542 | sp = i;
|
---|
543 | break;
|
---|
544 | }
|
---|
545 |
|
---|
546 | if (buf[i] >= '0' && buf[i] <= '9' && !leading) {
|
---|
547 | sig ++;
|
---|
548 | }
|
---|
549 | }
|
---|
550 |
|
---|
551 | result[0] = new Dfp(this, new String(buf, 0, sp));
|
---|
552 |
|
---|
553 | for (int i = 0; i < buf.length; i++) {
|
---|
554 | buf[i] = a.charAt(i);
|
---|
555 | if (buf[i] >= '0' && buf[i] <= '9' && i < sp) {
|
---|
556 | buf[i] = '0';
|
---|
557 | }
|
---|
558 | }
|
---|
559 |
|
---|
560 | result[1] = new Dfp(this, new String(buf));
|
---|
561 |
|
---|
562 | return result;
|
---|
563 |
|
---|
564 | }
|
---|
565 |
|
---|
566 | /** Recompute the high precision string constants.
|
---|
567 | * @param highPrecisionDecimalDigits precision at which the string constants mus be computed
|
---|
568 | */
|
---|
569 | private static void computeStringConstants(final int highPrecisionDecimalDigits) {
|
---|
570 | if (sqr2String == null || sqr2String.length() < highPrecisionDecimalDigits - 3) {
|
---|
571 |
|
---|
572 | // recompute the string representation of the transcendental constants
|
---|
573 | final DfpField highPrecisionField = new DfpField(highPrecisionDecimalDigits, false);
|
---|
574 | final Dfp highPrecisionOne = new Dfp(highPrecisionField, 1);
|
---|
575 | final Dfp highPrecisionTwo = new Dfp(highPrecisionField, 2);
|
---|
576 | final Dfp highPrecisionThree = new Dfp(highPrecisionField, 3);
|
---|
577 |
|
---|
578 | final Dfp highPrecisionSqr2 = highPrecisionTwo.sqrt();
|
---|
579 | sqr2String = highPrecisionSqr2.toString();
|
---|
580 | sqr2ReciprocalString = highPrecisionOne.divide(highPrecisionSqr2).toString();
|
---|
581 |
|
---|
582 | final Dfp highPrecisionSqr3 = highPrecisionThree.sqrt();
|
---|
583 | sqr3String = highPrecisionSqr3.toString();
|
---|
584 | sqr3ReciprocalString = highPrecisionOne.divide(highPrecisionSqr3).toString();
|
---|
585 |
|
---|
586 | piString = computePi(highPrecisionOne, highPrecisionTwo, highPrecisionThree).toString();
|
---|
587 | eString = computeExp(highPrecisionOne, highPrecisionOne).toString();
|
---|
588 | ln2String = computeLn(highPrecisionTwo, highPrecisionOne, highPrecisionTwo).toString();
|
---|
589 | ln5String = computeLn(new Dfp(highPrecisionField, 5), highPrecisionOne, highPrecisionTwo).toString();
|
---|
590 | ln10String = computeLn(new Dfp(highPrecisionField, 10), highPrecisionOne, highPrecisionTwo).toString();
|
---|
591 |
|
---|
592 | }
|
---|
593 | }
|
---|
594 |
|
---|
595 | /** Compute π using Jonathan and Peter Borwein quartic formula.
|
---|
596 | * @param one constant with value 1 at desired precision
|
---|
597 | * @param two constant with value 2 at desired precision
|
---|
598 | * @param three constant with value 3 at desired precision
|
---|
599 | * @return π
|
---|
600 | */
|
---|
601 | private static Dfp computePi(final Dfp one, final Dfp two, final Dfp three) {
|
---|
602 |
|
---|
603 | Dfp sqrt2 = two.sqrt();
|
---|
604 | Dfp yk = sqrt2.subtract(one);
|
---|
605 | Dfp four = two.add(two);
|
---|
606 | Dfp two2kp3 = two;
|
---|
607 | Dfp ak = two.multiply(three.subtract(two.multiply(sqrt2)));
|
---|
608 |
|
---|
609 | // The formula converges quartically. This means the number of correct
|
---|
610 | // digits is multiplied by 4 at each iteration! Five iterations are
|
---|
611 | // sufficient for about 160 digits, eight iterations give about
|
---|
612 | // 10000 digits (this has been checked) and 20 iterations more than
|
---|
613 | // 160 billions of digits (this has NOT been checked).
|
---|
614 | // So the limit here is considered sufficient for most purposes ...
|
---|
615 | for (int i = 1; i < 20; i++) {
|
---|
616 | final Dfp ykM1 = yk;
|
---|
617 |
|
---|
618 | final Dfp y2 = yk.multiply(yk);
|
---|
619 | final Dfp oneMinusY4 = one.subtract(y2.multiply(y2));
|
---|
620 | final Dfp s = oneMinusY4.sqrt().sqrt();
|
---|
621 | yk = one.subtract(s).divide(one.add(s));
|
---|
622 |
|
---|
623 | two2kp3 = two2kp3.multiply(four);
|
---|
624 |
|
---|
625 | final Dfp p = one.add(yk);
|
---|
626 | final Dfp p2 = p.multiply(p);
|
---|
627 | ak = ak.multiply(p2.multiply(p2)).subtract(two2kp3.multiply(yk).multiply(one.add(yk).add(yk.multiply(yk))));
|
---|
628 |
|
---|
629 | if (yk.equals(ykM1)) {
|
---|
630 | break;
|
---|
631 | }
|
---|
632 | }
|
---|
633 |
|
---|
634 | return one.divide(ak);
|
---|
635 |
|
---|
636 | }
|
---|
637 |
|
---|
638 | /** Compute exp(a).
|
---|
639 | * @param a number for which we want the exponential
|
---|
640 | * @param one constant with value 1 at desired precision
|
---|
641 | * @return exp(a)
|
---|
642 | */
|
---|
643 | public static Dfp computeExp(final Dfp a, final Dfp one) {
|
---|
644 |
|
---|
645 | Dfp y = new Dfp(one);
|
---|
646 | Dfp py = new Dfp(one);
|
---|
647 | Dfp f = new Dfp(one);
|
---|
648 | Dfp fi = new Dfp(one);
|
---|
649 | Dfp x = new Dfp(one);
|
---|
650 |
|
---|
651 | for (int i = 0; i < 10000; i++) {
|
---|
652 | x = x.multiply(a);
|
---|
653 | y = y.add(x.divide(f));
|
---|
654 | fi = fi.add(one);
|
---|
655 | f = f.multiply(fi);
|
---|
656 | if (y.equals(py)) {
|
---|
657 | break;
|
---|
658 | }
|
---|
659 | py = new Dfp(y);
|
---|
660 | }
|
---|
661 |
|
---|
662 | return y;
|
---|
663 |
|
---|
664 | }
|
---|
665 |
|
---|
666 |
|
---|
667 | /** Compute ln(a).
|
---|
668 | *
|
---|
669 | * Let f(x) = ln(x),
|
---|
670 | *
|
---|
671 | * We know that f'(x) = 1/x, thus from Taylor's theorem we have:
|
---|
672 | *
|
---|
673 | * ----- n+1 n
|
---|
674 | * f(x) = \ (-1) (x - 1)
|
---|
675 | * / ---------------- for 1 <= n <= infinity
|
---|
676 | * ----- n
|
---|
677 | *
|
---|
678 | * or
|
---|
679 | * 2 3 4
|
---|
680 | * (x-1) (x-1) (x-1)
|
---|
681 | * ln(x) = (x-1) - ----- + ------ - ------ + ...
|
---|
682 | * 2 3 4
|
---|
683 | *
|
---|
684 | * alternatively,
|
---|
685 | *
|
---|
686 | * 2 3 4
|
---|
687 | * x x x
|
---|
688 | * ln(x+1) = x - - + - - - + ...
|
---|
689 | * 2 3 4
|
---|
690 | *
|
---|
691 | * This series can be used to compute ln(x), but it converges too slowly.
|
---|
692 | *
|
---|
693 | * If we substitute -x for x above, we get
|
---|
694 | *
|
---|
695 | * 2 3 4
|
---|
696 | * x x x
|
---|
697 | * ln(1-x) = -x - - - - - - + ...
|
---|
698 | * 2 3 4
|
---|
699 | *
|
---|
700 | * Note that all terms are now negative. Because the even powered ones
|
---|
701 | * absorbed the sign. Now, subtract the series above from the previous
|
---|
702 | * one to get ln(x+1) - ln(1-x). Note the even terms cancel out leaving
|
---|
703 | * only the odd ones
|
---|
704 | *
|
---|
705 | * 3 5 7
|
---|
706 | * 2x 2x 2x
|
---|
707 | * ln(x+1) - ln(x-1) = 2x + --- + --- + ---- + ...
|
---|
708 | * 3 5 7
|
---|
709 | *
|
---|
710 | * By the property of logarithms that ln(a) - ln(b) = ln (a/b) we have:
|
---|
711 | *
|
---|
712 | * 3 5 7
|
---|
713 | * x+1 / x x x \
|
---|
714 | * ln ----- = 2 * | x + ---- + ---- + ---- + ... |
|
---|
715 | * x-1 \ 3 5 7 /
|
---|
716 | *
|
---|
717 | * But now we want to find ln(a), so we need to find the value of x
|
---|
718 | * such that a = (x+1)/(x-1). This is easily solved to find that
|
---|
719 | * x = (a-1)/(a+1).
|
---|
720 | * @param a number for which we want the exponential
|
---|
721 | * @param one constant with value 1 at desired precision
|
---|
722 | * @param two constant with value 2 at desired precision
|
---|
723 | * @return ln(a)
|
---|
724 | */
|
---|
725 |
|
---|
726 | public static Dfp computeLn(final Dfp a, final Dfp one, final Dfp two) {
|
---|
727 |
|
---|
728 | int den = 1;
|
---|
729 | Dfp x = a.add(new Dfp(a.getField(), -1)).divide(a.add(one));
|
---|
730 |
|
---|
731 | Dfp y = new Dfp(x);
|
---|
732 | Dfp num = new Dfp(x);
|
---|
733 | Dfp py = new Dfp(y);
|
---|
734 | for (int i = 0; i < 10000; i++) {
|
---|
735 | num = num.multiply(x);
|
---|
736 | num = num.multiply(x);
|
---|
737 | den = den + 2;
|
---|
738 | Dfp t = num.divide(den);
|
---|
739 | y = y.add(t);
|
---|
740 | if (y.equals(py)) {
|
---|
741 | break;
|
---|
742 | }
|
---|
743 | py = new Dfp(y);
|
---|
744 | }
|
---|
745 |
|
---|
746 | return y.multiply(two);
|
---|
747 |
|
---|
748 | }
|
---|
749 |
|
---|
750 | }
|
---|