use std::sync::Arc;
use scirs2_core::ndarray::Array2;
use crate::error::KernelError;
use crate::multitask::{LMCKernel, TaskInput};
use super::trait_def::MultiOutputKernel;
type Result<T> = std::result::Result<T, KernelError>;
pub struct KroneckerLMCKernel {
inner: Arc<LMCKernel>,
}
impl KroneckerLMCKernel {
pub fn new(inner: LMCKernel) -> Self {
Self {
inner: Arc::new(inner),
}
}
}
impl MultiOutputKernel for KroneckerLMCKernel {
fn n_outputs(&self) -> usize {
self.inner.num_tasks()
}
fn compute_block(&self, x: &[f64], y: &[f64]) -> Result<Array2<f64>> {
let p = self.inner.num_tasks();
let mut block = Array2::<f64>::zeros((p, p));
for i in 0..p {
for j in 0..p {
let xi = TaskInput::from_slice(x, i);
let yj = TaskInput::from_slice(y, j);
block[[i, j]] = self.inner.compute_tasks(&xi, &yj).map_err(|e| {
KernelError::ComputationError(format!(
"LMC compute_tasks({}, {}) failed: {}",
i, j, e
))
})?;
}
}
Ok(block)
}
fn name(&self) -> &str {
"KroneckerLMC"
}
}