use std::sync::Arc;
use computegraph::GraphOperation;
use tenferro_ops::std_tensor_op::StdTensorOp;
use crate::error::{Error, ErrorPhase, Result};
use crate::trace_ops::{append_core, append_extension, finish_derived};
use crate::traced::{ensure_same_context, TracedTensor};
pub use crate::compiler::CompilerOptions;
#[doc(hidden)]
pub use crate::shape_infer::{
infer_output_dtype, infer_output_extents, infer_output_shapes, promote_dtype,
promote_dtype_for_binary_op, promote_dtypes,
};
pub use tenferro_extension_macros::define_extension_runtime;
pub use tenferro_ops::ext_op::{
ExtensionAlias, ExtensionAliasDeclaration, ExtensionEffect, ExtensionEffectAccess,
ExtensionEffectDeclaration, ExtensionOp,
};
pub use tenferro_ops::{ExtensionFamilyId, ExtensionShapeContext, SymDim};
pub use crate::extension_cache::{
ExtensionCacheKey, ExtensionCacheLimits, ExtensionCacheSelector, ExtensionCacheStore,
};
pub use crate::extension_execution_context::ExtensionExecutionContext;
pub use crate::runtime::{ExtensionModule, ExtensionModuleId, ExtensionModuleRegistrar};
pub fn apply(op: Arc<dyn ExtensionOp>, inputs: &[&TracedTensor]) -> Result<Vec<TracedTensor>> {
if inputs.len() != op.input_count() {
return Err(Error::invalid_argument(
"extension::apply",
ErrorPhase::GraphBuild,
"inputs",
format!(
"op family {:?} expects {} inputs, got {}",
op.family_id(),
op.input_count(),
inputs.len()
),
));
}
let Some(first) = inputs.first() else {
return Err(Error::invalid_argument(
"extension::apply",
ErrorPhase::GraphBuild,
"inputs",
"an extension op needs at least one traced input",
));
};
for input in inputs.iter().skip(1) {
ensure_same_context(first, input)?;
}
let values: Vec<_> = inputs.iter().map(|input| input.value).collect();
let outputs = append_extension(&first.ctx, op, &values)?;
outputs
.iter()
.map(|&value| finish_derived(&first.ctx, value))
.collect()
}
pub fn apply_standard_op(op: StdTensorOp, inputs: &[&TracedTensor]) -> Result<Vec<TracedTensor>> {
let expected = op.input_count();
if inputs.len() != expected {
return Err(Error::invalid_argument(
"extension::apply_standard_op",
ErrorPhase::GraphBuild,
"inputs",
format!("op expects {expected} inputs, got {}", inputs.len()),
));
}
let Some(first) = inputs.first() else {
return Err(Error::invalid_argument(
"extension::apply_standard_op",
ErrorPhase::GraphBuild,
"inputs",
"a standard op needs at least one traced input",
));
};
for input in inputs.iter().skip(1) {
ensure_same_context(first, input)?;
}
let values: Vec<_> = inputs.iter().map(|input| input.value).collect();
let outputs = append_core(&first.ctx, &op, &values)?;
outputs
.iter()
.map(|&value| finish_derived(&first.ctx, value))
.collect()
}
#[cfg(test)]
mod tests;