On Fri, Nov 13, 2015 at 8:52 AM, Ronald S. Bultje <rsbul...@gmail.com> wrote: > Hi, > > On Fri, Nov 13, 2015 at 8:08 AM, Ronald S. Bultje <rsbul...@gmail.com> > wrote: >> >> Hi, >> >> On Thu, Nov 12, 2015 at 9:46 PM, Ganesh Ajjanagadde >> <gajjanaga...@gmail.com> wrote: >>> >>> The rationale for this function is reflected in the documentation for >>> it, and is copied here: >>> >>> Clip a double value into the long long amin-amax range. >>> This function is needed because conversion of floating point to integers >>> when >>> it does not fit in the integer's representation does not necessarily >>> saturate >>> correctly (usually converted to a cvttsd2si on x86) which saturates >>> numbers >>> > INT64_MAX to INT64_MIN. The standard marks such conversions as >>> > undefined >>> behavior, allowing this sort of mathematically bogus conversions. This >>> provides >>> a safe alternative that is slower obviously but assures safety and better >>> mathematical behavior. >>> API: >>> @param a value to clip >>> @param amin minimum value of the clip range >>> @param amax maximum value of the clip range >>> @return clipped value >>> >>> Note that a priori if one can guarantee from the calling side that the >>> double is in range, it is safe to simply do an explicit/implicit cast, >>> and that will be far faster. However, otherwise this function should be >>> used. >>> >>> avutil minor version is bumped. >>> >>> Reviewed-by: Ronald S. Bultje <rsbul...@gmail.com> >>> Signed-off-by: Ganesh Ajjanagadde <gajjanaga...@gmail.com> >>> --- >>> libavutil/common.h | 31 +++++++++++++++++++++++++++++++ >>> libavutil/version.h | 4 ++-- >>> 2 files changed, 33 insertions(+), 2 deletions(-) >>> >>> diff --git a/libavutil/common.h b/libavutil/common.h >>> index 6f0f582..4f60e72 100644 >>> --- a/libavutil/common.h >>> +++ b/libavutil/common.h >>> @@ -298,6 +298,34 @@ static av_always_inline av_const double >>> av_clipd_c(double a, double amin, double >>> else return a; >>> } >>> >>> +/** >>> + * Clip and convert a double value into the long long amin-amax range. >>> + * This function is needed because conversion of floating point to >>> integers when >>> + * it does not fit in the integer's representation does not necessarily >>> saturate >>> + * correctly (usually converted to a cvttsd2si on x86) which saturates >>> numbers >>> + * > INT64_MAX to INT64_MIN. The standard marks such conversions as >>> undefined >>> + * behavior, allowing this sort of mathematically bogus conversions. >>> This provides >>> + * a safe alternative that is slower obviously but assures safety and >>> better >>> + * mathematical behavior. >>> + * @param a value to clip >>> + * @param amin minimum value of the clip range >>> + * @param amax maximum value of the clip range >>> + * @return clipped value >>> + */ >>> +static av_always_inline av_const int64_t av_rint64_clip_c(double a, >>> int64_t amin, int64_t amax) >>> +{ >>> +#if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >>> >= 2 >>> + if (amin > amax) abort(); >>> +#endif >>> + // INT64_MAX+1,INT64_MIN are exactly representable as IEEE doubles >>> + if (a >= 9223372036854775808.0) >>> + return INT64_MAX; >>> + if (a <= INT64_MIN) >>> + return INT64_MIN; >>> + // Finally safe to call av_clipd_c >>> + return (int64_t)av_clipd_c(a, amin, amax); >> >> >> Also, please use llrint for casting (it rounds), and clip in integer >> domain (e.g. what happens if I set amin=amax=INT64_MAX, or any other number >> not exactly representable in floats)?
llrint does not work. Even casting "rounds", i.e rounds towards zero (albeit implementation defined). All that llrint does is sets the rounding behavior. > > > Yeah, I'm pretty sure that's broken right now: > > av_rint64_clip_c (9223372036854763520.000000, INT64_MAX, INT64_MAX) returns > -9223372036854775808. > > Given the bug you were trying to solve, that's somewhat funny :). Have a solution. > > Ronald _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel