home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / octa21fs.zip / octave / octave-2.1.23 / liboctave / Array2-idx.h < prev    next >
C/C++ Source or Header  |  2000-01-15  |  14KB  |  697 lines

  1. // Template array classes
  2. /*
  3.  
  4. Copyright (C) 1996, 1997 John W. Eaton
  5.  
  6. This file is part of Octave.
  7.  
  8. Octave is free software; you can redistribute it and/or modify it
  9. under the terms of the GNU General Public License as published by the
  10. Free Software Foundation; either version 2, or (at your option) any
  11. later version.
  12.  
  13. Octave is distributed in the hope that it will be useful, but WITHOUT
  14. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  16. for more details.
  17.  
  18. You should have received a copy of the GNU General Public License
  19. along with Octave; see the file COPYING.  If not, write to the Free
  20. Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  21.  
  22. */
  23.  
  24. #include "Array-flags.h"
  25. #include "idx-vector.h"
  26. #include "lo-error.h"
  27.  
  28. template <class T>
  29. Array2<T>
  30. Array2<T>::value (void)
  31. {
  32.   Array2<T> retval;
  33.  
  34.   int n_idx = index_count ();
  35.  
  36.   if (n_idx == 2)
  37.     {
  38.       idx_vector *tmp = get_idx ();
  39.       idx_vector idx_i = tmp[0];
  40.       idx_vector idx_j = tmp[1];
  41.  
  42.       return index (idx_i, idx_j);
  43.     }
  44.   else if (n_idx == 1)
  45.     {
  46.       idx_vector *tmp = get_idx ();
  47.       idx_vector idx = tmp[0];
  48.  
  49.       return index (idx);
  50.     }
  51.   else
  52.     (*current_liboctave_error_handler)
  53.       ("invalid number of indices for matrix expression");
  54.  
  55.   clear_index ();
  56.  
  57.   return retval;
  58. }
  59.  
  60. template <class T>
  61. Array2<T>
  62. Array2<T>::index (idx_vector& idx) const
  63. {
  64.   Array2<T> retval;
  65.  
  66.   int nr = d1;
  67.   int nc = d2;
  68.  
  69.   if (nr == 1 && nc == 1)
  70.     {
  71.       Array<T> tmp = Array<T>::index (idx);
  72.  
  73.       int len = tmp.length ();
  74.  
  75.       if (len == 0)
  76.     retval = Array2<T> (0, 0);
  77.       else
  78.     {
  79.       if (liboctave_pcv_flag)
  80.         retval = Array2<T> (tmp, len, 1);
  81.       else
  82.         retval = Array2<T> (tmp, 1, len);
  83.     }
  84.     }
  85.   else if (nr == 1 || nc == 1)
  86.     {
  87.       int result_is_column_vector = (nc == 1 || idx.is_colon ());
  88.  
  89.       Array<T> tmp = Array<T>::index (idx);
  90.  
  91.       int len = tmp.length ();
  92.  
  93.       if (len == 0)
  94.     retval = Array2<T> (0, 0);
  95.       else
  96.     {
  97.       if (result_is_column_vector)
  98.         retval = Array2<T> (tmp, len, 1);
  99.       else
  100.         retval = Array2<T> (tmp, 1, len);
  101.     }
  102.     }
  103.   else if (liboctave_dfi_flag || idx.is_colon ())
  104.     {
  105.       // This code is only for indexing matrices.  The vector
  106.       // cases are handled above.
  107.  
  108.       idx.freeze (nr * nc, "matrix");
  109.  
  110.       if (idx)
  111.     {
  112.       int result_nr = idx.orig_rows ();
  113.       int result_nc = idx.orig_columns ();
  114.  
  115.       if (idx.is_colon ())
  116.         {
  117.           result_nr = nr * nc;
  118.           result_nc = result_nr ? 1 : 0;
  119.         }
  120.       else if (idx.one_zero_only ())
  121.         {
  122.           result_nr = idx.ones_count ();
  123.           result_nc = (result_nr > 0 ? 1 : 0);
  124.         }
  125.  
  126.       retval.resize (result_nr, result_nc);
  127.  
  128.       int k = 0;
  129.       for (int j = 0; j < result_nc; j++)
  130.         {
  131.           for (int i = 0; i < result_nr; i++)
  132.         {
  133.           int ii = idx.elem (k++);
  134.           int fr = ii % nr;
  135.           int fc = (ii - fr) / nr;
  136.           retval.elem (i, j) = elem (fr, fc);
  137.         }
  138.         }
  139.     }
  140.       // idx_vector::freeze() printed an error message for us.
  141.     }
  142.   else
  143.     (*current_liboctave_error_handler)
  144.       ("single index only valid for row or column vector");
  145.  
  146.   return retval;
  147. }
  148.  
  149. template <class T>
  150. Array2<T>
  151. Array2<T>::index (idx_vector& idx_i, idx_vector& idx_j) const
  152. {
  153.   Array2<T> retval;
  154.  
  155.   int nr = d1;
  156.   int nc = d2;
  157.  
  158.   int n = idx_i.freeze (nr, "row");
  159.   int m = idx_j.freeze (nc, "column");
  160.  
  161.   if (idx_i && idx_j)
  162.     {
  163.       if (idx_i.orig_empty () || idx_j.orig_empty ())
  164.     {
  165.       retval.resize (n, m);
  166.     }
  167.       else if (n == 0)
  168.     {
  169.       if (m == 0)
  170.         retval.resize (0, 0);
  171.       else if (idx_j.is_colon_equiv (nc, 1))
  172.         retval.resize (0, nc);
  173.       else if (idx_i.is_colon_equiv (nr, 1))
  174.         retval.resize (0, m);
  175.       else
  176.         (*current_liboctave_error_handler) ("invalid row index = 0");
  177.     }
  178.       else if (m == 0)
  179.     {
  180.       if (n == 0)
  181.         retval.resize (0, 0);
  182.       else if (idx_i.is_colon_equiv (nr, 1))
  183.         retval.resize (nr, 0);
  184.       else if (idx_j.is_colon_equiv (nc, 1))
  185.         retval.resize (n, 0);
  186.       else
  187.         (*current_liboctave_error_handler) ("invalid column index = 0");
  188.     }
  189.       else if (idx_i.is_colon_equiv (nr) && idx_j.is_colon_equiv (nc))
  190.     {
  191.       retval = *this;
  192.     }
  193.       else
  194.     {
  195.       retval.resize (n, m);
  196.  
  197.       for (int j = 0; j < m; j++)
  198.         {
  199.           int jj = idx_j.elem (j);
  200.           for (int i = 0; i < n; i++)
  201.         {
  202.           int ii = idx_i.elem (i);
  203.           retval.elem (i, j) = elem (ii, jj);
  204.         }
  205.         }
  206.     }
  207.     }
  208.  
  209.   // idx_vector::freeze() printed an error message for us.
  210.  
  211.   return retval;
  212. }
  213.  
  214. template <class T>
  215. void
  216. Array2<T>::maybe_delete_elements (idx_vector& idx_i, idx_vector& idx_j)
  217. {
  218.   int nr = d1;
  219.   int nc = d2;
  220.  
  221.   if (nr == 0 && nc == 0)
  222.     return;
  223.  
  224.   if (idx_i.is_colon_equiv (nr, 1))
  225.     {
  226.       if (idx_j.is_colon_equiv (nc, 1))
  227.     resize (0, 0);
  228.       else
  229.     {
  230.       idx_j.sort (true);
  231.  
  232.       int num_to_delete = idx_j.length (nc);
  233.  
  234.       if (num_to_delete != 0)
  235.         {
  236.           if (nr == 1 && num_to_delete == nc)
  237.         resize (0, 0);
  238.           else
  239.         {
  240.           int new_nc = nc;
  241.  
  242.           int idx = 0;
  243.  
  244.           for (int j = 0; j < nc; j++)
  245.             if (j == idx_j.elem (idx))
  246.               {
  247.             idx++;
  248.             new_nc--;
  249.  
  250.             if (idx == num_to_delete)
  251.               break;
  252.               }
  253.  
  254.           if (new_nc > 0)
  255.             {
  256.               T *new_data = new T [nr * new_nc];
  257.  
  258.               int jj = 0;
  259.               idx = 0;
  260.               for (int j = 0; j < nc; j++)
  261.             {
  262.               if (idx < num_to_delete && j == idx_j.elem (idx))
  263.                 idx++;
  264.               else
  265.                 {
  266.                   for (int i = 0; i < nr; i++)
  267.                 new_data[nr*jj+i] = elem (i, j);
  268.                   jj++;
  269.                 }
  270.             }
  271.  
  272.               if (--rep->count <= 0)
  273.             delete rep;
  274.  
  275.               rep = new ArrayRep (new_data, nr * new_nc);
  276.  
  277.               d2 = new_nc;
  278.  
  279.               set_max_indices (2);
  280.             }
  281.           else
  282.             (*current_liboctave_error_handler)
  283.               ("A(idx) = []: index out of range");
  284.         }
  285.         }
  286.     }
  287.     }
  288.   else if (idx_j.is_colon_equiv (nc, 1))
  289.     {
  290.       if (idx_i.is_colon_equiv (nr, 1))
  291.     resize (0, 0);
  292.       else
  293.     {
  294.       idx_i.sort (true);
  295.  
  296.       int num_to_delete = idx_i.length (nr);
  297.  
  298.       if (num_to_delete != 0)
  299.         {
  300.           if (nc == 1 && num_to_delete == nr)
  301.         resize (0, 0);
  302.           else 
  303.         {
  304.           int new_nr = nr;
  305.  
  306.           int idx = 0;
  307.  
  308.           for (int i = 0; i < nr; i++)
  309.             if (i == idx_i.elem (idx))
  310.               {
  311.             idx++;
  312.             new_nr--;
  313.  
  314.             if (idx == num_to_delete)
  315.               break;
  316.               }
  317.  
  318.           if (new_nr > 0)
  319.             {
  320.               T *new_data = new T [new_nr * nc];
  321.  
  322.               int ii = 0;
  323.               idx = 0;
  324.               for (int i = 0; i < nr; i++)
  325.             {
  326.               if (idx < num_to_delete && i == idx_i.elem (idx))
  327.                 idx++;
  328.               else
  329.                 {
  330.                   for (int j = 0; j < nc; j++)
  331.                 new_data[new_nr*j+ii] = elem (i, j);
  332.                   ii++;
  333.                 }
  334.             }
  335.  
  336.               if (--rep->count <= 0)
  337.             delete rep;
  338.  
  339.               rep = new ArrayRep (new_data, new_nr * nc);
  340.  
  341.               d1 = new_nr;
  342.  
  343.               set_max_indices (2);
  344.             }
  345.           else
  346.             (*current_liboctave_error_handler)
  347.               ("A(idx) = []: index out of range");
  348.         }
  349.         }
  350.     }
  351.     }
  352. }
  353.  
  354. #define MAYBE_RESIZE_LHS \
  355.   do \
  356.     { \
  357.       if (liboctave_rre_flag) \
  358.     { \
  359.       int max_row_idx = idx_i_is_colon ? rhs_nr : idx_i.max () + 1; \
  360.       int max_col_idx = idx_j_is_colon ? rhs_nc : idx_j.max () + 1; \
  361.  \
  362.       int new_nr = max_row_idx > lhs_nr ? max_row_idx : lhs_nr; \
  363.       int new_nc = max_col_idx > lhs_nc ? max_col_idx : lhs_nc; \
  364.  \
  365.       lhs.resize (new_nr, new_nc, 0.0); \
  366.     } \
  367.     } \
  368.   while (0)
  369.  
  370. template <class LT, class RT>
  371. int
  372. assign (Array2<LT>& lhs, const Array2<RT>& rhs)
  373. {
  374.   int retval = 1;
  375.  
  376.   int n_idx = lhs.index_count ();
  377.  
  378.   int lhs_nr = lhs.rows ();
  379.   int lhs_nc = lhs.cols ();
  380.  
  381.   int rhs_nr = rhs.rows ();
  382.   int rhs_nc = rhs.cols ();
  383.  
  384.   if (n_idx == 2)
  385.     {
  386.       idx_vector *tmp = lhs.get_idx ();
  387.  
  388.       idx_vector idx_i = tmp[0];
  389.       idx_vector idx_j = tmp[1];
  390.  
  391.       int n = idx_i.freeze (lhs_nr, "row", liboctave_rre_flag);
  392.  
  393.       int m = idx_j.freeze (lhs_nc, "column", liboctave_rre_flag);
  394.  
  395.       int idx_i_is_colon = idx_i.is_colon ();
  396.       int idx_j_is_colon = idx_j.is_colon ();
  397.  
  398.       if (idx_i_is_colon)
  399.     n = lhs_nr > 0 ? lhs_nr : rhs_nr;
  400.  
  401.       if (idx_j_is_colon)
  402.     m = lhs_nc > 0 ? lhs_nc : rhs_nc;
  403.  
  404.       if (idx_i && idx_j)
  405.     {
  406.       if (rhs_nr == 0 && rhs_nc == 0)
  407.         {
  408.           lhs.maybe_delete_elements (idx_i, idx_j);
  409.         }
  410.       else
  411.         {
  412.           if (rhs_nr == 1 && rhs_nc == 1 && n > 0 && m > 0)
  413.         {
  414.           MAYBE_RESIZE_LHS;
  415.  
  416.           RT scalar = rhs.elem (0, 0);
  417.  
  418.           for (int j = 0; j < m; j++)
  419.             {
  420.               int jj = idx_j.elem (j);
  421.               for (int i = 0; i < n; i++)
  422.             {
  423.               int ii = idx_i.elem (i);
  424.               lhs.elem (ii, jj) = scalar;
  425.             }
  426.             }
  427.         }
  428.           else if (n == rhs_nr && m == rhs_nc)
  429.         {
  430.           MAYBE_RESIZE_LHS;
  431.  
  432.           for (int j = 0; j < m; j++)
  433.             {
  434.               int jj = idx_j.elem (j);
  435.               for (int i = 0; i < n; i++)
  436.             {
  437.               int ii = idx_i.elem (i);
  438.               lhs.elem (ii, jj) = rhs.elem (i, j);
  439.             }
  440.             }
  441.         }
  442.           else if (n == 0 && m == 0)
  443.         {
  444.           if (! ((rhs_nr == 1 && rhs_nc == 1)
  445.              || (rhs_nr == 0 && rhs_nc == 0)))
  446.             {
  447.               (*current_liboctave_error_handler)
  448.         ("A([], []) = X: X must be an empty matrix or a scalar");
  449.  
  450.               retval = 0;
  451.             }
  452.         }
  453.           else
  454.         {
  455.           (*current_liboctave_error_handler)
  456.     ("A(I, J) = X: X must be a scalar or the number of elements in I must");
  457.           (*current_liboctave_error_handler)
  458.     ("match the number of rows in X and the number of elements in J must");
  459.           (*current_liboctave_error_handler)
  460.     ("match the number of columns in X");
  461.  
  462.           retval = 0;
  463.         }
  464.         }
  465.     }
  466.       // idx_vector::freeze() printed an error message for us.
  467.     }
  468.   else if (n_idx == 1)
  469.     {
  470.       int lhs_is_empty = lhs_nr == 0 || lhs_nc == 0;
  471.  
  472.       if (lhs_is_empty || (lhs_nr == 1 && lhs_nc == 1))
  473.     {
  474.       idx_vector *tmp = lhs.get_idx ();
  475.  
  476.       idx_vector idx = tmp[0];
  477.  
  478.       int lhs_len = lhs.length ();
  479.  
  480.       int n = idx.freeze (lhs_len, 0, liboctave_rre_flag);
  481.  
  482.       if (idx)
  483.         {
  484.           if (rhs_nr == 0 && rhs_nc == 0)
  485.         {
  486.           if (n != 0 && (lhs_nr != 0 || lhs_nc != 0))
  487.             {
  488.               idx_vector tmp (':');
  489.               lhs.maybe_delete_elements (idx, tmp);
  490.             }
  491.         }
  492.           else if (! liboctave_dfi_flag && lhs_is_empty
  493.                && idx.is_colon ()
  494.                && ! (rhs_nr == 1 || rhs_nc == 1))
  495.         {
  496.           (*current_liboctave_error_handler)
  497.             ("A(:) = X: X must be a vector");
  498.         }
  499.           else
  500.         {
  501.           if (assign ((Array<LT>&) lhs, (Array<RT>&) rhs))
  502.             {
  503.               int len = lhs.length ();
  504.  
  505.               if (len > 0)
  506.             {
  507.               int idx_nr = idx.orig_rows ();
  508.               int idx_nc = idx.orig_columns ();
  509.  
  510.               // lhs_is_empty now means that lhs was
  511.               // *originally* empty, and lhs_len is the
  512.               // *original* length of the lhs.
  513.  
  514.               if (liboctave_dfi_flag
  515.                   || (idx_nr == 1 && idx_nc == 1)
  516.                   || (rhs_nr == 1 && rhs_nc == 1 && lhs_len == 1))
  517.                 {
  518.                   if (liboctave_pcv_flag)
  519.                 {
  520.                   lhs.d1 = lhs.length ();
  521.                   lhs.d2 = 1;
  522.                 }
  523.                   else
  524.                 {
  525.                   lhs.d1 = 1;
  526.                   lhs.d2 = lhs.length ();
  527.                 }
  528.                 }
  529.               else if (lhs_is_empty && idx.is_colon ())
  530.                 {
  531.                   lhs.d1 = rhs.d1;
  532.                   lhs.d2 = rhs.d2;
  533.                 }
  534.               else if (rhs_nr == 1
  535.                    && (idx_nr == 1 || lhs_len == 1))
  536.                 {
  537.                   lhs.d1 = 1;
  538.                   lhs.d2 = lhs.length ();
  539.                 }
  540.               else if (rhs_nc == 1
  541.                    && (idx_nc == 1 || lhs_len == 1))
  542.                 {
  543.                   lhs.d1 = lhs.length ();
  544.                   lhs.d2 = 1;
  545.                 }
  546.               else if (idx_nr == 0 && idx_nc == 0)
  547.                 {
  548.                   if (! ((rhs.d1 == 1 && rhs.d2 == 1)
  549.                      || (rhs.d1 == 0 && rhs.d2 == 0)))
  550.                 (*current_liboctave_error_handler)
  551.               ("A([]) = X: X must be an empty matrix or scalar");
  552.                 }
  553.               else
  554.                 (*current_liboctave_error_handler)
  555.       ("A(I) = X: X must be a scalar or a matrix with the same size as I");
  556.             }
  557.               else
  558.             {
  559.               lhs.d1 = 0;
  560.               lhs.d2 = 0;
  561.             }
  562.             }
  563.           else
  564.             retval = 0;
  565.         }
  566.         }
  567.       // idx_vector::freeze() printed an error message for us.
  568.     }
  569.       else if (lhs_nr == 1)
  570.     {
  571.       idx_vector *tmp = lhs.get_idx ();
  572.  
  573.       idx_vector idx = tmp[0];
  574.  
  575.       idx.freeze (lhs_nc, "vector", liboctave_rre_flag);
  576.  
  577.       if (idx)
  578.         {
  579.           if (rhs_nr == 0 && rhs_nc == 0)
  580.         {
  581.           idx_vector tmp (':');
  582.           lhs.maybe_delete_elements (tmp, idx);
  583.         }
  584.           else
  585.         {
  586.           if (assign ((Array<LT>&) lhs, (Array<RT>&) rhs))
  587.             lhs.d2 = lhs.length ();
  588.           else
  589.             retval = 0;
  590.         }
  591.         }
  592.       // idx_vector::freeze() printed an error message for us.
  593.     }
  594.       else if (lhs_nc == 1)
  595.     {
  596.       idx_vector *tmp = lhs.get_idx ();
  597.  
  598.       idx_vector idx = tmp[0];
  599.  
  600.       idx.freeze (lhs_nr, "vector", liboctave_rre_flag);
  601.  
  602.       if (idx)
  603.         {
  604.           if (rhs_nr == 0 && rhs_nc == 0)
  605.         {
  606.           idx_vector tmp (':');
  607.           lhs.maybe_delete_elements (idx, tmp);
  608.         }
  609.           else
  610.         {
  611.           if (assign ((Array<LT>&) lhs, (Array<RT>&) rhs))
  612.             lhs.d1 = lhs.length ();
  613.           else
  614.             retval = 0;
  615.         }
  616.         }
  617.       // idx_vector::freeze() printed an error message for us.
  618.     }
  619.       else if (liboctave_dfi_flag)
  620.     {
  621.       idx_vector *tmp = lhs.get_idx ();
  622.       idx_vector idx = tmp[0];
  623.  
  624.       int len = idx.freeze (lhs_nr * lhs_nc, "matrix");
  625.  
  626.       if (idx)
  627.         {
  628.           if (len == 0)
  629.         {
  630.           if (! ((rhs_nr == 1 && rhs_nc == 1)
  631.              || (rhs_nr == 0 && rhs_nc == 0)))
  632.             (*current_liboctave_error_handler)
  633.               ("A([]) = X: X must be an empty matrix or scalar");
  634.         }
  635.           else if (len == rhs_nr * rhs_nc)
  636.         {
  637.           int k = 0;
  638.           for (int j = 0; j < rhs_nc; j++)
  639.             {
  640.               for (int i = 0; i < rhs_nr; i++)
  641.             {
  642.               int ii = idx.elem (k++);
  643.               int fr = ii % lhs_nr;
  644.               int fc = (ii - fr) / lhs_nr;
  645.               lhs.elem (fr, fc) = rhs.elem (i, j);
  646.             }
  647.             }
  648.         }
  649.           else if (rhs_nr == 1 && rhs_nc == 1 && len <= lhs_nr * lhs_nc)
  650.         {
  651.           RT scalar = rhs.elem (0, 0);
  652.  
  653.           for (int i = 0; i < len; i++)
  654.             {
  655.               int ii = idx.elem (i);
  656.               int fr = ii % lhs_nr;
  657.               int fc = (ii - fr) / lhs_nr;
  658.               lhs.elem (fr, fc) = scalar;
  659.             }
  660.         }
  661.           else
  662.         {
  663.           (*current_liboctave_error_handler)
  664.       ("A(I) = X: X must be a scalar or a matrix with the same size as I");
  665.  
  666.           retval = 0;
  667.         }
  668.         }
  669.       // idx_vector::freeze() printed an error message for us.
  670.     }
  671.       else
  672.     {
  673.       (*current_liboctave_error_handler)
  674.         ("single index only valid for row or column vector");
  675.  
  676.       retval = 0;
  677.     }
  678.     }
  679.   else
  680.     {
  681.       (*current_liboctave_error_handler)
  682.     ("invalid number of indices for matrix expression");
  683.  
  684.       retval = 0;
  685.     }
  686.  
  687.   lhs.clear_index ();
  688.  
  689.   return retval;
  690. }
  691.  
  692. /*
  693. ;;; Local Variables: ***
  694. ;;; mode: C++ ***
  695. ;;; End: ***
  696. */
  697.