LAMMP 4.2.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
tiny.c
浏览该文件的文档.
1/**
2 * Copyright (C) 2026 HJimmyK(Jericho Knox)
3 *
4 * This file is part of LAMMP.
5 *
6 * LAMMP is free software: you can redistribute it and/or modify it under
7 * the terms of the GNU Lesser General Public License (LGPL) as published
8 * by the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed WITHOUT ANY WARRANTY.
12 *
13 * See <https://www.gnu.org/licenses/>.
14 */
15
16#include "../../../../include/lammp/impl/longlong.h"
17#include "../../../../include/lammp/lmmpn.h"
18#include "../../../../include/lammp/numth.h"
19
20
22 int k = 0;
23 while (x) {
24 x >>= 1;
25 k++;
26 }
27 return k;
28}
29
31#if defined(__GNUC__) || defined(__clang__)
33#if defined(__x86_64__) && defined(USE_ASM)
34 __asm__ volatile("popcnt %1, %0" : "=r"(count) : "r"(x) : "cc");
35#else
37#endif
38 return count;
39#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
40 return (int)__popcnt64(x);
41#else
42 int k = 0;
43 while (x) {
44 k += x & 1;
45 x >>= 1;
46 }
47 return k;
48#endif
49}
50
52 if (x == 0) return 64;
53#ifdef __GNUC__
54 return __builtin_clzll(x);
55#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
56 unsigned long index;
57 _BitScanReverse64(&index, x);
58 return 63 - (int)index;
59#else
60 int n = 0;
61 if (x <= 0x00000000FFFFFFFF) { n += 32; x <<= 32; }
62 if (x <= 0x0000FFFFFFFFFFFF) { n += 16; x <<= 16; }
63 if (x <= 0x00FFFFFFFFFFFFFF) { n += 8; x <<= 8; }
64 if (x <= 0x0FFFFFFFFFFFFFFF) { n += 4; x <<= 4; }
65 if (x <= 0x3FFFFFFFFFFFFFFF) { n += 2; x <<= 2; }
66 if (x <= 0x7FFFFFFFFFFFFFFF) { n += 1; x <<= 1; }
67 return n;
68#endif
69}
70
72 if (x == 0) return 64;
73#ifdef __GNUC__
74 return __builtin_ctzll(x);
75#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
76 unsigned long index;
77 _BitScanForward64(&index, x);
78 return (int)index;
79#else
80 int n = 0;
81 if ((x & 0x00000000FFFFFFFF) == 0) { n += 32; x >>= 32; }
82 if ((x & 0x000000000000FFFF) == 0) { n += 16; x >>= 16; }
83 if ((x & 0x00000000000000FF) == 0) { n += 8; x >>= 8; }
84 if ((x & 0x000000000000000F) == 0) { n += 4; x >>= 4; }
85 if ((x & 0x0000000000000003) == 0) { n += 2; x >>= 2; }
86 if ((x & 0x0000000000000001) == 0) { n += 1; x >>= 1; }
87 return n;
88#endif
89}
90
92#if (defined(__GNUC__) || defined(__clang__)) && defined(__SIZEOF_INT128__)
94 return (mp_limb_t)(t >> 64);
95#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
96 return __umulh(a, b);
97#else
98 uint64_t ah = a >> 32, bh = b >> 32;
99 a = (uint32_t)a, b = (uint32_t)b;
100 uint64_t r0 = a * b, r1 = a * bh, r2 = ah * b, r3 = ah * bh;
101 r3 += (r1 >> 32) + (r2 >> 32);
102 r1 = (uint32_t)r1, r2 = (uint32_t)r2;
103 r1 += r2;
104 r1 += (r0 >> 32);
105 return r3 + (r1 >> 32);
106#endif
107}
108
110#if (defined(__GNUC__) || defined(__clang__)) && defined(__SIZEOF_INT128__)
112 dst[0] = (mp_limb_t)prod;
113 dst[1] = (mp_limb_t)(prod >> 64);
114#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
115 dst[0] = _umul128(a, b, dst + 1);
116#else
117 uint64_t ah = a >> 32, bh = b >> 32;
118 a = (uint32_t)a, b = (uint32_t)b;
119 uint64_t r0 = a * b, r1 = a * bh, r2 = ah * b, r3 = ah * bh;
120 r3 += (r1 >> 32) + (r2 >> 32);
121 r1 = (uint32_t)r1, r2 = (uint32_t)r2;
122 r1 += r2;
123 r1 += (r0 >> 32);
124 dst[1] = r3 + (r1 >> 32);
125 dst[0] = (r1 << 32) | (uint32_t)r0;
126#endif
127}
128
131 mod <<= shl;
133 ulong ab[2];
134 ulong r;
135 _umul64to128_(a, b, ab, ab + 1);
136 if (shl > 0)
137 _u128lshl(ab, ab, shl);
138 _udiv_qrnnd_preinv(*q, r, ab[1], ab[0], mod, inv);
139 return r >> shl;
140}
#define k
#define lmmp_limb_bits_
Definition inlines.h:162
#define lmmp_leading_zeros_
Definition inlines.h:160
#define lmmp_mullh_
Definition inlines.h:164
#define lmmp_limb_popcnt_
Definition inlines.h:163
#define lmmp_tailing_zeros_
Definition inlines.h:161
#define lmmp_mulh_
Definition inlines.h:165
mp_limb_t * mp_ptr
Definition lmmp.h:80
uint64_t mp_limb_t
Definition lmmp.h:76
mp_limb_t lmmp_inv_1_(mp_limb_t x)
1阶逆元计算 (inv1)
Definition inv.c:117
static void _umul64to128_(uint64_t a, uint64_t b, uint64_t *low, uint64_t *high)
Definition longlong.h:174
#define _u128lshl(x, y, n)
Definition longlong.h:330
#define _udiv_qrnnd_preinv(q, r, nh, nl, d, di)
Definition longlong.h:415
#define r2
#define r1
#define r3
#define r0
#define t
#define n
uint64_t * ulongp
Definition numth.h:41
uint64_t ulong
Definition numth.h:32
ulong lmmp_mulmod_ulong_(ulong a, ulong b, ulong mod, ulongp restrict q)
Definition tiny.c:129