KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > math > RealNum


1 // Copyright (c) 1997, 2004, 2006 Per M.A. Bothner.
2
// This is free software; for terms and warranty disclaimer see ./COPYING.
3

4 package gnu.math;
5 import java.math.BigDecimal JavaDoc;
6
7 public abstract class RealNum extends Complex
8   /* #ifdef JAVA2 */
9   implements Comparable JavaDoc
10   /* #endif */
11 {
12   public final RealNum re() { return this; }
13   public final RealNum im() { return IntNum.zero(); }
14
15   public abstract boolean isNegative ();
16
17   /** Return 1 if >0; 0 if ==0; -1 if <0; -2 if NaN. */
18   public abstract int sign ();
19
20   public RealNum max (RealNum x)
21   {
22     boolean exact = isExact () && x.isExact ();
23     RealNum result = grt (x) ? this : x;
24     if (!exact && result.isExact ())
25       result = new DFloNum (result.doubleValue ());
26     return result;
27   }
28
29   public RealNum min (RealNum x)
30   {
31     boolean exact = isExact () && x.isExact ();
32     RealNum result = grt (x) ? x : this;
33     if (!exact && result.isExact ())
34       result = new DFloNum (result.doubleValue ());
35     return result;
36   }
37
38   public static RealNum add (RealNum x, RealNum y, int k)
39   {
40     return (RealNum)(x.add(y, k));
41   }
42
43   public static RealNum times(RealNum x, RealNum y)
44   {
45     return (RealNum)(x.mul(y));
46   }
47
48   public static RealNum divide (RealNum x, RealNum y)
49   {
50     return (RealNum)(x.div(y));
51   }
52
53   /* These are defined in Complex, but have to be overridden. */
54   public abstract Numeric add (Object JavaDoc obj, int k);
55   public abstract Numeric mul (Object JavaDoc obj);
56   public abstract Numeric div (Object JavaDoc obj);
57
58   public Numeric abs ()
59   {
60     return isNegative () ? neg () : this;
61   }
62
63   public final RealNum rneg() { return (RealNum) neg(); }
64
65   public boolean isZero ()
66   {
67     return sign () == 0;
68   }
69
70   /** Convert to an exact number.
71    * Implements the Scheme inexact->exact (for real numbers).
72    */

73   public RatNum toExact ()
74   {
75     return DFloNum.toExact (doubleValue ());
76   }
77
78   /** Converts a real to an integer, according to a specified rounding mode.
79    * Note an inexact argument gives an inexact result, following Scheme.
80    * See also RatNum.toExactInt. */

81   public static double toInt (double d, int rounding_mode)
82   {
83     switch (rounding_mode)
84       {
85       case FLOOR:
86     return Math.floor(d);
87       case CEILING:
88     return Math.ceil(d);
89       case TRUNCATE:
90     return d < 0.0 ? Math.ceil (d) : Math.floor (d);
91       case ROUND:
92     return Math.rint(d);
93       default: // Illegal rounding_mode
94
return d;
95       }
96   }
97
98   /** Converts a real to an integer, according to a specified rounding mode.
99    * Note an inexact argument gives an inexact result, following Scheme.
100    * See also toExactInt. */

101   public RealNum toInt (int rounding_mode)
102   {
103     return new DFloNum(toInt(doubleValue(), rounding_mode));
104   }
105
106   /** Converts to an exact integer, with specified rounding mode. */
107   public IntNum toExactInt (int rounding_mode)
108   {
109     return toExactInt(doubleValue(), rounding_mode);
110   }
111
112   /** Converts real to an exact integer, with specified rounding mode. */
113   public static IntNum toExactInt (double value, int rounding_mode)
114   {
115     return toExactInt(toInt(value, rounding_mode));
116   }
117
118   /** Converts an integral double (such as a toInt result) to an IntNum. */
119   public static IntNum toExactInt (double value)
120   {
121     if (Double.isInfinite (value) || Double.isNaN (value))
122       throw new ArithmeticException JavaDoc ("cannot convert "+value+" to exact integer");
123     long bits = Double.doubleToLongBits (value);
124     boolean neg = bits < 0;
125     int exp = (int) (bits >> 52) & 0x7FF;
126     bits &= 0xfffffffffffffL;
127     if (exp == 0)
128       bits <<= 1;
129     else
130       bits |= 0x10000000000000L;
131     if (exp <= 1075)
132       {
133     int rshift = 1075 - exp;
134     if (rshift > 53)
135       return IntNum.zero();
136     bits >>= rshift;
137     return IntNum.make (neg ? -bits : bits);
138       }
139     return IntNum.shift (IntNum.make (neg ? -bits : bits), exp - 1075);
140   }
141
142   public Complex exp ()
143   {
144     return new DFloNum(Math.exp(doubleValue()));
145   }
146
147   public Complex log ()
148   {
149     double x = doubleValue();
150     if (x < 0)
151       return DComplex.log(x, 0.0);
152     return new DFloNum(Math.log(x));
153   }
154
155   public final Complex sin() { return new DFloNum(Math.sin(doubleValue())); }
156
157   public final Complex sqrt ()
158   {
159     double d = doubleValue();
160     if (d >= 0)
161       return new DFloNum(Math.sqrt(d));
162     else
163       return DComplex.sqrt(d, 0);
164   }
165
166   /** Convert double to (rounded) integer, after multiplying by 10**k. */
167   public static IntNum toScaledInt (double f, int k)
168   {
169     return toScaledInt(DFloNum.toExact(f), k);
170   }
171
172   /** Convert rational to (rounded) integer, after multiplying by 10**k. */
173   public static IntNum toScaledInt (RatNum r, int k)
174   {
175     if (k != 0)
176       {
177     IntNum power = IntNum.power(IntNum.ten(), k < 0 ? -k : k);
178     IntNum num = r.numerator();
179     IntNum den = r.denominator();
180     if (k >= 0)
181       num = IntNum.times(num, power);
182     else
183       den = IntNum.times(den, power);
184     r = RatNum.make(num, den);
185       }
186     return r.toExactInt(ROUND);
187   }
188
189   /** Convert this to (rounded) integer, after multiplying by 10**k. */
190   public IntNum toScaledInt (int k)
191   {
192     return toScaledInt(toExact(), k);
193   }
194
195   /*
196   public static String toScaledIntString (double f, int k)
197   {
198     switch (k)
199       {
200       case 0: break;
201       case 1: f = f * 10; break;
202       case 2: f = f * 100; break;
203       case 3: f = f * 1000; break;
204       default: return toScaledInt(f, k).toString();
205       }
206     return Long.toString((long) f);
207   }
208   */

209
210   /** Implements the Comparable interface.
211    * This ordering isn't fully consistent with equals, since say
212    * it returns 0 when comparing 1.5 and 3/2, though they are not equals.
213    */

214   public int compareTo(Object JavaDoc o)
215   {
216     return compare(o);
217   }
218
219   public java.math.BigDecimal JavaDoc asBigDecimal ()
220   {
221     return new BigDecimal JavaDoc(doubleValue());
222   }
223
224   public static String JavaDoc toStringScientific (float d)
225   {
226     return toStringScientific(Float.toString(d));
227   }
228
229   public static String JavaDoc toStringScientific (double d)
230   {
231     return toStringScientific(Double.toString(d));
232   }
233
234   /** Convert result of Double.toString or Float.toString to
235    * scientific notation.
236    * Does not validate the input.
237    */

238   public static String JavaDoc toStringScientific (String JavaDoc dstr)
239   {
240     int indexE = dstr.indexOf('E');
241     if (indexE >= 0)
242       return dstr;
243     int len = dstr.length();
244     // Check for "Infinity" or "NaN".
245
char ch = dstr.charAt(len-1);
246     if (ch == 'y' || ch == 'N')
247       return dstr;
248     StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc(len+10);
249     int exp = toStringScientific(dstr, sbuf);
250     sbuf.append('E');
251     sbuf.append(exp);
252     return sbuf.toString();
253   }
254
255   public static int toStringScientific (String JavaDoc dstr, StringBuffer JavaDoc sbuf)
256   {
257     boolean neg = dstr.charAt(0) == '-';
258     if (neg)
259       sbuf.append('-');
260     int pos = neg ? 1 : 0;
261     int exp;
262     int len = dstr.length();
263     if (dstr.charAt(pos) == '0')
264       { // Value is < 1.0.
265
int start = pos;
266         for (;;)
267           {
268             if (pos == len)
269               {
270                 sbuf.append("0");
271                 exp = 0;
272                 break;
273               }
274             char ch = dstr.charAt(pos++);
275             if (ch >= '0' && ch <= '9' && (ch != '0' || pos == len))
276               {
277                 sbuf.append(ch);
278                 sbuf.append('.');
279                 exp = ch == '0' ? 0 : start - pos + 2;
280                 if (pos == len)
281                   sbuf.append('0');
282                 else
283                   {
284                     while (pos < len)
285                       sbuf.append(dstr.charAt(pos++));
286                   }
287                 break;
288               }
289           }
290       }
291     else
292       {
293         // Number of significant digits in string.
294
int ndigits = len - (neg ? 2 : 1);
295         int dot = dstr.indexOf('.');
296         // Number of fractional digits is len-dot-1.
297
// We want ndigits-1 fractional digits. Hence we need to move the
298
// decimal point ndigits-1-(len-dot-1) == ndigits-len+dot positions
299
// to the left. This becomes the exponent we need.
300
exp = ndigits - len + dot;
301         sbuf.append(dstr.charAt(pos++)); // Copy initial digit before point.
302
sbuf.append('.');
303         while (pos < len)
304           {
305             char ch = dstr.charAt(pos++);
306             if (ch != '.')
307               sbuf.append(ch);
308           }
309       }
310     // Remove excess zeros.
311
pos = sbuf.length();
312     int slen = -1;
313     for (;;)
314       {
315         char ch = sbuf.charAt(--pos);
316         if (ch == '0')
317           slen = pos;
318         else
319           {
320             if (ch == '.')
321               slen = pos + 2;
322             break;
323           }
324       }
325     if (slen >= 0)
326       sbuf.setLength(slen);
327     return exp;
328   }
329
330   public static String JavaDoc toStringDecimal (String JavaDoc dstr)
331   {
332     int indexE = dstr.indexOf('E');
333     if (indexE < 0)
334       return dstr;
335     int len = dstr.length();
336     // Check for "Infinity" or "NaN".
337
char ch = dstr.charAt(len-1);
338     if (ch == 'y' || ch == 'N')
339       return dstr;
340     StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc(len+10);
341     boolean neg = dstr.charAt(0) == '-';
342     if (dstr.charAt(indexE+1) != '-')
343       {
344         throw new Error JavaDoc("not implemented: toStringDecimal given non-negative exponent: "+dstr);
345       }
346     else
347       {
348         int pos = indexE+2; // skip "E-".
349
int exp = 0;
350         while (pos < len)
351           exp = 10 * exp + (dstr.charAt(pos++) - '0');
352         if (neg)
353           sbuf.append('-');
354         sbuf.append("0.");
355         while (--exp > 0) sbuf.append('0');
356         for (pos = 0; (ch = dstr.charAt(pos++)) != 'E'; )
357           {
358             if (ch != '-' & ch != '.'
359                 && (ch != '0' || pos < indexE))
360               sbuf.append(ch);
361           }
362         return sbuf.toString();
363       }
364   }
365 }
366
Popular Tags