package jscl;
import jscl.math.JsclInteger;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.HashSet;
import java.util.Set;
import static java.util.Arrays.asList;
public enum NumeralBase {
dec(10, 3) {
private final Set<Character> characters = new HashSet<>(asList('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'));
@Nonnull
@Override
public Double toDouble(@Nonnull String doubleString) {
return Double.valueOf(doubleString);
}
@Nonnull
@Override
public String getJsclPrefix() {
return "0d:";
}
@Nonnull
@Override
public Set<Character> getAcceptableCharacters() {
return characters;
}
},
hex(16, 2) {
private final Set<Character> characters = new HashSet<>(asList('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'));
@Nonnull
@Override
public String getJsclPrefix() {
return "0x:";
}
@Nonnull
@Override
public Set<Character> getAcceptableCharacters() {
return characters;
}
},
oct(8, 4) {
private final Set<Character> characters = new HashSet<>(asList('0', '1', '2', '3', '4', '5', '6', '7'));
@Nonnull
@Override
public String getJsclPrefix() {
return "0o:";
}
@Nonnull
@Override
public Set<Character> getAcceptableCharacters() {
return characters;
}
},
bin(2, 4) {
private final Set<Character> characters = new HashSet<>(asList('0', '1'));
@Nonnull
@Override
public String getJsclPrefix() {
return "0b:";
}
@Nonnull
@Override
public Set<Character> getAcceptableCharacters() {
return characters;
}
};
public final int radix;
public final int groupingSize;
NumeralBase(int radix, int groupingSize) {
this.radix = radix;
this.groupingSize = groupingSize;
}
@Nullable
public static NumeralBase getByPrefix(@Nonnull String prefix) {
for (NumeralBase nb : NumeralBase.values()) {
if (prefix.equals(nb.getJsclPrefix())) {
return nb;
}
}
return null;
}
@Nonnull
protected static String toString(@Nonnull Double value, int radix, int fractionDigits) {
final BigDecimal mult = BigDecimal.valueOf(radix).pow(fractionDigits);
final BigDecimal bd = BigDecimal.valueOf(value).multiply(mult);
final BigInteger bi = bd.toBigInteger();
final StringBuilder result = new StringBuilder(bi.toString(radix));
while (result.length() < fractionDigits + 1) { // +1 for leading zero
result.insert(0, "0");
}
result.insert(result.length() - fractionDigits, ".");
return result.toString().toUpperCase();
}
@Nonnull
public Double toDouble(@Nonnull String doubleString) throws NumberFormatException {
return Double.longBitsToDouble(Long.valueOf(doubleString, radix));
}
@Nonnull
public Integer toInteger(@Nonnull String integerString) throws NumberFormatException {
return Integer.valueOf(integerString, radix);
}
@Nonnull
public JsclInteger toJsclInteger(@Nonnull String integerString) throws NumberFormatException {
return new JsclInteger(toBigInteger(integerString));
}
@Nonnull
public BigInteger toBigInteger(@Nonnull String value) throws NumberFormatException {
return new BigInteger(value, radix);
}
public String toString(@Nonnull BigInteger value) {
return value.toString(radix).toUpperCase();
}
public String toString(@Nonnull Integer value) {
return Integer.toString(value, radix).toUpperCase();
}
@Nonnull
public abstract String getJsclPrefix();
@Nonnull
public abstract Set<Character> getAcceptableCharacters();
public int getGroupingSize() {
return groupingSize;
}
@Nonnull
public String toString(@Nonnull Double value, int fractionDigits) {
return toString(value, radix, fractionDigits);
}
}