PR #24668 opened by James Almer (jamrial)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24668
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24668.patch

It's specific to sws, so no reason to have it in avutil.


>From 1433217d4feed300a839651fdd68f8767d6da04e Mon Sep 17 00:00:00 2001
From: James Almer <[email protected]>
Date: Thu, 24 Sep 2026 11:03:22 -0300
Subject: [PATCH 1/2] swscale/rational64: replace av_ prefix with ff_

Even if not exported in sws, av_ prefixes are normally reserved for public 
functions.

Signed-off-by: James Almer <[email protected]>
---
 libswscale/format.c        | 22 +++++++++----------
 libswscale/ops.c           | 44 +++++++++++++++++++-------------------
 libswscale/ops_optimizer.c | 16 +++++++-------
 libswscale/rational64.c    | 12 +++++------
 libswscale/rational64.h    | 16 +++++++-------
 5 files changed, 55 insertions(+), 55 deletions(-)

diff --git a/libswscale/format.c b/libswscale/format.c
index 8c53832159..254b9353c4 100644
--- a/libswscale/format.c
+++ b/libswscale/format.c
@@ -1284,7 +1284,7 @@ static SwsLinearOp fmt_encode_range(const SwsFormat *fmt, 
bool *incomplete)
 
     if (fmt->format == AV_PIX_FMT_MONOWHITE) {
         /* This format is inverted, 0 = white, 1 = black */
-        c.m[0][4] = av_add_q64(c.m[0][4], c.m[0][0]);
+        c.m[0][4] = ff_add_q64(c.m[0][4], c.m[0][0]);
         c.m[0][0] = av_neg_q64(c.m[0][0]);
     }
 
@@ -1298,8 +1298,8 @@ static SwsLinearOp fmt_decode_range(const SwsFormat *fmt, 
bool *incomplete)
     /* Invert main diagonal + offset: x = s * y + k  ==>  y = (x - k) / s */
     for (int i = 0; i < 4; i++) {
         av_assert1(c.m[i][i].num);
-        c.m[i][i] = av_inv_q64(c.m[i][i]);
-        c.m[i][4] = av_mul_q64(c.m[i][4], av_neg_q64(c.m[i][i]));
+        c.m[i][i] = ff_inv_q64(c.m[i][i]);
+        c.m[i][4] = ff_mul_q64(c.m[i][4], av_neg_q64(c.m[i][i]));
     }
 
     /* Explicitly initialize alpha for sanity */
@@ -1327,9 +1327,9 @@ static AVRational64 *generate_bayer_matrix(const int 
size_log2)
         for (int y = 0; y < sz; y++) {
             for (int x = 0; x < sz; x++) {
                 const AVRational64 cur = m[y * size + x];
-                m[(y + sz) * size + x + sz] = av_add_q64(cur, av_make_q64(1, 
den));
-                m[(y     ) * size + x + sz] = av_add_q64(cur, av_make_q64(2, 
den));
-                m[(y + sz) * size + x     ] = av_add_q64(cur, av_make_q64(3, 
den));
+                m[(y + sz) * size + x + sz] = ff_add_q64(cur, ff_make_q64(1, 
den));
+                m[(y     ) * size + x + sz] = ff_add_q64(cur, ff_make_q64(2, 
den));
+                m[(y + sz) * size + x     ] = ff_add_q64(cur, ff_make_q64(3, 
den));
             }
         }
     }
@@ -1345,7 +1345,7 @@ static AVRational64 *generate_bayer_matrix(const int 
size_log2)
      * To make the average value equal to 1/2 = N/(2N), add a bias of 1/(2N).
      */
     for (int i = 0; i < num_entries; i++)
-        m[i] = av_add_q64(m[i], av_make_q64(1, 2 * num_entries));
+        m[i] = ff_add_q64(m[i], ff_make_q64(1, 2 * num_entries));
 
     return m;
 }
@@ -1412,9 +1412,9 @@ static int fmt_dither(SwsContext *ctx, SwsOpList *ops,
         const int size = 1 << dither.size_log2;
         dither.min = dither.max = dither.matrix[0];
         for (int i = 1; i < size * size; i++) {
-            if (av_cmp_q64(dither.min, dither.matrix[i]) > 0)
+            if (ff_cmp_q64(dither.min, dither.matrix[i]) > 0)
                 dither.min = dither.matrix[i];
-            if (av_cmp_q64(dither.matrix[i], dither.max) > 0)
+            if (ff_cmp_q64(dither.matrix[i], dither.max) > 0)
                 dither.max = dither.matrix[i];
         }
 
@@ -1460,7 +1460,7 @@ static int fmt_dither(SwsContext *ctx, SwsOpList *ops,
     return AVERROR(EINVAL);
 }
 
-#define Q64(x) av_make_q64((x).num, (x).den)
+#define Q64(x) ff_make_q64((x).num, (x).den)
 
 static inline SwsLinearOp
 linear_mat3(const AVRational m00, const AVRational m01, const AVRational m02,
@@ -1788,7 +1788,7 @@ int ff_sws_apply_lut3d(SwsContext *ctx, SwsPixelType 
type, SwsOpList *ops,
     }));
 
     /* Normalize back to [0, 1] */
-    const AVRational64 inv = av_inv_q64(Q(UINT16_MAX));
+    const AVRational64 inv = ff_inv_q64(Q(UINT16_MAX));
     RET(ff_sws_op_list_append(ops, &(SwsOp) {
         .type   = type,
         .op     = SWS_OP_LINEAR,
diff --git a/libswscale/ops.c b/libswscale/ops.c
index 5590915e30..4d2343f9ed 100644
--- a/libswscale/ops.c
+++ b/libswscale/ops.c
@@ -146,12 +146,12 @@ int ff_sws_rw_op_planes(const SwsOp *op)
 /* biased towards `a` */
 static AVRational64 av_min_q64(AVRational64 a, AVRational64 b)
 {
-    return av_cmp_q64(a, b) == 1 ? b : a;
+    return ff_cmp_q64(a, b) == 1 ? b : a;
 }
 
 static AVRational64 av_max_q64(AVRational64 a, AVRational64 b)
 {
-    return av_cmp_q64(a, b) == -1 ? b : a;
+    return ff_cmp_q64(a, b) == -1 ? b : a;
 }
 
 void ff_sws_apply_op_q(const SwsOp *op, AVRational64 x[4])
@@ -207,7 +207,7 @@ void ff_sws_apply_op_q(const SwsOp *op, AVRational64 x[4])
         av_assert1(ff_sws_pixel_type_is_int(op->type));
         AVRational64 mult = Q(1 << op->shift.amount);
         for (int i = 0; i < 4; i++)
-            x[i] = x[i].den ? av_mul_q64(x[i], mult) : x[i];
+            x[i] = x[i].den ? ff_mul_q64(x[i], mult) : x[i];
         return;
     }
     case SWS_OP_RSHIFT: {
@@ -228,7 +228,7 @@ void ff_sws_apply_op_q(const SwsOp *op, AVRational64 x[4])
             for (int i = 0; i < 4; i++) {
                 x[i] = x[i].den ? Q(x[i].num / x[i].den) : x[i];
                 if (op->convert.expand)
-                    x[i] = av_mul_q64(x[i], scale);
+                    x[i] = ff_mul_q64(x[i], scale);
             }
         }
         return;
@@ -236,7 +236,7 @@ void ff_sws_apply_op_q(const SwsOp *op, AVRational64 x[4])
         av_assert1(!ff_sws_pixel_type_is_int(op->type));
         for (int i = 0; i < 4; i++) {
             if (op->dither.y_offset[i] >= 0 && x[i].den)
-                x[i] = av_add_q64(x[i], av_make_q64(1, 2));
+                x[i] = ff_add_q64(x[i], ff_make_q64(1, 2));
         }
         return;
     case SWS_OP_MIN:
@@ -253,14 +253,14 @@ void ff_sws_apply_op_q(const SwsOp *op, AVRational64 x[4])
         for (int i = 0; i < 4; i++) {
             AVRational64 sum = op->lin.m[i][4];
             for (int j = 0; j < 4; j++)
-                sum = av_add_q64(sum, av_mul_q64(orig[j], op->lin.m[i][j]));
+                sum = ff_add_q64(sum, ff_mul_q64(orig[j], op->lin.m[i][j]));
             x[i] = sum;
         }
         return;
     }
     case SWS_OP_SCALE:
         for (int i = 0; i < 4; i++)
-            x[i] = x[i].den ? av_mul_q64(x[i], op->scale.factor) : x[i];
+            x[i] = x[i].den ? ff_mul_q64(x[i], op->scale.factor) : x[i];
         return;
     case SWS_OP_FILTER_H:
     case SWS_OP_FILTER_V:
@@ -304,10 +304,10 @@ static void apply_filter_weights(SwsComps *comps, const 
SwsComps *prev,
         if (weights->filter_size != 1)
             comps->flags[i] &= ~SWS_COMP_EXACT;
         /* Update min/max assuming extremes */
-        comps->min[i] = av_add_q64(av_mul_q64(prev->min[i], posw),
-                                   av_mul_q64(prev->max[i], negw));
-        comps->max[i] = av_add_q64(av_mul_q64(prev->min[i], negw),
-                                   av_mul_q64(prev->max[i], posw));
+        comps->min[i] = ff_add_q64(ff_mul_q64(prev->min[i], posw),
+                                   ff_mul_q64(prev->max[i], negw));
+        comps->max[i] = ff_add_q64(ff_mul_q64(prev->min[i], negw),
+                                   ff_mul_q64(prev->max[i], posw));
     }
 }
 
@@ -429,8 +429,8 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
                     continue;
                 /* Strip zero flag because of the nonzero dithering offset */
                 op->comps.flags[i] &= ~SWS_COMP_ZERO & SWS_COMP_DIRTY;
-                op->comps.min[i] = av_add_q64(op->comps.min[i], 
op->dither.min);
-                op->comps.max[i] = av_add_q64(op->comps.max[i], 
op->dither.max);
+                op->comps.min[i] = ff_add_q64(op->comps.min[i], 
op->dither.min);
+                op->comps.max[i] = ff_add_q64(op->comps.max[i], 
op->dither.max);
             }
             break;
         case SWS_OP_UNPACK:
@@ -485,17 +485,17 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
                 bool first = true;
                 for (int j = 0; j < 4; j++) {
                     const AVRational64 k = op->lin.m[i][j];
-                    AVRational64 mink = av_mul_q64(prev.min[j], k);
-                    AVRational64 maxk = av_mul_q64(prev.max[j], k);
+                    AVRational64 mink = ff_mul_q64(prev.min[j], k);
+                    AVRational64 maxk = ff_mul_q64(prev.max[j], k);
                     if (k.num) {
                         FORWARD(i, j, flags);
                         if (k.den != 1) /* fractional coefficient */
                             op->comps.flags[i] &= ~SWS_COMP_EXACT;
                         if (k.num < 0)
                             FFSWAP(AVRational64, mink, maxk);
-                        min = av_add_q64(min, mink);
-                        max = av_add_q64(max, maxk);
-                        if (!first || av_cmp_q64(k, Q(1)))
+                        min = ff_add_q64(min, mink);
+                        max = ff_add_q64(max, maxk);
+                        if (!first || ff_cmp_q64(k, Q(1)))
                             op->comps.flags[i] &= SWS_COMP_DIRTY;
                         first = false;
                     }
@@ -504,8 +504,8 @@ void ff_sws_op_list_update_comps(SwsOpList *ops)
                     op->comps.flags[i] &= ~SWS_COMP_ZERO & SWS_COMP_DIRTY;
                     if (op->lin.m[i][4].den != 1) /* fractional offset */
                         op->comps.flags[i] &= ~SWS_COMP_EXACT;
-                    min = av_add_q64(min, op->lin.m[i][4]);
-                    max = av_add_q64(max, op->lin.m[i][4]);
+                    min = ff_add_q64(min, op->lin.m[i][4]);
+                    max = ff_add_q64(max, op->lin.m[i][4]);
                 }
                 op->comps.min[i] = min;
                 op->comps.max[i] = max;
@@ -804,7 +804,7 @@ uint32_t ff_sws_linear_mask(const SwsLinearOp *c)
     uint32_t mask = 0;
     for (int i = 0; i < 4; i++) {
         for (int j = 0; j < 5; j++) {
-            if (av_cmp_q64(c->m[i][j], Q(i == j)))
+            if (ff_cmp_q64(c->m[i][j], Q(i == j)))
                 mask |= SWS_MASK(i, j);
         }
     }
@@ -847,7 +847,7 @@ static void print_q(AVBPrint *bp, const AVRational64 q)
     } else if (q.den == 1) {
         av_bprintf(bp, "%"PRId64, q.num);
     } else if (q.num > 1000 || q.num < -1000 || q.den > 1000 || q.den < -1000) 
{
-        av_bprintf(bp, "%f", av_q2d_64(q));
+        av_bprintf(bp, "%f", ff_q2d_64(q));
     } else {
         av_bprintf(bp, "%"PRId64"/%"PRId64, q.num, q.den);
     }
diff --git a/libswscale/ops_optimizer.c b/libswscale/ops_optimizer.c
index 9cc5db9717..3945de2034 100644
--- a/libswscale/ops_optimizer.c
+++ b/libswscale/ops_optimizer.c
@@ -128,7 +128,7 @@ static bool op_commute_swizzle(SwsOp *op, SwsOp *next)
             if (!SWS_OP_NEEDED(op, i))
                 continue;
             const int j = op->swizzle.in[i];
-            if (seen[j] && av_cmp_q64(next->clamp.limit[j], c.limit[i]))
+            if (seen[j] && ff_cmp_q64(next->clamp.limit[j], c.limit[i]))
                 return false;
             next->clamp.limit[j] = c.limit[i];
             seen[j] = true;
@@ -249,7 +249,7 @@ static bool extract_scalar(const SwsLinearOp *c,
         if ((prev->flags[i]  & SWS_COMP_ZERO) ||
             (comps->flags[i] & SWS_COMP_GARBAGE))
             continue;
-        if (scale.factor.den && av_cmp_q64(s, scale.factor))
+        if (scale.factor.den && ff_cmp_q64(s, scale.factor))
             return false;
         scale.factor = s;
     }
@@ -568,7 +568,7 @@ retry:
             if (next->op == SWS_OP_SCALE && !op->convert.expand &&
                 ff_sws_pixel_type_is_int(op->type) &&
                 ff_sws_pixel_type_is_int(op->convert.to) &&
-                !av_cmp_q64(next->scale.factor,
+                !ff_cmp_q64(next->scale.factor,
                             ff_sws_pixel_expand(op->type, op->convert.to)))
             {
                 op->convert.expand = true;
@@ -581,7 +581,7 @@ retry:
             for (int i = 0; i < 4; i++) {
                 if (!SWS_OP_NEEDED(op, i) || !op->clamp.limit[i].den)
                     continue;
-                if (av_cmp_q64(op->clamp.limit[i], prev->comps.max[i]) >= 0)
+                if (ff_cmp_q64(op->clamp.limit[i], prev->comps.max[i]) >= 0)
                     op->clamp.limit[i] = (AVRational64) {0}; /* no-op */
                 else
                     noop = false;
@@ -597,7 +597,7 @@ retry:
             for (int i = 0; i < 4; i++) {
                 if (!SWS_OP_NEEDED(op, i) || !op->clamp.limit[i].den)
                     continue;
-                if (av_cmp_q64(prev->comps.min[i], op->clamp.limit[i]) >= 0)
+                if (ff_cmp_q64(prev->comps.min[i], op->clamp.limit[i]) >= 0)
                     op->clamp.limit[i] = (AVRational64) {0};
                 else
                     noop = false;
@@ -647,9 +647,9 @@ retry:
                     for (int j = 0; j < 5; j++) {
                         AVRational64 sum = Q(0);
                         for (int k = 0; k < 4; k++)
-                            sum = av_add_q64(sum, av_mul_q64(m2.m[i][k], 
m1.m[k][j]));
+                            sum = ff_add_q64(sum, ff_mul_q64(m2.m[i][k], 
m1.m[k][j]));
                         if (j == 4) /* m1.m[4][j] == 1 */
-                            sum = av_add_q64(sum, m2.m[i][4]);
+                            sum = ff_add_q64(sum, m2.m[i][4]);
                         op->lin.m[i][j] = sum;
                     }
                 }
@@ -718,7 +718,7 @@ retry:
 
             /* Merge consecutive scaling operations */
             if (next->op == SWS_OP_SCALE) {
-                op->scale.factor = av_mul_q64(op->scale.factor, 
next->scale.factor);
+                op->scale.factor = ff_mul_q64(op->scale.factor, 
next->scale.factor);
                 ff_sws_op_list_remove_at(ops, n + 1, 1);
                 goto retry;
             }
diff --git a/libswscale/rational64.c b/libswscale/rational64.c
index 998e46c572..6577a66613 100644
--- a/libswscale/rational64.c
+++ b/libswscale/rational64.c
@@ -105,7 +105,7 @@ done:;
     return res;
 }
 
-int av_cmp_q64(AVRational64 a, AVRational64 b)
+int ff_cmp_q64(AVRational64 a, AVRational64 b)
 {
     const av_int128 p = av_mul128(av_to128i(a.num), av_to128i(b.den));
     const av_int128 q = av_mul128(av_to128i(b.num), av_to128i(a.den));
@@ -121,24 +121,24 @@ int av_cmp_q64(AVRational64 a, AVRational64 b)
         return INT_MIN;
 }
 
-AVRational64 av_mul_q64(AVRational64 b, AVRational64 c)
+AVRational64 ff_mul_q64(AVRational64 b, AVRational64 c)
 {
     return reduce64(av_mul128(av_to128i(b.num), av_to128i(c.num)),
                     av_mul128(av_to128i(b.den), av_to128i(c.den)));
 }
 
-AVRational64 av_div_q64(AVRational64 b, AVRational64 c)
+AVRational64 ff_div_q64(AVRational64 b, AVRational64 c)
 {
-    return av_mul_q64(b, av_inv_q64(c));
+    return ff_mul_q64(b, ff_inv_q64(c));
 }
 
-AVRational64 av_add_q64(AVRational64 b, AVRational64 c) {
+AVRational64 ff_add_q64(AVRational64 b, AVRational64 c) {
     return reduce64(av_add128(av_mul128(av_to128i(b.num), av_to128i(c.den)),
                               av_mul128(av_to128i(c.num), av_to128i(b.den))),
                     av_mul128(av_to128i(b.den), av_to128i(c.den)));
 }
 
-AVRational64 av_sub_q64(AVRational64 b, AVRational64 c)
+AVRational64 ff_sub_q64(AVRational64 b, AVRational64 c)
 {
     return reduce64(av_sub128(av_mul128(av_to128i(b.num), av_to128i(c.den)),
                               av_mul128(av_to128i(c.num), av_to128i(b.den))),
diff --git a/libswscale/rational64.h b/libswscale/rational64.h
index 03c952b0c2..edd0b958c0 100644
--- a/libswscale/rational64.h
+++ b/libswscale/rational64.h
@@ -61,7 +61,7 @@ typedef struct AVRational64 {
  *
  * @note The return value is not reduced.
  */
-static inline AVRational64 av_make_q64(int64_t num, int64_t den)
+static inline AVRational64 ff_make_q64(int64_t num, int64_t den)
 {
     AVRational64 r = { num, den };
     return r;
@@ -79,7 +79,7 @@ static inline AVRational64 av_make_q64(int64_t num, int64_t 
den)
  *         - -1 if `a < b`
  *         - `INT_MIN` if one of the values is of the form `0 / 0`
  */
-int av_cmp_q64(AVRational64 a, AVRational64 b);
+int ff_cmp_q64(AVRational64 a, AVRational64 b);
 
 /**
  * Convert an AVRational64 to a `double`.
@@ -87,7 +87,7 @@ int av_cmp_q64(AVRational64 a, AVRational64 b);
  * @return `a` in floating-point form
  * @see av_d2q()
  */
-static inline double av_q2d_64(AVRational64 a){
+static inline double ff_q2d_64(AVRational64 a){
     return a.num / (double) a.den;
 }
 
@@ -97,7 +97,7 @@ static inline double av_q2d_64(AVRational64 a){
  * @param c Second multiplicant
  * @return b*c
  */
-AVRational64 av_mul_q64(AVRational64 b, AVRational64 c) av_const;
+AVRational64 ff_mul_q64(AVRational64 b, AVRational64 c) av_const;
 
 /**
  * Divide one 64-bit rational by another.
@@ -105,7 +105,7 @@ AVRational64 av_mul_q64(AVRational64 b, AVRational64 c) 
av_const;
  * @param c Divisor
  * @return b/c
  */
-AVRational64 av_div_q64(AVRational64 b, AVRational64 c) av_const;
+AVRational64 ff_div_q64(AVRational64 b, AVRational64 c) av_const;
 
 /**
  * Add two 64-bit rationals.
@@ -113,7 +113,7 @@ AVRational64 av_div_q64(AVRational64 b, AVRational64 c) 
av_const;
  * @param c Second addend
  * @return b+c
  */
-AVRational64 av_add_q64(AVRational64 b, AVRational64 c) av_const;
+AVRational64 ff_add_q64(AVRational64 b, AVRational64 c) av_const;
 
 /**
  * Subtract one 64-bit rational from another.
@@ -121,14 +121,14 @@ AVRational64 av_add_q64(AVRational64 b, AVRational64 c) 
av_const;
  * @param c Subtrahend
  * @return b-c
  */
-AVRational64 av_sub_q64(AVRational64 b, AVRational64 c) av_const;
+AVRational64 ff_sub_q64(AVRational64 b, AVRational64 c) av_const;
 
 /**
  * Invert a 64-bit rational.
  * @param q value
  * @return 1 / q
  */
-static av_always_inline AVRational64 av_inv_q64(AVRational64 q)
+static av_always_inline AVRational64 ff_inv_q64(AVRational64 q)
 {
     AVRational64 r = { q.den, q.num };
     return r;
-- 
2.52.0


>From bf9cb9f396c3f2afa4a1538e822495a7dae43217 Mon Sep 17 00:00:00 2001
From: James Almer <[email protected]>
Date: Thu, 24 Sep 2026 11:10:18 -0300
Subject: [PATCH 2/2] swscale/tests: move rational64 test from avutil

Signed-off-by: James Almer <[email protected]>
---
 libavutil/tests/rational.c    | 123 ---------------------------
 libswscale/Makefile           |   1 +
 libswscale/tests/rational64.c | 155 ++++++++++++++++++++++++++++++++++
 3 files changed, 156 insertions(+), 123 deletions(-)
 create mode 100644 libswscale/tests/rational64.c

diff --git a/libavutil/tests/rational.c b/libavutil/tests/rational.c
index 69a8e896f7..2c9ca947fc 100644
--- a/libavutil/tests/rational.c
+++ b/libavutil/tests/rational.c
@@ -20,14 +20,12 @@
  */
 
 #include "libavutil/rational.c"
-#include "libswscale/rational64.c"
 #include "libavutil/integer.h"
 #include "libavutil/intfloat.h"
 
 int main(void)
 {
     AVRational a,b,r;
-    AVRational64 a64,b64,r64;
     int i,j,k;
     static const int64_t numlist[] = {
         INT64_MIN, INT64_MIN+1, INT64_MAX, INT32_MIN, INT32_MAX, 1,0,-1,
@@ -55,69 +53,6 @@ int main(void)
         }
     }
 
-    for (a64.num = -2; a64.num <= 2; a64.num++) {
-        for (a64.den = -2; a64.den <= 2; a64.den++) {
-            for (b64.num = -2; b64.num <= 2; b64.num++) {
-                for (b64.den = -2; b64.den <= 2; b64.den++) {
-                    const double adbl = av_q2d_64(a64);
-                    const double bdbl = av_q2d_64(b64);
-                    const int c = av_cmp_q64(a64,b64);
-                    const int d = adbl == bdbl ?  0 :
-                                  adbl >  bdbl ?  1 :
-                                  adbl <  bdbl ? -1 : INT_MIN;
-
-                    if (c != d)
-                        av_log(NULL, AV_LOG_ERROR, "%lld/%lld %lld/%lld, %d != 
%d\n",
-                               (long long) a64.num, (long long) a64.den,
-                               (long long) b64.num, (long long) b64.den, c,d);
-
-                    // Check arithmetic result
-                    if (a64.den && b64.den) {
-                        double rdbl;
-
-                        r64 = av_add_q64(a64, b64);
-                        rdbl = av_q2d_64(r64);
-                        if (rdbl != adbl + bdbl) {
-                            av_log(NULL, AV_LOG_ERROR, "%f + %f = %f != %f\n",
-                                   adbl, bdbl, rdbl, adbl + bdbl);
-                        }
-
-                        r64 = av_mul_q64(a64, b64);
-                        rdbl = av_q2d_64(r64);
-                        if (rdbl != adbl * bdbl) {
-                            av_log(NULL, AV_LOG_ERROR, "%f * %f = %f != %f\n",
-                                   adbl, bdbl, rdbl, adbl * bdbl);
-                        }
-                    }
-
-                    // Check addition round-trip
-                    r64 = av_sub_q64(av_add_q64(a64, b64), b64);
-                    if (b64.den && (r64.num*a64.den != a64.num*r64.den ||
-                        !r64.num != !a64.num ||
-                        !r64.den != !a64.den))
-                    {
-                        av_log(NULL, AV_LOG_ERROR, "%lld/%lld != %lld/%lld\n",
-                               (long long) a64.num, (long long) a64.den,
-                               (long long) r64.num, (long long) r64.den);
-                    }
-
-                    if (b64.num) {
-                        // Check multiplication round-trip
-                        r64 = av_div_q64(av_mul_q64(a64, b64), b64);
-                        if (b64.den && (r64.num*a64.den != a64.num*r64.den ||
-                            !r64.num != !a64.num ||
-                            !r64.den != !a64.den))
-                        {
-                            av_log(NULL, AV_LOG_ERROR, "%lld/%lld != 
%lld/%lld\n",
-                                   (long long) a64.num, (long long) a64.den,
-                                   (long long) r64.num, (long long) r64.den);
-                        }
-                    }
-                }
-            }
-        }
-    }
-
     /* Check overflow behavior and edge cases */
     static const AVRational unit_mul_q[][3] = {
         {{INT_MAX, 2},      { 2, 1},            { INT_MAX, 1}},
@@ -171,64 +106,6 @@ int main(void)
         }
     }
 
-    static const AVRational64 unit_mul_q64[][3] = {
-        {{INT64_MAX, 2},      { 2, 1},              { INT64_MAX, 1}},
-        {{INT64_MAX, 2},      {-2, 1},              {-INT64_MAX, 1}},
-        {{INT64_MAX, 2},      { 0, 1},              {0, 1}},
-        {{INT64_MIN, 2},      { 2, 1},              {-INT64_MAX, 1}}, /* not 
INT64_MIN */
-        {{INT64_MIN, 2},      {-2, 1},              { INT64_MAX, 1}},
-        {{INT64_MIN, 2},      { 0, 1},              {0, 1}},
-        {{INT64_MAX >> 8, 1}, {INT64_MAX >> 8, 1},  {INT64_MAX, 1}},
-        {{1, INT64_MAX >> 8}, {1, INT64_MAX >> 8},  {0, 1}},
-        {{1, 1},              {0, 0},               {0, 0}},
-        {{0, 1},              {0, 0},               {0, 0}},
-    };
-
-    for (i = 0; i < FF_ARRAY_ELEMS(unit_mul_q64); i++) {
-        for (int c = 0; c < 2; c++) { /* test commutativity */
-            AVRational64 a = unit_mul_q64[i][c ? 1 : 0];
-            AVRational64 b = unit_mul_q64[i][c ? 0 : 1];
-            AVRational64 c = unit_mul_q64[i][2];
-            AVRational64 r = av_mul_q64(a, b);
-            if (r.num != c.num || r.den != c.den) {
-                av_log(NULL, AV_LOG_ERROR, "%lld/%lld * %lld/%lld = %lld/%lld, 
expected %lld/%lld\n",
-                       (long long) a.num, (long long) a.den,
-                       (long long) b.num, (long long) b.den,
-                       (long long) r.num, (long long) r.den,
-                       (long long) c.num, (long long) c.den);
-            }
-        }
-    }
-
-    static const AVRational64 unit_add_q64[][3] = {
-        {{INT64_MAX, 1},      { 2, 2},            { INT64_MAX, 1}},
-        {{INT64_MAX, 1},      {-2, 2},            { INT64_MAX - 1, 1}},
-        {{INT64_MAX, 1},      { 0, 2},            { INT64_MAX, 1}},
-        {{INT64_MIN, 1},      { 2, 2},            {-INT64_MAX, 1}},
-        {{INT64_MIN, 1},      {-2, 2},            {-INT64_MAX, 1}},
-        {{INT64_MIN, 1},      { 0, 2},            {-INT64_MAX, 1}},
-        {{INT64_MAX - 10, 1}, {20, 1},            { INT64_MAX, 1}},
-        {{2, INT64_MAX},      {2, INT64_MAX},     {4, INT64_MAX}},
-        {{1, 1},              {0, 0},             {0, 0}},
-        {{0, 1},              {0, 0},             {0, 0}},
-    };
-
-    for (i = 0; i < FF_ARRAY_ELEMS(unit_add_q64); i++) {
-        for (int c = 0; c < 2; c++) { /* test commutativity */
-            AVRational64 a = unit_add_q64[i][c ? 1 : 0];
-            AVRational64 b = unit_add_q64[i][c ? 0 : 1];
-            AVRational64 c = unit_add_q64[i][2];
-            AVRational64 r = av_add_q64(a, b);
-            if (r.num != c.num || r.den != c.den) {
-                av_log(NULL, AV_LOG_ERROR, "%lld/%lld + %lld/%lld = %lld/%lld, 
expected %lld/%lld\n",
-                       (long long) a.num, (long long) a.den,
-                       (long long) b.num, (long long) b.den,
-                       (long long) r.num, (long long) r.den,
-                       (long long) c.num, (long long) c.den);
-            }
-        }
-    }
-
     for (i = 0; i < FF_ARRAY_ELEMS(numlist); i++) {
         int64_t a = numlist[i];
 
diff --git a/libswscale/Makefile b/libswscale/Makefile
index b53b815309..f6dbed3c08 100644
--- a/libswscale/Makefile
+++ b/libswscale/Makefile
@@ -56,5 +56,6 @@ TESTPROGS = colorspace                                        
          \
 
 TESTPROGS-$(CONFIG_UNSTABLE) = sws_ops                                  \
                                sws_ops_aarch64                          \
+                               rational64                               \
 
 DEVPROGS-$(CONFIG_UNSTABLE)  = uops_macros_gen                          \
diff --git a/libswscale/tests/rational64.c b/libswscale/tests/rational64.c
new file mode 100644
index 0000000000..ed24b97094
--- /dev/null
+++ b/libswscale/tests/rational64.c
@@ -0,0 +1,155 @@
+/*
+ * rational numbers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libswscale/rational64.c"
+#include "libavutil/integer.h"
+#include "libavutil/intfloat.h"
+#include "libavutil/log.h"
+#include "libavutil/macros.h"
+
+int main(void)
+{
+    AVRational64 a64,b64,r64;
+    int i;
+
+    for (a64.num = -2; a64.num <= 2; a64.num++) {
+        for (a64.den = -2; a64.den <= 2; a64.den++) {
+            for (b64.num = -2; b64.num <= 2; b64.num++) {
+                for (b64.den = -2; b64.den <= 2; b64.den++) {
+                    const double adbl = ff_q2d_64(a64);
+                    const double bdbl = ff_q2d_64(b64);
+                    const int c = ff_cmp_q64(a64,b64);
+                    const int d = adbl == bdbl ?  0 :
+                                  adbl >  bdbl ?  1 :
+                                  adbl <  bdbl ? -1 : INT_MIN;
+
+                    if (c != d)
+                        av_log(NULL, AV_LOG_ERROR, "%lld/%lld %lld/%lld, %d != 
%d\n",
+                               (long long) a64.num, (long long) a64.den,
+                               (long long) b64.num, (long long) b64.den, c,d);
+
+                    // Check arithmetic result
+                    if (a64.den && b64.den) {
+                        double rdbl;
+
+                        r64 = ff_add_q64(a64, b64);
+                        rdbl = ff_q2d_64(r64);
+                        if (rdbl != adbl + bdbl) {
+                            av_log(NULL, AV_LOG_ERROR, "%f + %f = %f != %f\n",
+                                   adbl, bdbl, rdbl, adbl + bdbl);
+                        }
+
+                        r64 = ff_mul_q64(a64, b64);
+                        rdbl = ff_q2d_64(r64);
+                        if (rdbl != adbl * bdbl) {
+                            av_log(NULL, AV_LOG_ERROR, "%f * %f = %f != %f\n",
+                                   adbl, bdbl, rdbl, adbl * bdbl);
+                        }
+                    }
+
+                    // Check addition round-trip
+                    r64 = ff_sub_q64(ff_add_q64(a64, b64), b64);
+                    if (b64.den && (r64.num*a64.den != a64.num*r64.den ||
+                        !r64.num != !a64.num ||
+                        !r64.den != !a64.den))
+                    {
+                        av_log(NULL, AV_LOG_ERROR, "%lld/%lld != %lld/%lld\n",
+                               (long long) a64.num, (long long) a64.den,
+                               (long long) r64.num, (long long) r64.den);
+                    }
+
+                    if (b64.num) {
+                        // Check multiplication round-trip
+                        r64 = ff_div_q64(ff_mul_q64(a64, b64), b64);
+                        if (b64.den && (r64.num*a64.den != a64.num*r64.den ||
+                            !r64.num != !a64.num ||
+                            !r64.den != !a64.den))
+                        {
+                            av_log(NULL, AV_LOG_ERROR, "%lld/%lld != 
%lld/%lld\n",
+                                   (long long) a64.num, (long long) a64.den,
+                                   (long long) r64.num, (long long) r64.den);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /* Check overflow behavior and edge cases */
+    static const AVRational64 unit_mul_q64[][3] = {
+        {{INT64_MAX, 2},      { 2, 1},              { INT64_MAX, 1}},
+        {{INT64_MAX, 2},      {-2, 1},              {-INT64_MAX, 1}},
+        {{INT64_MAX, 2},      { 0, 1},              {0, 1}},
+        {{INT64_MIN, 2},      { 2, 1},              {-INT64_MAX, 1}}, /* not 
INT64_MIN */
+        {{INT64_MIN, 2},      {-2, 1},              { INT64_MAX, 1}},
+        {{INT64_MIN, 2},      { 0, 1},              {0, 1}},
+        {{INT64_MAX >> 8, 1}, {INT64_MAX >> 8, 1},  {INT64_MAX, 1}},
+        {{1, INT64_MAX >> 8}, {1, INT64_MAX >> 8},  {0, 1}},
+        {{1, 1},              {0, 0},               {0, 0}},
+        {{0, 1},              {0, 0},               {0, 0}},
+    };
+
+    for (i = 0; i < FF_ARRAY_ELEMS(unit_mul_q64); i++) {
+        for (int c = 0; c < 2; c++) { /* test commutativity */
+            AVRational64 a = unit_mul_q64[i][c ? 1 : 0];
+            AVRational64 b = unit_mul_q64[i][c ? 0 : 1];
+            AVRational64 c = unit_mul_q64[i][2];
+            AVRational64 r = ff_mul_q64(a, b);
+            if (r.num != c.num || r.den != c.den) {
+                av_log(NULL, AV_LOG_ERROR, "%lld/%lld * %lld/%lld = %lld/%lld, 
expected %lld/%lld\n",
+                       (long long) a.num, (long long) a.den,
+                       (long long) b.num, (long long) b.den,
+                       (long long) r.num, (long long) r.den,
+                       (long long) c.num, (long long) c.den);
+            }
+        }
+    }
+
+    static const AVRational64 unit_add_q64[][3] = {
+        {{INT64_MAX, 1},      { 2, 2},            { INT64_MAX, 1}},
+        {{INT64_MAX, 1},      {-2, 2},            { INT64_MAX - 1, 1}},
+        {{INT64_MAX, 1},      { 0, 2},            { INT64_MAX, 1}},
+        {{INT64_MIN, 1},      { 2, 2},            {-INT64_MAX, 1}},
+        {{INT64_MIN, 1},      {-2, 2},            {-INT64_MAX, 1}},
+        {{INT64_MIN, 1},      { 0, 2},            {-INT64_MAX, 1}},
+        {{INT64_MAX - 10, 1}, {20, 1},            { INT64_MAX, 1}},
+        {{2, INT64_MAX},      {2, INT64_MAX},     {4, INT64_MAX}},
+        {{1, 1},              {0, 0},             {0, 0}},
+        {{0, 1},              {0, 0},             {0, 0}},
+    };
+
+    for (i = 0; i < FF_ARRAY_ELEMS(unit_add_q64); i++) {
+        for (int c = 0; c < 2; c++) { /* test commutativity */
+            AVRational64 a = unit_add_q64[i][c ? 1 : 0];
+            AVRational64 b = unit_add_q64[i][c ? 0 : 1];
+            AVRational64 c = unit_add_q64[i][2];
+            AVRational64 r = ff_add_q64(a, b);
+            if (r.num != c.num || r.den != c.den) {
+                av_log(NULL, AV_LOG_ERROR, "%lld/%lld + %lld/%lld = %lld/%lld, 
expected %lld/%lld\n",
+                       (long long) a.num, (long long) a.den,
+                       (long long) b.num, (long long) b.den,
+                       (long long) r.num, (long long) r.den,
+                       (long long) c.num, (long long) c.den);
+            }
+        }
+    }
+
+    return 0;
+}
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to