blob: 469ec39962ef3c9badaa1a2d3abd02207e1d32b4 [file] [log] [blame]
// Copyright 2023 Google LLC
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
#include "modules/bentleyottmann/include/Int96.h"
#include <cstdint>
#include <tuple>
namespace bentleyottmann {
Int96 Int96::Make(int32_t a) {
return {a >= 0 ? 0 : -1, (uint32_t)a};
}
Int96 Int96::Make(int64_t a) {
return {a >> 32, (uint32_t)(a & 0xFFFFFFFF)};
}
bool operator== (const Int96& a, const Int96& b) {
return std::tie(a.hi, a.lo) == std::tie(b.hi, b.lo);
}
bool operator< (const Int96& a, const Int96& b) {
return std::tie(a.hi, a.lo) < std::tie(b.hi, b.lo);
}
Int96 operator+ (const Int96& a, const Int96& b) {
uint32_t lo = a.lo + b.lo;
int64_t carry = lo < a.lo;
int64_t hi = a.hi + b.hi + carry;
return {hi, lo};
}
// Multiply a 64-bit int and a 32-bit int producing a 96-bit int.
// This proceeds in two multiplies.
// 1 - unsigned multiply of the low 32-bits of a and the 32-bits of b. Using an unsigned
// multiply for the lower 32-bits requires a compensation if b is actually negative. The lower
// bits of a are subtracted from the upper 64-bits of the result.
// 2 - signed multiply of the upper 32-bits of a and the 32-bits of b.
Int96 multiply(int64_t a, int32_t b) {
// Multiply the low 32-bits generating a 64-bit lower part.
uint64_t loA = a & 0xFFFFFFFF;
uint64_t loB = (uint32_t)b;
uint64_t newLo = loA * loB;
// Multiply the upper bits 32-bits of a and b resulting in the hi 64-bits of the Int96.
int64_t newHi = (a >> 32) * (int64_t)b;
// Calculate the overflow into the upper 32-bits.
// Remember that newLo is unsigned so will be zero filled by the shift.
int64_t lowOverflow = newLo >> 32;
// Add overflow from the low multiply into hi.
newHi += lowOverflow;
// Compensate for the negative b in the calculation of newLo by subtracting out 2^32 * a.
if (b < 0) {
newHi -= loA;
}
return {newHi, (uint32_t)newLo};
}
Int96 multiply(int32_t a, int64_t b) {
return multiply(b, a);
}
} // namespace bentleyottmann