Skip to content

Commit

Permalink
#54 step-1(Define Sub-units of Xdager)
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasMLK committed Jun 24, 2021
1 parent d824c94 commit 59229b9
Show file tree
Hide file tree
Showing 4 changed files with 299 additions and 0 deletions.
130 changes: 130 additions & 0 deletions src/main/java/io/xdag/core/XAmount.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package io.xdag.core;

import io.xdag.utils.BasicUtils;

import java.math.BigDecimal;

import static java.math.RoundingMode.FLOOR;
import static java.math.RoundingMode.HALF_UP;

public class XAmount implements Comparable<XAmount> {

public static final XAmount ZERO = new XAmount(0);
public static final XAmount ONE = new XAmount(1);
public static final XAmount TEN = new XAmount(10);

private final long nano;

private XAmount(long nano) {
this.nano = nano;
}

public static XAmount of(long n) {
return new XAmount(n);
}

public static XAmount of(String n) {
return new XAmount(Long.parseLong(n));
}

public static XAmount of(long n, XUnit unit) throws ArithmeticException {
return new XAmount(Math.multiplyExact(n, unit.factor));
}

public static XAmount of(BigDecimal d, XUnit unit) {
return new XAmount(d.movePointRight(unit.exp).setScale(0, FLOOR).longValueExact());
}

public BigDecimal toDecimal(int scale, XUnit unit) {
BigDecimal nano = BigDecimal.valueOf(this.nano);
return nano.movePointLeft(unit.exp).setScale(scale, FLOOR);
}

/**
* Of Xdag Amount from C
*/
public static XAmount ofXAmount(long n) {
BigDecimal d = BasicUtils.amount2xdagNew(n) ;
return new XAmount(d.movePointRight(9).setScale(0, HALF_UP).longValueExact());
}

/**
* To Xdag Amount from C
*/
public long toXAmount() {
return BasicUtils.xdag2amount(toDecimal(9, XUnit.XDAG).doubleValue());
}

@Override
public int compareTo(XAmount other) {
return this.lessThan(other) ? -1 : (this.greaterThan(other) ? 1 : 0);
}

@Override
public int hashCode() {
return Long.hashCode(nano);
}

@Override
public boolean equals(Object other) {
return other instanceof XAmount && ((XAmount) other).nano == nano;
}

@Override
public String toString() {
return String.valueOf(nano);
}

public boolean greaterThan(XAmount other) {
return nano > other.nano;
}

public boolean greaterThanOrEqual(XAmount other) {
return nano >= other.nano;
}

public boolean isPositive() {
return greaterThan(ZERO);
}

public boolean isNotNegative() {
return greaterThanOrEqual(ZERO);
}

public boolean lessThan(XAmount other) {
return nano < other.nano;
}

public boolean lessThanOrEqual(XAmount other) {
return nano <= other.nano;
}

public boolean isNegative() {
return lessThan(ZERO);
}

public boolean isNotPositive() {
return lessThanOrEqual(ZERO);
}

public XAmount negate() throws ArithmeticException {
return new XAmount(Math.negateExact(this.nano));
}

public XAmount add(XAmount a) throws ArithmeticException {
return new XAmount(Math.addExact(this.nano, a.nano));
}

public XAmount subtract(XAmount a) throws ArithmeticException {
return new XAmount(Math.subtractExact(this.nano, a.nano));
}

public XAmount multiply(long a) throws ArithmeticException {
return new XAmount(Math.multiplyExact(this.nano, a));
}

public static XAmount sum(XAmount a, XAmount b) throws ArithmeticException {
return new XAmount(Math.addExact(a.nano, b.nano));
}

}
37 changes: 37 additions & 0 deletions src/main/java/io/xdag/core/XUnit.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package io.xdag.core;

import static java.util.Arrays.stream;
import java.math.BigInteger;

public enum XUnit {

NANO_XDAG(0, "nXDAG"),

MICRO_XDAG(3, "μXDAG"),

MILLI_XDAG(6, "mXDAG"),

XDAG(9, "XDAG");

public final int exp;
public final long factor;
public final String symbol;

XUnit(int exp, String symbol) {
this.exp = exp;
this.factor = BigInteger.TEN.pow(exp).longValueExact();
this.symbol = symbol;
}

/**
* Decode the unit from symbol.
*
* @param symbol
* the symbol text
* @return a Unit object if valid; otherwise false
*/
public static XUnit of(String symbol) {
return stream(values()).filter(v -> v.symbol.equals(symbol)).findAny().orElse(null);
}

}
8 changes: 8 additions & 0 deletions src/main/java/io/xdag/utils/BasicUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,14 @@ public static double amount2xdag(long xdag) {
return bigDecimal.setScale(2, RoundingMode.HALF_UP).doubleValue();
}

public static BigDecimal amount2xdagNew(long xdag) {
if(xdag < 0) throw new XdagOverFlowException();
long first = xdag >> 32;
long temp = xdag - (first << 32);
double tem = temp / Math.pow(2, 32);
return new BigDecimal(first + tem);
}

public static boolean crc32Verify(byte[] src, int crc) {
CRC32 crc32 = new CRC32();
crc32.update(src, 0, 512);
Expand Down
124 changes: 124 additions & 0 deletions src/test/java/io/xdag/core/XAmountTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package io.xdag.core;

import org.junit.Test;

import java.math.BigDecimal;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import static io.xdag.core.XUnit.NANO_XDAG;
import static io.xdag.core.XUnit.MICRO_XDAG;
import static io.xdag.core.XUnit.MILLI_XDAG;
import static io.xdag.core.XUnit.XDAG;
import static io.xdag.core.XAmount.ZERO;

public class XAmountTest {

@Test
public void testUnits() {
assertEquals(ZERO, ZERO);
assertEquals(XAmount.of(1), XAmount.of(1));
assertEquals(XAmount.of(1000), XAmount.of(1, MICRO_XDAG));
assertEquals(XAmount.of(1000, MICRO_XDAG), XAmount.of(1, MILLI_XDAG));
assertEquals(XAmount.of(1000, MILLI_XDAG), XAmount.of(1, XDAG));
}

@Test
public void testFromDecimal() {
assertEquals(ZERO, XAmount.of(BigDecimal.ZERO, XDAG));
assertEquals(XAmount.of(10, XDAG), XAmount.of(new BigDecimal("10.000"), XDAG));
}

@Test
public void testFromSymbol() {
assertEquals(NANO_XDAG, XUnit.of("nXDAG"));
assertEquals(MICRO_XDAG, XUnit.of("μXDAG"));
assertEquals(MILLI_XDAG, XUnit.of("mXDAG"));
assertEquals(XDAG, XUnit.of("XDAG"));
}

@Test
public void testFromSymbolUnknown() {
assertNull(XUnit.of("???"));
}

@Test
public void testToDecimal() {
assertEquals(new BigDecimal("0"), ZERO.toDecimal(0, XDAG));
assertEquals(new BigDecimal("0.000"), ZERO.toDecimal(3, XDAG));

XAmount oneXdag = XAmount.of(1, XDAG);
assertEquals(new BigDecimal("1.000"), oneXdag.toDecimal(3, XDAG));
assertEquals(new BigDecimal("1000.000"), oneXdag.toDecimal(3, MILLI_XDAG));
}

@Test
public void testCompareTo() {
assertEquals(ZERO.compareTo(ZERO), 0);
assertEquals(XAmount.of(1000).compareTo(XAmount.of(1, MICRO_XDAG)), 0);

assertEquals(XAmount.of(10).compareTo(XAmount.of(10)), 0);
assertEquals(XAmount.of(5).compareTo(XAmount.of(10)), -1);
assertEquals(XAmount.of(10).compareTo(XAmount.of(5)), 1);
}

@Test
public void testHashCode() {
assertEquals(ZERO.hashCode(), XAmount.of(0, XDAG).hashCode());
assertEquals(XAmount.of(999, XDAG).hashCode(), XAmount.of(999, XDAG).hashCode());
}

@Test
public void testGtLtEtc() {
assertTrue(XAmount.of(19, XDAG).isPositive());
assertTrue(XAmount.of(-9, XDAG).isNegative());
assertFalse(ZERO.isPositive());
assertFalse(ZERO.isNegative());

assertTrue(ZERO.isNotNegative());
assertTrue(ZERO.isNotPositive());
assertFalse(XAmount.of(-9, XDAG).isNotNegative());
assertFalse(XAmount.of(99, XDAG).isNotPositive());

assertTrue(XAmount.of(999, XDAG).greaterThan(XAmount.of(999, MILLI_XDAG)));
assertTrue(XAmount.of(999, XDAG).greaterThanOrEqual(XAmount.of(999, MILLI_XDAG)));
assertFalse(XAmount.of(999, XDAG).lessThan(XAmount.of(999, MILLI_XDAG)));
assertFalse(XAmount.of(999, XDAG).lessThanOrEqual(XAmount.of(999, MILLI_XDAG)));
}

@Test
public void TestAmount2xdag() {
assertEquals(972.80, XAmount.ofXAmount(4178144185548L).toDecimal(2, XDAG).doubleValue(), 0.0);

// 3333333334
assertEquals(51.20, XAmount.ofXAmount(219902325556L).toDecimal(2, XDAG).doubleValue(), 0.0);

// 400 0000 0000?
assertEquals(1.49, XAmount.ofXAmount(6400000000L).toDecimal(2, XDAG).doubleValue(), 0.0);

// Xfer:transferred 44796588980 10.430000000 XDAG to the address 0000002f28322e9d817fd94a1357e51a. 10.43
assertEquals(10.43, XAmount.ofXAmount(44796588980L).toDecimal(2, XDAG).doubleValue(), 0.0);

// Xfer:transferred 42949672960 10.000000000 XDAG to the address 0000002f28322e9d817fd94a1357e51a. 10.00
assertEquals(10.00, XAmount.ofXAmount(42949672960L).toDecimal(2, XDAG).doubleValue(), 0.0);

// Xfer:transferred 4398046511104 1024.000000000 XDAG to the address 0000002f28322e9d817fd94a1357e51a. 1024.00
assertEquals(1024.00, XAmount.ofXAmount(4398046511104L).toDecimal(2, XDAG).doubleValue(), 0.0);
}

@Test
public void TestXdag2amount() {
BigDecimal a = BigDecimal.valueOf(972.80);
assertEquals(4178144185549L, XAmount.of(a, XDAG).toXAmount());

BigDecimal b = BigDecimal.valueOf(51.20);
assertEquals(219902325556L, XAmount.of(b, XDAG).toXAmount());

BigDecimal c = BigDecimal.valueOf(100.00);
assertEquals(429496729600L, XAmount.of(c, XDAG).toXAmount());
}

}

0 comments on commit 59229b9

Please sign in to comment.