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

浏览源代码.

函数

mp_limb_t lmmp_div_mulinv_ (mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb, mp_srcptr invappr, mp_size_t ni)
 乘法逆元除法
 
void lmmp_inv_prediv_ (mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t ni)
 除法前的逆元预计算,[dst,ni] = invappr( (ni+1 MSLs of numa) + 1 ) / B
 

函数说明

◆ lmmp_div_mulinv_()

mp_limb_t lmmp_div_mulinv_ ( mp_ptr  dstq,
mp_ptr  numa,
mp_size_t  na,
mp_srcptr  numb,
mp_size_t  nb,
mp_srcptr  invappr,
mp_size_t  ni 
)

乘法逆元除法

参数
dstq输出商的缓冲区,长度至少为na-nb
numa输入被除数(长度na),运算后存储余数(长度nb)
na被除数的 limb 长度
numb输入除数,长度为nb
nb除数的 limb 长度
invappr预计算的近似逆元,长度为ni
ni预计算逆元的 limb 长度
返回
商的最高位(qh)
警告
na>=nb>=ni>0, MSB(numb)=1, [invappr,ni]=inv_prediv([numb,nb]), sep(dstq,numa,numb,invappr))
注解
qh:[dstq,na-1]=[numa,na] div x, [numa,1]=[numa,na] mod x, return qh

在文件 div_mulinv.c36 行定义.

44 {
45 lmmp_param_assert(na >= nb && nb >= ni);
46 lmmp_param_assert(ni > 0);
47 lmmp_param_assert(numb[nb - 1] >= LIMB_B_2);
48 mp_size_t nq = na - nb, ntp = LMMP_MIN(ni, nq) + nb;
49 mp_limb_t qh;
52
53 numa += nq;
54 dstq += nq;
55
56 qh = lmmp_cmp_(numa, numb, nb) >= 0;
57 if (qh) {
58 lmmp_sub_n_(numa, numa, numb, nb);
59 }
60 while (nq) {
61 if (nq < ni) {
62 invappr += ni - nq;
63 ni = nq;
64 }
65 numa -= ni;
66 dstq -= ni;
67 nq -= ni;
68
69 lmmp_mul_n_(tp, numa + nb, invappr, ni);
70 lmmp_assert(lmmp_add_n_(dstq, tp + ni, numa + nb, ni) == 0);
71
72 mp_size_t mn, wn;
73 mp_limb_t cy;
74
75 if (nb < DIV_MULINV_MODM_THRESHOLD || (mn = lmmp_fft_next_size_(nb + 1)) >= nb + ni) {
76 lmmp_mul_(tp, numb, nb, dstq, ni); // nb+ni limbs, high 'ni' cancels
77 } else {
78 // 0<wn<ni<=nb<mn<nb+ni
79 wn = nb + ni - mn;
80
81 // x=b*q
82 // tp=x mod 2^mn-1
83 lmmp_mul_mersenne_(tp, mn, numb, nb, dstq, ni);
84
85 // tp-=ah:0 mod B^mn-1, if result=0, represent it as B^mn-1
86 cy = lmmp_sub_nc_(tp, tp, numa + mn, wn, 1);
87 if (cy)
88 cy = lmmp_sub_1_(tp + wn, tp + wn, mn - wn, 1);
89 if (!cy)
90 lmmp_inc(tp);
91
92 // if al<<tp,
93 if (lmmp_cmp_(numa + nb, tp + nb, mn - nb) < 0) {
94 // maybe ah=xh+1 and al<<xl,
95 // so we subtracted 1 too much when tp-=ah,
96 // now tp=xl-1 mod B^mn-1, and 0<=al<<xl-1<B^mn-1, so tp=xl-1
97 // or ah=xh and al>=xl,
98 // tp=xl mod B^mn-1, the only possibility is we represented xl=0 as tp=B^mn-1
99 // whatever, just inc and then tp=xl
100 tp[mn] = 0; // set a limit
101 lmmp_inc(tp);
102 }
103 }
104
105 mp_limb_t r = numa[nb] - tp[nb];
106 cy = lmmp_sub_n_(numa, numa, tp, nb);
107
108 while ((r -= cy) || lmmp_cmp_(numa, numb, nb) >= 0) {
109 lmmp_inc(dstq);
110 cy = lmmp_sub_n_(numa, numa, numb, nb);
111 }
112 }
113 TEMP_FREE;
114 return qh;
115}
mp_limb_t * mp_ptr
Definition lmmp.h:215
uint64_t mp_size_t
Definition lmmp.h:212
uint64_t mp_limb_t
Definition lmmp.h:211
#define lmmp_assert(x)
Definition lmmp.h:370
#define LMMP_MIN(l, o)
Definition lmmp.h:348
#define lmmp_param_assert(x)
Definition lmmp.h:398
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_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_size_t lmmp_fft_next_size_(mp_size_t n)
计算满足 >=n 的最小费马/梅森乘法可行尺寸
Definition mul_fft.c:84
static mp_limb_t lmmp_sub_1_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_limb_t x)
大数减单精度数静态内联函数 [dst,na]=[numa,na]-x
Definition lmmpn.h:1122
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 LIMB_B_2
Definition mparam.h:160
#define DIV_MULINV_MODM_THRESHOLD
Definition mparam.h:38
#define tp
#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

引用了 DIV_MULINV_MODM_THRESHOLD, LIMB_B_2, lmmp_add_n_(), lmmp_assert, lmmp_cmp_(), lmmp_fft_next_size_(), lmmp_inc, LMMP_MIN, lmmp_mul_(), lmmp_mul_mersenne_(), lmmp_mul_n_(), lmmp_param_assert, lmmp_sub_1_(), lmmp_sub_n_(), lmmp_sub_nc_(), TALLOC_TYPE, TEMP_DECL, TEMP_FREE , 以及 tp.

被这些函数引用 lmmp_div_(), lmmp_div_s_() , 以及 lmmp_to_str_divide_().

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

◆ lmmp_inv_prediv_()

void lmmp_inv_prediv_ ( mp_ptr  dst,
mp_srcptr  numa,
mp_size_t  na,
mp_size_t  ni 
)

除法前的逆元预计算,[dst,ni] = invappr( (ni+1 MSLs of numa) + 1 ) / B

参数
dst输出预计算逆元的缓冲区,长度为ni
numa输入操作数,长度为na
na输入操作数的 limb 长度
ni预计算逆元的目标尺寸
警告
na>=ni>0, MSB(numa)=1, eqsep(dst,numa)
注解
if (ni=na) [dst,na] = (B^(2*na)-1) / [numa,na] - B^na

在文件 div_mulinv.c11 行定义.

11 {
12 lmmp_param_assert(na >= ni);
13 lmmp_param_assert(ni > 0);
14 lmmp_param_assert(numa[na - 1] >= LIMB_B_2);
16 mp_limb_t cy;
17 mp_ptr tp = TALLOC_TYPE(ni + 1, mp_limb_t);
18
19 if (na == ni) {
20 lmmp_copy(tp + 1, numa, ni);
21 tp[0] = 1;
22 cy = 0;
23 } else {
24 cy = lmmp_add_1_(tp, numa + na - (ni + 1), ni + 1, 1);
25 }
26 if (cy)
27 lmmp_zero(dst, ni);
28 else {
29 mp_ptr invappr = TALLOC_TYPE(ni + 1, mp_limb_t);
30 lmmp_invappr_(invappr, tp, ni + 1);
31 lmmp_copy(dst, invappr + 1, ni);
32 }
34}
#define lmmp_copy(dst, src, n)
Definition lmmp.h:364
#define lmmp_zero(dst, n)
Definition lmmp.h:366
void lmmp_invappr_(mp_ptr dst, mp_srcptr numa, mp_size_t na)
近似逆元计算 (invappr)
Definition inv.c:176
static mp_limb_t lmmp_add_1_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_limb_t x)
大数加单精度数静态内联函数 [dst,na]=[numa,na]+x
Definition lmmpn.h:1111

引用了 LIMB_B_2, lmmp_add_1_(), lmmp_copy, lmmp_invappr_(), lmmp_param_assert, lmmp_zero, TALLOC_TYPE, TEMP_DECL, TEMP_FREE , 以及 tp.

被这些函数引用 lmmp_div_(), lmmp_div_s_() , 以及 lmmp_to_str_().

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