@@ -164,6 +164,19 @@ cdef double kahan_sum(double *darr, np.npy_intp n):
164
164
sum = t
165
165
return sum
166
166
167
+ cdef inline void compute_complex (double * rv_r , double * rv_i , double loc_r ,
168
+ double loc_i , double var_r , double var_i , double rho ) nogil :
169
+ cdef double scale_c , scale_i , scale_r
170
+
171
+ scale_c = sqrt (1 - rho * rho )
172
+ scale_r = sqrt (var_r )
173
+ scale_i = sqrt (var_i )
174
+
175
+ rv_i [0 ] = loc_i + scale_i * (rho * rv_r [0 ] + scale_c * rv_i [0 ])
176
+ rv_r [0 ] = loc_r + scale_r * rv_r [0 ]
177
+
178
+
179
+
167
180
cdef object _ensure_string (object s ):
168
181
try :
169
182
return '' .join (map (chr , s ))
@@ -1782,11 +1795,13 @@ cdef class RandomState:
1782
1795
1783
1796
>>> s = np.random.complex_normal(size=1000)
1784
1797
"""
1785
- cdef np .ndarray ogamma , orelation , oloc , randoms
1798
+ cdef np .ndarray ogamma , orelation , oloc , randoms , v_real , v_imag , rho
1786
1799
cdef double * randoms_data
1787
1800
cdef double fgamma_r , fgamma_i , frelation_r , frelation_i , frho , f_v_real , f_v_imag , \
1788
- floc_r , floc_i , f_real , f_imag , i_r_scale , r_scale , i_scale
1789
- cdef np .npy_intp i , j , n ,
1801
+ floc_r , floc_i , f_real , f_imag , i_r_scale , r_scale , i_scale , f_rho
1802
+ cdef complex cloc
1803
+ cdef np .npy_intp i , j , n
1804
+ cdef np .broadcast it
1790
1805
1791
1806
oloc = < np .ndarray > np .PyArray_FROM_OTF (loc , np .NPY_COMPLEX128 , np .NPY_ALIGNED )
1792
1807
ogamma = < np .ndarray > np .PyArray_FROM_OTF (gamma , np .NPY_COMPLEX128 , np .NPY_ALIGNED )
@@ -1832,7 +1847,7 @@ cdef class RandomState:
1832
1847
r_scale = sqrt (0.5 * f_v_real )
1833
1848
i_scale = sqrt (0.5 * f_v_imag )
1834
1849
j = 0
1835
- with self .lock , nogil :
1850
+ with self .lock : # , nogil:
1836
1851
for i in range (n ):
1837
1852
random_gauss_zig_double_fill (& self .rng_state , 1 , & f_real )
1838
1853
random_gauss_zig_double_fill (& self .rng_state , 1 , & f_imag )
@@ -1844,10 +1859,10 @@ cdef class RandomState:
1844
1859
1845
1860
gpc = ogamma + orelation
1846
1861
gmc = ogamma - orelation
1847
- v_real = 0.5 * np .real (gpc )
1862
+ v_real = < np . ndarray > ( 0.5 * np .real (gpc ) )
1848
1863
if np .any (np .less (v_real , 0 )):
1849
1864
raise ValueError ('Re(gamma + relation) < 0' )
1850
- v_imag = 0.5 * np .real (gmc )
1865
+ v_imag = < np . ndarray > ( 0.5 * np .real (gmc ) )
1851
1866
if np .any (np .less (v_imag , 0 )):
1852
1867
raise ValueError ('Re(gamma - relation) < 0' )
1853
1868
if np .any (np .not_equal (np .imag (ogamma ), 0 )):
@@ -1860,23 +1875,32 @@ cdef class RandomState:
1860
1875
if np .any (cov .flat [~ idx ] != 0 ) or np .any (np .abs (rho ) > 1 ):
1861
1876
raise ValueError ('Im(relation) ** 2 > Re(gamma ** 2 - relation ** 2)' )
1862
1877
1863
- if size is None :
1864
- size = np .broadcast (loc , gpc ).shape
1865
- elif np .PyArray_IsAnyScalar (size ):
1866
- size = (size ,)
1878
+ if size is not None :
1879
+ randoms = < np .ndarray > np .empty (size , np .complex128 )
1867
1880
else :
1868
- size = tuple (size )
1881
+ it = np .PyArray_MultiIterNew4 (oloc , v_real , v_imag , rho )
1882
+ randoms = < np .ndarray > np .empty (it .shape , np .complex128 )
1869
1883
1870
- norms = self .standard_normal (size + (2 ,), method = method )
1871
- real = norms [...,0 ]
1872
- imag = norms [...,1 ]
1884
+ randoms_data = < double * > np .PyArray_DATA (randoms )
1885
+ n = np .PyArray_SIZE (randoms )
1873
1886
1874
- imag *= np .sqrt (1 - rho ** 2 )
1875
- imag += rho * real
1876
- real *= np .sqrt (v_real )
1877
- imag *= np .sqrt (v_imag )
1878
-
1879
- return oloc + real + (0 + 1.0j ) * imag
1887
+ it = np .PyArray_MultiIterNew5 (randoms , oloc , v_real , v_imag , rho )
1888
+ # TODO: Box-Muller
1889
+ with self .lock , nogil :
1890
+ random_gauss_zig_double_fill (& self .rng_state , 2 * n , randoms_data )
1891
+ with nogil :
1892
+ j = 0
1893
+ for i in range (n ):
1894
+ floc_r = (< double * > np .PyArray_MultiIter_DATA (it , 1 ))[0 ]
1895
+ floc_i = (< double * > np .PyArray_MultiIter_DATA (it , 1 ))[1 ]
1896
+ f_v_real = (< double * > np .PyArray_MultiIter_DATA (it , 2 ))[0 ]
1897
+ f_v_imag = (< double * > np .PyArray_MultiIter_DATA (it , 3 ))[0 ]
1898
+ f_rho = (< double * > np .PyArray_MultiIter_DATA (it , 4 ))[0 ]
1899
+ compute_complex (& randoms_data [j ], & randoms_data [j + 1 ], floc_r , floc_i , f_v_real , f_v_imag , f_rho )
1900
+ j += 2
1901
+ np .PyArray_MultiIter_NEXT (it )
1902
+
1903
+ return randoms
1880
1904
1881
1905
def beta (self , a , b , size = None ):
1882
1906
"""
0 commit comments