source: libcfa/src/stdlib.cfa@ 30aab55

Last change on this file since 30aab55 was 54af365, checked in by Peter A. Buhr <pabuhr@…>, 19 months 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.