1*c8dee2aaSAndroid Build Coastguard Worker // Copyright 2023 Google LLC
2*c8dee2aaSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
3*c8dee2aaSAndroid Build Coastguard Worker
4*c8dee2aaSAndroid Build Coastguard Worker #include "modules/bentleyottmann/include/Int96.h"
5*c8dee2aaSAndroid Build Coastguard Worker
6*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
7*c8dee2aaSAndroid Build Coastguard Worker #include <tuple>
8*c8dee2aaSAndroid Build Coastguard Worker
9*c8dee2aaSAndroid Build Coastguard Worker namespace bentleyottmann {
10*c8dee2aaSAndroid Build Coastguard Worker
Make(int32_t a)11*c8dee2aaSAndroid Build Coastguard Worker Int96 Int96::Make(int32_t a) {
12*c8dee2aaSAndroid Build Coastguard Worker return {a >= 0 ? 0 : -1, (uint32_t)a};
13*c8dee2aaSAndroid Build Coastguard Worker }
14*c8dee2aaSAndroid Build Coastguard Worker
Make(int64_t a)15*c8dee2aaSAndroid Build Coastguard Worker Int96 Int96::Make(int64_t a) {
16*c8dee2aaSAndroid Build Coastguard Worker return {a >> 32, (uint32_t)(a & 0xFFFFFFFF)};
17*c8dee2aaSAndroid Build Coastguard Worker }
18*c8dee2aaSAndroid Build Coastguard Worker
operator ==(const Int96 & a,const Int96 & b)19*c8dee2aaSAndroid Build Coastguard Worker bool operator== (const Int96& a, const Int96& b) {
20*c8dee2aaSAndroid Build Coastguard Worker return std::tie(a.hi, a.lo) == std::tie(b.hi, b.lo);
21*c8dee2aaSAndroid Build Coastguard Worker }
22*c8dee2aaSAndroid Build Coastguard Worker
operator <(const Int96 & a,const Int96 & b)23*c8dee2aaSAndroid Build Coastguard Worker bool operator< (const Int96& a, const Int96& b) {
24*c8dee2aaSAndroid Build Coastguard Worker return std::tie(a.hi, a.lo) < std::tie(b.hi, b.lo);
25*c8dee2aaSAndroid Build Coastguard Worker }
26*c8dee2aaSAndroid Build Coastguard Worker
operator +(const Int96 & a,const Int96 & b)27*c8dee2aaSAndroid Build Coastguard Worker Int96 operator+ (const Int96& a, const Int96& b) {
28*c8dee2aaSAndroid Build Coastguard Worker uint32_t lo = a.lo + b.lo;
29*c8dee2aaSAndroid Build Coastguard Worker int64_t carry = lo < a.lo;
30*c8dee2aaSAndroid Build Coastguard Worker int64_t hi = a.hi + b.hi + carry;
31*c8dee2aaSAndroid Build Coastguard Worker return {hi, lo};
32*c8dee2aaSAndroid Build Coastguard Worker }
33*c8dee2aaSAndroid Build Coastguard Worker
34*c8dee2aaSAndroid Build Coastguard Worker
35*c8dee2aaSAndroid Build Coastguard Worker // Multiply a 64-bit int and a 32-bit int producing a 96-bit int.
36*c8dee2aaSAndroid Build Coastguard Worker // This proceeds in two multiplies.
37*c8dee2aaSAndroid Build Coastguard Worker // 1 - unsigned multiply of the low 32-bits of a and the 32-bits of b. Using an unsigned
38*c8dee2aaSAndroid Build Coastguard Worker // multiply for the lower 32-bits requires a compensation if b is actually negative. The lower
39*c8dee2aaSAndroid Build Coastguard Worker // bits of a are subtracted from the upper 64-bits of the result.
40*c8dee2aaSAndroid Build Coastguard Worker // 2 - signed multiply of the upper 32-bits of a and the 32-bits of b.
multiply(int64_t a,int32_t b)41*c8dee2aaSAndroid Build Coastguard Worker Int96 multiply(int64_t a, int32_t b) {
42*c8dee2aaSAndroid Build Coastguard Worker // Multiply the low 32-bits generating a 64-bit lower part.
43*c8dee2aaSAndroid Build Coastguard Worker uint64_t loA = a & 0xFFFFFFFF;
44*c8dee2aaSAndroid Build Coastguard Worker uint64_t loB = (uint32_t)b;
45*c8dee2aaSAndroid Build Coastguard Worker uint64_t newLo = loA * loB;
46*c8dee2aaSAndroid Build Coastguard Worker
47*c8dee2aaSAndroid Build Coastguard Worker // Multiply the upper bits 32-bits of a and b resulting in the hi 64-bits of the Int96.
48*c8dee2aaSAndroid Build Coastguard Worker int64_t newHi = (a >> 32) * (int64_t)b;
49*c8dee2aaSAndroid Build Coastguard Worker
50*c8dee2aaSAndroid Build Coastguard Worker // Calculate the overflow into the upper 32-bits.
51*c8dee2aaSAndroid Build Coastguard Worker // Remember that newLo is unsigned so will be zero filled by the shift.
52*c8dee2aaSAndroid Build Coastguard Worker int64_t lowOverflow = newLo >> 32;
53*c8dee2aaSAndroid Build Coastguard Worker
54*c8dee2aaSAndroid Build Coastguard Worker // Add overflow from the low multiply into hi.
55*c8dee2aaSAndroid Build Coastguard Worker newHi += lowOverflow;
56*c8dee2aaSAndroid Build Coastguard Worker
57*c8dee2aaSAndroid Build Coastguard Worker // Compensate for the negative b in the calculation of newLo by subtracting out 2^32 * a.
58*c8dee2aaSAndroid Build Coastguard Worker if (b < 0) {
59*c8dee2aaSAndroid Build Coastguard Worker newHi -= loA;
60*c8dee2aaSAndroid Build Coastguard Worker }
61*c8dee2aaSAndroid Build Coastguard Worker
62*c8dee2aaSAndroid Build Coastguard Worker return {newHi, (uint32_t)newLo};
63*c8dee2aaSAndroid Build Coastguard Worker }
64*c8dee2aaSAndroid Build Coastguard Worker
multiply(int32_t a,int64_t b)65*c8dee2aaSAndroid Build Coastguard Worker Int96 multiply(int32_t a, int64_t b) {
66*c8dee2aaSAndroid Build Coastguard Worker return multiply(b, a);
67*c8dee2aaSAndroid Build Coastguard Worker }
68*c8dee2aaSAndroid Build Coastguard Worker
69*c8dee2aaSAndroid Build Coastguard Worker } // namespace bentleyottmann
70