LAMMP 4.2.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
remove.c
浏览该文件的文档.
1/**
2 * Copyright (C) 2026 HJimmyK(Jericho Knox)
3 *
4 * This file is part of LAMMP.
5 *
6 * LAMMP is free software: you can redistribute it and/or modify it under
7 * the terms of the GNU Lesser General Public License (LGPL) as published
8 * by the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed WITHOUT ANY WARRANTY.
12 *
13 * See <https://www.gnu.org/licenses/>.
14 */
15
16#include "../../../include/lammp/impl/inlines.h"
17#include "../../../include/lammp/impl/tmp_alloc.h"
18#include "../../../include/lammp/lmmpn.h"
19#include "../../../include/lammp/numth.h"
20
21
22/*
23事实上,我们可以知道,[np,nn]至多为[dp,dn]的2^64次方
242^64 - 1 - 2 - 4 - 8 - ... - 2^63 最为接近2^64
25故,理论上MAX_EXP = 63
26
27但是,实际上,[np,nn]几乎不可能超过[dp,dn]的2^48次方
282^48 - 1 - 2 - 4 - 8 - ... - 2^47 最为接近2^48
29故,我们使用MAX_EXP = 48
30*/
31#define MAX_EXP 48
32
33/**
34 * qp 为商,rp 为余数,divp 为被除数,divn 为被除数长度,numb 为除数,nb 为除数长度
35 * 如果无法整除,则返回0,否则返回除数 qp 的长度
36 */
38 if (divn < nb) {
39 return 0;
40 } else {
41 int cmp;
42 if (divn > nb)
43 cmp = 1;
44 else
46 if (cmp == 0) {
47 qp[0] = 1;
48 return 1;
49 } else if (cmp < 0) {
50 return 0;
51 } else {
52 // 拷贝原始数,当无法整除时,再进行恢复
54 if (lmmp_zero_q_(rp, nb)) {
55 // 整除
56 divn = divn - nb + 1;
57 while (divn > 0 && qp[divn - 1] == 0) --divn;
58 return divn;
59 } else {
60 // 无法整除
61 return 0;
62 }
63 }
64 }
65}
66
68 lmmp_param_assert(np != NULL && *nn > 0);
69 lmmp_param_assert(dp != NULL && dn > 0);
70
73 // qp as quotient, rp as remainder, divp as divdend
74 mp_ptr qp, rp, divp;
76 mp_size_t divn = *nn, qn;
77 mp_size_t ret = 0;
78 int i, j;
79 pd_pow[0] = dp;
80 pn_pow[0] = dn;
81
83
84 qp = TALLOC_TYPE(*nn, mp_limb_t);
85 rp = TALLOC_TYPE(*nn, mp_limb_t);
86
87 divp = np;
88
89 for (i = 1; i < MAX_EXP; i++) {
90 // if qn == 0, means cannot be divided by pd_pow[i - 1]
91 if ((qn = try_div_(qp, rp, divp, divn, pd_pow[i - 1], pn_pow[i - 1]))) {
92 divn = qn;
94
95 ret += (mp_size_t)1 << (i - 1);
96 pn_pow[i] = 2 * pn_pow[i - 1];
97 if (divn < pn_pow[i]) {
98 ++i;
99 break;
100 }
102 lmmp_sqr_(prod, pd_pow[i - 1], pn_pow[i - 1]);
103 pn_pow[i] -= (prod[pn_pow[i] - 1] == 0) ? 1 : 0;
104 pd_pow[i] = prod;
105 } else {
106 break;
107 }
108 }
109 for (j = i - 1; j > 0; --j) {
110 if ((qn = try_div_(qp, rp, divp, divn, pd_pow[j - 1], pn_pow[j - 1]))) {
111 divn = qn;
113
114 ret += (mp_size_t)1 << (j - 1);
115 }
116 }
117 if (qn == 0) {
118 // 无法整除
119 lmmp_copy(np, divp, divn);
120 *nn = divn;
121 } else {
122 // 整除
123 lmmp_copy(np, qp, qn);
124 *nn = qn;
125 }
126
127 TEMP_FREE;
128 return ret;
129}
#define lmmp_sqr_
Definition inlines.h:166
mp_limb_t * mp_ptr
Definition lmmp.h:80
#define LMMP_SWAP(x, y, type)
Definition lmmp.h:355
#define lmmp_copy(dst, src, n)
Definition lmmp.h:367
uint64_t mp_size_t
Definition lmmp.h:77
const mp_limb_t * mp_srcptr
Definition lmmp.h:81
uint64_t mp_limb_t
Definition lmmp.h:76
#define lmmp_param_assert(x)
Definition lmmp.h:401
static int lmmp_cmp_(mp_srcptr numa, mp_srcptr numb, mp_size_t n)
大数比较函数(内联)
Definition lmmpn.h:996
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:74
static int lmmp_zero_q_(mp_srcptr p, mp_size_t n)
大数判零函数(内联)
Definition lmmpn.h:1019
#define numb
#define n
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:37
#define MAX_EXP
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition remove.c:31
mp_size_t lmmp_remove_(mp_ptr np, mp_size_t *restrict nn, mp_srcptr dp, mp_size_t dn)
Definition remove.c:67
#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