Download src/MultiplicityFunctor.cpp from Snapkitty/sovereign-multiplicity: direct link, hf CLI and curl.
- Browser
- Download file 6.47 kB
-
https://huggingface.co/Snapkitty/sovereign-multiplicity/resolve/main/src/MultiplicityFunctor.cpp
- Command line
-
hf download hf://Snapkitty/sovereign-multiplicity/src/MultiplicityFunctor.cpp
-
curl -L -o MultiplicityFunctor.cpp https://huggingface.co/Snapkitty/sovereign-multiplicity/resolve/main/src/MultiplicityFunctor.cpp
6.47 kB
| //===- MultiplicityFunctor.cpp - Rational Exponentiation Implementation ===// | |
| // | |
| // Non-recursive rational exponentiation engine. | |
| // Every computation is exact. Overflow produces an error, not undefined behavior. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| namespace pirtm { | |
| // --- Rational --- | |
| Rational::Rational() : numer(0), denom(1) {} | |
| Rational::Rational(int64_t n, int64_t d) : numer(n), denom(d) { | |
| reduce(); | |
| } | |
| void Rational::reduce() { | |
| if (denom == 0) return; | |
| if (denom < 0) { | |
| numer = -numer; | |
| denom = -denom; | |
| } | |
| int64_t g = std::gcd(std::abs(numer), denom); | |
| if (g > 1) { | |
| numer /= g; | |
| denom /= g; | |
| } | |
| } | |
| bool Rational::is_valid() const { | |
| return denom != 0; | |
| } | |
| std::string Rational::to_string() const { | |
| if (denom == 1) return std::to_string(numer); | |
| return std::to_string(numer) + "/" + std::to_string(denom); | |
| } | |
| bool Rational::operator==(const Rational& other) const { | |
| return numer == other.numer && denom == other.denom; | |
| } | |
| bool Rational::operator!=(const Rational& other) const { | |
| return !(*this == other); | |
| } | |
| // --- Multiplicity --- | |
| bool is_valid_prime(uint64_t p) { | |
| return p >= 2; | |
| } | |
| /// Compute p^n for integer exponent n (checked). | |
| static std::optional<uint64_t> pow_checked(uint64_t base, uint64_t exp) { | |
| if (exp == 0) return 1; | |
| if (base == 0) return 0; | |
| if (base == 1) return 1; | |
| uint64_t result = 1; | |
| while (exp > 0) { | |
| if (exp & 1) { | |
| if (result > UINT64_MAX / base) return std::nullopt; | |
| result *= base; | |
| } | |
| exp >>= 1; | |
| if (exp > 0) { | |
| if (base > UINT64_MAX / base) return std::nullopt; | |
| base *= base; | |
| } | |
| } | |
| return result; | |
| } | |
| /// Compute integer nth root of v (floor). | |
| static uint64_t integer_nth_root(uint64_t v, uint64_t n) { | |
| if (n == 0) return 1; | |
| if (n == 1) return v; | |
| if (v <= 1) return v; | |
| // Binary search for floor(v^(1/n)) | |
| uint64_t lo = 1, hi = v; | |
| while (lo < hi) { | |
| uint64_t mid = lo + (hi - lo + 1) / 2; | |
| auto p = pow_checked(mid, n); | |
| if (p.has_value() && *p <= v) { | |
| lo = mid; | |
| } else { | |
| hi = mid - 1; | |
| } | |
| } | |
| return lo; | |
| } | |
| MultiplicityResult compute_multiplicity(uint64_t prime, const Rational& exponent) { | |
| MultiplicityResult result; | |
| result.value = Rational(0, 1); | |
| result.error = MultiplicityError::None; | |
| // Validate prime | |
| if (!is_valid_prime(prime)) { | |
| result.error = MultiplicityError::InvalidPrime; | |
| result.error_msg = format_error(result.error, prime, exponent); | |
| return result; | |
| } | |
| // Validate exponent denominator | |
| if (exponent.denom == 0) { | |
| result.error = MultiplicityError::ZeroDenominator; | |
| result.error_msg = format_error(result.error, prime, exponent); | |
| return result; | |
| } | |
| // Handle negative exponents | |
| if (exponent.numer < 0) { | |
| result.error = MultiplicityError::NegativeExponent; | |
| result.error_msg = format_error(result.error, prime, exponent); | |
| return result; | |
| } | |
| // Special cases | |
| if (exponent.numer == 0) { | |
| result.value = Rational(1, 1); | |
| return result; | |
| } | |
| if (prime == 1) { | |
| result.value = Rational(1, 1); | |
| return result; | |
| } | |
| // Exact computation for integer exponents | |
| if (exponent.denom == 1) { | |
| auto val = pow_checked(prime, static_cast<uint64_t>(exponent.numer)); | |
| if (val.has_value()) { | |
| result.value = Rational(static_cast<int64_t>(*val), 1); | |
| return result; | |
| } | |
| result.error = MultiplicityError::Overflow; | |
| result.error_msg = format_error(result.error, prime, exponent); | |
| return result; | |
| } | |
| // Rational exponent: p^(a/b) = (p^a)^(1/b) | |
| // First compute p^a | |
| auto pa = pow_checked(prime, static_cast<uint64_t>(exponent.numer)); | |
| if (!pa.has_value()) { | |
| result.error = MultiplicityError::Overflow; | |
| result.error_msg = format_error(result.error, prime, exponent); | |
| return result; | |
| } | |
| // Then compute the b-th root | |
| uint64_t root = integer_nth_root(*pa, static_cast<uint64_t>(exponent.denom)); | |
| // Verify: root^denom should equal pa (exact result) | |
| auto check = pow_checked(root, static_cast<uint64_t>(exponent.denom)); | |
| if (check.has_value() && *check == *pa) { | |
| result.value = Rational(static_cast<int64_t>(root), 1); | |
| return result; | |
| } | |
| // Inexact result - return as rational | |
| result.value = Rational(static_cast<int64_t>(*pa), static_cast<int64_t>(exponent.denom)); | |
| result.value.reduce(); | |
| return result; | |
| } | |
| uint64_t max_prime_for_exponent(const Rational& exponent) { | |
| if (exponent.numer <= 0 || exponent.denom <= 0) return 2; | |
| // Find largest p such that p^(numer/denom) fits in u64 | |
| // p^(a/b) <= UINT64_MAX => p <= UINT64_MAX^(b/a) | |
| double max_val = std::pow(static_cast<double>(UINT64_MAX), | |
| static_cast<double>(exponent.denom) / static_cast<double>(exponent.numer)); | |
| if (max_val > static_cast<double>(UINT64_MAX) || max_val < 0) { | |
| return UINT64_MAX; | |
| } | |
| return static_cast<uint64_t>(max_val); | |
| } | |
| std::string format_error(MultiplicityError err, uint64_t prime, const Rational& exponent) { | |
| std::ostringstream oss; | |
| switch (err) { | |
| case MultiplicityError::None: | |
| return "no error"; | |
| case MultiplicityError::Overflow: | |
| oss << "PM001: Multiplicity overflow: " << prime << "^" << exponent.to_string() | |
| << " exceeds u64 range"; | |
| break; | |
| case MultiplicityError::ZeroDenominator: | |
| oss << "PM002: Zero denominator in rational exponent"; | |
| break; | |
| case MultiplicityError::InvalidPrime: | |
| oss << "PM003: Invalid prime index " << prime << " (must be >= 2)"; | |
| break; | |
| case MultiplicityError::NegativeExponent: | |
| oss << "PM004: Negative exponent " << exponent.to_string() << " not supported"; | |
| break; | |
| } | |
| return oss.str(); | |
| } | |
| } // namespace pirtm | |