FFmpeg
Loading...
Searching...
No Matches
rational64.c
Go to the documentation of this file.
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
34static av_int128 gcd128(av_int128 a, av_int128 b)
35{
36 while (av_test128(b)) {
37 av_int128 tmp = b;
38 b = av_mod128(a, b);
39 a = tmp;
40 }
41 return a;
42}
43
44static AVRational64 reduce64(av_int128 num, av_int128 den)
45{
46 const av_int128 zero = av_to128i(0);
47 const av_int128 max = av_to128i(INT64_MAX);
48 const int num_sign = av_cmp128(num, zero) < 0;
49 const int den_sign = av_cmp128(den, zero) < 0;
50 if (num_sign)
51 num = av_sub128(zero, num);
52 if (den_sign)
53 den = av_sub128(zero, den);
54
55 const av_int128 gcd = gcd128(num, den);
56 if (av_test128(gcd)) {
57 num = av_div128(num, gcd);
58 den = av_div128(den, gcd);
59 }
60
61 av_uint128 a0n = av_to128u(0), a0d = av_to128u(1);
62 av_uint128 a1n = av_to128u(1), a1d = av_to128u(0);
63 if (av_cmp128(num, max) <= 0 && av_cmp128(den, max) <= 0) {
64 a1n = num;
65 a1d = den;
66 goto done;
67 }
68
69 while (av_test128(den)) {
70 av_int128 x = av_div128(num, den);
71 av_int128 next_den = av_sub128(num, av_mul128(den, x));
72 av_uint128 a2n = av_add128(av_mul128(x, a1n), a0n);
73 av_uint128 a2d = av_add128(av_mul128(x, a1d), a0d);
74
75 if (av_cmp128(a2n, max) > 0 || av_cmp128(a2d, max) > 0) {
76 if (av_test128(a1n))
77 x = av_div128(av_sub128(max, a0n), a1n);
78 if (av_test128(a1d)) {
79 av_uint128 tmp = av_div128(av_sub128(max, a0d), a1d);
80 x = av_min128(x, tmp);
81 }
82
83 av_uint128 x1d = av_mul128(x, a1d);
84 av_uint128 a = av_mul128(den, av_add128(av_add128(x1d, x1d), a0d));
85 av_uint128 b = av_mul128(num, a1d);
86 if (av_cmp128(a, b) > 0) {
87 a1n = av_add128(av_mul128(x, a1n), a0n);
88 a1d = av_add128(x1d, a0d);
89 }
90 break;
91 }
92
93 a0n = a1n;
94 a0d = a1d;
95 a1n = a2n;
96 a1d = a2d;
97 num = den;
98 den = next_den;
99 }
100
101done:;
102 AVRational64 res = { av_from128i(a1n), av_from128i(a1d) };
103 if (num_sign ^ den_sign)
104 res.num = -res.num;
105 return res;
106}
107
109{
110 const av_int128 p = av_mul128(av_to128i(a.num), av_to128i(b.den));
111 const av_int128 q = av_mul128(av_to128i(b.num), av_to128i(a.den));
112 const int test = av_cmp128(p, q);
113
114 if (test)
115 return (a.den < 0) ^ (b.den < 0) ? -test : test;
116 else if (b.den && a.den)
117 return 0;
118 else if (a.num && b.num)
119 return (a.num >> 63) - (b.num >> 63);
120 else
121 return INT_MIN;
122}
123
129
134
140
#define max(a, b)
AVRational64 av_div_q64(AVRational64 b, AVRational64 c)
Divide one 64-bit rational by another.
Definition rational64.c:130
AVRational64 av_mul_q64(AVRational64 b, AVRational64 c)
Multiply two 64-bit rationals.
Definition rational64.c:124
int av_cmp_q64(AVRational64 a, AVRational64 b)
Compare two 64-bit rationals.
Definition rational64.c:108
static av_always_inline AVRational64 av_inv_q64(AVRational64 q)
Invert a 64-bit rational.
Definition rational64.h:131
AVRational64 av_add_q64(AVRational64 b, AVRational64 c)
Add two 64-bit rationals.
Definition rational64.c:135
AVRational64 av_sub_q64(AVRational64 b, AVRational64 c)
Subtract one 64-bit rational from another.
Definition rational64.c:141
int a
#define b
Definition input.c:43
128-bit integers, falling back to integer.h if necessary
#define av_mul128(a, b)
Definition int128.h:73
#define av_test128(a)
Definition int128.h:84
#define av_min128(a, b)
Definition int128.h:76
#define av_cmp128(a, b)
Definition int128.h:75
#define av_sub128(a, b)
Definition int128.h:72
static av_always_inline av_uint128 av_to128u(uint64_t a)
Definition int128.h:86
#define av_from128i(a)
Definition int128.h:82
#define av_add128(a, b)
Definition int128.h:71
#define av_mod128(a, b)
Definition int128.h:79
#define av_to128i(a)
Definition int128.h:81
#define av_div128(a, b)
Definition int128.h:74
static int zero(InterplayACMContext *s, unsigned ind, unsigned col)
static AVRational64 reduce64(av_int128 num, av_int128 den)
Definition rational64.c:44
static av_int128 gcd128(av_int128 a, av_int128 b)
Definition rational64.c:34
64-bit extension of AVRational.
64-bit Rational number (pair of numerator and denominator).
Definition rational64.h:52
int64_t num
Numerator.
Definition rational64.h:53
Definition idctdsp.c:35
static uint8_t tmp[40]
Definition aes_ctr.c:52
static double c[64]