Skip to content

MAINT: Remove Cython conditionals #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 26 additions & 41 deletions numpy/random/pcg64.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,8 @@ np.import_array()

# IF PCG_EMULATED_MATH==1:
cdef extern from "src/pcg64/pcg64.h":

ctypedef struct pcg128_t:
uint64_t high
uint64_t low
# ELSE:
# cdef extern from "inttypes.h":
# ctypedef unsigned long long __uint128_t
#
# cdef extern from "src/pcg64/pcg64.h":
# ctypedef __uint128_t pcg128_t

cdef extern from "src/pcg64/pcg64.h":

cdef struct pcg_state_setseq_128:
pcg128_t state
pcg128_t inc

ctypedef pcg_state_setseq_128 pcg64_random_t
# Use int as generic type, actual type read from pcg64.h and is platform dependent
ctypedef int pcg64_random_t

struct s_pcg64_state:
pcg64_random_t *pcg_state
Expand All @@ -48,6 +32,8 @@ cdef extern from "src/pcg64/pcg64.h":
void pcg64_jump(pcg64_state *state)
void pcg64_advance(pcg64_state *state, uint64_t *step)
void pcg64_set_seed(pcg64_state *state, uint64_t *seed, uint64_t *inc)
void pcg64_get_state(pcg64_state *state, uint64_t *state_arr, int *has_uint32, uint32_t *uinteger)
void pcg64_set_state(pcg64_state *state, uint64_t *state_arr, int has_uint32, uint32_t uinteger)

cdef uint64_t pcg64_uint64(void* st) nogil:
return pcg64_next64(<pcg64_state *>st)
Expand Down Expand Up @@ -280,40 +266,39 @@ cdef class PCG64:
Dictionary containing the information required to describe the
state of the RNG
"""
# IF PCG_EMULATED_MATH==1:
# TODO: push this into an #ifdef in the C code
state = 2 **64 * self.rng_state.pcg_state.state.high
state += self.rng_state.pcg_state.state.low
inc = 2 **64 * self.rng_state.pcg_state.inc.high
inc += self.rng_state.pcg_state.inc.low
# ELSE:
# state = self.rng_state.pcg_state.state
# inc = self.rng_state.pcg_state.inc

cdef np.ndarray state_vec
cdef int has_uint32
cdef uint32_t uinteger

# state_vec is state.high, state.low, inc.high, inc.low
state_vec = <np.ndarray>np.empty(4, dtype=np.uint64)
pcg64_get_state(self.rng_state, <uint64_t *>state_vec.data, &has_uint32, &uinteger)
state = int(state_vec[0]) * 2**64 + int(state_vec[1])
inc = int(state_vec[2]) * 2**64 + int(state_vec[3])
return {'brng': self.__class__.__name__,
'state': {'state': state, 'inc': inc},
'has_uint32': self.rng_state.has_uint32,
'uinteger': self.rng_state.uinteger}
'has_uint32': has_uint32,
'uinteger': uinteger}

@state.setter
def state(self, value):
cdef np.ndarray state_vec
cdef int has_uint32
cdef uint32_t uinteger
if not isinstance(value, dict):
raise TypeError('state must be a dict')
brng = value.get('brng', '')
if brng != self.__class__.__name__:
raise ValueError('state must be for a {0} '
'RNG'.format(self.__class__.__name__))
# IF PCG_EMULATED_MATH==1:
self.rng_state.pcg_state.state.high = value['state']['state'] // 2 ** 64
self.rng_state.pcg_state.state.low = value['state']['state'] % 2 ** 64
self.rng_state.pcg_state.inc.high = value['state']['inc'] // 2 ** 64
self.rng_state.pcg_state.inc.low = value['state']['inc'] % 2 ** 64
# ELSE:
# self.rng_state.pcg_state.state = value['state']['state']
# self.rng_state.pcg_state.inc = value['state']['inc']

self.rng_state.has_uint32 = value['has_uint32']
self.rng_state.uinteger = value['uinteger']
state_vec = <np.ndarray>np.empty(4, dtype=np.uint64)
state_vec[0] = value['state']['state'] // 2 ** 64
state_vec[1] = value['state']['state'] % 2 ** 64
state_vec[2] = value['state']['inc'] // 2 ** 64
state_vec[3] = value['state']['inc'] % 2 ** 64
has_uint32 = value['has_uint32']
uinteger = value['uinteger']
pcg64_set_state(self.rng_state, <uint64_t *>state_vec.data, has_uint32, uinteger)

def advance(self, delta):
"""
Expand Down
44 changes: 44 additions & 0 deletions numpy/random/src/pcg64/pcg64.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,47 @@ extern void pcg64_set_seed(pcg64_state *state, uint64_t *seed, uint64_t *inc) {
#endif
pcg64_srandom_r(state->pcg_state, s, i);
}

extern void pcg64_get_state(pcg64_state *state, uint64_t *state_arr,
int *has_uint32, uint32_t *uinteger) {
/*
* state_arr contains state.high, state.low, inc.high, inc.low
* which are interpreted as the upper 64 bits (high) or lower
* 64 bits of a uint128_t variable
*
*/
#if __SIZEOF_INT128__ && !defined(PCG_FORCE_EMULATED_128BIT_MATH)
state_arr[0] = (uint64_t)(state->pcg_state->state >> 64);
state_arr[1] = (uint64_t)(state->pcg_state->state & 0xFFFFFFFFFFFFFFFFULL);
state_arr[2] = (uint64_t)(state->pcg_state->inc >> 64);
state_arr[3] = (uint64_t)(state->pcg_state->inc & 0xFFFFFFFFFFFFFFFFULL);
#else
state_arr[0] = (uint64_t)state->pcg_state->state.high;
state_arr[1] = (uint64_t)state->pcg_state->state.low;
state_arr[2] = (uint64_t)state->pcg_state->inc.high;
state_arr[3] = (uint64_t)state->pcg_state->inc.low;
#endif
has_uint32[0] = state->has_uint32;
uinteger[0] = state->uinteger;
}

extern void pcg64_set_state(pcg64_state *state, uint64_t *state_arr,
int has_uint32, uint32_t uinteger) {
/*
* state_arr contains state.high, state.low, inc.high, inc.low
* which are interpreted as the upper 64 bits (high) or lower
* 64 bits of a uint128_t variable
*
*/
#if __SIZEOF_INT128__ && !defined(PCG_FORCE_EMULATED_128BIT_MATH)
state->pcg_state->state = (((pcg128_t)state_arr[0]) << 64) | state_arr[1];
state->pcg_state->inc = (((pcg128_t)state_arr[2]) << 64) | state_arr[3];
#else
state->pcg_state->state.high = state_arr[0];
state->pcg_state->state.low = state_arr[1];
state->pcg_state->inc.high = state_arr[2];
state->pcg_state->inc.low = state_arr[3];
#endif
state->has_uint32 = has_uint32;
state->uinteger = uinteger;
}
9 changes: 7 additions & 2 deletions numpy/random/src/pcg64/pcg64.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ static inline void _pcg_mult64(uint64_t x, uint64_t y, uint64_t *z1,
uint64_t *z0) {

#if defined _WIN32 && _MSC_VER >= 1900 && _M_AMD64
z0[0] = _umul128(x, y, z1);
z0[0] = _umul128(x, y, z1);
#else
uint64_t x0, x1, y0, y1;
uint64_t w0, w1, w2, t;
Expand All @@ -118,7 +118,6 @@ static inline void _pcg_mult64(uint64_t x, uint64_t y, uint64_t *z1,
w1 += x0 * y1;
*z1 = x1 * y1 + w2 + (w1 >> 32);
#endif

}

static inline pcg128_t _pcg128_mult(pcg128_t a, pcg128_t b) {
Expand Down Expand Up @@ -238,4 +237,10 @@ void pcg64_advance(pcg64_state *state, uint64_t *step);

void pcg64_set_seed(pcg64_state *state, uint64_t *seed, uint64_t *inc);

void pcg64_get_state(pcg64_state *state, uint64_t *state_arr, int *has_uint32,
uint32_t *uinteger);

void pcg64_set_state(pcg64_state *state, uint64_t *state_arr, int has_uint32,
uint32_t uinteger);

#endif /* PCG64_H_INCLUDED */