source: libcfa/src/stdlib.cfa @ 54af365

Last change on this file since 54af365 was 54af365, checked in by Peter A. Buhr <pabuhr@…>, 8 weeks ago

fix convert function for float-point values, add isspace-like routines for C arrays

  • Property mode set to 100644
File size: 10.3 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// stdlib.c --
8//
9// Author           : Peter A. Buhr
10// Created On       : Thu Jan 28 17:10:29 2016
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Fri Mar 15 18:47:28 2024
13// Update Count     : 685
14//
15
16#include "stdlib.hfa"
17#include "bits/random.hfa"
18#include "concurrency/invoke.h"                                                 // random_state
19
20//---------------------------------------
21
22#include <string.h>                                                                             // memcpy, memset
23//#include <math.h>                                                                             // fabsf, fabs, fabsl
24#include <complex.h>                                                                    // _Complex_I
25#include <assert.h>
26#include <ctype.h>
27
28#pragma GCC visibility push(default)
29
30//---------------------------------------
31
32// Cforall allocation/deallocation and constructor/destructor, array types
33
34forall( T & | sized(T), TT... | { void ?{}( T &, TT ); } )
35T * anew( size_t dim, TT p ) {
36        T * arr = alloc( dim );
37        for ( i; dim ) {
38                (arr[i]){ p };                                                                  // run constructor
39        } // for
40        return arr;
41} // anew
42
43forall( T & | sized(T) | { void ^?{}( T & ); } )
44void adelete( T arr[] ) {
45        if ( arr ) {                                                                            // ignore null
46                size_t dim = malloc_size( arr ) / sizeof( T );
47                for ( i; 0 -~= dim - 1 ) {                                              // reverse allocation order, must be unsigned
48                        ^(arr[i]){};                                                            // run destructor
49                } // for
50                free( arr );
51        } // if
52} // adelete
53
54forall( T & | sized(T) | { void ^?{}( T & ); }, TT... | { void adelete( TT ); } )
55void adelete( T arr[], TT rest ) {
56        if ( arr ) {                                                                            // ignore null
57                size_t dim = malloc_size( arr ) / sizeof( T );
58                for ( i; 0 -~= dim - 1 ) {                                              // reverse allocation order, must be unsigned
59                        ^(arr[i]){};                                                            // run destructor
60                } // for
61                free( arr );
62        } // if
63        adelete( rest );
64} // adelete
65
66//---------------------------------------
67
68// Cannot overload with singular (isspace) counterparts because they are macros.
69
70bool isalnums( const char s[] ) {
71        for () {
72                if ( *s == '\0' ) return true;
73                if ( ! isalnum( *s ) ) return false;
74                s += 1;
75        } // for
76} // isalnums
77
78bool isalphas( const char s[] ) {
79        for () {
80                if ( *s == '\0' ) return true;
81                if ( ! isalpha( *s ) ) return false;
82                s += 1;
83        } // for
84} // isblanks
85
86bool iscntrls( const char s[] ) {
87        for () {
88                if ( *s == '\0' ) return true;
89                if ( ! iscntrl( *s ) ) return false;
90                s += 1;
91        } // for
92} // iscntrls
93
94bool isdigits( const char s[] ) {
95        for () {
96                if ( *s == '\0' ) return true;
97                if ( ! isdigit( *s ) ) return false;
98                s += 1;
99        } // for
100} // isdigits
101
102bool isgraphs( const char s[] ) {
103        for () {
104                if ( *s == '\0' ) return true;
105                if ( ! isgraph( *s ) ) return false;
106                s += 1;
107        } // for
108} // isgraphs
109
110bool islowers( const char s[] ) {
111        for () {
112                if ( *s == '\0' ) return true;
113                if ( ! islower( *s ) ) return false;
114                s += 1;
115        } // for
116} // islowers
117
118bool isprints( const char s[] ) {
119        for () {
120                if ( *s == '\0' ) return true;
121                if ( ! isprint( *s ) ) return false;
122                s += 1;
123        } // for
124} // isprints
125
126bool ispuncts( const char s[] ) {
127        for () {
128                if ( *s == '\0' ) return true;
129                if ( ! ispunct( *s ) ) return false;
130                s += 1;
131        } // for
132} // ispuncts
133
134bool isspaces( const char s[] ) {
135        for () {
136                if ( *s == '\0' ) return true;
137                if ( ! isspace( *s ) ) return false;
138                s += 1;
139        } // for
140} // isspaces
141
142bool isblanks( const char s[] ) {
143        for () {
144                if ( *s == '\0' ) return true;
145                if ( ! isblank( *s ) ) return false;
146                s += 1;
147        } // for
148} // isblanks
149
150bool isuppers( const char s[] ) {
151        for () {
152                if ( *s == '\0' ) return true;
153                if ( ! isupper( *s ) ) return false;
154                s += 1;
155        } // for
156} // isuppers
157
158bool isxdigits( const char s[] ) {
159        for () {
160                if ( *s == '\0' ) return true;
161                if ( ! isxdigit( *s ) ) return false;
162                s += 1;
163        } // for
164} // isxdigits
165
166//---------------------------------------
167
168float _Complex strto( const char sptr[], char * eptr[] ) {
169        float re, im;
170        char * eeptr;
171        errno = 0;                                                                                      // reset
172        re = strtof( sptr, &eeptr );
173        if ( sptr != eeptr ) {
174                im = strtof( eeptr, &eeptr );
175                if ( sptr != eeptr ) {
176                        if ( *eeptr == 'i' ) {
177                                if ( eptr != 0p ) *eptr = eeptr + 1;
178                                return re + im * _Complex_I;
179                        } // if
180                } // if
181        } // if
182        if ( eptr != 0p ) *eptr = eeptr;                                        // error case
183        return 0.0f + 0.0f * _Complex_I;
184} // strto
185
186double _Complex strto( const char sptr[], char * eptr[] ) {
187        double re, im;
188        char * eeptr;
189        re = strtod( sptr, &eeptr );
190        if ( sptr != eeptr ) {
191                im = strtod( eeptr, &eeptr );
192                if ( sptr != eeptr ) {
193                        if ( *eeptr == 'i' ) {
194                                if ( eptr != 0p ) *eptr = eeptr + 1;
195                                return re + im * _Complex_I;
196                        } // if
197                } // if
198        } // if
199        if ( eptr != 0p ) *eptr = eeptr;                                        // error case
200        return 0.0 + 0.0 * _Complex_I;
201} // strto
202
203long double _Complex strto( const char sptr[], char * eptr[] ) {
204        long double re, im;
205        char * eeptr;
206        re = strtold( sptr, &eeptr );
207        if ( sptr != eeptr ) {
208                im = strtold( eeptr, &eeptr );
209                if ( sptr != eeptr ) {
210                        if ( *eeptr == 'i' ) {
211                                if ( eptr != 0p ) *eptr = eeptr + 1;
212                                return re + im * _Complex_I;
213                        } // if
214                } // if
215        } // if
216        if ( eptr != 0p ) *eptr = eeptr;                                        // error case
217        return 0.0L + 0.0L * _Complex_I;
218} // strto
219
220forall( T | { T strto( const char sptr[], char * eptr[], int ); } )
221T convert( const char sptr[] ) {                                                // integral
222        char * eptr;
223        errno = 0;                                                                                      // reset
224        T val = strto( sptr, &eptr, 10 );                                       // attempt conversion
225        if ( errno == ERANGE ) throw ExceptionInst( out_of_range );
226        if ( eptr == sptr ||                                                            // conversion failed, no characters generated
227                 eptr[0] != '\0' && ! isspaces( eptr ) ) throw ExceptionInst( invalid_argument ); // not at end of blank str ?
228        return val;
229} // convert
230
231forall( T | { T strto( const char sptr[], char * eptr[] ); } )
232T convert( const char sptr[] ) {                                                // floating-point
233        char * eptr;
234        errno = 0;                                                                                      // reset
235        T val = strto( sptr, &eptr );                                           // attempt conversion
236        if ( errno == ERANGE ) throw ExceptionInst( out_of_range );
237        if ( eptr == sptr ||                                                            // conversion failed, no characters generated
238                 eptr[0] != '\0' && ! isspaces( eptr ) ) throw ExceptionInst( invalid_argument ); // not at end of blank str ?
239        return val;
240} // convert
241
242//---------------------------------------
243
244forall( E | { int ?<?( E, E ); } ) {
245        E * bsearch( E key, const E * vals, size_t dim ) {
246                int cmp( const void * t1, const void * t2 ) {
247                        return *(E *)t1 < *(E *)t2 ? -1 : *(E *)t2 < *(E *)t1 ? 1 : 0;
248                } // cmp
249                return (E *)bsearch( &key, vals, dim, sizeof(E), cmp );
250        } // bsearch
251
252        size_t bsearch( E key, const E * vals, size_t dim ) {
253                E * result = bsearch( key, vals, dim );
254                return result ? result - vals : dim;                    // pointer subtraction includes sizeof(E)
255        } // bsearch
256
257        size_t bsearchl( E key, const E * vals, size_t dim ) {
258                size_t l = 0, m, h = dim;
259                while ( l < h ) {
260                        m = (l + h) / 2;
261                        if ( (E &)(vals[m]) < key ) {                           // cast away const
262                                l = m + 1;
263                        } else {
264                                h = m;
265                        } // if
266                } // while
267                return l;
268        } // bsearchl
269
270        E * bsearchl( E key, const E * vals, size_t dim ) {
271                size_t posn = bsearchl( key, vals, dim );
272                return (E *)(&vals[posn]);                                              // cast away const
273        } // bsearchl
274
275        size_t bsearchu( E key, const E * vals, size_t dim ) {
276                size_t l = 0, m, h = dim;
277                while ( l < h ) {
278                        m = (l + h) / 2;
279                        if ( ! ( key < (E &)(vals[m]) ) ) {                     // cast away const
280                                l = m + 1;
281                        } else {
282                                h = m;
283                        } // if
284                } // while
285                return l;
286        } // bsearchu
287
288        E * bsearchu( E key, const E * vals, size_t dim ) {
289                size_t posn = bsearchu( key, vals, dim );
290                return (E *)(&vals[posn]);
291        } // bsearchu
292
293
294        void qsort( E * vals, size_t dim ) {
295                int cmp( const void * t1, const void * t2 ) {
296                        return *(E *)t1 < *(E *)t2 ? -1 : *(E *)t2 < *(E *)t1 ? 1 : 0;
297                } // cmp
298                qsort( vals, dim, sizeof(E), cmp );
299        } // qsort
300} // distribution
301
302
303forall( K, E | { int ?<?( K, K ); K getKey( const E & ); } ) {
304        E * bsearch( K key, const E * vals, size_t dim ) {
305                int cmp( const void * t1, const void * t2 ) {
306                        return *(K *)t1 < getKey( *(E *)t2 ) ? -1 : getKey( *(E *)t2 ) < *(K *)t1 ? 1 : 0;
307                } // cmp
308                return (E *)bsearch( &key, vals, dim, sizeof(E), cmp );
309        } // bsearch
310
311        size_t bsearch( K key, const E * vals, size_t dim ) {
312                E * result = bsearch( key, vals, dim );
313                return result ? result - vals : dim;                    // pointer subtraction includes sizeof(E)
314        } // bsearch
315
316        size_t bsearchl( K key, const E * vals, size_t dim ) {
317                size_t l = 0, m, h = dim;
318                while ( l < h ) {
319                        m = (l + h) / 2;
320                        if ( getKey( vals[m] ) < key ) {
321                                l = m + 1;
322                        } else {
323                                h = m;
324                        } // if
325                } // while
326                return l;
327        } // bsearchl
328
329        E * bsearchl( K key, const E * vals, size_t dim ) {
330                size_t posn = bsearchl( key, vals, dim );
331                return (E *)(&vals[posn]);                                              // cast away const
332        } // bsearchl
333
334        size_t bsearchu( K key, const E * vals, size_t dim ) {
335                size_t l = 0, m, h = dim;
336                while ( l < h ) {
337                        m = (l + h) / 2;
338                        if ( ! ( key < getKey( vals[m] ) ) ) {
339                                l = m + 1;
340                        } else {
341                                h = m;
342                        } // if
343                } // while
344                return l;
345        } // bsearchu
346
347        E * bsearchu( K key, const E * vals, size_t dim ) {
348                size_t posn = bsearchu( key, vals, dim );
349                return (E *)(&vals[posn]);
350        } // bsearchu
351} // distribution
352
353//---------------------------------------
354
355extern "C" {                                                                                    // override C version
356        void srandom( unsigned int seed ) { srand48( (long int)seed ); }
357        long int random( void ) { return mrand48(); }           // GENERATES POSITIVE AND NEGATIVE VALUES
358} // extern "C"
359
360float random( void ) { return (float)drand48(); }               // cast otherwise float uses lrand48
361double random( void ) { return drand48(); }
362float _Complex random( void ) { return (float)drand48() + (float _Complex)(drand48() * _Complex_I); }
363double _Complex random( void ) { return drand48() + (double _Complex)(drand48() * _Complex_I); }
364long double _Complex random( void ) { return (long double)drand48() + (long double _Complex)(drand48() * _Complex_I); }
365
366//---------------------------------------
367
368// would be cool to make hidden but it's needed for libcfathread
369__attribute__((visibility("default"))) size_t __global_random_seed; // sequential/concurrent
370__attribute__((visibility("hidden"))) PRNG_STATE_T __global_random_state; // sequential only
371
372void set_seed( size_t seed ) {
373        __global_random_seed = seed;
374        PRNG_SET_SEED( __global_random_state, seed );
375} // set_seed
376
377size_t get_seed() { return __global_random_seed; }
378size_t prng( void ) { return PRNG_NAME( __global_random_state ); } // [0,UINT_MAX]
379
380//---------------------------------------
381
382bool threading_enabled( void ) __attribute__(( weak )) { return false; }
383
384// Local Variables: //
385// tab-width: 4 //
386// End: //
Note: See TracBrowser for help on using the repository browser.