diff --git a/build.jam b/build.jam index a051f0f3..d2c19066 100644 --- a/build.jam +++ b/build.jam @@ -6,13 +6,10 @@ require-b2 5.2 ; -project /boost/int128 - : common-requirements - include - ; +project /boost/int128 ; explicit - [ alias boost_int128 ] + [ alias boost_int128 : : : : include $(boost_dependencies) ] [ alias all : boost_int128 test ] ; diff --git a/doc/.gitignore b/doc/.gitignore index fa23d21c..728af078 100644 --- a/doc/.gitignore +++ b/doc/.gitignore @@ -1,4 +1,4 @@ /pdf/ /html/ -*.DS_Store -*.html +/build/ +/node_modules/ diff --git a/doc/Jamfile b/doc/Jamfile deleted file mode 100644 index 7abba94a..00000000 --- a/doc/Jamfile +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2017, 2018 Peter Dimov -# Copyright 2024 Matt Borland -# Distributed under the Boost Software License, Version 1.0. -# https://www.boost.org/LICENSE_1_0.txt - -import asciidoctor ; - -html int128.html : int128.adoc - : /boost/boostlook//boostlook - int128-docinfo-footer.html - ; - -install html_ : int128.html : html ; - -pdf int128.pdf : int128.adoc ; -explicit int128.pdf ; - -install pdf_ : int128.pdf : pdf ; -explicit pdf_ ; - -############################################################################### -alias boostdoc ; -explicit boostdoc ; -alias boostrelease : html_ ; -explicit boostrelease ; diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 new file mode 100644 index 00000000..ba20ae83 --- /dev/null +++ b/doc/Jamfile.v2 @@ -0,0 +1,28 @@ +# Copyright 2026 Joaquin M Lopez Munoz +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +import path ; + +make html_ : build_antora.sh : @run-script ; + +actions run-script +{ + bash $(>) +} + +path-constant DOC_DIR : . ; +.node_modules = [ path.join $(DOC_DIR) node_modules ] ; + +make cleanup_node_modules_ : html_ : @cleanup-node-modules ; + +actions cleanup-node-modules +{ + rm -rf $(.node_modules) +} + +############################################################################### +alias boostdoc ; +explicit boostdoc ; +alias boostrelease : html_ cleanup_node_modules_ ; +explicit boostrelease ; diff --git a/doc/antora.yml b/doc/antora.yml new file mode 100644 index 00000000..11c33ddb --- /dev/null +++ b/doc/antora.yml @@ -0,0 +1,6 @@ +name: ROOT +version: ~ +title: Boost.int128 +nav: + - modules/ROOT/nav.adoc +start_page: overview.adoc diff --git a/doc/build_antora.sh b/doc/build_antora.sh new file mode 100755 index 00000000..19ae4bc2 --- /dev/null +++ b/doc/build_antora.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +set -ex + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +cd "$SCRIPT_DIR" + +npm ci +npx antora int128-playbook.yml diff --git a/doc/int128-playbook.yml b/doc/int128-playbook.yml new file mode 100644 index 00000000..6379b801 --- /dev/null +++ b/doc/int128-playbook.yml @@ -0,0 +1,18 @@ +site: + title: Boost.int128 + start_page: ROOT::overview.adoc +content: + sources: + - url: .. + start_path: doc + branches: HEAD +output: + dir: html +ui: + bundle: + url: https://github.com/boostorg/website-v2-docs/releases/download/ui-develop/ui-bundle.zip + output_dir: _ +antora: + extensions: + - require: '@cppalliance/antora-downloads-extension' + - require: '@antora/lunr-extension' diff --git a/doc/int128.adoc b/doc/int128.adoc deleted file mode 100644 index b8128044..00000000 --- a/doc/int128.adoc +++ /dev/null @@ -1,61 +0,0 @@ -//// -Copyright 2025 Matt Borland -Distributed under the Boost Software License, Version 1.0. -https://www.boost.org/LICENSE_1_0.txt -//// - -:toc: left -:toclevels: 4 -:idprefix: -:listing-caption: Code Example -:docinfo: private-footer -:source-highlighter: rouge -:source-language: c++ - -:leveloffset: +1 -:imagesdir: ../img - -= Int128: Portable and Performant 128-bit integers -Matt Borland - -include::int128/overview.adoc[] - -include::int128/printer.adoc[] - -include::int128/api_reference.adoc[] - -include::int128/file_structure.adoc[] - -include::int128/concepts.adoc[] - -include::int128/uint128_t.adoc[] - -include::int128/int128_t.adoc[] - -include::int128/mixed_type_ops.adoc[] - -include::int128/literals.adoc[] - -include::int128/bit.adoc[] - -include::int128/charconv.adoc[] - -include::int128/cstdlib.adoc[] - -include::int128/stream.adoc[] - -include::int128/numeric.adoc[] - -include::int128/format.adoc[] - -include::int128/examples.adoc[] - -include::int128/u128_benchmarks.adoc[] - -include::int128/i128_benchmarks.adoc[] - -include::int128/reference.adoc[] - -include::int128/copyright.adoc[] - -:leveloffset: -1 diff --git a/doc/int128/api_reference.adoc b/doc/int128/api_reference.adoc deleted file mode 100644 index 0d97571d..00000000 --- a/doc/int128/api_reference.adoc +++ /dev/null @@ -1,120 +0,0 @@ -//// -Copyright 2025 Matt Borland -Distributed under the Boost Software License, Version 1.0. -https://www.boost.org/LICENSE_1_0.txt -//// - -[#api_reference] -= API Reference -:idprefix: api_ref_ - -== Namespaces - -- `boost::int128` contains all components of the library except `` functionality -- <> - -== Types - -- <> -- <> - -== Literals - -- <> -- <> -- <> -- <> - -== Structures - -- https://en.cppreference.com/w/cpp/types/numeric_limits[`std::numeric_limits`] -- https://en.cppreference.com/w/cpp/types/numeric_limits[`std::numeric_limits`] -- <> -- <> - -== Functions - -Listed by analogous STL header. - -=== `` -- <> -- <> -- <> -- <> -- <> -- <> -- <> -- <> -- <> -- <> -- <> -- <> - -=== `` -- <> -- <> - -=== `` -- `abs` - Absolute Value - -=== `` -- <> - -=== <`>> - -=== <> - -=== `` -- <> -- <>`>> - -=== `` -- <> -- <> -- <> -- <> -- <> - -=== `` -- <> -- <> -- <> -- <> -- <> -- <> -- <> -- <> - -== Concepts - -- <> -- <> -- <> - -== Macros - -=== Constants (``) - -- `BOOST_INT128_UINT128_MAX` -- `BOOST_INT128_INT128_MAX` -- `BOOST_INT128_INT128_MIN` - -=== Literals - -- <> -- <> - -=== Configuration - -==== User Configuration - -- <> -- <> -- <> -- <> - -==== Automatic Configuration - -- <> -- <> -- <> diff --git a/doc/int128/concepts.adoc b/doc/int128/concepts.adoc deleted file mode 100644 index 9d260cf7..00000000 --- a/doc/int128/concepts.adoc +++ /dev/null @@ -1,101 +0,0 @@ -//// -Copyright 2025 Matt Borland -Distributed under the Boost Software License, Version 1.0. -https://www.boost.org/LICENSE_1_0.txt -//// - -[#Concepts] -= Concepts -:idprefix: concepts_ - -The following are the definitions of the concepts used throughout the library to ensure consistency. -While these are from the detail folder of the library, they are included for clarity since they will be used in the function definitions of following sections. - -[#signed_integer] -== Signed Integer - -This is an extension of the `` definition to allow builtin `__int128` to be used. - -[source, c++] ----- -namespace boost { -namespace int128 { -namespace detail { - -template -struct signed_integer -{ - static constexpr bool value = (std::is_signed::value && std::is_integral::value) - #ifdef BOOST_INT128_HAS_INT128 - || std::is_same::value; - #endif - ; -}; - -template -static constexpr bool is_signed_integer_v = signed_integer::value; - -#define BOOST_INT128_DEFAULTED_SIGNED_INTEGER_CONCEPT typename SignedInteger, std::enable_if_t, bool> = true - -#define BOOST_INT128_SIGNED_INTEGER_CONCEPT typename SignedInteger, std::enable_if_t, bool> - -} // namespace detail -} // namespace int128 -} // namespace boost ----- - -[#unsigned_integer] -== Unsigned Integer - -This is an extension of the `` definition to allow builtin `unsigned __int128` to be used. - -[source, c++] ----- -namespace boost { -namespace int128 { -namespace detail { - -template -struct unsigned_integer -{ - static constexpr bool value = (std::is_unsigned::value && std::is_integral::value) - #ifdef BOOST_INT128_HAS_INT128 - || std::is_same::value; - #endif - ; -}; - -template -static constexpr bool is_unsigned_integer_v = unsigned_integer::value; - -#define BOOST_INT128_DEFAULTED_UNSIGNED_INTEGER_CONCEPT typename UnsignedInteger, std::enable_if_t, bool> = true - -#define BOOST_INT128_UNSIGNED_INTEGER_CONCEPT typename UnsignedInteger, std::enable_if_t, bool> - -} // namespace detail -} // namespace int128 -} // namespace boost ----- - -[#integer] -== Integer - -This is a combination of the above two in which any integer can be detected - -[source, c++] ----- -namespace boost { -namespace int128 { -namespace detail { - -template -static constexpr bool is_any_integer_v = signed_integer::value || unsigned_integer::value; - -#define BOOST_INT128_DEFAULTED_INTEGER_CONCEPT typename Integer, std::enable_if_t, bool> = true - -#define BOOST_INT128_INTEGER_CONCEPT typename Integer, std::enable_if_t, bool> - -} // namespace detail -} // namespace int128 -} // namespace boost ----- diff --git a/doc/int128/config.adoc b/doc/int128/config.adoc deleted file mode 100644 index 32472ab5..00000000 --- a/doc/int128/config.adoc +++ /dev/null @@ -1,37 +0,0 @@ -//// -Copyright 2025 Matt Borland -Distributed under the Boost Software License, Version 1.0. -https://www.boost.org/LICENSE_1_0.txt -//// - -[#configuration] -= Configuration Macros -:idprefix: config_ - -== User Configurable Macros - -[#no_int128] -- `BOOST_INT128_NO_BUILTIN_INT128`: The user may define this when they do not want the internal implementations to rely on builtin `\__int128` or `unsigned __int128` types. - -[#sign_compare] -- `BOOST_INT128_ALLOW_SIGN_COMPARE` - Allows only comparisons between this library's types, and built-in types of the opposite sign. - -IMPORTANT: DISABLED BY DEFAULT FOR CORRECTNESS - -[#sign_conversion] -- `BOOST_INT128_ALLOW_SIGN_CONVERSION` - Allows operations between this library's types, and built-in types of opposite signedness, to include sign comparisons. - -IMPORTANT: DISABLED BY DEFAULT FOR CORRECTNESS - -[#disable_exceptions] -- `BOOST_INT128_DISABLE_EXCEPTIONS` - Allows exceptions to be disabled. -This macro will automatically be defined in the presence of `-fno-exceptions` or similar MSVC flags. - -[#automatic_config] -== Automatic Configuration Macros - -- `BOOST_INT128_HAS_INT128`: This is defined when compiling on a platform that has builtin `\___int128` or `unsigned __int128` types (e.g. `\__x86_64___`). - -- `BOOST_INT128_ENDIAN_LITTLE_BYTE`: This is defined to `1` when compiling on a little endian architecture, otherwise `0`. - -- `BOOST_INT128_ENDIAN_BIG_BYTE`: This is defined to `1` when compiling on a big endian architecture, otherwise `0`. diff --git a/doc/int128/examples.adoc b/doc/int128/examples.adoc deleted file mode 100644 index b9c5d84d..00000000 --- a/doc/int128/examples.adoc +++ /dev/null @@ -1,415 +0,0 @@ -//// -Copyright 2025 Matt Borland -Distributed under the Boost Software License, Version 1.0. -https://www.boost.org/LICENSE_1_0.txt -//// - -[#examples] -= Examples -:idprefix: examples_ - -All the following examples can be found in the examples/ folder of the library. - -== Basic Construction -[source, c++] ----- -#include -#include -#include -#include -#include - -int main() -{ - // There are a number of ways to construct integer types - - // 1) From a builtin-integer type - constexpr boost::int128::uint128_t from_builtin {6U}; - assert(from_builtin == 6U); - - // 2) By directly adding 128-bit hex/integer values - constexpr boost::int128::uint128_t from_hex {UINT64_C(0xFFFFFFFFFFFFFFFF), UINT64_C(0xFFFFFFFFFFFFFFFF)}; - assert(from_hex == std::numeric_limits::max()); - - // 3) From literal which allows values >2^64 to be easily constructed - // To match expectations the literals are in a separate literals namespace - using namespace boost::int128::literals; - const auto from_literal = "36893488147419103232"_U128; // Can be constexpr, but older compilers (GCC <= 7) fail - static_assert(std::is_same::value, "uint128_t works fine with auto construction"); - - // 4) From macro appending the correct literal like UINT32_C, UINT64_C etc. - // This also allows values >2^64 to be constructed without needing to separate into high and low hex values - const auto from_macro {BOOST_INT128_UINT128_C(36893488147419103232)}; // Can be constexpr, but older compilers (GCC <= 7 and Clang <= 8) fail - assert(from_macro == from_literal); - - // 5) Istream is supported by the types - std::stringstream in; - in.str("340282366920938463463374607431768211455"); - boost::int128::uint128_t from_stream; - in >> from_stream; - assert(from_stream == from_hex); - - // These same methods also apply to int128_t - constexpr boost::int128::int128_t from_int {-42}; - assert(from_int == -42); - - constexpr boost::int128::int128_t from_hex_signed {INT64_MIN, 0}; - assert(from_hex_signed == std::numeric_limits::min()); - - // Both capital and lowercase letters work - const auto negative_literal {"-42"_i128}; - assert(negative_literal == from_int); - - const auto negative_macro {BOOST_INT128_INT128_C(-170141183460469231731687303715884105728)}; - assert(negative_macro == from_hex_signed); - - return 0; -} - ----- - -== Basic Arithmetic -[source, c++] ----- -#include -#include - -int main() -{ - // The types of this library support all arithmetic operations one would expect - // They can be between values of the same type, or same signedness by default. - // See `mixed_type_arithmetic.cpp` for other operations - boost::int128::int128_t x {42}; - boost::int128::int128_t y {-2}; - - // Comparisons - assert(x > y); - assert(x >= y); - assert(y < x); - assert(y <= x); - assert(x == x); - assert(y != x); - - // Add,sub,mul,div - assert(x + y == 40); - assert(y - x == -44); - assert(x * y == -84); - assert(x / y == -21); - assert(x % y == 0); - - // Absolute Value - // For generic programming add using boost::int128::abs; at the top of the function, - // so that it will be found by ADL just by writing abs(y); - assert(boost::int128::abs(y) == 2); - - // Compound operations - x /= y; - assert(x == -21); - - y += 4L; - assert(y == 2); - - y *= -5LL; - assert(y == -10); - - return 0; -} - ----- - -== IO Streaming -[source, c++] ----- -#include -#include -#include -#include - -int main() -{ - // Both types allow streaming as one would expect from a regular builtin-type - constexpr boost::int128::int128_t signed_value {-42}; - std::cout << "Signed value: " << signed_value << std::endl; - - // We can also use to change the output format - constexpr boost::int128::uint128_t unsigned_value {0x1, UINT64_MAX}; - std::cout << "Unsigned value (dec): " << unsigned_value << '\n' - << "Unsigned value (hex): " << std::hex << unsigned_value << '\n' - << "Unsigned value (oct): " << std::oct << unsigned_value << std::endl; - - // Hex also can be manipulated to be uppercase - std::cout << "Upper unsigned value: " << std::hex << std::uppercase << unsigned_value << std::endl; - - // And returned to default formating - std::cout << "Lower unsigned value: " << std::dec << std::nouppercase << unsigned_value << std::endl; - - - return 0; -} ----- - -== Bitwise Functions () -[source,c++] ----- -#include -#include - -int main() -{ - // The functions from bit are only available for uint128_t - - constexpr boost::int128::uint128_t x {1U}; - - // All the functions are constexpr - - // Does the value have only a single bit set? - static_assert(boost::int128::has_single_bit(x), "Should have one bit"); - - // How many zeros from the left - static_assert(boost::int128::countl_zero(x) == 127U, "Should be 127"); - - // The bit width of the value - // 1 + 1 is 10 in binary which is 2 bits wide - static_assert(boost::int128::bit_width(x + x) == 2U, "2 bits wide"); - - // The smallest power of two not greater than the input value - static_assert(boost::int128::bit_floor(3U * x) == 2U, "2 < 3"); - - // The smallest power of two not Smaller than the input value - static_assert(boost::int128::bit_ceil(5U * x) == 8U, "8 > 5"); - - // How many zeros from the right? - static_assert(boost::int128::countr_zero(2U * x) == 1, "1 zero to the right of 10"); - - // How many 1-bits in the value - static_assert(boost::int128::popcount(7U * x) == 3, "111"); - - // Swap the bytes - // Create a value with distinct byte pattern - constexpr boost::int128::uint128_t original{ - 0x0123456789ABCDEFULL, - 0xFEDCBA9876543210ULL - }; - - // Expected result after byteswap - constexpr boost::int128::uint128_t expected{ - 0x1032547698BADCFEULL, - 0xEFCDAB8967452301ULL - }; - - static_assert(boost::int128::byteswap(original) == expected, "Mismatched byteswap"); - static_assert(boost::int128::byteswap(expected) == original, "Mismatched byteswap"); - - return 0; -} - ----- - -== Saturating Arithmetic () -[source, c++] ----- -#include -#include - -// Or you can do a single header - -// #include - -#include -#include -#include - -int main() -{ - // std::numeric_limits is overloaded for both types - constexpr auto uint_max {std::numeric_limits::max()}; - static_assert(std::is_same::value, "Types should match"); - - constexpr boost::int128::int128_t int_max {std::numeric_limits::max()}; - - // Saturating arithmetic returns max on overflow, or min on underflow rather than rolling over - assert(boost::int128::add_sat(uint_max, uint_max) == uint_max); - assert(boost::int128::sub_sat(boost::int128::uint128_t{0}, uint_max) == 0U); - - // This is especially useful for signed types since rollover is undefined - assert(boost::int128::mul_sat(int_max, 2) == int_max); - assert(boost::int128::mul_sat(-(int_max - 2), 5) == std::numeric_limits::min()); - - // The only case in the library where div sat overflows is x = std::numeric_limits::min() and y = -1 - assert(boost::int128::div_sat(std::numeric_limits::min(), -1) == int_max); - - // Saturating case allows types to be safely converted without rollover behavior - assert(boost::int128::saturate_cast(uint_max) == int_max); - - // You can also cast to builtin types - assert(boost::int128::saturate_cast(int_max) == INT64_MAX); - - // Even of different signedness as this is treated like a static cast - assert(boost::int128::saturate_cast(uint_max) == INT32_MAX); - - return 0; -} ----- - -== Mixed Signedness Arithmetic -[source, c++] ----- -// #define BOOST_INT128_ALLOW_SIGN_CONVERSION -#include -#include - -int main() -{ - // By default, mixed type arithmetic is NOT ALLOWED - // In order for this file to compile #define BOOST_INT128_ALLOW_SIGN_CONVERSION - // BEFORE the inclusion of any file of this library (uncomment the top line) - // - // Unlike builtin types we cannot enforce sign correctness via compiler flag, - // so we made it the default. - - - constexpr boost::int128::uint128_t unsigned_value {3}; - - constexpr auto greater_unsigned_value {unsigned_value + 5}; - - assert(unsigned_value + 1 == 4); - assert(unsigned_value - 1 == 2); - assert(unsigned_value * 2 == 6); - assert(unsigned_value / 3 == 1); - assert(unsigned_value % 3 == 0); - assert(unsigned_value + 5 == greater_unsigned_value); - - constexpr boost::int128::int128_t signed_value {-3}; - - assert(signed_value + 1U == -2); - assert(signed_value - 4U == -7); - assert(signed_value * 2 == -6); - assert(signed_value / 4U == 0); - - return 0; -} ----- - -== Boost.Math and Boost.Random Integration - -[source, c++] ----- -// Allowing sign conversion is a required pre-requisite for Boost.Random -#define BOOST_INT128_ALLOW_SIGN_CONVERSION - -#include -#include -#include -#include -#include -#include -#include - -int main() -{ - // Setup our rng and distribution - std::mt19937_64 rng {42}; - boost::random::uniform_int_distribution dist {0, (std::numeric_limits::max)()}; - - // Create a dataset for ourselves of random uint128_ts using our dist and rng from above - std::array data_set; - for (auto& value : data_set) - { - value = dist(rng); - } - - // Perform some rudimentary statistical analysis on our dataset - std::cout << " Mean: " << boost::math::statistics::mean(data_set) << std::endl; - std::cout << "Variance: " << boost::math::statistics::variance(data_set) << std::endl; - std::cout << " Median: " << boost::math::statistics::median(data_set) << std::endl; - - return 0; -} - ----- - -== Boost.Charconv Integration -[source,c++] ----- -// Allowing sign conversion is a required pre-requisite for Boost.Charconv -#define BOOST_INT128_ALLOW_SIGN_CONVERSION - -#include -#include -#include -#include -#include -#include -#include - -int main() -{ - constexpr boost::int128::uint128_t max_value = std::numeric_limits::max(); - - // Boost.Charconv can be used as it would be with any builtin type - char buffer[64]; - auto r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), max_value); - assert(r); - *r.ptr = '\0'; // Boost/std charconv do not add null terminators - - std::cout << "Max unsigned value: " << buffer << std::endl; - - boost::int128::uint128_t return_value; - auto r_from = boost::charconv::from_chars(buffer, buffer + sizeof(buffer), return_value); - assert(r_from); - assert(max_value == return_value); - - // And same for signed types - constexpr auto min_signed_value = std::numeric_limits::min(); - - std::memset(buffer, 0, sizeof(buffer)); - r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), min_signed_value); - assert(r); - *r.ptr = '\0'; - - std::cout << "Min signed value: " << buffer << std::endl; - - boost::int128::int128_t signed_return_value; - r_from = boost::charconv::from_chars(buffer, buffer + sizeof(buffer), signed_return_value); - assert(r_from); - assert(min_signed_value == signed_return_value); - - // Boost from_chars also supports from_chars for a std::string or std::string_view - - std::string unsigned_string = "42"; - r_from = boost::charconv::from_chars(unsigned_string, return_value); - assert(r_from); - assert(return_value == boost::int128::uint128_t{42}); - - std::string signed_string = "-12345"; - r_from = boost::charconv::from_chars(signed_string, signed_return_value); - assert(r_from); - assert(signed_return_value == boost::int128::int128_t{-12345}); - - // We can also do non-base 10 value conversions for both types - std::memset(buffer, 0, sizeof(buffer)); - r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), max_value, 16); - assert(r); - *r.ptr = '\0'; - - std::cout << "Unsigned value in hex: 0x" << buffer << std::endl; - - return_value = 0U; - r_from = boost::charconv::from_chars(buffer, buffer + sizeof(buffer), return_value, 16); - assert(r_from); - - std::memset(buffer, 0, sizeof(buffer)); - r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), boost::int128::int128_t{42}, 8); - assert(r); - *r.ptr = '\0'; - - std::cout << "Signed value octal: 0" << buffer << std::endl; - - signed_return_value = 0; - r_from = boost::charconv::from_chars(buffer, buffer + sizeof(buffer), signed_return_value, 8); - assert(r_from); - assert(signed_return_value == 42); - - return 0; -} ----- diff --git a/doc/int128/file_structure.adoc b/doc/int128/file_structure.adoc deleted file mode 100644 index a1e24bde..00000000 --- a/doc/int128/file_structure.adoc +++ /dev/null @@ -1,29 +0,0 @@ -//// -Copyright 2025 Matt Borland -Distributed under the Boost Software License, Version 1.0. -https://www.boost.org/LICENSE_1_0.txt -//// - - -[#structure] -= Directory Structure -:idprefix: structure_ - -The entire library can be consumed via ``, or by independently selecting any of the library headers. -Below is the directory structure for reference: - ----- -boost/ -├── int128.hpp -└── int128/ - ├── bit.hpp - ├── charconv.hpp - ├── climits.hpp - ├── fmt_format.hpp - ├── format.hpp - ├── int128.hpp - ├── iostream.hpp - ├── limits.hpp - ├── literals.hpp - └── numeric.hpp ----- diff --git a/doc/int128/format.adoc b/doc/int128/format.adoc deleted file mode 100644 index 4de42a45..00000000 --- a/doc/int128/format.adoc +++ /dev/null @@ -1,134 +0,0 @@ -//// -Copyright 2025 Matt Borland -Distributed under the Boost Software License, Version 1.0. -https://www.boost.org/LICENSE_1_0.txt -//// - -[#format] -= Formatting Support -:idprefix: format_ - -Boost.int128 support formatting with both `` (when pass:[C++20] and the header are both available), and `` -The following modifiers are listed in order of how they should be specified in the format string to be valid, and all information applies for both `` and `` - -== Sign - -There are three allowable sings first in the format string: - -|=== -| Sign | Effect -| `+` | Adds a `+` to positive values, and a `-` to negative values -| `-` | Only adds a `-` to negative values -| pass:[` `] (Space) | Adds a ` ` to positive values, and a `-` to negative values. Preserves alignment -|=== - -== Padding - -You can then add any number of padding characters to make sure that a formatted value takes up a specified width (5 means minimum width of 5 characters and so on). -Any integer value is accepted here. - -== Prepend Prefix - -If you want to prepend the prefix to your number (if applicable) add `#` - -|=== -| Output Base | Effect -| Binary | `0b` or `0B` -| Octal | `O` -| Decimal | None -| Hex | `0x` or `0X` -|=== - -== Output Base Modifiers - -The following type modifiers are the same as those used by built-in integer values - -|=== -| Modifier | Format -| b, B | Binary -| o | Octal -| d | Decimal -| x, X | Hex -|=== - -NOTE: When the uppercase modifier is used all characters will be capitalized (e.g. 0x2a vs 0X2A) - -== Default - -The default format string `{}` will output the same as `{:-d}`, that is a decimal value which only has a sign if negative. - -[#std_format] -== `` - -Examples using all of the above modifiers in some permutation: - -[source, c++] ----- -#include -#include -#include - -int main() -{ - constexpr boost::decimal::deciaml32_t value {42}; - // Default format - std::cout << std::format("{}", value) << '\n'; // Outputs: 42 - - // Sign modifier - std::cout << std::format("{:+d}", value) << '\n'; // Outputs +42 - std::cout << std::format("{:+d}", -value) << '\n'; // Outputs -42 - - // Output base modifier and Prefix - std::cout << std::format("{:x}", value) << '\n'; // Outputs 2a - std::cout << std::format("{:X}", value) << '\n'; // Outputs 2A - std::cout << std::format("{:#X}", value) << '\n'; // Outputs 0X2A - - // Padding - // Notice there are a total of 5 charaters to the right of the prefix - std::cout << std::format("{:#5X}", value) << '\n'; // Outputs 0X0002A - - // All together - // Notice theres a space before the first character - quoted for clarity - std::cout << std::format("{: #5X}", value) << '\n'; // Outputs " 0X0002A" - - return 0; -} ----- - -[#fmt_format] -== `pass:[{fmt}]` - -This is nearly the same as above but with `fmt::format` in place of `std::format`: - -[source, c++] ----- -#include -#include -#include - -int main() -{ - constexpr boost::decimal::deciaml32_t value {42}; - // Default format - std::cout << fmt::format("{}", value) << '\n'; // Outputs: 42 - - // Sign modifier - std::cout << fmt::format("{:+d}", value) << '\n'; // Outputs +42 - std::cout << fmt::format("{:+d}", -value) << '\n'; // Outputs -42 - - // Output base modifier and Prefix - std::cout << fmt::format("{:x}", value) << '\n'; // Outputs 2a - std::cout << fmt::format("{:X}", value) << '\n'; // Outputs 2A - std::cout << fmt::format("{:#X}", value) << '\n'; // Outputs 0X2A - - // Padding - // Notice there are a total of 5 charaters to the right of the prefix - std::cout << fmt::format("{:#5X}", value) << '\n'; // Outputs 0X0002A - - // All together - // Notice theres a space before the first character - quoted for clarity - std::cout << fmt::format("{: #5X}", value) << '\n'; // Outputs " 0X0002A" - - return 0; -} ----- diff --git a/doc/int128/int128_t.adoc b/doc/int128/int128_t.adoc deleted file mode 100644 index 4c8ad4c6..00000000 --- a/doc/int128/int128_t.adoc +++ /dev/null @@ -1,340 +0,0 @@ -//// -Copyright 2025 Matt Borland -Distributed under the Boost Software License, Version 1.0. -https://www.boost.org/LICENSE_1_0.txt -//// - -[#int128_t] -= int128_t -:idprefix: int128_t_ - -== Description - -`int128_t` is a signed 128-bit integer - -[source, c++] ----- -#include - -namespace boost { -namespace int128 { - -struct int128_t { - - #if BOOST_INT128_ENDIAN_LITTLE_BYTE - - std::uint64_t low {}; - std::int64_t high {}; - - #else - - std::int64_t high {}; - std::uint64_t low {}; - - #endif - - // Defaulted basic construction - constexpr int128_t() noexcept = default; - constexpr int128_t(const int128_t&) noexcept = default; - constexpr int128_t(int128_t&&) noexcept = default; - constexpr int128_t& operator=(const int128_t&) noexcept = default; - constexpr int128_t& operator=(int128_t&&) noexcept = default; - - // Requires conversion file to be implemented - constexpr int128_t(const uint128_t& v) noexcept; - - // Construct from integral types - constexpr int128_t(const std::int64_t hi, const std::uint64_t lo) noexcept; - - template - constexpr int128_t(const SignedInteger v) noexcept; - - template - constexpr int128_t(const UnsignedInteger v) noexcept; - - #ifdef BOOST_INT128_HAS_INT128 - - constexpr int128_t(const detail::builtin_i128 v) noexcept; - - constexpr int128_t(const detail::builtin_u128 v) noexcept; - - #endif // BOOST_INT128_HAS_INT128 - - // Integer Conversion operators - constexpr operator bool() const noexcept; - - template - explicit constexpr operator SignedInteger() const noexcept; - - template - explicit constexpr operator UnsignedInteger() const noexcept; - - #ifdef BOOST_INT128_HAS_INT128 - - explicit constexpr operator detail::builtin_i128() const noexcept; - - explicit constexpr operator detail::builtin_u128() const noexcept; - - #endif // BOOST_INT128_HAS_INT128 - - // Conversion to float - // This is basically the same as ldexp(static_cast(high), 64) + static_cast(low), - // but can be constexpr at C++11 instead of C++26 - explicit constexpr operator float() const noexcept; - explicit constexpr operator double() const noexcept; - explicit constexpr operator long double() const noexcept; - - // Compound Or - template - constexpr int128_t& operator|=(Integer rhs) noexcept; - - constexpr int128_t& operator|=(int128_t rhs) noexcept; - - // Compound And - template - constexpr int128_t& operator&=(Integer rhs) noexcept; - - constexpr int128_t& operator&=(int128_t rhs) noexcept; - - // Compound XOR - template - constexpr int128_t& operator^=(Integer rhs) noexcept; - - constexpr int128_t& operator^=(int128_t rhs) noexcept; - - // Compound Left Shift - template - constexpr int128_t& operator<<=(Integer rhs) noexcept; - - constexpr int128_t& operator<<=(int128_t rhs) noexcept; - - // Compound Right Shift - template - constexpr int128_t& operator>>=(Integer rhs) noexcept; - - constexpr int128_t& operator>>=(int128_t rhs) noexcept; - - // Prefix and postfix increment - constexpr int128_t& operator++() noexcept; - constexpr int128_t& operator++(int) noexcept; - - // Prefix and postfix decrment - constexpr int128_t& operator--() noexcept; - constexpr int128_t& operator--(int) noexcept; - - // Compound Addition - template - constexpr int128_t& operator+=(Integer rhs) noexcept; - - constexpr int128_t& operator+=(int128_t rhs) noexcept; - - // Compound Subtraction - template - constexpr int128_t& operator-=(Integer rhs) noexcept; - - constexpr int128_t& operator-=(int128_t rhs) noexcept; - - // Compound Multiplication - template - constexpr int128_t& operator*=(Integer rhs) noexcept; - - constexpr int128_t& operator*=(int128_t rhs) noexcept; - - // Compound Division - template - constexpr int128_t& operator/=(Integer rhs) noexcept; - - constexpr int128_t& operator/=(int128_t rhs) noexcept; - - // Compound Modulo - template - constexpr int128_t& operator%=(Integer rhs) noexcept; - - constexpr int128_t& operator%=(int128_t rhs) noexcept; - -}; // struct int128_t - -} //namespace int128 -} //namespace boost - ----- - -We also have the following non-member free functions: - -[source, c++] ----- -namespace boost { -namespace int128 { - -//===================================== -// Comparison Operators -//===================================== - -template -constexpr bool operator<(const int128_t lhs, const Integer rhs) noexcept; - -template -constexpr bool operator<(const Integer lhs, const int128_t rhs) noexcept; - -constexpr bool operator<(const int128_t lhs, const int128_t rhs) noexcept; - -template -constexpr bool operator<=(const int128_t lhs, const Integer rhs) noexcept; - -template -constexpr bool operator<=(const Integer lhs, const int128_t rhs) noexcept; - -constexpr bool operator<=(const int128_t lhs, const int128_t rhs) noexcept; - -template -constexpr bool operator>(const int128_t lhs, const Integer rhs) noexcept; - -template -constexpr bool operator>(const Integer lhs, const int128_t rhs) noexcept; - -constexpr bool operator>(const int128_t lhs, const int128_t rhs) noexcept; - -template -constexpr bool operator>=(const int128_t lhs, const Integer rhs) noexcept; - -template -constexpr bool operator>=(const Integer lhs, const int128_t rhs) noexcept; - -constexpr bool operator>=(const int128_t lhs, const int128_t rhs) noexcept; - -template -constexpr bool operator==(const int128_t lhs, const Integer rhs) noexcept; - -template -constexpr bool operator==(const Integer lhs, const int128_t rhs) noexcept; - -constexpr bool operator==(const int128_t lhs, const int128_t rhs) noexcept; - -template -constexpr bool operator!=(const int128_t lhs, const Integer rhs) noexcept; - -template -constexpr bool operator!=(const Integer lhs, const int128_t rhs) noexcept; - -constexpr bool operator!=(const int128_t lhs, const int128_t rhs) noexcept; - -//===================================== -// Bit-wise Operators -//===================================== - -constexpr int128_t operator~(const int128_t rhs) noexcept - -template -constexpr int128_t operator|(const int128_t lhs, const Integer rhs) noexcept; - -template -constexpr int128_t operator|(const Integer lhs, const int128_t rhs) noexcept; - -constexpr int128_t operator|(const int128_t lhs, const int128_t rhs) noexcept; - -template -constexpr int128_t operator&(const int128_t lhs, const Integer rhs) noexcept; - -template -constexpr int128_t operator&(const Integer lhs, const int128_t rhs) noexcept; - -constexpr int128_t operator&(const int128_t lhs, const int128_t rhs) noexcept; - -template -constexpr int128_t operator^(const int128_t lhs, const Integer rhs) noexcept; - -template -constexpr int128_t operator^(const Integer lhs, const int128_t rhs) noexcept; - -constexpr int128_t operator^(const int128_t lhs, const int128_t rhs) noexcept; - -// Shift operators have a number of overloads to ensure they return type matches the behavior of built-in types - -template -constexpr int128_t operator<<(const int128_t lhs, const Integer rhs) noexcept; - -template ::value && (sizeof(Integer) * 8 > 16), bool> = true> -constexpr Integer operator<<(const Integer lhs, const int128_t rhs) noexcept; - -template && (sizeof(SignedInteger) * 8 <= 16), bool> = true> -constexpr int operator<<(const SignedInteger lhs, const int128_t rhs) noexcept; - -template && (sizeof(UnsignedInteger) * 8 <= 16), bool> = true> -constexpr unsigned int operator<<(const UnsignedInteger lhs, const int128_t rhs) noexcept; - -constexpr int128_t operator<<(const int128_t lhs, const int128_t rhs) noexcept; - -template ::value, bool> = true> -constexpr int128_t operator>>(const int128_t lhs, const Integer rhs) noexcept; - -template ::value && (sizeof(Integer) * 8 > 16), bool> = true> -constexpr Integer operator>>(const Integer lhs, const int128_t rhs) noexcept; - -template && (sizeof(SignedInteger) * 8 <= 16), bool> = true> -constexpr int operator>>(const SignedInteger lhs, const int128_t rhs) noexcept; - -template && (sizeof(UnsignedInteger) * 8 <= 16), bool> = true> -constexpr unsigned operator>>(UnsignedInteger lhs, const int128_t rhs) noexcept; - -constexpr int128_t operator>>(const int128_t lhs, const int128_t rhs) noexcept; - -//===================================== -// Increment and Decrement Operators -//===================================== - -constexpr int128_t& int128_t::operator++() noexcept; - -constexpr int128_t& int128_t::operator++(int) noexcept; - -constexpr int128_t& int128_t::operator--() noexcept; - -constexpr int128_t& int128_t::operator--(int) noexcept; - -//===================================== -// Add, Sub, Mul, Div, Mod -//===================================== - -template -constexpr int128_t operator+(const int128_t lhs, const Integer rhs) noexcept; - -template -constexpr int128_t operator+(const Integer lhs, const int128_t rhs) noexcept; - -constexpr int128_t operator+(const int128_t lhs, const int128_t rhs) noexcept; - -template -constexpr int128_t operator-(const int128_t lhs, const Integer rhs) noexcept; - -template -constexpr int128_t operator-(const Integer lhs, const int128_t rhs) noexcept; - -constexpr int128_t operator-(const int128_t lhs, const int128_t rhs) noexcept; - -template -constexpr int128_t operator*(const int128_t lhs, const Integer rhs) noexcept; - -template -constexpr int128_t operator*(const Integer lhs, const int128_t rhs) noexcept; - -constexpr int128_t operator*(const int128_t lhs, const int128_t rhs) noexcept; - -template -constexpr int128_t operator/(const int128_t lhs, const Integer rhs) noexcept; - -template -constexpr int128_t operator/(const Integer lhs, const int128_t rhs) noexcept; - -constexpr int128_t operator/(const int128_t lhs, const int128_t rhs) noexcept; - -template -constexpr int128_t operator%(const int128_t lhs, const Integer rhs) noexcept; - -template -constexpr int128_t operator%(const Integer lhs, const int128_t rhs) noexcept; - -constexpr int128_t operator%(const int128_t lhs, const int128_t rhs) noexcept; - -} // namespace int128 -} // namespace boost - ----- diff --git a/doc/int128/printer.adoc b/doc/int128/printer.adoc deleted file mode 100644 index 9b8df8e1..00000000 --- a/doc/int128/printer.adoc +++ /dev/null @@ -1,21 +0,0 @@ -//// -Copyright 2025 Matt Borland -Distributed under the Boost Software License, Version 1.0. -https://www.boost.org/LICENSE_1_0.txt -//// - -[#pretty_printer] -= Pretty Printers -:idprefix: pretty_printers_ - -The library contains a pretty printer for LLDB in the `extra/` folder. -To use this, add the following line to your `~/.lldbinit` file: - -[source] ----- -command script import /path/to/int128/extra/int128_printer.py ----- - -If this is successful, you should see the following message in your debugger upon startup: - -"int128_t and uint128_t pretty printers loaded successfully" diff --git a/doc/int128/uint128_t.adoc b/doc/int128/uint128_t.adoc deleted file mode 100644 index cefe16fe..00000000 --- a/doc/int128/uint128_t.adoc +++ /dev/null @@ -1,339 +0,0 @@ -//// -Copyright 2025 Matt Borland -Distributed under the Boost Software License, Version 1.0. -https://www.boost.org/LICENSE_1_0.txt -//// - -[#uint128_t] -= uint128_t -:idprefix: uint128_t_ - -== Description - -`uint128_t` is an unsigned 128-bit integer - -[source, c++] ----- -#include - -namespace boost { -namespace int128 { - -struct uint128_t { - - #if BOOST_INT128_ENDIAN_LITTLE_BYTE - - std::uint64_t low {}; - std::uint64_t high {}; - - #else - - std::uint64_t high {}; - std::uint64_t low {}; - - #endif // BOOST_INT128_ENDIAN_LITTLE_BYTE - - // Defaulted basic construction - constexpr uint128_t() noexcept = default; - constexpr uint128_t(const uint128_t&) noexcept = default; - constexpr uint128_t(uint128_t&&) noexcept = default; - constexpr uint128_t& operator=(const uint128_t&) noexcept = default; - constexpr uint128_t& operator=(uint128_t&&) noexcept = default; - - // Requires conversion file to be implemented - constexpr uint128_t(const int128_t& v) noexcept; - - // Construct from integral types - #if BOOST_INT128_ENDIAN_LITTLE_BYTE - - constexpr uint128_t(const std::uint64_t hi, const std::uint64_t lo) noexcept; - - template - constexpr uint128_t(const SignedInteger v) noexcept; - - template - constexpr uint128_t(const UnsignedInteger v) noexcept; - - #ifdef BOOST_INT128_HAS_INT128 - - constexpr uint128_t(const detail::builtin_i128 v) noexcept; - - constexpr uint128_t(const detail::builtin_u128 v) noexcept; - - #endif // BOOST_INT128_HAS_INT128 - - // Integer conversion operators - constexpr operator bool() const noexcept; - - template - explicit constexpr operator SignedInteger() const noexcept; - - template - explicit constexpr operator UnsignedInteger() const noexcept; - - #ifdef BOOST_INT128_HAS_INT128 - - explicit constexpr operator detail::builtin_i128() const noexcept; - - explicit constexpr operator detail::builtin_u128() const noexcept; - - #endif // BOOST_INT128_HAS_INT128 - - // Conversion to float - // This is basically the same as ldexp(static_cast(high), 64) + static_cast(low), - // but can be constexpr at C++11 instead of C++26 - explicit constexpr operator float() const noexcept; - explicit constexpr operator double() const noexcept; - explicit constexpr operator long double() const noexcept; - - // Compound OR - template - constexpr uint128_t& operator|=(Integer rhs) noexcept; - - constexpr uint128_t& operator|=(uint128_t rhs) noexcept; - - // Compound AND - template - constexpr uint128_t& operator&=(Integer rhs) noexcept; - - constexpr uint128_t& operator&=(uint128_t rhs) noexcept; - - // Compound XOR - template - constexpr uint128_t& operator^=(Integer rhs) noexcept; - - constexpr uint128_t& operator^=(uint128_t rhs) noexcept; - - // Compound Left Shift - template - constexpr uint128_t& operator<<=(Integer rhs) noexcept; - - constexpr uint128_t& operator<<=(uint128_t rhs) noexcept; - - // Compound Right Shift - template - constexpr uint128_t& operator>>=(Integer rhs) noexcept; - - constexpr uint128_t& operator>>=(uint128_t rhs) noexcept; - - constexpr uint128_t& operator++() noexcept; - constexpr uint128_t& operator++(int) noexcept; - constexpr uint128_t& operator--() noexcept; - constexpr uint128_t& operator--(int) noexcept; - - // Compound Addition - template - constexpr uint128_t& operator+=(Integer rhs) noexcept; - - constexpr uint128_t& operator+=(uint128_t rhs) noexcept; - - // Compound Subtraction - template - constexpr uint128_t& operator-=(Integer rhs) noexcept; - - constexpr uint128_t& operator-=(uint128_t rhs) noexcept; - - // Compound Multiplication - template - constexpr uint128_t& operator*=(Integer rhs) noexcept; - - constexpr uint128_t& operator*=(uint128_t rhs) noexcept; - - // Compound Division - template - constexpr uint128_t& operator/=(Integer rhs) noexcept; - - constexpr uint128_t& operator/=(uint128_t rhs) noexcept; - - // Compound modulo - template - constexpr uint128_t& operator%=(Integer rhs) noexcept; - - constexpr uint128_t& operator%=(uint128_t rhs) noexcept; - -}; // struct uint128_t - -} //namespace int128 -} //namespace boost - ----- - -We also have the following non-member free functions: - -[source, c++] ----- -namespace boost { -namespace int128 { - -//===================================== -// Comparison Operators -//===================================== - -template -constexpr bool operator<(const uint128_t lhs, const Integer rhs) noexcept; - -template -constexpr bool operator<(const Integer lhs, const uint128_t rhs) noexcept; - -constexpr bool operator<(const uint128_t lhs, const uint128_t rhs) noexcept; - -template -constexpr bool operator<=(const uint128_t lhs, const Integer rhs) noexcept; - -template -constexpr bool operator<=(const Integer lhs, const uint128_t rhs) noexcept; - -constexpr bool operator<=(const uint128_t lhs, const uint128_t rhs) noexcept; - -template -constexpr bool operator>(const uint128_t lhs, const Integer rhs) noexcept; - -template -constexpr bool operator>(const Integer lhs, const uint128_t rhs) noexcept; - -constexpr bool operator>(const uint128_t lhs, const uint128_t rhs) noexcept; - -template -constexpr bool operator>=(const uint128_t lhs, const Integer rhs) noexcept; - -template -constexpr bool operator>=(const Integer lhs, const uint128_t rhs) noexcept; - -constexpr bool operator>=(const uint128_t lhs, const uint128_t rhs) noexcept; - -template -constexpr bool operator==(const uint128_t lhs, const Integer rhs) noexcept; - -template -constexpr bool operator==(const Integer lhs, const uint128_t rhs) noexcept; - -constexpr bool operator==(const uint128_t lhs, const uint128_t rhs) noexcept; - -template -constexpr bool operator!=(const uint128_t lhs, const Integer rhs) noexcept; - -template -constexpr bool operator!=(const Integer lhs, const uint128_t rhs) noexcept; - -constexpr bool operator!=(const uint128_t lhs, const uint128_t rhs) noexcept; - -//===================================== -// Bit-wise Operators -//===================================== - -constexpr uint128_t operator~(const uint128_t rhs) noexcept - -template -constexpr uint128_t operator|(const uint128_t lhs, const Integer rhs) noexcept; - -template -constexpr uint128_t operator|(const Integer lhs, const uint128_t rhs) noexcept; - -constexpr uint128_t operator|(const uint128_t lhs, const uint128_t rhs) noexcept; - -template -constexpr uint128_t operator&(const uint128_t lhs, const Integer rhs) noexcept; - -template -constexpr uint128_t operator&(const Integer lhs, const uint128_t rhs) noexcept; - -constexpr uint128_t operator&(const uint128_t lhs, const uint128_t rhs) noexcept; - -template -constexpr uint128_t operator^(const uint128_t lhs, const Integer rhs) noexcept; - -template -constexpr uint128_t operator^(const Integer lhs, const uint128_t rhs) noexcept; - -constexpr uint128_t operator^(const uint128_t lhs, const uint128_t rhs) noexcept; - -// Shift operators have a number of overloads to ensure they return type matches the behavior of built-in types - -template -constexpr uint128_t operator<<(const uint128_t lhs, const Integer rhs) noexcept; - -template ::value && (sizeof(Integer) * 8 > 16), bool> = true> -constexpr Integer operator<<(const Integer lhs, const uint128_t rhs) noexcept; - -template && (sizeof(SignedInteger) * 8 <= 16), bool> = true> -constexpr int operator<<(const SignedInteger lhs, const uint128_t rhs) noexcept; - -template && (sizeof(UnsignedInteger) * 8 <= 16), bool> = true> -constexpr unsigned int operator<<(const UnsignedInteger lhs, const uint128_t rhs) noexcept; - -constexpr uint128_t operator<<(const uint128_t lhs, const uint128_t rhs) noexcept; - -template ::value, bool> = true> -constexpr uint128_t operator>>(const uint128_t lhs, const Integer rhs) noexcept; - -template ::value && (sizeof(Integer) * 8 > 16), bool> = true> -constexpr Integer operator>>(const Integer lhs, const uint128_t rhs) noexcept; - -template && (sizeof(SignedInteger) * 8 <= 16), bool> = true> -constexpr int operator>>(const SignedInteger lhs, const uint128_t rhs) noexcept; - -template && (sizeof(UnsignedInteger) * 8 <= 16), bool> = true> -constexpr unsigned operator>>(UnsignedInteger lhs, const uint128_t rhs) noexcept; - -constexpr uint128_t operator>>(const uint128_t lhs, const uint128_t rhs) noexcept; - -//===================================== -// Increment and Decrement Operators -//===================================== - -constexpr uint128_t& uint128_t::operator++() noexcept; - -constexpr uint128_t& uint128_t::operator++(int) noexcept; - -constexpr uint128_t& uint128_t::operator--() noexcept; - -constexpr uint128_t& uint128_t::operator--(int) noexcept; - -//===================================== -// Add, Sub, Mul, Div, Mod -//===================================== - -template -constexpr uint128_t operator+(const uint128_t lhs, const Integer rhs) noexcept; - -template -constexpr uint128_t operator+(const Integer lhs, const uint128_t rhs) noexcept; - -constexpr uint128_t operator+(const uint128_t lhs, const uint128_t rhs) noexcept; - -template -constexpr uint128_t operator-(const uint128_t lhs, const Integer rhs) noexcept; - -template -constexpr uint128_t operator-(const Integer lhs, const uint128_t rhs) noexcept; - -constexpr uint128_t operator-(const uint128_t lhs, const uint128_t rhs) noexcept; - -template -constexpr uint128_t operator*(const uint128_t lhs, const Integer rhs) noexcept; - -template -constexpr uint128_t operator*(const Integer lhs, const uint128_t rhs) noexcept; - -constexpr uint128_t operator*(const uint128_t lhs, const uint128_t rhs) noexcept; - -template -constexpr uint128_t operator/(const uint128_t lhs, const Integer rhs) noexcept; - -template -constexpr uint128_t operator/(const Integer lhs, const uint128_t rhs) noexcept; - -constexpr uint128_t operator/(const uint128_t lhs, const uint128_t rhs) noexcept; - -template -constexpr uint128_t operator%(const uint128_t lhs, const Integer rhs) noexcept; - -template -constexpr uint128_t operator%(const Integer lhs, const uint128_t rhs) noexcept; - -constexpr uint128_t operator%(const uint128_t lhs, const uint128_t rhs) noexcept; - -} // namespace int128 -} // namespace boost - ----- diff --git a/doc/modules/ROOT/examples b/doc/modules/ROOT/examples new file mode 120000 index 00000000..9f9d1de8 --- /dev/null +++ b/doc/modules/ROOT/examples @@ -0,0 +1 @@ +../../../examples \ No newline at end of file diff --git a/doc/img/i128_graphs/linux/ARM32_benchmarks.png b/doc/modules/ROOT/images/i128_graphs/linux/ARM32_benchmarks.png similarity index 100% rename from doc/img/i128_graphs/linux/ARM32_benchmarks.png rename to doc/modules/ROOT/images/i128_graphs/linux/ARM32_benchmarks.png diff --git a/doc/img/i128_graphs/linux/ARM32_relative_performance.png b/doc/modules/ROOT/images/i128_graphs/linux/ARM32_relative_performance.png similarity index 100% rename from doc/img/i128_graphs/linux/ARM32_relative_performance.png rename to doc/modules/ROOT/images/i128_graphs/linux/ARM32_relative_performance.png diff --git a/doc/img/i128_graphs/linux/ARM64_benchmarks.png b/doc/modules/ROOT/images/i128_graphs/linux/ARM64_benchmarks.png similarity index 100% rename from doc/img/i128_graphs/linux/ARM64_benchmarks.png rename to doc/modules/ROOT/images/i128_graphs/linux/ARM64_benchmarks.png diff --git a/doc/img/i128_graphs/linux/ARM64_relative_performance.png b/doc/modules/ROOT/images/i128_graphs/linux/ARM64_relative_performance.png similarity index 100% rename from doc/img/i128_graphs/linux/ARM64_relative_performance.png rename to doc/modules/ROOT/images/i128_graphs/linux/ARM64_relative_performance.png diff --git a/doc/img/i128_graphs/linux/ppc64le_benchmarks.png b/doc/modules/ROOT/images/i128_graphs/linux/ppc64le_benchmarks.png similarity index 100% rename from doc/img/i128_graphs/linux/ppc64le_benchmarks.png rename to doc/modules/ROOT/images/i128_graphs/linux/ppc64le_benchmarks.png diff --git a/doc/img/i128_graphs/linux/ppc64le_relative_performance.png b/doc/modules/ROOT/images/i128_graphs/linux/ppc64le_relative_performance.png similarity index 100% rename from doc/img/i128_graphs/linux/ppc64le_relative_performance.png rename to doc/modules/ROOT/images/i128_graphs/linux/ppc64le_relative_performance.png diff --git a/doc/img/i128_graphs/linux/s390x_benchmarks.png b/doc/modules/ROOT/images/i128_graphs/linux/s390x_benchmarks.png similarity index 100% rename from doc/img/i128_graphs/linux/s390x_benchmarks.png rename to doc/modules/ROOT/images/i128_graphs/linux/s390x_benchmarks.png diff --git a/doc/img/i128_graphs/linux/s390x_relative_performance.png b/doc/modules/ROOT/images/i128_graphs/linux/s390x_relative_performance.png similarity index 100% rename from doc/img/i128_graphs/linux/s390x_relative_performance.png rename to doc/modules/ROOT/images/i128_graphs/linux/s390x_relative_performance.png diff --git a/doc/img/i128_graphs/linux/x64_benchmarks.png b/doc/modules/ROOT/images/i128_graphs/linux/x64_benchmarks.png similarity index 100% rename from doc/img/i128_graphs/linux/x64_benchmarks.png rename to doc/modules/ROOT/images/i128_graphs/linux/x64_benchmarks.png diff --git a/doc/img/i128_graphs/linux/x64_relative_performance.png b/doc/modules/ROOT/images/i128_graphs/linux/x64_relative_performance.png similarity index 100% rename from doc/img/i128_graphs/linux/x64_relative_performance.png rename to doc/modules/ROOT/images/i128_graphs/linux/x64_relative_performance.png diff --git a/doc/img/i128_graphs/linux/x86_benchmarks.png b/doc/modules/ROOT/images/i128_graphs/linux/x86_benchmarks.png similarity index 100% rename from doc/img/i128_graphs/linux/x86_benchmarks.png rename to doc/modules/ROOT/images/i128_graphs/linux/x86_benchmarks.png diff --git a/doc/img/i128_graphs/linux/x86_relative_performance.png b/doc/modules/ROOT/images/i128_graphs/linux/x86_relative_performance.png similarity index 100% rename from doc/img/i128_graphs/linux/x86_relative_performance.png rename to doc/modules/ROOT/images/i128_graphs/linux/x86_relative_performance.png diff --git a/doc/img/i128_graphs/macos/ARM64_benchmarks.png b/doc/modules/ROOT/images/i128_graphs/macos/ARM64_benchmarks.png similarity index 100% rename from doc/img/i128_graphs/macos/ARM64_benchmarks.png rename to doc/modules/ROOT/images/i128_graphs/macos/ARM64_benchmarks.png diff --git a/doc/img/i128_graphs/macos/ARM64_relative_performance.png b/doc/modules/ROOT/images/i128_graphs/macos/ARM64_relative_performance.png similarity index 100% rename from doc/img/i128_graphs/macos/ARM64_relative_performance.png rename to doc/modules/ROOT/images/i128_graphs/macos/ARM64_relative_performance.png diff --git a/doc/img/i128_graphs/macos/x64_benchmarks.png b/doc/modules/ROOT/images/i128_graphs/macos/x64_benchmarks.png similarity index 100% rename from doc/img/i128_graphs/macos/x64_benchmarks.png rename to doc/modules/ROOT/images/i128_graphs/macos/x64_benchmarks.png diff --git a/doc/img/i128_graphs/macos/x64_relative_performance.png b/doc/modules/ROOT/images/i128_graphs/macos/x64_relative_performance.png similarity index 100% rename from doc/img/i128_graphs/macos/x64_relative_performance.png rename to doc/modules/ROOT/images/i128_graphs/macos/x64_relative_performance.png diff --git a/doc/img/i128_graphs/windows/ARM64_benchmarks.png b/doc/modules/ROOT/images/i128_graphs/windows/ARM64_benchmarks.png similarity index 100% rename from doc/img/i128_graphs/windows/ARM64_benchmarks.png rename to doc/modules/ROOT/images/i128_graphs/windows/ARM64_benchmarks.png diff --git a/doc/img/i128_graphs/windows/ARM64_relative_performance.png b/doc/modules/ROOT/images/i128_graphs/windows/ARM64_relative_performance.png similarity index 100% rename from doc/img/i128_graphs/windows/ARM64_relative_performance.png rename to doc/modules/ROOT/images/i128_graphs/windows/ARM64_relative_performance.png diff --git a/doc/img/i128_graphs/windows/x64_benchmarks.png b/doc/modules/ROOT/images/i128_graphs/windows/x64_benchmarks.png similarity index 100% rename from doc/img/i128_graphs/windows/x64_benchmarks.png rename to doc/modules/ROOT/images/i128_graphs/windows/x64_benchmarks.png diff --git a/doc/img/i128_graphs/windows/x64_relative_performance.png b/doc/modules/ROOT/images/i128_graphs/windows/x64_relative_performance.png similarity index 100% rename from doc/img/i128_graphs/windows/x64_relative_performance.png rename to doc/modules/ROOT/images/i128_graphs/windows/x64_relative_performance.png diff --git a/doc/img/i128_graphs/windows/x86_benchmarks.png b/doc/modules/ROOT/images/i128_graphs/windows/x86_benchmarks.png similarity index 100% rename from doc/img/i128_graphs/windows/x86_benchmarks.png rename to doc/modules/ROOT/images/i128_graphs/windows/x86_benchmarks.png diff --git a/doc/img/i128_graphs/windows/x86_relative_performance.png b/doc/modules/ROOT/images/i128_graphs/windows/x86_relative_performance.png similarity index 100% rename from doc/img/i128_graphs/windows/x86_relative_performance.png rename to doc/modules/ROOT/images/i128_graphs/windows/x86_relative_performance.png diff --git a/doc/img/u128_graphs/linux/ARM32_benchmarks.png b/doc/modules/ROOT/images/u128_graphs/linux/ARM32_benchmarks.png similarity index 100% rename from doc/img/u128_graphs/linux/ARM32_benchmarks.png rename to doc/modules/ROOT/images/u128_graphs/linux/ARM32_benchmarks.png diff --git a/doc/img/u128_graphs/linux/ARM32_relative_performance.png b/doc/modules/ROOT/images/u128_graphs/linux/ARM32_relative_performance.png similarity index 100% rename from doc/img/u128_graphs/linux/ARM32_relative_performance.png rename to doc/modules/ROOT/images/u128_graphs/linux/ARM32_relative_performance.png diff --git a/doc/img/u128_graphs/linux/ARM64_benchmarks.png b/doc/modules/ROOT/images/u128_graphs/linux/ARM64_benchmarks.png similarity index 100% rename from doc/img/u128_graphs/linux/ARM64_benchmarks.png rename to doc/modules/ROOT/images/u128_graphs/linux/ARM64_benchmarks.png diff --git a/doc/img/u128_graphs/linux/ARM64_relative_performance.png b/doc/modules/ROOT/images/u128_graphs/linux/ARM64_relative_performance.png similarity index 100% rename from doc/img/u128_graphs/linux/ARM64_relative_performance.png rename to doc/modules/ROOT/images/u128_graphs/linux/ARM64_relative_performance.png diff --git a/doc/img/u128_graphs/linux/ppc64le_benchmarks.png b/doc/modules/ROOT/images/u128_graphs/linux/ppc64le_benchmarks.png similarity index 100% rename from doc/img/u128_graphs/linux/ppc64le_benchmarks.png rename to doc/modules/ROOT/images/u128_graphs/linux/ppc64le_benchmarks.png diff --git a/doc/img/u128_graphs/linux/ppc64le_relative_performance.png b/doc/modules/ROOT/images/u128_graphs/linux/ppc64le_relative_performance.png similarity index 100% rename from doc/img/u128_graphs/linux/ppc64le_relative_performance.png rename to doc/modules/ROOT/images/u128_graphs/linux/ppc64le_relative_performance.png diff --git a/doc/img/u128_graphs/linux/s390x_benchmarks.png b/doc/modules/ROOT/images/u128_graphs/linux/s390x_benchmarks.png similarity index 100% rename from doc/img/u128_graphs/linux/s390x_benchmarks.png rename to doc/modules/ROOT/images/u128_graphs/linux/s390x_benchmarks.png diff --git a/doc/img/u128_graphs/linux/s390x_relative_performance.png b/doc/modules/ROOT/images/u128_graphs/linux/s390x_relative_performance.png similarity index 100% rename from doc/img/u128_graphs/linux/s390x_relative_performance.png rename to doc/modules/ROOT/images/u128_graphs/linux/s390x_relative_performance.png diff --git a/doc/img/u128_graphs/linux/x64_benchmarks.png b/doc/modules/ROOT/images/u128_graphs/linux/x64_benchmarks.png similarity index 100% rename from doc/img/u128_graphs/linux/x64_benchmarks.png rename to doc/modules/ROOT/images/u128_graphs/linux/x64_benchmarks.png diff --git a/doc/img/u128_graphs/linux/x64_relative_performance.png b/doc/modules/ROOT/images/u128_graphs/linux/x64_relative_performance.png similarity index 100% rename from doc/img/u128_graphs/linux/x64_relative_performance.png rename to doc/modules/ROOT/images/u128_graphs/linux/x64_relative_performance.png diff --git a/doc/img/u128_graphs/linux/x86_benchmarks.png b/doc/modules/ROOT/images/u128_graphs/linux/x86_benchmarks.png similarity index 100% rename from doc/img/u128_graphs/linux/x86_benchmarks.png rename to doc/modules/ROOT/images/u128_graphs/linux/x86_benchmarks.png diff --git a/doc/img/u128_graphs/linux/x86_relative_performance.png b/doc/modules/ROOT/images/u128_graphs/linux/x86_relative_performance.png similarity index 100% rename from doc/img/u128_graphs/linux/x86_relative_performance.png rename to doc/modules/ROOT/images/u128_graphs/linux/x86_relative_performance.png diff --git a/doc/img/u128_graphs/macos/ARM64_benchmarks.png b/doc/modules/ROOT/images/u128_graphs/macos/ARM64_benchmarks.png similarity index 100% rename from doc/img/u128_graphs/macos/ARM64_benchmarks.png rename to doc/modules/ROOT/images/u128_graphs/macos/ARM64_benchmarks.png diff --git a/doc/img/u128_graphs/macos/ARM64_relative_performance.png b/doc/modules/ROOT/images/u128_graphs/macos/ARM64_relative_performance.png similarity index 100% rename from doc/img/u128_graphs/macos/ARM64_relative_performance.png rename to doc/modules/ROOT/images/u128_graphs/macos/ARM64_relative_performance.png diff --git a/doc/img/u128_graphs/macos/x64_benchmarks.png b/doc/modules/ROOT/images/u128_graphs/macos/x64_benchmarks.png similarity index 100% rename from doc/img/u128_graphs/macos/x64_benchmarks.png rename to doc/modules/ROOT/images/u128_graphs/macos/x64_benchmarks.png diff --git a/doc/img/u128_graphs/macos/x64_relative_performance.png b/doc/modules/ROOT/images/u128_graphs/macos/x64_relative_performance.png similarity index 100% rename from doc/img/u128_graphs/macos/x64_relative_performance.png rename to doc/modules/ROOT/images/u128_graphs/macos/x64_relative_performance.png diff --git a/doc/img/u128_graphs/windows/arm64_benchmarks.png b/doc/modules/ROOT/images/u128_graphs/windows/arm64_benchmarks.png similarity index 100% rename from doc/img/u128_graphs/windows/arm64_benchmarks.png rename to doc/modules/ROOT/images/u128_graphs/windows/arm64_benchmarks.png diff --git a/doc/img/u128_graphs/windows/arm64_relative_performance.png b/doc/modules/ROOT/images/u128_graphs/windows/arm64_relative_performance.png similarity index 100% rename from doc/img/u128_graphs/windows/arm64_relative_performance.png rename to doc/modules/ROOT/images/u128_graphs/windows/arm64_relative_performance.png diff --git a/doc/img/u128_graphs/windows/x64_benchmarks.png b/doc/modules/ROOT/images/u128_graphs/windows/x64_benchmarks.png similarity index 100% rename from doc/img/u128_graphs/windows/x64_benchmarks.png rename to doc/modules/ROOT/images/u128_graphs/windows/x64_benchmarks.png diff --git a/doc/img/u128_graphs/windows/x64_relative_performance.png b/doc/modules/ROOT/images/u128_graphs/windows/x64_relative_performance.png similarity index 100% rename from doc/img/u128_graphs/windows/x64_relative_performance.png rename to doc/modules/ROOT/images/u128_graphs/windows/x64_relative_performance.png diff --git a/doc/img/u128_graphs/windows/x86_benchmarks.png b/doc/modules/ROOT/images/u128_graphs/windows/x86_benchmarks.png similarity index 100% rename from doc/img/u128_graphs/windows/x86_benchmarks.png rename to doc/modules/ROOT/images/u128_graphs/windows/x86_benchmarks.png diff --git a/doc/img/u128_graphs/windows/x86_relative_performance.png b/doc/modules/ROOT/images/u128_graphs/windows/x86_relative_performance.png similarity index 100% rename from doc/img/u128_graphs/windows/x86_relative_performance.png rename to doc/modules/ROOT/images/u128_graphs/windows/x86_relative_performance.png diff --git a/doc/modules/ROOT/nav.adoc b/doc/modules/ROOT/nav.adoc new file mode 100644 index 00000000..e93bb1fc --- /dev/null +++ b/doc/modules/ROOT/nav.adoc @@ -0,0 +1,60 @@ +* xref:overview.adoc[] +* xref:examples.adoc[] +** xref:examples.adoc#examples_construction[Basic Construction] +** xref:examples.adoc#examples_arithmetic[Basic Arithmetic] +** xref:examples.adoc#examples_io[IO Streaming] +** xref:examples.adoc#examples_bit[`` support] +** xref:examples.adoc#examples_numeric[`` support] +** xref:examples.adoc#examples_mixed_sign[Mixed Signedness Arithmetic] +** xref:examples.adoc#examples_boost_math_random[Boost Math and Random Integration] +** xref:examples.adoc#examples_boost_charconv[Boost.Charconv Integration] +* xref:api_reference.adoc[] +** xref:api_reference.adoc#api_namespaces[Namespaces] +** xref:api_reference.adoc#api_types[Types] +** xref:api_reference.adoc#api_literals[Literals] +** xref:api_reference.adoc#api_structs[Structs] +** xref:api_reference.adoc#api_functions[Functions] +*** xref:api_reference.adoc#api_bit[``] +*** xref:api_reference.adoc#api_cstdlib[``] +*** xref:api_reference.adoc#api_charconv[``] +*** xref:api_reference.adoc#api_cmath[``] +*** xref:api_reference.adoc#api_iostream[``] +*** xref:api_reference.adoc#api_ios[``] +*** xref:api_reference.adoc#api_numeric[``] +** xref:api_reference.adoc#api_macros[Macros] +*** xref:api_reference.adoc#api_macro_literals[Literals] +*** xref:api_reference.adoc#api_macro_configuration[Configuration] +* xref:uint128_t.adoc[] +** xref:uint128_t.adoc#u128_alignment[Alignment] +** xref:uint128_t.adoc#u128_operator_behavior[Operator Behavior] +** xref:uint128_t.adoc#u128_constructors[Constructors] +** xref:uint128_t.adoc#u128_conversions[Conversion Operators] +** xref:uint128_t.adoc#u128_comparison_operators[Comparison Operators] +** xref:uint128_t.adoc#u128_bitwise_operators[Bitwise Operators] +** xref:uint128_t.adoc#u128_math_operators[Mathematical Operators] +* xref:int128_t.adoc[] +** xref:int128_t.adoc#i128_alignment[Alignment] +** xref:int128_t.adoc#i128_operator_behavior[Operator Behavior] +** xref:int128_t.adoc#i128_constructors[Constructors] +** xref:int128_t.adoc#i128_conversions[Conversion Operators] +** xref:int128_t.adoc#i128_comparison_operators[Comparison Operators] +** xref:int128_t.adoc#i128_bitwise_operators[Bitwise Operators] +** xref:int128_t.adoc#i128_math_operators[Mathematical Operators] +* xref:mixed_type_ops.adoc[] +* xref:literals.adoc[] +* xref:bit.adoc[] +* xref:cstdlib.adoc[] +* xref:charconv.adoc[] +* xref:stream.adoc[] +* xref:numeric.adoc[] +* Benchmarks +** xref:u128_benchmarks.adoc[] +*** xref:u128_benchmarks.adoc#u128_linux[Linux] +*** xref:u128_benchmarks.adoc#u128_windows[Windows] +*** xref:u128_benchmarks.adoc#u128_mac[macOS] +** xref:i128_benchmarks.adoc[] +*** xref:i128_benchmarks.adoc#i128_linux[Linux] +*** xref:i128_benchmarks.adoc#i128_windows[Windows] +*** xref:i128_benchmarks.adoc#i128_mac[macOS] +* xref:reference.adoc[] +* xref:copyright.adoc[] diff --git a/doc/modules/ROOT/pages/api_reference.adoc b/doc/modules/ROOT/pages/api_reference.adoc new file mode 100644 index 00000000..f5eb8159 --- /dev/null +++ b/doc/modules/ROOT/pages/api_reference.adoc @@ -0,0 +1,316 @@ +//// +Copyright 2025 Matt Borland +Distributed under the Boost Software License, Version 1.0. +https://www.boost.org/LICENSE_1_0.txt +//// + +[#api_reference] += API Reference +:idprefix: api_ref_ + +[#api_namespaces] +== Namespaces + +[cols="1,2", options="header"] +|=== +| Namespace | Description + +| `boost::int128` +| Contains all components of the library except `` functionality + +| xref:literals.adoc[`boost::int128::literals`] +| User-defined literals for 128-bit integers +|=== + +[#api_types] +== Types + +[cols="1,2", options="header"] +|=== +| Type | Description + +| xref:uint128_t.adoc[`uint128_t`] +| Unsigned 128-bit integer + +| xref:int128_t.adoc[`int128_t`] +| Signed 128-bit integer +|=== + +[#api_literals] +== Literals + +[cols="1,2", options="header"] +|=== +| Literal | Description + +| xref:literals.adoc[`_u128`] +| Unsigned 128-bit literal (lowercase) + +| xref:literals.adoc[`_U128`] +| Unsigned 128-bit literal (uppercase) + +| xref:literals.adoc[`_i128`] +| Signed 128-bit literal (lowercase) + +| xref:literals.adoc[`_I128`] +| Signed 128-bit literal (uppercase) +|=== + +[#api_structs] +== Structures + +[cols="1,2", options="header"] +|=== +| Structure | Description + +| https://en.cppreference.com/w/cpp/types/numeric_limits[`std::numeric_limits`] +| Numeric limits specialization for `uint128_t` + +| https://en.cppreference.com/w/cpp/types/numeric_limits[`std::numeric_limits`] +| Numeric limits specialization for `int128_t` + +| xref:cstdlib.adoc#div_structs[`u128div_t`] +| Result type for `div(uint128_t, uint128_t)` + +| xref:cstdlib.adoc#div_structs[`i128div_t`] +| Result type for `div(int128_t, int128_t)` +|=== + +[#api_functions] +== Functions + +Listed by analogous STL header. + +[#api_bit] +=== xref:bit.adoc[``] + +[cols="1,2", options="header"] +|=== +| Function | Description + +| xref:bit.adoc#has_single_bit[`has_single_bit`] +| Checks if value is a power of two + +| xref:bit.adoc#countl_zero[`countl_zero`] +| Counts leading zeros + +| xref:bit.adoc#countl_one[`countl_one`] +| Counts leading ones + +| xref:bit.adoc#bit_width[`bit_width`] +| Returns minimum bits needed to represent value + +| xref:bit.adoc#bit_ceil[`bit_ceil`] +| Rounds up to nearest power of two + +| xref:bit.adoc#bit_floor[`bit_floor`] +| Rounds down to nearest power of two + +| xref:bit.adoc#countr_zero[`countr_zero`] +| Counts trailing zeros + +| xref:bit.adoc#countr_one[`countr_one`] +| Counts trailing ones + +| xref:bit.adoc#rotl[`rotl`] +| Rotates bits left + +| xref:bit.adoc#rotr[`rotr`] +| Rotates bits right + +| xref:bit.adoc#popcount[`popcount`] +| Counts number of set bits + +| xref:bit.adoc#byteswap[`byteswap`] +| Reverses byte order +|=== + +[#api_charconv] +=== xref:charconv.adoc[``] + +[cols="1,2", options="header"] +|=== +| Function | Description + +| xref:charconv.adoc#to_chars[`to_chars`] +| Converts integer to character sequence + +| xref:charconv.adoc#from_chars[`from_chars`] +| Converts character sequence to integer +|=== + +[#api_cmath] +=== `` + +[cols="1,2", options="header"] +|=== +| Function | Description + +| `abs` +| Absolute value +|=== + +[#api_cstdlib] +=== xref:cstdlib.adoc[``] + +[cols="1,2", options="header"] +|=== +| Function | Description + +| xref:cstdlib.adoc[`div`] +| Computes quotient and remainder simultaneously +|=== + +[#api_formatting] +=== xref:format.adoc[Formatting] + +[cols="1,2", options="header"] +|=== +| Library | Description + +| xref:format.adoc#std_format[``] +| C++20 `std::format` support + +| xref:format.adoc#fmt_format[`pass:[{fmt}]`] +| `pass:[{fmt}]` library support +|=== + +[#api_iostream] +=== xref:stream.adoc[``] + +[cols="1,2", options="header"] +|=== +| Operator | Description + +| xref:stream.adoc#stream[`operator<<`] +| Stream insertion operator + +| xref:stream.adoc#stream[`operator>>`] +| Stream extraction operator +|=== + +[#api_ios] +=== xref:stream.adoc#ios[``] + +[cols="1,2", options="header"] +|=== +| Manipulator | Description + +| xref:stream.adoc#ios[`std::oct`] +| Octal output format + +| xref:stream.adoc#ios[`std::dec`] +| Decimal output format + +| xref:stream.adoc#ios[`std::hex`] +| Hexadecimal output format + +| xref:stream.adoc#ios[`std::uppercase`] +| Uppercase hex digits + +| xref:stream.adoc#ios[`std::nouppercase`] +| Lowercase hex digits +|=== + +[#api_numeric] +=== xref:numeric.adoc[``] + +[cols="1,2", options="header"] +|=== +| Function | Description + +| xref:numeric.adoc#sat_arith[`add_sat`] +| Saturating addition + +| xref:numeric.adoc#sat_arith[`sub_sat`] +| Saturating subtraction + +| xref:numeric.adoc#sat_arith[`mul_sat`] +| Saturating multiplication + +| xref:numeric.adoc#sat_arith[`div_sat`] +| Saturating division + +| xref:numeric.adoc#saturating_cast[`saturate_cast`] +| Saturating type cast + +| xref:numeric.adoc#gcd[`gcd`] +| Greatest common divisor + +| xref:numeric.adoc#lcm[`lcm`] +| Least common multiple + +| xref:numeric.adoc#midpoint[`midpoint`] +| Midpoint between two values +|=== + +[#api_macros] +== Macros + +[#api_macro_literals] +=== Constants (``) + +[cols="1,2", options="header"] +|=== +| Macro | Description + +| `BOOST_INT128_UINT128_MAX` +| Maximum value for `uint128_t` + +| `BOOST_INT128_INT128_MAX` +| Maximum value for `int128_t` + +| `BOOST_INT128_INT128_MIN` +| Minimum value for `int128_t` +|=== + +=== Literals + +[cols="1,2", options="header"] +|=== +| Macro | Description + +| xref:literals.adoc[`BOOST_INT128_UINT128_C`] +| Unsigned 128-bit constant macro + +| xref:literals.adoc[`BOOST_INT128_INT128_C`] +| Signed 128-bit constant macro +|=== + +[#api_macro_configuration] +=== Configuration + +==== User Configuration + +[cols="1,2", options="header"] +|=== +| Macro | Description + +| xref:config.adoc#no_int128[`BOOST_INT128_NO_BUILTIN_INT128`] +| Disables use of compiler built-in `__int128` + +| xref:config.adoc#sign_compare[`BOOST_INT128_ALLOW_SIGN_COMPARE`] +| Allows comparison between signed and unsigned types + +| xref:config.adoc#sign_conversion[`BOOST_INT128_ALLOW_SIGN_CONVERSION`] +| Allows implicit sign conversion + +| xref:config.adoc#disable_exceptions[`BOOST_INT128_DISABLE_EXCEPTIONS`] +| Disables exception throwing +|=== + +==== Automatic Configuration + +[cols="1,2", options="header"] +|=== +| Macro | Description + +| xref:config.adoc#automatic_config[`BOOST_INT128_HAS_INT128`] +| Defined if compiler provides `__int128` + +| xref:config.adoc#automatic_config[`BOOST_INT128_ENDIAN_LITTLE_BYTE`] +| Defined on little-endian systems + +| xref:config.adoc#automatic_config[`BOOST_INT128_ENDIAN_BIG_BYTE`] +| Defined on big-endian systems +|=== \ No newline at end of file diff --git a/doc/int128/bit.adoc b/doc/modules/ROOT/pages/bit.adoc similarity index 86% rename from doc/int128/bit.adoc rename to doc/modules/ROOT/pages/bit.adoc index 11096bb6..f9bfe4eb 100644 --- a/doc/int128/bit.adoc +++ b/doc/modules/ROOT/pages/bit.adoc @@ -8,9 +8,14 @@ https://www.boost.org/LICENSE_1_0.txt = `` :idprefix: bit_ -The following are functions analogous to those found in C\++20's https://en.cppreference.com/w/cpp/header/bit[] header, but for `boost::int128::uint128_t`. -None of these functions applied to signed integral types, and thus none have overloads for `boost::int128::int128_t`. -All of these functions are available using C ++14 like the rest of the library. +[source,c++] +---- +#include +---- + +The following are functions analogous to those found in pass:[C++20] https://en.cppreference.com/w/cpp/header/bit[] header, but for `boost::int128::uint128_t`. +None of these functions apply to signed integral types, and thus none have overloads for `boost::int128::int128_t`. +All of these functions are available using pass:[C++14] like the rest of the library. [#has_single_bit] == has_single_bit @@ -36,7 +41,6 @@ Returns the number of consecutive `0` bits in the value `x`, starting from the m [source,c++] ---- - namespace boost { namespace int128 { @@ -44,7 +48,6 @@ constexpr int countl_zero(uint128_t x) noexcept; } // namespace int128 } // namespace boost - ---- [#countl_one] @@ -54,7 +57,6 @@ Returns the number of consecutive `1` bits in the value `x`, starting from the m [source,c++] ---- - namespace boost { namespace int128 { @@ -62,7 +64,6 @@ constexpr int countl_one(uint128_t x) noexcept; } // namespace int128 } // namespace boost - ---- [#bit_width] @@ -73,7 +74,6 @@ If `x` is zero, returns 0 [source,c++] ---- - namespace boost { namespace int128 { @@ -81,7 +81,6 @@ constexpr int bit_width(uint128_t x) noexcept; } // namespace int128 } // namespace boost - ---- [#bit_ceil] @@ -103,7 +102,7 @@ constexpr uint128_t bit_ceil(uint128_t x) noexcept; [#bit_floor] == bit_floor -Returns the smallest integral power of two that is not greater than `x`. +Returns the largest integral power of two that is not greater than `x`. If `x` is 0 then returns 0. [source, c++] @@ -124,7 +123,6 @@ Returns the number of consecutive `0` bits in the value `x`, starting from the l [source,c++] ---- - namespace boost { namespace int128 { @@ -132,7 +130,6 @@ constexpr int countr_zero(uint128_t x) noexcept; } // namespace int128 } // namespace boost - ---- [#countr_one] @@ -142,7 +139,6 @@ Returns the number of consecutive `1` bits in the value `x`, starting from the l [source,c++] ---- - namespace boost { namespace int128 { @@ -150,7 +146,6 @@ constexpr int countr_one(uint128_t x) noexcept; } // namespace int128 } // namespace boost - ---- [#rotl] @@ -161,7 +156,6 @@ This operation is also known as a left circular shift. [source,c++] ---- - namespace boost { namespace int128 { @@ -169,7 +163,6 @@ constexpr uint128_t rotl(uint128_t x, int s) noexcept; } // namespace int128 } // namespace boost - ---- [#rotr] @@ -180,7 +173,6 @@ This operation is also known as a right circular shift. [source,c++] ---- - namespace boost { namespace int128 { @@ -188,7 +180,6 @@ constexpr uint128_t rotr(uint128_t x, int s) noexcept; } // namespace int128 } // namespace boost - ---- [#popcount] @@ -198,7 +189,6 @@ Returns the number of `1` bits in `x`. [source,c++] ---- - namespace boost { namespace int128 { @@ -206,7 +196,6 @@ constexpr int popcount(uint128_t x) noexcept; } // namespace int128 } // namespace boost - ---- [#byteswap] @@ -216,14 +205,12 @@ Reverses the bytes in the given integer value `x`. [source,c++] ---- - namespace boost { namespace int128 { -constexpr int byteswap(uint128_t x) noexcept; +constexpr uint128_t byteswap(uint128_t x) noexcept; } // namespace int128 } // namespace boost - ---- diff --git a/doc/int128/charconv.adoc b/doc/modules/ROOT/pages/charconv.adoc similarity index 55% rename from doc/int128/charconv.adoc rename to doc/modules/ROOT/pages/charconv.adoc index 75b67c6a..ff1dfe27 100644 --- a/doc/int128/charconv.adoc +++ b/doc/modules/ROOT/pages/charconv.adoc @@ -10,13 +10,13 @@ https://www.boost.org/LICENSE_1_0.txt The following functions are all overloads injected into https://www.boost.org/doc/libs/master/libs/charconv/doc/html/charconv.html[Boost.Charconv]. -IMPORTANT: Unlike the rest of the library, using this header depends on Boost.Charconv being present. This header will `#error` if Boost.Charconv is missing +IMPORTANT: Unlike the rest of the library, using this header depends on the headers of Boost.Charconv being present, otherwise it will `#error`. [#to_chars] == to_chars `to_chars` is a set of functions that attempts to convert `value` into a character buffer specified by `[first, last)`. -For full documentation and explanation see the Boost.Charconv https://www.boost.org/doc/libs/master/libs/charconv/doc/html/charconv.html[`to_chars` docs] +For full documentation and explanation see the https://www.boost.org/doc/libs/develop/libs/charconv/doc/html/charconv.html[Boost.Charconv documentation]. [source,c++] ---- @@ -25,21 +25,35 @@ For full documentation and explanation see the Boost.Charconv https://www.boost. namespace boost { namespace charconv { -BOOST_CHARCONV_CONSTEXPR to_chars(char* first, char* last, int128::uint128_t, int base = 10) noexcept; +struct to_chars_result +{ + char* ptr; + std::errc ec; -BOOST_CHARCONV_CONSTEXPR to_chars(char* first, char* last, int128::int128_t, int base = 10) noexcept; + friend constexpr bool operator==(const to_chars_result& lhs, const to_chars_result& rhs) noexcept = default; + constexpr explicit operator bool() const noexcept { return ec == std::errc{}; } +}; + + +BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, int128::uint128_t value, int base = 10) noexcept; + +BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, int128::int128_t value, int base = 10) noexcept; } // namespace charconv } // namespace boost ---- +`BOOST_CHARCONV_CONSTEXPR` is defined as `constexpr` when using a compiler with pass:[__builtin_is_constant_evaluated], +or pass:[c++20] with `std::is_constant_evaluated()`. +Otherwise, it is defined as `inline`. + NOTE: These functions are in the namespace `boost::charconv`, and not `boost::int128` [#from_chars] == from_chars `from_chars` is a set of functions that parse a string from `[first, last)` in an attempt to convert the string into value according to the chars_format specified (if applicable). -For full documentation and explanation see the Boost.Charconv https://www.boost.org/doc/libs/master/libs/charconv/doc/html/charconv.html[`from_chars` docs] +For full documentation and explanation see the https://www.boost.org/doc/libs/develop/libs/charconv/doc/html/charconv.html[Boost.Charconv documentation]. [source,c++] ---- @@ -48,6 +62,15 @@ For full documentation and explanation see the Boost.Charconv https://www.boost. namespace boost { namespace charconv { +struct from_chars_result +{ + const char* ptr; + std::errc ec; + + friend constexpr bool operator==(const from_chars_result& lhs, const from_chars_result& rhs) noexcept = default; + constexpr explicit operator bool() const noexcept { return ec == std::errc{}; } +}; + constexpr from_chars_result from_chars(const char* first, const char* last, int128::uint128_t& value, int base = 10) noexcept; // Allows both std::string and std::string_view (when available) @@ -60,5 +83,4 @@ constexpr from_chars_result from_chars(core::string_view sv, int128::int128_t& v } // namespace charconv } // namespace boost - ---- diff --git a/doc/modules/ROOT/pages/config.adoc b/doc/modules/ROOT/pages/config.adoc new file mode 100644 index 00000000..701e0a46 --- /dev/null +++ b/doc/modules/ROOT/pages/config.adoc @@ -0,0 +1,44 @@ +//// +Copyright 2025 Matt Borland +Distributed under the Boost Software License, Version 1.0. +https://www.boost.org/LICENSE_1_0.txt +//// + +[#configuration] += Configuration Macros +:idprefix: config_ + +[source,c++] +---- +#include +---- + +== User Configurable Macros + +These macros allow customization of library behavior. User-configurable macros should be defined before including any library headers. + +[#no_int128] +- `BOOST_INT128_NO_BUILTIN_INT128`: The user may define this when they do not want the internal implementations to rely on builtin `pass:[__int128]` or `pass:[unsigned __int128]` types. + +[#sign_compare] +- `BOOST_INT128_ALLOW_SIGN_COMPARE`: Allows comparisons between this library's types and built-in types of opposite signedness. Analogous to disabling GCC's `-Wsign-compare` warning. + +IMPORTANT: NOT DEFINED BY DEFAULT FOR CORRECTNESS + +[#sign_conversion] +- `BOOST_INT128_ALLOW_SIGN_CONVERSION`: Allows arithmetic operations between this library's types and built-in types of opposite signedness. Analogous to disabling GCC's `-Wsign-conversion` warning. Implies `BOOST_INT128_ALLOW_SIGN_COMPARE`. + +IMPORTANT: NOT DEFINED BY DEFAULT FOR CORRECTNESS + +[#disable_exceptions] +- `BOOST_INT128_DISABLE_EXCEPTIONS`: Allows exceptions to be disabled. +This macro will automatically be defined in the presence of `-fno-exceptions` or similar MSVC flags. + +[#automatic_config] +== Automatic Configuration Macros + +- `BOOST_INT128_HAS_INT128`: This is defined when compiling on a platform that has builtin `pass:[__int128]` or `pass:[unsigned __int128]` types (e.g. `pass:[__x86_64__]`). + +- `BOOST_INT128_ENDIAN_LITTLE_BYTE`: This is defined to `1` when compiling on a little endian architecture, otherwise `0`. + +- `BOOST_INT128_ENDIAN_BIG_BYTE`: This is defined to `1` when compiling on a big endian architecture, otherwise `0`. diff --git a/doc/int128/copyright.adoc b/doc/modules/ROOT/pages/copyright.adoc similarity index 100% rename from doc/int128/copyright.adoc rename to doc/modules/ROOT/pages/copyright.adoc diff --git a/doc/int128/cstdlib.adoc b/doc/modules/ROOT/pages/cstdlib.adoc similarity index 78% rename from doc/int128/cstdlib.adoc rename to doc/modules/ROOT/pages/cstdlib.adoc index 1245453e..de43ed55 100644 --- a/doc/int128/cstdlib.adoc +++ b/doc/modules/ROOT/pages/cstdlib.adoc @@ -8,15 +8,20 @@ https://www.boost.org/LICENSE_1_0.txt = `` :idprefix: cstdlib_ -From the `` header we support functions and structures that are analogous to https://en.cppreference.com/w/cpp/numeric/math/div.html[`std::div`]. +From the `` header we support functions and structures that are analogous to https://en.cppreference.com/w/cpp/numeric/math/div[`std::div`]. These are of particular importance with this library since unlike a hardware type, the compiler may not be able to optimize a division followed by a modulo operation. Knuth's algorithm naturally returns both so it costs nearly nothing above a division or modulo to get both results. -[#div_structs] [source, c++] ---- #include +---- +[#div_structs] +== Structures + +[source, c++] +---- namespace boost { namespace int128 { @@ -34,16 +39,15 @@ struct i128div_t } // namespace int128 } // namespace boost - ---- [#div_source] -Using the `struct`s defined above we can then define the `div` function: +== div + +Using the structures defined above, the `div` function computes both quotient and remainder simultaneously: [source, c++] ---- -#include - namespace boost { namespace int128 { @@ -55,4 +59,4 @@ constexpr i128div_t div(int128_t lhs, int128_t rhs) noexcept; } // namespace boost ---- -The result of `quot` and `rem` from this function, to include the sign, are the same as if you did a division and modulo separately. +The result of `quot` and `rem` from this function, including the sign, are the same as if you performed division and modulo separately. diff --git a/doc/modules/ROOT/pages/examples.adoc b/doc/modules/ROOT/pages/examples.adoc new file mode 100644 index 00000000..ee1a5de9 --- /dev/null +++ b/doc/modules/ROOT/pages/examples.adoc @@ -0,0 +1,445 @@ +//// +Copyright 2025 Matt Borland +Distributed under the Boost Software License, Version 1.0. +https://www.boost.org/LICENSE_1_0.txt +//// + +[#examples] += Examples +:idprefix: examples_ + +All the following examples can be found in the examples/ folder of the library. + +[#examples_construction] +== Basic Construction + +.This https://github.com/cppalliance/int128/blob/develop/examples/construction.cpp[example] demonstrates the various ways to construct uint128_t and int128_t values +==== +[source, c++] +---- +include::example$construction.cpp[] +---- + +.Expected Output +[listing] +---- +=== uint128_t Construction === +From builtin (42U): 42 +From parts (1, 0) = 2^64: 18446744073709551616 +From parts (max, max): 340282366920938463463374607431768211455 + Equals numeric_limits max? true +From literal "36893488147419103232"_U128: 36893488147419103232 +From BOOST_INT128_UINT128_C(max): 340282366920938463463374607431768211455 +From stringstream: 12345678901234567890123456789 + +=== int128_t Construction === +From builtin (-42): -42 +From parts (INT64_MIN, 0): -170141183460469231731687303715884105728 + Equals numeric_limits min? true +From literal "-99999999999999999999"_i128: -99999999999999999999 +From literal "99999999999999999999"_I128: 99999999999999999999 +From BOOST_INT128_INT128_C(min): -170141183460469231731687303715884105728 + +=== Default and Copy Construction === +Default constructed: 0 +Copy constructed: 36893488147419103232 +---- +==== + +[#examples_arithmetic] +== Basic Arithmetic + +.This https://github.com/cppalliance/int128/blob/develop/examples/basic_arithmetic.cpp[example] demonstrates arithmetic operations with 128-bit integers +==== +[source, c++] +---- +include::example$basic_arithmetic.cpp[] +---- + +.Expected Output +[listing] +---- +=== Signed 128-bit Arithmetic === +x = 1000000000000 +y = 999999999999 + +Addition and Subtraction: +x + y = 1999999999999 +x - y = 1 + +Multiplication (exceeds 64-bit range): +x * y = 999999999999000000000000 + +Division and Modulo: +x / 7 = 142857142857 +x % 7 = 1 + +Comparisons: +x > y: true +x == y: false +x != y: true + +Negative values: +negative = -42 +abs(negative) = 42 + +Compound assignment operators: +z = 100 +z += 50: 150 +z -= 25: 125 +z *= 2: 250 +z /= 5: 50 +z %= 7: 1 + +=== Unsigned 128-bit Arithmetic === +large (2^64) = 18446744073709551616 +large * 2 = 36893488147419103232 +large + large = 36893488147419103232 + +Increment and Decrement: +counter = 10 +++counter = 11 +counter++ = 11 +counter = 12 +--counter = 11 +---- +==== + +[#examples_io] +== IO Streaming + +.This https://github.com/cppalliance/int128/blob/develop/examples/stream.cpp[example] demonstrates iostream support and string conversions +==== +[source, c++] +---- +include::example$stream.cpp[] +---- + +.Expected Output +[listing] +---- +=== Basic Streaming === +Signed value: -42 +Unsigned value (dec): 36893488147419103231 +Unsigned value (hex): 0x1ffffffffffffffff +Unsigned value (oct): 03777777777777777777777 +Upper unsigned value: 0X1FFFFFFFFFFFFFFFF +Lower unsigned value: 36893488147419103231 + +=== Large Values (Beyond 64-bit) === +2^64 = 18446744073709551616 +2^100 = 1267650600228229401496703205376 +uint128_t max = 340282366920938463463374607431768211455 +int128_t min = -170141183460469231731687303715884105728 +int128_t max = 170141183460469231731687303715884105727 + +=== String Conversion with std::stringstream === +uint128_t to string: "1267650600228229401496703205376" +String to uint128_t: 123456789012345678901234567890 + +=== Round-trip Conversion === +Original: 68915718020162848918556923512 +As string: "68915718020162848918556923512" +Round-tripped: 68915718020162848918556923512 +Match: true +---- +==== + +[#examples_rollover] +== Rollover Behavior + +.This https://github.com/cppalliance/int128/blob/develop/examples/rollover.cpp[example] demonstrates the rollover behavior of both the unsigned and signed type +==== +[source, c++] +---- +include::example$rollover.cpp[] +---- + +.Expected Output +[listing] +---- +=== uint128_t behavior === +Max of uint128_t: 340282366920938463463374607431768211455 +Max + 1U: 0 + +Min of uint128_t: 0 +Min - 1U: 340282366920938463463374607431768211455 + +=== int128_t behavior === +Max of int128_t: 170141183460469231731687303715884105727 +Max + 1: -170141183460469231731687303715884105728 + +Min of int128_t: -170141183460469231731687303715884105728 +Min - 1: 170141183460469231731687303715884105727 +---- +==== + +[#examples_bit] +== Bitwise Functions () + +.This https://github.com/cppalliance/int128/blob/develop/examples/bit.cpp[example] demonstrates bitwise operations from the header +==== +[source, c++] +---- +include::example$bit.cpp[] +---- +==== + +[#examples_numeric] +== Saturating Arithmetic () + +.This https://github.com/cppalliance/int128/blob/develop/examples/saturating_arithmetic.cpp[example] demonstrates saturating arithmetic operations that clamp to min/max instead of overflowing +==== +[source, c++] +---- +include::example$saturating_arithmetic.cpp[] +---- + +.Expected Output +[listing] +---- +=== Saturating Arithmetic === +uint128_t max = 340282366920938463463374607431768211455 +int128_t max = 170141183460469231731687303715884105727 +int128_t min = -170141183460469231731687303715884105728 + +=== Saturating Addition and Subtraction === +add_sat(uint_max, uint_max) = 340282366920938463463374607431768211455 (saturates to uint_max) +sub_sat(0, uint_max) = 0 (saturates to 0, not underflow) + +=== Saturating Multiplication === +mul_sat(int_max, 2) = 170141183460469231731687303715884105727 (saturates to int_max) +mul_sat(-(int_max - 2), 5) = -170141183460469231731687303715884105728 (saturates to int_min) + +=== Saturating Division === +div_sat(int_min, -1) = 170141183460469231731687303715884105727 (saturates to int_max; normally this overflows) + +=== Saturating Casts === +saturate_cast(uint_max) = 170141183460469231731687303715884105727 (saturates to int_max) +saturate_cast(int_max) = 9223372036854775807 (saturates to INT64_MAX) +saturate_cast(uint_max) = 2147483647 (saturates to INT32_MAX) +---- +==== + +[#examples_mixed_sign] +== Mixed Signedness Arithmetic + +.This https://github.com/cppalliance/int128/blob/develop/examples/mixed_type_arithmetic.cpp[example] demonstrates arithmetic between 128-bit and built-in integer types +==== +[source, c++] +---- +include::example$mixed_type_arithmetic.cpp[] +---- + +.Expected Output +[listing] +---- +=== Mixed Type Arithmetic with uint128_t === +unsigned_value = 3 +unsigned_value + 1 = 4 +unsigned_value - 1 = 2 +unsigned_value * 2 = 6 +unsigned_value / 3 = 1 +unsigned_value % 3 = 0 +unsigned_value + 5 = 8 (same as greater_unsigned_value: 8) + +=== Mixed Type Arithmetic with int128_t === +signed_value = -3 +signed_value + 1U = -2 +signed_value - 4U = -7 +signed_value * 2 = -6 +signed_value / 4U = 0 +---- +==== + +[#examples_boost_math_random] +== Boost.Math and Boost.Random Integration + +.This https://github.com/cppalliance/int128/blob/develop/examples/math_and_random.cpp[example] demonstrates integration with Boost.Math and Boost.Random libraries +==== +[source, c++] +---- +include::example$math_and_random.cpp[] +---- +==== + +[#examples_boost_charconv] +== Boost.Charconv Integration + +.This https://github.com/cppalliance/int128/blob/develop/examples/charconv.cpp[example] demonstrates fast string-to-number and number-to-string conversions using Boost.Charconv +==== +[source, c++] +---- +include::example$charconv.cpp[] +---- + +.Expected Output +[listing] +---- +=== to_chars === +uint128_t max (decimal): 340282366920938463463374607431768211455 +int128_t min (decimal): -170141183460469231731687303715884105728 +uint128_t (hex): 0xdeadbeefcafebabe12345678 +int128_t 511 (octal): 0777 + +=== from_chars === +Parsed "340282366920938463463374607431768211455" + Result: 340282366920938463463374607431768211455 + Equals max? true +Parsed "-170141183460469231731687303715884105728" + Result: -170141183460469231731687303715884105728 + Equals min? true +Parsed hex "DEADBEEFCAFEBABE12345678" + Result: 68915718020162848918556923512 +---- +==== + +[#examples_fmt_format] +== \{fmt} Library Integration + +.This https://github.com/cppalliance/int128/blob/develop/examples/fmt_format.cpp[example] demonstrates formatting with the \{fmt} library including alignment specifiers +==== +[source, c++] +---- +include::example$fmt_format.cpp[] +---- + +.Expected Output +[listing] +---- +=== Basic Formatting === +Default (decimal): 68915718020162848918556923512 +Signed value: -123456789012345678 + +=== Base Specifiers === +Binary: 11111111 +Octal: 377 +Decimal: 255 +Hexadecimal: ff +Hex (upper): FF + +=== Alternate Form (Prefixes) === +Binary with prefix: 0b11111111 +Octal with prefix: 0377 +Hex with prefix: 0xff +Hex upper prefix: 0XFF + +=== Sign Options === +Plus sign: +42 and -42 +Minus only: 42 and -42 +Space sign: 42 and -42 + +=== Zero Padding === +8-digit padding: 00000255 +16-digit padding: 0000000000000255 + +=== Alignment === +Left align: '42 ' +Right align: ' 42' +Center align: ' 42 ' + +=== Alignment with Fill Characters === +Left with *: '42********' +Right with 0: '0000000042' +Center with -: '----42----' + +=== Alignment with Sign === +Right align +: ' +42' +Left align +: '+42 ' +Center align +: ' +42 ' +Right align -: '*******-42' + +=== Alignment with Hex and Prefix === +Right align hex: ' ff' +Left align hex: 'ff ' +Center with prefix: '****0xff****' + +=== Large Values === +uint128_t max: 340282366920938463463374607431768211455 +uint128_t max (hex): 0xffffffffffffffffffffffffffffffff +int128_t min: -170141183460469231731687303715884105728 + +=== Combined Format Specifiers === +Hex with prefix, uppercase, padded: 0XDEADBEEFCAFEBABE12345678 +Signed with plus, padded: -00123456789012345678 +---- +==== + +[#examples_cstdlib] +== Division with Remainder () + +.This https://github.com/cppalliance/int128/blob/develop/examples/cstdlib.cpp[example] demonstrates the div() function that returns both quotient and remainder +==== +[source, c++] +---- +include::example$cstdlib.cpp[] +---- + +.Expected Output +[listing] +---- +=== div() Function === +Returns both quotient and remainder in a single operation + +--- Unsigned Division --- +1000000000000000000 / 7 = 142857142857142857 remainder 1 +Verification: 142857142857142857 * 7 + 1 = 1000000000000000000 + +--- Large Value Division --- +2^100 / 2^50 = 1125899906842624 remainder 0 + +--- Signed Division --- +-100 / 7 = -14 remainder -2 + +--- Sign Combinations --- + 17 / 5 = 3 remainder 2 + 17 / -5 = -3 remainder 2 +-17 / 5 = -3 remainder -2 +-17 / -5 = 3 remainder -2 + +--- Edge Cases --- +3 / 10 = 0 remainder 3 +---- +==== + +[#examples_numeric_algorithms] +== Numeric Algorithms () + +.This https://github.com/cppalliance/int128/blob/develop/examples/numeric_algorithms.cpp[example] demonstrates gcd, lcm, and midpoint algorithms +==== +[source, c++] +---- +include::example$numeric_algorithms.cpp[] +---- + +.Expected Output +[listing] +---- +=== Greatest Common Divisor (gcd) === +gcd(48, 18) = 6 +gcd(123456789012345678, 987654321098765432) = 2 +gcd(2^100, 2^80) = 1208925819614629174706176 (= 2^80) +gcd(-48, 18) = 6 (always positive) + +=== Least Common Multiple (lcm) === +lcm(12, 18) = 36 +lcm(7, 11) = 77 (coprime: lcm = p * q) + +Verifying gcd * lcm = a * b: +gcd(12, 18) * lcm(12, 18) = 216 +12 * 18 = 216 + +=== Midpoint === +midpoint(10, 20) = 15 +midpoint(10, 21) = 15 (rounds toward first arg) +midpoint(21, 10) = 16 (rounds toward first arg) + +--- Overflow-safe midpoint --- +midpoint(uint128_max, uint128_max - 10) = 340282366920938463463374607431768211450 +(This would overflow if computed as (a + b) / 2) + +--- Signed midpoint --- +midpoint(-100, 100) = 0 +midpoint(-100, -50) = -75 +---- +==== \ No newline at end of file diff --git a/doc/modules/ROOT/pages/file_structure.adoc b/doc/modules/ROOT/pages/file_structure.adoc new file mode 100644 index 00000000..c2d645a3 --- /dev/null +++ b/doc/modules/ROOT/pages/file_structure.adoc @@ -0,0 +1,53 @@ +//// +Copyright 2025 Matt Borland +Distributed under the Boost Software License, Version 1.0. +https://www.boost.org/LICENSE_1_0.txt +//// + + +[#structure] += Directory Structure +:idprefix: structure_ + +The entire library can be consumed via ``, or by independently selecting any of the library headers. + +[cols="1,2", options="header"] +|=== +| Header | Description + +| `` +| The complete library (includes all headers below) + +| xref:bit.adoc[``] +| Bit manipulation functions + +| xref:charconv.adoc[``] +| Character conversion (`to_chars`/`from_chars`) + +| xref:api_reference.adoc#api_macro_literals[``] +| C-style limit macros (`BOOST_INT128_INT128_MAX`, etc.) + +| xref:cstdlib.adoc[``] +| Division with quotient and remainder (`div`) + +| xref:format.adoc[``] +| `pass:[{fmt}]` library support + +| xref:format.adoc[``] +| C++20 `std::format` support + +| `` +| Core type definitions (`uint128_t`, `int128_t`) + +| xref:stream.adoc[``] +| Stream insertion/extraction operators + +| xref:api_reference.adoc#api_structs[``] +| `std::numeric_limits` specializations + +| xref:literals.adoc[``] +| User-defined literals (`_u128`, `_i128`) + +| xref:numeric.adoc[``] +| Numeric functions (`gcd`, `lcm`, saturating arithmetic) +|=== diff --git a/doc/modules/ROOT/pages/format.adoc b/doc/modules/ROOT/pages/format.adoc new file mode 100644 index 00000000..40304463 --- /dev/null +++ b/doc/modules/ROOT/pages/format.adoc @@ -0,0 +1,106 @@ +//// +Copyright 2025 Matt Borland +Distributed under the Boost Software License, Version 1.0. +https://www.boost.org/LICENSE_1_0.txt +//// + +[#format] += Formatting Support +:idprefix: format_ + +Boost.Int128 supports formatting with both `` (when pass:[C++20] and the header are both available), and `pass:[]`. +The following modifiers are listed in order of how they should be specified in the format string to be valid, and all information applies for both `` and `pass:[]`. + +== Fill and Alignment + +You can specify alignment with an optional fill character. The format is `[[fill]align]` where: + +[options="header"] +|=== +| Alignment | Effect +| `<` | Left-aligns the value within the available space +| `>` | Right-aligns the value within the available space +| `^` | Centers the value within the available space +|=== + +The optional fill character (default is space) appears before the alignment character. + +Examples: +[options="header"] +|=== +| Format | Output for 42 +| `{:<6d}` | `"42 "` (left-aligned with spaces) +| `{:>6d}` | `" 42"` (right-aligned with spaces) +| `{:^6d}` | `" 42 "` (centered with spaces) +| `{:*<6d}` | `"42****"` (left-aligned with asterisks) +| `{:0>6d}` | `"000042"` (right-aligned with zeros) +| `{:*^6d}` | `"**42**"` (centered with asterisks) +|=== + +NOTE: When no alignment is specified but a width is given (e.g., `{:6d}`), zero-padding is applied from the left. + +== Sign + +There are three allowable signs first in the format string: + +[options="header"] +|=== +| Sign | Effect +| `+` | Adds a `+` to positive values, and a `-` to negative values +| `-` | Only adds a `-` to negative values +| pass:[` `] (Space) | Adds a ` ` to positive values, and a `-` to negative values. Preserves alignment +|=== + +== Padding + +You can then add any number of padding characters to make sure that a formatted value takes up a specified width (5 means minimum width of 5 characters and so on). +Any integer value is accepted here. + +== Prepend Prefix + +If you want to prepend the prefix to your number (if applicable) add `#` + +[options="header"] +|=== +| Output Base | Effect +| Binary | `0b` or `0B` +| Octal | `0` +| Decimal | None +| Hex | `0x` or `0X` +|=== + +== Output Base Modifiers + +The following type modifiers are the same as those used by built-in integer values. + +[options="header"] +|=== +| Modifier | Format +| b, B | Binary +| o | Octal +| d | Decimal +| x, X | Hex +|=== + +NOTE: When the uppercase modifier is used, all characters will be capitalized (e.g. 0x2a vs 0X2A). + +== Default + +The default format string `{}` will output the same as `{:-d}`, that is a decimal value which only has a sign if negative. + +[#fmt_format] +== `pass:[{fmt}]` + +To use the `pass:[{fmt}]` library, include `` and ``. +The format specifiers described above work with `fmt::format`. + +See the xref:examples.adoc#examples_fmt_format[formatting example] for a complete demonstration of these features. + +[#std_format] +== `` + +To use `std::format`, include `` and ``. +The format specifiers described above work with `std::format`. + +The xref:examples.adoc#examples_fmt_format[formatting example] can be trivially modified by including ``, +and replacing all instances of `fmt::` with `std::` diff --git a/doc/int128/i128_benchmarks.adoc b/doc/modules/ROOT/pages/i128_benchmarks.adoc similarity index 99% rename from doc/int128/i128_benchmarks.adoc rename to doc/modules/ROOT/pages/i128_benchmarks.adoc index 541d1d5f..1914394d 100644 --- a/doc/int128/i128_benchmarks.adoc +++ b/doc/modules/ROOT/pages/i128_benchmarks.adoc @@ -15,6 +15,7 @@ On most platforms we use the builtin `\__int128` as the reference benchmark. When this is unavailable (such as on 32-bit architectures) we us `boost::multiprecision::int128_t` (abbreviated as `boost::mp::int128_t`) as it is widely used, and known to be portable. On MSVC platforms we use as reference `std::_Signed128` from the header `<__msvc_int128.hpp>` since this is bundled with their compiler. +[#i128_linux] == Linux === x86_64 @@ -142,6 +143,7 @@ image::i128_graphs/linux/ARM32_benchmarks.png[ARM32 Benchmark Results, width=100 image::i128_graphs/linux/ARM32_relative_performance.png[ARM32 Relative Performance, width=100%] +[#i128_windows] == Windows === x86_64 @@ -201,6 +203,7 @@ image::i128_graphs/windows/x86_benchmarks.png[x86_32 Benchmark Results, width=10 image::i128_graphs/windows/x86_relative_performance.png[x86_32 Relative Performance, width=100%] +[#i128_mac] == macOS === ARM64 (Apple Silicon) diff --git a/doc/modules/ROOT/pages/int128_t.adoc b/doc/modules/ROOT/pages/int128_t.adoc new file mode 100644 index 00000000..a03e6eb7 --- /dev/null +++ b/doc/modules/ROOT/pages/int128_t.adoc @@ -0,0 +1,477 @@ +//// +Copyright 2025 Matt Borland +Distributed under the Boost Software License, Version 1.0. +https://www.boost.org/LICENSE_1_0.txt +//// + +[#int128_t] += int128_t +:idprefix: int128_t_ + +== Description + +`int128_t` is a signed 128-bit integer. + +[source, c++] +---- +#include + +namespace boost { +namespace int128 { + +struct int128_t { + + #if BOOST_INT128_ENDIAN_LITTLE_BYTE + std::uint64_t low {}; + std::int64_t high {}; + #else + std::int64_t high {}; + std::uint64_t low {}; + #endif + + // Constructors, conversion operators, and member operators + // documented in detail below... +}; + +} // namespace int128 +} // namespace boost +---- + +The type provides: + +* Constructors from all built-in integer types and `uint128_t` +* Conversion operators to built-in integer and floating-point types +* Full set of comparison operators (`<`, `<=`, `>`, `>=`, `==`, `!=`) +* Bitwise operators (`~`, `|`, `&`, `^`, `<<`, `>>`) +* Arithmetic operators (`+`, `-`, `*`, `/`, `%`) +* Compound assignment variants of all binary operators +* Increment and decrement operators (`++`, `--`) + +[#i128_alignment] +== Alignment + +If your platform has a native 128-bit signed integer, the struct is defined as so: + +[source, c++] +---- +struct alignas(alignof(__int128)) int128_t +---- + +Otherwise, it is + +[source, c++] +---- +struct alignas(sizeof(std::uint64_t) * 2) int128_t +---- + +[#i128_operator_behavior] +== Operator Behavior + +For all the following operators use of unsigned overloads will error from `static_assert` by default. +This is the library's way of enforcing the behavior of `-Wsign-conversion` and `-Wsign-comparison` in a library type. +If you want to compare with unsigned types you must define `BOOST_INT128_ALLOW_SIGN_COMPARE`, +and similarly you must define `BOOST_INT128_ALLOW_SIGN_CONVERSION` for other operations with mixed signedness. +These will both cast the unsigned integer to a signed integer and then perform the operation. + +[#i128_constructors] +== Constructors + +[source, c++] +---- +namespace boost { +namespace int128 { + +struct int128_t +{ + ... + + // Defaulted basic construction + constexpr int128_t() noexcept = default; + constexpr int128_t(const int128_t&) noexcept = default; + constexpr int128_t(int128_t&&) noexcept = default; + constexpr int128_t& operator=(const int128_t&) noexcept = default; + constexpr int128_t& operator=(int128_t&&) noexcept = default; + + constexpr int128_t(const uint128_t& v) noexcept; + + // Construct from integral types + constexpr int128_t(const std::int64_t hi, const std::uint64_t lo) noexcept; + + template + constexpr int128_t(const SignedInteger v) noexcept; + + template + constexpr int128_t(const UnsignedInteger v) noexcept; + + #ifdef BOOST_INT128_HAS_INT128 + + // Typically a typedef from __int128 + constexpr int128_t(const detail::builtin_i128 v) noexcept; + + // Typically a typedef unsigned __int128 + constexpr int128_t(const detail::builtin_u128 v) noexcept; + + #endif // BOOST_INT128_HAS_INT128 +}; + +} // namespace int128 +} // namespace boost +---- + +All constructors are only defined for integers and are subject to mixed sign limitations discussed xref:int128_t.adoc#i128_operator_behavior[above]. +None are marked `explicit` in order to match the implicit conversion behavior of the built-in integer types. + +[#i128_conversions] +== Conversions + +[source, c++] +---- +namespace boost { +namespace int128 { + +struct int128_t +{ + ... + + // Integer conversion operators + constexpr operator bool() const noexcept; + + template + explicit constexpr operator SignedInteger() const noexcept; + + template + explicit constexpr operator UnsignedInteger() const noexcept; + + #ifdef BOOST_INT128_HAS_INT128 + + explicit constexpr operator detail::builtin_i128() const noexcept; + + explicit constexpr operator detail::builtin_u128() const noexcept; + + #endif // BOOST_INT128_HAS_INT128 + + // Conversion to float + explicit constexpr operator float() const noexcept; + explicit constexpr operator double() const noexcept; + explicit constexpr operator long double() const noexcept; +}; + +} // namespace int128 +} // namespace boost +---- + +Conversions to unsigned integers are subject to mixed sign limitations discussed xref:int128_t.adoc#i128_operator_behavior[above]. +Conversion to `bool` is not marked explicit to match the behavior of built-in integer types. +Conversions to floating point types may not be lossless depending on the value of the `int128_t` at time of conversion, +as the number of digits it represents can exceed the precision of the significand in floating point types. + +[#i128_comparison_operators] +== Comparison Operators + +=== Less Than + +[source, c++] +---- +template +constexpr bool operator<(const int128_t lhs, const Integer rhs) noexcept; + +template +constexpr bool operator<(const Integer lhs, const int128_t rhs) noexcept; + +constexpr bool operator<(const int128_t lhs, const int128_t rhs) noexcept; +---- + +Returns if the `lhs` value is less than the `rhs` value without exception. +This operation is only defined for integers and is subject to mixed sign limitations discussed xref:int128_t.adoc#i128_operator_behavior[above]. + +=== Less Than or Equal To + +[source, c++] +---- +template +constexpr bool operator<=(const int128_t lhs, const Integer rhs) noexcept; + +template +constexpr bool operator<=(const Integer lhs, const int128_t rhs) noexcept; + +constexpr bool operator<=(const int128_t lhs, const int128_t rhs) noexcept; +---- + +Returns if the `lhs` value is less than or equal to the `rhs` value without exception. +This operation is only defined for integers and is subject to mixed sign limitations discussed xref:int128_t.adoc#i128_operator_behavior[above]. + +=== Greater Than + +[source, c++] +---- +template +constexpr bool operator>(const int128_t lhs, const Integer rhs) noexcept; + +template +constexpr bool operator>(const Integer lhs, const int128_t rhs) noexcept; + +constexpr bool operator>(const int128_t lhs, const int128_t rhs) noexcept; +---- + +Returns if the `lhs` value is greater than the `rhs` value without exception. +This operation is only defined for integers and is subject to mixed sign limitations discussed xref:int128_t.adoc#i128_operator_behavior[above]. + +=== Greater Than or Equal To + +[source, c++] +---- +template +constexpr bool operator>=(const int128_t lhs, const Integer rhs) noexcept; + +template +constexpr bool operator>=(const Integer lhs, const int128_t rhs) noexcept; + +constexpr bool operator>=(const int128_t lhs, const int128_t rhs) noexcept; +---- + +Returns if the `lhs` value is greater than or equal to the `rhs` value without exception. +This operation is only defined for integers and is subject to mixed sign limitations discussed xref:int128_t.adoc#i128_operator_behavior[above]. + +=== Equality + +[source, c++] +---- +template +constexpr bool operator==(const int128_t lhs, const Integer rhs) noexcept; + +template +constexpr bool operator==(const Integer lhs, const int128_t rhs) noexcept; + +constexpr bool operator==(const int128_t lhs, const int128_t rhs) noexcept; +---- + +Returns if the `lhs` value is equal to the `rhs` value without exception. +This operation is only defined for integers and is subject to mixed sign limitations discussed xref:int128_t.adoc#i128_operator_behavior[above]. + +=== Inequality + +[source, c++] +---- +template +constexpr bool operator!=(const int128_t lhs, const Integer rhs) noexcept; + +template +constexpr bool operator!=(const Integer lhs, const int128_t rhs) noexcept; + +constexpr bool operator!=(const int128_t lhs, const int128_t rhs) noexcept; +---- + +Returns if the `lhs` value is not equal to the `rhs` value without exception. +This operation is only defined for integers and is subject to mixed sign limitations discussed xref:int128_t.adoc#i128_operator_behavior[above]. + +=== Spaceship Operator (Requires pass:[C++20]) + +[source, c++] +---- +constexpr std::strong_ordering operator<=>(const int128_t lhs, const int128_t rhs) noexcept; + +template +constexpr std::strong_ordering operator<=>(const int128_t lhs, const Integer rhs) noexcept; + +template +constexpr std::strong_ordering operator<=>(const Integer lhs, const int128_t rhs) noexcept; +---- + +Returns one of the following without exception: + +- `std::strong_ordering::less` if `lhs < rhs` +- `std::strong_ordering::equivalent` if `lhs == rhs` +- `std::strong_ordering::greater` otherwise (implies `lhs > rhs`) + +[#i128_bitwise_operators] +== Bitwise Operators + +=== Negation + +[source, c++] +---- +constexpr int128_t operator~(const int128_t rhs) noexcept +---- + +Returns the bitwise negation of `rhs` without exception. + +=== Or + +[source, c++] +---- +template +constexpr int128_t operator|(const int128_t lhs, const Integer rhs) noexcept; + +template +constexpr int128_t operator|(const Integer lhs, const int128_t rhs) noexcept; + +constexpr int128_t operator|(const int128_t lhs, const int128_t rhs) noexcept; +---- + +Returns the bitwise or of `lhs` and `rhs` without exception. +This operation is subject to mixed sign limitations discussed xref:int128_t.adoc#i128_operator_behavior[above]. + +=== And + +[source, c++] +---- +template +constexpr int128_t operator&(const int128_t lhs, const Integer rhs) noexcept; + +template +constexpr int128_t operator&(const Integer lhs, const int128_t rhs) noexcept; + +constexpr int128_t operator&(const int128_t lhs, const int128_t rhs) noexcept; +---- + +Returns the bitwise and of `lhs` and `rhs` without exception. +This operation is subject to mixed sign limitations discussed xref:int128_t.adoc#i128_operator_behavior[above]. + +=== Xor + +[source, c++] +---- +template +constexpr int128_t operator^(const int128_t lhs, const Integer rhs) noexcept; + +template +constexpr int128_t operator^(const Integer lhs, const int128_t rhs) noexcept; + +constexpr int128_t operator^(const int128_t lhs, const int128_t rhs) noexcept; +---- + +Returns the bitwise xor of `lhs` and `rhs` without exception. +This operation is subject to mixed sign limitations discussed xref:int128_t.adoc#i128_operator_behavior[above]. + +=== Left Shift + +[source, c++] +---- +template +constexpr int128_t operator<<(const int128_t lhs, const Integer rhs) noexcept; + +template ::value && (sizeof(Integer) * 8 > 16), bool> = true> +constexpr Integer operator<<(const Integer lhs, const int128_t rhs) noexcept; + +template && (sizeof(SignedInteger) * 8 <= 16), bool> = true> +constexpr int operator<<(const SignedInteger lhs, const int128_t rhs) noexcept; + +template && (sizeof(UnsignedInteger) * 8 <= 16), bool> = true> +constexpr unsigned int operator<<(const UnsignedInteger lhs, const int128_t rhs) noexcept; + +constexpr int128_t operator<<(const int128_t lhs, const int128_t rhs) noexcept; +---- + +Returns the bitwise left shift of `lhs` without exception. +The return type is dependent on the type of `Integer` when it is the `lhs` value to match the promotion behavior of built-in integer types. +This operation is subject to mixed sign limitations discussed xref:int128_t.adoc#i128_operator_behavior[above]. + +=== Right Shift + +[source, c++] +---- +template +constexpr int128_t operator>>(const int128_t lhs, const Integer rhs) noexcept; + +template ::value && (sizeof(Integer) * 8 > 16), bool> = true> +constexpr Integer operator>>(const Integer lhs, const int128_t rhs) noexcept; + +template && (sizeof(SignedInteger) * 8 <= 16), bool> = true> +constexpr int operator>>(const SignedInteger lhs, const int128_t rhs) noexcept; + +template && (sizeof(UnsignedInteger) * 8 <= 16), bool> = true> +constexpr unsigned operator>>(UnsignedInteger lhs, const int128_t rhs) noexcept; + +constexpr int128_t operator>>(const int128_t lhs, const int128_t rhs) noexcept; +---- + +Returns the bitwise right shift of `lhs` without exception. +The return type is dependent on the type of `Integer` when it is the `lhs` value to match the promotion behavior of built-in integer types. +This operation is subject to mixed sign limitations discussed xref:int128_t.adoc#i128_operator_behavior[above]. + + +[#i128_math_operators] +== Arithmetic Operators + +=== Addition + +[source, c++] +---- +template +constexpr int128_t operator+(const int128_t lhs, const Integer rhs) noexcept; + +template +constexpr int128_t operator+(const Integer lhs, const int128_t rhs) noexcept; + +constexpr int128_t operator+(const int128_t lhs, const int128_t rhs) noexcept; +---- + +Returns as an `int128_t` the sum of `lhs` and `rhs`. +If the sum is greater than `BOOST_INT128_INT128_MAX`, the operation silently performs signed rollover to `BOOST_INT128_INT128_MIN`. +This operation is only defined for integers and is subject to mixed sign limitations discussed xref:int128_t.adoc#i128_operator_behavior[above]. + +=== Subtraction + +[source, c++] +---- +template +constexpr int128_t operator-(const int128_t lhs, const Integer rhs) noexcept; + +template +constexpr int128_t operator-(const Integer lhs, const int128_t rhs) noexcept; + +constexpr int128_t operator-(const int128_t lhs, const int128_t rhs) noexcept; +---- + +Returns as an `int128_t` the difference of `lhs` and `rhs`. +If the difference is less than `BOOST_INT128_INT128_MIN`, the operation silently performs signed rollover to `BOOST_INT128_INT128_MAX`. +This operation is only defined for integers and is subject to mixed sign limitations discussed xref:int128_t.adoc#i128_operator_behavior[above]. + +=== Multiplication + +[source, c++] +---- +template +constexpr int128_t operator*(const int128_t lhs, const Integer rhs) noexcept; + +template +constexpr int128_t operator*(const Integer lhs, const int128_t rhs) noexcept; + +constexpr int128_t operator*(const int128_t lhs, const int128_t rhs) noexcept; +---- + +Returns as an `int128_t` the product of `lhs` and `rhs`. +If the product overflows, the operation silently performs signed rollover (wrapping from `BOOST_INT128_INT128_MAX` to `BOOST_INT128_INT128_MIN` or vice versa). +This operation is only defined for integers and is subject to mixed sign limitations discussed xref:int128_t.adoc#i128_operator_behavior[above]. + +=== Division + +[source, c++] +---- +template +constexpr int128_t operator/(const int128_t lhs, const Integer rhs) noexcept; + +template +constexpr int128_t operator/(const Integer lhs, const int128_t rhs) noexcept; + +constexpr int128_t operator/(const int128_t lhs, const int128_t rhs) noexcept; +---- + +Returns as an `int128_t` the quotient of `lhs` and `rhs` without exception. +This operation is only defined for integers and is subject to mixed sign limitations discussed xref:int128_t.adoc#i128_operator_behavior[above]. + +=== Modulo + +[source, c++] +---- +template +constexpr int128_t operator%(const int128_t lhs, const Integer rhs) noexcept; + +template +constexpr int128_t operator%(const Integer lhs, const int128_t rhs) noexcept; + +constexpr int128_t operator%(const int128_t lhs, const int128_t rhs) noexcept; +---- + +Returns as an `int128_t` the remainder of `lhs` and `rhs` without exception. +This operation is only defined for integers and is subject to mixed sign limitations discussed xref:int128_t.adoc#i128_operator_behavior[above]. diff --git a/doc/int128/literals.adoc b/doc/modules/ROOT/pages/literals.adoc similarity index 75% rename from doc/int128/literals.adoc rename to doc/modules/ROOT/pages/literals.adoc index faefb27e..c075e67b 100644 --- a/doc/int128/literals.adoc +++ b/doc/modules/ROOT/pages/literals.adoc @@ -8,7 +8,7 @@ https://www.boost.org/LICENSE_1_0.txt = Literals :idprefix: literals_ -The following literals and macros are provided for convenient construction of the types provided in the library: +The following literals and macros are provided for convenient construction of the types provided in the library. [source, c++] ---- @@ -51,21 +51,6 @@ constexpr int128_t operator ""_I128(const char* str, std::size_t len) noexcept; ---- -The macros at the end allow you to write out a 128-bit number like you would with say `UINT64_C` without having to add quotes: +The macros at the end allow you to write out a 128-bit number like you would with say `UINT64_C` without having to add quotes. -[source, c++] ----- - -#include - -int main() -{ - const boost::int128::uint128_t max_val {std::numeric_limits::max()}; - - // The following type for auto will be boost::int128::uint128_t - const auto macro_val{BOOST_INT128_UINT128_C(340282366920938463463374607431768211455)}; - - return !(max_val == macro_val); -} - ----- +See the xref:examples.adoc#examples_construction[construction examples] for usage demonstrations of both literals and macros. diff --git a/doc/int128/mixed_type_ops.adoc b/doc/modules/ROOT/pages/mixed_type_ops.adoc similarity index 75% rename from doc/int128/mixed_type_ops.adoc rename to doc/modules/ROOT/pages/mixed_type_ops.adoc index 03794fd1..bc932eae 100644 --- a/doc/int128/mixed_type_ops.adoc +++ b/doc/modules/ROOT/pages/mixed_type_ops.adoc @@ -14,13 +14,17 @@ The ability to convert between the two types via `static_cast` is available as d == Comparisons and Arithmetics -The following operations are *ALL ILLEGAL*. -Since we can not enforce `-Wsign-conversion` and `-Wsign-compare` through the compiler we instead `static_assert` that the operation is unavailable, and that the *USER MUST CAST TO A COMMON TYPE*. -This removes a common source of error (search "Sign Conversion" on Stack Overflow) +The following operations are *disabled by default*. +Since we cannot enforce `-Wsign-conversion` and `-Wsign-compare` through the compiler, we instead `static_assert` that the operation is unavailable. +This removes a common source of error (search "Sign Conversion" on Stack Overflow). + +To enable these operations, define the appropriate configuration macros before including any library headers: + +* xref:config.adoc#sign_compare[`BOOST_INT128_ALLOW_SIGN_COMPARE`] - enables comparison operators between signed and unsigned types +* xref:config.adoc#sign_conversion[`BOOST_INT128_ALLOW_SIGN_CONVERSION`] - enables arithmetic operators between signed and unsigned types (implies `BOOST_INT128_ALLOW_SIGN_COMPARE`) [source, c++] ---- - namespace boost { namespace int128 { diff --git a/doc/int128/numeric.adoc b/doc/modules/ROOT/pages/numeric.adoc similarity index 100% rename from doc/int128/numeric.adoc rename to doc/modules/ROOT/pages/numeric.adoc diff --git a/doc/int128/overview.adoc b/doc/modules/ROOT/pages/overview.adoc similarity index 84% rename from doc/int128/overview.adoc rename to doc/modules/ROOT/pages/overview.adoc index 6fe96949..236a54d4 100644 --- a/doc/int128/overview.adoc +++ b/doc/modules/ROOT/pages/overview.adoc @@ -5,13 +5,15 @@ https://www.boost.org/LICENSE_1_0.txt //// [#overview] -= Overview -:idprefix: overview_ + += Int128: Portable and Performant 128-bit integers + +Matt Borland == Description -Boost.Int128 is a portable implementation of a signed, and an unsigned 128-bit integer and related functionality (e.g. bit counting). -Importantly, on all platforms, the `sizeof` the types provided in this library are 128-bits. +Boost.Int128 is a portable implementation of a signed, and an unsigned 128-bit integer and related functionality (i.e. ``, ``, etc). +Importantly, on all platforms, the `sizeof` the types provided in this library are exactly 128-bits. The library is header-only, has no dependencies, and requires only C++14. @@ -22,7 +24,7 @@ An example is a 64-bit machine running Linux (say Ubuntu 24.04) has `__int128`, == Use Cases -Anywhere 128-bits are needed. +Anywhere 128-bit integers are needed. == Supported Compilers diff --git a/doc/modules/ROOT/pages/printer.adoc b/doc/modules/ROOT/pages/printer.adoc new file mode 100644 index 00000000..d1181dca --- /dev/null +++ b/doc/modules/ROOT/pages/printer.adoc @@ -0,0 +1,41 @@ +//// +Copyright 2025 Matt Borland +Distributed under the Boost Software License, Version 1.0. +https://www.boost.org/LICENSE_1_0.txt +//// + +[#pretty_printer] += Pretty Printers +:idprefix: pretty_printers_ + +Pretty printers allow debuggers to display `uint128_t` and `int128_t` values in human-readable decimal format instead of showing the raw struct members. +The library contains pretty printers for LLDB and GDB in the `extra/` folder. + +== LLDB + +To use this, add the following line to your `~/.lldbinit` file: + +[source] +---- +command script import /path/to/int128/extra/int128_printer.py +---- + +If this is successful, you should see the following message in your debugger upon startup: + +`"int128_t and uint128_t pretty printers loaded successfully"` + +== GDB + +To load the pretty printer, add the following line to your `.gdbinit`: + +[source] +---- +source /path/to/int128/extra/int128_printer_gdb.py +---- + +or you can source it manually in GDB. + +[source] +---- +(gdb) source /path/to/int128/extra/int128_printer_gdb.py +---- diff --git a/doc/int128/reference.adoc b/doc/modules/ROOT/pages/reference.adoc similarity index 100% rename from doc/int128/reference.adoc rename to doc/modules/ROOT/pages/reference.adoc diff --git a/doc/int128/stream.adoc b/doc/modules/ROOT/pages/stream.adoc similarity index 75% rename from doc/int128/stream.adoc rename to doc/modules/ROOT/pages/stream.adoc index 838b5d3a..b915f121 100644 --- a/doc/int128/stream.adoc +++ b/doc/modules/ROOT/pages/stream.adoc @@ -8,31 +8,32 @@ https://www.boost.org/LICENSE_1_0.txt = `` :idprefix: stream_ -The following stream operators are available, and work similar to built-in integer types: +The following stream operators are available and work similar to built-in integer types. [source, c++] ---- - #include +---- +[source, c++] +---- namespace boost { namespace int128 { template -std::basic_ostream& operator<<(std::basic_ostream& os, const int128_t& v) +std::basic_ostream& operator<<(std::basic_ostream& os, const int128_t& v); template -std::basic_istream& operator>>(std::basic_istream& is, int128_t& v) +std::basic_istream& operator>>(std::basic_istream& is, int128_t& v); template -std::basic_ostream& operator<<(std::basic_ostream& os, const uint128_t& v) +std::basic_ostream& operator<<(std::basic_ostream& os, const uint128_t& v); template -std::basic_istream& operator>>(std::basic_istream& is, uint128_t& v) +std::basic_istream& operator>>(std::basic_istream& is, uint128_t& v); } // namespace int128 } // namespace boost - ---- == Flags @@ -45,3 +46,5 @@ The following flags from `` are supported for both streaming directions: - `std::hex` - Hexadecimal Numbers - `std::uppercase` - Upper Case Formatting (e.g. 0XFFFF) - `std::nouppercase` - Lower Case Formatting (e.g. 0xffff) + +See the xref:examples.adoc#examples_io[IO streaming example] for usage demonstrations. diff --git a/doc/int128/u128_benchmarks.adoc b/doc/modules/ROOT/pages/u128_benchmarks.adoc similarity index 99% rename from doc/int128/u128_benchmarks.adoc rename to doc/modules/ROOT/pages/u128_benchmarks.adoc index a7578790..fabf1463 100644 --- a/doc/int128/u128_benchmarks.adoc +++ b/doc/modules/ROOT/pages/u128_benchmarks.adoc @@ -15,6 +15,7 @@ On most platforms we use the builtin `unsigned \__int128` as the reference bench When this is unavailable (such as on 32-bit architectures) we us `boost::multiprecision::uint128_t` (abbreviated as `boost::mp::uint128_t`) as it is widely used, and known to be portable. On MSVC platforms we use as reference `std::_Unsigned128` from the header `<__msvc_int128.hpp>` since this is bundled with their compiler. +[#u128_linux] == Linux === x86_64 @@ -142,6 +143,7 @@ image::u128_graphs/linux/ARM32_benchmarks.png[ARM32 Benchmark Results, width=100 image::u128_graphs/linux/ARM32_relative_performance.png[ARM32 Relative Performance, width=100%] +[#u128_windows] == Windows === x86_64 @@ -201,6 +203,7 @@ image::u128_graphs/windows/x86_benchmarks.png[x86_32 Benchmark Results, width=10 image::u128_graphs/windows/x86_relative_performance.png[x86_32 Relative Performance, width=100%] +[#u128_mac] == macOS === ARM64 (Apple Silicon) diff --git a/doc/modules/ROOT/pages/uint128_t.adoc b/doc/modules/ROOT/pages/uint128_t.adoc new file mode 100644 index 00000000..56473ed7 --- /dev/null +++ b/doc/modules/ROOT/pages/uint128_t.adoc @@ -0,0 +1,516 @@ +//// +Copyright 2025 Matt Borland +Distributed under the Boost Software License, Version 1.0. +https://www.boost.org/LICENSE_1_0.txt +//// + +[#uint128_t] += uint128_t +:idprefix: uint128_t_ + +== Description + +`uint128_t` is an unsigned 128-bit integer. + +[source, c++] +---- +#include + +namespace boost { +namespace int128 { + +struct uint128_t { + + #if BOOST_INT128_ENDIAN_LITTLE_BYTE + std::uint64_t low {}; + std::uint64_t high {}; + #else + std::uint64_t high {}; + std::uint64_t low {}; + #endif + + // Constructors, conversion operators, and member operators + // documented in detail below... +}; + +} // namespace int128 +} // namespace boost +---- + +The type provides: + +* Constructors from all built-in integer types and `int128_t` +* Conversion operators to built-in integer and floating-point types +* Full set of comparison operators (`<`, `<=`, `>`, `>=`, `==`, `!=`) +* Bitwise operators (`~`, `|`, `&`, `^`, `<<`, `>>`) +* Arithmetic operators (`+`, `-`, `*`, `/`, `%`) +* Compound assignment variants of all binary operators +* Increment and decrement operators (`++`, `--`) + +[#u128_alignment] +== Alignment + +If your platform has a native 128-bit unsigned integer, the struct is defined as so: + +[source, c++] +---- +struct alignas(alignof(unsigned __int128)) uint128_t +---- + +Otherwise, it is + +[source, c++] +---- +struct alignas(sizeof(std::uint64_t) * 2) uint128_t +---- + +[#u128_operator_behavior] +== Operator Behavior + +For all the following operators use of signed overloads will error from `static_assert` by default. +This is the library's way of enforcing the behavior of `-Wsign-conversion` and `-Wsign-comparison` in a library type. +If you want to compare with signed types you must define `BOOST_INT128_ALLOW_SIGN_COMPARE`, +and similarly you must define `BOOST_INT128_ALLOW_SIGN_CONVERSION` for other operations with mixed signedness. +These will both cast the signed integer to an unsigned integer and then perform the operation. + +=== Sign Compare Behavior Deviation + +The behavior of `uint128_t` will deviate from the behavior of builtin unsigned integers with mixed sign comparisons in hopefully a less surprising way. +A built-in sign compare looks something like + +[source, c++] +---- +template +constexpr bool operator>(const UnsignedInteger lhs, const SignedInteger rhs) +{ + return lhs > static_cast(rhs) +} +---- + +If you were to call this function with arguments 5U and -5, you would get the surprising answer of `false`. +Why? +The two's complement representation of -5 has its most significant bit set (along with many other high bits). +When cast to unsigned, this bit pattern is reinterpreted as a huge positive number, far greater than 5. + +With `uint128_t` we have checks even in this case like so: + +[source, c++] +---- +template +constexpr bool operator>(const uint128_t lhs, const SignedInteger rhs) noexcept +{ + if (rhs >= 0) + { + return lhs > static_cast(rhs); + } + else + { + return true; + } +} +---- + +This allows the library to return the correct answer even when mixing signs. + +[#u128_constructors] +== Constructors + +[source, c++] +---- +namespace boost { +namespace int128 { + +struct uint128_t +{ + ... + + // Defaulted basic construction + constexpr uint128_t() noexcept = default; + constexpr uint128_t(const uint128_t&) noexcept = default; + constexpr uint128_t(uint128_t&&) noexcept = default; + constexpr uint128_t& operator=(const uint128_t&) noexcept = default; + constexpr uint128_t& operator=(uint128_t&&) noexcept = default; + + constexpr uint128_t(const int128_t& v) noexcept; + + // Construct from integral types + constexpr uint128_t(const std::uint64_t hi, const std::uint64_t lo) noexcept; + + template + constexpr uint128_t(const SignedInteger v) noexcept; + + template + constexpr uint128_t(const UnsignedInteger v) noexcept; + + #ifdef BOOST_INT128_HAS_INT128 + + // Typically a typedef from __int128 + constexpr uint128_t(const detail::builtin_i128 v) noexcept; + + // Typically a typedef unsigned __int128 + constexpr uint128_t(const detail::builtin_u128 v) noexcept; + + #endif // BOOST_INT128_HAS_INT128 +}; + +} // namespace int128 +} // namespace boost +---- + +All constructors are only defined for integers and are subject to mixed sign limitations discussed xref:uint128_t.adoc#u128_operator_behavior[above]. +None are marked `explicit` in order to match the implicit conversion behavior of the built-in integer types. + +[#u128_conversions] +== Conversions + +[source, c++] +---- +namespace boost { +namespace int128 { + +struct uint128_t +{ + ... + + // Integer conversion operators + constexpr operator bool() const noexcept; + + template + explicit constexpr operator SignedInteger() const noexcept; + + template + explicit constexpr operator UnsignedInteger() const noexcept; + + #ifdef BOOST_INT128_HAS_INT128 + + explicit constexpr operator detail::builtin_i128() const noexcept; + + explicit constexpr operator detail::builtin_u128() const noexcept; + + #endif // BOOST_INT128_HAS_INT128 + + // Conversion to float + explicit constexpr operator float() const noexcept; + explicit constexpr operator double() const noexcept; + explicit constexpr operator long double() const noexcept; +}; + +} // namespace int128 +} // namespace boost +---- + +Conversions to signed integers are subject to mixed sign limitations discussed xref:uint128_t.adoc#u128_operator_behavior[above]. +Conversion to `bool` is not marked explicit to match the behavior of built-in integer types. +Conversions to floating point types may not be lossless depending on the value of the `uint128_t` at time of conversion, +as the number of digits it represents can exceed the precision of the significand in floating point types. + +[#u128_comparison_operators] +== Comparison Operators + +=== Less Than + +[source, c++] +---- +template +constexpr bool operator<(const uint128_t lhs, const Integer rhs) noexcept; + +template +constexpr bool operator<(const Integer lhs, const uint128_t rhs) noexcept; + +constexpr bool operator<(const uint128_t lhs, const uint128_t rhs) noexcept; +---- + +Returns if the `lhs` value is less than the `rhs` value without exception. +This operation is only defined for integers and is subject to mixed sign limitations discussed xref:uint128_t.adoc#u128_operator_behavior[above]. + +=== Less Than or Equal To + +[source, c++] +---- +template +constexpr bool operator<=(const uint128_t lhs, const Integer rhs) noexcept; + +template +constexpr bool operator<=(const Integer lhs, const uint128_t rhs) noexcept; + +constexpr bool operator<=(const uint128_t lhs, const uint128_t rhs) noexcept; +---- + +Returns if the `lhs` value is less than or equal to the `rhs` value without exception. +This operation is only defined for integers and is subject to mixed sign limitations discussed xref:uint128_t.adoc#u128_operator_behavior[above]. + +=== Greater Than + +[source, c++] +---- +template +constexpr bool operator>(const uint128_t lhs, const Integer rhs) noexcept; + +template +constexpr bool operator>(const Integer lhs, const uint128_t rhs) noexcept; + +constexpr bool operator>(const uint128_t lhs, const uint128_t rhs) noexcept; +---- + +Returns if the `lhs` value is greater than the `rhs` value without exception. +This operation is only defined for integers and is subject to mixed sign limitations discussed xref:uint128_t.adoc#u128_operator_behavior[above]. + +=== Greater Than or Equal To + +[source, c++] +---- +template +constexpr bool operator>=(const uint128_t lhs, const Integer rhs) noexcept; + +template +constexpr bool operator>=(const Integer lhs, const uint128_t rhs) noexcept; + +constexpr bool operator>=(const uint128_t lhs, const uint128_t rhs) noexcept; +---- + +Returns if the `lhs` value is greater than or equal to the `rhs` value without exception. +This operation is only defined for integers and is subject to mixed sign limitations discussed xref:uint128_t.adoc#u128_operator_behavior[above]. + +=== Equality + +[source, c++] +---- +template +constexpr bool operator==(const uint128_t lhs, const Integer rhs) noexcept; + +template +constexpr bool operator==(const Integer lhs, const uint128_t rhs) noexcept; + +constexpr bool operator==(const uint128_t lhs, const uint128_t rhs) noexcept; +---- + +Returns if the `lhs` value is equal to the `rhs` value without exception. +This operation is only defined for integers and is subject to mixed sign limitations discussed xref:uint128_t.adoc#u128_operator_behavior[above]. + +=== Inequality + +[source, c++] +---- +template +constexpr bool operator!=(const uint128_t lhs, const Integer rhs) noexcept; + +template +constexpr bool operator!=(const Integer lhs, const uint128_t rhs) noexcept; + +constexpr bool operator!=(const uint128_t lhs, const uint128_t rhs) noexcept; +---- + +Returns if the `lhs` value is not equal to the `rhs` value without exception. +This operation is only defined for integers and is subject to mixed sign limitations discussed xref:uint128_t.adoc#u128_operator_behavior[above]. + +=== Spaceship Operator (Requires pass:[C++20]) + +[source, c++] +---- +constexpr std::strong_ordering operator<=>(const uint128_t lhs, const uint128_t rhs) noexcept; + +template +constexpr std::strong_ordering operator<=>(const uint128_t lhs, const Integer rhs) noexcept; + +template +constexpr std::strong_ordering operator<=>(const Integer lhs, const uint128_t rhs) noexcept; +---- + +Returns one of the following without exception: + +- `std::strong_ordering::less` if `lhs < rhs` +- `std::strong_ordering::equivalent` if `lhs == rhs` +- `std::strong_ordering::greater` otherwise (implies `lhs > rhs`) + +[#u128_bitwise_operators] +== Bitwise Operators + +=== Negation + +[source, c++] +---- +constexpr uint128_t operator~(const uint128_t rhs) noexcept +---- + +Returns the bitwise negation of `rhs` without exception. + +=== Or + +[source, c++] +---- +template +constexpr uint128_t operator|(const uint128_t lhs, const Integer rhs) noexcept; + +template +constexpr uint128_t operator|(const Integer lhs, const uint128_t rhs) noexcept; + +constexpr uint128_t operator|(const uint128_t lhs, const uint128_t rhs) noexcept; +---- + +Returns the bitwise or of `lhs` and `rhs` without exception. +This operation is subject to mixed sign limitations discussed xref:uint128_t.adoc#u128_operator_behavior[above]. + +=== And + +[source, c++] +---- +template +constexpr uint128_t operator&(const uint128_t lhs, const Integer rhs) noexcept; + +template +constexpr uint128_t operator&(const Integer lhs, const uint128_t rhs) noexcept; + +constexpr uint128_t operator&(const uint128_t lhs, const uint128_t rhs) noexcept; +---- + +Returns the bitwise and of `lhs` and `rhs` without exception. +This operation is subject to mixed sign limitations discussed xref:uint128_t.adoc#u128_operator_behavior[above]. + +=== Xor + +[source, c++] +---- +template +constexpr uint128_t operator^(const uint128_t lhs, const Integer rhs) noexcept; + +template +constexpr uint128_t operator^(const Integer lhs, const uint128_t rhs) noexcept; + +constexpr uint128_t operator^(const uint128_t lhs, const uint128_t rhs) noexcept; +---- + +Returns the bitwise xor of `lhs` and `rhs` without exception. +This operation is subject to mixed sign limitations discussed xref:uint128_t.adoc#u128_operator_behavior[above]. + +=== Left Shift + +[source, c++] +---- +template +constexpr uint128_t operator<<(const uint128_t lhs, const Integer rhs) noexcept; + +template ::value && (sizeof(Integer) * 8 > 16), bool> = true> +constexpr Integer operator<<(const Integer lhs, const uint128_t rhs) noexcept; + +template && (sizeof(SignedInteger) * 8 <= 16), bool> = true> +constexpr int operator<<(const SignedInteger lhs, const uint128_t rhs) noexcept; + +template && (sizeof(UnsignedInteger) * 8 <= 16), bool> = true> +constexpr unsigned int operator<<(const UnsignedInteger lhs, const uint128_t rhs) noexcept; + +constexpr uint128_t operator<<(const uint128_t lhs, const uint128_t rhs) noexcept; +---- + +Returns the bitwise left shift of `lhs` without exception. +The return type is dependent on the type of `Integer` when it is the `lhs` value to match the promotion behavior of built-in integer types. +This operation is subject to mixed sign limitations discussed xref:uint128_t.adoc#u128_operator_behavior[above]. + +=== Right Shift + +[source, c++] +---- +template +constexpr uint128_t operator<<(const uint128_t lhs, const Integer rhs) noexcept; + +template ::value && (sizeof(Integer) * 8 > 16), bool> = true> +constexpr Integer operator<<(const Integer lhs, const uint128_t rhs) noexcept; + +template && (sizeof(SignedInteger) * 8 <= 16), bool> = true> +constexpr int operator<<(const SignedInteger lhs, const uint128_t rhs) noexcept; + +template && (sizeof(UnsignedInteger) * 8 <= 16), bool> = true> +constexpr unsigned int operator<<(const UnsignedInteger lhs, const uint128_t rhs) noexcept; + +constexpr uint128_t operator<<(const uint128_t lhs, const uint128_t rhs) noexcept; +---- + +Returns the bitwise right shift of `lhs` without exception. +The return type is dependent on the type of `Integer` when it is the `lhs` value to match the promotion behavior of built-in integer types. +This operation is subject to mixed sign limitations discussed xref:uint128_t.adoc#u128_operator_behavior[above]. + + +[#u128_math_operators] +== Arithmetic Operators + +=== Addition + +[source, c++] +---- +template +constexpr uint128_t operator+(const uint128_t lhs, const Integer rhs) noexcept; + +template +constexpr uint128_t operator+(const Integer lhs, const uint128_t rhs) noexcept; + +constexpr uint128_t operator+(const uint128_t lhs, const uint128_t rhs) noexcept; +---- + +Returns as a `uint128_t` the sum of `lhs` and `rhs`. +If the sum is greater than is representable by a `uint128_t`, the operation silently performs unsigned rollover in the direction of 0. +This operation is only defined for integers and is subject to mixed sign limitations discussed xref:uint128_t.adoc#u128_operator_behavior[above]. + +=== Subtraction + +[source, c++] +---- +template +constexpr uint128_t operator-(const uint128_t lhs, const Integer rhs) noexcept; + +template +constexpr uint128_t operator-(const Integer lhs, const uint128_t rhs) noexcept; + +constexpr uint128_t operator-(const uint128_t lhs, const uint128_t rhs) noexcept; +---- + +Returns as a `uint128_t` the difference of `lhs` and `rhs`. +If the difference is less than is representable by a `uint128_t`, the operation silently performs unsigned rollover in the direction of `BOOST_INT128_UINT128_MAX`. +This operation is only defined for integers and is subject to mixed sign limitations discussed xref:uint128_t.adoc#u128_operator_behavior[above]. + +=== Multiplication + +[source, c++] +---- +template +constexpr uint128_t operator*(const uint128_t lhs, const Integer rhs) noexcept; + +template +constexpr uint128_t operator*(const Integer lhs, const uint128_t rhs) noexcept; + +constexpr uint128_t operator*(const uint128_t lhs, const uint128_t rhs) noexcept; +---- + +Returns as a `uint128_t` the product of `lhs` and `rhs`. +If the product is greater than is representable by a `uint128_t`, the operation silently performs unsigned rollover in the direction of 0. +This operation is only defined for integers and is subject to mixed sign limitations discussed xref:uint128_t.adoc#u128_operator_behavior[above]. + +=== Division + +[source, c++] +---- +template +constexpr uint128_t operator/(const uint128_t lhs, const Integer rhs) noexcept; + +template +constexpr uint128_t operator/(const Integer lhs, const uint128_t rhs) noexcept; + +constexpr uint128_t operator/(const uint128_t lhs, const uint128_t rhs) noexcept; +---- + +Returns as a `uint128_t` the quotient of `lhs` and `rhs` without exception. +This operation is only defined for integers and is subject to mixed sign limitations discussed xref:uint128_t.adoc#u128_operator_behavior[above]. + +=== Modulo + +[source, c++] +---- +template +constexpr uint128_t operator%(const uint128_t lhs, const Integer rhs) noexcept; + +template +constexpr uint128_t operator%(const Integer lhs, const uint128_t rhs) noexcept; + +constexpr uint128_t operator%(const uint128_t lhs, const uint128_t rhs) noexcept; +---- + +Returns as a `uint128_t` the remainder of `lhs` and `rhs` without exception. +This operation is only defined for integers and is subject to mixed sign limitations discussed xref:uint128_t.adoc#u128_operator_behavior[above]. diff --git a/doc/package-lock.json b/doc/package-lock.json new file mode 100644 index 00000000..86eaeb65 --- /dev/null +++ b/doc/package-lock.json @@ -0,0 +1,2247 @@ +{ + "name": "doc", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@antora/lunr-extension": "^1.0.0-alpha.12", + "@cppalliance/antora-downloads-extension": "^0.0.2" + }, + "devDependencies": { + "@antora/cli": "3.1.14", + "@antora/site-generator": "3.1.14", + "antora": "3.1.14" + } + }, + "node_modules/@antora/asciidoc-loader": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/asciidoc-loader/-/asciidoc-loader-3.1.14.tgz", + "integrity": "sha512-4xxisnoBFrlLNY6f3xZtyyfgm+tBLsqesTcEStfc8jtXUMYJ4b2DWIzo1vULmxvZ7yY5+Q7YqEvS5o6kIWAG0A==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@antora/logger": "3.1.14", + "@antora/user-require-helper": "~3.0", + "@asciidoctor/core": "~2.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/cli": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/cli/-/cli-3.1.14.tgz", + "integrity": "sha512-I6WcygMU2bFInjdURJjkYjo7K5M8B3lBB53v9OO0IcY0LhEY8Wa7IlZ7wVinf5qEjHvaYzRGTZVl6RsJtVt7Sw==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@antora/logger": "3.1.14", + "@antora/playbook-builder": "3.1.14", + "@antora/user-require-helper": "~3.0", + "commander": "~11.1" + }, + "bin": { + "antora": "bin/antora" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/cli/node_modules/@antora/playbook-builder": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/playbook-builder/-/playbook-builder-3.1.14.tgz", + "integrity": "sha512-Ss2r7In00u/n9Da+JOxEqIE8NeRosf+f+agzH3Te09JV/mpgZKxEOE5V/VuP+TNNq4ww1eu5aOS8DiU2PYwj4Q==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@iarna/toml": "~2.2", + "convict": "~6.2", + "js-yaml": "~4.1", + "json5": "~2.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/content-aggregator": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/content-aggregator/-/content-aggregator-3.1.14.tgz", + "integrity": "sha512-FVuBgnrGPiktYqK1WHbGF8O8l4m5KHlkxoJumrbacgFo8SKuiRFEo31zalxrCUsv8QM3UBEgX+LdHrve/9CGLg==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@antora/expand-path-helper": "~3.0", + "@antora/logger": "3.1.14", + "@antora/user-require-helper": "~3.0", + "braces": "~3.0", + "cache-directory": "~2.0", + "fast-glob": "~3.3", + "hpagent": "~1.2", + "isomorphic-git": "~1.25", + "js-yaml": "~4.1", + "multi-progress": "~4.0", + "picomatch": "~4.0", + "progress": "~2.0", + "should-proxy": "~1.0", + "simple-get": "~4.0", + "vinyl": "~3.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/content-classifier": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/content-classifier/-/content-classifier-3.1.14.tgz", + "integrity": "sha512-y8Fk+KU1lqD3aawOu3ZFK92YfOZ1k3YBJhLI9QIFM6Ck4STPnf7AwYbhfOtjODlwer5/OhFmfhjUB2hn7onGnA==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@antora/asciidoc-loader": "3.1.14", + "@antora/logger": "3.1.14", + "mime-types": "~2.1", + "vinyl": "~3.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/document-converter": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/document-converter/-/document-converter-3.1.14.tgz", + "integrity": "sha512-f6wFnL+489DI0ZDgoxYWzbxxWqPviRiJ56OHS1NixEfvJ7OpRBDPEbX1xnsIeiyFBgqX4+nY92MsCWKTa+Gf3w==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@antora/asciidoc-loader": "3.1.14" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/expand-path-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/expand-path-helper/-/expand-path-helper-3.0.0.tgz", + "integrity": "sha512-7PdEIhk97v85/CSm3HynCsX14TR6oIVz1s233nNLsiWubE8tTnpPt4sNRJR+hpmIZ6Bx9c6QDp3XIoiyu/WYYA==", + "dev": true, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/file-publisher": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/file-publisher/-/file-publisher-3.1.14.tgz", + "integrity": "sha512-fTaAnkyKSOlsxQM1TBFCAmiERA6Q67XleDCD2bMPVgfcENmo0Xfx59KwCHaA92IcRSmMftydlXHPaFxNh0UVsg==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@antora/expand-path-helper": "~3.0", + "@antora/user-require-helper": "~3.0", + "vinyl": "~3.0", + "yazl": "~2.5" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/logger": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/logger/-/logger-3.1.14.tgz", + "integrity": "sha512-kVEeGqZbXR903hPIm+BlN97fLdQ3LoUzE/BOPZ6vRp9m9Mmbnm67Kg7fSYkfTMLB0S2UWpAPFg22RdsU5ZoAzA==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@antora/expand-path-helper": "~3.0", + "pino": "~9.2", + "pino-pretty": "~11.2", + "sonic-boom": "~4.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/lunr-extension": { + "version": "1.0.0-alpha.12", + "resolved": "https://registry.npmjs.org/@antora/lunr-extension/-/lunr-extension-1.0.0-alpha.12.tgz", + "integrity": "sha512-iiEXpJae8tCH22ao7kZ4I+eyQ/3IeFIFK1G5I9QLpkCezaVPotI8eLFY7e0xDI+zsqJEfCOsfoZGYXso6xCYlA==", + "license": "MPL-2.0", + "workspaces": [ + "." + ], + "dependencies": { + "htmlparser2": "~9.1", + "lunr": "~2.3", + "lunr-languages": "~1.10" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/navigation-builder": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/navigation-builder/-/navigation-builder-3.1.14.tgz", + "integrity": "sha512-/637YLGD7oUHGSfEfszXkk4ASfIhDAg5Xs9035J1dV07XYRlGqmtUb15rtapbcECpcQFjCyM5jFQYSNNvLrGcQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@antora/asciidoc-loader": "3.1.14" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/page-composer": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/page-composer/-/page-composer-3.1.14.tgz", + "integrity": "sha512-RfA+67TxCqUPrQbZdrfjgLpHh8MR2z2du7cyF3HGX4N6DpqEBvz81NHHl3rA3fj6BQZPQbGm2OYAMU6wzJ6Pog==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@antora/logger": "3.1.14", + "handlebars": "~4.7", + "require-from-string": "~2.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/redirect-producer": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/redirect-producer/-/redirect-producer-3.1.14.tgz", + "integrity": "sha512-5koAwRk1cZrvE/qfOWKXqb3jtxrZbWA5EYHYGFEoato5By3cbC42blH4Bre9/48pjyS6znFpbZhYUBpT7PRhZA==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "vinyl": "~3.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/site-generator": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/site-generator/-/site-generator-3.1.14.tgz", + "integrity": "sha512-hQIUVtM9+xwleYWc4fIRZmiKl2p+ItOJuUm2+Hkdh07BZsySxkMOxxCyZsvTn9rc+4R94CYqDQCYElwFwdB2WA==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@antora/asciidoc-loader": "3.1.14", + "@antora/content-aggregator": "3.1.14", + "@antora/content-classifier": "3.1.14", + "@antora/document-converter": "3.1.14", + "@antora/file-publisher": "3.1.14", + "@antora/logger": "3.1.14", + "@antora/navigation-builder": "3.1.14", + "@antora/page-composer": "3.1.14", + "@antora/playbook-builder": "3.1.14", + "@antora/redirect-producer": "3.1.14", + "@antora/site-mapper": "3.1.14", + "@antora/site-publisher": "3.1.14", + "@antora/ui-loader": "3.1.14", + "@antora/user-require-helper": "~3.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/site-generator/node_modules/@antora/playbook-builder": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/playbook-builder/-/playbook-builder-3.1.14.tgz", + "integrity": "sha512-Ss2r7In00u/n9Da+JOxEqIE8NeRosf+f+agzH3Te09JV/mpgZKxEOE5V/VuP+TNNq4ww1eu5aOS8DiU2PYwj4Q==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@iarna/toml": "~2.2", + "convict": "~6.2", + "js-yaml": "~4.1", + "json5": "~2.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/site-mapper": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/site-mapper/-/site-mapper-3.1.14.tgz", + "integrity": "sha512-3qbETtwadl+fWREjzrBUxPUorMcMiZ+hdkB1El9z7it9KzKh0Yp7Je0+2uTxGX+Lov9uik48dZJ9e/mr5PeaRQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@antora/content-classifier": "3.1.14", + "vinyl": "~3.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/site-publisher": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/site-publisher/-/site-publisher-3.1.14.tgz", + "integrity": "sha512-8apyEmgepUc7ms9CTEIPwN3tGtWwLqR6fbLMLs7hibqmOSR880Ut/4GRGb97sqcGQXSHdIyWK2oJKzRl1Akb6Q==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@antora/file-publisher": "3.1.14" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/ui-loader": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/@antora/ui-loader/-/ui-loader-3.1.14.tgz", + "integrity": "sha512-LVvTdKQOB44CmJ1JQDu8sJf6rrLZMxPAWWackdg2JtGyGHHpd80/MBcv4BSFk7//cJQ13Oqm/7JCbhD51KAFjg==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@antora/expand-path-helper": "~3.0", + "braces": "~3.0", + "cache-directory": "~2.0", + "fast-glob": "~3.3", + "hpagent": "~1.2", + "js-yaml": "~4.1", + "picomatch": "~4.0", + "should-proxy": "~1.0", + "simple-get": "~4.0", + "vinyl": "~3.0", + "yauzl": "~3.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@antora/user-require-helper": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@antora/user-require-helper/-/user-require-helper-3.0.0.tgz", + "integrity": "sha512-KIXb8WYhnrnwH7Jj21l1w+et9k5GvcgcqvLOwxqWLEd0uVZOiMFdqFjqbVm3M+zcrs1JXWMeh2LLvxBbQs3q/Q==", + "dev": true, + "dependencies": { + "@antora/expand-path-helper": "~3.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@asciidoctor/core": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/@asciidoctor/core/-/core-2.2.8.tgz", + "integrity": "sha512-oozXk7ZO1RAd/KLFLkKOhqTcG4GO3CV44WwOFg2gMcCsqCUTarvMT7xERIoWW2WurKbB0/ce+98r01p8xPOlBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "asciidoctor-opal-runtime": "0.3.3", + "unxhr": "1.0.1" + }, + "engines": { + "node": ">=8.11", + "npm": ">=5.0.0", + "yarn": ">=1.1.0" + } + }, + "node_modules/@cppalliance/antora-downloads-extension": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@cppalliance/antora-downloads-extension/-/antora-downloads-extension-0.0.2.tgz", + "integrity": "sha512-2wXahlvRz9J75ZSfzDeP4XpIZiqIm+w/YjmCWJxFPp6oWgP7e8f6ps7HqdtHNGxnK5mG38OjiCFdHjmHYfgbDA==", + "license": "BSL-1.0" + }, + "node_modules/@iarna/toml": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", + "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==", + "dev": true + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/antora": { + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/antora/-/antora-3.1.14.tgz", + "integrity": "sha512-z8HshJsT6pUfdDOUJ15RGtpOM9LmL6JXU5JBshoR/9/xd+1qLmKPkOnUv+HrijAk93r1imxZOdkmIqhLcv8B8A==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@antora/cli": "3.1.14", + "@antora/site-generator": "3.1.14" + }, + "bin": { + "antora": "bin/antora" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/asciidoctor-opal-runtime": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/asciidoctor-opal-runtime/-/asciidoctor-opal-runtime-0.3.3.tgz", + "integrity": "sha512-/CEVNiOia8E5BMO9FLooo+Kv18K4+4JBFRJp8vUy/N5dMRAg+fRNV4HA+o6aoSC79jVU/aT5XvUpxSxSsTS8FQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob": "7.1.3", + "unxhr": "1.0.1" + }, + "engines": { + "node": ">=8.11" + } + }, + "node_modules/async-lock": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.4.1.tgz", + "integrity": "sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/b4a": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.7.3.tgz", + "integrity": "sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==", + "dev": true, + "license": "Apache-2.0", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/bare-events": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", + "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", + "dev": true, + "license": "Apache-2.0", + "peerDependencies": { + "bare-abort-controller": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + } + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/cache-directory": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cache-directory/-/cache-directory-2.0.0.tgz", + "integrity": "sha512-7YKEapH+2Uikde8hySyfobXBqPKULDyHNl/lhKm7cKf/GJFdG/tU/WpLrOg2y9aUrQrWUilYqawFIiGJPS6gDA==", + "dev": true, + "license": "LGPL-3.0+", + "dependencies": { + "xdg-basedir": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/clean-git-ref": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/clean-git-ref/-/clean-git-ref-2.0.1.tgz", + "integrity": "sha512-bLSptAy2P0s6hU4PzuIMKmMJJSE6gLXGH1cntDu7bWJUksvuM+7ReOK61mozULErYvP6a15rnYl0zFDef+pyPw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convict": { + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/convict/-/convict-6.2.4.tgz", + "integrity": "sha512-qN60BAwdMVdofckX7AlohVJ2x9UvjTNoKVXCL2LxFk1l7757EJqf1nySdMkPQer0bt8kQ5lQiyZ9/2NvrFBuwQ==", + "dev": true, + "dependencies": { + "lodash.clonedeep": "^4.5.0", + "yargs-parser": "^20.2.7" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/diff3": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/diff3/-/diff3-0.0.3.tgz", + "integrity": "sha512-iSq8ngPOt0K53A6eVr4d5Kn6GNrM2nQZtC740pzIriHtn4pOQ2lyzEXQMBeVcWERN0ye7fhBsk9PbLLQOnUx/g==", + "dev": true, + "license": "MIT" + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.7.0" + } + }, + "node_modules/fast-copy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz", + "integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==", + "dev": true + }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-redact": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.5.0.tgz", + "integrity": "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", + "dev": true + }, + "node_modules/hpagent": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-1.2.0.tgz", + "integrity": "sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/htmlparser2": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz", + "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.1.0", + "entities": "^4.5.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isomorphic-git": { + "version": "1.25.10", + "resolved": "https://registry.npmjs.org/isomorphic-git/-/isomorphic-git-1.25.10.tgz", + "integrity": "sha512-IxGiaKBwAdcgBXwIcxJU6rHLk+NrzYaaPKXXQffcA0GW3IUrQXdUPDXDo+hkGVcYruuz/7JlGBiuaeTCgIgivQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-lock": "^1.4.1", + "clean-git-ref": "^2.0.1", + "crc-32": "^1.2.0", + "diff3": "0.0.3", + "ignore": "^5.1.4", + "minimisted": "^2.0.0", + "pako": "^1.0.10", + "pify": "^4.0.1", + "readable-stream": "^3.4.0", + "sha.js": "^2.4.9", + "simple-get": "^4.0.1" + }, + "bin": { + "isogit": "cli.cjs" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "dev": true + }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "license": "MIT" + }, + "node_modules/lunr-languages": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/lunr-languages/-/lunr-languages-1.10.0.tgz", + "integrity": "sha512-BBjKKcwrieJlzwwc9M5H/MRXGJ2qyOSDx/NXYiwkuKjiLOOoouh0WsDzeqcLoUWcX31y7i8sb8IgsZKObdUCkw==", + "license": "MPL-1.1" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minimisted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minimisted/-/minimisted-2.0.1.tgz", + "integrity": "sha512-1oPjfuLQa2caorJUM8HV8lGgWCc0qqAO1MNv/k05G4qslmsndV/5WdNZrqCiyqiz3wohia2Ij2B7w2Dr7/IyrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5" + } + }, + "node_modules/multi-progress": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/multi-progress/-/multi-progress-4.0.0.tgz", + "integrity": "sha512-9zcjyOou3FFCKPXsmkbC3ethv51SFPoA4dJD6TscIp2pUmy26kBDZW6h9XofPELrzseSkuD7r0V+emGEeo39Pg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "progress": "^2.0.0" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT" + }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true, + "license": "(MIT AND Zlib)" + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true, + "license": "MIT" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pino": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/pino/-/pino-9.2.0.tgz", + "integrity": "sha512-g3/hpwfujK5a4oVbaefoJxezLzsDgLcNJeITvC6yrfwYeT9la+edCK42j5QpEQSQCZgTKapXvnQIdgZwvRaZug==", + "dev": true, + "dependencies": { + "atomic-sleep": "^1.0.0", + "fast-redact": "^3.1.1", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.2.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^3.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^3.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz", + "integrity": "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==", + "dev": true, + "dependencies": { + "readable-stream": "^4.0.0", + "split2": "^4.0.0" + } + }, + "node_modules/pino-abstract-transport/node_modules/readable-stream": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.6.0.tgz", + "integrity": "sha512-cbAdYt0VcnpN2Bekq7PU+k363ZRsPwJoEEJOEtSJQlJXzwaxt3FIo/uL+KeDSGIjJqtkwyge4KQgD2S2kd+CQw==", + "dev": true, + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/pino-pretty": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-11.2.2.tgz", + "integrity": "sha512-2FnyGir8nAJAqD3srROdrF1J5BIcMT4nwj7hHSc60El6Uxlym00UbCCd8pYIterstVBFlMyF1yFV8XdGIPbj4A==", + "dev": true, + "dependencies": { + "colorette": "^2.0.7", + "dateformat": "^4.6.3", + "fast-copy": "^3.0.2", + "fast-safe-stringify": "^2.1.1", + "help-me": "^5.0.0", + "joycon": "^3.1.1", + "minimist": "^1.2.6", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^1.0.0", + "pump": "^3.0.0", + "readable-stream": "^4.0.0", + "secure-json-parse": "^2.4.0", + "sonic-boom": "^4.0.1", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "pino-pretty": "bin.js" + } + }, + "node_modules/pino-pretty/node_modules/readable-stream": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.6.0.tgz", + "integrity": "sha512-cbAdYt0VcnpN2Bekq7PU+k363ZRsPwJoEEJOEtSJQlJXzwaxt3FIo/uL+KeDSGIjJqtkwyge4KQgD2S2kd+CQw==", + "dev": true, + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/pino-std-serializers": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz", + "integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==", + "dev": true + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz", + "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ==", + "dev": true + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/pump": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", + "dev": true + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", + "dev": true, + "license": "ISC" + }, + "node_modules/replace-ext": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz", + "integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/secure-json-parse": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", + "dev": true + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/sha.js": { + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", + "dev": true, + "license": "(MIT AND BSD-3-Clause)", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" + }, + "bin": { + "sha.js": "bin.js" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/should-proxy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/should-proxy/-/should-proxy-1.0.4.tgz", + "integrity": "sha512-RPQhIndEIVUCjkfkQ6rs6sOR6pkxJWCNdxtfG5pP0RVgUYbK5911kLTF0TNcCC0G3YCGd492rMollFT2aTd9iQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/sonic-boom": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.0.1.tgz", + "integrity": "sha512-hTSD/6JMLyT4r9zeof6UtuBDpjJ9sO08/nmS5djaA9eozT9oOlNdpXSnzcgj4FTqpk3nkLrs61l4gip9r1HCrQ==", + "dev": true, + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "dev": true, + "engines": { + "node": ">= 10.x" + } + }, + "node_modules/streamx": { + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", + "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "events-universal": "^1.0.0", + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/teex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", + "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "streamx": "^2.12.5" + } + }, + "node_modules/text-decoder": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, + "node_modules/thread-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", + "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", + "dev": true, + "dependencies": { + "real-require": "^0.2.0" + } + }, + "node_modules/to-buffer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", + "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "isarray": "^2.0.5", + "safe-buffer": "^5.2.1", + "typed-array-buffer": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/unxhr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unxhr/-/unxhr-1.0.1.tgz", + "integrity": "sha512-MAhukhVHyaLGDjyDYhy8gVjWJyhTECCdNsLwlMoGFoNJ3o79fpQhtQuzmAE4IxCMDwraF4cW8ZjpAV0m9CRQbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.11" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/vinyl": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.1.tgz", + "integrity": "sha512-0QwqXteBNXgnLCdWdvPQBX6FXRHtIH3VhJPTd5Lwn28tJXc34YqSCWUmkOvtJHBmB3gGoPtrOKk3Ts8/kEZ9aA==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone": "^2.1.2", + "remove-trailing-separator": "^1.1.0", + "replace-ext": "^2.0.0", + "teex": "^1.0.1" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha512-1Dly4xqlulvPD3fZUQJLY+FUIeqN3N2MM3uqe4rCJftAvOjFa3jFGfctOgluGx4ahPbUCsZkmJILiP0Vi4T6lQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yauzl": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.1.3.tgz", + "integrity": "sha512-JCCdmlJJWv7L0q/KylOekyRaUrdEoUxWkWVcgorosTROCFWiS9p2NNPE9Yb91ak7b1N5SxAZEliWpspbZccivw==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "pend": "~1.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3" + } + } + } +} diff --git a/doc/package.json b/doc/package.json new file mode 100644 index 00000000..2d89d19c --- /dev/null +++ b/doc/package.json @@ -0,0 +1,11 @@ +{ + "devDependencies": { + "@antora/cli": "3.1.14", + "@antora/site-generator": "3.1.14", + "antora": "3.1.14" + }, + "dependencies": { + "@cppalliance/antora-downloads-extension": "^0.0.2", + "@antora/lunr-extension": "^1.0.0-alpha.12" + } +} diff --git a/examples/basic_arithmetic.cpp b/examples/basic_arithmetic.cpp index 4feccb63..76888dca 100644 --- a/examples/basic_arithmetic.cpp +++ b/examples/basic_arithmetic.cpp @@ -3,49 +3,87 @@ // https://www.boost.org/LICENSE_1_0.txt #include - -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wunused-variable" -#endif +#include +#include int main() { - // The types of this library support all arithmetic operations one would expect - // They can be between values of the same type, or same signedness by default. - // See `mixed_type_arithmetic.cpp` for other operations - boost::int128::int128_t x {42}; - boost::int128::int128_t y {-2}; + // The types of this library support all arithmetic operations one would expect. + // They can be between values of the same type, or the same signedness by default. + // See `mixed_type_arithmetic.cpp` for operations with different signedness. + + using boost::int128::int128_t; + using boost::int128::uint128_t; + + // Basic arithmetic with signed 128-bit integers + int128_t x {1000000000000LL}; // 1 trillion + int128_t y {999999999999LL}; // Just under 1 trillion + + std::cout << "=== Signed 128-bit Arithmetic ===" << std::endl; + std::cout << "x = " << x << std::endl; + std::cout << "y = " << y << std::endl; + + // Addition and subtraction + std::cout << "\nAddition and Subtraction:" << std::endl; + std::cout << "x + y = " << (x + y) << std::endl; + std::cout << "x - y = " << (x - y) << std::endl; + + // Multiplication - results that exceed 64-bit range + std::cout << "\nMultiplication (exceeds 64-bit range):" << std::endl; + std::cout << "x * y = " << (x * y) << std::endl; + + // Division and modulo + std::cout << "\nDivision and Modulo:" << std::endl; + std::cout << "x / 7 = " << (x / 7) << std::endl; + std::cout << "x % 7 = " << (x % 7) << std::endl; // Comparisons - assert(x > y); - assert(x >= y); - assert(y < x); - assert(y <= x); - assert(x == x); - assert(y != x); - - // Add,sub,mul,div - assert(x + y == 40); - assert(y - x == -44); - assert(x * y == -84); - assert(x / y == -21); - assert(x % y == 0); - - // Absolute Value - // For generic programming add using boost::int128::abs; at the top of the function, - // so that it will be found by ADL just by writing abs(y); - assert(boost::int128::abs(y) == 2); - - // Compound operations - x /= y; - assert(x == -21); - - y += 4L; - assert(y == 2); - - y *= -5LL; - assert(y == -10); + std::cout << "\nComparisons:" << std::endl; + std::cout << "x > y: " << std::boolalpha << (x > y) << std::endl; + std::cout << "x == y: " << (x == y) << std::endl; + std::cout << "x != y: " << (x != y) << std::endl; + + // Negative values and absolute value + int128_t negative {-42}; + std::cout << "\nNegative values:" << std::endl; + std::cout << "negative = " << negative << std::endl; + std::cout << "abs(negative) = " << boost::int128::abs(negative) << std::endl; + + // Compound assignment operators + std::cout << "\nCompound assignment operators:" << std::endl; + int128_t z {100}; + std::cout << "z = " << z << std::endl; + + z += 50; + std::cout << "z += 50: " << z << std::endl; + + z -= 25; + std::cout << "z -= 25: " << z << std::endl; + + z *= 2; + std::cout << "z *= 2: " << z << std::endl; + + z /= 5; + std::cout << "z /= 5: " << z << std::endl; + + z %= 7; + std::cout << "z %= 7: " << z << std::endl; + + // Unsigned 128-bit arithmetic - useful for very large positive values + std::cout << "\n=== Unsigned 128-bit Arithmetic ===" << std::endl; + uint128_t large {UINT64_C(0x1), UINT64_C(0x0)}; // 2^64 + std::cout << "large (2^64) = " << large << std::endl; + std::cout << "large * 2 = " << (large * 2U) << std::endl; + std::cout << "large + large = " << (large + large) << std::endl; + + // Increment and decrement + std::cout << "\nIncrement and Decrement:" << std::endl; + int128_t counter {10}; + std::cout << "counter = " << counter << std::endl; + std::cout << "++counter = " << ++counter << std::endl; + std::cout << "counter++ = " << counter++ << std::endl; + std::cout << "counter = " << counter << std::endl; + std::cout << "--counter = " << --counter << std::endl; return 0; -} +} \ No newline at end of file diff --git a/examples/charconv.cpp b/examples/charconv.cpp index 2965560b..0af5f1f1 100644 --- a/examples/charconv.cpp +++ b/examples/charconv.cpp @@ -1,90 +1,73 @@ // Copyright 2025 Matt Borland // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -// -// Allowing sign conversion is a required pre-requisite for Boost.Charconv -#define BOOST_INT128_ALLOW_SIGN_CONVERSION -#include +#include +#include #include #include #include #include #include -#include - -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wunused-variable" -#endif int main() { - constexpr boost::int128::uint128_t max_value = std::numeric_limits::max(); + using boost::int128::uint128_t; + using boost::int128::int128_t; - // Boost.Charconv can be used as it would be with any builtin type char buffer[64]; - auto r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), max_value); - assert(r); - *r.ptr = '\0'; // Boost/std charconv do not add null terminators - - std::cout << "Max unsigned value: " << buffer << std::endl; - - boost::int128::uint128_t return_value; - auto r_from = boost::charconv::from_chars(buffer, buffer + sizeof(buffer), return_value); - assert(r_from); - assert(max_value == return_value); - - // And same for signed types - constexpr auto min_signed_value = std::numeric_limits::min(); - - std::memset(buffer, 0, sizeof(buffer)); - r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), min_signed_value); - assert(r); - *r.ptr = '\0'; - - std::cout << "Min signed value: " << buffer << std::endl; - - boost::int128::int128_t signed_return_value; - r_from = boost::charconv::from_chars(buffer, buffer + sizeof(buffer), signed_return_value); - assert(r_from); - assert(min_signed_value == signed_return_value); - - // Boost from_chars also supports from_chars for a std::string or std::string_view - - std::string unsigned_string = "42"; - r_from = boost::charconv::from_chars(unsigned_string, return_value); - assert(r_from); - assert(return_value == boost::int128::uint128_t{42}); - - std::string signed_string = "-12345"; - r_from = boost::charconv::from_chars(signed_string, signed_return_value); - assert(r_from); - assert(signed_return_value == boost::int128::int128_t{-12345}); - - // We can also do non-base 10 value conversions for both types - std::memset(buffer, 0, sizeof(buffer)); - r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), max_value, 16); - assert(r); - *r.ptr = '\0'; - - std::cout << "Unsigned value in hex: 0x" << buffer << std::endl; - - return_value = 0U; - r_from = boost::charconv::from_chars(buffer, buffer + sizeof(buffer), return_value, 16); - assert(r_from); - - std::memset(buffer, 0, sizeof(buffer)); - r = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), boost::int128::int128_t{42}, 8); - assert(r); - *r.ptr = '\0'; - - std::cout << "Signed value octal: 0" << buffer << std::endl; - signed_return_value = 0; - r_from = boost::charconv::from_chars(buffer, buffer + sizeof(buffer), signed_return_value, 8); - assert(r_from); - assert(signed_return_value == 42); + // === to_chars: Convert integers to character strings === + std::cout << "=== to_chars ===" << std::endl; + + // Unsigned 128-bit to decimal string + constexpr uint128_t max_u128 {std::numeric_limits::max()}; + auto result {boost::charconv::to_chars(buffer, buffer + sizeof(buffer), max_u128)}; + *result.ptr = '\0'; + std::cout << "uint128_t max (decimal): " << buffer << std::endl; + + // Signed 128-bit to decimal string + constexpr int128_t min_i128 {std::numeric_limits::min()}; + result = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), min_i128); + *result.ptr = '\0'; + std::cout << "int128_t min (decimal): " << buffer << std::endl; + + // Hexadecimal output (base 16) + uint128_t hex_value {UINT64_C(0xDEADBEEF), UINT64_C(0xCAFEBABE12345678)}; + result = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), hex_value, 16); + *result.ptr = '\0'; + std::cout << "uint128_t (hex): 0x" << buffer << std::endl; + + // Octal output (base 8) + result = boost::charconv::to_chars(buffer, buffer + sizeof(buffer), int128_t{511}, 8); + *result.ptr = '\0'; + std::cout << "int128_t 511 (octal): 0" << buffer << std::endl; + + // === from_chars: Parse character strings to integers === + std::cout << "\n=== from_chars ===" << std::endl; + + // Parse decimal string to uint128_t + const char* decimal_str {"340282366920938463463374607431768211455"}; + uint128_t parsed_unsigned; + boost::charconv::from_chars(decimal_str, decimal_str + std::strlen(decimal_str), parsed_unsigned); + std::cout << "Parsed \"" << decimal_str << "\"" << std::endl; + std::cout << " Result: " << parsed_unsigned << std::endl; + std::cout << " Equals max? " << std::boolalpha << (parsed_unsigned == max_u128) << std::endl; + + // Parse negative decimal string to int128_t + const char* negative_str {"-170141183460469231731687303715884105728"}; + int128_t parsed_signed; + boost::charconv::from_chars(negative_str, negative_str + std::strlen(negative_str), parsed_signed); + std::cout << "Parsed \"" << negative_str << "\"" << std::endl; + std::cout << " Result: " << parsed_signed << std::endl; + std::cout << " Equals min? " << (parsed_signed == min_i128) << std::endl; + + // Parse hexadecimal string (base 16) + const char* hex_str {"DEADBEEFCAFEBABE12345678"}; + uint128_t parsed_hex; + boost::charconv::from_chars(hex_str, hex_str + std::strlen(hex_str), parsed_hex, 16); + std::cout << "Parsed hex \"" << hex_str << "\"" << std::endl; + std::cout << " Result: " << parsed_hex << std::endl; return 0; -} +} \ No newline at end of file diff --git a/examples/construction.cpp b/examples/construction.cpp index 6a048cb8..d7b234b7 100644 --- a/examples/construction.cpp +++ b/examples/construction.cpp @@ -2,60 +2,81 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -#include +#include +#include +#include +#include #include -#include -#include #include -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wunused-variable" -#endif - int main() { - // There are a number of ways to construct integer types + using boost::int128::uint128_t; + using boost::int128::int128_t; + + std::cout << "=== uint128_t Construction ===" << std::endl; - // 1) From a builtin-integer type - constexpr boost::int128::uint128_t from_builtin {6U}; - assert(from_builtin == 6U); + // 1) From a builtin integer type + constexpr uint128_t from_builtin {42U}; + std::cout << "From builtin (42U): " << from_builtin << std::endl; - // 2) By directly adding 128-bit hex/integer values - constexpr boost::int128::uint128_t from_hex {UINT64_C(0xFFFFFFFFFFFFFFFF), UINT64_C(0xFFFFFFFFFFFFFFFF)}; - assert(from_hex == std::numeric_limits::max()); + // 2) From high and low 64-bit values (high, low) + constexpr uint128_t from_parts {UINT64_C(0x1), UINT64_C(0x0)}; // 2^64 + std::cout << "From parts (1, 0) = 2^64: " << from_parts << std::endl; - // 3) From literal which allows values >2^64 to be easily constructed - // To match expectations the literals are in a separate literals namespace + constexpr uint128_t max_value {UINT64_C(0xFFFFFFFFFFFFFFFF), UINT64_C(0xFFFFFFFFFFFFFFFF)}; + std::cout << "From parts (max, max): " << max_value << std::endl; + std::cout << " Equals numeric_limits max? " << std::boolalpha + << (max_value == std::numeric_limits::max()) << std::endl; + + // 3) From user-defined literals (values > 2^64 without splitting) using namespace boost::int128::literals; - const auto from_literal = "36893488147419103232"_U128; // Can be constexpr, but older compilers (GCC <= 7) fail - static_assert(std::is_same::value, "uint128_t works fine with auto construction"); + const auto from_literal {"36893488147419103232"_U128}; // 2 * 2^64 + std::cout << "From literal \"36893488147419103232\"_U128: " << from_literal << std::endl; + + // 4) From macro (like UINT64_C but for 128-bit) + const auto from_macro {BOOST_INT128_UINT128_C(340282366920938463463374607431768211455)}; + std::cout << "From BOOST_INT128_UINT128_C(max): " << from_macro << std::endl; + + // 5) From input stream + std::stringstream ss; + ss.str("12345678901234567890123456789"); + uint128_t from_stream; + ss >> from_stream; + std::cout << "From stringstream: " << from_stream << std::endl; + + std::cout << "\n=== int128_t Construction ===" << std::endl; + + // Signed from builtin + constexpr int128_t signed_builtin {-42}; + std::cout << "From builtin (-42): " << signed_builtin << std::endl; + + // Signed from parts (high is signed, low is unsigned) + constexpr int128_t min_value {INT64_MIN, 0}; + std::cout << "From parts (INT64_MIN, 0): " << min_value << std::endl; + std::cout << " Equals numeric_limits min? " + << (min_value == std::numeric_limits::min()) << std::endl; - // 4) From macro appending the correct literal like UINT32_C, UINT64_C etc. - // This also allows values >2^64 to be constructed without needing to separate into high and low hex values - const auto from_macro {BOOST_INT128_UINT128_C(36893488147419103232)}; // Can be constexpr, but older compilers (GCC <= 7 and Clang <= 8) fail - assert(from_macro == from_literal); + // Signed literals (lowercase and uppercase both work) + const auto negative_literal {"-99999999999999999999"_i128}; + std::cout << "From literal \"-99999999999999999999\"_i128: " << negative_literal << std::endl; - // 5) Istream is supported by the types - std::stringstream in; - in.str("340282366920938463463374607431768211455"); - boost::int128::uint128_t from_stream; - in >> from_stream; - assert(from_stream == from_hex); + const auto positive_literal {"99999999999999999999"_I128}; + std::cout << "From literal \"99999999999999999999\"_I128: " << positive_literal << std::endl; - // These same methods also apply to int128_t - constexpr boost::int128::int128_t from_int {-42}; - assert(from_int == -42); + // Signed macro + const auto from_signed_macro {BOOST_INT128_INT128_C(-170141183460469231731687303715884105728)}; + std::cout << "From BOOST_INT128_INT128_C(min): " << from_signed_macro << std::endl; - constexpr boost::int128::int128_t from_hex_signed {INT64_MIN, 0}; - assert(from_hex_signed == std::numeric_limits::min()); + std::cout << "\n=== Default and Copy Construction ===" << std::endl; - // Both capital and lowercase letters work - const auto negative_literal {"-42"_i128}; - assert(negative_literal == from_int); + // Default construction (zero-initialized) + uint128_t default_constructed {}; + std::cout << "Default constructed: " << default_constructed << std::endl; - const auto negative_macro {BOOST_INT128_INT128_C(-170141183460469231731687303715884105728)}; - assert(negative_macro == from_hex_signed); + // Copy construction + uint128_t copied {from_literal}; + std::cout << "Copy constructed: " << copied << std::endl; return 0; -} +} \ No newline at end of file diff --git a/examples/cstdlib.cpp b/examples/cstdlib.cpp new file mode 100644 index 00000000..601a20c9 --- /dev/null +++ b/examples/cstdlib.cpp @@ -0,0 +1,77 @@ +// Copyright 2025 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +int main() +{ + using boost::int128::uint128_t; + using boost::int128::int128_t; + + std::cout << "=== div() Function ===" << std::endl; + std::cout << "Returns both quotient and remainder in a single operation" << std::endl; + + // Unsigned division + std::cout << "\n--- Unsigned Division ---" << std::endl; + + constexpr uint128_t dividend {1000000000000000000ULL}; + constexpr uint128_t divisor {7}; + + auto uresult {boost::int128::div(dividend, divisor)}; + std::cout << dividend << " / " << divisor << " = " << uresult.quot + << " remainder " << uresult.rem << std::endl; + + // Verify: quot * divisor + rem == dividend + std::cout << "Verification: " << uresult.quot << " * " << divisor + << " + " << uresult.rem << " = " << (uresult.quot * divisor + uresult.rem) << std::endl; + + // Large value division + std::cout << "\n--- Large Value Division ---" << std::endl; + + constexpr uint128_t large_dividend {uint128_t{1} << 100}; // 2^100 + constexpr uint128_t large_divisor {uint128_t{1} << 50}; // 2^50 + + auto large_result {boost::int128::div(large_dividend, large_divisor)}; + std::cout << "2^100 / 2^50 = " << large_result.quot + << " remainder " << large_result.rem << std::endl; + + // Signed division + std::cout << "\n--- Signed Division ---" << std::endl; + + constexpr int128_t signed_dividend {-100}; + constexpr int128_t signed_divisor {7}; + + auto sresult {boost::int128::div(signed_dividend, signed_divisor)}; + std::cout << signed_dividend << " / " << signed_divisor << " = " << sresult.quot + << " remainder " << sresult.rem << std::endl; + + // Different sign combinations + std::cout << "\n--- Sign Combinations ---" << std::endl; + + constexpr int128_t pos {17}; + constexpr int128_t neg {-17}; + constexpr int128_t div_pos {5}; + constexpr int128_t div_neg {-5}; + + auto pp {boost::int128::div(pos, div_pos)}; + auto pn {boost::int128::div(pos, div_neg)}; + auto np {boost::int128::div(neg, div_pos)}; + auto nn {boost::int128::div(neg, div_neg)}; + + std::cout << " 17 / 5 = " << pp.quot << " remainder " << pp.rem << std::endl; + std::cout << " 17 / -5 = " << pn.quot << " remainder " << pn.rem << std::endl; + std::cout << "-17 / 5 = " << np.quot << " remainder " << np.rem << std::endl; + std::cout << "-17 / -5 = " << nn.quot << " remainder " << nn.rem << std::endl; + + // Edge case: dividend smaller than divisor + std::cout << "\n--- Edge Cases ---" << std::endl; + + auto small_div {boost::int128::div(uint128_t{3}, uint128_t{10})}; + std::cout << "3 / 10 = " << small_div.quot << " remainder " << small_div.rem << std::endl; + + return 0; +} \ No newline at end of file diff --git a/examples/fmt_format.cpp b/examples/fmt_format.cpp new file mode 100644 index 00000000..880aa227 --- /dev/null +++ b/examples/fmt_format.cpp @@ -0,0 +1,127 @@ +// Copyright 2025 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +// This example demonstrates {fmt} library integration with int128 types. +// Requires {fmt} to be installed: https://github.com/fmtlib/fmt +// +// For C++20 std::format support, use instead, +// which provides the same formatting capabilities with std::format. + +#define FMT_HEADER_ONLY +#include +#include + +#ifdef BOOST_INT128_HAS_FMT_FORMAT + +#include +#include + +int main() +{ + using boost::int128::int128_t; + using boost::int128::uint128_t; + + std::cout << "=== Basic Formatting ===" << std::endl; + + constexpr uint128_t unsigned_value {0xDEADBEEF, 0xCAFEBABE12345678}; + constexpr int128_t signed_value {-123456789012345678}; + + // Default decimal formatting + std::cout << fmt::format("Default (decimal): {}", unsigned_value) << std::endl; + std::cout << fmt::format("Signed value: {}", signed_value) << std::endl; + + std::cout << "\n=== Base Specifiers ===" << std::endl; + + // Different bases: binary, octal, decimal, hex + constexpr uint128_t value {255}; + std::cout << fmt::format("Binary: {:b}", value) << std::endl; + std::cout << fmt::format("Octal: {:o}", value) << std::endl; + std::cout << fmt::format("Decimal: {:d}", value) << std::endl; + std::cout << fmt::format("Hexadecimal: {:x}", value) << std::endl; + std::cout << fmt::format("Hex (upper): {:X}", value) << std::endl; + + std::cout << "\n=== Alternate Form (Prefixes) ===" << std::endl; + + // Using # for alternate form adds base prefixes + std::cout << fmt::format("Binary with prefix: {:#b}", value) << std::endl; + std::cout << fmt::format("Octal with prefix: {:#o}", value) << std::endl; + std::cout << fmt::format("Hex with prefix: {:#x}", value) << std::endl; + std::cout << fmt::format("Hex upper prefix: {:#X}", value) << std::endl; + + std::cout << "\n=== Sign Options ===" << std::endl; + + constexpr int128_t positive {42}; + constexpr int128_t negative {-42}; + + // Sign specifiers: + (always show), - (default), space (space for positive) + std::cout << fmt::format("Plus sign: {:+} and {:+}", positive, negative) << std::endl; + std::cout << fmt::format("Minus only: {} and {}", positive, negative) << std::endl; + std::cout << fmt::format("Space sign: {: } and {: }", positive, negative) << std::endl; + + std::cout << "\n=== Zero Padding ===" << std::endl; + + // Padding with zeros (no alignment specifier) + std::cout << fmt::format("8-digit padding: {:08}", value) << std::endl; + std::cout << fmt::format("16-digit padding: {:016}", value) << std::endl; + + std::cout << "\n=== Alignment ===" << std::endl; + + // Left, right, and center alignment with default fill (space) + std::cout << fmt::format("Left align: '{:<10}'", positive) << std::endl; + std::cout << fmt::format("Right align: '{:>10}'", positive) << std::endl; + std::cout << fmt::format("Center align: '{:^10}'", positive) << std::endl; + + std::cout << "\n=== Alignment with Fill Characters ===" << std::endl; + + // Custom fill characters + std::cout << fmt::format("Left with *: '{:*<10}'", positive) << std::endl; + std::cout << fmt::format("Right with 0: '{:0>10}'", positive) << std::endl; + std::cout << fmt::format("Center with -: '{:-^10}'", positive) << std::endl; + + std::cout << "\n=== Alignment with Sign ===" << std::endl; + + // Alignment combined with sign specifiers + std::cout << fmt::format("Right align +: '{:>+10}'", positive) << std::endl; + std::cout << fmt::format("Left align +: '{:<+10}'", positive) << std::endl; + std::cout << fmt::format("Center align +: '{:^+11}'", positive) << std::endl; + std::cout << fmt::format("Right align -: '{:*>10}'", negative) << std::endl; + + std::cout << "\n=== Alignment with Hex and Prefix ===" << std::endl; + + // Alignment with base specifiers and prefixes + std::cout << fmt::format("Right align hex: '{:>10x}'", value) << std::endl; + std::cout << fmt::format("Left align hex: '{:<10x}'", value) << std::endl; + std::cout << fmt::format("Center with prefix: '{:*^#12x}'", value) << std::endl; + + std::cout << "\n=== Large Values ===" << std::endl; + + // Demonstrate with values beyond 64-bit range + constexpr auto uint_max {std::numeric_limits::max()}; + constexpr auto int_min {std::numeric_limits::min()}; + + std::cout << fmt::format("uint128_t max: {}", uint_max) << std::endl; + std::cout << fmt::format("uint128_t max (hex): {:#x}", uint_max) << std::endl; + std::cout << fmt::format("int128_t min: {}", int_min) << std::endl; + + std::cout << "\n=== Combined Format Specifiers ===" << std::endl; + + // Combining multiple specifiers + std::cout << fmt::format("Hex with prefix, uppercase, padded: {:#016X}", unsigned_value) << std::endl; + std::cout << fmt::format("Signed with plus, padded: {:+020}", signed_value) << std::endl; + + return 0; +} + +#else + +#include + +int main() +{ + std::cout << "This example requires {fmt} library to be installed." << std::endl; + std::cout << "Install from: https://github.com/fmtlib/fmt" << std::endl; + return 0; +} + +#endif diff --git a/examples/mixed_type_arithmetic.cpp b/examples/mixed_type_arithmetic.cpp index 7b11cb7f..1220b227 100644 --- a/examples/mixed_type_arithmetic.cpp +++ b/examples/mixed_type_arithmetic.cpp @@ -2,8 +2,9 @@ // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt -// #define BOOST_INT128_ALLOW_SIGN_CONVERSION +#define BOOST_INT128_ALLOW_SIGN_CONVERSION #include +#include int main() { @@ -11,27 +12,33 @@ int main() // In order for this file to compile #define BOOST_INT128_ALLOW_SIGN_CONVERSION // BEFORE the inclusion of any file of this library (uncomment the top line) // - // Unlike builtin types we cannot enforce sign correctness via compiler flag, + // Unlike builtin types, we cannot enforce sign correctness via a compiler flag, // so we made it the default. + std::cout << "=== Mixed Type Arithmetic with uint128_t ===" << std::endl; constexpr boost::int128::uint128_t unsigned_value {3}; + std::cout << "unsigned_value = " << unsigned_value << std::endl; constexpr auto greater_unsigned_value {unsigned_value + 5}; - assert(unsigned_value + 1 == 4); - assert(unsigned_value - 1 == 2); - assert(unsigned_value * 2 == 6); - assert(unsigned_value / 3 == 1); - assert(unsigned_value % 3 == 0); - assert(unsigned_value + 5 == greater_unsigned_value); + std::cout << "unsigned_value + 1 = " << (unsigned_value + 1) << std::endl; + std::cout << "unsigned_value - 1 = " << (unsigned_value - 1) << std::endl; + std::cout << "unsigned_value * 2 = " << (unsigned_value * 2) << std::endl; + std::cout << "unsigned_value / 3 = " << (unsigned_value / 3) << std::endl; + std::cout << "unsigned_value % 3 = " << (unsigned_value % 3) << std::endl; + std::cout << "unsigned_value + 5 = " << (unsigned_value + 5) + << " (same as greater_unsigned_value: " << greater_unsigned_value << ")" << std::endl; + + std::cout << "\n=== Mixed Type Arithmetic with int128_t ===" << std::endl; constexpr boost::int128::int128_t signed_value {-3}; + std::cout << "signed_value = " << signed_value << std::endl; - assert(signed_value + 1U == -2); - assert(signed_value - 4U == -7); - assert(signed_value * 2 == -6); - assert(signed_value / 4U == 0); + std::cout << "signed_value + 1U = " << (signed_value + 1U) << std::endl; + std::cout << "signed_value - 4U = " << (signed_value - 4U) << std::endl; + std::cout << "signed_value * 2 = " << (signed_value * 2) << std::endl; + std::cout << "signed_value / 4U = " << (signed_value / 4U) << std::endl; return 0; } diff --git a/examples/numeric_algorithms.cpp b/examples/numeric_algorithms.cpp new file mode 100644 index 00000000..e1e7dfd5 --- /dev/null +++ b/examples/numeric_algorithms.cpp @@ -0,0 +1,97 @@ +// Copyright 2025 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include + +int main() +{ + using boost::int128::uint128_t; + using boost::int128::int128_t; + + std::cout << "=== Greatest Common Divisor (gcd) ===" << std::endl; + + // Basic gcd + constexpr uint128_t a {48}; + constexpr uint128_t b {18}; + std::cout << "gcd(" << a << ", " << b << ") = " << boost::int128::gcd(a, b) << std::endl; + + // gcd with larger values + constexpr uint128_t large_a {123456789012345678ULL}; + constexpr uint128_t large_b {987654321098765432ULL}; + std::cout << "gcd(" << large_a << ", " << large_b << ") = " + << boost::int128::gcd(large_a, large_b) << std::endl; + + // gcd with 128-bit values + constexpr uint128_t huge_a {uint128_t{1} << 100}; + constexpr uint128_t huge_b {uint128_t{1} << 80}; + std::cout << "gcd(2^100, 2^80) = " << boost::int128::gcd(huge_a, huge_b) << " (= 2^80)" << std::endl; + + // Signed gcd (always returns positive) + constexpr int128_t neg_a {-48}; + constexpr int128_t neg_b {18}; + std::cout << "gcd(" << neg_a << ", " << neg_b << ") = " + << boost::int128::gcd(neg_a, neg_b) << " (always positive)" << std::endl; + + std::cout << "\n=== Least Common Multiple (lcm) ===" << std::endl; + + // Basic lcm + constexpr uint128_t x {12}; + constexpr uint128_t y {18}; + std::cout << "lcm(" << x << ", " << y << ") = " << boost::int128::lcm(x, y) << std::endl; + + // lcm with coprime numbers + constexpr uint128_t p {7}; + constexpr uint128_t q {11}; + std::cout << "lcm(" << p << ", " << q << ") = " << boost::int128::lcm(p, q) + << " (coprime: lcm = p * q)" << std::endl; + + // Relationship: gcd(a,b) * lcm(a,b) = a * b + std::cout << "\nVerifying gcd * lcm = a * b:" << std::endl; + auto g {boost::int128::gcd(x, y)}; + auto l {boost::int128::lcm(x, y)}; + std::cout << "gcd(" << x << ", " << y << ") * lcm(" << x << ", " << y << ") = " + << (g * l) << std::endl; + std::cout << x << " * " << y << " = " << (x * y) << std::endl; + + std::cout << "\n=== Midpoint ===" << std::endl; + + // Unsigned midpoint + constexpr uint128_t low {10}; + constexpr uint128_t high {20}; + std::cout << "midpoint(" << low << ", " << high << ") = " + << boost::int128::midpoint(low, high) << std::endl; + + // Midpoint with odd sum (rounds toward first argument) + constexpr uint128_t odd_low {10}; + constexpr uint128_t odd_high {21}; + std::cout << "midpoint(" << odd_low << ", " << odd_high << ") = " + << boost::int128::midpoint(odd_low, odd_high) << " (rounds toward first arg)" << std::endl; + std::cout << "midpoint(" << odd_high << ", " << odd_low << ") = " + << boost::int128::midpoint(odd_high, odd_low) << " (rounds toward first arg)" << std::endl; + + // Midpoint avoids overflow (unlike (a+b)/2) + std::cout << "\n--- Overflow-safe midpoint ---" << std::endl; + constexpr auto uint_max {std::numeric_limits::max()}; + constexpr auto uint_max_minus_10 {uint_max - 10U}; + std::cout << "midpoint(uint128_max, uint128_max - 10) = " + << boost::int128::midpoint(uint_max, uint_max_minus_10) << std::endl; + std::cout << "(This would overflow if computed as (a + b) / 2)" << std::endl; + + // Signed midpoint + std::cout << "\n--- Signed midpoint ---" << std::endl; + constexpr int128_t neg {-100}; + constexpr int128_t pos {100}; + std::cout << "midpoint(" << neg << ", " << pos << ") = " + << boost::int128::midpoint(neg, pos) << std::endl; + + constexpr int128_t neg2 {-100}; + constexpr int128_t neg3 {-50}; + std::cout << "midpoint(" << neg2 << ", " << neg3 << ") = " + << boost::int128::midpoint(neg2, neg3) << std::endl; + + return 0; +} \ No newline at end of file diff --git a/examples/rollover.cpp b/examples/rollover.cpp new file mode 100644 index 00000000..115f39bb --- /dev/null +++ b/examples/rollover.cpp @@ -0,0 +1,38 @@ +// Copyright 2025 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// +// This example demonstrates the rollover behavior for both signed and unsigned int128 + +#include +#include +#include +#include + +int main() +{ + using boost::int128::uint128_t; + using boost::int128::int128_t; + + constexpr uint128_t max_unsigned_value {std::numeric_limits::max()}; + constexpr uint128_t min_unsigned_value {std::numeric_limits::min()}; + + std::cout << "=== uint128_t behavior ===" << std::endl; + + std::cout << "Max of uint128_t: " << max_unsigned_value << '\n' + << "Max + 1U: " << max_unsigned_value + 1U << "\n\n"; + + std::cout << "Min of uint128_t: " << min_unsigned_value << '\n' + << "Min - 1U: " << min_unsigned_value - 1U << "\n\n"; + + constexpr int128_t max_signed_value {std::numeric_limits::max()}; + constexpr int128_t min_signed_value {std::numeric_limits::min()}; + + std::cout << "=== int128_t behavior ===" << std::endl; + + std::cout << "Max of int128_t: " << max_signed_value << '\n' + << "Max + 1: " << max_signed_value + 1 << "\n"; + + std::cout << "\nMin of int128_t: " << min_signed_value << '\n' + << "Min - 1: " << min_signed_value - 1 << '\n' << std::endl; +} diff --git a/examples/saturating_arithmetic.cpp b/examples/saturating_arithmetic.cpp index cf424497..44e2c98c 100644 --- a/examples/saturating_arithmetic.cpp +++ b/examples/saturating_arithmetic.cpp @@ -6,6 +6,7 @@ #include #include +#include // Or you can do a single header @@ -13,44 +14,56 @@ #include #include - -#ifdef __clang__ -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wunused-variable" -#endif - -#ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable:4146) // MSVC 14.1 only unary minus applied to unsigned type -#endif +#include int main() { + using boost::int128::uint128_t; + using boost::int128::int128_t; + // std::numeric_limits is overloaded for both types - constexpr auto uint_max {std::numeric_limits::max()}; - static_assert(std::is_same::value, "Types should match"); + constexpr auto uint_max {std::numeric_limits::max()}; + static_assert(std::is_same::value, "Types should match"); - constexpr boost::int128::int128_t int_max {std::numeric_limits::max()}; + constexpr auto int_max {std::numeric_limits::max()}; + constexpr auto int_min {std::numeric_limits::min()}; + + std::cout << "=== Saturating Arithmetic ===" << std::endl; + std::cout << "uint128_t max = " << uint_max << std::endl; + std::cout << "int128_t max = " << int_max << std::endl; + std::cout << "int128_t min = " << int_min << std::endl; // Saturating arithmetic returns max on overflow, or min on underflow rather than rolling over - assert(boost::int128::add_sat(uint_max, uint_max) == uint_max); - assert(boost::int128::sub_sat(boost::int128::uint128_t{0}, uint_max) == 0U); + std::cout << "\n=== Saturating Addition and Subtraction ===" << std::endl; + std::cout << "add_sat(uint_max, uint_max) = " << boost::int128::add_sat(uint_max, uint_max) + << " (saturates to uint_max)" << std::endl; + std::cout << "sub_sat(0, uint_max) = " << boost::int128::sub_sat(uint128_t{0}, uint_max) + << " (saturates to 0, not underflow)" << std::endl; // This is especially useful for signed types since rollover is undefined - assert(boost::int128::mul_sat(int_max, 2) == int_max); - assert(boost::int128::mul_sat(-(int_max - 2), 5) == std::numeric_limits::min()); - - // The only case in the library where div sat overflows is x = std::numeric_limits::min() and y = -1 - assert(boost::int128::div_sat(std::numeric_limits::min(), -1) == int_max); - - // Saturating case allows types to be safely converted without rollover behavior - assert(boost::int128::saturate_cast(uint_max) == int_max); + std::cout << "\n=== Saturating Multiplication ===" << std::endl; + std::cout << "mul_sat(int_max, 2) = " << boost::int128::mul_sat(int_max, 2) + << " (saturates to int_max)" << std::endl; + std::cout << "mul_sat(-(int_max - 2), 5) = " << boost::int128::mul_sat(-(int_max - 2), 5) + << " (saturates to int_min)" << std::endl; + + // The only case in the library where div_sat overflows is x = int_min and y = -1 + std::cout << "\n=== Saturating Division ===" << std::endl; + std::cout << "div_sat(int_min, -1) = " << boost::int128::div_sat(int_min, -1) + << " (saturates to int_max; normally this overflows)" << std::endl; + + // saturate_cast allows types to be safely converted without rollover behavior + std::cout << "\n=== Saturating Casts ===" << std::endl; + std::cout << "saturate_cast(uint_max) = " << boost::int128::saturate_cast(uint_max) + << " (saturates to int_max)" << std::endl; // You can also cast to builtin types - assert(boost::int128::saturate_cast(int_max) == INT64_MAX); + std::cout << "saturate_cast(int_max) = " << boost::int128::saturate_cast(int_max) + << " (saturates to INT64_MAX)" << std::endl; // Even of different signedness as this is treated like a static cast - assert(boost::int128::saturate_cast(uint_max) == INT32_MAX); + std::cout << "saturate_cast(uint_max) = " << boost::int128::saturate_cast(uint_max) + << " (saturates to INT32_MAX)" << std::endl; return 0; } diff --git a/examples/stream.cpp b/examples/stream.cpp index 4081568c..12e2961e 100644 --- a/examples/stream.cpp +++ b/examples/stream.cpp @@ -5,25 +5,82 @@ #include #include #include -#include +#include int main() { + using boost::int128::int128_t; + using boost::int128::uint128_t; + + std::cout << "=== Basic Streaming ===" << std::endl; + // Both types allow streaming as one would expect from a regular builtin-type - constexpr boost::int128::int128_t signed_value {-42}; + constexpr int128_t signed_value {-42}; std::cout << "Signed value: " << signed_value << std::endl; // We can also use to change the output format - constexpr boost::int128::uint128_t unsigned_value {0x1, UINT64_MAX}; + constexpr uint128_t unsigned_value {0x1, UINT64_MAX}; std::cout << "Unsigned value (dec): " << unsigned_value << '\n' - << "Unsigned value (hex): " << std::hex << unsigned_value << '\n' // LCOV_EXCL_LINE - << "Unsigned value (oct): " << std::oct << unsigned_value << std::endl; // LCOV_EXCL_LINE + << "Unsigned value (hex): " << std::hex << unsigned_value << '\n' + << "Unsigned value (oct): " << std::oct << unsigned_value << std::endl; // Hex also can be manipulated to be uppercase std::cout << "Upper unsigned value: " << std::hex << std::uppercase << unsigned_value << std::endl; - // And returned to default formating + // And returned to default formatting std::cout << "Lower unsigned value: " << std::dec << std::nouppercase << unsigned_value << std::endl; + // Large values that exceed 64-bit range + std::cout << "\n=== Large Values (Beyond 64-bit) ===" << std::endl; + + // 2^64 = 18446744073709551616 (first value that doesn't fit in uint64_t) + constexpr uint128_t two_to_64 {1, 0}; + std::cout << "2^64 = " << two_to_64 << std::endl; + + // 2^100 = a very large number + constexpr uint128_t two_to_100 {uint128_t{1} << 100}; + std::cout << "2^100 = " << two_to_100 << std::endl; + + // Maximum uint128_t value + constexpr auto uint_max {std::numeric_limits::max()}; + std::cout << "uint128_t max = " << uint_max << std::endl; + + // Minimum and maximum int128_t values + constexpr auto int_min {std::numeric_limits::min()}; + constexpr auto int_max {std::numeric_limits::max()}; + std::cout << "int128_t min = " << int_min << std::endl; + std::cout << "int128_t max = " << int_max << std::endl; + + // String conversion using stringstream + std::cout << "\n=== String Conversion with std::stringstream ===" << std::endl; + + // Convert uint128_t to string + std::ostringstream oss; + oss << two_to_100; + auto str {oss.str()}; + std::cout << "uint128_t to string: \"" << str << "\"" << std::endl; + + // Convert string to uint128_t + std::istringstream iss {"123456789012345678901234567890"}; + uint128_t parsed_value {}; + iss >> parsed_value; + std::cout << "String to uint128_t: " << parsed_value << std::endl; + + // Round-trip: value -> string -> value + std::cout << "\n=== Round-trip Conversion ===" << std::endl; + constexpr uint128_t original {0xDEADBEEF, 0xCAFEBABE12345678}; + std::ostringstream oss2; + oss2 << original; + auto original_str {oss2.str()}; + + std::istringstream iss2 {original_str}; + uint128_t round_tripped {}; + iss2 >> round_tripped; + + std::cout << "Original: " << original << std::endl; + std::cout << "As string: \"" << original_str << "\"" << std::endl; + std::cout << "Round-tripped: " << round_tripped << std::endl; + std::cout << "Match: " << std::boolalpha << (original == round_tripped) << std::endl; + return 0; } diff --git a/include/boost/int128/charconv.hpp b/include/boost/int128/charconv.hpp index 0d6b606d..9171cae7 100644 --- a/include/boost/int128/charconv.hpp +++ b/include/boost/int128/charconv.hpp @@ -11,6 +11,7 @@ #if __has_include() #include +#include #include #include @@ -37,9 +38,81 @@ struct make_signed { using type = int128::int128_t; }; template <> struct make_signed { using type = int128::int128_t; }; +BOOST_INT128_INLINE_CONSTEXPR int128::uint128_t int128_pow10[39] = +{ + int128::uint128_t{UINT64_C(0x0), UINT64_C(0x1)}, + int128::uint128_t{UINT64_C(0x0), UINT64_C(0xa)}, + int128::uint128_t{UINT64_C(0x0), UINT64_C(0x64)}, + int128::uint128_t{UINT64_C(0x0), UINT64_C(0x3e8)}, + int128::uint128_t{UINT64_C(0x0), UINT64_C(0x2710)}, + int128::uint128_t{UINT64_C(0x0), UINT64_C(0x186a0)}, + int128::uint128_t{UINT64_C(0x0), UINT64_C(0xf4240)}, + int128::uint128_t{UINT64_C(0x0), UINT64_C(0x989680)}, + int128::uint128_t{UINT64_C(0x0), UINT64_C(0x5f5e100)}, + int128::uint128_t{UINT64_C(0x0), UINT64_C(0x3b9aca00)}, + int128::uint128_t{UINT64_C(0x0), UINT64_C(0x2540be400)}, + int128::uint128_t{UINT64_C(0x0), UINT64_C(0x174876e800)}, + int128::uint128_t{UINT64_C(0x0), UINT64_C(0xe8d4a51000)}, + int128::uint128_t{UINT64_C(0x0), UINT64_C(0x9184e72a000)}, + int128::uint128_t{UINT64_C(0x0), UINT64_C(0x5af3107a4000)}, + int128::uint128_t{UINT64_C(0x0), UINT64_C(0x38d7ea4c68000)}, + int128::uint128_t{UINT64_C(0x0), UINT64_C(0x2386f26fc10000)}, + int128::uint128_t{UINT64_C(0x0), UINT64_C(0x16345785d8a0000)}, + int128::uint128_t{UINT64_C(0x0), UINT64_C(0xde0b6b3a7640000)}, + int128::uint128_t{UINT64_C(0x0), UINT64_C(0x8ac7230489e80000)}, + int128::uint128_t{UINT64_C(0x5), UINT64_C(0x6bc75e2d63100000)}, + int128::uint128_t{UINT64_C(0x36), UINT64_C(0x35c9adc5dea00000)}, + int128::uint128_t{UINT64_C(0x21e), UINT64_C(0x19e0c9bab2400000)}, + int128::uint128_t{UINT64_C(0x152d), UINT64_C(0x2c7e14af6800000)}, + int128::uint128_t{UINT64_C(0xd3c2), UINT64_C(0x1bcecceda1000000)}, + int128::uint128_t{UINT64_C(0x84595), UINT64_C(0x161401484a000000)}, + int128::uint128_t{UINT64_C(0x52b7d2), UINT64_C(0xdcc80cd2e4000000)}, + int128::uint128_t{UINT64_C(0x33b2e3c), UINT64_C(0x9fd0803ce8000000)}, + int128::uint128_t{UINT64_C(0x204fce5e), UINT64_C(0x3e25026110000000)}, + int128::uint128_t{UINT64_C(0x1431e0fae), UINT64_C(0x6d7217caa0000000)}, + int128::uint128_t{UINT64_C(0xc9f2c9cd0), UINT64_C(0x4674edea40000000)}, + int128::uint128_t{UINT64_C(0x7e37be2022), UINT64_C(0xc0914b2680000000)}, + int128::uint128_t{UINT64_C(0x4ee2d6d415b), UINT64_C(0x85acef8100000000)}, + int128::uint128_t{UINT64_C(0x314dc6448d93), UINT64_C(0x38c15b0a00000000)}, + int128::uint128_t{UINT64_C(0x1ed09bead87c0), UINT64_C(0x378d8e6400000000)}, + int128::uint128_t{UINT64_C(0x13426172c74d82), UINT64_C(0x2b878fe800000000)}, + int128::uint128_t{UINT64_C(0xc097ce7bc90715), UINT64_C(0xb34b9f1000000000)}, + int128::uint128_t{UINT64_C(0x785ee10d5da46d9), UINT64_C(0xf436a000000000)}, + int128::uint128_t{UINT64_C(0x4b3b4ca85a86c47a), UINT64_C(0x98a224000000000)} +}; + +constexpr int num_digits(const int128::uint128_t& x) noexcept +{ + if (x.high == UINT64_C(0)) + { + return num_digits(x.low); + } + + // Use the most significant bit position to approximate log10 + // log10(x) ~= log2(x) / log2(10) ~= log2(x) / 3.32 + + const auto msb {64 + (63 - int128::detail::impl::countl_impl(x.high))}; + + // Approximate log10 + const auto estimated_digits {(msb * 1000) / 3322 + 1}; + + if (estimated_digits < 39 && x >= int128_pow10[static_cast(estimated_digits)]) + { + return estimated_digits + 1; + } + + // Estimated digits can't be less than 20 digits (65-bits minimum) + if (x < int128_pow10[estimated_digits - 1]) + { + return estimated_digits - 1; + } + + return estimated_digits; +} + } // namespace detail -BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, int128::uint128_t value, int base = 10) noexcept +BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, const int128::uint128_t value, const int base = 10) noexcept { if (base == 10) { @@ -49,7 +122,7 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, int12 return detail::to_chars_integer_impl(first, last, value, base); } -BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, int128::int128_t value, int base = 10) noexcept +BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, const int128::int128_t value, const int base = 10) noexcept { if (base == 10) { @@ -59,17 +132,17 @@ BOOST_CHARCONV_CONSTEXPR to_chars_result to_chars(char* first, char* last, int12 return detail::to_chars_integer_impl(first, last, value, base); } -BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, int128::uint128_t& value, int base = 10) noexcept +BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, int128::uint128_t& value, const int base = 10) noexcept { return detail::from_chars_integer_impl(first, last, value, base); } -BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(core::string_view sv, int128::uint128_t& value, int base = 10) noexcept +BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(core::string_view sv, int128::uint128_t& value, const int base = 10) noexcept { return detail::from_chars_integer_impl(sv.data(), sv.data() + sv.size(), value, base); } -BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, int128::int128_t& value, int base = 10) noexcept +BOOST_CHARCONV_GCC5_CONSTEXPR from_chars_result from_chars(const char* first, const char* last, int128::int128_t& value, const int base = 10) noexcept { return detail::from_chars_integer_impl(first, last, value, base); } diff --git a/include/boost/int128/cstdlib.hpp b/include/boost/int128/cstdlib.hpp index 4f2c5b18..87c71994 100644 --- a/include/boost/int128/cstdlib.hpp +++ b/include/boost/int128/cstdlib.hpp @@ -81,11 +81,7 @@ constexpr i128div_t div(const int128_t x, const int128_t y) noexcept const auto unsigned_res {div(abs_lhs, abs_rhs)}; const auto negative_quot {(x.high < 0) != (y.high < 0)}; - #if defined(_MSC_VER) && !defined(__GNUC__) - const auto negative_rem {static_cast(x.high < 0)}; - #else - const auto negative_rem {static_cast((x.high < 0) != (y.high < 0))}; - #endif + const auto negative_rem {x.high < 0}; i128div_t res {static_cast(unsigned_res.quot), static_cast(unsigned_res.rem)}; diff --git a/include/boost/int128/detail/config.hpp b/include/boost/int128/detail/config.hpp index dd4a48c2..7fd2c8d2 100644 --- a/include/boost/int128/detail/config.hpp +++ b/include/boost/int128/detail/config.hpp @@ -278,4 +278,11 @@ using builtin_u128 = std::_Unsigned128; #endif // Exceptions +#if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L && __has_include() +# define BOOST_INT128_HAS_SPACESHIP_OPERATOR +# ifndef BOOST_INT128_BUILD_MODULE +# include +# endif +#endif + #endif // BOOST_INT128_DETAIL_CONFIG_HPP diff --git a/include/boost/int128/detail/int128_imp.hpp b/include/boost/int128/detail/int128_imp.hpp index 1bcc9251..58c2ef48 100644 --- a/include/boost/int128/detail/int128_imp.hpp +++ b/include/boost/int128/detail/int128_imp.hpp @@ -1100,6 +1100,120 @@ BOOST_INT128_BUILTIN_CONSTEXPR bool operator>=(const T, const int128_t) noexcept #endif // BOOST_INT128_HAS_INT128 +//===================================== +// Spaceship Operator +//===================================== + +#ifdef BOOST_INT128_HAS_SPACESHIP_OPERATOR + +BOOST_INT128_EXPORT constexpr std::strong_ordering operator<=>(const int128_t lhs, const int128_t rhs) noexcept +{ + if (lhs < rhs) + { + return std::strong_ordering::less; + } + else if (lhs == rhs) + { + return std::strong_ordering::equivalent; + } + else + { + return std::strong_ordering::greater; + } +} + +BOOST_INT128_EXPORT template +constexpr std::strong_ordering operator<=>(const int128_t lhs, const SignedInteger rhs) noexcept +{ + if (lhs < rhs) + { + return std::strong_ordering::less; + } + else if (lhs == rhs) + { + return std::strong_ordering::equivalent; + } + else + { + return std::strong_ordering::greater; + } +} + +BOOST_INT128_EXPORT template +constexpr std::strong_ordering operator<=>(const SignedInteger lhs, const int128_t rhs) noexcept +{ + if (lhs < rhs) + { + return std::strong_ordering::less; + } + else if (lhs == rhs) + { + return std::strong_ordering::equivalent; + } + else + { + return std::strong_ordering::greater; + } +} + +BOOST_INT128_EXPORT template +constexpr std::strong_ordering operator<=>(const int128_t lhs, const UnsignedInteger rhs) noexcept +{ + #ifdef BOOST_INT128_ALLOW_SIGN_COMPARE + + if (lhs < rhs) + { + return std::strong_ordering::less; + } + else if (lhs == rhs) + { + return std::strong_ordering::equivalent; + } + else + { + return std::strong_ordering::greater; + } + + #else + + static_assert(detail::is_signed_integer_v, "Sign Compare Error"); + static_cast(lhs); + static_cast(rhs); + return std::strong_ordering::less; + + #endif +} + +BOOST_INT128_EXPORT template +constexpr std::strong_ordering operator<=>(const UnsignedInteger lhs, const int128_t rhs) noexcept +{ + #ifdef BOOST_INT128_ALLOW_SIGN_COMPARE + + if (lhs < rhs) + { + return std::strong_ordering::less; + } + else if (lhs == rhs) + { + return std::strong_ordering::equivalent; + } + else + { + return std::strong_ordering::greater; + } + + #else + + static_assert(detail::is_signed_integer_v, "Sign Compare Error"); + static_cast(lhs); + static_cast(rhs); + return std::strong_ordering::less; + + #endif +} + +#endif + //===================================== // Not Operator //===================================== @@ -3100,11 +3214,7 @@ constexpr int128_t operator%(const int128_t lhs, const int128_t rhs) noexcept } #else - #if defined(_MSC_VER) && !defined(__GNUC__) const auto is_neg{static_cast(lhs < 0)}; - #else - const auto is_neg {static_cast((lhs < 0) != (rhs < 0))}; - #endif int128_t remainder {}; diff --git a/include/boost/int128/detail/uint128_imp.hpp b/include/boost/int128/detail/uint128_imp.hpp index 6a555819..7b971e2a 100644 --- a/include/boost/int128/detail/uint128_imp.hpp +++ b/include/boost/int128/detail/uint128_imp.hpp @@ -1216,6 +1216,120 @@ BOOST_INT128_BUILTIN_CONSTEXPR bool operator>=(const T, const uint128_t) noexcep #endif // BOOST_INT128_HAS_INT128 +//===================================== +// Spaceship Operator +//===================================== + +#ifdef BOOST_INT128_HAS_SPACESHIP_OPERATOR + +BOOST_INT128_EXPORT constexpr std::strong_ordering operator<=>(const uint128_t lhs, const uint128_t rhs) noexcept +{ + if (lhs < rhs) + { + return std::strong_ordering::less; + } + else if (lhs == rhs) + { + return std::strong_ordering::equivalent; + } + else + { + return std::strong_ordering::greater; + } +} + +BOOST_INT128_EXPORT template +constexpr std::strong_ordering operator<=>(const uint128_t lhs, const UnsignedInteger rhs) noexcept +{ + if (lhs < rhs) + { + return std::strong_ordering::less; + } + else if (lhs == rhs) + { + return std::strong_ordering::equivalent; + } + else + { + return std::strong_ordering::greater; + } +} + +BOOST_INT128_EXPORT template +constexpr std::strong_ordering operator<=>(const UnsignedInteger lhs, const uint128_t rhs) noexcept +{ + if (lhs < rhs) + { + return std::strong_ordering::less; + } + else if (lhs == rhs) + { + return std::strong_ordering::equivalent; + } + else + { + return std::strong_ordering::greater; + } +} + +BOOST_INT128_EXPORT template +constexpr std::strong_ordering operator<=>(const SignedInteger lhs, const uint128_t rhs) noexcept +{ + #ifdef BOOST_INT128_ALLOW_SIGN_COMPARE + + if (lhs < rhs) + { + return std::strong_ordering::less; + } + else if (lhs == rhs) + { + return std::strong_ordering::equivalent; + } + else + { + return std::strong_ordering::greater; + } + + #else + + static_assert(detail::is_unsigned_integer_v, "Sign Compare Error"); + static_cast(lhs); + static_cast(rhs); + return std::strong_ordering::less; + + #endif +} + +BOOST_INT128_EXPORT template +constexpr std::strong_ordering operator<=>(const uint128_t lhs, const SignedInteger rhs) noexcept +{ + #ifdef BOOST_INT128_ALLOW_SIGN_COMPARE + + if (lhs < rhs) + { + return std::strong_ordering::less; + } + else if (lhs == rhs) + { + return std::strong_ordering::equivalent; + } + else + { + return std::strong_ordering::greater; + } + + #else + + static_assert(detail::is_unsigned_integer_v, "Sign Compare Error"); + static_cast(lhs); + static_cast(rhs); + return std::strong_ordering::less; + + #endif +} + +#endif + //===================================== // Not Operator //===================================== diff --git a/include/boost/int128/fmt_format.hpp b/include/boost/int128/fmt_format.hpp index 8612efdb..6df48626 100644 --- a/include/boost/int128/fmt_format.hpp +++ b/include/boost/int128/fmt_format.hpp @@ -12,13 +12,13 @@ #include #include #include -#include #include #ifdef __GNUC__ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wconversion" # pragma GCC diagnostic ignored "-Wsign-conversion" +# pragma GCC diagnostic ignored "-Wfloat-equal" #endif #include @@ -41,6 +41,14 @@ enum class sign_option space }; +enum class alignment +{ + none, + left, // < + right, // > + center // ^ +}; + template constexpr auto parse_impl(ParseContext& ctx) { @@ -52,6 +60,56 @@ constexpr auto parse_impl(ParseContext& ctx) bool prefix = false; bool write_as_character = false; bool character_debug_format = false; + char fill_char = ' '; + auto align = alignment::none; + + // Parse fill and alignment: [[fill]align] + // Alignment characters are: < (left), > (right), ^ (center) + if (it != ctx.end()) + { + // Check if we have [fill]align (fill char followed by alignment) + auto next = it; + ++next; + if (next != ctx.end() && (*next == '<' || *next == '>' || *next == '^')) + { + fill_char = *it; + it = next; + switch (*it) + { + case '<': + align = alignment::left; + break; + case '>': + align = alignment::right; + break; + case '^': + align = alignment::center; + break; + default: // LCOV_EXCL_LINE + BOOST_INT128_UNREACHABLE; // LCOV_EXCL_LINE + } + ++it; + } + // Check if we just have align (no fill char) + else if (*it == '<' || *it == '>' || *it == '^') + { + switch (*it) + { + case '<': + align = alignment::left; + break; + case '>': + align = alignment::right; + break; + case '^': + align = alignment::center; + break; + default: // LCOV_EXCL_LINE + BOOST_INT128_UNREACHABLE; // LCOV_EXCL_LINE + } + ++it; + } + } // Handle sign or space if (it != ctx.end()) @@ -140,7 +198,7 @@ constexpr auto parse_impl(ParseContext& ctx) BOOST_INT128_THROW_EXCEPTION(std::logic_error("Expected '}' in format string")); // LCOV_EXCL_LINE } - return std::make_tuple(base, padding_digits, sign, is_upper, prefix, write_as_character, character_debug_format, it); + return std::make_tuple(base, padding_digits, sign, is_upper, prefix, write_as_character, character_debug_format, fill_char, align, it); } template @@ -162,6 +220,8 @@ struct formatter bool prefix; bool write_as_character; bool character_debug_format; + char fill_char; + alignment align; constexpr formatter() : base {10}, padding_digits {0}, @@ -169,7 +229,9 @@ struct formatter is_upper {false}, prefix {false}, write_as_character {false}, - character_debug_format {false} + character_debug_format {false}, + fill_char {' '}, + align {alignment::none} {} constexpr auto parse(fmt::format_parse_context& ctx) @@ -183,8 +245,10 @@ struct formatter prefix = std::get<4>(res); write_as_character = std::get<5>(res); character_debug_format = std::get<6>(res); + fill_char = std::get<7>(res); + align = std::get<8>(res); - return std::get<7>(res); + return std::get<9>(res); } template @@ -192,22 +256,79 @@ struct formatter { char buffer[64]; bool isneg {false}; + boost::int128::uint128_t abs_v {}; BOOST_INT128_IF_CONSTEXPR (std::is_same::value) { if (v < T{0}) { isneg = true; - v = -v; + // Can't negate int128_t::min(), handle specially + if (v == (std::numeric_limits::min)()) + { + abs_v = boost::int128::uint128_t{UINT64_C(0x8000000000000000), 0}; + } + else + { + abs_v = static_cast(-v); + } } + else + { + abs_v = static_cast(v); + } + } + else + { + abs_v = v; } - const auto end = detail::mini_to_chars(buffer, v, base, is_upper); + const auto end = detail::mini_to_chars(buffer, abs_v, base, is_upper); std::string s(end, buffer + sizeof(buffer)); - if (s.size() - 1u < static_cast(padding_digits)) + // Calculate prefix length that will be added later + std::size_t prefix_len {0}; + if (prefix) + { + switch (base) + { + case 2: + case 16: + prefix_len = 2; // "0b", "0B", "0x", or "0X" + break; + case 8: + prefix_len = 1; // "0" + break; + default: + break; + } + } + + // Calculate sign length that will be added later + std::size_t sign_len {0}; + if (sign == sign_option::plus || sign == sign_option::space || isneg) { - s.insert(s.begin(), static_cast(padding_digits) - s.size() + 1u, '0'); + sign_len = 1; + } + + // Zero-padding only applies when no explicit alignment is set + // Account for prefix and sign in the padding calculation + if (align == alignment::none && padding_digits > 0) + { + auto target_digit_width {static_cast(padding_digits)}; + if (target_digit_width > prefix_len + sign_len) + { + target_digit_width -= prefix_len + sign_len; + } + else + { + target_digit_width = 0; + } + + if (s.size() - 1u < target_digit_width) + { + s.insert(s.begin(), target_digit_width - s.size() + 1u, '0'); + } } if (prefix) @@ -249,7 +370,11 @@ struct formatter switch (sign) { case sign_option::plus: - if (!isneg) + if (isneg) + { + s.insert(s.begin(), '-'); + } + else { s.insert(s.begin(), '+'); } @@ -285,6 +410,33 @@ struct formatter s.erase(0, s.find_first_not_of('\0')); s.erase(s.find_last_not_of('\0') + 1); + // Apply alignment if specified + if (align != alignment::none && s.size() < static_cast(padding_digits)) + { + auto fill_count = static_cast(padding_digits) - s.size(); + switch (align) + { + case alignment::left: + s.append(fill_count, fill_char); + break; + case alignment::right: + s.insert(s.begin(), fill_count, fill_char); + break; + case alignment::center: + { + auto left_fill = fill_count / 2; + auto right_fill = fill_count - left_fill; + s.insert(s.begin(), left_fill, fill_char); + s.append(right_fill, fill_char); + break; + } + // LCOV_EXCL_START + default: + break; + // LCOV_EXCL_STOP + } + } + return fmt::format_to(ctx.out(), "{}", s); } }; diff --git a/include/boost/int128/format.hpp b/include/boost/int128/format.hpp index ab6ff3f9..d6e235ad 100644 --- a/include/boost/int128/format.hpp +++ b/include/boost/int128/format.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #define BOOST_INT128_HAS_FORMAT @@ -24,6 +25,14 @@ enum class sign_option space }; +enum class alignment +{ + none, + left, // < + right, // > + center // ^ +}; + template constexpr auto parse_impl(ParseContext& ctx) { @@ -35,6 +44,56 @@ constexpr auto parse_impl(ParseContext& ctx) bool prefix = false; bool write_as_character = false; bool character_debug_format = false; + char fill_char = ' '; + auto align = alignment::none; + + // Parse fill and alignment: [[fill]align] + // Alignment characters are: < (left), > (right), ^ (center) + if (it != ctx.end()) + { + // Check if we have [fill]align (fill char followed by alignment) + auto next = it; + ++next; + if (next != ctx.end() && (*next == '<' || *next == '>' || *next == '^')) + { + fill_char = *it; + it = next; + switch (*it) + { + case '<': + align = alignment::left; + break; + case '>': + align = alignment::right; + break; + case '^': + align = alignment::center; + break; + default: // LCOV_EXCL_LINE + BOOST_INT128_UNREACHABLE; // LCOV_EXCL_LINE + } + ++it; + } + // Check if we just have align (no fill char) + else if (*it == '<' || *it == '>' || *it == '^') + { + switch (*it) + { + case '<': + align = alignment::left; + break; + case '>': + align = alignment::right; + break; + case '^': + align = alignment::center; + break; + default: // LCOV_EXCL_LINE + BOOST_INT128_UNREACHABLE; // LCOV_EXCL_LINE + } + ++it; + } + } // Handle sign or space if (it != ctx.end()) @@ -121,7 +180,7 @@ constexpr auto parse_impl(ParseContext& ctx) BOOST_INT128_THROW_EXCEPTION(std::format_error("Expected '}' in format string")); // LCOV_EXCL_LINE } - return std::make_tuple(base, padding_digits, sign, is_upper, prefix, write_as_character, character_debug_format, it); + return std::make_tuple(base, padding_digits, sign, is_upper, prefix, write_as_character, character_debug_format, fill_char, align, it); } template @@ -150,6 +209,8 @@ struct formatter bool prefix; bool write_as_character; bool character_debug_format; + char fill_char; + boost::int128::detail::alignment align; constexpr formatter() : base {10}, padding_digits {0}, @@ -157,7 +218,9 @@ struct formatter is_upper {false}, prefix {false}, write_as_character {false}, - character_debug_format {false} + character_debug_format {false}, + fill_char {' '}, + align {boost::int128::detail::alignment::none} {} constexpr auto parse(format_parse_context& ctx) @@ -171,8 +234,10 @@ struct formatter prefix = std::get<4>(res); write_as_character = std::get<5>(res); character_debug_format = std::get<6>(res); + fill_char = std::get<7>(res); + align = std::get<8>(res); - return std::get<7>(res); + return std::get<9>(res); } template @@ -180,22 +245,79 @@ struct formatter { char buffer[64]; bool isneg {false}; + boost::int128::uint128_t abs_v {}; if constexpr (std::is_same_v) { if (v < 0) { isneg = true; - v = -v; + // Can't negate int128_t::min(), handle specially + if (v == (std::numeric_limits::min)()) + { + abs_v = boost::int128::uint128_t{UINT64_C(0x8000000000000000), 0}; + } + else + { + abs_v = static_cast(-v); + } } + else + { + abs_v = static_cast(v); + } + } + else + { + abs_v = v; } - const auto end = boost::int128::detail::mini_to_chars(buffer, v, base, is_upper); + const auto end = boost::int128::detail::mini_to_chars(buffer, abs_v, base, is_upper); std::string s(end, buffer + sizeof(buffer)); - if (s.size() - 1u < static_cast(padding_digits)) + // Calculate prefix length that will be added later + std::size_t prefix_len {0}; + if (prefix) + { + switch (base) + { + case 2: + case 16: + prefix_len = 2; // "0b", "0B", "0x", or "0X" + break; + case 8: + prefix_len = 1; // "0" + break; + default: + break; + } + } + + // Calculate sign length that will be added later + std::size_t sign_len {0}; + if (sign == boost::int128::detail::sign_option::plus || sign == boost::int128::detail::sign_option::space || isneg) { - s.insert(s.begin(), static_cast(padding_digits) - s.size() + 1u, '0'); + sign_len = 1; + } + + // Zero-padding only applies when no explicit alignment is set + // Account for prefix and sign in the padding calculation + if (align == boost::int128::detail::alignment::none && padding_digits > 0) + { + auto target_digit_width {static_cast(padding_digits)}; + if (target_digit_width > prefix_len + sign_len) + { + target_digit_width -= prefix_len + sign_len; + } + else + { + target_digit_width = 0; + } + + if (s.size() - 1u < target_digit_width) + { + s.insert(s.begin(), target_digit_width - s.size() + 1u, '0'); + } } if (prefix) @@ -237,7 +359,11 @@ struct formatter switch (sign) { case boost::int128::detail::sign_option::plus: - if (!isneg) + if (isneg) + { + s.insert(s.begin(), '-'); + } + else { s.insert(s.begin(), '+'); } @@ -273,6 +399,33 @@ struct formatter s.erase(0, s.find_first_not_of('\0')); s.erase(s.find_last_not_of('\0') + 1); + // Apply alignment if specified + if (align != boost::int128::detail::alignment::none && s.size() < static_cast(padding_digits)) + { + auto fill_count = static_cast(padding_digits) - s.size(); + switch (align) + { + case boost::int128::detail::alignment::left: + s.append(fill_count, fill_char); + break; + case boost::int128::detail::alignment::right: + s.insert(s.begin(), fill_count, fill_char); + break; + case boost::int128::detail::alignment::center: + { + auto left_fill = fill_count / 2; + auto right_fill = fill_count - left_fill; + s.insert(s.begin(), left_fill, fill_char); + s.append(right_fill, fill_char); + break; + } + // LCOV_EXCL_START + default: + break; + // LCOV_EXCL_STOP + } + } + return std::format_to(ctx.out(), "{}", s); } }; diff --git a/include/boost/int128/numeric.hpp b/include/boost/int128/numeric.hpp index 20a8d00b..5d09fd06 100644 --- a/include/boost/int128/numeric.hpp +++ b/include/boost/int128/numeric.hpp @@ -10,8 +10,6 @@ #ifndef BOOST_INT128_BUILD_MODULE -#include -#include #include #endif @@ -315,17 +313,11 @@ constexpr uint128_t gcd(uint128_t a, uint128_t b) noexcept } b -= a; + } while (b != 0U && (a.high | b.high) > 0U); - // Stop doing 128-bit math as soon as we can - if (a.high == 0U && b.high == 0U) - { - const auto g {detail::gcd64(a.low, b.low)}; - return uint128_t{0, g} << shift; - } - - } while (b != 0U); - - return a << shift; // LCOV_EXCL_LINE : Should be unreachable, but this is also the correct answer + // Stop doing 128-bit math as soon as we can + const auto g {detail::gcd64(a.low, b.low)}; + return uint128_t{0, g} << shift; } constexpr int128_t gcd(const int128_t a, const int128_t b) noexcept @@ -393,35 +385,41 @@ constexpr int128_t lcm(const int128_t a, const int128_t b) noexcept return static_cast(lcm(static_cast(abs(a)), static_cast(abs(b)))); } -namespace detail { - -template -constexpr T midpoint_impl(const T a, const T b) noexcept +constexpr uint128_t midpoint(const uint128_t a, const uint128_t b) noexcept { - const auto unsigned_a {static_cast(a)}; - const auto unsigned_b {static_cast(b)}; - - auto mid {(unsigned_a & unsigned_b) + ((unsigned_a ^ unsigned_b) >> 1)}; + // Bit manipulation formula works for unsigned integers + auto mid {(a & b) + ((a ^ b) >> 1)}; // std::midpoint rounds towards the first parameter - if ((unsigned_a ^ unsigned_b) & 1U && a > b) + if ((a ^ b) & 1U && a > b) { ++mid; } - return static_cast(mid); -} - -} // namespace detail - -constexpr uint128_t midpoint(const uint128_t a, const uint128_t b) noexcept -{ - return detail::midpoint_impl(a, b); + return mid; } constexpr int128_t midpoint(const int128_t a, const int128_t b) noexcept { - return detail::midpoint_impl(a, b); + // For signed integers, we use a + (b - a) / 2 or a - (a - b) / 2 + // The subtraction is done in unsigned arithmetic to handle overflow correctly + // Integer division automatically rounds toward the first argument + + const auto ua {static_cast(a)}; + const auto ub {static_cast(b)}; + + if (a <= b) + { + // diff = b - a (computed in unsigned, handles wrap-around correctly) + const auto diff {ub - ua}; + return a + static_cast(diff / 2U); + } + else + { + // diff = a - b (computed in unsigned, handles wrap-around correctly) + const auto diff {ua - ub}; + return a - static_cast(diff / 2U); + } } } // namespace int128 diff --git a/index.html b/index.html index 5e717127..a9d60f6a 100644 --- a/index.html +++ b/index.html @@ -1,15 +1,16 @@ + + + - + Automatic redirection failed, please go to -doc/html/int128.html. +doc/html/index.html - diff --git a/module/int128.cxx b/module/int128.cxx index 4afab064..050aaae1 100644 --- a/module/int128.cxx +++ b/module/int128.cxx @@ -13,6 +13,7 @@ module; #include #include #include +#include #if __has_include(<__msvc_int128.hpp>) && _MSVC_LANG >= 202002L diff --git a/ports/int128/portfile.cmake b/ports/int128/portfile.cmake index 7662adac..a4b70cca 100644 --- a/ports/int128/portfile.cmake +++ b/ports/int128/portfile.cmake @@ -7,8 +7,8 @@ vcpkg_from_github( OUT_SOURCE_PATH SOURCE_PATH REPO cppalliance/int128 - REF v1.3.0 - SHA512 ec08607f4782e16a8a5d7ea7ff8884418756d00f05209bd66451bea655139b34e4342953d555feded5302e8e425872ca1e15f9e3a266f39892e88ab820e70a03 + REF v1.5.1 + SHA512 cb60e310bc91191b48513f68a709444aa9e03a76573cee2734541557af21310200b0fceef546681806a34439000472f38024e277ad39091f032d282f5fcc53d8 HEAD_REF master ) diff --git a/ports/int128/vcpkg.json b/ports/int128/vcpkg.json index ebbe0e05..b9c12168 100644 --- a/ports/int128/vcpkg.json +++ b/ports/int128/vcpkg.json @@ -1,6 +1,6 @@ { "name": "int128", - "version": "1.3.0", + "version": "1.5.1", "description": "Portable and performant 128-bit integers", "homepage": "https://github.com/cppalliance/int128", "license": "BSL-1.0", diff --git a/test/Jamfile b/test/Jamfile index 015a42e3..cbbcde3f 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -83,15 +83,22 @@ run test_fmt_format.cpp ; run test_div.cpp ; +run test_num_digits.cpp ; +run test_spaceship_operator.cpp ; + # Make sure we run the examples as well run ../examples/construction.cpp ; run ../examples/bit.cpp ; run ../examples/saturating_arithmetic.cpp ; -compile-fail ../examples/mixed_type_arithmetic.cpp ; +run ../examples/mixed_type_arithmetic.cpp ; run ../examples/stream.cpp ; run ../examples/basic_arithmetic.cpp ; run ../examples/math_and_random.cpp ; run ../examples/charconv.cpp ; +run ../examples/fmt_format.cpp ; +run ../examples/cstdlib.cpp ; +run ../examples/numeric_algorithms.cpp ; +run ../examples/rollover.cpp ; run limits_link_1.cpp limits_link_2.cpp limits_link_3.cpp ; diff --git a/test/limits_link_2.cpp b/test/limits_link_2.cpp index 9fbb03fa..03cfca27 100644 --- a/test/limits_link_2.cpp +++ b/test/limits_link_2.cpp @@ -9,9 +9,9 @@ void test_odr_use( int const* ); void test_odr_use( std::size_t const* ); -template void test() +template void test() // LCOV_EXCL_LINE { - test_odr_use( &std::numeric_limits::digits10 ); + test_odr_use( &std::numeric_limits::digits10 ); // LCOV_EXCL_LINE } void f2() diff --git a/test/limits_link_3.cpp b/test/limits_link_3.cpp index ed079e4c..e3ee3fd0 100644 --- a/test/limits_link_3.cpp +++ b/test/limits_link_3.cpp @@ -18,6 +18,6 @@ void test_odr_use( int const* ) { } -void test_odr_use ( std::size_t const* ) +void test_odr_use ( std::size_t const* ) // LCOV_EXCL_LINE { } diff --git a/test/test_fmt_format.cpp b/test/test_fmt_format.cpp index 85816d74..6326042a 100644 --- a/test/test_fmt_format.cpp +++ b/test/test_fmt_format.cpp @@ -48,8 +48,10 @@ void test_binary() BOOST_TEST_CSTR_EQ(fmt::format("{:#B}", T{5}).c_str(), "0B101"); BOOST_TEST_CSTR_EQ(fmt::format("{:6b}", T{5}).c_str(), "000101"); - BOOST_TEST_CSTR_EQ(fmt::format("{:#6b}", T{5}).c_str(), "0b000101"); - BOOST_TEST_CSTR_EQ(fmt::format("{:#06B}", T{5}).c_str(), "0B000101"); + BOOST_TEST_CSTR_EQ(fmt::format("{:#6b}", T{5}).c_str(), "0b0101"); + BOOST_TEST_CSTR_EQ(fmt::format("{:#06B}", T{5}).c_str(), "0B0101"); + + BOOST_TEST_CSTR_EQ(fmt::format("{:#010b}", T{42}).c_str(), "0b00101010"); } template @@ -59,7 +61,7 @@ void test_octal() BOOST_TEST_CSTR_EQ(fmt::format("{:#o}", T{42}).c_str(), "052"); BOOST_TEST_CSTR_EQ(fmt::format("{:4o}", T{42}).c_str(), "0052"); - BOOST_TEST_CSTR_EQ(fmt::format("{:#4o}", T{42}).c_str(), "00052"); + BOOST_TEST_CSTR_EQ(fmt::format("{:#4o}", T{42}).c_str(), "0052"); } template @@ -74,8 +76,8 @@ void test_decimal() BOOST_TEST_CSTR_EQ(fmt::format("{: d}", T{42}).c_str(), " 42"); BOOST_TEST_CSTR_EQ(fmt::format("{: #d}", T{42}).c_str(), " 42"); - BOOST_TEST_CSTR_EQ(fmt::format("{:+3d}", T{42}).c_str(), "+042"); - BOOST_TEST_CSTR_EQ(fmt::format("{:+#3d}", T{42}).c_str(), "+042"); + BOOST_TEST_CSTR_EQ(fmt::format("{:+3d}", T{42}).c_str(), "+42"); + BOOST_TEST_CSTR_EQ(fmt::format("{:+#3d}", T{42}).c_str(), "+42"); BOOST_TEST_CSTR_EQ(fmt::format("{:-3d}", T{42}).c_str(), "042"); BOOST_TEST_CSTR_EQ(fmt::format("{:-#3d}", T{42}).c_str(), "042"); @@ -84,14 +86,14 @@ void test_decimal() template void test_decimal_negative() { - BOOST_TEST_CSTR_EQ(fmt::format("{: 3d}", T{42}).c_str(), " 042"); - BOOST_TEST_CSTR_EQ(fmt::format("{: #3d}", T{42}).c_str(), " 042"); + BOOST_TEST_CSTR_EQ(fmt::format("{: 3d}", T{42}).c_str(), " 42"); + BOOST_TEST_CSTR_EQ(fmt::format("{: #3d}", T{42}).c_str(), " 42"); - BOOST_TEST_CSTR_EQ(fmt::format("{:-3d}", T{-42}).c_str(), "-042"); - BOOST_TEST_CSTR_EQ(fmt::format("{:-#3d}", T{-42}).c_str(), "-042"); + BOOST_TEST_CSTR_EQ(fmt::format("{:-3d}", T{-42}).c_str(), "-42"); + BOOST_TEST_CSTR_EQ(fmt::format("{:-#3d}", T{-42}).c_str(), "-42"); - BOOST_TEST_CSTR_EQ(fmt::format("{: 3d}", T{-42}).c_str(), "-042"); - BOOST_TEST_CSTR_EQ(fmt::format("{: #3d}", T{-42}).c_str(), "-042"); + BOOST_TEST_CSTR_EQ(fmt::format("{: 3d}", T{-42}).c_str(), "-42"); + BOOST_TEST_CSTR_EQ(fmt::format("{: #3d}", T{-42}).c_str(), "-42"); } template @@ -110,10 +112,10 @@ void test_hex() BOOST_TEST_CSTR_EQ(fmt::format("{:+#X}", T{42}).c_str(), "+0X2A"); BOOST_TEST_CSTR_EQ(fmt::format("{:5X}", T{42}).c_str(), "0002A"); - BOOST_TEST_CSTR_EQ(fmt::format("{:#5X}", T{42}).c_str(), "0X0002A"); + BOOST_TEST_CSTR_EQ(fmt::format("{:#5X}", T{42}).c_str(), "0X02A"); - BOOST_TEST_CSTR_EQ(fmt::format("{: 5X}", T{42}).c_str(), " 0002A"); - BOOST_TEST_CSTR_EQ(fmt::format("{: #5X}", T{42}).c_str(), " 0X0002A"); + BOOST_TEST_CSTR_EQ(fmt::format("{: 5X}", T{42}).c_str(), " 002A"); + BOOST_TEST_CSTR_EQ(fmt::format("{: #5X}", T{42}).c_str(), " 0X2A"); } template @@ -133,6 +135,63 @@ void test_string_insertion() BOOST_TEST_CSTR_EQ(fmt::format("Height is: {} meters", T {2}).c_str(), "Height is: 2 meters"); } +template +void test_alignment() +{ + // Left alignment with default fill (space) + BOOST_TEST_CSTR_EQ(fmt::format("{:<6d}", T{42}).c_str(), "42 "); + BOOST_TEST_CSTR_EQ(fmt::format("{:<6}", T{42}).c_str(), "42 "); + + // Right alignment with default fill (space) + BOOST_TEST_CSTR_EQ(fmt::format("{:>6d}", T{42}).c_str(), " 42"); + BOOST_TEST_CSTR_EQ(fmt::format("{:>6}", T{42}).c_str(), " 42"); + + // Center alignment with default fill (space) + BOOST_TEST_CSTR_EQ(fmt::format("{:^6d}", T{42}).c_str(), " 42 "); + BOOST_TEST_CSTR_EQ(fmt::format("{:^7d}", T{42}).c_str(), " 42 "); + + // Left alignment with custom fill + BOOST_TEST_CSTR_EQ(fmt::format("{:*<6d}", T{42}).c_str(), "42****"); + BOOST_TEST_CSTR_EQ(fmt::format("{:-<6d}", T{42}).c_str(), "42----"); + BOOST_TEST_CSTR_EQ(fmt::format("{:0<6d}", T{42}).c_str(), "420000"); + + // Right alignment with custom fill + BOOST_TEST_CSTR_EQ(fmt::format("{:*>6d}", T{42}).c_str(), "****42"); + BOOST_TEST_CSTR_EQ(fmt::format("{:>>6d}", T{42}).c_str(), ">>>>42"); + BOOST_TEST_CSTR_EQ(fmt::format("{:0>6d}", T{42}).c_str(), "000042"); + + // Center alignment with custom fill + BOOST_TEST_CSTR_EQ(fmt::format("{:*^6d}", T{42}).c_str(), "**42**"); + BOOST_TEST_CSTR_EQ(fmt::format("{:*^7d}", T{42}).c_str(), "**42***"); + + // Alignment with sign + BOOST_TEST_CSTR_EQ(fmt::format("{:>+6d}", T{42}).c_str(), " +42"); + BOOST_TEST_CSTR_EQ(fmt::format("{:<+6d}", T{42}).c_str(), "+42 "); + BOOST_TEST_CSTR_EQ(fmt::format("{:^+7d}", T{42}).c_str(), " +42 "); + + // Alignment with hex + BOOST_TEST_CSTR_EQ(fmt::format("{:>6x}", T{42}).c_str(), " 2a"); + BOOST_TEST_CSTR_EQ(fmt::format("{:<6x}", T{42}).c_str(), "2a "); + BOOST_TEST_CSTR_EQ(fmt::format("{:*^6x}", T{42}).c_str(), "**2a**"); + + // Alignment with prefix (# comes before width in fmt spec) + BOOST_TEST_CSTR_EQ(fmt::format("{:>#8x}", T{42}).c_str(), " 0x2a"); + BOOST_TEST_CSTR_EQ(fmt::format("{:<#8x}", T{42}).c_str(), "0x2a "); + BOOST_TEST_CSTR_EQ(fmt::format("{:*^#8x}", T{42}).c_str(), "**0x2a**"); +} + +template +void test_alignment_negative() +{ + // Alignment with negative values + BOOST_TEST_CSTR_EQ(fmt::format("{:>6d}", T{-42}).c_str(), " -42"); + BOOST_TEST_CSTR_EQ(fmt::format("{:<6d}", T{-42}).c_str(), "-42 "); + BOOST_TEST_CSTR_EQ(fmt::format("{:^7d}", T{-42}).c_str(), " -42 "); + BOOST_TEST_CSTR_EQ(fmt::format("{:*>6d}", T{-42}).c_str(), "***-42"); + BOOST_TEST_CSTR_EQ(fmt::format("{:*<6d}", T{-42}).c_str(), "-42***"); + BOOST_TEST_CSTR_EQ(fmt::format("{:*^7d}", T{-42}).c_str(), "**-42**"); +} + int main() { test_empty(); @@ -156,6 +215,10 @@ int main() test_string_insertion(); test_string_insertion(); + test_alignment(); + test_alignment(); + test_alignment_negative(); + return boost::report_errors(); } diff --git a/test/test_format.cpp b/test/test_format.cpp index 9d1d270c..59f6d7a6 100644 --- a/test/test_format.cpp +++ b/test/test_format.cpp @@ -41,8 +41,8 @@ void test_binary() BOOST_TEST_CSTR_EQ(std::format("{:#B}", T{5}).c_str(), "0B101"); BOOST_TEST_CSTR_EQ(std::format("{:6b}", T{5}).c_str(), "000101"); - BOOST_TEST_CSTR_EQ(std::format("{:#6b}", T{5}).c_str(), "0b000101"); - BOOST_TEST_CSTR_EQ(std::format("{:#06B}", T{5}).c_str(), "0B000101"); + BOOST_TEST_CSTR_EQ(std::format("{:#6b}", T{5}).c_str(), "0b0101"); + BOOST_TEST_CSTR_EQ(std::format("{:#06B}", T{5}).c_str(), "0B0101"); } template @@ -52,7 +52,7 @@ void test_octal() BOOST_TEST_CSTR_EQ(std::format("{:#o}", T{42}).c_str(), "052"); BOOST_TEST_CSTR_EQ(std::format("{:4o}", T{42}).c_str(), "0052"); - BOOST_TEST_CSTR_EQ(std::format("{:#4o}", T{42}).c_str(), "00052"); + BOOST_TEST_CSTR_EQ(std::format("{:#4o}", T{42}).c_str(), "0052"); } template @@ -67,22 +67,22 @@ void test_decimal() BOOST_TEST_CSTR_EQ(std::format("{: d}", T{42}).c_str(), " 42"); BOOST_TEST_CSTR_EQ(std::format("{: #d}", T{42}).c_str(), " 42"); - BOOST_TEST_CSTR_EQ(std::format("{:+3d}", T{42}).c_str(), "+042"); - BOOST_TEST_CSTR_EQ(std::format("{:+#3d}", T{42}).c_str(), "+042"); + BOOST_TEST_CSTR_EQ(std::format("{:+3d}", T{42}).c_str(), "+42"); + BOOST_TEST_CSTR_EQ(std::format("{:+#3d}", T{42}).c_str(), "+42"); BOOST_TEST_CSTR_EQ(std::format("{:-3d}", T{42}).c_str(), "042"); BOOST_TEST_CSTR_EQ(std::format("{:-#3d}", T{42}).c_str(), "042"); if constexpr (std::is_same_v) { - BOOST_TEST_CSTR_EQ(std::format("{: 3d}", T{42}).c_str(), " 042"); - BOOST_TEST_CSTR_EQ(std::format("{: #3d}", T{42}).c_str(), " 042"); + BOOST_TEST_CSTR_EQ(std::format("{: 3d}", T{42}).c_str(), " 42"); + BOOST_TEST_CSTR_EQ(std::format("{: #3d}", T{42}).c_str(), " 42"); - BOOST_TEST_CSTR_EQ(std::format("{:-3d}", T{-42}).c_str(), "-042"); - BOOST_TEST_CSTR_EQ(std::format("{:-#3d}", T{-42}).c_str(), "-042"); + BOOST_TEST_CSTR_EQ(std::format("{:-3d}", T{-42}).c_str(), "-42"); + BOOST_TEST_CSTR_EQ(std::format("{:-#3d}", T{-42}).c_str(), "-42"); - BOOST_TEST_CSTR_EQ(std::format("{: 3d}", T{-42}).c_str(), "-042"); - BOOST_TEST_CSTR_EQ(std::format("{: #3d}", T{-42}).c_str(), "-042"); + BOOST_TEST_CSTR_EQ(std::format("{: 3d}", T{-42}).c_str(), "-42"); + BOOST_TEST_CSTR_EQ(std::format("{: #3d}", T{-42}).c_str(), "-42"); } BOOST_TEST_CSTR_EQ(std::format("{:+d}", T{42}).c_str(), "+42"); @@ -112,10 +112,10 @@ void test_hex() } BOOST_TEST_CSTR_EQ(std::format("{:5X}", T{42}).c_str(), "0002A"); - BOOST_TEST_CSTR_EQ(std::format("{:#5X}", T{42}).c_str(), "0X0002A"); + BOOST_TEST_CSTR_EQ(std::format("{:#5X}", T{42}).c_str(), "0X02A"); - BOOST_TEST_CSTR_EQ(std::format("{: 5X}", T{42}).c_str(), " 0002A"); - BOOST_TEST_CSTR_EQ(std::format("{: #5X}", T{42}).c_str(), " 0X0002A"); + BOOST_TEST_CSTR_EQ(std::format("{: 5X}", T{42}).c_str(), " 002A"); + BOOST_TEST_CSTR_EQ(std::format("{: #5X}", T{42}).c_str(), " 0X2A"); } template @@ -128,6 +128,63 @@ void test_string_insertion() BOOST_TEST_CSTR_EQ(std::format("Height is: {} meters", T {2}).c_str(), "Height is: 2 meters"); } +template +void test_alignment() +{ + // Left alignment with default fill (space) + BOOST_TEST_CSTR_EQ(std::format("{:<6d}", T{42}).c_str(), "42 "); + BOOST_TEST_CSTR_EQ(std::format("{:<6}", T{42}).c_str(), "42 "); + + // Right alignment with default fill (space) + BOOST_TEST_CSTR_EQ(std::format("{:>6d}", T{42}).c_str(), " 42"); + BOOST_TEST_CSTR_EQ(std::format("{:>6}", T{42}).c_str(), " 42"); + + // Center alignment with default fill (space) + BOOST_TEST_CSTR_EQ(std::format("{:^6d}", T{42}).c_str(), " 42 "); + BOOST_TEST_CSTR_EQ(std::format("{:^7d}", T{42}).c_str(), " 42 "); + + // Left alignment with custom fill + BOOST_TEST_CSTR_EQ(std::format("{:*<6d}", T{42}).c_str(), "42****"); + BOOST_TEST_CSTR_EQ(std::format("{:-<6d}", T{42}).c_str(), "42----"); + BOOST_TEST_CSTR_EQ(std::format("{:0<6d}", T{42}).c_str(), "420000"); + + // Right alignment with custom fill + BOOST_TEST_CSTR_EQ(std::format("{:*>6d}", T{42}).c_str(), "****42"); + BOOST_TEST_CSTR_EQ(std::format("{:>>6d}", T{42}).c_str(), ">>>>42"); + BOOST_TEST_CSTR_EQ(std::format("{:0>6d}", T{42}).c_str(), "000042"); + + // Center alignment with custom fill + BOOST_TEST_CSTR_EQ(std::format("{:*^6d}", T{42}).c_str(), "**42**"); + BOOST_TEST_CSTR_EQ(std::format("{:*^7d}", T{42}).c_str(), "**42***"); + + // Alignment with sign + BOOST_TEST_CSTR_EQ(std::format("{:>+6d}", T{42}).c_str(), " +42"); + BOOST_TEST_CSTR_EQ(std::format("{:<+6d}", T{42}).c_str(), "+42 "); + BOOST_TEST_CSTR_EQ(std::format("{:^+7d}", T{42}).c_str(), " +42 "); + + // Alignment with hex + BOOST_TEST_CSTR_EQ(std::format("{:>6x}", T{42}).c_str(), " 2a"); + BOOST_TEST_CSTR_EQ(std::format("{:<6x}", T{42}).c_str(), "2a "); + BOOST_TEST_CSTR_EQ(std::format("{:*^6x}", T{42}).c_str(), "**2a**"); + + // Alignment with prefix (# comes before width in format spec) + BOOST_TEST_CSTR_EQ(std::format("{:>#8x}", T{42}).c_str(), " 0x2a"); + BOOST_TEST_CSTR_EQ(std::format("{:<#8x}", T{42}).c_str(), "0x2a "); + BOOST_TEST_CSTR_EQ(std::format("{:*^#8x}", T{42}).c_str(), "**0x2a**"); +} + +template +void test_alignment_negative() +{ + // Alignment with negative values + BOOST_TEST_CSTR_EQ(std::format("{:>6d}", T{-42}).c_str(), " -42"); + BOOST_TEST_CSTR_EQ(std::format("{:<6d}", T{-42}).c_str(), "-42 "); + BOOST_TEST_CSTR_EQ(std::format("{:^7d}", T{-42}).c_str(), " -42 "); + BOOST_TEST_CSTR_EQ(std::format("{:*>6d}", T{-42}).c_str(), "***-42"); + BOOST_TEST_CSTR_EQ(std::format("{:*<6d}", T{-42}).c_str(), "-42***"); + BOOST_TEST_CSTR_EQ(std::format("{:*^7d}", T{-42}).c_str(), "**-42**"); +} + int main() { test_empty(); @@ -148,6 +205,10 @@ int main() test_string_insertion(); test_string_insertion(); + test_alignment(); + test_alignment(); + test_alignment_negative(); + return boost::report_errors(); } diff --git a/test/test_midpoint.cpp b/test/test_midpoint.cpp index 5ec2df26..e1d9ffa8 100644 --- a/test/test_midpoint.cpp +++ b/test/test_midpoint.cpp @@ -49,7 +49,7 @@ void test_big() constexpr auto max = std::numeric_limits::max(); constexpr auto min = std::numeric_limits::min(); - BOOST_TEST_EQ(BOOST_INT128_INT128_C(-170141183460469231731687303715884105728), midpoint(max, min)); + BOOST_TEST_EQ(0, midpoint(max, min)); BOOST_TEST_EQ(max - 1, midpoint(max, max - 2)); BOOST_TEST_EQ(min, midpoint(min, min + 1)); diff --git a/test/test_num_digits.cpp b/test/test_num_digits.cpp new file mode 100644 index 00000000..f7a62785 --- /dev/null +++ b/test/test_num_digits.cpp @@ -0,0 +1,90 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#ifndef BOOST_INT128_ALLOW_SIGN_CONVERSION +# define BOOST_INT128_ALLOW_SIGN_CONVERSION +#endif + +#include +#include +#include +#include +#include + +#ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wold-style-cast" +#endif + +#include + +#ifdef __clang__ +# pragma clang diagnostic pop +#endif + +static std::mt19937_64 rng{42}; +boost::random::uniform_int_distribution dist(std::numeric_limits::min(), + std::numeric_limits::max()); + +constexpr std::array edge_cases {{ + boost::int128::uint128_t{1, 0}, + boost::int128::uint128_t{1, 1}, + boost::int128::uint128_t{2, 0}, + boost::int128::uint128_t{2, UINT64_MAX - 1U}, + boost::int128::uint128_t{4, 0}, +}}; + +constexpr int trivial_num_digits(boost::int128::uint128_t x) noexcept +{ + int digits = 0; + + while (x) + { + x /= UINT64_C(10); + ++digits; + } + + return digits; +} + +void test() +{ + for (int i {}; i < 39; ++i) + { + const auto current_val {boost::charconv::detail::int128_pow10[static_cast(i)]}; + const auto current_val_digits {boost::charconv::detail::num_digits(current_val)}; + BOOST_TEST_EQ(current_val_digits, i + 1); + } + + for (int i {1}; i < 39; ++i) + { + const auto current_val {boost::charconv::detail::int128_pow10[static_cast(i)] - 1U}; + const auto current_val_digits {boost::charconv::detail::num_digits(current_val)}; + BOOST_TEST_EQ(current_val_digits, i); + } + + for (int i {}; i < 1024; ++i) + { + const auto value {dist(rng)}; + const auto current_val_digits {boost::charconv::detail::num_digits(value)}; + const auto trivial_digits {trivial_num_digits(value)}; + + BOOST_TEST_EQ(current_val_digits, trivial_digits); + } + + for (const auto value : edge_cases) + { + const auto current_val_digits {boost::charconv::detail::num_digits(value)}; + const auto trivial_digits {trivial_num_digits(value)}; + + BOOST_TEST_EQ(current_val_digits, trivial_digits); + } +} + +int main() +{ + test(); + + return boost::report_errors(); +} diff --git a/test/test_spaceship_operator.cpp b/test/test_spaceship_operator.cpp new file mode 100644 index 00000000..bf839583 --- /dev/null +++ b/test/test_spaceship_operator.cpp @@ -0,0 +1,44 @@ +// Copyright 2026 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include + +#ifdef BOOST_INT128_HAS_SPACESHIP_OPERATOR + +#include + +void test_u128() +{ + constexpr boost::int128::uint128_t x {5U}; + BOOST_TEST((x <=> 4U) == std::strong_ordering::greater); + BOOST_TEST((x <=> 5U) == std::strong_ordering::equivalent); + BOOST_TEST((x <=> 5U) == std::strong_ordering::equal); + BOOST_TEST((x <=> 6U) == std::strong_ordering::less); +} + +void test_int128() +{ + constexpr boost::int128::int128_t x {5}; + BOOST_TEST((x <=> 4) == std::strong_ordering::greater); + BOOST_TEST((x <=> 5) == std::strong_ordering::equivalent); + BOOST_TEST((x <=> 5) == std::strong_ordering::equal); + BOOST_TEST((x <=> 6) == std::strong_ordering::less); +} + +int main() +{ + test_u128(); + test_int128(); + + return boost::report_errors(); +} + +#else + +int main() +{ + return 0; +} + +#endif