[FFmpeg-devel] [PATCH 0/2] first steps to resolving float to int undefined behavior

Ganesh Ajjanagadde gajjanagadde at gmail.com
Mon Nov 2 00:22:29 CET 2015


On Sun, Nov 1, 2015 at 6:18 PM, Ronald S. Bultje <rsbultje at gmail.com> wrote:
> Hi,
>
> On Sun, Nov 1, 2015 at 6:15 PM, Ganesh Ajjanagadde <gajjanagadde at gmail.com>
> wrote:
>>
>> On Sun, Nov 1, 2015 at 6:12 PM, Ronald S. Bultje <rsbultje at gmail.com>
>> wrote:
>> > Hi,
>> >
>> > On Sun, Nov 1, 2015 at 1:03 PM, Ganesh Ajjanagadde
>> > <gajjanagadde at gmail.com>
>> > wrote:
>> >>
>> >> Floating point to integer conversion is well defined when the float
>> >> lies
>> >> within
>> >> the representation bounds of the integer after discarding the
>> >> fractional
>> >> part.
>> >> However, in other cases, unfortunately the standard leaves it
>> >> undefined.
>> >> In particular, assuming that it saturates in a sane way is a dangerous
>> >> assumption.
>> >>
>> >> In light of recent events, I would not have bothered if this was a
>> >> merely
>> >> theoretical
>> >> issue, and that common environments saturate correctly. Sadly, x86 (for
>> >> example)
>> >> converts casts to a cvttsd2si instruction which saturates numbers >
>> >> INT64_MAX to
>> >> INT64_MIN. This is mathematically completely bogus.
>> >>
>> >> http://blog.frama-c.com/index.php?post/2013/10/09/Overflow-float-integer
>> >> gives
>> >> a nice overview of the issue.
>> >>
>> >> 1/2 adds an av_clipd64 API for this purpose to clip a float to an
>> >> integral
>> >> range.
>> >> Obviously it will be slower than a cvttsd2si, but there is no option if
>> >> one wants
>> >> safe and well-defined behavior. Of course, if one knows a priori that a
>> >> float
>> >> lives in the integral type's range, then there is no issue. Safe
>> >> speedups
>> >> are
>> >> entirely possible, but API should be finalized first IMHO.
>> >> Most common anticipated usages are clipping to [INT64_MIN, INT64_MAX]
>> >> or
>> >> [INT_MIN, INT_MAX].
>> >> I have given some thought as to whether a separate av_clipd32 API (for
>> >> example)
>> >> is necessary. It seems to me to not be the case, since an IEEE-754
>> >> double
>> >> is
>> >> guaranteed to represent exactly integers up to ~ 2^53.
>> >> Similarly, av_clipf64 and the like also seem unnecessary, since a
>> >> double
>> >> is guaranteed
>> >> to represent all the values a float does. Such an API may be useful for
>> >> performance
>> >> though; I do not know how/what float to double conversions entail and
>> >> at
>> >> the
>> >> moment ignore such complications.
>> >>
>> >> 1/2 also accordingly documents av_clipd64.
>> >
>> >
>> > So, is this a bug in llrint, or is this a failure to use llrint, or is
>> > this
>> > different from llrint? It sounds to me that llrint should be used, not
>> > our
>> > own alternative.
>>
>> Not a bug, just a standard "undefined behavior" cop-out from the
>> standards committee. We need to roll our own: all standard functions
>> cop out when it does not fit in the integer range, and Intel (and
>> others) have wonderfully exploited the cop-out: see e.g the link I
>> gave and my other reply.
>
>
> So how are we going to define "correct" behaviour? Let's take your INT64_MAX
> + 100 example. INT64_MAX is nowhere near the correct answer. Now what?

Why not? It is the saturated result, and the "best effort" answer. It
is far more sane (when such things are needed) than returning
INT64_MIN which is actually undefined behavior that can't be relied
on.

Maybe I was not clear enough, but I defined this API to do a
mathematically best effort saturation.

>
> Ronald


More information about the ffmpeg-devel mailing list