Zulip Chat Archive

Stream: lean4

Topic: Casting Float to some integral type


Reed Mullanix (Jan 13 2021 at 07:15):

For the life of me I can't figure out how to turn a Float into an integral type (IE: Int, UInt32, etc). For the record, I've tried some nasty C FFI hacks as well, but I don't think I've figured out exactly how to get that to generate the requisite code.

Reid Barton (Jan 13 2021 at 12:31):

how about

def Float.toInt (f : Float) : Int :=
(f.toString.takeWhile (fun c => c == '-' || c.isDigit)).toInt!

:upside_down:

Sebastian Ullrich (Jan 13 2021 at 12:41):

Something like

@[extern c inline "(uint32)#1"]  constant Float.toUInt32 : Float  UInt32

should work, though you won't be able to use it in the interpreter without compiling it into a native library first. Implementing Int/Nat should be a bit more interesting if it's supposed to work on values > 2^64...

Reed Mullanix (Jan 13 2021 at 17:07):

That inline cast was my first attempt, but I couldn't figure out how to compile as a native library. The solution I settled on was

partial def UInt8.ofFloat (x : Float) : UInt8 :=
  if x >= 255 then 255
  else if x < 0 then 0
  else go 0 255

  where
    go (lo : Nat) (hi : Nat) : UInt8 :=
      let mid := (lo + hi)/2
      if hi <= lo then (UInt8.ofNat $ lo - 1)
      else if x < (Float.ofNat mid) then go lo mid else go (mid + 1) hi

Also, while floats are up for discussion, I think there is a missing instance for Neg Float


Last updated: Dec 20 2023 at 11:08 UTC