Line | Hits | Source |
---|---|---|
1 | /* | |
2 | * Copyright (c) 2003, the JUNG Project and the Regents of the University | |
3 | * of California | |
4 | * All rights reserved. | |
5 | * | |
6 | * This software is open-source under the BSD license; see either | |
7 | * "license.txt" or | |
8 | * http://jung.sourceforge.net/license.txt for a description. | |
9 | */ | |
10 | package edu.uci.ics.jung.utils; | |
11 | ||
12 | import java.io.PrintStream; | |
13 | /** | |
14 | * Implements additional mathematical functions to within numerical | |
15 | * precision tolerances, and determines the parameters of the | |
16 | * floating point representation. | |
17 | */ | |
18 | 0 | public final class NumericalPrecision { |
19 | /** | |
20 | * Typical meaningful precision for numerical calculations. | |
21 | */ | |
22 | 15 | static private double defaultNumericalPrecision = 0; |
23 | /** | |
24 | * Typical meaningful small number for numerical calculations. | |
25 | */ | |
26 | 15 | static private double smallNumber = 0; |
27 | /** | |
28 | * Radix used by floating-point numbers. | |
29 | */ | |
30 | 15 | static private int radix = 0; |
31 | /** | |
32 | * Largest positive value which, when added to 1.0, yields 0. | |
33 | */ | |
34 | 15 | static private double machinePrecision = 0; |
35 | /** | |
36 | * Largest positive value which, when subtracted to 1.0, yields 0. | |
37 | */ | |
38 | 15 | static private double negativeMachinePrecision = 0; |
39 | /** | |
40 | * Smallest number different from zero. | |
41 | */ | |
42 | 15 | static private double smallestNumber = 0; |
43 | /** | |
44 | * Largest possible number | |
45 | */ | |
46 | 15 | static private double largestNumber = 0; |
47 | /** | |
48 | * Largest argument for the exponential | |
49 | */ | |
50 | 15 | static private double largestExponentialArgument = 0; |
51 | /** | |
52 | * Values used to compute human readable scales. | |
53 | */ | |
54 | 15 | private static final double scales[] = { 1.25, 2, 2.5, 4, 5, 7.5, 8, 10 }; |
55 | 15 | private static final double semiIntegerScales[] = |
56 | { 2, 2.5, 4, 5, 7.5, 8, 10 }; | |
57 | 15 | private static final double integerScales[] = { 2, 4, 5, 8, 10 }; |
58 | ||
59 | private static void computeLargestNumber() { | |
60 | 0 | double floatingRadix = getRadix(); |
61 | 0 | double fullMantissaNumber = |
62 | 1.0d - floatingRadix * getNegativeMachinePrecision(); | |
63 | 0 | while (!Double.isInfinite(fullMantissaNumber)) { |
64 | 0 | largestNumber = fullMantissaNumber; |
65 | 0 | fullMantissaNumber *= floatingRadix; |
66 | } | |
67 | 0 | } |
68 | private static void computeMachinePrecision() { | |
69 | 14 | double floatingRadix = getRadix(); |
70 | 14 | double inverseRadix = 1.0d / floatingRadix; |
71 | 14 | machinePrecision = 1.0d; |
72 | 14 | double tmp = 1.0d + machinePrecision; |
73 | 756 | while (tmp - 1.0d != 0.0d) { |
74 | 742 | machinePrecision *= inverseRadix; |
75 | 742 | tmp = 1.0d + machinePrecision; |
76 | } | |
77 | 14 | } |
78 | private static void computeNegativeMachinePrecision() { | |
79 | 0 | double floatingRadix = getRadix(); |
80 | 0 | double inverseRadix = 1.0d / floatingRadix; |
81 | 0 | negativeMachinePrecision = 1.0d; |
82 | 0 | double tmp = 1.0d - negativeMachinePrecision; |
83 | 0 | while (tmp - 1.0d != 0.0d) { |
84 | 0 | negativeMachinePrecision *= inverseRadix; |
85 | 0 | tmp = 1.0d - negativeMachinePrecision; |
86 | } | |
87 | 0 | } |
88 | private static void computeRadix() { | |
89 | 14 | double a = 1.0d; |
90 | double tmp1, tmp2; | |
91 | do { | |
92 | 14 | a += a; |
93 | 14 | tmp1 = a + 1.0d; |
94 | 14 | tmp2 = tmp1 - a; |
95 | 14 | } while (tmp2 - 1.0d != 0.0d); |
96 | 14 | double b = 1.0d; |
97 | 28 | while (radix == 0) { |
98 | 14 | b += b; |
99 | 14 | tmp1 = a + b; |
100 | 14 | radix = (int) (tmp1 - a); |
101 | } | |
102 | 14 | } |
103 | private static void computeSmallestNumber() { | |
104 | 0 | double floatingRadix = getRadix(); |
105 | 0 | double inverseRadix = 1.0d / floatingRadix; |
106 | 0 | double fullMantissaNumber = |
107 | 1.0d - floatingRadix * getNegativeMachinePrecision(); | |
108 | 0 | while (fullMantissaNumber != 0.0d) { |
109 | 0 | smallestNumber = fullMantissaNumber; |
110 | 0 | fullMantissaNumber *= inverseRadix; |
111 | } | |
112 | 0 | } |
113 | public static double defaultNumericalPrecision() { | |
114 | 34 | if (defaultNumericalPrecision == 0) |
115 | 14 | defaultNumericalPrecision = Math.sqrt(getMachinePrecision()); |
116 | 34 | return defaultNumericalPrecision; |
117 | } | |
118 | /** | |
119 | * @return boolean true if the difference between a and b is | |
120 | * less than the default numerical precision | |
121 | * @param a double | |
122 | * @param b double | |
123 | */ | |
124 | public static boolean equal(double a, double b) { | |
125 | 0 | return equal(a, b, defaultNumericalPrecision()); |
126 | } | |
127 | /** | |
128 | * @return boolean true if the relative difference between a and b | |
129 | * is less than precision | |
130 | * @param a double | |
131 | * @param b double | |
132 | * @param precision double | |
133 | */ | |
134 | public static boolean equal(double a, double b, double precision) { | |
135 | 285 | double norm = Math.max(Math.abs(a), Math.abs(b)); |
136 | 285 | return norm < precision || Math.abs(a - b) < precision * norm; |
137 | } | |
138 | public static double getLargestExponentialArgument() { | |
139 | 0 | if (largestExponentialArgument == 0) |
140 | 0 | largestExponentialArgument = Math.log(getLargestNumber()); |
141 | 0 | return largestExponentialArgument; |
142 | } | |
143 | /** | |
144 | * (c) Copyrights Didier BESSET, 1999, all rights reserved. | |
145 | */ | |
146 | public static double getLargestNumber() { | |
147 | 0 | if (largestNumber == 0) |
148 | 0 | computeLargestNumber(); |
149 | 0 | return largestNumber; |
150 | } | |
151 | public static double getMachinePrecision() { | |
152 | 14 | if (machinePrecision == 0) |
153 | 14 | computeMachinePrecision(); |
154 | 14 | return machinePrecision; |
155 | } | |
156 | public static double getNegativeMachinePrecision() { | |
157 | 0 | if (negativeMachinePrecision == 0) |
158 | 0 | computeNegativeMachinePrecision(); |
159 | 0 | return negativeMachinePrecision; |
160 | } | |
161 | public static int getRadix() { | |
162 | 14 | if (radix == 0) |
163 | 14 | computeRadix(); |
164 | 14 | return radix; |
165 | } | |
166 | public static double getSmallestNumber() { | |
167 | 0 | if (smallestNumber == 0) |
168 | 0 | computeSmallestNumber(); |
169 | 0 | return smallestNumber; |
170 | } | |
171 | public static void printParameters(PrintStream printStream) { | |
172 | 0 | printStream.println("Floating-point machine parameters"); |
173 | 0 | printStream.println("---------------------------------"); |
174 | 0 | printStream.println(" "); |
175 | 0 | printStream.println("radix = " + getRadix()); |
176 | 0 | printStream.println("Machine precision = " + getMachinePrecision()); |
177 | 0 | printStream.println( |
178 | "Negative machine precision = " + getNegativeMachinePrecision()); | |
179 | 0 | printStream.println("Smallest number = " + getSmallestNumber()); |
180 | 0 | printStream.println("Largest number = " + getLargestNumber()); |
181 | 0 | return; |
182 | } | |
183 | public static void reset() { | |
184 | 0 | defaultNumericalPrecision = 0; |
185 | 0 | smallNumber = 0; |
186 | 0 | radix = 0; |
187 | 0 | machinePrecision = 0; |
188 | 0 | negativeMachinePrecision = 0; |
189 | 0 | smallestNumber = 0; |
190 | 0 | largestNumber = 0; |
191 | 0 | } |
192 | /** | |
193 | * This method returns the specified value rounded to | |
194 | * the nearest integer multiple of the specified scale. | |
195 | * | |
196 | * @param value number to be rounded | |
197 | * @param scale defining the rounding scale | |
198 | * @return rounded value | |
199 | */ | |
200 | public static double roundTo(double value, double scale) { | |
201 | 0 | return Math.round(value / scale) * scale; |
202 | } | |
203 | /** | |
204 | * Round the specified value upward to the next scale value. | |
205 | * @param value the value to be rounded. | |
206 | * @param integerValued a flag specified whether integer scale are used, otherwise double scale is used. | |
207 | * @return a number rounded upward to the next scale value. | |
208 | */ | |
209 | public static double roundToScale(double value, boolean integerValued) { | |
210 | double[] scaleValues; | |
211 | 2 | int orderOfMagnitude = |
212 | (int) Math.floor(Math.log(value) / Math.log(10.0)); | |
213 | 2 | if (integerValued) { |
214 | 0 | orderOfMagnitude = Math.max(1, orderOfMagnitude); |
215 | 0 | if (orderOfMagnitude == 1) |
216 | 0 | scaleValues = integerScales; |
217 | 0 | else if (orderOfMagnitude == 2) |
218 | 0 | scaleValues = semiIntegerScales; |
219 | else | |
220 | 0 | scaleValues = scales; |
221 | } else | |
222 | 2 | scaleValues = scales; |
223 | 2 | double exponent = Math.pow(10.0, orderOfMagnitude); |
224 | 2 | double rValue = value / exponent; |
225 | 13 | for (int n = 0; n < scaleValues.length; n++) { |
226 | 13 | if (rValue <= scaleValues[n]) |
227 | 2 | return scaleValues[n] * exponent; |
228 | } | |
229 | 0 | return exponent; // Should never reach here |
230 | } | |
231 | ||
232 | /** | |
233 | * Returns the smallest number that the system can handle. | |
234 | * | |
235 | * @return double The smallest number the machine can handle. | |
236 | */ | |
237 | public static double smallNumber() { | |
238 | 0 | if (smallNumber == 0) |
239 | 0 | smallNumber = Math.sqrt(getSmallestNumber()); |
240 | 0 | return smallNumber; |
241 | } | |
242 | } |
this report was generated by version 1.0.5 of jcoverage. |
copyright © 2003, jcoverage ltd. all rights reserved. |