LAMMP 4.1.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
tiny.c
浏览该文件的文档.
1/*
2 * LAMMP - Copyright (C) 2025-2026 HJimmyK(Jericho Knox)
3 * This file is part of lammp, under the GNU LGPL v2 license.
4 * See LICENSE in the project root for the full license text.
5 */
6
7#include "../../../include/lammp/lmmpn.h"
8#include "../../../include/lammp/numth.h"
9#include "../../../include/lammp/impl/longlong.h"
10
12 int k = 0;
13 while (x) {
14 x >>= 1;
15 k++;
16 }
17 return k;
18}
19
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}
34
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}
53
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}
72
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}
90
91void lmmp_mullh_(mp_limb_t a, mp_limb_t b, mp_ptr restrict dst) {
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}
110
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}
#define k
mp_limb_t * mp_ptr
Definition lmmp.h:215
uint64_t mp_limb_t
Definition lmmp.h:211
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
#define r2
#define r1
#define r3
#define r0
uint64_t * ulongp
Definition numth.h:45
uint64_t ulong
Definition numth.h:36
int lmmp_leading_zeros_(mp_limb_t x)
计算一个单精度数(limb)中前导零的个数
Definition tiny.c:35
int lmmp_tailing_zeros_(mp_limb_t x)
计算一个单精度数(limb)中末尾零的个数
Definition tiny.c:54
void lmmp_mullh_(mp_limb_t a, mp_limb_t b, mp_ptr restrict dst)
Definition tiny.c:91
mp_limb_t lmmp_mulh_(mp_limb_t a, mp_limb_t b)
计算两个64位无符号整数相乘的高位结果 (a*b)/2^64
Definition tiny.c:73
int lmmp_limb_bits_(mp_limb_t x)
计算满足 2^k > x 的最小自然数k
Definition tiny.c:11
int lmmp_limb_popcnt_(mp_limb_t x)
计算一个64位无符号整数中1的个数
Definition tiny.c:20
ulong lmmp_mulmod_ulong_(ulong a, ulong b, ulong mod, ulongp restrict q)
Definition tiny.c:111