001: /*
002: * Copyright 2003-2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.commons.math.util;
018:
019: import java.math.BigDecimal;
020:
021: /**
022: * Some useful additions to the built-in functions in {@link Math}.
023: * @version $Revision: 321510 $ $Date: 2005-10-15 15:33:14 -0700 (Sat, 15 Oct 2005) $
024: */
025: public final class MathUtils {
026:
027: /** -1.0 cast as a byte. */
028: private static final byte NB = (byte) -1;
029:
030: /** -1.0 cast as a short. */
031: private static final short NS = (short) -1;
032:
033: /** 1.0 cast as a byte. */
034: private static final byte PB = (byte) 1;
035:
036: /** 1.0 cast as a short. */
037: private static final short PS = (short) 1;
038:
039: /** 0.0 cast as a byte. */
040: private static final byte ZB = (byte) 0;
041:
042: /** 0.0 cast as a short. */
043: private static final short ZS = (short) 0;
044:
045: /**
046: * Private Constructor
047: */
048: private MathUtils() {
049: super ();
050: }
051:
052: /**
053: * Add two integers, checking for overflow.
054: *
055: * @param x an addend
056: * @param y an addend
057: * @return the sum <code>x+y</code>
058: * @throws ArithmeticException if the result can not be represented as an
059: * int
060: * @since 1.1
061: */
062: public static int addAndCheck(int x, int y) {
063: long s = (long) x + (long) y;
064: if (s < Integer.MIN_VALUE || s > Integer.MAX_VALUE) {
065: throw new ArithmeticException("overflow: add");
066: }
067: return (int) s;
068: }
069:
070: /**
071: * Returns an exact representation of the <a
072: * href="http://mathworld.wolfram.com/BinomialCoefficient.html"> Binomial
073: * Coefficient</a>, "<code>n choose k</code>", the number of
074: * <code>k</code>-element subsets that can be selected from an
075: * <code>n</code>-element set.
076: * <p>
077: * <Strong>Preconditions</strong>:
078: * <ul>
079: * <li> <code>0 <= k <= n </code> (otherwise
080: * <code>IllegalArgumentException</code> is thrown)</li>
081: * <li> The result is small enough to fit into a <code>long</code>. The
082: * largest value of <code>n</code> for which all coefficients are
083: * <code> < Long.MAX_VALUE</code> is 66. If the computed value exceeds
084: * <code>Long.MAX_VALUE</code> an <code>ArithMeticException
085: * </code> is
086: * thrown.</li>
087: * </ul>
088: *
089: * @param n the size of the set
090: * @param k the size of the subsets to be counted
091: * @return <code>n choose k</code>
092: * @throws IllegalArgumentException if preconditions are not met.
093: * @throws ArithmeticException if the result is too large to be represented
094: * by a long integer.
095: */
096: public static long binomialCoefficient(final int n, final int k) {
097: if (n < k) {
098: throw new IllegalArgumentException(
099: "must have n >= k for binomial coefficient (n,k)");
100: }
101: if (n < 0) {
102: throw new IllegalArgumentException(
103: "must have n >= 0 for binomial coefficient (n,k)");
104: }
105: if ((n == k) || (k == 0)) {
106: return 1;
107: }
108: if ((k == 1) || (k == n - 1)) {
109: return n;
110: }
111:
112: long result = Math.round(binomialCoefficientDouble(n, k));
113: if (result == Long.MAX_VALUE) {
114: throw new ArithmeticException(
115: "result too large to represent in a long integer");
116: }
117: return result;
118: }
119:
120: /**
121: * Returns a <code>double</code> representation of the <a
122: * href="http://mathworld.wolfram.com/BinomialCoefficient.html"> Binomial
123: * Coefficient</a>, "<code>n choose k</code>", the number of
124: * <code>k</code>-element subsets that can be selected from an
125: * <code>n</code>-element set.
126: * <p>
127: * <Strong>Preconditions</strong>:
128: * <ul>
129: * <li> <code>0 <= k <= n </code> (otherwise
130: * <code>IllegalArgumentException</code> is thrown)</li>
131: * <li> The result is small enough to fit into a <code>double</code>. The
132: * largest value of <code>n</code> for which all coefficients are <
133: * Double.MAX_VALUE is 1029. If the computed value exceeds Double.MAX_VALUE,
134: * Double.POSITIVE_INFINITY is returned</li>
135: * </ul>
136: *
137: * @param n the size of the set
138: * @param k the size of the subsets to be counted
139: * @return <code>n choose k</code>
140: * @throws IllegalArgumentException if preconditions are not met.
141: */
142: public static double binomialCoefficientDouble(final int n,
143: final int k) {
144: return Math.floor(Math.exp(binomialCoefficientLog(n, k)) + 0.5);
145: }
146:
147: /**
148: * Returns the natural <code>log</code> of the <a
149: * href="http://mathworld.wolfram.com/BinomialCoefficient.html"> Binomial
150: * Coefficient</a>, "<code>n choose k</code>", the number of
151: * <code>k</code>-element subsets that can be selected from an
152: * <code>n</code>-element set.
153: * <p>
154: * <Strong>Preconditions</strong>:
155: * <ul>
156: * <li> <code>0 <= k <= n </code> (otherwise
157: * <code>IllegalArgumentException</code> is thrown)</li>
158: * </ul>
159: *
160: * @param n the size of the set
161: * @param k the size of the subsets to be counted
162: * @return <code>n choose k</code>
163: * @throws IllegalArgumentException if preconditions are not met.
164: */
165: public static double binomialCoefficientLog(final int n, final int k) {
166: if (n < k) {
167: throw new IllegalArgumentException(
168: "must have n >= k for binomial coefficient (n,k)");
169: }
170: if (n < 0) {
171: throw new IllegalArgumentException(
172: "must have n >= 0 for binomial coefficient (n,k)");
173: }
174: if ((n == k) || (k == 0)) {
175: return 0;
176: }
177: if ((k == 1) || (k == n - 1)) {
178: return Math.log((double) n);
179: }
180: double logSum = 0;
181:
182: // n!/k!
183: for (int i = k + 1; i <= n; i++) {
184: logSum += Math.log((double) i);
185: }
186:
187: // divide by (n-k)!
188: for (int i = 2; i <= n - k; i++) {
189: logSum -= Math.log((double) i);
190: }
191:
192: return logSum;
193: }
194:
195: /**
196: * Returns the <a href="http://mathworld.wolfram.com/HyperbolicCosine.html">
197: * hyperbolic cosine</a> of x.
198: *
199: * @param x double value for which to find the hyperbolic cosine
200: * @return hyperbolic cosine of x
201: */
202: public static double cosh(double x) {
203: return (Math.exp(x) + Math.exp(-x)) / 2.0;
204: }
205:
206: /**
207: * Returns true iff both arguments are NaN or neither is NaN and they are
208: * equal
209: *
210: * @param x first value
211: * @param y second value
212: * @return true if the values are equal or both are NaN
213: */
214: public static boolean equals(double x, double y) {
215: return ((Double.isNaN(x) && Double.isNaN(y)) || x == y);
216: }
217:
218: /**
219: * Returns n!. Shorthand for <code>n</code> <a
220: * href="http://mathworld.wolfram.com/Factorial.html"> Factorial</a>, the
221: * product of the numbers <code>1,...,n</code>.
222: * <p>
223: * <Strong>Preconditions</strong>:
224: * <ul>
225: * <li> <code>n >= 0</code> (otherwise
226: * <code>IllegalArgumentException</code> is thrown)</li>
227: * <li> The result is small enough to fit into a <code>long</code>. The
228: * largest value of <code>n</code> for which <code>n!</code> <
229: * Long.MAX_VALUE</code> is 20. If the computed value exceeds <code>Long.MAX_VALUE</code>
230: * an <code>ArithMeticException </code> is thrown.</li>
231: * </ul>
232: * </p>
233: *
234: * @param n argument
235: * @return <code>n!</code>
236: * @throws ArithmeticException if the result is too large to be represented
237: * by a long integer.
238: * @throws IllegalArgumentException if n < 0
239: */
240: public static long factorial(final int n) {
241: long result = Math.round(factorialDouble(n));
242: if (result == Long.MAX_VALUE) {
243: throw new ArithmeticException(
244: "result too large to represent in a long integer");
245: }
246: return result;
247: }
248:
249: /**
250: * Returns n!. Shorthand for <code>n</code> <a
251: * href="http://mathworld.wolfram.com/Factorial.html"> Factorial</a>, the
252: * product of the numbers <code>1,...,n</code> as a <code>double</code>.
253: * <p>
254: * <Strong>Preconditions</strong>:
255: * <ul>
256: * <li> <code>n >= 0</code> (otherwise
257: * <code>IllegalArgumentException</code> is thrown)</li>
258: * <li> The result is small enough to fit into a <code>double</code>. The
259: * largest value of <code>n</code> for which <code>n!</code> <
260: * Double.MAX_VALUE</code> is 170. If the computed value exceeds
261: * Double.MAX_VALUE, Double.POSITIVE_INFINITY is returned</li>
262: * </ul>
263: * </p>
264: *
265: * @param n argument
266: * @return <code>n!</code>
267: * @throws IllegalArgumentException if n < 0
268: */
269: public static double factorialDouble(final int n) {
270: if (n < 0) {
271: throw new IllegalArgumentException(
272: "must have n >= 0 for n!");
273: }
274: return Math.floor(Math.exp(factorialLog(n)) + 0.5);
275: }
276:
277: /**
278: * Returns the natural logarithm of n!.
279: * <p>
280: * <Strong>Preconditions</strong>:
281: * <ul>
282: * <li> <code>n >= 0</code> (otherwise
283: * <code>IllegalArgumentException</code> is thrown)</li>
284: * </ul>
285: *
286: * @param n argument
287: * @return <code>n!</code>
288: * @throws IllegalArgumentException if preconditions are not met.
289: */
290: public static double factorialLog(final int n) {
291: if (n < 0) {
292: throw new IllegalArgumentException("must have n > 0 for n!");
293: }
294: double logSum = 0;
295: for (int i = 2; i <= n; i++) {
296: logSum += Math.log((double) i);
297: }
298: return logSum;
299: }
300:
301: /**
302: * <p>
303: * Gets the greatest common divisor of the absolute value of two numbers,
304: * using the "binary gcd" method which avoids division and modulo
305: * operations. See Knuth 4.5.2 algorithm B. This algorithm is due to Josef
306: * Stein (1961).
307: * </p>
308: *
309: * @param u a non-zero number
310: * @param v a non-zero number
311: * @return the greatest common divisor, never zero
312: * @since 1.1
313: */
314: public static int gcd(int u, int v) {
315: if (u * v == 0) {
316: return (Math.abs(u) + Math.abs(v));
317: }
318: // keep u and v negative, as negative integers range down to
319: // -2^31, while positive numbers can only be as large as 2^31-1
320: // (i.e. we can't necessarily negate a negative number without
321: // overflow)
322: /* assert u!=0 && v!=0; */
323: if (u > 0) {
324: u = -u;
325: } // make u negative
326: if (v > 0) {
327: v = -v;
328: } // make v negative
329: // B1. [Find power of 2]
330: int k = 0;
331: while ((u & 1) == 0 && (v & 1) == 0 && k < 31) { // while u and v are
332: // both even...
333: u /= 2;
334: v /= 2;
335: k++; // cast out twos.
336: }
337: if (k == 31) {
338: throw new ArithmeticException("overflow: gcd is 2^31");
339: }
340: // B2. Initialize: u and v have been divided by 2^k and at least
341: // one is odd.
342: int t = ((u & 1) == 1) ? v : -(u / 2)/* B3 */;
343: // t negative: u was odd, v may be even (t replaces v)
344: // t positive: u was even, v is odd (t replaces u)
345: do {
346: /* assert u<0 && v<0; */
347: // B4/B3: cast out twos from t.
348: while ((t & 1) == 0) { // while t is even..
349: t /= 2; // cast out twos
350: }
351: // B5 [reset max(u,v)]
352: if (t > 0) {
353: u = -t;
354: } else {
355: v = t;
356: }
357: // B6/B3. at this point both u and v should be odd.
358: t = (v - u) / 2;
359: // |u| larger: t positive (replace u)
360: // |v| larger: t negative (replace v)
361: } while (t != 0);
362: return -u * (1 << k); // gcd is u*2^k
363: }
364:
365: /**
366: * Returns an integer hash code representing the given double value.
367: *
368: * @param value the value to be hashed
369: * @return the hash code
370: */
371: public static int hash(double value) {
372: long bits = Double.doubleToLongBits(value);
373: return (int) (bits ^ (bits >>> 32));
374: }
375:
376: /**
377: * For a byte value x, this method returns (byte)(+1) if x >= 0 and
378: * (byte)(-1) if x < 0.
379: *
380: * @param x the value, a byte
381: * @return (byte)(+1) or (byte)(-1), depending on the sign of x
382: */
383: public static byte indicator(final byte x) {
384: return (x >= ZB) ? PB : NB;
385: }
386:
387: /**
388: * For a double precision value x, this method returns +1.0 if x >= 0 and
389: * -1.0 if x < 0. Returns <code>NaN</code> if <code>x</code> is
390: * <code>NaN</code>.
391: *
392: * @param x the value, a double
393: * @return +1.0 or -1.0, depending on the sign of x
394: */
395: public static double indicator(final double x) {
396: if (Double.isNaN(x)) {
397: return Double.NaN;
398: }
399: return (x >= 0.0) ? 1.0 : -1.0;
400: }
401:
402: /**
403: * For a float value x, this method returns +1.0F if x >= 0 and -1.0F if x <
404: * 0. Returns <code>NaN</code> if <code>x</code> is <code>NaN</code>.
405: *
406: * @param x the value, a float
407: * @return +1.0F or -1.0F, depending on the sign of x
408: */
409: public static float indicator(final float x) {
410: if (Float.isNaN(x)) {
411: return Float.NaN;
412: }
413: return (x >= 0.0F) ? 1.0F : -1.0F;
414: }
415:
416: /**
417: * For an int value x, this method returns +1 if x >= 0 and -1 if x < 0.
418: *
419: * @param x the value, an int
420: * @return +1 or -1, depending on the sign of x
421: */
422: public static int indicator(final int x) {
423: return (x >= 0) ? 1 : -1;
424: }
425:
426: /**
427: * For a long value x, this method returns +1L if x >= 0 and -1L if x < 0.
428: *
429: * @param x the value, a long
430: * @return +1L or -1L, depending on the sign of x
431: */
432: public static long indicator(final long x) {
433: return (x >= 0L) ? 1L : -1L;
434: }
435:
436: /**
437: * For a short value x, this method returns (short)(+1) if x >= 0 and
438: * (short)(-1) if x < 0.
439: *
440: * @param x the value, a short
441: * @return (short)(+1) or (short)(-1), depending on the sign of x
442: */
443: public static short indicator(final short x) {
444: return (x >= ZS) ? PS : NS;
445: }
446:
447: /**
448: * Returns the least common multiple between two integer values.
449: *
450: * @param a the first integer value.
451: * @param b the second integer value.
452: * @return the least common multiple between a and b.
453: * @throws ArithmeticException if the lcm is too large to store as an int
454: * @since 1.1
455: */
456: public static int lcm(int a, int b) {
457: return Math.abs(mulAndCheck(a / gcd(a, b), b));
458: }
459:
460: /**
461: * Multiply two integers, checking for overflow.
462: *
463: * @param x a factor
464: * @param y a factor
465: * @return the product <code>x*y</code>
466: * @throws ArithmeticException if the result can not be represented as an
467: * int
468: * @since 1.1
469: */
470: public static int mulAndCheck(int x, int y) {
471: long m = ((long) x) * ((long) y);
472: if (m < Integer.MIN_VALUE || m > Integer.MAX_VALUE) {
473: throw new ArithmeticException("overflow: mul");
474: }
475: return (int) m;
476: }
477:
478: /**
479: * Round the given value to the specified number of decimal places. The
480: * value is rounded using the {@link BigDecimal#ROUND_HALF_UP} method.
481: *
482: * @param x the value to round.
483: * @param scale the number of digits to the right of the decimal point.
484: * @return the rounded value.
485: * @since 1.1
486: */
487: public static double round(double x, int scale) {
488: return round(x, scale, BigDecimal.ROUND_HALF_UP);
489: }
490:
491: /**
492: * Round the given value to the specified number of decimal places. The
493: * value is rounded using the given method which is any method defined in
494: * {@link BigDecimal}.
495: *
496: * @param x the value to round.
497: * @param scale the number of digits to the right of the decimal point.
498: * @param roundingMethod the rounding method as defined in
499: * {@link BigDecimal}.
500: * @return the rounded value.
501: * @since 1.1
502: */
503: public static double round(double x, int scale, int roundingMethod) {
504: double sign = indicator(x);
505: double factor = Math.pow(10.0, scale) * sign;
506: return roundUnscaled(x * factor, sign, roundingMethod) / factor;
507: }
508:
509: /**
510: * Round the given value to the specified number of decimal places. The
511: * value is rounding using the {@link BigDecimal#ROUND_HALF_UP} method.
512: *
513: * @param x the value to round.
514: * @param scale the number of digits to the right of the decimal point.
515: * @return the rounded value.
516: * @since 1.1
517: */
518: public static float round(float x, int scale) {
519: return round(x, scale, BigDecimal.ROUND_HALF_UP);
520: }
521:
522: /**
523: * Round the given value to the specified number of decimal places. The
524: * value is rounded using the given method which is any method defined in
525: * {@link BigDecimal}.
526: *
527: * @param x the value to round.
528: * @param scale the number of digits to the right of the decimal point.
529: * @param roundingMethod the rounding method as defined in
530: * {@link BigDecimal}.
531: * @return the rounded value.
532: * @since 1.1
533: */
534: public static float round(float x, int scale, int roundingMethod) {
535: float sign = indicator(x);
536: float factor = (float) Math.pow(10.0f, scale) * sign;
537: return (float) roundUnscaled(x * factor, sign, roundingMethod)
538: / factor;
539: }
540:
541: /**
542: * Round the given non-negative, value to the "nearest" integer. Nearest is
543: * determined by the rounding method specified. Rounding methods are defined
544: * in {@link BigDecimal}.
545: *
546: * @param unscaled the value to round.
547: * @param sign the sign of the original, scaled value.
548: * @param roundingMethod the rounding method as defined in
549: * {@link BigDecimal}.
550: * @return the rounded value.
551: * @since 1.1
552: */
553: private static double roundUnscaled(double unscaled, double sign,
554: int roundingMethod) {
555: switch (roundingMethod) {
556: case BigDecimal.ROUND_CEILING:
557: if (sign == -1) {
558: unscaled = Math.floor(unscaled);
559: } else {
560: unscaled = Math.ceil(unscaled);
561: }
562: break;
563: case BigDecimal.ROUND_DOWN:
564: unscaled = Math.floor(unscaled);
565: break;
566: case BigDecimal.ROUND_FLOOR:
567: if (sign == -1) {
568: unscaled = Math.ceil(unscaled);
569: } else {
570: unscaled = Math.floor(unscaled);
571: }
572: break;
573: case BigDecimal.ROUND_HALF_DOWN: {
574: double fraction = Math.abs(unscaled - Math.floor(unscaled));
575: if (fraction > 0.5) {
576: unscaled = Math.ceil(unscaled);
577: } else {
578: unscaled = Math.floor(unscaled);
579: }
580: break;
581: }
582: case BigDecimal.ROUND_HALF_EVEN: {
583: double fraction = Math.abs(unscaled - Math.floor(unscaled));
584: if (fraction > 0.5) {
585: unscaled = Math.ceil(unscaled);
586: } else if (fraction < 0.5) {
587: unscaled = Math.floor(unscaled);
588: } else {
589: if (Math.floor(unscaled) / 2.0 == Math.floor(Math
590: .floor(unscaled) / 2.0)) { // even
591: unscaled = Math.floor(unscaled);
592: } else { // odd
593: unscaled = Math.ceil(unscaled);
594: }
595: }
596: break;
597: }
598: case BigDecimal.ROUND_HALF_UP: {
599: double fraction = Math.abs(unscaled - Math.floor(unscaled));
600: if (fraction >= 0.5) {
601: unscaled = Math.ceil(unscaled);
602: } else {
603: unscaled = Math.floor(unscaled);
604: }
605: break;
606: }
607: case BigDecimal.ROUND_UNNECESSARY:
608: if (unscaled != Math.floor(unscaled)) {
609: throw new ArithmeticException(
610: "Inexact result from rounding");
611: }
612: break;
613: case BigDecimal.ROUND_UP:
614: unscaled = Math.ceil(unscaled);
615: break;
616: default:
617: throw new IllegalArgumentException(
618: "Invalid rounding method.");
619: }
620: return unscaled;
621: }
622:
623: /**
624: * Returns the <a href="http://mathworld.wolfram.com/Sign.html"> sign</a>
625: * for byte value <code>x</code>.
626: * <p>
627: * For a byte value x, this method returns (byte)(+1) if x > 0, (byte)(0) if
628: * x = 0, and (byte)(-1) if x < 0.
629: *
630: * @param x the value, a byte
631: * @return (byte)(+1), (byte)(0), or (byte)(-1), depending on the sign of x
632: */
633: public static byte sign(final byte x) {
634: return (x == ZB) ? ZB : (x > ZB) ? PB : NB;
635: }
636:
637: /**
638: * Returns the <a href="http://mathworld.wolfram.com/Sign.html"> sign</a>
639: * for double precision <code>x</code>.
640: * <p>
641: * For a double value <code>x</code>, this method returns
642: * <code>+1.0</code> if <code>x > 0</code>, <code>0.0</code> if
643: * <code>x = 0.0</code>, and <code>-1.0</code> if <code>x < 0</code>.
644: * Returns <code>NaN</code> if <code>x</code> is <code>NaN</code>.
645: *
646: * @param x the value, a double
647: * @return +1.0, 0.0, or -1.0, depending on the sign of x
648: */
649: public static double sign(final double x) {
650: if (Double.isNaN(x)) {
651: return Double.NaN;
652: }
653: return (x == 0.0) ? 0.0 : (x > 0.0) ? 1.0 : -1.0;
654: }
655:
656: /**
657: * Returns the <a href="http://mathworld.wolfram.com/Sign.html"> sign</a>
658: * for float value <code>x</code>.
659: * <p>
660: * For a float value x, this method returns +1.0F if x > 0, 0.0F if x =
661: * 0.0F, and -1.0F if x < 0. Returns <code>NaN</code> if <code>x</code>
662: * is <code>NaN</code>.
663: *
664: * @param x the value, a float
665: * @return +1.0F, 0.0F, or -1.0F, depending on the sign of x
666: */
667: public static float sign(final float x) {
668: if (Float.isNaN(x)) {
669: return Float.NaN;
670: }
671: return (x == 0.0F) ? 0.0F : (x > 0.0F) ? 1.0F : -1.0F;
672: }
673:
674: /**
675: * Returns the <a href="http://mathworld.wolfram.com/Sign.html"> sign</a>
676: * for int value <code>x</code>.
677: * <p>
678: * For an int value x, this method returns +1 if x > 0, 0 if x = 0, and -1
679: * if x < 0.
680: *
681: * @param x the value, an int
682: * @return +1, 0, or -1, depending on the sign of x
683: */
684: public static int sign(final int x) {
685: return (x == 0) ? 0 : (x > 0) ? 1 : -1;
686: }
687:
688: /**
689: * Returns the <a href="http://mathworld.wolfram.com/Sign.html"> sign</a>
690: * for long value <code>x</code>.
691: * <p>
692: * For a long value x, this method returns +1L if x > 0, 0L if x = 0, and
693: * -1L if x < 0.
694: *
695: * @param x the value, a long
696: * @return +1L, 0L, or -1L, depending on the sign of x
697: */
698: public static long sign(final long x) {
699: return (x == 0L) ? 0L : (x > 0L) ? 1L : -1L;
700: }
701:
702: /**
703: * Returns the <a href="http://mathworld.wolfram.com/Sign.html"> sign</a>
704: * for short value <code>x</code>.
705: * <p>
706: * For a short value x, this method returns (short)(+1) if x > 0, (short)(0)
707: * if x = 0, and (short)(-1) if x < 0.
708: *
709: * @param x the value, a short
710: * @return (short)(+1), (short)(0), or (short)(-1), depending on the sign of
711: * x
712: */
713: public static short sign(final short x) {
714: return (x == ZS) ? ZS : (x > ZS) ? PS : NS;
715: }
716:
717: /**
718: * Returns the <a href="http://mathworld.wolfram.com/HyperbolicSine.html">
719: * hyperbolic sine</a> of x.
720: *
721: * @param x double value for which to find the hyperbolic sine
722: * @return hyperbolic sine of x
723: */
724: public static double sinh(double x) {
725: return (Math.exp(x) - Math.exp(-x)) / 2.0;
726: }
727:
728: /**
729: * Subtract two integers, checking for overflow.
730: *
731: * @param x the minuend
732: * @param y the subtrahend
733: * @return the difference <code>x-y</code>
734: * @throws ArithmeticException if the result can not be represented as an
735: * int
736: * @since 1.1
737: */
738: public static int subAndCheck(int x, int y) {
739: long s = (long) x - (long) y;
740: if (s < Integer.MIN_VALUE || s > Integer.MAX_VALUE) {
741: throw new ArithmeticException("overflow: subtract");
742: }
743: return (int) s;
744: }
745: }
|