View Javadoc

1   /*
2    * To change this template, choose Tools | Templates
3    * and open the template in the editor.
4    */
5   
6   package net.sf.zel.nr;
7   
8   import java.math.BigDecimal;
9   import java.math.BigInteger;
10  import javax.annotation.concurrent.Immutable;
11  import net.sf.zel.math.ExtendedMathContext;
12  
13  /**
14   * THis class currently is implemented via the gnu mp library,
15   * for corect rounding a reimplementation using mpfr will be done later
16   * THis class is very good if better precision math is needed
17   *
18   * @author zoly
19   */
20  
21  @Immutable
22  public final class OperableGNUBigFloat extends OperableGNUNumber
23  {
24  
25      /**
26       * The pointer is a 64 bit pointer to support 64 bit jvms
27       */
28      private transient long pointer;
29  
30      private final int precision;
31  
32      public static final OperableGNUBigFloat ZERO = new OperableGNUBigFloat("0");
33      public static final OperableGNUBigFloat ONE = new OperableGNUBigFloat("1");
34  
35      public OperableGNUBigFloat(final String number)
36      {
37          precision = ExtendedMathContext.CURRENT_EXTENDED_MATH_CONTEXT.get().getMathContext().getPrecision();
38          pointer = allocateGMP(number, precision);
39      }
40  
41      public OperableGNUBigFloat(final byte[] bytes)
42      {
43          precision = ExtendedMathContext.CURRENT_EXTENDED_MATH_CONTEXT.get().getMathContext().getPrecision();
44          pointer = allocateGMP(toString(bytes, 10), precision);
45      }
46  
47      private OperableGNUBigFloat(final long pointer)
48      {
49          this.pointer = pointer;
50          precision = ExtendedMathContext.CURRENT_EXTENDED_MATH_CONTEXT.get().getMathContext().getPrecision();
51      }
52  
53      @Override
54      protected void finalize() throws Throwable
55      {
56          try
57          {
58              super.finalize();
59          }
60          finally
61          {
62              freeGMP(pointer);
63          }
64      }
65  
66      private static native long allocateGMP(String number, int precision);
67  
68      private static native void freeGMP(long pointer);
69  
70      private static native String toString(byte number[], int base);
71  
72      private static native String toString(long pointer, int base, int precision);
73  
74      private static native long add(long a, long b);
75  
76      private static native long substract(long a, long b);
77  
78      public static native long multiply(long a, long b);
79  
80      public static native long divide(long a, long b);
81  
82  
83      @Override
84      public OperableNumber add(final OperableNumber addend)
85      {
86          return new OperableGNUBigFloat(add(this.pointer, addend.gnuBigFloatValue().pointer));
87      }
88  
89      @Override
90      public OperableNumber subtract(final OperableNumber subtrahend)
91      {
92          return new OperableGNUBigFloat(substract(this.pointer, subtrahend.gnuBigFloatValue().pointer));
93      }
94  
95      @Override
96      public OperableNumber multiply(final OperableNumber multiplier)
97      {
98          return new OperableGNUBigFloat(multiply(this.pointer, multiplier.gnuBigFloatValue().pointer));
99      }
100 
101     @Override
102     public OperableNumber divide(final OperableNumber divisor)
103     {
104         return new OperableGNUBigFloat(divide(this.pointer, divisor.gnuBigFloatValue().pointer));
105     }
106 
107     @Override
108     public OperableNumber mod(final OperableNumber divisor)
109     {
110        throw new UnsupportedOperationException("Modulus is a invalid operation on decimals");
111     }
112 
113     @Override
114     public Type getType()
115     {
116         return OperableNumber.Type.REAL;
117     }
118 
119     @Override
120     public BigDecimal bigDecimalValue()
121     {
122         return new BigDecimal(toString());
123     }
124 
125     @Override
126     public BigInteger bigIntegerValue()
127     {
128         return new BigInteger(toString());
129 
130     }
131 
132     @Override
133     public OperableGNUBigInteger gnuBigIntegerValue()
134     {
135         return new OperableGNUBigInteger(toString());
136     }
137 
138     @Override
139     public int intValue()
140     {
141         return Integer.parseInt(toString());
142     }
143 
144     @Override
145     public long longValue()
146     {
147         return Long.parseLong(toString());
148     }
149 
150     @Override
151     public float floatValue()
152     {
153         return Float.parseFloat(toString());
154     }
155 
156     @Override
157     public double doubleValue()
158     {
159         return Double.parseDouble(toString());
160     }
161 
162     @Override
163     public String toString()
164     {
165         return toString(this.pointer, 10, ExtendedMathContext.CURRENT_EXTENDED_MATH_CONTEXT.get().getMathContext().getPrecision());
166     }
167 
168     public int compareTo(Object o)
169     {
170         throw new UnsupportedOperationException("Not supported yet.");
171     }
172 
173     @Override
174     public ExtendedNumber zero()
175     {
176         throw new UnsupportedOperationException("Not supported yet.");
177     }
178 
179     @Override
180     public OperableGNUBigFloat gnuBigFloatValue()
181     {
182         return this;
183     }
184 
185     @Override
186     public int getPrecision()
187     {
188         return precision;
189     }
190 
191     @Override
192     public OperableNumber create(final String val)
193     {
194         if ("0.0".equals(val))
195             return ZERO;
196         else
197             return new OperableGNUBigFloat(val);
198     }
199 
200     @Override
201     public ExtendedNumber one()
202     {
203         return ONE;
204     }
205 
206     @Override
207     public OperableNumber convert(ExtendedNumber val)
208     {
209         return new OperableGNUBigFloat(val.toString());
210     }
211 
212 
213 }