Skip to content

Commit

Permalink
Use unsafe Array initialization to avoid manually counting number of …
Browse files Browse the repository at this point in the history
…None's

The number of standard gates is specified by STANDARD_GATE_SIZE. To add a gate, the dev
has to read the value from one source file, then add (possible count) `None`s in two
places in another file to initialize arrays. After learning it all once it's not so bad,
but it still could be better.

After this commit the dev is required to change only the value of STANDARD_GATE_SIZE.
  • Loading branch information
jlapeyre committed Jun 5, 2024
1 parent a13ee16 commit d52943a
Showing 1 changed file with 17 additions and 17 deletions.
34 changes: 17 additions & 17 deletions crates/circuit/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,19 +100,28 @@ static STDGATE_IMPORT_PATHS: [[&str; 2]; STANDARD_GATE_SIZE] = [
static mut STDGATE_PYTHON_GATES: GILOnceCell<[Option<PyObject>; STANDARD_GATE_SIZE]> =
GILOnceCell::new();

// A fixed size array is initialized like this because using the `[T; 5]` syntax
// requires T to be `Copy`. But `PyObject` isn't Copy so therefore Option<PyObject>
// as T isn't Copy.
fn _array_of_option_pyobject() -> [Option<PyObject>; STANDARD_GATE_SIZE] {
use std::mem::{self, MaybeUninit};
let array = unsafe {
let mut data: [MaybeUninit<Option<PyObject>>; STANDARD_GATE_SIZE] = MaybeUninit::uninit().assume_init();
for elem in &mut data[..] {
*elem = MaybeUninit::new(None);
}
mem::transmute::<_, [Option<PyObject>; STANDARD_GATE_SIZE]>(data)
};
array
}

#[inline]
pub fn populate_std_gate_map(py: Python, rs_gate: StandardGate, py_gate: PyObject) {
let gate_map = unsafe {
match STDGATE_PYTHON_GATES.get_mut() {
Some(gate_map) => gate_map,
None => {
// A fixed size array is initialized like this because using the `[T; 5]` syntax
// requires T to be `Copy`. But `PyObject` isn't Copy so therefore Option<PyObject>
// as T isn't Copy. To avoid that we just list out None STANDARD_GATE_SIZE times
let array: [Option<PyObject>; STANDARD_GATE_SIZE] = [
None, None, None, None, None, None, None, None, None, None, None, None, None,
None, None, None, None, None, None,
];
let array = _array_of_option_pyobject();
STDGATE_PYTHON_GATES.set(py, array).unwrap();
STDGATE_PYTHON_GATES.get_mut().unwrap()
}
Expand All @@ -127,16 +136,7 @@ pub fn populate_std_gate_map(py: Python, rs_gate: StandardGate, py_gate: PyObjec
#[inline]
pub fn get_std_gate_class(py: Python, rs_gate: StandardGate) -> PyResult<PyObject> {
let gate_map = unsafe {
STDGATE_PYTHON_GATES.get_or_init(py, || {
// A fixed size array is initialized like this because using the `[T; 5]` syntax
// requires T to be `Copy`. But `PyObject` isn't Copy so therefore Option<PyObject>
// as T isn't Copy. To avoid that we just list out None STANDARD_GATE_SIZE times
let array: [Option<PyObject>; STANDARD_GATE_SIZE] = [
None, None, None, None, None, None, None, None, None, None, None, None, None, None,
None, None, None, None, None,
];
array
})
STDGATE_PYTHON_GATES.get_or_init(py, _array_of_option_pyobject)
};
let gate = &gate_map[rs_gate as usize];
let populate = gate.is_none();
Expand Down

0 comments on commit d52943a

Please sign in to comment.