Skip to content

Commit aa09b31

Browse files
ENH: update multinomial and lognormal (#680)
1 parent d246a3d commit aa09b31

File tree

2 files changed

+63
-54
lines changed

2 files changed

+63
-54
lines changed

dpnp/backend/kernels/dpnp_krnl_random.cpp

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -475,54 +475,72 @@ void dpnp_rng_logistic_c(void* result, const double loc, const double scale, con
475475
template <typename _DataType>
476476
void dpnp_rng_lognormal_c(void* result, const _DataType mean, const _DataType stddev, const size_t size)
477477
{
478-
if (!size)
478+
if (!size || !result)
479479
{
480480
return;
481481
}
482482
_DataType* result1 = reinterpret_cast<_DataType*>(result);
483483

484-
const _DataType displacement = _DataType(0.0);
485-
486-
const _DataType scalefactor = _DataType(1.0);
484+
if (stddev == 0.0)
485+
{
486+
_DataType* fill_value = reinterpret_cast<_DataType*>(dpnp_memory_alloc_c(sizeof(_DataType)));
487+
fill_value[0] = static_cast<_DataType>(std::exp(mean + (stddev * stddev) / 2));
488+
dpnp_initval_c<_DataType>(result, fill_value, size);
489+
dpnp_memory_free_c(fill_value);
490+
}
491+
else
492+
{
493+
const _DataType displacement = _DataType(0.0);
494+
const _DataType scalefactor = _DataType(1.0);
487495

488-
mkl_rng::lognormal<_DataType> distribution(mean, stddev, displacement, scalefactor);
489-
// perform generation
490-
auto event_out = mkl_rng::generate(distribution, DPNP_RNG_ENGINE, size, result1);
491-
event_out.wait();
496+
mkl_rng::lognormal<_DataType> distribution(mean, stddev, displacement, scalefactor);
497+
auto event_out = mkl_rng::generate(distribution, DPNP_RNG_ENGINE, size, result1);
498+
event_out.wait();
499+
}
500+
return;
492501
}
493502

494503
template <typename _DataType>
495504
void dpnp_rng_multinomial_c(
496505
void* result, const int ntrial, const double* p_vector, const size_t p_vector_size, const size_t size)
497506
{
498-
if (!size)
507+
if (!size || !result)
499508
{
500509
return;
501510
}
502-
std::int32_t* result1 = reinterpret_cast<std::int32_t*>(result);
503-
std::vector<double> p(p_vector, p_vector + p_vector_size);
504-
// size = size
505-
// `result` is a array for random numbers
506-
// `size` is a `result`'s len. `size = n * p.size()`
507-
// `n` is a number of random values to be generated.
508-
size_t n = size / p.size();
509511

510-
if (dpnp_queue_is_cpu_c())
512+
if (ntrial == 0)
511513
{
512-
mkl_rng::multinomial<std::int32_t> distribution(ntrial, p);
513-
// perform generation
514-
auto event_out = mkl_rng::generate(distribution, DPNP_RNG_ENGINE, n, result1);
515-
event_out.wait();
514+
dpnp_zeros_c<_DataType>(result, size);
516515
}
517516
else
518517
{
519-
int errcode = viRngMultinomial(
520-
VSL_RNG_METHOD_MULTINOMIAL_MULTPOISSON, get_rng_stream(), n, result1, ntrial, p_vector_size, p_vector);
521-
if (errcode != VSL_STATUS_OK)
518+
std::int32_t* result1 = reinterpret_cast<std::int32_t*>(result);
519+
std::vector<double> p(p_vector, p_vector + p_vector_size);
520+
// size = size
521+
// `result` is a array for random numbers
522+
// `size` is a `result`'s len. `size = n * p.size()`
523+
// `n` is a number of random values to be generated.
524+
size_t n = size / p.size();
525+
526+
if (dpnp_queue_is_cpu_c())
522527
{
523-
throw std::runtime_error("DPNP RNG Error: dpnp_rng_multinomial_c() failed.");
528+
mkl_rng::multinomial<std::int32_t> distribution(ntrial, p);
529+
// perform generation
530+
auto event_out = mkl_rng::generate(distribution, DPNP_RNG_ENGINE, n, result1);
531+
event_out.wait();
532+
}
533+
else
534+
{
535+
int errcode = viRngMultinomial(
536+
VSL_RNG_METHOD_MULTINOMIAL_MULTPOISSON, get_rng_stream(), n, result1, ntrial, p_vector_size, p_vector);
537+
if (errcode != VSL_STATUS_OK)
538+
{
539+
throw std::runtime_error("DPNP RNG Error: dpnp_rng_multinomial_c() failed.");
540+
}
524541
}
525542
}
543+
return;
526544
}
527545

528546
template <typename _DataType>

dpnp/random/dpnp_algo_random.pyx

Lines changed: 20 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -456,24 +456,19 @@ cpdef dparray dpnp_rng_lognormal(double mean, double stddev, size):
456456
cdef DPNPFuncData kernel_data
457457
cdef fptr_dpnp_rng_lognormal_c_1out_t func
458458

459-
if stddev == 0.0:
460-
val = numpy.exp(mean + (stddev ** 2) / 2)
461-
result = dparray(size, dtype=dtype)
462-
result.fill(val)
463-
else:
464-
# convert string type names (dparray.dtype) to C enum DPNPFuncType
465-
param1_type = dpnp_dtype_to_DPNPFuncType(dtype)
459+
# convert string type names (dparray.dtype) to C enum DPNPFuncType
460+
param1_type = dpnp_dtype_to_DPNPFuncType(dtype)
466461

467-
# get the FPTR data structure
468-
kernel_data = get_dpnp_function_ptr(DPNP_FN_RNG_LOGNORMAL, param1_type, param1_type)
462+
# get the FPTR data structure
463+
kernel_data = get_dpnp_function_ptr(DPNP_FN_RNG_LOGNORMAL, param1_type, param1_type)
469464

470-
result_type = dpnp_DPNPFuncType_to_dtype(< size_t > kernel_data.return_type)
471-
# ceate result array with type given by FPTR data
472-
result = dparray(size, dtype=result_type)
465+
result_type = dpnp_DPNPFuncType_to_dtype(< size_t > kernel_data.return_type)
466+
# ceate result array with type given by FPTR data
467+
result = dparray(size, dtype=result_type)
473468

474-
func = <fptr_dpnp_rng_lognormal_c_1out_t > kernel_data.ptr
475-
# call FPTR function
476-
func(result.get_data(), mean, stddev, result.size)
469+
func = <fptr_dpnp_rng_lognormal_c_1out_t > kernel_data.ptr
470+
# call FPTR function
471+
func(result.get_data(), mean, stddev, result.size)
477472

478473
return result
479474

@@ -498,23 +493,19 @@ cpdef dparray dpnp_rng_multinomial(int ntrial, p, size):
498493
cdef double * p_vector = <double * > numpy.PyArray_DATA(p)
499494
cdef size_t p_vector_size = len(p)
500495

501-
if ntrial == 0:
502-
result = dparray(size, dtype=dtype)
503-
result.fill(0.0)
504-
else:
505-
# convert string type names (dparray.dtype) to C enum DPNPFuncType
506-
param1_type = dpnp_dtype_to_DPNPFuncType(dtype)
496+
# convert string type names (dparray.dtype) to C enum DPNPFuncType
497+
param1_type = dpnp_dtype_to_DPNPFuncType(dtype)
507498

508-
# get the FPTR data structure
509-
kernel_data = get_dpnp_function_ptr(DPNP_FN_RNG_MULTINOMIAL, param1_type, param1_type)
499+
# get the FPTR data structure
500+
kernel_data = get_dpnp_function_ptr(DPNP_FN_RNG_MULTINOMIAL, param1_type, param1_type)
510501

511-
result_type = dpnp_DPNPFuncType_to_dtype(< size_t > kernel_data.return_type)
512-
# ceate result array with type given by FPTR data
513-
result = dparray(size, dtype=result_type)
502+
result_type = dpnp_DPNPFuncType_to_dtype(< size_t > kernel_data.return_type)
503+
# ceate result array with type given by FPTR data
504+
result = dparray(size, dtype=result_type)
514505

515-
func = <fptr_dpnp_rng_multinomial_c_1out_t > kernel_data.ptr
516-
# call FPTR function
517-
func(result.get_data(), ntrial, p_vector, p_vector_size, result.size)
506+
func = <fptr_dpnp_rng_multinomial_c_1out_t > kernel_data.ptr
507+
# call FPTR function
508+
func(result.get_data(), ntrial, p_vector, p_vector_size, result.size)
518509

519510
return result
520511

0 commit comments

Comments
 (0)