|
|
@@ -7,7 +7,10 @@
|
|
|
|
|
|
package net.ranides.assira.math;
|
|
|
|
|
|
+import java.math.BigDecimal;
|
|
|
import java.util.Arrays;
|
|
|
+import net.ranides.assira.annotations.Meta;
|
|
|
+import net.ranides.assira.collection.ArrayUtils;
|
|
|
import net.ranides.assira.text.Strings;
|
|
|
|
|
|
/**
|
|
|
@@ -18,8 +21,8 @@ public class BCDecimal extends Number implements Comparable<BCDecimal> {
|
|
|
|
|
|
private final byte[] data;
|
|
|
|
|
|
- public BCDecimal(long value) {
|
|
|
- this(32, value);
|
|
|
+ public BCDecimal(int size) {
|
|
|
+ this.data = new byte[floor2(size)];
|
|
|
}
|
|
|
|
|
|
public BCDecimal(int size, long value) {
|
|
|
@@ -45,8 +48,20 @@ public class BCDecimal extends Number implements Comparable<BCDecimal> {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public BCDecimal(Number value) {
|
|
|
- throw new UnsupportedOperationException("Not supported yet.");
|
|
|
+ public BCDecimal(BCDecimal value) {
|
|
|
+ this.data = ArrayUtils.arraycopy(value.data);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static BCDecimal valueOf(Number value) {
|
|
|
+ assert value != null;
|
|
|
+
|
|
|
+ if(value instanceof BCDecimal) {
|
|
|
+ return new BCDecimal((BCDecimal)value);
|
|
|
+ }
|
|
|
+ if(value instanceof Long || value instanceof Integer || value instanceof Short || value instanceof Byte) {
|
|
|
+ return new BCDecimal( 32, value.longValue() );
|
|
|
+ }
|
|
|
+ throw new UnsupportedOperationException("Not supported type: " + value.getClass());
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
@@ -79,6 +94,10 @@ public class BCDecimal extends Number implements Comparable<BCDecimal> {
|
|
|
return longValue();
|
|
|
}
|
|
|
|
|
|
+ public BigDecimal bigValue() {
|
|
|
+ return new BigDecimal(toString());
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public int compareTo(BCDecimal value) {
|
|
|
int n = Math.max(size(), value.size());
|
|
|
@@ -105,7 +124,11 @@ public class BCDecimal extends Number implements Comparable<BCDecimal> {
|
|
|
return 0 == compareTo( (BCDecimal)object );
|
|
|
}
|
|
|
if( object instanceof Number) {
|
|
|
- return 0 == new BCDecimal((Number)object).compareTo(this);
|
|
|
+ try {
|
|
|
+ return 0 == BCDecimal.valueOf((Number)object).compareTo(this);
|
|
|
+ } catch(UnsupportedOperationException cause) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
@@ -127,8 +150,53 @@ public class BCDecimal extends Number implements Comparable<BCDecimal> {
|
|
|
return builder.toString();
|
|
|
}
|
|
|
|
|
|
+ public final void at(int index, int value) {
|
|
|
+ int seg = data.length - index / 2 - 1;
|
|
|
+ if(0 == index % 2) {
|
|
|
+ data[seg] = (byte)((data[seg] & 0xF0) | (value & 0x0F));
|
|
|
+ } else {
|
|
|
+ data[seg] = (byte)((data[seg] & 0x0F) | (value << 4));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public final int at(int index) {
|
|
|
+ int seg = data.length - index / 2 - 1;
|
|
|
+ if( seg <0 ) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ if(0 == index % 2) {
|
|
|
+ return data[seg] & 0x0F;
|
|
|
+ } else {
|
|
|
+ return (data[seg] >> 4) & 0x0F;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public final int size() {
|
|
|
+ return data.length * 2;
|
|
|
+ }
|
|
|
+
|
|
|
public BCDecimal add(BCDecimal value) {
|
|
|
- throw new UnsupportedOperationException("Not supported yet.");
|
|
|
+ return add(this, value);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static BCDecimal add(BCDecimal number1, BCDecimal number2) {
|
|
|
+ if( number1.size() < number2.size() ) {
|
|
|
+ return add(number2, number1);
|
|
|
+ }
|
|
|
+ BCDecimal ret = new BCDecimal(number1.size());
|
|
|
+ int cv = 0;
|
|
|
+ for(int i=0, n=number2.size(); i<n; i++) {
|
|
|
+ int v = number1.at(i) + number2.at(i) + cv;
|
|
|
+ ret.at(i, v % 10);
|
|
|
+ cv = v / 10;
|
|
|
+ }
|
|
|
+ if(cv > 0) {
|
|
|
+ if( ret.size() == number2.size() ) {
|
|
|
+ throw new ArithmeticException("BCDecimal: value is too large.");
|
|
|
+ }
|
|
|
+ ret.at(number2.size(), cv);
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
public BCDecimal sub(BCDecimal value) {
|
|
|
@@ -171,31 +239,4 @@ public class BCDecimal extends Number implements Comparable<BCDecimal> {
|
|
|
return (value / 2) + (value % 2);
|
|
|
}
|
|
|
|
|
|
- public final void at(int index, int value) {
|
|
|
- int seg = data.length - index / 2 - 1;
|
|
|
- if(0 == index % 2) {
|
|
|
- data[seg] = (byte)((data[seg] & 0xF0) | (value & 0x0F));
|
|
|
- } else {
|
|
|
- data[seg] = (byte)((data[seg] & 0x0F) | (value << 4));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public int at(int index) {
|
|
|
- int seg = data.length - index / 2 - 1;
|
|
|
- if( seg <0 ) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
- if(0 == index % 2) {
|
|
|
- return data[seg] & 0x0F;
|
|
|
- } else {
|
|
|
- return (data[seg] >> 4) & 0x0F;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public int size() {
|
|
|
- return data.length * 2;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
}
|