|
30 | 30 | 'ComplexModulus', 'ComplexModulusSquared')
|
31 | 31 |
|
32 | 32 |
|
33 |
| -def _scale_op(operator, scalar): |
34 |
| - """Scale an operator, optimizing for ``scalar=0`` and ``scalar=1``.""" |
35 |
| - if scalar == 0: |
36 |
| - return ZeroOperator(operator.domain, operator.range) |
37 |
| - elif scalar == 1: |
38 |
| - return operator |
39 |
| - else: |
40 |
| - return scalar * operator |
41 |
| - |
42 |
| - |
43 |
| -def _lico_ops(a, op1, b, op2): |
44 |
| - """Linear combination of operators, optimizing trivial cases.""" |
45 |
| - if op1.domain != op2.domain or op1.range != op2.range: |
46 |
| - raise ValueError('domain/range mismatch between {!r} and {!r}' |
47 |
| - .format(op1, op2)) |
48 |
| - dom, ran = op1.domain, op1.range |
49 |
| - if a == 0: |
50 |
| - if b == 0: |
51 |
| - return ZeroOperator(dom, ran) |
52 |
| - elif b == 1: |
53 |
| - return op2 |
54 |
| - else: |
55 |
| - return b * op2 |
56 |
| - elif a == 1: |
57 |
| - if b == 0: |
58 |
| - return op1 |
59 |
| - elif b == 1: |
60 |
| - return op1 + op2 |
61 |
| - else: |
62 |
| - return op1 + b * op2 |
63 |
| - else: |
64 |
| - if b == 0: |
65 |
| - return a * op1 |
66 |
| - elif b == 1: |
67 |
| - return a * op1 + op2 |
68 |
| - else: |
69 |
| - return a * op1 + b * op2 |
70 |
| - |
71 |
| - |
72 | 33 | class ScalingOperator(Operator):
|
73 | 34 |
|
74 | 35 | """Operator of multiplication with a scalar.
|
@@ -1538,24 +1499,33 @@ def inverse(self):
|
1538 | 1499 | return ZeroOperator(self.range, self.domain)
|
1539 | 1500 |
|
1540 | 1501 | if self.domain.is_real:
|
1541 |
| - # Real domain |
1542 |
| - # Optimizations for simple cases. |
| 1502 | + # Real domain, with optimizations for simple cases |
1543 | 1503 | if self.scalar.real == self.scalar:
|
1544 |
| - return _scale_op(RealPart(self.range, self.domain), |
1545 |
| - 1 / self.scalar.real) |
| 1504 | + # embedding x -> (a + i*0) * x |
| 1505 | + op = RealPart(self.range, self.domain) |
| 1506 | + if self.scalar.real != 1: |
| 1507 | + op = (1 / self.scalar.real) * op |
| 1508 | + return op |
1546 | 1509 | elif 1j * self.scalar.imag == self.scalar:
|
1547 |
| - return _scale_op(ImagPart(self.range, self.domain), |
1548 |
| - 1 / self.scalar.imag) |
| 1510 | + # embedding x -> (0 + i*b) * x |
| 1511 | + op = ImagPart(self.range, self.domain) |
| 1512 | + if self.scalar.imag != 1: |
| 1513 | + op = (1 / self.scalar.imag) * op |
| 1514 | + return op |
1549 | 1515 | else:
|
1550 |
| - # General case |
1551 |
| - inv_scalar = (1 / self.scalar).conjugate() |
1552 |
| - return _lico_ops( |
1553 |
| - inv_scalar.real, RealPart(self.range, self.domain), |
1554 |
| - inv_scalar.imag, ImagPart(self.range, self.domain)) |
| 1516 | + # embedding x -> (a + i*b) * x |
| 1517 | + inv_scalar = 1 / self.scalar |
| 1518 | + re_op = RealPart(self.range, self.domain) |
| 1519 | + if inv_scalar.real != 1: |
| 1520 | + re_op = inv_scalar.real * re_op |
| 1521 | + im_op = ImagPart(self.range, self.domain) |
| 1522 | + if inv_scalar.imag != 1: |
| 1523 | + im_op = inv_scalar.imag * im_op |
| 1524 | + |
| 1525 | + return re_op + im_op |
1555 | 1526 | else:
|
1556 | 1527 | # Complex domain
|
1557 |
| - return ComplexEmbedding(self.range, self.domain, |
1558 |
| - self.scalar.conjugate()) |
| 1528 | + return ComplexEmbedding(self.range, self.domain, 1 / self.scalar) |
1559 | 1529 |
|
1560 | 1530 | @property
|
1561 | 1531 | def adjoint(self):
|
@@ -1602,19 +1572,29 @@ def adjoint(self):
|
1602 | 1572 | return ZeroOperator(self.range, self.domain)
|
1603 | 1573 |
|
1604 | 1574 | if self.domain.is_real:
|
1605 |
| - # Real domain |
1606 |
| - # Optimizations for simple cases. |
| 1575 | + # Real domain, with optimizations for simple cases |
1607 | 1576 | if self.scalar.real == self.scalar:
|
1608 |
| - return _scale_op(self.scalar.real, |
1609 |
| - ComplexEmbedding(self.range, self.domain)) |
| 1577 | + # embedding x -> (a + i*0) * x |
| 1578 | + op = RealPart(self.range, self.domain) |
| 1579 | + if self.scalar.real != 1: |
| 1580 | + op = self.scalar.real * op |
| 1581 | + return op |
1610 | 1582 | elif 1j * self.scalar.imag == self.scalar:
|
1611 |
| - return _scale_op(self.scalar.imag, |
1612 |
| - ImagPart(self.range, self.domain)) |
| 1583 | + # embedding x -> (0 + i*b) * x |
| 1584 | + op = ImagPart(self.range, self.domain) |
| 1585 | + if self.scalar.imag != 1: |
| 1586 | + op = self.scalar.imag * op |
| 1587 | + return op |
1613 | 1588 | else:
|
1614 |
| - # General case |
1615 |
| - return _lico_ops( |
1616 |
| - self.scalar.real, RealPart(self.range, self.domain), |
1617 |
| - self.scalar.imag, ImagPart(self.range, self.domain)) |
| 1589 | + # embedding x -> (a + i*b) * x |
| 1590 | + re_op = RealPart(self.range, self.domain) |
| 1591 | + if self.scalar.real != 1: |
| 1592 | + re_op = self.scalar.real * re_op |
| 1593 | + im_op = ImagPart(self.range, self.domain) |
| 1594 | + if self.scalar.imag != 1: |
| 1595 | + im_op = self.scalar.imag * im_op |
| 1596 | + |
| 1597 | + return re_op + im_op |
1618 | 1598 | else:
|
1619 | 1599 | # Complex domain
|
1620 | 1600 | return ComplexEmbedding(self.range, self.domain,
|
|
0 commit comments