[Git][NTPsec/ntpsec][master] 3 commits: Simplify dtolfp an lfptod conversions

Eric S. Raymond gitlab at mg.gitlab.com
Sun Mar 12 19:01:04 UTC 2017


Eric S. Raymond pushed to branch master at NTPsec / ntpsec


Commits:
3dd0816b by Achim Gratz at 2017-03-12T15:00:33-04:00
Simplify dtolfp an lfptod conversions

include/ntp_fp.h (dtolfp, lfptod): Assume that C99/POSIX standard
library functions are implemented correctly.

- - - - -
11128723 by Achim Gratz at 2017-03-12T15:00:33-04:00
Remove s_fp, simplify DTOUFP and FPTOD macros dealing with u_fp.

include/ntp_fp.h (s_fp, DTOFP, FPTOD, FRIC, fptoa, fptoms):
Remove.  (DTOUFP): Leave the actual work to the FPU via ldexp.
libntp/dofptoa.c ()fptoa, fptoms: Remove.
ntpd/ntp_proto.c (peer_xmit, pool_xmit): Replace DTOFP with DTOUFP,
produces the same bit pattern anyway. (ctl_putsfp): Replace FPTOD
with direct conversion via ldexp.
tests/libntp/sfptostr.c: Remove.
tests/common/tests_main.c (RunAllTests): Remove sfptostr tests.
tests/wscript: Remove build recipe for libntp/sfptostr.c
devel/tour.txt: Hopefully more clear description of the internal NTP
date and timestamp types.  Mention removal of s_fp.

- - - - -
a58fe23d by Achim Gratz at 2017-03-12T15:00:33-04:00
Provide FP scaling macros and use them.

include/ntp_fp.h (FP_SCALE, FP_UNSCALE): Scale and unscale 16
bits.  (DTOUFP): use new macro.
ntpd/ntp_control.c: Use new macro and remove direct scaling.
ntptime/ntptime.c (main): Use new macros instead of direct computations.

- - - - -


9 changed files:

- devel/tour.txt
- include/ntp_fp.h
- libntp/dofptoa.c
- ntpd/ntp_control.c
- ntpd/ntp_proto.c
- ntptime/ntptime.c
- tests/common/tests_main.c
- − tests/libntp/sfptostr.c
- tests/wscript


Changes:

=====================================
devel/tour.txt
=====================================
--- a/devel/tour.txt
+++ b/devel/tour.txt
@@ -23,13 +23,29 @@ home-brews three fixed-point types of its own.  Of these l_fp is the
 most common, with 32 bits of precision in both integer and fractional
 parts. Gory details are in include/ntp_fp.h.
 
-One point not covered there is that when used to represent dates
-internally an l_fp is normally interpreted as a pair consisting of
-an *unsigned* number of seconds since 1900-01-01T00:00:00Z (the
-NTP epoch) and unsigned decimal fractional seconds.  Just to complicate
-matters, however, some uses of l_fp are time offsets with a signed
-seconds part - how it's interpreted depends on which member of a union
-is used.
+One point not covered there is that an l_fp is actually a symmetrical
+truncation of the full NTP date (for which no data type exists) about
+the fixed point location.  The full NTP date has 64 bits for both the
+integer and fractional part, which get truncated to the right 32bit
+for the fractional and the left 32bit for the fractional part to
+become an l_fp.  For most calculations with l_fp it's easier to
+envision it as a 64bit integer that represents time with a unit of
+2^-32s, slightly short of 233 ps.
+
+When used to represent dates internally an l_fp must be interpreted in
+relation to the NTP era (the left 32 bits of the integer part of the
+NTP date that got cut off).  The NTP prime epoch (or epoch 0) is then
+an *unsigned* number of seconds since 1900-01-01T00:00:00Z and
+unsigned decimal fractional seconds.  Just to complicate matters,
+however, some uses of l_fp are time offsets with a signed seconds
+part.  Under the assumption that only adjacent epochs get compared,
+the offset calculations work correctly without taking the era number
+into account.
+
+Most time offsets are much smaller than the NTP epoch, so a 32 bit
+representation is used for these.  Actually, there were two of these:
+s_fp for signed offsets and u_fp for strictly non-negative ones.  The
+signed version has already been removed in NTPsec.
 
 The comments in libntp/ntp_calendar.c are pretty illuminating about
 calendar representations.  A high-level point they don't make is


=====================================
include/ntp_fp.h
=====================================
--- a/include/ntp_fp.h
+++ b/include/ntp_fp.h
@@ -101,7 +101,6 @@ static inline l_fp lfpinit_u(uint32_t sec, uint32_t frac)
  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *
  */
-typedef int32_t s_fp;
 typedef uint32_t u_fp;
 
 /*
@@ -149,12 +148,12 @@ static inline l_fp ntohl_fp(l_fp_w lfpw) {
 #define	L_ISGTU(a, b)	((a) > (b))
 
 /*
- * s_fp/double and u_fp/double conversions
+ * scaling to 32bit FP format
+ * double to u_fp conversion
  */
-#define FRIC		65536.0			/* 2^16 as a double */
-#define DTOFP(r)	((s_fp)((r) * FRIC))
-#define DTOUFP(r)	((u_fp)((r) * FRIC))
-#define FPTOD(r)	((double)(r) / FRIC)
+#define FP_SCALE(r)	(ldexp((double)(r),  16))
+#define FP_UNSCALE(r)	(ldexp((double)(r), -16))
+#define DTOUFP(r)	((u_fp)FP_SCALE(r))
 
 /*
  * l_fp/double conversions
@@ -164,41 +163,19 @@ static inline l_fp ntohl_fp(l_fp_w lfpw) {
 #include <math.h>	/* ldexp() */
 
 static inline l_fp dtolfp(double d)
-/* double to l_fp */
+/* double to l_fp
+ * assumes signed l_fp, i.e. a time offset
+ */
 {
-	double	d_tmp;
-	uint64_t	q_tmp;
-	int	M_isneg;
-
-	d_tmp = (d);
-	M_isneg = (d_tmp < 0.);
-	if (M_isneg) {
-		d_tmp = -d_tmp;
-	}
-	q_tmp = (uint64_t)ldexp(d_tmp, 32);
-	if (M_isneg) {
-		q_tmp = ~q_tmp + 1;
-	}
-	return lfpinit_u(q_tmp >> 32, (uint32_t)q_tmp);
+	return (l_fp)((int64_t)ldexp(d, 32));
 }
 
 static inline double lfptod(l_fp r)
-/* l_fp to double */
+/* l_fp to double
+ * assumes signed l_fp, i.e. a time offset
+ */
 {
-	double	d;
-	uint64_t	q_tmp;
-	int	M_isneg;
-
-	q_tmp = ((uint64_t)lfpuint(r) << 32) + lfpfrac(r);
-	M_isneg = M_ISNEG(lfpuint(r));
-	if (M_isneg) {
-		q_tmp = ~q_tmp + 1;
-	}
-	d = ldexp((double)q_tmp, -32);
-	if (M_isneg) {
-		d = -d;
-	}
-	return d;
+	return ldexp((double)((int64_t)r), -32);
 }
 
 /*
@@ -210,8 +187,6 @@ extern	char *	mfptoa		(l_fp, short);
 extern	char *	mfptoms		(l_fp, short);
 
 extern	bool	atolfp		(const char *, l_fp *);
-extern	char *	fptoa		(s_fp, short);
-extern	char *	fptoms		(s_fp, short);
 extern	bool	hextolfp	(const char *, l_fp *);
 extern  void	gpstolfp	(int, int, unsigned long, l_fp *);
 extern	bool	mstolfp		(const char *, l_fp *);


=====================================
libntp/dofptoa.c
=====================================
--- a/libntp/dofptoa.c
+++ b/libntp/dofptoa.c
@@ -117,43 +117,3 @@ dofptoa(
 	*bp = '\0';
 	return buf;
 }
-
-
-char *
-fptoa(
-	s_fp	fpv,
-	short	ndec
-	)
-{
-	u_fp	plusfp;
-	bool	isneg;
-
-	isneg = (fpv < 0);
-	if (isneg) {
-		plusfp = (u_fp)(-fpv);
-	} else {
-		plusfp = (u_fp)fpv;
-	}
-
-	return dofptoa(plusfp, isneg, ndec, false);
-}
-
-
-char *
-fptoms(
-	s_fp	fpv,
-	short	ndec
-	)
-{
-	u_fp	plusfp;
-	bool	isneg;
-
-	isneg = (fpv < 0);
-	if (isneg) {
-		plusfp = (u_fp)(-fpv);
-	} else {
-		plusfp = (u_fp)fpv;
-	}
-
-	return dofptoa(plusfp, isneg, ndec, true);
-}


=====================================
ntpd/ntp_control.c
=====================================
--- a/ntpd/ntp_control.c
+++ b/ntpd/ntp_control.c
@@ -58,7 +58,7 @@ static	void	ctl_putdblf	(const char *, int, int, double);
 #define	ctl_putdbl(tag, d)	ctl_putdblf(tag, 1, 3, d)
 #define	ctl_putdbl6(tag, d)	ctl_putdblf(tag, 1, 6, d)
 #define	ctl_putsfp(tag, sfp)	ctl_putdblf(tag, 0, -1, \
-					    FPTOD(sfp))
+					    FP_UNSCALE(sfp))
 static	void	ctl_putuint	(const char *, u_long);
 static	void	ctl_puthex	(const char *, u_long);
 static	void	ctl_putint	(const char *, long);


=====================================
ntpd/ntp_proto.c
=====================================
--- a/ntpd/ntp_proto.c
+++ b/ntpd/ntp_proto.c
@@ -2164,7 +2164,7 @@ peer_xmit(
 	xpkt.ppoll = peer->hpoll;
 	xpkt.precision = sys_precision;
 	xpkt.refid = sys_refid;
-	xpkt.rootdelay = HTONS_FP(DTOFP(sys_rootdelay));
+	xpkt.rootdelay = HTONS_FP(DTOUFP(sys_rootdelay));
 	xpkt.rootdisp =	 HTONS_FP(DTOUFP(sys_rootdisp));
 	xpkt.reftime = htonl_fp(sys_reftime);
 	xpkt.org = htonl_fp(peer->rec);
@@ -2324,7 +2324,7 @@ fast_xmit(
 		xpkt.ppoll = max(rpkt->ppoll, ntp_minpoll);
 		xpkt.precision = sys_precision;
 		xpkt.refid = sys_refid;
-		xpkt.rootdelay = HTONS_FP(DTOFP(sys_rootdelay));
+		xpkt.rootdelay = HTONS_FP(DTOUFP(sys_rootdelay));
 		xpkt.rootdisp = HTONS_FP(DTOUFP(sys_rootdisp));
 
 #ifdef ENABLE_LEAP_SMEAR
@@ -2474,7 +2474,7 @@ pool_xmit(
 	xpkt.ppoll = pool->hpoll;
 	xpkt.precision = sys_precision;
 	xpkt.refid = sys_refid;
-	xpkt.rootdelay = HTONS_FP(DTOFP(sys_rootdelay));
+	xpkt.rootdelay = HTONS_FP(DTOUFP(sys_rootdelay));
 	xpkt.rootdisp = HTONS_FP(DTOUFP(sys_rootdisp));
 	xpkt.reftime = htonl_fp(sys_reftime);
 	get_systime(&xmt_tx);


=====================================
ntptime/ntptime.c
=====================================
--- a/ntptime/ntptime.c
+++ b/ntptime/ntptime.c
@@ -63,8 +63,6 @@ int ntp_gettime(struct ntptimeval *ntv)
 \11PPSSIGNAL\12PPSJITTER\13PPSWANDER\14PPSERROR\15CLOCKERR\
 \16NANO\17MODE\20CLK"
 
-#define SCALE_FREQ 65536		/* frequency scale */
-
 /*
  * These constants are used to round the time stamps computed from
  * a struct timeval to the microsecond (more or less).  This keeps
@@ -152,7 +150,7 @@ main(
 
 		case 'f':
 			ntx.modes |= MOD_FREQUENCY;
-			ntx.freq = (long)(atof(ntp_optarg) * SCALE_FREQ);
+			ntx.freq = (long)FP_SCALE(atof(ntp_optarg));
 			break;
 
 		case 'j':
@@ -378,14 +376,14 @@ main(
 		       snprintb(sizeof(binbuf), binbuf, ntx.modes, TIMEX_MOD_BITS));
 		ftemp = (double)ntx.offset/NS_PER_MS_FLOAT;
 		printf(json ? jfmt9 : ofmt9, ftemp);
-		ftemp = (double)ntx.freq / SCALE_FREQ;
+		ftemp = FP_UNSCALE(ntx.freq);
 		printf(json ? jfmt10 : ofmt10, ftemp, 1 << ntx.shift);
 		printf(json ? jfmt11 : ofmt11,
 		     (u_long)ntx.maxerror, (u_long)ntx.esterror);
 		printf(json ? jfmt12 : ofmt12,
 		       snprintb(sizeof(binbuf), binbuf,
 			       (u_int)ntx.status, TIMEX_STA_BITS));
-		ftemp = (double)ntx.tolerance / SCALE_FREQ;
+		ftemp = FP_UNSCALE(ntx.tolerance);
 		/*
 		 * Before the introduction of ntp_adjtime_ns() the
 		 * ntptime code divided this by 1000 when the STA_NANO
@@ -397,8 +395,8 @@ main(
 		printf(json ? jfmt13 : ofmt13,
 			(u_long)ntx.constant, gtemp, ftemp);
 		if (ntx.shift != 0) {
-			ftemp = (double)ntx.ppsfreq / SCALE_FREQ;
-			gtemp = (double)ntx.stabil / SCALE_FREQ;
+		  ftemp = FP_UNSCALE(ntx.ppsfreq);
+		  gtemp = FP_UNSCALE(ntx.stabil);
 			htemp = (double)ntx.jitter/NS_PER_MS_FLOAT;
 			printf(json ? jfmt14 : ofmt14,
 			    ftemp, gtemp, htemp);


=====================================
tests/common/tests_main.c
=====================================
--- a/tests/common/tests_main.c
+++ b/tests/common/tests_main.c
@@ -54,7 +54,6 @@ static void RunAllTests(void)
 	RUN_TEST_GROUP(prettydate);
 	RUN_TEST_GROUP(recvbuff);
 	RUN_TEST_GROUP(refidsmear);
-	RUN_TEST_GROUP(sfptostr);
 	RUN_TEST_GROUP(socktoa);
 	RUN_TEST_GROUP(statestr);
 	RUN_TEST_GROUP(strtolfp);


=====================================
tests/libntp/sfptostr.c deleted
=====================================
--- a/tests/libntp/sfptostr.c
+++ /dev/null
@@ -1,89 +0,0 @@
-#include "config.h"
-#include "ntp_stdlib.h"
-
-#include "unity.h"
-#include "unity_fixture.h"
-
-TEST_GROUP(sfptostr);
-
-TEST_SETUP(sfptostr) {}
-
-TEST_TEAR_DOWN(sfptostr) {}
-
-/* 
- * This file contains test for both fptoa and fptoms (which uses dofptoa),
- * since all these functions are very similar.
- */
-
-
-#include "ntp_fp.h"
-
-static const int SFP_MAX_PRECISION = 6;
-
-TEST(sfptostr, PositiveInteger) {
-	s_fp test = 300 << 16; // exact 300.000000
-
-	TEST_ASSERT_EQUAL_STRING("300.000000", fptoa(test, SFP_MAX_PRECISION));
-	TEST_ASSERT_EQUAL_STRING("300000.000", fptoms(test, SFP_MAX_PRECISION));
-}
-
-TEST(sfptostr, NegativeInteger) {
-	/* Mask to avoid warnings.  See issue #71 */
-	s_fp test = (-200 & 0xffff)  << 16; // exact -200.000000
-
-	TEST_ASSERT_EQUAL_STRING("-200.000000", fptoa(test, SFP_MAX_PRECISION));
-	TEST_ASSERT_EQUAL_STRING("-200000.000", fptoms(test, SFP_MAX_PRECISION));
-}
-
-TEST(sfptostr, PositiveIntegerPositiveFraction) {
-	s_fp test = (300 << 16) + (1 << 15); // 300 + 0.5
-
-	TEST_ASSERT_EQUAL_STRING("300.500000", fptoa(test, SFP_MAX_PRECISION));
-	TEST_ASSERT_EQUAL_STRING("300500.000", fptoms(test, SFP_MAX_PRECISION));
-}
-
-TEST(sfptostr, NegativeIntegerNegativeFraction) {
-	s_fp test = ((-200 & 0xffff) << 16) - (1 << 15); // -200 - 0.5
-
-	TEST_ASSERT_EQUAL_STRING("-200.500000", fptoa(test, SFP_MAX_PRECISION));
-	TEST_ASSERT_EQUAL_STRING("-200500.000", fptoms(test, SFP_MAX_PRECISION));
-}
-
-TEST(sfptostr, PositiveIntegerNegativeFraction) {
-	s_fp test = (300 << 16) - (1 << 14); // 300 - 0.25
-
-	TEST_ASSERT_EQUAL_STRING("299.750000", fptoa(test, SFP_MAX_PRECISION));
-	TEST_ASSERT_EQUAL_STRING("299750.000", fptoms(test, SFP_MAX_PRECISION));
-}
-
-TEST(sfptostr, NegativeIntegerPositiveFraction) {
-	s_fp test = ((-200 & 0xffff) << 16) + (1 << 14)*3; // -200 + 0.75
-
-	TEST_ASSERT_EQUAL_STRING("-199.250000", fptoa(test, SFP_MAX_PRECISION));
-	TEST_ASSERT_EQUAL_STRING("-199250.000", fptoms(test, SFP_MAX_PRECISION));
-}
-
-TEST(sfptostr, SingleDecimalInteger) {
-	s_fp test = 300 << 16; // 300
-
-	TEST_ASSERT_EQUAL_STRING("300.0", fptoa(test, 1));
-	TEST_ASSERT_EQUAL_STRING("300000.0", fptoms(test, 1));
-}
-
-TEST(sfptostr, SingleDecimalRounding) {
-	s_fp test = (2 << 16) + (1 << 14)*3; // 2 + 0.25*3 = 2.75
-
-	TEST_ASSERT_EQUAL_STRING("2.8", fptoa(test, 1));
-	TEST_ASSERT_EQUAL_STRING("2750.0", fptoms(test, 1));
-}
-
-TEST_GROUP_RUNNER(sfptostr) {
-	RUN_TEST_CASE(sfptostr, PositiveInteger);
-	RUN_TEST_CASE(sfptostr, NegativeInteger);
-	RUN_TEST_CASE(sfptostr, PositiveIntegerPositiveFraction);
-	RUN_TEST_CASE(sfptostr, NegativeIntegerNegativeFraction);
-	RUN_TEST_CASE(sfptostr, PositiveIntegerNegativeFraction);
-	RUN_TEST_CASE(sfptostr, NegativeIntegerPositiveFraction);
-	RUN_TEST_CASE(sfptostr, SingleDecimalInteger);
-	RUN_TEST_CASE(sfptostr, SingleDecimalRounding);
-}


=====================================
tests/wscript
=====================================
--- a/tests/wscript
+++ b/tests/wscript
@@ -41,7 +41,6 @@ def build(ctx):
         "libntp/prettydate.c",
         "libntp/recvbuff.c",
         "libntp/refidsmear.c",
-        "libntp/sfptostr.c",
         "libntp/socktoa.c",
         "libntp/statestr.c",
         "libntp/strtolfp.c",



View it on GitLab: https://gitlab.com/NTPsec/ntpsec/compare/e0cd833887b6ad20819a0110ab16705ee2ebdc78...a58fe23d91eee1478f08a4e08d8d75a37ace6f8f
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.ntpsec.org/pipermail/vc/attachments/20170312/6436a535/attachment.html>


More information about the vc mailing list