Skip to content

Commit e743113

Browse files
revise random number generator; move LAGraph_Random.c to src/utility
1 parent e3e4c4e commit e743113

File tree

8 files changed

+140
-48
lines changed

8 files changed

+140
-48
lines changed

config/LAGraph.h.in

+52
Original file line numberDiff line numberDiff line change
@@ -2021,6 +2021,58 @@ int LAGraph_Vector_IsEqualOp
20212021
char *msg
20222022
) ;
20232023

2024+
//------------------------------------------------------------------------------
2025+
// Random number generator
2026+
//------------------------------------------------------------------------------
2027+
2028+
// FIXME: rename these methods? Rename the vector "Seed" to "State".
2029+
2030+
/** LAGraph_Random_Seed creates a random vector. On input, its values are
2031+
* ignored but its structure is used. On output, all entries that were in
2032+
* the original structure are assigned random values, depending on the scalar
2033+
* seed value. Each entry is considered its own pseudo-random number stream,
2034+
* with the overall seed value being revised for each entry in the vector,
2035+
* depending on their index in the vector.
2036+
*
2037+
* @param[out,out] Seed vector to initialize with random numbers.
2038+
* @param[in] seed scalar seed value.
2039+
* @param[in,out] msg any error messages.
2040+
*
2041+
* @retval GrB_SUCCESS if successful.
2042+
* @retval GrB_NULL_POINTER if Seed is NULL.
2043+
* @returns any GraphBLAS errors that may have been encountered.
2044+
*/
2045+
2046+
LAGRAPH_PUBLIC
2047+
int LAGraph_Random_Seed // construct a random seed vector
2048+
(
2049+
// input/output:
2050+
GrB_Vector Seed, // vector of random number seeds, normally GrB_UINT64
2051+
// input:
2052+
uint64_t seed, // scalar input seed
2053+
char *msg
2054+
) ;
2055+
2056+
/** LAGraph_Random_Next takes as input a vector previously initialized by
2057+
* LAGraph_Random_Seed, and modifies all of them so that they take on their
2058+
* next value in its pseudo-random number stream.
2059+
*
2060+
* @param[out,out] Seed vector with random numbers to be advanced.
2061+
* @param[in,out] msg any error messages.
2062+
*
2063+
* @retval GrB_SUCCESS if successful.
2064+
* @retval GrB_NULL_POINTER if Seed is NULL.
2065+
* @returns any GraphBLAS errors that may have been encountered.
2066+
*/
2067+
2068+
LAGRAPH_PUBLIC
2069+
int LAGraph_Random_Next // advance to next random vector
2070+
(
2071+
// input/output:
2072+
GrB_Vector Seed,
2073+
char *msg
2074+
) ;
2075+
20242076
//==============================================================================
20252077
// LAGraph Basic algorithms
20262078
//==============================================================================

include/LAGraph.h

+50
Original file line numberDiff line numberDiff line change
@@ -2021,6 +2021,56 @@ int LAGraph_Vector_IsEqualOp
20212021
char *msg
20222022
) ;
20232023

2024+
//------------------------------------------------------------------------------
2025+
// Random number generator
2026+
//------------------------------------------------------------------------------
2027+
2028+
// FIXME: rename these methods?
2029+
2030+
/** LAGraph_Random_Seed creates a random vector. On input, its values are
2031+
* ignored but its structure is used. On output, all entries that were in
2032+
* the original structure are assigned random values, depending on the scalar
2033+
* seed value. Each entry is considered its own pseudo-random number stream.
2034+
*
2035+
* @param[out,out] Seed vector to initialize with random numbers.
2036+
* @param[in] seed scalar seed value.
2037+
* @param[in,out] msg any error messages.
2038+
*
2039+
* @retval GrB_SUCCESS if successful.
2040+
* @retval GrB_NULL_POINTER if Seed is NULL.
2041+
* @returns any GraphBLAS errors that may have been encountered.
2042+
*/
2043+
2044+
LAGRAPH_PUBLIC
2045+
int LAGraph_Random_Seed // construct a random seed vector
2046+
(
2047+
// input/output
2048+
GrB_Vector Seed, // vector of random number seeds, normally GrB_UINT64
2049+
// input
2050+
uint64_t seed, // scalar input seed
2051+
char *msg
2052+
) ;
2053+
2054+
/** LAGraph_Random_Next takes as input a vector previously initialized by
2055+
* LAGraph_Random_Seed, and modifies all of them so that they take on their
2056+
* next value in its pseudo-random number stream.
2057+
*
2058+
* @param[out,out] Seed vector with random numbers to be advanced.
2059+
* @param[in,out] msg any error messages.
2060+
*
2061+
* @retval GrB_SUCCESS if successful.
2062+
* @retval GrB_NULL_POINTER if Seed is NULL.
2063+
* @returns any GraphBLAS errors that may have been encountered.
2064+
*/
2065+
2066+
LAGRAPH_PUBLIC
2067+
int LAGraph_Random_Next // advance to next random vector
2068+
(
2069+
// input/output
2070+
GrB_Vector Seed,
2071+
char *msg
2072+
) ;
2073+
20242074
//==============================================================================
20252075
// LAGraph Basic algorithms
20262076
//==============================================================================

include/LAGraphX.h

+2-20
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,12 @@ extern "C"
5757
//------------------------------------------------------------------------------
5858

5959
LAGRAPHX_PUBLIC
60-
int LAGraph_Random_Init
60+
int LAGraph_Random_Init // FIXME: remove this
6161
(
6262
char *msg
6363
) ;
6464
LAGRAPHX_PUBLIC
65-
int LAGraph_Random_Finalize
65+
int LAGraph_Random_Finalize // FIXME: remove this
6666
(
6767
char *msg
6868
) ;
@@ -72,24 +72,6 @@ int LAGraph_Random_Finalize
7272
LAGRAPHX_PUBLIC extern bool random_hack ;
7373
#endif
7474

75-
LAGRAPHX_PUBLIC
76-
int LAGraph_Random_Seed // construct a random seed vector
77-
(
78-
// input/output
79-
GrB_Vector Seed, // vector of random number seeds, normally GrB_UINT64
80-
// input
81-
uint64_t seed, // scalar input seed
82-
char *msg
83-
) ;
84-
85-
LAGRAPHX_PUBLIC
86-
int LAGraph_Random_Next // advance to next random vector
87-
(
88-
// input/output
89-
GrB_Vector Seed,
90-
char *msg
91-
) ;
92-
9375
LAGRAPHX_PUBLIC
9476
GrB_Info LAGraph_Random_Matrix // random matrix of any built-in type
9577
(
File renamed without changes.

src/utility/LAGr_Init.c

+2
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,8 @@ int LAGr_Init
218218
// create global objects
219219
//--------------------------------------------------------------------------
220220

221+
LG_Random_Init (msg) ;
222+
221223
// LAGraph_plus_first_T: using the GrB_PLUS_MONOID_T monoid and the
222224
// GrB_FIRST_T multiplicative operator. These semirings compute C=A*B
223225
// where only the structure of B is accessed. In MATLAB, this can be

src/utility/LAGraph_Finalize.c

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ int LAGraph_Finalize (char *msg)
3030
// free global objects
3131
//--------------------------------------------------------------------------
3232

33+
LG_TRY (LG_Random_Finalize (msg)) ;
34+
3335
GRB_TRY (GrB_Semiring_free (&LAGraph_plus_first_int8 )) ;
3436
GRB_TRY (GrB_Semiring_free (&LAGraph_plus_first_int16 )) ;
3537
GRB_TRY (GrB_Semiring_free (&LAGraph_plus_first_int32 )) ;
@@ -82,3 +84,4 @@ int LAGraph_Finalize (char *msg)
8284
GRB_TRY (GrB_finalize ( )) ;
8385
return (GrB_SUCCESS) ;
8486
}
87+

experimental/utility/LAGraph_Random.c renamed to src/utility/LAGraph_Random.c

+21-28
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,7 @@
1717

1818
// A very simple thread-safe parallel pseudo-random nuumber generator.
1919

20-
// FIXME: ready for src?
21-
22-
// FIXME: add LAGraph_Random_Init to LAGraph_Init,
23-
// and added LAGraph_Random_Finalize to LAGraph_Finalize.
24-
25-
// FIXME: is the new init function more complicated than it needs to be?
20+
// FIXME: ready for src
2621

2722
#include "LG_internal.h"
2823
#include "LAGraphX.h"
@@ -91,9 +86,8 @@ void LG_rand_next_f2 (uint64_t *z, const uint64_t *x)
9186

9287
// From these references, the recommendation is to create the initial state of
9388
// a random number generator with an entirely different random number
94-
// generator. splitmix64 is recommended, but here we initialize the State(i)
95-
// with xorshift (i+1) to get a good start, add the scalar seed, and then
96-
// randomize the State with splitmix64.
89+
// generator. splitmix64 is recommended, so we initialize the State(i) with
90+
// (i+seed) then randomize the State with splitmix64.
9791

9892
// References:
9993
//
@@ -121,17 +115,12 @@ void LG_rand_next_f2 (uint64_t *z, const uint64_t *x)
121115

122116
#endif
123117

124-
// The init function computes z = splitmix64 (xorshift (i+1) + seed)
118+
// The init function computes z = splitmix64 (i + seed)
125119
void LG_rand_init_func (uint64_t *z, const void *x,
126120
GrB_Index i, GrB_Index j, const uint64_t *seed)
127121
{
128-
// state = xorshift64 (i+1) + seed
129-
uint64_t state = i + 1 ;
130-
state ^= state << 13 ;
131-
state ^= state >> 7 ;
132-
state ^= state << 17 ;
133-
state += (*seed) ;
134-
// result = shiftmix64 (state)
122+
uint64_t state = i + (*seed) ;
123+
// result = splitmix64 (state)
135124
uint64_t result = (state += 0x9E3779B97f4A7C15) ;
136125
result = (result ^ (result >> 30)) * 0xBF58476D1CE4E5B9 ;
137126
result = (result ^ (result >> 27)) * 0x94D049BB133111EB ;
@@ -146,11 +135,7 @@ void LG_rand_init_func (uint64_t *z, const void *x,
146135
"void LG_rand_init_func (uint64_t *z, const void *x, \n" \
147136
" GrB_Index i, GrB_Index j, const uint64_t *seed) \n" \
148137
"{ \n" \
149-
" uint64_t state = i + 1 ; \n" \
150-
" state ^= state << 13 ; \n" \
151-
" state ^= state >> 7 ; \n" \
152-
" state ^= state << 17 ; \n" \
153-
" state += (*seed) ; \n" \
138+
" uint64_t state = i + (*seed) ; \n" \
154139
" uint64_t result = (state += 0x9E3779B97f4A7C15) ; \n" \
155140
" result = (result ^ (result >> 30)) * 0xBF58476D1CE4E5B9 ; \n" \
156141
" result = (result ^ (result >> 27)) * 0x94D049BB133111EB ; \n" \
@@ -170,16 +155,21 @@ void LG_rand_init_func (uint64_t *z, const void *x,
170155
GrB_IndexUnaryOp_free (&LG_rand_init_op) ; \
171156
}
172157

173-
int LAGraph_Random_Init (char *msg)
158+
int LAGraph_Random_Init (char *msg) // FIXME: remove this method
159+
{
160+
return (LG_Random_Init (msg)) ;
161+
}
162+
163+
int LG_Random_Init (char *msg)
174164
{
175165
LG_CLEAR_MSG ;
166+
LG_FREE_WORK ; // free the two ops in case LG_Random_Init is called twice
176167
LG_rand_next_op = NULL ;
177168
LG_rand_init_op = NULL ;
178169

179170
#if LAGRAPH_SUITESPARSE
180171
{
181172
// give SuiteSparse:GraphBLAS the strings that define the functions
182-
// using the xorshift generator from LAGraph v1.2
183173
GRB_TRY (GxB_UnaryOp_new (&LG_rand_next_op,
184174
(GxB_unary_function) LG_rand_next_f2,
185175
GrB_UINT64, GrB_UINT64,
@@ -192,7 +182,6 @@ int LAGraph_Random_Init (char *msg)
192182
#else
193183
{
194184
// vanilla GraphBLAS, no strings to define the new operators
195-
// using the xorshift generator from LAGraph v1.2
196185
GRB_TRY (GrB_UnaryOp_new (&LG_rand_next_op,
197186
(GxB_unary_function) LG_rand_next_f2,
198187
GrB_UINT64, GrB_UINT64)) ;
@@ -209,13 +198,18 @@ int LAGraph_Random_Init (char *msg)
209198
// LAGraph_Random_Finalize: free the random state operator
210199
//------------------------------------------------------------------------------
211200

212-
int LAGraph_Random_Finalize (char *msg)
201+
int LG_Random_Finalize (char *msg)
213202
{
214203
LG_CLEAR_MSG ;
215204
LG_FREE_WORK ;
216205
return (GrB_SUCCESS) ;
217206
}
218207

208+
int LAGraph_Random_Finalize (char *msg) // FIXME: remove this method
209+
{
210+
return (LG_Random_Finalize (msg)) ;
211+
}
212+
219213
//------------------------------------------------------------------------------
220214
// LAGraph_Random_Seed: create a vector of random states
221215
//------------------------------------------------------------------------------
@@ -249,8 +243,7 @@ int LAGraph_Random_Seed // construct a random state vector
249243
LG_CLEAR_MSG ;
250244
LG_ASSERT (State != NULL, GrB_NULL_POINTER) ;
251245

252-
// LAGraph v1.2:
253-
// State = splitmix64 (xorshift64 (i+1) + seed)
246+
// State = splitmix64 (i + seed)
254247
GRB_TRY (GrB_apply (State, NULL, NULL, LG_rand_init_op, State, seed,
255248
NULL)) ;
256249

src/utility/LG_internal.h

+10
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,9 @@ int LG_nself_edges
588588
// simple and portable random number generator (internal use only)
589589
//------------------------------------------------------------------------------
590590

591+
// This is for testing and special-case use only, not for LAGraph
592+
// algorithms.
593+
591594
#define LG_RANDOM15_MAX 32767
592595
#define LG_RANDOM60_MAX ((1ULL << 60) -1)
593596

@@ -597,6 +600,13 @@ GrB_Index LG_Random15 (uint64_t *seed) ;
597600
// return a random uint64_t, in range 0 to LG_RANDOM60_MAX
598601
GrB_Index LG_Random60 (uint64_t *seed) ;
599602

603+
//------------------------------------------------------------------------------
604+
// a better random number generator, for algorithmic usage
605+
//------------------------------------------------------------------------------
606+
607+
int LG_Random_Init (char *msg) ;
608+
int LG_Random_Finalize (char *msg) ;
609+
600610
//------------------------------------------------------------------------------
601611
// LG_KindName: return the name of a kind
602612
//------------------------------------------------------------------------------

0 commit comments

Comments
 (0)