Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Cost.h

    r9504a89 rddf8a29  
    77// Cost.h --
    88//
    9 // Author           : Peter Buhr and Aaron Moss
     9// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 09:39:50 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Jun 21 11:39:13 2019
    13 // Update Count     : 63
     12// Last Modified On : Sat Jul 22 09:35:55 2017
     13// Update Count     : 5
    1414//
    1515
     
    1717
    1818#include <iostream>
    19 #include <cassert>
    20 #include <climits>
    2119
    2220namespace ResolvExpr {
    23         // To maximize performance and space, the 7 resolution costs are packed into a single 64-bit word. However, the
    24         // specialization cost is a negative value so a correction is needed is a few places.
     21        class Cost {
     22          private:
     23                Cost( int unsafeCost, int polyCost, int safeCost, int referenceCost );
    2524
    26         class Cost {
    27                 union {
    28                         struct {
    29                         #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
    30                                 // Little-endian => first value is low priority and last is high priority.
    31                                 unsigned char padding;                                  ///< unused
    32                                 unsigned char referenceCost;                    ///< reference conversions
    33                                 unsigned char specCost;                                 ///< Polymorphic type specializations (type assertions), negative cost
    34                                 unsigned char varCost;                                  ///< Count of polymorphic type variables
    35                                 unsigned char signCost;                                 ///< Count of safe sign conversions
    36                                 unsigned char safeCost;                                 ///< Safe (widening) conversions
    37                                 unsigned char polyCost;                                 ///< Count of parameters and return values bound to some poly type
    38                                 unsigned char unsafeCost;                               ///< Unsafe (narrowing) conversions
    39                         #else
    40                                 #error Cost BIG_ENDIAN unsupported
    41                         #endif
    42                         } v;
    43                         uint64_t all;
    44                 };
    45                 static const unsigned char correctb = 0xff;             // byte correction for negative spec cost
    46                 static const uint64_t correctw = 0x00'00'00'00'00'ff'00'00; //' word correction for negative spec cost
    4725          public:
    48                 // Compiler adjusts constants for correct endian.
    49                 enum : uint64_t {
    50                         zero      = 0x00'00'00'00'00'ff'00'00,
    51                         infinity  = 0xff'ff'ff'ff'ff'00'ff'ff,
    52                         unsafe    = 0x01'00'00'00'00'ff'00'00,
    53                         poly      = 0x00'01'00'00'00'ff'00'00,
    54                         safe      = 0x00'00'01'00'00'ff'00'00,
    55                         sign      = 0x00'00'00'01'00'ff'00'00,
    56                         var       = 0x00'00'00'00'01'ff'00'00,
    57                         spec      = 0x00'00'00'00'00'fe'00'00,
    58                         reference = 0x00'00'00'00'00'ff'01'00,
    59                 }; //'
     26                Cost & incUnsafe( int inc = 1 );
     27                Cost & incPoly( int inc = 1 );
     28                Cost & incSafe( int inc = 1 );
     29                Cost & incReference( int inc = 1 );
    6030
    61                 Cost( uint64_t all ) { Cost::all = all; }
    62                 Cost( int unsafeCost, int polyCost, int safeCost, int signCost, int varCost, int specCost, int referenceCost ) {
    63                         // Assume little-endian => first value is low priority and last is high priority.
    64                         v = {
    65                         #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
    66                                 (unsigned char)0,                                               // padding
    67                                 (unsigned char)referenceCost,                   // low priority
    68                                 (unsigned char)(specCost + correctb),   // correct for signedness
    69                                 (unsigned char)varCost,
    70                                 (unsigned char)signCost,
    71                                 (unsigned char)safeCost,
    72                                 (unsigned char)polyCost,
    73                                 (unsigned char)unsafeCost,                              // high priority
    74                         #else
    75                                 #error Cost BIG_ENDIAN unsupported
    76                         #endif
    77                         };
    78                 }
     31                int get_unsafeCost() const { return unsafeCost; }
     32                int get_polyCost() const { return polyCost; }
     33                int get_safeCost() const { return safeCost; }
     34                int get_referenceCost() const { return referenceCost; }
    7935
    80                 int get_unsafeCost() const { return v.unsafeCost; }
    81                 int get_polyCost() const { return v.polyCost; }
    82                 int get_safeCost() const { return v.safeCost; }
    83                 int get_signCost() const { return v.signCost; }
    84                 int get_varCost() const { return v.varCost; }
    85                 int get_specCost() const { return -(correctb - v.specCost); }
    86                 int get_referenceCost() const { return v.referenceCost; }
     36                Cost operator+( const Cost &other ) const;
     37                Cost operator-( const Cost &other ) const;
     38                Cost &operator+=( const Cost &other );
     39                bool operator<( const Cost &other ) const;
     40                bool operator==( const Cost &other ) const;
     41                bool operator!=( const Cost &other ) const;
     42                friend std::ostream &operator<<( std::ostream &os, const Cost &cost );
    8743
    88                 friend bool operator==( const Cost, const Cost );
    89                 friend bool operator!=( const Cost lhs, const Cost rhs );
    90                 // returns negative for *this < rhs, 0 for *this == rhs, positive for *this > rhs
    91                 int compare( const Cost rhs ) const {
    92                         if ( all == infinity ) return 1;
    93                         if ( rhs.all == infinity ) return -1;
    94                         return all > rhs.all ? 1 : all == rhs.all ? 0 : -1;
    95                 }
    96                 friend bool operator<( const Cost lhs, const Cost rhs );
     44                static const Cost zero;
     45                static const Cost infinity;
    9746
    98                 friend Cost operator+( const Cost lhs, const Cost rhs );
    99  
    100                 Cost operator+=( const Cost rhs ) {
    101                         if ( all == infinity ) return *this;
    102                         if ( rhs.all == infinity ) {
    103                                 all = infinity;
    104                                 return *this;
    105                         }
    106                         all += rhs.all - correctw;                                      // correct for negative spec cost
     47                static const Cost unsafe;
     48                static const Cost poly;
     49                static const Cost safe;
     50                static const Cost reference;
     51          private:
     52                int compare( const Cost &other ) const;
     53
     54                int unsafeCost;
     55                int polyCost;
     56                int safeCost;
     57                int referenceCost;
     58        };
     59
     60        inline Cost::Cost( int unsafeCost, int polyCost, int safeCost, int referenceCost ) : unsafeCost( unsafeCost ), polyCost( polyCost ), safeCost( safeCost ), referenceCost( referenceCost ) {}
     61
     62        inline Cost & Cost::incUnsafe( int inc ) {
     63                if ( *this == infinity ) return *this;
     64                unsafeCost += inc;
     65                return *this;
     66        }
     67
     68        inline Cost & Cost::incPoly( int inc ) {
     69                if ( *this == infinity ) return *this;
     70                polyCost += inc;
     71                return *this;
     72        }
     73
     74        inline Cost & Cost::incSafe( int inc ) {
     75                if ( *this == infinity ) return *this;
     76                safeCost += inc;
     77                return *this;
     78        }
     79
     80        inline Cost & Cost::incReference( int inc ) {
     81                if ( *this == infinity ) return *this;
     82                referenceCost += inc;
     83                return *this;
     84        }
     85
     86        inline Cost Cost::operator+( const Cost &other ) const {
     87                if ( *this == infinity || other == infinity ) return infinity;
     88                return Cost( unsafeCost + other.unsafeCost, polyCost + other.polyCost, safeCost + other.safeCost, referenceCost + other.referenceCost );
     89        }
     90
     91        inline Cost Cost::operator-( const Cost &other ) const {
     92                if ( *this == infinity || other == infinity ) return infinity;
     93                return Cost( unsafeCost - other.unsafeCost, polyCost - other.polyCost, safeCost - other.safeCost, referenceCost - other.referenceCost );
     94        }
     95
     96        inline Cost &Cost::operator+=( const Cost &other ) {
     97                if ( *this == infinity ) return *this;
     98                if ( other == infinity ) {
     99                        *this = infinity;
    107100                        return *this;
    108101                }
    109 
    110                 Cost incUnsafe( int inc = 1 ) {
    111                         if ( all != infinity ) { assert( v.unsafeCost + inc <= UCHAR_MAX ); v.unsafeCost += inc; }
    112                         return *this;
    113                 }
    114 
    115                 Cost incPoly( int inc = 1 ) {
    116                         if ( all != infinity ) { assert( v.polyCost + inc <= UCHAR_MAX ); v.polyCost += inc; }
    117                         return *this;
    118                 }
    119 
    120                 Cost incSafe( int inc = 1 ) {
    121                         if ( all != infinity ) { assert( v.safeCost + inc <= UCHAR_MAX ); v.safeCost += inc; }
    122                         return *this;
    123                 }
    124 
    125                 Cost incSign( int inc = 1 ) {
    126                         if ( all != infinity ) { assert( v.signCost + inc <= UCHAR_MAX ); v.signCost += inc; }
    127                         return *this;
    128                 }
    129 
    130                 Cost incVar( int inc = 1 ) {
    131                         if ( all != infinity ) { assert( v.varCost + inc <= UCHAR_MAX ); v.varCost += inc; }
    132                         return *this;
    133                 }
    134 
    135                 Cost decSpec( int dec = 1 ) {
    136                         if ( all != infinity ) { assert( v.specCost - dec >= 0 ); v.specCost -= dec; }
    137                         return *this;
    138                 }
    139 
    140                 Cost incReference( int inc = 1 ) {
    141                         if ( all != infinity ) { assert( v.referenceCost + inc <= UCHAR_MAX ); v.referenceCost += inc; }
    142                         return *this;
    143                 }
    144 
    145                 friend std::ostream & operator<<( std::ostream & os, const Cost cost );
    146         };
    147 
    148         inline bool operator==( const Cost lhs, const Cost rhs ) {
    149                 return lhs.all == rhs.all;
     102                unsafeCost += other.unsafeCost;
     103                polyCost += other.polyCost;
     104                safeCost += other.safeCost;
     105                referenceCost += other.referenceCost;
     106                return *this;
    150107        }
    151108
    152         inline bool operator!=( const Cost lhs, const Cost rhs ) {
    153                 return !( lhs.all == rhs.all );
     109        inline bool Cost::operator<( const Cost &other ) const {
     110                if ( *this == infinity ) return false;
     111                if ( other == infinity ) return true;
     112
     113                if ( unsafeCost > other.unsafeCost ) {
     114                        return false;
     115                } else if ( unsafeCost < other.unsafeCost ) {
     116                        return true;
     117                } else if ( polyCost > other.polyCost ) {
     118                        return false;
     119                } else if ( polyCost < other.polyCost ) {
     120                        return true;
     121                } else if ( safeCost > other.safeCost ) {
     122                        return false;
     123                } else if ( safeCost < other.safeCost ) {
     124                        return true;
     125                } else if ( referenceCost > other.referenceCost ) {
     126                        return false;
     127                } else if ( referenceCost < other.referenceCost ) {
     128                        return true;
     129                } else {
     130                        return false;
     131                } // if
    154132        }
    155133
    156         inline bool operator<( const Cost lhs, const Cost rhs ) {
    157                 if ( lhs.all == Cost::infinity ) return false;
    158                 if ( rhs.all == Cost::infinity ) return true;
    159                 return lhs.all < rhs.all;
     134        inline bool Cost::operator==( const Cost &other ) const {
     135                return unsafeCost == other.unsafeCost
     136                        && polyCost == other.polyCost
     137                        && safeCost == other.safeCost
     138                        && referenceCost == other.referenceCost;
    160139        }
    161140
    162         inline Cost operator+( const Cost lhs, const Cost rhs ) {
    163                 if ( lhs.all == Cost::infinity || rhs.all == Cost::infinity ) return Cost{ Cost::infinity };
    164                 return Cost{ lhs.all + rhs.all - Cost::correctw }; // correct for negative spec cost
     141        inline bool Cost::operator!=( const Cost &other ) const {
     142                return !( *this == other );
    165143        }
    166144
    167         inline std::ostream & operator<<( std::ostream & os, const Cost cost ) {
    168                 return os << "( " << cost.get_unsafeCost() << ", " << cost.get_polyCost() << ", " << cost.get_safeCost()
    169                                   << ", " << cost.get_signCost() << ", " << cost.get_varCost() << ", " << cost.get_specCost()
    170                                   << ", " << cost.get_referenceCost() << " )";
     145        inline std::ostream &operator<<( std::ostream &os, const Cost &cost ) {
     146                os << "( " << cost.unsafeCost << ", " << cost.polyCost << ", " << cost.safeCost << ", " << cost.referenceCost << " )";
     147                return os;
    171148        }
    172149} // namespace ResolvExpr
Note: See TracChangeset for help on using the changeset viewer.