mod base;
mod eval;
mod fold;
mod restrict;
use slop_algebra::Field;
use slop_alloc::Buffer;
use slop_alloc::{mem::CopyError, CpuBackend};
use slop_multilinear::{Mle, MleBaseBackend};
pub use eval::{DeviceMleEval, DevicePoint, PartialGeqKernel, PartialLagrangeKernel};
pub use fold::FoldKernel;
pub use restrict::MleFixLastVariableKernel;
use slop_tensor::Tensor;
use crate::tensor::transpose::DeviceTransposeKernel;
use crate::{DeviceCopy, DeviceTensor, TaskScope};
#[derive(Debug, Clone)]
pub struct DeviceMle<F> {
guts: DeviceTensor<F>,
}
impl<F: DeviceCopy + Field> DeviceMle<F> {
pub fn new(guts: DeviceTensor<F>) -> Self {
Self { guts }
}
fn from_tensor(tensor: Tensor<F, TaskScope>) -> Self {
let tensor = DeviceTensor::from_raw(tensor);
Self { guts: tensor }
}
pub fn uninit(
num_polynomials: usize,
num_non_zero_entries: usize,
backend: &TaskScope,
) -> Self {
let guts = backend.uninit_mle(num_polynomials, num_non_zero_entries);
Self { guts: DeviceTensor::from_raw(guts) }
}
pub fn as_ptr(&self) -> *const F {
self.guts.as_ptr()
}
pub fn as_mut_ptr(&mut self) -> *mut F {
self.guts.as_mut_ptr()
}
pub unsafe fn assume_init(&mut self) {
self.guts.assume_init();
}
pub fn guts(&self) -> &DeviceTensor<F> {
&self.guts
}
pub fn guts_mut(&mut self) -> &mut DeviceTensor<F> {
&mut self.guts
}
pub fn into_guts(self) -> DeviceTensor<F> {
self.guts
}
pub fn num_polynomials(&self) -> usize {
self.guts.sizes()[0]
}
pub fn num_variables(&self) -> u32 {
self.guts.sizes()[1].next_power_of_two().ilog2()
}
pub fn num_non_zero_entries(&self) -> usize {
self.guts.sizes()[1]
}
pub fn backend(&self) -> &TaskScope {
self.guts.backend()
}
fn into_mle(self) -> Mle<F, TaskScope> {
Mle::new(self.guts.into_inner())
}
pub fn from_host(host_mle: &Mle<F, CpuBackend>, scope: &TaskScope) -> Result<Self, CopyError>
where
TaskScope: DeviceTransposeKernel<F>,
{
let host_guts = host_mle.guts();
let device_guts_untransposed = DeviceTensor::from_host(host_guts, scope)?;
let device_guts = device_guts_untransposed.transpose();
Ok(Self::new(device_guts))
}
pub fn to_host(&self) -> Result<Mle<F, CpuBackend>, CopyError>
where
TaskScope: DeviceTransposeKernel<F>,
{
let transposed = self.guts.transpose();
let host_guts = transposed.to_host()?;
Ok(Mle::new(host_guts))
}
}
impl<F: DeviceCopy + Field> From<Tensor<F, TaskScope>> for DeviceMle<F> {
#[inline]
fn from(tensor: Tensor<F, TaskScope>) -> Self {
DeviceMle::from_tensor(tensor)
}
}
impl<F: DeviceCopy + Field> From<Buffer<F, TaskScope>> for DeviceMle<F> {
#[inline]
fn from(buffer: Buffer<F, TaskScope>) -> Self {
let len = buffer.len();
let tensor = Tensor::from(buffer).reshape([1, len]);
let mle = DeviceMle::from_tensor(tensor);
assert_eq!(mle.num_polynomials(), 1);
mle
}
}
impl<F: DeviceCopy + Field> From<Mle<F, TaskScope>> for DeviceMle<F> {
#[inline]
fn from(tensor: Mle<F, TaskScope>) -> Self {
DeviceMle::from_tensor(tensor.into_guts())
}
}
impl<F: DeviceCopy + Field> From<DeviceMle<F>> for Mle<F, TaskScope> {
#[inline]
fn from(device_mle: DeviceMle<F>) -> Self {
device_mle.into_mle()
}
}