 # Faking a i256 with (i128, u128)?

Is there an easy way to fake a i256 with an (i128, u128) for +-*/ ?

Context: I am doing some computational geometry on i64's. I can guarantee that all intermediate values will fit in i256's.

I think it would be a lot easier to do this if you represent it as `(i64, u64, u64, u64)` because then you can cast each piece to `u128`, do the operation, and split it into two `u64`s.

4 Likes

For example, you can implement addition like this:

``````struct I256 {
data: [u64; 4],
}

impl From<u128> for I256 {
fn from(value: u128) -> Self {
Self {
data: [0, 0, (value >> 64) as u64, value as u64],
}
}
}

type Output = I256;

fn add(self, other: I256) -> I256 {
let x0 = (self.data as u128).wrapping_add(other.data as u128);
let v0 = x0 as u64;
let c0 = x0 >> 64;

let x1 = (self.data as u128).wrapping_add(other.data as u128)
let v1 = x1 as u64;
let c1 = x1 >> 64;

let x2 = (self.data as u128).wrapping_add(other.data as u128)
let v2 = x2 as u64;
let c2 = x2 >> 64;

let x3 = (self.data as u128).wrapping_add(other.data as u128)
let v3 = x3 as u64;
let c3 = x3 >> 64;

I256 {
data: [v0, v1, v2, v3],
}
}
}
``````

Look up the wikipedia article for two's complement to see how to implement other operations. When it comes to the operations +, - and *, their implementation is completely identical for signed and unsigned integers. The only difference is what constitutes as overflow and underflow. Division is more tricky.

2 Likes

It looks to me that your `add` is little endian, but your `from` is big endian.

1 Like

Oops, thanks for noticing.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.