FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libswscale/rational64.c
Date: 2026-08-26 01:27:24
Exec Total Coverage
Lines: 69 76 90.8%
Functions: 5 7 71.4%
Branches: 41 50 82.0%

Line Branch Exec Source
1 /*
2 * 64-bit rational numbers
3 * Copyright (c) 2025 Niklas Haas
4 * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 /**
24 * @file
25 * 64-bit rational numbers
26 * @author Niklas Haas
27 */
28
29 #include <limits.h>
30
31 #include "libavutil/int128.h"
32 #include "rational64.h"
33
34 1728134216 static av_int128 gcd128(av_int128 a, av_int128 b)
35 {
36
2/2
✓ Branch 0 taken 5108610918 times.
✓ Branch 1 taken 1728134216 times.
6836745134 while (av_test128(b)) {
37 5108610918 av_int128 tmp = b;
38 5108610918 b = av_mod128(a, b);
39 5108610918 a = tmp;
40 }
41 1728134216 return a;
42 }
43
44 1728134216 static AVRational64 reduce64(av_int128 num, av_int128 den)
45 {
46 1728134216 const av_int128 zero = av_to128i(0);
47 1728134216 const av_int128 max = av_to128i(INT64_MAX);
48 1728134216 const int num_sign = av_cmp128(num, zero) < 0;
49 1728134216 const int den_sign = av_cmp128(den, zero) < 0;
50
2/2
✓ Branch 0 taken 121690560 times.
✓ Branch 1 taken 1606443656 times.
1728134216 if (num_sign)
51 121690560 num = av_sub128(zero, num);
52
2/2
✓ Branch 0 taken 66262 times.
✓ Branch 1 taken 1728067954 times.
1728134216 if (den_sign)
53 66262 den = av_sub128(zero, den);
54
55 1728134216 const av_int128 gcd = gcd128(num, den);
56
2/2
✓ Branch 0 taken 1496227326 times.
✓ Branch 1 taken 231906890 times.
1728134216 if (av_test128(gcd)) {
57 1496227326 num = av_div128(num, gcd);
58 1496227326 den = av_div128(den, gcd);
59 }
60
61 1728134216 av_uint128 a0n = av_to128u(0), a0d = av_to128u(1);
62 1728134216 av_uint128 a1n = av_to128u(1), a1d = av_to128u(0);
63
6/8
✓ Branch 0 taken 937849 times.
✓ Branch 1 taken 1727196367 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 937849 times.
✓ Branch 4 taken 34186 times.
✓ Branch 5 taken 1727162181 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 34186 times.
1728134216 if (av_cmp128(num, max) <= 0 && av_cmp128(den, max) <= 0) {
64 1727162181 a1n = num;
65 1727162181 a1d = den;
66 1727162181 goto done;
67 }
68
69
1/2
✓ Branch 0 taken 34724380 times.
✗ Branch 1 not taken.
34724380 while (av_test128(den)) {
70 34724380 av_int128 x = av_div128(num, den);
71 34724380 av_int128 next_den = av_sub128(num, av_mul128(den, x));
72 34724380 av_uint128 a2n = av_add128(av_mul128(x, a1n), a0n);
73 34724380 av_uint128 a2d = av_add128(av_mul128(x, a1d), a0d);
74
75
6/8
✓ Branch 0 taken 850550 times.
✓ Branch 1 taken 33873830 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 850550 times.
✓ Branch 4 taken 121485 times.
✓ Branch 5 taken 33752345 times.
✓ Branch 6 taken 121485 times.
✗ Branch 7 not taken.
34724380 if (av_cmp128(a2n, max) > 0 || av_cmp128(a2d, max) > 0) {
76
1/2
✓ Branch 0 taken 972035 times.
✗ Branch 1 not taken.
972035 if (av_test128(a1n))
77 972035 x = av_div128(av_sub128(max, a0n), a1n);
78
1/2
✓ Branch 0 taken 972035 times.
✗ Branch 1 not taken.
972035 if (av_test128(a1d)) {
79 972035 av_uint128 tmp = av_div128(av_sub128(max, a0d), a1d);
80 972035 x = av_min128(x, tmp);
81 }
82
83 972035 av_uint128 x1d = av_mul128(x, a1d);
84 972035 av_uint128 a = av_mul128(den, av_add128(av_add128(x1d, x1d), a0d));
85 972035 av_uint128 b = av_mul128(num, a1d);
86
3/4
✓ Branch 0 taken 222202 times.
✓ Branch 1 taken 749833 times.
✓ Branch 2 taken 222202 times.
✗ Branch 3 not taken.
972035 if (av_cmp128(a, b) > 0) {
87 222202 a1n = av_add128(av_mul128(x, a1n), a0n);
88 222202 a1d = av_add128(x1d, a0d);
89 }
90 972035 break;
91 }
92
93 33752345 a0n = a1n;
94 33752345 a0d = a1d;
95 33752345 a1n = a2n;
96 33752345 a1d = a2d;
97 33752345 num = den;
98 33752345 den = next_den;
99 }
100
101 done:;
102 1728134216 AVRational64 res = { av_from128i(a1n), av_from128i(a1d) };
103
2/2
✓ Branch 0 taken 121741950 times.
✓ Branch 1 taken 1606392266 times.
1728134216 if (num_sign ^ den_sign)
104 121741950 res.num = -res.num;
105 1728134216 return res;
106 }
107
108 730054401 int av_cmp_q64(AVRational64 a, AVRational64 b)
109 {
110 730054401 const av_int128 p = av_mul128(av_to128i(a.num), av_to128i(b.den));
111 730054401 const av_int128 q = av_mul128(av_to128i(b.num), av_to128i(a.den));
112
2/2
✓ Branch 0 taken 401903700 times.
✓ Branch 1 taken 328150701 times.
730054401 const int test = av_cmp128(p, q);
113
114
2/2
✓ Branch 0 taken 465854576 times.
✓ Branch 1 taken 264199825 times.
730054401 if (test)
115
2/2
✓ Branch 0 taken 25813 times.
✓ Branch 1 taken 465828763 times.
465854576 return (a.den < 0) ^ (b.den < 0) ? -test : test;
116
4/4
✓ Branch 0 taken 233087589 times.
✓ Branch 1 taken 31112236 times.
✓ Branch 2 taken 214673928 times.
✓ Branch 3 taken 18413661 times.
264199825 else if (b.den && a.den)
117 214673928 return 0;
118
3/4
✓ Branch 0 taken 12140935 times.
✓ Branch 1 taken 37384962 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12140935 times.
49525897 else if (a.num && b.num)
119 return (a.num >> 63) - (b.num >> 63);
120 else
121 49525897 return INT_MIN;
122 }
123
124 985065996 AVRational64 av_mul_q64(AVRational64 b, AVRational64 c)
125 {
126 1970131992 return reduce64(av_mul128(av_to128i(b.num), av_to128i(c.num)),
127 985065996 av_mul128(av_to128i(b.den), av_to128i(c.den)));
128 }
129
130 AVRational64 av_div_q64(AVRational64 b, AVRational64 c)
131 {
132 return av_mul_q64(b, av_inv_q64(c));
133 }
134
135 743068220 AVRational64 av_add_q64(AVRational64 b, AVRational64 c) {
136 1486136440 return reduce64(av_add128(av_mul128(av_to128i(b.num), av_to128i(c.den)),
137 av_mul128(av_to128i(c.num), av_to128i(b.den))),
138 743068220 av_mul128(av_to128i(b.den), av_to128i(c.den)));
139 }
140
141 AVRational64 av_sub_q64(AVRational64 b, AVRational64 c)
142 {
143 return reduce64(av_sub128(av_mul128(av_to128i(b.num), av_to128i(c.den)),
144 av_mul128(av_to128i(c.num), av_to128i(b.den))),
145 av_mul128(av_to128i(b.den), av_to128i(c.den)));
146 }
147