From 5743da7bb6f4b95b805413fa65ec8aa19a185c00 Mon Sep 17 00:00:00 2001 From: Feliciss <10203-feliciss@users.noreply.0xacab.org> Date: Wed, 24 Jul 2024 17:25:05 +0900 Subject: [PATCH] [gh-1117] remove macros. --- frameworks/move-stdlib/Move.toml | 3 +- frameworks/move-stdlib/sources/macros.move | 122 --------------------- frameworks/move-stdlib/sources/u128.move | 102 +++++++++++------ frameworks/move-stdlib/sources/u16.move | 87 +++++++++++---- frameworks/move-stdlib/sources/u256.move | 69 ++++++++---- frameworks/move-stdlib/sources/u32.move | 87 +++++++++++---- frameworks/move-stdlib/sources/u64.move | 87 +++++++++++---- frameworks/move-stdlib/sources/u8.move | 87 +++++++++++---- 8 files changed, 368 insertions(+), 276 deletions(-) delete mode 100644 frameworks/move-stdlib/sources/macros.move diff --git a/frameworks/move-stdlib/Move.toml b/frameworks/move-stdlib/Move.toml index e038b066a0..d15b9e1946 100644 --- a/frameworks/move-stdlib/Move.toml +++ b/frameworks/move-stdlib/Move.toml @@ -1,7 +1,6 @@ [package] name = "MoveStdlib" -version = "1.6.0" -edition = "2024.beta" +version = "1.5.0" [addresses] std = "0x1" diff --git a/frameworks/move-stdlib/sources/macros.move b/frameworks/move-stdlib/sources/macros.move deleted file mode 100644 index c99477a73e..0000000000 --- a/frameworks/move-stdlib/sources/macros.move +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (c) RoochNetwork -// SPDX-License-Identifier: Apache-2.0 - -// Copyright (c) Mysten Labs, Inc. -// SPDX-License-Identifier: Apache-2.0 - -/// This module holds shared implementation of macros used in `std` -module std::macros { - public macro fun num_max($x: _, $y: _): _ { - let x = $x; - let y = $y; - if (x > y) x - else y - } - - public macro fun num_min($x: _, $y: _): _ { - let x = $x; - let y = $y; - if (x < y) x - else y - } - - public macro fun num_diff($x: _, $y: _): _ { - let x = $x; - let y = $y; - if (x > y) x - y - else y - x - } - - public macro fun num_divide_and_round_up($x: _, $y: _): _ { - let x = $x; - let y = $y; - if (x % y == 0) x / y - else x / y + 1 - } - - // Ref: https://github.com/starcoinorg/starcoin-framework/blob/main/sources/Math.move - public macro fun num_multiple_and_divide($x: _, $y: _, $z: _): _ { - let x = $x; - let y = $y; - let z = $z; - - if (y == z) x - if (x == z) y - - let a = x / z; - let b = x % z; - let c = y / z; - let d = y % z; - let res = a * c * z + a * d + b * c + b * d / z - - res - } - - public macro fun num_pow($base: _, $exponent: u8): _ { - let mut base = $base; - let mut exponent = $exponent; - let mut res = 1; - while (exponent >= 1) { - if (exponent % 2 == 0) { - base = base * base; - exponent = exponent / 2; - } else { - res = res * base; - exponent = exponent - 1; - } - }; - - res - } - - public macro fun num_sqrt<$T, $U>($x: $T, $bitsize: u8): $T { - let x = $x; - let mut bit = (1: $U) << $bitsize; - let mut res = (0: $U); - let mut x = x as $U; - - while (bit != 0) { - if (x >= res + bit) { - x = x - (res + bit); - res = (res >> 1) + bit; - } else { - res = res >> 1; - }; - bit = bit >> 2; - }; - - res as $T - } - - public macro fun range_do($start: _, $stop: _, $f: |_|) { - let mut i = $start; - let stop = $stop; - while (i < stop) { - $f(i); - i = i + 1; - } - } - - public macro fun range_do_eq($start: _, $stop: _, $f: |_|) { - let mut i = $start; - let stop = $stop; - // we check `i >= stop` inside the loop instead of `i <= stop` as `while` condition to avoid - // incrementing `i` past the MAX integer value. - // Because of this, we need to check if `i > stop` and return early--instead of letting the - // loop bound handle it, like in the `range_do` macro. - if (i > stop) return; - loop { - $f(i); - if (i >= stop) break; - i = i + 1; - } - } - - public macro fun do($stop: _, $f: |_|) { - range_do!(0, $stop, $f) - } - - public macro fun do_eq($stop: _, $f: |_|) { - range_do_eq!(0, $stop, $f) - } -} \ No newline at end of file diff --git a/frameworks/move-stdlib/sources/u128.move b/frameworks/move-stdlib/sources/u128.move index dfebaec752..66fa01326c 100644 --- a/frameworks/move-stdlib/sources/u128.move +++ b/frameworks/move-stdlib/sources/u128.move @@ -8,32 +8,72 @@ module std::u128 { /// Return the larger of `x` and `y` public fun max(x: u128, y: u128): u128 { - std::macros::num_max!(x, y) + if (x > y) { + x + } else { + y + } } /// Return the smaller of `x` and `y` public fun min(x: u128, y: u128): u128 { - std::macros::num_min!(x, y) + if (x < y) { + x + } else { + y + } } /// Return the absolute value of x - y public fun diff(x: u128, y: u128): u128 { - std::macros::num_diff!(x, y) + if (x > y) { + x - y + } else { + y - x + } } /// Calculate x / y, but round up the result. public fun divide_and_round_up(x: u128, y: u128): u128 { - std::macros::num_divide_and_round_up!(x, y) + if (x % y == 0) { + x / y + } else { + x / y + 1 + } } /// Returns x * y / z with as little loss of precision as possible and avoid overflow public fun multiple_and_divide(x: u128, y: u128, z: u128): u128 { - std::macros::num_multiple_and_divide!(x, y, z) + if (y == z) { + x + } + if (x == z) { + y + } + + let a = x / z; + let b = x % z; + let c = y / z; + let d = y % z; + let res = a * c * z + a * d + b * c + b * d / z + + res } /// Return the value of a base raised to a power public fun pow(base: u128, exponent: u8): u128 { - std::macros::num_pow!(base, exponent) + let res = 1; + while (exponent >= 1) { + if (exponent % 2 == 0) { + base = base * base; + exponent = exponent / 2; + } else { + res = res * base; + exponent = exponent - 1; + } + }; + + res } /// Get a nearest lower integer Square Root for `x`. Given that this @@ -62,43 +102,37 @@ module std::u128 { /// math::sqrt(8 * 1000000) => 2828; // same as above, 2828 / 1000 (2.828) /// ``` public fun sqrt(x: u128): u128 { - std::macros::num_sqrt!(x, 128) + let bit = 1u256 << 128; + let res = 0u256; + let x = (x as u256); + + while (bit != 0) { + if (x >= res + bit) { + x = x - (res + bit); + res = (res >> 1) + bit; + } else { + res = res >> 1; + }; + bit = bit >> 2; + }; + + (res as u128) } - /// Loops applying `$f` to each number from `$start` to `$stop` (exclusive) - public macro fun range_do($start: u128, $stop: u128, $f: |u128|) { - std::macros::range_do!($start, $stop, $f) - } - - /// Loops applying `$f` to each number from `$start` to `$stop` (inclusive) - public macro fun range_do_eq($start: u128, $stop: u128, $f: |u128|) { - std::macros::range_do_eq!($start, $stop, $f) - } - - /// Loops applying `$f` to each number from `0` to `$stop` (exclusive) - public macro fun do($stop: u128, $f: |u128|) { - std::macros::do!($stop, $f) - } - - /// Loops applying `$f` to each number from `0` to `$stop` (inclusive) - public macro fun do_eq($stop: u128, $f: |u128|) { - std::macros::do_eq!($stop, $f) - } - - + // TODO: add test cases to other files #[test] - public entry fun test_mul_div() { + public entry fun test_multiple_and_divide() { let tmp: u128 = 1<<127; - assert!(mul_div(tmp,tmp,tmp) == tmp, 0); + assert!(multiple_and_divide(tmp,tmp,tmp) == tmp, 0); - assert!(mul_div(tmp,5,5) == tmp, 0); + assert!(multiple_and_divide(tmp,5,5) == tmp, 0); // Note that ordering other way is imprecise. assert!((tmp / 5) * 5 != tmp, 0); } #[test] - #[expected_failure(abort_code = 0x10004, location = aptos_std::math128)] - public entry fun test_mul_div_by_zero() { - mul_div(1, 1, 0); + #[expected_failure(abort_code = 0x10004, location = std::u128)] + public entry fun test_multiple_and_divide_by_zero() { + multiple_and_divide(1, 1, 0); } } \ No newline at end of file diff --git a/frameworks/move-stdlib/sources/u16.move b/frameworks/move-stdlib/sources/u16.move index d681832ca1..da409383e0 100644 --- a/frameworks/move-stdlib/sources/u16.move +++ b/frameworks/move-stdlib/sources/u16.move @@ -5,27 +5,72 @@ module std::u16 { /// Return the larger of `x` and `y` public fun max(x: u16, y: u16): u16 { - std::macros::num_max!(x, y) + if (x > y) { + x + } else { + y + } } /// Return the smaller of `x` and `y` public fun min(x: u16, y: u16): u16 { - std::macros::num_min!(x, y) + if (x < y) { + x + } else { + y + } } /// Return the absolute value of x - y public fun diff(x: u16, y: u16): u16 { - std::macros::num_diff!(x, y) + if (x > y) { + x - y + } else { + y - x + } } /// Calculate x / y, but round up the result. public fun divide_and_round_up(x: u16, y: u16): u16 { - std::macros::num_divide_and_round_up!(x, y) + if (x % y == 0) { + x / y + } else { + x / y + 1 + } + } + + /// Returns x * y / z with as little loss of precision as possible and avoid overflow + public fun multiple_and_divide(x: u16, y: u16, z: u16): u16 { + if (y == z) { + x + } + if (x == z) { + y + } + + let a = x / z; + let b = x % z; + let c = y / z; + let d = y % z; + let res = a * c * z + a * d + b * c + b * d / z + + res } /// Return the value of a base raised to a power public fun pow(base: u16, exponent: u8): u16 { - std::macros::num_pow!(base, exponent) + let res = 1; + while (exponent >= 1) { + if (exponent % 2 == 0) { + base = base * base; + exponent = exponent / 2; + } else { + res = res * base; + exponent = exponent - 1; + } + }; + + res } /// Get a nearest lower integer Square Root for `x`. Given that this @@ -54,26 +99,20 @@ module std::u16 { /// math::sqrt(8 * 1000000) => 2828; // same as above, 2828 / 1000 (2.828) /// ``` public fun sqrt(x: u16): u16 { - std::macros::num_sqrt!(x, 16) - } + let bit = 1u32 << 16; + let res = 0u32; + let x = (x as u32); - /// Loops applying `$f` to each number from `$start` to `$stop` (exclusive) - public macro fun range_do($start: u16, $stop: u16, $f: |u16|) { - std::macros::range_do!($start, $stop, $f) - } - - /// Loops applying `$f` to each number from `$start` to `$stop` (inclusive) - public macro fun range_do_eq($start: u16, $stop: u16, $f: |u16|) { - std::macros::range_do_eq!($start, $stop, $f) - } - - /// Loops applying `$f` to each number from `0` to `$stop` (exclusive) - public macro fun do($stop: u16, $f: |u16|) { - std::macros::do!($stop, $f) - } + while (bit != 0) { + if (x >= res + bit) { + x = x - (res + bit); + res = (res >> 1) + bit; + } else { + res = res >> 1; + }; + bit = bit >> 2; + }; - /// Loops applying `$f` to each number from `0` to `$stop` (inclusive) - public macro fun do_eq($stop: u16, $f: |u16|) { - std::macros::do_eq!($stop, $f) + (res as u16) } } \ No newline at end of file diff --git a/frameworks/move-stdlib/sources/u256.move b/frameworks/move-stdlib/sources/u256.move index cdd11cdc78..5a6a37b7f2 100644 --- a/frameworks/move-stdlib/sources/u256.move +++ b/frameworks/move-stdlib/sources/u256.move @@ -5,46 +5,71 @@ module std::u256 { /// Return the larger of `x` and `y` public fun max(x: u256, y: u256): u256 { - std::macros::num_max!(x, y) + if (x > y) { + x + } else { + y + } } /// Return the smaller of `x` and `y` public fun min(x: u256, y: u256): u256 { - std::macros::num_min!(x, y) + if (x < y) { + x + } else { + y + } } /// Return the absolute value of x - y public fun diff(x: u256, y: u256): u256 { - std::macros::num_diff!(x, y) + if (x > y) { + x - y + } else { + y - x + } } /// Calculate x / y, but round up the result. public fun divide_and_round_up(x: u256, y: u256): u256 { - std::macros::num_divide_and_round_up!(x, y) + if (x % y == 0) { + x / y + } else { + x / y + 1 + } } - /// Return the value of a base raised to a power - public fun pow(base: u256, exponent: u8): u256 { - std::macros::num_pow!(base, exponent) - } + /// Returns x * y / z with as little loss of precision as possible and avoid overflow + public fun multiple_and_divide(x: u256, y: u256, z: u256): u256 { + if (y == z) { + x + } + if (x == z) { + y + } - /// Loops applying `$f` to each number from `$start` to `$stop` (exclusive) - public macro fun range_do($start: u256, $stop: u256, $f: |u256|) { - std::macros::range_do!($start, $stop, $f) - } + let a = x / z; + let b = x % z; + let c = y / z; + let d = y % z; + let res = a * c * z + a * d + b * c + b * d / z - /// Loops applying `$f` to each number from `$start` to `$stop` (inclusive) - public macro fun range_do_eq($start: u256, $stop: u256, $f: |u256|) { - std::macros::range_do_eq!($start, $stop, $f) + res } - /// Loops applying `$f` to each number from `0` to `$stop` (exclusive) - public macro fun do($stop: u256, $f: |u256|) { - std::macros::do!($stop, $f) - } + /// Return the value of a base raised to a power + public fun pow(base: u256, exponent: u8): u256 { + let res = 1; + while (exponent >= 1) { + if (exponent % 2 == 0) { + base = base * base; + exponent = exponent / 2; + } else { + res = res * base; + exponent = exponent - 1; + } + }; - /// Loops applying `$f` to each number from `0` to `$stop` (inclusive) - public macro fun do_eq($stop: u256, $f: |u256|) { - std::macros::do_eq!($stop, $f) + res } } \ No newline at end of file diff --git a/frameworks/move-stdlib/sources/u32.move b/frameworks/move-stdlib/sources/u32.move index 8a8fa2de1b..6ff42403f7 100644 --- a/frameworks/move-stdlib/sources/u32.move +++ b/frameworks/move-stdlib/sources/u32.move @@ -5,27 +5,72 @@ module std::u32 { /// Return the larger of `x` and `y` public fun max(x: u32, y: u32): u32 { - std::macros::num_max!(x, y) + if (x > y) { + x + } else { + y + } } /// Return the smaller of `x` and `y` public fun min(x: u32, y: u32): u32 { - std::macros::num_min!(x, y) + if (x < y) { + x + } else { + y + } } /// Return the absolute value of x - y public fun diff(x: u32, y: u32): u32 { - std::macros::num_diff!(x, y) + if (x > y) { + x - y + } else { + y - x + } } /// Calculate x / y, but round up the result. public fun divide_and_round_up(x: u32, y: u32): u32 { - std::macros::num_divide_and_round_up!(x, y) + if (x % y == 0) { + x / y + } else { + x / y + 1 + } + } + + /// Returns x * y / z with as little loss of precision as possible and avoid overflow + public fun multiple_and_divide(x: u32, y: u32, z: u32): u32 { + if (y == z) { + x + } + if (x == z) { + y + } + + let a = x / z; + let b = x % z; + let c = y / z; + let d = y % z; + let res = a * c * z + a * d + b * c + b * d / z + + res } /// Return the value of a base raised to a power public fun pow(base: u32, exponent: u8): u32 { - std::macros::num_pow!(base, exponent) + let res = 1; + while (exponent >= 1) { + if (exponent % 2 == 0) { + base = base * base; + exponent = exponent / 2; + } else { + res = res * base; + exponent = exponent - 1; + } + }; + + res } /// Get a nearest lower integer Square Root for `x`. Given that this @@ -54,26 +99,20 @@ module std::u32 { /// math::sqrt(8 * 1000000) => 2828; // same as above, 2828 / 1000 (2.828) /// ``` public fun sqrt(x: u32): u32 { - std::macros::num_sqrt!(x, 32) - } + let bit = 1u64 << 32; + let res = 0u64; + let x = (x as u64); - /// Loops applying `$f` to each number from `$start` to `$stop` (exclusive) - public macro fun range_do($start: u32, $stop: u32, $f: |u32|) { - std::macros::range_do!($start, $stop, $f) - } - - /// Loops applying `$f` to each number from `$start` to `$stop` (inclusive) - public macro fun range_do_eq($start: u32, $stop: u32, $f: |u32|) { - std::macros::range_do_eq!($start, $stop, $f) - } - - /// Loops applying `$f` to each number from `0` to `$stop` (exclusive) - public macro fun do($stop: u32, $f: |u32|) { - std::macros::do!($stop, $f) - } + while (bit != 0) { + if (x >= res + bit) { + x = x - (res + bit); + res = (res >> 1) + bit; + } else { + res = res >> 1; + }; + bit = bit >> 2; + }; - /// Loops applying `$f` to each number from `0` to `$stop` (inclusive) - public macro fun do_eq($stop: u32, $f: |u32|) { - std::macros::do_eq!($stop, $f) + (res as u32) } } \ No newline at end of file diff --git a/frameworks/move-stdlib/sources/u64.move b/frameworks/move-stdlib/sources/u64.move index e16eba410d..d648988d88 100644 --- a/frameworks/move-stdlib/sources/u64.move +++ b/frameworks/move-stdlib/sources/u64.move @@ -5,27 +5,72 @@ module std::u64 { /// Return the larger of `x` and `y` public fun max(x: u64, y: u64): u64 { - std::macros::num_max!(x, y) + if (x > y) { + x + } else { + y + } } /// Return the smaller of `x` and `y` public fun min(x: u64, y: u64): u64 { - std::macros::num_min!(x, y) + if (x < y) { + x + } else { + y + } } /// Return the absolute value of x - y public fun diff(x: u64, y: u64): u64 { - std::macros::num_diff!(x, y) + if (x > y) { + x - y + } else { + y - x + } } /// Calculate x / y, but round up the result. public fun divide_and_round_up(x: u64, y: u64): u64 { - std::macros::num_divide_and_round_up!(x, y) + if (x % y == 0) { + x / y + } else { + x / y + 1 + } + } + + /// Returns x * y / z with as little loss of precision as possible and avoid overflow + public fun multiple_and_divide(x: u64, y: u64, z: u64): u64 { + if (y == z) { + x + } + if (x == z) { + y + } + + let a = x / z; + let b = x % z; + let c = y / z; + let d = y % z; + let res = a * c * z + a * d + b * c + b * d / z + + res } /// Return the value of a base raised to a power public fun pow(base: u64, exponent: u8): u64 { - std::macros::num_pow!(base, exponent) + let res = 1; + while (exponent >= 1) { + if (exponent % 2 == 0) { + base = base * base; + exponent = exponent / 2; + } else { + res = res * base; + exponent = exponent - 1; + } + }; + + res } /// Get a nearest lower integer Square Root for `x`. Given that this @@ -54,26 +99,20 @@ module std::u64 { /// math::sqrt(8 * 1000000) => 2828; // same as above, 2828 / 1000 (2.828) /// ``` public fun sqrt(x: u64): u64 { - std::macros::num_sqrt!(x, 64) - } + let bit = 1u128 << 64; + let res = 0u128; + let x = (x as u128); - /// Loops applying `$f` to each number from `$start` to `$stop` (exclusive) - public macro fun range_do($start: u64, $stop: u64, $f: |u64|) { - std::macros::range_do!($start, $stop, $f) - } - - /// Loops applying `$f` to each number from `$start` to `$stop` (inclusive) - public macro fun range_do_eq($start: u64, $stop: u64, $f: |u64|) { - std::macros::range_do_eq!($start, $stop, $f) - } - - /// Loops applying `$f` to each number from `0` to `$stop` (exclusive) - public macro fun do($stop: u64, $f: |u64|) { - std::macros::do!($stop, $f) - } + while (bit != 0) { + if (x >= res + bit) { + x = x - (res + bit); + res = (res >> 1) + bit; + } else { + res = res >> 1; + }; + bit = bit >> 2; + }; - /// Loops applying `$f` to each number from `0` to `$stop` (inclusive) - public macro fun do_eq($stop: u64, $f: |u64|) { - std::macros::do_eq!($stop, $f) + (res as u64) } } \ No newline at end of file diff --git a/frameworks/move-stdlib/sources/u8.move b/frameworks/move-stdlib/sources/u8.move index 08565783f7..efc84fce93 100644 --- a/frameworks/move-stdlib/sources/u8.move +++ b/frameworks/move-stdlib/sources/u8.move @@ -5,27 +5,72 @@ module std::u8 { /// Return the larger of `x` and `y` public fun max(x: u8, y: u8): u8 { - std::macros::num_max!(x, y) + if (x > y) { + x + } else { + y + } } /// Return the smaller of `x` and `y` public fun min(x: u8, y: u8): u8 { - std::macros::num_min!(x, y) + if (x < y) { + x + } else { + y + } } /// Return the absolute value of x - y public fun diff(x: u8, y: u8): u8 { - std::macros::num_diff!(x, y) + if (x > y) { + x - y + } else { + y - x + } } /// Calculate x / y, but round up the result. public fun divide_and_round_up(x: u8, y: u8): u8 { - std::macros::num_divide_and_round_up!(x, y) + if (x % y == 0) { + x / y + } else { + x / y + 1 + } + } + + /// Returns x * y / z with as little loss of precision as possible and avoid overflow + public fun multiple_and_divide(x: u8, y: u8, z: u8): u8 { + if (y == z) { + x + } + if (x == z) { + y + } + + let a = x / z; + let b = x % z; + let c = y / z; + let d = y % z; + let res = a * c * z + a * d + b * c + b * d / z + + res } /// Return the value of a base raised to a power public fun pow(base: u8, exponent: u8): u8 { - std::macros::num_pow!(base, exponent) + let res = 1; + while (exponent >= 1) { + if (exponent % 2 == 0) { + base = base * base; + exponent = exponent / 2; + } else { + res = res * base; + exponent = exponent - 1; + } + }; + + res } /// Get a nearest lower integer Square Root for `x`. Given that this @@ -54,26 +99,20 @@ module std::u8 { /// math::sqrt(8 * 1000000) => 2828; // same as above, 2828 / 1000 (2.828) /// ``` public fun sqrt(x: u8): u8 { - std::macros::num_sqrt!(x, 8) - } + let bit = 1u16 << 8; + let res = 0u16; + let x = (x as u16); - /// Loops applying `$f` to each number from `$start` to `$stop` (exclusive) - public macro fun range_do($start: u8, $stop: u8, $f: |u8|) { - std::macros::range_do!($start, $stop, $f) - } - - /// Loops applying `$f` to each number from `$start` to `$stop` (inclusive) - public macro fun range_do_eq($start: u8, $stop: u8, $f: |u8|) { - std::macros::range_do_eq!($start, $stop, $f) - } - - /// Loops applying `$f` to each number from `0` to `$stop` (exclusive) - public macro fun do($stop: u8, $f: |u8|) { - std::macros::do!($stop, $f) - } + while (bit != 0) { + if (x >= res + bit) { + x = x - (res + bit); + res = (res >> 1) + bit; + } else { + res = res >> 1; + }; + bit = bit >> 2; + }; - /// Loops applying `$f` to each number from `0` to `$stop` (inclusive) - public macro fun do_eq($stop: u8, $f: |u8|) { - std::macros::do_eq!($stop, $f) + (res as u8) } } \ No newline at end of file