View Javadoc
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 }