NAC_Blockchain/charter-std/utils/math.ch

477 lines
9.9 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

///! # 数学运算库
///!
///! Math Utilities
///! 提供安全的数学运算函数
///!
///! **版本**: v1.0
///! **模块**: charter-std/utils/math.ch
// ============================================================================
// 安全算术运算
// ============================================================================
/// 安全加法(检查溢出)
///
/// # 参数
/// - `a`: 第一个数
/// - `b`: 第二个数
///
/// # 返回
/// - `u256`: 和
///
/// # Panics
/// - 如果发生溢出
pub fn safe_add(a: u256, b: u256) -> u256 {
let result = a + b;
require(result >= a, "Addition overflow");
return result;
}
/// 安全减法(检查下溢)
///
/// # 参数
/// - `a`: 被减数
/// - `b`: 减数
///
/// # 返回
/// - `u256`: 差
///
/// # Panics
/// - 如果发生下溢
pub fn safe_sub(a: u256, b: u256) -> u256 {
require(a >= b, "Subtraction underflow");
return a - b;
}
/// 安全乘法(检查溢出)
///
/// # 参数
/// - `a`: 第一个数
/// - `b`: 第二个数
///
/// # 返回
/// - `u256`: 积
///
/// # Panics
/// - 如果发生溢出
pub fn safe_mul(a: u256, b: u256) -> u256 {
if a == 0 {
return 0;
}
let result = a * b;
require(result / a == b, "Multiplication overflow");
return result;
}
/// 安全除法(检查除零)
///
/// # 参数
/// - `a`: 被除数
/// - `b`: 除数
///
/// # 返回
/// - `u256`: 商
///
/// # Panics
/// - 如果除数为0
pub fn safe_div(a: u256, b: u256) -> u256 {
require(b > 0, "Division by zero");
return a / b;
}
/// 安全取模(检查除零)
///
/// # 参数
/// - `a`: 被除数
/// - `b`: 除数
///
/// # 返回
/// - `u256`: 余数
///
/// # Panics
/// - 如果除数为0
pub fn safe_mod(a: u256, b: u256) -> u256 {
require(b > 0, "Modulo by zero");
return a % b;
}
// ============================================================================
// 比较函数
// ============================================================================
/// 返回两个数中的最大值
///
/// # 参数
/// - `a`: 第一个数
/// - `b`: 第二个数
///
/// # 返回
/// - `u256`: 最大值
pub fn max(a: u256, b: u256) -> u256 {
return if a >= b { a } else { b };
}
/// 返回两个数中的最小值
///
/// # 参数
/// - `a`: 第一个数
/// - `b`: 第二个数
///
/// # 返回
/// - `u256`: 最小值
pub fn min(a: u256, b: u256) -> u256 {
return if a <= b { a } else { b };
}
/// 计算绝对差值
///
/// # 参数
/// - `a`: 第一个数
/// - `b`: 第二个数
///
/// # 返回
/// - `u256`: 绝对差值
pub fn abs_diff(a: u256, b: u256) -> u256 {
return if a >= b { a - b } else { b - a };
}
// ============================================================================
// 百分比和比例计算
// ============================================================================
/// 计算百分比使用基点1基点 = 0.01%
///
/// # 参数
/// - `amount`: 数量
/// - `basis_points`: 基点0-1000010000 = 100%
///
/// # 返回
/// - `u256`: 结果
///
/// # 示例
/// ```
/// let result = percentage(1000, 500); // 1000 * 5% = 50
/// ```
pub fn percentage(amount: u256, basis_points: u16) -> u256 {
require(basis_points <= 10000, "Basis points must be <= 10000");
return safe_mul(amount, basis_points as u256) / 10000;
}
/// 计算比例
///
/// # 参数
/// - `amount`: 数量
/// - `numerator`: 分子
/// - `denominator`: 分母
///
/// # 返回
/// - `u256`: 结果
///
/// # 示例
/// ```
/// let result = proportion(1000, 3, 4); // 1000 * 3/4 = 750
/// ```
pub fn proportion(amount: u256, numerator: u256, denominator: u256) -> u256 {
require(denominator > 0, "Denominator cannot be zero");
return safe_mul(amount, numerator) / denominator;
}
/// 向上取整除法
///
/// # 参数
/// - `a`: 被除数
/// - `b`: 除数
///
/// # 返回
/// - `u256`: 向上取整的商
pub fn ceil_div(a: u256, b: u256) -> u256 {
require(b > 0, "Division by zero");
if a == 0 {
return 0;
}
return (a - 1) / b + 1;
}
// ============================================================================
// 幂运算
// ============================================================================
/// 计算幂a^b
///
/// # 参数
/// - `base`: 底数
/// - `exponent`: 指数
///
/// # 返回
/// - `u256`: 结果
///
/// # Panics
/// - 如果发生溢出
pub fn pow(base: u256, exponent: u256) -> u256 {
if exponent == 0 {
return 1;
}
if base == 0 {
return 0;
}
let mut result: u256 = 1;
let mut b = base;
let mut e = exponent;
while e > 0 {
if e % 2 == 1 {
result = safe_mul(result, b);
}
b = safe_mul(b, b);
e = e / 2;
}
return result;
}
/// 计算平方根(整数部分)
///
/// # 参数
/// - `x`: 被开方数
///
/// # 返回
/// - `u256`: 平方根的整数部分
///
/// # 算法
/// 使用牛顿迭代法
pub fn sqrt(x: u256) -> u256 {
if x == 0 {
return 0;
}
if x <= 3 {
return 1;
}
// 初始猜测值
let mut z = x;
let mut y = (x + 1) / 2;
// 牛顿迭代
while y < z {
z = y;
y = (x / y + y) / 2;
}
return z;
}
// ============================================================================
// 平均值计算
// ============================================================================
/// 计算算术平均值
///
/// # 参数
/// - `a`: 第一个数
/// - `b`: 第二个数
///
/// # 返回
/// - `u256`: 平均值
pub fn average(a: u256, b: u256) -> u256 {
// (a + b) / 2 可能溢出,使用 (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2)
return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
}
/// 计算加权平均值
///
/// # 参数
/// - `values`: 数值数组
/// - `weights`: 权重数组
///
/// # 返回
/// - `u256`: 加权平均值
///
/// # Panics
/// - 如果数组长度不匹配
/// - 如果权重总和为0
pub fn weighted_average(values: Vec<u256>, weights: Vec<u256>) -> u256 {
require(values.len() == weights.len(), "Arrays length mismatch");
require(values.len() > 0, "Arrays cannot be empty");
let mut sum: u256 = 0;
let mut weight_sum: u256 = 0;
for i in 0..values.len() {
sum = safe_add(sum, safe_mul(values[i], weights[i]));
weight_sum = safe_add(weight_sum, weights[i]);
}
require(weight_sum > 0, "Weight sum cannot be zero");
return sum / weight_sum;
}
// ============================================================================
// 数组统计函数
// ============================================================================
/// 计算数组总和
///
/// # 参数
/// - `values`: 数值数组
///
/// # 返回
/// - `u256`: 总和
pub fn sum(values: Vec<u256>) -> u256 {
let mut result: u256 = 0;
for value in values {
result = safe_add(result, value);
}
return result;
}
/// 查找数组最大值
///
/// # 参数
/// - `values`: 数值数组
///
/// # 返回
/// - `u256`: 最大值
///
/// # Panics
/// - 如果数组为空
pub fn array_max(values: Vec<u256>) -> u256 {
require(values.len() > 0, "Array cannot be empty");
let mut max_value = values[0];
for value in values {
if value > max_value {
max_value = value;
}
}
return max_value;
}
/// 查找数组最小值
///
/// # 参数
/// - `values`: 数值数组
///
/// # 返回
/// - `u256`: 最小值
///
/// # Panics
/// - 如果数组为空
pub fn array_min(values: Vec<u256>) -> u256 {
require(values.len() > 0, "Array cannot be empty");
let mut min_value = values[0];
for value in values {
if value < min_value {
min_value = value;
}
}
return min_value;
}
// ============================================================================
// 金融计算函数
// ============================================================================
/// 计算复利
///
/// # 参数
/// - `principal`: 本金
/// - `rate_basis_points`: 利率基点1基点 = 0.01%
/// - `periods`: 计息期数
///
/// # 返回
/// - `u256`: 本息和
///
/// # 公式
/// A = P * (1 + r)^n
pub fn compound_interest(
principal: u256,
rate_basis_points: u16,
periods: u256
) -> u256 {
require(rate_basis_points <= 10000, "Rate must be <= 100%");
if periods == 0 {
return principal;
}
// 使用基点计算:(10000 + rate) / 10000
let rate_factor = 10000 + (rate_basis_points as u256);
let mut result = principal;
for _ in 0..periods {
result = safe_mul(result, rate_factor) / 10000;
}
return result;
}
/// 计算单利
///
/// # 参数
/// - `principal`: 本金
/// - `rate_basis_points`: 利率(基点)
/// - `periods`: 计息期数
///
/// # 返回
/// - `u256`: 本息和
///
/// # 公式
/// A = P * (1 + r * n)
pub fn simple_interest(
principal: u256,
rate_basis_points: u16,
periods: u256
) -> u256 {
require(rate_basis_points <= 10000, "Rate must be <= 100%");
let interest = safe_mul(
safe_mul(principal, rate_basis_points as u256),
periods
) / 10000;
return safe_add(principal, interest);
}
/// 计算年化收益率APY
///
/// # 参数
/// - `initial_value`: 初始价值
/// - `final_value`: 最终价值
/// - `days`: 天数
///
/// # 返回
/// - `u16`: 年化收益率(基点)
pub fn calculate_apy(
initial_value: u256,
final_value: u256,
days: u256
) -> u16 {
require(initial_value > 0, "Initial value must be positive");
require(days > 0, "Days must be positive");
if final_value <= initial_value {
return 0;
}
// APY = ((final / initial) - 1) * (365 / days) * 10000
let gain = final_value - initial_value;
let return_rate = safe_mul(gain, 10000) / initial_value;
let apy = safe_mul(return_rate, 365) / days;
return min(apy, 10000) as u16;
}