1- using csFastFloat . Enums ;
2- using csFastFloat . Structures ;
3- using System ;
1+ using System ;
2+ using System . Diagnostics ;
43using System . Numerics ;
54using System . Runtime . CompilerServices ;
6-
7- [ assembly: InternalsVisibleTo ( "TestcsFastFloat" ) ]
8-
9- [ assembly: InternalsVisibleTo ( "Benchmark" ) ]
10-
5+ using System . Runtime . InteropServices ;
6+ using csFastFloat . Enums ;
7+ using csFastFloat . Structures ;
118
129namespace csFastFloat
1310{
1411 public static class FastFloatParser
1512 {
1613 private static void ThrowArgumentException ( ) => throw new ArgumentException ( ) ;
17- public static float exact_power_of_ten ( long power ) => Constants . powers_of_ten_float [ power ] ;
1814
19- public static float ToFloat ( bool negative , AdjustedMantissa am )
15+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
16+ public static float exact_power_of_ten ( long power )
17+ {
18+ #if NET5_0
19+ Debug . Assert ( power < Constants . powers_of_ten_float . Length ) ;
20+ ref float tableRef = ref MemoryMarshal . GetArrayDataReference ( Constants . powers_of_ten_float ) ;
21+ return Unsafe . Add ( ref tableRef , ( nint ) power ) ;
22+ #else
23+ return Constants . powers_of_ten_float [ power ] ;
24+ #endif
25+ }
26+
27+ public static unsafe float ToFloat ( bool negative , AdjustedMantissa am )
2028 {
21- float d ;
2229 ulong word = am . mantissa ;
23- word |= ( ulong ) ( am . power2 ) << FloatBinaryConstants . mantissa_explicit_bits ;
30+ word |= ( ulong ) ( uint ) ( am . power2 ) << FloatBinaryConstants . mantissa_explicit_bits ;
2431 word = negative ? word | ( ( ulong ) ( 1 ) << FloatBinaryConstants . sign_index ) : word ;
2532
26- unsafe
27- {
28- Buffer . MemoryCopy ( & word , & d , sizeof ( float ) , sizeof ( float ) ) ;
29- }
33+ float d = 0 ;
34+ Unsafe . Copy ( ref d , & word ) ;
3035
3136 return d ;
3237 }
@@ -55,15 +60,15 @@ public static unsafe float ParseFloat(string s, chars_format expectedFormat = ch
5560
5661 fixed ( char * pStart = s )
5762 {
58- return ParseFloat ( pStart , pStart + s . Length , expectedFormat , decimal_separator ) ;
63+ return ParseFloat ( pStart , pStart + ( uint ) s . Length , expectedFormat , decimal_separator ) ;
5964 }
6065 }
6166
6267 public static unsafe float ParseFloat ( ReadOnlySpan < char > s , chars_format expectedFormat = chars_format . is_general , char decimal_separator = '.' )
6368 {
6469 fixed ( char * pStart = s )
6570 {
66- return ParseFloat ( pStart , pStart + s . Length , expectedFormat , decimal_separator ) ;
71+ return ParseFloat ( pStart , pStart + ( uint ) s . Length , expectedFormat , decimal_separator ) ;
6772 }
6873 }
6974
@@ -241,9 +246,7 @@ internal static AdjustedMantissa ComputeFloat(DecimalInfo d)
241246 if ( d . num_digits == 0 )
242247 {
243248 // should be zero
244- answer . power2 = 0 ;
245- answer . mantissa = 0 ;
246- return answer ;
249+ return default ;
247250 }
248251 // At this point, going further, we can assume that d.num_digits > 0.
249252 //
@@ -258,9 +261,7 @@ internal static AdjustedMantissa ComputeFloat(DecimalInfo d)
258261 // We have something smaller than 1e-324 which is always zero
259262 // in binary64 and binary32.
260263 // It should be zero.
261- answer . power2 = 0 ;
262- answer . mantissa = 0 ;
263- return answer ;
264+ return default ;
264265 }
265266 else if ( d . decimal_point >= 310 )
266267 {
@@ -272,15 +273,12 @@ internal static AdjustedMantissa ComputeFloat(DecimalInfo d)
272273 }
273274 const int max_shift = 60 ;
274275 const uint num_powers = 19 ;
275- ReadOnlySpan < byte > powers = new byte [ ] {
276- 0 , 3 , 6 , 9 , 13 , 16 , 19 , 23 , 26 , 29 , //
277- 33 , 36 , 39 , 43 , 46 , 49 , 53 , 56 , 59 , //
278- } ;
276+
279277 int exp2 = 0 ;
280278 while ( d . decimal_point > 0 )
281279 {
282280 uint n = ( uint ) ( d . decimal_point ) ;
283- int shift = ( n < num_powers ) ? powers [ ( int ) n ] : max_shift ;
281+ int shift = ( n < num_powers ) ? Constants . get_powers ( n ) : max_shift ;
284282
285283 d . decimal_right_shift ( shift ) ;
286284 if ( d . decimal_point < - Constants . decimal_point_range )
@@ -309,7 +307,7 @@ internal static AdjustedMantissa ComputeFloat(DecimalInfo d)
309307 else
310308 {
311309 uint n = ( uint ) ( - d . decimal_point ) ;
312- shift = ( n < num_powers ) ? powers [ ( int ) n ] : max_shift ;
310+ shift = ( n < num_powers ) ? Constants . get_powers ( n ) : max_shift ;
313311 }
314312
315313 d . decimal_left_shift ( shift ) ;
@@ -430,7 +428,7 @@ unsafe static internal ParsedNumberString ParseNumberString(char* p, char* pend,
430428 {
431429 return answer ;
432430 }
433- if ( ! Utils . is_integer ( * p ) && ( * p != decimal_separator ) ) // culture info ?
431+ if ( ! Utils . is_integer ( * p , out uint _ ) && ( * p != decimal_separator ) ) // culture info ?
434432 { // a sign must be followed by an integer or the dot
435433 return answer ;
436434 }
@@ -439,12 +437,11 @@ unsafe static internal ParsedNumberString ParseNumberString(char* p, char* pend,
439437
440438 ulong i = 0 ; // an unsigned int avoids signed overflows (which are bad)
441439
442- while ( ( p != pend ) && Utils . is_integer ( * p ) )
440+ while ( ( p != pend ) && Utils . is_integer ( * p , out uint cMinus0 ) )
443441 {
444442 // a multiplication by 10 is cheaper than an arbitrary integer
445443 // multiplication
446- i = 10 * i +
447- ( ulong ) ( * p - '0' ) ; // might overflow, we will handle the overflow later
444+ i = 10 * i + ( ulong ) cMinus0 ; // might overflow, we will handle the overflow later
448445 ++ p ;
449446 }
450447 char * end_of_integer_part = p ;
@@ -453,9 +450,9 @@ unsafe static internal ParsedNumberString ParseNumberString(char* p, char* pend,
453450 if ( ( p != pend ) && ( * p == decimal_separator ) )
454451 {
455452 ++ p ;
456- while ( ( p != pend ) && Utils . is_integer ( * p ) )
453+ while ( ( p != pend ) && Utils . is_integer ( * p , out uint cMinus0 ) )
457454 {
458- byte digit = ( byte ) ( * p - '0' ) ;
455+ byte digit = ( byte ) cMinus0 ;
459456 ++ p ;
460457 i = i * 10 + digit ; // in rare cases, this will overflow, but that's ok
461458 }
@@ -482,7 +479,7 @@ unsafe static internal ParsedNumberString ParseNumberString(char* p, char* pend,
482479 {
483480 ++ p ;
484481 }
485- if ( ( p == pend ) || ! Utils . is_integer ( * p ) )
482+ if ( ( p == pend ) || ! Utils . is_integer ( * p , out uint _ ) )
486483 {
487484 if ( expectedFormat != chars_format . is_fixed )
488485 {
@@ -494,9 +491,9 @@ unsafe static internal ParsedNumberString ParseNumberString(char* p, char* pend,
494491 }
495492 else
496493 {
497- while ( ( p != pend ) && Utils . is_integer ( * p ) )
494+ while ( ( p != pend ) && Utils . is_integer ( * p , out uint cMinus0 ) )
498495 {
499- byte digit = ( byte ) ( * p - '0' ) ;
496+ byte digit = ( byte ) cMinus0 ;
500497 if ( exp_number < 0x10000 )
501498 {
502499 exp_number = 10 * exp_number + digit ;
@@ -539,9 +536,9 @@ unsafe static internal ParsedNumberString ParseNumberString(char* p, char* pend,
539536 i = 0 ;
540537 p = start_digits ;
541538 const ulong minimal_nineteen_digit_integer = 1000000000000000000 ;
542- while ( ( i < minimal_nineteen_digit_integer ) && ( p != pend ) && Utils . is_integer ( * p ) )
539+ while ( ( i < minimal_nineteen_digit_integer ) && ( p != pend ) && Utils . is_integer ( * p , out uint cMinus0 ) )
543540 {
544- i = i * 10 + ( ulong ) ( * p - '0' ) ;
541+ i = i * 10 + ( ulong ) cMinus0 ;
545542 ++ p ;
546543 }
547544 if ( i >= minimal_nineteen_digit_integer )
@@ -552,9 +549,9 @@ unsafe static internal ParsedNumberString ParseNumberString(char* p, char* pend,
552549 { // We have a value with a fractional component.
553550 p ++ ; // skip the '.'
554551 char * first_after_period = p ;
555- while ( ( i < minimal_nineteen_digit_integer ) && ( p != pend ) && Utils . is_integer ( * p ) )
552+ while ( ( i < minimal_nineteen_digit_integer ) && ( p != pend ) && Utils . is_integer ( * p , out uint cMinus0 ) )
556553 {
557- i = i * 10 + ( ulong ) ( * p - '0' ) ;
554+ i = i * 10 + ( ulong ) cMinus0 ;
558555 ++ p ;
559556 }
560557 exponent = first_after_period - p + exp_number ;
0 commit comments