pub struct Tol {
pub ct: f64,
pub by_smaller: bool,
pub floor_rule: FloorRule,
}Expand description
How close two floats have to be to count as equal.
Both languages compare reals with a relative tolerance: J’s 9!:18
comparison tolerance, APL’s ⎕CT. Two values are equal when they differ
by less than the tolerance scaled by one of their magnitudes — the
smaller one in J, the larger one in APL. Both references answer strictly:
a difference exactly at the threshold is not equal. Integers, characters
and boxes are unaffected, and an exact bit-for-bit equality (the
infinities included) is equality whatever the tolerance is.
Fields§
§ct: f64Relative tolerance; zero compares exactly.
by_smaller: boolScale by the smaller magnitude (J) rather than the larger (APL).
floor_rule: FloorRuleWhich reading ⌊ and ⌈ take. Unread under J, whose floor is
the tolerant comparison itself.
Implementations§
Source§impl Tol
impl Tol
Sourcepub fn is_j(self) -> bool
pub fn is_j(self) -> bool
Whose rule this is. A scalar verb is handed the tolerance and nothing else about the dialect, and two rules below need to know which one they are under: J reads a magnitude below the tolerance as zero, and J’s equality is total across the box boundary where APL’s reaches inside the box instead.
Sourcepub fn is_zero(self, y: f64) -> bool
pub fn is_zero(self, y: f64) -> bool
Whether the tolerance reads this magnitude as zero.
J’s signum does: * 1e_15 is 0 and * 6e_14 is 1, the threshold
being the tolerance itself. APL’s × is exact there. With !.0 the
tolerance is zero, so the rule falls away with it.
Sourcepub fn eq_cx(self, a: Cx, b: Cx) -> bool
pub fn eq_cx(self, a: Cx, b: Cx) -> bool
Tolerant equality on complex values: the magnitude of the difference
against the same scale the real comparison uses. J answers
3j4 = 3.0000000000001j4 with 1, which is this rule on magnitudes.
Sourcepub fn floor(self, y: f64) -> f64
pub fn floor(self, y: f64) -> f64
<. y: the largest integer not above y, with a value just under an
integer counting as that integer.
The three readings were each probed. J scales the gap by the
magnitude, so <. 99.999999999995 is 100 and <. _1e_14 is _1.
GNU APL shifts by the tolerance itself, so ⌊99.999999999995 is 99
— the gap of 5e¯12 is larger than ⎕CT however big the value is —
while ⌊¯1E¯13 is 0. Dyalog scales the shift by the magnitude but
never below 1, which keeps ⌊¯1E¯14 at 0 and lifts
⌊9.9999999999999 to 10.
Sourcepub fn ceil(self, y: f64) -> f64
pub fn ceil(self, y: f64) -> f64
>. y: the ceiling, with a value just over an integer counting as
that integer. The three readings are Tol::floor’s, mirrored.
Sourcepub fn residue(self, x: f64, y: f64) -> f64
pub fn residue(self, x: f64, y: f64) -> f64
x | y: the remainder of y on division by x, with the quotient read
tolerantly. Both references round the quotient before subtracting,
which is what makes 0.1|0.3 zero rather than a rounding error, and
each rounds it its own way.
J takes the tolerant floor of the quotient and then answers an exact
zero whenever the product is tolerantly the dividend: 2 | 1e_14 is
1e_14 (the quotient is nowhere near an integer) while
2 | 4 + 1e_14 is 0 (the product 4 is tolerantly the dividend).
GNU APL reads the remainder against the MODULUS instead: a remainder
within ⎕CT of the modulus’s magnitude is zero, so 2|1E¯14 is 0
where J keeps the 1e_14. A remainder that rounding has pushed out
of [0, x) comes back into range.
Sourcepub fn mul(self, x: f64, y: f64) -> f64
pub fn mul(self, x: f64, y: f64) -> f64
x * y, with J’s rule that a zero factor wins.
J defines 0 * _ as 0 where IEEE arithmetic has no value for it, and
the rule is the factor’s, not the product’s: 0 * _. is 0 too, and
*/ 0 , _ is 0. It is also what gives j. _ its value, because a
complex product is four real ones and _ * 0j1 is 0j_ only when
each of them follows this rule. APL never meets the case — GNU APL
refuses an infinite operand to × outright — so the rule is J’s
alone and a finite pair is untouched, negative zero included.
Sourcepub fn made_nan(self, r: f64, x: f64, y: f64) -> bool
pub fn made_nan(self, r: f64, x: f64, y: f64) -> bool
Whether a result must be refused because the arithmetic MADE this
NaN: J answers _ - _, _ % _, 2 | _, 0 ^. 0 and ! __ with a
NaN error, while a NaN the program itself wrote travels on unrefused
(_. + 1 is _.). Distinguishing the two is exactly the operand
test below. APL never reaches a NaN with a value of its own, so the
rule stays J’s.
Trait Implementations§
impl Copy for Tol
impl StructuralPartialEq for Tol
Auto Trait Implementations§
impl Freeze for Tol
impl RefUnwindSafe for Tol
impl Send for Tol
impl Sync for Tol
impl Unpin for Tol
impl UnsafeUnpin for Tol
impl UnwindSafe for Tol
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more