use num_bigint::{BigInt, ToBigInt};
use num_rational::BigRational;
use num_traits::{Zero, One, Signed};
use crate::core::{Expression, Number};
use super::ComputeError;
pub struct NumberTheoryEngine;
impl NumberTheoryEngine {
pub fn new() -> Self {
Self
}
pub fn gcd(&self, a: &Expression, b: &Expression) -> Result<Expression, ComputeError> {
match (a, b) {
(Expression::Number(Number::Integer(a)), Expression::Number(Number::Integer(b))) => {
let result = self.gcd_bigint(a, b);
Ok(Expression::Number(Number::Integer(result)))
}
(Expression::Number(Number::Rational(a)), Expression::Number(Number::Rational(b))) => {
let a_num = a.numer();
let a_den = a.denom();
let b_num = b.numer();
let b_den = b.denom();
let numerator_gcd = self.gcd_bigint(&(a_num * b_den), &(b_num * a_den));
let denominator = a_den * b_den;
let result = BigRational::new(numerator_gcd, denominator.clone());
Ok(Expression::Number(Number::Rational(result)))
}
_ => Err(ComputeError::unsupported_operation(
"gcd 函数只支持整数和有理数,请确保参数是整数或有理数"
))
}
}
pub fn lcm(&self, a: &Expression, b: &Expression) -> Result<Expression, ComputeError> {
match (a, b) {
(Expression::Number(Number::Integer(a)), Expression::Number(Number::Integer(b))) => {
if a.is_zero() || b.is_zero() {
return Ok(Expression::Number(Number::Integer(BigInt::zero())));
}
let gcd_val = self.gcd_bigint(a, b);
let result = (a * b).abs() / gcd_val;
Ok(Expression::Number(Number::Integer(result)))
}
_ => Err(ComputeError::unsupported_operation(
"lcm 函数只支持整数,请确保参数是整数"
))
}
}
pub fn is_prime(&self, n: &Expression) -> Result<bool, ComputeError> {
match n {
Expression::Number(Number::Integer(n)) => {
Ok(self.is_prime_bigint(n))
}
_ => Err(ComputeError::unsupported_operation(
"is_prime 函数只支持整数,请确保参数是正整数"
))
}
}
pub fn prime_factors(&self, n: &Expression) -> Result<Vec<Expression>, ComputeError> {
match n {
Expression::Number(Number::Integer(n)) => {
if n <= &BigInt::one() {
return Err(ComputeError::domain_error(
"质因数分解要求输入大于1的正整数"
));
}
let factors = self.prime_factors_bigint(n);
let result = factors.into_iter()
.map(|f| Expression::Number(Number::Integer(f)))
.collect();
Ok(result)
}
_ => Err(ComputeError::unsupported_operation(
"prime_factors 函数只支持整数,请确保参数是大于1的正整数"
))
}
}
pub fn binomial(&self, n: &Expression, k: &Expression) -> Result<Expression, ComputeError> {
match (n, k) {
(Expression::Number(Number::Integer(n)), Expression::Number(Number::Integer(k))) => {
if n < &BigInt::zero() || k < &BigInt::zero() || k > n {
return Ok(Expression::Number(Number::Integer(BigInt::zero())));
}
let result = self.binomial_coefficient(n, k)?;
Ok(Expression::Number(Number::Integer(result)))
}
_ => Err(ComputeError::unsupported_operation(
"binomial 函数只支持非负整数,请确保参数是非负整数且 k <= n"
))
}
}
pub fn permutation(&self, n: &Expression, k: &Expression) -> Result<Expression, ComputeError> {
match (n, k) {
(Expression::Number(Number::Integer(n)), Expression::Number(Number::Integer(k))) => {
if n < &BigInt::zero() || k < &BigInt::zero() || k > n {
return Ok(Expression::Number(Number::Integer(BigInt::zero())));
}
let result = self.permutation_count(n, k)?;
Ok(Expression::Number(Number::Integer(result)))
}
_ => Err(ComputeError::unsupported_operation(
"permutation 函数只支持非负整数,请确保参数是非负整数且 k <= n"
))
}
}
pub fn mean(&self, values: &[Expression]) -> Result<Expression, ComputeError> {
if values.is_empty() {
return Err(ComputeError::domain_error(
"无法计算空列表的平均值,请提供至少一个数值"
));
}
let mut sum = Number::Integer(BigInt::zero());
let count = values.len();
for value in values {
match value {
Expression::Number(num) => {
sum = self.add_numbers(&sum, num)?;
}
_ => return Err(ComputeError::unsupported_operation(
"mean 函数只支持数值,请确保所有参数都是数值"
))
}
}
let count_num = Number::Integer(count.to_bigint().unwrap());
let result = self.divide_numbers(&sum, &count_num)?;
Ok(Expression::Number(result))
}
pub fn variance(&self, values: &[Expression]) -> Result<Expression, ComputeError> {
if values.len() < 2 {
return Err(ComputeError::domain_error(
"计算方差需要至少两个数值"
));
}
let mean_expr = self.mean(values)?;
let mean_num = match mean_expr {
Expression::Number(num) => num,
_ => unreachable!()
};
let mut sum_squares = Number::Integer(BigInt::zero());
for value in values {
match value {
Expression::Number(num) => {
let diff = self.subtract_numbers(num, &mean_num)?;
let square = self.multiply_numbers(&diff, &diff)?;
sum_squares = self.add_numbers(&sum_squares, &square)?;
}
_ => return Err(ComputeError::unsupported_operation(
"variance 函数只支持数值,请确保所有参数都是数值"
))
}
}
let count_num = Number::Integer(values.len().to_bigint().unwrap());
let result = self.divide_numbers(&sum_squares, &count_num)?;
Ok(Expression::Number(result))
}
pub fn standard_deviation(&self, values: &[Expression]) -> Result<Expression, ComputeError> {
let variance_expr = self.variance(values)?;
match variance_expr {
Expression::Number(variance_num) => {
let sqrt_result = self.sqrt_number(&variance_num)?;
Ok(Expression::Number(sqrt_result))
}
_ => unreachable!()
}
}
fn gcd_bigint(&self, a: &BigInt, b: &BigInt) -> BigInt {
let mut a = a.abs();
let mut b = b.abs();
while !b.is_zero() {
let temp = b.clone();
b = &a % &b;
a = temp;
}
a
}
fn is_prime_bigint(&self, n: &BigInt) -> bool {
if n <= &BigInt::one() {
return false;
}
if n == &(BigInt::from(2)) {
return true;
}
if n % 2 == BigInt::zero() {
return false;
}
let mut i = BigInt::from(3);
let sqrt_n = self.integer_sqrt(n);
while i <= sqrt_n {
if n % &i == BigInt::zero() {
return false;
}
i += 2; }
true
}
fn prime_factors_bigint(&self, n: &BigInt) -> Vec<BigInt> {
let mut factors = Vec::new();
let mut n = n.clone();
while &n % 2 == BigInt::zero() {
factors.push(BigInt::from(2));
n /= 2;
}
let mut i = BigInt::from(3);
let sqrt_n = self.integer_sqrt(&n);
while i <= sqrt_n && n > BigInt::one() {
while &n % &i == BigInt::zero() {
factors.push(i.clone());
n /= &i;
}
i += 2;
}
if n > BigInt::one() {
factors.push(n);
}
factors
}
fn binomial_coefficient(&self, n: &BigInt, k: &BigInt) -> Result<BigInt, ComputeError> {
let k = if k > &(n - k) { n - k } else { k.clone() };
if k.is_zero() {
return Ok(BigInt::one());
}
let mut result = BigInt::one();
let mut i = BigInt::zero();
while i < k {
result = result * (n - &i) / (&i + 1);
i += 1;
}
Ok(result)
}
fn permutation_count(&self, n: &BigInt, k: &BigInt) -> Result<BigInt, ComputeError> {
if k.is_zero() {
return Ok(BigInt::one());
}
let mut result = BigInt::one();
let mut i = BigInt::zero();
while i < *k {
result *= n - &i;
i += 1;
}
Ok(result)
}
fn integer_sqrt(&self, n: &BigInt) -> BigInt {
if n.is_zero() {
return BigInt::zero();
}
let mut x = n.clone();
let mut y: BigInt = (n + 1) / 2;
while y < x {
x = y.clone();
y = (&x + n / &x) / 2;
}
x
}
fn add_numbers(&self, a: &Number, b: &Number) -> Result<Number, ComputeError> {
match (a, b) {
(Number::Integer(a), Number::Integer(b)) => {
Ok(Number::Integer(a + b))
}
(Number::Rational(a), Number::Rational(b)) => {
Ok(Number::Rational(a + b))
}
(Number::Integer(a), Number::Rational(b)) => {
let a_rational = BigRational::from(a.clone());
Ok(Number::Rational(a_rational + b))
}
(Number::Rational(a), Number::Integer(b)) => {
let b_rational = BigRational::from(b.clone());
Ok(Number::Rational(a + b_rational))
}
_ => Err(ComputeError::unsupported_operation(
"不支持的数值类型组合"
))
}
}
fn subtract_numbers(&self, a: &Number, b: &Number) -> Result<Number, ComputeError> {
match (a, b) {
(Number::Integer(a), Number::Integer(b)) => {
Ok(Number::Integer(a - b))
}
(Number::Rational(a), Number::Rational(b)) => {
Ok(Number::Rational(a - b))
}
(Number::Integer(a), Number::Rational(b)) => {
let a_rational = BigRational::from(a.clone());
Ok(Number::Rational(a_rational - b))
}
(Number::Rational(a), Number::Integer(b)) => {
let b_rational = BigRational::from(b.clone());
Ok(Number::Rational(a - b_rational))
}
_ => Err(ComputeError::unsupported_operation(
"不支持的数值类型组合"
))
}
}
fn multiply_numbers(&self, a: &Number, b: &Number) -> Result<Number, ComputeError> {
match (a, b) {
(Number::Integer(a), Number::Integer(b)) => {
Ok(Number::Integer(a * b))
}
(Number::Rational(a), Number::Rational(b)) => {
Ok(Number::Rational(a * b))
}
(Number::Integer(a), Number::Rational(b)) => {
let a_rational = BigRational::from(a.clone());
Ok(Number::Rational(a_rational * b))
}
(Number::Rational(a), Number::Integer(b)) => {
let b_rational = BigRational::from(b.clone());
Ok(Number::Rational(a * b_rational))
}
_ => Err(ComputeError::unsupported_operation(
"不支持的数值类型组合"
))
}
}
fn divide_numbers(&self, a: &Number, b: &Number) -> Result<Number, ComputeError> {
match (a, b) {
(Number::Integer(a), Number::Integer(b)) => {
if b.is_zero() {
return Err(ComputeError::DivisionByZero);
}
Ok(Number::Rational(BigRational::new(a.clone(), b.clone())))
}
(Number::Rational(a), Number::Rational(b)) => {
if b.is_zero() {
return Err(ComputeError::DivisionByZero);
}
Ok(Number::Rational(a / b))
}
(Number::Integer(a), Number::Rational(b)) => {
if b.is_zero() {
return Err(ComputeError::DivisionByZero);
}
let a_rational = BigRational::from(a.clone());
Ok(Number::Rational(a_rational / b))
}
(Number::Rational(a), Number::Integer(b)) => {
if b.is_zero() {
return Err(ComputeError::DivisionByZero);
}
let b_rational = BigRational::from(b.clone());
Ok(Number::Rational(a / b_rational))
}
_ => Err(ComputeError::unsupported_operation(
"不支持的数值类型组合"
))
}
}
fn sqrt_number(&self, n: &Number) -> Result<Number, ComputeError> {
match n {
Number::Integer(n) => {
if n < &BigInt::zero() {
return Err(ComputeError::domain_error(
"负数没有实数平方根,请使用复数运算"
));
}
let sqrt_int = self.integer_sqrt(n);
if &sqrt_int * &sqrt_int == *n {
Ok(Number::Integer(sqrt_int))
} else {
Ok(Number::Symbolic(Box::new(Expression::UnaryOp {
op: crate::core::UnaryOperator::Sqrt,
operand: Box::new(Expression::Number(Number::Integer(n.clone()))),
})))
}
}
Number::Rational(r) => {
let num_sqrt = self.integer_sqrt(r.numer());
let den_sqrt = self.integer_sqrt(r.denom());
if &num_sqrt * &num_sqrt == *r.numer() && &den_sqrt * &den_sqrt == *r.denom() {
Ok(Number::Rational(BigRational::new(num_sqrt, den_sqrt)))
} else {
Ok(Number::Symbolic(Box::new(Expression::UnaryOp {
op: crate::core::UnaryOperator::Sqrt,
operand: Box::new(Expression::Number(Number::Rational(r.clone()))),
})))
}
}
_ => Err(ComputeError::unsupported_operation(
"不支持的数值类型"
))
}
}
}
impl Default for NumberTheoryEngine {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
#[path = "number_theory_tests.rs"]
mod number_theory_tests;