• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Qiskit / qiskit / 23548889554

25 Mar 2026 03:22PM UTC coverage: 87.191% (-0.04%) from 87.235%
23548889554

Pull #15836

github

web-flow
Merge 4df6d9082 into 3e8032600
Pull Request #15836: Use `np.bitwise_count` in `BitArray.bitcount`

1 of 5 new or added lines in 1 file covered. (20.0%)

1085 existing lines in 41 files now uncovered.

103626 of 118850 relevant lines covered (87.19%)

1001189.12 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.51
/crates/circuit/src/classical/expr/unary.rs
1
// This code is part of Qiskit.
2
//
3
// (C) Copyright IBM 2025
4
//
5
// This code is licensed under the Apache License, Version 2.0. You may
6
// obtain a copy of this license in the LICENSE.txt file in the root directory
7
// of this source tree or at https://www.apache.org/licenses/LICENSE-2.0.
8
//
9
// Any modifications or derivative works of this code must retain this
10
// copyright notice, and modified files need to carry a notice indicating
11
// that they have been altered from the originals.
12

13
use crate::classical::expr::{Expr, ExprKind, PyExpr};
14
use crate::classical::types::Type;
15
use crate::imports;
16
use pyo3::prelude::*;
17
use pyo3::types::PyTuple;
18
use pyo3::{IntoPyObjectExt, intern};
19

20
/// A unary expression.
21
#[derive(Clone, Debug, PartialEq)]
22
pub struct Unary {
23
    pub op: UnaryOp,
24
    pub operand: Expr,
25
    pub ty: Type,
26
    pub constant: bool,
27
}
28

29
/// The Rust-side enum indicating a [Unary] expression's kind.
30
///
31
/// The values are part of the public Qiskit Python interface, since
32
/// they are public in the sister Python enum `_UnaryOp` in `expr.py`
33
/// and used in our QPY serialization format.
34
///
35
/// WARNING: If you add more, **be sure to update expr.py** as well
36
/// as the implementation of [::bytemuck::CheckedBitPattern]
37
/// below.
38
#[repr(u8)]
39
#[derive(Copy, Hash, Clone, Debug, PartialEq)]
40
pub enum UnaryOp {
41
    BitNot = 1,
42
    LogicNot = 2,
43
    Negate = 3,
44
}
45

46
unsafe impl ::bytemuck::CheckedBitPattern for UnaryOp {
47
    type Bits = u8;
48

49
    fn is_valid_bit_pattern(bits: &Self::Bits) -> bool {
424✔
50
        *bits > 0 && *bits < 4
424✔
51
    }
424✔
52
}
53

54
impl UnaryOp {
55
    pub fn from_u8(value: u8) -> PyResult<UnaryOp> {
52✔
56
        Ok(bytemuck::checked::cast::<u8, UnaryOp>(value))
52✔
57
    }
52✔
58
}
59

60
impl<'py> IntoPyObject<'py> for Unary {
61
    type Target = PyAny;
62
    type Output = Bound<'py, PyAny>;
63
    type Error = PyErr;
64

65
    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
202✔
66
        Ok(Bound::new(py, (PyUnary(self), PyExpr(ExprKind::Unary)))?.into_any())
202✔
67
    }
202✔
68
}
69

70
impl<'a, 'py> FromPyObject<'a, 'py> for Unary {
71
    type Error = <PyUnary as FromPyObject<'a, 'py>>::Error;
72

73
    fn extract(ob: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {
376✔
74
        let PyUnary(u) = ob.extract()?;
376✔
75
        Ok(u)
376✔
76
    }
376✔
77
}
78

79
impl<'py> IntoPyObject<'py> for UnaryOp {
80
    type Target = PyAny;
81
    type Output = Bound<'py, Self::Target>;
82
    type Error = PyErr;
83

84
    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
132✔
85
        imports::UNARY_OP.get_bound(py).call1((self as usize,))
132✔
86
    }
132✔
87
}
88

89
impl<'a, 'py> FromPyObject<'a, 'py> for UnaryOp {
90
    type Error = PyErr;
91

92
    fn extract(ob: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {
372✔
93
        let value = ob.getattr(intern!(ob.py(), "value"))?;
372✔
94
        Ok(bytemuck::checked::cast(value.extract::<u8>()?))
372✔
95
    }
372✔
96
}
97

98
/// A Python descriptor to prevent PyO3 from attempting to import the Python-side
99
/// enum before we're initialized.
100
#[pyclass(module = "qiskit._accelerate.circuit.classical.expr")]
101
struct PyUnaryOp;
102

103
#[pymethods]
104
impl PyUnaryOp {
105
    fn __get__(&self, obj: &Bound<PyAny>, _obj_type: &Bound<PyAny>) -> Py<PyAny> {
366✔
106
        imports::UNARY_OP.get_bound(obj.py()).clone().unbind()
366✔
107
    }
366✔
108
}
109

110
/// A unary expression.
111
///
112
/// Args:
113
///     op: The opcode describing which operation is being done.
114
///     operand: The operand of the operation.
115
///     type: The resolved type of the result.
116
#[pyclass(
117
    eq,
118
    extends = PyExpr,
119
    name = "Unary",
120
    module = "qiskit._accelerate.circuit.classical.expr",
UNCOV
121
    from_py_object
×
122
)]
123
#[derive(PartialEq, Clone, Debug)]
124
pub struct PyUnary(Unary);
125

UNCOV
126
#[pymethods]
×
127
impl PyUnary {
128
    // The docstring for 'Op' is defined in Python (expr.py).
129
    #[classattr]
130
    #[allow(non_snake_case)]
131
    fn Op(py: Python) -> PyResult<Py<PyAny>> {
12✔
132
        PyUnaryOp.into_py_any(py)
12✔
133
    }
12✔
134

135
    #[new]
136
    #[pyo3(text_signature = "(op, operand, type)")]
137
    fn new(py: Python, op: UnaryOp, operand: Expr, ty: Type) -> PyResult<Py<Self>> {
372✔
138
        let constant = operand.is_const();
372✔
139
        Py::new(
372✔
140
            py,
372✔
141
            (
372✔
142
                PyUnary(Unary {
372✔
143
                    op,
372✔
144
                    operand,
372✔
145
                    ty,
372✔
146
                    constant,
372✔
147
                }),
372✔
148
                PyExpr(ExprKind::Unary),
372✔
149
            ),
372✔
150
        )
151
    }
372✔
152

153
    #[getter]
154
    fn get_op(&self, py: Python) -> PyResult<Py<PyAny>> {
132✔
155
        self.0.op.into_py_any(py)
132✔
156
    }
132✔
157

158
    #[getter]
159
    fn get_operand(&self, py: Python) -> PyResult<Py<PyAny>> {
360✔
160
        self.0.operand.clone().into_py_any(py)
360✔
161
    }
360✔
162

163
    #[getter]
164
    fn get_const(&self) -> bool {
×
165
        self.0.constant
×
UNCOV
166
    }
×
167

168
    #[getter]
169
    fn get_type(&self, py: Python) -> PyResult<Py<PyAny>> {
676✔
170
        self.0.ty.into_py_any(py)
676✔
171
    }
676✔
172

173
    fn accept<'py>(
332✔
174
        slf: PyRef<'py, Self>,
332✔
175
        visitor: &Bound<'py, PyAny>,
332✔
176
    ) -> PyResult<Bound<'py, PyAny>> {
332✔
177
        visitor.call_method1(intern!(visitor.py(), "visit_unary"), (slf,))
332✔
178
    }
332✔
179

180
    fn __reduce__<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyTuple>> {
18✔
181
        (
182
            py.get_type::<Self>(),
18✔
183
            (self.get_op(py)?, self.get_operand(py)?, self.get_type(py)?),
18✔
184
        )
185
            .into_pyobject(py)
18✔
186
    }
18✔
187

188
    fn __repr__(&self, py: Python) -> PyResult<String> {
×
UNCOV
189
        Ok(format!(
×
190
            "Unary({}, {}, {})",
191
            self.get_op(py)?.bind(py).repr()?,
×
192
            self.get_operand(py)?.bind(py).repr()?,
×
UNCOV
193
            self.get_type(py)?.bind(py).repr()?,
×
194
        ))
UNCOV
195
    }
×
196
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc