Skip to content

Conversation

@gururaj1512
Copy link

Resolves #963

  • Add convenience overloads for rvs_normal that accept (mold, array_size) and return standard-normal arrays (loc=0, scale=1) for both real and complex kinds.
  • Add deterministic tests that compare the new (mold, array_size) call with the explicit (loc=0, scale=1, array_size) call to ensure identical behavior.

@gururaj1512
Copy link
Author

@jvdp1, Can you have a look. Needs review...!

Copy link
Member

@jvdp1 jvdp1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @gururaj1512 . I have some suggestions below.

Comment on lines +38 to +39
#:for k1, t1 in RC_KINDS_TYPES
module procedure rvs_norm_array_default_${t1[0]}$${k1}$ !2 dummy variables (mold, array_size)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be included in the previous fypp loop (Line 35).

#:endfor
#:for k1, t1 in REAL_KINDS_TYPES
impure function rvs_norm_array_default_${t1[0]}$${k1}$ (mold, array_size) result(res)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
impure function rvs_norm_array_default_${t1[0]}$${k1}$ (mold, array_size) result(res)
impure function rvs_norm_array_default_${t1[0]}$${k1}$ (array_size, mold) result(res)

mold is usually the last argument.

Comment on lines +254 to +294
${t1}$, parameter :: r = 3.442619855899_${k1}$, rr = 1.0_${k1}$/r
${t1}$ :: x, y, re
integer :: hz, iz, i
if (.not. zig_norm_initialized) call zigset
do i = 1, array_size
iz = 0
hz = dist_rand(1_int32)
iz = iand(hz, 127)
if (abs(hz) < kn(iz)) then
re = hz*wn(iz)
else
L1: do
L2: if (iz == 0) then
do
x = -log(uni(1.0_${k1}$))*rr
y = -log(uni(1.0_${k1}$))
if (y + y >= x*x) exit
end do
re = r + x
if (hz <= 0) re = -re
exit L1
end if L2
x = hz*wn(iz)
if (fn(iz) + uni(1.0_${k1}$)*(fn(iz - 1) - fn(iz)) < &
exp(-HALF*x*x)) then
re = x
exit L1
end if
hz = dist_rand(1_int32)
iz = iand(hz, 127)
if (abs(hz) < kn(iz)) then
re = hz*wn(iz)
exit L1
end if
end do L1
end if
res(i) = re ! Default: loc=0, scale=1, so re*1 + 0 = re
end do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
${t1}$, parameter :: r = 3.442619855899_${k1}$, rr = 1.0_${k1}$/r
${t1}$ :: x, y, re
integer :: hz, iz, i
if (.not. zig_norm_initialized) call zigset
do i = 1, array_size
iz = 0
hz = dist_rand(1_int32)
iz = iand(hz, 127)
if (abs(hz) < kn(iz)) then
re = hz*wn(iz)
else
L1: do
L2: if (iz == 0) then
do
x = -log(uni(1.0_${k1}$))*rr
y = -log(uni(1.0_${k1}$))
if (y + y >= x*x) exit
end do
re = r + x
if (hz <= 0) re = -re
exit L1
end if L2
x = hz*wn(iz)
if (fn(iz) + uni(1.0_${k1}$)*(fn(iz - 1) - fn(iz)) < &
exp(-HALF*x*x)) then
re = x
exit L1
end if
hz = dist_rand(1_int32)
iz = iand(hz, 127)
if (abs(hz) < kn(iz)) then
re = hz*wn(iz)
exit L1
end if
end do L1
end if
res(i) = re ! Default: loc=0, scale=1, so re*1 + 0 = re
end do
res = rvs_norm_array_default_${t1[0]}$${k1}$(0._${k1}, 1._${k1}$, array_size)

I propose to call the procedure, instead of repeating the code, except if there is a good reason to repeat it (I didn't look carefully to the code; if the code needs to be (partly) repeated, the reason should be provided in the comments)..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make loc and scale arguments of rvs_normal optional when returning an array

2 participants