/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.hadoop.examples.pi.math; import java.math.BigInteger; /** Support 124-bit integer arithmetic. */ class LongLong { static final int BITS_PER_LONG = 62; static final int MID = BITS_PER_LONG >> 1; static final int SIZE = BITS_PER_LONG << 1; static final long FULL_MASK = (1L << BITS_PER_LONG) - 1; static final long LOWER_MASK = FULL_MASK >>> MID; static final long UPPER_MASK = LOWER_MASK << MID; private long d0; private long d1; /** Set the values. */ LongLong set(long d0, long d1) { this.d0 = d0; this.d1 = d1; return this; } /** And operation (&). */ long and(long mask) { return d0 & mask; } /** Shift right operation (<<). */ long shiftRight(int n) { return (d1 << (BITS_PER_LONG - n)) + (d0 >>> n); } /** Plus equal operation (+=). */ LongLong plusEqual(LongLong that) { this.d0 += that.d0; this.d1 += that.d1; return this; } /** Convert this to a BigInteger. */ BigInteger toBigInteger() { return BigInteger.valueOf(d1).shiftLeft(BITS_PER_LONG).add(BigInteger.valueOf(d0)); } /** {@inheritDoc} */ @Override public String toString() { final int remainder = BITS_PER_LONG % 4; return String.format("%x*2^%d + %016x", d1<<remainder, BITS_PER_LONG-remainder, d0); } /** Compute a*b and store the result to r. * @return r */ static LongLong multiplication(final LongLong r, final long a, final long b) { /* final long x0 = a & LOWER_MASK; final long x1 = (a & UPPER_MASK) >> MID; final long y0 = b & LOWER_MASK; final long y1 = (b & UPPER_MASK) >> MID; final long t = (x0 + x1)*(y0 + y1); final long u = (x0 - x1)*(y0 - y1); final long v = x1*y1; final long tmp = (t - u)>>>1; result.d0 = ((t + u)>>>1) - v + ((tmp << MID) & FULL_MASK);; result.d1 = v + (tmp >> MID); return result; */ final long a_lower = a & LOWER_MASK; final long a_upper = (a & UPPER_MASK) >> MID; final long b_lower = b & LOWER_MASK; final long b_upper = (b & UPPER_MASK) >> MID; final long tmp = a_lower*b_upper + a_upper*b_lower; r.d0 = a_lower*b_lower + ((tmp << MID) & FULL_MASK); r.d1 = a_upper*b_upper + (tmp >> MID); return r; } }