wadray 0.5.0

Fixed-point decimal numbers for Cairo

This library implements two types of fixed-point decimal numbers, "wad" (18 decimals of precision) and "ray" (27 decimals of decimal numbers), available in signed (`SignedWad`

and `SignedRay`

) and unsigned (`Wad`

and `Ray`

) versions, written in Cairo for Starknet.

`Wad`

and `Ray`

are implemented as structs with a single `u128`

member for the value, while `SignedWad`

and `SignedRay`

are implemented as structs with a `u128`

member for the value and `bool`

member for the `sign`

(i.e. if the `sign`

is `true`

, then the value is negative).

This library includes arithmetic, comparison and conversion functions.

Addition and subtraction can be performed via the `Add`

, `AddEq`

, `Sub`

and `SubEq`

traits as follows:

`a + b`

`a += b`

`a - b`

`a -= b`

where both `a`

and `b`

are of the same type.

Multiplication and division can be performed via the the `Mul`

, `MulEq`

, `Div`

and `DivEq`

traits as follows:

`a * b`

`a *= b`

`a / b`

`a /= b`

where both`a`

and`b`

are of the same type.

There is also a set of functions for operations involving a `Wad`

and a `Ray`

:

`wmul_wr`

/`wmul_rw`

: Multiply a`Wad`

value with a`Ray`

value, and divide the product by one`Wad`

scale to return a`Ray`

`wdiv_rw`

: Scale up a`Ray`

value by one`Wad`

scale and divide the scaled value by a`Wad`

value to return a`Ray`

`rmul_wr`

/`rmul_rw`

: Multiply a`Wad`

value with a`Ray`

value, and divide the product by one`Ray`

scale to return a`Wad`

`rdiv_wr`

: Scale up a`Wad`

value by one`Ray`

scale and divide the scaled value by a`Ray`

to return a`Wad`

`rdiv_ww`

: Scale up a`Wad`

value by one`Ray`

scale and divide the scaled value by a`Wad`

to return a`Ray`

For multiplication, the prefixes `w`

and `r`

denote whether the product is divided (i.e. scaled down) by a `Wad`

or `Ray`

respectively. For division, the prefixes `w`

and `r`

denote whether the first operand is multiplied (i.e. scaled up) by a `Wad`

or `Ray`

before the division respectively.

As these are fixed point operations, do take note that there will be a loss of precision.

Zero and one valuesThe following values and functions for both `Wad`

and `Ray`

, and `SignedWad`

and `SignedRay`

, are available via the `Zeroable`

and `Oneable`

traits.

`WadZeroable::zero()`

/`RayZeroable::zero()`

: Returns the zero value for`Wad`

and`Ray`

respectively`is_zero()`

: Returns true if the`Wad`

or`Ray`

value is zero`is_non_zero()`

Returns true if the`Wad`

or`Ray`

value is not zero`WadOneable::one()`

/`RayOneable::one()`

: Returns the scale value for`Wad`

(i.e. 10^{18}) and`Ray`

(i.e. 10^{27}) respectively`is_one()`

: Returns true if the`Wad`

or`Ray`

value is the scale value (i.e. 10^{18}and 10^{27}respectively)`is_non_one()`

Returns true if the`Wad`

or`Ray`

value is not the scale value (i.e. 10^{18}and 10^{27}respectively)

`SignedWadZeroable::zero()`

/`SignedRayZeroable::zero()`

: Returns the zero value for`Wad`

and`Ray`

respectively`is_zero()`

: Returns true if the`SignedWad`

or`SignedRay`

value is zero, regardless of the`sign`

.`is_non_zero()`

Returns true if the`SignedWad`

or`SignedRay`

value is not zero`SignedWadOneable::one()`

/`SignedRayOneable::one()`

: Returns the positive scale value for "wad" (i.e. 10^{18}) and "ray" (i.e. 10^{27}) respectively`is_one()`

: Returns true if the`SignedWad`

or`SignedRay`

value is the positive scale value (i.e. 10^{18}and 10^{27}respectively)`is_non_one()`

Returns true if the`SignedWad`

or`SignedRay`

value is not the positive scale value (i.e. 10^{18}and 10^{27}respectively)

The bound values for both `Wad`

and `Ray`

can be obtained via the `BoundedInt`

trait.

`BoundedWad::max()`

: Returns the maximum`Wad`

value of 2^{128}- 1`BoundedWad::min()`

: Returns the minimum`Wad`

value of 0`BoundedRay::max()`

: Returns the maximum`Ray`

value of 2^{128}- 1`BoundedRay::min()`

: Returns the minimum`Ray`

value of 0

Comparison for both `Wad`

and `Ray`

, and `SignedWad`

and `SignedRay`

, can be performed via the `PartialEq`

and `PartialOrd`

traits as follows:

`a == b`

`a != b`

`a > b`

`a >= b`

`a < b`

`a <= b`

where both `a`

and `b`

are of the same type.

Any type that can be converted to a `u128`

via the `Into`

trait can similarly be converted to a `Wad`

or `Ray`

via the `Into`

trait.

Additionally, the following conversions from integer types are supported for `SignedWad`

and `SignedRay`

via the `Into`

trait`:

`u128`

->`SignedWad`

: Convert a`u128`

to a`SignedWad`

without modifying the value, with the`sign`

set to`false`

`u128`

->`SignedRay`

: Convert a`u128`

to a`SignedRay`

without modifying the value, with the`sign`

set to`false`

The following conversions from this library's types can also be performed via the `Into`

trait:

`Wad`

->`felt252`

: Convert a`Wad`

to a`felt252`

without modifying the value`Wad`

->`u256`

: Convert a`Wad`

to a`u256`

without modifying the value`Wad`

->`SignedWad`

: Convert a`Wad`

to a`SignedWad`

without modifying the value, with the`sign`

set to`false`

`Ray`

->`SignedRay`

: Convert a`Ray`

to a`SignedRay`

without modifying the value, with the`sign`

set to`false`

`SignedWad`

->`felt252`

: Convert a`SignedWad`

to a`felt252`

without modifying the value`SignedRay`

->`felt252`

: Convert a`SignedRay`

to a`felt252`

without modifying the value

The following conversions can be performed via the `TryInto`

trait:

`u256`

->`Option::<Wad>`

: Returns`Option::Some<Wad>`

if the value is within bounds of`u128`

or`Option::None`

otherwise`SignedWad`

->`Option::<Wad>`

: Returns`Option::Some<Wad>`

if`sign`

is false or`Option::None`

otherwise`SignedRay`

->`Option::<Ray>`

: Returns`Option::Some<Ray>`

if`sign`

is false or`Option::None`

otherwise

The following functions can be used to scale between `Wad`

and `Ray`

:

`fn ray_to_wad(x: Ray) -> Wad`

: Divide the`Ray`

value by 10^{9}and return a`Wad`

`fn wad_to_ray(x: Wad) -> Option::<Ray>`

: Multiply the`Wad`

value by 10^{9}and return`Option::Some<Ray>`

if there is no overflow or`Option::None`

otherwise

`Wad`

and `Ray`

Overview
Starting from `v0.5.0`

of this library, we have made significant changes to how `Wad`

values are converted to `Ray`

values and vice versa. This aims to improve type safety and align with the semantics of Rust's `Into`

trait.

- Previously,
`Into<Wad, Ray>`

scaled the value by 10^{9}while`Into<Ray, Wad>`

scaled the value by 10^{-9}. Both now perform direct type cast without value modification - Introduced
`wad_to_ray()`

and`ray_to_wad()`

functions for value-preserving conversions

- Prefer
`wad_to_ray()`

and`ray_to_wad()`

for most conversions between`Wad`

and`Ray`

. - Use the
`Into`

trait only when a simple type cast is required (expected to be rare).

The following functions are available for `SignedWad`

and `SignedRay`

via the `Signed`

trait:

`is_negative()`

: Returns true if the value is less than zero`is_positive()`

: Returns true if the value is greater than zero

To use this library, add the repository as a dependency in your `Scarb.toml`

:

```
[dependencies]
wadray = "0.5.0"
```

then add the following line in your `.cairo`

file

```
use wadray::Wad;
fn add_wad(a: Wad, b: Wad) -> Wad {
a + b
}
```

You can also refer to the test file `src/test_wadray.cairo`

for another example.

To run the tests:

```
scarb test
```

This library has been formally verified using our tool Aegis. Specifications and their correctness proof can be found in this repository, the verification currently refers to revision 30f7664 of this repo.

We welcome contributions of any kind! Please feel free to submit an issue or open a PR if you have a solution to an existing bug.

This library is released under the MIT License.

Version 0.5.0

Uploaded 2 weeks ago

Size 12.2 KB

Run the following command in your project dir

```
scarb add wadray@0.5.0
```

Or add the following line to your Scarb.toml

```
wadray = "0.5.0"
```

Repository github.com/lindy-labs/wadray

- fixed-point
- wad
- ray
- cairo
- starknet