// SPDX-FileCopyrightText: 2020 Evandro Chagas Ribeiro da Rosa <evandro@quantuloop.com>
// SPDX-FileCopyrightText: 2020 Rafael de Santiago <r.santiago@ufsc.br>
//
// SPDX-License-Identifier: Apache-2.0

use std::{
    iter::Sum,
    ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign},
};

pub mod bitwise;
pub mod block;
pub mod c_api;
pub mod convert;
pub mod dense;
pub mod dense_gpu;
pub mod dense_v2;
pub mod error;
pub mod quantum_execution;
pub mod sparse;
pub mod sparse_v2;

pub trait FloatOps:
    num_traits::Float
    + num_traits::FloatConst
    + AddAssign
    + SubAssign
    + MulAssign
    + DivAssign
    + RemAssign
    + Sum
    + Send
    + Sync
{
    fn small_epsilon() -> f32;
}

impl FloatOps for f32 {
    fn small_epsilon() -> f32 {
        1e-6
    }
}
impl FloatOps for f64 {
    fn small_epsilon() -> f32 {
        1e-15
    }
}

pub type Dense = dense::Dense<f32>;
pub type DenseSimulator = quantum_execution::QubitManager<Dense>;

pub type DenseV2 = dense_v2::DenseV2<f32>;
pub type DenseV2Simulator = quantum_execution::QubitManager<DenseV2>;
pub type DenseV2Block = block::Block<(), DenseV2>;
pub type DenseV2BlockSimulator = quantum_execution::QubitManager<DenseV2Block>;

pub type DenseGPU = dense_gpu::DenseGPU<cubecl::wgpu::WgpuRuntime, f32>;
pub type DenseGPUSimulator = quantum_execution::QubitManager<DenseGPU>;
pub type DenseGPUBlock = block::Block<
    (
        std::rc::Rc<std::cell::RefCell<cubecl::client::ComputeClient<cubecl::wgpu::WgpuRuntime>>>,
        std::rc::Rc<std::cell::RefCell<usize>>,
        std::rc::Rc<std::cell::RefCell<cubecl::server::Handle>>,
        std::rc::Rc<std::cell::RefCell<cubecl::server::Handle>>,
    ),
    dense_gpu::DenseGPU<cubecl::wgpu::WgpuRuntime, f32>,
>;
pub type DenseGPUSBlockSimulator = quantum_execution::QubitManager<DenseGPUBlock>;

pub type SparseSimulator = quantum_execution::QubitManager<sparse::Sparse<f32>>;
pub type SparseV2Simulator = quantum_execution::QubitManager<sparse_v2::SparseV2<f32>>;
