Changeset 1bb0170


Ignore:
Timestamp:
Jul 28, 2024, 8:41:11 AM (5 hours ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
master
Children:
5ff721a
Parents:
876739f
Message:

formatting, replace subscript-check asserts with error message

File:
1 edited

Legend:

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

    r876739f r1bb0170  
    88#define ztag(n) ttag(n)
    99
     10#define subcheck( arr, sub, lb, ub ) \
     11        if ( (sub) < (lb) || (sub) >= (ub) ) \
     12                abort( "subscript %ld exceeds dimension range [%d,%zd) for array %p\n", \
     13                           (sub), (lb), (ub), (arr) );
    1014
    1115//
     
    3640//
    3741forall( [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) ) {}
     42        //
     43        // Single-dim array sruct (with explicit packing and atom)
     44        //
     45        struct arpk {
     46                S strides[N];
     47        };
     48
     49        // About the choice of integral types offered as subscript overloads:
     50        // Intent is to cover these use cases:
     51        //    a[0]                                                // i : zero_t
     52        //    a[1]                                                // i : one_t
     53        //    a[2]                                                // i : int
     54        //    float foo( ptrdiff_t i ) { return a[i]; }           // i : ptrdiff_t
     55        //    float foo( size_t i ) { return a[i]; }              // i : size_t
     56        //    forall( [N] ) ... for( i; N ) { total += a[i]; }    // i : typeof( sizeof(42) )
     57        //    for( i; 5 ) { total += a[i]; }                      // i : int
     58        //
     59        // It gets complicated by:
     60        // -  CFA does overloading on concrete types, like int and unsigned int, not on typedefed
     61        //    types like size_t.  So trying to overload on ptrdiff_t vs int works in 64-bit mode
     62        //    but not in 32-bit mode.
     63        // -  Given bug of Trac #247, CFA gives sizeof expressions type unsigned long int, when it
     64        //    should give them type size_t.
     65        //
     66        //                          gcc -m32         cfa -m32 given bug         gcc -m64 (and cfa)
     67        // ptrdiff_t                int              int                        long int
     68        // size_t                   unsigned int     unsigned int               unsigned long int
     69        // typeof( sizeof(42) )     unsigned int     unsigned long int          unsigned long int
     70        // int                      int              int                        int
     71        //
     72        // So the solution must support types {zero_t, one_t, int, unsigned int, long int, unsigned long int}
     73        //
     74        // The solution cannot rely on implicit conversions (e.g. just have one overload for ptrdiff_t)
     75        // because assertion satisfaction requires types to match exacly.  Both higher-dimensional
     76        // subscripting and operations on slices use asserted subscript operators.  The test case
     77        // array-container/array-sbscr-cases covers the combinations.  Mike beleives that commenting out
     78        // any of the current overloads leads to one of those cases failing, either on 64- or 32-bit.
     79        // Mike is open to being shown a smaller set of overloads that still passes the test.
     80
     81        static inline Timmed & ?[?]( arpk(N, S, Timmed, Tbase ) & a, zero_t ) {
     82                //assert( 0 < N );
     83                subcheck( a, 0L, 0, N );
     84                return (Timmed &) a.strides[0];
     85        }
     86
     87        static inline Timmed & ?[?]( arpk(N, S, Timmed, Tbase ) & a, one_t ) {
     88                //assert( 1 < N );
     89                subcheck( a, 1L, 0, N );
     90                return (Timmed &) a.strides[1];
     91        }
     92
     93        static inline Timmed & ?[?]( arpk(N, S, Timmed, Tbase ) & a, int i ) {
     94                //assert( i < N );
     95                subcheck( a, (long int)i, 0, N );
     96                return (Timmed &) a.strides[i];
     97        }
     98
     99        static inline const Timmed & ?[?]( const arpk(N, S, Timmed, Tbase ) & a, int i ) {
     100                //assert( i < N );
     101                subcheck( a, (long int)i, 0, N );
     102                return (Timmed &) a.strides[i];
     103        }
     104
     105        static inline Timmed & ?[?]( arpk(N, S, Timmed, Tbase ) & a, unsigned int i ) {
     106                //assert( i < N );
     107                subcheck( a, (long int)i, 0, N );
     108                return (Timmed &) a.strides[i];
     109        }
     110
     111        static inline const Timmed & ?[?]( const arpk(N, S, Timmed, Tbase ) & a, unsigned int i ) {
     112                //assert( i < N );
     113                subcheck( a, (unsigned long int)i, 0, N );
     114                return (Timmed &) a.strides[i];
     115        }
     116
     117        static inline Timmed & ?[?]( arpk(N, S, Timmed, Tbase ) & a, long int i ) {
     118                //assert( i < N );
     119                subcheck( a, i, 0, N );
     120                return (Timmed &) a.strides[i];
     121        }
     122
     123        static inline const Timmed & ?[?]( const arpk(N, S, Timmed, Tbase ) & a, long int i ) {
     124                //assert( i < N );
     125                subcheck( a, i, 0, N );
     126                return (Timmed &) a.strides[i];
     127        }
     128
     129        static inline Timmed & ?[?]( arpk(N, S, Timmed, Tbase ) & a, unsigned long int i ) {
     130                //assert( i < N );
     131                subcheck( a, i, 0, N );
     132                return (Timmed &) a.strides[i];
     133        }
     134
     135        static inline const Timmed & ?[?]( const arpk(N, S, Timmed, Tbase ) & a, unsigned long int i ) {
     136                //assert( i < N );
     137                subcheck( a, i, 0, N );
     138                return (Timmed &) a.strides[i];
     139        }
     140
     141        static inline size_t ?`len( arpk(N, S, Timmed, Tbase ) & a ) {
     142                return N;
     143        }
     144
     145        static inline void __taglen( tag(arpk(N, S, Timmed, Tbase )), tag(N) ) {}
    133146}
    134147
    135148// RAII pattern has workarounds for
    136149//  - 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 ^?{}.
     150//      raii happen.  Performance on even a couple dimensions is unacceptable because of exponential
     151//      thunk creation: ?{}() needs all four otype funcs from next level, so does ^?{}(), so do the
     152//      other two.  This solution offers ?{}() that needs only ?{}(), and similar for ^?{}.
    140153
    141154forall( [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] );
     155static inline void ?{}( arpk(N, S, Timmed, Tbase ) & this ) {   
     156        void ?{}( S (&)[N] ) {}
     157        ?{}(this.strides);
     158
     159        for (i; N) ?{}( (Timmed &) this.strides[i] );
    147160}
    148161
    149162forall( [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     }
     163static inline void ^?{}( arpk(N, S, Timmed, Tbase ) & this ) {
     164        void ^?{}( S (&)[N] ) {}
     165        ^?{}(this.strides);
     166
     167        for (i; N ) {
     168                ^?{}( (Timmed &) this.strides[N-i-1] );
     169        }
    157170}
    158171
     
    169182// based on https://stackoverflow.com/questions/1872220/is-it-possible-to-iterate-over-arguments-in-variadic-macros
    170183
    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__)
     184        // Make a FOREACH macro
     185        #define FE_0(WHAT)
     186        #define FE_1(WHAT, X) WHAT(X)
     187        #define FE_2(WHAT, X, ...) WHAT(X)FE_1(WHAT, __VA_ARGS__)
     188        #define FE_3(WHAT, X, ...) WHAT(X)FE_2(WHAT, __VA_ARGS__)
     189        #define FE_4(WHAT, X, ...) WHAT(X)FE_3(WHAT, __VA_ARGS__)
     190        #define FE_5(WHAT, X, ...) WHAT(X)FE_4(WHAT, __VA_ARGS__)
     191        //... repeat as needed
     192
     193        #define GET_MACRO(_0,_1,_2,_3,_4,_5,NAME,...) NAME
     194        #define FOR_EACH(action,...) \
     195        GET_MACRO(_0,__VA_ARGS__,FE_5,FE_4,FE_3,FE_2,FE_1,FE_0)(action,__VA_ARGS__)
    183196
    184197#define COMMA_ttag(X) , ttag(X)
     
    200213forall( TA &, TB &, TC &, IxAB, IxBC ... | { TB & ?[?]( TA &, IxAB ); TC & ?[?]( TB &, IxBC ); } )
    201214static inline TC & ?[?]( TA & this, IxAB ab, IxBC bc ) {
    202     return this[ab][bc];
     215        return this[ab][bc];
    203216}
    204217
     
    209222forall( TA &, TB &, TC &, IxAB_0, IxBC | { TB & ?[?]( TA &, IxAB_0 ); TC & ?[?]( TB &, IxBC ); } )
    210223static inline TC & ?[?]( TA & this, IxAB_0 ab, IxBC bc ) {
    211     return this[ab][bc];
     224        return this[ab][bc];
    212225}
    213226
    214227forall( TA &, TB &, TC &, IxAB_0, IxAB_1, IxBC | { TB & ?[?]( TA &, IxAB_0, IxAB_1 ); TC & ?[?]( TB &, IxBC ); } )
    215228static inline TC & ?[?]( TA & this, IxAB_0 ab0, IxAB_1 ab1, IxBC bc ) {
    216     return this[[ab0,ab1]][bc];
     229        return this[[ab0,ab1]][bc];
    217230}
    218231
    219232forall( TA &, TB &, TC &, IxAB_0, IxAB_1, IxAB_2, IxBC | { TB & ?[?]( TA &, IxAB_0, IxAB_1, IxAB_2 ); TC & ?[?]( TB &, IxBC ); } )
    220233static inline TC & ?[?]( TA & this, IxAB_0 ab0, IxAB_1 ab1, IxAB_2 ab2, IxBC bc ) {
    221     return this[[ab0,ab1,ab2]][bc];
     234        return this[[ab0,ab1,ab2]][bc];
    222235}
    223236
     
    237250// Base
    238251forall( [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;
     252static inline tag(arpk(Nq, Sq, Tbase, Tbase )) enq_( tag(Tbase ), tag(Nq), tag(Sq), tag(Tbase ) ) {
     253        tag(arpk(Nq, Sq, Tbase, Tbase )) ret;
     254        return ret;
    242255}
    243256
    244257// Rec
    245 forall( [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;
     258forall( [Nq], Sq & | sized(Sq), [N], S & | sized(S), recq &, recr &, Tbase & | { tag(recr) enq_( tag(Tbase ), tag(Nq), tag(Sq), tag(recq) ); } )
     259static inline tag(arpk(N, S, recr, Tbase )) enq_( tag(Tbase ), tag(Nq), tag(Sq), tag(arpk(N, S, recq, Tbase )) ) {
     260        tag(arpk(N, S, recr, Tbase )) ret;
     261        return ret;
    249262}
    250263
    251264// Wrapper
    252265extern struct all_t {} all;
    253 forall( [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;
     266forall( [N], S & | sized(S), Te &, result &, Tbase & | { tag(result) enq_( tag(Tbase ), tag(N), tag(S), tag(Te) ); } )
     267static inline result & ?[?]( arpk(N, S, Te, Tbase ) & this, all_t ) {
     268        return (result&) this;
    256269}
    257270
     
    263276// forall(A &, Tv &, [N])
    264277// 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) );
     278//      Tv& ?[?]( A&, zero_t );
     279//      Tv& ?[?]( A&, one_t  );
     280//       Tv& ?[?]( A&, int      );
     281//                                 ...
     282//      size_t ?`len( A& );
     283//      void __taglen( tag(C), tag(N) );
    271284// };
    272285
    273286// working around N's not being accepted as arguments to traits
    274287
    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 }
     288#define ar( A, Tv, N ) {                                \
     289        Tv& ?[?]( A&, zero_t );                         \
     290        Tv& ?[?]( A&, one_t );                          \
     291        Tv& ?[?]( A&, int );                            \
     292        Tv& ?[?]( A&, unsigned int );           \
     293        Tv& ?[?]( A&, long int );                       \
     294        Tv& ?[?]( A&, unsigned long int );      \
     295        size_t ?`len( A& );                                     \
     296        void __taglen( tag(A), tag(N) );        \
     297}
Note: See TracChangeset for help on using the changeset viewer.