summaryrefslogtreecommitdiff
path: root/dev-python/numpy/files/numpy-1.25.0-fix-long-double-check.patch
blob: 4f3ef21c93b3961c495ce3cdf31941a0d3cbb6dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
https://github.com/numpy/numpy/commit/de0b2d5c6dee9303c4a055e7591978ed5a06e403

From de0b2d5c6dee9303c4a055e7591978ed5a06e403 Mon Sep 17 00:00:00 2001
From: matoro <matoro@users.noreply.github.com>
Date: Sun, 18 Jun 2023 19:39:06 -0400
Subject: [PATCH] BLD: Port long double identification to C for meson

This ports the old Python code for identifying the long double
representation to C, so that it can be easily invoked by meson.  The
original implementation is at https://github.com/numpy/numpy/blob/eead09a3d02c09374942cdc787c0b5e4fe9e7472/numpy/core/setup_common.py#L264-L434

The C portion of the code has been tested and confirmed to work on
systems with the following formats, either natively or via an
alternative ABI:  INTEL_EXTENDED_16_BYTES_LE, IEEE_QUAD_BE,
IEEE_QUAD_LE, IBM_DOUBLE_DOUBLE_BE, IBM_DOUBLE_DOUBLE_LE,
IEEE_DOUBLE_BE, INTEL_EXTENDED_12_BYTES_LE.

The original meson port includes an error condition with the comment
"This should not be possible, 12 bits of "content" should still result
in sizeof() being 16."  As far as I can tell this is incorrect, as
compiling on an x86_64 system with 32-bit ABI (gcc -m32) does indeed
have sizeof(long double)==12.  This is reflected in the C code.

Closes gh-23972, closes
https://github.com/mesonbuild/meson/issues/11068.
---
 numpy/core/meson.build | 110 ++++++++++++++++++++++++++++++++---------
 1 file changed, 87 insertions(+), 23 deletions(-)

diff --git a/numpy/core/meson.build b/numpy/core/meson.build
index 3427de408f1..92b393e4bc1 100644
--- a/numpy/core/meson.build
+++ b/numpy/core/meson.build
@@ -361,29 +361,93 @@ foreach intrin: optional_intrinsics
   endif
 endforeach
 
-# long double representation detection (see setup_common.py)
-# TODO: this is still incomplete, and different from how it's done in the
-# numpy.distutils based build, see https://github.com/mesonbuild/meson/issues/11068
-longdouble_size = cc.sizeof('long double')
-if longdouble_size == 8
-  if host_machine.endian() == 'little'
-    longdouble_format = 'IEEE_DOUBLE_LE'
-  else
-    longdouble_format = 'IEEE_DOUBLE_BE'
-  endif
-elif longdouble_size == 12
-  error('This should not be possible, 12 bits of "content" should still result in sizeof() being 16. Please report this error!'
-  )
-elif longdouble_size == 16
-  if host_machine.endian() == 'little'
-    # FIXME: this varies, there's multiple formats here! Not yet implemented.
-    #        TBD how we deal with the mess of old long double formats.
-    longdouble_format = 'INTEL_EXTENDED_16_BYTES_LE'
-  else
-    error('No idea what this is ....')
-  endif
-else
-  error('Unknown long double size: ' + londouble_size)
+# This is a port of the old python code for identifying the long double
+# representation to C.  The old Python code is in this range:
+# https://github.com/numpy/numpy/blob/eead09a3d02c09374942cdc787c0b5e4fe9e7472/numpy/core/setup_common.py#L264-L434
+# This port is in service of solving gh-23972
+# as well as https://github.com/mesonbuild/meson/issues/11068
+longdouble_format = meson.get_compiler('c').run(
+'''
+#include <stdio.h>
+#include <string.h>
+
+#define repcmp(z) (memcmp((const char *)&foo.x, z, sizeof(foo.x)) == 0)
+
+const struct {
+  char before[16];
+  long double x;
+  char after[8];
+} foo = {{'\0'}, -123456789.0, {'\0'}};
+
+int main(void) {
+  switch (sizeof(foo.x)) {
+  case 8: {
+    if (repcmp(
+            ((const char[]){0000, 0000, 0000, 0124, 0064, 0157, 0235, 0301}))) {
+      fprintf(stdout, "IEEE_DOUBLE_LE");
+      return 0;
+    }
+    if (repcmp(
+            ((const char[]){0301, 0235, 0157, 0064, 0124, 0000, 0000, 0000}))) {
+      fprintf(stdout, "IEEE_DOUBLE_BE");
+      return 0;
+    }
+    fprintf(stdout, "UNKNOWN");
+    return 1;
+  }
+  case 12: {
+    if (repcmp(((const char[]){0000, 0000, 0000, 0000, 0240, 0242, 0171, 0353,
+                               0031, 0300, 0000, 0000}))) {
+      fprintf(stdout, "INTEL_EXTENDED_12_BYTES_LE");
+      return 0;
+    }
+    if (repcmp(((const char[]){0300, 0031, 0000, 0000, 0353, 0171, 0242, 0240,
+                               0000, 0000, 0000, 0000}))) {
+      fprintf(stdout, "MOTOROLA_EXTENDED_12_BYTES_BE");
+      return 0;
+    }
+    fprintf(stdout, "UNKNOWN");
+    return 1;
+  }
+  case 16: {
+    if (repcmp(
+            ((const char[]){0000, 0000, 0000, 0000, 0240, 0242, 0171, 0353,
+                            0031, 0300, 0000, 0000, 0000, 0000, 0000, 0000}))) {
+      fprintf(stdout, "INTEL_EXTENDED_16_BYTES_LE");
+      return 0;
+    }
+    if (repcmp(
+            ((const char[]){0300, 0031, 0326, 0363, 0105, 0100, 0000, 0000,
+                            0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000}))) {
+      fprintf(stdout, "IEEE_QUAD_BE");
+      return 0;
+    }
+    if (repcmp(
+            ((const char[]){0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000,
+                            0000, 0000, 0100, 0105, 0363, 0326, 0031, 0300}))) {
+      fprintf(stdout, "IEEE_QUAD_LE");
+      return 0;
+    }
+    if (repcmp(
+            ((const char[]){0000, 0000, 0000, 0124, 0064, 0157, 0235, 0301,
+                            0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000}))) {
+      fprintf(stdout, "IBM_DOUBLE_DOUBLE_LE");
+      return 0;
+    }
+    if (repcmp(
+            ((const char[]){0301, 0235, 0157, 0064, 0124, 0000, 0000, 0000,
+                            0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000}))) {
+      fprintf(stdout, "IBM_DOUBLE_DOUBLE_BE");
+      return 0;
+    }
+    fprintf(stdout, "UNKNOWN");
+    return 1;
+  }
+  }
+}
+''').stdout()
+if longdouble_format == 'UNKNOWN' or longdouble_format == 'UNDEFINED'
+  error('Unknown long double format of size: ' + cc.sizeof('long double').to_string())
 endif
 cdata.set10('HAVE_LDOUBLE_' + longdouble_format, true)