use crate::core::fields::m31::BaseField;
use crate::core::vcs::blake2_hash::Blake2sHash;
use crate::prover::backend::simd::column::{BaseColumn, SecureColumn};
use crate::prover::backend::simd::SimdBackend;
use crate::prover::line::LineEvaluation;
use crate::prover::poly::circle::{CircleCoefficients, CircleEvaluation, SecureEvaluation};
use crate::prover::poly::twiddles::TwiddleTree;
use crate::prover::poly::BitReversedOrder;
use crate::prover::secure_column::SecureColumnByCoords;
use super::GpuBackend;
const _: () = {
fn _assert_same_base_column<T>(_: T) where T: Into<BaseColumn> {}
fn _assert_same_secure_column<T>(_: T) where T: Into<SecureColumn> {}
};
#[inline]
pub fn base_col_ref_to_simd(col: &BaseColumn) -> &BaseColumn {
col }
#[inline]
pub fn secure_col_ref_to_simd(col: &SecureColumn) -> &SecureColumn {
col
}
#[inline]
pub fn secure_col_mut_to_simd(col: &mut SecureColumn) -> &mut SecureColumn {
col
}
#[inline]
pub fn circle_eval_ref_to_simd<'a>(
eval: &'a CircleEvaluation<GpuBackend, BaseField, BitReversedOrder>
) -> &'a CircleEvaluation<SimdBackend, BaseField, BitReversedOrder> {
unsafe { std::mem::transmute(eval) }
}
#[inline]
pub fn circle_eval_to_gpu(
eval: CircleEvaluation<SimdBackend, BaseField, BitReversedOrder>
) -> CircleEvaluation<GpuBackend, BaseField, BitReversedOrder> {
CircleEvaluation::new(eval.domain, eval.values)
}
#[inline]
pub fn circle_eval_to_simd(
eval: CircleEvaluation<GpuBackend, BaseField, BitReversedOrder>
) -> CircleEvaluation<SimdBackend, BaseField, BitReversedOrder> {
CircleEvaluation::new(eval.domain, eval.values)
}
#[inline]
pub fn secure_eval_ref_to_simd<'a>(
eval: &'a SecureEvaluation<GpuBackend, BitReversedOrder>
) -> &'a SecureEvaluation<SimdBackend, BitReversedOrder> {
unsafe { std::mem::transmute(eval) }
}
#[inline]
pub fn secure_eval_to_gpu(
eval: SecureEvaluation<SimdBackend, BitReversedOrder>
) -> SecureEvaluation<GpuBackend, BitReversedOrder> {
unsafe { std::mem::transmute(eval) }
}
#[inline]
pub fn circle_coeffs_ref_to_simd<'a>(
coeffs: &'a CircleCoefficients<GpuBackend>
) -> &'a CircleCoefficients<SimdBackend> {
unsafe { std::mem::transmute(coeffs) }
}
#[inline]
pub fn circle_coeffs_to_gpu(
coeffs: CircleCoefficients<SimdBackend>
) -> CircleCoefficients<GpuBackend> {
CircleCoefficients::new(coeffs.coeffs)
}
#[inline]
pub fn line_eval_ref_to_simd<'a>(
eval: &'a LineEvaluation<GpuBackend>
) -> &'a LineEvaluation<SimdBackend> {
unsafe { std::mem::transmute(eval) }
}
#[inline]
pub fn line_eval_mut_to_simd<'a>(
eval: &'a mut LineEvaluation<GpuBackend>
) -> &'a mut LineEvaluation<SimdBackend> {
unsafe { std::mem::transmute(eval) }
}
#[inline]
pub fn line_eval_to_gpu(
eval: LineEvaluation<SimdBackend>
) -> LineEvaluation<GpuBackend> {
unsafe { std::mem::transmute(eval) }
}
#[inline]
pub fn twiddle_ref_to_simd<'a>(
twiddles: &'a TwiddleTree<GpuBackend>
) -> &'a TwiddleTree<SimdBackend> {
unsafe { std::mem::transmute(twiddles) }
}
#[inline]
pub fn twiddle_to_gpu(
twiddles: TwiddleTree<SimdBackend>
) -> TwiddleTree<GpuBackend> {
unsafe { std::mem::transmute(twiddles) }
}
#[inline]
pub fn secure_col_coords_mut_to_simd<'a>(
col: &'a mut SecureColumnByCoords<GpuBackend>
) -> &'a mut SecureColumnByCoords<SimdBackend> {
unsafe { std::mem::transmute(col) }
}
#[inline]
pub fn secure_col_coords_ref_to_simd<'a>(
col: &'a SecureColumnByCoords<GpuBackend>
) -> &'a SecureColumnByCoords<SimdBackend> {
unsafe { std::mem::transmute(col) }
}
#[inline]
pub fn hash_col_ref_to_simd<'a>(
col: &'a Vec<Blake2sHash>
) -> &'a Vec<Blake2sHash> {
col }
#[inline]
pub fn hash_col_to_gpu(
col: Vec<Blake2sHash>
) -> Vec<Blake2sHash> {
col }
pub fn secure_column_to_aos(col: &SecureColumnByCoords<SimdBackend>, n: usize) -> Vec<u32> {
let c0 = col_data_as_u32(&col.columns[0], n);
let c1 = col_data_as_u32(&col.columns[1], n);
let c2 = col_data_as_u32(&col.columns[2], n);
let c3 = col_data_as_u32(&col.columns[3], n);
let mut aos = Vec::with_capacity(n * 4);
for i in 0..n {
aos.push(c0[i]);
aos.push(c1[i]);
aos.push(c2[i]);
aos.push(c3[i]);
}
aos
}
pub fn aos_to_secure_column(aos: &[u32], n: usize) -> SecureColumnByCoords<SimdBackend> {
use crate::core::fields::m31::M31;
assert_eq!(aos.len(), n * 4);
let mut c0 = Vec::with_capacity(n);
let mut c1 = Vec::with_capacity(n);
let mut c2 = Vec::with_capacity(n);
let mut c3 = Vec::with_capacity(n);
for i in 0..n {
c0.push(M31(aos[i * 4]));
c1.push(M31(aos[i * 4 + 1]));
c2.push(M31(aos[i * 4 + 2]));
c3.push(M31(aos[i * 4 + 3]));
}
SecureColumnByCoords {
columns: [
BaseColumn::from_iter(c0),
BaseColumn::from_iter(c1),
BaseColumn::from_iter(c2),
BaseColumn::from_iter(c3),
],
}
}
pub fn aos_to_secure_column_from_soa(
c0: &[u32], c1: &[u32], c2: &[u32], c3: &[u32], n: usize,
) -> SecureColumnByCoords<GpuBackend> {
use crate::core::fields::m31::M31;
assert_eq!(c0.len(), n);
assert_eq!(c1.len(), n);
assert_eq!(c2.len(), n);
assert_eq!(c3.len(), n);
SecureColumnByCoords {
columns: [
BaseColumn::from_iter((0..n).map(|i| M31(c0[i]))),
BaseColumn::from_iter((0..n).map(|i| M31(c1[i]))),
BaseColumn::from_iter((0..n).map(|i| M31(c2[i]))),
BaseColumn::from_iter((0..n).map(|i| M31(c3[i]))),
],
}
}
fn col_data_as_u32(col: &BaseColumn, n: usize) -> &[u32] {
let ptr = col.data.as_ptr() as *const u32;
let total = col.data.len() * 16; let slice = unsafe { std::slice::from_raw_parts(ptr, total) };
&slice[..n]
}
#[cfg(test)]
mod tests {
use super::*;
use crate::prover::backend::Column;
#[test]
fn test_base_column_identity() {
let col = BaseColumn::zeros(100);
let converted = base_col_ref_to_simd(&col);
assert_eq!(col.len(), converted.len());
}
#[test]
fn test_aos_roundtrip() {
use crate::core::fields::m31::M31;
let n = 32; let mut col = SecureColumnByCoords::<SimdBackend>::zeros(n);
for i in 0..n {
let val = crate::core::fields::qm31::SecureField::from_m31(
M31(i as u32),
M31(i as u32 + 100),
M31(i as u32 + 200),
M31(i as u32 + 300),
);
col.set(i, val);
}
let aos = secure_column_to_aos(&col, n);
assert_eq!(aos.len(), n * 4);
let recovered = aos_to_secure_column(&aos, n);
for i in 0..n {
assert_eq!(col.at(i), recovered.at(i), "mismatch at index {}", i);
}
}
}