FFmpeg源码:av_gcd函数分析

news2024/11/14 15:31:21

一、引言

公约数,是一个能同时整除几个整数的数。如果一个整数同时是几个整数的约数,称这个整数为它们的“公约数”;公约数中最大的称为最大公约数。对任意的若干个正整数,1总是它们的公约数。
公约数与公倍数相反,就是既是A的约数同时也是B的约数的数,12和15的公约数有1,3,最大公约数就是3。再举个例子,30和40,它们的公约数有1,2,5,10,最大公约数是10。FFmpeg源码中使用av_gcd函数来计算两个整数的最大公约数。

二、av_gcd函数的声明

av_gcd函数声明在FFmpeg源码(本文演示用的FFmpeg源码版本为7.0.1)的头文件libavutil/mathematics.h中:

/**
 * Compute the greatest common divisor of two integer operands.
 *
 * @param a Operand
 * @param b Operand
 * @return GCD of a and b up to sign; if a >= 0 and b >= 0, return value is >= 0;
 * if a == 0 and b == 0, returns 0.
 */
int64_t av_const av_gcd(int64_t a, int64_t b);

该函数作用是:计算两个整数操作数的最大公约数。

形参a:输入型参数。第一个整数操作数。

形参b:输入型参数。第二个整数操作数。

返回值:两个整数操作数a和b的最大公约数。如果a和b都不小于0,返回值不小于0;如果a和b都等于0,返回值等于0(0既不是质数也不是合数 且它没有任何约数,最好避免形参值为0的情况)。

三、av_gcd函数的定义

av_gcd函数定义在FFmpeg源码的源文件libavutil/mathematics.c中:

/* Stein's binary GCD algorithm:
 * https://en.wikipedia.org/wiki/Binary_GCD_algorithm */
int64_t av_gcd(int64_t a, int64_t b) {
    int za, zb, k;
    int64_t u, v;
    if (a == 0)
        return b;
    if (b == 0)
        return a;
    za = ff_ctzll(a);
    zb = ff_ctzll(b);
    k  = FFMIN(za, zb);
    u = llabs(a >> za);
    v = llabs(b >> zb);
    while (u != v) {
        if (u > v)
            FFSWAP(int64_t, v, u);
        v -= u;
        v >>= ff_ctzll(v);
    }
    return (uint64_t)u << k;
}

该函数内部使用了二进制GCD算法寻找两个整数操作数的最大公约数。二进制GCD算法(binary GCD algorithm),也被称为Stein's算法或二进制欧氏算法(binary Euclidean algorithm),是一种计算两个非负整数的最大公约数(GCD)的算法。Stein's算法比传统的Euclidean算法使用更简单的算术运算,它用算术移位、比较和减法代替除法(用移位的方法得到代码比调用乘除法子程序生成的代码效率高。实际上,只要是乘以或除以一个整数,均可以想办法用移位的方法得到结果。整数除法是整数运算中最慢的,所以应该尽可能避免)。

虽然这种现代形式的算法是由物理学家和程序员Josef Stein在1967年首次发表的,但它在公元前2世纪,即古代中国被人们所知。

四、编写av_gcd函数的使用例子

编写测试例子main.c,在Ubuntu中使用9.4.0版本的gcc编译通过:

#include <stdio.h>
#include <stdint.h>
#include <limits.h>
#include <features.h>


#ifdef __GNUC__
#    define AV_GCC_VERSION_AT_LEAST(x,y) (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y))
#    define AV_GCC_VERSION_AT_MOST(x,y)  (__GNUC__ < (x) || __GNUC__ == (x) && __GNUC_MINOR__ <= (y))
#else
#    define AV_GCC_VERSION_AT_LEAST(x,y) 0
#    define AV_GCC_VERSION_AT_MOST(x,y)  0
#endif


#ifndef av_always_inline
#if AV_GCC_VERSION_AT_LEAST(3,1)
#    define av_always_inline __attribute__((always_inline)) inline
#elif defined(_MSC_VER)
#    define av_always_inline __forceinline
#else
#    define av_always_inline inline
#endif
#endif


#if AV_GCC_VERSION_AT_LEAST(2,6) || defined(__clang__)
#    define av_const __attribute__((const))
#else
#    define av_const
#endif


#define FFMIN(a,b) ((a) > (b) ? (b) : (a))
#define FFSWAP(type,a,b) do{type SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0)


#ifdef __USE_ISOC99
__extension__ extern long long int llabs (long long int __x)
     __THROW __attribute__ ((__const__)) __wur;
#endif


#ifndef ff_ctzll
#define ff_ctzll ff_ctzll_c
/* We use the De-Bruijn method outlined in:
 * http://supertech.csail.mit.edu/papers/debruijn.pdf. */
static av_always_inline av_const int ff_ctzll_c(long long v)
{
    static const uint8_t debruijn_ctz64[64] = {
        0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28,
        62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11,
        63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
        51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12
    };
    return debruijn_ctz64[(uint64_t)((v & -v) * 0x022FDD63CC95386DU) >> 58];
}
#endif




int64_t av_gcd(int64_t a, int64_t b) {
    int za, zb, k;
    int64_t u, v;
    if (a == 0)
        return b;
    if (b == 0)
        return a;
    za = ff_ctzll(a);
    zb = ff_ctzll(b);
    k  = FFMIN(za, zb);
    u = llabs(a >> za);
    v = llabs(b >> zb);
    while (u != v) {
        if (u > v)
            FFSWAP(int64_t, v, u);
        v -= u;
        v >>= ff_ctzll(v);
    }
    return (uint64_t)u << k;
}


int main()
{
    int64_t a = 12;
    int64_t b = 15;
    printf("av_gcd(%ld, %ld): %ld\n", a, b, av_gcd(a, b));

    int64_t c = 30;
    int64_t d = 40;
    printf("av_gcd(%ld, %ld): %ld\n", c, d, av_gcd(c, d));

    int64_t e = 0;
    int64_t f = 5;
    printf("av_gcd(%ld, %ld): %ld\n", e, f, av_gcd(e, f));

    int64_t g = 0;
    int64_t h = 0;
    printf("av_gcd(%ld, %ld): %ld\n", g, h, av_gcd(g, h));

    return 0;
}

输出如下:

五、参考

维基百科:《Binary GCD algorithm》

百度百科:《公约数》

《C语言如何用移位来解决乘除法问题》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1974257.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据科学 - 数据预处理 (数据清洗,结构化数据)

1. 前言 数据清洗与结构化数据在数据分析和机器学习项目中扮演着至关重要的角色。随着大数据时代的到来&#xff0c;数据的质量、准确性和可用性成为决定项目成功与否的关键因素。 数据清洗提高数据质量&#xff0c;保证数据集的一致性&#xff1b;促进数据分析与挖掘&#xf…

剪映课+短视频综合课程:抖音底层算法

课程内容&#xff1a; 01-直播回放精选&#xff1a;2024抖音4_5月新知识.mp4 02-直播回放&#xff1a;核心算法讲解.mp4 03-直播回放&#xff1a;推流人群顺序和赛马依据.mp4 04-直播回放&#xff1a;从0-1kw推流细节.mp4 05-直播回放&#xff1a;抖加投放①.mp4 06-直播回…

调试模式下如何调试看门狗?

大家在调试GD32 MCU系统的时候&#xff0c;若开了看门狗外设&#xff0c;是否会碰到进入调试模式看门狗就会咬狗造成无法调试的问题&#xff1f; 碰到这种情况&#xff0c;一般是将看门狗关闭&#xff0c;然后再进行调试&#xff0c;但这个时候看门狗外设就无法工作了&#xf…

SSH远程服务器MobaXterm PuTTY XShell Tabby

云服务器运维SSH远程工具软件&#xff0c; PuTTY 相比有很大的优势&#xff0c;有兼顾 SSH 和 FTP一体的工具。 SSH的软件&#xff0c;而且有支持 Mac 、Windows 、Linux等跨平台的。 1、XShell 官网地址&#xff1a;https://www.xshell.com/en/xshell/ 免费地址&#xff1a;h…

Kimi居然能做PPT了,是职场人的得力助手还是噱头满满?

你们有没有发现&#xff0c;Kimi最近搞了个大新闻——它竟然能做PPT了&#xff01;是的&#xff0c;你没听错&#xff0c;就是那个让我们又爱又恨的演示PPT。这不&#xff0c;我一看到公告&#xff0c;就激动得像打了鸡血&#xff0c;连夜把市面上其他的几款主流AI PPT产品测了…

数据工程解决的十大数据生命周期问题

欢迎来到雲闪世界。解决关键痛点的明确策略 使用Kandinsky 的AI 生成图像 在本文中&#xff0c;我想解决数据工程师在整个数据生命周期中使用管道时面临的一些最大挑战。了解如何管理数据生命周期是我们不断变化的领域的关键。作为一名数据工程师&#xff0c;我经常处理大量不同…

【Spring Boot】用 Spring Security 实现后台登录及权限认证功能

用 Spring Security 实现后台登录及权限认证功能 1.引入依赖2.创建权限开放的页面3.创建需要权限验证的页面4.配置 Spring Security4.1 配置 Spring MVC4.2 配置 Spring Security 5.创建登录页面6.测试权限 1.引入依赖 使用前需要引入相关依赖&#xff0c;见以下代码&#xff…

DeDe-cms 漏洞

一、文件管理上传shell 我们写一个一句话木马&#xff0c; 上传 点击访问后使用工具连接 连接成功 二、修改模板文件拿shell 找到index.html修改 保存,进行如下操作 更新html 访问返回的地址 拿工具连接 三、后台任意命令执行拿shell 写入一个木马 添加成功后点击代码 这里是文…

python-鼠标绘画线条程序

闲来无聊简单编写了一个绘图小程序。 主要思路 主要是基于Python中的内置模块turtle编写的&#xff0c;简单扩展了一下&#xff0c;通过绑定事件能够达到鼠标绘制、删除、存储已经绘制图案的线条这几个功能。 路径结构 -draw- define.py- main.py- myturtle.py使用 点住鼠…

zabbix7.0TLS-01-部署

文章目录 1 介绍1.1 架构1.2 主要概念和名词1.3 最新 7.0 TLS 版本的部分新特性更灵活的资源发现和管理 2 官方部署指导地址3 在 Rocky Linux 9 上安装 zabbix3.1 安装软件包3.2 创建初始化数据库3.3 配置zabbix-server3.4 启动Zabbix server和agent进程3.5 默认监听端口3.6 访…

电脑新加的硬盘如何分区?新加硬盘分区选MBR还是GPT

最近有网友问我,电脑新加的硬盘如何分区?电脑新加的硬盘分区选MBR还是GPT要看引导模式采用uefi还是传统的legacy模式&#xff0c;如果采用的是uefi引导模式&#xff0c;分区类型对应的就是gpt分区(guid)&#xff0c;如果引导模式采用的是legacy&#xff0c;对应的分区类型为mb…

springboot专家门诊预约管理平台-计算机毕业设计源码79775

摘要 随着互联网技术的快速发展&#xff0c;医疗健康领域数字化需求日益增长&#xff0c;专家门诊预约管理平台应运而生。本研究基于Spring Boot框架开发了一款专家门诊预约管理平台。该平台涵盖了患者用户、专家用户和管理员三个角色&#xff0c;实现了患者的预约、评价、信息…

Java:进程和线程

文章目录 进程线程的概念和区别总结如何创建线程1.继承Thread重写run2.实现Runnable重写run3.继承Thread重写run,通过匿名内部类来实现4. 实现Runnable重写run,通过匿名内部类来实现5.基于lambda表达式来创建 虚拟线程 并发编程: 通过写特殊的代码&#xff0c;把多个CPU核心都利…

C# OpenCvSharp 打开4K高清摄像头

一、前言 整了个1200w像素的usb摄像头&#xff0c;使用 OpenCvSharp读取&#xff0c;读取和设置分辨率代码耗时居然10几秒&#xff0c;查询资料发现&#xff0c;必须对VideoCapture进行设置&#xff0c;使用DSHOW模式打开&#xff0c;并且设置分辨率代码下必须增加 指定MJPG编码…

php的mysql操作可实现简单登录功能

文章目录 1. 表单和请求(1) 表单操作(2) 网络请求(3) $_REQUEST超全局变量 2. mysql数据库操作1) mysqli连接操作2) 操作数据库3) 预处理语句4) pdo操作数据库5) 创建连接并执行查询语句 1. 表单和请求 主要使用到**$_GET** 和 $_POST这两个超全局变量,分别对应两种请求 (1) …

【2024蓝桥杯/C++/B组/小球反弹】

题目 分析 Sx 2 * k1 * x; Sy 2 * k2 * y; &#xff08;其中k1, k2为整数&#xff09; Vx * t Sx; Vy * t Sy; k1 / k2 (15 * y) / (17 * x)&#xff1b; 目标1&#xff1a;根据k1与k2的关系&#xff0c;找出一组最小整数组&#xff08;k1, k2&#xff09;&#xff…

北京崇文门中医院贾英才主任解读头晕:症状与根源

头晕是一种常见的症状&#xff0c;可能由多种原因引起。为了更深入地了解头晕这一症状&#xff0c;我们有幸邀请到了北京崇文门中医院的贾英才主任&#xff0c;听听他对于头晕的见解。 北京崇文门中医院贾英才主任指出&#xff0c;头晕并非一种单一的疾病&#xff0c;而是许多潜…

鉴权-RBAC模型

文章目录 1.技术选型1.网址2.Sa-Token介绍3.[Sa-Token 功能一览](https://sa-token.cc/doc.html#/?idsa-token-功能一览) 2.鉴权数据模型设计1.数据模型图2.SQL1.用户信息表2.角色表3.用户角色表&#xff08;关联表&#xff09;4.权限表5.角色权限表&#xff08;关联表&#x…

1518.换水问题

1.题目描述 超市正在促销&#xff0c;你可以用 numExchange 个空水瓶从超市兑换一瓶水。最开始&#xff0c;你一共购入了 numBottles 瓶水。 如果喝掉了水瓶中的水&#xff0c;那么水瓶就会变成空的。 给你两个整数 numBottles 和 numExchange &#xff0c;返回你 最多 可以喝到…

辩论赛评委依据什么标准进行评分呢

在辩论赛中&#xff0c;评委依据什么标准进行对参赛个人和团队进行评分呢&#xff1f;下面对这两部分介绍一些常用评分标准。 一、 个人评分标准 语言表达 1、普通话标准、语速适中&#xff1b; 2、语调平仄合理&#xff1b; 3、口头、肢体语言和谐&#xff1b; 4、修辞得当、…