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

浏览源代码.

函数

mp_size_t lmmp_to_str_ (mp_byte_t *dst, mp_srcptr numa, mp_size_t na, int base)
 大数转字符串操作 [numa,na,B] to [dst,return value,base]
 
static mp_size_t lmmp_to_str_basecase_ (mp_byte_t *dst, mp_srcptr numa, mp_size_t na, int base)
 将mp_limb_t数组转换为字符串
 
static mp_size_t lmmp_to_str_divide_ (mp_byte_t *dst, mp_ptr restrict numa, mp_size_t na, mp_basepow_t *pow, mp_ptr restrict tpq)
 将mp_limb_t数组转换为字符串
 
mp_size_t lmmp_to_str_len_ (mp_srcptr numa, mp_size_t na, int base)
 Copyright (C) 2026 HJimmyK(Jericho Knox)
 

函数说明

◆ lmmp_to_str_()

mp_size_t lmmp_to_str_ ( mp_byte_t dst,
mp_srcptr  numa,
mp_size_t  na,
int  base 
)

大数转字符串操作 [numa,na,B] to [dst,return value,base]

警告
na>=0, 2<=base<=256
参数
dst字符串结果输出指针
numa大数源指针
na大数的 limb 长度
base目标字符串的进制基数
返回
转换后的字符串长度

在文件 to_str.c175 行定义.

175 {
176 lmmp_param_assert(base >= 2 && base <= 256);
177 do {
178 if (na == 0)
179 return 0;
180 } while (numa[--na] == 0);
181 ++na;
182
183 mp_size_t digits;
184 if (LMMP_POW2_Q(base)) {
185 mp_limb_t curlimb = numa[na - 1];
186 int cnt = lmmp_bases_table[base - 2].large_base;
188 int mask = (1 << cnt) - 1;
189 mp_size_t bits = bitsh + LIMB_BITS * (na - 1);
190 digits = (bits - 1) / cnt + 1;
191 dst += digits;
192 int bitpos = digits * cnt - LIMB_BITS * (na - 1);
193
194 do {
195 while ((bitpos -= cnt) >= 0) {
196 *--dst = curlimb >> bitpos & mask;
197 }
198 if (--na == 0)
199 break;
201 curlimb = numa[na - 1];
202 bitpos += LIMB_BITS;
203 *--dst = (prevlimb | curlimb >> bitpos) & mask;
204 } while (1);
205 } else if (na < TO_STR_BASEPOW_THRESHOLD) {
206 digits = lmmp_to_str_basecase_(dst, numa, na, base);
207 } else {
208 TEMP_DECL;
213 mp_size_t bexp = (lmmp_to_str_len_(numa, na, base) - 1) / digitspl + 1;
215 // numa 的拷贝空间,多一个 limb 预留规整化移位所需
216 mp_size_t alloc_size = na + 1;
218 mp_ptr tp;
219
220 int cpow = 0;
221
222 do {
223 bexp = (bexp + 1) >> 1;
224 exps[cpow] = bexp;
225 ++cpow;
226
227 // we will calculate lbase^(bexp-1) first, and trim it s. t.
228 // it contains at most 2 tailing 0 limb, then multiply it by lbase,
229 // so we need npow limbs to store lbase^bexp
230 mp_size_t npow = lmmp_from_str_len_(0, (bexp - 1) * digitspl + 1, base) + 1;
231
232 // space needed for quotients in recursive calls,
233 // quotients are smaller than lbase^bexp
234 alloc_size += npow + 1;
235
236 if (tzbit) {
237 mp_size_t tzlimb = tzbit * (bexp - 1) / LIMB_BITS;
238 if (tzlimb >= 2)
239 npow -= tzlimb - 2;
240 }
241
242 // space needed for a trimmed npow-limb lbase^bexp and its inverse
243 alloc_size += npow * 2;
244 } while (bexp > 1);
245
247
248 for (int i = 0; i < 2; ++i) {
249 tp[0] = lbase;
250 powers[i].p = tp;
251 powers[i].np = 1;
252 tp += i + 1;
253 powers[i].zeros = 0;
254 powers[i].digits = digitspl * (i + 1);
255 powers[i].base = base;
256 }
257
258 mp_ptr p = powers[1].p;
259 mp_size_t zeros = 0, np = 1;
260 bexp = 1;
261 for (int i = 2; i < cpow; ++i) {
262 lmmp_sqr_(tp, p, np);
263 bexp *= 2;
264 np *= 2;
265 np -= tp[np - 1] == 0;
266 if (bexp + 1 < exps[cpow - 1 - i]) {
267 cy = lmmp_mul_1_(tp, tp, np, lbase);
268 tp[np] = cy;
269 np += cy != 0;
270 ++bexp;
271 }
272 zeros *= 2;
273 while (tp[0] == 0) {
274 // at most 2 tailing 0 limb here
275 ++zeros;
276 ++tp;
277 --np;
278 }
279 p = tp;
280 powers[i].p = p;
281 powers[i].np = np;
282 powers[i].zeros = zeros;
283 powers[i].digits = digitspl * (bexp + 1);
284 powers[i].base = base;
285 tp += np + 1;
286 }
287
288 for (int i = 1; i < cpow; ++i) {
289 p = powers[i].p;
290 np = powers[i].np;
291 cy = lmmp_mul_1_(p, p, np, lbase);
292 p[np] = cy;
293 np += cy != 0;
294 if (p[0] == 0) {
295 ++powers[i].zeros;
296 ++p;
297 --np;
298 }
299
300 powers[i].p = p;
301 powers[i].np = np;
302
303 // Note: all powers except powers[0] are normalized
304 // ASSERT: powers[0] will be never used in lmmp_to_str_divide_
305 // i.e. TO_STR_DIVIDE_THRESHOLD >= 3
306 int cnt = lmmp_leading_zeros_(p[np - 1]);
307 if ((powers[i].norm_cnt = cnt))
308 lmmp_shl_(p, p, np, cnt);
309
310 if (np < DIV_MULINV_L_THRESHOLD) {
311 // use divs, no need to compute inv
312 powers[i].invp = 0;
313 powers[i].ni = 0;
314 } else {
315 // pre-compute inverse
316 mp_size_t ni = lmmp_div_inv_size_(np + powers[i].zeros, np);
317 lmmp_inv_prediv_(tp, p, np, ni);
318 powers[i].invp = tp;
319 powers[i].ni = ni;
320 tp += ni;
321 }
322 }
323
324 lmmp_copy(tp, numa, na);
325 digits = lmmp_to_str_divide_(dst, tp, na, powers + cpow - 1, tp + na + 1);
326
327 TEMP_FREE;
328 }
329
330 return digits;
331}
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
#define lmmp_limb_bits_
Definition inlines.h:162
#define lmmp_leading_zeros_
Definition inlines.h:160
#define lmmp_sqr_
Definition inlines.h:166
#define lmmp_tailing_zeros_
Definition inlines.h:161
mp_limb_t * mp_ptr
Definition lmmp.h:80
#define lmmp_copy(dst, src, n)
Definition lmmp.h:367
#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_size_t lmmp_div_inv_size_(mp_size_t nq, mp_size_t nb)
计算预计算逆元的尺寸
Definition lmmpn.h:804
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:22
mp_limb_t lmmp_shl_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t shl)
大数左移操作 [dst,na] = [numa,na]<<shl,dst的低shl位填充0
Definition shl.c:19
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_size_t lmmp_from_str_len_(const mp_byte_t *src, mp_size_t len, int base)
计算字符串转大数所需的 limb 缓冲区长度
Definition from_str.c:23
#define DIV_MULINV_L_THRESHOLD
Definition mparam.h:28
#define TO_STR_BASEPOW_THRESHOLD
Definition mparam.h:70
#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
static mp_size_t lmmp_to_str_divide_(mp_byte_t *dst, mp_ptr restrict numa, mp_size_t na, mp_basepow_t *pow, mp_ptr restrict tpq)
将mp_limb_t数组转换为字符串
Definition to_str.c:97
static mp_size_t lmmp_to_str_basecase_(mp_byte_t *dst, mp_srcptr numa, mp_size_t na, int base)
将mp_limb_t数组转换为字符串
Definition to_str.c:45
mp_size_t lmmp_to_str_len_(mp_srcptr numa, mp_size_t na, int base)
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition to_str.c:23

引用了 BALLOC_TYPE, mp_base_t::digits_in_limb, DIV_MULINV_L_THRESHOLD, mp_base_t::large_base, LIMB_BITS, lmmp_bases_table, lmmp_copy, lmmp_div_inv_size_(), lmmp_from_str_len_(), lmmp_inv_prediv_(), lmmp_leading_zeros_, lmmp_limb_bits_, lmmp_mul_1_(), lmmp_param_assert, LMMP_POW2_Q, lmmp_shl_(), lmmp_sqr_, lmmp_tailing_zeros_, lmmp_to_str_basecase_(), lmmp_to_str_divide_(), lmmp_to_str_len_(), n, TEMP_DECL, TEMP_FREE, TO_STR_BASEPOW_THRESHOLD , 以及 tp.

+ 函数调用图:

◆ lmmp_to_str_basecase_()

static mp_size_t lmmp_to_str_basecase_ ( mp_byte_t dst,
mp_srcptr  numa,
mp_size_t  na,
int  base 
)
static

将mp_limb_t数组转换为字符串

参数
dst输出字符串
numa输入数组
na输入数组长度
base转换基数
警告
numa[na-1]!=0
返回
返回转换后的字符串长度

在文件 to_str.c45 行定义.

45 {
47 lmmp_param_assert(numa[na - 1]!= 0);
48 int i;
51 mp_size_t n = 0;
54 lmmp_copy(tp + 1, numa, na);
55
56 do {
57 tp[0] = 0;
58 lmmp_div_1_(tp, tp, na + 1, lbase);
59 frac = tp[0] + 1;
60 na -= tp[na] == 0;
61 if (na == 0)
62 break;
63 i = digitspl;
64 do {
65 dst[--i] = lmmp_mulh_(frac, base);
66 frac *= base;
67 } while (i);
68 dst += digitspl;
69 n += digitspl;
70 } while (1);
71
73 i = digitspl;
74 while (i && (msbyte = lmmp_mulh_(frac, base)) == 0) {
75 --i;
76 frac *= base;
77 }
78 n += i;
79 while (i) {
80 dst[--i] = msbyte;
81 frac *= base;
82 msbyte = lmmp_mulh_(frac, base);
83 }
84 return n;
85}
#define lmmp_mulh_
Definition inlines.h:165
uint8_t mp_byte_t
Definition lmmp.h:75
mp_limb_t lmmp_div_1_(mp_ptr dstq, mp_srcptr numa, mp_size_t na, mp_limb_t x)
单精度数除法
Definition div.c:77

引用了 mp_base_t::digits_in_limb, mp_base_t::large_base, lmmp_bases_table, lmmp_copy, lmmp_div_1_(), lmmp_mulh_, lmmp_param_assert, n, TO_STR_BASEPOW_THRESHOLD , 以及 tp.

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

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

◆ lmmp_to_str_divide_()

static mp_size_t lmmp_to_str_divide_ ( mp_byte_t dst,
mp_ptr restrict  numa,
mp_size_t  na,
mp_basepow_t pow,
mp_ptr restrict  tpq 
)
static

将mp_limb_t数组转换为字符串

参数
dst输出字符串
numa输入数组
na输入数组长度
pow指数表
tpq临时数组
警告
numa[na-1]!=0, sep(dst,tpq)
返回
返回转换后的字符串长度

在文件 to_str.c97 行定义.

103 {
105 lmmp_param_assert(numa[na - 1] != 0);
107 mp_size_t digits;
109 digits = lmmp_to_str_basecase_(dst, numa, na, pow->base);
110 } else {
111 mp_ptr p = pow->p, invp = pow->invp;
112 mp_size_t np = pow->np, ni = pow->ni;
113 mp_size_t zeros = pow->zeros;
114 mp_size_t pdigits = pow->digits;
115 int cnt = pow->norm_cnt;
116 int adjust = 0;
117
118 // may adjust na s.t. qh=0
119 if (na >= np + zeros) {
120 mp_limb_t ah = 0, al = numa[na - 1] << cnt;
121 if (cnt) {
122 ah = numa[na - 1] >> (LIMB_BITS - cnt);
123 if (na > zeros + 1)
124 al |= numa[na - 2] >> (LIMB_BITS - cnt);
125 }
126 adjust = (ah || al >= p[np - 1]);
127 }
128
129 // if numa<p
130 if (na + adjust <= np + zeros) {
131 // skip this power
132 digits = lmmp_to_str_divide_(dst, numa, na, pow - 1, tpq);
133 } else {
134 numa[na] = 0;
135 na += adjust;
136
137 numa += zeros;
138 na -= zeros;
139
140 mp_size_t nq = na - np, nr = np + zeros;
141 mp_ptr q = tpq, r = numa - zeros;
142
143 if (cnt)
145 if (invp)
146 lmmp_div_mulinv_(q, numa, na, p, np, invp, ni);
147 else
148 lmmp_div_s_(q, numa, na, p, np);
149 if (cnt)
150 lmmp_shr_(numa, numa, np, cnt);
151
152 mp_size_t digitsh = 0, digitsl = 0;
153
154 while (nq && q[nq - 1] == 0) --nq;
155 if (nq)
156 digitsh = lmmp_to_str_divide_(dst + pdigits, q, nq, pow - 1, tpq + nq + 1);
157
158 while (nr && r[nr - 1] == 0) --nr;
159 if (nr)
161
162 if (digitsh) {
163 while (digitsl != pdigits) {
164 dst[digitsl] = 0;
165 ++digitsl;
166 }
167 }
168
169 digits = digitsl + digitsh;
170 }
171 }
172 return digits;
173}
mp_limb_t lmmp_div_s_(mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
除法运算
mp_limb_t lmmp_shr_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_size_t shr)
大数右移操作 [dst,na] = [numa,na]>>shr,dst的高shr位填充0
Definition shr.c:19
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)
乘法逆元除法
#define TO_STR_DIVIDE_THRESHOLD
Definition mparam.h:68

引用了 LIMB_BITS, lmmp_div_mulinv_(), lmmp_div_s_(), lmmp_param_assert, lmmp_shl_(), lmmp_shr_(), lmmp_to_str_basecase_(), lmmp_to_str_divide_(), n , 以及 TO_STR_DIVIDE_THRESHOLD.

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

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

◆ lmmp_to_str_len_()

mp_size_t lmmp_to_str_len_ ( mp_srcptr  numa,
mp_size_t  na,
int  base 
)

Copyright (C) 2026 HJimmyK(Jericho Knox)

计算大数转换为字符串,字符串需要的缓冲区长度

This file is part of LAMMP.

LAMMP is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

This program is distributed WITHOUT ANY WARRANTY.

See https://www.gnu.org/licenses/.

在文件 to_str.c23 行定义.

23 {
24 lmmp_param_assert(base >= 2 && base <= 256);
25 int mslbits = 0;
26 if (numa) {
27 do {
28 if (na == 0)
29 return 1;
30 } while (numa[--na] == 0);
32 }
33 return lmmp_mulh_(na * LIMB_BITS + mslbits, lmmp_bases_table[base - 2].inv_lg_base) + 1;
34}

引用了 LIMB_BITS, lmmp_bases_table, lmmp_limb_bits_, lmmp_mulh_, lmmp_param_assert , 以及 n.

被这些函数引用 lmmp_to_str_().

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