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

浏览源代码.

函数

mp_limb_t lmmp_inv_1_ (mp_limb_t x)
 1阶逆元计算 (inv1)
 
mp_limb_t lmmp_inv_2_1_ (mp_limb_t xh, mp_limb_t xl)
 Copyright (C) 2026 HJimmyK(Jericho Knox)
 

函数说明

◆ lmmp_inv_1_()

mp_limb_t lmmp_inv_1_ ( mp_limb_t  x)

1阶逆元计算 (inv1)

参数
x输入的64位无符号整数,最高位为1(MSB(x)=1)
返回
计算结果:(B^2-1)/x - B
警告
MSB(x)=1, 即x>=2^63

在文件 inv.c117 行定义.

117 {
118 mp_limb_t r, m;
119 {
120 mp_limb_t p, ql;
121 unsigned ul, uh, qh;
122
123 ul = x & LLIMB_MASK;
124 uh = x >> (LIMB_BITS / 2);
125 qh = (x ^ LIMB_MAX) / uh;
126
127 r = ((~x - (mp_limb_t)qh * uh) << (LIMB_BITS / 2)) | LLIMB_MASK;
128 p = (mp_limb_t)qh * ul;
129 if (r < p) {
130 qh--;
131 r += x;
132 if (r >= x)
133 if (r < p) {
134 qh--;
135 r += x;
136 }
137 }
138 r -= p;
139 p = (r >> (LIMB_BITS / 2)) * qh + r;
140 ql = (p >> (LIMB_BITS / 2)) + 1;
141 r = (r << (LIMB_BITS / 2)) + LLIMB_MASK - ql * x;
142 if (r >= (LIMB_MAX & (p << (LIMB_BITS / 2)))) {
143 ql--;
144 r += x;
145 }
146 m = ((mp_limb_t)qh << (LIMB_BITS / 2)) + ql;
147 if (r >= x) {
148 m++;
149 r -= x;
150 }
151 }
152 return m;
153}
#define LLIMB_MASK
Definition lmmp.h:92
#define LIMB_MAX
Definition lmmp.h:89
uint64_t mp_limb_t
Definition lmmp.h:76
#define LIMB_BITS
Definition lmmp.h:86
#define n

引用了 LIMB_BITS, LIMB_MAX, LLIMB_MASK , 以及 n.

被这些函数引用 lmmp_div_1_(), lmmp_div_1_s_(), lmmp_inv_basecase_(), lmmp_mod_1_() , 以及 lmmp_mulmod_ulong_().

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

◆ lmmp_inv_2_1_()

mp_limb_t lmmp_inv_2_1_ ( mp_limb_t  xh,
mp_limb_t  xl 
)

Copyright (C) 2026 HJimmyK(Jericho Knox)

2-1阶逆元计算 (inv21)

This file is part of LAMMP.

LAMMP is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This program is distributed WITHOUT ANY WARRANTY.

See https://www.gnu.org/licenses/.

在文件 inv.c20 行定义.

20 {
21 mp_limb_t r, m;
22 {
23 mp_limb_t p, ql;
24 unsigned ul, uh, qh;
25
26 /* For notation, let b denote the half-limb base, so that B = b^2.
27 Split u1 = b uh + ul. */
28 ul = xh & LLIMB_MASK;
29 uh = xh >> (LIMB_BITS / 2);
30
31 /* Approximation of the high half of quotient. Differs from the 2/1
32 inverse of the half limb uh, since we have already subtracted
33 u0. */
34 qh = (xh ^ LIMB_MAX) / uh;
35
36 /* Adjust to get a half-limb 3/2 inverse, i.e., we want
37
38 qh' = floor( (b^3 - 1) / u) - b = floor ((b^3 - b u - 1) / u
39 = floor( (b (~u) + b-1) / u),
40
41 and the remainder
42
43 r = b (~u) + b-1 - qh (b uh + ul)
44 = b (~u - qh uh) + b-1 - qh ul
45
46 Subtraction of qh ul may underflow, which implies adjustments.
47 But by normalization, 2 u >= B > qh ul, so we need to adjust by
48 at most 2.
49 */
50
51 r = ((~xh - (mp_limb_t)qh * uh) << (LIMB_BITS / 2)) | LLIMB_MASK;
52
53 p = (mp_limb_t)qh * ul;
54 /* Adjustment steps taken from udiv_qrnnd_c */
55 if (r < p) {
56 qh--;
57 r += xh;
58 if (r >= xh) /* i.e. we didn't get carry when adding to r */
59 if (r < p) {
60 qh--;
61 r += xh;
62 }
63 }
64 r -= p;
65
66 /* Low half of the quotient is
67
68 ql = floor ( (b r + b-1) / u1).
69
70 This is a 3/2 division (on half-limbs), for which qh is a
71 suitable inverse. */
72
73 p = (r >> (LIMB_BITS / 2)) * qh + r;
74 /* Unlike full-limb 3/2, we can add 1 without overflow. For this to
75 work, it is essential that ql is a full mp_limb_t. */
76 ql = (p >> (LIMB_BITS / 2)) + 1;
77
78 /* By the 3/2 trick, we don't need the high half limb. */
79 r = (r << (LIMB_BITS / 2)) + LLIMB_MASK - ql * xh;
80
81 if (r >= (LIMB_MAX & (p << (LIMB_BITS / 2)))) {
82 ql--;
83 r += xh;
84 }
85 m = ((mp_limb_t)qh << (LIMB_BITS / 2)) + ql;
86 if (r >= xh) {
87 m++;
88 r -= xh;
89 }
90 }
91
92 /* Now m is the 2/1 inverse of u1. If u0 > 0, adjust it to become a
93 3/2 inverse. */
94 if (xl > 0) {
96 r = ~r;
97 r += xl;
98 if (r < xl) {
99 m--;
100 if (r >= xh) {
101 m--;
102 r -= xh;
103 }
104 r -= xh;
105 }
106 _umul64to128_(xl, m, &tl, &th);
107 r += th;
108 if (r < th) {
109 m--;
110 m -= ((r > xh) | ((r == xh) & (tl > xl)));
111 }
112 }
113
114 return m;
115}
static void _umul64to128_(uint64_t a, uint64_t b, uint64_t *low, uint64_t *high)
Definition longlong.h:174

引用了 _umul64to128_(), LIMB_BITS, LIMB_MAX, LLIMB_MASK , 以及 n.

被这些函数引用 lmmp_bninv_appr_newton_(), lmmp_div_(), lmmp_div_2_(), lmmp_div_2_s_(), lmmp_div_s_(), lmmp_inv_basecase_() , 以及 lmmp_mod_2_().

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