14void BigInt::realloc_to(mp_size_t new_alloc) {
15 if (new_alloc <= capacity_)
return;
16 const std::size_t requested =
static_cast<std::size_t
>(new_alloc);
17 if (requested > std::numeric_limits<std::size_t>::max() - 3) {
18 throw std::length_error(
"BigInt allocation size overflow");
20 const std::size_t rounded = (requested + 3) & ~std::size_t(3);
21 if (rounded > std::numeric_limits<std::size_t>::max() /
sizeof(mp_limb_t) ||
22 rounded >
static_cast<std::size_t
>(std::numeric_limits<mp_size_t>::max())) {
23 throw std::length_error(
"BigInt allocation byte size overflow");
27 static_cast<mp_ptr
>(::operator
new[](rounded *
sizeof(mp_limb_t)));
29 if (size_ > 0 && data_) {
30 std::memcpy(new_data, data_, size_ *
sizeof(mp_limb_t));
32 if (data_) ::operator
delete[](data_);
34 capacity_ =
static_cast<mp_size_t
>(rounded);
37void BigInt::normalize() {
38 if (size_ > 0 && !data_) {
39 throw std::logic_error(
"BigInt invariant violated: nonzero size without storage");
41 while (size_ > 0 && data_[size_ - 1] == 0) {
46 }
else if (sign_ == ZERO) {
56BigInt::BigInt() =
default;
59 if (data_) ::operator
delete[](data_);
62BigInt::BigInt(
const BigInt& other) {
63 if (other.size_ > 0) {
64 realloc_to(other.size_);
65 std::memcpy(data_, other.data_, other.size_ *
sizeof(mp_limb_t));
73BigInt::BigInt(BigInt&& other) noexcept
74 : data_(other.data_), size_(other.size_), capacity_(other.capacity_), sign_(other.sign_) {
75 other.data_ =
nullptr;
81BigInt& BigInt::operator=(
const BigInt& other) {
83 if (other.size_ > capacity_) {
84 realloc_to(other.size_);
87 std::memcpy(data_, other.data_, other.size_ *
sizeof(mp_limb_t));
94BigInt& BigInt::operator=(BigInt&& other)
noexcept {
96 if (data_) ::operator
delete[](data_);
99 capacity_ = other.capacity_;
102 other.data_ =
nullptr;
109void BigInt::import_unsigned(std::uint64_t magnitude) {
111 if (magnitude == 0) {
114 constexpr auto limb_bits = std::numeric_limits<mp_limb_t>::digits;
115 constexpr auto value_bits = std::numeric_limits<std::uint64_t>::digits;
116 realloc_to((value_bits + limb_bits - 1) / limb_bits);
118 data_[size_++] =
static_cast<mp_limb_t
>(magnitude);
119 if constexpr (limb_bits < value_bits) {
120 magnitude >>= limb_bits % value_bits;
124 }
while (magnitude != 0);
128BigInt::BigInt(std::int64_t
value) {
129 const auto bits =
static_cast<std::uint64_t
>(
value);
130 import_unsigned(
value < 0 ? std::uint64_t{0} - bits : bits);
136BigInt::BigInt(std::uint64_t
value) {
137 import_unsigned(
value);
140BigInt::BigInt(
int value) : BigInt(static_cast<std::int64_t>(
value)) {}
142BigInt::BigInt(
unsigned int value) : BigInt(static_cast<std::uint64_t>(
value)) {}
144BigInt::BigInt(
const std::string& str) {
146 throw std::invalid_argument(
"BigInt: decimal string must contain digits");
153 }
else if (str[0] ==
'+') {
157 if (start == str.length()) {
158 throw std::invalid_argument(
"BigInt: sign must be followed by digits");
161 size_t len = str.length() - start;
163 std::vector<mp_byte_t> digit_buf(len);
164 for (
size_t i = 0; i < len; ++i) {
165 char c = str[start + i];
166 if (c <
'0' || c >
'9') {
167 throw std::invalid_argument(
168 "BigInt: invalid character '" + std::string(1, c) +
169 "' at position " + std::to_string(start + i) +
170 " in input \"" + str +
"\"");
172 uint8_t d =
static_cast<uint8_t
>(
c -
'0');
174 digit_buf[len - 1 - i] = d;
177 mp_size_t needed = len / 19 + 2;
181 size_ = lmmp_from_str_(data_, digit_buf.data(), len, 10);
191std::string BigInt::to_string()
const {
193 if (size_ == 0)
return "0";
195 size_t len_needed = size_ * 20 + 5;
196 std::vector<mp_byte_t> buf(len_needed);
198 mp_size_t str_len = lmmp_to_str_((mp_byte_t*)buf.data(), data_, size_, 10);
200 if (str_len == 0)
return "0";
203 res.reserve(str_len + 2);
204 if (sign_ == NEGATIVE) res +=
'-';
206 for(mp_size_t i = str_len; i > 0; --i) {
207 res += (char)(buf[i - 1] +
'0');
213std::size_t BigInt::bit_length() const noexcept {
217 std::size_t top_bits = 0;
218 for (mp_limb_t top = data_[size_ - 1]; top != 0; top >>= 1) {
221 constexpr auto limb_bits = std::numeric_limits<mp_limb_t>::digits;
222 return (
static_cast<std::size_t
>(size_) - 1) * limb_bits + top_bits;
225std::optional<std::uint64_t> BigInt::magnitude_uint64() const noexcept {
226 constexpr auto value_bits = std::numeric_limits<std::uint64_t>::digits;
227 constexpr auto limb_bits = std::numeric_limits<mp_limb_t>::digits;
228 if (bit_length() > value_bits) {
231 std::uint64_t magnitude = 0;
232 for (mp_size_t i = size_; i > 0; --i) {
233 if constexpr (limb_bits < value_bits) {
234 magnitude <<= limb_bits % value_bits;
236 magnitude |=
static_cast<std::uint64_t
>(data_[i - 1]);
241std::optional<std::uint64_t> BigInt::try_to_uint64() const noexcept {
242 if (sign_ == NEGATIVE) {
245 return magnitude_uint64();
248std::optional<std::int64_t> BigInt::try_to_int64() const noexcept {
249 const auto magnitude = magnitude_uint64();
253 constexpr auto maximum =
254 static_cast<std::uint64_t
>(std::numeric_limits<std::int64_t>::max());
255 if (sign_ == NEGATIVE) {
256 if (*magnitude > maximum + std::uint64_t{1}) {
259 if (*magnitude == maximum + std::uint64_t{1}) {
260 return std::numeric_limits<std::int64_t>::min();
262 return -
static_cast<std::int64_t
>(*magnitude);
264 if (*magnitude > maximum) {
267 return static_cast<std::int64_t
>(*magnitude);
270int BigInt::to_int()
const {
271 const auto value = try_to_int64();
273 return sign_ == NEGATIVE ? std::numeric_limits<int>::min()
274 : std::numeric_limits<int>::max();
276 if (*value < std::numeric_limits<int>::min()) {
277 return std::numeric_limits<int>::min();
279 if (*value > std::numeric_limits<int>::max()) {
280 return std::numeric_limits<int>::max();
282 return static_cast<int>(*value);
285lmmc_real_t BigInt::to_double()
const {
286 if (size_ == 0)
return 0.0;
287 lmmc_real_t res = 0.0;
288 const lmmc_real_t base_mul =
289 std::ldexp(lmmc_real_t{1}, std::numeric_limits<mp_limb_t>::digits);
291 for (mp_size_t i = size_; i > 0; --i) {
292 LMMC_REAL_MUL(&res, &res, &base_mul);
293 lmmc_real_t val = (lmmc_real_t)data_[i-1];
294 LMMC_REAL_ADD(&res, &res, &val);
296 if (sign_ == NEGATIVE) {
297 lmmc_real_t zero = 0.0;
298 LMMC_REAL_SUB(&res, &zero, &res);
303int BigInt::cmp_abs(
const BigInt& a,
const BigInt& b) {
304 if (
a.size_ !=
b.size_) {
305 return a.size_ >
b.size_ ? 1 : -1;
310 for (mp_size_t i =
a.size_; i > 0; --i) {
311 if (
a.data_[i - 1] !=
b.data_[i - 1]) {
312 return a.data_[i - 1] >
b.data_[i - 1] ? 1 : -1;
318bool BigInt::operator==(
const BigInt& other)
const {
319 return sign_ == other.sign_ && cmp_abs(*
this, other) == 0;
322bool BigInt::operator!=(
const BigInt& other)
const {
return !(*
this == other); }
324bool BigInt::operator<(
const BigInt& other)
const {
325 if (sign_ != other.sign_)
return sign_ < other.sign_;
326 if (sign_ == ZERO)
return false;
327 int cmp = cmp_abs(*
this, other);
328 return sign_ == POSITIVE ? cmp < 0 : cmp > 0;
331bool BigInt::operator>(
const BigInt& other)
const {
return other < *
this; }
333bool BigInt::operator<=(
const BigInt& other)
const {
return !(*
this > other); }
335bool BigInt::operator>=(
const BigInt& other)
const {
return !(*
this < other); }
337bool BigInt::operator!()
const {
return size_ == 0; }
339BigInt::operator bool()
const {
return size_ != 0; }
341bool BigInt::is_zero()
const {
return size_ == 0; }
343std::vector<uint64_t> BigInt::get_digits()
const {
344 std::vector<uint64_t> d;
346 for(mp_size_t i = 0; i < size_; ++i) {
347 d.push_back(data_[i]);
352std::size_t BigInt::hash()
const {
353 std::size_t seed = 0;
354 for (mp_size_t i = 0; i < size_; ++i) {
355 seed ^= std::hash<uint64_t>{}(data_[i]) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
357 if (sign_ == NEGATIVE) { seed ^= std::hash<int>{}(-1) + 0x9e3779b9 + (seed << 6) + (seed >> 2); }
361BigInt BigInt::abs()
const {
364 ret.sign_ = POSITIVE;
369bool BigInt::is_negative()
const {
return sign_ == NEGATIVE; }
371BigInt BigInt::negate()
const {
374 ret.sign_ = (ret.sign_ == POSITIVE) ? NEGATIVE : POSITIVE;
379BigInt BigInt::operator-()
const {
return negate(); }
任意精度整数 BigInt,底层调用 LMMP 实现高性能大数运算。
ExpressionResult normalize(const Node &value, ComputationContext &context)
Node negate(const Node &value)
int sign(const Rational &value)
void ensure_lmmc_lifecycle() noexcept
const VectorField const VectorField & c
__attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) std const VectorField const std::string const std::shared_ptr< SymbolicExpr > & a
const std::string const ExprPtr & value