我正在寻找64位划分算法,但不依赖于GPL许可证。
我在Hacker Delight书中找到了以下代码(图9-5):
unsigned long long udivdi3(unsigned long long u,
unsigned long long v)
if (v >> 32 == 0) {
if (u >> 32 < v)
return DIVU(u, v) & 0xFFFFFFFF;
else {
.....
}
}
问题在于“ return DIVU”计算得出的64/32除法数,因此不是我想要的。 该怎么办?
答案 0 :(得分:1)
这是编译器-rt存在的原因。 __udivdi3
最终调用中的Here is the C implementation,但请注意,还使用了特定于平台的程序集版本,例如在x86上。
但是,实际上,避免libgcc是没有意义的-它更成熟了,支持更多平台,并且由于运行时库异常,GPL在很大程度上已经放荡了-而且您绝对不应该为以下内容修改上游源这样,您无需提供任何修改的源代码。
答案 1 :(得分:0)
在Linux内核代码中执行64位分割似乎很棘手。我不确定您是否遇到了同样的问题,但这就是我所知道的。
看来指令集不能完全处理64位算术运算。看起来gcc发出了对辅助函数的调用。例如,在ARM上,如果我写
t /= 86400;
其中t
是64位变量,我的内核构建失败,并带有“ undefined reference to '__aeabi_ldivmod'
”。显然,内核没有链接到存在诸如__aeabi_ldivmod
之类的函数的完整C库。
解决方案似乎是改为调用do_div
。 do_div
实际上不是一个函数;它是在特定于体系结构的头文件中声明的宏。 (对于ARM,它在arch/arm/include/asm/div64.h
中。x86有一个类似的文件。)
解决方案是将t /= 86400
替换为
(void)do_div(t, 86400);
do_div
将其第一个参数除以第二个参数,然后返回余数(在此示例中我将忽略)。
div64.h
中有一条很大的评论,告诉您有关do_div
以及如何使用它的更多信息。