LAMMP 4.1.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
remove.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/numth.h"
8#include "../../../include/lammp/lmmpn.h"
9#include "../../../include/lammp/impl/tmp_alloc.h"
10
11/*
12事实上,我们可以知道,[np,nn]至多为[dp,dn]的2^64次方
132^64 - 1 - 2 - 4 - 8 - ... - 2^63 最为接近2^64
14故,理论上MAX_EXP = 63
15
16但是,实际上,[np,nn]几乎不可能超过[dp,dn]的2^48次方
172^48 - 1 - 2 - 4 - 8 - ... - 2^47 最为接近2^48
18故,我们使用MAX_EXP = 48
19*/
20#define MAX_EXP 48
21
22/**
23 * qp 为商,rp 为余数,divp 为被除数,divn 为被除数长度,numb 为除数,nb 为除数长度
24 * 如果无法整除,则返回0,否则返回除数 qp 的长度
25 */
26static inline mp_size_t try_div_(mp_ptr qp, mp_ptr rp, mp_srcptr divp, mp_size_t divn, mp_srcptr numb, mp_size_t nb) {
27 if (divn < nb) {
28 return 0;
29 } else {
30 int cmp;
31 if (divn > nb)
32 cmp = 1;
33 else
34 cmp = lmmp_cmp_(divp, numb, nb);
35 if (cmp == 0) {
36 qp[0] = 1;
37 return 1;
38 } else if (cmp < 0) {
39 return 0;
40 } else {
41 // 拷贝原始数,当无法整除时,再进行恢复
42 lmmp_div_(qp, rp, divp, divn, numb, nb);
43 if (lmmp_zero_q_(rp, nb)) {
44 // 整除
45 divn = divn - nb + 1;
46 while (divn > 0 && qp[divn - 1] == 0) --divn;
47 return divn;
48 } else {
49 // 无法整除
50 return 0;
51 }
52 }
53 }
54}
55
57 lmmp_param_assert(np != NULL && *nn > 0);
58 lmmp_param_assert(dp != NULL && dn > 0);
59
60 mp_srcptr pd_pow[MAX_EXP];
61 mp_size_t pn_pow[MAX_EXP];
62 // qp as quotient, rp as remainder, divp as divdend
63 mp_ptr qp, rp, divp;
64 mp_ptr prod;
65 mp_size_t divn = *nn, qn;
66 mp_size_t ret = 0;
67 int i, j;
68 pd_pow[0] = dp;
69 pn_pow[0] = dn;
70
72
73 qp = TALLOC_TYPE(*nn, mp_limb_t);
74 rp = TALLOC_TYPE(*nn, mp_limb_t);
75
76 divp = np;
77
78 for (i = 1; i < MAX_EXP; i++) {
79 // if qn == 0, means cannot be divided by pd_pow[i - 1]
80 if (qn = try_div_(qp, rp, divp, divn, pd_pow[i - 1], pn_pow[i - 1])) {
81 divn = qn;
82 LMMP_SWAP(qp, divp, mp_ptr);
83
84 ret += 1 << (i - 1);
85 pn_pow[i] = 2 * pn_pow[i - 1];
86 if (divn < pn_pow[i]) {
87 ++i;
88 break;
89 }
90 prod = TALLOC_TYPE(pn_pow[i], mp_limb_t);
91 lmmp_sqr_(prod, pd_pow[i - 1], pn_pow[i - 1]);
92 pn_pow[i] -= (prod[pn_pow[i] - 1] == 0) ? 1 : 0;
93 pd_pow[i] = prod;
94 } else {
95 break;
96 }
97 }
98 for (j = i - 1; j > 0; --j) {
99 if (qn = try_div_(qp, rp, divp, divn, pd_pow[j - 1], pn_pow[j - 1])) {
100 divn = qn;
101 LMMP_SWAP(qp, divp, mp_ptr);
102
103 ret += 1 << (j - 1);
104 }
105 }
106 if (qn == 0) {
107 // 无法整除
108 lmmp_copy(np, divp, divn);
109 *nn = divn;
110 } else {
111 // 整除
112 lmmp_copy(np, qp, qn);
113 *nn = qn;
114 }
115
116 TEMP_FREE;
117 return ret;
118}
mp_limb_t * mp_ptr
Definition lmmp.h:215
#define LMMP_SWAP(x, y, type)
Definition lmmp.h:352
#define lmmp_copy(dst, src, n)
Definition lmmp.h:364
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_param_assert(x)
Definition lmmp.h:398
static int lmmp_cmp_(mp_srcptr numa, mp_srcptr numb, mp_size_t n)
大数比较函数(内联)
Definition lmmpn.h:1004
void lmmp_sqr_(mp_ptr dst, mp_srcptr numa, mp_size_t na)
大数平方操作 [dst,2*na] = [numa,na]^2
Definition sqr.c:10
void lmmp_div_(mp_ptr dstq, mp_ptr dstr, mp_srcptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
大数除法和取模操作
Definition div.c:57
static int lmmp_zero_q_(mp_srcptr p, mp_size_t n)
大数判零函数(内联)
Definition lmmpn.h:1027
mp_size_t lmmp_remove_(mp_ptr np, mp_size_t *nn, mp_srcptr dp, mp_size_t dn)
除去[np,nn]中的[dp,dn]的因子
Definition remove.c:56
static mp_size_t try_div_(mp_ptr qp, mp_ptr rp, mp_srcptr divp, mp_size_t divn, mp_srcptr numb, mp_size_t nb)
qp 为商,rp 为余数,divp 为被除数,divn 为被除数长度,numb 为除数,nb 为除数长度 如果无法整除,则返回0,否则返回除数 qp 的长度
Definition remove.c:26
#define MAX_EXP
Definition remove.c:20
#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