LAMMP 4.1.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
div_mulinv.c
浏览该文件的文档.
1/*
2 * LAMMP - Copyright (C) 2025-2026 HJimmyK(Jericho Knox)
3 * This file is part of lammp, under the GNU LGPL v2 license.
4 * See LICENSE in the project root for the full license text.
5 */
6
7#include "../../include/lammp/impl/mparam.h"
8#include "../../include/lammp/impl/tmp_alloc.h"
9#include "../../include/lammp/lmmpn.h"
10
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}
35
37 mp_ptr dstq,
38 mp_ptr numa,
39 mp_size_t na,
40 mp_srcptr numb,
41 mp_size_t nb,
42 mp_srcptr invappr,
43 mp_size_t ni
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}
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
Definition div_mulinv.c:11
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)
乘法逆元除法
Definition div_mulinv.c:36
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_size_t
Definition lmmp.h:212
const mp_limb_t * mp_srcptr
Definition lmmp.h:216
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_invappr_(mp_ptr dst, mp_srcptr numa, mp_size_t na)
近似逆元计算 (invappr)
Definition inv.c:176
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
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
#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