Skip to content

Commit

Permalink
Merge pull request #902 from adler-j/issue-319__linearspace_more_perm…
Browse files Browse the repository at this point in the history
…issive

Issue 319  linearspace more permissive
  • Loading branch information
adler-j committed Feb 13, 2017
2 parents e2e970c + 62c9109 commit 796ffb0
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 47 deletions.
23 changes: 16 additions & 7 deletions odl/operator/operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -1251,8 +1251,12 @@ def derivative(self, point):

def __repr__(self):
"""Return ``repr(self)``."""
return '{}({!r}, {!r})'.format(self.__class__.__name__, self.operator,
self.vector)
return '{}({!r}, {!r})'.format(self.__class__.__name__,
self.operator, self.vector)

def __str__(self):
"""Return ``str(self)``."""
return '({} + {})'.format(self.left, self.right)


class OperatorComp(Operator):
Expand Down Expand Up @@ -1614,7 +1618,8 @@ def adjoint(self):

def __repr__(self):
"""Return ``repr(self)``."""
return '{} * {!r}'.format(self.scalar, self.operator)
return '{}({!r}, {!r})'.format(self.__class__.__name__,
self.operator, self.scalar)

def __str__(self):
"""Return ``str(self)``."""
Expand Down Expand Up @@ -1793,7 +1798,8 @@ def adjoint(self):

def __repr__(self):
"""Return ``repr(self)``."""
return '{!r} * {}'.format(self.operator, self.scalar)
return '{}({!r}, {!r})'.format(self.__class__.__name__,
self.operator, self.scalar)

def __str__(self):
"""Return ``str(self)``."""
Expand Down Expand Up @@ -1908,7 +1914,8 @@ def adjoint(self):

def __repr__(self):
"""Return ``repr(self)``."""
return '{} * {!r}'.format(self.vector, self.functional)
return '{}({!r}, {!r})'.format(self.__class__.__name__,
self.functional, self.vector)

def __str__(self):
"""Return ``str(self)``."""
Expand Down Expand Up @@ -2016,7 +2023,8 @@ def adjoint(self):

def __repr__(self):
"""Return ``repr(self)``."""
return '{} * {!r}'.format(self.vector, self.operator)
return '{}({!r}, {!r})'.format(self.__class__.__name__,
self.operator, self.vector)

def __str__(self):
"""Return ``str(self)``."""
Expand Down Expand Up @@ -2131,7 +2139,8 @@ def adjoint(self):

def __repr__(self):
"""Return ``repr(self)``."""
return '{!r} * {}'.format(self.operator, self.vector)
return '{}({!r}, {!r})'.format(self.__class__.__name__,
self.operator, self.vector)

def __str__(self):
"""Return ``str(self)``."""
Expand Down
15 changes: 9 additions & 6 deletions odl/operator/pspace_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -798,8 +798,9 @@ def __repr__(self):
>>> id = odl.IdentityOperator(spc)
>>> odl.BroadcastOperator(id, 3)
BroadcastOperator(IdentityOperator(rn(3)), 3)
>>> odl.BroadcastOperator(id, 2 * id)
BroadcastOperator(IdentityOperator(rn(3)), 2 * IdentityOperator(rn(3)))
>>> scale = odl.ScalingOperator(spc, 3)
>>> odl.BroadcastOperator(id, scale)
BroadcastOperator(IdentityOperator(rn(3)), ScalingOperator(rn(3), 3.0))
"""
if all(op == self[0] for op in self):
return '{}({!r}, {})'.format(self.__class__.__name__,
Expand Down Expand Up @@ -971,8 +972,9 @@ def __repr__(self):
>>> id = odl.IdentityOperator(spc)
>>> odl.ReductionOperator(id, 3)
ReductionOperator(IdentityOperator(rn(3)), 3)
>>> odl.ReductionOperator(id, 2 * id)
ReductionOperator(IdentityOperator(rn(3)), 2 * IdentityOperator(rn(3)))
>>> scale = odl.ScalingOperator(spc, 3)
>>> odl.ReductionOperator(id, scale)
ReductionOperator(IdentityOperator(rn(3)), ScalingOperator(rn(3), 3.0))
"""
if all(op == self[0] for op in self):
return '{}({!r}, {})'.format(self.__class__.__name__,
Expand Down Expand Up @@ -1173,8 +1175,9 @@ def __repr__(self):
>>> id = odl.IdentityOperator(spc)
>>> odl.DiagonalOperator(id, 3)
DiagonalOperator(IdentityOperator(rn(3)), 3)
>>> odl.DiagonalOperator(id, 2 * id)
DiagonalOperator(IdentityOperator(rn(3)), 2 * IdentityOperator(rn(3)))
>>> scale = odl.ScalingOperator(spc, 3)
>>> odl.DiagonalOperator(id, scale)
DiagonalOperator(IdentityOperator(rn(3)), ScalingOperator(rn(3), 3.0))
"""
if all(op == self[0] for op in self):
return '{}({!r}, {})'.format(self.__class__.__name__,
Expand Down
162 changes: 130 additions & 32 deletions odl/set/space.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,26 +508,39 @@ def __iadd__(self, other):
"""Implement ``self += other``."""
if other in self.space:
return self.space.lincomb(1, self, 1, other, out=self)
elif isinstance(other, LinearSpaceElement):
# We do not `return NotImplemented` here since we don't want a
# fallback for in-place. Otherwise python attempts
# `self = self + other` which does not modify self.
raise TypeError('cannot add {!r} and {!r} in place'
''.format(self, other))
elif other in self.space.field:
one = getattr(self.space, 'one', None)
if one is None:
return NotImplemented
raise TypeError('cannot add {!r} and {!r} in place'
''.format(self, other))
else:
# other --> other * space.one()
return self.space.lincomb(1, self, other, one(), out=self)
else:
# We do not `return NotImplemented` here since we don't want a
# fallback for in-place. Otherwise python attempts
# `self = self + other` which does not modify self.
raise TypeError('cannot add {!r} and {!r} in place'
''.format(self, other))
try:
other = self.space.element(other)
except (TypeError, ValueError):
raise TypeError('cannot add {!r} and {!r} in place'
''.format(self, other))
else:
return self.__iadd__(other)

def __add__(self, other):
"""Return ``self + other``."""
# Instead of using __iadd__ we duplicate code here for performance
if other in self.space:
if getattr(other, '__array_priority__', 0) > self.__array_priority__:
return other.__radd__(self)
elif other in self.space:
tmp = self.space.element()
return self.space.lincomb(1, self, 1, other, out=tmp)
elif isinstance(other, LinearSpaceElement):
return NotImplemented
elif other in self.space.field:
one = getattr(self.space, 'one', None)
if one is None:
Expand All @@ -536,33 +549,56 @@ def __add__(self, other):
tmp = one()
return self.space.lincomb(1, self, other, tmp, out=tmp)
else:
return NotImplemented
try:
other = self.space.element(other)
except (TypeError, ValueError):
return NotImplemented
else:
return self.__add__(other)

__radd__ = __add__
def __radd__(self, other):
"""Return ``other + self``."""
if getattr(other, '__array_priority__', 0) > self.__array_priority__:
return other.__add__(self)
else:
return self.__add__(other)

def __isub__(self, other):
"""Implement ``self -= other``."""
if other in self.space:
return self.space.lincomb(1, self, -1, other, out=self)
elif isinstance(other, LinearSpaceElement):
# We do not `return NotImplemented` here since we don't want a
# fallback for in-place. Otherwise python attempts
# `self = self - other` which does not modify self.
raise TypeError('cannot subtract {!r} and {!r} in place'
''.format(self, other))
elif other in self.space.field:
one = getattr(self.space, 'one', None)
if one is None:
return NotImplemented
raise TypeError('cannot subtract {!r} and {!r} in place'
''.format(self, other))
else:
return self.space.lincomb(1, self, -other, one(), out=self)
else:
# We do not `return NotImplemented` here since we don't want a
# fallback for in-place. Otherwise python attempts
# `self = self - other` which does not modify self.
raise TypeError('cannot subtract {!r} and {!r} in place'
''.format(self, other))
try:
other = self.space.element(other)
except (TypeError, ValueError):
raise TypeError('cannot subtract {!r} and {!r} in place'
''.format(self, other))
else:
return self.__isub__(other)

def __sub__(self, other):
"""Return ``self - other``."""
# Instead of using __isub__ we duplicate code here for performance
if other in self.space:
if getattr(other, '__array_priority__', 0) > self.__array_priority__:
return other.__rsub__(self)
elif other in self.space:
tmp = self.space.element()
return self.space.lincomb(1, self, -1, other, out=tmp)
elif isinstance(other, LinearSpaceElement):
return NotImplemented
elif other in self.space.field:
one = getattr(self.space, 'one', None)
if one is None:
Expand All @@ -571,14 +607,23 @@ def __sub__(self, other):
tmp = one()
return self.space.lincomb(1, self, -other, tmp, out=tmp)
else:
return NotImplemented
try:
other = self.space.element(other)
except (TypeError, ValueError):
return NotImplemented
else:
return self.__sub__(other)

def __rsub__(self, other):
"""Return ``other - self``."""
if other in self.space:
if getattr(other, '__array_priority__', 0) > self.__array_priority__:
return other.__sub__(self)
elif other in self.space:
tmp = self.space.element()
return self.space.lincomb(1, other, -1, self, out=tmp)
if other in self.space.field:
elif isinstance(other, LinearSpaceElement):
return NotImplemented
elif other in self.space.field:
one = getattr(self.space, 'one', None)
if one is None:
return NotImplemented
Expand All @@ -588,66 +633,112 @@ def __rsub__(self, other):
self.space.lincomb(other, tmp, out=tmp)
return self.space.lincomb(1, tmp, -1, self, out=tmp)
else:
return NotImplemented
try:
other = self.space.element(other)
except (TypeError, ValueError):
return NotImplemented
else:
return self.__rsub__(other)

def __imul__(self, other):
"""Implement ``self *= other``."""
if other in self.space.field:
return self.space.lincomb(other, self, out=self)
elif other in self.space:
return self.space.multiply(other, self, out=self)
else:
elif isinstance(other, LinearSpaceElement):
# We do not `return NotImplemented` here since we don't want a
# fallback for in-place. Otherwise python attempts
# `self = self * other` which does not modify self.
raise TypeError('cannot multiply {!r} and {!r} in place'
''.format(self, other))
else:
try:
other = self.space.element(other)
except (TypeError, ValueError):
raise TypeError('cannot multiply {!r} and {!r} in place'
''.format(self, other))
else:
return self.__imul__(other)

def __mul__(self, other):
"""Return ``self * other``."""
# Instead of using __imul__ we duplicate code here for performance
if other in self.space.field:
if getattr(other, '__array_priority__', 0) > self.__array_priority__:
return other.__rmul__(self)
elif other in self.space.field:
tmp = self.space.element()
return self.space.lincomb(other, self, out=tmp)
elif other in self.space:
tmp = self.space.element()
return self.space.multiply(other, self, out=tmp)
else:
elif isinstance(other, LinearSpaceElement):
return NotImplemented
else:
try:
other = self.space.element(other)
except (TypeError, ValueError):
return NotImplemented
else:
return self.__mul__(other)

__rmul__ = __mul__
def __rmul__(self, other):
"""Return ``other * self``."""
if getattr(other, '__array_priority__', 0) > self.__array_priority__:
return other.__mul__(self)
else:
return self.__mul__(other)

def __itruediv__(self, other):
"""Implement ``self /= other``."""
if other in self.space.field:
return self.space.lincomb(1.0 / other, self, out=self)
elif other in self.space:
return self.space.divide(self, other, out=self)
else:
elif isinstance(other, LinearSpaceElement):
# We do not `return NotImplemented` here since we don't want a
# fallback for in-place. Otherwise python attempts
# `self = self / other` which does not modify self.
raise TypeError('cannot divide {!r} and {!r} in place'
''.format(self, other))
else:
try:
other = self.space.element(other)
except (TypeError, ValueError):
raise TypeError('cannot divide {!r} and {!r} in place'
''.format(self, other))
else:
return self.__itruediv__(other)

__idiv__ = __itruediv__

def __truediv__(self, other):
"""Return ``self / other``."""
if other in self.space.field:
if getattr(other, '__array_priority__', 0) > self.__array_priority__:
return other.__rtruediv__(self)
elif other in self.space.field:
tmp = self.space.element()
return self.space.lincomb(1.0 / other, self, out=tmp)
elif other in self.space:
tmp = self.space.element()
return self.space.divide(self, other, out=tmp)
else:
elif isinstance(other, LinearSpaceElement):
return NotImplemented
else:
try:
other = self.space.element(other)
except (TypeError, ValueError):
return NotImplemented
else:
return self.__truediv__(other)

__div__ = __truediv__

def __rtruediv__(self, other):
"""Return ``other / self``."""
if other in self.space.field:
if getattr(other, '__array_priority__', 0) > self.__array_priority__:
return other.__truediv__(self)
elif other in self.space.field:
one = getattr(self.space, 'one', None)
if one is None:
return NotImplemented
Expand All @@ -659,8 +750,15 @@ def __rtruediv__(self, other):
elif other in self.space:
tmp = self.space.element()
return self.space.divide(other, self, out=tmp)
else:
elif isinstance(other, LinearSpaceElement):
return NotImplemented
else:
try:
other = self.space.element(other)
except (TypeError, ValueError):
return NotImplemented
else:
return self.__rtruediv__(other)

__rdiv__ = __rtruediv__

Expand All @@ -681,14 +779,14 @@ def __ipow__(self, p):
elif p == 1:
return self
elif p % 2 == 0:
self.space.multiply(self, self, out=self)
self *= self
self **= p // 2
return self
else:
tmp = self.copy()
for _ in range(p - 2):
self.space.multiply(tmp, self, out=tmp)
self.space.multiply(tmp, self, out=self)
tmp *= self
self *= tmp
return self

def __pow__(self, p):
Expand Down
Loading

0 comments on commit 796ffb0

Please sign in to comment.