]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
Replace fixed-point format with floating-point in cmdmon protocol
authorMiroslav Lichvar <mlichvar@redhat.com>
Sat, 12 Dec 2009 17:23:26 +0000 (18:23 +0100)
committerMiroslav Lichvar <mlichvar@redhat.com>
Sun, 13 Dec 2009 10:07:34 +0000 (11:07 +0100)
candm.h
client.c
cmdmon.c
util.c
util.h

diff --git a/candm.h b/candm.h
index 9f44808098494b857b3806e950003ca201042fa9..fd937058a480292be265b8053fab75754db6f67b 100644 (file)
--- a/candm.h
+++ b/candm.h
@@ -102,6 +102,13 @@ typedef struct {
 /* This is used in tv_sec_high for 32-bit timestamps */
 #define TV_NOHIGHSEC 0x7fffffff
 
+/* 32-bit floating-point format consisting of 7-bit signed exponent
+   and 25-bit signed coefficient without hidden bit.
+   The result is calculated as: 2^(exp - 25) * coef */
+typedef struct {
+  int32_t f;
+} Float;
+
 /* The EOR (end of record) fields are used by the offsetof operator in
    pktlength.c, to get the number of bytes that ought to be
    transmitted for each packet type. */
@@ -145,18 +152,18 @@ typedef struct {
 
 typedef struct {
   IPAddr address;
-  int32_t new_max_delay;
+  Float new_max_delay;
   int32_t EOR;
 } REQ_Modify_Maxdelay;
 
 typedef struct {
   IPAddr address;
-  int32_t new_max_delay_ratio;
+  Float new_max_delay_ratio;
   int32_t EOR;
 } REQ_Modify_Maxdelayratio;
 
 typedef struct {
-  int32_t new_max_update_skew;
+  Float new_max_update_skew;
   int32_t EOR;
 } REQ_Modify_Maxupdateskew;
 
@@ -216,8 +223,8 @@ typedef struct {
   int32_t maxpoll;
   int32_t presend_minpoll;
   uint32_t authkey;
-  int32_t max_delay;
-  int32_t max_delay_ratio;
+  Float max_delay;
+  Float max_delay_ratio;
   uint32_t flags;
   int32_t EOR;
 } REQ_NTP_Source;
@@ -232,7 +239,7 @@ typedef struct {
 } REQ_WriteRtc;
 
 typedef struct {
-  int32_t dfreq;
+  Float dfreq;
   int32_t EOR;
 } REQ_Dfreq;
 
@@ -325,7 +332,8 @@ typedef struct {
    Version 3 : NTP_Source message lengthened (auto_offline)
 
    Version 4 : IPv6 addressing added, 64-bit time values, sourcestats 
-   and tracking reports extended, added flags to NTP source request
+   and tracking reports extended, added flags to NTP source request,
+   replaced fixed-point format with floating-point
 
  */
 
@@ -398,13 +406,6 @@ typedef struct {
 #define PERMIT_LOCAL 1
 #define PERMIT_AUTH 2
 
-/* ================================================== */
-/* These conversion utilities are used to convert between the internal
-   and the 'wire' representation of real quantities */
-
-#define WIRE2REAL(x) ((double) ((int32_t) ntohl(x)) / 65536.0)
-#define REAL2WIRE(x) (htonl((int32_t)(0.5 + 65536.0 * (x))))
-
 /* ================================================== */
 
 /* Reply codes */
@@ -487,11 +488,11 @@ typedef struct {
   Timeval ref_time;
   uint32_t current_correction_s;
   uint32_t current_correction_us;
-  int32_t freq_ppm;
-  int32_t resid_freq_ppm;
-  int32_t skew_ppm;
-  int32_t root_delay;
-  int32_t root_dispersion;
+  Float freq_ppm;
+  Float resid_freq_ppm;
+  Float skew_ppm;
+  Float root_delay;
+  Float root_dispersion;
   int32_t EOR;
 } RPY_Tracking;
 
@@ -502,8 +503,8 @@ typedef struct {
   uint32_t n_runs;
   uint32_t span_seconds;
   uint32_t sd_us;
-  int32_t resid_freq_ppm;
-  int32_t skew_ppm;
+  Float resid_freq_ppm;
+  Float skew_ppm;
   int32_t EOR;
 } RPY_Sourcestats;
 
@@ -512,15 +513,15 @@ typedef struct {
   uint16_t n_samples;
   uint16_t n_runs;
   uint32_t span_seconds;
-  int32_t rtc_seconds_fast;
-  int32_t rtc_gain_rate_ppm;
+  Float rtc_seconds_fast;
+  Float rtc_gain_rate_ppm;
   int32_t EOR;
 } RPY_Rtc;
 
 typedef struct {
   uint32_t centiseconds;
-  int32_t dfreq_ppm;
-  int32_t new_afreq_ppm;
+  Float dfreq_ppm;
+  Float new_afreq_ppm;
   int32_t EOR;
 } RPY_ManualTimestamp;
 
@@ -562,9 +563,9 @@ typedef struct {
 
 typedef struct {
   Timeval when;
-  int32_t slewed_offset;
-  int32_t orig_offset;
-  int32_t residual;
+  Float slewed_offset;
+  Float orig_offset;
+  Float residual;
 } RPY_ManualListSample;
 
 typedef struct {
index 1872d12c2b2a2defed80c2de111632b617fbb452..28ee1f60533873bbab6d11ec455b80db16106f4a 100644 (file)
--- a/client.c
+++ b/client.c
@@ -423,7 +423,7 @@ process_cmd_maxdelay(CMD_Request *msg, char *line)
   
   if (read_address_double(line, &address, &max_delay)) {
     UTI_IPHostToNetwork(&address, &msg->data.modify_maxdelay.address);
-    msg->data.modify_maxdelay.new_max_delay = REAL2WIRE(max_delay);
+    msg->data.modify_maxdelay.new_max_delay = UTI_FloatHostToNetwork(max_delay);
     msg->command = htons(REQ_MODIFY_MAXDELAY);
     ok = 1;
   } else {
@@ -445,7 +445,7 @@ process_cmd_maxdelayratio(CMD_Request *msg, char *line)
   
   if (read_address_double(line, &address, &max_delay_ratio)) {
     UTI_IPHostToNetwork(&address, &msg->data.modify_maxdelayratio.address);
-    msg->data.modify_maxdelayratio.new_max_delay_ratio = REAL2WIRE(max_delay_ratio);
+    msg->data.modify_maxdelayratio.new_max_delay_ratio = UTI_FloatHostToNetwork(max_delay_ratio);
     msg->command = htons(REQ_MODIFY_MAXDELAYRATIO);
     ok = 1;
   } else {
@@ -465,7 +465,7 @@ process_cmd_maxupdateskew(CMD_Request *msg, char *line)
   double new_max_update_skew;
   
   if (sscanf(line, "%lf", &new_max_update_skew) == 1) {
-    msg->data.modify_maxupdateskew.new_max_update_skew = REAL2WIRE(new_max_update_skew);
+    msg->data.modify_maxupdateskew.new_max_update_skew = UTI_FloatHostToNetwork(new_max_update_skew);
     msg->command = htons(REQ_MODIFY_MAXUPDATESKEW);
     ok = 1;
   } else {
@@ -845,9 +845,9 @@ process_cmd_dfreq(CMD_Request *msg, char *line)
   double dfreq;
   msg->command = htons(REQ_DFREQ);
   if (sscanf(line, "%lf", &dfreq) == 1) {
-    msg->data.dfreq.dfreq = REAL2WIRE(dfreq);
+    msg->data.dfreq.dfreq = UTI_FloatHostToNetwork(dfreq);
   } else {
-    msg->data.dfreq.dfreq = REAL2WIRE(0.0);
+    msg->data.dfreq.dfreq = UTI_FloatHostToNetwork(0.0);
   }
 }
 
@@ -908,8 +908,8 @@ process_cmd_add_server_or_peer(CMD_Request *msg, char *line)
       msg->data.ntp_source.maxpoll = htonl(data.params.maxpoll);
       msg->data.ntp_source.presend_minpoll = htonl(data.params.presend_minpoll);
       msg->data.ntp_source.authkey = htonl(data.params.authkey);
-      msg->data.ntp_source.max_delay = REAL2WIRE(data.params.max_delay);
-      msg->data.ntp_source.max_delay_ratio = REAL2WIRE(data.params.max_delay_ratio);
+      msg->data.ntp_source.max_delay = UTI_FloatHostToNetwork(data.params.max_delay);
+      msg->data.ntp_source.max_delay_ratio = UTI_FloatHostToNetwork(data.params.max_delay_ratio);
       msg->data.ntp_source.flags = htonl(
           (data.params.online ? REQ_ADDSRC_ONLINE : 0) |
           (data.params.auto_offline ? REQ_ADDSRC_AUTOOFFLINE : 0));
@@ -1682,9 +1682,9 @@ process_cmd_sourcestats(char *line)
           n_samples = ntohl(reply.data.sourcestats.n_samples);
           n_runs = ntohl(reply.data.sourcestats.n_runs);
           span_seconds = ntohl(reply.data.sourcestats.span_seconds);
-          resid_freq_ppm = WIRE2REAL(reply.data.sourcestats.resid_freq_ppm);
-          skew_ppm = WIRE2REAL(reply.data.sourcestats.skew_ppm);
           sd_us = ntohl(reply.data.sourcestats.sd_us);
+          resid_freq_ppm = UTI_FloatNetworkToHost(reply.data.sourcestats.resid_freq_ppm);
+          skew_ppm = UTI_FloatNetworkToHost(reply.data.sourcestats.skew_ppm);
 
           if (ip_addr.family == IPADDR_UNSPEC)
             snprintf(hostname_buf, sizeof(hostname_buf), "%s", UTI_RefidToString(ref_id));
@@ -1760,11 +1760,11 @@ process_cmd_tracking(char *line)
     correction = (double) correction_tv.tv_sec + 1.0e-6 * correction_tv.tv_usec;
     printf("System time     : %.6f seconds %s of NTP time\n", fabs(correction),
            (correction > 0.0) ? "slow" : "fast");
-    freq_ppm = WIRE2REAL(reply.data.tracking.freq_ppm);
-    resid_freq_ppm = WIRE2REAL(reply.data.tracking.resid_freq_ppm);
-    skew_ppm = WIRE2REAL(reply.data.tracking.skew_ppm);
-    root_delay = WIRE2REAL(reply.data.tracking.root_delay);
-    root_dispersion = WIRE2REAL(reply.data.tracking.root_dispersion);
+    freq_ppm = UTI_FloatNetworkToHost(reply.data.tracking.freq_ppm);
+    resid_freq_ppm = UTI_FloatNetworkToHost(reply.data.tracking.resid_freq_ppm);
+    skew_ppm = UTI_FloatNetworkToHost(reply.data.tracking.skew_ppm);
+    root_delay = UTI_FloatNetworkToHost(reply.data.tracking.root_delay);
+    root_dispersion = UTI_FloatNetworkToHost(reply.data.tracking.root_dispersion);
     printf("Frequency       : %.3f ppm %s\n", fabs(freq_ppm), (freq_ppm < 0.0) ? "slow" : "fast"); 
     printf("Residual freq   : %.3f ppm\n", resid_freq_ppm);
     printf("Skew            : %.3f ppm\n", skew_ppm);
@@ -1796,8 +1796,8 @@ process_cmd_rtcreport(char *line)
     n_samples = ntohs(reply.data.rtc.n_samples);
     n_runs = ntohs(reply.data.rtc.n_runs);
     span_seconds = ntohl(reply.data.rtc.span_seconds);
-    coef_seconds_fast = WIRE2REAL(reply.data.rtc.rtc_seconds_fast);
-    coef_gain_rate_ppm = WIRE2REAL(reply.data.rtc.rtc_gain_rate_ppm);
+    coef_seconds_fast = UTI_FloatNetworkToHost(reply.data.rtc.rtc_seconds_fast);
+    coef_gain_rate_ppm = UTI_FloatNetworkToHost(reply.data.rtc.rtc_gain_rate_ppm);
     printf("RTC ref time (UTC) : %s", asctime(&ref_time_tm));
     printf("Number of samples  : %d\n", n_samples);
     printf("Number of runs     : %d\n", n_runs);
@@ -2126,9 +2126,9 @@ process_cmd_manual_list(const char *line)
           for (i=0; i<n_samples; i++) {
             sample = &reply.data.manual_list.samples[i];
             UTI_TimevalNetworkToHost(&sample->when, &when);
-            slewed_offset = WIRE2REAL(sample->slewed_offset);
-            orig_offset = WIRE2REAL(sample->orig_offset);
-            residual = WIRE2REAL(sample->residual);
+            slewed_offset = UTI_FloatNetworkToHost(sample->slewed_offset);
+            orig_offset = UTI_FloatNetworkToHost(sample->orig_offset);
+            residual = UTI_FloatNetworkToHost(sample->residual);
             printf("%2d %s %10.2f %10.2f %10.2f\n", i, time_to_log_form(when.tv_sec), slewed_offset, orig_offset, residual);
           }
           return 1;
@@ -2180,8 +2180,8 @@ process_cmd_settime(char *line)
     if (request_reply(&request, &reply, RPY_MANUAL_TIMESTAMP, 1)) {
           offset_cs = ntohl(reply.data.manual_timestamp.centiseconds);
           offset = 0.01 * (double) offset_cs;
-          dfreq_ppm = WIRE2REAL(reply.data.manual_timestamp.dfreq_ppm);
-          new_afreq_ppm = WIRE2REAL(reply.data.manual_timestamp.new_afreq_ppm);
+          dfreq_ppm = UTI_FloatNetworkToHost(reply.data.manual_timestamp.dfreq_ppm);
+          new_afreq_ppm = UTI_FloatNetworkToHost(reply.data.manual_timestamp.new_afreq_ppm);
           printf("Clock was %.2f seconds fast.  Frequency change = %.2fppm, new frequency = %.2fppm\n",
               offset, dfreq_ppm, new_afreq_ppm);
           return 1;
index d1e69e4b6efda953a18914dbf28bf0a7fed0079d..afcf9c753590b978d5e395844c335655b126676e 100644 (file)
--- a/cmdmon.c
+++ b/cmdmon.c
@@ -881,7 +881,7 @@ handle_modify_maxdelay(CMD_Request *rx_message, CMD_Reply *tx_message)
   IPAddr address;
   UTI_IPNetworkToHost(&rx_message->data.modify_maxdelay.address, &address);
   status = NSR_ModifyMaxdelay(&address,
-                              WIRE2REAL(rx_message->data.modify_maxdelay.new_max_delay));
+                              UTI_FloatNetworkToHost(rx_message->data.modify_maxdelay.new_max_delay));
   if (status) {
     tx_message->status = htons(STT_SUCCESS);
   } else {
@@ -898,7 +898,7 @@ handle_modify_maxdelayratio(CMD_Request *rx_message, CMD_Reply *tx_message)
   IPAddr address;
   UTI_IPNetworkToHost(&rx_message->data.modify_maxdelayratio.address, &address);
   status = NSR_ModifyMaxdelayratio(&address,
-                                   WIRE2REAL(rx_message->data.modify_maxdelayratio.new_max_delay_ratio));
+                                   UTI_FloatNetworkToHost(rx_message->data.modify_maxdelayratio.new_max_delay_ratio));
   if (status) {
     tx_message->status = htons(STT_SUCCESS);
   } else {
@@ -911,7 +911,7 @@ handle_modify_maxdelayratio(CMD_Request *rx_message, CMD_Reply *tx_message)
 static void
 handle_modify_maxupdateskew(CMD_Request *rx_message, CMD_Reply *tx_message)
 {
-  REF_ModifyMaxupdateskew(WIRE2REAL(rx_message->data.modify_maxupdateskew.new_max_update_skew));
+  REF_ModifyMaxupdateskew(UTI_FloatNetworkToHost(rx_message->data.modify_maxupdateskew.new_max_update_skew));
   tx_message->status = htons(STT_SUCCESS);
 }
 
@@ -928,8 +928,8 @@ handle_settime(CMD_Request *rx_message, CMD_Reply *tx_message)
     tx_message->status = htons(STT_SUCCESS);
     tx_message->reply = htons(RPY_MANUAL_TIMESTAMP);
     tx_message->data.manual_timestamp.centiseconds = htonl(offset_cs);
-    tx_message->data.manual_timestamp.dfreq_ppm = REAL2WIRE(dfreq_ppm);
-    tx_message->data.manual_timestamp.new_afreq_ppm = REAL2WIRE(new_afreq_ppm);
+    tx_message->data.manual_timestamp.dfreq_ppm = UTI_FloatHostToNetwork(dfreq_ppm);
+    tx_message->data.manual_timestamp.new_afreq_ppm = UTI_FloatHostToNetwork(new_afreq_ppm);
   } else {
     tx_message->status = htons(STT_NOTENABLED);
   }
@@ -1236,8 +1236,8 @@ handle_add_server(CMD_Request *rx_message, CMD_Reply *tx_message)
   params.authkey = ntohl(rx_message->data.ntp_source.authkey);
   params.online  = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_ONLINE ? 1 : 0;
   params.auto_offline = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_AUTOOFFLINE ? 1 : 0;
-  params.max_delay = WIRE2REAL(rx_message->data.ntp_source.max_delay);
-  params.max_delay_ratio = WIRE2REAL(rx_message->data.ntp_source.max_delay_ratio);
+  params.max_delay = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay);
+  params.max_delay_ratio = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay_ratio);
   status = NSR_AddServer(&rem_addr, &params);
   switch (status) {
     case NSR_Success:
@@ -1276,8 +1276,8 @@ handle_add_peer(CMD_Request *rx_message, CMD_Reply *tx_message)
   params.authkey = ntohl(rx_message->data.ntp_source.authkey);
   params.online  = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_ONLINE ? 1 : 0;
   params.auto_offline = ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_AUTOOFFLINE ? 1 : 0;
-  params.max_delay = WIRE2REAL(rx_message->data.ntp_source.max_delay);
-  params.max_delay_ratio = WIRE2REAL(rx_message->data.ntp_source.max_delay_ratio);
+  params.max_delay = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay);
+  params.max_delay_ratio = UTI_FloatNetworkToHost(rx_message->data.ntp_source.max_delay_ratio);
   status = NSR_AddPeer(&rem_addr, &params);
   switch (status) {
     case NSR_Success:
@@ -1350,7 +1350,7 @@ static void
 handle_dfreq(CMD_Request *rx_message, CMD_Reply *tx_message)
 {
   double dfreq;
-  dfreq = WIRE2REAL(rx_message->data.dfreq.dfreq);
+  dfreq = UTI_FloatNetworkToHost(rx_message->data.dfreq.dfreq);
   LCL_AccumulateDeltaFrequency(dfreq * 1.0e-6);
   LOG(LOGS_INFO, LOGF_CmdMon, "Accumulated delta freq of %.3fppm", dfreq);
 }
@@ -1385,11 +1385,11 @@ handle_tracking(CMD_Request *rx_message, CMD_Reply *tx_message)
   UTI_TimevalHostToNetwork(&rpt.ref_time, &tx_message->data.tracking.ref_time);
   tx_message->data.tracking.current_correction_s = htonl(rpt.current_correction.tv_sec);
   tx_message->data.tracking.current_correction_us = htonl(rpt.current_correction.tv_usec);
-  tx_message->data.tracking.freq_ppm = REAL2WIRE(rpt.freq_ppm);
-  tx_message->data.tracking.resid_freq_ppm = REAL2WIRE(rpt.resid_freq_ppm);
-  tx_message->data.tracking.skew_ppm = REAL2WIRE(rpt.skew_ppm);
-  tx_message->data.tracking.root_delay = REAL2WIRE(rpt.root_delay);
-  tx_message->data.tracking.root_dispersion = REAL2WIRE(rpt.root_dispersion);
+  tx_message->data.tracking.freq_ppm = UTI_FloatHostToNetwork(rpt.freq_ppm);
+  tx_message->data.tracking.resid_freq_ppm = UTI_FloatHostToNetwork(rpt.resid_freq_ppm);
+  tx_message->data.tracking.skew_ppm = UTI_FloatHostToNetwork(rpt.skew_ppm);
+  tx_message->data.tracking.root_delay = UTI_FloatHostToNetwork(rpt.root_delay);
+  tx_message->data.tracking.root_dispersion = UTI_FloatHostToNetwork(rpt.root_dispersion);
 }
 
 /* ================================================== */
@@ -1410,9 +1410,9 @@ handle_sourcestats(CMD_Request *rx_message, CMD_Reply *tx_message)
     tx_message->data.sourcestats.n_samples = htonl(report.n_samples);
     tx_message->data.sourcestats.n_runs = htonl(report.n_runs);
     tx_message->data.sourcestats.span_seconds = htonl(report.span_seconds);
-    tx_message->data.sourcestats.resid_freq_ppm = REAL2WIRE(report.resid_freq_ppm);
-    tx_message->data.sourcestats.skew_ppm = REAL2WIRE(report.skew_ppm);
     tx_message->data.sourcestats.sd_us = htonl((unsigned long) (0.5 + report.sd_us));
+    tx_message->data.sourcestats.resid_freq_ppm = UTI_FloatHostToNetwork(report.resid_freq_ppm);
+    tx_message->data.sourcestats.skew_ppm = UTI_FloatHostToNetwork(report.skew_ppm);
   } else {
     tx_message->status = htons(STT_NOSUCHSOURCE);
   }
@@ -1433,8 +1433,8 @@ handle_rtcreport(CMD_Request *rx_message, CMD_Reply *tx_message)
     tx_message->data.rtc.n_samples = htons(report.n_samples);
     tx_message->data.rtc.n_runs = htons(report.n_runs);
     tx_message->data.rtc.span_seconds = htonl(report.span_seconds);
-    tx_message->data.rtc.rtc_seconds_fast = REAL2WIRE(report.rtc_seconds_fast);
-    tx_message->data.rtc.rtc_gain_rate_ppm = REAL2WIRE(report.rtc_gain_rate_ppm);
+    tx_message->data.rtc.rtc_seconds_fast = UTI_FloatHostToNetwork(report.rtc_seconds_fast);
+    tx_message->data.rtc.rtc_gain_rate_ppm = UTI_FloatHostToNetwork(report.rtc_gain_rate_ppm);
   } else {
     tx_message->status = htons(STT_NORTC);
   }
@@ -1648,9 +1648,9 @@ handle_manual_list(CMD_Request *rx_message, CMD_Reply *tx_message)
   for (i=0; i<n_samples; i++) {
     sample = &tx_message->data.manual_list.samples[i];
     UTI_TimevalHostToNetwork(&report[i].when, &sample->when);
-    sample->slewed_offset = REAL2WIRE(report[i].slewed_offset);
-    sample->orig_offset = REAL2WIRE(report[i].orig_offset);
-    sample->residual = REAL2WIRE(report[i].residual);
+    sample->slewed_offset = UTI_FloatHostToNetwork(report[i].slewed_offset);
+    sample->orig_offset = UTI_FloatHostToNetwork(report[i].orig_offset);
+    sample->residual = UTI_FloatHostToNetwork(report[i].residual);
   }
 }
 
diff --git a/util.c b/util.c
index 7ee93b8c7c8294a3962010ea1b76a857c387d6e7..c55f305987eb6133239257c850561dc88c8aee85 100644 (file)
--- a/util.c
+++ b/util.c
@@ -522,5 +522,77 @@ UTI_TimevalHostToNetwork(struct timeval *src, Timeval *dest)
   dest->tv_sec_low = htonl(src->tv_sec);
 }
 
+/* ================================================== */
+
+#define FLOAT_EXP_BITS 7
+#define FLOAT_EXP_MIN (-(1 << (FLOAT_EXP_BITS - 1)))
+#define FLOAT_EXP_MAX (-FLOAT_EXP_MIN - 1)
+#define FLOAT_COEF_BITS ((int)sizeof (int32_t) * 8 - FLOAT_EXP_BITS)
+#define FLOAT_COEF_MIN (-(1 << (FLOAT_COEF_BITS - 1)))
+#define FLOAT_COEF_MAX (-FLOAT_COEF_MIN - 1)
+
+double
+UTI_FloatNetworkToHost(Float f)
+{
+  int32_t exp, coef, x;
+
+  x = ntohl(f.f);
+  exp = (x >> FLOAT_COEF_BITS) - FLOAT_COEF_BITS;
+  coef = x << FLOAT_EXP_BITS >> FLOAT_EXP_BITS;
+  return coef * pow(2.0, exp);
+}
+
+Float
+UTI_FloatHostToNetwork(double x)
+{
+  int32_t exp, coef, neg;
+  Float f;
+
+  if (x < 0.0) {
+    x = -x;
+    neg = 1;
+  } else {
+    neg = 0;
+  }
+
+  if (x < 1.0e-100) {
+    exp = coef = 0;
+  } else if (x > 1.0e100) {
+    exp = FLOAT_EXP_MAX;
+    coef = FLOAT_COEF_MAX + neg;
+  } else {
+    exp = log(x) / log(2) + 1;
+    coef = x * pow(2.0, -exp + FLOAT_COEF_BITS) + 0.5;
+
+    assert(coef > 0);
+
+    /* we may need to shift up to two bits down */
+    while (coef > FLOAT_COEF_MAX + neg) {
+      coef >>= 1;
+      exp++;
+    }
+
+    if (exp > FLOAT_EXP_MAX) {
+      /* overflow */
+      exp = FLOAT_EXP_MAX;
+      coef = FLOAT_COEF_MAX + neg;
+    } else if (exp < FLOAT_EXP_MIN) {
+      /* underflow */
+      if (exp + FLOAT_COEF_BITS >= FLOAT_EXP_MIN) {
+        coef >>= FLOAT_EXP_MIN - exp;
+        exp = FLOAT_EXP_MIN;
+      } else {
+        exp = coef = 0;
+      }
+    }
+  }
+
+  /* negate back */
+  if (neg)
+    coef = (uint32_t)-coef << FLOAT_EXP_BITS >> FLOAT_EXP_BITS;
+
+  f.f = htonl(exp << FLOAT_COEF_BITS | coef);
+  return f;
+}
 
 /* ================================================== */
diff --git a/util.h b/util.h
index 31e790c1a5655fb96d973223ce8d4588ea6968a8..645659fe8e00988b2aa3b51dea5170b60940cde7 100644 (file)
--- a/util.h
+++ b/util.h
@@ -99,6 +99,9 @@ extern void UTI_Int64ToTimeval(NTP_int64 *src, struct timeval *dest);
 extern void UTI_TimevalNetworkToHost(Timeval *src, struct timeval *dest);
 extern void UTI_TimevalHostToNetwork(struct timeval *src, Timeval *dest);
 
+extern double UTI_FloatNetworkToHost(Float x);
+extern Float UTI_FloatHostToNetwork(double x);
+
 #if defined (INLINE_UTILITIES)
 #define INLINE_STATIC inline static
 #include "util.c"