LAMMP 4.2.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
from_str.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/base_table.h"
17#include "../../../include/lammp/impl/inlines.h"
18#include "../../../include/lammp/impl/mparam.h"
19#include "../../../include/lammp/impl/tmp_alloc.h"
20#include "../../../include/lammp/lmmpn.h"
21
22
24 lmmp_param_assert(base >= 2 && base <= 256);
25 if (src) {
26 do {
27 if (len == 0)
28 return 1;
29 } while (src[--len] == 0);
30 ++len;
31 }
32 return lmmp_mulh_(len, lmmp_bases_table[base - 2].lg_base) + 1;
33}
34
35/**
36 * @brief 将字符串转换为mp_limb_t数组
37 * @param dst 输出数组
38 * @param src 输入字符串
39 * @param len 字符串长度
40 * @param base 转换基数
41 * @warning src[len-1]!=0
42 * @return 返回转换后的limb数量
43 */
45 lmmp_param_assert(src[len - 1] != 0);
48 mp_size_t limbs = 0, i = len;
49
50 while (i) {
52 if (i >= digitspl) {
53 curlimb = src[--i];
54 for (mp_size_t j = 1; j < digitspl; ++j) {
55 curlimb = curlimb * base + src[--i];
56 }
57 } else {
58 curlimb = src[--i];
59 lbase = base;
60 while (i) {
61 curlimb = curlimb * base + src[--i];
62 lbase *= base;
63 }
64 }
65
66 if (limbs == 0) {
67 dst[0] = curlimb;
68 limbs = 1;
69 } else {
72 if (cy) {
73 dst[limbs] = cy;
74 ++limbs;
75 }
76 }
77 }
78
79 return limbs;
80}
81
82/**
83 * @brief 将字符串转换为mp_limb_t数组
84 * @param dst 输出数组
85 * @param src 输入字符串
86 * @param len 字符串长度
87 * @param pow 指数表
88 * @param tp 临时数组
89 * @warning src[len-1]!=0, sep(dst,tp)
90 * @note 第一层调用时:nh>=2, [dst,2*N], [tp,limbs]
91 * 后序递归时:N>=2, [dst,limbs+1], [tp,2*N-1]
92 * limbs为返回值,N = pow->np + pow->zeros
93 * @return 返回转换后的limb数量
94 */
97 const mp_byte_t* src,
101) {
102 lmmp_param_assert(src[len - 1] != 0);
104
107 } else {
108 mp_size_t pdigits = pow->digits;
109 if (len <= pdigits) {
111 } else {
112 mp_ptr p = pow->p;
113 mp_size_t np = pow->np;
114 mp_size_t zeros = pow->zeros;
115 mp_ptr lp = tp, hp = tp + np + zeros - 2; // overwrite 2 limbs
116 mp_size_t nl = 0, nh;
117
119 while (llen && src[llen - 1] == 0) --llen;
120 if (llen)
122
123 mp_limb_t save0 = hp[0], save1 = hp[1]; // save 2 limbs
125 if (nh >= np)
126 lmmp_mul_(dst + zeros, hp, nh, p, np);
127 else
128 lmmp_mul_(dst + zeros, p, np, hp, nh);
129 // restore 2 limbs
130 hp[0] = save0;
131 hp[1] = save1;
132
133 if (zeros < nl) {
134 lmmp_copy(dst, lp, zeros);
135 mp_limb_t cy = lmmp_add_n_(dst + zeros, dst + zeros, lp + zeros, nl - zeros);
136 // h*p+l<=(B^nh-1)*p+(p-1)<B^nh*p, limited by nh+np limbs,
137 // so inc won't overflow
138 if (cy)
139 lmmp_inc(dst + nl);
140 } else {
141 lmmp_copy(dst, lp, nl);
142 if (zeros > nl)
143 lmmp_zero(dst + nl, zeros - nl);
144 }
145
146 limbs = nh + np + zeros;
147 limbs -= dst[limbs - 1] == 0;
148 }
149 }
150
151 return limbs;
152}
153
155 lmmp_param_assert(base >= 2 && base <= 256);
156 do {
157 if (len == 0)
158 return 0;
159 } while (src[--len] == 0);
160 ++len;
161
163 if (LMMP_POW2_Q(base)) {
164 mp_limb_t curlimb = 0;
165 const mp_byte_t* srcend = src + len;
166 int bitspd = lmmp_bases_table[base - 2].large_base;
167 int bitpos = 0;
168 limbs = 0;
169
170 do {
172 curlimb |= curdigit << bitpos;
173 bitpos += bitspd;
174 if (bitpos >= LIMB_BITS) {
175 dst[limbs] = curlimb;
176 ++limbs;
177 bitpos -= LIMB_BITS;
178 curlimb = curdigit >> (bitspd - bitpos);
179 }
180 } while (++src != srcend);
181 if (curlimb) {
182 dst[limbs] = curlimb;
183 ++limbs;
184 }
185 } else if (lmmp_from_str_len_(0, len, base) < FROM_STR_BASEPOW_THRESHOLD) {
187 } else {
188 TEMP_DECL;
192 mp_size_t bexp, lexp = (len - 1) / digitspl + 1;
194 // need 1 extra limb to store result
197 mp_ptr tp;
198
199 int cpow = lmmp_limb_bits_(lexp - 1);
200
201 for (int i = cpow; i > 0; --i) {
202 // we will calculate lbase^bexp
203 bexp = ((lexp - 1) >> i) + 1;
204 // we will calculate lbase^(bexp-1) first, and trim it s. t.
205 // it contains at most 2 tailing 0 limb, then multiply it by lbase,
206 // so we need npow limbs to store lbase^bexp
207 mp_size_t npow = lmmp_from_str_len_(0, (bexp - 1) * digitspl + 1, base) + 1;
208
209 if (tzbit) {
210 mp_size_t tzlimb = tzbit * (bexp - 1) / LIMB_BITS;
211 if (tzlimb >= 2)
212 npow -= tzlimb - 2;
213 }
214
215 // space needed for a trimmed npow-limb lbase^bexp
216 alloc_size += npow;
217 }
218
220
221 for (int i = 0; i < 2; ++i) {
222 tp[0] = lbase;
223 powers[i].p = tp;
224 powers[i].np = 1;
225 tp += i + 1;
226 powers[i].zeros = 0;
227 powers[i].digits = digitspl * (i + 1);
228 powers[i].base = base;
229 }
230
231 mp_ptr p = powers[1].p;
232 mp_size_t zeros = 0, np = 1;
233 for (int i = 2; i < cpow; ++i) {
234 lmmp_sqr_(tp, p, np);
235 np *= 2;
236 np -= tp[np - 1] == 0;
237 bexp = (lexp - 1) >> (cpow - i);
238 if (bexp & 1) {
239 cy = lmmp_mul_1_(tp, tp, np, lbase);
240 tp[np] = cy;
241 np += cy != 0;
242 }
243 zeros *= 2;
244 while (tp[0] == 0) {
245 // at most 2 tailing 0 limb here
246 ++zeros;
247 ++tp;
248 --np;
249 }
250 p = tp;
251 powers[i].p = p;
252 powers[i].np = np;
253 powers[i].zeros = zeros;
254 powers[i].digits = digitspl * (bexp + 1);
255 powers[i].base = base;
256 tp += np + 1;
257 }
258
259 for (int i = 1; i < cpow; ++i) {
260 p = powers[i].p;
261 np = powers[i].np;
262 cy = lmmp_mul_1_(p, p, np, lbase);
263 p[np] = cy;
264 np += cy != 0;
265 if (p[0] == 0) {
266 ++powers[i].zeros;
267 ++p;
268 --np;
269 }
270
271 powers[i].p = p;
272 powers[i].np = np;
273 }
274
277
278 TEMP_FREE;
279 }
280 return limbs;
281}
int digits_in_limb
Definition base_table.h:34
const mp_base_t lmmp_bases_table[255]
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition base_table.c:18
mp_limb_t large_base
Definition base_table.h:25
mp_size_t lmmp_from_str_(mp_ptr dst, const mp_byte_t *src, mp_size_t len, int base)
字符串转大数操作 [src,len,base] to [dst,return value,B]
Definition from_str.c:154
static mp_size_t lmmp_from_str_basecase_(mp_ptr dst, const mp_byte_t *src, mp_size_t len, int base)
将字符串转换为mp_limb_t数组
Definition from_str.c:44
static mp_size_t lmmp_from_str_divide_(mp_ptr restrict dst, const mp_byte_t *src, mp_size_t len, mp_basepow_t *pow, mp_ptr restrict tp)
将字符串转换为mp_limb_t数组
Definition from_str.c:95
mp_size_t lmmp_from_str_len_(const mp_byte_t *src, mp_size_t len, int base)
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition from_str.c:23
#define lmmp_limb_bits_
Definition inlines.h:162
#define lmmp_sqr_
Definition inlines.h:166
#define lmmp_tailing_zeros_
Definition inlines.h:161
#define lmmp_mulh_
Definition inlines.h:165
mp_limb_t * mp_ptr
Definition lmmp.h:80
uint8_t mp_byte_t
Definition lmmp.h:75
#define lmmp_copy(dst, src, n)
Definition lmmp.h:367
#define lmmp_zero(dst, n)
Definition lmmp.h:369
#define LMMP_POW2_Q(n)
Definition lmmp.h:362
uint64_t mp_size_t
Definition lmmp.h:77
uint64_t mp_limb_t
Definition lmmp.h:76
#define LIMB_BITS
Definition lmmp.h:86
#define lmmp_param_assert(x)
Definition lmmp.h:401
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:1103
#define lmmp_inc(p)
大数加1宏(预期无进位)
Definition lmmpn.h:938
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]
mp_limb_t lmmp_mul_1_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_limb_t x)
大数乘以单limb操作 [dst,na] = [numa,na] * x
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:81
#define FROM_STR_BASEPOW_THRESHOLD
Definition mparam.h:74
#define FROM_STR_DIVIDE_THRESHOLD
Definition mparam.h:72
#define tp
#define n
#define TEMP_DECL
Definition tmp_alloc.h:131
#define TEMP_FREE
Definition tmp_alloc.h:150
#define BALLOC_TYPE(n, type)
Definition tmp_alloc.h:146