LAMMP 4.1.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
tiny.c 文件参考
+ tiny.c 的引用(Include)关系图:

浏览源代码.

函数

int lmmp_leading_zeros_ (mp_limb_t x)
 计算一个单精度数(limb)中前导零的个数
 
int lmmp_limb_bits_ (mp_limb_t x)
 计算满足 2^k > x 的最小自然数k
 
int lmmp_limb_popcnt_ (mp_limb_t x)
 计算一个64位无符号整数中1的个数
 
mp_limb_t lmmp_mulh_ (mp_limb_t a, mp_limb_t b)
 计算两个64位无符号整数相乘的高位结果 (a*b)/2^64
 
void lmmp_mullh_ (mp_limb_t a, mp_limb_t b, mp_ptr restrict dst)
 
ulong lmmp_mulmod_ulong_ (ulong a, ulong b, ulong mod, ulongp restrict q)
 
int lmmp_tailing_zeros_ (mp_limb_t x)
 计算一个单精度数(limb)中末尾零的个数
 

函数说明

◆ lmmp_leading_zeros_()

int lmmp_leading_zeros_ ( mp_limb_t  x)

计算一个单精度数(limb)中前导零的个数

参数
x输入的64位无符号整数
返回
前导零的位数(范围:0~64)

在文件 tiny.c35 行定义.

35 {
36 if (x == 0) return 64;
37#ifdef __GNUC__
38 return __builtin_clzll(x);
39#elif _MSC_VER
40 unsigned long index;
41 _BitScanReverse64(&index, x);
42 return 63 - (int)index;
43#else
44 int n = 0;
45 if (x <= 0x00000000FFFFFFFF) { n += 32; x <<= 32; }
46 if (x <= 0x0000FFFFFFFFFFFF) { n += 16; x <<= 16; }
47 if (x <= 0x00FFFFFFFFFFFFFF) { n += 8; x <<= 8; }
48 if (x <= 0x0FFFFFFFFFFFFFFF) { n += 4; x <<= 4; }
49 if (x <= 0x3FFFFFFFFFFFFFFF) { n += 2; x <<= 2; }
50 if (x <= 0x7FFFFFFFFFFFFFFF) { n += 1; x <<= 1; }
51#endif
52}

被这些函数引用 lmmp_bninv_(), lmmp_div_(), lmmp_div_1_(), lmmp_div_2_(), lmmp_inv_(), lmmp_mod_1_(), lmmp_mod_2_(), lmmp_mulmod_ulong_(), lmmp_pow_basecase_(), lmmp_sqrt_(), lmmp_sqrt_newton_(), lmmp_to_str_() , 以及 mont63_R2().

+ 这是这个函数的调用关系图:

◆ lmmp_limb_bits_()

int lmmp_limb_bits_ ( mp_limb_t  x)

计算满足 2^k > x 的最小自然数k

参数
x输入的64位无符号整数
返回
满足条件的最小自然数k

在文件 tiny.c11 行定义.

11 {
12 int k = 0;
13 while (x) {
14 x >>= 1;
15 k++;
16 }
17 return k;
18}
#define k

引用了 k.

被这些函数引用 lmmp_extract_bits_(), lmmp_from_str_(), lmmp_lehmer_extract_(), lmmp_pow_(), lmmp_to_str_() , 以及 lmmp_to_str_len_().

+ 这是这个函数的调用关系图:

◆ lmmp_limb_popcnt_()

int lmmp_limb_popcnt_ ( mp_limb_t  x)

计算一个64位无符号整数中1的个数

参数
x输入的64位无符号整数
返回
1的个数

在文件 tiny.c20 行定义.

20 {
21#ifdef __GNUC__
22 return __builtin_popcountll(x);
23#elif _MSC_VER
24 return (int)__popcnt64(x);
25#else
26 int k = 0;
27 while (x) {
28 k += x & 1;
29 x >>= 1;
30 }
31 return k;
32#endif
33}

引用了 k.

被这些函数引用 lmmp_factorial_size_(), lmmp_multinomial_(), lmmp_nCr_size_(), lmmp_nPr_size_() , 以及 lmmp_pow_().

+ 这是这个函数的调用关系图:

◆ lmmp_mulh_()

mp_limb_t lmmp_mulh_ ( mp_limb_t  a,
mp_limb_t  b 
)

计算两个64位无符号整数相乘的高位结果 (a*b)/2^64

参数
a第一个64位无符号整数
b第二个64位无符号整数
返回
乘积的高64位结果

在文件 tiny.c73 行定义.

73 {
74#if (defined(__GNUC__) || defined(__clang__)) && defined(__SIZEOF_INT128__)
75 __uint128_t t = (__uint128_t)a * (__uint128_t)b;
76 return (mp_limb_t)(t >> 64);
77#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
78 return __umulh(a, b);
79#else
80 uint64_t ah = a >> 32, bh = b >> 32;
81 a = (uint32_t)a, b = (uint32_t)b;
82 uint64_t r0 = a * b, r1 = a * bh, r2 = ah * b, r3 = ah * bh;
83 r3 += (r1 >> 32) + (r2 >> 32);
84 r1 = (uint32_t)r1, r2 = (uint32_t)r2;
85 r1 += r2;
86 r1 += (r0 >> 32);
87 return r3 + (r1 >> 32);
88#endif
89}
uint64_t mp_limb_t
Definition lmmp.h:211
#define r2
#define r1
#define r3
#define r0

引用了 r0, r1, r2 , 以及 r3.

被这些函数引用 lmmp_from_str_len_(), lmmp_to_str_basecase_() , 以及 lmmp_to_str_len_().

+ 这是这个函数的调用关系图:

◆ lmmp_mullh_()

void lmmp_mullh_ ( mp_limb_t  a,
mp_limb_t  b,
mp_ptr restrict  dst 
)

在文件 tiny.c91 行定义.

91 {
92#if (defined(__GNUC__) || defined(__clang__)) && defined(__SIZEOF_INT128__)
93 __uint128_t prod = (__uint128_t)a * b;
94 dst[0] = (mp_limb_t)prod;
95 dst[1] = (mp_limb_t)(prod >> 64);
96#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
97 dst[0] = _umul128(a, b, dst + 1);
98#else
99 uint64_t ah = a >> 32, bh = b >> 32;
100 a = (uint32_t)a, b = (uint32_t)b;
101 uint64_t r0 = a * b, r1 = a * bh, r2 = ah * b, r3 = ah * bh;
102 r3 += (r1 >> 32) + (r2 >> 32);
103 r1 = (uint32_t)r1, r2 = (uint32_t)r2;
104 r1 += r2;
105 r1 += (r0 >> 32);
106 dst[1] = r3 + (r1 >> 32);
107 dst[0] = (r1 << 32) | (uint32_t)r0;
108#endif
109}

引用了 r0, r1, r2 , 以及 r3.

◆ lmmp_mulmod_ulong_()

ulong lmmp_mulmod_ulong_ ( ulong  a,
ulong  b,
ulong  mod,
ulongp restrict  q 
)

在文件 tiny.c111 行定义.

111 {
112 int shl = lmmp_leading_zeros_(mod);
113 mod <<= shl;
114 ulong inv = lmmp_inv_1_(mod);
115 ulong ab[2];
116 ulong r;
117 _umul64to128_(a, b, ab, ab + 1);
118 if (shl > 0)
119 _u128lshl(ab, ab, shl);
120 _udiv_qrnnd_preinv(*q, r, ab[1], ab[0], mod, inv);
121 return r >> shl;
122}
mp_limb_t lmmp_inv_1_(mp_limb_t x)
1阶逆元计算 (inv1)
Definition inv.c:107
static void _umul64to128_(uint64_t a, uint64_t b, uint64_t *low, uint64_t *high)
Definition longlong.h:31
#define _u128lshl(x, y, n)
Definition longlong.h:244
#define _udiv_qrnnd_preinv(q, r, nh, nl, d, di)
Definition longlong.h:424
uint64_t ulong
Definition numth.h:36
int lmmp_leading_zeros_(mp_limb_t x)
计算一个单精度数(limb)中前导零的个数
Definition tiny.c:35

引用了 _u128lshl, _udiv_qrnnd_preinv, _umul64to128_(), lmmp_inv_1_() , 以及 lmmp_leading_zeros_().

+ 函数调用图:

◆ lmmp_tailing_zeros_()

int lmmp_tailing_zeros_ ( mp_limb_t  x)

计算一个单精度数(limb)中末尾零的个数

参数
x输入的64位无符号整数
返回
末尾零的位数(范围:0~64)

在文件 tiny.c54 行定义.

54 {
55 if (x == 0) return 64;
56#ifdef __GNUC__
57 return __builtin_ctzll(x);
58#elif _MSC_VER
59 unsigned long index;
60 _BitScanForward64(&index, x);
61 return (int)index;
62#else
63 int n = 0;
64 if ((x & 0x00000000FFFFFFFF) == 0) { n += 32; x >>= 32; }
65 if ((x & 0x000000000000FFFF) == 0) { n += 16; x >>= 16; }
66 if ((x & 0x00000000000000FF) == 0) { n += 8; x >>= 8; }
67 if ((x & 0x000000000000000F) == 0) { n += 4; x >>= 4; }
68 if ((x & 0x0000000000000003) == 0) { n += 2; x >>= 2; }
69 if ((x & 0x0000000000000001) == 0) { n += 1; x >>= 1; }
70#endif
71}

被这些函数引用 lmmp_from_str_(), lmmp_gcd_11_(), lmmp_gcd_22_(), lmmp_pow_(), lmmp_pow_1_(), lmmp_to_str_() , 以及 pow_nPr_().

+ 这是这个函数的调用关系图: