From 55a1a3d5d0fcce55997dc31ce18369154088fa23 Mon Sep 17 00:00:00 2001 From: rostyslavtyshko <106978277+rostyslavtyshko@users.noreply.github.com> Date: Tue, 7 Feb 2023 19:20:56 +0100 Subject: [PATCH] Fix signed integer bugs (#66) Fixed subtraction logic, and fix after renaming `from` and `from_int` --- libs/signed_integers/src/i128.sw | 67 ++++++++++++---- libs/signed_integers/src/i16.sw | 61 ++++++++++---- libs/signed_integers/src/i256.sw | 80 ++++++++++++++----- libs/signed_integers/src/i32.sw | 61 ++++++++++---- libs/signed_integers/src/i64.sw | 60 ++++++++++---- libs/signed_integers/src/i8.sw | 58 +++++++++++--- .../signed_integers/signed_i256/src/main.sw | 8 +- 7 files changed, 299 insertions(+), 96 deletions(-) diff --git a/libs/signed_integers/src/i128.sw b/libs/signed_integers/src/i128.sw index b57d682f..15ba3bb8 100644 --- a/libs/signed_integers/src/i128.sw +++ b/libs/signed_integers/src/i128.sw @@ -94,7 +94,22 @@ impl core::ops::Add for I128 { /// Add a I128 to a I128. Panics on overflow. fn add(self, other: Self) -> Self { // subtract 1 << 63 to avoid double move - Self::from(self.underlying - Self::indent() + other.underlying) + let mut res = Self::new(); + if (self.underlying > Self::indent() + || self.underlying == Self::indent()) + { + res = Self::from_uint(self.underlying - Self::indent() + other.underlying) // subtract 1 << 31 to avoid double move + } else if self.underlying < Self::indent() + && other.underlying < Self::indent() + { + res = Self::from_uint(self.underlying + other.underlying - Self::indent()); + } else if self.underlying < Self::indent() + && (other.underlying > Self::indent() + || other.underlying == Self::indent()) + { + res = Self::from_uint(other.underlying - Self::indent() + self.underlying); + } + res } } @@ -107,20 +122,20 @@ impl core::ops::Divide for I128 { || self.underlying == Self::indent()) && divisor.underlying > Self::indent() { - res = Self::from((self.underlying - Self::indent()) / (divisor.underlying - Self::indent()) + Self::indent()); + res = Self::from_uint((self.underlying - Self::indent()) / (divisor.underlying - Self::indent()) + Self::indent()); } else if self.underlying < Self::indent() && divisor.underlying < Self::indent() { - res = Self::from((Self::indent() - self.underlying) / (Self::indent() - divisor.underlying) + Self::indent()); + res = Self::from_uint((Self::indent() - self.underlying) / (Self::indent() - divisor.underlying) + Self::indent()); } else if (self.underlying > Self::indent() || self.underlying == Self::indent()) && divisor.underlying < Self::indent() { - res = Self::from(Self::indent() - (self.underlying - Self::indent()) / (Self::indent() - divisor.underlying)); + res = Self::from_uint(Self::indent() - (self.underlying - Self::indent()) / (Self::indent() - divisor.underlying)); } else if self.underlying < Self::indent() && divisor.underlying > Self::indent() { - res = Self::from(Self::indent() - (Self::indent() - self.underlying) / (divisor.underlying - Self::indent())); + res = Self::from_uint(Self::indent() - (Self::indent() - self.underlying) / (divisor.underlying - Self::indent())); } res } @@ -135,21 +150,21 @@ impl core::ops::Multiply for I128 { && (other.underlying > Self::indent() || other.underlying == Self::indent()) { - res = Self::from((self.underlying - Self::indent()) * (other.underlying - Self::indent()) + Self::indent()); + res = Self::from_uint((self.underlying - Self::indent()) * (other.underlying - Self::indent()) + Self::indent()); } else if self.underlying < Self::indent() && other.underlying < Self::indent() { - res = Self::from((Self::indent() - self.underlying) * (Self::indent() - other.underlying) + Self::indent()); + res = Self::from_uint((Self::indent() - self.underlying) * (Self::indent() - other.underlying) + Self::indent()); } else if (self.underlying > Self::indent() || self.underlying == Self::indent()) && other.underlying < Self::indent() { - res = Self::from(Self::indent() - (self.underlying - Self::indent()) * (Self::indent() - other.underlying)); + res = Self::from_uint(Self::indent() - (self.underlying - Self::indent()) * (Self::indent() - other.underlying)); } else if self.underlying < Self::indent() && (other.underlying > Self::indent() || other.underlying == Self::indent()) { - res = Self::from(Self::indent() - (other.underlying - Self::indent()) * (Self::indent() - self.underlying)); + res = Self::from_uint(Self::indent() - (other.underlying - Self::indent()) * (Self::indent() - self.underlying)); } res } @@ -159,12 +174,34 @@ impl core::ops::Subtract for I128 { /// Subtract a I128 from a I128. Panics of overflow. fn subtract(self, other: Self) -> Self { let mut res = Self::new(); - if self > other { - // add 1 << 63 to avoid loosing the move - res = Self::from(self.underlying - other.underlying + Self::indent()); - } else { - // subtract from 1 << 63 as we are getting a negative value - res = Self::from(Self::indent() - (other.underlying - self.underlying)); + if (self.underlying > Self::indent() + || self.underlying == Self::indent()) + && (other.underlying > Self::indent() + || other.underlying == Self::indent()) + { + if self.underlying > other.underlying { + res = Self::from_uint(self.underlying - other.underlying + Self::indent()); + } else { + res = Self::from_uint(self.underlying - (other.underlying - Self::indent())); + } + } else if (self.underlying > Self::indent() + || self.underlying == Self::indent()) + && other.underlying < Self::indent() + { + res = Self::from_uint(self.underlying - Self::indent() + other.underlying); + } else if self.underlying < Self::indent() + && (other.underlying > Self::indent() + || other.underlying == Self::indent()) + { + res = Self::from_uint(self.underlying - (other.underlying - Self::indent())); + } else if self.underlying < Self::indent() + && other.underlying < Self::indent() + { + if self.underlying < other.underlying { + res = Self::from_uint(other.underlying - self.underlying + Self::indent()); + } else { + res = Self::from_uint(self.underlying + other.underlying - Self::indent()); + } } res } diff --git a/libs/signed_integers/src/i16.sw b/libs/signed_integers/src/i16.sw index 2a533bfa..7201336c 100644 --- a/libs/signed_integers/src/i16.sw +++ b/libs/signed_integers/src/i16.sw @@ -89,8 +89,19 @@ impl I16 { impl core::ops::Add for I16 { /// Add a I16 to a I16. Panics on overflow. fn add(self, other: Self) -> Self { - // subtract 1 << 15 to avoid double move - Self::from(self.underlying - Self::indent() + other.underlying) + let mut res = Self::new(); + if self.underlying >= Self::indent() { + res = Self::from_uint(self.underlying - Self::indent() + other.underlying) // subtract 1 << 15 to avoid double move + } else if self.underlying < Self::indent() + && other.underlying < Self::indent() + { + res = Self::from_uint(self.underlying + other.underlying - Self::indent()); + } else if self.underlying < Self::indent() + && other.underlying >= Self::indent() + { + res = Self::from_uint(other.underlying - Self::indent() + self.underlying); + } + res } } @@ -102,19 +113,19 @@ impl core::ops::Divide for I16 { if self.underlying >= Self::indent() && divisor.underlying > Self::indent() { - res = Self::from((self.underlying - Self::indent()) / (divisor.underlying - Self::indent()) + Self::indent()); + res = Self::from_uint((self.underlying - Self::indent()) / (divisor.underlying - Self::indent()) + Self::indent()); } else if self.underlying < Self::indent() && divisor.underlying < Self::indent() { - res = Self::from((Self::indent() - self.underlying) / (Self::indent() - divisor.underlying) + Self::indent()); + res = Self::from_uint((Self::indent() - self.underlying) / (Self::indent() - divisor.underlying) + Self::indent()); } else if self.underlying >= Self::indent() && divisor.underlying < Self::indent() { - res = Self::from(Self::indent() - (self.underlying - Self::indent()) / (Self::indent() - divisor.underlying)); + res = Self::from_uint(Self::indent() - (self.underlying - Self::indent()) / (Self::indent() - divisor.underlying)); } else if self.underlying < Self::indent() && divisor.underlying > Self::indent() { - res = Self::from(Self::indent() - (Self::indent() - self.underlying) / (divisor.underlying - Self::indent())); + res = Self::from_uint(Self::indent() - (Self::indent() - self.underlying) / (divisor.underlying - Self::indent())); } res } @@ -127,19 +138,19 @@ impl core::ops::Multiply for I16 { if self.underlying >= Self::indent() && other.underlying >= Self::indent() { - res = Self::from((self.underlying - Self::indent()) * (other.underlying - Self::indent()) + Self::indent()); + res = Self::from_uint((self.underlying - Self::indent()) * (other.underlying - Self::indent()) + Self::indent()); } else if self.underlying < Self::indent() && other.underlying < Self::indent() { - res = Self::from((Self::indent() - self.underlying) * (Self::indent() - other.underlying) + Self::indent()); + res = Self::from_uint((Self::indent() - self.underlying) * (Self::indent() - other.underlying) + Self::indent()); } else if self.underlying >= Self::indent() && other.underlying < Self::indent() { - res = Self::from(Self::indent() - (self.underlying - Self::indent()) * (Self::indent() - other.underlying)); + res = Self::from_uint(Self::indent() - (self.underlying - Self::indent()) * (Self::indent() - other.underlying)); } else if self.underlying < Self::indent() && other.underlying >= Self::indent() { - res = Self::from(Self::indent() - (other.underlying - Self::indent()) * (Self::indent() - self.underlying)); + res = Self::from_uint(Self::indent() - (other.underlying - Self::indent()) * (Self::indent() - self.underlying)); } res } @@ -149,12 +160,30 @@ impl core::ops::Subtract for I16 { /// Subtract a I16 from a I16. Panics of overflow. fn subtract(self, other: Self) -> Self { let mut res = Self::new(); - if self > other { - // add 1 << 15 to avoid loosing the move - res = Self::from(self.underlying - other.underlying + Self::indent()); - } else { - // subtract from 1 << 15 as we are getting a negative value - res = Self::from(Self::indent() - (other.underlying - self.underlying)); + if self.underlying >= Self::indent() + && other.underlying >= Self::indent() + { + if self.underlying > other.underlying { + res = Self::from_uint(self.underlying - other.underlying + Self::indent()); + } else { + res = Self::from_uint(self.underlying - (other.underlying - Self::indent())); + } + } else if self.underlying >= Self::indent() + && other.underlying < Self::indent() + { + res = Self::from_uint(self.underlying - Self::indent() + other.underlying); + } else if self.underlying < Self::indent() + && other.underlying >= Self::indent() + { + res = Self::from_uint(self.underlying - (other.underlying - Self::indent())); + } else if self.underlying < Self::indent() + && other.underlying < Self::indent() + { + if self.underlying < other.underlying { + res = Self::from_uint(other.underlying - self.underlying + Self::indent()); + } else { + res = Self::from_uint(self.underlying + other.underlying - Self::indent()); + } } res } diff --git a/libs/signed_integers/src/i256.sw b/libs/signed_integers/src/i256.sw index b32104c8..c8e3e085 100644 --- a/libs/signed_integers/src/i256.sw +++ b/libs/signed_integers/src/i256.sw @@ -95,7 +95,22 @@ impl core::ops::Add for I256 { /// Add a I256 to a I256. Panics on overflow. fn add(self, other: Self) -> Self { // subtract 1 << 63 to avoid double move - Self::from(self.underlying - Self::indent() + other.underlying) + let mut res = Self::new(); + if (self.underlying > Self::indent() + || self.underlying == Self::indent()) + { + res = Self::from_uint(self.underlying - Self::indent() + other.underlying) // subtract 1 << 31 to avoid double move + } else if self.underlying < Self::indent() + && other.underlying < Self::indent() + { + res = Self::from_uint(self.underlying + other.underlying - Self::indent()); + } else if self.underlying < Self::indent() + && (other.underlying > Self::indent() + || other.underlying == Self::indent()) + { + res = Self::from_uint(other.underlying - Self::indent() + self.underlying); + } + res } } @@ -104,24 +119,23 @@ impl core::ops::Divide for I256 { fn divide(self, divisor: Self) -> Self { require(divisor != Self::new(), Error::ZeroDivisor); let mut res = Self::new(); - if (self.underlying > Self::indent() - || self.underlying == Self::indent()) - && divisor.underlying > Self::indent() - { - res = Self::from((self.underlying - Self::indent()) / (divisor.underlying - Self::indent()) + Self::indent()); + let self_ge_indent = self.underlying > Self::indent() || self.underlying == Self::indent(); + let divisor_gt_indent = divisor.underlying > Self::indent(); + if self_ge_indent && divisor_gt_indent { + res = Self::from_uint((self.underlying - Self::indent()) / (divisor.underlying - Self::indent()) + Self::indent()); } else if self.underlying < Self::indent() && divisor.underlying < Self::indent() { - res = Self::from((Self::indent() - self.underlying) / (Self::indent() - divisor.underlying) + Self::indent()); + res = Self::from_uint((Self::indent() - self.underlying) / (Self::indent() - divisor.underlying) + Self::indent()); } else if (self.underlying > Self::indent() || self.underlying == Self::indent()) && divisor.underlying < Self::indent() { - res = Self::from(Self::indent() - (self.underlying - Self::indent()) / (Self::indent() - divisor.underlying)); + res = Self::from_uint(Self::indent() - (self.underlying - Self::indent()) / (Self::indent() - divisor.underlying)); } else if self.underlying < Self::indent() && divisor.underlying > Self::indent() { - res = Self::from(Self::indent() - (Self::indent() - self.underlying) / (divisor.underlying - Self::indent())); + res = Self::from_uint(Self::indent() - (Self::indent() - self.underlying) / (divisor.underlying - Self::indent())); } res } @@ -136,21 +150,21 @@ impl core::ops::Multiply for I256 { && (other.underlying > Self::indent() || other.underlying == Self::indent()) { - res = Self::from((self.underlying - Self::indent()) * (other.underlying - Self::indent()) + Self::indent()); + res = Self::from_uint((self.underlying - Self::indent()) * (other.underlying - Self::indent()) + Self::indent()); } else if self.underlying < Self::indent() && other.underlying < Self::indent() { - res = Self::from((Self::indent() - self.underlying) * (Self::indent() - other.underlying) + Self::indent()); + res = Self::from_uint((Self::indent() - self.underlying) * (Self::indent() - other.underlying) + Self::indent()); } else if (self.underlying > Self::indent() || self.underlying == Self::indent()) && other.underlying < Self::indent() { - res = Self::from(Self::indent() - (self.underlying - Self::indent()) * (Self::indent() - other.underlying)); + res = Self::from_uint(Self::indent() - (self.underlying - Self::indent()) * (Self::indent() - other.underlying)); } else if self.underlying < Self::indent() && (other.underlying > Self::indent() || other.underlying == Self::indent()) { - res = Self::from(Self::indent() - (other.underlying - Self::indent()) * (Self::indent() - self.underlying)); + res = Self::from_uint(Self::indent() - (other.underlying - Self::indent()) * (Self::indent() - self.underlying)); } res } @@ -160,12 +174,40 @@ impl core::ops::Subtract for I256 { /// Subtract a I256 from a I256. Panics of overflow. fn subtract(self, other: Self) -> Self { let mut res = Self::new(); - if self > other { - // add 1 << 63 to avoid loosing the move - res = Self::from(self.underlying - other.underlying + Self::indent()); - } else { - // subtract from 1 << 63 as we are getting a negative value - res = Self::from(Self::indent() - (other.underlying - self.underlying)); + if (self.underlying > Self::indent() + || self.underlying == Self::indent()) + && (other.underlying > Self::indent() + || other.underlying == Self::indent()) + { + if self.underlying > other.underlying { + res = Self::from_uint(self.underlying - other.underlying + Self::indent()); + } else { + let q = other.underlying - Self::indent(); + + // std::logging::log(self.underlying.a); + // std::logging::log(self.underlying.b); + // std::logging::log(self.underlying.c); + // std::logging::log(self.underlying.d); + res = Self::from_uint(self.underlying - q); + } + } else if (self.underlying > Self::indent() + || self.underlying == Self::indent()) + && other.underlying < Self::indent() + { + res = Self::from_uint(self.underlying - Self::indent() + other.underlying); + } else if self.underlying < Self::indent() + && (other.underlying > Self::indent() + || other.underlying == Self::indent()) + { + res = Self::from_uint(self.underlying - (other.underlying - Self::indent())); + } else if self.underlying < Self::indent() + && other.underlying < Self::indent() + { + if self.underlying < other.underlying { + res = Self::from_uint(other.underlying - self.underlying + Self::indent()); + } else { + res = Self::from_uint(self.underlying + other.underlying - Self::indent()); + } } res } diff --git a/libs/signed_integers/src/i32.sw b/libs/signed_integers/src/i32.sw index 6c42f57f..2b78136b 100644 --- a/libs/signed_integers/src/i32.sw +++ b/libs/signed_integers/src/i32.sw @@ -88,8 +88,19 @@ impl I32 { impl core::ops::Add for I32 { /// Add a I32 to a I32. Panics on overflow. fn add(self, other: Self) -> Self { - // subtract 1 << 31 to avoid double move - Self::from(self.underlying - Self::indent() + other.underlying) + let mut res = Self::new(); + if self.underlying >= Self::indent() { + res = Self::from_uint(self.underlying - Self::indent() + other.underlying) // subtract 1 << 31 to avoid double move + } else if self.underlying < Self::indent() + && other.underlying < Self::indent() + { + res = Self::from_uint(self.underlying + other.underlying - Self::indent()); + } else if self.underlying < Self::indent() + && other.underlying >= Self::indent() + { + res = Self::from_uint(other.underlying - Self::indent() + self.underlying); + } + res } } @@ -97,12 +108,30 @@ impl core::ops::Subtract for I32 { /// Subtract a I32 from a I32. Panics of overflow. fn subtract(self, other: Self) -> Self { let mut res = Self::new(); - if self > other { - // add 1 << 31 to avoid loosing the move - res = Self::from(self.underlying - other.underlying + Self::indent()); - } else { - // subtract from 1 << 31 as we are getting a negative value - res = Self::from(Self::indent() - (other.underlying - self.underlying)); + if self.underlying >= Self::indent() + && other.underlying >= Self::indent() + { + if self.underlying > other.underlying { + res = Self::from_uint(self.underlying - other.underlying + Self::indent()); + } else { + res = Self::from_uint(self.underlying - (other.underlying - Self::indent())); + } + } else if self.underlying >= Self::indent() + && other.underlying < Self::indent() + { + res = Self::from_uint(self.underlying - Self::indent() + other.underlying); + } else if self.underlying < Self::indent() + && other.underlying >= Self::indent() + { + res = Self::from_uint(self.underlying - (other.underlying - Self::indent())); + } else if self.underlying < Self::indent() + && other.underlying < Self::indent() + { + if self.underlying < other.underlying { + res = Self::from_uint(other.underlying - self.underlying + Self::indent()); + } else { + res = Self::from_uint(self.underlying + other.underlying - Self::indent()); + } } res } @@ -115,19 +144,19 @@ impl core::ops::Multiply for I32 { if self.underlying >= Self::indent() && other.underlying >= Self::indent() { - res = Self::from((self.underlying - Self::indent()) * (other.underlying - Self::indent()) + Self::indent()); + res = Self::from_uint((self.underlying - Self::indent()) * (other.underlying - Self::indent()) + Self::indent()); } else if self.underlying < Self::indent() && other.underlying < Self::indent() { - res = Self::from((Self::indent() - self.underlying) * (Self::indent() - other.underlying) + Self::indent()); + res = Self::from_uint((Self::indent() - self.underlying) * (Self::indent() - other.underlying) + Self::indent()); } else if self.underlying >= Self::indent() && other.underlying < Self::indent() { - res = Self::from(Self::indent() - (self.underlying - Self::indent()) * (Self::indent() - other.underlying)); + res = Self::from_uint(Self::indent() - (self.underlying - Self::indent()) * (Self::indent() - other.underlying)); } else if self.underlying < Self::indent() && other.underlying >= Self::indent() { - res = Self::from(Self::indent() - (other.underlying - Self::indent()) * (Self::indent() - self.underlying)); + res = Self::from_uint(Self::indent() - (other.underlying - Self::indent()) * (Self::indent() - self.underlying)); } res } @@ -141,19 +170,19 @@ impl core::ops::Divide for I32 { if self.underlying >= Self::indent() && divisor.underlying > Self::indent() { - res = Self::from((self.underlying - Self::indent()) / (divisor.underlying - Self::indent()) + Self::indent()); + res = Self::from_uint((self.underlying - Self::indent()) / (divisor.underlying - Self::indent()) + Self::indent()); } else if self.underlying < Self::indent() && divisor.underlying < Self::indent() { - res = Self::from((Self::indent() - self.underlying) / (Self::indent() - divisor.underlying) + Self::indent()); + res = Self::from_uint((Self::indent() - self.underlying) / (Self::indent() - divisor.underlying) + Self::indent()); } else if self.underlying >= Self::indent() && divisor.underlying < Self::indent() { - res = Self::from(Self::indent() - (self.underlying - Self::indent()) / (Self::indent() - divisor.underlying)); + res = Self::from_uint(Self::indent() - (self.underlying - Self::indent()) / (Self::indent() - divisor.underlying)); } else if self.underlying < Self::indent() && divisor.underlying > Self::indent() { - res = Self::from(Self::indent() - (Self::indent() - self.underlying) / (divisor.underlying - Self::indent())); + res = Self::from_uint(Self::indent() - (Self::indent() - self.underlying) / (divisor.underlying - Self::indent())); } res } diff --git a/libs/signed_integers/src/i64.sw b/libs/signed_integers/src/i64.sw index a5f05a5d..f641fc2a 100644 --- a/libs/signed_integers/src/i64.sw +++ b/libs/signed_integers/src/i64.sw @@ -89,7 +89,19 @@ impl core::ops::Add for I64 { /// Add a I64 to a I64. Panics on overflow. fn add(self, other: Self) -> Self { // subtract 1 << 63 to avoid double move - Self::from(self.underlying - Self::indent() + other.underlying) + let mut res = Self::new(); + if self.underlying >= Self::indent() { + res = Self::from_uint(self.underlying - Self::indent() + other.underlying) // subtract 1 << 31 to avoid double move + } else if self.underlying < Self::indent() + && other.underlying < Self::indent() + { + res = Self::from_uint(self.underlying + other.underlying - Self::indent()); + } else if self.underlying < Self::indent() + && other.underlying >= Self::indent() + { + res = Self::from_uint(other.underlying - Self::indent() + self.underlying); + } + res } } @@ -97,12 +109,30 @@ impl core::ops::Subtract for I64 { /// Subtract a I64 from a I64. Panics of overflow. fn subtract(self, other: Self) -> Self { let mut res = Self::new(); - if self > other { - // add 1 << 63 to avoid loosing the move - res = Self::from(self.underlying - other.underlying + Self::indent()); - } else { - // subtract from 1 << 63 as we are getting a negative value - res = Self::from(Self::indent() - (other.underlying - self.underlying)); + if self.underlying >= Self::indent() + && other.underlying >= Self::indent() + { + if self.underlying > other.underlying { + res = Self::from_uint(self.underlying - other.underlying + Self::indent()); + } else { + res = Self::from_uint(self.underlying - (other.underlying - Self::indent())); + } + } else if self.underlying >= Self::indent() + && other.underlying < Self::indent() + { + res = Self::from_uint(self.underlying - Self::indent() + other.underlying); + } else if self.underlying < Self::indent() + && other.underlying >= Self::indent() + { + res = Self::from_uint(self.underlying - (other.underlying - Self::indent())); + } else if self.underlying < Self::indent() + && other.underlying < Self::indent() + { + if self.underlying < other.underlying { + res = Self::from_uint(other.underlying - self.underlying + Self::indent()); + } else { + res = Self::from_uint(self.underlying + other.underlying - Self::indent()); + } } res } @@ -115,19 +145,19 @@ impl core::ops::Multiply for I64 { if self.underlying >= Self::indent() && other.underlying >= Self::indent() { - res = Self::from((self.underlying - Self::indent()) * (other.underlying - Self::indent()) + Self::indent()); + res = Self::from_uint((self.underlying - Self::indent()) * (other.underlying - Self::indent()) + Self::indent()); } else if self.underlying < Self::indent() && other.underlying < Self::indent() { - res = Self::from((Self::indent() - self.underlying) * (Self::indent() - other.underlying) + Self::indent()); + res = Self::from_uint((Self::indent() - self.underlying) * (Self::indent() - other.underlying) + Self::indent()); } else if self.underlying >= Self::indent() && other.underlying < Self::indent() { - res = Self::from(Self::indent() - (self.underlying - Self::indent()) * (Self::indent() - other.underlying)); + res = Self::from_uint(Self::indent() - (self.underlying - Self::indent()) * (Self::indent() - other.underlying)); } else if self.underlying < Self::indent() && other.underlying >= Self::indent() { - res = Self::from(Self::indent() - (other.underlying - Self::indent()) * (Self::indent() - self.underlying)); + res = Self::from_uint(Self::indent() - (other.underlying - Self::indent()) * (Self::indent() - self.underlying)); } res } @@ -141,19 +171,19 @@ impl core::ops::Divide for I64 { if self.underlying >= Self::indent() && divisor.underlying > Self::indent() { - res = Self::from((self.underlying - Self::indent()) / (divisor.underlying - Self::indent()) + Self::indent()); + res = Self::from_uint((self.underlying - Self::indent()) / (divisor.underlying - Self::indent()) + Self::indent()); } else if self.underlying < Self::indent() && divisor.underlying < Self::indent() { - res = Self::from((Self::indent() - self.underlying) / (Self::indent() - divisor.underlying) + Self::indent()); + res = Self::from_uint((Self::indent() - self.underlying) / (Self::indent() - divisor.underlying) + Self::indent()); } else if self.underlying >= Self::indent() && divisor.underlying < Self::indent() { - res = Self::from(Self::indent() - (self.underlying - Self::indent()) / (Self::indent() - divisor.underlying)); + res = Self::from_uint(Self::indent() - (self.underlying - Self::indent()) / (Self::indent() - divisor.underlying)); } else if self.underlying < Self::indent() && divisor.underlying > Self::indent() { - res = Self::from(Self::indent() - (Self::indent() - self.underlying) / (divisor.underlying - Self::indent())); + res = Self::from_uint(Self::indent() - (Self::indent() - self.underlying) / (divisor.underlying - Self::indent())); } res } diff --git a/libs/signed_integers/src/i8.sw b/libs/signed_integers/src/i8.sw index 7e855b8d..44ba3263 100644 --- a/libs/signed_integers/src/i8.sw +++ b/libs/signed_integers/src/i8.sw @@ -88,7 +88,19 @@ impl I8 { impl core::ops::Add for I8 { /// Add a I8 to a I8. Panics on overflow. fn add(self, other: Self) -> Self { - Self::from(self.underlying - Self::indent() + other.underlying) // subtract 1 << 7 to avoid double move + let mut res = Self::new(); + if self.underlying >= Self::indent() { + res = Self::from_uint(self.underlying - Self::indent() + other.underlying) // subtract 1 << 7 to avoid double move + } else if self.underlying < Self::indent() + && other.underlying < Self::indent() + { + res = Self::from_uint(self.underlying + other.underlying - Self::indent()); + } else if self.underlying < Self::indent() + && other.underlying >= Self::indent() + { + res = Self::from_uint(other.underlying - Self::indent() + self.underlying); + } + res } } @@ -100,19 +112,19 @@ impl core::ops::Divide for I8 { if self.underlying >= Self::indent() && divisor.underlying > Self::indent() { - res = Self::from((self.underlying - Self::indent()) / (divisor.underlying - Self::indent()) + Self::indent()); + res = Self::from_uint((self.underlying - Self::indent()) / (divisor.underlying - Self::indent()) + Self::indent()); } else if self.underlying < Self::indent() && divisor.underlying < Self::indent() { - res = Self::from((Self::indent() - self.underlying) / (Self::indent() - divisor.underlying) + Self::indent()); + res = Self::from_uint((Self::indent() - self.underlying) / (Self::indent() - divisor.underlying) + Self::indent()); } else if self.underlying >= Self::indent() && divisor.underlying < Self::indent() { - res = Self::from(Self::indent() - (self.underlying - Self::indent()) / (Self::indent() - divisor.underlying)); + res = Self::from_uint(Self::indent() - (self.underlying - Self::indent()) / (Self::indent() - divisor.underlying)); } else if self.underlying < Self::indent() && divisor.underlying > Self::indent() { - res = Self::from(Self::indent() - (Self::indent() - self.underlying) / (divisor.underlying - Self::indent())); + res = Self::from_uint(Self::indent() - (Self::indent() - self.underlying) / (divisor.underlying - Self::indent())); } res } @@ -125,19 +137,19 @@ impl core::ops::Multiply for I8 { if self.underlying >= Self::indent() && other.underlying >= Self::indent() { - res = Self::from((self.underlying - Self::indent()) * (other.underlying - Self::indent()) + Self::indent()); + res = Self::from_uint((self.underlying - Self::indent()) * (other.underlying - Self::indent()) + Self::indent()); } else if self.underlying < Self::indent() && other.underlying < Self::indent() { - res = Self::from((Self::indent() - self.underlying) * (Self::indent() - other.underlying) + Self::indent()); + res = Self::from_uint((Self::indent() - self.underlying) * (Self::indent() - other.underlying) + Self::indent()); } else if self.underlying >= Self::indent() && other.underlying < Self::indent() { - res = Self::from(Self::indent() - (self.underlying - Self::indent()) * (Self::indent() - other.underlying)); + res = Self::from_uint(Self::indent() - (self.underlying - Self::indent()) * (Self::indent() - other.underlying)); } else if self.underlying < Self::indent() && other.underlying >= Self::indent() { - res = Self::from(Self::indent() - (other.underlying - Self::indent()) * (Self::indent() - self.underlying)); + res = Self::from_uint(Self::indent() - (other.underlying - Self::indent()) * (Self::indent() - self.underlying)); } res } @@ -147,10 +159,30 @@ impl core::ops::Subtract for I8 { /// Subtract a I8 from a I8. Panics of overflow. fn subtract(self, other: Self) -> Self { let mut res = Self::new(); - if self > other { - res = Self::from(self.underlying - other.underlying + Self::indent()); // add 1 << 7 to avoid loosing the move - } else { - res = Self::from(Self::indent() - (other.underlying - self.underlying)); // subtract from 1 << 7 as we are getting a negative value + if self.underlying >= Self::indent() + && other.underlying >= Self::indent() + { + if self.underlying > other.underlying { + res = Self::from_uint(self.underlying - other.underlying + Self::indent()); + } else { + res = Self::from_uint(self.underlying - (other.underlying - Self::indent())); + } + } else if self.underlying >= Self::indent() + && other.underlying < Self::indent() + { + res = Self::from_uint(self.underlying - Self::indent() + other.underlying); + } else if self.underlying < Self::indent() + && other.underlying >= Self::indent() + { + res = Self::from_uint(self.underlying - (other.underlying - Self::indent())); + } else if self.underlying < Self::indent() + && other.underlying < Self::indent() + { + if self.underlying < other.underlying { + res = Self::from_uint(other.underlying - self.underlying + Self::indent()); + } else { + res = Self::from_uint(self.underlying + other.underlying - Self::indent()); + } } res } diff --git a/tests/src/signed_integers/signed_i256/src/main.sw b/tests/src/signed_integers/signed_i256/src/main.sw index 8fe26cb8..a8587fa3 100644 --- a/tests/src/signed_integers/signed_i256/src/main.sw +++ b/tests/src/signed_integers/signed_i256/src/main.sw @@ -71,9 +71,13 @@ fn main() -> bool { c: 0, d: 2, }; + + let i256_10 = I256::from(u128_10); + let i256_5 = I256::from(u128_5); + let i256_2 = I256::from(u128_2); - res = I256::from(u128_10) / I256::from(u128_5); - assert(res == I256::from(u128_2)); + res = i256_10 / i256_5; + assert(res == i256_2); true }