@brief Bind the get_state cudaq function
| 379 | |
| 380 | /// @brief Bind the get_state cudaq function |
| 381 | void cudaq::bindPyState(nanobind::module_ &mod, LinkedLibraryHolder &holder) { |
| 382 | nanobind::enum_<InitialState>(mod, "InitialStateType", |
| 383 | "Enumeration describing the initial state " |
| 384 | "type to be created in the backend") |
| 385 | .value("ZERO", InitialState::ZERO) |
| 386 | .value("UNIFORM", InitialState::UNIFORM) |
| 387 | .export_values(); |
| 388 | |
| 389 | nanobind::class_<SimulationState::Tensor>( |
| 390 | mod, "Tensor", |
| 391 | "The `Tensor` describes a pointer to simulation data as well as the rank " |
| 392 | "and extents for that tensorial data it represents.") |
| 393 | .def("data", |
| 394 | [](SimulationState::Tensor &tensor) { |
| 395 | return reinterpret_cast<intptr_t>(tensor.data); |
| 396 | }) |
| 397 | .def_ro("extents", &SimulationState::Tensor::extents) |
| 398 | .def("get_rank", &SimulationState::Tensor::get_rank) |
| 399 | .def("get_element_size", &SimulationState::Tensor::element_size) |
| 400 | .def("get_num_elements", &SimulationState::Tensor::get_num_elements); |
| 401 | |
| 402 | nanobind::class_<state>( |
| 403 | mod, "State", |
| 404 | "A data-type representing the quantum state of the internal simulator. " |
| 405 | "This type is not user-constructible and instances can only be retrieved " |
| 406 | "via the `cudaq.get_state(...)` function or the static " |
| 407 | "`cudaq.State.from_data()` method.\n") |
| 408 | .def( |
| 409 | "to_numpy", |
| 410 | [](const state &self) -> nanobind::object { |
| 411 | if (self.get_num_tensors() != 1) |
| 412 | throw std::runtime_error( |
| 413 | "Numpy interop is only supported for vector " |
| 414 | "and matrix state data."); |
| 415 | |
| 416 | auto stateVector = self.get_tensor(); |
| 417 | auto precision = self.get_precision(); |
| 418 | std::vector<size_t> shape(stateVector.extents.begin(), |
| 419 | stateVector.extents.end()); |
| 420 | |
| 421 | if (self.is_on_gpu()) { |
| 422 | auto numElements = stateVector.get_num_elements(); |
| 423 | |
| 424 | if (precision == SimulationState::precision::fp32) { |
| 425 | auto *hostData = new std::complex<float>[numElements]; |
| 426 | self.to_host(hostData, numElements); |
| 427 | |
| 428 | nanobind::capsule owner(hostData, [](void *p) noexcept { |
| 429 | CUDAQ_INFO("freeing data that was copied from GPU device " |
| 430 | "for compatibility with NumPy"); |
| 431 | delete[] static_cast<std::complex<float> *>(p); |
| 432 | }); |
| 433 | |
| 434 | return nanobind::cast( |
| 435 | nanobind::ndarray<nanobind::numpy, std::complex<float>>( |
| 436 | hostData, shape.size(), shape.data(), owner)); |
| 437 | } else { |
| 438 | auto *hostData = new std::complex<double>[numElements]; |
nothing calls this directly
no test coverage detected