opEquals/opCmp returning other types
Simen Kjærås
simen.kjaras at gmail.com
Mon Mar 19 10:28:00 PDT 2012
On Mon, 19 Mar 2012 09:29:34 +0100, Timon Gehr <timon.gehr at gmx.ch> wrote:
> The current limitations make it impossible to define (for example) a
> floating point type with NaN that behaves like built-in
> float/double/real.
As it turns out, this is possible. opCmp can return a float, and
things work just fine (!<, !>=, etc). The problem appears with
opEquals.
This is the generated assembly:
fldz
fucompp
fnstsw ax
sahf
jne <somewhere>
So it compares the result to 0.0, copies status flags to the CPU,
then checks if any of the flags are set. If the returned value *is*
equal to 0.0, the C3 flag is set. The result is that the jump is
taken only when the returned value is *less* than 0.0. I have a
feeling this is wrong. Should I file this in BugZilla?
Anyways. With this newly-won knowledge, we can design an opEquals
that returns a float, and behaves correctly (until the above bug
[if I'm right] is fixed):
struct MyInt {
int n;
float opEquals(MyInt other) const {
if (n == int.min || other.n == int.min) {
return float.nan;
}
return n == other.n ? -1.0 : 1.0; // Note workaround.
//return n - other.n; // Should work.
}
float opCmp(MyInt other) const {
if (n == int.min || other.n == int.min) {
return float.nan;
}
return n - other.n;
}
}
unittest {
assert( MyInt(int.min) != MyInt(int.min) );
assert( MyInt(0) == MyInt(0) );
assert( MyInt(int.min) !< MyInt(0) );
assert( MyInt(int.min) !> MyInt(0) );
assert( MyInt(int.min) !<= MyInt(0) );
assert( MyInt(int.min) !>= MyInt(0) );
assert( MyInt(0) !< MyInt(int.min) );
assert( MyInt(0) !> MyInt(int.min) );
assert( MyInt(0) !<= MyInt(int.min) );
assert( MyInt(0) !>= MyInt(int.min) );
assert( MyInt(1) > MyInt(0) );
assert( MyInt(1) >= MyInt(0) );
assert( MyInt(0) < MyInt(1) );
assert( MyInt(0) <= MyInt(1) );
}
More information about the Digitalmars-d
mailing list