Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion simf/lib/asserts.simf
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::lib::u128::eq_128;
use crate::lib::u128::bit::eq_128;

/// Asserts that two `u1` are equal
pub fn assert_eq_1(a: u1, b: u1) {
Expand Down
79 changes: 79 additions & 0 deletions simf/lib/u128/bit.simf
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use crate::lib::binary::and;

/// Bit logic

/// Bitwise AND of two 128-bit values
pub fn and_128(a: u128, b: u128) -> u128 {
let (a_high, a_low): (u64, u64) = <u128>::into(a);
let (b_high, b_low): (u64, u64) = <u128>::into(b);

<(u64, u64)>::into((jet::and_64(a_high, b_high), jet::and_64(a_low, b_low)))
}

/// Bitwise OR of two 128-bit values
pub fn or_128(a: u128, b: u128) -> u128 {
let (a_high, a_low): (u64, u64) = <u128>::into(a);
let (b_high, b_low): (u64, u64) = <u128>::into(b);

<(u64, u64)>::into((jet::or_64(a_high, b_high), jet::or_64(a_low, b_low)))
}

/// Checks if two 128-bit values are equal
pub fn eq_128(a: u128, b: u128) -> bool {
let (a_high, a_low): (u64, u64) = <u128>::into(a);
let (b_high, b_low): (u64, u64) = <u128>::into(b);

and(jet::eq_64(a_high, b_high), jet::eq_64(a_low, b_low))
}

/// Left-shift a 128-bit value by the given amount. Bits are filled with zeroes
pub fn left_shift_128(shift: u8, a: u128) -> u128 {
match jet::is_zero_8(shift) {
true => a,
false => {
let (a_high, a_low): (u64, u64) = <u128>::into(a);

match jet::lt_8(shift, 64) {
true => {
let (_, low_to_high_amount): (bool, u8) = jet::subtract_8(64, shift); // shift < 64
let shifted_bits: u64 = jet::right_shift_64(low_to_high_amount, a_low);

let res_high: u64 = jet::or_64(jet::left_shift_64(shift, a_high), shifted_bits);

<(u64, u64)>::into((res_high, jet::left_shift_64(shift, a_low)))
},
false => {
let (_, shift): (bool, u8) = jet::subtract_8(shift, 64); // shift >= 64

<(u64, u64)>::into((jet::left_shift_64(shift, a_low), 0))
}
}
}
}
}

/// Right-shift a 128-bit value by the given amount. Bits are filled with zeroes
pub fn right_shift_128(shift: u8, a: u128) -> u128 {
match jet::is_zero_8(shift) {
true => a,
false => {
let (a_high, a_low): (u64, u64) = <u128>::into(a);

match jet::lt_8(shift, 64) {
true => {
let (_, high_to_low_amount): (bool, u8) = jet::subtract_8(64, shift); // shift < 64
let shifted_bits: u64 = jet::left_shift_64(high_to_low_amount, a_high);

let res_low: u64 = jet::or_64(jet::right_shift_64(shift, a_low), shifted_bits);

<(u64, u64)>::into((jet::right_shift_64(shift, a_high), res_low))
},
false => {
let (_, shift): (bool, u8) = jet::subtract_8(shift, 64); // shift >= 64

<(u64, u64)>::into((0, jet::right_shift_64(shift, a_high)))
}
}
}
}
}
48 changes: 48 additions & 0 deletions simf/lib/u128/comparison.simf
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use crate::lib::binary::and;

/// Comparison operations

/// Checks if an integer is zero
pub fn is_zero_128(a: u128) -> bool {
let (a_high, a_low): (u64, u64) = <u128>::into(a);

and(jet::is_zero_64(a_high), jet::is_zero_64(a_low))
}

/// Checks if an integer is less than another integer
pub fn lt_128(a: u128, b: u128) -> bool {
let (a_high, a_low): (u64, u64) = <u128>::into(a);
let (b_high, b_low): (u64, u64) = <u128>::into(b);

match jet::lt_64(a_high, b_high) {
true => true,
false => match jet::eq_64(a_high, b_high) {
true => jet::lt_64(a_low, b_low),
false => false,
},
}
}

/// Checks if an integer is less than or equal to another integer
pub fn le_128(a: u128, b: u128) -> bool {
let (a_high, a_low): (u64, u64) = <u128>::into(a);
let (b_high, b_low): (u64, u64) = <u128>::into(b);

match jet::lt_64(a_high, b_high) {
true => true,
false => match jet::eq_64(a_high, b_high) {
true => jet::le_64(a_low, b_low),
false => false,
},
}
}

/// Check if an integer is greater than another integer
pub fn gt_128(a: u128, b: u128) -> bool {
lt_128(b, a)
}

/// Check if an integer is greater than or equal to another integer
pub fn ge_128(a: u128, b: u128) -> bool {
le_128(b, a)
}
94 changes: 94 additions & 0 deletions simf/lib/u128/convert.simf
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use crate::lib::u1::convert::u1_to_u128;
use crate::lib::u8::convert::u8_to_u128;
use crate::lib::u16::convert::u16_to_u128;
use crate::lib::u32::convert::u32_to_u128;
use crate::lib::u64::convert::u64_to_u128;
use crate::lib::u128::comparison::le_128;

/// Widening uint conversions

/// Converts u128 to u256
pub fn u128_to_u256(a: u128) -> u256 {
<(u128, u128)>::into((0, a))
}

/// Splitting uint conversions

/// Splits u128 into sixteen u8
pub fn split_u128_into_u8(
a: u128
) -> (u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8) {
<u128>::into(a)
}

/// Splits u128 into eight u16
pub fn split_u128_into_u16(a: u128) -> (u16, u16, u16, u16, u16, u16, u16, u16) {
<u128>::into(a)
}

/// Splits u128 into four u32
pub fn split_u128_into_u32(a: u128) -> (u32, u32, u32, u32) {
<u128>::into(a)
}

/// Splits u128 into two u64
pub fn split_u128_into_u64(a: u128) -> (u64, u64) {
<u128>::into(a)
}

/// Narrowing uint conversions

/// Converts u128 into u1.
/// Panics if the value does not fit in u1
pub fn safe_u128_to_u1(a: u128) -> u1 {
let u1_max: u128 = u1_to_u128(jet::high_1());
let (_, a_64): (u64, u64) = split_u128_into_u64(a);

assert!(le_128(a, u1_max));

jet::rightmost_64_1(a_64)
}

/// Converts u128 into u8.
/// Panics if the value does not fit in u8
pub fn safe_u128_to_u8(a: u128) -> u8 {
let u8_max: u128 = u8_to_u128(jet::high_8());
let (_, a_64): (u64, u64) = split_u128_into_u64(a);

assert!(le_128(a, u8_max));

jet::rightmost_64_8(a_64)
}

/// Converts u128 into u16.
/// Panics if the value does not fit in u16
pub fn safe_u128_to_u16(a: u128) -> u16 {
let u16_max: u128 = u16_to_u128(jet::high_16());
let (_, a_64): (u64, u64) = split_u128_into_u64(a);

assert!(le_128(a, u16_max));

jet::rightmost_64_16(a_64)
}

/// Converts u128 into u32.
/// Panics if the value does not fit in u32
pub fn safe_u128_to_u32(a: u128) -> u32 {
let u32_max: u128 = u32_to_u128(jet::high_32());
let (_, a_64): (u64, u64) = split_u128_into_u64(a);

assert!(le_128(a, u32_max));

jet::rightmost_64_32(a_64)
}

/// Converts u128 into u64.
/// Panics if the value does not fit in u64
pub fn safe_u128_to_u64(a: u128) -> u64 {
let u64_max: u128 = u64_to_u128(jet::high_64());
let (_, a_64): (u64, u64) = split_u128_into_u64(a);

assert!(le_128(a, u64_max));

a_64
}
124 changes: 1 addition & 123 deletions simf/lib/u128.simf → simf/lib/u128/math.simf
Original file line number Diff line number Diff line change
@@ -1,130 +1,8 @@
use crate::lib::binary::{not, or, and};

/// Bit logic

/// Bitwise AND of two 128-bit values
pub fn and_128(a: u128, b: u128) -> u128 {
let (a_high, a_low): (u64, u64) = <u128>::into(a);
let (b_high, b_low): (u64, u64) = <u128>::into(b);

<(u64, u64)>::into((jet::and_64(a_high, b_high), jet::and_64(a_low, b_low)))
}

/// Bitwise OR of two 128-bit values
pub fn or_128(a: u128, b: u128) -> u128 {
let (a_high, a_low): (u64, u64) = <u128>::into(a);
let (b_high, b_low): (u64, u64) = <u128>::into(b);

<(u64, u64)>::into((jet::or_64(a_high, b_high), jet::or_64(a_low, b_low)))
}

/// Checks if two 128-bit values are equal
pub fn eq_128(a: u128, b: u128) -> bool {
let (a_high, a_low): (u64, u64) = <u128>::into(a);
let (b_high, b_low): (u64, u64) = <u128>::into(b);

and(jet::eq_64(a_high, b_high), jet::eq_64(a_low, b_low))
}

/// Left-shift a 128-bit value by the given amount. Bits are filled with zeroes
pub fn left_shift_128(shift: u8, a: u128) -> u128 {
match jet::is_zero_8(shift) {
true => a,
false => {
let (a_high, a_low): (u64, u64) = <u128>::into(a);

match jet::lt_8(shift, 64) {
true => {
let (_, low_to_high_amount): (bool, u8) = jet::subtract_8(64, shift); // shift < 64
let shifted_bits: u64 = jet::right_shift_64(low_to_high_amount, a_low);

let res_high: u64 = jet::or_64(jet::left_shift_64(shift, a_high), shifted_bits);

<(u64, u64)>::into((res_high, jet::left_shift_64(shift, a_low)))
},
false => {
let (_, shift): (bool, u8) = jet::subtract_8(shift, 64); // shift >= 64

<(u64, u64)>::into((jet::left_shift_64(shift, a_low), 0))
}
}
}
}
}

/// Right-shift a 128-bit value by the given amount. Bits are filled with zeroes
pub fn right_shift_128(shift: u8, a: u128) -> u128 {
match jet::is_zero_8(shift) {
true => a,
false => {
let (a_high, a_low): (u64, u64) = <u128>::into(a);

match jet::lt_8(shift, 64) {
true => {
let (_, high_to_low_amount): (bool, u8) = jet::subtract_8(64, shift); // shift < 64
let shifted_bits: u64 = jet::left_shift_64(high_to_low_amount, a_high);

let res_low: u64 = jet::or_64(jet::right_shift_64(shift, a_low), shifted_bits);

<(u64, u64)>::into((jet::right_shift_64(shift, a_high), res_low))
},
false => {
let (_, shift): (bool, u8) = jet::subtract_8(shift, 64); // shift >= 64

<(u64, u64)>::into((0, jet::right_shift_64(shift, a_high)))
}
}
}
}
}
use crate::lib::u128::comparison::{is_zero_128, lt_128};

/// Arithmetic

/// Checks if an integer is zero
pub fn is_zero_128(a: u128) -> bool {
let (a_high, a_low): (u64, u64) = <u128>::into(a);

and(jet::is_zero_64(a_high), jet::is_zero_64(a_low))
}

/// Checks if an integer is less than another integer
pub fn lt_128(a: u128, b: u128) -> bool {
let (a_high, a_low): (u64, u64) = <u128>::into(a);
let (b_high, b_low): (u64, u64) = <u128>::into(b);

match jet::lt_64(a_high, b_high) {
true => true,
false => match jet::eq_64(a_high, b_high) {
true => jet::lt_64(a_low, b_low),
false => false,
},
}
}

/// Checks if an integer is less than or equal to another integer
pub fn le_128(a: u128, b: u128) -> bool {
let (a_high, a_low): (u64, u64) = <u128>::into(a);
let (b_high, b_low): (u64, u64) = <u128>::into(b);

match jet::lt_64(a_high, b_high) {
true => true,
false => match jet::eq_64(a_high, b_high) {
true => jet::le_64(a_low, b_low),
false => false,
},
}
}

/// Check if an integer is greater than another integer
pub fn gt_128(a: u128, b: u128) -> bool {
lt_128(b, a)
}

/// Check if an integer is greater than or equal to another integer
pub fn ge_128(a: u128, b: u128) -> bool {
le_128(b, a)
}

/// Adds two integers and returns the carry
pub fn add_128(a: u128, b: u128) -> (bool, u128) {
let (a_high, a_low): (u64, u64) = <u128>::into(a);
Expand Down
12 changes: 3 additions & 9 deletions simf/lib/u256.simf
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
use crate::lib::binary::{not, and};
use crate::lib::u128::{
and_128,
or_128,
eq_128,
left_shift_128,
right_shift_128,
is_zero_128,
lt_128,
le_128,
use crate::lib::u128::math::{
add_128,
full_add_128,
sub_128,
Expand All @@ -20,6 +12,8 @@ use crate::lib::u128::{
div_mod_128,
div_mod_128_64
};
use crate::lib::u128::bit::{and_128, or_128, eq_128, left_shift_128, right_shift_128};
use crate::lib::u128::comparison::{is_zero_128, lt_128, le_128};

/// Bit logic

Expand Down
Loading