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

浏览源代码.

函数

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]
 
static mp_size_t lmmp_from_str_basecase_ (mp_ptr dst, const mp_byte_t *src, mp_size_t len, int base)
 
static mp_size_t lmmp_from_str_divide_ (mp_ptr dst, const mp_byte_t *src, mp_size_t len, mp_basepow_t *pow, mp_ptr tp)
 
mp_size_t lmmp_from_str_len_ (const mp_byte_t *src, mp_size_t len, int base)
 计算字符串转大数所需的 limb 缓冲区长度
 

函数说明

◆ lmmp_from_str_()

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]

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

在文件 from_str.c128 行定义.

128 {
129 do {
130 if (len == 0)
131 return 0;
132 } while (src[--len] == 0);
133 ++len;
134
135 mp_size_t limbs;
136 if (LMMP_POW2_Q(base)) {
137 mp_limb_t curlimb = 0;
138 const mp_byte_t* srcend = src + len;
139 int bitspd = lmmp_bases_table[base - 2].large_base;
140 int bitpos = 0;
141 limbs = 0;
142
143 do {
144 mp_limb_t curdigit = *src;
145 curlimb |= curdigit << bitpos;
146 bitpos += bitspd;
147 if (bitpos >= LIMB_BITS) {
148 dst[limbs] = curlimb;
149 ++limbs;
150 bitpos -= LIMB_BITS;
151 curlimb = curdigit >> (bitspd - bitpos);
152 }
153 } while (++src != srcend);
154 if (curlimb) {
155 dst[limbs] = curlimb;
156 ++limbs;
157 }
158 } else if (lmmp_from_str_len_(0, len, base) < FROM_STR_BASEPOW_THRESHOLD) {
159 limbs = lmmp_from_str_basecase_(dst, src, len, base);
160 } else {
161 TEMP_DECL;
162 mp_basepow_t powers[LIMB_BITS];
163 mp_limb_t lbase = lmmp_bases_table[base - 2].large_base;
164 mp_size_t digitspl = lmmp_bases_table[base - 2].digits_in_limb;
165 mp_size_t bexp, lexp = (len - 1) / digitspl + 1;
166 mp_size_t tzbit = lmmp_tailing_zeros_(lbase);
167 // need 1 extra limb to store result
168 mp_size_t alloc_size = lmmp_from_str_len_(0, len, base) + 1;
169 mp_limb_t cy;
170 mp_ptr tp;
171
172 int cpow = lmmp_limb_bits_(lexp - 1);
173
174 for (int i = cpow; i > 0; --i) {
175 // we will calculate lbase^bexp
176 bexp = ((lexp - 1) >> i) + 1;
177 // we will calculate lbase^(bexp-1) first, and trim it s. t.
178 // it contains at most 2 tailing 0 limb, then multiply it by lbase,
179 // so we need npow limbs to store lbase^bexp
180 mp_size_t npow = lmmp_from_str_len_(0, (bexp - 1) * digitspl + 1, base) + 1;
181
182 if (tzbit) {
183 mp_size_t tzlimb = tzbit * (bexp - 1) / LIMB_BITS;
184 if (tzlimb >= 2)
185 npow -= tzlimb - 2;
186 }
187
188 // space needed for a trimmed npow-limb lbase^bexp
189 alloc_size += npow;
190 }
191
192 tp = BALLOC_TYPE(alloc_size, mp_limb_t);
193
194 for (int i = 0; i < 2; ++i) {
195 tp[0] = lbase;
196 powers[i].p = tp;
197 powers[i].np = 1;
198 tp += i + 1;
199 powers[i].zeros = 0;
200 powers[i].digits = digitspl * (i + 1);
201 powers[i].base = base;
202 }
203
204 mp_ptr p = powers[1].p;
205 mp_size_t zeros = 0, np = 1;
206 for (int i = 2; i < cpow; ++i) {
207 lmmp_sqr_(tp, p, np);
208 np *= 2;
209 np -= tp[np - 1] == 0;
210 bexp = (lexp - 1) >> (cpow - i);
211 if (bexp & 1) {
212 cy = lmmp_mul_1_(tp, tp, np, lbase);
213 tp[np] = cy;
214 np += cy != 0;
215 }
216 zeros *= 2;
217 while (tp[0] == 0) {
218 // at most 2 tailing 0 limb here
219 ++zeros;
220 ++tp;
221 --np;
222 }
223 p = tp;
224 powers[i].p = p;
225 powers[i].np = np;
226 powers[i].zeros = zeros;
227 powers[i].digits = digitspl * (bexp + 1);
228 powers[i].base = base;
229 tp += np + 1;
230 }
231
232 for (int i = 1; i < cpow; ++i) {
233 p = powers[i].p;
234 np = powers[i].np;
235 cy = lmmp_mul_1_(p, p, np, lbase);
236 p[np] = cy;
237 np += cy != 0;
238 if (p[0] == 0) {
239 ++powers[i].zeros;
240 ++p;
241 --np;
242 }
243
244 powers[i].p = p;
245 powers[i].np = np;
246 }
247
248 limbs = lmmp_from_str_divide_(tp, src, len, powers + cpow - 1, dst);
249 lmmp_copy(dst, tp, limbs);
250
251 TEMP_FREE;
252 }
253 return limbs;
254}
int digits_in_limb
Definition base_table.h:37
mp_size_t digits
Definition base_table.h:54
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
static mp_size_t lmmp_from_str_basecase_(mp_ptr dst, const mp_byte_t *src, mp_size_t len, int base)
Definition from_str.c:26
static mp_size_t lmmp_from_str_divide_(mp_ptr dst, const mp_byte_t *src, mp_size_t len, mp_basepow_t *pow, mp_ptr tp)
Definition from_str.c:69
mp_size_t lmmp_from_str_len_(const mp_byte_t *src, mp_size_t len, int base)
计算字符串转大数所需的 limb 缓冲区长度
Definition from_str.c:13
mp_limb_t * mp_ptr
Definition lmmp.h:215
uint8_t mp_byte_t
Definition lmmp.h:210
#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
int lmmp_tailing_zeros_(mp_limb_t x)
计算一个单精度数(limb)中末尾零的个数
Definition tiny.c:54
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_mul_1_(mp_ptr dst, mp_srcptr numa, mp_size_t na, mp_limb_t x)
大数乘以单limb操作 [dst,na] = [numa,na] * x
#define FROM_STR_BASEPOW_THRESHOLD
Definition mparam.h:74
#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

引用了 BALLOC_TYPE, mp_basepow_t::base, mp_basepow_t::digits, mp_base_t::digits_in_limb, FROM_STR_BASEPOW_THRESHOLD, mp_base_t::large_base, LIMB_BITS, lmmp_bases_table, lmmp_copy, lmmp_from_str_basecase_(), lmmp_from_str_divide_(), lmmp_from_str_len_(), lmmp_limb_bits_(), lmmp_mul_1_(), LMMP_POW2_Q, lmmp_sqr_(), lmmp_tailing_zeros_(), mp_basepow_t::np, mp_basepow_t::p, TEMP_DECL, TEMP_FREE, tp , 以及 mp_basepow_t::zeros.

+ 函数调用图:

◆ lmmp_from_str_basecase_()

static mp_size_t lmmp_from_str_basecase_ ( mp_ptr  dst,
const mp_byte_t src,
mp_size_t  len,
int  base 
)
static

在文件 from_str.c26 行定义.

26 {
27 lmmp_param_assert(src[len - 1] != 0);
28 mp_size_t digitspl = lmmp_bases_table[base - 2].digits_in_limb;
29 mp_limb_t lbase = lmmp_bases_table[base - 2].large_base;
30 mp_size_t limbs = 0, i = len;
31
32 while (i) {
33 mp_limb_t curlimb;
34 if (i >= digitspl) {
35 curlimb = src[--i];
36 for (mp_size_t j = 1; j < digitspl; ++j) {
37 curlimb = curlimb * base + src[--i];
38 }
39 } else {
40 curlimb = src[--i];
41 lbase = base;
42 while (i) {
43 curlimb = curlimb * base + src[--i];
44 lbase *= base;
45 }
46 }
47
48 if (limbs == 0) {
49 dst[0] = curlimb;
50 limbs = 1;
51 } else {
52 mp_limb_t cy = lmmp_mul_1_(dst, dst, limbs, lbase);
53 cy += lmmp_add_1_(dst, dst, limbs, curlimb);
54 if (cy) {
55 dst[limbs] = cy;
56 ++limbs;
57 }
58 }
59 }
60
61 return limbs;
62}
#define lmmp_param_assert(x)
Definition lmmp.h:398
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:1111

引用了 mp_base_t::digits_in_limb, mp_base_t::large_base, lmmp_add_1_(), lmmp_bases_table, lmmp_mul_1_() , 以及 lmmp_param_assert.

被这些函数引用 lmmp_from_str_() , 以及 lmmp_from_str_divide_().

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

◆ lmmp_from_str_divide_()

static mp_size_t lmmp_from_str_divide_ ( mp_ptr  dst,
const mp_byte_t src,
mp_size_t  len,
mp_basepow_t pow,
mp_ptr  tp 
)
static

在文件 from_str.c69 行定义.

75 {
76 lmmp_param_assert(src[len - 1] != 0);
77 mp_size_t limbs;
78
80 limbs = lmmp_from_str_basecase_(dst, src, len, pow->base);
81 } else {
82 mp_size_t pdigits = pow->digits;
83 if (len <= pdigits) {
84 limbs = lmmp_from_str_divide_(dst, src, len, pow - 1, tp);
85 } else {
86 mp_ptr p = pow->p;
87 mp_size_t np = pow->np;
88 mp_size_t zeros = pow->zeros;
89 mp_ptr lp = tp, hp = tp + np + zeros - 2; // overwrite 2 limbs
90 mp_size_t nl = 0, nh;
91
92 mp_size_t llen = pdigits;
93 while (llen && src[llen - 1] == 0) --llen;
94 if (llen)
95 nl = lmmp_from_str_divide_(lp, src, llen, pow - 1, dst);
96
97 mp_limb_t save0 = hp[0], save1 = hp[1]; // save 2 limbs
98 nh = lmmp_from_str_divide_(hp, src + pdigits, len - pdigits, pow - 1, dst);
99 if (nh >= np)
100 lmmp_mul_(dst + zeros, hp, nh, p, np);
101 else
102 lmmp_mul_(dst + zeros, p, np, hp, nh);
103 // restore 2 limbs
104 hp[0] = save0;
105 hp[1] = save1;
106
107 if (zeros < nl) {
108 lmmp_copy(dst, lp, zeros);
109 mp_limb_t cy = lmmp_add_n_(dst + zeros, dst + zeros, lp + zeros, nl - zeros);
110 // h*p+l<=(B^nh-1)*p+(p-1)<B^nh*p, limited by nh+np limbs,
111 // so inc won't overflow
112 if (cy)
113 lmmp_inc(dst + nl);
114 } else {
115 lmmp_copy(dst, lp, nl);
116 if (zeros > nl)
117 lmmp_zero(dst + nl, zeros - nl);
118 }
119
120 limbs = nh + np + zeros;
121 limbs -= dst[limbs - 1] == 0;
122 }
123 }
124
125 return limbs;
126}
#define lmmp_zero(dst, n)
Definition lmmp.h:366
#define lmmp_inc(p)
大数加1宏(预期无进位)
Definition lmmpn.h:946
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_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:71
#define FROM_STR_DIVIDE_THRESHOLD
Definition mparam.h:72

引用了 mp_basepow_t::base, mp_basepow_t::digits, FROM_STR_DIVIDE_THRESHOLD, lmmp_add_n_(), lmmp_copy, lmmp_from_str_basecase_(), lmmp_from_str_divide_(), lmmp_from_str_len_(), lmmp_inc, lmmp_mul_(), lmmp_param_assert, lmmp_zero, mp_basepow_t::np, mp_basepow_t::p, tp , 以及 mp_basepow_t::zeros.

被这些函数引用 lmmp_from_str_() , 以及 lmmp_from_str_divide_().

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

◆ lmmp_from_str_len_()

mp_size_t lmmp_from_str_len_ ( const mp_byte_t src,
mp_size_t  len,
int  base 
)

计算字符串转大数所需的 limb 缓冲区长度

参数
src输入字符串指针
len字符串长度
base字符串的基数(2~256)
返回
存储该字符串数值所需的 limb 缓冲区长度
警告
len>=0, 2<=base<=256
注解
将会忽略前导零,
  1. if (src!=NULL) 返回的长度可能会多分配一个 limb 空间
  2. if (src==NULL) 返回len位base进制数的最大可能 limb 长度(最坏情况)

在文件 from_str.c13 行定义.

13 {
14 lmmp_param_assert(base >= 2 && base <= 256);
15 if (src) {
16 do {
17 if (len == 0)
18 return 1;
19 } while (src[--len] == 0);
20 ++len;
21 }
22 return lmmp_mulh_(len, lmmp_bases_table[base - 2].lg_base) + 1;
23}
mp_limb_t lmmp_mulh_(mp_limb_t a, mp_limb_t b)
计算两个64位无符号整数相乘的高位结果 (a*b)/2^64
Definition tiny.c:73

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

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

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