24#if !defined(__SIZEOF_INT128__)
27#include <boost/multiprecision/cpp_int.hpp>
54#if defined(__SIZEOF_INT128__)
64using int128 = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<
65 127, 127, boost::multiprecision::signed_magnitude, boost::multiprecision::unchecked,
void>>;
68#if defined(__SIZEOF_INT128__)
80 __uint128_t magnitude = value < 0 ? -
static_cast<__uint128_t
>(value)
81 :
static_cast<__uint128_t
>(value);
83 char* first = digits +
sizeof(digits) - 1;
86 *--first =
static_cast<char>(
'0' +
static_cast<int>(magnitude % 10));
88 }
while (magnitude != 0);
92 return stream << first;
106inline std::istream& operator>>(std::istream& stream,
int128& value) {
107 std::istream::sentry sentry(stream);
112 int c = stream.peek();
113 if (c ==
'+' || c ==
'-') {
118 if (c <
'0' || c >
'9') {
119 stream.setstate(std::ios::failbit);
124 __uint128_t result = 0;
125 for (; c >=
'0' && c <=
'9'; c = stream.peek()) {
127 result = result * 10 +
static_cast<unsigned>(c -
'0');
129 value =
static_cast<int128>(neg ? -result : result);
136#if !defined(__SIZEOF_INT128__)
154 return static_cast<double>(a) <=> b;
157 return static_cast<double>(a) == b;
170namespace pgl::detail {
185struct numeric_limits : std::numeric_limits<T> {};
187#if defined(__SIZEOF_INT128__)
189struct numeric_limits<__int128_t> {
190 static constexpr bool is_specialized =
true;
191 static constexpr bool is_signed =
true;
192 static constexpr bool is_integer =
true;
193 static constexpr bool is_exact =
true;
194 static constexpr bool is_bounded =
true;
195 static constexpr int digits = 127;
196 static constexpr int digits10 = 38;
197 static constexpr __int128_t min() noexcept {
198 return static_cast<__int128_t
>(
static_cast<__uint128_t
>(1) << 127);
200 static constexpr __int128_t lowest() noexcept {
return min(); }
201 static constexpr __int128_t max() noexcept {
202 return static_cast<__int128_t
>(~(
static_cast<__uint128_t
>(1) << 127));
208concept extended_integral =
232template <
class A,
class B>
233constexpr std::strong_ordering strongOrder(
const A& a,
const B& b) {
234 if constexpr (
requires { std::strong_order(a, b); }) {
235 if constexpr (std::is_floating_point_v<A> || std::is_floating_point_v<B>) {
237 return std::strong_ordering::equal;
240 return std::strong_order(a, b);
242 if (a < b)
return std::strong_ordering::less;
243 if (b < a)
return std::strong_ordering::greater;
244 return std::strong_ordering::equal;
257template <
class A,
class B>
258constexpr auto threeWay(
const A& a,
const B& b) {
259 if constexpr (
requires { a <=> b; }) {
262 return a < b ? std::strong_ordering::less
263 : b < a ? std::strong_ordering::greater
264 : std::strong_ordering::equal;
281#ifndef PGL_DISABLE_PROMOTION
297 requires std::signed_integral<T>
300 std::conditional_t<
sizeof(T) <= 1, int16_t,
301 std::conditional_t<
sizeof(T) <= 2, int32_t,
302 std::conditional_t<
sizeof(T) <= 4, int64_t,
303 std::conditional_t<
sizeof(T) <= 8,
pgl::int128, pgl::BigInt>>>>;
310struct _promote<pgl::
int128> {
311 using type = pgl::BigInt;
315struct _promote<float> {
320struct _promote<double> {
321 using type =
long double;
326using promoted_number_t =
typename _promote<T>::type;
361template <
class Target,
class Number>
362constexpr decltype(
auto) asNumber(
const Number& value) {
363 if constexpr (std::is_same_v<Target, Number>) {
366 return static_cast<Target
>(value);
379inline constexpr bool arbitraryPrecision =
false;
382inline constexpr bool arbitraryPrecision<pgl::BigInt> =
true;
385inline constexpr bool arbitraryPrecision<pgl::Rational<Int>> = arbitraryPrecision<Int>;
401template <
class ResultNumber>
402using floating_result_t =
403 std::conditional_t<std::is_floating_point_v<ResultNumber>, ResultNumber,
double>;
408constexpr auto gcd(std::integral
auto a, std::integral
auto b) {
409 return std::gcd(a, b);
415inline auto gcd(
auto a,
auto b) {
421 const auto remainder = a % b;
440template <
class Integer>
441inline std::array<Integer, 3> extendedGcd(Integer a, Integer b) {
442 Integer remainder = a, currentRemainder = b;
443 Integer coefficientA(1), nextCoefficientA(0);
444 Integer coefficientB(0), nextCoefficientB(1);
445 while (currentRemainder != Integer(0)) {
446 const Integer quotient = remainder / currentRemainder;
447 Integer next = remainder - quotient * currentRemainder;
448 remainder = currentRemainder;
449 currentRemainder = next;
450 next = coefficientA - quotient * nextCoefficientA;
451 coefficientA = nextCoefficientA;
452 nextCoefficientA = next;
453 next = coefficientB - quotient * nextCoefficientB;
454 coefficientB = nextCoefficientB;
455 nextCoefficientB = next;
457 if (remainder < Integer(0)) {
458 remainder = -remainder;
459 coefficientA = -coefficientA;
460 coefficientB = -coefficientB;
462 return {remainder, coefficientA, coefficientB};
469template <
class Integer>
470inline Integer nearestQuotient(
const Integer& numerator,
const Integer& divisor) {
471 Integer quotient = numerator / divisor;
472 Integer remainder = numerator - quotient * divisor;
473 if (remainder < Integer(0)) {
474 quotient -= Integer(1);
475 remainder += divisor;
477 if (Integer(2) * remainder >= divisor) {
478 quotient += Integer(1);
490template <
class Target,
class Integer>
491inline bool representableAs(
const Integer& value) {
492 if constexpr (!numeric_limits<Target>::is_bounded) {
495 return value >= Integer(numeric_limits<Target>::lowest())
496 && value <= Integer(numeric_limits<Target>::max());
508template <
class Target,
class Integer>
509inline Target narrowTo(
const Integer& value) {
510 if constexpr (std::same_as<Target, Integer>) {
513 return static_cast<Target
>(
static_cast<pgl::int128>(value));
520constexpr auto abs(extended_integral
auto value) {
521 using T =
decltype(value);
522 if constexpr (std::is_unsigned_v<T>) {
525 return value < 0 ? -value : value;
532constexpr auto abs(std::floating_point
auto value) {
533 return std::abs(value);
543inline constexpr auto abs(
auto value) {
544 return value >= 0 ? value : -value;
550template <
typename Int>
568template <
class To,
class From>
569[[nodiscard]]
constexpr To convertCoordinate(From value) {
570 return static_cast<To
>(value);
Arbitrary precision signed integer.
Definition bigint.hpp:157
Exact rational number class template.
Definition rational.hpp:106
constexpr Int numerator() const noexcept
Get numerator (in lowest terms).
Definition rational.hpp:359
constexpr void simplify()
Reduces the stored fraction to lowest terms in place (den stays > 0).
Definition rational.hpp:388
constexpr Int denominator() const noexcept
Get denominator (in lowest terms).
Definition rational.hpp:365
Strongly typed index handles shared by the topological data structures.
Definition numeric.hpp:152
std::partial_ordering operator<=>(const pgl::int128 &a, double b)
Definition numeric.hpp:153
double operator/(const pgl::int128 &a, double b)
Definition numeric.hpp:165
double operator-(const pgl::int128 &a, double b)
Definition numeric.hpp:161
double operator+(const pgl::int128 &a, double b)
Definition numeric.hpp:159
bool operator==(const pgl::int128 &a, double b)
Definition numeric.hpp:156
double operator*(const pgl::int128 &a, double b)
Definition numeric.hpp:163
Definition arrangement.hpp:67
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 127, 127, boost::multiprecision::signed_magnitude, boost::multiprecision::unchecked, void > > int128
Signed 128-bit integer.
Definition numeric.hpp:64
Rational(T) -> Rational< T >
std::ostream & operator<<(std::ostream &stream, const Point< Number, Label > &point)
Streams a point as (x,y) or label:(x,y).
Definition io.hpp:27