Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/Cost.h

    rb10c39a0 rd97c3a4  
    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
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Apr 29 18:33:44 2019
    13 // Update Count     : 49
     11// Last Modified By : Aaron B. Moss
     12// Last Modified On : Fri Oct 05 14:32:00 2018
     13// Update Count     : 7
    1414//
    1515
     
    1717
    1818#include <iostream>
    19 #include <cassert>
    20 #include <climits>
    2119
    2220namespace ResolvExpr {
    23 #if 0
    24 
    25         //*************************** OLD ***************************
    26 
    2721        class Cost {
    2822          private:
    29                 Cost( int unsafeCost, int polyCost, int safeCost, int signCost,
    30                           int varCost, int specCost, int referenceCost );
     23                Cost( int unsafeCost, int polyCost, int safeCost, int varCost, int specCost,
     24                        int referenceCost );
     25
    3126          public:
    3227                Cost & incUnsafe( int inc = 1 );
    3328                Cost & incPoly( int inc = 1 );
    3429                Cost & incSafe( int inc = 1 );
    35                 Cost & incSign( int inc = 1 );
    3630                Cost & incVar( int inc = 1 );
    3731                Cost & decSpec( int inc = 1 );
     
    4135                int get_polyCost() const { return polyCost; }
    4236                int get_safeCost() const { return safeCost; }
    43                 int get_signCost() const { return signCost; }
    4437                int get_varCost() const { return varCost; }
    4538                int get_specCost() const { return specCost; }
     
    4740
    4841                Cost operator+( const Cost &other ) const;
     42                Cost operator-( const Cost &other ) const;
    4943                Cost &operator+=( const Cost &other );
    5044                bool operator<( const Cost &other ) const;
     
    6155                static const Cost poly;
    6256                static const Cost safe;
    63                 static const Cost sign;
    6457                static const Cost var;
    6558                static const Cost spec;
     
    7063                int polyCost;       ///< Count of parameters and return values bound to some poly type
    7164                int safeCost;       ///< Safe (widening) conversions
    72                 int signCost;       ///< Count of safe sign conversions
    7365                int varCost;        ///< Count of polymorphic type variables
    7466                int specCost;       ///< Polymorphic type specializations (type assertions), negative cost
     
    7668        };
    7769
    78         inline Cost::Cost( int unsafeCost, int polyCost, int safeCost, int signCost,
    79                                            int varCost, int specCost, int referenceCost )
    80                 : unsafeCost( unsafeCost ), polyCost( polyCost ), safeCost( safeCost ), signCost( signCost ),
    81                   varCost( varCost ), specCost( specCost ), referenceCost( referenceCost ) {}
     70        inline Cost::Cost( int unsafeCost, int polyCost, int safeCost, int varCost, int specCost,
     71                        int referenceCost )
     72                : unsafeCost( unsafeCost ), polyCost( polyCost ), safeCost( safeCost ), varCost( varCost ),
     73                  specCost( specCost ), referenceCost( referenceCost ) {}
    8274
    8375        inline Cost & Cost::incUnsafe( int inc ) {
     
    9688                if ( *this == infinity ) return *this;
    9789                safeCost += inc;
    98                 return *this;
    99         }
    100 
    101         inline Cost & Cost::incSign( int inc ) {
    102                 if ( *this == infinity ) return *this;
    103                 signCost += inc;
    10490                return *this;
    10591        }
     
    125111        inline Cost Cost::operator+( const Cost &other ) const {
    126112                if ( *this == infinity || other == infinity ) return infinity;
    127                 return Cost{
    128                         unsafeCost + other.unsafeCost, polyCost + other.polyCost, safeCost + other.safeCost,
    129                                 signCost + other.signCost, varCost + other.varCost, specCost + other.specCost,
    130                                 referenceCost + other.referenceCost };
     113                return Cost{
     114                        unsafeCost + other.unsafeCost, polyCost + other.polyCost, safeCost + other.safeCost,
     115                        varCost + other.varCost, specCost + other.specCost,
     116                        referenceCost + other.referenceCost };
     117        }
     118
     119        inline Cost Cost::operator-( const Cost &other ) const {
     120                if ( *this == infinity || other == infinity ) return infinity;
     121                return Cost{
     122                        unsafeCost - other.unsafeCost, polyCost - other.polyCost, safeCost - other.safeCost,
     123                        varCost - other.varCost, specCost - other.specCost,
     124                        referenceCost - other.referenceCost };
    131125        }
    132126
     
    140134                polyCost += other.polyCost;
    141135                safeCost += other.safeCost;
    142                 signCost += other.signCost;
    143136                varCost += other.varCost;
    144137                specCost += other.specCost;
     
    163156                } else if ( safeCost < other.safeCost ) {
    164157                        return true;
    165                 } else if ( signCost > other.signCost ) {
    166                         return false;
    167                 } else if ( signCost < other.signCost ) {
    168                         return true;
    169158                } else if ( varCost > other.varCost ) {
    170159                        return false;
     
    191180                c = polyCost - other.polyCost; if ( c ) return c;
    192181                c = safeCost - other.safeCost; if ( c ) return c;
    193                 c = signCost - other.signCost; if ( c ) return c;
    194182                c = varCost - other.varCost; if ( c ) return c;
    195183                c = specCost - other.specCost; if ( c ) return c;
     
    201189                        && polyCost == other.polyCost
    202190                        && safeCost == other.safeCost
    203                         && signCost == other.signCost
    204191                        && varCost == other.varCost
    205192                        && specCost == other.specCost
     
    212199
    213200        inline std::ostream &operator<<( std::ostream &os, const Cost &cost ) {
    214                 return os << "( " << cost.unsafeCost << ", " << cost.polyCost << ", "
    215                           << cost.safeCost << ", " << cost.signCost << ", "
    216                                   << cost.varCost << ", " << cost.specCost << ", "
     201                return os << "( " << cost.unsafeCost << ", " << cost.polyCost << ", "
     202                          << cost.safeCost << ", " << cost.varCost << ", " << cost.specCost << ", "
    217203                          << cost.referenceCost << " )";
    218204        }
    219 
    220 #else
    221 
    222         //*************************** NEW ***************************
    223 
    224         // To maximize performance and space, the 7 resolution costs are packed into a single 64-bit word. However, the
    225         // specialization cost is a negative value so a correction is needed is a few places.
    226 
    227         class Cost {
    228                 union {
    229                         struct {
    230                         #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
    231                                 // Little-endian => first value is low priority and last is high priority.
    232                                 unsigned char padding;                                  ///< unused
    233                                 unsigned char referenceCost;                    ///< reference conversions
    234                                 unsigned char specCost;                                 ///< Polymorphic type specializations (type assertions), negative cost
    235                                 unsigned char varCost;                                  ///< Count of polymorphic type variables
    236                                 unsigned char signCost;                                 ///< Count of safe sign conversions
    237                                 unsigned char safeCost;                                 ///< Safe (widening) conversions
    238                                 unsigned char polyCost;                                 ///< Count of parameters and return values bound to some poly type
    239                                 unsigned char unsafeCost;                               ///< Unsafe (narrowing) conversions
    240                         #else
    241                                 #error Cost BIG_ENDIAN unsupported
    242                         #endif
    243                         } v;
    244                         uint64_t all;
    245                 };
    246                 static const unsigned char correctb = 0xff;             // byte correction for negative spec cost
    247                 static const uint64_t correctw = 0x00'00'00'00'00'ff'00'00; //' word correction for negative spec cost
    248           public:
    249                 // Compiler adjusts constants for correct endian.
    250                 enum : uint64_t {
    251                         zero      = 0x00'00'00'00'00'ff'00'00,
    252                         infinity  = 0xff'ff'ff'ff'ff'00'ff'ff,
    253                         unsafe    = 0x01'00'00'00'00'ff'00'00,
    254                         poly      = 0x00'01'00'00'00'ff'00'00,
    255                         safe      = 0x00'00'01'00'00'ff'00'00,
    256                         sign      = 0x00'00'00'01'00'ff'00'00,
    257                         var       = 0x00'00'00'00'01'ff'00'00,
    258                         spec      = 0x00'00'00'00'00'fe'00'00,
    259                         reference = 0x00'00'00'00'00'ff'01'00,
    260                 }; //'
    261 
    262                 Cost( uint64_t all ) { Cost::all = all; }
    263                 Cost( int unsafeCost, int polyCost, int safeCost, int signCost, int varCost, int specCost, int referenceCost ) {
    264                         // Assume little-endian => first value is low priority and last is high priority.
    265                         v = {
    266                         #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
    267                                 (unsigned char)0,                                               // padding
    268                                 (unsigned char)referenceCost,                   // low priority
    269                                 (unsigned char)(specCost + correctb),   // correct for signedness
    270                                 (unsigned char)varCost,
    271                                 (unsigned char)signCost,
    272                                 (unsigned char)safeCost,
    273                                 (unsigned char)polyCost,
    274                                 (unsigned char)unsafeCost,                              // high priority
    275                         #else
    276                                 #error Cost BIG_ENDIAN unsupported
    277                         #endif
    278                         };
    279                 }
    280 
    281                 int get_unsafeCost() const { return v.unsafeCost; }
    282                 int get_polyCost() const { return v.polyCost; }
    283                 int get_safeCost() const { return v.safeCost; }
    284                 int get_signCost() const { return v.signCost; }
    285                 int get_varCost() const { return v.varCost; }
    286                 int get_specCost() const { return -(correctb - v.specCost); }
    287                 int get_referenceCost() const { return v.referenceCost; }
    288 
    289                 friend bool operator==( const Cost, const Cost );
    290                 friend bool operator!=( const Cost lhs, const Cost rhs );
    291                 // returns negative for *this < rhs, 0 for *this == rhs, positive for *this > rhs
    292                 int compare( const Cost rhs ) const {
    293                         if ( all == infinity ) return 1;
    294                         if ( rhs.all == infinity ) return -1;
    295                         return all > rhs.all ? 1 : all == rhs.all ? 0 : -1;
    296                 }
    297                 friend bool operator<( const Cost lhs, const Cost rhs );
    298 
    299                 friend Cost operator+( const Cost lhs, const Cost rhs );
    300  
    301                 Cost operator+=( const Cost rhs ) {
    302                         if ( all == infinity ) return *this;
    303                         if ( rhs.all == infinity ) {
    304                                 all = infinity;
    305                                 return *this;
    306                         }
    307                         all += rhs.all - correctw;                                      // correct for negative spec cost
    308                         return *this;
    309                 }
    310 
    311                 Cost incUnsafe( int inc = 1 ) {
    312                         if ( all != infinity ) { assert( v.unsafeCost + inc <= UCHAR_MAX ); v.unsafeCost += inc; }
    313                         return *this;
    314                 }
    315 
    316                 Cost incPoly( int inc = 1 ) {
    317                         if ( all != infinity ) { assert( v.polyCost + inc <= UCHAR_MAX ); v.polyCost += inc; }
    318                         return *this;
    319                 }
    320 
    321                 Cost incSafe( int inc = 1 ) {
    322                         if ( all != infinity ) { assert( v.safeCost + inc <= UCHAR_MAX ); v.safeCost += inc; }
    323                         return *this;
    324                 }
    325 
    326                 Cost incSign( int inc = 1 ) {
    327                         if ( all != infinity ) { assert( v.signCost + inc <= UCHAR_MAX ); v.signCost += inc; }
    328                         return *this;
    329                 }
    330 
    331                 Cost incVar( int inc = 1 ) {
    332                         if ( all != infinity ) { assert( v.varCost + inc <= UCHAR_MAX ); v.varCost += inc; }
    333                         return *this;
    334                 }
    335 
    336                 Cost decSpec( int dec = 1 ) {
    337                         if ( all != infinity ) { assert( v.specCost - dec >= 0 ); v.specCost -= dec; }
    338                         return *this;
    339                 }
    340 
    341                 Cost incReference( int inc = 1 ) {
    342                         if ( all != infinity ) { assert( v.referenceCost + inc <= UCHAR_MAX ); v.referenceCost += inc; }
    343                         return *this;
    344                 }
    345 
    346                 friend std::ostream & operator<<( std::ostream & os, const Cost cost );
    347         };
    348 
    349         inline bool operator==( const Cost lhs, const Cost rhs ) {
    350                 return lhs.all == rhs.all;
    351         }
    352 
    353         inline bool operator!=( const Cost lhs, const Cost rhs ) {
    354                 return !( lhs.all == rhs.all );
    355         }
    356 
    357         inline bool operator<( const Cost lhs, const Cost rhs ) {
    358                 if ( lhs.all == Cost::infinity ) return false;
    359                 if ( rhs.all == Cost::infinity ) return true;
    360                 return lhs.all < rhs.all;
    361         }
    362 
    363         inline Cost operator+( const Cost lhs, const Cost rhs ) {
    364                 if ( lhs.all == Cost::infinity || rhs.all == Cost::infinity ) return Cost{ Cost::infinity };
    365                 return Cost{ lhs.all + rhs.all - Cost::correctw }; // correct for negative spec cost
    366         }
    367 
    368         inline std::ostream & operator<<( std::ostream & os, const Cost cost ) {
    369                 return os << "( " << cost.get_unsafeCost() << ", " << cost.get_polyCost() << ", " << cost.get_safeCost()
    370                                   << ", " << cost.get_signCost() << ", " << cost.get_varCost() << ", " << cost.get_specCost()
    371                                   << ", " << cost.get_referenceCost() << " )";
    372         }
    373 #endif // 0
    374205} // namespace ResolvExpr
    375206
Note: See TracChangeset for help on using the changeset viewer.