max() in phobos?

Sean Kelly sean at f4.ca
Tue Nov 7 22:41:58 PST 2006


Bill Baxter wrote:
> Sean Kelly wrote:
>> Bill Baxter wrote:
>>
>>> Is there a generic 'max' function anywhere in phobos?
>>> The closest I could find was std.math.fmax().
>>
>>
>> Not that works for all input types, as far as I know.  However, 
>> something like the code below should work.  This is off the top of my 
>> head so it may have bugs, but it's a general idea of what such a 
>> template function may need to do.
> 
> Great!  How do we get it into std.math?
> 
> Here's one with the typos fixed and unittests:

I rewrote the code to work a bit better and added some more tests. 
However, I think it should probably error when comparing a signed and 
unsigned integer type.  At the moment, it accepts this and the choice of 
return type is somewhat arbitrary.  Also, I haven't tested interfaces 
and am not sure they should be comparable anyway, but I added support 
for them for the heck of it.  I'd play with it a bit more but I'm tired 
and bed is calling :-)


template commonBaseTypeOf( T, U )
{
     static assert( ( is( T == class )     && is( U == class ) ) ||
                    ( is( T == interface ) && is( U == interface ) ),
                    "Supplied types are not siblings." );

     static if( is( T : U ) )
         alias U commonBaseTypeOf;
     else static if( is( U : T ) )
         alias T commonBaseTypeOf;
     else static if( is( T == class ) )
         alias Object commonBaseTypeOf;
     else
         static assert( false, "Interfaces have no generic parent." );
}

template bestCommonTypeOf( T, U )
{
     static if( is( T == class )     || is( U == class ) ||
                is( T == interface ) || is( U == interface ) )
     {
         alias commonBaseTypeOf!( T, U ) bestCommonTypeOf;
     }
     else static if( is( T : U ) && is( U : T ) )
     {
         static if( T.sizeof >= U.sizeof )
             alias T bestCommonTypeOf;
         else
             alias U bestCommonTypeOf;
     }
     else static if( is( U : T ) )
         alias T bestCommonTypeOf;
     else static if( is( T : U ) )
         alias U bestCommonTypeOf;
     else
         static assert( false, "Unable to find common type." );
}

template min( T, U )
{
     bestCommonTypeOf!(T, U) min( T t, U u )
     {
         alias bestCommonTypeOf!(T, U) rt;
         if( cast(rt) t < cast(rt) u )
             return t;
         return u;
     }
}

template max( T, U )
{
     bestCommonTypeOf!(T, U) max( T t, U u )
     {
         alias bestCommonTypeOf!(T, U) rt;
         if( cast(rt) t > cast(rt) u )
             return t;
         return u;
     }
}

unittest
{
     int ismall=1, ibig=5;
     byte bsmall=1, bbig=5;
     float fsmall=1, fbig=5;
     double dsmall=1, dbig=5;
     assert(max(ibig,ismall)==ibig);
     assert(max(ismall,ibig)==ibig);
     assert(min(ibig,ismall)==ismall);
     assert(min(ismall,ibig)==ismall);

     assert(max(fbig,fsmall)==fbig);
     assert(max(fsmall,fbig)==fbig);
     assert(min(fbig,fsmall)==fsmall);
     assert(min(fsmall,fbig)==fsmall);

     assert(min(dsmall,fbig)==dsmall);
     assert(max(dsmall,fbig)==fbig);
     assert(min(dbig,fsmall)==fsmall);
     assert(max(dbig,fsmall)==dbig);

     assert( is(typeof(min(dsmall,fbig)) == double) );
     assert( is(typeof(max(dsmall,fbig)) == double) );
     assert( is(typeof(min(dbig,fsmall)) == double) );
     assert( is(typeof(max(dbig,fsmall)) == double) );

     assert( is(typeof(min(bsmall,ibig))==int) );
     assert( is(typeof(max(bsmall,ibig))==int) );
     assert( is(typeof(min(bbig,ismall))==int) );
     assert( is(typeof(max(bbig,ismall))==int) );

     class B
     {
         this( int v )
         {
             value = v;
         }

         int opCmp( B rhs )
         {
             return value - rhs.value;
         }

         int opCmp( Object rhs )
         {
             return opCmp( cast(B) rhs );
         }

         private int value;
     }

     class C : B
     {
         this( int v )
         {
             super( v );
         }
     }

     class D : B
     {
         this( int v )
         {
             super( v );
         }
     }

     // BUG? what to do about implicit signed-unsigned conversion?
     static assert( is( bestCommonTypeOf!( int, uint ) == int ) );
     static assert( is( bestCommonTypeOf!( uint, int ) == uint ) );

     static assert( is( bestCommonTypeOf!( byte, long ) == long ) );
     static assert( is( bestCommonTypeOf!( long, byte ) == long ) );
     static assert( is( bestCommonTypeOf!( long, float ) == float ) );
     static assert( is( bestCommonTypeOf!( float, long ) == float ) );
     static assert( is( bestCommonTypeOf!( float, real ) == real ) );
     static assert( is( bestCommonTypeOf!( cfloat, creal ) == creal ) );
     static assert( is( bestCommonTypeOf!( creal, cfloat ) == creal ) );

     static assert( is( bestCommonTypeOf!( B, C ) == B ) );
     static assert( is( bestCommonTypeOf!( C, B ) == B ) );
     static assert( is( bestCommonTypeOf!( C, D ) == Object ) );
     static assert( is( bestCommonTypeOf!( D, C ) == Object ) );

     B b = new B( 1 );
     C c = new C( 2 );
     D d = new D( 3 );

     assert( min( b, c ) == b );
     assert( max( b, c ) == c );
     assert( min( c, d ) == c );
     assert( max( c, d ) == d );
}



More information about the Digitalmars-d-learn mailing list