Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: update moc 0.13.4 #672

Merged
merged 3 commits into from
Nov 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ on:
# Remember to update me in package-set.yml as well
env:
vessel_version: "v0.7.0"
moc_version: "0.13.3"
moc_version: "0.13.4"

jobs:
tests:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/package-set.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:

env:
vessel_version: "v0.7.0"
moc_version: "0.13.3"
moc_version: "0.13.4"

jobs:
verify:
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
## 0.13.4

* Breaking change (minor): `Float.format(#hex)` is no longer supported.
This is because newer versions of Motoko (such as with enhanced orthogonal persistence)
rely on the Rust-native formatter that does not offer this functionality.
It is expected that this formatter is very rarely used in practice.

* Formatter change (minor): The text formatting of `NaN`, positive or negative,
will be `NaN` in newer Motoko versions, while it was `nan` or `-nan` in older versions.

## 0.13.3

* Add modules `OrderedMap` and `OrderedSet` to replace `RBTree` (thanks to Serokell) (#662).
Expand Down
4 changes: 2 additions & 2 deletions mops.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "base"
version = "0.13.3"
version = "0.13.4"
description = "The Motoko base library"
repository = "https://github.com/dfinity/motoko-base"
keywords = [ "base" ]
Expand All @@ -10,5 +10,5 @@ license = "Apache-2.0"
matchers = "https://github.com/kritzcreek/motoko-matchers#v1.3.0@3dac8a071b69e4e651b25a7d9683fe831eb7cffd"

[toolchain]
moc = "0.13.3"
moc = "0.13.4"
wasmtime = "17.0.0"
13 changes: 7 additions & 6 deletions src/Float.mo
Original file line number Diff line number Diff line change
Expand Up @@ -402,25 +402,26 @@ module {
/// * `#fix prec` as fixed-point format with `prec` digits
/// * `#exp prec` as exponential format with `prec` digits
/// * `#gen prec` as generic format with `prec` digits
/// * `#hex prec` as hexadecimal format with `prec` digits
/// * `#exact` as exact format that can be decoded without loss.
///
/// `-0.0` is formatted with negative sign bit.
/// Positive infinity is formatted as `inf`.
/// Negative infinity is formatted as `-inf`.
/// `NaN` is formatted as `NaN` or `-NaN` depending on its sign bit.
/// Positive infinity is formatted as "inf".
/// Negative infinity is formatted as "-inf".
///
/// Note: The numerical precision and the text format can vary between
/// Motoko versions and runtime configuration. Moreover, `NaN` can be printed
/// differently, i.e. "NaN" or "nan", potentially omitting the `NaN` sign.
///
/// Example:
/// ```motoko
/// import Float "mo:base/Float";
///
/// Float.format(#exp 3, 123.0) // => "1.230e+02"
/// ```
public func format(fmt : { #fix : Nat8; #exp : Nat8; #gen : Nat8; #hex : Nat8; #exact }, x : Float) : Text = switch fmt {
public func format(fmt : { #fix : Nat8; #exp : Nat8; #gen : Nat8; #exact }, x : Float) : Text = switch fmt {
case (#fix(prec)) { Prim.floatToFormattedText(x, prec, 0) };
case (#exp(prec)) { Prim.floatToFormattedText(x, prec, 1) };
case (#gen(prec)) { Prim.floatToFormattedText(x, prec, 2) };
case (#hex(prec)) { Prim.floatToFormattedText(x, prec, 3) };
case (#exact) { Prim.floatToFormattedText(x, 17, 2) }
};

Expand Down
134 changes: 66 additions & 68 deletions test/Float.test.mo
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import Debug "../src/Debug";
import Float "../src/Float";
import Text "../src/Text";

import Suite "mo:matchers/Suite";
import T "mo:matchers/Testable";
Expand Down Expand Up @@ -44,11 +45,11 @@ let positiveNaN = Float.copySign(0.0 / 0.0, 1.0);
let negativeNaN = Float.copySign(0.0 / 0.0, -1.0);

func isPositiveNaN(number : Float) : Bool {
debug_show (number) == "nan"
Float.isNaN(number) and Float.copySign(1.0, number) == 1.0
};

func isNegativeNaN(number : Float) : Bool {
debug_show (number) == "-nan"
Float.isNaN(number) and Float.copySign(1.0, number) == -1.0
};

let positiveZero = 0.0;
Expand Down Expand Up @@ -87,7 +88,7 @@ let smallEpsilon = 1e-6;

class NaNMatcher() : M.Matcher<Float> {
public func describeMismatch(number : Float, _description : M.Description) {
Debug.print(debug_show (number) # " should be 'nan' or '-nan'")
Debug.print(debug_show (number) # " should be 'NaN' or '-NaN'")
};

public func matches(number : Float) : Bool {
Expand All @@ -97,7 +98,7 @@ class NaNMatcher() : M.Matcher<Float> {

class PositiveNaNMatcher() : M.Matcher<Float> {
public func describeMismatch(number : Float, _description : M.Description) {
Debug.print(debug_show (number) # " should be 'nan' (positive)")
Debug.print(debug_show (number) # " should be 'NaN' (positive)")
};

public func matches(number : Float) : Bool {
Expand All @@ -107,14 +108,49 @@ class PositiveNaNMatcher() : M.Matcher<Float> {

class NegativeNaNMatcher() : M.Matcher<Float> {
public func describeMismatch(number : Float, _description : M.Description) {
Debug.print(debug_show (number) # " should be '-nan' (negative)")
Debug.print(debug_show (number) # " should be '-NaN' (negative)")
};

public func matches(number : Float) : Bool {
isNegativeNaN(number)
}
};

// The Rust float formatter prints `NaN`.
// The Musl float formatter prints `nan`.
class PositiveNaNTextMatcher() : M.Matcher<Text> {
public func describeMismatch(text : Text, _description : M.Description) {
Debug.print("'" # text # "' should be 'NaN' or 'nan', depending on the Motoko version and runtime configuration")
};

public func matches(text : Text) : Bool {
text == "NaN" or text == "nan"
}
};

// The Rust float formatter ignores the sign of NaN and emits `NaN`.
// The Musl float formatter prints `-nan`.
class NegativeNaNTextMatcher() : M.Matcher<Text> {
public func describeMismatch(text : Text, _description : M.Description) {
Debug.print("'" # text # "' should be 'NaN' or '-nan', depending on the Motoko version and runtime configuration")
};

public func matches(text : Text) : Bool {
text == "NaN" or text == "-nan"
}
};

// Account for different numerical errors becoming visible in float formatting.
class TextPrefixMatcher(prefix : Text) : M.Matcher<Text> {
public func describeMismatch(text : Text, _description : M.Description) {
Debug.print("'" # text # "' does not start with '" # prefix # "'")
};

public func matches(text : Text) : Bool {
Text.startsWith(text, #text prefix)
}
};

// Some tests are adopted from Motoko compiler test `float-ops.mo`.

/* --------------------------------------- */
Expand Down Expand Up @@ -1341,7 +1377,7 @@ run(
test(
"one",
Float.exp(1.0),
M.equals(FloatTestable(Float.e, noEpsilon))
M.equals(FloatTestable(Float.e, smallEpsilon))
),
test(
"positive infinity",
Expand Down Expand Up @@ -1431,22 +1467,22 @@ run(
test(
"exact positive",
Float.format(#exact, 20.12345678901),
M.equals(T.text("20.12345678901"))
TextPrefixMatcher("20.1234567890")
),
test(
"exact negative",
Float.format(#exact, -20.12345678901),
M.equals(T.text("-20.12345678901"))
TextPrefixMatcher("-20.1234567890")
),
test(
"exact positive zero",
Float.format(#exact, positiveZero),
M.equals(T.text("0"))
M.anyOf([M.equals(T.text("0")), M.equals(T.text("0.00000000000000000"))])
),
test(
"exact negative zero",
Float.format(#exact, negativeZero),
M.equals(T.text("-0"))
M.anyOf([M.equals(T.text("-0")), M.equals(T.text("-0.00000000000000000"))])
),
test(
"exact positive infinity",
Expand All @@ -1461,12 +1497,12 @@ run(
test(
"exact positive NaN",
Float.format(#exact, positiveNaN),
M.equals(T.text("nan"))
PositiveNaNTextMatcher()
),
test(
"exact negative NaN",
Float.format(#exact, negativeNaN),
M.equals(T.text("-nan"))
NegativeNaNTextMatcher()
),
test(
"fix positive",
Expand Down Expand Up @@ -1501,32 +1537,32 @@ run(
test(
"fix positive NaN",
Float.format(#fix 6, positiveNaN),
M.equals(T.text("nan"))
PositiveNaNTextMatcher()
),
test(
"fix negative NaN",
Float.format(#fix 6, negativeNaN),
M.equals(T.text("-nan"))
NegativeNaNTextMatcher()
),
test(
"exp positive",
Float.format(#exp 9, 20.12345678901),
M.equals(T.text("2.012345679e+01"))
M.anyOf([M.equals(T.text("2.012345679e1")), M.equals(T.text("2.012345679e+01"))])
),
test(
"exp negative",
Float.format(#exp 9, -20.12345678901),
M.equals(T.text("-2.012345679e+01"))
M.anyOf([M.equals(T.text("-2.012345679e1")), M.equals(T.text("-2.012345679e+01"))])
),
test(
"exp positive zero",
Float.format(#exp 9, positiveZero),
M.equals(T.text("0.000000000e+00"))
M.anyOf([M.equals(T.text("0.000000000e0")), M.equals(T.text("0.000000000e+00"))])
),
test(
"exp negative zero",
Float.format(#exp 9, negativeZero),
M.equals(T.text("-0.000000000e+00"))
M.anyOf([M.equals(T.text("-0.000000000e0")), M.equals(T.text("-0.000000000e+00"))])
),
test(
"exp positive infinity",
Expand All @@ -1541,32 +1577,32 @@ run(
test(
"exp positive NaN",
Float.format(#exp 9, positiveNaN),
M.equals(T.text("nan"))
PositiveNaNTextMatcher()
),
test(
"exp negative NaN",
Float.format(#exp 9, negativeNaN),
M.equals(T.text("-nan"))
NegativeNaNTextMatcher()
),
test(
"gen positive",
Float.format(#gen 12, 20.12345678901),
M.equals(T.text("20.123456789"))
TextPrefixMatcher("20.123456789")
),
test(
"gen negative",
Float.format(#gen 12, -20.12345678901),
M.equals(T.text("-20.123456789"))
TextPrefixMatcher("-20.123456789")
),
test(
"gen positive zero",
Float.format(#gen 12, positiveZero),
M.equals(T.text("0"))
M.anyOf([M.equals(T.text("0")), M.equals(T.text("0.000000000000"))])
),
test(
"gen negative zero",
Float.format(#gen 12, negativeZero),
M.equals(T.text("-0"))
M.anyOf([M.equals(T.text("-0")), M.equals(T.text("-0.000000000000"))])
),
test(
"gen positive infinity",
Expand All @@ -1581,53 +1617,15 @@ run(
test(
"gen positive NaN",
Float.format(#gen 12, positiveNaN),
M.equals(T.text("nan"))
PositiveNaNTextMatcher()
),
test(
"gen negative NaN",
Float.format(#gen 12, negativeNaN),
M.equals(T.text("-nan"))
),
test(
"hex positive",
Float.format(#hex 10, 20.12345678901),
M.equals(T.text("0x1.41f9add374p+4"))
NegativeNaNTextMatcher()
),
test(
"hex negative",
Float.format(#hex 10, -20.12345678901),
M.equals(T.text("-0x1.41f9add374p+4"))
),
test(
"hex positive zero",
Float.format(#hex 10, positiveZero),
M.equals(T.text("0x0.0000000000p+0"))
),
test(
"hex negative zero",
Float.format(#hex 10, negativeZero),
M.equals(T.text("-0x0.0000000000p+0"))
),
test(
"hex positive infinity",
Float.format(#hex 10, positiveInfinity),
M.equals(T.text("inf"))
),
test(
"hex negative infinity",
Float.format(#hex 10, negativeInfinity),
M.equals(T.text("-inf"))
),
test(
"hex positive NaN",
Float.format(#hex 10, positiveNaN),
M.equals(T.text("nan"))
),
test(
"hex negative NaN",
Float.format(#hex 10, negativeNaN),
M.equals(T.text("-nan"))
)
// hex float formatting was only supported with Musl
// and is no longer supported with Rust-implemented formatter.
]
)
);
Expand Down Expand Up @@ -1671,12 +1669,12 @@ run(
test(
"positive NaN",
Float.toText(positiveNaN),
M.equals(T.text("nan"))
PositiveNaNTextMatcher()
),
test(
"negative NaN",
Float.toText(negativeNaN),
M.equals(T.text("-nan"))
NegativeNaNTextMatcher()
)
]
)
Expand Down
Loading