1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.statistics.descriptive;
18
19 import java.math.BigInteger;
20 import java.nio.ByteBuffer;
21
22 /**
23 * A mutable 128-bit unsigned integer.
24 *
25 * <p>This is a specialised class to implement an accumulator of {@code long} values
26 * generated by squaring {@code int} values.
27 *
28 * @since 1.1
29 */
30 final class UInt128 {
31 /** Mask for the lower 32-bits of a long. */
32 private static final long MASK32 = 0xffff_ffffL;
33
34 // Data is stored using integers to allow efficient sum-with-carry addition
35
36 /** bits 32-1 (low 32-bits). */
37 private int d;
38 /** bits 64-33. */
39 private int c;
40 /** bits 128-65. */
41 private long ab;
42
43 /**
44 * Create an instance.
45 */
46 private UInt128() {
47 // No-op
48 }
49
50 /**
51 * Create an instance using a direct binary representation.
52 *
53 * @param hi High 64-bits.
54 * @param mid Middle 32-bits.
55 * @param lo Low 32-bits.
56 */
57 private UInt128(long hi, int mid, int lo) {
58 this.d = lo;
59 this.c = mid;
60 this.ab = hi;
61 }
62
63 /**
64 * Create an instance using a direct binary representation.
65 * This is package-private for testing.
66 *
67 * @param hi High 64-bits.
68 * @param lo Low 64-bits.
69 */
70 UInt128(long hi, long lo) {
71 this.d = (int) lo;
72 this.c = (int) (lo >>> Integer.SIZE);
73 this.ab = hi;
74 }
75
76 /**
77 * Create an instance. The initial value is zero.
78 *
79 * @return the instance
80 */
81 static UInt128 create() {
82 return new UInt128();
83 }
84
85 /**
86 * Create an instance of the {@code UInt96} value.
87 *
88 * @param x Value.
89 * @return the instance
90 */
91 static UInt128 of(UInt96 x) {
92 final int lo = x.lo32();
93 final long hi = x.hi64();
94 final UInt128 y = new UInt128();
95 y.d = lo;
96 y.c = (int) hi;
97 y.ab = hi >>> Integer.SIZE;
98 return y;
99 }
100
101 /**
102 * Adds the value in place. It is assumed to be positive, for example the square of an
103 * {@code int} value. However no check is performed for a negative value.
104 *
105 * <p>Note: This addition handles {@value Long#MIN_VALUE} as an unsigned
106 * value of 2^63.
107 *
108 * @param x Value.
109 */
110 void addPositive(long x) {
111 // Sum with carry.
112 // Assuming x is positive then x + lo will not overflow 64-bits
113 // so we do not have to split x into upper and lower 32-bit values.
114 long s = x + (d & MASK32);
115 d = (int) s;
116 s = (s >>> Integer.SIZE) + (c & MASK32);
117 c = (int) s;
118 ab += s >>> Integer.SIZE;
119 }
120
121 /**
122 * Adds the value in-place.
123 *
124 * @param x Value.
125 */
126 void add(UInt128 x) {
127 // Avoid issues adding to itself
128 final int dd = x.d;
129 final int cc = x.c;
130 final long aabb = x.ab;
131 // Sum with carry.
132 long s = (dd & MASK32) + (d & MASK32);
133 d = (int) s;
134 s = (s >>> Integer.SIZE) + (cc & MASK32) + (c & MASK32);
135 c = (int) s;
136 ab += (s >>> Integer.SIZE) + aabb;
137 }
138
139 /**
140 * Multiply by the unsigned value.
141 * Any overflow bits are lost.
142 *
143 * @param x Value.
144 * @return the product
145 */
146 UInt128 unsignedMultiply(int x) {
147 final long xx = x & MASK32;
148 // Multiply with carry.
149 long product = xx * (d & MASK32);
150 final int dd = (int) product;
151 product = (product >>> Integer.SIZE) + xx * (c & MASK32);
152 final int cc = (int) product;
153 // Possible overflow here and bits are lost
154 final long aabb = (product >>> Integer.SIZE) + xx * ab;
155 return new UInt128(aabb, cc, dd);
156 }
157
158 /**
159 * Subtracts the value.
160 * Any overflow bits (negative result) are lost.
161 *
162 * @param x Value.
163 * @return the difference
164 */
165 UInt128 subtract(UInt128 x) {
166 // Difference with carry.
167 long diff = (d & MASK32) - (x.d & MASK32);
168 final int dd = (int) diff;
169 diff = (diff >> Integer.SIZE) + (c & MASK32) - (x.c & MASK32);
170 final int cc = (int) diff;
171 // Possible overflow here and bits are lost containing info on the
172 // magnitude of the true negative value
173 final long aabb = (diff >> Integer.SIZE) + ab - x.ab;
174 return new UInt128(aabb, cc, dd);
175 }
176
177 /**
178 * Convert to a BigInteger.
179 *
180 * @return the value
181 */
182 BigInteger toBigInteger() {
183 // Test if we have more than 63-bits
184 if (ab != 0 || c < 0) {
185 return new BigInteger(1, ByteBuffer.allocate(Integer.BYTES * 4)
186 .putLong(ab)
187 .putInt(c)
188 .putInt(d).array());
189 }
190 // Create from a long
191 return BigInteger.valueOf(lo64());
192 }
193
194 /**
195 * Convert to a {@code double}.
196 *
197 * @return the value
198 */
199 double toDouble() {
200 return IntMath.uint128ToDouble(hi64(), lo64());
201 }
202
203 /**
204 * Convert to an {@code int}; throwing an exception if the value overflows an {@code int}.
205 *
206 * @return the value
207 * @throws ArithmeticException if the value overflows an {@code int}.
208 * @see Math#toIntExact(long)
209 */
210 int toIntExact() {
211 return Math.toIntExact(toLongExact());
212 }
213
214 /**
215 * Convert to a {@code long}; throwing an exception if the value overflows a {@code long}.
216 *
217 * @return the value
218 * @throws ArithmeticException if the value overflows a {@code long}.
219 */
220 long toLongExact() {
221 // Test if we have more than 63-bits
222 if (ab != 0 || c < 0) {
223 throw new ArithmeticException("long integer overflow");
224 }
225 return lo64();
226 }
227
228 /**
229 * Return the lower 64-bits as a {@code long} value.
230 *
231 * @return bits 64-1
232 */
233 long lo64() {
234 return (d & MASK32) | ((c & MASK32) << Integer.SIZE);
235 }
236
237 /**
238 * Return the low 32-bits as an {@code int} value.
239 *
240 * @return bits 32-1
241 */
242 int lo32() {
243 return d;
244 }
245
246 /**
247 * Return the middle 32-bits as an {@code int} value.
248 *
249 * @return bits 64-33
250 */
251 int mid32() {
252 return c;
253 }
254
255 /**
256 * Return the higher 64-bits as a {@code long} value.
257 *
258 * @return bits 128-65
259 */
260 long hi64() {
261 return ab;
262 }
263 }