This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Implementation of RANDOM_INIT from F2018


I have attached my current implementation for RANDOM_INIT.

For programs compiled without -fcoarry= or with -fcoarray=single,
the one gets, 

% cat random_init_2.f90
program foo
   real x(2)
   call random_init(.false., .false.)
   call random_number(x)
   print *, x
   call random_init(.false., .false.)
   call random_number(x)
   print *, x

   call random_init(.true., .false.)
   call random_number(x)
   print *, x
   call random_init(.true., .false.)
   call random_number(x)
   print *, x
end program foo
% gfcx -o z random_init_2.f90 && ./z
  0.817726076      0.318128884    
  0.598739505       2.99510360E-02
  0.336736381      0.870776474    
  0.336736381      0.870776474  

Now, with -fcoarray=lib, one gets 

%  gfcx -fcoarray=lib -c random_init_2.f90
f951: Fatal Error: RANDOM_INIT with co-arrays is broken!
compilation terminated.

I have zero knowledge about co-arrays and especially zero
knowledge about gfortran internals for co-arrays.  I'm
disinclined to waste another 12 hours trying to get gfortran
to emit essentially a call to this_image().  See iresolve.c
for details.

2018-01-07  Steven G. Kargl  <kargl@gcc.gnu.org>

	* check.c (gfc_check_random_init): New function.
	* gfortran.h: Define GFC_ISYM_RANDOM_INIT.
	* intrinsic.c (add_subroutines): Add random_init to list of subroutines.
	(gfc_check_intrinsic_standard): Update error message for Fortran 2018.
	* intrinsic.h: Add prototypes for gfc_check_random_init and
	gfc_resolve_random_init.
	* iresolve.c (gfc_resolve_random_init): Implementation.

2018-01-07  Steven G. Kargl  <kargl@gcc.gnu.org>

	* libgfortran/gfortran.map: Add _gfortran_random_init.
	* libgfortran/intrinsics/random.c: Add implemention of
	_gfortran_random_init

-- 
Steve
Index: gcc/fortran/check.c
===================================================================
--- gcc/fortran/check.c	(revision 256045)
+++ gcc/fortran/check.c	(working copy)
@@ -5671,6 +5671,19 @@ gfc_check_mvbits (gfc_expr *from, gfc_expr *frompos, g
 
 
 bool
+gfc_check_random_init (gfc_expr *repeatable, gfc_expr *image_distinct)
+{
+  if (!type_check (repeatable, 0, BT_LOGICAL))
+    return false;
+
+  if (!type_check (image_distinct, 1, BT_LOGICAL))
+    return false;
+
+  return true;
+}
+
+
+bool
 gfc_check_random_number (gfc_expr *harvest)
 {
   if (!type_check (harvest, 0, BT_REAL))
Index: gcc/fortran/expr.c
===================================================================
--- gcc/fortran/expr.c	(revision 256045)
+++ gcc/fortran/expr.c	(working copy)
@@ -3853,7 +3853,7 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_expr *
 
   /* Error for assignments of contiguous pointers to targets which is not
      contiguous.  Be lenient in the definition of what counts as
-     congiguous.  */
+     contiguous.  */
 
   if (lhs_attr.contiguous && !gfc_is_simply_contiguous (rvalue, false, true))
     gfc_error ("Assignment to contiguous pointer from non-contiguous "
Index: gcc/fortran/gfortran.h
===================================================================
--- gcc/fortran/gfortran.h	(revision 256045)
+++ gcc/fortran/gfortran.h	(working copy)
@@ -551,6 +551,7 @@ enum gfc_isym_id
   GFC_ISYM_PRODUCT,
   GFC_ISYM_RADIX,
   GFC_ISYM_RAND,
+  GFC_ISYM_RANDOM_INIT,
   GFC_ISYM_RANDOM_NUMBER,
   GFC_ISYM_RANDOM_SEED,
   GFC_ISYM_RANGE,
Index: gcc/fortran/intrinsic.c
===================================================================
--- gcc/fortran/intrinsic.c	(revision 256045)
+++ gcc/fortran/intrinsic.c	(working copy)
@@ -3549,6 +3549,12 @@ add_subroutines (void)
       make_alias ("kmvbits", GFC_STD_GNU);
     }
 
+  add_sym_2s ("random_init", GFC_ISYM_RANDOM_INIT, CLASS_IMPURE,
+	      BT_UNKNOWN, 0, GFC_STD_F2018,
+	      gfc_check_random_init, NULL, gfc_resolve_random_init,
+	      "repeatable",     BT_LOGICAL, dl, REQUIRED, INTENT_IN,
+	      "image_distinct", BT_LOGICAL, dl, REQUIRED, INTENT_IN);
+
   add_sym_1s ("random_number", GFC_ISYM_RANDOM_NUMBER, CLASS_IMPURE,
 	      BT_UNKNOWN, 0, GFC_STD_F95,
 	      gfc_check_random_number, NULL, gfc_resolve_random_number,
@@ -4601,6 +4607,10 @@ gfc_check_intrinsic_standard (const gfc_intrinsic_sym*
 
     case GFC_STD_F2008_TS:
       symstd_msg = "new in TS 29113/TS 18508";
+      break;
+
+    case GFC_STD_F2018:
+      symstd_msg = "new in Fortran 2018";
       break;
 
     case GFC_STD_GNU:
Index: gcc/fortran/intrinsic.h
===================================================================
--- gcc/fortran/intrinsic.h	(revision 256045)
+++ gcc/fortran/intrinsic.h	(working copy)
@@ -203,6 +203,7 @@ bool gfc_check_getlog (gfc_expr *);
 bool gfc_check_move_alloc (gfc_expr *, gfc_expr *);
 bool gfc_check_mvbits (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *,
 		      gfc_expr *);
+bool gfc_check_random_init (gfc_expr *, gfc_expr *);
 bool gfc_check_random_number (gfc_expr *);
 bool gfc_check_random_seed (gfc_expr *, gfc_expr *, gfc_expr *);
 bool gfc_check_dtime_etime_sub (gfc_expr *, gfc_expr *);
@@ -643,6 +644,7 @@ void gfc_resolve_lstat_sub (gfc_code *);
 void gfc_resolve_ltime (gfc_code *);
 void gfc_resolve_mvbits (gfc_code *);
 void gfc_resolve_perror (gfc_code *);
+void gfc_resolve_random_init (gfc_code *);
 void gfc_resolve_random_number (gfc_code *);
 void gfc_resolve_random_seed (gfc_code *);
 void gfc_resolve_rename_sub (gfc_code *);
Index: gcc/fortran/iresolve.c
===================================================================
--- gcc/fortran/iresolve.c	(revision 256045)
+++ gcc/fortran/iresolve.c	(working copy)
@@ -35,7 +35,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "intrinsic.h"
 #include "constructor.h"
 #include "arith.h"
+#include "tm.h"		/* For flag_coarray.  */
 
+
 /* Given printf-like arguments, return a stable version of the result string. 
 
    We already have a working, optimized string hashing table in the form of
@@ -3118,6 +3120,8 @@ gfc_resolve_trim (gfc_expr *f, gfc_expr *string)
 {
   f->ts.type = BT_CHARACTER;
   f->ts.kind = string->ts.kind;
+  f->ts.u.cl = NULL;
+  f->ts.u.pad = 0;
   f->value.function.name = gfc_get_string ("__trim_%d", string->ts.kind);
 }
 
@@ -3368,6 +3372,61 @@ gfc_resolve_mvbits (gfc_code *c)
   /* Create a dummy formal arglist so the INTENTs are known later for purpose
      of creating temporaries.  */
   c->resolved_sym->formal = create_formal_for_intents (c->ext.actual, INTENTS);
+}
+
+
+/* Set up the call to RANDOM_INIT.  To deal with image_distinct, we need to
+   send a hidden argument into the library function.  For program that don't
+   use co-arrays or uses -fcoarray=single, the hidden argument is set to 0.
+   For -fcoarray=lib, the hidden argument should be set to the value 
+   returned by this_image().  Using R for REPEATABLE and I for
+   IMAGE_DISTINCT. So, RANDOM_INIT(R, I) is mapped to the library routine
+   _gfortran_random_init(R, I, 0) for a single image, and it should be
+   mapped to _gfortran_random_init(R, I, this_image()).  */ 
+
+void
+gfc_resolve_random_init (gfc_code *c)
+{
+  gfc_actual_arglist *a;
+  const char *name;
+
+  name = gfc_get_string (PREFIX ("random_init"));
+  c->resolved_sym = gfc_get_intrinsic_sub_symbol (name);
+
+  /* Pass a hidden integer to deal with seeding images for coarrays.  */
+  a = gfc_get_actual_arglist ();
+  if (flag_coarray != GFC_FCOARRAY_LIB)
+    {
+      a->expr = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind,
+					&c->ext.actual->next->expr->where);
+      mpz_set_si (a->expr->value.integer, 0);
+    }
+  else
+    {
+      gfc_fatal_error ("RANDOM_INIT with co-arrays is broken!");
+#if 0
+/* Well, this didn't work. :(  */
+      static const char name[] = "this_image";
+      a->expr = gfc_get_expr ();
+      a->expr->expr_type = EXPR_FUNCTION;
+      a->expr->ts.type = BT_INTEGER;
+      a->expr->ts.kind = gfc_default_integer_kind;
+      a->expr->where = gfc_current_locus;
+      a->expr->value.function.isym = gfc_find_function (name);
+      a->expr->value.function.name = a->expr->value.function.isym->name;
+
+      a->expr->value.function.actual = gfc_get_actual_arglist ();
+      a->expr->value.function.actual->next = gfc_get_actual_arglist ();
+      a->expr->value.function.actual->next->next = gfc_get_actual_arglist ();
+      a->expr->value.function.isym->formal->actual = gfc_get_actual_arglist ();
+      a->expr->value.function.isym->formal->actual->next = gfc_get_actual_arglist ();
+      a->expr->value.function.isym->formal->actual->next->next = gfc_get_actual_arglist ();
+
+      gfc_simplify_expr (a->expr, 0);
+      c->resolved_isym->formal->actual->next->next = a;
+#endif
+    }
+    c->ext.actual->next->next = a;
 }
 
 
Index: libgfortran/gfortran.map
===================================================================
--- libgfortran/gfortran.map	(revision 256045)
+++ libgfortran/gfortran.map	(working copy)
@@ -801,6 +801,7 @@ GFORTRAN_8 {
     _gfortran_product_r4;
     _gfortran_product_r8;
     _gfortran_rand;
+    _gfortran_random_init;
     _gfortran_random_r10;
     _gfortran_random_r16;
     _gfortran_random_r4;
Index: libgfortran/intrinsics/random.c
===================================================================
--- libgfortran/intrinsics/random.c	(revision 256045)
+++ libgfortran/intrinsics/random.c	(working copy)
@@ -44,6 +44,9 @@ see the files COPYING3 and COPYING.RUNTIME respectivel
 #include <_mingw.h> /* For __MINGW64_VERSION_MAJOR  */
 #endif
 
+extern void random_init (GFC_LOGICAL_4 *, GFC_LOGICAL_4 *, GFC_INTEGER_4 *);
+iexport_proto(random_init);
+
 extern void random_r4 (GFC_REAL_4 *);
 iexport_proto(random_r4);
 
@@ -205,7 +208,6 @@ static uint64_t master_state[] = {
   0x625288bc262faf33ULL
 };
 
-
 static __gthread_key_t rand_state_key;
 
 static xorshift1024star_state*
@@ -927,6 +929,46 @@ random_seed_i8 (GFC_INTEGER_8 *size, gfc_array_i8 *put
 }
 iexport(random_seed_i8);
 
+
+/* random_init is used to seed the PRNG with either a default
+   set of seeds or a random set of seeds.  */
+
+void
+random_init (GFC_LOGICAL_4 *repeatable, GFC_LOGICAL_4 *image_distinct,
+	     GFC_INTEGER_4 *hidden)
+{
+  static const uint64_t repeat_state[] = {
+    0x25b946ebc0b36173ULL, 0x31fffb768dfde2d1ULL, 0xb08dbf28a70a6b08ULL,
+    0x60b1fc7fbcc04151ULL, 0xb4018862d654635dULL, 0x5c2fc35553bb5470ULL,
+    0xd588f951b8984a2bULL, 0x060c05384e97789dULL, 0x2b992ddfa23249d6ULL,
+    0x4034650f1c98bd69ULL, 0x79267e9c00e018afULL, 0x449eb881a2869d0eULL,
+    0xe2fee08d1e670313ULL, 0x17afc3eef0f0c640ULL, 0x2002db4f8acb8a0eULL,
+    0x50cd06b1b61a6804ULL
+  };
+
+  xorshift1024star_state* rs = get_rand_state();
+
+  __gthread_mutex_lock (&random_lock);
+
+  if (*repeatable)
+    {
+      /* Copy the repeat seeds.   */
+      memcpy (&rs->s, repeat_state, sizeof (repeat_state));
+      njumps = 0;
+      if (*image_distinct) njumps = *hidden;
+      master_init = true;
+      init_rand_state (rs, true);
+	  rs->p = 0;
+    }
+  else
+    {
+      master_init = false;
+      init_rand_state (rs, true);
+    }
+
+  __gthread_mutex_unlock (&random_lock);
+}
+iexport(random_init);
 
 #if !defined __GTHREAD_MUTEX_INIT || defined __GTHREADS
 static void __attribute__((constructor))

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]