// // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // Cost.h -- // // Author : Peter Buhr and Aaron Moss // Created On : Sun May 17 09:39:50 2015 // Last Modified By : Peter A. Buhr // Last Modified On : Sun Apr 28 18:26:36 2019 // Update Count : 29 // #pragma once #include #include namespace ResolvExpr { #if 0 //*************************** OLD *************************** class Cost { private: Cost( int unsafeCost, int polyCost, int safeCost, int signCost, int varCost, int specCost, int referenceCost ); public: Cost & incUnsafe( int inc = 1 ); Cost & incPoly( int inc = 1 ); Cost & incSafe( int inc = 1 ); Cost & incSign( int inc = 1 ); Cost & incVar( int inc = 1 ); Cost & decSpec( int inc = 1 ); Cost & incReference( int inc = 1 ); int get_unsafeCost() const { return unsafeCost; } int get_polyCost() const { return polyCost; } int get_safeCost() const { return safeCost; } int get_signCost() const { return signCost; } int get_varCost() const { return varCost; } int get_specCost() const { return specCost; } int get_referenceCost() const { return referenceCost; } Cost operator+( const Cost &other ) const; Cost &operator+=( const Cost &other ); bool operator<( const Cost &other ) const; bool operator==( const Cost &other ) const; bool operator!=( const Cost &other ) const; friend std::ostream &operator<<( std::ostream &os, const Cost &cost ); // returns negative for *this < other, 0 for *this == other, positive for *this > other int compare( const Cost &other ) const; static const Cost zero; static const Cost infinity; static const Cost unsafe; static const Cost poly; static const Cost safe; static const Cost sign; static const Cost var; static const Cost spec; static const Cost reference; private: int unsafeCost; ///< Unsafe (narrowing) conversions int polyCost; ///< Count of parameters and return values bound to some poly type int safeCost; ///< Safe (widening) conversions int signCost; ///< Count of safe sign conversions int varCost; ///< Count of polymorphic type variables int specCost; ///< Polymorphic type specializations (type assertions), negative cost int referenceCost; ///< reference conversions }; inline Cost::Cost( int unsafeCost, int polyCost, int safeCost, int signCost, int varCost, int specCost, int referenceCost ) : unsafeCost( unsafeCost ), polyCost( polyCost ), safeCost( safeCost ), signCost( signCost ), varCost( varCost ), specCost( specCost ), referenceCost( referenceCost ) {} inline Cost & Cost::incUnsafe( int inc ) { if ( *this == infinity ) return *this; unsafeCost += inc; return *this; } inline Cost & Cost::incPoly( int inc ) { if ( *this == infinity ) return *this; polyCost += inc; return *this; } inline Cost & Cost::incSafe( int inc ) { if ( *this == infinity ) return *this; safeCost += inc; return *this; } inline Cost & Cost::incSign( int inc ) { if ( *this == infinity ) return *this; signCost += inc; return *this; } inline Cost & Cost::incVar( int inc ) { if ( *this == infinity ) return *this; varCost += inc; return *this; } inline Cost& Cost::decSpec( int dec ) { if ( *this == infinity ) return *this; specCost -= dec; return *this; } inline Cost & Cost::incReference( int inc ) { if ( *this == infinity ) return *this; referenceCost += inc; return *this; } inline Cost Cost::operator+( const Cost &other ) const { if ( *this == infinity || other == infinity ) return infinity; return Cost{ unsafeCost + other.unsafeCost, polyCost + other.polyCost, safeCost + other.safeCost, signCost + other.signCost, varCost + other.varCost, specCost + other.specCost, referenceCost + other.referenceCost }; } inline Cost &Cost::operator+=( const Cost &other ) { if ( *this == infinity ) return *this; if ( other == infinity ) { *this = infinity; return *this; } unsafeCost += other.unsafeCost; polyCost += other.polyCost; safeCost += other.safeCost; signCost += other.signCost; varCost += other.varCost; specCost += other.specCost; referenceCost += other.referenceCost; return *this; } inline bool Cost::operator<( const Cost &other ) const { if ( *this == infinity ) return false; if ( other == infinity ) return true; if ( unsafeCost > other.unsafeCost ) { return false; } else if ( unsafeCost < other.unsafeCost ) { return true; } else if ( polyCost > other.polyCost ) { return false; } else if ( polyCost < other.polyCost ) { return true; } else if ( safeCost > other.safeCost ) { return false; } else if ( safeCost < other.safeCost ) { return true; } else if ( signCost > other.signCost ) { return false; } else if ( signCost < other.signCost ) { return true; } else if ( varCost > other.varCost ) { return false; } else if ( varCost < other.varCost ) { return true; } else if ( specCost > other.specCost ) { return false; } else if ( specCost > other.specCost ) { return true; } else if ( referenceCost > other.referenceCost ) { return false; } else if ( referenceCost < other.referenceCost ) { return true; } else { return false; } // if } inline int Cost::compare( const Cost &other ) const { if ( *this == infinity ) return +1; if ( other == infinity ) return -1; int c = unsafeCost - other.unsafeCost; if ( c ) return c; c = polyCost - other.polyCost; if ( c ) return c; c = safeCost - other.safeCost; if ( c ) return c; c = signCost - other.signCost; if ( c ) return c; c = varCost - other.varCost; if ( c ) return c; c = specCost - other.specCost; if ( c ) return c; return referenceCost - other.referenceCost; } inline bool Cost::operator==( const Cost &other ) const { return unsafeCost == other.unsafeCost && polyCost == other.polyCost && safeCost == other.safeCost && signCost == other.signCost && varCost == other.varCost && specCost == other.specCost && referenceCost == other.referenceCost; } inline bool Cost::operator!=( const Cost &other ) const { return !( *this == other ); } inline std::ostream &operator<<( std::ostream &os, const Cost &cost ) { return os << "( " << cost.unsafeCost << ", " << cost.polyCost << ", " << cost.safeCost << ", " << cost.signCost << ", " << cost.varCost << ", " << cost.specCost << ", " << cost.referenceCost << " )"; } #endif // 0 //*************************** NEW *************************** class Cost { union { struct { #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ // Little-endian => first value is low priority and last is high priority. unsigned char padding; ///< unused unsigned char referenceCost; ///< reference conversions unsigned char specCost; ///< Polymorphic type specializations (type assertions), negative cost unsigned char varCost; ///< Count of polymorphic type variables unsigned char signCost; ///< Count of safe sign conversions unsigned char safeCost; ///< Safe (widening) conversions unsigned char polyCost; ///< Count of parameters and return values bound to some poly type unsigned char unsafeCost; ///< Unsafe (narrowing) conversions #else #error BIG_ENDIAN unsupported #endif } v; uint64_t all; }; public: // Compiler adjusts constants for correct endian. enum : uint64_t { zero = 0x00'00'00'00'00'ff'00'00, infinity = 0xff'ff'ff'ff'ff'00'ff'ff, correction = 0x00'00'00'00'00'ff'00'00, // correct for negative spec cost unsafe = 0x01'00'00'00'00'ff'00'00, poly = 0x00'01'00'00'00'ff'00'00, safe = 0x00'00'01'00'00'ff'00'00, sign = 0x00'00'00'01'00'ff'00'00, var = 0x00'00'00'00'01'ff'00'00, spec = 0x00'00'00'00'00'fe'00'00, reference = 0x00'00'00'00'00'ff'01'00, }; // Cost( uint64_t all ) { Cost::all = all; } Cost( int unsafeCost, int polyCost, int safeCost, int signCost, int varCost, int specCost, int referenceCost ) { // Assume little-endian => first value is low priority and last is high priority. v = { (unsigned char)0, // padding (unsigned char)referenceCost, (unsigned char)(specCost + 0xff ), // correct for signedness (unsigned char)varCost, (unsigned char)signCost, (unsigned char)safeCost, (unsigned char)polyCost, (unsigned char)unsafeCost, }; } int get_unsafeCost() const { return v.unsafeCost; } int get_polyCost() const { return v.polyCost; } int get_safeCost() const { return v.safeCost; } int get_signCost() const { return v.signCost; } int get_varCost() const { return v.varCost; } int get_specCost() const { return -(0xff - v.specCost); } int get_referenceCost() const { return v.referenceCost; } friend bool operator==( const Cost, const Cost ); friend bool operator!=( const Cost lhs, const Cost rhs ); // returns negative for *this < rhs, 0 for *this == rhs, positive for *this > rhs int compare( const Cost rhs ) const { if ( all == infinity ) return 1; if ( rhs.all == infinity ) return -1; return all > rhs.all ? 1 : all == rhs.all ? 0 : -1; } friend bool operator<( const Cost lhs, const Cost rhs ); friend Cost operator+( const Cost lhs, const Cost rhs ); Cost operator+=( const Cost rhs ) { if ( all == infinity ) return *this; if ( rhs.all == infinity ) { all = infinity; return *this; } all += rhs.all - correction; // correct for negative spec cost return *this; } Cost incUnsafe( int inc = 1 ) { if ( all != infinity ) { assert( v.unsafeCost + inc < 256 ); v.unsafeCost += inc; } return *this; } Cost incPoly( int inc = 1 ) { if ( all != infinity ) { assert( v.polyCost + inc < 256 ); v.polyCost += inc; } return *this; } Cost incSafe( int inc = 1 ) { if ( all != infinity ) { assert( v.safeCost + inc < 256 ); v.safeCost += inc; } return *this; } Cost incSign( int inc = 1 ) { if ( all != infinity ) { assert( v.signCost + inc < 256 ); v.signCost += inc; } return *this; } Cost incVar( int inc = 1 ) { if ( all != infinity ) { assert( v.varCost + inc < 256 ); v.varCost += inc; } return *this; } Cost decSpec( int dec = 1 ) { if ( all != infinity ) { v.specCost -= dec; } return *this; } Cost incReference( int inc = 1 ) { if ( all != infinity ) { assert( v.referenceCost + inc < 256 ); v.referenceCost += inc; } return *this; } friend std::ostream & operator<<( std::ostream & os, const Cost cost ); }; inline bool operator==( const Cost lhs, const Cost rhs ) { return lhs.all == rhs.all; } inline bool operator!=( const Cost lhs, const Cost rhs ) { return !( lhs.all == rhs.all ); } inline bool operator<( const Cost lhs, const Cost rhs ) { if ( lhs.all == Cost::infinity ) return false; if ( rhs.all == Cost::infinity ) return true; return lhs.all < rhs.all; } inline Cost operator+( const Cost lhs, const Cost rhs ) { if ( lhs.all == Cost::infinity || rhs.all == Cost::infinity ) return Cost{ Cost::infinity }; return Cost{ lhs.all + rhs.all - Cost::correction }; // correct for negative spec cost } inline std::ostream & operator<<( std::ostream & os, const Cost cost ) { return os << "( " << cost.get_unsafeCost() << ", " << cost.get_polyCost() << ", " << cost.get_safeCost() << ", " << cost.get_signCost() << ", " << cost.get_varCost() << ", " << cost.get_specCost() << ", " << cost.get_referenceCost() << " )"; } } // namespace ResolvExpr // Local Variables: // // tab-width: 4 // // mode: c++ // // compile-command: "make install" // // End: //