source: libcfa/src/stdlib.cfa@ 2df85ce

Last change on this file since 2df85ce was 2df85ce, checked in by Peter A. Buhr <pabuhr@…>, 10 hours ago

update anew/adelete ctor/dtor to handle array with 0-byte elements

  • Property mode set to 100644
File size: 9.0 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 : Wed Sep 24 18:01:01 2025
13// Update Count : 759
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 <complex.h> // _Complex_I
24#include <assert.h>
25#include <ctype.h> // isblank
26
27#pragma GCC visibility push(default)
28
29//---------------------------------------
30
31// Cforall allocation/deallocation and constructor/destructor, array types
32
33forall( T & | sized(T), Parms ... | { void ?{}( T &, Parms ); } )
34T * anew( size_t dim, Parms p ) {
35 T * arr;
36 if ( sizeof( T ) == 0 ) { // empty element size ?
37 arr = (T *)(size_t *)alloc(); // create fake array
38 *((size_t *)arr) = dim; // remember dimension
39 } else arr = alloc( dim );
40 for ( i; dim ) {
41 (arr[i]){ p }; // run constructor
42 } // for
43 return arr;
44} // anew
45
46forall( T & | sized(T) | { void ^?{}( T & ); } )
47void adelete( T arr[] ) {
48 if ( arr == 0p ) return; // 0p ? special case
49 size_t dim = sizeof( T ) == 0 ? (size_t)(*(size_t *)arr) : malloc_size( arr ) / sizeof( T ); // compute dimension
50 for ( i; 0 -~= dim - 1 ) { // reverse allocation order, must be signed
51 ^(arr[i]){}; // run destructor
52 } // for
53 if ( sizeof( T ) == 0 ) free( (size_t *)arr ); else free( arr );
54} // adelete
55
56forall( T & | sized(T) | { void ^?{}( T & ); }, List ... | { void adelete( List ); } )
57void adelete( T arr[], List rest ) {
58 adelete( arr );
59 adelete( rest );
60} // adelete
61
62//---------------------------------------
63
64// Check if all string characters are a specific kind, e.g., checkif( s, isblank )
65
66bool checkif( const char s[], int (* kind)( int ) ) {
67 for () {
68 if ( *s == '\0' ) return true;
69 if ( ! kind( *s ) ) return false;
70 s += 1;
71 } // for
72} // checkif
73
74bool checkif( const char s[], int (* kind)( int, locale_t ), locale_t locale ) {
75 for () {
76 if ( *s == '\0' ) return true;
77 if ( ! kind( *s, locale ) ) return false;
78 s += 1;
79 } // for
80} // checkif
81
82//---------------------------------------
83
84float _Complex strto( const char sptr[], char * eptr[] ) {
85 float re, im;
86 char * eeptr;
87 errno = 0; // reset
88 re = strtof( sptr, &eeptr );
89 if ( sptr != eeptr ) {
90 im = strtof( eeptr, &eeptr );
91 if ( sptr != eeptr ) {
92 if ( *eeptr == 'i' ) {
93 if ( eptr != 0p ) *eptr = eeptr + 1;
94 return re + im * _Complex_I;
95 } // if
96 } // if
97 } // if
98 if ( eptr != 0p ) *eptr = eeptr; // error case
99 return 0.0f + 0.0f * _Complex_I;
100} // strto
101
102double _Complex strto( const char sptr[], char * eptr[] ) {
103 double re, im;
104 char * eeptr;
105 re = strtod( sptr, &eeptr );
106 if ( sptr != eeptr ) {
107 im = strtod( eeptr, &eeptr );
108 if ( sptr != eeptr ) {
109 if ( *eeptr == 'i' ) {
110 if ( eptr != 0p ) *eptr = eeptr + 1;
111 return re + im * _Complex_I;
112 } // if
113 } // if
114 } // if
115 if ( eptr != 0p ) *eptr = eeptr; // error case
116 return 0.0 + 0.0 * _Complex_I;
117} // strto
118
119long double _Complex strto( const char sptr[], char * eptr[] ) {
120 long double re, im;
121 char * eeptr;
122 re = strtold( sptr, &eeptr );
123 if ( sptr != eeptr ) {
124 im = strtold( eeptr, &eeptr );
125 if ( sptr != eeptr ) {
126 if ( *eeptr == 'i' ) {
127 if ( eptr != 0p ) *eptr = eeptr + 1;
128 return re + im * _Complex_I;
129 } // if
130 } // if
131 } // if
132 if ( eptr != 0p ) *eptr = eeptr; // error case
133 return 0.0L + 0.0L * _Complex_I;
134} // strto
135
136forall( T | { T strto( const char sptr[], char * eptr[], int ); } )
137T convert( const char sptr[] ) { // integral
138 char * eptr;
139 errno = 0; // reset
140 T val = strto( sptr, &eptr, 10 ); // attempt conversion
141 if ( errno == ERANGE ) throw ExceptionInst( out_of_range );
142 if ( eptr == sptr || // conversion failed, no characters generated
143 eptr[0] != '\0' && ! checkif( eptr, isblank ) ) throw ExceptionInst( invalid_argument ); // not at end of blank str ?
144 return val;
145} // convert
146
147forall( T | { T strto( const char sptr[], char * eptr[] ); } )
148T convert( const char sptr[] ) { // floating-point
149 char * eptr;
150 errno = 0; // reset
151 T val = strto( sptr, &eptr ); // attempt conversion
152 if ( errno == ERANGE ) throw ExceptionInst( out_of_range );
153 if ( eptr == sptr || // conversion failed, no characters generated
154 eptr[0] != '\0' && ! checkif( eptr, isblank ) ) throw ExceptionInst( invalid_argument ); // not at end of blank str ?
155 return val;
156} // convert
157
158//---------------------------------------
159
160forall( E | { int ?<?( E, E ); } ) {
161 E * bsearch( E key, const E * vals, size_t dim ) {
162 int cmp( const void * t1, const void * t2 ) {
163 return *(E *)t1 < *(E *)t2 ? -1 : *(E *)t2 < *(E *)t1 ? 1 : 0;
164 } // cmp
165 return (E *)bsearch( &key, vals, dim, sizeof(E), cmp );
166 } // bsearch
167
168 size_t bsearch( E key, const E * vals, size_t dim ) {
169 E * result = bsearch( key, vals, dim );
170 return result ? result - vals : dim; // pointer subtraction includes sizeof(E)
171 } // bsearch
172
173 size_t bsearchl( E key, const E * vals, size_t dim ) {
174 size_t l = 0, m, h = dim;
175 while ( l < h ) {
176 m = (l + h) / 2;
177 if ( (E &)(vals[m]) < key ) { // cast away const
178 l = m + 1;
179 } else {
180 h = m;
181 } // if
182 } // while
183 return l;
184 } // bsearchl
185
186 E * bsearchl( E key, const E * vals, size_t dim ) {
187 size_t posn = bsearchl( key, vals, dim );
188 return (E *)(&vals[posn]); // cast away const
189 } // bsearchl
190
191 size_t bsearchu( E key, const E * vals, size_t dim ) {
192 size_t l = 0, m, h = dim;
193 while ( l < h ) {
194 m = (l + h) / 2;
195 if ( ! ( key < (E &)(vals[m]) ) ) { // cast away const
196 l = m + 1;
197 } else {
198 h = m;
199 } // if
200 } // while
201 return l;
202 } // bsearchu
203
204 E * bsearchu( E key, const E * vals, size_t dim ) {
205 size_t posn = bsearchu( key, vals, dim );
206 return (E *)(&vals[posn]);
207 } // bsearchu
208
209
210 void qsort( E * vals, size_t dim ) {
211 int cmp( const void * t1, const void * t2 ) {
212 return *(E *)t1 < *(E *)t2 ? -1 : *(E *)t2 < *(E *)t1 ? 1 : 0;
213 } // cmp
214 qsort( vals, dim, sizeof(E), cmp );
215 } // qsort
216} // distribution
217
218
219forall( K, E | { int ?<?( K, K ); K getKey( const E & ); } ) {
220 E * bsearch( K key, const E * vals, size_t dim ) {
221 int cmp( const void * t1, const void * t2 ) {
222 return *(K *)t1 < getKey( *(E *)t2 ) ? -1 : getKey( *(E *)t2 ) < *(K *)t1 ? 1 : 0;
223 } // cmp
224 return (E *)bsearch( &key, vals, dim, sizeof(E), cmp );
225 } // bsearch
226
227 size_t bsearch( K key, const E * vals, size_t dim ) {
228 E * result = bsearch( key, vals, dim );
229 return result ? result - vals : dim; // pointer subtraction includes sizeof(E)
230 } // bsearch
231
232 size_t bsearchl( K key, const E * vals, size_t dim ) {
233 size_t l = 0, m, h = dim;
234 while ( l < h ) {
235 m = (l + h) / 2;
236 if ( getKey( vals[m] ) < key ) {
237 l = m + 1;
238 } else {
239 h = m;
240 } // if
241 } // while
242 return l;
243 } // bsearchl
244
245 E * bsearchl( K key, const E * vals, size_t dim ) {
246 size_t posn = bsearchl( key, vals, dim );
247 return (E *)(&vals[posn]); // cast away const
248 } // bsearchl
249
250 size_t bsearchu( K key, const E * vals, size_t dim ) {
251 size_t l = 0, m, h = dim;
252 while ( l < h ) {
253 m = (l + h) / 2;
254 if ( ! ( key < getKey( vals[m] ) ) ) {
255 l = m + 1;
256 } else {
257 h = m;
258 } // if
259 } // while
260 return l;
261 } // bsearchu
262
263 E * bsearchu( K key, const E * vals, size_t dim ) {
264 size_t posn = bsearchu( key, vals, dim );
265 return (E *)(&vals[posn]);
266 } // bsearchu
267} // distribution
268
269//---------------------------------------
270
271extern "C" { // override C version
272 void srandom( unsigned int seed ) { srand48( (long int)seed ); }
273 long int random( void ) { return mrand48(); } // GENERATES POSITIVE AND NEGATIVE VALUES
274} // extern "C"
275
276float random( void ) { return (float)drand48(); } // cast otherwise float uses lrand48
277double random( void ) { return drand48(); }
278float _Complex random( void ) { return (float)drand48() + (float _Complex)(drand48() * _Complex_I); }
279double _Complex random( void ) { return drand48() + (double _Complex)(drand48() * _Complex_I); }
280long double _Complex random( void ) { return (long double)drand48() + (long double _Complex)(drand48() * _Complex_I); }
281
282//---------------------------------------
283
284// would be cool to make hidden but it's needed for libcfathread
285__attribute__((visibility("default"))) size_t __global_random_seed; // sequential/concurrent
286__attribute__((visibility("hidden"))) PRNG_STATE_T __global_random_state; // sequential only
287
288void set_seed( size_t seed ) {
289 __global_random_seed = seed;
290 PRNG_SET_SEED( __global_random_state, seed );
291} // set_seed
292
293size_t get_seed() { return __global_random_seed; }
294size_t prng( void ) { return PRNG_NAME( __global_random_state ); } // [0,UINT_MAX]
295
296//---------------------------------------
297
298bool threading_enabled( void ) __attribute__(( weak )) { return false; }
299
300// Local Variables: //
301// tab-width: 4 //
302// End: //
Note: See TracBrowser for help on using the repository browser.