1use wasm_bindgen::prelude::*;
2
3mod utils;
4mod simd_ops;
5mod simd_tests;
6mod memory_pool;
7
8pub use utils::{set_panic_hook, RuntimeFeatures};
9pub use simd_ops::{SimdVectorOps, SimdMatrixOps, SimdBenchmark, detect_simd_capabilities};
10pub use simd_tests::{run_simd_verification_suite, simd_performance_report, validate_simd_implementation};
11pub use memory_pool::MemoryPool;
12
13#[cfg(feature = "wee_alloc")]
16#[global_allocator]
17static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
18
19#[wasm_bindgen(start)]
20pub fn init() {
21 set_panic_hook();
22}
23
24#[wasm_bindgen]
25#[derive(Debug, Clone, Copy)]
26pub enum ActivationFunction {
27 Linear,
28 Sigmoid,
29 SymmetricSigmoid,
30 Tanh,
31 ReLU,
32 LeakyReLU,
33 Swish,
34 Gaussian,
35 Elliot,
36 SymmetricElliot,
37 Sine,
38 Cosine,
39 SinSymmetric,
40 CosSymmetric,
41 ThresholdSymmetric,
42 Threshold,
43 StepSymmetric,
44 Step,
45}
46
47#[wasm_bindgen]
48pub struct WasmNeuralNetwork {
49 layers: Vec<usize>,
50 weights: Vec<f64>,
51 biases: Vec<f64>,
52 activation: ActivationFunction,
53}
54
55#[wasm_bindgen]
56impl WasmNeuralNetwork {
57 #[wasm_bindgen(constructor)]
58 pub fn new(layers: &[usize], activation: ActivationFunction) -> Self {
59 let total_weights = layers.windows(2).map(|w| w[0] * w[1]).sum();
60 let total_biases = layers[1..].iter().sum();
61
62 Self {
63 layers: layers.to_vec(),
64 weights: vec![0.0; total_weights],
65 biases: vec![0.0; total_biases],
66 activation,
67 }
68 }
69
70 #[wasm_bindgen]
71 pub fn randomize_weights(&mut self, min: f64, max: f64) {
72 use js_sys::Math;
73 for weight in &mut self.weights {
74 *weight = min + (max - min) * Math::random();
75 }
76 for bias in &mut self.biases {
77 *bias = min + (max - min) * Math::random();
78 }
79 }
80
81 #[wasm_bindgen]
82 pub fn set_weights(&mut self, weights: &[f64]) {
83 if weights.len() == self.weights.len() {
84 self.weights.copy_from_slice(weights);
85 }
86 }
87
88 #[wasm_bindgen]
89 pub fn get_weights(&self) -> Vec<f64> {
90 self.weights.clone()
91 }
92
93 #[wasm_bindgen]
94 pub fn run(&self, inputs: &[f64]) -> Vec<f64> {
95 let mut current_outputs = inputs.to_vec();
96
97 for layer_idx in 1..self.layers.len() {
98 let prev_size = self.layers[layer_idx - 1];
99 let curr_size = self.layers[layer_idx];
100
101 let mut layer_weights = vec![0.0; prev_size * curr_size];
103 for curr_neuron in 0..curr_size {
104 for prev_neuron in 0..prev_size {
105 let weight_idx = self.get_weight_index(layer_idx - 1, prev_neuron, curr_neuron);
106 layer_weights[curr_neuron * prev_size + prev_neuron] = self.weights[weight_idx] as f64;
107 }
108 }
109
110 let current_f32: Vec<f32> = current_outputs.iter().map(|&x| x as f32).collect();
112 let weights_f32: Vec<f32> = layer_weights.iter().map(|&x| x as f32).collect();
113
114 let simd_ops = crate::simd_ops::SimdMatrixOps::new();
116 let simd_result = simd_ops.matrix_vector_multiply(
117 &weights_f32,
118 ¤t_f32,
119 curr_size,
120 prev_size
121 );
122
123 let mut new_outputs = vec![0.0; curr_size];
125 for curr_neuron in 0..curr_size {
126 let bias_idx = self.get_bias_index(layer_idx, curr_neuron);
127 let sum = simd_result[curr_neuron] as f64 + self.biases[bias_idx];
128 new_outputs[curr_neuron] = self.apply_activation(sum);
129 }
130
131 current_outputs = new_outputs;
132 }
133
134 current_outputs
135 }
136
137 fn get_weight_index(&self, from_layer: usize, from_neuron: usize, to_neuron: usize) -> usize {
138 let mut index = 0;
139 for layer in 0..from_layer {
140 index += self.layers[layer] * self.layers[layer + 1];
141 }
142 index + from_neuron * self.layers[from_layer + 1] + to_neuron
143 }
144
145 fn get_bias_index(&self, layer: usize, neuron: usize) -> usize {
146 let mut index = 0;
147 for l in 1..layer {
148 index += self.layers[l];
149 }
150 index + neuron
151 }
152
153 fn apply_activation(&self, x: f64) -> f64 {
154 match self.activation {
155 ActivationFunction::Linear => x,
156 ActivationFunction::Sigmoid => 1.0 / (1.0 + (-x).exp()),
157 ActivationFunction::SymmetricSigmoid => 2.0 / (1.0 + (-x).exp()) - 1.0,
158 ActivationFunction::Tanh => x.tanh(),
159 ActivationFunction::ReLU => x.max(0.0),
160 ActivationFunction::LeakyReLU => if x > 0.0 { x } else { 0.01 * x },
161 ActivationFunction::Swish => x * (1.0 / (1.0 + (-x).exp())),
162 ActivationFunction::Gaussian => (-x * x).exp(),
163 ActivationFunction::Elliot => x / (1.0 + x.abs()),
164 ActivationFunction::SymmetricElliot => 2.0 * x / (1.0 + x.abs()),
165 ActivationFunction::Sine => x.sin(),
166 ActivationFunction::Cosine => x.cos(),
167 ActivationFunction::SinSymmetric => 2.0 * x.sin() - 1.0,
168 ActivationFunction::CosSymmetric => 2.0 * x.cos() - 1.0,
169 ActivationFunction::ThresholdSymmetric => if x > 0.0 { 1.0 } else { -1.0 },
170 ActivationFunction::Threshold => if x > 0.0 { 1.0 } else { 0.0 },
171 ActivationFunction::StepSymmetric => if x > 0.0 { 1.0 } else { -1.0 },
172 ActivationFunction::Step => if x > 0.0 { 1.0 } else { 0.0 },
173 }
174 }
175}
176
177#[wasm_bindgen]
178pub struct WasmSwarmOrchestrator {
179 agents: Vec<WasmAgent>,
180 topology: String,
181 task_counter: u32,
182}
183
184#[wasm_bindgen]
185#[derive(Clone)]
186pub struct WasmAgent {
187 id: String,
188 agent_type: String,
189 status: String,
190 capabilities: Vec<String>,
191}
192
193#[wasm_bindgen]
194impl WasmAgent {
195 #[wasm_bindgen(constructor)]
196 pub fn new(id: &str, agent_type: &str) -> Self {
197 Self {
198 id: id.to_string(),
199 agent_type: agent_type.to_string(),
200 status: "idle".to_string(),
201 capabilities: Vec::new(),
202 }
203 }
204
205 #[wasm_bindgen(getter)]
206 pub fn id(&self) -> String {
207 self.id.clone()
208 }
209
210 #[wasm_bindgen(getter)]
211 pub fn agent_type(&self) -> String {
212 self.agent_type.clone()
213 }
214
215 #[wasm_bindgen(getter)]
216 pub fn status(&self) -> String {
217 self.status.clone()
218 }
219
220 #[wasm_bindgen]
221 pub fn set_status(&mut self, status: &str) {
222 self.status = status.to_string();
223 }
224
225 #[wasm_bindgen]
226 pub fn add_capability(&mut self, capability: &str) {
227 self.capabilities.push(capability.to_string());
228 }
229
230 #[wasm_bindgen]
231 pub fn has_capability(&self, capability: &str) -> bool {
232 self.capabilities.contains(&capability.to_string())
233 }
234}
235
236#[wasm_bindgen]
237pub struct WasmTaskResult {
238 task_id: String,
239 description: String,
240 status: String,
241 assigned_agents: Vec<String>,
242 priority: String,
243}
244
245#[wasm_bindgen]
246impl WasmTaskResult {
247 #[wasm_bindgen(getter)]
248 pub fn task_id(&self) -> String {
249 self.task_id.clone()
250 }
251
252 #[wasm_bindgen(getter)]
253 pub fn description(&self) -> String {
254 self.description.clone()
255 }
256
257 #[wasm_bindgen(getter)]
258 pub fn status(&self) -> String {
259 self.status.clone()
260 }
261
262 #[wasm_bindgen(getter)]
263 pub fn assigned_agents(&self) -> Vec<String> {
264 self.assigned_agents.clone()
265 }
266
267 #[wasm_bindgen(getter)]
268 pub fn priority(&self) -> String {
269 self.priority.clone()
270 }
271}
272
273#[wasm_bindgen]
274impl WasmSwarmOrchestrator {
275 #[wasm_bindgen(constructor)]
276 pub fn new(topology: &str) -> Self {
277 Self {
278 agents: Vec::new(),
279 topology: topology.to_string(),
280 task_counter: 0,
281 }
282 }
283
284 #[wasm_bindgen]
285 pub fn spawn(&mut self, config: &str) -> String {
286 let agent_id = format!("agent-{}", self.agents.len() + 1);
288 let mut agent = WasmAgent::new(&agent_id, "researcher");
289
290 agent.add_capability("research");
292 agent.add_capability("analysis");
293
294 self.agents.push(agent);
295
296 serde_json::json!({
298 "agent_id": agent_id,
299 "name": format!("Agent-{}", self.agents.len()),
300 "type": "researcher",
301 "capabilities": ["research", "analysis"],
302 "cognitive_pattern": "adaptive",
303 "neural_network_id": format!("nn-{}", self.agents.len())
304 }).to_string()
305 }
306
307 #[wasm_bindgen]
308 pub fn orchestrate(&mut self, config: &str) -> WasmTaskResult {
309 self.task_counter += 1;
310 let task_id = format!("task-{}", self.task_counter);
311
312 let description = "Sample task"; let priority = "medium"; let mut assigned_agents = Vec::new();
318 for agent in &mut self.agents {
319 if agent.status == "idle" && assigned_agents.len() < 3 {
320 agent.set_status("busy");
321 assigned_agents.push(agent.id());
322 }
323 }
324
325 WasmTaskResult {
326 task_id,
327 description: description.to_string(),
328 status: "orchestrated".to_string(),
329 assigned_agents,
330 priority: priority.to_string(),
331 }
332 }
333
334 #[wasm_bindgen]
335 pub fn add_agent(&mut self, agent_id: &str) {
336 let agent = WasmAgent::new(agent_id, "generic");
337 self.agents.push(agent);
338 }
339
340 #[wasm_bindgen]
341 pub fn get_agent_count(&self) -> usize {
342 self.agents.len()
343 }
344
345 #[wasm_bindgen]
346 pub fn get_topology(&self) -> String {
347 self.topology.clone()
348 }
349
350 #[wasm_bindgen]
351 pub fn get_status(&self, detailed: bool) -> String {
352 let idle_count = self.agents.iter().filter(|a| a.status == "idle").count();
353 let busy_count = self.agents.iter().filter(|a| a.status == "busy").count();
354
355 if detailed {
356 serde_json::json!({
357 "agents": {
358 "total": self.agents.len(),
359 "idle": idle_count,
360 "busy": busy_count
361 },
362 "topology": self.topology,
363 "agent_details": self.agents.iter().map(|a| {
364 serde_json::json!({
365 "id": a.id(),
366 "type": a.agent_type(),
367 "status": a.status()
368 })
369 }).collect::<Vec<_>>()
370 }).to_string()
371 } else {
372 serde_json::json!({
373 "agents": {
374 "total": self.agents.len(),
375 "idle": idle_count,
376 "busy": busy_count
377 },
378 "topology": self.topology
379 }).to_string()
380 }
381 }
382}
383
384#[wasm_bindgen]
385pub struct WasmForecastingModel {
386 model_type: String,
387 parameters: Vec<f64>,
388}
389
390#[wasm_bindgen]
391impl WasmForecastingModel {
392 #[wasm_bindgen(constructor)]
393 pub fn new(model_type: &str) -> Self {
394 Self {
395 model_type: model_type.to_string(),
396 parameters: Vec::new(),
397 }
398 }
399
400 #[wasm_bindgen]
401 pub fn predict(&self, input: &[f64]) -> Vec<f64> {
402 match self.model_type.as_str() {
404 "linear" => {
405 let slope = if input.len() > 1 {
406 input[input.len() - 1] - input[input.len() - 2]
407 } else {
408 0.0
409 };
410 vec![input[input.len() - 1] + slope]
411 }
412 "mean" => {
413 let mean = input.iter().sum::<f64>() / input.len() as f64;
414 vec![mean]
415 }
416 _ => vec![input[input.len() - 1]]
417 }
418 }
419
420 #[wasm_bindgen]
421 pub fn get_model_type(&self) -> String {
422 self.model_type.clone()
423 }
424}
425
426#[wasm_bindgen]
428pub fn create_neural_network(layers: &[usize], activation: ActivationFunction) -> WasmNeuralNetwork {
429 WasmNeuralNetwork::new(layers, activation)
430}
431
432#[wasm_bindgen]
433pub fn create_swarm_orchestrator(topology: &str) -> WasmSwarmOrchestrator {
434 WasmSwarmOrchestrator::new(topology)
435}
436
437#[wasm_bindgen]
438pub fn create_forecasting_model(model_type: &str) -> WasmForecastingModel {
439 WasmForecastingModel::new(model_type)
440}
441
442#[wasm_bindgen]
443pub fn get_version() -> String {
444 "0.1.0".to_string()
445}
446
447#[wasm_bindgen]
448pub fn get_features() -> String {
449 let simd_support = detect_simd_support();
450 serde_json::json!({
451 "neural_networks": true,
452 "forecasting": true,
453 "swarm_orchestration": true,
454 "cognitive_diversity": true,
455 "simd_support": simd_support,
456 "simd_capabilities": detect_simd_capabilities()
457 }).to_string()
458}
459
460fn detect_simd_support() -> bool {
462 #[cfg(target_arch = "wasm32")]
464 {
465 #[cfg(feature = "simd")]
467 {
468 true
470 }
471
472 #[cfg(not(feature = "simd"))]
474 {
475 false }
477 }
478
479 #[cfg(not(target_arch = "wasm32"))]
481 {
482 #[cfg(any(target_feature = "sse", target_feature = "avx", target_feature = "avx2", target_feature = "neon"))]
483 {
484 true
485 }
486 #[cfg(not(any(target_feature = "sse", target_feature = "avx", target_feature = "avx2", target_feature = "neon")))]
487 {
488 false
489 }
490 }
491}
492
493fn test_simd_runtime() -> bool {
495 let test_vec_a = vec![1.0f32, 2.0, 3.0, 4.0];
497 let test_vec_b = vec![2.0f32, 3.0, 4.0, 5.0];
498
499 let result = std::panic::catch_unwind(|| {
501 let ops = crate::simd_ops::SimdVectorOps::new();
502 ops.dot_product(&test_vec_a, &test_vec_b)
503 });
504
505 match result {
506 Ok(value) => {
507 (value - 40.0).abs() < 0.1
509 }
510 Err(_) => false
511 }
512}
513
514#[wasm_bindgen]
516pub struct PerformanceMonitor {
517 load_time: f64,
518 spawn_times: Vec<f64>,
519 memory_usage: usize,
520 simd_enabled: bool,
521}
522
523#[wasm_bindgen]
524impl PerformanceMonitor {
525 #[wasm_bindgen(constructor)]
526 pub fn new() -> Self {
527 Self {
528 load_time: 0.0,
529 spawn_times: Vec::new(),
530 memory_usage: 0,
531 simd_enabled: detect_simd_support(),
532 }
533 }
534
535 pub fn record_load_time(&mut self, time: f64) {
536 self.load_time = time;
537 }
538
539 pub fn record_spawn_time(&mut self, time: f64) {
540 self.spawn_times.push(time);
541 }
542
543 pub fn update_memory_usage(&mut self, bytes: usize) {
544 self.memory_usage = bytes;
545 }
546
547 pub fn get_average_spawn_time(&self) -> f64 {
548 if self.spawn_times.is_empty() {
549 0.0
550 } else {
551 self.spawn_times.iter().sum::<f64>() / self.spawn_times.len() as f64
552 }
553 }
554
555 pub fn get_memory_usage_mb(&self) -> f64 {
556 (self.memory_usage as f64) / (1024.0 * 1024.0)
557 }
558
559 pub fn meets_performance_targets(&self) -> bool {
560 self.load_time < 500.0 &&
561 self.get_average_spawn_time() < 100.0 &&
562 self.get_memory_usage_mb() < 50.0
563 }
564
565 pub fn get_report(&self) -> String {
566 format!(
567 "Performance Report:\n\
568 - Load Time: {:.2}ms (Target: <500ms) {}\n\
569 - Avg Spawn Time: {:.2}ms (Target: <100ms) {}\n\
570 - Memory Usage: {:.2}MB (Target: <50MB) {}\n\
571 - SIMD Enabled: {}\n\
572 - All Targets Met: {}",
573 self.load_time,
574 if self.load_time < 500.0 { "✓" } else { "✗" },
575 self.get_average_spawn_time(),
576 if self.get_average_spawn_time() < 100.0 { "✓" } else { "✗" },
577 self.get_memory_usage_mb(),
578 if self.get_memory_usage_mb() < 50.0 { "✓" } else { "✗" },
579 self.simd_enabled,
580 self.meets_performance_targets()
581 )
582 }
583}
584
585#[wasm_bindgen]
587pub struct OptimizedAgentSpawner {
588 memory_pool: memory_pool::AgentMemoryPool,
589 performance_monitor: PerformanceMonitor,
590 active_agents: Vec<OptimizedAgent>,
591}
592
593#[wasm_bindgen]
594pub struct OptimizedAgent {
595 id: String,
596 agent_type: String,
597 memory_size: usize,
598 #[wasm_bindgen(skip)]
599 memory: Vec<u8>,
600}
601
602#[wasm_bindgen]
603impl OptimizedAgentSpawner {
604 #[wasm_bindgen(constructor)]
605 pub fn new() -> Self {
606 Self {
607 memory_pool: memory_pool::AgentMemoryPool::new(),
608 performance_monitor: PerformanceMonitor::new(),
609 active_agents: Vec::new(),
610 }
611 }
612
613 pub fn spawn_agent(&mut self, agent_type: &str, complexity: &str) -> Result<String, JsValue> {
614 let start = js_sys::Date::now();
615
616 let memory = self.memory_pool
618 .allocate_for_agent(complexity)
619 .ok_or_else(|| JsValue::from_str("Memory allocation failed"))?;
620
621 let memory_size = memory.len();
622 let agent_id = format!("agent-{}-{}", agent_type, js_sys::Math::random());
623
624 let agent = OptimizedAgent {
625 id: agent_id.clone(),
626 agent_type: agent_type.to_string(),
627 memory_size,
628 memory,
629 };
630
631 self.active_agents.push(agent);
632
633 let spawn_time = js_sys::Date::now() - start;
635 self.performance_monitor.record_spawn_time(spawn_time);
636 self.performance_monitor.update_memory_usage(
637 self.memory_pool.total_memory_usage_mb() as usize * 1024 * 1024
638 );
639
640 Ok(agent_id)
641 }
642
643 pub fn release_agent(&mut self, agent_id: &str) -> Result<(), JsValue> {
644 if let Some(pos) = self.active_agents.iter().position(|a| a.id == agent_id) {
645 let agent = self.active_agents.remove(pos);
646 self.memory_pool.deallocate_agent_memory(agent.memory);
647 self.performance_monitor.update_memory_usage(
648 self.memory_pool.total_memory_usage_mb() as usize * 1024 * 1024
649 );
650 Ok(())
651 } else {
652 Err(JsValue::from_str("Agent not found"))
653 }
654 }
655
656 pub fn get_performance_report(&self) -> String {
657 self.performance_monitor.get_report()
658 }
659
660 pub fn get_active_agent_count(&self) -> usize {
661 self.active_agents.len()
662 }
663
664 pub fn is_within_memory_target(&self) -> bool {
665 self.memory_pool.is_within_memory_target()
666 }
667}