| 294 | } |
| 295 | |
| 296 | static cudaq::state createStateFromPyBuffer(nanobind::object data, |
| 297 | LinkedLibraryHolder &holder) { |
| 298 | const bool isHostData = !nanobind::hasattr(data, "__cuda_array_interface__"); |
| 299 | // Check that the target is GPU-based, i.e., can handle device |
| 300 | // pointer. |
| 301 | if (!holder.getTarget().config.GpuRequired && !isHostData) |
| 302 | throw std::runtime_error( |
| 303 | fmt::format("Current target '{}' does not support CuPy arrays.", |
| 304 | holder.getTarget().name)); |
| 305 | |
| 306 | auto info = isHostData ? getNumpyBufferInfo(data) : getCupyBufferInfo(data); |
| 307 | if (info.shape.size() > 2) |
| 308 | throw std::runtime_error( |
| 309 | "state.from_data only supports 1D or 2D array data."); |
| 310 | if (info.format != "Zf" && info.format != "Zd") |
| 311 | throw std::runtime_error( |
| 312 | "A numpy array with only floating point elements passed to " |
| 313 | "`state.from_data`. Input must be of complex float type. Please add to " |
| 314 | "your array creation `dtype=numpy.complex64` if simulation is FP32 and " |
| 315 | "`dtype=numpy.complex128` if simulation is FP64, or " |
| 316 | "`dtype=cudaq.complex()` for precision-agnostic code."); |
| 317 | |
| 318 | if (!isHostData && shouldCanonicalizeCupyArray(info, holder.getTarget().name)) |
| 319 | return createStateFromPyBuffer(canonicalizeCupyArrayToNumpy(data), holder); |
| 320 | |
| 321 | if (!isHostData) { |
| 322 | if (holder.getTarget().name == "dynamics") { |
| 323 | if (info.shape.size() == 2 && info.shape[0] != info.shape[1]) |
| 324 | throw std::runtime_error( |
| 325 | "state.from_data 2D array (density matrix) input must be " |
| 326 | "square matrix data."); |
| 327 | TensorStateData tensorData{ |
| 328 | std::pair<const void *, std::vector<std::size_t>>{info.ptr, |
| 329 | info.shape}}; |
| 330 | return state::from_data(tensorData); |
| 331 | } |
| 332 | |
| 333 | if (info.format == "Zf") |
| 334 | return state::from_data(std::make_pair( |
| 335 | reinterpret_cast<std::complex<float> *>(info.ptr), info.size)); |
| 336 | |
| 337 | return state::from_data(std::make_pair( |
| 338 | reinterpret_cast<std::complex<double> *>(info.ptr), info.size)); |
| 339 | } |
| 340 | |
| 341 | if (info.shape.size() == 1) { |
| 342 | if (info.format == "Zf") |
| 343 | return state::from_data(std::make_pair( |
| 344 | reinterpret_cast<std::complex<float> *>(info.ptr), info.size)); |
| 345 | |
| 346 | return state::from_data(std::make_pair( |
| 347 | reinterpret_cast<std::complex<double> *>(info.ptr), info.size)); |
| 348 | } |
| 349 | |
| 350 | const std::size_t rows = info.shape[0]; |
| 351 | const std::size_t cols = info.shape[1]; |
| 352 | if (rows != cols) |
| 353 | throw std::runtime_error( |
no test coverage detected