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