Skip to content

Commit 05658e0

Browse files
ENH: impl random.power (#520)
* ENH: impl random.power * disabled incorrect test checks for dpnp.random.power
1 parent 0e80c50 commit 05658e0

File tree

8 files changed

+114
-6
lines changed

8 files changed

+114
-6
lines changed

dpnp/backend/include/dpnp_iface.hpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,20 @@ INP_DLLEXPORT void dpnp_rng_pareto_c(void* result, double alpha, size_t size);
883883
template <typename _DataType>
884884
INP_DLLEXPORT void dpnp_rng_poisson_c(void* result, double lambda, size_t size);
885885

886+
/**
887+
* @ingroup BACKEND_API
888+
* @brief math library implementation of random number generator (power distribution)
889+
*
890+
* @param [in] size Number of elements in `result` arrays.
891+
*
892+
* @param [in] alpha Shape of the distribution, alpha.
893+
*
894+
* @param [out] result Output array.
895+
*
896+
*/
897+
template <typename _DataType>
898+
INP_DLLEXPORT void dpnp_rng_power_c(void* result, double alpha, size_t size);
899+
886900
/**
887901
* @ingroup BACKEND_API
888902
* @brief math library implementation of random number generator (rayleigh distribution)

dpnp/backend/include/dpnp_iface_fptr.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ enum class DPNPFuncName : size_t
139139
DPNP_FN_RNG_NORMAL, /**< Used in numpy.random.normal() implementation */
140140
DPNP_FN_RNG_PARETO, /**< Used in numpy.random.pareto() implementation */
141141
DPNP_FN_RNG_POISSON, /**< Used in numpy.random.poisson() implementation */
142+
DPNP_FN_RNG_POWER, /**< Used in numpy.random.power() implementation */
142143
DPNP_FN_RNG_RAYLEIGH, /**< Used in numpy.random.rayleigh() implementation */
143144
DPNP_FN_RNG_STANDARD_CAUCHY, /**< Used in numpy.random.standard_cauchy() implementation */
144145
DPNP_FN_RNG_STANDARD_EXPONENTIAL, /**< Used in numpy.random.standard_exponential() implementation */

dpnp/backend/kernels/dpnp_krnl_random.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,30 @@ void dpnp_rng_poisson_c(void* result, double lambda, size_t size)
477477
event_out.wait();
478478
}
479479

480+
template <typename _DataType>
481+
void dpnp_rng_power_c(void* result, double alpha, size_t size)
482+
{
483+
if (!size)
484+
{
485+
return;
486+
}
487+
cl::sycl::vector_class<cl::sycl::event> no_deps;
488+
489+
const _DataType d_zero = _DataType(0.0);
490+
const _DataType d_one = _DataType(1.0);
491+
_DataType neg_rec_alp = 1.0/alpha;
492+
493+
_DataType* result1 = reinterpret_cast<_DataType*>(result);
494+
495+
mkl_rng::uniform<_DataType> distribution(d_zero, d_one);
496+
auto event_out = mkl_rng::generate(distribution, DPNP_RNG_ENGINE, size, result1);
497+
event_out.wait();
498+
499+
event_out = mkl_vm::powx(DPNP_QUEUE, size, result1, neg_rec_alp,
500+
result1, no_deps, mkl_vm::mode::ha);
501+
event_out.wait();
502+
}
503+
480504
template <typename _DataType>
481505
void dpnp_rng_rayleigh_c(void* result, _DataType scale, size_t size)
482506
{
@@ -713,6 +737,8 @@ void func_map_init_random(func_map_t& fmap)
713737

714738
fmap[DPNPFuncName::DPNP_FN_RNG_POISSON][eft_INT][eft_INT] = {eft_INT, (void*)dpnp_rng_poisson_c<int>};
715739

740+
fmap[DPNPFuncName::DPNP_FN_RNG_POWER][eft_DBL][eft_DBL] = {eft_DBL, (void*)dpnp_rng_power_c<double>};
741+
716742
fmap[DPNPFuncName::DPNP_FN_RNG_RAYLEIGH][eft_DBL][eft_DBL] = {eft_DBL, (void*)dpnp_rng_rayleigh_c<double>};
717743

718744
fmap[DPNPFuncName::DPNP_FN_RNG_STANDARD_CAUCHY][eft_DBL][eft_DBL] = {eft_DBL,

dpnp/dpnp_algo/dpnp_algo.pxd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ cdef extern from "dpnp_iface_fptr.hpp" namespace "DPNPFuncName": # need this na
112112
DPNP_FN_RNG_NORMAL
113113
DPNP_FN_RNG_PARETO
114114
DPNP_FN_RNG_POISSON
115+
DPNP_FN_RNG_POWER
115116
DPNP_FN_RNG_RAYLEIGH
116117
DPNP_FN_RNG_STANDARD_CAUCHY
117118
DPNP_FN_RNG_STANDARD_EXPONENTIAL

dpnp/random/dpnp_algo_random.pyx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ __all__ = [
5959
"dpnp_normal",
6060
"dpnp_pareto",
6161
"dpnp_poisson",
62+
"dpnp_rng_power",
6263
"dpnp_randn",
6364
"dpnp_random",
6465
"dpnp_rayleigh",
@@ -96,6 +97,7 @@ ctypedef void(*fptr_dpnp_rng_negative_binomial_c_1out_t)(void *, double, double,
9697
ctypedef void(*fptr_dpnp_rng_normal_c_1out_t)(void *, double, double, size_t) except +
9798
ctypedef void(*fptr_dpnp_rng_pareto_c_1out_t)(void *, double, size_t) except +
9899
ctypedef void(*fptr_dpnp_rng_poisson_c_1out_t)(void *, double, size_t) except +
100+
ctypedef void(*fptr_dpnp_rng_power_c_1out_t)(void *, double, size_t) except +
99101
ctypedef void(*fptr_dpnp_rng_rayleigh_c_1out_t)(void *, double, size_t) except +
100102
ctypedef void(*fptr_dpnp_rng_standard_cauchy_c_1out_t)(void *, size_t) except +
101103
ctypedef void(*fptr_dpnp_rng_standard_exponential_c_1out_t)(void *, size_t) except +
@@ -661,6 +663,31 @@ cpdef dparray dpnp_poisson(double lam, size):
661663
return result
662664

663665

666+
cpdef dparray dpnp_rng_power(double alpha, size):
667+
"""
668+
Returns an array populated with samples from power distribution.
669+
`dpnp_power` generates a matrix filled with random floats sampled from a
670+
univariate power distribution of `alpha`.
671+
"""
672+
673+
dtype = numpy.float64
674+
# convert string type names (dparray.dtype) to C enum DPNPFuncType
675+
cdef DPNPFuncType param1_type = dpnp_dtype_to_DPNPFuncType(dtype)
676+
677+
# get the FPTR data structure
678+
cdef DPNPFuncData kernel_data = get_dpnp_function_ptr(DPNP_FN_RNG_POWER, param1_type, param1_type)
679+
680+
result_type = dpnp_DPNPFuncType_to_dtype( < size_t > kernel_data.return_type)
681+
# ceate result array with type given by FPTR data
682+
cdef dparray result = dparray(size, dtype=dtype)
683+
684+
cdef fptr_dpnp_rng_power_c_1out_t func = <fptr_dpnp_rng_power_c_1out_t > kernel_data.ptr
685+
# call FPTR function
686+
func(result.get_data(), alpha, result.size)
687+
688+
return result
689+
690+
664691
cpdef dparray dpnp_randn(dims):
665692
"""
666693
Returns an array populated with samples from standard normal distribution.

dpnp/random/dpnp_iface_random.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -889,18 +889,35 @@ def poisson(lam=1.0, size=None):
889889
def power(a, size=None):
890890
"""Power distribution.
891891
892-
Draws samples in [0, 1] from a power distribution with positive exponent
893-
a - 1.
892+
Draws samples in [0, 1] from a power distribution with positive
893+
exponent a - 1.
894894
895895
For full documentation refer to :obj:`numpy.random.power`.
896896
897-
Notes
898-
-----
899-
The function uses `numpy.random.power` on the backend and
900-
will be executed on fallback backend.
897+
Limitations
898+
-----------
899+
Parameter ``a`` is supported as a scalar.
900+
Otherwise, :obj:`numpy.random.power(a, size)` samples are drawn.
901+
Output array data type is :obj:`dpnp.float64`.
902+
903+
Examples
904+
--------
905+
Draw samples from the distribution:
906+
>>> a = .5 # alpha
907+
>>> s = dpnp.random.power(a, 1000)
901908
902909
"""
903910

911+
if not use_origin_backend(a):
912+
# TODO:
913+
# array_like of floats for `a`
914+
if not dpnp.isscalar(a):
915+
pass
916+
elif a <= 0:
917+
pass
918+
else:
919+
return dpnp_rng_power(a, size)
920+
904921
return call_origin(numpy.random.power, a, size)
905922

906923

tests/test_random.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,26 @@ def test_seed(self):
598598
self.check_seed('poisson', {'lam': lam})
599599

600600

601+
class TestDistributionsPower(TestDistribution):
602+
603+
def test_moments(self):
604+
a = 30.0
605+
neg_a = -a
606+
expected_mean = neg_a / (neg_a - 1)
607+
expected_var = neg_a / (((neg_a - 1)**2) * (neg_a - 2))
608+
self.check_moments('power', expected_mean,
609+
expected_var, {'a': a})
610+
611+
def test_invalid_args(self):
612+
size = 10
613+
a = -1.0 # positive `a` is expected
614+
self.check_invalid_args('power', {'a': a})
615+
616+
def test_seed(self):
617+
a = 3.0 # a param for pareto distr
618+
self.check_seed('power', {'a': a})
619+
620+
601621
class TestDistributionsRayleigh(TestDistribution):
602622

603623
def test_extreme_value(self):

tests_external/skipped_tests_numpy.tbl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,6 +1493,7 @@ tests/test_random.py::TestRandomDist::test_random_integers_deprecated
14931493
tests/test_random.py::TestRandomDist::test_random_integers_max_int
14941494
tests/test_random.py::TestRandomDist::test_rayleigh
14951495
tests/test_random.py::TestRandomDist::test_rayleigh_0
1496+
tests/test_random.py::TestRandomDist::test_power
14961497
tests/test_random.py::TestRandomDist::test_scalar_exception_propagation
14971498
tests/test_random.py::TestRandomDist::test_shuffle
14981499
tests/test_random.py::TestRandomDist::test_shuffle_masked
@@ -1588,6 +1589,7 @@ tests/test_randomstate.py::TestRandomDist::test_random_sample
15881589
tests/test_randomstate.py::TestRandomDist::test_rand_singleton
15891590
tests/test_randomstate.py::TestRandomDist::test_rayleigh
15901591
tests/test_randomstate.py::TestRandomDist::test_rayleigh_0
1592+
tests/test_randomstate.py::TestRandomDist::test_power
15911593
tests/test_randomstate.py::TestRandomDist::test_scalar_exception_propagation
15921594
tests/test_randomstate.py::TestRandomDist::test_shuffle
15931595
tests/test_randomstate.py::TestRandomDist::test_shuffle_masked

0 commit comments

Comments
 (0)