When I call the function INSIDE_WHICH_INTVAL below, it correctly returns IVL_NUM for input of type INTY :: Float64. When I broadcast the function to cover all elements of an array INTY_ARRAY also, as INSIDE_WHICH_INTVAL.(INTY_ARRAY, Ref(INT_BOU), Ref(N_INTEN)), it does execute correctly without issues, but hangs after the last array element is done with. Any help?
function INSIDE_WHICH_INTVAL(INTY, INT_BOU, N_INTEN)
IS_OUTS :: Bool = true
INT_MIN = INT_BOU[1]
INT_MAX = INT_BOU[2]
INT_INC = (INT_MAX - INT_MIN)/ N_INTEN
IVL_NUM = 0
I = 1
while IS_OUTS
IVL_LOW = INT_MIN + (I - 1)* INT_INC
IVL_HIH = INT_MIN + (I - 0)* INT_INC
IS_INSI = (IVL_LOW < INTY) && (INTY < IVL_HIH)
if IS_INSI == 1
IVL_NUM = I
IS_OUTS = false
break
end
I += 1
end
println("IVL_NUM = ", IVL_NUM)
return IVL_NUM
end
I just added the `println` to confirm that `INSIDE_WHICH_INTVAL` does finish evaluating all array elements.
In particular, tell us exactly how to call your code to see the error.
Also, can I suggest using more descriptive variable names and following the Julia variable naming conventions: Style Guide · The Julia Language
This will not only help us understand your code so we can help you, it will help you write maintainable code in the long run.
It hangs after! To test with any other data, just note 0.0 < INTY < 1.0, INT_BOU is a 2- element vector with elements in (0.0,1.0), N_INTEN is an I64 scalar >0 that specifies the number of intervals within one of whichINTY lies.
Regarding suggestion on style, appearance, kindly bear with me. I’ve been coding in this caps- dominant style for decades, across many languages from Ada 2012 thru MATLAB and now Julia 1.10.4. Indeed I find it lot easier to comprehend and extend a longer set made up of multiple short lines of code than a shorter set with longer lines that’ve lots of nesting and associations. Surely will think over style once I’ve got seasoned enough with Julia.
Just occurred to me if INTY[9] = 1.0 is why it’s hanging. The while might after all be unable to figure IVL_NUM when any INTY[k] ==1.0 unlike with elements 1..8 for which INTY[k] < 1.0. Will modify the IS_INSI assignment and try.
You need to make sure the number under test is guaranteed to be in one of the tested intervals. It’s difficult to figure out what the code is supposed to be doing because of your choice of variable names, but 1.0 does indeed seem to fall between the cracks.
It might be better to test only one comparison per loop iteration. For instance, if I read it right, the lower bound should not be necessary, since the limits increase monotonically. You only have to check whether the number is below the increasing upper bound.
Here’s an example of what I mean. Does this do what you expect your function to do?
"""
which_interval(x, grand_interval, num_intervals)
Give which of `num_intervals` subdivisions of the left-open interval `grand_interval` that contains number `x`.
For instance, `which_interval(0.5, (0, 3), 3) == 1`, because `0.5` is in the first third of the interval ``(0, 3]``.
If `x` does not lie within `grand_interval`, returns `nothing`.
"""
function which_interval(x, grand_interval, num_intervals)
grand_interval[1] < x <= grand_interval[2] || return nothing
increment = (grand_interval[2]-grand_interval[1])/num_intervals
for i = 1:num_intervals-1
x <= grand_interval[1] + increment*i && return i
end
return num_intervals
end
Thanks for suggesting a code, @gustaphe. It was indeed the runtime issue of me not checking for INTY being equal to either of the interval’s limits. I also simplified the function, as my bounds (grand_interval in your code) would never be outside [0.0, 1.0]. The function now reads as follows:
function INSIDE_WHICH_INTVAL(INTY , N_INTEN)
IS_OUTS :: Bool = true
INT_INC = 1.0/ N_INTEN
IVL_NUM = 0
I = 1
while IS_OUTS
IVL_LOW = (I - 1) * INT_INC
IVL_HIH = (I - 0) * INT_INC
IS_INSI = (IVL_LOW <= INTY) && (INTY <= IVL_HIH)
if IS_INSI == 1
IVL_NUM = I
IS_OUTS = false
break
end
I += 1
end
return IVL_NUM
end
Both lower and upper interval bounds are necessary, as otherwise all values INTY > Lower_Bound OR all values INTY < Upper_Boundcould qualify to fire IS_INSI as true.
But as long as you test whether it is inside the full interval before you start the loop, it will only get to the next iteration if it did not pass in the last, meaning that half of your comparisons are superfluous. And that extra complexity is what caused your bug.
Not quite so. INSIDE_WHICH_INTVAL is a simple function, similar to returning on which step one is, given the x in a flight of stairs of total span 0.0 <= x <= 1.0; see the sketch here.
Right, but you only need to check that the number is larger than 0, and then upper bound checks. Because the only way you’re getting to the loop iteration where the lower bound is 3/8, is to advance from the iteration where the upper bound was 3/8. So you have already found that x !< 3/8, no need to also check that x >= 3/8.
Oh, you’re right, can get going with checking for exceeding only one of the two bounds. But typically N_INTEN is quite small, < 10, so it wouldn’t matter a lot, in my opinion.