-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
## Type of change <!--Delete points that do not apply--> - New feature ## Changes The following changes have been made: Addition of signed typers: `i8`, `i16`, `i32`, `i64` ## Notes - Note 1 ## Related Issues <!--Delete everything after the "#" symbol and replace it with a number. No spaces between hash and number--> Closes #36 Co-authored-by: tyshkor <[email protected]> Co-authored-by: Cameron Carstens <[email protected]> Co-authored-by: Simon <[email protected]>
- Loading branch information
1 parent
98ed79c
commit 2c99891
Showing
43 changed files
with
1,478 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,12 @@ | ||
library sway_libs; | ||
|
||
dep merkle_proof/binary_merkle_proof; | ||
dep signed_integers/signed_integers; | ||
dep signed_integers/i8; | ||
dep signed_integers/i16; | ||
dep signed_integers/i32; | ||
dep signed_integers/i64; | ||
dep signed_integers/i128; | ||
dep signed_integers/i256; | ||
dep nft/nft; | ||
dep string/string; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# Overview | ||
|
||
The Signed Integers library provides a library to use signed numbers in Sway. It has 6 distinct types: `I8`, `I16`, `I32`, `I64`, `I128`, `I256`. These types are stack allocated. | ||
|
||
These types are stored as unsigned integers, therefore either `u64` or a number of them. Therefore the size can be known at compile time and the length is static. | ||
|
||
For more information please see the [specification](./SPECIFICATION.md). | ||
|
||
# Using the Library | ||
|
||
## Getting Started | ||
|
||
In order to use the `Signed Integers` type it must be added to the Forc.toml file and then imported into your Sway project. To add Sway-libs as a dependency to the Forc.toml in your project, please see the [README.md](../../../README.md). | ||
|
||
```rust | ||
use sway_libs::i8::I8; | ||
``` | ||
|
||
Once imported, a `Signed Integer` type can be instantiated defining a new variable and calling the `new` function. | ||
|
||
```rust | ||
let mut i8_value = I8::new(); | ||
``` | ||
|
||
## Basic Functionality | ||
|
||
Basic arithmetic operations are working as usual | ||
|
||
```rust | ||
// Add 2 signed values | ||
let i8_value_3 = i8_value_1 + i8_value_2; | ||
|
||
// Subtract one signed value from another | ||
let i8_value_3 = i8_value_1 - i8_value_2; | ||
``` | ||
|
||
Helper functions | ||
|
||
```rust | ||
// To get a negative value from an unsigned value | ||
let neg_value = I8::neg_from(); | ||
|
||
// Maximum value | ||
let max_i8_value = I8::max(); | ||
``` | ||
|
||
## Known Issues | ||
The current implementation of `U128` and `U256` will compile large bytecode sizes when performing mathematical computations. As a result, `I128` and `I256` inherit the same issue and could cause high transaction costs. This should be resolved with future optimizations of the Sway compiler. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Overview | ||
|
||
This document provides an overview of the Signed Integers library. | ||
|
||
It outlines the use cases, i.e. specification, and describes how to implement the library. | ||
|
||
## Use Cases | ||
|
||
The Signed Integers library can be used anytime a one needs negative numbers. | ||
|
||
## Public Functions | ||
|
||
### `bits()` | ||
|
||
The size of this type in bits. | ||
|
||
### `max()` | ||
|
||
The largest value that can be represented by this integer type. | ||
|
||
### `min()` | ||
|
||
The smallest value that can be represented by this integer type. | ||
|
||
### `neg_from` | ||
|
||
Helper function to get a negative value of an unsigned number | ||
|
||
### Basic arithmetic operations | ||
|
||
`+`, `-`, `*`, `/` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
library errors; | ||
|
||
pub enum Error { | ||
ZeroDivisor: (), | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
library i128; | ||
|
||
use std::u128::U128; | ||
use ::signed_integers::errors::Error; | ||
|
||
/// The 128-bit signed integer type. | ||
/// Represented as an underlying U128 value. | ||
/// Actual value is underlying value minus 2 ^ 127 | ||
/// Max value is 2 ^ 127 - 1, min value is - 2 ^ 127 | ||
pub struct I128 { | ||
underlying: U128, | ||
} | ||
|
||
impl I128 { | ||
/// The underlying value that corresponds to zero signed value | ||
pub fn indent() -> U128 { | ||
U128 { | ||
upper: 1, | ||
lower: 0, | ||
} | ||
} | ||
} | ||
|
||
impl From<U128> for I128 { | ||
/// Helper function to get a signed number from with an underlying | ||
fn from(value: U128) -> Self { | ||
// as the minimal value of I128 is -I128::indent() (1 << 63) we should add I128::indent() (1 << 63) | ||
let underlying: U128 = value + Self::indent(); | ||
Self { underlying } | ||
} | ||
|
||
fn into(self) -> U128 { | ||
self.underlying - Self::indent() | ||
} | ||
} | ||
|
||
impl core::ops::Eq for I128 { | ||
fn eq(self, other: Self) -> bool { | ||
self.underlying == other.underlying | ||
} | ||
} | ||
|
||
impl core::ops::Ord for I128 { | ||
fn gt(self, other: Self) -> bool { | ||
self.underlying > other.underlying | ||
} | ||
|
||
fn lt(self, other: Self) -> bool { | ||
self.underlying < other.underlying | ||
} | ||
} | ||
|
||
impl I128 { | ||
/// The size of this type in bits. | ||
pub fn bits() -> u32 { | ||
128 | ||
} | ||
|
||
/// Helper function to get a positive value from an unsigned number | ||
fn from_uint(underlying: U128) -> Self { | ||
Self { underlying } | ||
} | ||
|
||
/// The largest value that can be represented by this integer type, | ||
pub fn max() -> Self { | ||
Self { | ||
underlying: U128::max(), | ||
} | ||
} | ||
|
||
/// The smallest value that can be represented by this integer type. | ||
pub fn min() -> Self { | ||
Self { | ||
underlying: U128::min(), | ||
} | ||
} | ||
|
||
/// Helper function to get a negative value of an unsigned number | ||
pub fn neg_from(value: U128) -> Self { | ||
Self { | ||
underlying: Self::indent() - value, | ||
} | ||
} | ||
|
||
/// Initializes a new, zeroed I128. | ||
pub fn new() -> Self { | ||
Self { | ||
underlying: Self::indent(), | ||
} | ||
} | ||
} | ||
|
||
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) | ||
} | ||
} | ||
|
||
impl core::ops::Divide for I128 { | ||
/// Divide a I128 by a I128. Panics if divisor is zero. | ||
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()); | ||
} else if self.underlying < Self::indent() | ||
&& divisor.underlying < Self::indent() | ||
{ | ||
res = Self::from((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)); | ||
} else if self.underlying < Self::indent() | ||
&& divisor.underlying > Self::indent() | ||
{ | ||
res = Self::from(Self::indent() - (Self::indent() - self.underlying) / (divisor.underlying - Self::indent())); | ||
} | ||
res | ||
} | ||
} | ||
|
||
impl core::ops::Multiply for I128 { | ||
/// Multiply a I128 with a I128. Panics of overflow. | ||
fn multiply(self, other: Self) -> Self { | ||
let mut res = Self::new(); | ||
if (self.underlying > Self::indent() | ||
|| self.underlying == Self::indent()) | ||
&& (other.underlying > Self::indent() | ||
|| other.underlying == Self::indent()) | ||
{ | ||
res = Self::from((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()); | ||
} 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)); | ||
} 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 | ||
} | ||
} | ||
|
||
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)); | ||
} | ||
res | ||
} | ||
} |
Oops, something went wrong.