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.

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],
}
}
}
impl Add<I256> for I256 {
type Output = I256;
fn add(self, other: I256) -> I256 {
let x0 = (self.data[0] as u128).wrapping_add(other.data[0] as u128);
let v0 = x0 as u64;
let c0 = x0 >> 64;
let x1 = (self.data[1] as u128).wrapping_add(other.data[1] as u128)
.wrapping_add(c0);
let v1 = x1 as u64;
let c1 = x1 >> 64;
let x2 = (self.data[2] as u128).wrapping_add(other.data[2] as u128)
.wrapping_add(c1);
let v2 = x2 as u64;
let c2 = x2 >> 64;
let x3 = (self.data[3] as u128).wrapping_add(other.data[3] as u128)
.wrapping_add(c2);
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.