GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
xdiv.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1993-2013 John W. Eaton
4 Copyright (C) 2008 Jaroslav Hajek
5 Copyright (C) 2009-2010 VZLU Prague
6 
7 This file is part of Octave.
8 
9 Octave is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 3 of the License, or (at your
12 option) any later version.
13 
14 Octave is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Octave; see the file COPYING. If not, see
21 <http://www.gnu.org/licenses/>.
22 
23 */
24 
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28 
29 #include <cassert>
30 
31 #include "Array-util.h"
32 #include "CMatrix.h"
33 #include "dMatrix.h"
34 #include "CNDArray.h"
35 #include "dNDArray.h"
36 #include "fCMatrix.h"
37 #include "fMatrix.h"
38 #include "fCNDArray.h"
39 #include "fNDArray.h"
40 #include "oct-cmplx.h"
41 #include "dDiagMatrix.h"
42 #include "fDiagMatrix.h"
43 #include "CDiagMatrix.h"
44 #include "fCDiagMatrix.h"
45 #include "quit.h"
46 
47 #include "error.h"
48 #include "xdiv.h"
49 
50 static inline bool
52 {
53  assert (info != -1);
54 
55  return (info != -2);
56 }
57 
58 static void
60 {
61  warning_with_id ("Octave:singular-matrix-div",
62  "matrix singular to machine precision, rcond = %g", rcond);
63 }
64 
65 template <class T1, class T2>
66 bool
67 mx_leftdiv_conform (const T1& a, const T2& b, blas_trans_type blas_trans)
68 {
69  octave_idx_type a_nr = blas_trans == blas_no_trans ? a.rows () : a.cols ();
70  octave_idx_type b_nr = b.rows ();
71 
72  if (a_nr != b_nr)
73  {
74  octave_idx_type a_nc = blas_trans == blas_no_trans ? a.cols ()
75  : a.rows ();
76  octave_idx_type b_nc = b.cols ();
77 
78  gripe_nonconformant ("operator \\", a_nr, a_nc, b_nr, b_nc);
79  return false;
80  }
81 
82  return true;
83 }
84 
85 #define INSTANTIATE_MX_LEFTDIV_CONFORM(T1, T2) \
86  template bool mx_leftdiv_conform (const T1&, const T2&, blas_trans_type)
87 
92 
93 template <class T1, class T2>
94 bool
95 mx_div_conform (const T1& a, const T2& b)
96 {
97  octave_idx_type a_nc = a.cols ();
98  octave_idx_type b_nc = b.cols ();
99 
100  if (a_nc != b_nc)
101  {
102  octave_idx_type a_nr = a.rows ();
103  octave_idx_type b_nr = b.rows ();
104 
105  gripe_nonconformant ("operator /", a_nr, a_nc, b_nr, b_nc);
106  return false;
107  }
108 
109  return true;
110 }
111 
112 #define INSTANTIATE_MX_DIV_CONFORM(T1, T2) \
113  template bool mx_div_conform (const T1&, const T2&)
114 
119 
120 // Right division functions.
121 //
122 // op2 / op1: m cm
123 // +-- +---+----+
124 // matrix | 1 | 3 |
125 // +---+----+
126 // complex_matrix | 2 | 4 |
127 // +---+----+
128 
129 // -*- 1 -*-
130 Matrix
131 xdiv (const Matrix& a, const Matrix& b, MatrixType &typ)
132 {
133  if (! mx_div_conform (a, b))
134  return Matrix ();
135 
136  octave_idx_type info;
137  double rcond = 0.0;
138 
139  Matrix result
140  = b.solve (typ, a.transpose (), info, rcond,
142 
143  return result.transpose ();
144 }
145 
146 // -*- 2 -*-
148 xdiv (const Matrix& a, const ComplexMatrix& b, MatrixType &typ)
149 {
150  if (! mx_div_conform (a, b))
151  return ComplexMatrix ();
152 
153  octave_idx_type info;
154  double rcond = 0.0;
155 
156  ComplexMatrix result
157  = b.solve (typ, a.transpose (), info, rcond,
159 
160  return result.transpose ();
161 }
162 
163 // -*- 3 -*-
165 xdiv (const ComplexMatrix& a, const Matrix& b, MatrixType &typ)
166 {
167  if (! mx_div_conform (a, b))
168  return ComplexMatrix ();
169 
170  octave_idx_type info;
171  double rcond = 0.0;
172 
173  ComplexMatrix result
174  = b.solve (typ, a.transpose (), info, rcond,
176 
177  return result.transpose ();
178 }
179 
180 // -*- 4 -*-
182 xdiv (const ComplexMatrix& a, const ComplexMatrix& b, MatrixType &typ)
183 {
184  if (! mx_div_conform (a, b))
185  return ComplexMatrix ();
186 
187  octave_idx_type info;
188  double rcond = 0.0;
189 
190  ComplexMatrix result
191  = b.solve (typ, a.transpose (), info, rcond,
193 
194  return result.transpose ();
195 }
196 
197 // Funny element by element division operations.
198 //
199 // op2 \ op1: s cs
200 // +-- +---+----+
201 // matrix | 1 | 3 |
202 // +---+----+
203 // complex_matrix | 2 | 4 |
204 // +---+----+
205 
206 Matrix
207 x_el_div (double a, const Matrix& b)
208 {
209  octave_idx_type nr = b.rows ();
210  octave_idx_type nc = b.columns ();
211 
212  Matrix result (nr, nc);
213 
214  for (octave_idx_type j = 0; j < nc; j++)
215  for (octave_idx_type i = 0; i < nr; i++)
216  {
217  octave_quit ();
218  result (i, j) = a / b (i, j);
219  }
220 
221  return result;
222 }
223 
225 x_el_div (double a, const ComplexMatrix& b)
226 {
227  octave_idx_type nr = b.rows ();
228  octave_idx_type nc = b.columns ();
229 
230  ComplexMatrix result (nr, nc);
231 
232  for (octave_idx_type j = 0; j < nc; j++)
233  for (octave_idx_type i = 0; i < nr; i++)
234  {
235  octave_quit ();
236  result (i, j) = a / b (i, j);
237  }
238 
239  return result;
240 }
241 
243 x_el_div (const Complex a, const Matrix& b)
244 {
245  octave_idx_type nr = b.rows ();
246  octave_idx_type nc = b.columns ();
247 
248  ComplexMatrix result (nr, nc);
249 
250  for (octave_idx_type j = 0; j < nc; j++)
251  for (octave_idx_type i = 0; i < nr; i++)
252  {
253  octave_quit ();
254  result (i, j) = a / b (i, j);
255  }
256 
257  return result;
258 }
259 
261 x_el_div (const Complex a, const ComplexMatrix& b)
262 {
263  octave_idx_type nr = b.rows ();
264  octave_idx_type nc = b.columns ();
265 
266  ComplexMatrix result (nr, nc);
267 
268  for (octave_idx_type j = 0; j < nc; j++)
269  for (octave_idx_type i = 0; i < nr; i++)
270  {
271  octave_quit ();
272  result (i, j) = a / b (i, j);
273  }
274 
275  return result;
276 }
277 
278 // Funny element by element division operations.
279 //
280 // op2 \ op1: s cs
281 // +-- +---+----+
282 // N-d array | 1 | 3 |
283 // +---+----+
284 // complex N-d array | 2 | 4 |
285 // +---+----+
286 
287 NDArray
288 x_el_div (double a, const NDArray& b)
289 {
290  NDArray result (b.dims ());
291 
292  for (octave_idx_type i = 0; i < b.length (); i++)
293  {
294  octave_quit ();
295  result (i) = a / b (i);
296  }
297 
298  return result;
299 }
300 
302 x_el_div (double a, const ComplexNDArray& b)
303 {
304  ComplexNDArray result (b.dims ());
305 
306  for (octave_idx_type i = 0; i < b.length (); i++)
307  {
308  octave_quit ();
309  result (i) = a / b (i);
310  }
311 
312  return result;
313 }
314 
316 x_el_div (const Complex a, const NDArray& b)
317 {
318  ComplexNDArray result (b.dims ());
319 
320  for (octave_idx_type i = 0; i < b.length (); i++)
321  {
322  octave_quit ();
323  result (i) = a / b (i);
324  }
325 
326  return result;
327 }
328 
330 x_el_div (const Complex a, const ComplexNDArray& b)
331 {
332  ComplexNDArray result (b.dims ());
333 
334  for (octave_idx_type i = 0; i < b.length (); i++)
335  {
336  octave_quit ();
337  result (i) = a / b (i);
338  }
339 
340  return result;
341 }
342 
343 // Left division functions.
344 //
345 // op2 \ op1: m cm
346 // +-- +---+----+
347 // matrix | 1 | 3 |
348 // +---+----+
349 // complex_matrix | 2 | 4 |
350 // +---+----+
351 
352 // -*- 1 -*-
353 Matrix
354 xleftdiv (const Matrix& a, const Matrix& b, MatrixType &typ,
355  blas_trans_type transt)
356 {
357  if (! mx_leftdiv_conform (a, b, transt))
358  return Matrix ();
359 
360  octave_idx_type info;
361  double rcond = 0.0;
362  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);
363 }
364 
365 // -*- 2 -*-
367 xleftdiv (const Matrix& a, const ComplexMatrix& b, MatrixType &typ,
368  blas_trans_type transt)
369 {
370  if (! mx_leftdiv_conform (a, b, transt))
371  return ComplexMatrix ();
372 
373  octave_idx_type info;
374  double rcond = 0.0;
375 
376  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);
377 }
378 
379 // -*- 3 -*-
381 xleftdiv (const ComplexMatrix& a, const Matrix& b, MatrixType &typ,
382  blas_trans_type transt)
383 {
384  if (! mx_leftdiv_conform (a, b, transt))
385  return ComplexMatrix ();
386 
387  octave_idx_type info;
388  double rcond = 0.0;
389  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);
390 }
391 
392 // -*- 4 -*-
394 xleftdiv (const ComplexMatrix& a, const ComplexMatrix& b, MatrixType &typ,
395  blas_trans_type transt)
396 {
397  if (! mx_leftdiv_conform (a, b, transt))
398  return ComplexMatrix ();
399 
400  octave_idx_type info;
401  double rcond = 0.0;
402  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);
403 }
404 
405 static void
407 {
408  warning ("matrix singular to machine precision, rcond = %g", rcond);
409  warning ("attempting to find minimum norm solution");
410 }
411 
416 
421 
422 // Right division functions.
423 //
424 // op2 / op1: m cm
425 // +-- +---+----+
426 // matrix | 1 | 3 |
427 // +---+----+
428 // complex_matrix | 2 | 4 |
429 // +---+----+
430 
431 // -*- 1 -*-
433 xdiv (const FloatMatrix& a, const FloatMatrix& b, MatrixType &typ)
434 {
435  if (! mx_div_conform (a, b))
436  return FloatMatrix ();
437 
438  octave_idx_type info;
439  float rcond = 0.0;
440 
441  FloatMatrix result
442  = b.solve (typ, a.transpose (), info, rcond,
444 
445  return result.transpose ();
446 }
447 
448 // -*- 2 -*-
450 xdiv (const FloatMatrix& a, const FloatComplexMatrix& b, MatrixType &typ)
451 {
452  if (! mx_div_conform (a, b))
453  return FloatComplexMatrix ();
454 
455  octave_idx_type info;
456  float rcond = 0.0;
457 
458  FloatComplexMatrix result
459  = b.solve (typ, a.transpose (), info, rcond,
461 
462  return result.transpose ();
463 }
464 
465 // -*- 3 -*-
467 xdiv (const FloatComplexMatrix& a, const FloatMatrix& b, MatrixType &typ)
468 {
469  if (! mx_div_conform (a, b))
470  return FloatComplexMatrix ();
471 
472  octave_idx_type info;
473  float rcond = 0.0;
474 
475  FloatComplexMatrix result
476  = b.solve (typ, a.transpose (), info, rcond,
478 
479  return result.transpose ();
480 }
481 
482 // -*- 4 -*-
485 {
486  if (! mx_div_conform (a, b))
487  return FloatComplexMatrix ();
488 
489  octave_idx_type info;
490  float rcond = 0.0;
491 
492  FloatComplexMatrix result
493  = b.solve (typ, a.transpose (), info, rcond,
495 
496  return result.transpose ();
497 }
498 
499 // Funny element by element division operations.
500 //
501 // op2 \ op1: s cs
502 // +-- +---+----+
503 // matrix | 1 | 3 |
504 // +---+----+
505 // complex_matrix | 2 | 4 |
506 // +---+----+
507 
509 x_el_div (float a, const FloatMatrix& b)
510 {
511  octave_idx_type nr = b.rows ();
512  octave_idx_type nc = b.columns ();
513 
514  FloatMatrix result (nr, nc);
515 
516  for (octave_idx_type j = 0; j < nc; j++)
517  for (octave_idx_type i = 0; i < nr; i++)
518  {
519  octave_quit ();
520  result (i, j) = a / b (i, j);
521  }
522 
523  return result;
524 }
525 
527 x_el_div (float a, const FloatComplexMatrix& b)
528 {
529  octave_idx_type nr = b.rows ();
530  octave_idx_type nc = b.columns ();
531 
532  FloatComplexMatrix result (nr, nc);
533 
534  for (octave_idx_type j = 0; j < nc; j++)
535  for (octave_idx_type i = 0; i < nr; i++)
536  {
537  octave_quit ();
538  result (i, j) = a / b (i, j);
539  }
540 
541  return result;
542 }
543 
545 x_el_div (const FloatComplex a, const FloatMatrix& b)
546 {
547  octave_idx_type nr = b.rows ();
548  octave_idx_type nc = b.columns ();
549 
550  FloatComplexMatrix result (nr, nc);
551 
552  for (octave_idx_type j = 0; j < nc; j++)
553  for (octave_idx_type i = 0; i < nr; i++)
554  {
555  octave_quit ();
556  result (i, j) = a / b (i, j);
557  }
558 
559  return result;
560 }
561 
564 {
565  octave_idx_type nr = b.rows ();
566  octave_idx_type nc = b.columns ();
567 
568  FloatComplexMatrix result (nr, nc);
569 
570  for (octave_idx_type j = 0; j < nc; j++)
571  for (octave_idx_type i = 0; i < nr; i++)
572  {
573  octave_quit ();
574  result (i, j) = a / b (i, j);
575  }
576 
577  return result;
578 }
579 
580 // Funny element by element division operations.
581 //
582 // op2 \ op1: s cs
583 // +-- +---+----+
584 // N-d array | 1 | 3 |
585 // +---+----+
586 // complex N-d array | 2 | 4 |
587 // +---+----+
588 
590 x_el_div (float a, const FloatNDArray& b)
591 {
592  FloatNDArray result (b.dims ());
593 
594  for (octave_idx_type i = 0; i < b.length (); i++)
595  {
596  octave_quit ();
597  result (i) = a / b (i);
598  }
599 
600  return result;
601 }
602 
604 x_el_div (float a, const FloatComplexNDArray& b)
605 {
606  FloatComplexNDArray result (b.dims ());
607 
608  for (octave_idx_type i = 0; i < b.length (); i++)
609  {
610  octave_quit ();
611  result (i) = a / b (i);
612  }
613 
614  return result;
615 }
616 
618 x_el_div (const FloatComplex a, const FloatNDArray& b)
619 {
620  FloatComplexNDArray result (b.dims ());
621 
622  for (octave_idx_type i = 0; i < b.length (); i++)
623  {
624  octave_quit ();
625  result (i) = a / b (i);
626  }
627 
628  return result;
629 }
630 
633 {
634  FloatComplexNDArray result (b.dims ());
635 
636  for (octave_idx_type i = 0; i < b.length (); i++)
637  {
638  octave_quit ();
639  result (i) = a / b (i);
640  }
641 
642  return result;
643 }
644 
645 // Left division functions.
646 //
647 // op2 \ op1: m cm
648 // +-- +---+----+
649 // matrix | 1 | 3 |
650 // +---+----+
651 // complex_matrix | 2 | 4 |
652 // +---+----+
653 
654 // -*- 1 -*-
656 xleftdiv (const FloatMatrix& a, const FloatMatrix& b, MatrixType &typ,
657  blas_trans_type transt)
658 {
659  if (! mx_leftdiv_conform (a, b, transt))
660  return FloatMatrix ();
661 
662  octave_idx_type info;
663  float rcond = 0.0;
664  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);
665 }
666 
667 // -*- 2 -*-
670  blas_trans_type transt)
671 {
672  if (! mx_leftdiv_conform (a, b, transt))
673  return FloatComplexMatrix ();
674 
675  octave_idx_type info;
676  float rcond = 0.0;
677 
678  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);
679 }
680 
681 // -*- 3 -*-
684  blas_trans_type transt)
685 {
686  if (! mx_leftdiv_conform (a, b, transt))
687  return FloatComplexMatrix ();
688 
689  octave_idx_type info;
690  float rcond = 0.0;
691  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);
692 }
693 
694 // -*- 4 -*-
697  MatrixType &typ, blas_trans_type transt)
698 {
699  if (! mx_leftdiv_conform (a, b, transt))
700  return FloatComplexMatrix ();
701 
702  octave_idx_type info;
703  float rcond = 0.0;
704  return a.solve (typ, b, info, rcond, solve_singularity_warning, true, transt);
705 }
706 
707 // Diagonal matrix division.
708 
709 template <class MT, class DMT>
710 MT
711 mdm_div_impl (const MT& a, const DMT& d)
712 {
713  if (! mx_div_conform (a, d))
714  return MT ();
715 
716  octave_idx_type m = a.rows (), n = d.rows (), l = d.length ();
717  MT x (m, n);
718  typedef typename DMT::element_type S;
719  typedef typename MT::element_type T;
720  const T *aa = a.data ();
721  const S *dd = d.data ();
722  T *xx = x.fortran_vec ();
723 
724  for (octave_idx_type j = 0; j < l; j++)
725  {
726  const S del = dd[j];
727  if (del != S ())
728  for (octave_idx_type i = 0; i < m; i++)
729  xx[i] = aa[i] / del;
730  else
731  for (octave_idx_type i = 0; i < m; i++)
732  xx[i] = T ();
733  aa += m; xx += m;
734  }
735 
736  for (octave_idx_type i = l*m; i < n*m; i++)
737  xx[i] = T ();
738 
739  return x;
740 }
741 
742 // Right division functions.
743 //
744 // op2 / op1: dm cdm
745 // +-- +---+----+
746 // matrix | 1 | |
747 // +---+----+
748 // complex_matrix | 2 | 3 |
749 // +---+----+
750 
751 // -*- 1 -*-
752 Matrix
753 xdiv (const Matrix& a, const DiagMatrix& b)
754 { return mdm_div_impl (a, b); }
755 
756 // -*- 2 -*-
758 xdiv (const ComplexMatrix& a, const DiagMatrix& b)
759 { return mdm_div_impl (a, b); }
760 
761 // -*- 3 -*-
764 { return mdm_div_impl (a, b); }
765 
766 // Right division functions, float type.
767 //
768 // op2 / op1: dm cdm
769 // +-- +---+----+
770 // matrix | 1 | |
771 // +---+----+
772 // complex_matrix | 2 | 3 |
773 // +---+----+
774 
775 // -*- 1 -*-
777 xdiv (const FloatMatrix& a, const FloatDiagMatrix& b)
778 { return mdm_div_impl (a, b); }
779 
780 // -*- 2 -*-
783 { return mdm_div_impl (a, b); }
784 
785 // -*- 3 -*-
788 { return mdm_div_impl (a, b); }
789 
790 template <class MT, class DMT>
791 MT
792 dmm_leftdiv_impl (const DMT& d, const MT& a)
793 {
794  if (! mx_leftdiv_conform (d, a, blas_no_trans))
795  return MT ();
796 
797  octave_idx_type m = d.cols (), n = a.cols (), k = a.rows (), l = d.length ();
798  MT x (m, n);
799  typedef typename DMT::element_type S;
800  typedef typename MT::element_type T;
801  const T *aa = a.data ();
802  const S *dd = d.data ();
803  T *xx = x.fortran_vec ();
804 
805  for (octave_idx_type j = 0; j < n; j++)
806  {
807  for (octave_idx_type i = 0; i < l; i++)
808  xx[i] = dd[i] != S () ? aa[i] / dd[i] : T ();
809  for (octave_idx_type i = l; i < m; i++)
810  xx[i] = T ();
811  aa += k; xx += m;
812  }
813 
814  return x;
815 }
816 
817 // Left division functions.
818 //
819 // op2 \ op1: m cm
820 // +---+----+
821 // diag_matrix | 1 | 2 |
822 // +---+----+
823 // complex_diag_matrix | | 3 |
824 // +---+----+
825 
826 // -*- 1 -*-
827 Matrix
828 xleftdiv (const DiagMatrix& a, const Matrix& b)
829 { return dmm_leftdiv_impl (a, b); }
830 
831 // -*- 2 -*-
833 xleftdiv (const DiagMatrix& a, const ComplexMatrix& b)
834 { return dmm_leftdiv_impl (a, b); }
835 
836 // -*- 3 -*-
839 { return dmm_leftdiv_impl (a, b); }
840 
841 // Left division functions, float type.
842 //
843 // op2 \ op1: m cm
844 // +---+----+
845 // diag_matrix | 1 | 2 |
846 // +---+----+
847 // complex_diag_matrix | | 3 |
848 // +---+----+
849 
850 // -*- 1 -*-
853 { return dmm_leftdiv_impl (a, b); }
854 
855 // -*- 2 -*-
858 { return dmm_leftdiv_impl (a, b); }
859 
860 // -*- 3 -*-
863 { return dmm_leftdiv_impl (a, b); }
864 
865 // Diagonal by diagonal matrix division.
866 
867 template <class MT, class DMT>
868 MT
869 dmdm_div_impl (const MT& a, const DMT& d)
870 {
871  if (! mx_div_conform (a, d))
872  return MT ();
873 
874  octave_idx_type m = a.rows (), n = d.rows (), k = d.cols ();
875  octave_idx_type l = std::min (m, n), lk = std::min (l, k);
876  MT x (m, n);
877  typedef typename DMT::element_type S;
878  typedef typename MT::element_type T;
879  const T *aa = a.data ();
880  const S *dd = d.data ();
881  T *xx = x.fortran_vec ();
882 
883  for (octave_idx_type i = 0; i < lk; i++)
884  xx[i] = dd[i] != S () ? aa[i] / dd[i] : T ();
885  for (octave_idx_type i = lk; i < l; i++)
886  xx[i] = T ();
887 
888  return x;
889 }
890 
891 // Right division functions.
892 //
893 // op2 / op1: dm cdm
894 // +-- +---+----+
895 // diag_matrix | 1 | |
896 // +---+----+
897 // complex_diag_matrix | 2 | 3 |
898 // +---+----+
899 
900 // -*- 1 -*-
902 xdiv (const DiagMatrix& a, const DiagMatrix& b)
903 { return dmdm_div_impl (a, b); }
904 
905 // -*- 2 -*-
907 xdiv (const ComplexDiagMatrix& a, const DiagMatrix& b)
908 { return dmdm_div_impl (a, b); }
909 
910 // -*- 3 -*-
913 { return dmdm_div_impl (a, b); }
914 
915 // Right division functions, float type.
916 //
917 // op2 / op1: dm cdm
918 // +-- +---+----+
919 // diag_matrix | 1 | |
920 // +---+----+
921 // complex_diag_matrix | 2 | 3 |
922 // +---+----+
923 
924 // -*- 1 -*-
927 { return dmdm_div_impl (a, b); }
928 
929 // -*- 2 -*-
932 { return dmdm_div_impl (a, b); }
933 
934 // -*- 3 -*-
937 { return dmdm_div_impl (a, b); }
938 
939 template <class MT, class DMT>
940 MT
941 dmdm_leftdiv_impl (const DMT& d, const MT& a)
942 {
943  if (! mx_leftdiv_conform (d, a, blas_no_trans))
944  return MT ();
945 
946  octave_idx_type m = d.cols (), n = a.cols (), k = d.rows ();
947  octave_idx_type l = std::min (m, n), lk = std::min (l, k);
948  MT x (m, n);
949  typedef typename DMT::element_type S;
950  typedef typename MT::element_type T;
951  const T *aa = a.data ();
952  const S *dd = d.data ();
953  T *xx = x.fortran_vec ();
954 
955  for (octave_idx_type i = 0; i < lk; i++)
956  xx[i] = dd[i] != S () ? aa[i] / dd[i] : T ();
957  for (octave_idx_type i = lk; i < l; i++)
958  xx[i] = T ();
959 
960  return x;
961 }
962 
963 // Left division functions.
964 //
965 // op2 \ op1: dm cdm
966 // +---+----+
967 // diag_matrix | 1 | 2 |
968 // +---+----+
969 // complex_diag_matrix | | 3 |
970 // +---+----+
971 
972 // -*- 1 -*-
974 xleftdiv (const DiagMatrix& a, const DiagMatrix& b)
975 { return dmdm_leftdiv_impl (a, b); }
976 
977 // -*- 2 -*-
980 { return dmdm_leftdiv_impl (a, b); }
981 
982 // -*- 3 -*-
985 { return dmdm_leftdiv_impl (a, b); }
986 
987 // Left division functions, float type.
988 //
989 // op2 \ op1: dm cdm
990 // +---+----+
991 // diag_matrix | 1 | 2 |
992 // +---+----+
993 // complex_diag_matrix | | 3 |
994 // +---+----+
995 
996 // -*- 1 -*-
999 { return dmdm_leftdiv_impl (a, b); }
1000 
1001 // -*- 2 -*-
1004 { return dmdm_leftdiv_impl (a, b); }
1005 
1006 // -*- 3 -*-
1009 { return dmdm_leftdiv_impl (a, b); }