FFmpeg
mathematics.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include <inttypes.h>
20 #include <stdint.h>
21 #include <stdio.h>
22 
23 #include "libavutil/avutil.h"
24 #include "libavutil/macros.h"
25 #include "libavutil/mathematics.h"
26 #include "libavutil/rational.h"
27 
28 int main(void)
29 {
30  int64_t last;
31 
32  /* av_gcd */
33  printf("Testing av_gcd()\n");
34  static const struct { int64_t a, b, expected; } gcd_tests[] = {
35  { 0, 0, 0 },
36  { 1, 0, 1 },
37  { 0, 1, 1 },
38  { 6, 4, 2 },
39  { 12, 8, 4 },
40  { 17, 13, 1 },
41  { 100, 75, 25 },
42  { -6, 4, 2 },
43  { 6, -4, 2 },
44  };
45  for (int i = 0; i < FF_ARRAY_ELEMS(gcd_tests); i++)
46  printf("gcd(%"PRId64", %"PRId64") = %"PRId64" %s\n",
47  gcd_tests[i].a, gcd_tests[i].b,
48  av_gcd(gcd_tests[i].a, gcd_tests[i].b),
49  av_gcd(gcd_tests[i].a, gcd_tests[i].b) == gcd_tests[i].expected ? "OK" : "FAIL");
50 
51  /* av_rescale */
52  printf("\nTesting av_rescale()\n");
53  printf("rescale(6, 3, 2) = %"PRId64"\n", av_rescale(6, 3, 2));
54  printf("rescale(0, 3, 2) = %"PRId64"\n", av_rescale(0, 3, 2));
55  printf("rescale(1, 1, 1) = %"PRId64"\n", av_rescale(1, 1, 1));
56  printf("rescale(-6, 3, 2) = %"PRId64"\n", av_rescale(-6, 3, 2));
57  printf("rescale(90000, 1, 90000) = %"PRId64"\n", av_rescale(90000, 1, 90000));
58 
59  /* av_rescale_rnd with different rounding modes */
60  printf("\nTesting av_rescale_rnd()\n");
61  static const struct {
62  int64_t a, b, c;
63  enum AVRounding rnd;
64  int64_t expected;
65  } rnd_tests[] = {
66  { 7, 1, 2, AV_ROUND_ZERO, 3 },
67  { 7, 1, 2, AV_ROUND_INF, 4 },
68  { 7, 1, 2, AV_ROUND_DOWN, 3 },
69  { 7, 1, 2, AV_ROUND_UP, 4 },
70  { 7, 1, 2, AV_ROUND_NEAR_INF, 4 },
71  { -7, 1, 2, AV_ROUND_ZERO, -3 },
72  { -7, 1, 2, AV_ROUND_INF, -4 },
73  { -7, 1, 2, AV_ROUND_DOWN, -4 },
74  { -7, 1, 2, AV_ROUND_UP, -3 },
75  { 6, 1, 2, AV_ROUND_NEAR_INF, 3 },
76  };
77  for (int i = 0; i < FF_ARRAY_ELEMS(rnd_tests); i++) {
78  int64_t r = av_rescale_rnd(rnd_tests[i].a, rnd_tests[i].b,
79  rnd_tests[i].c, rnd_tests[i].rnd);
80  printf("rescale_rnd(%"PRId64", %"PRId64", %"PRId64", %d) = %"PRId64" %s\n",
81  rnd_tests[i].a, rnd_tests[i].b, rnd_tests[i].c,
82  rnd_tests[i].rnd, r,
83  r == rnd_tests[i].expected ? "OK" : "FAIL");
84  }
85 
86  /* AV_ROUND_PASS_MINMAX */
87  printf("\nTesting AV_ROUND_PASS_MINMAX\n");
88  printf("INT64_MIN passthrough: %s\n",
89  av_rescale_rnd(INT64_MIN, 1, 2,
90  AV_ROUND_UP | AV_ROUND_PASS_MINMAX) == INT64_MIN ? "OK" : "FAIL");
91  printf("INT64_MAX passthrough: %s\n",
92  av_rescale_rnd(INT64_MAX, 1, 2,
93  AV_ROUND_UP | AV_ROUND_PASS_MINMAX) == INT64_MAX ? "OK" : "FAIL");
94  printf("normal with PASS_MINMAX: %"PRId64"\n",
96 
97  /* large value rescale (exercises 128-bit multiply path) */
98  printf("\nTesting large value rescale\n");
99  printf("rescale(INT64_MAX/2, 2, 1) = %"PRId64"\n",
100  av_rescale_rnd(INT64_MAX / 2, 2, 1, AV_ROUND_ZERO));
101  printf("rescale(1000000007, 1000000009, 1000000007) = %"PRId64"\n",
102  av_rescale(1000000007LL, 1000000009LL, 1000000007LL));
103  /* b and c both > INT_MAX triggers 128-bit multiply */
104  printf("rescale_rnd(10, INT_MAX+1, INT_MAX+1, ZERO) = %"PRId64"\n",
105  av_rescale_rnd(10, (int64_t)INT32_MAX + 1, (int64_t)INT32_MAX + 1, AV_ROUND_ZERO));
106  printf("rescale_rnd(7, 3000000000, 2000000000, NEAR_INF) = %"PRId64"\n",
107  av_rescale_rnd(7, 3000000000LL, 2000000000LL, AV_ROUND_NEAR_INF));
108 
109  /* av_rescale_q */
110  printf("\nTesting av_rescale_q()\n");
111  printf("rescale_q(90000, 1/90000, 1/1000) = %"PRId64"\n",
112  av_rescale_q(90000, (AVRational){1, 90000}, (AVRational){1, 1000}));
113  printf("rescale_q(48000, 1/48000, 1/44100) = %"PRId64"\n",
114  av_rescale_q(48000, (AVRational){1, 48000}, (AVRational){1, 44100}));
115 
116  /* av_compare_ts */
117  printf("\nTesting av_compare_ts()\n");
118  printf("compare(1, 1/1, 1, 1/1) = %d\n",
119  av_compare_ts(1, (AVRational){1, 1}, 1, (AVRational){1, 1}));
120  printf("compare(1, 1/1, 2, 1/1) = %d\n",
121  av_compare_ts(1, (AVRational){1, 1}, 2, (AVRational){1, 1}));
122  printf("compare(2, 1/1, 1, 1/1) = %d\n",
123  av_compare_ts(2, (AVRational){1, 1}, 1, (AVRational){1, 1}));
124  printf("compare(1, 1/1000, 1, 1/90000) = %d\n",
125  av_compare_ts(1, (AVRational){1, 1000}, 1, (AVRational){1, 90000}));
126  /* large values trigger rescale-based comparison path */
127  printf("compare(INT64_MAX/2, 1/1, INT64_MAX/3, 1/1) = %d\n",
128  av_compare_ts(INT64_MAX / 2, (AVRational){1, 1},
129  INT64_MAX / 3, (AVRational){1, 1}));
130 
131  /* av_compare_mod */
132  printf("\nTesting av_compare_mod()\n");
133  printf("compare_mod(3, 1, 16) = %"PRId64"\n", av_compare_mod(3, 1, 16));
134  printf("compare_mod(1, 3, 16) = %"PRId64"\n", av_compare_mod(1, 3, 16));
135  printf("compare_mod(5, 5, 16) = %"PRId64"\n", av_compare_mod(5, 5, 16));
136 
137  /* av_rescale_delta */
138  printf("\nTesting av_rescale_delta()\n");
139  last = AV_NOPTS_VALUE;
140  for (int i = 0; i < 4; i++)
141  printf("delta step %d: %"PRId64"\n", i,
142  av_rescale_delta((AVRational){1, 48000}, i * 1024,
143  (AVRational){1, 48000}, 1024,
144  &last, (AVRational){1, 44100}));
145  /* trigger clip-based path: use different in_tb and fs_tb */
146  last = AV_NOPTS_VALUE;
147  for (int i = 0; i < 4; i++)
148  printf("delta clip %d: %"PRId64"\n", i,
149  av_rescale_delta((AVRational){1, 44100}, i * 940,
150  (AVRational){1, 48000}, 1024,
151  &last, (AVRational){1, 90000}));
152 
153  /* av_add_stable */
154  printf("\nTesting av_add_stable()\n");
155  printf("add_stable(0, 1/1, 1/1000, 500) = %"PRId64"\n",
156  av_add_stable((AVRational){1, 1}, 0, (AVRational){1, 1000}, 500));
157  printf("add_stable(1000, 1/90000, 1/48000, 1024) = %"PRId64"\n",
158  av_add_stable((AVRational){1, 90000}, 1000, (AVRational){1, 48000}, 1024));
159  /* non-exact division path (m >= d, general case) */
160  printf("add_stable(0, 1/48000, 1/90000, 90000) = %"PRId64"\n",
161  av_add_stable((AVRational){1, 48000}, 0, (AVRational){1, 90000}, 90000));
162  printf("add_stable(100, 1/1000, 1/90000, 3000) = %"PRId64"\n",
163  av_add_stable((AVRational){1, 1000}, 100, (AVRational){1, 90000}, 3000));
164  /* repeated addition: verify no rounding error accumulation */
165  {
166  int64_t ts = 0;
167  for (int i = 0; i < 10000; i++)
168  ts = av_add_stable((AVRational){1, 48000}, ts, (AVRational){1, 48000}, 1024);
169  printf("add_stable 10000x1024 at 1/48000: %"PRId64" (expected %"PRId64") %s\n",
170  ts, (int64_t)10000 * 1024,
171  ts == (int64_t)10000 * 1024 ? "OK" : "FAIL");
172  }
173 
174  return 0;
175 }
AV_ROUND_UP
@ AV_ROUND_UP
Round toward +infinity.
Definition: mathematics.h:134
r
const char * r
Definition: vf_curves.c:127
printf
__device__ int printf(const char *,...)
av_compare_ts
int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b)
Compare two timestamps each in its own time base.
Definition: mathematics.c:147
av_add_stable
int64_t av_add_stable(AVRational ts_tb, int64_t ts, AVRational inc_tb, int64_t inc)
Add a value to a timestamp.
Definition: mathematics.c:191
rational.h
int64_t
long long int64_t
Definition: coverity.c:34
b
#define b
Definition: input.c:42
AV_ROUND_ZERO
@ AV_ROUND_ZERO
Round toward zero.
Definition: mathematics.h:131
AVRounding
AVRounding
Rounding methods.
Definition: mathematics.h:130
mathematics.h
av_gcd
int64_t av_gcd(int64_t a, int64_t b)
Compute the greatest common divisor of two integer operands.
Definition: mathematics.c:37
macros.h
rnd
#define rnd()
Definition: checkasm.h:207
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_rescale_q
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
AV_ROUND_NEAR_INF
@ AV_ROUND_NEAR_INF
Round to nearest and halfway cases away from zero.
Definition: mathematics.h:135
AV_ROUND_PASS_MINMAX
@ AV_ROUND_PASS_MINMAX
Flag telling rescaling functions to pass INT64_MIN/MAX through unchanged, avoiding special cases for ...
Definition: mathematics.h:159
av_rescale_delta
int64_t av_rescale_delta(AVRational in_tb, int64_t in_ts, AVRational fs_tb, int duration, int64_t *last, AVRational out_tb)
Rescale a timestamp while preserving known durations.
Definition: mathematics.c:168
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
AV_ROUND_DOWN
@ AV_ROUND_DOWN
Round toward -infinity.
Definition: mathematics.h:133
av_rescale_rnd
int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding rnd)
Rescale a 64-bit integer with specified rounding.
Definition: mathematics.c:58
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:247
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
AV_ROUND_INF
@ AV_ROUND_INF
Round away from zero.
Definition: mathematics.h:132
av_rescale
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
Rescale a 64-bit integer with rounding to nearest.
Definition: mathematics.c:129
av_compare_mod
int64_t av_compare_mod(uint64_t a, uint64_t b, uint64_t mod)
Compare the remainders of two integer operands divided by a common divisor.
Definition: mathematics.c:160
main
int main(void)
Definition: mathematics.c:28
avutil.h