internal static double StringToNumber(string s, int start, int radix)
{
char digitMax = '9';
char lowerCaseBound = 'a';
char upperCaseBound = 'A';
int len = s.Length;
if (radix < 10)
{
digitMax = (char)('0' + radix - 1);
}
if (radix > 10)
{
lowerCaseBound = (char)('a' + radix - 10);
upperCaseBound = (char)('A' + radix - 10);
}
int end;
double sum = 0.0;
for (end = start; end < len; end++)
{
char c = s[end];
int newDigit;
if ('0' <= c && c <= digitMax)
{
newDigit = c - '0';
}
else
{
if ('a' <= c && c < lowerCaseBound)
{
newDigit = c - 'a' + 10;
}
else
{
if ('A' <= c && c < upperCaseBound)
{
newDigit = c - 'A' + 10;
}
else
{
break;
}
}
}
sum = sum * radix + newDigit;
}
if (start == end)
{
return NaN;
}
if (sum >= 9007199254740992.0)
{
if (radix == 10)
{
try
{
return System.Double.Parse(Sharpen.Runtime.Substring(s, start, end));
}
catch (FormatException)
{
return NaN;
}
}
else
{
if (radix == 2 || radix == 4 || radix == 8 || radix == 16 || radix == 32)
{
int bitShiftInChar = 1;
int digit = 0;
int SKIP_LEADING_ZEROS = 0;
int FIRST_EXACT_53_BITS = 1;
int AFTER_BIT_53 = 2;
int ZEROS_AFTER_54 = 3;
int MIXED_AFTER_54 = 4;
int state = SKIP_LEADING_ZEROS;
int exactBitsLimit = 53;
double factor = 0.0;
bool bit53 = false;
// bit54 is the 54th bit (the first dropped from the mantissa)
bool bit54 = false;
for (; ; )
{
if (bitShiftInChar == 1)
{
if (start == end)
{
break;
}
digit = s[start++];
if ('0' <= digit && digit <= '9')
{
digit -= '0';
}
else
{
if ('a' <= digit && digit <= 'z')
{
digit -= 'a' - 10;
}
else
{
digit -= 'A' - 10;
}
}
bitShiftInChar = radix;
}
bitShiftInChar >>= 1;
bool bit = (digit & bitShiftInChar) != 0;
switch (state)
{
case SKIP_LEADING_ZEROS:
{
if (bit)
{
--exactBitsLimit;
sum = 1.0;
state = FIRST_EXACT_53_BITS;
}
break;
}
case FIRST_EXACT_53_BITS:
{
sum *= 2.0;
if (bit)
{
sum += 1.0;
}
--exactBitsLimit;
if (exactBitsLimit == 0)
{
bit53 = bit;
state = AFTER_BIT_53;
}
break;
}
case AFTER_BIT_53:
{
bit54 = bit;
factor = 2.0;
state = ZEROS_AFTER_54;
break;
}
case ZEROS_AFTER_54:
{
if (bit)
{
state = MIXED_AFTER_54;
}
goto case MIXED_AFTER_54;
}
case MIXED_AFTER_54:
{
// fallthrough
factor *= 2;
break;
}
}
}
switch (state)
{
case SKIP_LEADING_ZEROS:
{
sum = 0.0;
break;
}
case FIRST_EXACT_53_BITS:
case AFTER_BIT_53:
{
// do nothing
break;
}
case ZEROS_AFTER_54:
{
// x1.1 -> x1 + 1 (round up)
// x0.1 -> x0 (round down)
if (bit54 & bit53)
{
sum += 1.0;
}
sum *= factor;
break;
}
case MIXED_AFTER_54:
{
// x.100...1.. -> x + 1 (round up)
// x.0anything -> x (round down)
if (bit54)
{
sum += 1.0;
}
sum *= factor;
break;
}
}
}
}
}
return sum;
}