Statistics
| Revision:

root / trunk / libraries / libTopology / src / org / geotools / referencefork / math / XMath.java @ 22875

History | View | Annotate | Download (16.7 KB)

1
/*
2
 *    GeoTools - The Open Source Java GIS Toolkit
3
 *    http://geotools.org
4
 *
5
 *    (C) 2001-2008, Open Source Geospatial Foundation (OSGeo)
6
 *
7
 *    This library is free software; you can redistribute it and/or
8
 *    modify it under the terms of the GNU Lesser General Public
9
 *    License as published by the Free Software Foundation;
10
 *    version 2.1 of the License.
11
 *
12
 *    This library is distributed in the hope that it will be useful,
13
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 *    Lesser General Public License for more details.
16
 */
17
package org.geotools.referencefork.math;
18

    
19
//import org.geotools.resources.XArray;
20
//import static org.geotools.resources.XMath.next;
21
//import static org.geotools.resources.XMath.previous;
22

    
23

    
24
/**
25
 * Simple mathematical functions in addition to the ones provided in {@link Math}.
26
 *
27
 * @since 2.5
28
 * @source $URL$
29
 * @version $Id$
30
 * @author Martin Desruisseaux (IRD)
31
 */
32
public final class XMath {
33
    /**
34
     * Table of some integer powers of 10. Used for fast computation of {@link #pow10(int)}.
35
     */
36
    private static final double[] POW10 = {
37
        1E+00, 1E+01, 1E+02, 1E+03, 1E+04, 1E+05, 1E+06, 1E+07, 1E+08, 1E+09,
38
        1E+10, 1E+11, 1E+12, 1E+13, 1E+14, 1E+15, 1E+16, 1E+17, 1E+18, 1E+19,
39
        1E+20, 1E+21, 1E+22
40
        // Do not add more elements, unless we verified that 1/x is accurate.
41
        // Last time we tried, it was not accurate anymore starting at 1E+23.
42
    };
43

    
44
    /**
45
     * The sequence of prime numbers computed so far. Will be expanded as needed.
46
     * We limit ourself to 16 bits numbers because they are suffisient for computing
47
     * divisors of any 32 bits number.
48
     */
49
    private static short[] primes = new short[] {2, 3};
50

    
51
    /**
52
     * Maximum length allowed for the {@link #primes} array. This is the index
53
     * of the first prime number that can not be stored as 16 bits unsigned.
54
     */
55
    private static final int MAX_PRIMES_LENGTH = 6542;
56

    
57
    /**
58
     * Do not allow instantiation of this class.
59
     */
60
    private XMath() {
61
    }
62

    
63
    /**
64
     * Computes 10 raised to the power of <var>x</var>. This method delegates to
65
     * {@link #pow10(int)} if <var>x</var> is an integer, or to {@link Math#pow}
66
     * otherwise.
67
     *
68
     * @param x The exponent.
69
     * @return 10 raised to the given exponent.
70
     */
71
    public static double pow10(final double x) {
72
        final int ix = (int) x;
73
        if (ix == x) {
74
            return pow10(ix);
75
        } else {
76
            return Math.pow(10, x);
77
        }
78
    }
79

    
80
    /**
81
     * Computes 10 raised to the power of <var>x</var>. This method tries to be slightly more
82
     * accurate than <code>{@linkplain Math#pow Math.pow}(10,x)</code>, sometime at the cost
83
     * of performance.
84
     * <p>
85
     * The {@code Math.pow(10,x)} method doesn't always return the closest IEEE floating point
86
     * representation. More accurate calculations are slower and usually not necessary, but the
87
     * base 10 is a special case since it is used for scaling axes or formatting human-readable
88
     * output, in which case the precision may matter.
89
     *
90
     * @param x The exponent.
91
     * @return 10 raised to the given exponent.
92
     */
93
    public static strictfp double pow10(final int x) {
94
        if (x >= 0) {
95
            if (x < POW10.length) {
96
                return POW10[x];
97
            }
98
        } else if (x != Integer.MIN_VALUE) {
99
            final int nx = -x;
100
            if (nx < POW10.length) {
101
                return 1 / POW10[nx];
102
            }
103
        }
104
        try {
105
            /*
106
             * Double.parseDouble("1E"+x) give gives as good or better numbers than Math.pow(10,x)
107
             * for ALL integer powers, but is slower. We hope that the current workaround is only
108
             * temporary. See http://developer.java.sun.com/developer/bugParade/bugs/4358794.html
109
             */
110
            return Double.parseDouble("1E" + x);
111
        } catch (NumberFormatException exception) {
112
            return StrictMath.pow(10, x);
113
        }
114
    }
115

    
116
    /**
117
     * Returns the sign of <var>x</var>. This method returns
118
     *    -1 if <var>x</var> is negative,
119
     *     0 if <var>x</var> is zero or {@code NaN} and
120
     *    +1 if <var>x</var> is positive.
121
     *
122
     * @param x The number from which to get the sign.
123
     * @return {@code +1} if <var>x</var> is positive, {@code -1} if negative, or 0 otherwise.
124
     *
125
     * @see Math#signum(double)
126
     */
127
    public static int sgn(final double x) {
128
        if (x > 0) return +1;
129
        if (x < 0) return -1;
130
        else       return  0;
131
    }
132

    
133
    /**
134
     * Returns the sign of <var>x</var>. This method returns
135
     *    -1 if <var>x</var> is negative,
136
     *     0 if <var>x</var> is zero or {@code NaN} and
137
     *    +1 if <var>x</var> is positive.
138
     *
139
     * @param x The number from which to get the sign.
140
     * @return {@code +1} if <var>x</var> is positive, {@code -1} if negative, or 0 otherwise.
141
     *
142
     * @see Math#signum(float)
143
     */
144
    public static int sgn(final float x) {
145
        if (x > 0) return +1;
146
        if (x < 0) return -1;
147
        else       return  0;
148
    }
149

    
150
    /**
151
     * Returns the sign of <var>x</var>. This method returns
152
     *    -1 if <var>x</var> is negative,
153
     *     0 if <var>x</var> is zero and
154
     *    +1 if <var>x</var> is positive.
155
     *
156
     * @param x The number from which to get the sign.
157
     * @return {@code +1} if <var>x</var> is positive, {@code -1} if negative, or 0 otherwise.
158
     */
159
    public static int sgn(long x) {
160
        if (x > 0) return +1;
161
        if (x < 0) return -1;
162
        else       return  0;
163
    }
164

    
165
    /**
166
     * Returns the sign of <var>x</var>. This method returns
167
     *    -1 if <var>x</var> is negative,
168
     *     0 if <var>x</var> is zero and
169
     *    +1 if <var>x</var> is positive.
170
     *
171
     * @param x The number from which to get the sign.
172
     * @return {@code +1} if <var>x</var> is positive, {@code -1} if negative, or 0 otherwise.
173
     */
174
    public static int sgn(int x) {
175
        if (x > 0) return +1;
176
        if (x < 0) return -1;
177
        else       return  0;
178
    }
179

    
180
    /**
181
     * Returns the sign of <var>x</var>. This method returns
182
     *    -1 if <var>x</var> is negative,
183
     *     0 if <var>x</var> is zero and
184
     *    +1 if <var>x</var> is positive.
185
     *
186
     * @param x The number from which to get the sign.
187
     * @return {@code +1} if <var>x</var> is positive, {@code -1} if negative, or 0 otherwise.
188
     */
189
    public static short sgn(short x) {
190
        if (x > 0) return (short) +1;
191
        if (x < 0) return (short) -1;
192
        else       return (short)  0;
193
    }
194

    
195
    /**
196
     * Returns the sign of <var>x</var>. This method returns
197
     *    -1 if <var>x</var> is negative,
198
     *     0 if <var>x</var> is zero and
199
     *    +1 if <var>x</var> is positive.
200
     *
201
     * @param x The number from which to get the sign.
202
     * @return {@code +1} if <var>x</var> is positive, {@code -1} if negative, or 0 otherwise.
203
     */
204
    public static byte sgn(byte x) {
205
        if (x > 0) return (byte) +1;
206
        if (x < 0) return (byte) -1;
207
        else       return (byte)  0;
208
    }
209

    
210
    /**
211
     * Rounds the specified value, providing that the difference between the original value and
212
     * the rounded value is not greater than the specified amount of floating point units. This
213
     * method can be used for hiding floating point error likes 2.9999999996.
214
     *
215
     * @param  value The value to round.
216
     * @param  maxULP The maximal change allowed in ULPs (Unit in the Last Place).
217
     * @return The rounded value, of {@code value} if it was not close enough to an integer.
218
     */
219
//    public static double roundIfAlmostInteger(final double value, int maxULP) {
220
//        final double target = Math.rint(value);
221
//        if (value != target) {
222
//            final boolean pos = (value < target);
223
//            double candidate = value;
224
//            while (--maxULP >= 0) {
225
//                candidate = pos ? next(candidate) : previous(candidate);
226
//                if (candidate == target) {
227
//                    return target;
228
//                }
229
//            }
230
//        }
231
//        return value;
232
//    }
233

    
234
    /**
235
     * Tries to remove at least {@code n} fraction digits in the decimal representation of
236
     * the specified value. This method tries small changes to {@code value}, by adding or
237
     * substracting up to {@code maxULP} (Unit in the Last Place). If there is no small
238
     * change that remove at least {@code n} fraction digits, then the value is returned
239
     * unchanged. This method is used for hiding rounding errors, like in conversions from
240
     * radians to degrees.
241
     * <P>
242
     * Example:
243
     * {@code XMath.trimLastDecimalDigits(-61.500000000000014, 12, 4)} returns {@code -61.5}.
244
     *
245
     * @param  value The value to fix.
246
     * @param  maxULP The maximal change allowed in ULPs (Unit in the Last Place).
247
     *         A typical value is 4.
248
     * @param  n The minimum amount of fraction digits.
249
     * @return The trimmed value, or the unchanged {@code value} if there is no small change
250
     *         that remove at least {@code n} fraction digits.
251
     */
252
//    public static double trimDecimalFractionDigits(final double value, final int maxULP, int n) {
253
//        double lower = value;
254
//        double upper = value;
255
//        n = countDecimalFractionDigits(value) - n;
256
//        if (n > 0) {
257
//            for (int i=0; i<maxULP; i++) {
258
//                if (countDecimalFractionDigits(lower = previous(lower)) <= n) return lower;
259
//                if (countDecimalFractionDigits(upper = next    (upper)) <= n) return upper;
260
//            }
261
//        }
262
//        return value;
263
//    }
264

    
265
    /**
266
     * Counts the fraction digits in the string representation of the specified value. This method
267
     * is equivalent to a calling <code>{@linkplain Double#toString(double) Double.toString}(value)</code>
268
     * and counting the number of digits after the decimal separator.
269
     *
270
     * @param value The value for which to count the fraction digits.
271
     * @return The number of fraction digits.
272
     */
273
    public static int countDecimalFractionDigits(final double value) {
274
        final String asText = Double.toString(value);
275
        final int exp = asText.indexOf('E');
276
        int upper, power;
277
        if (exp >= 0) {
278
            upper = exp;
279
            power = Integer.parseInt(asText.substring(exp+1));
280
        } else {
281
            upper = asText.length();
282
            power = 0;
283
        }
284
        while ((asText.charAt(--upper)) == '0');
285
        return Math.max(upper - asText.indexOf('.') - power, 0);
286
    }
287

    
288
    /**
289
     * Returns a {@link Float#NaN NaN} number for the specified index. Valid NaN numbers have
290
     * bit fields ranging from {@code 0x7f800001} through {@code 0x7fffffff} or {@code 0xff800001}
291
     * through {@code 0xffffffff}. The standard {@link Float#NaN} has bit fields {@code 0x7fc00000}.
292
     * See {@link Float#intBitsToFloat} for more details on NaN bit values.
293
     *
294
     * @param  index The index, from -2097152 to 2097151 inclusive.
295
     * @return One of the legal {@link Float#NaN NaN} values as a float.
296
     * @throws IndexOutOfBoundsException if the specified index is out of bounds.
297
     *
298
     * @see Float#intBitsToFloat
299
     */
300
    public static float toNaN(int index) throws IndexOutOfBoundsException {
301
        index += 0x200000;
302
        if (index>=0 && index<=0x3FFFFF) {
303
            final float value = Float.intBitsToFloat(0x7FC00000 + index);
304
            assert Float.isNaN(value) : value;
305
            return value;
306
        }
307
        else {
308
            throw new IndexOutOfBoundsException(Integer.toHexString(index));
309
        }
310
    }
311

    
312
    /**
313
     * Returns the <var>i</var><sup>th</sup> prime number. This method returns (2,3,5,7,11...)
314
     * for index (0,1,2,3,4...). This method is designed for relatively small prime numbers only;
315
     * don't use it for large values.
316
     *
317
     * @param  index The prime number index, starting at index 0 for prime number 2.
318
     * @return The prime number at the specified index.
319
     * @throws IndexOutOfBoundsException if the specified index is too large.
320
     *
321
     * @see java.math.BigInteger#isProbablePrime
322
     */
323
//    public static synchronized int primeNumber(final int index) throws IndexOutOfBoundsException {
324
//        // 6541 is the largest index returning a 16 bits unsigned prime number.
325
//        if (index < 0 || index >= MAX_PRIMES_LENGTH) {
326
//            throw new IndexOutOfBoundsException(String.valueOf(index));
327
//        }
328
//        short[] primes = XMath.primes;
329
//        if (index >= primes.length) {
330
//            int i = primes.length;
331
//            int n = primes[i - 1] & 0xFFFF;
332
//            primes = XArray.resize(primes, Math.min((index | 0xF) + 1, MAX_PRIMES_LENGTH));
333
//            do {
334
//next:           while (true) {
335
//                    n += 2;
336
//                    for (int j=1; j<i; j++) {
337
//                        if (n % (primes[j] & 0xFFFF) == 0) {
338
//                            continue next;
339
//                        }
340
//                        // We could stop the search at the first value greater than sqrt(n), but
341
//                        // given that the array is relatively short (because we limit ourself to
342
//                        // 16 bits prime numbers), it probably doesn't worth.
343
//                    }
344
//                    assert n < 0xFFFF : i;
345
//                    primes[i] = (short) n;
346
//                    break;
347
//                }
348
//            } while (++i < primes.length);
349
//            XMath.primes = primes;
350
//        }
351
//        return primes[index] & 0xFFFF;
352
//    }
353

    
354
    /**
355
     * Returns the divisors of the specified number as positive integers. For any value other
356
     * than {@code O} (which returns an empty array), the first element in the returned array
357
     * is always {@code 1} and the last element is always the absolute value of {@code number}.
358
     *
359
     * @param number The number for which to compute the divisors.
360
     * @return The divisors in strictly increasing order.
361
     */
362
//    public static int[] divisors(int number) {
363
//        if (number == 0) {
364
//            return new int[0];
365
//        }
366
//        number = Math.abs(number);
367
//        int[] divisors = new int[16];
368
//        divisors[0] = 1;
369
//        int count = 1;
370
//        /*
371
//         * Searchs for the first divisors among the prime numbers. We stop the search at the
372
//         * square root of 'n' because every values above that point can be inferred from the
373
//         * values before that point, i.e. if n=p1*p2 and p2 is greater than 'sqrt', than p1
374
//         * most be lower than 'sqrt'.
375
//         */
376
//        final int sqrt = (int) (Math.sqrt(number) + 1E-6); // Really wants rounding toward 0.
377
//        for (int p,i=0; (p=primeNumber(i)) <= sqrt; i++) {
378
//            if (number % p == 0) {
379
//                if (count == divisors.length) {
380
//                    divisors = XArray.resize(divisors, count*2);
381
//                }
382
//                divisors[count++] = p;
383
//            }
384
//        }
385
//        /*
386
//         * Completes the divisors past 'sqrt'. The numbers added here may or may not be prime
387
//         * numbers. Side note: checking that they are prime numbers would be costly, but this
388
//         * algorithm doesn't need that.
389
//         */
390
//        int source = count;
391
//        if (count*2 > divisors.length) {
392
//            divisors = XArray.resize(divisors, count*2);
393
//        }
394
//        int d1 = divisors[--source];
395
//        int d2 = number / d1;
396
//        if (d1 != d2) {
397
//            divisors[count++] = d2;
398
//        }
399
//        while (--source >= 0) {
400
//            divisors[count++] = number / divisors[source];
401
//        }
402
//        /*
403
//         * Checks the products of divisors found so far. For example if 2 and 3 are divisors,
404
//         * checks if 6 is a divisor as well. The products found will themself be used for
405
//         * computing new products.
406
//         */
407
//        for (int i=1; i<count; i++) {
408
//            d1 = divisors[i];
409
//            for (int j=i; j<count; j++) {
410
//                d2 = d1 * divisors[j];
411
//                if (number % d2 == 0) {
412
//                    int p = org.geotools.resources.Java6.binarySearch(divisors, j, count, d2);
413
//                    if (p < 0) {
414
//                        p = ~p; // ~ operator, not minus
415
//                        if (count == divisors.length) {
416
//                            divisors = XArray.resize(divisors, count*2);
417
//                        }
418
//                        System.arraycopy(divisors, p, divisors, p+1, count-p);
419
//                        divisors[p] = d2;
420
//                        count++;
421
//                    }
422
//                }
423
//            }
424
//        }
425
//        divisors = XArray.resize(divisors, count);
426
//        assert XArray.isStrictlySorted(divisors);
427
//        return divisors;
428
//    }
429
}