private static string ConvertToDecimal(double val, int minLen, char zero, string groupSeparator, int groupSize) {
Debug.Assert(val >= 0 && val == Math.Round(val), "ConvertToArabic operates on non-negative integer numbers only");
string str = XPathConvert.DoubleToString(val);
int shift = zero - '0';
// Figure out new string length without separators
int oldLen = str.Length;
int newLen = Math.Max(oldLen, minLen);
// Calculate length of string with separators
if (groupSize != 0) {
Debug.Assert(groupSeparator.Length == 1);
checked { newLen += (newLen - 1) / groupSize; }
}
// If the new number of characters equals the old one, no changes need to be made
if (newLen == oldLen && shift == 0) {
return str;
}
// If grouping is not needed, add zero padding only
if (groupSize == 0 && shift == 0) {
return str.PadLeft(newLen, zero);
}
// Add both grouping separators and zero padding to the string representation of a number
#if true
unsafe {
char *result = stackalloc char[newLen];
char separator = (groupSeparator.Length > 0) ? groupSeparator[0] : ' ';
fixed (char *pin = str) {
char *pOldEnd = pin + oldLen - 1;
char *pNewEnd = result + newLen - 1;
int cnt = groupSize;
while (true) {
// Move digit to its new location (zero if we've run out of digits)
*pNewEnd-- = (pOldEnd >= pin) ? (char)(*pOldEnd-- + shift) : zero;
if (pNewEnd < result) {
break;
}
if (/*groupSize > 0 && */--cnt == 0) {
// Every groupSize digits insert the separator
*pNewEnd-- = separator;
cnt = groupSize;
Debug.Assert(pNewEnd >= result, "Separator cannot be the first character");
}
}
}
return new string(result, 0, newLen);
}
#else
// Safe version is about 20% slower after NGEN
char[] result = new char[newLen];
char separator = (groupSeparator.Length > 0) ? groupSeparator[0] : ' ';
int oldEnd = oldLen - 1;
int newEnd = newLen - 1;
int cnt = groupSize;
while (true) {
// Move digit to its new location (zero if we've run out of digits)
result[newEnd--] = (oldEnd >= 0) ? (char)(str[oldEnd--] + shift) : zero;
if (newEnd < 0) {
break;
}
if (/*groupSize > 0 && */--cnt == 0) {
// Every groupSize digits insert the separator
result[newEnd--] = separator;
cnt = groupSize;
Debug.Assert(newEnd >= 0, "Separator cannot be the first character");
}
}
return new string(result, 0, newLen);
#endif
}
}