#include #include using namespace libnum; /* Digits of the decimal part, from most to least significant. Returns the number of digits (which is 0 when x=0). The operand should be nonnegative. The string should have room for 32 characters; no NUL is added. */ template requires(is_num && N >= 0) static int decimalDigitsBase(char *str, T x) { I v = x.frac().v; int i = 0; while(v != 0) { v *= 10; I digit = v >> N; str[i++] = (v >> N) + '0'; v -= digit << N; } return i; } template requires(is_num) static int decimalDigits(char *str, T x) { return 0; } template<> int decimalDigits(char *str, num8 x) { return decimalDigitsBase(str, x); } template<> int decimalDigits(char *str, num16 x) { return decimalDigitsBase(str, x); } template<> int decimalDigits(char *str, num32 x) { return decimalDigitsBase(str, x); } template<> int decimalDigits(char *str, num64 x) { return decimalDigitsBase(str, x); } /* TODO: Complex string representations like %f/%e/%g Generates the string representation of x in str; returns the number of characters written. A NUL terminator is added (but not counted in the return value). A total of 45 bytes is required for the longest 64-bit value. */ template requires(is_num) static int toString(char *str, T x) { int n = 0; /* We need to be able to represent the opposite of INT_MIN */ int64_t integral_part = (int)x; if(x.v == 0) { str[0] = '0'; str[1] = 0; return 1; } if(x.v < 0) { *str = '-'; n++; /* This might overflow, which is why we separated the integral part */ x = -x; integral_part = -integral_part - (x.frac().v != 0); } n += sprintf(str + n, "%ld", integral_part); if(x.frac().v != 0) { str[n++] = '.'; n += decimalDigits(str + n, x); } str[n] = 0; return n; } int num8::strToBuffer(char *str) { return toString(str, *this); } int num16::strToBuffer(char *str) { return toString(str, *this); } int num32::strToBuffer(char *str) { return toString(str, *this); } int num64::strToBuffer(char *str) { return toString(str, *this); }