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 import org.apache.commons.numbers.core.DD;
22
23 /**
24 * A mutable 128-bit signed integer.
25 *
26 * <p>This is a specialised class to implement an accumulator of {@code long} values.
27 *
28 * <p>Note: This number uses a signed long integer representation of:
29 *
30 * <pre>value = 2<sup>64</sup> * hi64 + lo64</pre>
31 *
32 * <p>If the high value is zero then the low value is the long representation of the
33 * number including the sign bit. Otherwise the low value corresponds to a correction
34 * term for the scaled high value which contains the sign-bit of the number.
35 *
36 * @since 1.1
37 */
38 final class Int128 {
39 /** Mask for the lower 32-bits of a long. */
40 private static final long MASK32 = 0xffff_ffffL;
41 /** 2^53. */
42 private static final long TWO_POW_53 = 1L << 53;
43
44 /** low 64-bits. */
45 private long lo;
46 /** high 64-bits. */
47 private long hi;
48
49 /**
50 * Create an instance.
51 */
52 private Int128() {
53 // No-op
54 }
55
56 /**
57 * Create an instance.
58 *
59 * @param x Value.
60 */
61 private Int128(long x) {
62 lo = x;
63 }
64
65 /**
66 * Create an instance using a direct binary representation.
67 * This is package-private for testing.
68 *
69 * @param hi High 64-bits.
70 * @param lo Low 64-bits.
71 */
72 Int128(long hi, long lo) {
73 this.lo = lo;
74 this.hi = hi;
75 }
76
77 /**
78 * Create an instance. The initial value is zero.
79 *
80 * @return the instance
81 */
82 static Int128 create() {
83 return new Int128();
84 }
85
86 /**
87 * Create an instance of the {@code long} value.
88 *
89 * @param x Value.
90 * @return the instance
91 */
92 static Int128 of(long x) {
93 return new Int128(x);
94 }
95
96 /**
97 * Adds the value.
98 *
99 * @param x Value.
100 */
101 void add(long x) {
102 final long y = lo;
103 final long r = y + x;
104 // Overflow if the result has the opposite sign of both arguments
105 // (+,+) -> -
106 // (-,-) -> +
107 // Detect opposite sign:
108 if (((y ^ r) & (x ^ r)) < 0) {
109 // Carry overflow bit
110 hi += x < 0 ? -1 : 1;
111 }
112 lo = r;
113 }
114
115 /**
116 * Adds the value.
117 *
118 * @param x Value.
119 */
120 void add(Int128 x) {
121 // Avoid issues adding to itself
122 final long l = x.lo;
123 final long h = x.hi;
124 add(l);
125 hi += h;
126 }
127
128 /**
129 * Compute the square of the low 64-bits of this number.
130 *
131 * <p>Warning: This ignores the upper 64-bits. Use with caution.
132 *
133 * @return the square
134 */
135 UInt128 squareLow() {
136 final long x = lo;
137 final long upper = IntMath.squareHigh(x);
138 return new UInt128(upper, x * x);
139 }
140
141 /**
142 * Convert to a BigInteger.
143 *
144 * @return the value
145 */
146 BigInteger toBigInteger() {
147 long h = hi;
148 long l = lo;
149 // Special cases
150 if (h == 0) {
151 return BigInteger.valueOf(l);
152 }
153 if (l == 0) {
154 return BigInteger.valueOf(h).shiftLeft(64);
155 }
156
157 // The representation is 2^64 * hi64 + lo64.
158 // Here we avoid evaluating the addition:
159 // BigInteger.valueOf(l).add(BigInteger.valueOf(h).shiftLeft(64))
160 // It is faster to create from bytes.
161 // BigInteger bytes are an unsigned integer in BigEndian format, plus a sign.
162 // If both values are positive we can use the values unchanged.
163 // Otherwise selective negation is used to create a positive magnitude
164 // and we track the sign.
165 // Note: Negation of -2^63 is valid to create an unsigned 2^63.
166
167 int sign = 1;
168 if ((h ^ l) < 0) {
169 // Opposite signs and lo64 is not zero.
170 // The lo64 bits are an adjustment to the magnitude of hi64
171 // to make it smaller.
172 // Here we rearrange to [2^64 * (hi64-1)] + [2^64 - lo64].
173 // The second term [2^64 - lo64] can use lo64 as an unsigned 64-bit integer.
174 // The first term [2^64 * (hi64-1)] does not work if low is zero.
175 // It would work if zero was detected and we carried the overflow
176 // bit up to h to make it equal to: (h - 1) + 1 == h.
177 // Instead lo64 == 0 is handled as a special case above.
178
179 if (h >= 0) {
180 // Treat (unchanged) low as an unsigned add
181 h = h - 1;
182 } else {
183 // As above with negation
184 h = ~h; // -h - 1
185 l = -l;
186 sign = -1;
187 }
188 } else if (h < 0) {
189 // Invert negative values to create the equivalent positive magnitude.
190 h = -h;
191 l = -l;
192 sign = -1;
193 }
194
195 return new BigInteger(sign,
196 ByteBuffer.allocate(Long.BYTES * 2)
197 .putLong(h).putLong(l).array());
198 }
199
200 /**
201 * Convert to a {@code double}.
202 *
203 * @return the value
204 */
205 double toDouble() {
206 long h = hi;
207 long l = lo;
208 // Special cases
209 if (h == 0) {
210 return l;
211 }
212 if (l == 0) {
213 return h * 0x1.0p64;
214 }
215 // Both h and l are non-zero and can be negated to a positive magnitude.
216 // Use the same logic as toBigInteger to create magnitude (h, l) and a sign.
217 int sign = 1;
218 if ((h ^ l) < 0) {
219 // Here we rearrange to [2^64 * (hi64-1)] + [2^64 - lo64].
220 if (h >= 0) {
221 h = h - 1;
222 } else {
223 // As above with negation
224 h = ~h; // -h - 1
225 l = -l;
226 sign = -1;
227 }
228 } else if (h < 0) {
229 // Invert negative values to create the equivalent positive magnitude.
230 h = -h;
231 l = -l;
232 sign = -1;
233 }
234 final double x = IntMath.uint128ToDouble(h, l);
235 return sign < 0 ? -x : x;
236 }
237
238 /**
239 * Convert to a double-double.
240 *
241 * @return the value
242 */
243 DD toDD() {
244 // Don't combine two 64-bit DD numbers:
245 // DD.of(hi).scalb(64).add(DD.of(lo))
246 // It is more accurate to create a 96-bit number and add the final 32-bits.
247 // Sum low to high.
248 // Note: Masking a negative hi number will create a small positive magnitude
249 // to add to a larger negative number:
250 // e.g. x = (x & 0xff) + ((x >> 8) << 8)
251 return DD.of(lo).add((hi & MASK32) * 0x1.0p64).add((hi >> Integer.SIZE) * 0x1.0p96);
252 }
253
254 /**
255 * Divide by the count {@code n}, returning the value as a {@code double}.
256 *
257 * @param n Count.
258 * @return the quotient
259 */
260 double divideToDouble(long n) {
261 final DD a = toDD();
262 if (n < TWO_POW_53) {
263 // n is a representable double
264 return a.divide(n).doubleValue();
265 }
266 // Extended precision divide when n > 2^53
267 return a.divide(DD.of(n)).doubleValue();
268 }
269
270 /**
271 * Convert to an {@code int}; throwing an exception if the value overflows an {@code int}.
272 *
273 * @return the value
274 * @throws ArithmeticException if the value overflows an {@code int}.
275 * @see Math#toIntExact(long)
276 */
277 int toIntExact() {
278 return Math.toIntExact(toLongExact());
279 }
280
281 /**
282 * Convert to a {@code long}; throwing an exception if the value overflows a {@code long}.
283 *
284 * @return the value
285 * @throws ArithmeticException if the value overflows a {@code long}.
286 */
287 long toLongExact() {
288 if (hi != 0) {
289 throw new ArithmeticException("long integer overflow");
290 }
291 return lo;
292 }
293
294 /**
295 * Return the lower 64-bits as a {@code long} value.
296 *
297 * <p>If the high value is zero then the low value is the long representation of the
298 * number including the sign bit. Otherwise this value corresponds to a correction
299 * term for the scaled high value which contains the sign-bit of the number
300 * (see {@link Int128}).
301 *
302 * @return the low 64-bits
303 */
304 long lo64() {
305 return lo;
306 }
307
308 /**
309 * Return the higher 64-bits as a {@code long} value.
310 *
311 * @return the high 64-bits
312 * @see #lo64()
313 */
314 long hi64() {
315 return hi;
316 }
317 }