mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-30 17:22:27 +00:00
Fix ecvt/fcvt issues w.r.t. value==0 and ndigit==0 (#1282)
Before this commit, cosmopolitan had some issues with handling arguments of 0 and signs, such as returning an incorrect sign when the input value == -0.0, and incorrectly handling ndigit == 0 on fcvt (ndigit determines the amount of digits *after* the radix character on fcvt, thus the parts before it still must be outputted before fcvt's job is completely done). This patch fixes these issues, and adds tests with corresponding inputs.
This commit is contained in:
parent
dc579b79cd
commit
f882887178
2 changed files with 45 additions and 4 deletions
|
@ -22,6 +22,7 @@
|
||||||
│ Materiel Command, USAF, under agreement number F39502-99-1-0512. │
|
│ Materiel Command, USAF, under agreement number F39502-99-1-0512. │
|
||||||
│ SUCH DAMAGE. │
|
│ SUCH DAMAGE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/math.h"
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/mem/mem.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
|
@ -53,8 +54,11 @@ __cvt(double value, int ndigit, int *decpt, int *sign, int fmode, int pad)
|
||||||
char *p, *rve, c;
|
char *p, *rve, c;
|
||||||
size_t siz;
|
size_t siz;
|
||||||
|
|
||||||
if (ndigit == 0) {
|
// Note that we exclude the case of fmode here, since for fcvt having
|
||||||
*sign = value < 0.0;
|
// `ndigit == 0` just means we have to output 0 digits *after* the radix
|
||||||
|
// character
|
||||||
|
if (ndigit == 0 && !fmode) {
|
||||||
|
*sign = signbit(value);
|
||||||
*decpt = 0;
|
*decpt = 0;
|
||||||
return ("");
|
return ("");
|
||||||
}
|
}
|
||||||
|
@ -71,10 +75,12 @@ __cvt(double value, int ndigit, int *decpt, int *sign, int fmode, int pad)
|
||||||
/* __dtoa() doesn't allocate space for 0 so we do it by hand */
|
/* __dtoa() doesn't allocate space for 0 so we do it by hand */
|
||||||
if (value == 0.0) {
|
if (value == 0.0) {
|
||||||
*decpt = 1 - fmode; /* 1 for 'e', 0 for 'f' */
|
*decpt = 1 - fmode; /* 1 for 'e', 0 for 'f' */
|
||||||
*sign = 0;
|
*sign = signbit(value);
|
||||||
if ((rve = s = malloc(siz)) == NULL)
|
if ((rve = s = malloc(siz)) == NULL)
|
||||||
return(NULL);
|
return(NULL);
|
||||||
*rve++ = '0';
|
// handle fcvt(0, 0, ...) by returning ""
|
||||||
|
if (siz > 1)
|
||||||
|
*rve++ = '0';
|
||||||
*rve = '\0';
|
*rve = '\0';
|
||||||
} else {
|
} else {
|
||||||
p = dtoa(value, fmode + 2, ndigit, decpt, sign, &rve);
|
p = dtoa(value, fmode + 2, ndigit, decpt, sign, &rve);
|
||||||
|
|
|
@ -31,3 +31,38 @@ TEST(fcvt, test) {
|
||||||
ASSERT_EQ(1, decpt);
|
ASSERT_EQ(1, decpt);
|
||||||
ASSERT_EQ(0, sign);
|
ASSERT_EQ(0, sign);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ecvt, minus0) {
|
||||||
|
int decpt = 110000000, sign = 110000000;
|
||||||
|
|
||||||
|
ASSERT_STREQ("00000", ecvt(-0.0, 5, &decpt, &sign));
|
||||||
|
ASSERT_LE(0, decpt);
|
||||||
|
ASSERT_GE(1, decpt);
|
||||||
|
ASSERT_EQ(1, sign);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ecvt, minus0ndigits0) {
|
||||||
|
int decpt = 110000000, sign = 110000000;
|
||||||
|
|
||||||
|
ASSERT_STREQ("", ecvt(-0.0, 0, &decpt, &sign));
|
||||||
|
ASSERT_LE(0, decpt);
|
||||||
|
ASSERT_GE(1, decpt);
|
||||||
|
ASSERT_EQ(1, sign);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(fcvt, ndigits0) {
|
||||||
|
int decpt = 110000000, sign = 110000000;
|
||||||
|
|
||||||
|
ASSERT_STREQ("1", fcvt(0.6, 0, &decpt, &sign));
|
||||||
|
ASSERT_EQ(1, decpt);
|
||||||
|
ASSERT_EQ(0, sign);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(fcvt, minus0ndigits0) {
|
||||||
|
int decpt = 110000000, sign = 110000000;
|
||||||
|
|
||||||
|
ASSERT_STREQ("", fcvt(-0.0, 0, &decpt, &sign));
|
||||||
|
ASSERT_LE(0, decpt);
|
||||||
|
ASSERT_GE(1, decpt);
|
||||||
|
ASSERT_EQ(1, sign);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue