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

浏览源代码.

函数

void lmmp_inv_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t nf)
 大数求逆操作 [dst,na+nf+1] = (B^(2*(na+nf)) - 1) / ([numa,na]*B^nf) + [0|-1]
 
void lmmp_inv_basecase_ (mp_ptr restrict dst, mp_srcptr restrict numa, mp_size_t na)
 Copyright (C) 2026 HJimmyK(Jericho Knox)
 
void lmmp_invappr_ (mp_ptr restrict dst, mp_srcptr restrict numa, mp_size_t na)
 
void lmmp_invappr_newton_ (mp_ptr restrict dst, mp_srcptr restrict numa, mp_size_t na)
 

函数说明

◆ lmmp_inv_()

void lmmp_inv_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_size_t  nf 
)

大数求逆操作 [dst,na+nf+1] = (B^(2*(na+nf)) - 1) / ([numa,na]*B^nf) + [0|-1]

参数
dst逆元结果输出指针
numa源操作数指针
na操作数的 limb 长度
nf精度因子
警告
na>0, numa[na-1]!=0, eqsep(dst,numa)

在文件 inv.c163 行定义.

163 {
165 lmmp_param_assert(numa[na - 1] != 0);
166 mp_limb_t high = numa[na - 1];
168 TEMP_DECL;
169 if (dst == numa || nsh || nf) {
170 nf += nsh != 0;
173 if (nsh)
174 lmmp_shl_(numa2 + nf, numa, na, nsh);
175 else
176 lmmp_copy(numa2 + nf, numa, na);
177 numa = numa2;
178 }
180 if (nsh)
182 else
183 dst[na + nf] = 1;
184 TEMP_FREE;
185}
#define lmmp_leading_zeros_
Definition inlines.h:160
void lmmp_invappr_(mp_ptr restrict dst, mp_srcptr restrict numa, mp_size_t na)
Definition inv.c:187
mp_limb_t * mp_ptr
Definition lmmp.h:80
#define lmmp_copy(dst, src, n)
Definition lmmp.h:367
#define lmmp_zero(dst, n)
Definition lmmp.h:369
uint64_t mp_limb_t
Definition lmmp.h:76
#define LIMB_BITS
Definition lmmp.h:86
#define lmmp_param_assert(x)
Definition lmmp.h:401
mp_limb_t lmmp_shr_c_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t shr, mp_limb_t c)
带进位的大数右移操作 [dst,na] = [numa,na]>>shr,dst的高shr位填充c的高shr位
Definition shr.c:40
mp_limb_t lmmp_shl_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t shl)
大数左移操作 [dst,na] = [numa,na]<<shl,dst的低shl位填充0
Definition shl.c:19
#define n
#define TEMP_DECL
Definition tmp_alloc.h:131
#define TEMP_FREE
Definition tmp_alloc.h:150
#define TALLOC_TYPE(n, type)
Definition tmp_alloc.h:148

引用了 LIMB_BITS, lmmp_copy, lmmp_invappr_(), lmmp_leading_zeros_, lmmp_param_assert, lmmp_shl_(), lmmp_shr_c_(), lmmp_zero, n, TALLOC_TYPE, TEMP_DECL , 以及 TEMP_FREE.

+ 函数调用图:

◆ lmmp_inv_basecase_()

void lmmp_inv_basecase_ ( mp_ptr restrict  dst,
mp_srcptr restrict  numa,
mp_size_t  na 
)

Copyright (C) 2026 HJimmyK(Jericho Knox)

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.c22 行定义.

22 {
25 if (na == 1)
26 *dst = lmmp_inv_1_(*numa);
27 else {
30 mp_size_t i = na;
31 do {
32 xp[--i] = LIMB_MAX;
33 } while (i);
34 lmmp_not_(xp + na, numa, na);
35 //[xp,2*na] = B^(2*na)-1 - [numa,na]*B^na
36
37 if (na == 2) {
39 } else {
43 } else {
45 }
46 }
48 }
49}
mp_limb_t lmmp_inv_1_(mp_limb_t x)
1阶逆元计算 (inv1)
Definition inv.c:117
mp_limb_t lmmp_inv_2_1_(mp_limb_t xh, mp_limb_t xl)
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition inv.c:20
uint64_t mp_size_t
Definition lmmp.h:77
#define LIMB_MAX
Definition lmmp.h:89
mp_limb_t lmmp_div_2_s_(mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_srcptr numb)
双精度数除法(除数为2个limb)
void lmmp_not_(mp_ptr dst, mp_srcptr numa, mp_size_t na)
大数按位取反操作 [dst,na] = ~[numa,na] (对每个limb执行按位非操作)
mp_limb_t lmmp_div_basecase_(mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb, mp_limb_t inv21)
基础除法运算
mp_limb_t lmmp_div_divide_(mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb, mp_limb_t inv21)
分治除法运算
#define DIV_DIVIDE_THRESHOLD
Definition mparam.h:26
#define LIMB_B_2
Definition mparam.h:157

引用了 DIV_DIVIDE_THRESHOLD, LIMB_B_2, LIMB_MAX, lmmp_div_2_s_(), lmmp_div_basecase_(), lmmp_div_divide_(), lmmp_inv_1_(), lmmp_inv_2_1_(), lmmp_not_(), lmmp_param_assert, n, TALLOC_TYPE, TEMP_DECL , 以及 TEMP_FREE.

被这些函数引用 lmmp_invappr_() , 以及 lmmp_invappr_newton_().

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

◆ lmmp_invappr_()

void lmmp_invappr_ ( mp_ptr restrict  dst,
mp_srcptr restrict  numa,
mp_size_t  na 
)

在文件 inv.c187 行定义.

187 {
190 else
192}
void lmmp_inv_basecase_(mp_ptr restrict dst, mp_srcptr restrict numa, mp_size_t na)
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition inv.c:22
void lmmp_invappr_newton_(mp_ptr restrict dst, mp_srcptr restrict numa, mp_size_t na)
Definition inv.c:51
#define INV_NEWTON_THRESHOLD
Definition mparam.h:33

引用了 INV_NEWTON_THRESHOLD, lmmp_inv_basecase_(), lmmp_invappr_newton_() , 以及 n.

被这些函数引用 lmmp_inv_().

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

◆ lmmp_invappr_newton_()

void lmmp_invappr_newton_ ( mp_ptr restrict  dst,
mp_srcptr restrict  numa,
mp_size_t  na 
)

在文件 inv.c51 行定义.

51 {
54
56 mp_size_t nr = na, mn;
58
59 do {
60 *sizp = nr;
61 nr = (nr >> 1) + 1;
62 ++sizp;
63 } while (nr >= INV_NEWTON_THRESHOLD);
64
65 numa += na;
66 dst += na;
67
69
71 mp_ptr restrict xp = TALLOC_TYPE(3 * (na >> 1) + 3, mp_limb_t);
72 do {
73 na = *--sizp;
74
75 // ar = 0:[numa-nr,nr]
76 // an = 0:[numa-na,na]
77 // ir = 1:[dst-nr,nr] = (B^(2*nr)-1)/ar - [0|1]
78 // rem = ir*an-B^(na+nr)
79 //-2*B^na < rem < 2*B^na
80
81 //[xp] = rem
82 if (na < INV_MODM_THRESHOLD || (mn = lmmp_fft_next_size_(na + 1)) >= na + nr) {
83 lmmp_mul_(xp, numa - na, na, dst - nr, nr);
84 lmmp_add_n_(xp + nr, xp + nr, numa - na, na + 1 - nr);
85 cy = 1; // for mod B^(na+1)
86 } else { // nr < na < mn < na+nr
87
88 //[xp,mn] = [dst,nr] * [numa,na] mod (B^mn-1)
89 lmmp_mul_mersenne_(xp, mn, numa - na, na, dst - nr, nr);
90
91 //[xp,mn] += [numa,na]*B^nr mod (B^mn-1)
92 cy = lmmp_add_n_(xp + nr, xp + nr, numa - na, mn - nr);
93 cy = lmmp_add_nc_(xp, xp, numa - (na - (mn - nr)), na - (mn - nr), cy);
94
95 //[xp,mn] -= B^(na+nr) mod (B^mn-1)
96 xp[mn] = 1;
97 lmmp_dec_1(xp + na + nr - mn, 1 - cy);
98 lmmp_dec_1(xp, 1 - xp[mn]);
99
100 cy = 0; // for mod (B^mn-1)
101 }
102
103 // adjust ir,rem s.t.
104 // -B^na < rem = ir*an - B^(na+nr) < 0
105 // use this we can prove B^nr <= ir < 2*B^nr
106 // so inc/dec ir won't overflow
107 if (xp[na] < 2) { // rem>=0
108
109 // rem-=cy*an s.t. rem[na]=0
110 if ((cy = xp[na])) {
111 if (!lmmp_sub_n_(xp, xp, numa - na, na)) {
112 ++cy;
113 lmmp_sub_n_(xp, xp, numa - na, na);
114 }
115 }
116
117 // rem-=cy*an s.t. 0<=rem<an
118 if (lmmp_cmp_(xp, numa - na, na) >= 0) {
119 lmmp_sub_n_(xp, xp, numa - na, na);
120 ++cy;
121 }
122
123 // 0 < an-rem <= an < B^na , trunc to nr limbs
124 lmmp_sub_nc_(xp + 2 * nr, numa - nr, xp + na - nr, nr, lmmp_cmp_(xp, numa - na, na - nr) > 0);
125 ++cy;
126
127 lmmp_dec_1(dst - nr, cy);
128 } else { // rem<0
129 if (cy)
130 lmmp_dec(xp); // for neg to not
131 // else (neg to not) compensate (mod transfer)
132
133 if (xp[na] != LIMB_MAX) {
135 lmmp_inc(dst - nr);
136 }
137
138 //-rem
139 lmmp_not_(xp + 2 * nr, xp + na - nr, nr);
140 }
141
142 // in = 1:[dst-na,na]
143 // in = ir*B^(na-nr) + ir*(-rem/B^(na-nr))/B^(3*nr-na)
144 // use inequality an*ir!=B^(na+nr),
145 //(otherwise obviously contradictory),
146 // we can prove
147 // an*in <= an*ir * ( 2*B^(na+nr) - an*ir ) * B^(-2*nr) < B^(2*na)
148 // so in < B^(2*na)/an <= 2*B^(na),
149 // inc below won't overflow
150
151 // and via inequality -B^na < an*ir - B^(na+nr) < 0
152 // we can prove in = (B^(2*na)-1)/an - [0|1]
153 lmmp_mul_n_(xp, xp + 2 * nr, dst - nr, nr);
154 cy = lmmp_add_n_(xp + nr, xp + nr, xp + 2 * nr, 2 * nr - na);
155 if (lmmp_add_nc_(dst - na, xp + 3 * nr - na, xp + 4 * nr - na, na - nr, cy))
156 lmmp_inc(dst - nr);
157
158 nr = na;
159 } while (sizp != sizes);
160 TEMP_FREE;
161}
#define lmmp_mul_n_
Definition inlines.h:167
#define lmmp_assert(x)
Definition lmmp.h:373
void lmmp_mul_mersenne_(mp_ptr dst, mp_size_t rn, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
梅森数模乘法 [dst,rn] = [numa,na]*[numb,nb] mod B^rn-1
Definition mul_fft.c:761
static int lmmp_cmp_(mp_srcptr numa, mp_srcptr numb, mp_size_t n)
大数比较函数(内联)
Definition lmmpn.h:996
#define lmmp_dec(p)
大数减1宏(预期无借位)
Definition lmmpn.h:965
#define lmmp_inc(p)
大数加1宏(预期无进位)
Definition lmmpn.h:938
void lmmp_mul_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
不等长大数乘法操作 [dst,na+nb] = [numa,na] * [numb,nb]
mp_limb_t lmmp_add_nc_(mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n, mp_limb_t c)
带进位的n位加法 [dst,n] = [numa,n] + [numb,n] + c
Definition add_n.c:19
mp_size_t lmmp_fft_next_size_(mp_size_t n)
计算满足 >=n 的最小费马/梅森乘法可行尺寸
Definition mul_fft.c:95
#define lmmp_dec_1(p, dec)
大数减指定值宏(预期无借位)
Definition lmmpn.h:977
mp_limb_t lmmp_sub_n_(mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n)
无借位的n位减法 [dst,n] = [numa,n] - [numb,n]
Definition sub_n.c:80
mp_limb_t lmmp_sub_nc_(mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n, mp_limb_t c)
带借位的n位减法 [dst,n] = [numa,n] - [numb,n] - c
Definition sub_n.c:19
mp_limb_t lmmp_add_n_(mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n)
无进位的n位加法 [dst,n] = [numa,n] + [numb,n]
Definition add_n.c:81
#define INV_MODM_THRESHOLD
Definition mparam.h:35

引用了 INV_MODM_THRESHOLD, INV_NEWTON_THRESHOLD, LIMB_B_2, LIMB_BITS, LIMB_MAX, lmmp_add_n_(), lmmp_add_nc_(), lmmp_assert, lmmp_cmp_(), lmmp_dec, lmmp_dec_1, lmmp_fft_next_size_(), lmmp_inc, lmmp_inv_basecase_(), lmmp_mul_(), lmmp_mul_mersenne_(), lmmp_mul_n_, lmmp_not_(), lmmp_param_assert, lmmp_sub_n_(), lmmp_sub_nc_(), n, TALLOC_TYPE, TEMP_DECL , 以及 TEMP_FREE.

被这些函数引用 lmmp_invappr_().

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