@@ -9,7 +9,7 @@ module mir.bignum.decimal;
99import mir.serde: serdeProxy, serdeScoped;
1010import std.traits : isSomeChar;
1111// /
12- public import mir.bignum.low_level_view : DecimalExponentKey;
12+ public import mir.parse : DecimalExponentKey;
1313import mir.bignum.low_level_view: ceilLog10Exp2;
1414
1515private enum expBufferLength = 2 + ceilLog10Exp2(ulong .sizeof * 8 );
@@ -180,283 +180,6 @@ struct Decimal(uint size64)
180180 scope @trusted pure @nogc nothrow
181181 if (isSomeChar! C)
182182 {
183- enum optimize = size_t .sizeof == 8 && size64 == 1 ;
184- version (LDC )
185- {
186- static if (optimize || (allowSpecialValues && allowDExponent && allowStartingPlus && checkEmpty) == false )
187- pragma (inline, true );
188- }
189- static if (optimize)
190- {
191- import mir.utility: _expect;
192- static if (checkEmpty)
193- {
194- if (_expect(str.length == 0 , false ))
195- return false ;
196- }
197-
198- coefficient.sign = str[0 ] == ' -' ;
199- if (coefficient.sign)
200- {
201- str = str[1 .. $];
202- if (_expect(str.length == 0 , false ))
203- return false ;
204- }
205- else
206- static if (allowStartingPlus)
207- {
208- if (_expect(str[0 ] == ' +' , false ))
209- {
210- str = str[1 .. $];
211- if (_expect(str.length == 0 , false ))
212- return false ;
213- }
214- }
215-
216- ulong d = str[0 ] - C(' 0' );
217- str = str[1 .. $];
218- exponent = 0 ;
219-
220- ulong v, multplier = void ;
221-
222- if (_expect(d >= 10 , false ))
223- {
224- static if (allowDotOnBounds)
225- {
226- if (d == ' .' - ' 0' )
227- {
228- if (str.length == 0 )
229- return false ;
230- key = DecimalExponentKey.dot;
231- d = str[0 ] - C(' 0' );
232- str = str[1 .. $];
233- if (_expect(d < 10 , true ))
234- goto FI ;
235- return false ;
236- }
237- }
238- static if (allowSpecialValues)
239- goto NI ;
240- else
241- return false ;
242- }
243-
244- static if (! allowLeadingZeros)
245- {
246- if (_expect(d == 0 , false ))
247- {
248- if (str.length == 0 )
249- goto R;
250- d = str[0 ] - C(' 0' );
251- str = str[1 .. $];
252- if (d < 10 )
253- return false ;
254- goto DOT ;
255- }
256- }
257-
258- v = d;
259-
260- S:
261- if (str.length == 0 )
262- goto R;
263- d = str[0 ] - C(' 0' );
264- str = str[1 .. $];
265-
266- if (d < 10 )
267- {
268- F0 :
269- import mir.checkedint: mulu, addu;
270- bool overflow;
271- v = mulu(v, 10u , overflow);
272- if (overflow)
273- return false ;
274- v = addu(v, d, overflow);
275- if (overflow)
276- return false ;
277- goto S;
278- }
279-
280- static if (allowUnderscores)
281- {
282- if (d == ' _' - ' 0' )
283- {
284- if (str.length == 0 )
285- return false ;
286- d = str[0 ] - C(' 0' );
287- str = str[1 .. $];
288- if (_expect(d < 10 , true ))
289- goto F0 ;
290- return false ;
291- }
292- }
293- DOT :
294- if (d == DecimalExponentKey.dot)
295- {
296- // The dot modifier CANNOT be preceded by any modifiers.
297- if (key != DecimalExponentKey.none)
298- return false ;
299-
300- key = DecimalExponentKey.dot;
301-
302- if (str.length == 0 )
303- {
304- static if (allowDotOnBounds)
305- goto R;
306- else
307- return false ;
308- }
309-
310- IF :
311-
312- static if (is (C == char ))
313- {
314- import mir.bignum.internal.parse: isMadeOfEightDigits, parseEightDigits;
315- if (str.length >= 8 && isMadeOfEightDigits(str[0 .. 8 ]))
316- {
317- multplier = 100000000 ;
318- d = parseEightDigits(str[0 .. 8 ]);
319- str = str[8 .. $];
320- exponentShift -= 8 ;
321- if (str.length >= 7 )
322- {
323- if (isMadeOfEightDigits((str.ptr - 1 )[0 .. 8 ]))
324- {
325- multplier = 100000000 * 10000000 ;
326- d -= str.ptr[- 1 ] - ' 0' ;
327- d *= 10000000 ;
328- d += parseEightDigits((str.ptr - 1 )[0 .. 8 ]);
329- str = str[7 .. $];
330- exponentShift -= 7 ;
331- if (str.length)
332- {
333- auto md = str[0 ] - C(' 0' );
334- if (md < 10 )
335- {
336- d *= 10 ;
337- multplier = 100000000 * 100000000 ;
338- d += md;
339- str = str[1 .. $];
340- }
341- }
342- }
343- else
344- {
345- TrySix:
346- if (isMadeOfEightDigits((str.ptr - 2 )[0 .. 8 ]))
347- {
348- multplier = 100000000 * 1000000 ;
349- d -= str.ptr[- 1 ] - ' 0' ;
350- d -= (str.ptr[- 2 ] - ' 0' ) * 10 ;
351- d *= 1000000 ;
352- d += parseEightDigits((str.ptr - 2 )[0 .. 8 ]);
353- str = str[6 .. $];
354- exponentShift -= 6 ;
355- }
356- }
357-
358- }
359- else
360- if (str.length == 6 )
361- goto TrySix;
362- goto FIL ;
363- }
364- }
365-
366- d = str[0 ] - C(' 0' );
367- str = str[1 .. $];
368- if (_expect(d >= 10 , false ))
369- goto DOB ;
370- FI :
371- exponentShift-- ;
372- multplier = 10 ;
373- FIL :
374- {
375- import mir.checkedint: mulu, addu;
376- bool overflow;
377- v = mulu(v, multplier, overflow);
378- if (overflow)
379- return false ;
380- v = addu(v, d, overflow);
381- if (overflow)
382- return false ;
383- }
384- if (str.length == 0 )
385- goto E;
386- d = str[0 ] - C(' 0' );
387- str = str[1 .. $];
388- if (d < 10 )
389- goto FI ;
390-
391- static if (allowUnderscores)
392- {
393- if (d == ' _' - ' 0' )
394- {
395- if (str.length == 0 )
396- return false ;
397- d = str[0 ] - C(' 0' );
398- str = str[1 .. $];
399- if (_expect(d < 10 , true ))
400- goto FI ;
401- return false ;
402- }
403- }
404- DOB :
405- static if (! allowDotOnBounds)
406- {
407- if (exponentShift == 0 )
408- return false ;
409- }
410-
411- }
412-
413- static if (allowExponent)
414- {
415- if (d == DecimalExponentKey.e
416- || d == DecimalExponentKey.E
417- || d == DecimalExponentKey.d && allowDExponent
418- || d == DecimalExponentKey.D && allowDExponent
419- )
420- {
421- import mir.parse: parse;
422- key = cast (DecimalExponentKey)d;
423- if (parse(str, exponent) && str.length == 0 )
424- goto E;
425- }
426- }
427- return false ;
428-
429- E:
430- exponent += exponentShift;
431- R:
432- coefficient.data[0 ] = v;
433- coefficient.length = v != 0 ;
434- return true ;
435-
436- static if (allowSpecialValues)
437- {
438- NI :
439- exponent = exponent.max;
440- if (str.length == 2 )
441- {
442- auto stail = cast (C[2 ])str[0 .. 2 ];
443- if (d == ' i' - ' 0' && stail == cast (C[2 ])" nf" || d == ' I' - ' 0' && (stail == cast (C[2 ])" nf" || stail == cast (C[2 ])" NF" ))
444- {
445- key = DecimalExponentKey.infinity;
446- goto R;
447- }
448- if (d == ' n' - ' 0' && stail == cast (C[2 ])" an" || d == ' N' - ' 0' && (stail == cast (C[2 ])" aN" || stail == cast (C[2 ])" AN" ))
449- {
450- v = 1 ;
451- key = DecimalExponentKey.nan;
452- goto R;
453- }
454- }
455- return false ;
456- }
457- }
458- else
459- {
460183 import mir.bignum.low_level_view: DecimalView, BigUIntView, MaxWordPow10;
461184 auto work = DecimalView! size_t (false , 0 , BigUIntView! size_t (coefficient.data));
462185 auto ret = work.fromStringImpl! (C,
@@ -473,7 +196,6 @@ struct Decimal(uint size64)
473196 coefficient.sign = work.sign;
474197 exponent = work.exponent;
475198 return ret;
476- }
477199 }
478200
479201 private enum coefficientBufferLength = 2 + ceilLog10Exp2(coefficient.data.length * (size_t .sizeof * 8 )); // including dot and sign
@@ -723,13 +445,13 @@ struct Decimal(uint size64)
723445}
724446
725447// /
726- version (mir_bignum_test)
448+ version (mir_bignum_test)
727449@safe pure nothrow @nogc
728450unittest
729451{
730452 import mir.test: should;
731453 import mir.conv: to;
732- Decimal! 256 decimal = void ;
454+ Decimal! 128 decimal = void ;
733455 DecimalExponentKey key;
734456
735457 assert (decimal.fromStringImpl(" 3.141592653589793378e-10" , key));
0 commit comments