summaryrefslogtreecommitdiffstats
path: root/contrib/ntp/libntp/dolfptoa.c
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2015-07-15 19:21:26 +0000
committerdelphij <delphij@FreeBSD.org>2015-07-15 19:21:26 +0000
commit2a25cee78ab1d37e7d2bc40ae675646974d99f56 (patch)
treeb0302ac4be59e104f4e1e54014561a1389397192 /contrib/ntp/libntp/dolfptoa.c
parenta0741a75537b2e0514472ac3b28afc55a7846c30 (diff)
downloadFreeBSD-src-2a25cee78ab1d37e7d2bc40ae675646974d99f56.zip
FreeBSD-src-2a25cee78ab1d37e7d2bc40ae675646974d99f56.tar.gz
MFC r280849,280915-280916,281015-281016,282097,282408,282415,283542,
284864,285169-285170,285435: ntp 4.2.8p3. Relnotes: yes Approved by: re (?)
Diffstat (limited to 'contrib/ntp/libntp/dolfptoa.c')
-rw-r--r--contrib/ntp/libntp/dolfptoa.c207
1 files changed, 104 insertions, 103 deletions
diff --git a/contrib/ntp/libntp/dolfptoa.c b/contrib/ntp/libntp/dolfptoa.c
index f68679c..07ead95 100644
--- a/contrib/ntp/libntp/dolfptoa.c
+++ b/contrib/ntp/libntp/dolfptoa.c
@@ -1,6 +1,7 @@
/*
* dolfptoa - do the grunge work of converting an l_fp number to decimal
*/
+#include <config.h>
#include <stdio.h>
#include "ntp_fp.h"
@@ -10,20 +11,17 @@
char *
dolfptoa(
- u_long fpi,
- u_long fpv,
+ u_int32 fpi,
+ u_int32 fpv,
int neg,
short ndec,
int msec
)
{
- register u_char *cp, *cpend;
- register u_long lwork;
- register int dec;
+ u_char *cp, *cpend, *cpdec;
+ int dec;
u_char cbuf[24];
- u_char *cpdec;
- char *buf;
- char *bp;
+ char *buf, *bp;
/*
* Get a string buffer before starting
@@ -33,113 +31,81 @@ dolfptoa(
/*
* Zero the character buffer
*/
- memset((char *) cbuf, 0, sizeof(cbuf));
+ ZERO(cbuf);
/*
- * safeguard against sign extensions and other mishaps on 64 bit platforms
- * the code following is designed for and only for 32-bit inputs and
- * only 32-bit worth of input are supplied.
- */
- fpi &= 0xffffffff;
- fpv &= 0xffffffff;
-
- /*
- * Work on the integral part. This is biased by what I know
- * compiles fairly well for a 68000.
+ * 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 = &cbuf[10];
- lwork = fpi;
- if (lwork & 0xffff0000) {
- register u_long lten = 10;
- register u_long ltmp;
-
- do {
- ltmp = lwork;
- lwork /= lten;
- ltmp -= (lwork << 3) + (lwork << 1);
- if (cp < cbuf) abort(); /* rather die a horrible death than trash the memory */
- *--cp = (u_char)ltmp;
- } while (lwork & 0xffff0000);
- }
- if (lwork != 0) {
- register u_short sten = 10;
- register u_short stmp;
- register u_short swork = (u_short)lwork;
-
- do {
- stmp = swork;
- swork = (u_short) (swork/sten);
- stmp = (u_short)(stmp - ((swork<<3) + (swork<<1)));
- if (cp < cbuf) abort(); /* rather die a horrible death than trash the memory */
- *--cp = (u_char)stmp;
- } while (swork != 0);
+ 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 = ndec + 3;
- if (dec < 3)
- dec = 3;
- cpdec = &cbuf[13];
- } else {
- dec = ndec;
- if (dec < 0)
- dec = 0;
- cpdec = &cbuf[10];
+ dec += 3;
+ cpdec += 3;
}
- if (dec > 12)
- dec = 12;
+ if ((size_t)dec > sizeof(cbuf) - (cpend - cbuf))
+ dec = sizeof(cbuf) - (cpend - cbuf);
/*
* If there's a fraction to deal with, do so.
*/
- if (fpv != 0) {
- l_fp work;
-
- work.l_ui = 0;
- work.l_uf = fpv;
- while (dec > 0) {
- l_fp ftmp;
-
- dec--;
- /*
- * 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.
- */
- work.l_ui = 0;
- L_LSHIFT(&work);
- ftmp = work;
- L_LSHIFT(&work);
- L_LSHIFT(&work);
- L_ADD(&work, &ftmp);
- *cpend++ = (u_char)work.l_ui;
- if (work.l_uf == 0)
- break;
- if (cpend > (cbuf + sizeof(cbuf))) abort(); /* rather die a horrible death than trash the memory */
- }
-
+ for (/*NOP*/; dec > 0 && fpv != 0; dec--) {
+ u_int32 digit, tmph, tmpl;
+
/*
- * Rounding is rotten
+ * 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.
*/
- if (work.l_uf & 0x80000000) {
- register u_char *tp = cpend;
+ 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);
- *(--tp) += 1;
- while (*tp >= 10) {
+ for (dec = tp - cbuf; carry && dec > 0; dec--) {
+ *--tp += 1;
+ if (*tp == 10)
*tp = 0;
- *(--tp) += 1;
- };
- if (tp < cp)
- cp = tp;
+ else
+ carry = FALSE;
}
- }
- cpend += dec;
+ if (tp < cp) /* rounding from 999 to 1000 or similiar? */
+ cp = tp;
+ }
/*
* We've now got the fraction in cbuf[], with cp pointing at
@@ -148,21 +114,18 @@ dolfptoa(
* Remove leading zeros, then format the number into the
* buffer.
*/
- while (cp < cpdec) {
- if (*cp != 0)
- break;
+ while (cp < cpdec && *cp == 0)
cp++;
- }
- if (cp == cpdec)
- --cp;
+ if (cp >= cpdec)
+ cp = cpdec - 1;
bp = buf;
if (neg)
- *bp++ = '-';
+ *bp++ = '-';
while (cp < cpend) {
if (cp == cpdec)
- *bp++ = '.';
- *bp++ = (char)(*cp++ + '0'); /* ascii dependent? */
+ *bp++ = '.';
+ *bp++ = (char)(*cp++) + '0';
}
*bp = '\0';
@@ -171,3 +134,41 @@ dolfptoa(
*/
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);
+}
+
+
OpenPOWER on IntegriCloud