|
|
@@ -0,0 +1,201 @@
|
|
|
+/*
|
|
|
+ * @author Ranides Atterwim <ranides@gmail.com>
|
|
|
+ * @copyright Ranides Atterwim
|
|
|
+ * @license WTFPL
|
|
|
+ * @url http://ranides.net/projects/assira
|
|
|
+ */
|
|
|
+
|
|
|
+package net.ranides.assira.math;
|
|
|
+
|
|
|
+import java.util.Arrays;
|
|
|
+import net.ranides.assira.text.Strings;
|
|
|
+
|
|
|
+/**
|
|
|
+ *
|
|
|
+ * @author ranides
|
|
|
+ */
|
|
|
+public class BCDecimal extends Number implements Comparable<BCDecimal> {
|
|
|
+
|
|
|
+ private final byte[] data;
|
|
|
+
|
|
|
+ public BCDecimal(long value) {
|
|
|
+ this(32, value);
|
|
|
+ }
|
|
|
+
|
|
|
+ public BCDecimal(int size, long value) {
|
|
|
+ this.data = new byte[floor2(size)];
|
|
|
+ int index = 0;
|
|
|
+ while(value > 0) {
|
|
|
+ if(index >= size) {
|
|
|
+ throw new ArithmeticException("BCDecimal: value is too large.");
|
|
|
+ }
|
|
|
+ at(index++, (int)(value % 10));
|
|
|
+ value /= 10;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public BCDecimal(int size, char[] value) {
|
|
|
+ this(size, Strings.asSequence(value));
|
|
|
+ }
|
|
|
+
|
|
|
+ public BCDecimal(int size, CharSequence value) {
|
|
|
+ this.data = new byte[floor2(size)];
|
|
|
+ for(int n=value.length()-1, i=0; i<=n; i++) {
|
|
|
+ at(n-i, value.charAt(i)-'0');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public BCDecimal(Number value) {
|
|
|
+ throw new UnsupportedOperationException("Not supported yet.");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int intValue() {
|
|
|
+ int ret = 0;
|
|
|
+ int di= 1;
|
|
|
+ for(int i=0; i<9; i++) {
|
|
|
+ ret += di * at(i);
|
|
|
+ di*=10;
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public long longValue() {
|
|
|
+ long ret = 0;
|
|
|
+ for(int i=0; i<20; i++) {
|
|
|
+ ret += i * at(i);
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public float floatValue() {
|
|
|
+ return longValue();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public double doubleValue() {
|
|
|
+ return longValue();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int compareTo(BCDecimal value) {
|
|
|
+ int n = Math.max(size(), value.size());
|
|
|
+ for(int i=n-1; i>=0; i--) {
|
|
|
+ int d = at(i)-value.at(i);
|
|
|
+ if(d != 0) {
|
|
|
+ return d;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int hashCode() {
|
|
|
+ return Arrays.hashCode(data);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean equals(Object object) {
|
|
|
+ if( object == this) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ if( object instanceof BCDecimal ) {
|
|
|
+ return 0 == compareTo( (BCDecimal)object );
|
|
|
+ }
|
|
|
+ if( object instanceof Number) {
|
|
|
+ return 0 == new BCDecimal((Number)object).compareTo(this);
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String toString() {
|
|
|
+ StringBuilder builder = new StringBuilder( size() );
|
|
|
+ boolean nz = false;
|
|
|
+ for(int i=size()-1; i>=0; i--) {
|
|
|
+ char v = (char)('0' + at(i));
|
|
|
+ if(v != '0' || nz) {
|
|
|
+ builder.append(v);
|
|
|
+ nz = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(!nz) {
|
|
|
+ return "0";
|
|
|
+ }
|
|
|
+ return builder.toString();
|
|
|
+ }
|
|
|
+
|
|
|
+ public BCDecimal add(BCDecimal value) {
|
|
|
+ throw new UnsupportedOperationException("Not supported yet.");
|
|
|
+ }
|
|
|
+
|
|
|
+ public BCDecimal sub(BCDecimal value) {
|
|
|
+ throw new UnsupportedOperationException("Not supported yet.");
|
|
|
+ }
|
|
|
+
|
|
|
+ public BCDecimal mul(BCDecimal value) {
|
|
|
+ throw new UnsupportedOperationException("Not supported yet.");
|
|
|
+ }
|
|
|
+
|
|
|
+ public BCDecimal div(BCDecimal value) {
|
|
|
+ throw new UnsupportedOperationException("Not supported yet.");
|
|
|
+ }
|
|
|
+
|
|
|
+ public BCDecimal mod(BCDecimal value) {
|
|
|
+ throw new UnsupportedOperationException("Not supported yet.");
|
|
|
+ }
|
|
|
+
|
|
|
+ public BCDecimal pow(BCDecimal value) {
|
|
|
+ throw new UnsupportedOperationException("Not supported yet.");
|
|
|
+ }
|
|
|
+
|
|
|
+ public BCDecimal abs() {
|
|
|
+ throw new UnsupportedOperationException("Not supported yet.");
|
|
|
+ }
|
|
|
+
|
|
|
+ public BCDecimal neg() {
|
|
|
+ throw new UnsupportedOperationException("Not supported yet.");
|
|
|
+ }
|
|
|
+
|
|
|
+ public BCDecimal min(BCDecimal value) {
|
|
|
+ throw new UnsupportedOperationException("Not supported yet.");
|
|
|
+ }
|
|
|
+
|
|
|
+ public BCDecimal max(BCDecimal value) {
|
|
|
+ throw new UnsupportedOperationException("Not supported yet.");
|
|
|
+ }
|
|
|
+
|
|
|
+ private static int floor2(int value) {
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+}
|