Skip to content

Commit a880f15

Browse files
committed
Fix a few errors, replace README, add basic tests
1 parent f44bfd6 commit a880f15

File tree

5 files changed

+37
-63
lines changed

5 files changed

+37
-63
lines changed

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Float128 is licensed under the MIT License:
22

3-
Copyright (c) 2016: Harald Hofstätter
3+
Copyright (c) 2016: Harald Hofstätter, Simon Byrne
44

55
Permission is hereby granted, free of charge, to any person obtaining
66
a copy of this software and associated documentation files (the

README.md

Lines changed: 6 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,12 @@
11
# Quadmath.jl
2-
Float128 and libquadmath for the Julia language
32

4-
##Installation
5-
```julia
6-
Pkg.clone("https://github.com/HaraldHofstaetter/Quadmath.jl")
7-
Pkg.build("Quadmath")
8-
```
9-
##Examples
10-
To get easy access to the examples, copy them into the home directory:
3+
This is a Julia interface to libquadmath, providing a `Float128` type corresponding to the IEEE754 binary128 floating point format.
4+
5+
## Installation
116
```julia
12-
cp(joinpath(homedir(), ".julia/v0.4/Quadmath/examples/"), joinpath(homedir(), "Quadmath_examples"))
7+
Pkg.clone("https://github.com/simonbyrne/Quadmath.jl")
138
```
14-
Then 'Quadmath_examples' will be listed in the JuliaBox home screen. The examples contain among others
15-
+ [BesselZeros.ipynb](https://github.com/HaraldHofstaetter/Quadmath.jl/blob/master/examples/BesselZeros.ipynb):
16-
In this notebook it is demonstrated that `Float128` is about 4 times faster than `BigFloat` with 113 bit precision
17-
(the precision of `Float128`).
18-
19-
##Bugs
20-
+ `ccall` does not treat parameters and returning values of Julia type `Float128` properly as C type `__float128`.
21-
22-
Unfortunately, this is a bug which cannot easily be fixed without modifying the internals of Julia.
23-
The [x86-64 Application Binary Interface](http://www.x86-64.org/documentation.html)
24-
says that parameters and returning values of type `__float128` should be passed preferably in the (128 bit long) SSE floating point registers `xmm0`,...,`xmm7`. However, for the datatype `Float128` defined as
25-
```julia
26-
bitstype 128 Float128 <: AbstractFloat
27-
```
28-
in [Quadmath.jl](https://github.com/HaraldHofstaetter/Quadmath.jl/blob/master/src/Quadmath.jl),
29-
`ccall` seems to use the same calling convention as for something like
30-
```c
31-
struct{
32-
uint64_t u0;
33-
uint64_t u1;
34-
} words64;
35-
```
36-
in C.
37-
38-
As a remedy, you can implement a wrapper function for each external function with `__float128` parameters
39-
or return values, that you want to call with `ccall`. Such a wrapper takes parameters `x` of type
40-
`myfloat128` declared as
41-
```c
42-
typedef union
43-
{
44-
__float128 value;
45-
46-
struct{
47-
uint64_t u0;
48-
uint64_t u1;
49-
} words64;
50-
} myfloat128;
51-
```
52-
and calls the original function with `x.value` as actual parameter for the corresponding formal parameter of type
53-
`__float128`.
54-
This is exactly the technique we use in
55-
[quadmath_wrapper.c](https://github.com/HaraldHofstaetter/Quadmath.jl/blob/master/deps/src/quadmath_wrapper.c)
56-
to call the functions of the [libquadmath](https://gcc.gnu.org/onlinedocs/libquadmath/) library.
57-
589

10+
## Acknowledgements
5911

12+
Thank you to Harald Hofstätter, who provided the first iteration of [Quadmath.jl](https://github.com/HaraldHofstaetter/Quadmath.jl).

REQUIRE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
julia 0.4-
1+
julia 0.5

src/Quadmath.jl

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
# This file is modelled after https://github.com/JuliaLang/julia/blob/master/base/mpfr.jl
2-
# which implements the BigFloat type
3-
41
__precompile__()
52
module Quadmath
63

74
export Float128, Complex256
85

9-
import Base: (*), +, -, /, <, <=, ==, >, >=, ^, convert, reinterpret,
6+
import Base: (*), +, -, /, <, <=, ==, ^, convert,
7+
reinterpret, sign_mask, exponent_mask, exponent_one, exponent_half,
8+
significand_mask,
109
promote_rule, widen,
1110
string, print, show, showcompact, parse,
1211
acos, acosh, asin, asinh, atan, atanh, cosh, cos,
@@ -22,6 +21,8 @@ import Base: (*), +, -, /, <, <=, ==, >, >=, ^, convert, reinterpret,
2221

2322
const libquadmath = "libquadmath.0"
2423

24+
# we use this slightly cumbersome definition to ensure that the value is passed
25+
# on the xmm registers, matching the x86_64 ABI for __float128.
2526
typealias Cfloat128 NTuple{2,VecElement{Float64}}
2627

2728
immutable Float128 <: AbstractFloat
@@ -33,8 +34,8 @@ typealias Complex256 Complex{Float128}
3334

3435
Base.cconvert(::Type{Cfloat128}, x::Float128) = x.data
3536

36-
# reinterpret
3737

38+
# reinterpret
3839
function reinterpret(::Type{UInt128}, x::Float128)
3940
hi = reinterpret(UInt64, x.data[2].value)
4041
lo = reinterpret(UInt64, x.data[1].value)
@@ -45,12 +46,22 @@ function reinterpret(::Type{Float128}, x::UInt128)
4546
flo = reinterpret(Float64, x % UInt64)
4647
Float128((VecElement(flo), VecElement(fhi)))
4748
end
49+
reinterpret(::Type{Unsigned}, x::Float128) = reinterpret(UInt128, x)
50+
4851
reinterpret(::Type{Int128}, x::Float128) =
4952
reinterpret(Int128, reinterpret(UInt128, x))
5053
reinterpret(::Type{Float128}, x::Int128) =
5154
reinterpret(Float128, reinterpret(UInt128, x))
5255

5356

57+
sign_mask(::Type{Float128}) = 0x8000_0000_0000_0000_0000_0000_0000_0000
58+
exponent_mask(::Type{Float128}) = 0x7fff_0000_0000_0000_0000_0000_0000_0000
59+
exponent_one(::Type{Float128}) = 0x3fff_0000_0000_0000_0000_0000_0000_0000
60+
exponent_half(::Type{Float128}) = 0x3ffe_0000_0000_0000_0000_0000_0000_0000
61+
significand_mask(::Type{Float128}) = 0x0000_ffff_ffff_ffff_ffff_ffff_ffff_ffff
62+
63+
fpinttype(::Type{Float128}) = UInt128
64+
5465
# conversion
5566

5667
## Float64
@@ -80,13 +91,13 @@ convert(::Type{Float128}, x::Clong) =
8091
# comparison
8192

8293
(==)(x::Float128, y::Float128) =
83-
0 != ccall((:__eqtf2,libquadmath), Cint, (Cfloat128,Cfloat128), x, y)
94+
ccall((:__eqtf2,libquadmath), Cint, (Cfloat128,Cfloat128), x, y) == 0
8495

8596
(<)(x::Float128, y::Float128) =
86-
0 != ccall((:__lttf2,libquadmath), Cint, (Cfloat128,Cfloat128), x, y)
97+
ccall((:__letf2,libquadmath), Cint, (Cfloat128,Cfloat128), x, y) == -1
8798

8899
(<=)(x::Float128, y::Float128) =
89-
0 != ccall((:__letf2,libquadmath), Cint, (Cfloat128,Cfloat128), x, y)
100+
ccall((:__letf2,libquadmath), Cint, (Cfloat128,Cfloat128), x, y) <= 0
90101

91102
# arithmetic
92103

test/runtests.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using Base.Test
2+
using Quadmath
3+
4+
@test Float128(1) + Float128(2) == Float128(3)
5+
@test Float128(1) + Float128(2) <= Float128(3)
6+
@test Float128(1) + Float128(2) != Float128(4)
7+
@test Float128(1) + Float128(2) < Float128(4)
8+
@test Float64(Float128(1) + Float128(2)) === 3.0
9+
10+
@test Base.exponent_one(Float128) == reinterpret(UInt128, Float128(1))

0 commit comments

Comments
 (0)