Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 10 additions & 51 deletions bandmat/core.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ cimport cython
cnp.import_array()
cnp.import_ufunc()

class BandMat(object):
class BandMat:
"""A memory-efficient representation of a square banded matrix.

An N by N matrix with bandwidth D can be stored efficiently by storing its
Expand Down Expand Up @@ -56,8 +56,7 @@ class BandMat(object):
assert self.data.shape[0] == self.l + self.u + 1

def __repr__(self):
return ('BandMat(%r, %r, %r, transposed=%r)' %
(self.l, self.u, self.data, self.transposed))
return f'BandMat({self.l!r}, {self.u!r}, {self.data!r}, transposed={self.transposed!r})'

@property
def size(self):
Expand Down Expand Up @@ -344,7 +343,7 @@ class BandMat(object):
"""
try:
mult = float(other)
except:
except (TypeError, ValueError):
return NotImplemented

return BandMat(self.l, self.u, self.data * mult,
Expand All @@ -365,36 +364,16 @@ class BandMat(object):
"""
try:
mult = float(other)
except:
except (TypeError, ValueError):
return NotImplemented

return BandMat(self.l, self.u, self.data.__floordiv__(mult),
transposed=self.transposed)

def __div__(self, other):
"""Old-style divides a banded matrix by a scalar.

When using old-style division (c.f. `from __future__ import division`),
the expression `a_bm / mult` where `a_bm` is a BandMat is the
equivalent of:

a_full / mult

where `a_full` is a square numpy array.
"""
try:
mult = float(other)
except:
return NotImplemented

return BandMat(self.l, self.u, self.data.__div__(mult),
transposed=self.transposed)

def __truediv__(self, other):
"""Divides a banded matrix by a scalar.

When using new-style division (c.f. `from __future__ import division`),
the expression `a_bm / mult` where `a_bm` is a BandMat is the
The expression `a_bm / mult` where `a_bm` is a BandMat is the
equivalent of:

a_full / mult
Expand All @@ -403,7 +382,7 @@ class BandMat(object):
"""
try:
mult = float(other)
except:
except (TypeError, ValueError):
return NotImplemented

return BandMat(self.l, self.u, self.data.__truediv__(mult),
Expand All @@ -421,7 +400,7 @@ class BandMat(object):
"""
try:
mult = float(other)
except:
except (TypeError, ValueError):
return NotImplemented

self.data *= mult
Expand All @@ -439,36 +418,16 @@ class BandMat(object):
"""
try:
mult = float(other)
except:
except (TypeError, ValueError):
return NotImplemented

self.data.__ifloordiv__(mult)
return self

def __idiv__(self, other):
"""Old-style divides this matrix by a scalar in-place.

When using old-style division (c.f. `from __future__ import division`),
the expression `a_bm /= mult` where `a_bm` is a BandMat is the
equivalent of:

a_full /= mult

where `a_full` is a square numpy array.
"""
try:
mult = float(other)
except:
return NotImplemented

self.data.__itruediv__(mult)
return self

def __itruediv__(self, other):
"""Divides this matrix by a scalar in-place.

When using new-style division (c.f. `from __future__ import division`),
the expression `a_bm /= mult` where `a_bm` is a BandMat is the
The statement `a_bm /= mult` where `a_bm` is a BandMat is the
equivalent of:

a_full /= mult
Expand All @@ -477,7 +436,7 @@ class BandMat(object):
"""
try:
mult = float(other)
except:
except (TypeError, ValueError):
return NotImplemented

self.data.__itruediv__(mult)
Expand Down
4 changes: 2 additions & 2 deletions bandmat/linalg.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def _cholesky_banded(cnp.ndarray[cnp.float64_t, ndim=2] mat,
v0 = mat[<unsigned long>(0), frame]
if v0 <= 0.0:
raise sla.LinAlgError(
'%d-th leading minor not positive definite' % (frame + 1)
f'{frame + 1}-th leading minor not positive definite'
)
iv0 = 1.0 / v0
siv0 = sqrt(iv0)
Expand Down Expand Up @@ -167,7 +167,7 @@ def _solve_triangular_banded(cnp.ndarray[cnp.float64_t, ndim=2] a_rect,
denom = a_rect[depth, frame]
if denom == 0.0:
raise sla.LinAlgError(
'singular matrix: resolution failed at diagonal %d' % frame
f'singular matrix: resolution failed at diagonal {frame}'
)
x[frame] = diff / denom

Expand Down
3 changes: 1 addition & 2 deletions bandmat/test_linalg.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,7 @@ def test__solve_triangular_banded(self, its=100):
b_arg = b.copy()
if badFrame is not None:
msg = (
'singular matrix: resolution failed at diagonal %d' %
badFrame
f'singular matrix: resolution failed at diagonal {badFrame}'
)
msgRe = '^' + re.escape(msg) + '$'
with self.assertRaisesRegex(la.LinAlgError, msgRe):
Expand Down
25 changes: 14 additions & 11 deletions bandmat/testhelp.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,27 @@
def assert_allclose(actual, desired, rtol=1e-7, atol=1e-14,
msg='items not almost equal'):
if np.shape(actual) != np.shape(desired):
raise AssertionError('%s (wrong shape)\n ACTUAL: %r\n DESIRED: %r' %
(msg, actual, desired))
raise AssertionError(
f'{msg} (wrong shape)\n ACTUAL: {actual!r}\n DESIRED: {desired!r}'
)
if not np.allclose(actual, desired, rtol, atol):
abs_err = np.abs(actual - desired)
rel_err = np.abs((actual - desired) / desired)
raise AssertionError('%s\n ACTUAL:\n%r\n DESIRED:\n%r\n'
' ABS ERR: %r (max %s)\n REL ERR: %r (max %s)' %
(msg, actual, desired,
abs_err, np.max(abs_err),
rel_err, np.max(rel_err)))
raise AssertionError(
f'{msg}\n ACTUAL:\n{actual!r}\n DESIRED:\n{desired!r}\n'
f' ABS ERR: {abs_err!r} (max {np.max(abs_err)})\n'
f' REL ERR: {rel_err!r} (max {np.max(rel_err)})'
)

def assert_allequal(actual, desired, msg='items not equal'):
if np.shape(actual) != np.shape(desired):
raise AssertionError('%s (wrong shape)\n ACTUAL: %r\n DESIRED: %r' %
(msg, actual, desired))
raise AssertionError(
f'{msg} (wrong shape)\n ACTUAL: {actual!r}\n DESIRED: {desired!r}'
)
if not np.all(actual == desired):
raise AssertionError('%s\n ACTUAL:\n%r\n DESIRED:\n%r' %
(msg, actual, desired))
raise AssertionError(
f'{msg}\n ACTUAL:\n{actual!r}\n DESIRED:\n{desired!r}'
)

def randomize_extra_entries(l, u, mat_rect):
"""Randomizes the extra entries of a rectangular matrix.
Expand Down
Loading