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