Skip to content

Commit 46f424d

Browse files
yashrajguptadpsanders
authored andcommitted
Fix rational power function[WIP] (#286)
* Fix rational power function * Modify rational power function * Removing Big interval * Add rounding * Add rational power function * improve rational power function * Using ccall function * wrapping mpfr function * add tests * add version * Add project.toml file * Remove older julia versions * correcting in julia versions
1 parent 766bef9 commit 46f424d

File tree

8 files changed

+143
-18
lines changed

8 files changed

+143
-18
lines changed

.travis.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ os:
1010
- osx
1111

1212
julia:
13-
- 0.7
14-
- 1.0
1513
- 1.1
1614
- nightly
1715

Project.toml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name = "IntervalArithmetic"
2+
uuid = "d1acc4aa-44c8-5952-acd4-ba5d80a2a253"
3+
4+
[compat]
5+
CRlibm = "≥ 0.7.0"
6+
StaticArrays = "≥ 0.8.0"
7+
FastRounding = "≥ 0.1.2"
8+
SetRounding = "≥ 0.2.0"
9+
RecipesBase = "≥ 0.5.0"
10+
julia = "≥ 1.1.0"
11+
12+
[deps]
13+
CRlibm = "96374032-68de-5a5b-8d9e-752f78720389"
14+
FastRounding = "fa42c844-2597-5d31-933b-ebd51ab2693f"
15+
RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
16+
SetRounding = "3cc68bcd-71a2-5612-b932-767ffbe40ab0"
17+
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
18+
19+
[extras]
20+
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
21+
22+
[targets]
23+
test = ["Test"]

REQUIRE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
julia 0.7
1+
julia 1.1
22
CRlibm 0.7
33
StaticArrays 0.8
44
FastRounding 0.1.2

appveyor.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
environment:
22
matrix:
3-
- julia_version: 0.7
4-
- julia_version: 1
3+
- julia_version: 1.1
54
- julia_version: nightly
65

76
platform:

src/IntervalArithmetic.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ import Base: # for IntervalBox
4343
getindex, setindex,
4444
iterate, eltype
4545

46+
import Base.MPFR: MPFRRoundingMode
47+
import Base.MPFR: MPFRRoundUp, MPFRRoundDown, MPFRRoundNearest, MPFRRoundToZero, MPFRRoundFromZero
48+
4649
import .Broadcast: broadcasted
4750

4851
export

src/intervals/functions.jl

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# Use the BigFloat version from MPFR instead, which is correctly-rounded:
77

88
# Write explicitly like this to avoid ambiguity warnings:
9-
for T in (:Integer, :Rational, :Float64, :BigFloat, :Interval)
9+
for T in (:Integer, :Float64, :BigFloat, :Interval)
1010
@eval ^(a::Interval{Float64}, x::$T) = atomic(Interval{Float64}, big53(a)^x)
1111
end
1212

@@ -142,25 +142,61 @@ function ^(a::Interval{Rational{T}}, x::AbstractFloat) where T<:Integer
142142
end
143143

144144
# Rational power
145-
function ^(a::Interval{BigFloat}, r::Rational{S}) where S<:Integer
146-
T = BigFloat
145+
function ^(a::Interval{T}, x::Rational) where T
147146
domain = Interval{T}(0, Inf)
148147

148+
p = x.num
149+
q = x.den
150+
151+
isempty(a) && return emptyinterval(a)
152+
x == 0 && return one(a)
153+
149154
if a == zero(a)
150-
a = a domain
151-
r > zero(r) && return zero(a)
155+
x > zero(x) && return zero(a)
152156
return emptyinterval(a)
153157
end
154158

155-
isinteger(r) && return atomic(Interval{T}, a^round(S,r))
156-
r == one(S)//2 && return sqrt(a)
159+
x == (1//2) && return sqrt(a)
160+
161+
if x >= 0
162+
if a.lo 0
163+
isinteger(x) && return a ^ Int64(x)
164+
a = @biginterval(a)
165+
ui = convert(Culong, q)
166+
low = BigFloat()
167+
high = BigFloat()
168+
ccall((:mpfr_rootn_ui, :libmpfr) , Int32 , (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode) , low , a.lo , ui, MPFRRoundDown)
169+
ccall((:mpfr_rootn_ui, :libmpfr) , Int32 , (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode) , high , a.hi , ui, MPFRRoundUp)
170+
b = interval(low, high)
171+
b = convert(Interval{T}, b)
172+
return b^p
173+
end
157174

158-
a = a domain
159-
(isempty(r) || isempty(a)) && return emptyinterval(a)
175+
if a.lo < 0 && a.hi 0
176+
isinteger(x) && return a ^ Int64(x)
177+
a = a Interval{T}(0, Inf)
178+
a = @biginterval(a)
179+
ui = convert(Culong, q)
180+
low = BigFloat()
181+
high = BigFloat()
182+
ccall((:mpfr_rootn_ui, :libmpfr) , Int32 , (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode) , low , a.lo , ui, MPFRRoundDown)
183+
ccall((:mpfr_rootn_ui, :libmpfr) , Int32 , (Ref{BigFloat}, Ref{BigFloat}, Culong, MPFRRoundingMode) , high , a.hi , ui, MPFRRoundUp)
184+
b = interval(low, high)
185+
b = convert(Interval{T}, b)
186+
return b^p
187+
end
188+
189+
if a.hi < 0
190+
isinteger(x) && return a ^ Int64(x)
191+
return emptyinterval(a)
192+
end
160193

161-
y = atomic(Interval{BigFloat}, r)
194+
end
195+
196+
if x < 0
197+
return inv(a^(-x))
198+
end
162199

163-
a^y
164200
end
165201

166202
# Interval power of an interval:

test/interval_tests/numeric.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,15 @@ end
114114
setprecision(Interval, 256)
115115
x = @biginterval(27)
116116
y = x^(1//3)
117-
@test (0 < diam(y) < 1e-76)
117+
@test diam(y) == 0
118118
y = x^(1/3)
119-
@test (0 < diam(y) < 1e-76)
119+
@test (0 <= diam(y) < 1e-76)
120+
x = @biginterval(9.595703125)
121+
y = x^(1//3)
122+
@test diam(y) == 0
123+
x = @biginterval(0.1)
124+
y = x^(1//3)
125+
@test (0 <= diam(y) < 1e-76)
120126

121127
end
122128

test/interval_tests/power.jl

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#Test library imports
2+
using Test
3+
4+
#Arithmetic library imports
5+
using IntervalArithmetic
6+
7+
#Preamble
8+
setprecision(53)
9+
setprecision(Interval, Float64)
10+
setrounding(Interval, :tight)
11+
# Set full format, and show decorations
12+
@format full
13+
@testset "rational_power_test" begin
14+
@test ^(∅, 1//3) ==
15+
@test ^(1 .. 8, 1//3) == Interval(1, 2)
16+
@test ^(2 .. 8, 1//3) Interval(2^(1//3), 2)
17+
@test ^(1 .. 9, 1//3) Interval(1, 9^(1//3))
18+
@test ^(2 .. 9, 1//3) Interval(2^(1//3), 9^(1//3))
19+
@test ^(-1 .. 8, 1//3) == Interval(0, 2)
20+
@test ^(-2 .. 8, 1//3) Interval(0, 2)
21+
@test ^(-1 .. 9, 1//3) Interval(0, 9^(1//3))
22+
@test ^(-2 .. 9, 1//3) Interval(0, 9^(1//3))
23+
@test ^(1 .. 8, -1//3) == Interval(0.5, 1)
24+
@test ^(2 .. 8, -1//3) Interval(0.5, 2^(-1//3))
25+
@test ^(1 .. 9, -1//3) Interval(9^(-1//3), 1)
26+
@test ^(2 .. 9, -1//3) Interval(9^(-1//3), 2^(-1//3))
27+
@test ^(-1 .. 8, -1//3) == Interval(0.5, Inf)
28+
@test ^(-2 .. 8, -1//3) Interval(0.5, Inf)
29+
@test ^(-1 .. 9, -1//3) Interval(9^(-1//3), Inf)
30+
@test ^(-2 .. 9, -1//3) Interval(9^(-1//3), Inf)
31+
@test ^(-2 .. 4 , 1//2) == Interval(0, 2)
32+
@test ^(-2 .. 8 , 1//3) == Interval(0, 2)
33+
@test ^(-8 .. -2 , 1//3) ==
34+
@test ^(-8 .. -2 , 1//2) ==
35+
@test ^(-8 .. -2 , -1//3) ==
36+
@test ^(-8 .. -2 , -1//2) ==
37+
@test ^(∅, 2//3) ==
38+
@test ^(1 .. 8, 2//3) == Interval(1, 4)
39+
@test ^(2 .. 8, 2//3) Interval(2^(2//3), 4)
40+
@test ^(1 .. 9, 2//3) Interval(1, 9^(2//3))
41+
@test ^(2 .. 9, 2//3) Interval(2^(2//3), 9^(2//3))
42+
@test ^(-1 .. 8, 2//3) == Interval(0, 4)
43+
@test ^(-2 .. 8, 2//3) Interval(0, 4)
44+
@test ^(-1 .. 9, 2//3) Interval(0, 9^(2//3))
45+
@test ^(-2 .. 9, 2//3) Interval(0, 9^(2//3))
46+
@test ^(1 .. 8, -2//3) == Interval(0.25, 1)
47+
@test ^(2 .. 8, -2//3) Interval(0.25, 2^(-2//3))
48+
@test ^(1 .. 9, -2//3) Interval(9^(-2//3), 1)
49+
@test ^(2 .. 9, -2//3) Interval(9^(-2//3), 2^(-2//3))
50+
@test ^(-1 .. 8, -2//3) == Interval(0.25, Inf)
51+
@test ^(-2 .. 8, -2//3) Interval(0.25, Inf)
52+
@test ^(-1 .. 9, -2//3) Interval(9^(-2//3), Inf)
53+
@test ^(-2 .. 9, -2//3) Interval(9^(-2//3), Inf)
54+
@test ^(-2 .. 4 , 3//2) == Interval(0, 8)
55+
@test ^(-2 .. 8 , 2//3) == Interval(0, 4)
56+
@test ^(-8 .. -2 , 2//3) ==
57+
@test ^(-8 .. -2 , 3//2) ==
58+
@test ^(-8 .. -2 , -2//3) ==
59+
@test ^(-8 .. -2 , -3//2) ==
60+
end

0 commit comments

Comments
 (0)