comparison src/DLD-FUNCTIONS/sparse.cc @ 7515:f3c00dc0912b

Eliminate the rest of the dispatched sparse functions
author David Bateman <dbateman@free.fr>
date Fri, 22 Feb 2008 15:50:51 +0100
parents f5005d9510f4
children 8a42498edb30
comparison
equal deleted inserted replaced
7514:4f6a73fd8df9 7515:f3c00dc0912b
36 #include "quit.h" 36 #include "quit.h"
37 37
38 #include "ov-re-sparse.h" 38 #include "ov-re-sparse.h"
39 #include "ov-cx-sparse.h" 39 #include "ov-cx-sparse.h"
40 #include "ov-bool-sparse.h" 40 #include "ov-bool-sparse.h"
41
42 static bool
43 is_sparse (const octave_value& arg)
44 {
45 return (arg.is_sparse_type ());
46 }
47 41
48 DEFUN_DLD (issparse, args, , 42 DEFUN_DLD (issparse, args, ,
49 "-*- texinfo -*-\n\ 43 "-*- texinfo -*-\n\
50 @deftypefn {Loadable Function} {} issparse (@var{expr})\n\ 44 @deftypefn {Loadable Function} {} issparse (@var{expr})\n\
51 Return 1 if the value of the expression @var{expr} is a sparse matrix.\n\ 45 Return 1 if the value of the expression @var{expr} is a sparse matrix.\n\
55 { 49 {
56 print_usage (); 50 print_usage ();
57 return octave_value (); 51 return octave_value ();
58 } 52 }
59 else 53 else
60 return octave_value (is_sparse (args(0))); 54 return octave_value (args(0).is_sparse_type ());
61 } 55 }
62 56
63 DEFUN_DLD (sparse, args, , 57 DEFUN_DLD (sparse, args, ,
64 "-*- texinfo -*-\n\ 58 "-*- texinfo -*-\n\
65 @deftypefn {Loadable Function} {@var{s} =} sparse (@var{a})\n\ 59 @deftypefn {Loadable Function} {@var{s} =} sparse (@var{a})\n\
130 124
131 if (nargin == 1) 125 if (nargin == 1)
132 { 126 {
133 octave_value arg = args (0); 127 octave_value arg = args (0);
134 128
135 if (is_sparse (arg)) 129 if (arg.is_sparse_type ())
136 { 130 {
137 if (use_complex) 131 if (use_complex)
138 { 132 {
139 SparseComplexMatrix sm = arg.sparse_complex_matrix_value (); 133 SparseComplexMatrix sm = arg.sparse_complex_matrix_value ();
140 retval = new octave_sparse_complex_matrix (sm); 134 retval = new octave_sparse_complex_matrix (sm);
385 gripe_wrong_type_arg ("full", args(0)); 379 gripe_wrong_type_arg ("full", args(0));
386 380
387 return retval; 381 return retval;
388 } 382 }
389 383
390 #define SPARSE_DIM_ARG_BODY(NAME, FUNC) \
391 int nargin = args.length(); \
392 octave_value retval; \
393 if ((nargin != 1 ) && (nargin != 2)) \
394 print_usage (); \
395 else { \
396 int dim = (nargin == 1 ? -1 : args(1).int_value(true) - 1); \
397 if (error_state) return retval; \
398 if (dim < -1 || dim > 1) { \
399 error (#NAME ": invalid dimension argument = %d", dim + 1); \
400 return retval; \
401 } \
402 if (args(0).type_id () == \
403 octave_sparse_matrix::static_type_id () || args(0).type_id () == \
404 octave_sparse_bool_matrix::static_type_id ()) { \
405 retval = args(0).sparse_matrix_value () .FUNC (dim); \
406 } else if (args(0).type_id () == \
407 octave_sparse_complex_matrix::static_type_id ()) { \
408 retval = args(0).sparse_complex_matrix_value () .FUNC (dim); \
409 } else \
410 print_usage (); \
411 } \
412 return retval
413
414 // PKG_ADD: dispatch ("prod", "spprod", "sparse matrix");
415 // PKG_ADD: dispatch ("prod", "spprod", "sparse complex matrix");
416 // PKG_ADD: dispatch ("prod", "spprod", "sparse bool matrix");
417 DEFUN_DLD (spprod, args, ,
418 "-*- texinfo -*-\n\
419 @deftypefn {Loadable Function} {@var{y} =} spprod (@var{x},@var{dim})\n\
420 Product of elements along dimension @var{dim}. If @var{dim} is omitted,\n\
421 it defaults to 1 (column-wise products).\n\
422 @seealso{spsum, spsumsq}\n\
423 @end deftypefn")
424 {
425 SPARSE_DIM_ARG_BODY (spprod, prod);
426 }
427
428 // PKG_ADD: dispatch ("cumprod", "spcumprod", "sparse matrix");
429 // PKG_ADD: dispatch ("cumprod", "spcumprod", "sparse complex matrix");
430 // PKG_ADD: dispatch ("cumprod", "spcumprod", "sparse bool matrix");
431 DEFUN_DLD (spcumprod, args, ,
432 "-*- texinfo -*-\n\
433 @deftypefn {Loadable Function} {@var{y} =} spcumprod (@var{x},@var{dim})\n\
434 Cumulative product of elements along dimension @var{dim}. If @var{dim}\n\
435 is omitted, it defaults to 1 (column-wise cumulative products).\n\
436 @seealso{spcumsum}\n\
437 @end deftypefn")
438 {
439 SPARSE_DIM_ARG_BODY (spcumprod, cumprod);
440 }
441
442 // PKG_ADD: dispatch ("sum", "spsum", "sparse matrix");
443 // PKG_ADD: dispatch ("sum", "spsum", "sparse complex matrix");
444 // PKG_ADD: dispatch ("sum", "spsum", "sparse bool matrix");
445 DEFUN_DLD (spsum, args, ,
446 "-*- texinfo -*-\n\
447 @deftypefn {Loadable Function} {@var{y} =} spsum (@var{x},@var{dim})\n\
448 Sum of elements along dimension @var{dim}. If @var{dim} is omitted, it\n\
449 defaults to 1 (column-wise sum).\n\
450 @seealso{spprod, spsumsq}\n\
451 @end deftypefn")
452 {
453 SPARSE_DIM_ARG_BODY (spsum, sum);
454 }
455
456 // PKG_ADD: dispatch ("cumsum", "spcumsum", "sparse matrix");
457 // PKG_ADD: dispatch ("cumsum", "spcumsum", "sparse complex matrix");
458 // PKG_ADD: dispatch ("cumsum", "spcumsum", "sparse bool matrix");
459 DEFUN_DLD (spcumsum, args, ,
460 "-*- texinfo -*-\n\
461 @deftypefn {Loadable Function} {@var{y} =} spcumsum (@var{x},@var{dim})\n\
462 Cumulative sum of elements along dimension @var{dim}. If @var{dim}\n\
463 is omitted, it defaults to 1 (column-wise cumulative sums).\n\
464 @seealso{spcumprod}\n\
465 @end deftypefn")
466 {
467 SPARSE_DIM_ARG_BODY (spcumsum, cumsum);
468 }
469
470 // PKG_ADD: dispatch ("sumsq", "spsumsq", "sparse matrix");
471 // PKG_ADD: dispatch ("sumsq", "spsumsq", "sparse complex matrix");
472 // PKG_ADD: dispatch ("sumsq", "spsumsq", "sparse bool matrix");
473 DEFUN_DLD (spsumsq, args, ,
474 "-*- texinfo -*-\n\
475 @deftypefn {Loadable Function} {@var{y} =} spsumsq (@var{x},@var{dim})\n\
476 Sum of squares of elements along dimension @var{dim}. If @var{dim}\n\
477 is omitted, it defaults to 1 (column-wise sum of squares).\n\
478 This function is equivalent to computing\n\
479 @example\n\
480 spsum (x .* spconj (x), dim)\n\
481 @end example\n\
482 but it uses less memory and avoids calling @code{spconj} if @var{x} is\n\
483 real.\n\
484 @seealso{spprod, spsum}\n\
485 @end deftypefn")
486 {
487 SPARSE_DIM_ARG_BODY (spsumsq, sumsq);
488 }
489
490
491 static octave_value
492 make_spdiag (const octave_value& a, const octave_value& b)
493 {
494 octave_value retval;
495
496 if (a.is_complex_type ())
497 {
498 SparseComplexMatrix m = a.sparse_complex_matrix_value ();
499 octave_idx_type k = b.nint_value(true);
500
501 if (error_state)
502 return retval;
503
504 octave_idx_type nr = m.rows ();
505 octave_idx_type nc = m.columns ();
506
507 if (nr == 0 || nc == 0)
508 retval = m;
509 else if (nr == 1 || nc == 1)
510 {
511 octave_idx_type roff = 0;
512 octave_idx_type coff = 0;
513 if (k > 0)
514 {
515 roff = 0;
516 coff = k;
517 }
518 else if (k < 0)
519 {
520 k = -k;
521 roff = k;
522 coff = 0;
523 }
524
525 if (nr == 1)
526 {
527 octave_idx_type n = nc + k;
528 octave_idx_type nz = m.nzmax ();
529 SparseComplexMatrix r (n, n, nz);
530 for (octave_idx_type i = 0; i < coff+1; i++)
531 r.xcidx (i) = 0;
532 for (octave_idx_type j = 0; j < nc; j++)
533 {
534 for (octave_idx_type i = m.cidx(j); i < m.cidx(j+1); i++)
535 {
536 r.xdata (i) = m.data (i);
537 r.xridx (i) = j + roff;
538 }
539 r.xcidx (j+coff+1) = m.cidx(j+1);
540 }
541 for (octave_idx_type i = nc+coff+1; i < n+1; i++)
542 r.xcidx (i) = nz;
543 retval = r;
544 }
545 else
546 {
547 octave_idx_type n = nr + k;
548 octave_idx_type nz = m.nzmax ();
549 octave_idx_type ii = 0;
550 octave_idx_type ir = m.ridx(0);
551 SparseComplexMatrix r (n, n, nz);
552 for (octave_idx_type i = 0; i < coff+1; i++)
553 r.xcidx (i) = 0;
554 for (octave_idx_type i = 0; i < nr; i++)
555 {
556 if (ir == i)
557 {
558 r.xdata (ii) = m.data (ii);
559 r.xridx (ii++) = ir + roff;
560 if (ii != nz)
561 ir = m.ridx (ii);
562 }
563 r.xcidx (i+coff+1) = ii;
564 }
565 for (octave_idx_type i = nr+coff+1; i < n+1; i++)
566 r.xcidx (i) = nz;
567 retval = r;
568 }
569 }
570 else
571 {
572 SparseComplexMatrix r = m.diag (k);
573 // Don't use numel, since it can overflow for very large matrices
574 if (r.rows () > 0 && r.cols () > 0)
575 retval = r;
576 }
577 }
578 else if (a.is_real_type ())
579 {
580 SparseMatrix m = a.sparse_matrix_value ();
581
582 octave_idx_type k = b.nint_value(true);
583
584 if (error_state)
585 return retval;
586
587 octave_idx_type nr = m.rows ();
588 octave_idx_type nc = m.columns ();
589
590 if (nr == 0 || nc == 0)
591 retval = m;
592 else if (nr == 1 || nc == 1)
593 {
594 octave_idx_type roff = 0;
595 octave_idx_type coff = 0;
596 if (k > 0)
597 {
598 roff = 0;
599 coff = k;
600 }
601 else if (k < 0)
602 {
603 k = -k;
604 roff = k;
605 coff = 0;
606 }
607
608 if (nr == 1)
609 {
610 octave_idx_type n = nc + k;
611 octave_idx_type nz = m.nzmax ();
612 SparseMatrix r (n, n, nz);
613
614 for (octave_idx_type i = 0; i < coff+1; i++)
615 r.xcidx (i) = 0;
616 for (octave_idx_type j = 0; j < nc; j++)
617 {
618 for (octave_idx_type i = m.cidx(j); i < m.cidx(j+1); i++)
619 {
620 r.xdata (i) = m.data (i);
621 r.xridx (i) = j + roff;
622 }
623 r.xcidx (j+coff+1) = m.cidx(j+1);
624 }
625 for (octave_idx_type i = nc+coff+1; i < n+1; i++)
626 r.xcidx (i) = nz;
627 retval = r;
628 }
629 else
630 {
631 octave_idx_type n = nr + k;
632 octave_idx_type nz = m.nzmax ();
633 octave_idx_type ii = 0;
634 octave_idx_type ir = m.ridx(0);
635 SparseMatrix r (n, n, nz);
636 for (octave_idx_type i = 0; i < coff+1; i++)
637 r.xcidx (i) = 0;
638 for (octave_idx_type i = 0; i < nr; i++)
639 {
640 if (ir == i)
641 {
642 r.xdata (ii) = m.data (ii);
643 r.xridx (ii++) = ir + roff;
644 if (ii != nz)
645 ir = m.ridx (ii);
646 }
647 r.xcidx (i+coff+1) = ii;
648 }
649 for (octave_idx_type i = nr+coff+1; i < n+1; i++)
650 r.xcidx (i) = nz;
651 retval = r;
652 }
653 }
654 else
655 {
656 SparseMatrix r = m.diag (k);
657 if (r.rows () > 0 && r.cols () > 0)
658 retval = r;
659 }
660 }
661 else
662 gripe_wrong_type_arg ("spdiag", a);
663
664 return retval;
665 }
666
667 static octave_value
668 make_spdiag (const octave_value& a)
669 {
670 octave_value retval;
671 octave_idx_type nr = a.rows ();
672 octave_idx_type nc = a.columns ();
673
674 if (nr == 0 || nc == 0)
675 retval = SparseMatrix ();
676 else
677 retval = make_spdiag (a, octave_value (0.));
678
679 return retval;
680 }
681
682 // PKG_ADD: dispatch ("diag", "spdiag", "sparse matrix");
683 // PKG_ADD: dispatch ("diag", "spdiag", "sparse complex matrix");
684 // PKG_ADD: dispatch ("diag", "spdiag", "sparse bool matrix");
685 DEFUN_DLD (spdiag, args, ,
686 "-*- texinfo -*-\n\
687 @deftypefn {Loadable Function} {} spdiag (@var{v}, @var{k})\n\
688 Return a diagonal matrix with the sparse vector @var{v} on diagonal\n\
689 @var{k}. The second argument is optional. If it is positive, the vector is\n\
690 placed on the @var{k}-th super-diagonal. If it is negative, it is placed\n\
691 on the @var{-k}-th sub-diagonal. The default value of @var{k} is 0, and\n\
692 the vector is placed on the main diagonal. For example,\n\
693 \n\
694 @example\n\
695 @group\n\
696 spdiag ([1, 2, 3], 1)\n\
697 ans =\n\
698 \n\
699 Compressed Column Sparse (rows=4, cols=4, nnz=3)\n\
700 (1 , 2) -> 1\n\
701 (2 , 3) -> 2\n\
702 (3 , 4) -> 3\n\
703 @end group\n\
704 @end example\n\
705 \n\
706 @noindent\n\
707 Given a matrix argument, instead of a vector, @code{spdiag} extracts the\n\
708 @var{k}-th diagonal of the sparse matrix.\n\
709 @seealso{diag}\n\
710 @end deftypefn")
711 {
712 octave_value retval;
713
714 int nargin = args.length ();
715
716 if (nargin == 1 && args(0).is_defined ())
717 retval = make_spdiag (args(0));
718 else if (nargin == 2 && args(0).is_defined () && args(1).is_defined ())
719 retval = make_spdiag (args(0), args(1));
720 else
721 print_usage ();
722
723 return retval;
724 }
725
726 /* 384 /*
727 ;;; Local Variables: *** 385 ;;; Local Variables: ***
728 ;;; mode: C++ *** 386 ;;; mode: C++ ***
729 ;;; End: *** 387 ;;; End: ***
730 */ 388 */