diff options
author | Jakub Jelinek <jakub@redhat.com> | 2022-01-04 21:32:05 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2022-01-11 23:49:50 +0100 |
commit | 5db042b2b8484e28d1bf8726fa9ef69b8495ddac (patch) | |
tree | 3e0f48801e5a46fe4c04a04daabaea89edda220e /libgfortran/intrinsics/random.c | |
parent | 06a74228ce589dc24b37341d22a6933cdccdb6bd (diff) | |
download | gcc-5db042b2b8484e28d1bf8726fa9ef69b8495ddac.zip gcc-5db042b2b8484e28d1bf8726fa9ef69b8495ddac.tar.gz gcc-5db042b2b8484e28d1bf8726fa9ef69b8495ddac.tar.bz2 |
fortran, libgfortran: Add remaining missing *_r17 symbols
Following patch adds remaining missing *_r17 entrypoints, so that
we have 91 *_r16 and 91 *_r17 entrypoints (and 24 *_c16 and 24 *_c17).
This fixes:
FAIL: gfortran.dg/dec_math.f90 -O0 execution test
FAIL: gfortran.dg/dec_math.f90 -O1 execution test
FAIL: gfortran.dg/dec_math.f90 -O2 execution test
FAIL: gfortran.dg/dec_math.f90 -O3 -fomit-frame-pointer -funroll-loops -fpeel-loops -ftracer -finline-functions execution test
FAIL: gfortran.dg/dec_math.f90 -O3 -g execution test
FAIL: gfortran.dg/dec_math.f90 -Os execution test
FAIL: gfortran.dg/ieee/dec_math_1.f90 -O0 execution test
FAIL: gfortran.dg/ieee/dec_math_1.f90 -O1 execution test
FAIL: gfortran.dg/ieee/dec_math_1.f90 -O2 execution test
FAIL: gfortran.dg/ieee/dec_math_1.f90 -O3 -fomit-frame-pointer -funroll-loops -fpeel-loops -ftracer -finline-functions execution test
FAIL: gfortran.dg/ieee/dec_math_1.f90 -O3 -g execution test
FAIL: gfortran.dg/ieee/dec_math_1.f90 -Os execution test
2022-01-04 Jakub Jelinek <jakub@redhat.com>
gcc/fortran/
* trans-intrinsic.c (gfc_get_intrinsic_lib_fndecl): Use
gfc_type_abi_kind.
libgfortran/
* libgfortran.h (GFC_REAL_17_INFINITY, GFC_REAL_17_QUIET_NAN): Define.
(__erfcieee128): Declare.
* intrinsics/trigd.c (_gfortran_sind_r17, _gfortran_cosd_r17,
_gfortran_tand_r17): Define for HAVE_GFC_REAL_17.
* intrinsics/random.c (random_r17, arandom_r17, rnumber_17): Define.
* intrinsics/erfc_scaled.c (ERFC_SCALED): Define.
(erfc_scaled_r16): Use ERFC_SCALED macro.
(erfc_scaled_r17): Define.
Diffstat (limited to 'libgfortran/intrinsics/random.c')
-rw-r--r-- | libgfortran/intrinsics/random.c | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/libgfortran/intrinsics/random.c b/libgfortran/intrinsics/random.c index ab4d7d8..b5732e6 100644 --- a/libgfortran/intrinsics/random.c +++ b/libgfortran/intrinsics/random.c @@ -79,6 +79,16 @@ export_proto(arandom_r16); #endif +#ifdef HAVE_GFC_REAL_17 + +extern void random_r17 (GFC_REAL_17 *); +iexport_proto(random_r17); + +extern void arandom_r17 (gfc_array_r17 *); +export_proto(arandom_r17); + +#endif + #ifdef __GTHREAD_MUTEX_INIT static __gthread_mutex_t random_lock = __GTHREAD_MUTEX_INIT; #else @@ -161,6 +171,27 @@ rnumber_16 (GFC_REAL_16 *f, GFC_UINTEGER_8 v1, GFC_UINTEGER_8 v2) } #endif +#ifdef HAVE_GFC_REAL_17 + +/* For REAL(KIND=16), we only need to mask off the lower bits. */ + +static void +rnumber_17 (GFC_REAL_17 *f, GFC_UINTEGER_8 v1, GFC_UINTEGER_8 v2) +{ + GFC_UINTEGER_8 mask; +#if GFC_REAL_17_RADIX == 2 + mask = ~ (GFC_UINTEGER_8) 0u << (128 - GFC_REAL_17_DIGITS); +#elif GFC_REAL_17_RADIX == 16 + mask = ~ (GFC_UINTEGER_8) 0u << ((32 - GFC_REAL_17_DIGITS) * 4); +#else +#error "GFC_REAL_17_RADIX has unknown value" +#endif + v2 = v2 & mask; + *f = (GFC_REAL_17) v1 * GFC_REAL_17_LITERAL(0x1.p-64) + + (GFC_REAL_17) v2 * GFC_REAL_17_LITERAL(0x1.p-128); +} +#endif + /* @@ -445,6 +476,28 @@ iexport(random_r16); #endif +/* This function produces a REAL(16) value from the uniform distribution + with range [0,1). */ + +#ifdef HAVE_GFC_REAL_17 + +void +random_r17 (GFC_REAL_17 *x) +{ + GFC_UINTEGER_8 r1, r2; + prng_state* rs = get_rand_state(); + + if (unlikely (!rs->init)) + init_rand_state (rs, false); + r1 = prng_next (rs); + r2 = prng_next (rs); + rnumber_17 (x, r1, r2); +} +iexport(random_r17); + + +#endif + /* This function fills a REAL(4) array with values from the uniform distribution with range [0,1). */ @@ -719,6 +772,77 @@ arandom_r16 (gfc_array_r16 *x) #endif +#ifdef HAVE_GFC_REAL_17 + +/* This function fills a REAL(16) array with values from the uniform + distribution with range [0,1). */ + +void +arandom_r17 (gfc_array_r17 *x) +{ + index_type count[GFC_MAX_DIMENSIONS]; + index_type extent[GFC_MAX_DIMENSIONS]; + index_type stride[GFC_MAX_DIMENSIONS]; + index_type stride0; + index_type dim; + GFC_REAL_17 *dest; + prng_state* rs = get_rand_state(); + + dest = x->base_addr; + + dim = GFC_DESCRIPTOR_RANK (x); + + for (index_type n = 0; n < dim; n++) + { + count[n] = 0; + stride[n] = GFC_DESCRIPTOR_STRIDE(x,n); + extent[n] = GFC_DESCRIPTOR_EXTENT(x,n); + if (extent[n] <= 0) + return; + } + + stride0 = stride[0]; + + if (unlikely (!rs->init)) + init_rand_state (rs, false); + + while (dest) + { + /* random_r17 (dest); */ + uint64_t r1 = prng_next (rs); + uint64_t r2 = prng_next (rs); + rnumber_17 (dest, r1, r2); + + /* Advance to the next element. */ + dest += stride0; + count[0]++; + /* Advance to the next source element. */ + index_type n = 0; + while (count[n] == extent[n]) + { + /* When we get to the end of a dimension, reset it and increment + the next dimension. */ + count[n] = 0; + /* We could precalculate these products, but this is a less + frequently used path so probably not worth it. */ + dest -= stride[n] * extent[n]; + n++; + if (n == dim) + { + dest = NULL; + break; + } + else + { + count[n]++; + dest += stride[n]; + } + } + } +} + +#endif + /* Number of elements in master_state array. */ #define SZU64 (sizeof (master_state.s) / sizeof (uint64_t)) |