use scirs2_core::ndarray::{Array1, Array2, Array3, ArrayView2};
use scirs2_core::numeric::{Float, FromPrimitive, Zero};
use statrs::statistics::Statistics;
use std::collections::{HashMap, VecDeque};
use std::f64::consts::PI;
use super::config::*;
use crate::error::{NdimageError, NdimageResult};
#[derive(Debug)]
pub struct PredictiveCodingResult<T> {
pub prediction: Array2<T>,
pub prediction_error: f64,
pub hierarchical_priors: Vec<Array2<f64>>,
pub precision_weights: Array2<f64>,
}
#[derive(Debug)]
pub struct MetaCognitiveState {
pub confidence_level: f64,
pub processing_effort: f64,
pub error_monitoring: f64,
pub self_awareness_index: f64,
}
#[allow(dead_code)]
pub fn consciousness_inspired_global_workspace<T>(
image: ArrayView2<T>,
config: &QuantumNeuromorphicConfig,
) -> NdimageResult<Array2<T>>
where
T: Float + FromPrimitive + Copy + Send + Sync,
{
let (height, width) = image.dim();
let consciousness_config = ConsciousnessConfig::default();
let mut perceptual_module = Array2::zeros((height, width));
let mut attention_module = Array2::zeros((height, width));
let mut memory_module = Array2::zeros((height, width));
let mut consciousness_workspace = Array2::zeros((height, width));
for y in 0..height {
for x in 0..width {
let pixel_value = image[(y, x)].to_f64().unwrap_or(0.0);
let perceptual_activation =
unconscious_perceptual_processing(pixel_value, &image, (y, x), config)?;
perceptual_module[(y, x)] = perceptual_activation;
let attention_activation = attention_schema_processing(
pixel_value,
&perceptual_module,
(y, x),
&consciousness_config,
)?;
attention_module[(y, x)] = attention_activation;
let memory_activation =
memory_trace_activation(pixel_value, perceptual_activation, &consciousness_config)?;
memory_module[(y, x)] = memory_activation;
}
}
for y in 0..height {
for x in 0..width {
let coalition_strength = calculate_coalition_strength(
perceptual_module[(y, x)],
attention_module[(y, x)],
memory_module[(y, x)],
&consciousness_config,
)?;
if coalition_strength > consciousness_config.broadcast_threshold {
consciousness_workspace[(y, x)] = coalition_strength;
global_broadcast_influence(
&mut perceptual_module,
&mut attention_module,
&mut memory_module,
(y, x),
coalition_strength,
&consciousness_config,
)?;
}
}
}
let mut conscious_output = Array2::zeros((height, width));
for y in 0..height {
for x in 0..width {
let integrated_response = integrate_conscious_response(
consciousness_workspace[(y, x)],
perceptual_module[(y, x)],
attention_module[(y, x)],
memory_module[(y, x)],
&consciousness_config,
)?;
conscious_output[(y, x)] = T::from_f64(integrated_response).ok_or_else(|| {
NdimageError::ComputationError("Consciousness integration failed".to_string())
})?;
}
}
Ok(conscious_output)
}
#[allow(dead_code)]
pub fn integrated_information_processing<T>(
image: ArrayView2<T>,
config: &QuantumNeuromorphicConfig,
) -> NdimageResult<(Array2<T>, f64)>
where
T: Float + FromPrimitive + Copy + Send + Sync,
{
let (height, width) = image.dim();
let consciousness_config = ConsciousnessConfig::default();
let mut phi_network = Array3::zeros((height, width, 4));
for y in 0..height {
for x in 0..width {
let pixel_value = image[(y, x)].to_f64().unwrap_or(0.0);
let quantum_encoding = encode_pixel_to_quantumstates(pixel_value, config)?;
for (i, &litude) in quantum_encoding.iter().enumerate() {
phi_network[(y, x, i)] = amplitude;
}
}
}
let mut total_phi = 0.0;
let mut phi_processedimage = Array2::<f64>::zeros((height, width));
for partition_size in 1..=((height * width) / 2) {
let bipartitions = generate_bipartitions(&phi_network, partition_size)?;
for (part_a, part_b) in bipartitions {
let ei_whole = calculate_effective_information(&phi_network, &consciousness_config)?;
let ei_parts = calculate_effective_information(&part_a, &consciousness_config)?
+ calculate_effective_information(&part_b, &consciousness_config)?;
let phi_contribution = (ei_whole - ei_parts).max(0.0);
total_phi += phi_contribution;
apply_phi_weighted_processing(
&mut phi_processedimage,
&phi_network,
phi_contribution,
&consciousness_config,
)?;
}
}
total_phi /= calculate_num_bipartitions(height * width) as f64;
let mut result = Array2::<T>::zeros((height, width));
for y in 0..height {
for x in 0..width {
result[(y, x)] = T::from_f64(phi_processedimage[(y, x)])
.ok_or_else(|| NdimageError::ComputationError("Φ conversion failed".to_string()))?;
}
}
Ok((result, total_phi))
}
#[allow(dead_code)]
pub fn predictive_coding_hierarchy<T>(
image: ArrayView2<T>,
hierarchy_sizes: &[usize],
_config: &QuantumNeuromorphicConfig,
) -> NdimageResult<PredictiveCodingResult<T>>
where
T: Float + FromPrimitive + Copy + Send + Sync,
{
let _height_width = image.dim();
let consciousness_config = ConsciousnessConfig::default();
if hierarchy_sizes.is_empty() {
return Err(NdimageError::InvalidInput("Empty hierarchy".to_string()));
}
let mut hierarchical_levels = Vec::new();
let mut prediction_errors = Vec::new();
let mut current_representation = image.to_owned().mapv(|x| x.to_f64().unwrap_or(0.0));
for (level, &level_size) in hierarchy_sizes.iter().enumerate() {
let level_predictions = if level == 0 {
generate_sensory_predictions(¤t_representation, &consciousness_config)?
} else {
generate_hierarchical_predictions(
&hierarchical_levels[level - 1],
¤t_representation,
level_size,
&consciousness_config,
)?
};
let pred_error = calculate_prediction_error(
¤t_representation,
&level_predictions,
&consciousness_config,
)?;
prediction_errors.push(pred_error);
let updated_representation = update_representation_with_error(
¤t_representation,
&level_predictions,
pred_error,
&consciousness_config,
)?;
hierarchical_levels.push(level_predictions);
current_representation = updated_representation;
}
let mut final_prediction = hierarchical_levels
.last()
.expect("Operation failed")
.clone();
for level in (0..hierarchical_levels.len()).rev() {
final_prediction = refine_prediction_top_down(
&final_prediction,
&hierarchical_levels[level],
prediction_errors[level],
&consciousness_config,
)?;
}
let precision_weights = calculate_precision_weights(&prediction_errors, &consciousness_config)?;
let total_prediction_error =
prediction_errors.iter().sum::<f64>() / prediction_errors.len() as f64;
let output_prediction = final_prediction.mapv(|x| T::from_f64(x).unwrap_or_else(|| T::zero()));
Ok(PredictiveCodingResult {
prediction: output_prediction,
prediction_error: total_prediction_error,
hierarchical_priors: hierarchical_levels,
precision_weights,
})
}
#[allow(dead_code)]
pub fn meta_cognitive_monitoring<T>(
image: ArrayView2<T>,
processinghistory: &[Array2<f64>],
_config: &QuantumNeuromorphicConfig,
) -> NdimageResult<(Array2<T>, MetaCognitiveState)>
where
T: Float + FromPrimitive + Copy + Send + Sync,
{
let (height, width) = image.dim();
let consciousness_config = ConsciousnessConfig::default();
let mut metacognitive_output = Array2::zeros((height, width));
let mut confidence_map = Array2::zeros((height, width));
let mut effort_map = Array2::zeros((height, width));
let mut error_monitoring_map = Array2::zeros((height, width));
for y in 0..height {
for x in 0..width {
let pixel_value = image[(y, x)].to_f64().unwrap_or(0.0);
let confidence = calculate_processing_confidence(
pixel_value,
processinghistory,
(y, x),
&consciousness_config,
)?;
confidence_map[(y, x)] = confidence;
let effort =
calculate_processing_effort(processinghistory, (y, x), &consciousness_config)?;
effort_map[(y, x)] = effort;
let error_signal = calculate_error_monitoring_signal(
pixel_value,
processinghistory,
(y, x),
&consciousness_config,
)?;
error_monitoring_map[(y, x)] = error_signal;
let metacognitive_value = integrate_metacognitive_signals(
confidence,
effort,
error_signal,
&consciousness_config,
)?;
metacognitive_output[(y, x)] = T::from_f64(metacognitive_value).ok_or_else(|| {
NdimageError::ComputationError("Meta-cognitive integration failed".to_string())
})?;
}
}
let global_confidence = confidence_map.mean();
let global_effort = effort_map.mean();
let global_error_monitoring = error_monitoring_map.mean();
let self_awareness_index = calculate_self_awareness_index(
global_confidence,
global_effort,
global_error_monitoring,
&consciousness_config,
)?;
let metacognitivestate = MetaCognitiveState {
confidence_level: global_confidence,
processing_effort: global_effort,
error_monitoring: global_error_monitoring,
self_awareness_index,
};
Ok((metacognitive_output, metacognitivestate))
}
#[allow(dead_code)]
pub fn temporal_binding_consciousness<T>(
image_sequence: &[ArrayView2<T>],
config: &QuantumNeuromorphicConfig,
) -> NdimageResult<Array2<T>>
where
T: Float + FromPrimitive + Copy + Send + Sync,
{
let consciousness_config = ConsciousnessConfig::default();
if image_sequence.is_empty() {
return Err(NdimageError::InvalidInput(
"Empty image _sequence".to_string(),
));
}
let (height, width) = image_sequence[0].dim();
let window_size = consciousness_config.temporal_binding_window;
let mut binding_windows = VecDeque::new();
let mut consciousness_moments = Vec::new();
for (t, currentimage) in image_sequence.iter().enumerate() {
let temporal_frame = image_to_temporal_representation(currentimage, t, config)?;
binding_windows.push_back(temporal_frame);
if binding_windows.len() > window_size {
binding_windows.pop_front();
}
if binding_windows.len() == window_size {
let consciousness_moment =
create_consciousness_moment(&binding_windows, &consciousness_config)?;
consciousness_moments.push(consciousness_moment);
}
}
let final_consciousstate = integrate_consciousness_moments(
&consciousness_moments,
(height, width),
&consciousness_config,
)?;
Ok(final_consciousstate)
}
#[allow(dead_code)]
fn unconscious_perceptual_processing<T>(
pixel_value: f64,
image: &ArrayView2<T>,
position: (usize, usize),
config: &QuantumNeuromorphicConfig,
) -> NdimageResult<f64>
where
T: Float + FromPrimitive + Copy,
{
let (y, x) = position;
let (height, width) = image.dim();
let mut activation = 0.0;
if y > 0 && y < height - 1 && x > 0 && x < width - 1 {
let neighbors = [
image[(y - 1, x - 1)].to_f64().unwrap_or(0.0),
image[(y - 1, x)].to_f64().unwrap_or(0.0),
image[(y - 1, x + 1)].to_f64().unwrap_or(0.0),
image[(y, x - 1)].to_f64().unwrap_or(0.0),
image[(y, x + 1)].to_f64().unwrap_or(0.0),
image[(y + 1, x - 1)].to_f64().unwrap_or(0.0),
image[(y + 1, x)].to_f64().unwrap_or(0.0),
image[(y + 1, x + 1)].to_f64().unwrap_or(0.0),
];
let gradient = neighbors
.iter()
.map(|&n| (pixel_value - n).abs())
.sum::<f64>()
/ 8.0;
activation += gradient * 0.3;
}
let texture_response = pixel_value * (pixel_value * PI).sin().abs();
activation += texture_response * 0.4;
let quantum_phase = pixel_value * config.quantum.entanglement_strength * PI;
activation += quantum_phase.cos().abs() * 0.3;
Ok(activation)
}
#[allow(dead_code)]
fn attention_schema_processing(
_pixel_value: f64,
perceptual_module: &Array2<f64>,
position: (usize, usize),
config: &ConsciousnessConfig,
) -> NdimageResult<f64> {
let (y, x) = position;
let (height, width) = perceptual_module.dim();
let local_perceptual_strength = perceptual_module[(y, x)];
let mut attention_competition = 0.0;
let window_size = 3;
let start_y = y.saturating_sub(window_size);
let end_y = (y + window_size + 1).min(height);
let start_x = x.saturating_sub(window_size);
let end_x = (x + window_size + 1).min(width);
for ny in start_y..end_y {
for nx in start_x..end_x {
if ny != y || nx != x {
attention_competition += perceptual_module[(ny, nx)];
}
}
}
let attention_strength = local_perceptual_strength / (1.0 + attention_competition * 0.1);
let attention_activation = attention_strength * config.attention_schema_strength;
Ok(attention_activation)
}
#[allow(dead_code)]
fn memory_trace_activation(
pixel_value: f64,
perceptual_activation: f64,
_config: &ConsciousnessConfig,
) -> NdimageResult<f64> {
let memory_strength = perceptual_activation * pixel_value;
let memory_trace = memory_strength * (1.0 - (-memory_strength * 2.0).exp());
Ok(memory_trace.min(1.0))
}
#[allow(dead_code)]
fn calculate_coalition_strength(
perceptual: f64,
attention: f64,
memory: f64,
config: &ConsciousnessConfig,
) -> NdimageResult<f64> {
let coalition = perceptual * 0.4 + attention * 0.4 + memory * 0.2;
Ok(coalition.min(1.0))
}
#[allow(dead_code)]
fn global_broadcast_influence(
perceptual_module: &mut Array2<f64>,
attention_module: &mut Array2<f64>,
memory_module: &mut Array2<f64>,
broadcast_source: (usize, usize),
strength: f64,
config: &ConsciousnessConfig,
) -> NdimageResult<()> {
let (height, width) = perceptual_module.dim();
let (source_y, source_x) = broadcast_source;
for y in 0..height {
for x in 0..width {
let distance = ((y as f64 - source_y as f64).powi(2)
+ (x as f64 - source_x as f64).powi(2))
.sqrt();
let influence = strength * (-distance * 0.1).exp();
perceptual_module[(y, x)] += influence * 0.1;
attention_module[(y, x)] += influence * 0.2;
memory_module[(y, x)] += influence * 0.15;
}
}
Ok(())
}
#[allow(dead_code)]
fn integrate_conscious_response(
workspace_activation: f64,
perceptual: f64,
attention: f64,
memory: f64,
config: &ConsciousnessConfig,
) -> NdimageResult<f64> {
let integrated = workspace_activation * (perceptual + attention + memory) / 3.0;
Ok(integrated.min(1.0))
}
#[allow(dead_code)]
fn encode_pixel_to_quantumstates(
pixel_value: f64,
config: &QuantumNeuromorphicConfig,
) -> NdimageResult<Array1<f64>> {
let mut quantumstates = Array1::zeros(4);
let angle = pixel_value * PI * 2.0;
quantumstates[0] = angle.cos().abs(); quantumstates[1] = angle.sin().abs(); quantumstates[2] = (angle.cos() * angle.sin()).abs(); quantumstates[3] = (pixel_value * config.quantum.entanglement_strength).min(1.0);
let norm = quantumstates.sum();
if norm > 0.0 {
quantumstates /= norm;
}
Ok(quantumstates)
}
#[allow(dead_code)]
fn calculate_effective_information(
system: &Array3<f64>,
_config: &ConsciousnessConfig,
) -> NdimageResult<f64> {
let (height, width, states) = system.dim();
let mut total_entropy = 0.0;
for y in 0..height {
for x in 0..width {
for s in 0..states {
let p = system[(y, x, s)].abs();
if p > 1e-10 {
total_entropy -= p * p.ln();
}
}
}
}
Ok(total_entropy / (height * width * states) as f64)
}
#[allow(dead_code)]
fn generate_bipartitions(
network: &Array3<f64>,
partition_size: usize,
) -> NdimageResult<Vec<(Array3<f64>, Array3<f64>)>> {
let (height, width, states) = network.dim();
let total_elements = height * width;
if partition_size >= total_elements {
return Ok(Vec::new());
}
let mut bipartitions = Vec::new();
let mid_x = width / 2;
let mut part_a = Array3::zeros((height, mid_x, states));
let mut part_b = Array3::zeros((height, width - mid_x, states));
for y in 0..height {
for x in 0..mid_x {
for s in 0..states {
part_a[(y, x, s)] = network[(y, x, s)];
}
}
for x in mid_x..width {
for s in 0..states {
part_b[(y, x - mid_x, s)] = network[(y, x, s)];
}
}
}
bipartitions.push((part_a, part_b));
Ok(bipartitions)
}
#[allow(dead_code)]
fn apply_phi_weighted_processing(
output: &mut Array2<f64>,
network: &Array3<f64>,
phi_weight: f64,
_config: &ConsciousnessConfig,
) -> NdimageResult<()> {
let (height, width, states) = network.dim();
for y in 0..height {
for x in 0..width {
let mut integrated_value = 0.0;
for s in 0..states {
integrated_value += network[(y, x, s)] * phi_weight;
}
output[(y, x)] += integrated_value / states as f64;
}
}
Ok(())
}
#[allow(dead_code)]
fn calculate_num_bipartitions(n: usize) -> usize {
(2_usize.pow(n as u32) - 2) / 2
}
#[allow(dead_code)]
fn generate_sensory_predictions(
representation: &Array2<f64>,
_config: &ConsciousnessConfig,
) -> NdimageResult<Array2<f64>> {
let (height, width) = representation.dim();
let mut predictions = Array2::zeros((height, width));
for y in 1..height - 1 {
for x in 1..width - 1 {
let neighbors = [
representation[(y - 1, x - 1)],
representation[(y - 1, x)],
representation[(y - 1, x + 1)],
representation[(y, x - 1)],
representation[(y, x + 1)],
representation[(y + 1, x - 1)],
representation[(y + 1, x)],
representation[(y + 1, x + 1)],
];
predictions[(y, x)] = neighbors.iter().sum::<f64>() / 8.0;
}
}
Ok(predictions)
}
#[allow(dead_code)]
fn generate_hierarchical_predictions(
higher_level: &Array2<f64>,
current_level: &Array2<f64>,
_level_size: usize,
_config: &ConsciousnessConfig,
) -> NdimageResult<Array2<f64>> {
let (height, width) = current_level.dim();
let mut predictions = Array2::zeros((height, width));
for y in 0..height {
for x in 0..width {
let higher_value = higher_level[(y, x)];
let prediction = higher_value * 0.8 + current_level[(y, x)] * 0.2;
predictions[(y, x)] = prediction;
}
}
Ok(predictions)
}
#[allow(dead_code)]
fn calculate_prediction_error(
actual: &Array2<f64>,
predicted: &Array2<f64>,
_config: &ConsciousnessConfig,
) -> NdimageResult<f64> {
let diff = actual - predicted;
let squared_error = diff.mapv(|x| x * x);
Ok(squared_error.mean())
}
#[allow(dead_code)]
fn update_representation_with_error(
current: &Array2<f64>,
prediction: &Array2<f64>,
_error: f64,
config: &ConsciousnessConfig,
) -> NdimageResult<Array2<f64>> {
let learning_rate = 0.1;
let error_signal = current - prediction;
let updated = current + &(error_signal * learning_rate);
Ok(updated)
}
#[allow(dead_code)]
fn refine_prediction_top_down(
higher_prediction: &Array2<f64>,
level_prediction: &Array2<f64>,
_error: f64,
config: &ConsciousnessConfig,
) -> NdimageResult<Array2<f64>> {
let refinement_strength = 0.3;
let refined =
higher_prediction * (1.0 - refinement_strength) + level_prediction * refinement_strength;
Ok(refined)
}
#[allow(dead_code)]
fn calculate_precision_weights(
errors: &[f64],
_config: &ConsciousnessConfig,
) -> NdimageResult<Array2<f64>> {
let height = 4; let width = 4;
let mut weights = Array2::zeros((height, width));
let avg_error = errors.iter().sum::<f64>() / errors.len() as f64;
let precision = 1.0 / (1.0 + avg_error);
weights.fill(precision);
Ok(weights)
}
#[allow(dead_code)]
fn calculate_processing_confidence(
_pixel_value: f64,
history: &[Array2<f64>],
position: (usize, usize),
_config: &ConsciousnessConfig,
) -> NdimageResult<f64> {
let (y, x) = position;
if history.is_empty() {
return Ok(0.5); }
let mut values = Vec::new();
for frame in history {
if y < frame.nrows() && x < frame.ncols() {
values.push(frame[(y, x)]);
}
}
if values.is_empty() {
return Ok(0.5);
}
let mean = values.iter().sum::<f64>() / values.len() as f64;
let variance = values.iter().map(|v| (v - mean).powi(2)).sum::<f64>() / values.len() as f64;
let confidence = 1.0 / (1.0 + variance);
Ok(confidence)
}
#[allow(dead_code)]
fn calculate_processing_effort(
history: &[Array2<f64>],
position: (usize, usize),
_config: &ConsciousnessConfig,
) -> NdimageResult<f64> {
let (y, x) = position;
if history.len() < 2 {
return Ok(0.0);
}
let mut total_change = 0.0;
for i in 1..history.len() {
if y < history[i].nrows()
&& x < history[i].ncols()
&& y < history[i - 1].nrows()
&& x < history[i - 1].ncols()
{
let change = (history[i][(y, x)] - history[i - 1][(y, x)]).abs();
total_change += change;
}
}
Ok(total_change / (history.len() - 1) as f64)
}
#[allow(dead_code)]
fn calculate_error_monitoring_signal(
pixel_value: f64,
history: &[Array2<f64>],
position: (usize, usize),
_config: &ConsciousnessConfig,
) -> NdimageResult<f64> {
let (y, x) = position;
if history.is_empty() {
return Ok(0.0);
}
let mut deviations = Vec::new();
for frame in history {
if y < frame.nrows() && x < frame.ncols() {
let deviation = (pixel_value - frame[(y, x)]).abs();
deviations.push(deviation);
}
}
if deviations.is_empty() {
return Ok(0.0);
}
let mean_deviation = deviations.iter().sum::<f64>() / deviations.len() as f64;
Ok(mean_deviation.min(1.0))
}
#[allow(dead_code)]
fn integrate_metacognitive_signals(
confidence: f64,
effort: f64,
error_signal: f64,
_config: &ConsciousnessConfig,
) -> NdimageResult<f64> {
let metacognitive_value = confidence * 0.4 + (1.0 - effort) * 0.3 + (1.0 - error_signal) * 0.3;
Ok(metacognitive_value.min(1.0))
}
#[allow(dead_code)]
fn calculate_self_awareness_index(
confidence: f64,
effort: f64,
error_monitoring: f64,
config: &ConsciousnessConfig,
) -> NdimageResult<f64> {
let self_awareness = (confidence * effort * (1.0 - error_monitoring)).cbrt();
Ok(self_awareness * config.metacognitive_sensitivity)
}
#[allow(dead_code)]
fn image_to_temporal_representation<T>(
image: &ArrayView2<T>,
timestamp: usize,
config: &QuantumNeuromorphicConfig,
) -> NdimageResult<Array3<f64>>
where
T: Float + FromPrimitive + Copy,
{
let (height, width) = image.dim();
let temporal_depth = 8;
let mut temporal_rep = Array3::zeros((height, width, temporal_depth));
for y in 0..height {
for x in 0..width {
let pixel_value = image[(y, x)].to_f64().unwrap_or(0.0);
for d in 0..temporal_depth {
let temporal_phase = (timestamp as f64 + d as f64) * PI / temporal_depth as f64;
temporal_rep[(y, x, d)] = pixel_value * temporal_phase.cos();
}
}
}
Ok(temporal_rep)
}
#[allow(dead_code)]
fn create_consciousness_moment(
binding_window: &VecDeque<Array3<f64>>,
_config: &ConsciousnessConfig,
) -> NdimageResult<Array2<f64>> {
if binding_window.is_empty() {
return Err(NdimageError::InvalidInput(
"Empty binding _window".to_string(),
));
}
let (height, width, depth) = binding_window[0].dim();
let mut consciousness_moment = Array2::zeros((height, width));
for y in 0..height {
for x in 0..width {
let mut temporal_integration = 0.0;
for (t, frame) in binding_window.iter().enumerate() {
for d in 0..depth {
let weight = ((t as f64 - binding_window.len() as f64 / 2.0).abs())
.exp()
.recip();
temporal_integration += frame[(y, x, d)] * weight;
}
}
consciousness_moment[(y, x)] =
temporal_integration / (binding_window.len() * depth) as f64;
}
}
Ok(consciousness_moment)
}
#[allow(dead_code)]
fn integrate_consciousness_moments<T>(
moments: &[Array2<f64>],
outputshape: (usize, usize),
_config: &ConsciousnessConfig,
) -> NdimageResult<Array2<T>>
where
T: Float + FromPrimitive + Copy,
{
let (height, width) = outputshape;
let mut integrated = Array2::zeros((height, width));
for moment in moments {
integrated = integrated + moment;
}
if !moments.is_empty() {
integrated /= moments.len() as f64;
}
let output = integrated.mapv(|x| T::from_f64(x).unwrap_or_else(|| T::zero()));
Ok(output)
}