Ignore:
Timestamp:
Jul 29, 2024, 1:32:51 PM (6 weeks ago)
Author:
JiadaL <j82liang@…>
Branches:
master
Children:
f3d2a4f
Parents:
38e20a80 (diff), 1661ad7 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/collections/array.hfa

    r38e20a80 rce02877  
    11#pragma once
    22
    3 #include <assert.h>
     3//#include <assert.h>
    44
    55
     
    88#define ztag(n) ttag(n)
    99
     10#ifdef __CFA_DEBUG__
     11#define subcheck( arr, sub, lb, ub ) \
     12        if ( (sub) < (lb) || (sub) >= (ub) ) \
     13                abort( "subscript %ld exceeds dimension range [%d,%zd) for array %p.\n", \
     14                           (sub), (lb), (ub), (arr) )
     15#else
     16#define subcheck( arr, sub, lb, ub ) do {} while (0)
     17#endif
    1018
    1119//
     
    3644//
    3745forall( [N], S & | sized(S), Timmed &, Tbase & ) {
    38 
    39     //
    40     // Single-dim array sruct (with explicit packing and atom)
    41     //
    42     struct arpk {
    43         S strides[N];
    44     };
    45 
    46     // About the choice of integral types offered as subscript overloads:
    47     // Intent is to cover these use cases:
    48     //    a[0]                                                // i : zero_t
    49     //    a[1]                                                // i : one_t
    50     //    a[2]                                                // i : int
    51     //    float foo( ptrdiff_t i ) { return a[i]; }           // i : ptrdiff_t
    52     //    float foo( size_t i ) { return a[i]; }              // i : size_t
    53     //    forall( [N] ) ... for( i; N ) { total += a[i]; }    // i : typeof( sizeof(42) )
    54     //    for( i; 5 ) { total += a[i]; }                      // i : int
    55     //
    56     // It gets complicated by:
    57     // -  CFA does overloading on concrete types, like int and unsigned int, not on typedefed
    58     //    types like size_t.  So trying to overload on ptrdiff_t vs int works in 64-bit mode
    59     //    but not in 32-bit mode.
    60     // -  Given bug of Trac #247, CFA gives sizeof expressions type unsigned long int, when it
    61     //    should give them type size_t.
    62     //
    63     //                          gcc -m32         cfa -m32 given bug         gcc -m64 (and cfa)
    64     // ptrdiff_t                int              int                        long int
    65     // size_t                   unsigned int     unsigned int               unsigned long int
    66     // typeof( sizeof(42) )     unsigned int     unsigned long int          unsigned long int
    67     // int                      int              int                        int
    68     //
    69     // So the solution must support types {zero_t, one_t, int, unsigned int, long int, unsigned long int}
    70     //
    71     // The solution cannot rely on implicit conversions (e.g. just have one overload for ptrdiff_t)
    72     // because assertion satisfaction requires types to match exacly.  Both higher-dimensional
    73     // subscripting and operations on slices use asserted subscript operators.  The test case
    74     // array-container/array-sbscr-cases covers the combinations.  Mike beleives that commenting out
    75     // any of the current overloads leads to one of those cases failing, either on 64- or 32-bit.
    76     // Mike is open to being shown a smaller set of overloads that still passes the test.
    77 
    78     static inline Timmed & ?[?]( arpk(N, S, Timmed, Tbase) & a, zero_t ) {
    79         assert( 0 < N );
    80         return (Timmed &) a.strides[0];
    81     }
    82 
    83     static inline Timmed & ?[?]( arpk(N, S, Timmed, Tbase) & a, one_t ) {
    84         assert( 1 < N );
    85         return (Timmed &) a.strides[1];
    86     }
    87 
    88     static inline Timmed & ?[?]( arpk(N, S, Timmed, Tbase) & a, int i ) {
    89         assert( i < N );
    90         return (Timmed &) a.strides[i];
    91     }
    92 
    93     static inline const Timmed & ?[?]( const arpk(N, S, Timmed, Tbase) & a, int i ) {
    94         assert( i < N );
    95         return (Timmed &) a.strides[i];
    96     }
    97 
    98     static inline Timmed & ?[?]( arpk(N, S, Timmed, Tbase) & a, unsigned int i ) {
    99         assert( i < N );
    100         return (Timmed &) a.strides[i];
    101     }
    102 
    103     static inline const Timmed & ?[?]( const arpk(N, S, Timmed, Tbase) & a, unsigned int i ) {
    104         assert( i < N );
    105         return (Timmed &) a.strides[i];
    106     }
    107 
    108     static inline Timmed & ?[?]( arpk(N, S, Timmed, Tbase) & a, long int i ) {
    109         assert( i < N );
    110         return (Timmed &) a.strides[i];
    111     }
    112 
    113     static inline const Timmed & ?[?]( const arpk(N, S, Timmed, Tbase) & a, long int i ) {
    114         assert( i < N );
    115         return (Timmed &) a.strides[i];
    116     }
    117 
    118     static inline Timmed & ?[?]( arpk(N, S, Timmed, Tbase) & a, unsigned long int i ) {
    119         assert( i < N );
    120         return (Timmed &) a.strides[i];
    121     }
    122 
    123     static inline const Timmed & ?[?]( const arpk(N, S, Timmed, Tbase) & a, unsigned long int i ) {
    124         assert( i < N );
    125         return (Timmed &) a.strides[i];
    126     }
    127 
    128     static inline size_t ?`len( arpk(N, S, Timmed, Tbase) & a ) {
    129         return N;
    130     }
    131 
    132     static inline void __taglen( tag(arpk(N, S, Timmed, Tbase)), tag(N) ) {}
     46        //
     47        // Single-dim array struct (with explicit packing and atom)
     48        //
     49        struct arpk {
     50                S strides[N];
     51        };
     52
     53        // About the choice of integral types offered as subscript overloads:
     54        // Intent is to cover these use cases:
     55        //    a[0]                                                // i : zero_t
     56        //    a[1]                                                // i : one_t
     57        //    a[2]                                                // i : int
     58        //    float foo( ptrdiff_t i ) { return a[i]; }           // i : ptrdiff_t
     59        //    float foo( size_t i ) { return a[i]; }              // i : size_t
     60        //    forall( [N] ) ... for( i; N ) { total += a[i]; }    // i : typeof( sizeof(42) )
     61        //    for( i; 5 ) { total += a[i]; }                      // i : int
     62        //
     63        // It gets complicated by:
     64        // -  CFA does overloading on concrete types, like int and unsigned int, not on typedefed
     65        //    types like size_t.  So trying to overload on ptrdiff_t vs int works in 64-bit mode
     66        //    but not in 32-bit mode.
     67        // -  Given bug of Trac #247, CFA gives sizeof expressions type unsigned long int, when it
     68        //    should give them type size_t.
     69        //
     70        //                          gcc -m32         cfa -m32 given bug         gcc -m64 (and cfa)
     71        // ptrdiff_t                int              int                        long int
     72        // size_t                   unsigned int     unsigned int               unsigned long int
     73        // typeof( sizeof(42) )     unsigned int     unsigned long int          unsigned long int
     74        // int                      int              int                        int
     75        //
     76        // So the solution must support types {zero_t, one_t, int, unsigned int, long int, unsigned long int}
     77        //
     78        // The solution cannot rely on implicit conversions (e.g. just have one overload for ptrdiff_t)
     79        // because assertion satisfaction requires types to match exacly.  Both higher-dimensional
     80        // subscripting and operations on slices use asserted subscript operators.  The test case
     81        // array-container/array-sbscr-cases covers the combinations.  Mike beleives that commenting out
     82        // any of the current overloads leads to one of those cases failing, either on 64- or 32-bit.
     83        // Mike is open to being shown a smaller set of overloads that still passes the test.
     84
     85        static inline Timmed & ?[?]( arpk( N, S, Timmed, Tbase ) & a, zero_t ) {
     86                //assert( 0 < N );
     87                subcheck( a, 0L, 0, N );
     88                return (Timmed &)a.strides[0];
     89        }
     90
     91        static inline Timmed & ?[?]( arpk( N, S, Timmed, Tbase ) & a, one_t ) {
     92                //assert( 1 < N );
     93                subcheck( a, 1L, 0, N );
     94                return (Timmed &)a.strides[1];
     95        }
     96
     97        static inline Timmed & ?[?]( arpk( N, S, Timmed, Tbase ) & a, int i ) {
     98                //assert( i < N );
     99                subcheck( a, (long int)i, 0, N );
     100                return (Timmed &)a.strides[i];
     101        }
     102
     103        static inline const Timmed & ?[?]( const arpk( N, S, Timmed, Tbase ) & a, int i ) {
     104                //assert( i < N );
     105                subcheck( a, (long int)i, 0, N );
     106                return (Timmed &)a.strides[i];
     107        }
     108
     109        static inline Timmed & ?[?]( arpk( N, S, Timmed, Tbase ) & a, unsigned int i ) {
     110                //assert( i < N );
     111                subcheck( a, (long int)i, 0, N );
     112                return (Timmed &)a.strides[i];
     113        }
     114
     115        static inline const Timmed & ?[?]( const arpk( N, S, Timmed, Tbase ) & a, unsigned int i ) {
     116                //assert( i < N );
     117                subcheck( a, (unsigned long int)i, 0, N );
     118                return (Timmed &)a.strides[i];
     119        }
     120
     121        static inline Timmed & ?[?]( arpk( N, S, Timmed, Tbase ) & a, long int i ) {
     122                //assert( i < N );
     123                subcheck( a, i, 0, N );
     124                return (Timmed &)a.strides[i];
     125        }
     126
     127        static inline const Timmed & ?[?]( const arpk( N, S, Timmed, Tbase ) & a, long int i ) {
     128                //assert( i < N );
     129                subcheck( a, i, 0, N );
     130                return (Timmed &)a.strides[i];
     131        }
     132
     133        static inline Timmed & ?[?]( arpk( N, S, Timmed, Tbase ) & a, unsigned long int i ) {
     134                //assert( i < N );
     135                subcheck( a, i, 0, N );
     136                return (Timmed &)a.strides[i];
     137        }
     138
     139        static inline const Timmed & ?[?]( const arpk( N, S, Timmed, Tbase ) & a, unsigned long int i ) {
     140                //assert( i < N );
     141                subcheck( a, i, 0, N );
     142                return (Timmed &)a.strides[i];
     143        }
     144
     145        static inline size_t ?`len( arpk( N, S, Timmed, Tbase ) & a ) {
     146                return N;
     147        }
     148
     149        static inline void __taglen( tag(arpk( N, S, Timmed, Tbase )), tag(N) ) {}
    133150}
    134151
    135152// RAII pattern has workarounds for
    136153//  - Trac 226:  Simplest handling would be, require immediate element to be otype, let autogen
    137 //    raii happen.  Performance on even a couple dimensions is unacceptable because of exponential
    138 //    thunk creation: ?{}() needs all four otype funcs from next level, so does ^?{}(), so do the
    139 //    other two.  This solution offers ?{}() that needs only ?{}(), and similar for ^?{}.
     154//      raii happen.  Performance on even a couple dimensions is unacceptable because of exponential
     155//      thunk creation: ?{}() needs all four otype funcs from next level, so does ^?{}(), so do the
     156//      other two.  This solution offers ?{}() that needs only ?{}(), and similar for ^?{}.
    140157
    141158forall( [N], S & | sized(S), Timmed &, Tbase & | { void ?{}( Timmed & ); } )
    142 static inline void ?{}( arpk(N, S, Timmed, Tbase) & this ) {   
    143     void ?{}( S (&)[N] ) {}
    144     ?{}(this.strides);
    145 
    146     for (i; N) ?{}( (Timmed &) this.strides[i] );
     159static inline void ?{}( arpk( N, S, Timmed, Tbase ) & this ) { 
     160        void ?{}( S (&)[N] ) {}
     161        ?{}(this.strides);
     162
     163        for (i; N) ?{}( (Timmed &)this.strides[i] );
    147164}
    148165
    149166forall( [N], S & | sized(S), Timmed &, Tbase & | { void ^?{}( Timmed & ); } )
    150 static inline void ^?{}( arpk(N, S, Timmed, Tbase) & this ) {
    151     void ^?{}( S (&)[N] ) {}
    152     ^?{}(this.strides);
    153 
    154     for (i; N ) {
    155         ^?{}( (Timmed &) this.strides[N-i-1] );
    156     }
     167static inline void ^?{}( arpk( N, S, Timmed, Tbase ) & this ) {
     168        void ^?{}( S (&)[N] ) {}
     169        ^?{}(this.strides);
     170
     171        for (i; N ) {
     172                ^?{}( (Timmed &)this.strides[N-i-1] );
     173        }
    157174}
    158175
     
    165182
    166183forall( [N], ZTags ... , Trslt &, Tatom & | { Trslt mkar_( tag(Tatom), ZTags ); } )
    167 static inline arpk(N, Trslt, Trslt, Tatom) mkar_( tag(Tatom), tag(N), ZTags ) {}
     184static inline arpk( N, Trslt, Trslt, Tatom) mkar_( tag(Tatom), tag(N), ZTags ) {}
    168185
    169186// based on https://stackoverflow.com/questions/1872220/is-it-possible-to-iterate-over-arguments-in-variadic-macros
    170187
    171     // Make a FOREACH macro
    172     #define FE_0(WHAT)
    173     #define FE_1(WHAT, X) WHAT(X)
    174     #define FE_2(WHAT, X, ...) WHAT(X)FE_1(WHAT, __VA_ARGS__)
    175     #define FE_3(WHAT, X, ...) WHAT(X)FE_2(WHAT, __VA_ARGS__)
    176     #define FE_4(WHAT, X, ...) WHAT(X)FE_3(WHAT, __VA_ARGS__)
    177     #define FE_5(WHAT, X, ...) WHAT(X)FE_4(WHAT, __VA_ARGS__)
    178     //... repeat as needed
    179 
    180     #define GET_MACRO(_0,_1,_2,_3,_4,_5,NAME,...) NAME
    181     #define FOR_EACH(action,...) \
    182     GET_MACRO(_0,__VA_ARGS__,FE_5,FE_4,FE_3,FE_2,FE_1,FE_0)(action,__VA_ARGS__)
     188        // Make a FOREACH macro
     189        #define FE_0(WHAT)
     190        #define FE_1(WHAT, X) WHAT(X)
     191        #define FE_2(WHAT, X, ...) WHAT(X)FE_1(WHAT, __VA_ARGS__)
     192        #define FE_3(WHAT, X, ...) WHAT(X)FE_2(WHAT, __VA_ARGS__)
     193        #define FE_4(WHAT, X, ...) WHAT(X)FE_3(WHAT, __VA_ARGS__)
     194        #define FE_5(WHAT, X, ...) WHAT(X)FE_4(WHAT, __VA_ARGS__)
     195        //... repeat as needed
     196
     197        #define GET_MACRO(_0,_1,_2,_3,_4,_5,NAME,...) NAME
     198        #define FOR_EACH(action,...) \
     199        GET_MACRO(_0,__VA_ARGS__,FE_5,FE_4,FE_3,FE_2,FE_1,FE_0)(action,__VA_ARGS__)
    183200
    184201#define COMMA_ttag(X) , ttag(X)
     
    200217forall( TA &, TB &, TC &, IxAB, IxBC ... | { TB & ?[?]( TA &, IxAB ); TC & ?[?]( TB &, IxBC ); } )
    201218static inline TC & ?[?]( TA & this, IxAB ab, IxBC bc ) {
    202     return this[ab][bc];
     219        return this[ab][bc];
    203220}
    204221
     
    209226forall( TA &, TB &, TC &, IxAB_0, IxBC | { TB & ?[?]( TA &, IxAB_0 ); TC & ?[?]( TB &, IxBC ); } )
    210227static inline TC & ?[?]( TA & this, IxAB_0 ab, IxBC bc ) {
    211     return this[ab][bc];
     228        return this[ab][bc];
    212229}
    213230
    214231forall( TA &, TB &, TC &, IxAB_0, IxAB_1, IxBC | { TB & ?[?]( TA &, IxAB_0, IxAB_1 ); TC & ?[?]( TB &, IxBC ); } )
    215232static inline TC & ?[?]( TA & this, IxAB_0 ab0, IxAB_1 ab1, IxBC bc ) {
    216     return this[[ab0,ab1]][bc];
     233        return this[[ab0,ab1]][bc];
    217234}
    218235
    219236forall( TA &, TB &, TC &, IxAB_0, IxAB_1, IxAB_2, IxBC | { TB & ?[?]( TA &, IxAB_0, IxAB_1, IxAB_2 ); TC & ?[?]( TB &, IxBC ); } )
    220237static inline TC & ?[?]( TA & this, IxAB_0 ab0, IxAB_1 ab1, IxAB_2 ab2, IxBC bc ) {
    221     return this[[ab0,ab1,ab2]][bc];
     238        return this[[ab0,ab1,ab2]][bc];
    222239}
    223240
     
    237254// Base
    238255forall( [Nq], Sq & | sized(Sq), Tbase & )
    239 static inline tag(arpk(Nq, Sq, Tbase, Tbase)) enq_( tag(Tbase), tag(Nq), tag(Sq), tag(Tbase) ) {
    240     tag(arpk(Nq, Sq, Tbase, Tbase)) ret;
    241     return ret;
     256static inline tag(arpk( Nq, Sq, Tbase, Tbase )) enq_( tag(Tbase ), tag(Nq), tag(Sq), tag(Tbase ) ) {
     257        tag(arpk( Nq, Sq, Tbase, Tbase )) ret;
     258        return ret;
    242259}
    243260
    244261// Rec
    245262forall( [Nq], Sq & | sized(Sq), [N], S & | sized(S), recq &, recr &, Tbase & | { tag(recr) enq_( tag(Tbase), tag(Nq), tag(Sq), tag(recq) ); } )
    246 static inline tag(arpk(N, S, recr, Tbase)) enq_( tag(Tbase), tag(Nq), tag(Sq), tag(arpk(N, S, recq, Tbase)) ) {
    247     tag(arpk(N, S, recr, Tbase)) ret;
    248     return ret;
     263static inline tag(arpk( N, S, recr, Tbase )) enq_( tag(Tbase ), tag(Nq), tag(Sq), tag(arpk( N, S, recq, Tbase )) ) {
     264        tag(arpk( N, S, recr, Tbase )) ret;
     265        return ret;
    249266}
    250267
     
    252269extern struct all_t {} all;
    253270forall( [N], S & | sized(S), Te &, result &, Tbase & | { tag(result) enq_( tag(Tbase), tag(N), tag(S), tag(Te) ); } )
    254 static inline result & ?[?]( arpk(N, S, Te, Tbase) & this, all_t ) {
    255     return (result&) this;
     271static inline result & ?[?]( arpk( N, S, Te, Tbase ) & this, all_t ) {
     272        return (result&) this;
    256273}
    257274
     
    263280// forall(A &, Tv &, [N])
    264281// trait ar {
    265 //    Tv& ?[?]( A&, zero_t );
    266 //    Tv& ?[?]( A&, one_t  );
    267 //     Tv& ?[?]( A&, int    );
    268 //                   ...
    269 //    size_t ?`len( A& );
    270 //    void __taglen( tag(C), tag(N) );
     282//      Tv& ?[?]( A&, zero_t );
     283//      Tv& ?[?]( A&, one_t  );
     284//       Tv& ?[?]( A&, int      );
     285//                                 ...
     286//      size_t ?`len( A& );
     287//      void __taglen( tag(C), tag(N) );
    271288// };
    272289
    273290// working around N's not being accepted as arguments to traits
    274291
    275 #define ar(A, Tv, N) {                 \
    276     Tv& ?[?]( A&, zero_t );            \
    277     Tv& ?[?]( A&, one_t );             \
    278     Tv& ?[?]( A&, int );               \
    279     Tv& ?[?]( A&, unsigned int );      \
    280     Tv& ?[?]( A&, long int );          \
    281     Tv& ?[?]( A&, unsigned long int ); \
    282     size_t ?`len( A& );                \
    283     void __taglen( tag(A), tag(N) );   \
    284 }
     292#define ar( A, Tv, N ) {                                \
     293        Tv& ?[?]( A&, zero_t );                         \
     294        Tv& ?[?]( A&, one_t );                          \
     295        Tv& ?[?]( A&, int );                            \
     296        Tv& ?[?]( A&, unsigned int );           \
     297        Tv& ?[?]( A&, long int );                       \
     298        Tv& ?[?]( A&, unsigned long int );      \
     299        size_t ?`len( A& );                                     \
     300        void __taglen( tag(A), tag(N) );        \
     301}
Note: See TracChangeset for help on using the changeset viewer.