问题描述
基于条件掩码选择一个小于或大于例如的值非常容易:
select *
from mytable
where enrollmentmonth = date '2020-07-01'
order by least(enddate,date '2020-07-31') - greatest(startdate,'2020-07-01')
fetch first row with ties
对于小于0.0f的矢量分量,以上内容将返回select *
from (
select t.*,rank() over(
partition by enrollmentmonth
order by least(enddate,last_day(enrollmentmonth)) - greatest(startdate,trunc(enrollmentmonth,'month'))
) rn
from mytable t
) t
where rn = 1
,如果矢量分量大于1.0f,则返回using vec4_t __attribute__((vector_size(4*sizeof(float)))) = float;
inline auto chooseValIfInRange(vec4_t val,vec4_t if_too_small,vec4_t if_too_large)
{
return val < vec4_t{0.0f,0.0f,0.0f}?
val_small
: (val > vec4_t{1.0f,1.0f,1.0f}?
val_large : val);
}
,如果矢量分量在0.0f和1.0f(含)之间,则返回val。是否可以为nan选择第三个值而没有任何分支?如果可以,怎么办?
解决方法
您可以利用以下事实:只有val=NaN
和val>=0
都为val<=1
都是错误的:
using vec4_t __attribute__((vector_size(4*sizeof(float)))) = float;
auto chooseValIfInRange(vec4_t val,vec4_t val_small,vec4_t val_large,vec4_t val_nan)
{
return val >= 0.0f
? ( val <= 1.0f ? val : val_large)
: ( val <= 1.0f ? val_small : val_nan )
;
}
启用优化后,val <= 1.0f
比较将仅执行一次:https://godbolt.org/z/Pcjezq
仅当f为NaN时才使用f != f
(未经测试的代码)
inline auto chooseValIfInRange(vec4_t val,vec4_t if_too_small,vec4_t if_too_large)
{
return val < vec4_t{0.0f,0.0f,0.0f}?
val_small
: (val > vec4_t{1.0f,1.0f,1.0f}?
val_large
: ((val != val) ? val_nan : val));
}