aboutsummaryrefslogtreecommitdiff
path: root/libgfortran/intrinsics/random.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2022-01-04 21:32:05 +0100
committerJakub Jelinek <jakub@redhat.com>2022-01-11 23:49:50 +0100
commit5db042b2b8484e28d1bf8726fa9ef69b8495ddac (patch)
tree3e0f48801e5a46fe4c04a04daabaea89edda220e /libgfortran/intrinsics/random.c
parent06a74228ce589dc24b37341d22a6933cdccdb6bd (diff)
downloadgcc-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.c124
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))