use super::{DynProofExpr, ProofExpr};
use crate::{
base::{
database::{can_not_type, Column, ColumnRef, ColumnType, LiteralValue, Table},
map::{IndexMap, IndexSet},
proof::{PlaceholderResult, ProofError},
scalar::Scalar,
},
sql::{
proof::{FinalRoundBuilder, VerificationBuilder},
AnalyzeError, AnalyzeResult,
},
utils::log,
};
use alloc::boxed::Box;
use bumpalo::Bump;
use serde::{Deserialize, Serialize};
use sqlparser::ast::Ident;
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct NotExpr {
expr: Box<DynProofExpr>,
}
impl NotExpr {
pub fn try_new(expr: Box<DynProofExpr>) -> AnalyzeResult<Self> {
let expr_type = expr.data_type();
can_not_type(expr_type)
.then_some(Self { expr })
.ok_or(AnalyzeError::InvalidDataType { expr_type })
}
pub fn input(&self) -> &DynProofExpr {
&self.expr
}
}
impl ProofExpr for NotExpr {
fn data_type(&self) -> ColumnType {
ColumnType::Boolean
}
#[tracing::instrument(name = "NotExpr::first_round_evaluate", level = "debug", skip_all)]
fn first_round_evaluate<'a, S: Scalar>(
&self,
alloc: &'a Bump,
table: &Table<'a, S>,
params: &[LiteralValue],
) -> PlaceholderResult<Column<'a, S>> {
log::log_memory_usage("Start");
let expr_column: Column<'a, S> = self.expr.first_round_evaluate(alloc, table, params)?;
let expr = expr_column.as_boolean().expect("expr is not boolean");
let res = Column::Boolean(alloc.alloc_slice_fill_with(expr.len(), |i| !expr[i]));
log::log_memory_usage("End");
Ok(res)
}
#[tracing::instrument(name = "NotExpr::final_round_evaluate", level = "debug", skip_all)]
fn final_round_evaluate<'a, S: Scalar>(
&self,
builder: &mut FinalRoundBuilder<'a, S>,
alloc: &'a Bump,
table: &Table<'a, S>,
params: &[LiteralValue],
) -> PlaceholderResult<Column<'a, S>> {
log::log_memory_usage("Start");
let expr_column: Column<'a, S> = self
.expr
.final_round_evaluate(builder, alloc, table, params)?;
let expr = expr_column.as_boolean().expect("expr is not boolean");
let res = Column::Boolean(alloc.alloc_slice_fill_with(expr.len(), |i| !expr[i]));
log::log_memory_usage("End");
Ok(res)
}
fn verifier_evaluate<S: Scalar>(
&self,
builder: &mut impl VerificationBuilder<S>,
accessor: &IndexMap<Ident, S>,
chi_eval: S,
params: &[LiteralValue],
) -> Result<S, ProofError> {
let eval = self
.expr
.verifier_evaluate(builder, accessor, chi_eval, params)?;
Ok(chi_eval - eval)
}
fn get_column_references(&self, columns: &mut IndexSet<ColumnRef>) {
self.expr.get_column_references(columns);
}
}