LAMMP 4.1.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 dst, mp_srcptr numa, mp_size_t na)
 近似逆元计算
 
void lmmp_invappr_ (mp_ptr dst, mp_srcptr numa, mp_size_t na)
 近似逆元计算 (invappr)
 
void lmmp_invappr_newton_ (mp_ptr dst, mp_srcptr 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.c152 行定义.

152 {
153 lmmp_param_assert(na > 0);
154 lmmp_param_assert(numa[na - 1] != 0);
155 mp_limb_t high = numa[na - 1];
156 int nsh = lmmp_leading_zeros_(high);
157 TEMP_DECL;
158 if (dst == numa || nsh || nf) {
159 nf += nsh != 0;
160 mp_ptr numa2 = TALLOC_TYPE(na + nf, mp_limb_t);
161 lmmp_zero(numa2, nf);
162 if (nsh)
163 lmmp_shl_(numa2 + nf, numa, na, nsh);
164 else
165 lmmp_copy(numa2 + nf, numa, na);
166 numa = numa2;
167 }
168 lmmp_invappr_(dst, numa, na + nf);
169 if (nsh)
170 lmmp_shr_c_(dst, dst, na + nf, LIMB_BITS - nsh, (mp_limb_t)1 << nsh);
171 else
172 dst[na + nf] = 1;
173 TEMP_FREE;
174}
void lmmp_invappr_(mp_ptr dst, mp_srcptr numa, mp_size_t na)
近似逆元计算 (invappr)
Definition inv.c:176
mp_limb_t * mp_ptr
Definition lmmp.h:215
#define lmmp_copy(dst, src, n)
Definition lmmp.h:364
#define lmmp_zero(dst, n)
Definition lmmp.h:366
uint64_t mp_limb_t
Definition lmmp.h:211
#define LIMB_BITS
Definition lmmp.h:221
#define lmmp_param_assert(x)
Definition lmmp.h:398
int lmmp_leading_zeros_(mp_limb_t x)
计算一个单精度数(limb)中前导零的个数
Definition tiny.c:35
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:30
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:9
#define TEMP_DECL
Definition tmp_alloc.h:72
#define TEMP_FREE
Definition tmp_alloc.h:93
#define TALLOC_TYPE(n, type)
Definition tmp_alloc.h:91

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

+ 函数调用图:

◆ lmmp_inv_basecase_()

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

近似逆元计算

参数
dst输出结果缓冲区,长度为na
numa输入操作数,长度为na
na输入操作数的 limb 长度
警告
na>0, MSB(numa)=1, sep(dst,numa)
返回
无返回值,结果存储在dst中,[dst,na]=(B^(2*na)-1)/[numa,na] - B^na

在文件 inv.c11 行定义.

11 {
12 lmmp_param_assert(na > 0);
13 lmmp_param_assert(numa[na - 1] >= LIMB_B_2);
14 if (na == 1)
15 *dst = lmmp_inv_1_(*numa);
16 else {
18 mp_ptr xp = TALLOC_TYPE(2 * na, mp_limb_t);
19 mp_size_t i = na;
20 do {
21 xp[--i] = LIMB_MAX;
22 } while (i);
23 lmmp_not_(xp + na, numa, na);
24 //[xp,2*na] = B^(2*na)-1 - [numa,na]*B^na
25
26 if (na == 2) {
27 lmmp_div_2_s_(dst, xp, 4, numa);
28 } else {
29 mp_limb_t inv21 = lmmp_inv_2_1_(numa[na - 1], numa[na - 2]);
30 if (na < DIV_DIVIDE_THRESHOLD) {
31 lmmp_div_basecase_(dst, xp, 2 * na, numa, na, inv21);
32 } else {
33 lmmp_div_divide_(dst, xp, 2 * na, numa, na, inv21);
34 }
35 }
37 }
38}
mp_limb_t lmmp_inv_2_1_(mp_limb_t xh, mp_limb_t xl)
2-1阶逆元计算 (inv21)
Definition inv.c:10
uint64_t mp_size_t
Definition lmmp.h:212
#define LIMB_MAX
Definition lmmp.h:224
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_inv_1_(mp_limb_t x)
1阶逆元计算 (inv1)
Definition inv.c:107
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)
分治除法运算
Definition div_divide.c:53
#define DIV_DIVIDE_THRESHOLD
Definition mparam.h:26
#define LIMB_B_2
Definition mparam.h:160

引用了 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, TALLOC_TYPE, TEMP_DECL , 以及 TEMP_FREE.

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

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

◆ lmmp_invappr_()

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

近似逆元计算 (invappr)

参数
dst输出结果缓冲区,长度为na
numa输入操作数,长度为na
na输入操作数的 limb 长度
警告
na>0, MSB(numa)=1, sep(dst,numa)
返回
无返回值,结果存储在dst中,[dst,na] = (B^(2*na)-1)/[numa,na] - B^na + [0|-1]

在文件 inv.c176 行定义.

176 {
177 if (na < INV_NEWTON_THRESHOLD)
178 lmmp_inv_basecase_(dst, numa, na);
179 else
180 lmmp_invappr_newton_(dst, numa, na);
181}
void lmmp_invappr_newton_(mp_ptr dst, mp_srcptr numa, mp_size_t na)
近似逆元计算(牛顿迭代法)
Definition inv.c:40
void lmmp_inv_basecase_(mp_ptr dst, mp_srcptr numa, mp_size_t na)
近似逆元计算
Definition inv.c:11
#define INV_NEWTON_THRESHOLD
Definition mparam.h:33

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

被这些函数引用 lmmp_inv_() , 以及 lmmp_inv_prediv_().

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

◆ lmmp_invappr_newton_()

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

近似逆元计算(牛顿迭代法)

参数
dst输出结果缓冲区,长度为na
numa输入操作数,长度为na
na输入操作数的 limb 长度
警告
na>4, MSB(numa)=1, sep(dst,numa)
返回
无返回值,结果存储在dst中,[dst,na]=(B^(2*na)-1)/[numa,na]-B^na+[0|-1]

在文件 inv.c40 行定义.

40 {
41 lmmp_param_assert(na > 4);
42 lmmp_param_assert(numa[na - 1] >= LIMB_B_2);
43
44 mp_limb_t cy;
45 mp_size_t nr = na, mn;
46 mp_size_t sizes[LIMB_BITS], *sizp = sizes;
47
48 do {
49 *sizp = nr;
50 nr = (nr >> 1) + 1;
51 ++sizp;
52 } while (nr >= INV_NEWTON_THRESHOLD);
53
54 numa += na;
55 dst += na;
56
57 lmmp_inv_basecase_(dst - nr, numa - nr, nr);
58
60 mp_ptr xp = TALLOC_TYPE(3 * (na >> 1) + 3, mp_limb_t);
61 do {
62 na = *--sizp;
63
64 // ar = 0:[numa-nr,nr]
65 // an = 0:[numa-na,na]
66 // ir = 1:[dst-nr,nr] = (B^(2*nr)-1)/ar - [0|1]
67 // rem = ir*an-B^(na+nr)
68 //-2*B^na < rem < 2*B^na
69
70 //[xp] = rem
71 if (na < INV_MODM_THRESHOLD || (mn = lmmp_fft_next_size_(na + 1)) >= na + nr) {
72 lmmp_mul_(xp, numa - na, na, dst - nr, nr);
73 lmmp_add_n_(xp + nr, xp + nr, numa - na, na + 1 - nr);
74 cy = 1; // for mod B^(na+1)
75 } else { // nr < na < mn < na+nr
76
77 //[xp,mn] = [dst,nr] * [numa,na] mod (B^mn-1)
78 lmmp_mul_mersenne_(xp, mn, numa - na, na, dst - nr, nr);
79
80 //[xp,mn] += [numa,na]*B^nr mod (B^mn-1)
81 cy = lmmp_add_n_(xp + nr, xp + nr, numa - na, mn - nr);
82 cy = lmmp_add_nc_(xp, xp, numa - (na - (mn - nr)), na - (mn - nr), cy);
83
84 //[xp,mn] -= B^(na+nr) mod (B^mn-1)
85 xp[mn] = 1;
86 lmmp_dec_1(xp + na + nr - mn, 1 - cy);
87 lmmp_dec_1(xp, 1 - xp[mn]);
88
89 cy = 0; // for mod (B^mn-1)
90 }
91
92 // adjust ir,rem s.t.
93 // -B^na < rem = ir*an - B^(na+nr) < 0
94 // use this we can prove B^nr <= ir < 2*B^nr
95 // so inc/dec ir won't overflow
96 if (xp[na] < 2) { // rem>=0
97
98 // rem-=cy*an s.t. rem[na]=0
99 if (cy = xp[na]) {
100 if (!lmmp_sub_n_(xp, xp, numa - na, na)) {
101 ++cy;
102 lmmp_sub_n_(xp, xp, numa - na, na);
103 }
104 }
105
106 // rem-=cy*an s.t. 0<=rem<an
107 if (lmmp_cmp_(xp, numa - na, na) >= 0) {
108 lmmp_sub_n_(xp, xp, numa - na, na);
109 ++cy;
110 }
111
112 // 0 < an-rem <= an < B^na , trunc to nr limbs
113 lmmp_sub_nc_(xp + 2 * nr, numa - nr, xp + na - nr, nr, lmmp_cmp_(xp, numa - na, na - nr) > 0);
114 ++cy;
115
116 lmmp_dec_1(dst - nr, cy);
117 } else { // rem<0
118 if (cy)
119 lmmp_dec(xp); // for neg to not
120 // else (neg to not) compensate (mod transfer)
121
122 if (xp[na] != LIMB_MAX) {
123 lmmp_assert(xp[na] + lmmp_add_n_(xp, xp, numa - na, na) == LIMB_MAX);
124 lmmp_inc(dst - nr);
125 }
126
127 //-rem
128 lmmp_not_(xp + 2 * nr, xp + na - nr, nr);
129 }
130
131 // in = 1:[dst-na,na]
132 // in = ir*B^(na-nr) + ir*(-rem/B^(na-nr))/B^(3*nr-na)
133 // use inequality an*ir!=B^(na+nr),
134 //(otherwise obviously contradictory),
135 // we can prove
136 // an*in <= an*ir * ( 2*B^(na+nr) - an*ir ) * B^(-2*nr) < B^(2*na)
137 // so in < B^(2*na)/an <= 2*B^(na),
138 // inc below won't overflow
139
140 // and via inequality -B^na < an*ir - B^(na+nr) < 0
141 // we can prove in = (B^(2*na)-1)/an - [0|1]
142 lmmp_mul_n_(xp, xp + 2 * nr, dst - nr, nr);
143 cy = lmmp_add_n_(xp + nr, xp + nr, xp + 2 * nr, 2 * nr - na);
144 if (lmmp_add_nc_(dst - na, xp + 3 * nr - na, xp + 4 * nr - na, na - nr, cy))
145 lmmp_inc(dst - nr);
146
147 nr = na;
148 } while (sizp != sizes);
149 TEMP_FREE;
150}
#define lmmp_assert(x)
Definition lmmp.h:370
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:752
static int lmmp_cmp_(mp_srcptr numa, mp_srcptr numb, mp_size_t n)
大数比较函数(内联)
Definition lmmpn.h:1004
#define lmmp_dec(p)
大数减1宏(预期无借位)
Definition lmmpn.h:973
#define lmmp_inc(p)
大数加1宏(预期无进位)
Definition lmmpn.h:946
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]
void lmmp_mul_n_(mp_ptr dst, mp_srcptr numa, mp_srcptr numb, mp_size_t n)
等长大数乘法操作 [dst,2*n] = [numa,n] * [numb,n]
Definition mul.c:99
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:9
mp_size_t lmmp_fft_next_size_(mp_size_t n)
计算满足 >=n 的最小费马/梅森乘法可行尺寸
Definition mul_fft.c:84
#define lmmp_dec_1(p, dec)
大数减指定值宏(预期无借位)
Definition lmmpn.h:985
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:70
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:9
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:71
#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_(), TALLOC_TYPE, TEMP_DECL , 以及 TEMP_FREE.

被这些函数引用 lmmp_invappr_().

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