LAMMP 4.1.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)
 
static mp_size_t lmmp_to_str_divide_ (mp_byte_t *dst, mp_ptr numa, mp_size_t na, mp_basepow_t *pow, mp_ptr tpq)
 
mp_size_t lmmp_to_str_len_ (mp_srcptr numa, mp_size_t na, int base)
 计算大数转换为字符串,字符串需要的缓冲区长度
 

函数说明

◆ 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.c147 行定义.

147 {
148 do {
149 if (na == 0)
150 return 0;
151 } while (numa[--na] == 0);
152 ++na;
153
154 mp_size_t digits;
155 if (LMMP_POW2_Q(base)) {
156 mp_limb_t curlimb = numa[na - 1];
157 int cnt = lmmp_bases_table[base - 2].large_base;
158 int bitsh = lmmp_limb_bits_(curlimb);
159 int mask = (1 << cnt) - 1;
160 mp_size_t bits = bitsh + LIMB_BITS * (na - 1);
161 digits = (bits - 1) / cnt + 1;
162 dst += digits;
163 int bitpos = digits * cnt - LIMB_BITS * (na - 1);
164
165 do {
166 while ((bitpos -= cnt) >= 0) {
167 *--dst = curlimb >> bitpos & mask;
168 }
169 if (--na == 0)
170 break;
171 mp_limb_t prevlimb = curlimb << -bitpos;
172 curlimb = numa[na - 1];
173 bitpos += LIMB_BITS;
174 *--dst = (prevlimb | curlimb >> bitpos) & mask;
175 } while (1);
176 } else if (na < TO_STR_BASEPOW_THRESHOLD) {
177 digits = lmmp_to_str_basecase_(dst, numa, na, base);
178 } else {
179 TEMP_DECL;
180 mp_basepow_t powers[LIMB_BITS];
181 mp_size_t exps[LIMB_BITS];
182 mp_limb_t lbase = lmmp_bases_table[base - 2].large_base;
183 mp_size_t digitspl = lmmp_bases_table[base - 2].digits_in_limb;
184 mp_size_t bexp = (lmmp_to_str_len_(numa, na, base) - 1) / digitspl + 1;
185 mp_size_t tzbit = lmmp_tailing_zeros_(lbase);
186 // numa 的拷贝空间,多一个 limb 预留规整化移位所需
187 mp_size_t alloc_size = na + 1;
188 mp_limb_t cy;
189 mp_ptr tp;
190
191 int cpow = 0;
192
193 do {
194 bexp = (bexp + 1) >> 1;
195 exps[cpow] = bexp;
196 ++cpow;
197
198 // we will calculate lbase^(bexp-1) first, and trim it s. t.
199 // it contains at most 2 tailing 0 limb, then multiply it by lbase,
200 // so we need npow limbs to store lbase^bexp
201 mp_size_t npow = lmmp_from_str_len_(0, (bexp - 1) * digitspl + 1, base) + 1;
202
203 // space needed for quotients in recursive calls,
204 // quotients are smaller than lbase^bexp
205 alloc_size += npow + 1;
206
207 if (tzbit) {
208 mp_size_t tzlimb = tzbit * (bexp - 1) / LIMB_BITS;
209 if (tzlimb >= 2)
210 npow -= tzlimb - 2;
211 }
212
213 // space needed for a trimmed npow-limb lbase^bexp and its inverse
214 alloc_size += npow * 2;
215 } while (bexp > 1);
216
217 tp = BALLOC_TYPE(alloc_size, mp_limb_t);
218
219 for (int i = 0; i < 2; ++i) {
220 tp[0] = lbase;
221 powers[i].p = tp;
222 powers[i].np = 1;
223 tp += i + 1;
224 powers[i].zeros = 0;
225 powers[i].digits = digitspl * (i + 1);
226 powers[i].base = base;
227 }
228
229 mp_ptr p = powers[1].p;
230 mp_size_t zeros = 0, np = 1;
231 bexp = 1;
232 for (int i = 2; i < cpow; ++i) {
233 lmmp_sqr_(tp, p, np);
234 bexp *= 2;
235 np *= 2;
236 np -= tp[np - 1] == 0;
237 if (bexp + 1 < exps[cpow - 1 - i]) {
238 cy = lmmp_mul_1_(tp, tp, np, lbase);
239 tp[np] = cy;
240 np += cy != 0;
241 ++bexp;
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 // Note: all powers except powers[0] are normalized
275 // ASSERT: powers[0] will be never used in lmmp_to_str_divide_
276 // i.e. TO_STR_DIVIDE_THRESHOLD >= 3
277 int cnt = lmmp_leading_zeros_(p[np - 1]);
278 if (powers[i].norm_cnt = cnt)
279 lmmp_shl_(p, p, np, cnt);
280
281 if (np < DIV_MULINV_L_THRESHOLD) {
282 // use divs, no need to compute inv
283 powers[i].invp = 0;
284 powers[i].ni = 0;
285 } else {
286 // pre-compute inverse
287 mp_size_t ni = lmmp_div_inv_size_(np + powers[i].zeros, np);
288 lmmp_inv_prediv_(tp, p, np, ni);
289 powers[i].invp = tp;
290 powers[i].ni = ni;
291 tp += ni;
292 }
293 }
294
295 lmmp_copy(tp, numa, na);
296 digits = lmmp_to_str_divide_(dst, tp, na, powers + cpow - 1, tp + na + 1);
297
298 TEMP_FREE;
299 }
300
301 return digits;
302}
mp_size_t ni
Definition base_table.h:50
int digits_in_limb
Definition base_table.h:37
mp_size_t digits
Definition base_table.h:54
mp_ptr invp
Definition base_table.h:48
mp_size_t np
Definition base_table.h:46
const mp_base_t lmmp_bases_table[255]
Definition base_table.c:9
mp_limb_t large_base
Definition base_table.h:28
mp_size_t zeros
Definition base_table.h:52
mp_limb_t * mp_ptr
Definition lmmp.h:215
#define lmmp_copy(dst, src, n)
Definition lmmp.h:364
#define LMMP_POW2_Q(n)
Definition lmmp.h:359
uint64_t mp_size_t
Definition lmmp.h:212
uint64_t mp_limb_t
Definition lmmp.h:211
#define LIMB_BITS
Definition lmmp.h:221
static mp_size_t lmmp_div_inv_size_(mp_size_t nq, mp_size_t nb)
计算预计算逆元的尺寸
Definition lmmpn.h:812
int lmmp_leading_zeros_(mp_limb_t x)
计算一个单精度数(limb)中前导零的个数
Definition tiny.c:35
int lmmp_tailing_zeros_(mp_limb_t x)
计算一个单精度数(limb)中末尾零的个数
Definition tiny.c:54
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
void lmmp_sqr_(mp_ptr dst, mp_srcptr numa, mp_size_t na)
大数平方操作 [dst,2*na] = [numa,na]^2
Definition sqr.c:10
int lmmp_limb_bits_(mp_limb_t x)
计算满足 2^k > x 的最小自然数k
Definition tiny.c:11
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:9
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:13
#define DIV_MULINV_L_THRESHOLD
Definition mparam.h:28
#define TO_STR_BASEPOW_THRESHOLD
Definition mparam.h:70
#define tp
#define TEMP_DECL
Definition tmp_alloc.h:72
#define TEMP_FREE
Definition tmp_alloc.h:93
#define BALLOC_TYPE(n, type)
Definition tmp_alloc.h:89
static mp_size_t lmmp_to_str_basecase_(mp_byte_t *dst, mp_srcptr numa, mp_size_t na, int base)
Definition to_str.c:26
mp_size_t lmmp_to_str_len_(mp_srcptr numa, mp_size_t na, int base)
计算大数转换为字符串,字符串需要的缓冲区长度
Definition to_str.c:12
static mp_size_t lmmp_to_str_divide_(mp_byte_t *dst, mp_ptr numa, mp_size_t na, mp_basepow_t *pow, mp_ptr tpq)
Definition to_str.c:69

引用了 BALLOC_TYPE, mp_basepow_t::base, mp_basepow_t::digits, mp_base_t::digits_in_limb, DIV_MULINV_L_THRESHOLD, mp_basepow_t::invp, 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_POW2_Q, lmmp_shl_(), lmmp_sqr_(), lmmp_tailing_zeros_(), lmmp_to_str_basecase_(), lmmp_to_str_divide_(), lmmp_to_str_len_(), mp_basepow_t::ni, mp_basepow_t::np, mp_basepow_t::p, TEMP_DECL, TEMP_FREE, TO_STR_BASEPOW_THRESHOLD, tp , 以及 mp_basepow_t::zeros.

+ 函数调用图:

◆ 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

在文件 to_str.c26 行定义.

26 {
27 lmmp_param_assert(na > 0);
28 lmmp_param_assert(numa[na - 1]!= 0);
29 int i;
30 int digitspl = lmmp_bases_table[base - 2].digits_in_limb;
31 mp_limb_t lbase = lmmp_bases_table[base - 2].large_base;
32 mp_size_t n = 0;
33 mp_limb_t frac;
35 lmmp_copy(tp + 1, numa, na);
36
37 do {
38 tp[0] = 0;
39 lmmp_div_1_(tp, tp, na + 1, lbase);
40 frac = tp[0] + 1;
41 na -= tp[na] == 0;
42 if (na == 0)
43 break;
44 i = digitspl;
45 do {
46 dst[--i] = lmmp_mulh_(frac, base);
47 frac *= base;
48 } while (i);
49 dst += digitspl;
50 n += digitspl;
51 } while (1);
52
53 mp_byte_t msbyte;
54 i = digitspl;
55 while (i && (msbyte = lmmp_mulh_(frac, base)) == 0) {
56 --i;
57 frac *= base;
58 }
59 n += i;
60 while (i) {
61 dst[--i] = msbyte;
62 frac *= base;
63 msbyte = lmmp_mulh_(frac, base);
64 }
65 return n;
66}
uint8_t mp_byte_t
Definition lmmp.h:210
#define lmmp_param_assert(x)
Definition lmmp.h:398
mp_limb_t lmmp_div_1_(mp_ptr dstq, mp_srcptr numa, mp_size_t na, mp_limb_t x)
单精度数除法
Definition div.c:66
mp_limb_t lmmp_mulh_(mp_limb_t a, mp_limb_t b)
计算两个64位无符号整数相乘的高位结果 (a*b)/2^64
Definition tiny.c:73

引用了 mp_base_t::digits_in_limb, mp_base_t::large_base, lmmp_bases_table, lmmp_copy, lmmp_div_1_(), lmmp_mulh_(), lmmp_param_assert, 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  numa,
mp_size_t  na,
mp_basepow_t pow,
mp_ptr  tpq 
)
static

在文件 to_str.c69 行定义.

75 {
76 lmmp_param_assert(na > 0);
77 lmmp_param_assert(numa[na - 1] != 0);
78 lmmp_param_assert(pow != NULL);
79 mp_size_t digits;
80 if (na < TO_STR_DIVIDE_THRESHOLD) {
81 digits = lmmp_to_str_basecase_(dst, numa, na, pow->base);
82 } else {
83 mp_ptr p = pow->p, invp = pow->invp;
84 mp_size_t np = pow->np, ni = pow->ni;
85 mp_size_t zeros = pow->zeros;
86 mp_size_t pdigits = pow->digits;
87 int cnt = pow->norm_cnt;
88 int adjust = 0;
89
90 // may adjust na s.t. qh=0
91 if (na >= np + zeros) {
92 mp_limb_t ah = 0, al = numa[na - 1] << cnt;
93 if (cnt) {
94 ah = numa[na - 1] >> (LIMB_BITS - cnt);
95 if (na > zeros + 1)
96 al |= numa[na - 2] >> (LIMB_BITS - cnt);
97 }
98 adjust = (ah || al >= p[np - 1]);
99 }
100
101 // if numa<p
102 if (na + adjust <= np + zeros) {
103 // skip this power
104 digits = lmmp_to_str_divide_(dst, numa, na, pow - 1, tpq);
105 } else {
106 numa[na] = 0;
107 na += adjust;
108
109 numa += zeros;
110 na -= zeros;
111
112 mp_size_t nq = na - np, nr = np + zeros;
113 mp_ptr q = tpq, r = numa - zeros;
114
115 if (cnt)
116 lmmp_shl_(numa, numa, na, cnt);
117 if (invp)
118 lmmp_div_mulinv_(q, numa, na, p, np, invp, ni);
119 else
120 lmmp_div_s_(q, numa, na, p, np);
121 if (cnt)
122 lmmp_shr_(numa, numa, np, cnt);
123
124 mp_size_t digitsh = 0, digitsl = 0;
125
126 while (nq && q[nq - 1] == 0) --nq;
127 if (nq)
128 digitsh = lmmp_to_str_divide_(dst + pdigits, q, nq, pow - 1, tpq + nq + 1);
129
130 while (nr && r[nr - 1] == 0) --nr;
131 if (nr)
132 digitsl = lmmp_to_str_divide_(dst, r, nr, pow - 1, tpq);
133
134 if (digitsh) {
135 while (digitsl != pdigits) {
136 dst[digitsl] = 0;
137 ++digitsl;
138 }
139 }
140
141 digits = digitsl + digitsh;
142 }
143 }
144 return digits;
145}
mp_limb_t lmmp_div_s_(mp_ptr dstq, mp_ptr numa, mp_size_t na, mp_srcptr numb, mp_size_t nb)
除法运算
Definition div.c:11
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:9
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
#define TO_STR_DIVIDE_THRESHOLD
Definition mparam.h:68

引用了 mp_basepow_t::base, mp_basepow_t::digits, mp_basepow_t::invp, LIMB_BITS, lmmp_div_mulinv_(), lmmp_div_s_(), lmmp_param_assert, lmmp_shl_(), lmmp_shr_(), lmmp_to_str_basecase_(), lmmp_to_str_divide_(), mp_basepow_t::ni, mp_basepow_t::norm_cnt, mp_basepow_t::np, mp_basepow_t::p, TO_STR_DIVIDE_THRESHOLD , 以及 mp_basepow_t::zeros.

被这些函数引用 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 
)

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

参数
numa输入大数,长度为na
na大数的 limb 长度
base目标基数(2~256)
返回
大数在指定基数下的位数
警告
na>=0, 2<=base<=256
注解
将会忽略numa的前导零,
  1. if (numa!=NULL) 返回的长度可能会多分配一个字符空间
  2. if (numa==NULL) 返回na个limb长度的数的最大可能字符长度(最坏情况)

在文件 to_str.c12 行定义.

12 {
13 lmmp_param_assert(base >= 2 && base <= 256);
14 int mslbits = 0;
15 if (numa) {
16 do {
17 if (na == 0)
18 return 1;
19 } while (numa[--na] == 0);
20 mslbits = lmmp_limb_bits_(numa[na]);
21 }
22 return lmmp_mulh_(na * LIMB_BITS + mslbits, lmmp_bases_table[base - 2].inv_lg_base) + 1;
23}

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

被这些函数引用 lmmp_to_str_().

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