Skip to content

Commit 498e041

Browse files
conversions to/from BigFloat
1 parent 5e764fc commit 498e041

File tree

6 files changed

+366
-32
lines changed

6 files changed

+366
-32
lines changed

Makefile

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,14 @@ all: libfloat128.so
33
float128.o: float128.c
44
gcc -O3 -fPIC -c -o float128.o float128.c
55

6-
libfloat128.so: float128.o
7-
gcc -shared -o libfloat128.so float128.o -lquadmath
6+
set_float128.o: set_float128.c
7+
gcc -O3 -fpic -c -I/home/hofi/LibDownloads/mpfr-3.1.3/src -I/home/hofi/include -o set_float128.o -I/home/hofi/LibDownloads/mpfr-3.1.3/src/x86_64/core2 set_float128.c
88

9+
get_float128.o: get_float128.c
10+
gcc -O3 -fpic -c -I/home/hofi/LibDownloads/mpfr-3.1.3/src -I/home/hofi/include -o get_float128.o -I/home/hofi/LibDownloads/mpfr-3.1.3/src/x86_64/core2 get_float128.c
11+
12+
libfloat128.so: float128.o set_float128.o get_float128.o
13+
gcc -shared -o libfloat128.so float128.o set_float128.o get_float128.o -lquadmath -L/usr/lib/sagemath/local/lib/ -lmpfr
14+
15+
16+

float128.c

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,7 @@
11
#include <stdio.h>
22
#include <stdint.h>
33
#include <quadmath.h>
4-
5-
6-
typedef union
7-
{
8-
__float128 value;
9-
10-
struct{
11-
uint64_t u0;
12-
uint64_t u1;
13-
} words64;
14-
15-
} myfloat128;
16-
17-
typedef union
18-
{
19-
__complex128 value;
20-
21-
struct{
22-
uint64_t u0;
23-
uint64_t u1;
24-
uint64_t u2;
25-
uint64_t u3;
26-
} words64;
27-
28-
} mycomplex128;
29-
30-
31-
#define F(x) (x.value)
32-
4+
#include "float128.h"
335

346
myfloat128 convert_qd(double a) { myfloat128 res; F(res) = a; return res; }
357
myfloat128 convert_qui(unsigned long a) { myfloat128 res; F(res) = a; return res; }

float128.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#include <stdint.h>
2+
#include <quadmath.h>
3+
4+
typedef union
5+
{
6+
__float128 value;
7+
8+
struct{
9+
uint64_t u0;
10+
uint64_t u1;
11+
} words64;
12+
13+
} myfloat128;
14+
15+
typedef union
16+
{
17+
__complex128 value;
18+
19+
struct{
20+
uint64_t u0;
21+
uint64_t u1;
22+
uint64_t u2;
23+
uint64_t u3;
24+
} words64;
25+
26+
} mycomplex128;
27+
28+
29+
#define F(x) (x.value)
30+

float128.jl

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,12 +263,24 @@ end
263263
function string(x::Float128)
264264
lng = 64
265265
buf = Array(UInt8, lng + 1)
266-
lng = ccall((:stringq,:libfloat128), Int32, (Ptr{UInt8}, Culong, Ptr{UInt8}, Float128,), buf, lng + 1, "%.33Qe", x)
266+
lng = ccall((:stringq,:libfloat128), Int32, (Ptr{UInt8}, Culong, Ptr{UInt8}, Float128,), buf, lng + 1, "%.35Qe", x)
267267
return bytestring(pointer(buf), lng)
268268
end
269269

270270
print(io::IO, b::Float128) = print(io, string(b))
271271
show(io::IO, b::Float128) = print(io, string(b))
272272
showcompact(io::IO, b::Float128) = print(io, string(b))
273273

274+
const ROUNDING_MODE = Cint[0]
275+
276+
function convert(::Type{BigFloat}, x::Float128)
277+
z = BigFloat()
278+
ccall((:mpfr_set_float128_xxx, :libfloat128), Int32, (Ptr{BigFloat}, Float128, Int32), &z, x, ROUNDING_MODE[end])
279+
return z
280+
end
281+
282+
convert(::Type{Float128}, x::BigFloat) =
283+
ccall((:mpfr_get_float128_xxx, :libfloat128), Float128, (Ptr{BigFloat},Int32), &x, ROUNDING_MODE[end])
284+
285+
274286
end

get_float128.c

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/* mpfr_get_float128 -- convert a multiple precision floating-point
2+
number to a __float128 number
3+
4+
Copyright 2012-2015 Free Software Foundation, Inc.
5+
Contributed by the AriC and Caramel projects, INRIA.
6+
7+
This file is part of the GNU MPFR Library.
8+
9+
The GNU MPFR Library is free software; you can redistribute it and/or modify
10+
it under the terms of the GNU Lesser General Public License as published by
11+
the Free Software Foundation; either version 3 of the License, or (at your
12+
option) any later version.
13+
14+
The GNU MPFR Library is distributed in the hope that it will be useful, but
15+
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16+
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17+
License for more details.
18+
19+
You should have received a copy of the GNU Lesser General Public License
20+
along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see
21+
http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
22+
51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
23+
24+
#define MPFR_WANT_FLOAT128
25+
#define IEEE_FLOAT128_MANT_DIG 113
26+
27+
#include "mpfr-impl.h"
28+
29+
#ifdef MPFR_WANT_FLOAT128
30+
31+
/* generic code */
32+
__float128
33+
mpfr_get_float128 (mpfr_srcptr x, mpfr_rnd_t rnd_mode)
34+
{
35+
36+
if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
37+
return (__float128) mpfr_get_d (x, rnd_mode);
38+
else /* now x is a normal non-zero number */
39+
{
40+
__float128 r; /* result */
41+
__float128 m;
42+
double s; /* part of result */
43+
mpfr_exp_t sh; /* exponent shift, so that x/2^sh is in the double range */
44+
mpfr_t y, z;
45+
int sign;
46+
47+
/* first round x to the target __float128 precision, so that
48+
all subsequent operations are exact (this avoids double rounding
49+
problems) */
50+
mpfr_init2 (y, IEEE_FLOAT128_MANT_DIG);
51+
mpfr_init2 (z, IEEE_FLOAT128_MANT_DIG);
52+
53+
mpfr_set (y, x, rnd_mode);
54+
sh = MPFR_GET_EXP (y);
55+
sign = MPFR_SIGN (y);
56+
MPFR_SET_EXP (y, 0);
57+
MPFR_SET_POS (y);
58+
59+
r = 0.0;
60+
do
61+
{
62+
s = mpfr_get_d (y, MPFR_RNDN); /* high part of y */
63+
r += (__float128) s;
64+
mpfr_set_d (z, s, MPFR_RNDN); /* exact */
65+
mpfr_sub (y, y, z, MPFR_RNDN); /* exact */
66+
}
67+
while (MPFR_NOTZERO (y));
68+
69+
mpfr_clear (z);
70+
mpfr_clear (y);
71+
72+
/* we now have to multiply r by 2^sh */
73+
MPFR_ASSERTD (r > 0);
74+
if (sh != 0)
75+
{
76+
/* An overflow may occur (example: 0.5*2^1024) */
77+
while (r < 1.0)
78+
{
79+
r += r;
80+
sh--;
81+
}
82+
83+
if (sh > 0)
84+
m = 2.0;
85+
else
86+
{
87+
m = 0.5;
88+
sh = -sh;
89+
}
90+
91+
for (;;)
92+
{
93+
if (sh % 2)
94+
r = r * m;
95+
sh >>= 1;
96+
if (sh == 0)
97+
break;
98+
m = m * m;
99+
}
100+
}
101+
if (sign < 0)
102+
r = -r;
103+
return r;
104+
}
105+
}
106+
107+
#endif /* MPFR_WANT_FLOAT128 */
108+
109+
110+
#include <stdint.h>
111+
#include "float128.h"
112+
113+
myfloat128
114+
mpfr_get_float128_xxx (mpfr_srcptr x, mpfr_rnd_t rnd_mode)
115+
{
116+
myfloat128 res;
117+
F(res) = mpfr_get_float128 (x, rnd_mode);
118+
return res;
119+
}
120+
121+

0 commit comments

Comments
 (0)