Skip to content

Commit c90ab86

Browse files
authored
Convert functions for u16 (#36)
* added convert functions for u16 * typo
1 parent 276a10e commit c90ab86

6 files changed

Lines changed: 345 additions & 10 deletions

File tree

simf/lib/u16/convert.simf

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/// Widening uint conversions
2+
3+
/// Converts u16 to u32
4+
pub fn u16_to_u32(a: u16) -> u32 {
5+
jet::left_pad_low_16_32(a)
6+
}
7+
8+
/// Converts u16 to u64
9+
pub fn u16_to_u64(a: u16) -> u64 {
10+
jet::left_pad_low_16_64(a)
11+
}
12+
13+
/// Converts u16 to u128
14+
pub fn u16_to_u128(a: u16) -> u128 {
15+
let a_u64: u64 = u16_to_u64(a);
16+
17+
<(u64, u64)>::into((0, a_u64))
18+
}
19+
20+
/// Converts u16 to u256
21+
pub fn u16_to_u256(a: u16) -> u256 {
22+
let a_u128: u128 = u16_to_u128(a);
23+
24+
<(u128, u128)>::into((0, a_u128))
25+
}
26+
27+
/// Splitting uint conversions
28+
29+
/// Splits u16 into two u8
30+
pub fn split_u16_to_u8(a: u16) -> (u8, u8) {
31+
<u16>::into(a)
32+
}
33+
34+
/// Narrowing uint conversions
35+
36+
/// Converts u16 into u1.
37+
/// Panics if the value does not fit in u1
38+
pub fn safe_u16_to_u1(a: u16) -> u1 {
39+
let u1_max: u16 = jet::left_pad_low_1_16(jet::high_1());
40+
41+
assert!(jet::le_16(a, u1_max));
42+
43+
jet::rightmost_16_1(a)
44+
}
45+
46+
/// Converts u16 into u8.
47+
/// Panics if the value does not fit in u8
48+
pub fn safe_u16_to_u8(a: u16) -> u8 {
49+
let u8_max: u16 = jet::left_pad_low_8_16(jet::high_8());
50+
51+
assert!(jet::le_16(a, u8_max));
52+
53+
jet::rightmost_16_8(a)
54+
}

simf/u16_convert_test.simf

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
use crate::lib::u16::convert::{
2+
u16_to_u32,
3+
u16_to_u64,
4+
u16_to_u128,
5+
u16_to_u256,
6+
split_u16_to_u8,
7+
safe_u16_to_u1,
8+
safe_u16_to_u8
9+
};
10+
use crate::lib::u128::eq_128;
11+
use crate::lib::asserts::{assert_eq_1, assert_eq_8};
12+
use crate::helper::if_test_this_function;
13+
14+
fn main() {
15+
let fn_idx: u8 = witness::FUNCTION_INDEX;
16+
17+
let a: u16 = witness::FIRST_ARG;
18+
19+
let expected: u256 = witness::EXPECTED;
20+
21+
match if_test_this_function(0, fn_idx) {
22+
true => {
23+
let (_, _, _, expected): (u64, u64, u64, u64) = <u256>::into(expected);
24+
let (_, expected): (u32, u32) = <u64>::into(expected);
25+
26+
assert!(jet::eq_32(u16_to_u32(a), expected));
27+
},
28+
false => {},
29+
};
30+
31+
match if_test_this_function(1, fn_idx) {
32+
true => {
33+
let (_, _, _, expected): (u64, u64, u64, u64) = <u256>::into(expected);
34+
35+
assert!(jet::eq_64(u16_to_u64(a), expected));
36+
},
37+
false => {},
38+
};
39+
40+
match if_test_this_function(2, fn_idx) {
41+
true => {
42+
let (_, expected): (u128, u128) = <u256>::into(expected);
43+
44+
assert!(eq_128(u16_to_u128(a), expected));
45+
},
46+
false => {},
47+
};
48+
49+
match if_test_this_function(3, fn_idx) {
50+
true => {
51+
assert!(jet::eq_256(u16_to_u256(a), expected));
52+
},
53+
false => {},
54+
};
55+
56+
match if_test_this_function(4, fn_idx) {
57+
true => {
58+
let (a1, a0): (u8, u8) = split_u16_to_u8(a);
59+
60+
let (_, _, _, expected): (u64, u64, u64, u64) = <u256>::into(expected);
61+
let expected: u16 = jet::rightmost_64_16(expected);
62+
let (expected1, expected0): (u8, u8) = <u16>::into(expected);
63+
64+
assert_eq_8(a1, expected1);
65+
assert_eq_8(a0, expected0);
66+
},
67+
false => {},
68+
};
69+
70+
match if_test_this_function(5, fn_idx) {
71+
true => {
72+
let (_, _, _, expected): (u64, u64, u64, u64) = <u256>::into(expected);
73+
let expected: u1 = jet::rightmost_64_1(expected);
74+
75+
assert_eq_1(safe_u16_to_u1(a), expected);
76+
},
77+
false => {},
78+
};
79+
80+
match if_test_this_function(6, fn_idx) {
81+
true => {
82+
let (_, _, _, expected): (u64, u64, u64, u64) = <u256>::into(expected);
83+
let expected: u8 = jet::rightmost_64_8(expected);
84+
85+
assert_eq_8(safe_u16_to_u8(a), expected);
86+
},
87+
false => {},
88+
};
89+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::lib::u16::{checked_add_16, safe_add_16, checked_sub_16, safe_sub_16, checked_mul_16, safe_mul_16, checked_div_16, safe_div_16, gt_16, ge_16};
1+
use crate::lib::u16::math::{checked_add_16, safe_add_16, checked_sub_16, safe_sub_16, checked_mul_16, safe_mul_16, checked_div_16, safe_div_16, gt_16, ge_16};
22
use crate::lib::asserts::{assert_none_16, assert_eq_16};
33
use crate::lib::binary::not;
44
use crate::helper::if_test_this_function;

tests/u16_convert_test.rs

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
mod common;
2+
3+
use primitive_types::U256;
4+
use rand::Rng;
5+
6+
use common::core::{Expect, run};
7+
8+
use simplicityhl_std::artifacts::u16_convert_test::U16ConvertTestProgram;
9+
use simplicityhl_std::artifacts::u16_convert_test::derived_u16_convert_test::{
10+
U16ConvertTestArguments, U16ConvertTestWitness,
11+
};
12+
13+
enum FunctionToTest {
14+
U16ToU32,
15+
U16ToU64,
16+
U16ToU128,
17+
U16ToU256,
18+
SplitU16ToU8,
19+
SafeU16ToU1,
20+
SafeU16ToU8,
21+
}
22+
23+
#[inline]
24+
fn op(o: FunctionToTest) -> u8 {
25+
o as u8
26+
}
27+
28+
fn program() -> U16ConvertTestProgram {
29+
U16ConvertTestProgram::new(U16ConvertTestArguments {})
30+
}
31+
32+
fn build_witness(function: u8, a: u16, expected: [u8; 32]) -> U16ConvertTestWitness {
33+
U16ConvertTestWitness {
34+
function_index: function,
35+
first_arg: a,
36+
expected,
37+
}
38+
}
39+
40+
mod u16_convert_test {
41+
use super::*;
42+
43+
#[simplex::test]
44+
fn u16_convert_test_u16_to_u32(context: simplex::TestContext) -> anyhow::Result<()> {
45+
let a = rand::thread_rng().gen_range(0..=u16::MAX);
46+
47+
run(
48+
&context,
49+
program(),
50+
build_witness(
51+
op(FunctionToTest::U16ToU32),
52+
a,
53+
U256::from(a).to_big_endian(),
54+
),
55+
Expect::Ok,
56+
)
57+
}
58+
59+
#[simplex::test]
60+
fn u16_convert_test_u16_to_u64(context: simplex::TestContext) -> anyhow::Result<()> {
61+
let a = rand::thread_rng().gen_range(0..=u16::MAX);
62+
63+
run(
64+
&context,
65+
program(),
66+
build_witness(
67+
op(FunctionToTest::U16ToU64),
68+
a,
69+
U256::from(a).to_big_endian(),
70+
),
71+
Expect::Ok,
72+
)
73+
}
74+
75+
#[simplex::test]
76+
fn u16_convert_test_u16_to_u128(context: simplex::TestContext) -> anyhow::Result<()> {
77+
let a = rand::thread_rng().gen_range(0..=u16::MAX);
78+
79+
run(
80+
&context,
81+
program(),
82+
build_witness(
83+
op(FunctionToTest::U16ToU128),
84+
a,
85+
U256::from(a).to_big_endian(),
86+
),
87+
Expect::Ok,
88+
)
89+
}
90+
91+
#[simplex::test]
92+
fn u16_convert_test_u16_to_u256(context: simplex::TestContext) -> anyhow::Result<()> {
93+
let a = rand::thread_rng().gen_range(0..=u16::MAX);
94+
95+
run(
96+
&context,
97+
program(),
98+
build_witness(
99+
op(FunctionToTest::U16ToU256),
100+
a,
101+
U256::from(a).to_big_endian(),
102+
),
103+
Expect::Ok,
104+
)
105+
}
106+
107+
#[simplex::test]
108+
fn u16_convert_test_split_u16_to_u8(context: simplex::TestContext) -> anyhow::Result<()> {
109+
let a = rand::thread_rng().gen_range(0..=u16::MAX);
110+
111+
run(
112+
&context,
113+
program(),
114+
build_witness(
115+
op(FunctionToTest::SplitU16ToU8),
116+
a,
117+
U256::from(a).to_big_endian(),
118+
),
119+
Expect::Ok,
120+
)
121+
}
122+
123+
#[simplex::test]
124+
fn u16_convert_test_safe_u16_to_u1(context: simplex::TestContext) -> anyhow::Result<()> {
125+
let a = rand::thread_rng().gen_range(0..=1);
126+
127+
run(
128+
&context,
129+
program(),
130+
build_witness(
131+
op(FunctionToTest::SafeU16ToU1),
132+
a,
133+
U256::from(a).to_big_endian(),
134+
),
135+
Expect::Ok,
136+
)
137+
}
138+
139+
#[simplex::test]
140+
fn u16_convert_test_safe_u16_to_u1_overflow(
141+
context: simplex::TestContext,
142+
) -> anyhow::Result<()> {
143+
let a = rand::thread_rng().gen_range(2..=u16::MAX);
144+
145+
run(
146+
&context,
147+
program(),
148+
build_witness(
149+
op(FunctionToTest::SafeU16ToU1),
150+
a,
151+
U256::from(a).to_big_endian(),
152+
),
153+
Expect::AssertFailed,
154+
)
155+
}
156+
157+
#[simplex::test]
158+
fn u16_convert_test_safe_u16_to_u8(context: simplex::TestContext) -> anyhow::Result<()> {
159+
let a = rand::thread_rng().gen_range(0..=u8::MAX as u16);
160+
161+
run(
162+
&context,
163+
program(),
164+
build_witness(
165+
op(FunctionToTest::SafeU16ToU8),
166+
a,
167+
U256::from(a).to_big_endian(),
168+
),
169+
Expect::Ok,
170+
)
171+
}
172+
173+
#[simplex::test]
174+
fn u16_convert_test_safe_u16_to_u8_overflow(
175+
context: simplex::TestContext,
176+
) -> anyhow::Result<()> {
177+
let a = rand::thread_rng().gen_range(u8::MAX as u16 + 1..=u16::MAX);
178+
179+
run(
180+
&context,
181+
program(),
182+
build_witness(
183+
op(FunctionToTest::SafeU16ToU8),
184+
a,
185+
U256::from(a).to_big_endian(),
186+
),
187+
Expect::AssertFailed,
188+
)
189+
}
190+
}
Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,28 @@ mod common;
22

33
use common::uint::TestUint;
44

5-
use simplicityhl_std::artifacts::u16_test::U16TestProgram;
6-
use simplicityhl_std::artifacts::u16_test::derived_u16_test::{U16TestArguments, U16TestWitness};
5+
use simplicityhl_std::artifacts::u16_math_test::U16MathTestProgram;
6+
use simplicityhl_std::artifacts::u16_math_test::derived_u16_math_test::{
7+
U16MathTestArguments, U16MathTestWitness,
8+
};
79

810
// The only per-width code for the common operations.
911
impl TestUint for u16 {
10-
type Program = U16TestProgram;
11-
type Witness = U16TestWitness;
12+
type Program = U16MathTestProgram;
13+
type Witness = U16MathTestWitness;
1214

1315
const ZERO: u16 = 0;
1416
const ONE: u16 = 1;
1517
const MAX: u16 = u16::MAX;
1618
const HALF_MAX: u16 = u16::MAX / 2;
1719
const MUL_BOUND: u16 = 1 << 8; // 2^(16/2)
1820

19-
fn program() -> U16TestProgram {
20-
U16TestProgram::new(U16TestArguments {})
21+
fn program() -> U16MathTestProgram {
22+
U16MathTestProgram::new(U16MathTestArguments {})
2123
}
2224

23-
fn witness(op: u8, a: u16, b: u16, expected: Option<u16>) -> U16TestWitness {
24-
U16TestWitness {
25+
fn witness(op: u8, a: u16, b: u16, expected: Option<u16>) -> U16MathTestWitness {
26+
U16MathTestWitness {
2527
function_index: op,
2628
first_arg: a,
2729
second_arg: b,
@@ -30,7 +32,7 @@ impl TestUint for u16 {
3032
}
3133
}
3234

33-
mod u16_tests {
35+
mod u16_math_tests {
3436
use super::*;
3537

3638
// Stamps the 16 `#[simplex::test]` entry points for u16. Logic lives in common::uint.

0 commit comments

Comments
 (0)