Ignore:
File:
1 edited

Legend:

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

    rb8e047a rcfbc56ec  
    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
    1810
    1911//
     
    4436//
    4537forall( [N], S & | sized(S), Timmed &, Tbase & ) {
    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) ) {}
     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) ) {}
    150133}
    151134
    152135// RAII pattern has workarounds for
    153136//  - Trac 226:  Simplest handling would be, require immediate element to be otype, let autogen
    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 ^?{}.
     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 ^?{}.
    157140
    158141forall( [N], S & | sized(S), Timmed &, Tbase & | { void ?{}( Timmed & ); } )
    159 static inline void ?{}( arpk( N, S, Timmed, Tbase ) & this ) { 
    160         void ?{}( S (&)[N] ) {}
    161         ?{}(this.strides);
    162 
    163         for (i; N) ?{}( (Timmed &)this.strides[i] );
     142static inline void ?{}( arpk(N, S, Timmed, Tbase) & this ) {   
     143    void ?{}( S (&)[N] ) {}
     144    ?{}(this.strides);
     145
     146    for (i; N) ?{}( (Timmed &) this.strides[i] );
    164147}
    165148
    166149forall( [N], S & | sized(S), Timmed &, Tbase & | { void ^?{}( Timmed & ); } )
    167 static 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         }
     150static 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    }
    174157}
    175158
     
    182165
    183166forall( [N], ZTags ... , Trslt &, Tatom & | { Trslt mkar_( tag(Tatom), ZTags ); } )
    184 static inline arpk( N, Trslt, Trslt, Tatom) mkar_( tag(Tatom), tag(N), ZTags ) {}
     167static inline arpk(N, Trslt, Trslt, Tatom) mkar_( tag(Tatom), tag(N), ZTags ) {}
    185168
    186169// based on https://stackoverflow.com/questions/1872220/is-it-possible-to-iterate-over-arguments-in-variadic-macros
    187170
    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__)
     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__)
    200183
    201184#define COMMA_ttag(X) , ttag(X)
     
    217200forall( TA &, TB &, TC &, IxAB, IxBC ... | { TB & ?[?]( TA &, IxAB ); TC & ?[?]( TB &, IxBC ); } )
    218201static inline TC & ?[?]( TA & this, IxAB ab, IxBC bc ) {
    219         return this[ab][bc];
     202    return this[ab][bc];
    220203}
    221204
     
    226209forall( TA &, TB &, TC &, IxAB_0, IxBC | { TB & ?[?]( TA &, IxAB_0 ); TC & ?[?]( TB &, IxBC ); } )
    227210static inline TC & ?[?]( TA & this, IxAB_0 ab, IxBC bc ) {
    228         return this[ab][bc];
     211    return this[ab][bc];
    229212}
    230213
    231214forall( TA &, TB &, TC &, IxAB_0, IxAB_1, IxBC | { TB & ?[?]( TA &, IxAB_0, IxAB_1 ); TC & ?[?]( TB &, IxBC ); } )
    232215static inline TC & ?[?]( TA & this, IxAB_0 ab0, IxAB_1 ab1, IxBC bc ) {
    233         return this[[ab0,ab1]][bc];
     216    return this[[ab0,ab1]][bc];
    234217}
    235218
    236219forall( TA &, TB &, TC &, IxAB_0, IxAB_1, IxAB_2, IxBC | { TB & ?[?]( TA &, IxAB_0, IxAB_1, IxAB_2 ); TC & ?[?]( TB &, IxBC ); } )
    237220static inline TC & ?[?]( TA & this, IxAB_0 ab0, IxAB_1 ab1, IxAB_2 ab2, IxBC bc ) {
    238         return this[[ab0,ab1,ab2]][bc];
     221    return this[[ab0,ab1,ab2]][bc];
    239222}
    240223
     
    254237// Base
    255238forall( [Nq], Sq & | sized(Sq), Tbase & )
    256 static 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;
     239static 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;
    259242}
    260243
    261244// Rec
    262245forall( [Nq], Sq & | sized(Sq), [N], S & | sized(S), recq &, recr &, Tbase & | { tag(recr) enq_( tag(Tbase), tag(Nq), tag(Sq), tag(recq) ); } )
    263 static 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;
     246static 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;
    266249}
    267250
     
    269252extern struct all_t {} all;
    270253forall( [N], S & | sized(S), Te &, result &, Tbase & | { tag(result) enq_( tag(Tbase), tag(N), tag(S), tag(Te) ); } )
    271 static inline result & ?[?]( arpk( N, S, Te, Tbase ) & this, all_t ) {
    272         return (result&) this;
     254static inline result & ?[?]( arpk(N, S, Te, Tbase) & this, all_t ) {
     255    return (result&) this;
    273256}
    274257
     
    280263// forall(A &, Tv &, [N])
    281264// trait ar {
    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) );
     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) );
    288271// };
    289272
    290273// working around N's not being accepted as arguments to traits
    291274
    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 }
     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}
Note: See TracChangeset for help on using the changeset viewer.