Int class is added
All checks were successful
ci/woodpecker/push/workflow Pipeline was successful

`Parser::feed` method is redesigned for compatibility
This commit is contained in:
2025-10-07 21:14:07 +03:00
parent a0124b791d
commit b3c2bcb92d
2 changed files with 767 additions and 0 deletions

425
src/include/int.hpp Normal file
View File

@@ -0,0 +1,425 @@
#include <gmp.h>
#include <gmpxx.h>
#include <string>
/**
* @brief Options for `base` parameter used in GMP's `mpz_set_str` and
* `mpz_sizeinbase`.
* @see https://gmplib.org/manual/Assigning-Integers
*
* `base_N`: no characters, no case sensitivity.
* `ci_N`: case-insensitive (`A`=`10`, `a`=`10`)
* `cs_N`: case-sensitive (`A`=`10`, `a`=`36`)
*/
enum class base {
base_2 = 2,
base_3 = 3,
base_4 = 4,
base_5 = 5,
base_6 = 6,
base_7 = 7,
base_8 = 8,
base_9 = 9,
ci_10 = 10,
ci_11 = 11,
ci_12 = 12,
ci_13 = 13,
ci_14 = 14,
ci_15 = 15,
ci_16 = 16,
ci_17 = 17,
ci_18 = 18,
ci_19 = 19,
ci_20 = 20,
ci_21 = 21,
ci_22 = 22,
ci_23 = 23,
ci_24 = 24,
ci_25 = 25,
ci_26 = 26,
ci_27 = 27,
ci_28 = 28,
ci_29 = 29,
ci_30 = 30,
ci_31 = 31,
ci_32 = 32,
ci_33 = 33,
ci_34 = 34,
ci_35 = 35,
ci_36 = 36,
cs_37 = 37,
cs_38 = 38,
cs_39 = 39,
cs_40 = 40,
cs_41 = 41,
cs_42 = 42,
cs_43 = 43,
cs_44 = 44,
cs_45 = 45,
cs_46 = 46,
cs_47 = 47,
cs_48 = 48,
cs_49 = 49,
cs_50 = 50,
cs_51 = 51,
cs_52 = 52,
cs_53 = 53,
cs_54 = 54,
cs_55 = 55,
cs_56 = 56,
cs_57 = 57,
cs_58 = 58,
cs_59 = 59,
cs_60 = 60,
cs_61 = 61,
cs_62 = 62,
binary = base_2,
octal = base_8,
decimal = ci_10,
hexadecimal = ci_16,
};
/**
* @brief Options for `base` parameter used in GMP's `mpz_get_str`.
* @see https://gmplib.org/manual/Converting-Integers
*
* `base_N`: case sensitive. It doesn't have its upper and lower case versions.
*
* `lc_N`: lower-case, base N. All letters are lower case.
*
* `uc_N`: upper-case, base N. All letters are upper case.
*/
enum class print_base {
lc_2 = 2,
lc_3 = 3,
lc_4 = 4,
lc_5 = 5,
lc_6 = 6,
lc_7 = 7,
lc_8 = 8,
lc_9 = 9,
lc_10 = 10,
lc_11 = 11,
lc_12 = 12,
lc_13 = 13,
lc_14 = 14,
lc_15 = 15,
lc_16 = 16,
lc_17 = 17,
lc_18 = 18,
lc_19 = 19,
lc_20 = 20,
lc_21 = 21,
lc_22 = 22,
lc_23 = 23,
lc_24 = 24,
lc_25 = 25,
lc_26 = 26,
lc_27 = 27,
lc_28 = 28,
lc_29 = 29,
lc_30 = 30,
lc_31 = 31,
lc_32 = 32,
lc_33 = 33,
lc_34 = 34,
lc_35 = 35,
lc_36 = 36,
uc_2 = -2,
uc_3 = -3,
uc_4 = -4,
uc_5 = -5,
uc_6 = -6,
uc_7 = -7,
uc_8 = -8,
uc_9 = -9,
uc_10 = -10,
uc_11 = -11,
uc_12 = -12,
uc_13 = -13,
uc_14 = -14,
uc_15 = -15,
uc_16 = -16,
uc_17 = -17,
uc_18 = -18,
uc_19 = -19,
uc_20 = -20,
uc_21 = -21,
uc_22 = -22,
uc_23 = -23,
uc_24 = -24,
uc_25 = -25,
uc_26 = -26,
uc_27 = -27,
uc_28 = -28,
uc_29 = -29,
uc_30 = -30,
uc_31 = -31,
uc_32 = -32,
uc_33 = -33,
uc_34 = -34,
uc_35 = -35,
uc_36 = -36,
base_37 = 37,
base_38 = 38,
base_39 = 39,
base_40 = 40,
base_41 = 41,
base_42 = 42,
base_43 = 43,
base_44 = 44,
base_45 = 45,
base_46 = 46,
base_47 = 47,
base_48 = 48,
base_49 = 49,
base_50 = 50,
base_51 = 51,
base_52 = 52,
base_53 = 53,
base_54 = 54,
base_55 = 55,
base_56 = 56,
base_57 = 57,
base_58 = 58,
base_59 = 59,
base_60 = 60,
base_61 = 61,
base_62 = 62,
octal_lower_case = lc_8,
hex_lower_case = lc_16,
decimal = lc_10,
binary = lc_2,
octal_upper_case = uc_8,
hex_upper_case = uc_16,
};
base print_base_to_base(print_base);
/**
* @brief is an high-performance, arbitrary precision Integer class for mash
*/
class Int {
private:
mpz_t inner;
public:
Int();
Int(const Int &);
Int(unsigned long);
Int(long);
Int(double);
Int(const std::string &, base);
unsigned long to_ul();
long to_l();
double to_d();
std::string to_string(print_base);
void swap(Int &);
void operator+(const Int &);
void operator+(unsigned long);
void operator+(long);
void operator-(const Int &);
void operator-(unsigned long);
void operator-(long);
void operator*(const Int &);
void operator*(unsigned long);
void operator*(long);
void operator/(const Int &);
void operator/(unsigned long);
void operator/(long);
void operator%(const Int &);
void operator%(unsigned long);
void add_mul(Int &);
void add_mul(unsigned long);
void add_mul(long);
void sub_mul(Int &);
void sub_mul(unsigned long);
void sub_mul(long);
void mul_2exp(unsigned long);
void operator~();
void abs();
void ceil_div_quotient(Int &);
void ceil_div_remainder(Int &);
void ceil_div_both(Int &);
void ceil_div(unsigned long);
void ceil_div_both(unsigned long);
void ceil_div_quotient(unsigned long);
void ceil_div_remainder(unsigned long);
void ceil_div(long);
void ceil_div_both(long);
void ceil_div_quotient(long);
void ceil_div_remainder(long);
void ceil_div_quotient_2exp(unsigned long);
void ceil_div_remainder_2exp(unsigned long);
void floor_div_quotient(Int &);
void floor_div_remainder(Int &);
void floor_div_both(Int &);
void floor_div(unsigned long);
void floor_div_both(unsigned long);
void floor_div_quotient(unsigned long);
void floor_div_remainder(unsigned long);
void floor_div(long);
void floor_div_both(long);
void floor_div_quotient(long);
void floor_div_remainder(long);
void floor_div_quotient_2exp(unsigned long);
void floor_div_remainder_2exp(unsigned long);
void truncate_div_quotient(Int &);
void truncate_div_remainder(Int &);
void truncate_div_both(Int &);
void truncate_div(unsigned long);
void truncate_div_both(unsigned long);
void truncate_div_quotient(unsigned long);
void truncate_div_remainder(unsigned long);
void truncate_div(long);
void truncate_div_both(long);
void truncate_div_quotient(long);
void truncate_div_remainder(long);
void truncate_div_quotient_2exp(unsigned long);
void truncate_div_remainder_2exp(unsigned long);
void mod(Int &);
void mod(unsigned long);
void mod(long);
void div_exact(Int &);
void div_exact(unsigned long);
void div_exact(long);
int divisible(Int &);
int divisible(unsigned long);
int divisible(long);
int divisible_2exp(unsigned long);
int congruent(Int &);
int congruent(unsigned long);
int congruent(long);
int congruent_2exp(unsigned long);
void mod_pow(Int &);
void mod_pow(unsigned long);
void mod_pow(long);
void powm_sec(Int &);
void pow(Int &);
void pow(unsigned long, unsigned long);
void pow(long, unsigned long);
~Int() { mpz_clear(inner); };
};
/*
///
/// Enum for the number's sign.
///
/// `Zero` is for when number is zero.
///
pub const Sign = enum(i8) {
Negative = -1,
Positive = 1,
Zero = 0,
pub fn toChar(self: @This()) u8 {
return switch (self) {
.Negative => '-',
.Positive => '+',
.Zero => '0',
};
}
pub fn toString(self: @This()) []const u8 {
return switch (self) {
.Negative => "negative",
.Positive => "positive",
.Zero => "zero",
};
}
};
///
/// Enum for the comparison of two numbers.
///
pub const Ordering = enum(i8) {
Less = -1,
Greater = 1,
Equals = 0,
const Self = @This();
pub fn toChar(self: Self) u8 {
return switch (self) {
.Less => '<',
.Greater => '>',
.Equals => '=',
};
}
pub fn toString(self: Self) []const u8 {
return switch (self) {
.Less => "less",
.Greater => "greater",
.Equals => "equals",
};
}
pub fn fromC(num: c_int) Self {
if (num < 0) return .Less;
if (num > 0) return .Greater;
return .Equals;
}
};
/// Enum for the number's parity.
pub const Parity = enum(i8) {
Even = 0,
Odd = 1,
pub fn toString(self: @This()) []const u8 {
return switch (self) {
.Even => "even",
.Odd => "odd",
};
}
};
////
/// Rounding methods for division.
///
/// `Truncate` rounds the integer towards 0.
/// `Ceil` rounds the integer towards positive infinity.
/// `Floor` rounds the integer towrds positiv infinity.
///
/// |`Number`|`Truncate`|`Ceil`|`Floor`|
/// |--------|----------|------|-------|
/// |`4.5` |`4` |`5` |`4` |
/// |`-4.5` |`-4` |`-4` |`-5` |
///
pub const RoundingMethod = enum(i8) {
Truncate = 0,
Ceil = 1,
Floor = -1,
};
///
/// Option for which result will be written to the integer.
///
pub const Output = enum(i8) {
Quotient = 0,
Remainder = 1,
};
*/

342
src/int.cpp Normal file
View File

@@ -0,0 +1,342 @@
#include <cmath>
#include <cstdlib>
#include <gmp.h>
#include <int.hpp>
#include <string>
#include <utility>
Int::Int() { mpz_init(this->inner); };
Int::Int(const Int &big) { mpz_init_set(this->inner, big.inner); };
Int::Int(unsigned long ul) { mpz_init_set_ui(this->inner, ul); };
Int::Int(long l) { mpz_init_set_si(this->inner, l); };
Int::Int(double d) { mpz_init_set_d(this->inner, d); };
Int::Int(const std::string &str, base b) {
int result = mpz_init_set_str(this->inner, str.data(), static_cast<int>(b));
if (result == 1)
throw std::exception();
};
base print_base_to_base(print_base p_base) {
switch (p_base) {
case print_base::lc_2:
case print_base::uc_2:
return base::base_2;
case print_base::lc_3:
case print_base::uc_3:
return base::base_3;
case print_base::lc_4:
case print_base::uc_4:
return base::base_4;
case print_base::lc_5:
case print_base::uc_5:
return base::base_5;
case print_base::lc_6:
case print_base::uc_6:
return base::base_6;
case print_base::lc_7:
case print_base::uc_7:
return base::base_7;
case print_base::lc_8:
case print_base::uc_8:
return base::base_8;
case print_base::lc_9:
case print_base::uc_9:
return base::base_9;
case print_base::lc_10:
case print_base::uc_10:
return base::ci_10;
case print_base::lc_11:
case print_base::uc_11:
return base::ci_11;
case print_base::lc_12:
case print_base::uc_12:
return base::ci_12;
case print_base::lc_13:
case print_base::uc_13:
return base::ci_13;
case print_base::lc_14:
case print_base::uc_14:
return base::ci_14;
case print_base::lc_15:
case print_base::uc_15:
return base::ci_15;
case print_base::lc_16:
case print_base::uc_16:
return base::ci_16;
case print_base::lc_17:
case print_base::uc_17:
return base::ci_17;
case print_base::lc_18:
case print_base::uc_18:
return base::ci_18;
case print_base::lc_19:
case print_base::uc_19:
return base::ci_19;
case print_base::lc_20:
case print_base::uc_20:
return base::ci_20;
case print_base::lc_21:
case print_base::uc_21:
return base::ci_21;
case print_base::lc_22:
case print_base::uc_22:
return base::ci_22;
case print_base::lc_23:
case print_base::uc_23:
return base::ci_23;
case print_base::lc_24:
case print_base::uc_24:
return base::ci_24;
case print_base::lc_25:
case print_base::uc_25:
return base::ci_25;
case print_base::lc_26:
case print_base::uc_26:
return base::ci_26;
case print_base::lc_27:
case print_base::uc_27:
return base::ci_27;
case print_base::lc_28:
case print_base::uc_28:
return base::ci_28;
case print_base::lc_29:
case print_base::uc_29:
return base::ci_29;
case print_base::lc_30:
case print_base::uc_30:
return base::ci_30;
case print_base::lc_31:
case print_base::uc_31:
return base::ci_31;
case print_base::lc_32:
case print_base::uc_32:
return base::ci_32;
case print_base::lc_33:
case print_base::uc_33:
return base::ci_33;
case print_base::lc_34:
case print_base::uc_34:
return base::ci_34;
case print_base::lc_35:
case print_base::uc_35:
return base::ci_35;
case print_base::lc_36:
case print_base::uc_36:
return base::ci_36;
case print_base::base_37:
return base::cs_37;
case print_base::base_38:
return base::cs_38;
case print_base::base_39:
return base::cs_39;
case print_base::base_40:
return base::cs_40;
case print_base::base_41:
return base::cs_41;
case print_base::base_42:
return base::cs_42;
case print_base::base_43:
return base::cs_43;
case print_base::base_44:
return base::cs_44;
case print_base::base_45:
return base::cs_45;
case print_base::base_46:
return base::cs_46;
case print_base::base_47:
return base::cs_47;
case print_base::base_48:
return base::cs_48;
case print_base::base_49:
return base::cs_49;
case print_base::base_50:
return base::cs_50;
case print_base::base_51:
return base::cs_51;
case print_base::base_52:
return base::cs_52;
case print_base::base_53:
return base::cs_53;
case print_base::base_54:
return base::cs_54;
case print_base::base_55:
return base::cs_55;
case print_base::base_56:
return base::cs_56;
case print_base::base_57:
return base::cs_57;
case print_base::base_58:
return base::cs_58;
case print_base::base_59:
return base::cs_59;
case print_base::base_60:
return base::cs_60;
case print_base::base_61:
return base::cs_61;
case print_base::base_62:
return base::cs_62;
}
std::unreachable();
}
unsigned long Int::to_ul() { return mpz_get_ui(this->inner); };
long Int::to_l() { return mpz_get_si(this->inner); };
double Int::to_d() { return mpz_get_d(this->inner); };
std::string Int::to_string(print_base base) {
int print_base_int = static_cast<int>(base);
char *str = mpz_get_str(NULL, print_base_int, this->inner);
std::string res(str);
free(str);
return res;
};
void Int::swap(Int &rhs) { mpz_swap(this->inner, rhs.inner); }
void Int::operator+(const Int &rhs) {
mpz_add(this->inner, this->inner, rhs.inner);
};
void Int::operator+(unsigned long rhs) {
mpz_add_ui(this->inner, this->inner, rhs);
};
void Int::operator+(long rhs) {
if (rhs < 0)
mpz_sub_ui(this->inner, this->inner, std::abs(rhs));
else
mpz_add_ui(this->inner, this->inner, rhs);
};
void Int::operator-(const Int &rhs) {
mpz_sub(this->inner, this->inner, rhs.inner);
};
void Int::operator-(unsigned long rhs) {
mpz_sub_ui(this->inner, this->inner, rhs);
};
void Int::operator-(long rhs) {
if (rhs < 0)
mpz_add_ui(this->inner, this->inner, std::abs(rhs));
else
mpz_sub_ui(this->inner, this->inner, rhs);
};
void Int::operator*(const Int &rhs) {
mpz_mul(this->inner, this->inner, rhs.inner);
};
void Int::operator*(unsigned long rhs) {
mpz_mul_ui(this->inner, this->inner, rhs);
};
void Int::operator*(long rhs) {
if (rhs < 0) {
mpz_mul_ui(this->inner, this->inner, std::abs(rhs));
this->operator~();
} else
mpz_mul_ui(this->inner, this->inner, rhs);
};
void Int::operator/(const Int &rhs) {
mpz_tdiv_q(this->inner, this->inner, rhs.inner);
};
void Int::operator/(unsigned long rhs) {
mpz_tdiv_q_ui(this->inner, this->inner, rhs);
};
void Int::operator/(long rhs) {
if (rhs < 0) {
mpz_tdiv_q_ui(this->inner, this->inner, std::abs(rhs));
this->operator~();
} else
mpz_tdiv_q_ui(this->inner, this->inner, rhs);
};
void Int::operator%(const Int &rhs) {
mpz_mod(this->inner, this->inner, rhs.inner);
};
void Int::operator%(unsigned long rhs) {
mpz_mod_ui(this->inner, this->inner, rhs);
};
void add_mul(Int &);
void add_mul(unsigned long);
void add_mul(long);
void sub_mul(Int &);
void sub_mul(unsigned long);
void sub_mul(long);
void mul_2exp(unsigned long);
void Int::operator~() { mpz_neg(this->inner, this->inner); };
void abs();
void ceil_div_quotient(Int &);
void ceil_div_remainder(Int &);
void ceil_div_both(Int &);
void ceil_div(unsigned long);
void ceil_div_both(unsigned long);
void ceil_div_quotient(unsigned long);
void ceil_div_remainder(unsigned long);
void ceil_div(long);
void ceil_div_both(long);
void ceil_div_quotient(long);
void ceil_div_remainder(long);
void ceil_div_quotient_2exp(unsigned long);
void ceil_div_remainder_2exp(unsigned long);
void floor_div_quotient(Int &);
void floor_div_remainder(Int &);
void floor_div_both(Int &);
void floor_div(unsigned long);
void floor_div_both(unsigned long);
void floor_div_quotient(unsigned long);
void floor_div_remainder(unsigned long);
void floor_div(long);
void floor_div_both(long);
void floor_div_quotient(long);
void floor_div_remainder(long);
void floor_div_quotient_2exp(unsigned long);
void floor_div_remainder_2exp(unsigned long);
void truncate_div_quotient(Int &);
void truncate_div_remainder(Int &);
void truncate_div_both(Int &);
void truncate_div(unsigned long);
void truncate_div_both(unsigned long);
void truncate_div_quotient(unsigned long);
void truncate_div_remainder(unsigned long);
void truncate_div(long);
void truncate_div_both(long);
void truncate_div_quotient(long);
void truncate_div_remainder(long);
void truncate_div_quotient_2exp(unsigned long);
void truncate_div_remainder_2exp(unsigned long);
void mod(Int &);
void mod(unsigned long);
void mod(long);
void div_exact(Int &);
void div_exact(unsigned long);
void div_exact(long);
int divisible(Int &);
int divisible(unsigned long);
int divisible(long);
int divisible_2exp(unsigned long);
int congruent(Int &);
int congruent(unsigned long);
int congruent(long);
int congruent_2exp(unsigned long);