mirror of
https://github.com/gcc-mirror/gcc.git
synced 2024-11-21 13:40:47 +00:00
Add random numbers and fix some bugs.
This patch adds random number support for UNSIGNED, plus fixes two bugs, with array I/O where the type used to be set to BT_INTEGER, and for division with the divisor being a constant. gcc/fortran/ChangeLog: * check.cc (gfc_check_random_number): Adjust for unsigned. * iresolve.cc (gfc_resolve_random_number): Handle unsigned. * trans-expr.cc (gfc_conv_expr_op): Handle BT_UNSIGNED for divide. * trans-types.cc (gfc_get_dtype_rank_type): Handle BT_UNSIGNED. * gfortran.texi: Add RANDOM_NUMBER for UNSIGNED. libgfortran/ChangeLog: * gfortran.map: Add _gfortran_random_m1, _gfortran_random_m2, _gfortran_random_m4, _gfortran_random_m8 and _gfortran_random_m16. * intrinsics/random.c (random_m1): New function. (random_m2): New function. (random_m4): New function. (random_m8): New function. (random_m16): New function. (arandom_m1): New function. (arandom_m2): New function. (arandom_m4): New function. (arandom_m8): New funciton. (arandom_m16): New function. gcc/testsuite/ChangeLog: * gfortran.dg/unsigned_30.f90: New test.
This commit is contained in:
parent
fbeb1a965d
commit
291e20e860
@ -7007,8 +7007,14 @@ gfc_check_random_init (gfc_expr *repeatable, gfc_expr *image_distinct)
|
|||||||
bool
|
bool
|
||||||
gfc_check_random_number (gfc_expr *harvest)
|
gfc_check_random_number (gfc_expr *harvest)
|
||||||
{
|
{
|
||||||
if (!type_check (harvest, 0, BT_REAL))
|
if (flag_unsigned)
|
||||||
return false;
|
{
|
||||||
|
if (!type_check2 (harvest, 0, BT_REAL, BT_UNSIGNED))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (!type_check (harvest, 0, BT_REAL))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!variable_check (harvest, 0, false))
|
if (!variable_check (harvest, 0, false))
|
||||||
return false;
|
return false;
|
||||||
|
@ -2790,6 +2790,7 @@ As of now, the following intrinsics take unsigned arguments:
|
|||||||
@item @code{TRANSFER}
|
@item @code{TRANSFER}
|
||||||
@item @code{SUM}, @code{PRODUCT}, @code{MATMUL} and @code{DOT_PRODUCT}
|
@item @code{SUM}, @code{PRODUCT}, @code{MATMUL} and @code{DOT_PRODUCT}
|
||||||
@item @code{IANY}, @code{IALL} and @code{IPARITY}
|
@item @code{IANY}, @code{IALL} and @code{IPARITY}
|
||||||
|
@item @code{RANDOM_NUMBER}.
|
||||||
@end itemize
|
@end itemize
|
||||||
This list will grow in the near future.
|
This list will grow in the near future.
|
||||||
@c ---------------------------------------------------------------------
|
@c ---------------------------------------------------------------------
|
||||||
|
@ -3452,12 +3452,14 @@ gfc_resolve_random_number (gfc_code *c)
|
|||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
int kind;
|
int kind;
|
||||||
|
char type;
|
||||||
|
|
||||||
kind = gfc_type_abi_kind (&c->ext.actual->expr->ts);
|
kind = gfc_type_abi_kind (&c->ext.actual->expr->ts);
|
||||||
|
type = gfc_type_letter (c->ext.actual->expr->ts.type);
|
||||||
if (c->ext.actual->expr->rank == 0)
|
if (c->ext.actual->expr->rank == 0)
|
||||||
name = gfc_get_string (PREFIX ("random_r%d"), kind);
|
name = gfc_get_string (PREFIX ("random_%c%d"), type, kind);
|
||||||
else
|
else
|
||||||
name = gfc_get_string (PREFIX ("arandom_r%d"), kind);
|
name = gfc_get_string (PREFIX ("arandom_%c%d"), type, kind);
|
||||||
|
|
||||||
c->resolved_sym = gfc_get_intrinsic_sub_symbol (name);
|
c->resolved_sym = gfc_get_intrinsic_sub_symbol (name);
|
||||||
}
|
}
|
||||||
|
@ -3973,9 +3973,9 @@ gfc_conv_expr_op (gfc_se * se, gfc_expr * expr)
|
|||||||
|
|
||||||
case INTRINSIC_DIVIDE:
|
case INTRINSIC_DIVIDE:
|
||||||
/* If expr is a real or complex expr, use an RDIV_EXPR. If op1 is
|
/* If expr is a real or complex expr, use an RDIV_EXPR. If op1 is
|
||||||
an integer, we must round towards zero, so we use a
|
an integer or unsigned, we must round towards zero, so we use a
|
||||||
TRUNC_DIV_EXPR. */
|
TRUNC_DIV_EXPR. */
|
||||||
if (expr->ts.type == BT_INTEGER)
|
if (expr->ts.type == BT_INTEGER || expr->ts.type == BT_UNSIGNED)
|
||||||
code = TRUNC_DIV_EXPR;
|
code = TRUNC_DIV_EXPR;
|
||||||
else
|
else
|
||||||
code = RDIV_EXPR;
|
code = RDIV_EXPR;
|
||||||
|
@ -1651,7 +1651,12 @@ gfc_get_dtype_rank_type (int rank, tree etype)
|
|||||||
&& TYPE_STRING_FLAG (ptype))
|
&& TYPE_STRING_FLAG (ptype))
|
||||||
n = BT_CHARACTER;
|
n = BT_CHARACTER;
|
||||||
else
|
else
|
||||||
n = BT_INTEGER;
|
{
|
||||||
|
if (TYPE_UNSIGNED (etype))
|
||||||
|
n = BT_UNSIGNED;
|
||||||
|
else
|
||||||
|
n = BT_INTEGER;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BOOLEAN_TYPE:
|
case BOOLEAN_TYPE:
|
||||||
|
63
gcc/testsuite/gfortran.dg/unsigned_30.f90
Normal file
63
gcc/testsuite/gfortran.dg/unsigned_30.f90
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
! { dg-do run }
|
||||||
|
! { dg-options "-funsigned" }
|
||||||
|
|
||||||
|
! The leading bytes of the unsigned sequences should be the same for
|
||||||
|
! kinds 1 to 8. This also tests array I/O for unsigneds.
|
||||||
|
|
||||||
|
program memain
|
||||||
|
implicit none
|
||||||
|
integer, dimension(:), allocatable :: seed
|
||||||
|
integer :: n
|
||||||
|
call random_seed (size=n)
|
||||||
|
allocate(seed(n))
|
||||||
|
call test1
|
||||||
|
call test2
|
||||||
|
contains
|
||||||
|
subroutine test1
|
||||||
|
unsigned(1) :: u1
|
||||||
|
unsigned(2) :: u2
|
||||||
|
unsigned(4) :: u4
|
||||||
|
unsigned(8) :: u8
|
||||||
|
character (len=16) :: line1, line2, line4, line8
|
||||||
|
integer :: i, n
|
||||||
|
do i=1,10
|
||||||
|
call random_seed(get=seed)
|
||||||
|
call random_number(u1)
|
||||||
|
write (line1,'(Z2.2)') u1
|
||||||
|
call random_seed(put=seed)
|
||||||
|
call random_number(u2)
|
||||||
|
write (line2,'(Z4.4)') u2
|
||||||
|
call random_seed(put=seed)
|
||||||
|
call random_number(u4)
|
||||||
|
write (line4,'(Z8.8)') u4
|
||||||
|
call random_seed(put=seed)
|
||||||
|
call random_number(u8)
|
||||||
|
write (line8,'(Z16.16)') u8
|
||||||
|
if (line8(1:8) /= line4 (1:8)) error stop 1
|
||||||
|
if (line4(1:4) /= line2 (1:4)) error stop 2
|
||||||
|
if (line2(1:2) /= line1 (1:2)) error stop 3
|
||||||
|
end do
|
||||||
|
end subroutine test1
|
||||||
|
subroutine test2
|
||||||
|
unsigned(1), dimension(2,2) :: v1
|
||||||
|
unsigned(2), dimension(2,2) :: v2
|
||||||
|
unsigned(4), dimension(2,2) :: v4
|
||||||
|
unsigned(8), dimension(2,2) :: v8
|
||||||
|
character(len=16), dimension(4) :: c1, c2, c4, c8
|
||||||
|
call random_seed(put=seed)
|
||||||
|
call random_number (v1)
|
||||||
|
write (c1,'(Z2.2)') v1
|
||||||
|
call random_seed(put=seed)
|
||||||
|
call random_number (v2)
|
||||||
|
write (c2,'(Z4.4)') v2
|
||||||
|
call random_seed(put=seed)
|
||||||
|
call random_number (v4)
|
||||||
|
write (c4,'(Z8.8)') v4
|
||||||
|
call random_seed(put=seed)
|
||||||
|
call random_number (v8)
|
||||||
|
write (c8,'(Z16.16)') v8
|
||||||
|
if (any(c8(:)(1:8) /= c4(:)(1:8))) error stop 10
|
||||||
|
if (any(c4(:)(1:4) /= c2(:)(1:4))) error stop 11
|
||||||
|
if (any(c2(:)(1:2) /= c1(:)(1:2))) error stop 12
|
||||||
|
end subroutine test2
|
||||||
|
end program memain
|
@ -1777,4 +1777,14 @@ GFORTRAN_15 {
|
|||||||
_gfortran_internal_unpack_class;
|
_gfortran_internal_unpack_class;
|
||||||
_gfortran_transfer_unsigned;
|
_gfortran_transfer_unsigned;
|
||||||
_gfortran_transfer_unsigned_write;
|
_gfortran_transfer_unsigned_write;
|
||||||
|
_gfortran_random_m1;
|
||||||
|
_gfortran_random_m2;
|
||||||
|
_gfortran_random_m4;
|
||||||
|
_gfortran_random_m8;
|
||||||
|
_gfortran_random_m16;
|
||||||
|
_gfortran_arandom_m1;
|
||||||
|
_gfortran_arandom_m2;
|
||||||
|
_gfortran_arandom_m4;
|
||||||
|
_gfortran_arandom_m8;
|
||||||
|
_gfortran_arandom_m16;
|
||||||
} GFORTRAN_14;
|
} GFORTRAN_14;
|
||||||
|
@ -89,6 +89,43 @@ export_proto(arandom_r17);
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern void random_m1 (GFC_UINTEGER_1 *);
|
||||||
|
export_proto (random_m1);
|
||||||
|
|
||||||
|
extern void random_m2 (GFC_UINTEGER_2 *);
|
||||||
|
export_proto (random_m2);
|
||||||
|
|
||||||
|
extern void random_m4 (GFC_UINTEGER_4 *);
|
||||||
|
export_proto (random_m4);
|
||||||
|
|
||||||
|
extern void random_m8 (GFC_UINTEGER_8 *);
|
||||||
|
export_proto (random_m8);
|
||||||
|
|
||||||
|
#ifdef HAVE_GFC_UINTEGER_16
|
||||||
|
extern void random_m16 (GFC_UINTEGER_16 *);
|
||||||
|
export_proto (random_m16);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern void arandom_m1 (gfc_array_m1 *);
|
||||||
|
export_proto (arandom_m1);
|
||||||
|
|
||||||
|
extern void arandom_m2 (gfc_array_m2 *);
|
||||||
|
export_proto (arandom_m2);
|
||||||
|
|
||||||
|
extern void arandom_m4 (gfc_array_m4 *);
|
||||||
|
export_proto (arandom_m4);
|
||||||
|
|
||||||
|
extern void arandom_m8 (gfc_array_m8 *);
|
||||||
|
export_proto (arandom_m8);
|
||||||
|
|
||||||
|
#ifdef HAVE_GFC_UINTEGER_16
|
||||||
|
|
||||||
|
extern void arandom_m16 (gfc_array_m16 *);
|
||||||
|
export_proto (arandom_m16);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __GTHREAD_MUTEX_INIT
|
#ifdef __GTHREAD_MUTEX_INIT
|
||||||
static __gthread_mutex_t random_lock = __GTHREAD_MUTEX_INIT;
|
static __gthread_mutex_t random_lock = __GTHREAD_MUTEX_INIT;
|
||||||
#else
|
#else
|
||||||
@ -498,6 +535,81 @@ iexport(random_r17);
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Versions for unsigned numbers. */
|
||||||
|
|
||||||
|
/* Returns a random byte. */
|
||||||
|
|
||||||
|
void
|
||||||
|
random_m1 (GFC_UINTEGER_1 *x)
|
||||||
|
{
|
||||||
|
prng_state* rs = get_rand_state();
|
||||||
|
|
||||||
|
if (unlikely (!rs->init))
|
||||||
|
init_rand_state (rs, false);
|
||||||
|
GFC_UINTEGER_8 r = prng_next (rs);
|
||||||
|
|
||||||
|
*x = r >> 56;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A random 16-bit number. */
|
||||||
|
|
||||||
|
void
|
||||||
|
random_m2 (GFC_UINTEGER_2 *x)
|
||||||
|
{
|
||||||
|
prng_state* rs = get_rand_state();
|
||||||
|
|
||||||
|
if (unlikely (!rs->init))
|
||||||
|
init_rand_state (rs, false);
|
||||||
|
GFC_UINTEGER_8 r = prng_next (rs);
|
||||||
|
|
||||||
|
*x = r >> 48;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A random 32-bit number. */
|
||||||
|
|
||||||
|
void
|
||||||
|
random_m4 (GFC_UINTEGER_4 *x)
|
||||||
|
{
|
||||||
|
prng_state* rs = get_rand_state();
|
||||||
|
|
||||||
|
if (unlikely (!rs->init))
|
||||||
|
init_rand_state (rs, false);
|
||||||
|
GFC_UINTEGER_8 r = prng_next (rs);
|
||||||
|
|
||||||
|
*x = r >> 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A random 64-bit number. */
|
||||||
|
|
||||||
|
void
|
||||||
|
random_m8 (GFC_UINTEGER_8 *x)
|
||||||
|
{
|
||||||
|
prng_state* rs = get_rand_state();
|
||||||
|
|
||||||
|
if (unlikely (!rs->init))
|
||||||
|
init_rand_state (rs, false);
|
||||||
|
GFC_UINTEGER_8 r = prng_next (rs);
|
||||||
|
|
||||||
|
*x = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ... and a random 128-bit number, if we have the type. */
|
||||||
|
|
||||||
|
#ifdef HAVE_GFC_UINTEGER_16
|
||||||
|
void
|
||||||
|
random_m16 (GFC_UINTEGER_16 *x)
|
||||||
|
{
|
||||||
|
prng_state* rs = get_rand_state();
|
||||||
|
|
||||||
|
if (unlikely (!rs->init))
|
||||||
|
init_rand_state (rs, false);
|
||||||
|
GFC_UINTEGER_8 r1 = prng_next (rs);
|
||||||
|
GFC_UINTEGER_8 r2 = prng_next (rs);
|
||||||
|
|
||||||
|
*x = (((GFC_UINTEGER_16) r1) << 64) | (GFC_UINTEGER_16) r2;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* This function fills a REAL(4) array with values from the uniform
|
/* This function fills a REAL(4) array with values from the uniform
|
||||||
distribution with range [0,1). */
|
distribution with range [0,1). */
|
||||||
|
|
||||||
@ -843,6 +955,334 @@ arandom_r17 (gfc_array_r17 *x)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Fill an unsigned array with random bytes. */
|
||||||
|
|
||||||
|
void
|
||||||
|
arandom_m1 (gfc_array_m1 *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_UINTEGER_1 *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_m1 (dest); */
|
||||||
|
uint64_t r = prng_next (rs);
|
||||||
|
*dest = r >> 56;
|
||||||
|
|
||||||
|
/* 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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fill an unsigned array with random 16-bit unsigneds. */
|
||||||
|
|
||||||
|
void
|
||||||
|
arandom_m2 (gfc_array_m2 *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_UINTEGER_2 *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_m1 (dest); */
|
||||||
|
uint64_t r = prng_next (rs);
|
||||||
|
*dest = r >> 48;
|
||||||
|
|
||||||
|
/* 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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fill an array with random 32-bit unsigneds. */
|
||||||
|
|
||||||
|
void
|
||||||
|
arandom_m4 (gfc_array_m4 *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_UINTEGER_4 *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_m4 (dest); */
|
||||||
|
uint64_t r = prng_next (rs);
|
||||||
|
*dest = r >> 32;
|
||||||
|
|
||||||
|
/* 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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fill an array with random 64-bit unsigneds. */
|
||||||
|
|
||||||
|
void
|
||||||
|
arandom_m8 (gfc_array_m8 *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_UINTEGER_8 *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_m8 (dest); */
|
||||||
|
uint64_t r = prng_next (rs);
|
||||||
|
*dest = r;
|
||||||
|
|
||||||
|
/* 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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef GFC_HAVE_GFC_UINTEGER_16
|
||||||
|
|
||||||
|
/* Fill an unsigned array with random bytes. */
|
||||||
|
|
||||||
|
void
|
||||||
|
arandom_m16 (gfc_array_m16 *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_UINTEGER_16 *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_m16 (dest); */
|
||||||
|
uint64_t r1 = prng_next (rs), r2 = prng_next (rs);
|
||||||
|
*dest = (((GFC_UINTEGER_16) r1) << 64) | (GFC_UINTEGER_16) 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. */
|
/* Number of elements in master_state array. */
|
||||||
#define SZU64 (sizeof (master_state.s) / sizeof (uint64_t))
|
#define SZU64 (sizeof (master_state.s) / sizeof (uint64_t))
|
||||||
|
Loading…
Reference in New Issue
Block a user