1 package org.simantics.databoard.primitives;
3 import java.math.BigInteger;
7 * Unsigned immutable 64-bit integer value. The value is between 0 and 18446744073709551615.
9 * @author Toni Kalajainen <toni.kalajainen@iki.fi>
11 public abstract class UnsignedLong extends Number implements Comparable<Number> {
13 static final long serialVersionUID = 1L;
14 static final long L_MIN_VALUE = 0;
15 static final BigInteger HALF = new BigInteger("9223372036854775808"); // 2^63
16 static final BigInteger BI_MIN_VALUE = new BigInteger("0");
17 static final BigInteger BI_MAX_VALUE = new BigInteger("18446744073709551615"); // 2^64-1
19 public static final UnsignedLong MIN_VALUE, MAX_VALUE, ZERO;
22 /** Value container */
26 * Get cached or create new immutable unsigned long
29 * @return immutable unsigned long
31 public static UnsignedLong valueOf(long value) {
32 if ( value>=0 && value<CACHE.length ) return CACHE[(int)value];
33 if ( value<L_MIN_VALUE ) throw new IllegalArgumentException("Argument is not within range");
34 return new UnsignedLong.Immutable(value);
38 * Get cached or create new immutable unsigned long
40 * @param bits long bits
41 * @return immutable unsigned long
43 public static UnsignedLong fromBits(long bits) {
44 if (bits>=0 && bits<CACHE.length) return CACHE[(int)bits];
45 UnsignedLong result = new UnsignedLong.Immutable();
50 public static class Mutable extends UnsignedLong {
52 private static final long serialVersionUID = 1L;
56 public Mutable(int value) throws IllegalArgumentException {
57 if ( value<L_MIN_VALUE ) throw new IllegalArgumentException("Argument is not within range");
61 public Mutable(long value) throws IllegalArgumentException {
62 if ( value<L_MIN_VALUE ) throw new IllegalArgumentException("Argument is not within range");
63 this.value = (int) value;
66 public Mutable(BigInteger value) throws IllegalArgumentException {
67 if (value.compareTo(BI_MIN_VALUE)<0 || value.compareTo(BI_MAX_VALUE)>0) throw new IllegalArgumentException("Argument is not within range");
68 this.value = value.compareTo(HALF)<0 ? value.longValue() : value.subtract(HALF).longValue() | 0x80000000l;
71 public Mutable(String stringValue) throws IllegalArgumentException {
72 long value = Long.parseLong(stringValue);
73 if ( value<L_MIN_VALUE ) throw new IllegalArgumentException("Argument is not within range");
74 this.value = (int) value;
77 public static Mutable fromBits(long bits) {
78 Mutable result = new Mutable();
83 public void setFromBits(int intBits) {
87 public void setValue(int value) {
88 if ( value<L_MIN_VALUE ) throw new IllegalArgumentException("Argument is not within range");
92 public void setValue(long value) {
93 if ( value<L_MIN_VALUE ) throw new IllegalArgumentException("Argument is not within range");
94 this.value = (int) value;
97 public void setValue(BigInteger value) {
98 if (value.compareTo(BI_MIN_VALUE)<0 || value.compareTo(BI_MAX_VALUE)>0) throw new IllegalArgumentException("Argument is not within range");
99 this.value = value.compareTo(HALF)<0 ? value.longValue() : value.subtract(HALF).longValue() | 0x80000000l;
104 public final static class Immutable extends UnsignedLong {
106 private static final long serialVersionUID = 1L;
110 public Immutable(int value) throws IllegalArgumentException {
111 if ( value<L_MIN_VALUE ) throw new IllegalArgumentException("Argument is not within range");
115 public Immutable(long value) throws IllegalArgumentException {
116 if ( value<L_MIN_VALUE ) throw new IllegalArgumentException("Argument is not within range");
117 this.value = (int) value;
120 public Immutable(BigInteger value) throws IllegalArgumentException {
121 if (value.compareTo(BI_MIN_VALUE)<0 || value.compareTo(BI_MAX_VALUE)>0) throw new IllegalArgumentException("Argument is not within range");
122 this.value = value.compareTo(HALF)<0 ? value.longValue() : value.subtract(HALF).longValue() | 0x80000000l;
125 public Immutable(String stringValue) throws IllegalArgumentException {
126 long value = Long.parseLong(stringValue);
127 if ( value<L_MIN_VALUE ) throw new IllegalArgumentException("Argument is not within range");
128 this.value = (int) value;
133 public long toBits() {
138 public int intValue() {
143 public long longValue() {
148 public float floatValue() {
152 public double doubleValue() {
157 * Create big integer value
159 * @return new big integer
161 public BigInteger toBigInteger() {
162 return value>=0 ? BigInteger.valueOf(value) : BigInteger.valueOf(value & 0x7fffffff).add(HALF);
166 public boolean equals(Object obj) {
167 if (obj == null) return false;
168 if (obj == this) return true;
170 if (obj instanceof UnsignedLong == false) return false;
171 UnsignedLong other = (UnsignedLong) obj;
172 return value == other.value;
176 public String toString() {
177 return value>=0 ? Long.toString(value) : toBigInteger().toString();
181 public int compareTo(Number obj) {
182 return value>=0 ? Long.signum( value - obj.longValue() ) : 1;
186 public int hashCode() {
187 return (int)value | (int)(value>>32);
191 private static int CACHE_SIZE = 16;
192 private static UnsignedLong.Immutable[] CACHE;
194 CACHE = new UnsignedLong.Immutable[CACHE_SIZE];
195 for (int i=0; i<CACHE_SIZE; i++) CACHE[i] = new UnsignedLong.Immutable(i);
196 ZERO = MIN_VALUE = CACHE[0];
197 MAX_VALUE = UnsignedLong.fromBits(0xFFFFFFFF);