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.examples.jmh.descriptive; 18 19 import java.math.BigInteger; 20 import java.nio.ByteBuffer; 21 import org.apache.commons.numbers.core.DD; 22 23 /** 24 * A 96-bit unsigned integer. 25 * 26 * <p>This is a copy of {@code o.a.c.statistics.descriptive.Int96} to allow benchmarking. 27 * Additional methods may have been added for comparative benchmarks. 28 * 29 * <p>This is a specialised class to implement an accumulator of {@code long} values 30 * generated by squaring {@code int} values from an array (max observations=2^31). 31 * 32 * @since 1.1 33 */ 34 final class UInt96 { 35 /** Mask for the lower 32-bits of a long. */ 36 private static final long MASK32 = 0xffff_ffffL; 37 38 // Low data is stored using an integer to allow efficient sum-with-carry addition 39 40 /** bits 32-1 (low 32-bits). */ 41 private int c; 42 /** bits 96-33. */ 43 private long ab; 44 45 /** 46 * Create an instance. 47 */ 48 private UInt96() { 49 // No-op 50 } 51 52 /** 53 * Create an instance. 54 * 55 * @param x Value. 56 */ 57 private UInt96(long x) { 58 c = (int) x; 59 ab = (int) (x >>> Integer.SIZE); 60 } 61 62 /** 63 * Create an instance using a direct binary representation. 64 * This is package-private for testing. 65 * 66 * @param hi High 64-bits. 67 * @param lo Low 32-bits. 68 */ 69 UInt96(long hi, int lo) { 70 this.c = lo; 71 this.ab = hi; 72 } 73 74 /** 75 * Create an instance. The initial value is zero. 76 * 77 * @return the instance 78 */ 79 static UInt96 create() { 80 return new UInt96(); 81 } 82 83 /** 84 * Create an instance of the {@code long} value. 85 * The value is assumed to be an unsigned 64-bit integer. 86 * 87 * @param x Value (must be positive). 88 * @return the instance 89 */ 90 static UInt96 of(long x) { 91 return new UInt96(x); 92 } 93 94 /** 95 * Adds the value. It is assumed to be positive, for example the square of an 96 * {@code int} value. However no check is performed for a negative value. 97 * 98 * <p>Note: This addition handles {@value Long#MIN_VALUE} as an unsigned 99 * value of 2^63. 100 * 101 * @param x Value. 102 */ 103 void addPositive(long x) { 104 // Sum with carry. 105 // Assuming x is positive then x + lo will not overflow 64-bits 106 // so we do not have to split x into upper and lower 32-bit values. 107 final long s = x + (c & MASK32); 108 c = (int) s; 109 ab += s >>> Integer.SIZE; 110 } 111 112 /** 113 * Adds the value. 114 * 115 * @param x Value. 116 */ 117 void add(UInt96 x) { 118 // Avoid issues adding to itself 119 final int cc = x.c; 120 final long aabb = x.ab; 121 // Sum with carry. 122 final long s = (cc & MASK32) + (c & MASK32); 123 c = (int) s; 124 ab += (s >>> Integer.SIZE) + aabb; 125 } 126 127 /** 128 * Convert to a BigInteger. 129 * 130 * @return the value 131 */ 132 BigInteger toBigInteger() { 133 if (ab != 0) { 134 final ByteBuffer bb = ByteBuffer.allocate(Integer.BYTES * 3) 135 .putLong(ab) 136 .putInt(c); 137 return new BigInteger(1, bb.array()); 138 } 139 return BigInteger.valueOf(c & MASK32); 140 } 141 142 /** 143 * Convert to a double-double. 144 * 145 * @return the value 146 */ 147 DD toDD() { 148 // Sum low to high 149 return DD.ofSum(c & MASK32, (ab & MASK32) * 0x1.0p32) 150 .add((ab >>> Integer.SIZE) * 0x1.0p64); 151 } 152 153 /** 154 * Return the lower 32-bits as an {@code int} value. 155 * 156 * @return bits 32-1 157 */ 158 int lo32() { 159 return c; 160 } 161 162 /** 163 * Return the higher 64-bits as a {@code long} value. 164 * 165 * @return bits 96-33 166 */ 167 long hi64() { 168 return ab; 169 } 170 }