-
Notifications
You must be signed in to change notification settings - Fork 2
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
Miscellaneous #121
Miscellaneous #121
Changes from all commits
5324608
639c8b1
eec5f46
ddad2b5
0341b00
2e653f5
46fbaed
dc2c6fa
01439d3
5b53de1
76f6347
bc25c0b
40e261b
0477b33
7cca0af
a026ed2
3334f44
84b166e
fd7e4c2
cc2e171
db8bfa1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,7 +32,7 @@ | |
/// let y = 0.3; | ||
/// | ||
/// let epsilon = 1e-6; // This depends on the application case (needs a numerical error analysis). | ||
/// Float.equalWithin(x, y, epsilon) // => true | ||
/// Float.equal(x, y, epsilon) // => true | ||
/// ``` | ||
/// | ||
/// * For absolute precision, it is recommened to encode the fraction number as a pair of a Nat for the base | ||
|
@@ -491,14 +491,6 @@ module { | |
/// ``` | ||
public let fromInt : Int -> Float = Prim.intToFloat; | ||
|
||
/// Returns `x == y`. | ||
/// @deprecated Use `Float.equalWithin()` as this function does not consider numerical errors. | ||
public func equal(x : Float, y : Float) : Bool { x == y }; | ||
|
||
/// Returns `x != y`. | ||
/// @deprecated Use `Float.notEqualWithin()` as this function does not consider numerical errors. | ||
public func notEqual(x : Float, y : Float) : Bool { x != y }; | ||
|
||
/// Determines whether `x` is equal to `y` within the defined tolerance of `epsilon`. | ||
/// The `epsilon` considers numerical erros, see comment above. | ||
/// Equivalent to `Float.abs(x - y) <= epsilon` for a non-negative epsilon. | ||
|
@@ -507,25 +499,25 @@ module { | |
/// | ||
/// Special cases: | ||
/// ``` | ||
/// equalWithin(+0.0, -0.0, epsilon) => true for any `epsilon >= 0.0` | ||
/// equalWithin(-0.0, +0.0, epsilon) => true for any `epsilon >= 0.0` | ||
/// equalWithin(+inf, +inf, epsilon) => true for any `epsilon >= 0.0` | ||
/// equalWithin(-inf, -inf, epsilon) => true for any `epsilon >= 0.0` | ||
/// equalWithin(x, NaN, epsilon) => false for any x and `epsilon >= 0.0` | ||
/// equalWithin(NaN, y, epsilon) => false for any y and `epsilon >= 0.0` | ||
/// equal(+0.0, -0.0, epsilon) => true for any `epsilon >= 0.0` | ||
/// equal(-0.0, +0.0, epsilon) => true for any `epsilon >= 0.0` | ||
/// equal(+inf, +inf, epsilon) => true for any `epsilon >= 0.0` | ||
/// equal(-inf, -inf, epsilon) => true for any `epsilon >= 0.0` | ||
/// equal(x, NaN, epsilon) => false for any x and `epsilon >= 0.0` | ||
/// equal(NaN, y, epsilon) => false for any y and `epsilon >= 0.0` | ||
/// ``` | ||
/// | ||
/// Example: | ||
/// ```motoko | ||
/// import Float "mo:base/Float"; | ||
/// | ||
/// let epsilon = 1e-6; | ||
/// Float.equalWithin(-12.3, -1.23e1, epsilon) // => true | ||
/// Float.equal(-12.3, -1.23e1, epsilon) // => true | ||
/// ``` | ||
public func equalWithin(x : Float, y : Float, epsilon : Float) : Bool { | ||
public func equal(x : Float, y : Float, epsilon : Float) : Bool { | ||
if (not (epsilon >= 0.0)) { | ||
// also considers NaN, not identical to `epsilon < 0.0` | ||
Prim.trap("epsilon must be greater or equal 0.0") | ||
Prim.trap("Float.equal(): epsilon must be greater or equal 0.0") | ||
}; | ||
x == y or abs(x - y) <= epsilon // `x == y` to also consider infinity equal | ||
}; | ||
|
@@ -538,23 +530,27 @@ module { | |
/// | ||
/// Special cases: | ||
/// ``` | ||
/// notEqualWithin(+0.0, -0.0, epsilon) => false for any `epsilon >= 0.0` | ||
/// notEqualWithin(-0.0, +0.0, epsilon) => false for any `epsilon >= 0.0` | ||
/// notEqualWithin(+inf, +inf, epsilon) => false for any `epsilon >= 0.0` | ||
/// notEqualWithin(-inf, -inf, epsilon) => false for any `epsilon >= 0.0` | ||
/// notEqualWithin(x, NaN, epsilon) => true for any x and `epsilon >= 0.0` | ||
/// notEqualWithin(NaN, y, epsilon) => true for any y and `epsilon >= 0.0` | ||
/// notEqual(+0.0, -0.0, epsilon) => false for any `epsilon >= 0.0` | ||
/// notEqual(-0.0, +0.0, epsilon) => false for any `epsilon >= 0.0` | ||
/// notEqual(+inf, +inf, epsilon) => false for any `epsilon >= 0.0` | ||
/// notEqual(-inf, -inf, epsilon) => false for any `epsilon >= 0.0` | ||
/// notEqual(x, NaN, epsilon) => true for any x and `epsilon >= 0.0` | ||
/// notEqual(NaN, y, epsilon) => true for any y and `epsilon >= 0.0` | ||
/// ``` | ||
/// | ||
/// Example: | ||
/// ```motoko | ||
/// import Float "mo:base/Float"; | ||
/// | ||
/// let epsilon = 1e-6; | ||
/// Float.notEqualWithin(-12.3, -1.23e1, epsilon) // => false | ||
/// Float.notEqual(-12.3, -1.23e1, epsilon) // => false | ||
/// ``` | ||
public func notEqualWithin(x : Float, y : Float, epsilon : Float) : Bool { | ||
not equalWithin(x, y, epsilon) | ||
public func notEqual(x : Float, y : Float, epsilon : Float) : Bool { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we even want There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems reasonable to remove this function. I'll merge and open another PR to start working on the merge conflicts in parallel. |
||
if (not (epsilon >= 0.0)) { | ||
// also considers NaN, not identical to `epsilon < 0.0` | ||
Prim.trap("Float.notEqual(): epsilon must be greater or equal 0.0") | ||
}; | ||
not (x == y or abs(x - y) <= epsilon) | ||
}; | ||
|
||
/// Returns `x < y`. | ||
|
@@ -632,8 +628,8 @@ module { | |
/// Defines a total order of `x` and `y` for use in sorting. | ||
/// | ||
/// Note: Using this operation to determine equality or inequality is discouraged for two reasons: | ||
/// * It does not consider numerical errors, see comment above. Use `equalWithin(x, y, espilon)` or | ||
/// `notEqualWithin(x, y, epsilon)` to test for equality or inequality, respectively. | ||
/// * It does not consider numerical errors, see comment above. Use `equal(x, y, espilon)` or | ||
/// `notEqual(x, y, epsilon)` to test for equality or inequality, respectively. | ||
/// * `NaN` are here considered equal if their sign matches, which is different to the standard equality | ||
/// by `==` or when using `equal()` or `notEqual()`. | ||
/// | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,29 +22,4 @@ module { | |
ha == hb | ||
}; | ||
|
||
/// Computes a hash from the least significant 32-bits of `n`, ignoring other bits. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we aren't going to even provide any hash based data structures (are we?) I'd be tempted to get rid of this whole module There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Opened a separate PR for this: #129. |
||
/// @deprecated For large `Nat` values consider using a bespoke hash function that considers all of the argument's bits. | ||
public func hash(n : Nat) : Hash { | ||
let j = Prim.intToNat32Wrap(n); | ||
hashNat8([ | ||
j & (255 << 0), | ||
j & (255 << 8), | ||
j & (255 << 16), | ||
j & (255 << 24) | ||
]) | ||
}; | ||
|
||
func hashNat8(key : [Hash]) : Hash { | ||
var hash : Nat32 = 0; | ||
for (natOfKey in key.vals()) { | ||
hash := hash +% natOfKey; | ||
hash := hash +% hash << 10; | ||
hash := hash ^ (hash >> 6) | ||
}; | ||
hash := hash +% hash << 3; | ||
hash := hash ^ (hash >> 11); | ||
hash := hash +% hash << 15; | ||
return hash | ||
}; | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@luc-blaeser are you ok with renaming equalWIthin (and notEqualWithin) to equal and notEqual?
Also another option might be to make both of these curried functions, that take the epsilon as a first argument and return an equality/inequality function of the usual binary type:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The motivation here is for API uniformity. I suppose we could curry the arguments, although I think
equal(x, y, epsilon)
is more consistent with how we handle thecompare
andequal
functions for data structures.On the other hand, it could be worth doing something different to reduce possible confusion about the argument order, given the
equal(Float, Float, Float)
signature.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I thinking about the situation where you want to pass the equality function as a first-class argument (which is why we define it for convenience...)
I don't have a strong opinion...