diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2014-12-02 09:01:21 +0000 |
---|---|---|
committer | <> | 2014-12-04 16:11:25 +0000 |
commit | bdab5265fcbf3f472545073a23f8999749a9f2b9 (patch) | |
tree | c6018dd03dea906f8f1fb5f105f05b71a7dc250a /libntp/dolfptoa.c | |
download | ntp-bdab5265fcbf3f472545073a23f8999749a9f2b9.tar.gz |
Imported from /home/lorry/working-area/delta_ntp/ntp-dev-4.2.7p482.tar.gz.ntp-dev-4.2.7p482
Diffstat (limited to 'libntp/dolfptoa.c')
-rw-r--r-- | libntp/dolfptoa.c | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/libntp/dolfptoa.c b/libntp/dolfptoa.c new file mode 100644 index 0000000..07ead95 --- /dev/null +++ b/libntp/dolfptoa.c @@ -0,0 +1,174 @@ +/* + * dolfptoa - do the grunge work of converting an l_fp number to decimal + */ +#include <config.h> +#include <stdio.h> + +#include "ntp_fp.h" +#include "lib_strbuf.h" +#include "ntp_string.h" +#include "ntp_stdlib.h" + +char * +dolfptoa( + u_int32 fpi, + u_int32 fpv, + int neg, + short ndec, + int msec + ) +{ + u_char *cp, *cpend, *cpdec; + int dec; + u_char cbuf[24]; + char *buf, *bp; + + /* + * Get a string buffer before starting + */ + LIB_GETBUF(buf); + + /* + * Zero the character buffer + */ + ZERO(cbuf); + + /* + * Work on the integral part. This should work reasonable on + * all machines with 32 bit arithmetic. Please note that 32 bits + * can *always* be represented with at most 10 decimal digits, + * including a possible rounding from the fractional part. + */ + cp = cpend = cpdec = &cbuf[10]; + for (dec = cp - cbuf; dec > 0 && fpi != 0; dec--) { + /* can add another digit */ + u_int32 digit; + + digit = fpi; + fpi /= 10U; + digit -= (fpi << 3) + (fpi << 1); /* i*10 */ + *--cp = (u_char)digit; + } + + /* + * Done that, now deal with the problem of the fraction. First + * determine the number of decimal places. + */ + dec = ndec; + if (dec < 0) + dec = 0; + if (msec) { + dec += 3; + cpdec += 3; + } + if ((size_t)dec > sizeof(cbuf) - (cpend - cbuf)) + dec = sizeof(cbuf) - (cpend - cbuf); + + /* + * If there's a fraction to deal with, do so. + */ + for (/*NOP*/; dec > 0 && fpv != 0; dec--) { + u_int32 digit, tmph, tmpl; + + /* + * The scheme here is to multiply the fraction + * (0.1234...) by ten. This moves a junk of BCD into + * the units part. record that and iterate. + * multiply by shift/add in two dwords. + */ + digit = 0; + M_LSHIFT(digit, fpv); + tmph = digit; + tmpl = fpv; + M_LSHIFT(digit, fpv); + M_LSHIFT(digit, fpv); + M_ADD(digit, fpv, tmph, tmpl); + *cpend++ = (u_char)digit; + } + + /* decide whether to round or simply extend by zeros */ + if (dec > 0) { + /* only '0' digits left -- just reposition end */ + cpend += dec; + } else { + /* some bits remain in 'fpv'; do round */ + u_char *tp = cpend; + int carry = ((fpv & 0x80000000) != 0); + + for (dec = tp - cbuf; carry && dec > 0; dec--) { + *--tp += 1; + if (*tp == 10) + *tp = 0; + else + carry = FALSE; + } + + if (tp < cp) /* rounding from 999 to 1000 or similiar? */ + cp = tp; + } + + /* + * We've now got the fraction in cbuf[], with cp pointing at + * the first character, cpend pointing past the last, and + * cpdec pointing at the first character past the decimal. + * Remove leading zeros, then format the number into the + * buffer. + */ + while (cp < cpdec && *cp == 0) + cp++; + if (cp >= cpdec) + cp = cpdec - 1; + + bp = buf; + if (neg) + *bp++ = '-'; + while (cp < cpend) { + if (cp == cpdec) + *bp++ = '.'; + *bp++ = (char)(*cp++) + '0'; + } + *bp = '\0'; + + /* + * Done! + */ + return buf; +} + + +char * +mfptoa( + u_int32 fpi, + u_int32 fpf, + short ndec + ) +{ + int isneg; + + isneg = M_ISNEG(fpi); + if (isneg) { + M_NEG(fpi, fpf); + } + + return dolfptoa(fpi, fpf, isneg, ndec, FALSE); +} + + +char * +mfptoms( + u_int32 fpi, + u_int32 fpf, + short ndec + ) +{ + int isneg; + + isneg = M_ISNEG(fpi); + if (isneg) { + M_NEG(fpi, fpf); + } + + return dolfptoa(fpi, fpf, isneg, ndec, TRUE); +} + + |