utils: pass correction factor around

Pass the correction factor around to get rid of the enum, some code
and some branches.
This commit is contained in:
Wim Taymans 2009-08-28 12:30:41 +02:00
parent 75e8e9eb42
commit 2b8d7a54cc

View file

@ -204,14 +204,6 @@ typedef union
} l; } l;
} GstUInt64; } GstUInt64;
/* used internally by muldiv functions to control rounding mode */
typedef enum
{
GST_ROUND_TONEAREST,
GST_ROUND_UP,
GST_ROUND_DOWN,
} GstRoundingMode;
/* multiply two 64-bit unsigned ints into a 128-bit unsigned int. the high /* multiply two 64-bit unsigned ints into a 128-bit unsigned int. the high
* and low 64 bits of the product are placed in c1 and c0 respectively. * and low 64 bits of the product are placed in c1 and c0 respectively.
* this operation cannot overflow. */ * this operation cannot overflow. */
@ -363,29 +355,15 @@ gst_util_div96_32 (guint64 c1, guint64 c0, guint32 denom)
static guint64 static guint64
gst_util_uint64_scale_uint64_unchecked (guint64 val, guint64 num, gst_util_uint64_scale_uint64_unchecked (guint64 val, guint64 num,
guint64 denom, GstRoundingMode mode) guint64 denom, guint64 correct)
{ {
GstUInt64 c1, c0; GstUInt64 c1, c0;
/* compute 128-bit numerator product */ /* compute 128-bit numerator product */
gst_util_uint64_mul_uint64 (&c1, &c0, val, num); gst_util_uint64_mul_uint64 (&c1, &c0, val, num);
/* condition numerator based on rounding mode */ /* perform rounding correction */
switch (mode) { CORRECT (c0, c1, correct);
case GST_ROUND_TONEAREST:
/* add 1/2 the denominator to the numerator with carry */
CORRECT (c0, c1, denom / 2);
break;
case GST_ROUND_UP:
/* add denominator - 1 to the numerator with carry */
CORRECT (c0, c1, denom - 1);
break;
case GST_ROUND_DOWN:
/* natural behaviour */
break;
}
/* high word as big as or bigger than denom --> overflow */ /* high word as big as or bigger than denom --> overflow */
if (G_UNLIKELY (c1.ll >= denom)) if (G_UNLIKELY (c1.ll >= denom))
@ -397,7 +375,7 @@ gst_util_uint64_scale_uint64_unchecked (guint64 val, guint64 num,
static inline guint64 static inline guint64
gst_util_uint64_scale_uint32_unchecked (guint64 val, guint32 num, gst_util_uint64_scale_uint32_unchecked (guint64 val, guint32 num,
guint32 denom, GstRoundingMode mode) guint32 denom, guint32 correct)
{ {
GstUInt64 c1, c0; GstUInt64 c1, c0;
@ -405,21 +383,7 @@ gst_util_uint64_scale_uint32_unchecked (guint64 val, guint32 num,
gst_util_uint64_mul_uint32 (&c1, &c0, val, num); gst_util_uint64_mul_uint32 (&c1, &c0, val, num);
/* condition numerator based on rounding mode */ /* condition numerator based on rounding mode */
switch (mode) { CORRECT (c0, c1, correct);
case GST_ROUND_TONEAREST:
/* add 1/2 the denominator to the numerator with carry */
CORRECT (c0, c1, denom / 2);
break;
case GST_ROUND_UP:
/* add denominator - 1 to the numerator with carry */
CORRECT (c0, c1, denom - 1);
break;
case GST_ROUND_DOWN:
/* natural behaviour */
break;
}
/* high 32 bits as big as or bigger than denom --> overflow */ /* high 32 bits as big as or bigger than denom --> overflow */
if (G_UNLIKELY (c1.l.high >= denom)) if (G_UNLIKELY (c1.l.high >= denom))
@ -432,7 +396,7 @@ gst_util_uint64_scale_uint32_unchecked (guint64 val, guint32 num,
/* the guts of the gst_util_uint64_scale() variants */ /* the guts of the gst_util_uint64_scale() variants */
static guint64 static guint64
_gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom, _gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom,
GstRoundingMode mode) guint64 correct)
{ {
g_return_val_if_fail (denom != 0, G_MAXUINT64); g_return_val_if_fail (denom != 0, G_MAXUINT64);
@ -447,16 +411,16 @@ _gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom,
/* num is low --> use 96 bit muldiv */ /* num is low --> use 96 bit muldiv */
if (G_LIKELY (num <= G_MAXUINT32)) if (G_LIKELY (num <= G_MAXUINT32))
return gst_util_uint64_scale_uint32_unchecked (val, (guint32) num, return gst_util_uint64_scale_uint32_unchecked (val, (guint32) num,
(guint32) denom, mode); (guint32) denom, correct);
/* num is high but val is low --> swap and use 96-bit muldiv */ /* num is high but val is low --> swap and use 96-bit muldiv */
if (G_LIKELY (val <= G_MAXUINT32)) if (G_LIKELY (val <= G_MAXUINT32))
return gst_util_uint64_scale_uint32_unchecked (num, (guint32) val, return gst_util_uint64_scale_uint32_unchecked (num, (guint32) val,
(guint32) denom, mode); (guint32) denom, correct);
} }
/* val is high and num is high --> use 128-bit muldiv */ /* val is high and num is high --> use 128-bit muldiv */
return gst_util_uint64_scale_uint64_unchecked (val, num, denom, mode); return gst_util_uint64_scale_uint64_unchecked (val, num, denom, correct);
} }
/** /**
@ -481,7 +445,7 @@ _gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom,
guint64 guint64
gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom) gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom)
{ {
return _gst_util_uint64_scale (val, num, denom, GST_ROUND_DOWN); return _gst_util_uint64_scale (val, num, denom, 0);
} }
/** /**
@ -506,7 +470,7 @@ gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom)
guint64 guint64
gst_util_uint64_scale_round (guint64 val, guint64 num, guint64 denom) gst_util_uint64_scale_round (guint64 val, guint64 num, guint64 denom)
{ {
return _gst_util_uint64_scale (val, num, denom, GST_ROUND_TONEAREST); return _gst_util_uint64_scale (val, num, denom, denom / 2);
} }
/** /**
@ -531,13 +495,12 @@ gst_util_uint64_scale_round (guint64 val, guint64 num, guint64 denom)
guint64 guint64
gst_util_uint64_scale_ceil (guint64 val, guint64 num, guint64 denom) gst_util_uint64_scale_ceil (guint64 val, guint64 num, guint64 denom)
{ {
return _gst_util_uint64_scale (val, num, denom, GST_ROUND_UP); return _gst_util_uint64_scale (val, num, denom, denom - 1);
} }
/* the guts of the gst_util_uint64_scale_int() variants */ /* the guts of the gst_util_uint64_scale_int() variants */
static guint64 static guint64
_gst_util_uint64_scale_int (guint64 val, gint num, gint denom, _gst_util_uint64_scale_int (guint64 val, gint num, gint denom, gint correct)
GstRoundingMode mode)
{ {
g_return_val_if_fail (denom > 0, G_MAXUINT64); g_return_val_if_fail (denom > 0, G_MAXUINT64);
g_return_val_if_fail (num >= 0, G_MAXUINT64); g_return_val_if_fail (num >= 0, G_MAXUINT64);
@ -554,27 +517,15 @@ _gst_util_uint64_scale_int (guint64 val, gint num, gint denom,
* because val*num <= G_MAXUINT32 * G_MAXINT32 < G_MAXUINT64 - * because val*num <= G_MAXUINT32 * G_MAXINT32 < G_MAXUINT64 -
* G_MAXINT32, so there's room to add another gint32. */ * G_MAXINT32, so there's room to add another gint32. */
val *= (guint64) num; val *= (guint64) num;
switch (mode) { /* add rounding correction */
case GST_ROUND_TONEAREST: val += correct;
/* add 1/2 the denominator to the numerator. */
val += denom / 2;
break;
case GST_ROUND_UP:
/* add denominator - 1 to the numerator. */
val += denom - 1;
break;
case GST_ROUND_DOWN:
/* natural behaviour */
break;
}
return val / (guint64) denom; return val / (guint64) denom;
} }
/* num and denom are not negative so casts are OK */ /* num and denom are not negative so casts are OK */
return gst_util_uint64_scale_uint32_unchecked (val, (guint32) num, return gst_util_uint64_scale_uint32_unchecked (val, (guint32) num,
(guint32) denom, mode); (guint32) denom, (guint32) correct);
} }
/** /**
@ -597,7 +548,7 @@ _gst_util_uint64_scale_int (guint64 val, gint num, gint denom,
guint64 guint64
gst_util_uint64_scale_int (guint64 val, gint num, gint denom) gst_util_uint64_scale_int (guint64 val, gint num, gint denom)
{ {
return _gst_util_uint64_scale_int (val, num, denom, GST_ROUND_DOWN); return _gst_util_uint64_scale_int (val, num, denom, 0);
} }
/** /**
@ -620,7 +571,7 @@ gst_util_uint64_scale_int (guint64 val, gint num, gint denom)
guint64 guint64
gst_util_uint64_scale_int_round (guint64 val, gint num, gint denom) gst_util_uint64_scale_int_round (guint64 val, gint num, gint denom)
{ {
return _gst_util_uint64_scale_int (val, num, denom, GST_ROUND_TONEAREST); return _gst_util_uint64_scale_int (val, num, denom, denom / 2);
} }
/** /**
@ -643,7 +594,7 @@ gst_util_uint64_scale_int_round (guint64 val, gint num, gint denom)
guint64 guint64
gst_util_uint64_scale_int_ceil (guint64 val, gint num, gint denom) gst_util_uint64_scale_int_ceil (guint64 val, gint num, gint denom)
{ {
return _gst_util_uint64_scale_int (val, num, denom, GST_ROUND_UP); return _gst_util_uint64_scale_int (val, num, denom, denom - 1);
} }
/** /**