Skip to content

Commit e712ed9

Browse files
committed
v0.5.1 upgrade whole lib into generic-type-based. API changed. more safer than before. update Cargo.toml
1 parent c37ab2a commit e712ed9

14 files changed

+280
-222
lines changed

Cargo.toml

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
[package]
22
name = "lib_xch"
3-
version = "0.4.0"
3+
version = "0.5.1"
44
authors = ["LEXUGE <LEXUGEyky@outlook.com>"]
55
description = "Crate xch-ceb's official lib"
66
license = "GPL-3.0"
77
repository = "https://github.com/LEXUGE/lib-xch-ceb"
88

99
[dependencies]
10-
lazy_static = "^1.x"
10+
lazy_static = "^1.0"
1111
regex = "^0.2"
12+
num-traits = "^0.2"

src/balancer_mod/frac_util.rs

+32-32
Original file line numberDiff line numberDiff line change
@@ -22,34 +22,34 @@ use super::math_methods::{gcd, lcm};
2222
use handler::ErrorCases::UndefinedFrac;
2323
use handler::ErrorCases;
2424
use public::Operator::{Abs, Add, Div, Mul, Sub};
25-
use public::safe_calc;
25+
use public::{safe_calc, CheckedType};
2626

27-
fn rfcd(a: &Frac, b: &Frac) -> Result<(i32, i32, i32), ErrorCases> {
27+
fn rfcd<T: CheckedType>(a: &Frac<T>, b: &Frac<T>) -> Result<(T, T, T), ErrorCases> {
2828
// reduction of fractions to a common denominator
2929
let d = lcm(a.denominator, b.denominator)?;
30-
let mut a_n = safe_calc(d, a.denominator, &Div)?;
31-
let mut b_n = safe_calc(d, b.denominator, &Div)?;
32-
a_n = safe_calc(a_n, a.numerator, &Mul)?;
33-
b_n = safe_calc(b_n, b.numerator, &Mul)?;
30+
let mut a_n = safe_calc(&d, &a.denominator, &Div)?;
31+
let mut b_n = safe_calc(&d, &b.denominator, &Div)?;
32+
a_n = safe_calc(&a_n, &a.numerator, &Mul)?;
33+
b_n = safe_calc(&b_n, &b.numerator, &Mul)?;
3434
Ok((a_n, b_n, d))
3535
}
3636

3737
#[derive(Clone, Copy)]
38-
pub struct Frac {
39-
pub numerator: i32,
40-
pub denominator: i32,
38+
pub struct Frac<T: CheckedType> {
39+
pub numerator: T,
40+
pub denominator: T,
4141
}
4242

43-
impl Frac {
44-
pub fn new(numerator: i32, denominator: i32) -> Self {
43+
impl<T: CheckedType> Frac<T> {
44+
pub fn new(numerator: T, denominator: T) -> Self {
4545
Self {
4646
numerator,
4747
denominator,
4848
}
4949
}
5050

5151
pub fn check(&self) -> Result<bool, ErrorCases> {
52-
if self.denominator == 0 {
52+
if self.denominator == T::zero() {
5353
Err(UndefinedFrac)
5454
} else {
5555
Ok(true)
@@ -60,31 +60,31 @@ impl Frac {
6060
self.check()?;
6161
let gcd = gcd(self.numerator, self.denominator)?;
6262
Ok(Self {
63-
numerator: safe_calc(self.numerator, gcd, &Div)?,
64-
denominator: safe_calc(self.denominator, gcd, &Div)?,
63+
numerator: safe_calc(&self.numerator, &gcd, &Div)?,
64+
denominator: safe_calc(&self.denominator, &gcd, &Div)?,
6565
})
6666
}
6767

6868
pub fn abs(&self) -> Result<Self, ErrorCases> {
6969
self.check()?;
7070
let mut tmp = Self {
71-
numerator: safe_calc(self.numerator, 0, &Abs)?,
72-
denominator: safe_calc(self.denominator, 0, &Abs)?,
71+
numerator: safe_calc(&self.numerator, &T::zero(), &Abs)?,
72+
denominator: safe_calc(&self.denominator, &T::zero(), &Abs)?,
7373
};
7474
tmp = tmp.simple()?;
7575
tmp.check()?;
7676
Ok(tmp)
7777
}
7878
}
7979

80-
impl ops::Add for Frac {
80+
impl<T: CheckedType> ops::Add for Frac<T> {
8181
type Output = Result<Self, ErrorCases>;
8282
fn add(self, b: Self) -> Result<Self, ErrorCases> {
8383
self.check()?;
8484
b.check()?;
8585
let (a_n, b_n, d) = rfcd(&self, &b)?;
8686
let mut tmp = Self {
87-
numerator: safe_calc(a_n, b_n, &Add)?,
87+
numerator: safe_calc(&a_n, &b_n, &Add)?,
8888
denominator: d,
8989
};
9090
tmp = tmp.simple()?;
@@ -93,14 +93,14 @@ impl ops::Add for Frac {
9393
}
9494
}
9595

96-
impl ops::Sub for Frac {
96+
impl<T: CheckedType> ops::Sub for Frac<T> {
9797
type Output = Result<Self, ErrorCases>;
9898
fn sub(self, b: Self) -> Result<Self, ErrorCases> {
9999
self.check()?;
100100
b.check()?;
101101
let (a_n, b_n, d) = rfcd(&self, &b)?;
102102
let mut tmp = Self {
103-
numerator: safe_calc(a_n, b_n, &Sub)?,
103+
numerator: safe_calc(&a_n, &b_n, &Sub)?,
104104
denominator: d,
105105
};
106106
tmp = tmp.simple()?;
@@ -109,37 +109,37 @@ impl ops::Sub for Frac {
109109
}
110110
}
111111

112-
impl ops::Mul for Frac {
112+
impl<T: CheckedType> ops::Mul for Frac<T> {
113113
type Output = Result<Self, ErrorCases>;
114114
fn mul(self, b: Self) -> Result<Self, ErrorCases> {
115115
self.check()?;
116116
b.check()?;
117117
let mut tmp = Self {
118-
numerator: safe_calc(self.numerator, b.numerator, &Mul)?,
119-
denominator: safe_calc(self.denominator, b.denominator, &Mul)?,
118+
numerator: safe_calc(&self.numerator, &b.numerator, &Mul)?,
119+
denominator: safe_calc(&self.denominator, &b.denominator, &Mul)?,
120120
};
121121
tmp = tmp.simple()?;
122122
tmp.check()?;
123123
Ok(tmp)
124124
}
125125
}
126126

127-
impl ops::Div for Frac {
127+
impl<T: CheckedType> ops::Div for Frac<T> {
128128
type Output = Result<Self, ErrorCases>;
129129
fn div(self, b: Self) -> Result<Self, ErrorCases> {
130130
self.check()?;
131131
b.check()?;
132132
let mut tmp = Self {
133-
numerator: safe_calc(self.numerator, b.denominator, &Mul)?,
134-
denominator: safe_calc(self.denominator, b.numerator, &Mul)?,
133+
numerator: safe_calc(&self.numerator, &b.denominator, &Mul)?,
134+
denominator: safe_calc(&self.denominator, &b.numerator, &Mul)?,
135135
};
136136
tmp = tmp.simple()?;
137137
tmp.check()?;
138138
Ok(tmp)
139139
}
140140
}
141141

142-
impl PartialOrd for Frac {
142+
impl<T: CheckedType> PartialOrd for Frac<T> {
143143
fn partial_cmp(&self, b: &Self) -> Option<Ordering> {
144144
if self.check().is_err() || b.check().is_err() {
145145
None
@@ -148,19 +148,19 @@ impl PartialOrd for Frac {
148148
Ok(s) => s,
149149
Err(e) => panic!("[Ord] `lcm` Err: {:?}", e),
150150
};
151-
let mut a_n = match safe_calc(d, self.denominator, &Div) {
151+
let mut a_n = match safe_calc(&d, &self.denominator, &Div) {
152152
Ok(s) => s,
153153
Err(e) => panic!("[Ord] Err: {:?}", e),
154154
};
155-
let mut b_n = match safe_calc(d, b.denominator, &Div) {
155+
let mut b_n = match safe_calc(&d, &b.denominator, &Div) {
156156
Ok(s) => s,
157157
Err(e) => panic!("[Ord] Err: {:?}", e),
158158
};
159-
a_n = match safe_calc(a_n, self.numerator, &Mul) {
159+
a_n = match safe_calc(&a_n, &self.numerator, &Mul) {
160160
Ok(s) => s,
161161
Err(e) => panic!("[Ord] Err: {:?}", e),
162162
};
163-
b_n = match safe_calc(b_n, b.numerator, &Mul) {
163+
b_n = match safe_calc(&b_n, &b.numerator, &Mul) {
164164
Ok(s) => s,
165165
Err(e) => panic!("[Ord] Err: {:?}", e),
166166
};
@@ -169,7 +169,7 @@ impl PartialOrd for Frac {
169169
}
170170
}
171171

172-
impl PartialEq for Frac {
172+
impl<T: CheckedType> PartialEq for Frac<T> {
173173
fn eq(&self, b: &Self) -> bool {
174174
if b.check().is_err() || self.check().is_err() {
175175
panic!("[Eq] UndefinedFrac")

src/balancer_mod/gauss_eliminate.rs

+18-16
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,22 @@
1616
// Overall: This is the source code of the AlphaForce Balancer.
1717

1818
use std::collections::HashMap;
19+
// inside uses
1920
use handler::{ErrorCases, ResultHandler};
2021
use handler::ErrorCases::Unsolvable;
2122
use handler::WarnCases::{FreeVariablesDetected, NoWarn};
2223
use super::frac_util::Frac;
24+
use public::CheckedType;
2325

24-
pub struct GaussianElimination {
25-
matrix_a: Vec<Vec<Frac>>, // A n*n matrix.
26-
matrix_b: Vec<Frac>, // A n*1 matrix.
26+
pub struct GaussianElimination<T: CheckedType> {
27+
matrix_a: Vec<Vec<Frac<T>>>, // A n*n matrix.
28+
matrix_b: Vec<Frac<T>>, // A n*1 matrix.
2729
n: usize,
2830
m: usize,
2931
}
3032

31-
impl GaussianElimination {
32-
pub fn new(matrix_a: Vec<Vec<Frac>>, matrix_b: Vec<Frac>, n: usize, m: usize) -> Self {
33+
impl<T: CheckedType> GaussianElimination<T> {
34+
pub fn new(matrix_a: Vec<Vec<Frac<T>>>, matrix_b: Vec<Frac<T>>, n: usize, m: usize) -> Self {
3335
// Create a GaussianElimination Solution.
3436
Self {
3537
matrix_a,
@@ -39,7 +41,7 @@ impl GaussianElimination {
3941
}
4042
}
4143

42-
pub fn solve(&mut self) -> Result<ResultHandler<Vec<Frac>>, ErrorCases> {
44+
pub fn solve(&mut self) -> Result<ResultHandler<Vec<Frac<T>>>, ErrorCases> {
4345
// The Gaussian-Jordan Algorithm
4446
for i in 0..self.n {
4547
let leftmosti = match self.get_leftmost_row(i) {
@@ -54,7 +56,7 @@ impl GaussianElimination {
5456
None => continue,
5557
};
5658
let maxi = self.get_max_abs_row(i, j)?;
57-
if self.matrix_a[maxi][j].numerator != 0 {
59+
if self.matrix_a[maxi][j].numerator != T::zero() {
5860
self.matrix_a.swap(i, maxi);
5961
self.matrix_b.swap(i, maxi); // swap row i and maxi in matrix_a and matrix_b
6062
{
@@ -85,19 +87,19 @@ impl GaussianElimination {
8587
self.matrix_b[u] = (self.matrix_b[u] - v[self.m])?;
8688
}
8789
} // RREF
88-
let mut ans: Vec<Frac> = vec![Frac::new(0, 1); self.m];
90+
let mut ans: Vec<Frac<T>> = vec![Frac::new(T::zero(), T::one()); self.m];
8991
let pivots = self.check()?;
9092
let mut free_variable = false;
9193
for i in (0..self.m).rev() {
9294
if pivots.contains_key(&i) {
93-
let mut sum = Frac::new(0, 1);
95+
let mut sum = Frac::new(T::zero(), T::one());
9496
for (k, item) in ans.iter().enumerate().take(self.m).skip(i + 1) {
9597
sum = (sum + (self.matrix_a[pivots[&i]][k] * (*item))?)?;
9698
}
9799
ans[i] = ((self.matrix_b[pivots[&i]] - sum)? / self.matrix_a[pivots[&i]][i])?;
98100
} else {
99101
free_variable = true;
100-
ans[i] = Frac::new(1, 1); // set all free variables = 1/1.
102+
ans[i] = Frac::new(T::one(), T::one()); // set all free variables = 1/1.
101103
}
102104
}
103105
Ok(ResultHandler {
@@ -116,8 +118,8 @@ impl GaussianElimination {
116118
if self.get_pivot(i).is_some() {
117119
pivots.insert(self.get_pivot(i).unwrap(), i); // safe unwrap
118120
}
119-
if self.matrix_a[i] == vec![Frac::new(0, 1); self.n + 1]
120-
&& self.matrix_b[i] != Frac::new(0, 1)
121+
if self.matrix_a[i] == vec![Frac::new(T::zero(), T::one()); self.n + 1]
122+
&& self.matrix_b[i] != Frac::new(T::zero(), T::one())
121123
{
122124
return Err(Unsolvable);
123125
}
@@ -127,7 +129,7 @@ impl GaussianElimination {
127129

128130
fn get_pivot(&self, row: usize) -> Option<usize> {
129131
for column in 0..self.m {
130-
if self.matrix_a[row][column] != Frac::new(0, 1) {
132+
if self.matrix_a[row][column] != Frac::new(T::zero(), T::one()) {
131133
return Some(column);
132134
}
133135
}
@@ -162,16 +164,16 @@ impl GaussianElimination {
162164
}
163165
}
164166

165-
fn mul_row(&self, row: usize, multiplicator: Frac) -> Result<Vec<Frac>, ErrorCases> {
166-
let mut v: Vec<Frac> = Vec::new();
167+
fn mul_row(&self, row: usize, multiplicator: Frac<T>) -> Result<Vec<Frac<T>>, ErrorCases> {
168+
let mut v: Vec<Frac<T>> = Vec::new();
167169
for column in 0..self.m {
168170
v.push((self.matrix_a[row][column] * multiplicator)?);
169171
}
170172
v.push((self.matrix_b[row] * multiplicator)?);
171173
Ok(v)
172174
}
173175

174-
fn divide_row(&mut self, row: usize, divisor: Frac) -> Result<bool, ErrorCases> {
176+
fn divide_row(&mut self, row: usize, divisor: Frac<T>) -> Result<bool, ErrorCases> {
175177
for column in 0..self.m {
176178
self.matrix_a[row][column] = (self.matrix_a[row][column] / divisor)?;
177179
}

src/balancer_mod/math_methods.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,27 @@
1515

1616
// Overall: This is the source code of the AlphaForce Balancer.
1717

18+
// inside uses
1819
use handler::ErrorCases;
19-
use public::{safe_calc, Operator};
20+
use public::{safe_calc, CheckedType, Operator};
2021

21-
pub fn gcd(mut a: i32, mut b: i32) -> Result<i32, ErrorCases> {
22-
let mut t: i32;
23-
while b != 0 {
22+
pub fn gcd<T: CheckedType + PartialEq>(mut a: T, mut b: T) -> Result<T, ErrorCases> {
23+
let mut t: T;
24+
while b != T::zero() {
2425
t = b;
25-
b = safe_calc(a, b, &Operator::Rem)?;
26+
b = safe_calc(&a, &b, &Operator::Rem)?;
2627
a = t;
2728
}
2829
Ok(a)
2930
}
3031

31-
pub fn lcm(a: i32, b: i32) -> Result<i32, ErrorCases> {
32-
let a_b = safe_calc(a, b, &Operator::Mul)?;
33-
safe_calc(a_b, gcd(a, b)?, &Operator::Div)
32+
pub fn lcm<T: CheckedType>(a: T, b: T) -> Result<T, ErrorCases> {
33+
let a_b = safe_calc(&a, &b, &Operator::Mul)?;
34+
safe_calc(&a_b, &gcd(a, b)?, &Operator::Div)
3435
}
3536

36-
pub fn nlcm(v: Vec<i32>) -> Result<i32, ErrorCases> {
37-
let mut ans: i32 = 1;
37+
pub fn nlcm<T: CheckedType>(v: Vec<T>) -> Result<T, ErrorCases> {
38+
let mut ans: T = T::one();
3839
for i in v {
3940
ans = lcm(ans, i)?;
4041
}

0 commit comments

Comments
 (0)