diff --git a/src/printf.c b/src/printf.c index 26104c4..e609d5c 100644 --- a/src/printf.c +++ b/src/printf.c @@ -80,125 +80,140 @@ s->precision = 6; double val = va_arg(*arg, double); - char sign = 0; - - if (val < 0) - { - sign = '-'; - val = -val; - } - - if ((s->flags & FLAG_PLUS) && (sign == 0)) - sign = '+'; - //round the number to the precision specified - uint64_t p = 1; - for(int32_t i = 0; i < s->precision; i++) - p *= 10; - - - uint64_t integer = (uint64_t)val; - const double frac_d = (val - integer) * p; - uint64_t frac = (uint64_t)frac_d; - const double diff = frac_d - frac; - - if (diff > 0.5) + if (isnan(val)) { - frac++; - - if (frac >= p) - { - frac = 0; - integer++; - } + OUTPUT_CHARS(user, "NaN", 3); } - else if (diff < 0.5) + else if (isinf(val) > 0) { + OUTPUT_CHARS(user, "+Inf", 4); } - else if ((frac == 0) || (frac & 1)) + else if (ininf(val) < 0) { - //banker's rounding rule - frac++; - } - - - if (s->precision == 0) - { - const double diff = val - integer; - if (!((diff < 0.5) || (diff > 0.5)) && (integer & 1)) - integer++; - } - - - //get the digits - char str[40]; //will fit 10^38 (integer part only) - char *ptr = str + sizeof(str); - if (integer) - { - while(integer) - { - *--ptr = (integer % 10) + '0'; - integer /= 10; - } + OUTPUT_CHARS(user, "-Inf", 4); } else - *--ptr = '0'; - - //get the decimals - char decimals[s->precision + 1]; - if (s->precision) { - char *p_decimal = decimals + sizeof(decimals); + char sign = 0; + if (val < 0) + { + sign = '-'; + val = -val; + } + + if ((s->flags & FLAG_PLUS) && (sign == 0)) + sign = '+'; + + //round the number to the precision specified + uint64_t p = 1; for(int32_t i = 0; i < s->precision; i++) + p *= 10; + + uint64_t integer = (uint64_t)val; + const double frac_d = (val - integer) * p; + uint64_t frac = (uint64_t)frac_d; + const double diff = frac_d - frac; + + if (diff > 0.5) { - *--p_decimal = (frac % 10) + '0'; - frac /= 10; - } + frac++; - *--p_decimal = '.'; - } - - - const uint32_t significant_digits = str + sizeof(str) - ptr; //total number of significant digits (without the sign) - const uint32_t total_chars = significant_digits + (sign ? 1 : 0) + (s->precision ? s->precision + 1 : 0); - - const uint32_t width_total = max(s->width, total_chars); - uint32_t width_padding = width_total - total_chars; - - - if (s->flags & FLAG_MINUS) - { - //left alignment - if (sign) - OUTPUT_CHARS(user, &sign, 1); - - OUTPUT_CHARS(user, ptr, significant_digits); + if (frac >= p) + { + frac = 0; + integer++; + } + } + else if (diff < 0.5) + { + } + else if ((frac == 0) || (frac & 1)) + { + //banker's rounding rule + frac++; + } + + if (s->precision == 0) + { + const double diff = val - integer; + if (!((diff < 0.5) || (diff > 0.5)) && (integer & 1)) + integer++; + } + + + //get the digits + char str[40]; //will fit 10^38 (integer part only) + char *ptr = str + sizeof(str); + if (integer) + { + while(integer) + { + *--ptr = (integer % 10) + '0'; + integer /= 10; + } + } + else + *--ptr = '0'; + + //get the decimals + char decimals[s->precision + 1]; if (s->precision) - OUTPUT_CHARS(user, decimals, s->precision + 1); + { + char *p_decimal = decimals + sizeof(decimals); + + for(int32_t i = 0; i < s->precision; i++) + { + *--p_decimal = (frac % 10) + '0'; + frac /= 10; + } + + *--p_decimal = '.'; + } - while(width_padding--) - OUTPUT_CHARS(user, " ", 1); - } - else - { - const char pad_char = (s->flags & FLAG_ZERO) ? '0' : ' '; - //right alignment - if ((s->flags & FLAG_ZERO) && sign) - OUTPUT_CHARS(user, &sign, 1); + const uint32_t significant_digits = str + sizeof(str) - ptr; //total number of significant digits (without the sign) + const uint32_t total_chars = significant_digits + (sign ? 1 : 0) + (s->precision ? s->precision + 1 : 0); - while(width_padding--) - OUTPUT_CHARS(user, &pad_char, 1); - - if (!(s->flags & FLAG_ZERO) && sign) - OUTPUT_CHARS(user, &sign, 1); - - OUTPUT_CHARS(user, ptr, significant_digits); + const uint32_t width_total = max(s->width, total_chars); + uint32_t width_padding = width_total - total_chars; - if (s->precision) - OUTPUT_CHARS(user, decimals, s->precision + 1); + + if (s->flags & FLAG_MINUS) + { + //left alignment + if (sign) + OUTPUT_CHARS(user, &sign, 1); + + OUTPUT_CHARS(user, ptr, significant_digits); + + if (s->precision) + OUTPUT_CHARS(user, decimals, s->precision + 1); + + while(width_padding--) + OUTPUT_CHARS(user, " ", 1); + } + else + { + const char pad_char = (s->flags & FLAG_ZERO) ? '0' : ' '; + + //right alignment + if ((s->flags & FLAG_ZERO) && sign) + OUTPUT_CHARS(user, &sign, 1); + + while(width_padding--) + OUTPUT_CHARS(user, &pad_char, 1); + + if (!(s->flags & FLAG_ZERO) && sign) + OUTPUT_CHARS(user, &sign, 1); + + OUTPUT_CHARS(user, ptr, significant_digits); + + if (s->precision) + OUTPUT_CHARS(user, decimals, s->precision + 1); + } }