Skip to content

fld1 is really buggy when used with floats #62426

Description

@rokke-git

I don't think this behavior could be considered desirable by anyone:

julia> fld1(-0.533669923120631, 3.430469)
-1.0

julia> fld1(prevfloat(-0.533669923120631), 3.430469)
0.0

julia> fld1(nextfloat(-0.533669923120631), 3.430469)
0.0

(confirmed on 1.12.5 and 1.14.0-DEV.2662)

it seems like the right thing to do here is to make fld1 an alias of cld, and deprecate its use. I don't know why we have a separate fld1 and cld anyways, since they are logically equivalent for integer inputs:

julia> @code_typed fld1(20,3)
CodeInfo(
1%1  = intrinsic Base.checked_sdiv_int(x, y)::Int64%2  = intrinsic Base.xor_int(x, y)::Int64%3  = intrinsic Base.slt_int(%2, 0)::Bool%4  = intrinsic Base.not_int(%3)::Bool%5  = intrinsic Base.mul_int(%1, y)::Int64%6  =   builtin (%5 === x)::Bool%7  = intrinsic Base.not_int(%6)::Bool%8  = intrinsic Base.and_int(%4, %7)::Bool%9  = intrinsic Core.zext_int(Core.Int64, %8)::Int64%10 = intrinsic Core.and_int(%9, 1)::Int64%11 = intrinsic Base.add_int(%1, %10)::Int64
└──       return %11
) => Int64

julia> @code_typed cld(20,3)
CodeInfo(
1%1  = intrinsic Base.checked_sdiv_int(a, b)::Int64%2  = intrinsic Base.slt_int(0, a)::Bool%3  = intrinsic Base.slt_int(0, b)::Bool%4  =   builtin (%2 === %3)::Bool%5  = intrinsic Base.mul_int(%1, b)::Int64%6  =   builtin (%5 === a)::Bool%7  = intrinsic Base.not_int(%6)::Bool%8  = intrinsic Base.and_int(%4, %7)::Bool%9  = intrinsic Core.zext_int(Core.Int64, %8)::Int64%10 = intrinsic Core.and_int(%9, 1)::Int64%11 = intrinsic Base.add_int(%1, %10)::Int64
└──       return %11
) => Int64

((0<=a) == (0<=b) and (a⊻b) >= 0 are equivalent statements; and fld1 and cld are trivially equivalent when a or b is zero)

it would also be nice if we could make fldmod1 an alias for cldmod1 and deprecate the fldmod1 name as well.

admire the flickeryness:
julia> using GLMakie

julia> fig = Figure()

julia> ax = Axis(fig[1, 1], xticks = (1:4, ["div", "cld", "fld", "fld1"]), title = "op(a, b)")
Axis with 0 plots:


julia> sl = SliderGrid(fig[2, 1],
       (range = [-logrange(100,.001,100); logrange(.001,100,100)], label = "a", format = "{:.15f}"),
       (range = [-logrange(100,.001,100); logrange(.001,100,100)], label = "b", format = "{:.15f}")
       )
SliderGrid()

julia> bars = lift([s.value for s in sl.sliders]...) do a, b
           [div(a,b), cld(a,b), fld(a,b), fld1(a,b)]
       end
Observable([1.0, 1.0, 1.0, 1.0])

julia> plt = barplot!(ax, bars)
BarPlot{Tuple{Vector{Point{2, Float64}}}}

julia> on(bars) do b
         ylims!(ax, minimum(b)-1, maximum(b)+1)
       end
ObserverFunction defined at REPL[73]:2 operating on Observable([1.0, 1.0, 1.0, 1.0])

julia> while events(fig).window_open[]
          a = sl.sliders[1].selected_index[]
          if a==200
              a=0
              b=sl.sliders[2].selected_index[]
              if b==200 b=0 end
              set_close_to!(sl.sliders[2], sl.sliders[2].range[][b+1])
          end
          set_close_to!(sl.sliders[1], sl.sliders[1].range[][a+1])
          sleep(1/60)
       end

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions