1use crate::blas1;
10use crate::vector::{Vector, VectorCache};
11use pounce_common::tagged::{Tag, TaggedObject};
12use pounce_common::types::{Index, Number};
13use std::any::Any;
14use std::cell::RefCell;
15use std::collections::BTreeMap;
16use std::rc::Rc;
17
18#[derive(Debug, Default)]
22pub struct DenseVectorSpace {
23 dim: Index,
24 string_meta: RefCell<BTreeMap<String, Vec<String>>>,
25 integer_meta: RefCell<BTreeMap<String, Vec<Index>>>,
26 numeric_meta: RefCell<BTreeMap<String, Vec<Number>>>,
27}
28
29impl DenseVectorSpace {
30 pub fn new(dim: Index) -> Rc<Self> {
31 Rc::new(Self {
32 dim,
33 string_meta: RefCell::new(BTreeMap::new()),
34 integer_meta: RefCell::new(BTreeMap::new()),
35 numeric_meta: RefCell::new(BTreeMap::new()),
36 })
37 }
38
39 pub fn dim(&self) -> Index {
40 self.dim
41 }
42
43 pub fn make_new_dense(self: &Rc<Self>) -> DenseVector {
44 DenseVector::new(Rc::clone(self))
45 }
46
47 pub fn has_string_meta(&self, tag: &str) -> bool {
48 self.string_meta.borrow().contains_key(tag)
49 }
50 pub fn set_string_meta(&self, tag: &str, data: Vec<String>) {
51 self.string_meta.borrow_mut().insert(tag.to_string(), data);
52 }
53 pub fn get_string_meta(&self, tag: &str) -> Option<Vec<String>> {
54 self.string_meta.borrow().get(tag).cloned()
55 }
56
57 pub fn has_integer_meta(&self, tag: &str) -> bool {
58 self.integer_meta.borrow().contains_key(tag)
59 }
60 pub fn set_integer_meta(&self, tag: &str, data: Vec<Index>) {
61 self.integer_meta.borrow_mut().insert(tag.to_string(), data);
62 }
63 pub fn get_integer_meta(&self, tag: &str) -> Option<Vec<Index>> {
64 self.integer_meta.borrow().get(tag).cloned()
65 }
66
67 pub fn has_numeric_meta(&self, tag: &str) -> bool {
68 self.numeric_meta.borrow().contains_key(tag)
69 }
70 pub fn set_numeric_meta(&self, tag: &str, data: Vec<Number>) {
71 self.numeric_meta.borrow_mut().insert(tag.to_string(), data);
72 }
73 pub fn get_numeric_meta(&self, tag: &str) -> Option<Vec<Number>> {
74 self.numeric_meta.borrow().get(tag).cloned()
75 }
76}
77
78#[derive(Debug)]
80pub struct DenseVector {
81 space: Rc<DenseVectorSpace>,
82 cache: VectorCache,
83 values: Vec<Number>,
85 initialized: bool,
86 homogeneous: bool,
87 scalar: Number,
88}
89
90impl DenseVector {
91 pub fn new(space: Rc<DenseVectorSpace>) -> Self {
92 let dim = space.dim();
93 let (initialized, homogeneous, scalar) = if dim == 0 {
95 (true, true, 0.0)
96 } else {
97 (false, false, 0.0)
98 };
99 Self {
100 space,
101 cache: VectorCache::new(),
102 values: Vec::new(),
103 initialized,
104 homogeneous,
105 scalar,
106 }
107 }
108
109 pub fn space(&self) -> &Rc<DenseVectorSpace> {
110 &self.space
111 }
112
113 pub fn is_homogeneous(&self) -> bool {
114 self.homogeneous
115 }
116
117 pub fn scalar(&self) -> Number {
118 debug_assert!(self.homogeneous);
119 self.scalar
120 }
121
122 pub fn is_initialized(&self) -> bool {
123 self.initialized
124 }
125
126 pub fn values(&self) -> &[Number] {
131 debug_assert!(self.initialized && !self.homogeneous);
132 &self.values
133 }
134
135 pub fn values_mut(&mut self) -> &mut [Number] {
138 if self.initialized && self.homogeneous {
139 self.materialize_from_scalar();
140 }
141 self.ensure_storage();
142 self.cache.bump();
143 self.initialized = true;
144 self.homogeneous = false;
145 &mut self.values
146 }
147
148 pub fn expanded_values(&self) -> Vec<Number> {
152 if self.homogeneous {
153 vec![self.scalar; self.space.dim() as usize]
154 } else {
155 self.values.clone()
156 }
157 }
158
159 pub fn set_values(&mut self, x: &[Number]) {
160 let dim = self.space.dim() as usize;
161 assert_eq!(x.len(), dim);
162 self.ensure_storage();
163 self.values[..dim].copy_from_slice(x);
164 self.initialized = true;
165 self.homogeneous = false;
166 self.cache.bump();
167 }
168
169 pub fn copy_to_pos(&mut self, pos: Index, x: &dyn Vector) {
171 let pos = pos as usize;
172 let dim_x = x.dim() as usize;
173 assert!(pos + dim_x <= self.space.dim() as usize);
174 let dense_x = downcast_dense(x);
175 if self.homogeneous && self.initialized {
176 self.materialize_from_scalar();
177 }
178 self.ensure_storage();
179 self.homogeneous = false;
180 if dense_x.homogeneous {
181 for v in &mut self.values[pos..pos + dim_x] {
182 *v = dense_x.scalar;
183 }
184 } else {
185 self.values[pos..pos + dim_x].copy_from_slice(&dense_x.values[..dim_x]);
186 }
187 self.initialized = true;
188 self.cache.bump();
189 }
190
191 pub fn copy_from_pos(&mut self, pos: Index, x: &dyn Vector) {
193 let pos = pos as usize;
194 let dim = self.space.dim() as usize;
195 assert!(pos + dim <= x.dim() as usize);
196 let dense_x = downcast_dense(x);
197 if dense_x.homogeneous {
198 self.set(dense_x.scalar);
199 } else {
200 self.ensure_storage();
201 self.values[..dim].copy_from_slice(&dense_x.values[pos..pos + dim]);
202 self.initialized = true;
203 self.homogeneous = false;
204 self.cache.bump();
205 }
206 }
207
208 pub fn ensure_storage(&mut self) {
209 let dim = self.space.dim() as usize;
210 if self.values.len() != dim {
211 self.values.resize(dim, 0.0);
212 }
213 }
214
215 fn materialize_from_scalar(&mut self) {
217 debug_assert!(self.homogeneous);
218 let dim = self.space.dim() as usize;
219 self.values.clear();
220 self.values.resize(dim, self.scalar);
221 self.homogeneous = false;
222 self.initialized = true;
223 }
224}
225
226fn downcast_dense(x: &dyn Vector) -> &DenseVector {
227 match x.as_any().downcast_ref::<DenseVector>() {
228 Some(v) => v,
229 None => panic!(
230 "Vector argument is not a DenseVector — mixed-type linear algebra is not supported in v1.0"
231 ),
232 }
233}
234
235impl TaggedObject for DenseVector {
236 fn get_tag(&self) -> Tag {
237 self.cache.tag()
238 }
239}
240
241impl Vector for DenseVector {
242 fn dim(&self) -> Index {
243 self.space.dim()
244 }
245
246 fn cache(&self) -> &VectorCache {
247 &self.cache
248 }
249
250 fn make_new(&self) -> Box<dyn Vector> {
251 Box::new(DenseVector::new(Rc::clone(&self.space)))
252 }
253
254 fn as_any(&self) -> &dyn Any {
255 self
256 }
257
258 fn as_any_mut(&mut self) -> &mut dyn Any {
259 self
260 }
261
262 fn as_tagged(&self) -> &dyn TaggedObject {
263 self
264 }
265
266 fn as_dyn_vector(&self) -> &dyn Vector {
267 self
268 }
269
270 fn copy_impl(&mut self, x: &dyn Vector) {
271 let dx = downcast_dense(x);
272 debug_assert!(dx.initialized);
273 debug_assert_eq!(self.space.dim(), dx.space.dim());
274 self.homogeneous = dx.homogeneous;
275 if dx.homogeneous {
276 self.scalar = dx.scalar;
277 self.values.clear();
278 } else {
279 self.ensure_storage();
280 let dim = self.space.dim() as usize;
281 self.values[..dim].copy_from_slice(&dx.values[..dim]);
282 }
283 self.initialized = true;
284 }
285
286 fn scal_impl(&mut self, alpha: Number) {
287 debug_assert!(self.initialized);
288 if self.homogeneous {
289 self.scalar *= alpha;
290 } else {
291 blas1::scal(alpha, &mut self.values, 1, self.space.dim());
292 }
293 }
294
295 fn axpy_impl(&mut self, alpha: Number, x: &dyn Vector) {
296 debug_assert!(self.initialized);
297 let dx = downcast_dense(x);
298 debug_assert!(dx.initialized);
299 let dim = self.space.dim();
300 if dim == 0 {
301 return;
302 }
303 if self.homogeneous {
304 if dx.homogeneous {
305 self.scalar += alpha * dx.scalar;
306 } else {
307 let s0 = self.scalar;
308 self.homogeneous = false;
309 self.ensure_storage();
310 let n = dim as usize;
311 for i in 0..n {
312 self.values[i] = s0 + alpha * dx.values[i];
313 }
314 }
315 } else if dx.homogeneous {
316 if dx.scalar != 0.0 {
317 let inc = alpha * dx.scalar;
318 for v in &mut self.values[..dim as usize] {
319 *v += inc;
320 }
321 }
322 } else {
323 blas1::axpy(alpha, &dx.values, 1, &mut self.values, 1, dim);
324 }
325 }
326
327 fn dot_impl(&self, x: &dyn Vector) -> Number {
328 debug_assert!(self.initialized);
329 let dx = downcast_dense(x);
330 debug_assert!(dx.initialized);
331 let dim = self.space.dim();
332 let n = dim as usize;
333 if dim == 0 {
334 return 0.0;
335 }
336 match (self.homogeneous, dx.homogeneous) {
337 (true, true) => (n as Number) * self.scalar * dx.scalar,
338 (true, false) => {
339 let mut s = 0.0;
341 for v in &dx.values[..n] {
342 s += self.scalar * v;
343 }
344 s
345 }
346 (false, true) => {
347 let mut s = 0.0;
348 for v in &self.values[..n] {
349 s += dx.scalar * v;
350 }
351 s
352 }
353 (false, false) => blas1::dot(&self.values, 1, &dx.values, 1, dim),
354 }
355 }
356
357 fn nrm2_impl(&self) -> Number {
358 debug_assert!(self.initialized);
359 if self.homogeneous {
360 (self.space.dim() as Number).sqrt() * self.scalar.abs()
361 } else {
362 blas1::nrm2(&self.values, 1, self.space.dim())
363 }
364 }
365
366 fn asum_impl(&self) -> Number {
367 debug_assert!(self.initialized);
368 if self.homogeneous {
369 (self.space.dim() as Number) * self.scalar.abs()
370 } else {
371 blas1::asum(&self.values, 1, self.space.dim())
372 }
373 }
374
375 fn amax_impl(&self) -> Number {
376 debug_assert!(self.initialized);
377 if self.space.dim() == 0 {
378 return 0.0;
379 }
380 if self.homogeneous {
381 return self.scalar.abs();
382 }
383 let i = blas1::iamax(&self.values, 1, self.space.dim()) as usize;
384 self.values[i].abs()
385 }
386
387 fn set_impl(&mut self, value: Number) {
388 self.initialized = true;
389 self.homogeneous = true;
390 self.scalar = value;
391 self.values.clear();
393 self.values.shrink_to_fit();
394 }
395
396 fn element_wise_divide_impl(&mut self, x: &dyn Vector) {
397 debug_assert!(self.initialized);
398 let dx = downcast_dense(x);
399 debug_assert!(dx.initialized);
400 let n = self.space.dim() as usize;
401 if n == 0 {
402 return;
403 }
404 match (self.homogeneous, dx.homogeneous) {
405 (true, true) => self.scalar /= dx.scalar,
406 (true, false) => {
407 let s0 = self.scalar;
408 self.homogeneous = false;
409 self.ensure_storage();
410 for i in 0..n {
411 self.values[i] = s0 / dx.values[i];
412 }
413 }
414 (false, true) => {
415 for v in &mut self.values[..n] {
416 *v /= dx.scalar;
417 }
418 }
419 (false, false) => {
420 for i in 0..n {
421 self.values[i] /= dx.values[i];
422 }
423 }
424 }
425 }
426
427 fn element_wise_multiply_impl(&mut self, x: &dyn Vector) {
428 debug_assert!(self.initialized);
429 let dx = downcast_dense(x);
430 debug_assert!(dx.initialized);
431 let n = self.space.dim() as usize;
432 if n == 0 {
433 return;
434 }
435 match (self.homogeneous, dx.homogeneous) {
436 (true, true) => self.scalar *= dx.scalar,
437 (true, false) => {
438 let s0 = self.scalar;
439 self.homogeneous = false;
440 self.ensure_storage();
441 for i in 0..n {
442 self.values[i] = s0 * dx.values[i];
443 }
444 }
445 (false, true) => {
446 if dx.scalar != 1.0 {
447 for v in &mut self.values[..n] {
448 *v *= dx.scalar;
449 }
450 }
451 }
452 (false, false) => {
453 for i in 0..n {
454 self.values[i] *= dx.values[i];
455 }
456 }
457 }
458 }
459
460 fn element_wise_select_impl(&mut self, x: &dyn Vector) {
461 debug_assert!(self.initialized);
462 let dx = downcast_dense(x);
463 debug_assert!(dx.initialized);
464 let n = self.space.dim() as usize;
465 if n == 0 {
466 return;
467 }
468 if self.homogeneous {
469 if self.scalar == 0.0 {
470 return;
471 }
472 if dx.homogeneous {
473 self.scalar *= dx.scalar;
474 } else {
475 let s0 = self.scalar;
476 self.homogeneous = false;
477 self.ensure_storage();
478 for i in 0..n {
479 self.values[i] = s0 * dx.values[i];
480 }
481 }
482 } else if dx.homogeneous {
483 if dx.scalar != 1.0 {
484 for v in &mut self.values[..n] {
485 if *v > 0.0 {
486 *v = dx.scalar;
487 } else if *v < 0.0 {
488 *v = -dx.scalar;
489 }
490 }
491 }
492 } else {
493 for i in 0..n {
494 if self.values[i] > 0.0 {
495 self.values[i] = dx.values[i];
496 } else if self.values[i] < 0.0 {
497 self.values[i] = -dx.values[i];
498 }
499 }
500 }
501 }
502
503 fn element_wise_max_impl(&mut self, x: &dyn Vector) {
504 debug_assert!(self.initialized);
505 let dx = downcast_dense(x);
506 debug_assert!(dx.initialized);
507 let n = self.space.dim() as usize;
508 if n == 0 {
509 return;
510 }
511 match (self.homogeneous, dx.homogeneous) {
512 (true, true) => self.scalar = self.scalar.max(dx.scalar),
513 (true, false) => {
514 let s0 = self.scalar;
515 self.homogeneous = false;
516 self.ensure_storage();
517 for i in 0..n {
518 self.values[i] = s0.max(dx.values[i]);
519 }
520 }
521 (false, true) => {
522 for v in &mut self.values[..n] {
523 *v = (*v).max(dx.scalar);
524 }
525 }
526 (false, false) => {
527 for i in 0..n {
528 self.values[i] = self.values[i].max(dx.values[i]);
529 }
530 }
531 }
532 }
533
534 fn element_wise_min_impl(&mut self, x: &dyn Vector) {
535 debug_assert!(self.initialized);
536 let dx = downcast_dense(x);
537 debug_assert!(dx.initialized);
538 let n = self.space.dim() as usize;
539 if n == 0 {
540 return;
541 }
542 match (self.homogeneous, dx.homogeneous) {
543 (true, true) => self.scalar = self.scalar.min(dx.scalar),
544 (true, false) => {
545 let s0 = self.scalar;
546 self.homogeneous = false;
547 self.ensure_storage();
548 for i in 0..n {
549 self.values[i] = s0.min(dx.values[i]);
550 }
551 }
552 (false, true) => {
553 for v in &mut self.values[..n] {
554 *v = (*v).min(dx.scalar);
555 }
556 }
557 (false, false) => {
558 for i in 0..n {
559 self.values[i] = self.values[i].min(dx.values[i]);
560 }
561 }
562 }
563 }
564
565 fn element_wise_reciprocal_impl(&mut self) {
566 debug_assert!(self.initialized);
567 let n = self.space.dim() as usize;
568 if n == 0 {
569 return;
570 }
571 if self.homogeneous {
572 self.scalar = 1.0 / self.scalar;
573 } else {
574 for v in &mut self.values[..n] {
575 *v = 1.0 / *v;
576 }
577 }
578 }
579
580 fn element_wise_abs_impl(&mut self) {
581 debug_assert!(self.initialized);
582 if self.homogeneous {
583 self.scalar = self.scalar.abs();
584 } else {
585 for v in &mut self.values[..self.space.dim() as usize] {
586 *v = v.abs();
587 }
588 }
589 }
590
591 fn element_wise_sqrt_impl(&mut self) {
592 debug_assert!(self.initialized);
593 if self.homogeneous {
594 self.scalar = self.scalar.sqrt();
595 } else {
596 for v in &mut self.values[..self.space.dim() as usize] {
597 *v = v.sqrt();
598 }
599 }
600 }
601
602 fn element_wise_sgn_impl(&mut self) {
603 debug_assert!(self.initialized);
604 let sgn = |v: Number| -> Number {
605 if v > 0.0 {
606 1.0
607 } else if v < 0.0 {
608 -1.0
609 } else {
610 0.0
611 }
612 };
613 if self.homogeneous {
614 self.scalar = sgn(self.scalar);
615 } else {
616 for v in &mut self.values[..self.space.dim() as usize] {
617 *v = sgn(*v);
618 }
619 }
620 }
621
622 fn add_scalar_impl(&mut self, scalar: Number) {
623 debug_assert!(self.initialized);
624 if self.homogeneous {
625 self.scalar += scalar;
626 } else {
627 for v in &mut self.values[..self.space.dim() as usize] {
628 *v += scalar;
629 }
630 }
631 }
632
633 fn max_impl(&self) -> Number {
634 debug_assert!(self.initialized);
635 let n = self.space.dim() as usize;
636 if n == 0 {
637 return -Number::MAX;
638 }
639 if self.homogeneous {
640 return self.scalar;
641 }
642 let mut m = self.values[0];
643 for &v in &self.values[1..n] {
644 if v > m {
645 m = v;
646 }
647 }
648 m
649 }
650
651 fn min_impl(&self) -> Number {
652 debug_assert!(self.initialized);
653 let n = self.space.dim() as usize;
654 if n == 0 {
655 return Number::MAX;
656 }
657 if self.homogeneous {
658 return self.scalar;
659 }
660 let mut m = self.values[0];
661 for &v in &self.values[1..n] {
662 if v < m {
663 m = v;
664 }
665 }
666 m
667 }
668
669 fn sum_impl(&self) -> Number {
670 debug_assert!(self.initialized);
671 let n = self.space.dim() as usize;
672 if self.homogeneous {
673 (n as Number) * self.scalar
674 } else {
675 let mut s = 0.0;
676 for &v in &self.values[..n] {
677 s += v;
678 }
679 s
680 }
681 }
682
683 fn sum_logs_impl(&self) -> Number {
684 debug_assert!(self.initialized);
685 let n = self.space.dim() as usize;
686 if n == 0 {
687 return 0.0;
688 }
689 if self.homogeneous {
690 (n as Number) * self.scalar.ln()
691 } else {
692 let mut s = 0.0;
693 for &v in &self.values[..n] {
694 s += v.ln();
695 }
696 s
697 }
698 }
699
700 fn frac_to_bound_impl(&self, delta: &dyn Vector, tau: Number) -> Number {
701 debug_assert_eq!(self.space.dim(), delta.dim());
702 debug_assert!(tau >= 0.0);
703 let dd = downcast_dense(delta);
704 let n = self.space.dim() as usize;
705 if n == 0 {
706 return 1.0;
707 }
708 let mut alpha: Number = 1.0;
709 match (self.homogeneous, dd.homogeneous) {
710 (true, true) => {
711 if dd.scalar < 0.0 {
712 alpha = alpha.min(-tau / dd.scalar * self.scalar);
713 }
714 }
715 (true, false) => {
716 for &d in &dd.values[..n] {
717 if d < 0.0 {
718 alpha = alpha.min(-tau / d * self.scalar);
719 }
720 }
721 }
722 (false, true) => {
723 if dd.scalar < 0.0 {
724 let f = -tau / dd.scalar;
725 for &x in &self.values[..n] {
726 alpha = alpha.min(f * x);
727 }
728 }
729 }
730 (false, false) => {
731 for i in 0..n {
732 let d = dd.values[i];
733 if d < 0.0 {
734 alpha = alpha.min(-tau / d * self.values[i]);
735 }
736 }
737 }
738 }
739 debug_assert!(alpha >= 0.0);
740 alpha
741 }
742
743 fn add_two_vectors_impl(
744 &mut self,
745 a: Number,
746 v1: &dyn Vector,
747 b: Number,
748 v2: &dyn Vector,
749 c: Number,
750 ) {
751 let n = self.space.dim() as usize;
752 if n == 0 {
753 debug_assert!(self.initialized);
754 return;
755 }
756 let dv1 = if a != 0.0 {
757 Some(downcast_dense(v1))
758 } else {
759 None
760 };
761 let dv2 = if b != 0.0 {
762 Some(downcast_dense(v2))
763 } else {
764 None
765 };
766 let homog_v1 = dv1.map(|d| d.homogeneous).unwrap_or(true);
767 let homog_v2 = dv2.map(|d| d.homogeneous).unwrap_or(true);
768 let s_v1 = dv1.map(|d| d.scalar).unwrap_or(0.0);
769 let s_v2 = dv2.map(|d| d.scalar).unwrap_or(0.0);
770
771 if (c == 0.0 || self.homogeneous) && homog_v1 && homog_v2 {
773 let prev = if c == 0.0 { 0.0 } else { c * self.scalar };
774 self.scalar = prev + a * s_v1 + b * s_v2;
775 self.homogeneous = true;
776 self.initialized = true;
777 return;
778 }
779
780 if c == 0.0 {
782 self.ensure_storage();
783 self.homogeneous = false;
784 } else if self.homogeneous {
785 self.materialize_from_scalar();
786 }
787
788 let v1_arr: Option<Vec<Number>> = dv1.map(|d| {
791 if d.homogeneous {
792 vec![d.scalar; n]
793 } else {
794 d.values[..n].to_vec()
795 }
796 });
797 let v2_arr: Option<Vec<Number>> = dv2.map(|d| {
798 if d.homogeneous {
799 vec![d.scalar; n]
800 } else {
801 d.values[..n].to_vec()
802 }
803 });
804
805 if c == 0.0 {
809 for i in 0..n {
810 let v1i = v1_arr.as_ref().map(|v| v[i]).unwrap_or(0.0);
811 let v2i = v2_arr.as_ref().map(|v| v[i]).unwrap_or(0.0);
812 self.values[i] = a * v1i + b * v2i;
813 }
814 } else {
815 for i in 0..n {
816 let v1i = v1_arr.as_ref().map(|v| v[i]).unwrap_or(0.0);
817 let v2i = v2_arr.as_ref().map(|v| v[i]).unwrap_or(0.0);
818 self.values[i] = a * v1i + b * v2i + c * self.values[i];
819 }
820 }
821 self.initialized = true;
822 }
823
824 fn add_vector_quotient_impl(&mut self, a: Number, z: &dyn Vector, s: &dyn Vector, c: Number) {
825 debug_assert_eq!(self.space.dim(), z.dim());
826 debug_assert_eq!(self.space.dim(), s.dim());
827 let dz = downcast_dense(z);
828 let ds = downcast_dense(s);
829 debug_assert!(dz.initialized && ds.initialized);
830 let n = self.space.dim() as usize;
831 if n == 0 {
832 return;
833 }
834 let homog_z = dz.homogeneous;
835 let homog_s = ds.homogeneous;
836 if (c == 0.0 || self.homogeneous) && homog_z && homog_s {
837 self.scalar = if c == 0.0 {
838 a * dz.scalar / ds.scalar
839 } else {
840 c * self.scalar + a * dz.scalar / ds.scalar
841 };
842 self.initialized = true;
843 self.homogeneous = true;
844 self.values.clear();
845 return;
846 }
847 if c == 0.0 {
849 self.ensure_storage();
850 self.homogeneous = false;
851 } else if self.homogeneous {
852 self.materialize_from_scalar();
853 }
854 let z_arr: Vec<Number> = if homog_z {
855 vec![dz.scalar; n]
856 } else {
857 dz.values[..n].to_vec()
858 };
859 let s_arr: Vec<Number> = if homog_s {
860 vec![ds.scalar; n]
861 } else {
862 ds.values[..n].to_vec()
863 };
864 if c == 0.0 {
865 for i in 0..n {
866 self.values[i] = a * z_arr[i] / s_arr[i];
867 }
868 } else {
869 for i in 0..n {
870 self.values[i] = c * self.values[i] + a * z_arr[i] / s_arr[i];
871 }
872 }
873 self.initialized = true;
874 self.homogeneous = false;
875 }
876}
877
878#[cfg(test)]
879mod tests {
880 use super::*;
881
882 fn vec_of(space: &Rc<DenseVectorSpace>, vals: &[Number]) -> DenseVector {
883 let mut v = DenseVector::new(Rc::clone(space));
884 v.set_values(vals);
885 v
886 }
887
888 #[test]
889 fn axpy_basic() {
890 let s = DenseVectorSpace::new(3);
891 let x = vec_of(&s, &[1.0, 2.0, 3.0]);
892 let mut y = vec_of(&s, &[10.0, 20.0, 30.0]);
893 y.axpy(2.0, &x);
894 assert_eq!(y.values(), &[12.0, 24.0, 36.0]);
895 }
896
897 #[test]
898 fn dot_homogeneous_pair() {
899 let s = DenseVectorSpace::new(4);
900 let mut x = DenseVector::new(Rc::clone(&s));
901 x.set(2.0); let mut y = DenseVector::new(Rc::clone(&s));
903 y.set(3.0); assert_eq!(x.dot(&y), 24.0);
906 }
907
908 #[test]
909 fn dot_mixed_homog_dense() {
910 let s = DenseVectorSpace::new(3);
911 let mut x = DenseVector::new(Rc::clone(&s));
912 x.set(2.0);
913 let y = vec_of(&s, &[1.0, 2.0, 3.0]);
914 assert_eq!(x.dot(&y), 12.0);
916 assert_eq!(y.dot(&x), 12.0);
917 }
918
919 #[test]
920 fn nrm2_homogeneous_uses_sqrt_n() {
921 let s = DenseVectorSpace::new(4);
922 let mut x = DenseVector::new(Rc::clone(&s));
923 x.set(3.0);
924 assert!((x.nrm2() - 6.0).abs() < 1e-15);
926 }
927
928 #[test]
929 fn nrm2_cache_invalidated_by_mutation() {
930 let s = DenseVectorSpace::new(2);
931 let mut x = vec_of(&s, &[3.0, 4.0]);
932 assert_eq!(x.nrm2(), 5.0);
933 x.scal(2.0);
934 assert!((x.nrm2() - 10.0).abs() < 1e-15);
935 }
936
937 #[test]
938 fn dot_cache_hits_after_first_call() {
939 let s = DenseVectorSpace::new(3);
940 let x = vec_of(&s, &[1.0, 2.0, 3.0]);
941 let y = vec_of(&s, &[1.0, 1.0, 1.0]);
942 assert_eq!(x.dot(&y), 6.0);
943 assert_eq!(x.dot(&y), 6.0);
945 }
946
947 #[test]
948 fn dot_self_uses_nrm2_squared_path() {
949 let s = DenseVectorSpace::new(2);
950 let x = vec_of(&s, &[3.0, 4.0]);
951 assert_eq!(x.dot(&x), 25.0);
953 }
954
955 #[test]
956 fn add_two_vectors_all_homogeneous() {
957 let s = DenseVectorSpace::new(5);
958 let mut y = DenseVector::new(Rc::clone(&s));
959 y.set(1.0);
960 let mut v1 = DenseVector::new(Rc::clone(&s));
961 v1.set(2.0);
962 let mut v2 = DenseVector::new(Rc::clone(&s));
963 v2.set(3.0);
964 y.add_two_vectors(4.0, &v1, 5.0, &v2, 0.5);
966 assert!(y.is_homogeneous());
967 assert_eq!(y.scalar(), 23.5);
968 }
969
970 #[test]
971 fn add_two_vectors_mixed_dense_overrides_homog() {
972 let s = DenseVectorSpace::new(3);
973 let mut y = DenseVector::new(Rc::clone(&s));
974 y.set(0.0);
975 let v1 = vec_of(&s, &[1.0, 2.0, 3.0]);
976 let v2 = vec_of(&s, &[10.0, 10.0, 10.0]);
977 y.add_two_vectors(1.0, &v1, 1.0, &v2, 0.0);
979 assert!(!y.is_homogeneous());
980 assert_eq!(y.values(), &[11.0, 12.0, 13.0]);
981 }
982
983 #[test]
984 fn frac_to_bound_basic() {
985 let s = DenseVectorSpace::new(3);
986 let x = vec_of(&s, &[1.0, 2.0, 3.0]);
987 let delta = vec_of(&s, &[-2.0, 1.0, -1.5]);
988 let alpha = x.frac_to_bound(&delta, 1.0);
992 assert!((alpha - 0.5).abs() < 1e-15);
993 }
994
995 #[test]
996 fn element_wise_divide_homog_dense() {
997 let s = DenseVectorSpace::new(3);
998 let mut y = DenseVector::new(Rc::clone(&s));
999 y.set(6.0);
1000 let x = vec_of(&s, &[1.0, 2.0, 3.0]);
1001 y.element_wise_divide(&x);
1002 assert!(!y.is_homogeneous());
1003 assert_eq!(y.values(), &[6.0, 3.0, 2.0]);
1004 }
1005
1006 #[test]
1007 fn element_wise_sgn_handles_all_three_signs() {
1008 let s = DenseVectorSpace::new(3);
1009 let mut x = vec_of(&s, &[-2.5, 0.0, 7.0]);
1010 x.element_wise_sgn();
1011 assert_eq!(x.values(), &[-1.0, 0.0, 1.0]);
1012 }
1013
1014 #[test]
1015 fn sum_and_max_min_homogeneous() {
1016 let s = DenseVectorSpace::new(4);
1017 let mut x = DenseVector::new(Rc::clone(&s));
1018 x.set(2.5);
1019 assert_eq!(x.sum(), 10.0);
1020 assert_eq!(x.max(), 2.5);
1021 assert_eq!(x.min(), 2.5);
1022 }
1023
1024 #[test]
1025 fn has_valid_numbers_detects_nan() {
1026 let s = DenseVectorSpace::new(3);
1027 let bad = vec_of(&s, &[1.0, Number::NAN, 2.0]);
1028 assert!(!bad.has_valid_numbers());
1029 let good = vec_of(&s, &[1.0, 2.0, 3.0]);
1030 assert!(good.has_valid_numbers());
1031 }
1032
1033 #[test]
1034 fn copy_to_pos_pastes_into_subrange() {
1035 let s_big = DenseVectorSpace::new(5);
1036 let s_small = DenseVectorSpace::new(2);
1037 let mut y = DenseVector::new(Rc::clone(&s_big));
1038 y.set(0.0);
1039 let x = vec_of(&s_small, &[7.0, 8.0]);
1040 y.copy_to_pos(2, &x);
1041 assert_eq!(y.values(), &[0.0, 0.0, 7.0, 8.0, 0.0]);
1042 }
1043
1044 #[test]
1045 fn make_new_copy_clones_values() {
1046 let s = DenseVectorSpace::new(3);
1047 let x = vec_of(&s, &[1.0, 2.0, 3.0]);
1048 let y = x.make_new_copy();
1049 let dy = y.as_any().downcast_ref::<DenseVector>().unwrap();
1050 assert_eq!(dy.values(), &[1.0, 2.0, 3.0]);
1051 }
1052
1053 #[test]
1054 fn add_vector_quotient_all_homogeneous() {
1055 let s = DenseVectorSpace::new(4);
1056 let mut y = DenseVector::new(Rc::clone(&s));
1057 y.set(1.0);
1058 let mut z = DenseVector::new(Rc::clone(&s));
1059 z.set(6.0);
1060 let mut sd = DenseVector::new(Rc::clone(&s));
1061 sd.set(2.0);
1062 y.add_vector_quotient(2.0, &z, &sd, 0.5);
1064 assert!(y.is_homogeneous());
1065 assert_eq!(y.scalar(), 6.5);
1066 }
1067
1068 #[test]
1069 fn dim_zero_is_consistent() {
1070 let s = DenseVectorSpace::new(0);
1071 let x = DenseVector::new(Rc::clone(&s));
1072 assert!(x.is_initialized());
1073 assert!(x.is_homogeneous());
1074 assert_eq!(x.nrm2(), 0.0);
1075 }
1076}