Skip to content

Commit ae1d514

Browse files
authored
refactor: Turn pow into a generic function (#198)
<!--- Please provide a general summary of your changes in the title above --> ## Pull Request type <!-- Please try to limit your pull request to one type; submit multiple pull requests if needed. --> Please check the type of change your PR introduces: - [ ] Bugfix - [ ] Feature - [ ] Code style update (formatting, renaming) - [x] Refactoring (no functional changes, no API changes) - [ ] Build-related changes - [ ] Documentation content changes - [ ] Other (please describe): ## What is the current behavior? <!-- Please describe the current behavior that you are modifying, or link to a relevant issue. --> Issue Number: N/A ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> - - - ## Does this introduce a breaking change? - [ ] Yes - [ ] No <!-- If this does introduce a breaking change, please describe the impact and migration path for existing applications below. --> ## Other information <!-- Any other information that is important to this PR, such as screenshots of how the component looks before and after the change. -->
1 parent 1965197 commit ae1d514

2 files changed

Lines changed: 162 additions & 243 deletions

File tree

src/math/src/lib.cairo

Lines changed: 22 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,18 @@ use debug::PrintTrait;
1111
/// * `base` - The number to raise.
1212
/// * `exp` - The exponent.
1313
/// # Returns
14-
/// * `u128` - The result of base raised to the power of exp.
15-
fn pow(base: u128, exp: u128) -> u128 {
16-
if exp == 0 {
17-
1
18-
} else if exp == 1 {
14+
/// * `T` - The result of base raised to the power of exp.
15+
fn pow<T, +Sub<T>, +Mul<T>, +Div<T>, +Rem<T>, +PartialEq<T>, +Into<u8, T>, +Drop<T>, +Copy<T>>(
16+
base: T, exp: T
17+
) -> T {
18+
if exp == 0_u8.into() {
19+
1_u8.into()
20+
} else if exp == 1_u8.into() {
1921
base
20-
} else if exp % 2 == 0 {
21-
pow(base * base, exp / 2)
22+
} else if exp % 2_u8.into() == 0_u8.into() {
23+
pow(base * base, exp / 2_u8.into())
2224
} else {
23-
base * pow(base * base, (exp - 1) / 2)
25+
base * pow(base * base, exp / 2_u8.into())
2426
}
2527
}
2628

@@ -43,142 +45,69 @@ fn count_digits_of_base(mut num: u128, base: u128) -> u128 {
4345
}
4446

4547
trait BitShift<T> {
46-
fn fpow(x: T, n: T) -> T;
4748
fn shl(x: T, n: T) -> T;
4849
fn shr(x: T, n: T) -> T;
4950
}
5051

5152
impl U8BitShift of BitShift<u8> {
52-
fn fpow(x: u8, n: u8) -> u8 {
53-
if n == 0 {
54-
1
55-
} else if n == 1 {
56-
x
57-
} else if (n & 1) == 1 {
58-
x * BitShift::fpow(x * x, n / 2)
59-
} else {
60-
BitShift::fpow(x * x, n / 2)
61-
}
62-
}
6353
fn shl(x: u8, n: u8) -> u8 {
64-
(u8_wide_mul(x, BitShift::fpow(2, n)) & BoundedInt::<u8>::max().into()).try_into().unwrap()
54+
(u8_wide_mul(x, pow(2, n)) & BoundedInt::<u8>::max().into()).try_into().unwrap()
6555
}
6656

6757
fn shr(x: u8, n: u8) -> u8 {
68-
x / BitShift::fpow(2, n)
58+
x / pow(2, n)
6959
}
7060
}
7161

7262
impl U16BitShift of BitShift<u16> {
73-
fn fpow(x: u16, n: u16) -> u16 {
74-
if n == 0 {
75-
1
76-
} else if n == 1 {
77-
x
78-
} else if (n & 1) == 1 {
79-
x * BitShift::fpow(x * x, n / 2)
80-
} else {
81-
BitShift::fpow(x * x, n / 2)
82-
}
83-
}
8463
fn shl(x: u16, n: u16) -> u16 {
85-
(u16_wide_mul(x, BitShift::fpow(2, n)) & BoundedInt::<u16>::max().into())
86-
.try_into()
87-
.unwrap()
64+
(u16_wide_mul(x, pow(2, n)) & BoundedInt::<u16>::max().into()).try_into().unwrap()
8865
}
8966

9067
fn shr(x: u16, n: u16) -> u16 {
91-
x / BitShift::fpow(2, n)
68+
x / pow(2, n)
9269
}
9370
}
9471

9572
impl U32BitShift of BitShift<u32> {
96-
fn fpow(x: u32, n: u32) -> u32 {
97-
if n == 0 {
98-
1
99-
} else if n == 1 {
100-
x
101-
} else if (n & 1) == 1 {
102-
x * BitShift::fpow(x * x, n / 2)
103-
} else {
104-
BitShift::fpow(x * x, n / 2)
105-
}
106-
}
10773
fn shl(x: u32, n: u32) -> u32 {
108-
(u32_wide_mul(x, BitShift::fpow(2, n)) & BoundedInt::<u32>::max().into())
109-
.try_into()
110-
.unwrap()
74+
(u32_wide_mul(x, pow(2, n)) & BoundedInt::<u32>::max().into()).try_into().unwrap()
11175
}
11276

11377
fn shr(x: u32, n: u32) -> u32 {
114-
x / BitShift::fpow(2, n)
78+
x / pow(2, n)
11579
}
11680
}
11781

11882
impl U64BitShift of BitShift<u64> {
119-
fn fpow(x: u64, n: u64) -> u64 {
120-
if n == 0 {
121-
1
122-
} else if n == 1 {
123-
x
124-
} else if (n & 1) == 1 {
125-
x * BitShift::fpow(x * x, n / 2)
126-
} else {
127-
BitShift::fpow(x * x, n / 2)
128-
}
129-
}
13083
fn shl(x: u64, n: u64) -> u64 {
131-
(u64_wide_mul(x, BitShift::fpow(2, n)) & BoundedInt::<u64>::max().into())
132-
.try_into()
133-
.unwrap()
84+
(u64_wide_mul(x, pow(2, n)) & BoundedInt::<u64>::max().into()).try_into().unwrap()
13485
}
13586

13687
fn shr(x: u64, n: u64) -> u64 {
137-
x / BitShift::fpow(2, n)
88+
x / pow(2, n)
13889
}
13990
}
14091

14192
impl U128BitShift of BitShift<u128> {
142-
fn fpow(x: u128, n: u128) -> u128 {
143-
if n == 0 {
144-
1
145-
} else if n == 1 {
146-
x
147-
} else if (n & 1) == 1 {
148-
x * BitShift::fpow(x * x, n / 2)
149-
} else {
150-
BitShift::fpow(x * x, n / 2)
151-
}
152-
}
15393
fn shl(x: u128, n: u128) -> u128 {
154-
let (_, bottom_word) = u128_wide_mul(x, BitShift::fpow(2, n));
94+
let (_, bottom_word) = u128_wide_mul(x, pow(2, n));
15595
bottom_word
15696
}
15797

15898
fn shr(x: u128, n: u128) -> u128 {
159-
x / BitShift::fpow(2, n)
99+
x / pow(2, n)
160100
}
161101
}
162102

163103
impl U256BitShift of BitShift<u256> {
164-
fn fpow(x: u256, n: u256) -> u256 {
165-
if n == 0 {
166-
1
167-
} else if n == 1 {
168-
x
169-
} else if (n & 1) == 1 {
170-
x * BitShift::fpow(x * x, n / 2)
171-
} else {
172-
BitShift::fpow(x * x, n / 2)
173-
}
174-
}
175104
fn shl(x: u256, n: u256) -> u256 {
176-
let (r, _) = u256_overflow_mul(x, BitShift::fpow(2, n));
105+
let (r, _) = u256_overflow_mul(x, pow(2, n));
177106
r
178107
}
179108

180109
fn shr(x: u256, n: u256) -> u256 {
181-
x / BitShift::fpow(2, n)
110+
x / pow(2, n)
182111
}
183112
}
184113

0 commit comments

Comments
 (0)