Skip to content

Commit 69653ed

Browse files
authored
Clean up addition/subtraction code (#87)
1 parent 86973fa commit 69653ed

File tree

11 files changed

+1434
-1405
lines changed

11 files changed

+1434
-1405
lines changed

arbi/src/add.rs

Lines changed: 0 additions & 1399 deletions
This file was deleted.

arbi/src/comparisons.rs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
/*
2-
Copyright 2024 Owain Davies
2+
Copyright 2024-2025 Owain Davies
33
SPDX-License-Identifier: Apache-2.0 OR MIT
44
*/
55

66
use crate::Arbi;
7+
use crate::Digit;
78
use core::cmp::Ordering;
89

910
impl Ord for Arbi {
@@ -26,6 +27,56 @@ impl PartialEq for Arbi {
2627

2728
impl Eq for Arbi {}
2829

30+
#[inline(always)]
31+
pub(crate) fn s_size(digits: &[Digit]) -> usize {
32+
let mut len = digits.len();
33+
while len > 0 && digits[len - 1] == 0 {
34+
len -= 1;
35+
}
36+
len
37+
}
38+
39+
pub(crate) fn s_cmp_impl(
40+
a: &[Digit],
41+
b: &[Digit],
42+
assume_normalized: bool,
43+
) -> Ordering {
44+
let (a_size, b_size) = if assume_normalized {
45+
(a.len(), b.len())
46+
} else {
47+
(s_size(a), s_size(b))
48+
};
49+
match a_size.cmp(&b_size) {
50+
Ordering::Equal => {
51+
for i in (0..a_size).rev() {
52+
match a[i].cmp(&b[i]) {
53+
Ordering::Equal => continue,
54+
other => return other,
55+
}
56+
}
57+
Ordering::Equal
58+
}
59+
other => other,
60+
}
61+
}
62+
63+
#[allow(dead_code)]
64+
pub(crate) fn s_cmp(a: &[Digit], b: &[Digit]) -> Ordering {
65+
s_cmp_impl(a, b, false)
66+
}
67+
68+
pub(crate) fn s_cmp_normalized(a: &[Digit], b: &[Digit]) -> Ordering {
69+
debug_assert!(
70+
a.is_empty() || a.last() != Some(&0),
71+
"slice a not normalized"
72+
);
73+
debug_assert!(
74+
b.is_empty() || b.last() != Some(&0),
75+
"slice b not normalized"
76+
);
77+
s_cmp_impl(a, b, true)
78+
}
79+
2980
impl Arbi {
3081
// Assumes x, y >= 0
3182
pub(crate) fn cmp_abs(x: &Self, y: &Self) -> Ordering {

arbi/src/division.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
/*
2-
Copyright 2024 Owain Davies
2+
Copyright 2024-2025 Owain Davies
33
SPDX-License-Identifier: Apache-2.0 OR MIT
44
*/
55

66
use crate::util::to_digits::{length_digits, ToDigits};
7+
use crate::util::ArbiLikeView;
78
use crate::{Arbi, BitCount, DDigit, Digit, SDDigit};
89
use core::ops::{Div, DivAssign, Rem, RemAssign};
910

@@ -72,8 +73,8 @@ impl Arbi {
7273
if Arbi::cmp_abs(r, v) != core::cmp::Ordering::Less {
7374
// (3)(III)(a)
7475
// *r = &(*r) - v;
75-
Arbi::sub_abs_inplace(r, v, false);
76-
// (3)(III)(b)
76+
r.isub_with_arbi_like_view(v.into()); // previously, Arbi::sub_abs_inplace(r, v, false); r = |r| - |v|
77+
// (3)(III)(b)
7778
q.set_bit(i);
7879
}
7980
}
@@ -265,7 +266,10 @@ impl Arbi {
265266
q.negate_mut();
266267
*q -= 1;
267268
r.negate_mut();
268-
r.dadd_inplace(d, d_sign == -1); // *r += d;
269+
r.iadd_with_arbi_like_view(ArbiLikeView {
270+
vec: d,
271+
neg: d_sign == -1,
272+
}); // *r += d;
269273
}
270274
}
271275
_ => {}

arbi/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ extern crate test;
1515

1616
use alloc::vec::Vec;
1717

18-
mod add;
1918
mod assign;
2019
mod assign_double;
2120
mod assign_integral;

arbi/src/ops/add/arbi_x_arbi.rs

Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
/*
2+
Copyright 2025 Owain Davies
3+
SPDX-License-Identifier: Apache-2.0 OR MIT
4+
*/
5+
6+
use crate::Arbi;
7+
use core::ops::{Add, AddAssign, Sub, SubAssign};
8+
9+
/// `a += &b`
10+
///
11+
/// # Examples
12+
/// ```
13+
/// use arbi::Arbi;
14+
/// let mut a = Arbi::from(-1234567);
15+
/// let b = Arbi::from(-123456);
16+
/// a += &b;
17+
/// assert_eq!(a, -1358023);
18+
/// ```
19+
impl<'a> AddAssign<&'a Arbi> for Arbi {
20+
fn add_assign(&mut self, other: &'a Arbi) {
21+
self.iadd(other);
22+
}
23+
}
24+
25+
/// `a += b`
26+
///
27+
/// # Examples
28+
/// ```
29+
/// use arbi::Arbi;
30+
/// let mut a = Arbi::from(-1234567);
31+
/// let b = Arbi::from(-123456);
32+
/// a += b;
33+
/// assert_eq!(a, -1358023);
34+
/// ```
35+
impl AddAssign<Arbi> for Arbi {
36+
fn add_assign(&mut self, mut other: Self) {
37+
if other.capacity() > self.capacity() {
38+
core::mem::swap(self, &mut other);
39+
}
40+
*self += &other;
41+
}
42+
}
43+
44+
/// `a + b`
45+
///
46+
/// # Examples
47+
/// ```
48+
/// use arbi::Arbi;
49+
/// let a = Arbi::from(-1234567);
50+
/// let b = Arbi::from(-123456);
51+
/// let c = a + b;
52+
/// assert_eq!(c, -1358023);
53+
/// ```
54+
impl Add<Arbi> for Arbi {
55+
type Output = Self;
56+
fn add(mut self, other: Self) -> Self {
57+
self += other;
58+
self
59+
}
60+
}
61+
62+
/// `a + &b`
63+
///
64+
/// # Examples
65+
/// ```
66+
/// use arbi::Arbi;
67+
/// let a = Arbi::from(-1234567);
68+
/// let b = Arbi::from(-123456);
69+
/// let c = a + &b;
70+
/// assert_eq!(c, -1358023);
71+
/// ```
72+
impl<'a> Add<&'a Arbi> for Arbi {
73+
type Output = Self;
74+
fn add(mut self, other: &'a Arbi) -> Self {
75+
self += other;
76+
self
77+
}
78+
}
79+
80+
/// `&a + b`
81+
///
82+
/// # Examples
83+
/// ```
84+
/// use arbi::{Arbi, Digit};
85+
///
86+
/// let a = Arbi::from(-123456);
87+
/// let b = Arbi::from(1234567);
88+
/// let b_cap = b.capacity();
89+
/// let c = &a + b; // In this case, no memory allocation (b's memory is
90+
/// // used.
91+
/// assert_eq!(c, 1111111);
92+
/// assert_eq!(c.capacity(), b_cap);
93+
///
94+
/// let a = Arbi::from(-(Digit::MAX as i128));
95+
/// let b = Arbi::from(-1234567);
96+
/// let b_cap = b.capacity();
97+
/// let c = &a + b; // In this case, memory allocation may or may not occur,
98+
/// // depending on b's capacity.
99+
/// assert!(c.capacity() >= b_cap);
100+
/// ```
101+
impl Add<Arbi> for &Arbi {
102+
type Output = Arbi;
103+
fn add(self, mut other: Arbi) -> Arbi {
104+
other += self;
105+
other
106+
}
107+
}
108+
109+
/// `&a + &b`
110+
///
111+
/// # Examples
112+
/// ```
113+
/// use arbi::Arbi;
114+
/// let a = Arbi::from(-1234567);
115+
/// let b = Arbi::from(-123456);
116+
/// let c = &a + &b;
117+
/// assert_eq!(c, -1358023);
118+
/// ```
119+
impl<'b> Add<&'b Arbi> for &Arbi {
120+
type Output = Arbi;
121+
fn add(self, other: &'b Arbi) -> Arbi {
122+
let mut ret;
123+
if self.size() <= other.size() {
124+
ret = Arbi::with_capacity_and_copy(other.size() + 1, other);
125+
ret += self;
126+
} else {
127+
ret = Arbi::with_capacity_and_copy(self.size() + 1, self);
128+
ret += other;
129+
}
130+
ret
131+
}
132+
}
133+
134+
/// `a -= &b`
135+
///
136+
/// # Examples
137+
/// ```
138+
/// use arbi::Arbi;
139+
/// let mut a = Arbi::from(-1234567);
140+
/// let b = Arbi::from(-123456);
141+
/// a -= &b;
142+
/// assert_eq!(a, -1111111);
143+
/// ```
144+
impl<'a> SubAssign<&'a Arbi> for Arbi {
145+
fn sub_assign(&mut self, other: &'a Arbi) {
146+
self.isub(other);
147+
}
148+
}
149+
150+
/// `a -= b`
151+
///
152+
/// # Examples
153+
/// ```
154+
/// use arbi::Arbi;
155+
/// let mut a = Arbi::from(-1234567);
156+
/// let b = Arbi::from(-123456);
157+
/// a -= b;
158+
/// assert_eq!(a, -1111111);
159+
/// ```
160+
impl SubAssign for Arbi {
161+
fn sub_assign(&mut self, mut other: Self) {
162+
if self.capacity() >= other.capacity() {
163+
*self -= &other;
164+
} else {
165+
// -(other - self) = self - other
166+
core::mem::swap(self, &mut other);
167+
*self -= &other;
168+
self.negate_mut();
169+
}
170+
}
171+
}
172+
173+
/// `a - b`
174+
///
175+
/// # Examples
176+
/// ```
177+
/// use arbi::Arbi;
178+
/// let a = Arbi::from(-1234567);
179+
/// let a_cap = a.capacity();
180+
/// let b = Arbi::from(-123456);
181+
/// let c = a - b; // no memory allocation
182+
/// assert_eq!(c, -1111111);
183+
/// assert_eq!(c.capacity(), a_cap);
184+
/// ```
185+
impl Sub<Arbi> for Arbi {
186+
type Output = Self;
187+
fn sub(mut self, other: Self) -> Self {
188+
self -= other;
189+
self
190+
}
191+
}
192+
193+
/// `a - &b`
194+
///
195+
/// # Examples
196+
/// ```
197+
/// use arbi::Arbi;
198+
/// let a = Arbi::from(-1234567);
199+
/// let a_cap = a.capacity();
200+
/// let b = Arbi::from(-123456);
201+
/// let c = a - &b; // no memory allocation
202+
/// assert_eq!(c, -1111111);
203+
/// assert_eq!(c.capacity(), a_cap);
204+
/// ```
205+
impl<'a> Sub<&'a Arbi> for Arbi {
206+
type Output = Self;
207+
fn sub(mut self, other: &'a Arbi) -> Self {
208+
self -= other;
209+
self
210+
}
211+
}
212+
213+
/// `&a - b`
214+
///
215+
/// # Examples
216+
/// ```
217+
/// use arbi::{Arbi, Digit};
218+
///
219+
/// let a = Arbi::from(1234567);
220+
/// let b = Arbi::from(123456);
221+
/// let b_cap = b.capacity();
222+
/// let c = &a - b; // In this case, no memory allocation (b's memory is
223+
/// // used.
224+
/// assert_eq!(c, 1111111);
225+
/// assert_eq!(c.capacity(), b_cap);
226+
///
227+
/// let a = Arbi::from(-(Digit::MAX as i128));
228+
/// let b = Arbi::from(-1234567);
229+
/// let b_cap = b.capacity();
230+
/// let c = &a - b; // In this case, no memory allocation
231+
/// assert_eq!(c.capacity(), b_cap);
232+
/// ```
233+
impl Sub<Arbi> for &Arbi {
234+
type Output = Arbi;
235+
fn sub(self, mut other: Arbi) -> Arbi {
236+
// a - b = -(b - a)
237+
other -= self;
238+
other.negate_mut();
239+
other
240+
}
241+
}
242+
243+
/// `&a - &b`
244+
///
245+
/// # Examples
246+
/// ```
247+
/// use arbi::Arbi;
248+
/// let a = Arbi::from(-1234567);
249+
/// let b = Arbi::from(-123456);
250+
/// let c = &a - &b; // memory allocation
251+
/// assert_eq!(c, -1111111);
252+
/// ```
253+
impl<'b> Sub<&'b Arbi> for &Arbi {
254+
type Output = Arbi;
255+
fn sub(self, other: &'b Arbi) -> Arbi {
256+
let mut ret;
257+
if self.size() <= other.size() {
258+
// -(other - self) = self - other
259+
ret = Arbi::with_capacity_and_copy(other.size(), other);
260+
ret -= self;
261+
ret.negate_mut();
262+
} else {
263+
ret = Arbi::with_capacity_and_copy(self.size(), self);
264+
ret -= other;
265+
}
266+
ret
267+
}
268+
}

0 commit comments

Comments
 (0)