Patchwork [3,of,6,faster-obsmarkers,v2] util: add getbefloat64

login
register
mail settings
Submitter Augie Fackler
Date Feb. 3, 2015, 6:31 p.m.
Message ID <b39c616665257bd5107e.1422988271@arthedain.pit.corp.google.com>
Download mbox | patch
Permalink /patch/7640/
State Accepted
Commit fb93721cc22957e42f9b16d12c927826f564d419
Headers show

Comments

Augie Fackler - Feb. 3, 2015, 6:31 p.m.
# HG changeset patch
# User Augie Fackler <augie@google.com>
# Date 1422987441 18000
#      Tue Feb 03 13:17:21 2015 -0500
# Node ID b39c616665257bd5107ee68329fff3a126db255b
# Parent  0c18599df5197890d37fcb9397c5f9cfe7d770a8
util: add getbefloat64

As far as I can tell, this is wrong. double's format isn't strictly
specified in the C standard, but the wikipedia article implies that
platforms implementing optional Annex F "IEC 60559 floating-point
arithmetic" will work correctly.

My local C experts believe doing *((double *) &t) is a strict aliasing
violation, and that using a union is also one. Doing memcpy appears to
be the least-undefined behavior possible.
Matt Mackall - Feb. 4, 2015, 12:32 a.m.
On Tue, 2015-02-03 at 13:31 -0500, Augie Fackler wrote:
> # HG changeset patch
> # User Augie Fackler <augie@google.com>
> # Date 1422987441 18000
> #      Tue Feb 03 13:17:21 2015 -0500
> # Node ID b39c616665257bd5107ee68329fff3a126db255b
> # Parent  0c18599df5197890d37fcb9397c5f9cfe7d770a8
> util: add getbefloat64
> 
> As far as I can tell, this is wrong. double's format isn't strictly
> specified in the C standard, but the wikipedia article implies that
> platforms implementing optional Annex F "IEC 60559 floating-point
> arithmetic" will work correctly.
> 
> My local C experts believe doing *((double *) &t) is a strict aliasing
> violation, and that using a union is also one. Doing memcpy appears to
> be the least-undefined behavior possible.

The union thing is specifically called out as an exception to the strict
aliasing rule for at least C99 and later, in the same bullet list that
excepts char * (thus letting memcpy work). (Sec 6.5 par 7)

(Using a union as the recommended way to do type punning goes all the
way back to first edition K&R, and it's arguably its primary use case as
a language feature.)

Patch

diff --git a/mercurial/util.h b/mercurial/util.h
--- a/mercurial/util.h
+++ b/mercurial/util.h
@@ -196,4 +196,17 @@  static inline void putbe32(uint32_t x, c
 	c[3] = (x) & 0xff;
 }
 
+static inline double getbefloat64(const char *c)
+{
+	const unsigned char *d = (const unsigned char *)c;
+	double ret;
+	int i;
+	uint64_t t = 0;
+	for (i = 0; i < 8; i++) {
+		t = (t<<8) + d[i];
+	}
+	memcpy(&ret, &t, sizeof(t));
+	return ret;
+}
+
 #endif /* _HG_UTIL_H_ */