else
break;
}
- while( c = *format++ );
+ while( (c = *format++) );
// Padding length
if( c == '*' ) {
pos += _printf_ftoa(putch_cb, putch_h, arg_f, 10, FPN_SCI,
precision, 0, bJustifyLeft, c == 'E');
break;
+ // Scientific Float
+ case 'g':
+ case 'G':
+ arg_f = bLong ? va_arg(args, long double) : va_arg(args, double);
+ pos += _printf_ftoa(putch_cb, putch_h, arg_f, 10, FPN_SHORTEST,
+ precision, 0, bJustifyLeft, c == 'G');
+ break;
// Hexadecimal Scientific
case 'a':
case 'A':
// String
case 's':
p = va_arg(args, char*);
- sprintf_puts:
if(!p) p = "(null)";
//_SysDebug("vsnprintf: p = '%s'", p);
if(precision >= 0)
tmpBuf[pos++] = map[ num % base ]; // Last digit of {number}
// length of number, minus the sign character
- PadLength -= pos - sign_is_neg - (SignChar != '\0');
+ PadLength -= pos + (sign_is_neg || SignChar != '\0');
+ Precision -= pos + (sign_is_neg || SignChar != '\0');
if( !bPadRight )
{
while(PadLength-- > 0)
return ret;
}
+#if 0
+size_t _printf_itoa_fixed(printf_putch_t putch_cb, void *putch_h, uint64_t num, size_t Base)
+{
+ uint64_t den;
+ size_t ret = 0;
+
+ den = 1ULL << (64-1);
+
+ while( den )
+ {
+ putch_cb(putch_h, cDIGITS[num / den]);
+ ret ++;
+ num %= den;
+ den /= Base;
+ }
+
+ return ret;
+}
+
+size_t _printf_ftoa_dec(printf_putch_t putch_cb, void *putch_h, long double num, enum eFPN Notation, int Precision, int bForcePoint, int bForceSign, int bCapitals)
+{
+ size_t ret = 0;
+ int i;
+
+ #define _putch(_ch) do{\
+ putch_cb(putch_h, bCapitals ? toupper(_ch) : _ch), ret++;\
+ }while(0)
+
+ uint64_t significand;
+ int16_t exponent;
+ int signisneg;
+ int rv = expand_double(num, &significand, &exponent, &signisneg);
+ switch(rv)
+ {
+ // 0: No errors, nothing special
+ case 0:
+ break;
+ // 1: Subnormals
+ case 1:
+ // TODO: Subnormal = 0?
+ break;
+ // 2: Infinity
+ case 2:
+ _putch('i');
+ _putch('n');
+ _putch('f');
+ return 3;
+ case 3:
+ _putch('N');
+ _putch('a');
+ _putch('N');
+ return 3;
+ }
+
+ uint64_t whole, part;
+ int pre_zeros, post_zeros;
+
+ #define XXX 0
+ if( Notation == FPN_SCI )
+ {
+ }
+ else if( exponent < 0 )
+ {
+ whole = 0;
+ part = XXX;
+ pre_zeros = 0;
+ post_zeros = XXX;
+ }
+ else if( exponent >= 64 )
+ {
+ part = 0;
+ whole = XXX;
+ pre_zeros = XXX;
+ post_zeros = 0;
+ }
+ else
+ {
+ // Split into fixed point
+ whole = (1 << exponent) | (significand >> (64-exponent));
+ part = significand << exponent;
+ pre_zeros = 0;
+ post_zeros = 0;
+ }
+
+
+ // Whole portion
+ ret += _printf_itoa(putch_cb, putch_h, whole, 10, FALSE, FALSE, '\0', 0, 0, '\0', FALSE);
+ for(i = pre_zeros; i --; ) _putch('0');
+ // TODO: Conditional point
+ _putch('-');
+ for(i = post_zeros; i--; ) _putch('0');
+ ret += _printf_itoa_fixed(putch_cb, putch_h, part, 10);
+
+ #undef _putch
+
+ return 0;
+}
+#endif
+
size_t _printf_ftoa(printf_putch_t putch_cb, void *putch_h, long double num, size_t Base, enum eFPN Notation, int Precision, int bForcePoint, int bForceSign, int bCapitals)
{
uint64_t significand;
int16_t exponent;
int signisneg;
- int rv;
+ int rv, i;
size_t ret = 0;
#define _putch(_ch) do{\
{
//TODO:
//int first_set_sig = BSL(significand);
- // TODO: if( num > pos(Base, 2+Precision+2+log_base(exponent) )
- Notation = FPN_SCI;
+ // bSign+log10(num)+1+precision vs. bSign+1+1+precision+1+1+log10(exponent)
+ int log10_num = exponent * 301 / 1000; // log_10(2) = 0.30102999566...
+ int log10_exp10 = 2;
+ int sci_len = (signisneg || bForceSign) + 2 + (Precision-1) + 2 + log10_exp10;
+ int std_whole_len = (log10_num > 0 ? log10_num : 1);
+ int std_len = (signisneg || bForceSign) + std_whole_len + 1 + (Precision-std_whole_len);
+ if( sci_len > std_len ) {
+ Precision -= std_whole_len;
+ Notation = FPN_STD;
+ }
+ else {
+ Precision -= 1;
+ Notation = FPN_SCI;
+ }
}
double precision_max = 1;
- while(Precision--)
+ for(i = Precision; i--; )
precision_max /= Base;
// Determine scientific's exponent and starting denominator
}
den = 1;
}
- else
+ else if( num != 0.0 )
{
- while( den < num )
+ while( den <= num )
den *= Base;
den /= Base;
}
_putch('+');
else {
}
+
+ num += precision_max/10 * 4.999;
int value;
// Whole section
} while( den >= 1 );
// Decimal point (if needed/forced)
- if( den >= precision_max || bForcePoint )
+ if( Precision > 0 || bForcePoint )
_putch('.');
// Decimal section
- while( den >= precision_max )
+ for(i = Precision; i--; )
{
num = _longdiv(num, den, &value);
_putch(cDIGITS[value]);
_putch('p');
else
_putch('e');
- ret += _printf_itoa(putch_cb, putch_h, sci_exponent, Base, FALSE, TRUE, '+', 0, 0, '\0', FALSE);
+ ret += _printf_itoa(putch_cb, putch_h, sci_exponent, Base, FALSE, TRUE, '+', 3, 0, '\0', FALSE);
}
#undef _putch