Skip to content

Commit 2773333

Browse files
authored
Add divrem and fldmod (#24)
1 parent dd6e408 commit 2773333

File tree

3 files changed

+37
-0
lines changed

3 files changed

+37
-0
lines changed

src/functions.jl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,21 @@ end
5353
invlog1(b, x) = b^x
5454

5555
invlog2(b, x) = x^inv(b)
56+
57+
58+
function invdivrem((q, r), divisor)
59+
res = muladd(q, divisor, r)
60+
if abs(r) abs(divisor) && (iszero(r) || sign(r) == sign(res))
61+
res
62+
else
63+
throw(DomainError((q, r), "inverse for divrem(x) is not defined at this point"))
64+
end
65+
end
66+
67+
function invfldmod((q, r), divisor)
68+
if abs(r) abs(divisor) && (iszero(r) || sign(r) == sign(divisor))
69+
muladd(q, divisor, r)
70+
else
71+
throw(DomainError((q, r), "inverse for fldmod(x) is not defined at this point"))
72+
end
73+
end

src/inverse.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,8 @@ inverse(f::Base.Fix1{typeof(log)}) = Base.Fix1(invlog1, f.x)
143143
inverse(f::Base.Fix1{typeof(invlog1)}) = Base.Fix1(log, f.x)
144144
inverse(f::Base.Fix2{typeof(log)}) = Base.Fix2(invlog2, f.x)
145145
inverse(f::Base.Fix2{typeof(invlog2)}) = Base.Fix2(log, f.x)
146+
147+
inverse(f::Base.Fix2{typeof(divrem)}) = Base.Fix2(invdivrem, f.x)
148+
inverse(f::Base.Fix2{typeof(invdivrem)}) = Base.Fix2(divrem, f.x)
149+
inverse(f::Base.Fix2{typeof(fldmod)}) = Base.Fix2(invfldmod, f.x)
150+
inverse(f::Base.Fix2{typeof(invfldmod)}) = Base.Fix2(fldmod, f.x)

test/test_inverse.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,15 @@ InverseFunctions.inverse(f::Bar) = Bar(inv(f.A))
5252
end
5353
InverseFunctions.test_inverse(conj, 2 - 3im)
5454

55+
x = rand(0:10)
56+
for f in (Base.Fix2(divrem, rand([-5:-1; 1:5])), Base.Fix2(fldmod, rand([-5:-1; 1:5])), Base.Fix2(divrem, 0.123), Base.Fix2(fldmod, 0.123))
57+
compare = (a, b) -> all(isapprox.(a, b))
58+
InverseFunctions.test_inverse(f, x; compare=compare)
59+
InverseFunctions.test_inverse(f, -x; compare=compare)
60+
InverseFunctions.test_inverse(f, x/9; compare=compare)
61+
InverseFunctions.test_inverse(f, -x/9; compare=compare)
62+
end
63+
5564
# ensure that inverses have domains compatible with original functions
5665
@test_throws DomainError inverse(Base.Fix1(*, 0))
5766
@test_throws DomainError inverse(Base.Fix2(^, 0))
@@ -66,6 +75,11 @@ InverseFunctions.inverse(f::Bar) = Bar(inv(f.A))
6675
@test_throws DomainError inverse(Base.Fix1(^, -2))(3)
6776
@test_throws DomainError inverse(Base.Fix1(^, -2))(3)
6877

78+
@test_throws DomainError inverse(Base.Fix2(divrem, 5))((-3, 2))
79+
@test_throws DomainError inverse(Base.Fix2(fldmod, 5))((-3, -2))
80+
InverseFunctions.test_inverse(inverse(Base.Fix2(divrem, 5)), (-3, -2); compare=(==))
81+
InverseFunctions.test_inverse(inverse(Base.Fix2(fldmod, 5)), (-3, 2); compare=(==))
82+
6983
A = rand(5, 5)
7084
for f in (
7185
identity, inv, adjoint, transpose,

0 commit comments

Comments
 (0)