// // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // stdlib -- // // Author : Peter A. Buhr // Created On : Thu Jan 28 17:12:35 2016 // Last Modified By : Peter A. Buhr // Last Modified On : Mon Jul 20 19:04:33 2020 // Update Count : 472 // #pragma once #include "bits/defs.hfa" #include "bits/align.hfa" #include // *alloc, strto*, ato* #include // Reduce includes by explicitly defining these routines. extern "C" { void * memalign( size_t alignment, size_t size ); // malloc.h void * pvalloc( size_t size ); // malloc.h void * memset( void * dest, int fill, size_t size ); // string.h void * memcpy( void * dest, const void * src, size_t size ); // string.h } // extern "C" //--------------------------------------- #ifndef EXIT_FAILURE #define EXIT_FAILURE 1 // failing exit status #define EXIT_SUCCESS 0 // successful exit status #endif // ! EXIT_FAILURE //--------------------------------------- // Macro because of returns #define $VAR_ALLOC( allocation, alignment ) \ if ( _Alignof(T) <= libAlign() ) return (T *)(void *)allocation( (size_t)sizeof(T) ); /* C allocation */ \ else return (T *)alignment( _Alignof(T), sizeof(T) ) #define $ARRAY_ALLOC( allocation, alignment, dim ) \ if ( _Alignof(T) <= libAlign() ) return (T *)(void *)allocation( dim, (size_t)sizeof(T) ); /* C allocation */ \ else return (T *)alignment( _Alignof(T), dim, sizeof(T) ) #define $RE_SPECIALS( ptr, size, allocation, alignment ) \ if ( unlikely( size == 0 ) || unlikely( ptr == 0p ) ) { \ if ( unlikely( size == 0 ) ) free( ptr ); \ $VAR_ALLOC( malloc, memalign ); \ } /* if */ static inline forall( dtype T | sized(T) ) { // Cforall safe equivalents, i.e., implicit size specification T * malloc( void ) { $VAR_ALLOC( malloc, memalign ); } // malloc T * aalloc( size_t dim ) { $ARRAY_ALLOC( aalloc, amemalign, dim ); } // aalloc T * calloc( size_t dim ) { $ARRAY_ALLOC( calloc, cmemalign, dim ); } // calloc T * resize( T * ptr, size_t size ) { // CFA resize, eliminate return-type cast $RE_SPECIALS( ptr, size, malloc, memalign ); return (T *)(void *)resize( (void *)ptr, size ); // CFA resize } // resize T * realloc( T * ptr, size_t size ) { // CFA realloc, eliminate return-type cast $RE_SPECIALS( ptr, size, malloc, memalign ); return (T *)(void *)realloc( (void *)ptr, size ); // C realloc } // realloc T * memalign( size_t align ) { return (T *)memalign( align, sizeof(T) ); // C memalign } // memalign T * amemalign( size_t align, size_t dim ) { return (T *)amemalign( align, dim, sizeof(T) ); // CFA amemalign } // amemalign T * cmemalign( size_t align, size_t dim ) { return (T *)cmemalign( align, dim, sizeof(T) ); // CFA cmemalign } // cmemalign T * aligned_alloc( size_t align ) { return (T *)aligned_alloc( align, sizeof(T) ); // C aligned_alloc } // aligned_alloc int posix_memalign( T ** ptr, size_t align ) { return posix_memalign( (void **)ptr, align, sizeof(T) ); // C posix_memalign } // posix_memalign T * valloc( void ) { return (T *)valloc( sizeof(T) ); // C valloc } // valloc T * pvalloc( void ) { return (T *)pvalloc( sizeof(T) ); // C pvalloc } // pvalloc } // distribution static inline forall( dtype T | sized(T) ) { // Cforall safe general allocation, fill, resize, array T * alloc( void ) { return malloc(); } // alloc T * alloc( size_t dim ) { return aalloc( dim ); } // alloc forall( dtype S | sized(S) ) T * alloc( S ptr[], size_t dim = 1 ) { // singleton/array resize size_t len = malloc_usable_size( ptr ); // current bucket size if ( sizeof(T) * dim > len ) { // not enough space ? T * temp = alloc( dim ); // new storage free( ptr ); // free old storage return temp; } else { return (T *)ptr; } // if } // alloc T * alloc( T ptr[], size_t dim, bool copy = true ) { if ( copy ) { return realloc( ptr, dim * sizeof(T) ); // CFA realloc } else { return resize( ptr, dim * sizeof(T) ); // CFA resize } // if } // alloc T * alloc_set( char fill ) { return (T *)memset( (T *)alloc(), (int)fill, sizeof(T) ); // initialize with fill value } // alloc T * alloc_set( T fill ) { return (T *)memcpy( (T *)alloc(), &fill, sizeof(T) ); // initialize with fill value } // alloc T * alloc_set( size_t dim, char fill ) { return (T *)memset( (T *)alloc( dim ), (int)fill, dim * sizeof(T) ); // initialize with fill value } // alloc T * alloc_set( size_t dim, T fill ) { T * r = (T *)alloc( dim ); for ( i; dim ) { memcpy( &r[i], &fill, sizeof(T) ); } // initialize with fill value return r; } // alloc T * alloc_set( size_t dim, const T fill[] ) { return (T *)memcpy( (T *)alloc( dim ), fill, dim * sizeof(T) ); // initialize with fill value } // alloc T * alloc_set( T ptr[], size_t dim, char fill ) { // realloc array with fill size_t osize = malloc_size( ptr ); // current allocation T * nptr = realloc( ptr, dim * sizeof(T) ); // CFA realloc size_t nsize = malloc_size( nptr ); // new allocation if ( nsize > osize ) { // larger ? memset( (char *)nptr + osize, (int)fill, nsize - osize ); // initialize added storage } // if return (T *)nptr; } // alloc_set T * alloc_set( T ptr[], size_t dim, T & fill ) { // realloc array with fill size_t odim = malloc_size( ptr ) / sizeof(T); // current allocation T * nptr = realloc( ptr, dim * sizeof(T) ); // CFA realloc size_t ndim = malloc_size( nptr ) / sizeof(T); // new allocation if ( ndim > odim ) { // larger ? for ( i; odim ~ ndim ) { memcpy( &nptr[i], &fill, sizeof(T) ); // initialize with fill value } // for } // if return (T *)nptr; } // alloc_align_set } // distribution static inline forall( dtype T | sized(T) ) { T * alloc_align( size_t align ) { return (T *)memalign( align, sizeof(T) ); } // alloc_align T * alloc_align( size_t align, size_t dim ) { return (T *)memalign( align, dim * sizeof(T) ); } // alloc_align T * alloc_align( T * ptr, size_t align ) { // aligned realloc array return (T *)(void *)realloc( (void *)ptr, align, sizeof(T) ); // CFA realloc } // alloc_align forall( dtype S | sized(S) ) T * alloc_align( S ptr[], size_t align ) { // aligned reuse array return (T *)(void *)resize( (void *)ptr, align, sizeof(T) ); // CFA realloc } // alloc_align T * alloc_align( T ptr[], size_t align, size_t dim ) { // aligned realloc array return (T *)(void *)realloc( (void *)ptr, align, dim * sizeof(T) ); // CFA realloc } // alloc_align T * alloc_align_set( size_t align, char fill ) { return (T *)memset( (T *)alloc_align( align ), (int)fill, sizeof(T) ); // initialize with fill value } // alloc_align T * alloc_align_set( size_t align, T fill ) { return (T *)memcpy( (T *)alloc_align( align ), &fill, sizeof(T) ); // initialize with fill value } // alloc_align T * alloc_align_set( size_t align, size_t dim, char fill ) { return (T *)memset( (T *)alloc_align( align, dim ), (int)fill, dim * sizeof(T) ); // initialize with fill value } // alloc_align T * alloc_align_set( size_t align, size_t dim, T fill ) { T * r = (T *)alloc_align( align, dim ); for ( i; dim ) { memcpy( &r[i], &fill, sizeof(T) ); } // initialize with fill value return r; } // alloc_align T * alloc_align_set( size_t align, size_t dim, const T fill[] ) { return (T *)memcpy( (T *)alloc_align( align, dim ), fill, dim * sizeof(T) ); } // alloc_align T * alloc_align_set( T ptr[], size_t align, size_t dim, char fill ) { size_t osize = malloc_size( ptr ); // current allocation T * nptr = realloc( ptr, align, dim * sizeof(T) ); // CFA realloc size_t nsize = malloc_size( nptr ); // new allocation if ( nsize > osize ) { // larger ? memset( (char *)nptr + osize, (int)fill, nsize - osize ); // initialize added storage } // if return (T *)nptr; } // alloc_align_set T * alloc_align_set( T ptr[], size_t align, size_t dim, T & fill ) { size_t odim = malloc_size( ptr ) / sizeof(T); // current allocation T * nptr = realloc( ptr, align, dim * sizeof(T) ); // CFA realloc size_t ndim = malloc_size( nptr ); // new allocation if ( ndim > odim ) { // larger ? for ( i; odim ~ ndim ) { memcpy( &nptr[i], &fill, sizeof(T) ); // initialize with fill value } // for } // if return (T *)nptr; } // alloc_align_set } // distribution static inline forall( dtype T | sized(T) ) { // Cforall safe initialization/copy, i.e., implicit size specification, non-array types T * memset( T * dest, char fill ) { return (T *)memset( dest, fill, sizeof(T) ); } // memset T * memcpy( T * dest, const T * src ) { return (T *)memcpy( dest, src, sizeof(T) ); } // memcpy } // distribution static inline forall( dtype T | sized(T) ) { // Cforall safe initialization/copy, i.e., implicit size specification, array types T * amemset( T dest[], char fill, size_t dim ) { return (T *)(void *)memset( dest, fill, dim * sizeof(T) ); // C memset } // amemset T * amemcpy( T dest[], const T src[], size_t dim ) { return (T *)(void *)memcpy( dest, src, dim * sizeof(T) ); // C memcpy } // amemcpy } // distribution // Cforall allocation/deallocation and constructor/destructor, non-array types forall( dtype T | sized(T), ttype Params | { void ?{}( T &, Params ); } ) T * new( Params p ); forall( dtype T | { void ^?{}( T & ); } ) void delete( T * ptr ); forall( dtype T, ttype Params | { void ^?{}( T & ); void delete( Params ); } ) void delete( T * ptr, Params rest ); // Cforall allocation/deallocation and constructor/destructor, array types forall( dtype T | sized(T), ttype Params | { void ?{}( T &, Params ); } ) T * anew( size_t dim, Params p ); forall( dtype T | sized(T) | { void ^?{}( T & ); } ) void adelete( size_t dim, T arr[] ); forall( dtype T | sized(T) | { void ^?{}( T & ); }, ttype Params | { void adelete( Params ); } ) void adelete( size_t dim, T arr[], Params rest ); //--------------------------------------- static inline { int strto( const char sptr[], char ** eptr, int base ) { return (int)strtol( sptr, eptr, base ); } unsigned int strto( const char sptr[], char ** eptr, int base ) { return (unsigned int)strtoul( sptr, eptr, base ); } long int strto( const char sptr[], char ** eptr, int base ) { return strtol( sptr, eptr, base ); } unsigned long int strto( const char sptr[], char ** eptr, int base ) { return strtoul( sptr, eptr, base ); } long long int strto( const char sptr[], char ** eptr, int base ) { return strtoll( sptr, eptr, base ); } unsigned long long int strto( const char sptr[], char ** eptr, int base ) { return strtoull( sptr, eptr, base ); } float strto( const char sptr[], char ** eptr ) { return strtof( sptr, eptr ); } double strto( const char sptr[], char ** eptr ) { return strtod( sptr, eptr ); } long double strto( const char sptr[], char ** eptr ) { return strtold( sptr, eptr ); } } // distribution float _Complex strto( const char sptr[], char ** eptr ); double _Complex strto( const char sptr[], char ** eptr ); long double _Complex strto( const char sptr[], char ** eptr ); static inline { int ato( const char sptr[] ) { return (int)strtol( sptr, 0p, 10 ); } unsigned int ato( const char sptr[] ) { return (unsigned int)strtoul( sptr, 0p, 10 ); } long int ato( const char sptr[] ) { return strtol( sptr, 0p, 10 ); } unsigned long int ato( const char sptr[] ) { return strtoul( sptr, 0p, 10 ); } long long int ato( const char sptr[] ) { return strtoll( sptr, 0p, 10 ); } unsigned long long int ato( const char sptr[] ) { return strtoull( sptr, 0p, 10 ); } float ato( const char sptr[] ) { return strtof( sptr, 0p ); } double ato( const char sptr[] ) { return strtod( sptr, 0p ); } long double ato( const char sptr[] ) { return strtold( sptr, 0p ); } float _Complex ato( const char sptr[] ) { return strto( sptr, 0p ); } double _Complex ato( const char sptr[] ) { return strto( sptr, 0p ); } long double _Complex ato( const char sptr[] ) { return strto( sptr, 0p ); } } // distribution //--------------------------------------- forall( otype E | { int ?