home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / octave-1.1.1p1-src.tgz / tar.out / fsf / octave / src / tc-rep-ass.cc < prev    next >
C/C++ Source or Header  |  1996-09-28  |  55KB  |  2,489 lines

  1. // tc-rep-ass.cc                                            -*- C++ -*-
  2. /*
  3.  
  4. Copyright (C) 1992, 1993, 1994, 1995 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, 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  
  22. */
  23.  
  24. #ifdef HAVE_CONFIG_H
  25. #include "config.h"
  26. #endif
  27.  
  28. #include <ctype.h>
  29. #include <string.h>
  30. #include <fstream.h>
  31. #include <iostream.h>
  32. #include <strstream.h>
  33.  
  34. #include "mx-base.h"
  35. #include "Range.h"
  36.  
  37. #include "arith-ops.h"
  38. #include "variables.h"
  39. #include "sysdep.h"
  40. #include "error.h"
  41. #include "gripes.h"
  42. #include "user-prefs.h"
  43. #include "utils.h"
  44. #include "pager.h"
  45. #include "pr-output.h"
  46. #include "tree-const.h"
  47. #include "idx-vector.h"
  48. #include "oct-map.h"
  49.  
  50. #include "tc-inlines.h"
  51.  
  52. // Top-level tree-constant function that handles assignments.  Only
  53. // decide if the left-hand side is currently a scalar or a matrix and
  54. // hand off to other functions to do the real work.
  55.  
  56. void
  57. TC_REP::assign (tree_constant& rhs, const Octave_object& args)
  58. {
  59.   tree_constant rhs_tmp = rhs.make_numeric ();
  60.  
  61.   if (error_state)
  62.     return;
  63.  
  64. // This is easier than actually handling assignments to strings.
  65. // An assignment to a range will normally require a conversion to a
  66. // vector since it will normally destroy the equally-spaced property
  67. // of the range elements.
  68.  
  69.   if (is_defined () && ! is_numeric_type ())
  70.     force_numeric ();
  71.  
  72.   if (error_state)
  73.     return;
  74.  
  75.   switch (type_tag)
  76.     {
  77.     case complex_scalar_constant:
  78.     case scalar_constant:
  79.     case unknown_constant:
  80.       do_scalar_assignment (rhs_tmp, args);
  81.       break;
  82.  
  83.     case complex_matrix_constant:
  84.     case matrix_constant:
  85.       do_matrix_assignment (rhs_tmp, args);
  86.       break;
  87.  
  88.     default:
  89.       ::error ("invalid assignment to %s", type_as_string ());
  90.       break;
  91.     }
  92. }
  93.  
  94. // Assignments to scalars.  If resize_on_range_error is true,
  95. // this can convert the left-hand side to a matrix.
  96.  
  97. void
  98. TC_REP::do_scalar_assignment (const tree_constant& rhs,
  99.                   const Octave_object& args) 
  100. {
  101.   assert (type_tag == unknown_constant
  102.       || type_tag == scalar_constant
  103.       || type_tag == complex_scalar_constant);
  104.  
  105.   int nargin = args.length ();
  106.  
  107.   if (rhs.is_zero_by_zero ())
  108.     {
  109.       if (valid_scalar_indices (args))
  110.     {
  111.       if (type_tag == complex_scalar_constant)
  112.         delete complex_scalar;
  113.  
  114.       matrix = new Matrix (0, 0);
  115.       type_tag = matrix_constant;
  116.     }
  117.       else if (! valid_zero_index (args))
  118.     {
  119.       ::error ("invalid assigment of empty matrix to scalar");
  120.       return;
  121.     }
  122.     }
  123.   else if (rhs.is_scalar_type () && valid_scalar_indices (args))
  124.     {
  125.       if (type_tag == unknown_constant || type_tag == scalar_constant)
  126.     {
  127.       if (rhs.const_type () == scalar_constant)
  128.         {
  129.           scalar = rhs.double_value ();
  130.           type_tag = scalar_constant;
  131.         }
  132.       else if (rhs.const_type () == complex_scalar_constant)
  133.         {
  134.           complex_scalar = new Complex (rhs.complex_value ());
  135.           type_tag = complex_scalar_constant;
  136.         }
  137.       else
  138.         {
  139.           ::error ("invalid assignment to scalar");
  140.           return;
  141.         }
  142.     }
  143.       else
  144.     {
  145.       if (rhs.const_type () == scalar_constant)
  146.         {
  147.           delete complex_scalar;
  148.           scalar = rhs.double_value ();
  149.           type_tag = scalar_constant;
  150.         }
  151.       else if (rhs.const_type () == complex_scalar_constant)
  152.         {
  153.           *complex_scalar = rhs.complex_value ();
  154.           type_tag = complex_scalar_constant;
  155.         }
  156.       else
  157.         {
  158.           ::error ("invalid assignment to scalar");
  159.           return;
  160.         }
  161.     }
  162.     }
  163.   else if (user_pref.resize_on_range_error)
  164.     {
  165.       TC_REP::constant_type old_type_tag = type_tag;
  166.  
  167.       if (type_tag == complex_scalar_constant)
  168.     {
  169.       Complex *old_complex = complex_scalar;
  170.       complex_matrix = new ComplexMatrix (1, 1, *complex_scalar);
  171.       type_tag = complex_matrix_constant;
  172.       delete old_complex;
  173.     }
  174.       else if (type_tag == scalar_constant)
  175.     {
  176.       matrix = new Matrix (1, 1, scalar);
  177.       type_tag = matrix_constant;
  178.     }
  179.  
  180. // If there is an error, the call to do_matrix_assignment should not
  181. // destroy the current value.
  182. // TC_REP::eval(int) will take
  183. // care of converting single element matrices back to scalars.
  184.  
  185.       do_matrix_assignment (rhs, args);
  186.  
  187. // I don't think there's any other way to revert back to unknown
  188. // constant types, so here it is.
  189.  
  190.       if (old_type_tag == unknown_constant && error_state)
  191.     {
  192.       if (type_tag == matrix_constant)
  193.         delete matrix;
  194.       else if (type_tag == complex_matrix_constant)
  195.         delete complex_matrix;
  196.  
  197.       type_tag = unknown_constant;
  198.     }
  199.     }
  200.   else if (nargin > 2 || nargin < 1)
  201.     ::error ("invalid index expression for scalar type");
  202.   else
  203.     ::error ("index invalid or out of range for scalar type");
  204. }
  205.  
  206. // Assignments to matrices (and vectors).
  207. //
  208. // For compatibility with Matlab, we allow assignment of an empty
  209. // matrix to an expression with empty indices to do nothing.
  210.  
  211. void
  212. TC_REP::do_matrix_assignment (const tree_constant& rhs,
  213.                   const Octave_object& args)
  214. {
  215.   assert (type_tag == unknown_constant
  216.       || type_tag == matrix_constant
  217.       || type_tag == complex_matrix_constant);
  218.  
  219.   if (type_tag == matrix_constant && rhs.is_complex_type ())
  220.     {
  221.       Matrix *old_matrix = matrix;
  222.       complex_matrix = new ComplexMatrix (*matrix);
  223.       type_tag = complex_matrix_constant;
  224.       delete old_matrix;
  225.     }
  226.   else if (type_tag == unknown_constant)
  227.     {
  228.       if (rhs.is_complex_type ())
  229.     {
  230.       complex_matrix = new ComplexMatrix ();
  231.       type_tag = complex_matrix_constant;
  232.     }
  233.       else
  234.     {
  235.       matrix = new Matrix ();
  236.       type_tag = matrix_constant;
  237.     }
  238.     }
  239.  
  240.   int nargin = args.length ();
  241.  
  242. // The do_matrix_assignment functions can't handle empty matrices, so
  243. // don't let any pass through here.
  244.   switch (nargin)
  245.     {
  246.     case 1:
  247.       {
  248.     tree_constant arg = args(0);
  249.  
  250.     if (arg.is_undefined ())
  251.       ::error ("matrix index is undefined");
  252.     else
  253.       do_matrix_assignment (rhs, arg);
  254.       }
  255.       break;
  256.  
  257.     case 2:
  258.       {
  259.     tree_constant arg_a = args(0);
  260.     tree_constant arg_b = args(1);
  261.  
  262.     if (arg_a.is_undefined ())
  263.       ::error ("first matrix index is undefined");
  264.     else if (arg_b.is_undefined ())
  265.       ::error ("second matrix index is undefined");
  266.     else if (arg_a.is_empty () || arg_b.is_empty ())
  267.       {
  268.         if (! rhs.is_empty ())
  269.           {
  270.         ::error ("in assignment expression, a matrix index is empty");
  271.         ::error ("but the right hand side is not an empty matrix");
  272.           }
  273. // XXX FIXME XXX -- to really be correct here, we should probably
  274. // check to see if the assignment conforms, but that seems like more
  275. // work than it's worth right now...
  276.       }
  277.     else
  278.       do_matrix_assignment (rhs, arg_a, arg_b);
  279.       }
  280.       break;
  281.  
  282.     default:
  283.       if (nargin == 0)
  284.     ::error ("matrix indices expected, but none provided");
  285.       else
  286.     ::error ("too many indices for matrix expression");
  287.       break;
  288.     }
  289. }
  290.  
  291. // Matrix assignments indexed by a single value.
  292.  
  293. void
  294. TC_REP::do_matrix_assignment (const tree_constant& rhs,
  295.                   const tree_constant& i_arg)
  296. {
  297.   int nr = rows ();
  298.   int nc = columns ();
  299.  
  300.   if (user_pref.do_fortran_indexing || nr <= 1 || nc <= 1)
  301.     {
  302.       if (i_arg.is_empty ())
  303.     {
  304.       if (! rhs.is_empty ())
  305.         {
  306.           ::error ("in assignment expression, matrix index is empty but");
  307.           ::error ("right hand side is not an empty matrix");
  308.         }
  309. // XXX FIXME XXX -- to really be correct here, we should probably
  310. // check to see if the assignment conforms, but that seems like more
  311. // work than it's worth right now...
  312.  
  313. // The assignment functions can't handle empty matrices, so don't let
  314. // any pass through here.
  315.       return;
  316.     }
  317.  
  318. // We can't handle the case of assigning to a vector first, since even
  319. // then, the two operations are not equivalent.  For example, the
  320. // expression V(:) = M is handled differently depending on whether the
  321. // user specified do_fortran_indexing = "true".
  322.  
  323.       if (user_pref.do_fortran_indexing)
  324.     fortran_style_matrix_assignment (rhs, i_arg);
  325.       else if (nr <= 1 || nc <= 1)
  326.     vector_assignment (rhs, i_arg);
  327.       else
  328.     panic_impossible ();
  329.     }
  330.   else
  331.     ::error ("single index only valid for row or column vector");
  332. }
  333.  
  334. // Fortran-style assignments.  Matrices are assumed to be stored in
  335. // column-major order and it is ok to use a single index for
  336. // multi-dimensional matrices.
  337.  
  338. void
  339. TC_REP::fortran_style_matrix_assignment (const tree_constant& rhs,
  340.                      const tree_constant& i_arg)
  341. {
  342.   tree_constant tmp_i = i_arg.make_numeric_or_magic ();
  343.  
  344.   if (error_state)
  345.     return;
  346.  
  347.   TC_REP::constant_type itype = tmp_i.const_type ();
  348.  
  349.   int nr = rows ();
  350.   int nc = columns ();
  351.  
  352.   int rhs_nr = rhs.rows ();
  353.   int rhs_nc = rhs.columns ();
  354.  
  355.   switch (itype)
  356.     {
  357.     case complex_scalar_constant:
  358.     case scalar_constant:
  359.       {
  360.     double dval = tmp_i.double_value ();
  361.  
  362.     if (xisnan (dval))
  363.       {
  364.         error ("NaN is invalid as a matrix index");
  365.         return;
  366.       }
  367.  
  368.     int i = NINT (dval);
  369.     int idx = i - 1;
  370.  
  371.     if (rhs_nr == 0 && rhs_nc == 0)
  372.       {
  373.         int len = nr * nc;
  374.  
  375.         if (idx < len && len > 0)
  376.           {
  377.         convert_to_row_or_column_vector ();
  378.  
  379.         nr = rows ();
  380.         nc = columns ();
  381.  
  382.         if (nr == 1)
  383.           delete_column (idx);
  384.         else if (nc == 1)
  385.           delete_row (idx);
  386.         else
  387.           panic_impossible ();
  388.           }
  389.         else if (idx < 0)
  390.           {
  391.         error ("invalid index = %d", idx+1);
  392.           }
  393.  
  394.         return;
  395.       }
  396.  
  397.     if (index_check (idx, "") < 0)
  398.       return;
  399.  
  400.     if (nr <= 1 || nc <= 1)
  401.       {
  402.         maybe_resize (idx);
  403.         if (error_state)
  404.           return;
  405.       }
  406.     else if (range_max_check (idx, nr * nc) < 0)
  407.       return;
  408.  
  409.     nr = rows ();
  410.     nc = columns ();
  411.  
  412.     if (! indexed_assign_conforms (1, 1, rhs_nr, rhs_nc))
  413.       {
  414.         ::error ("for A(int) = X: X must be a scalar");
  415.         return;
  416.       }
  417.     int ii = fortran_row (i, nr) - 1;
  418.     int jj = fortran_column (i, nr) - 1;
  419.     do_matrix_assignment (rhs, ii, jj);
  420.       }
  421.       break;
  422.  
  423.     case complex_matrix_constant:
  424.     case matrix_constant:
  425.       {
  426.     Matrix mi = tmp_i.matrix_value ();
  427.     int len = nr * nc;
  428.     idx_vector ii (mi, 1, "", len);  // Always do fortran indexing here...
  429.     if (! ii)
  430.       return;
  431.  
  432.     if (rhs_nr == 0 && rhs_nc == 0)
  433.       {
  434.         ii.sort_uniq ();
  435.         int num_to_delete = 0;
  436.         for (int i = 0; i < ii.length (); i++)
  437.           {
  438.         if (ii.elem (i) < len)
  439.           num_to_delete++;
  440.         else
  441.           break;
  442.           }
  443.  
  444.         if (num_to_delete > 0)
  445.           {
  446.         if (num_to_delete != ii.length ())
  447.           ii.shorten (num_to_delete);
  448.  
  449.         convert_to_row_or_column_vector ();
  450.  
  451.         nr = rows ();
  452.         nc = columns ();
  453.  
  454.         if (nr == 1)
  455.           delete_columns (ii);
  456.         else if (nc == 1)
  457.           delete_rows (ii);
  458.         else
  459.           panic_impossible ();
  460.           }
  461.         return;
  462.       }
  463.  
  464.     if (nr <= 1 || nc <= 1)
  465.       {
  466.         maybe_resize (ii.max ());
  467.         if (error_state)
  468.           return;
  469.       }
  470.     else if (range_max_check (ii.max (), len) < 0)
  471.       return;
  472.  
  473.     int ilen = ii.capacity ();
  474.  
  475.     if (ilen != rhs_nr * rhs_nc)
  476.       {
  477.         ::error ("A(matrix) = X: X and matrix must have the same number");
  478.         ::error ("of elements");
  479.       }
  480.     else if (ilen == 1 && rhs.is_scalar_type ())
  481.       {
  482.         int nr = rows ();
  483.         int idx = ii.elem (0);
  484.         int ii = fortran_row (idx + 1, nr) - 1;
  485.         int jj = fortran_column (idx + 1, nr) - 1;
  486.  
  487.         if (rhs.const_type () == scalar_constant)
  488.           matrix->elem (ii, jj) = rhs.double_value ();
  489.         else if (rhs.const_type () == complex_scalar_constant)
  490.           complex_matrix->elem (ii, jj) = rhs.complex_value ();
  491.         else
  492.           panic_impossible ();
  493.       }
  494.     else
  495.       fortran_style_matrix_assignment (rhs, ii);
  496.       }
  497.       break;
  498.  
  499.     case string_constant:
  500.       gripe_string_invalid ();
  501.       break;
  502.  
  503.     case range_constant:
  504.       gripe_range_invalid ();
  505.       break;
  506.  
  507.     case magic_colon:
  508. // a(:) = [] is equivalent to a(:,:) = [].
  509.       if (rhs_nr == 0 && rhs_nc == 0)
  510.     do_matrix_assignment (rhs, magic_colon, magic_colon);
  511.       else
  512.     fortran_style_matrix_assignment (rhs, magic_colon);
  513.       break;
  514.  
  515.     default:
  516.       panic_impossible ();
  517.       break;
  518.     }
  519. }
  520.  
  521. // Fortran-style assignment for vector index.
  522.  
  523. void
  524. TC_REP::fortran_style_matrix_assignment (const tree_constant& rhs,
  525.                      idx_vector& i)
  526. {
  527.   assert (rhs.is_matrix_type ());
  528.  
  529.   int ilen = i.capacity ();
  530.  
  531.   REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
  532.  
  533.   int len = rhs_nr * rhs_nc;
  534.  
  535.   if (len == ilen)
  536.     {
  537.       int nr = rows ();
  538.       if (rhs.const_type () == matrix_constant)
  539.     {
  540.       double *cop_out = rhs_m.fortran_vec ();
  541.       for (int k = 0; k < len; k++)
  542.         {
  543.           int ii = fortran_row (i.elem (k) + 1, nr) - 1;
  544.           int jj = fortran_column (i.elem (k) + 1, nr) - 1;
  545.  
  546.           matrix->elem (ii, jj) = *cop_out++;
  547.         }
  548.     }
  549.       else
  550.     {
  551.       Complex *cop_out = rhs_cm.fortran_vec ();
  552.       for (int k = 0; k < len; k++)
  553.         {
  554.           int ii = fortran_row (i.elem (k) + 1, nr) - 1;
  555.           int jj = fortran_column (i.elem (k) + 1, nr) - 1;
  556.  
  557.           complex_matrix->elem (ii, jj) = *cop_out++;
  558.         }
  559.     }
  560.     }
  561.   else
  562.     ::error ("number of rows and columns must match for indexed assignment");
  563. }
  564.  
  565. // Fortran-style assignment for colon index.
  566.  
  567. void
  568. TC_REP::fortran_style_matrix_assignment (const tree_constant& rhs,
  569.                      TC_REP::constant_type mci)
  570. {
  571.   assert (rhs.is_matrix_type () && mci == TC_REP::magic_colon);
  572.  
  573.   int nr = rows ();
  574.   int nc = columns ();
  575.  
  576.   REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
  577.  
  578.   int rhs_size = rhs_nr * rhs_nc;
  579.   if (rhs_size == 0)
  580.     {
  581.       if (rhs.const_type () == matrix_constant)
  582.     {
  583.       delete matrix;
  584.       matrix = new Matrix (0, 0);
  585.       return;
  586.     }
  587.       else
  588.     panic_impossible ();
  589.     }
  590.   else if (nr*nc != rhs_size)
  591.     {
  592.       ::error ("A(:) = X: X and A must have the same number of elements");
  593.       return;
  594.     }
  595.  
  596.   if (rhs.const_type () == matrix_constant)
  597.     {
  598.       double *cop_out = rhs_m.fortran_vec ();
  599.       for (int j = 0; j < nc; j++)
  600.     for (int i = 0; i < nr; i++)
  601.       matrix->elem (i, j) = *cop_out++;
  602.     }
  603.   else
  604.     {
  605.       Complex *cop_out = rhs_cm.fortran_vec ();
  606.       for (int j = 0; j < nc; j++)
  607.     for (int i = 0; i < nr; i++)
  608.       complex_matrix->elem (i, j) = *cop_out++;
  609.     }
  610. }
  611.  
  612. // Assignments to vectors.  Hand off to other functions once we know
  613. // what kind of index we have.  For a colon, it is the same as
  614. // assignment to a matrix indexed by two colons.
  615.  
  616. void
  617. TC_REP::vector_assignment (const tree_constant& rhs,
  618.                const tree_constant& i_arg)
  619. {
  620.   int nr = rows ();
  621.   int nc = columns ();
  622.  
  623.   assert ((nr == 1 || nc == 1 || (nr == 0 && nc == 0))
  624.       && ! user_pref.do_fortran_indexing);
  625.  
  626.   tree_constant tmp_i = i_arg.make_numeric_or_range_or_magic ();
  627.  
  628.   if (error_state)
  629.     return;
  630.  
  631.   TC_REP::constant_type itype = tmp_i.const_type ();
  632.  
  633.   switch (itype)
  634.     {
  635.     case complex_scalar_constant:
  636.     case scalar_constant:
  637.       {
  638.     int i = tree_to_mat_idx (tmp_i.double_value ());
  639.     if (index_check (i, "") < 0)
  640.       return;
  641.     do_vector_assign (rhs, i);
  642.       }
  643.       break;
  644.  
  645.     case complex_matrix_constant:
  646.     case matrix_constant:
  647.       {
  648.     Matrix mi = tmp_i.matrix_value ();
  649.     int len = nr * nc;
  650.     idx_vector iv (mi, user_pref.do_fortran_indexing, "", len);
  651.     if (! iv)
  652.       return;
  653.  
  654.     do_vector_assign (rhs, iv);
  655.       }
  656.       break;
  657.  
  658.     case string_constant:
  659.       gripe_string_invalid ();
  660.       break;
  661.  
  662.     case range_constant:
  663.       {
  664.     Range ri = tmp_i.range_value ();
  665.     int len = nr * nc;
  666.     if (len == 2 && is_zero_one (ri))
  667.       {
  668.         do_vector_assign (rhs, 1);
  669.       }
  670.     else if (len == 2 && is_one_zero (ri))
  671.       {
  672.         do_vector_assign (rhs, 0);
  673.       }
  674.     else
  675.       {
  676.         if (index_check (ri, "") < 0)
  677.           return;
  678.         do_vector_assign (rhs, ri);
  679.       }
  680.       }
  681.       break;
  682.  
  683.     case magic_colon:
  684.       {
  685.     int rhs_nr = rhs.rows ();
  686.     int rhs_nc = rhs.columns ();
  687.  
  688.     if (! indexed_assign_conforms (nr, nc, rhs_nr, rhs_nc))
  689.       {
  690.         ::error ("A(:) = X: X and A must have the same dimensions");
  691.         return;
  692.       }
  693.     do_matrix_assignment (rhs, magic_colon, magic_colon);
  694.       }
  695.       break;
  696.  
  697.     default:
  698.       panic_impossible ();
  699.       break;
  700.     }
  701. }
  702.  
  703. // Check whether an indexed assignment to a vector is valid.
  704.  
  705. void
  706. TC_REP::check_vector_assign (int rhs_nr, int rhs_nc, int ilen, const char *rm)
  707. {
  708.   int nr = rows ();
  709.   int nc = columns ();
  710.  
  711.   if ((nr == 1 && nc == 1) || nr == 0 || nc == 0)  // No orientation.
  712.     {
  713.       if (! (ilen == rhs_nr || ilen == rhs_nc))
  714.     {
  715.       ::error ("A(%s) = X: X and %s must have the same number of elements",
  716.          rm, rm);
  717.     }
  718.     }
  719.   else if (nr == 1)  // Preserve current row orientation.
  720.     {
  721.       if (! (rhs_nr == 1 && rhs_nc == ilen))
  722.     {
  723.       ::error ("A(%s) = X: where A is a row vector, X must also be a", rm);
  724.       ::error ("row vector with the same number of elements as %s", rm);
  725.     }
  726.     }
  727.   else if (nc == 1)  // Preserve current column orientation.
  728.     {
  729.       if (! (rhs_nc == 1 && rhs_nr == ilen))
  730.     {
  731.       ::error ("A(%s) = X: where A is a column vector, X must also be", rm);
  732.       ::error ("a column vector with the same number of elements as %s", rm);
  733.     }
  734.     }
  735.   else
  736.     panic_impossible ();
  737. }
  738.  
  739. // Assignment to a vector with an integer index.
  740.  
  741. void
  742. TC_REP::do_vector_assign (const tree_constant& rhs, int i)
  743. {
  744.   int rhs_nr = rhs.rows ();
  745.   int rhs_nc = rhs.columns ();
  746.  
  747.   if (indexed_assign_conforms (1, 1, rhs_nr, rhs_nc))
  748.     {
  749.       maybe_resize (i);
  750.       if (error_state)
  751.     return;
  752.  
  753.       int nr = rows ();
  754.       int nc = columns ();
  755.  
  756.       if (nr == 1)
  757.     {
  758.       REP_ELEM_ASSIGN (0, i, rhs.double_value (), rhs.complex_value (),
  759.                rhs.is_real_type ());
  760.     }
  761.       else if (nc == 1)
  762.     {
  763.       REP_ELEM_ASSIGN (i, 0, rhs.double_value (), rhs.complex_value (),
  764.                rhs.is_real_type ());
  765.     }
  766.       else
  767.     panic_impossible ();
  768.     }
  769.   else if (rhs_nr == 0 && rhs_nc == 0)
  770.     {
  771.       int nr = rows ();
  772.       int nc = columns ();
  773.  
  774.       int len = MAX (nr, nc);
  775.  
  776.       if (i < 0 || i >= len)
  777.     {
  778.       ::error ("A(int) = []: index out of range");
  779.       return;
  780.     }
  781.  
  782.       if (nr == 1)
  783.     delete_column (i);
  784.       else if (nc == 1)
  785.     delete_row (i);
  786.       else
  787.     panic_impossible ();
  788.     }
  789.   else
  790.     {
  791.       ::error ("for A(int) = X: X must be a scalar");
  792.       return;
  793.     }
  794. }
  795.  
  796. // Assignment to a vector with a vector index.
  797.  
  798. void
  799. TC_REP::do_vector_assign (const tree_constant& rhs, idx_vector& iv)
  800. {
  801.   if (rhs.is_zero_by_zero ())
  802.     {
  803.       int nr = rows ();
  804.       int nc = columns ();
  805.  
  806.       int len = MAX (nr, nc);
  807.  
  808.       if (iv.max () >= len)
  809.     {
  810.       ::error ("A(matrix) = []: index out of range");
  811.       return;
  812.     }
  813.  
  814.       if (nr == 1)
  815.     delete_columns (iv);
  816.       else if (nc == 1)
  817.     delete_rows (iv);
  818.       else
  819.     panic_impossible ();
  820.     }
  821.   else if (rhs.is_scalar_type ())
  822.     {
  823.       int nr = rows ();
  824.       int nc = columns ();
  825.  
  826.       if (iv.capacity () == 1)
  827.     {
  828.       int idx = iv.elem (0);
  829.  
  830.       if (nr == 1)
  831.         {
  832.           REP_ELEM_ASSIGN (0, idx, rhs.double_value (),
  833.                    rhs.complex_value (), rhs.is_real_type ());
  834.         }
  835.       else if (nc == 1)
  836.         {
  837.           REP_ELEM_ASSIGN (idx, 0, rhs.double_value (),
  838.                    rhs.complex_value (), rhs.is_real_type ());
  839.         }
  840.       else
  841.         panic_impossible ();
  842.     }
  843.       else
  844.     {
  845.       if (nr == 1)
  846.         {
  847.           ::error ("A(matrix) = X: where A is a row vector, X must also be a");
  848.           ::error ("row vector with the same number of elements as matrix");
  849.         }
  850.       else if (nc == 1)
  851.         {
  852.           ::error ("A(matrix) = X: where A is a column vector, X must also be a");
  853.           ::error ("column vector with the same number of elements as matrix");
  854.         }
  855.       else
  856.         panic_impossible ();
  857.     }
  858.     }
  859.   else if (rhs.is_matrix_type ())
  860.     {
  861.       REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
  862.  
  863.       int ilen = iv.capacity ();
  864.       check_vector_assign (rhs_nr, rhs_nc, ilen, "matrix");
  865.       if (error_state)
  866.     return;
  867.  
  868.       force_orient f_orient = no_orient;
  869.       if (rhs_nr == 1 && rhs_nc != 1)
  870.     f_orient = row_orient;
  871.       else if (rhs_nc == 1 && rhs_nr != 1)
  872.     f_orient = column_orient;
  873.  
  874.       maybe_resize (iv.max (), f_orient);
  875.       if (error_state)
  876.     return;
  877.  
  878.       int nr = rows ();
  879.       int nc = columns ();
  880.  
  881.       if (nr == 1 && rhs_nr == 1)
  882.     {
  883.       for (int i = 0; i < iv.capacity (); i++)
  884.         REP_ELEM_ASSIGN (0, iv.elem (i), rhs_m.elem (0, i),
  885.                  rhs_cm.elem (0, i), rhs.is_real_type ());
  886.     }
  887.       else if (nc == 1 && rhs_nc == 1)
  888.     {
  889.       for (int i = 0; i < iv.capacity (); i++)
  890.         REP_ELEM_ASSIGN (iv.elem (i), 0, rhs_m.elem (i, 0),
  891.                  rhs_cm.elem (i, 0), rhs.is_real_type ());
  892.     }
  893.       else
  894.     ::error ("A(vector) = X: X must be the same size as vector");
  895.     }
  896.   else
  897.     panic_impossible ();
  898. }
  899.  
  900. // Assignment to a vector with a range index.
  901.  
  902. void
  903. TC_REP::do_vector_assign (const tree_constant& rhs, Range& ri)
  904. {
  905.   if (rhs.is_zero_by_zero ())
  906.     {
  907.       int nr = rows ();
  908.       int nc = columns ();
  909.  
  910.       int len = MAX (nr, nc);
  911.  
  912.       int b = tree_to_mat_idx (ri.min ());
  913.       int l = tree_to_mat_idx (ri.max ());
  914.       if (b < 0 || l >= len)
  915.     {
  916.       ::error ("A(range) = []: index out of range");
  917.       return;
  918.     }
  919.  
  920.       if (nr == 1)
  921.     delete_columns (ri);
  922.       else if (nc == 1)
  923.     delete_rows (ri);
  924.       else
  925.     panic_impossible ();
  926.     }
  927.   else if (rhs.is_scalar_type ())
  928.     {
  929.       int nr = rows ();
  930.       int nc = columns ();
  931.  
  932.       if (nr == 1)
  933.     {
  934.       ::error ("A(range) = X: where A is a row vector, X must also be a");
  935.       ::error ("row vector with the same number of elements as range");
  936.     }
  937.       else if (nc == 1)
  938.     {
  939.       ::error ("A(range) = X: where A is a column vector, X must also be a");
  940.       ::error ("column vector with the same number of elements as range");
  941.     }
  942.       else
  943.     panic_impossible ();
  944.     }
  945.   else if (rhs.is_matrix_type ())
  946.     {
  947.       REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
  948.  
  949.       int ilen = ri.nelem ();
  950.       check_vector_assign (rhs_nr, rhs_nc, ilen, "range");
  951.       if (error_state)
  952.     return;
  953.  
  954.       force_orient f_orient = no_orient;
  955.       if (rhs_nr == 1 && rhs_nc != 1)
  956.     f_orient = row_orient;
  957.       else if (rhs_nc == 1 && rhs_nr != 1)
  958.     f_orient = column_orient;
  959.  
  960.       maybe_resize (tree_to_mat_idx (ri.max ()), f_orient);
  961.       if (error_state)
  962.     return;
  963.  
  964.       int nr = rows ();
  965.       int nc = columns ();
  966.  
  967.       double b = ri.base ();
  968.       double increment = ri.inc ();
  969.  
  970.       if (nr == 1)
  971.     {
  972.       for (int i = 0; i < ri.nelem (); i++)
  973.         {
  974.           double tmp = b + i * increment;
  975.           int col = tree_to_mat_idx (tmp);
  976.           REP_ELEM_ASSIGN (0, col, rhs_m.elem (0, i), rhs_cm.elem (0, i),
  977.                    rhs.is_real_type ());
  978.         }
  979.     }
  980.       else if (nc == 1)
  981.     {
  982.       for (int i = 0; i < ri.nelem (); i++)
  983.         {
  984.           double tmp = b + i * increment;
  985.           int row = tree_to_mat_idx (tmp);
  986.           REP_ELEM_ASSIGN (row, 0, rhs_m.elem (i, 0), rhs_cm.elem (i, 0),
  987.                    rhs.is_real_type ());
  988.         }
  989.     }
  990.       else
  991.     panic_impossible ();
  992.     }
  993.   else
  994.     panic_impossible ();
  995. }
  996.  
  997. // Matrix assignment indexed by two values.  This function determines
  998. // the type of the first arugment, checks as much as possible, and
  999. // then calls one of a set of functions to handle the specific cases:
  1000. //
  1001. //   M (integer, arg2) = RHS  (MA1)
  1002. //   M (vector,  arg2) = RHS  (MA2)
  1003. //   M (range,   arg2) = RHS  (MA3)
  1004. //   M (colon,   arg2) = RHS  (MA4)
  1005. //
  1006. // Each of those functions determines the type of the second argument
  1007. // and calls another function to handle the real work of doing the
  1008. // assignment.
  1009.  
  1010. void
  1011. TC_REP::do_matrix_assignment (const tree_constant& rhs,
  1012.                   const tree_constant& i_arg,
  1013.                   const tree_constant& j_arg)
  1014. {
  1015.   tree_constant tmp_i = i_arg.make_numeric_or_range_or_magic ();
  1016.  
  1017.   if (error_state)
  1018.     return;
  1019.  
  1020.   TC_REP::constant_type itype = tmp_i.const_type ();
  1021.  
  1022.   switch (itype)
  1023.     {
  1024.     case complex_scalar_constant:
  1025.     case scalar_constant:
  1026.       {
  1027.     int i = tree_to_mat_idx (tmp_i.double_value ());
  1028.     do_matrix_assignment (rhs, i, j_arg);
  1029.       }
  1030.       break;
  1031.  
  1032.     case complex_matrix_constant:
  1033.     case matrix_constant:
  1034.       {
  1035.     Matrix mi = tmp_i.matrix_value ();
  1036.     idx_vector iv (mi, user_pref.do_fortran_indexing, "row", rows ());
  1037.     if (! iv)
  1038.       return;
  1039.  
  1040.     do_matrix_assignment (rhs, iv, j_arg);
  1041.       }
  1042.       break;
  1043.  
  1044.     case string_constant:
  1045.       gripe_string_invalid ();
  1046.       break;
  1047.  
  1048.     case range_constant:
  1049.       {
  1050.     Range ri = tmp_i.range_value ();
  1051.     int nr = rows ();
  1052.     if (nr == 2 && is_zero_one (ri))
  1053.       {
  1054.         do_matrix_assignment (rhs, 1, j_arg);
  1055.       }
  1056.     else if (nr == 2 && is_one_zero (ri))
  1057.       {
  1058.         do_matrix_assignment (rhs, 0, j_arg);
  1059.       }
  1060.     else
  1061.       {
  1062.         if (index_check (ri, "row") < 0)
  1063.           return;
  1064.         do_matrix_assignment (rhs, ri, j_arg);
  1065.       }
  1066.       }
  1067.       break;
  1068.  
  1069.     case magic_colon:
  1070.       do_matrix_assignment (rhs, magic_colon, j_arg);
  1071.       break;
  1072.  
  1073.     default:
  1074.       panic_impossible ();
  1075.       break;
  1076.     }
  1077. }
  1078.  
  1079. /* MA1 */
  1080. void
  1081. TC_REP::do_matrix_assignment (const tree_constant& rhs, int i,
  1082.                   const tree_constant& j_arg)
  1083. {
  1084.   tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic ();
  1085.  
  1086.   if (error_state)
  1087.     return;
  1088.  
  1089.   TC_REP::constant_type jtype = tmp_j.const_type ();
  1090.  
  1091.   int rhs_nr = rhs.rows ();
  1092.   int rhs_nc = rhs.columns ();
  1093.  
  1094.   switch (jtype)
  1095.     {
  1096.     case complex_scalar_constant:
  1097.     case scalar_constant:
  1098.       {
  1099.     if (index_check (i, "row") < 0)
  1100.       return;
  1101.     int j = tree_to_mat_idx (tmp_j.double_value ());
  1102.     if (index_check (j, "column") < 0)
  1103.       return;
  1104.     if (! indexed_assign_conforms (1, 1, rhs_nr, rhs_nc))
  1105.       {
  1106.         ::error ("A(int,int) = X, X must be a scalar");
  1107.         return;
  1108.       }
  1109.     maybe_resize (i, j);
  1110.     if (error_state)
  1111.       return;
  1112.  
  1113.     do_matrix_assignment (rhs, i, j);
  1114.       }
  1115.       break;
  1116.  
  1117.     case complex_matrix_constant:
  1118.     case matrix_constant:
  1119.       {
  1120.     if (index_check (i, "row") < 0)
  1121.       return;
  1122.     Matrix mj = tmp_j.matrix_value ();
  1123.     idx_vector jv (mj, user_pref.do_fortran_indexing, "column",
  1124.                columns ());
  1125.     if (! jv)
  1126.       return;
  1127.  
  1128.     if (! indexed_assign_conforms (1, jv.capacity (), rhs_nr, rhs_nc))
  1129.       {
  1130.         ::error ("A(int,matrix) = X: X must be a row vector with the same");
  1131.         ::error ("number of elements as matrix");
  1132.         return;
  1133.       }
  1134.     maybe_resize (i, jv.max ());
  1135.     if (error_state)
  1136.       return;
  1137.  
  1138.     do_matrix_assignment (rhs, i, jv);
  1139.       }
  1140.       break;
  1141.  
  1142.     case string_constant:
  1143.       gripe_string_invalid ();
  1144.       break;
  1145.  
  1146.     case range_constant:
  1147.       {
  1148.     if (index_check (i, "row") < 0)
  1149.       return;
  1150.     Range rj = tmp_j.range_value ();
  1151.     if (! indexed_assign_conforms (1, rj.nelem (), rhs_nr, rhs_nc))
  1152.       {
  1153.         ::error ("A(int,range) = X: X must be a row vector with the same");
  1154.         ::error ("number of elements as range");
  1155.         return;
  1156.       }
  1157.  
  1158.     int nc = columns ();
  1159.     if (nc == 2 && is_zero_one (rj) && rhs_nc == 1)
  1160.       {
  1161.         do_matrix_assignment (rhs, i, 1);
  1162.       }
  1163.     else if (nc == 2 && is_one_zero (rj) && rhs_nc == 1)
  1164.       {
  1165.         do_matrix_assignment (rhs, i, 0);
  1166.       }
  1167.     else
  1168.       {
  1169.         if (index_check (rj, "column") < 0)
  1170.           return;
  1171.         maybe_resize (i, tree_to_mat_idx (rj.max ()));
  1172.         if (error_state)
  1173.           return;
  1174.  
  1175.         do_matrix_assignment (rhs, i, rj);
  1176.       }
  1177.       }
  1178.       break;
  1179.  
  1180.     case magic_colon:
  1181.       {
  1182.     int nc = columns ();
  1183.     int nr = rows ();
  1184.     if (i == -1 && nr == 1 && rhs_nr == 0 && rhs_nc == 0
  1185.         || index_check (i, "row") < 0)
  1186.       return;
  1187.     else if (nc == 0 && nr == 0 && rhs_nr == 1)
  1188.       {
  1189.         if (rhs.is_complex_type ())
  1190.           {
  1191.         complex_matrix = new ComplexMatrix ();
  1192.         type_tag = complex_matrix_constant;
  1193.           }
  1194.         else
  1195.           {
  1196.         matrix = new Matrix ();
  1197.         type_tag = matrix_constant;
  1198.           }
  1199.         maybe_resize (i, rhs_nc-1);
  1200.         if (error_state)
  1201.           return;
  1202.       }
  1203.     else if (indexed_assign_conforms (1, nc, rhs_nr, rhs_nc))
  1204.       {
  1205.         maybe_resize (i, nc-1);
  1206.         if (error_state)
  1207.           return;
  1208.       }
  1209.     else if (rhs_nr == 0 && rhs_nc == 0)
  1210.       {
  1211.         if (i < 0 || i >= nr)
  1212.           {
  1213.         ::error ("A(int,:) = []: row index out of range");
  1214.         return;
  1215.           }
  1216.       }
  1217.     else
  1218.       {
  1219.         ::error ("A(int,:) = X: X must be a row vector with the same");
  1220.         ::error ("number of columns as A");
  1221.         return;
  1222.       }
  1223.  
  1224.     do_matrix_assignment (rhs, i, magic_colon);
  1225.       }
  1226.       break;
  1227.  
  1228.     default:
  1229.       panic_impossible ();
  1230.       break;
  1231.     }
  1232. }
  1233.  
  1234. /* MA2 */
  1235. void
  1236. TC_REP::do_matrix_assignment (const tree_constant& rhs,
  1237.                   idx_vector& iv, const tree_constant& j_arg)
  1238. {
  1239.   tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic ();
  1240.  
  1241.   if (error_state)
  1242.     return;
  1243.  
  1244.   TC_REP::constant_type jtype = tmp_j.const_type ();
  1245.  
  1246.   int rhs_nr = rhs.rows ();
  1247.   int rhs_nc = rhs.columns ();
  1248.  
  1249.   switch (jtype)
  1250.     {
  1251.     case complex_scalar_constant:
  1252.     case scalar_constant:
  1253.       {
  1254.     int j = tree_to_mat_idx (tmp_j.double_value ());
  1255.     if (index_check (j, "column") < 0)
  1256.       return;
  1257.     if (! indexed_assign_conforms (iv.capacity (), 1, rhs_nr, rhs_nc))
  1258.       {
  1259.         ::error ("A(matrix,int) = X: X must be a column vector with the");
  1260.         ::error ("same number of elements as matrix");
  1261.         return;
  1262.       }
  1263.     maybe_resize (iv.max (), j);
  1264.     if (error_state)
  1265.       return;
  1266.  
  1267.     do_matrix_assignment (rhs, iv, j);
  1268.       }
  1269.       break;
  1270.  
  1271.     case complex_matrix_constant:
  1272.     case matrix_constant:
  1273.       {
  1274.     Matrix mj = tmp_j.matrix_value ();
  1275.     idx_vector jv (mj, user_pref.do_fortran_indexing, "column",
  1276.                columns ());
  1277.     if (! jv)
  1278.       return;
  1279.  
  1280.     if (! indexed_assign_conforms (iv.capacity (), jv.capacity (),
  1281.                        rhs_nr, rhs_nc))
  1282.       {
  1283.         ::error ("A(r_mat,c_mat) = X: the number of rows in X must match");
  1284.         ::error ("the number of elements in r_mat and the number of");
  1285.         ::error ("columns in X must match the number of elements in c_mat");
  1286.         return;
  1287.       }
  1288.     maybe_resize (iv.max (), jv.max ());
  1289.     if (error_state)
  1290.       return;
  1291.  
  1292.     do_matrix_assignment (rhs, iv, jv);
  1293.       }
  1294.       break;
  1295.  
  1296.     case string_constant:
  1297.       gripe_string_invalid ();
  1298.       break;
  1299.  
  1300.     case range_constant:
  1301.       {
  1302.     Range rj = tmp_j.range_value ();
  1303.     if (! indexed_assign_conforms (iv.capacity (), rj.nelem (),
  1304.                        rhs_nr, rhs_nc))
  1305.       {
  1306.         ::error ("A(matrix,range) = X: the number of rows in X must match");
  1307.         ::error ("the number of elements in matrix and the number of");
  1308.         ::error ("columns in X must match the number of elements in range");
  1309.         return;
  1310.       }
  1311.  
  1312.     int nc = columns ();
  1313.     if (nc == 2 && is_zero_one (rj) && rhs_nc == 1)
  1314.       {
  1315.         do_matrix_assignment (rhs, iv, 1);
  1316.       }
  1317.     else if (nc == 2 && is_one_zero (rj) && rhs_nc == 1)
  1318.       {
  1319.         do_matrix_assignment (rhs, iv, 0);
  1320.       }
  1321.     else
  1322.       {
  1323.         if (index_check (rj, "column") < 0)
  1324.           return;
  1325.         maybe_resize (iv.max (), tree_to_mat_idx (rj.max ()));
  1326.         if (error_state)
  1327.           return;
  1328.  
  1329.         do_matrix_assignment (rhs, iv, rj);
  1330.       }
  1331.       }
  1332.       break;
  1333.  
  1334.     case magic_colon:
  1335.       {
  1336.     int nc = columns ();
  1337.     int new_nc = nc;
  1338.     if (nc == 0)
  1339.       new_nc = rhs_nc;
  1340.  
  1341.     if (indexed_assign_conforms (iv.capacity (), new_nc,
  1342.                      rhs_nr, rhs_nc))
  1343.       {
  1344.         maybe_resize (iv.max (), new_nc-1);
  1345.         if (error_state)
  1346.           return;
  1347.       }
  1348.     else if (rhs_nr == 0 && rhs_nc == 0)
  1349.       {
  1350.         if (iv.max () >= rows ())
  1351.           {
  1352.         ::error ("A(matrix,:) = []: row index out of range");
  1353.         return;
  1354.           }
  1355.       }
  1356.     else
  1357.       {
  1358.         ::error ("A(matrix,:) = X: the number of rows in X must match the");
  1359.         ::error ("number of elements in matrix, and the number of columns");
  1360.         ::error ("in X must match the number of columns in A");
  1361.         return;
  1362.       }
  1363.  
  1364.     do_matrix_assignment (rhs, iv, magic_colon);
  1365.       }
  1366.       break;
  1367.  
  1368.     default:
  1369.       panic_impossible ();
  1370.       break;
  1371.     }
  1372. }
  1373.  
  1374. /* MA3 */
  1375. void
  1376. TC_REP::do_matrix_assignment (const tree_constant& rhs, Range& ri,
  1377.                   const tree_constant& j_arg)
  1378. {
  1379.   tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic ();
  1380.  
  1381.   if (error_state)
  1382.     return;
  1383.  
  1384.   TC_REP::constant_type jtype = tmp_j.const_type ();
  1385.  
  1386.   int rhs_nr = rhs.rows ();
  1387.   int rhs_nc = rhs.columns ();
  1388.  
  1389.   switch (jtype)
  1390.     {
  1391.     case complex_scalar_constant:
  1392.     case scalar_constant:
  1393.       {
  1394.     int j = tree_to_mat_idx (tmp_j.double_value ());
  1395.     if (index_check (j, "column") < 0)
  1396.       return;
  1397.     if (! indexed_assign_conforms (ri.nelem (), 1, rhs_nr, rhs_nc))
  1398.       {
  1399.         ::error ("A(range,int) = X: X must be a column vector with the");
  1400.         ::error ("same number of elements as range");
  1401.         return;
  1402.       }
  1403.     maybe_resize (tree_to_mat_idx (ri.max ()), j);
  1404.     if (error_state)
  1405.       return;
  1406.  
  1407.     do_matrix_assignment (rhs, ri, j);
  1408.       }
  1409.       break;
  1410.  
  1411.     case complex_matrix_constant:
  1412.     case matrix_constant:
  1413.       {
  1414.     Matrix mj = tmp_j.matrix_value ();
  1415.     idx_vector jv (mj, user_pref.do_fortran_indexing, "column",
  1416.                columns ());
  1417.     if (! jv)
  1418.       return;
  1419.  
  1420.     if (! indexed_assign_conforms (ri.nelem (), jv.capacity (),
  1421.                        rhs_nr, rhs_nc))
  1422.       {
  1423.         ::error ("A(range,matrix) = X: the number of rows in X must match");
  1424.         ::error ("the number of elements in range and the number of");
  1425.         ::error ("columns in X must match the number of elements in matrix");
  1426.         return;
  1427.       }
  1428.     maybe_resize (tree_to_mat_idx (ri.max ()), jv.max ());
  1429.     if (error_state)
  1430.       return;
  1431.  
  1432.     do_matrix_assignment (rhs, ri, jv);
  1433.       }
  1434.       break;
  1435.  
  1436.     case string_constant:
  1437.       gripe_string_invalid ();
  1438.       break;
  1439.  
  1440.     case range_constant:
  1441.       {
  1442.     Range rj = tmp_j.range_value ();
  1443.     if (! indexed_assign_conforms (ri.nelem (), rj.nelem (),
  1444.                        rhs_nr, rhs_nc))
  1445.       {
  1446.         ::error ("A(r_range,c_range) = X: the number of rows in X must");
  1447.         ::error ("match the number of elements in r_range and the number");
  1448.         ::error ("of columns in X must match the number of elements in");
  1449.         ::error ("c_range");
  1450.         return;
  1451.       }
  1452.  
  1453.     int nc = columns ();
  1454.     if (nc == 2 && is_zero_one (rj) && rhs_nc == 1)
  1455.       {
  1456.         do_matrix_assignment (rhs, ri, 1);
  1457.       }
  1458.     else if (nc == 2 && is_one_zero (rj) && rhs_nc == 1)
  1459.       {
  1460.         do_matrix_assignment (rhs, ri, 0);
  1461.       }
  1462.     else
  1463.       {
  1464.         if (index_check (rj, "column") < 0)
  1465.           return;
  1466.  
  1467.         maybe_resize (tree_to_mat_idx (ri.max ()),
  1468.               tree_to_mat_idx (rj.max ()));
  1469.  
  1470.         if (error_state)
  1471.           return;
  1472.  
  1473.         do_matrix_assignment (rhs, ri, rj);
  1474.       }
  1475.       }
  1476.       break;
  1477.  
  1478.     case magic_colon:
  1479.       {
  1480.     int nc = columns ();
  1481.     int new_nc = nc;
  1482.     if (nc == 0)
  1483.       new_nc = rhs_nc;
  1484.  
  1485.     if (indexed_assign_conforms (ri.nelem (), new_nc, rhs_nr, rhs_nc))
  1486.       {
  1487.         maybe_resize (tree_to_mat_idx (ri.max ()), new_nc-1);
  1488.         if (error_state)
  1489.           return;
  1490.       }
  1491.     else if (rhs_nr == 0 && rhs_nc == 0)
  1492.       {
  1493.         int b = tree_to_mat_idx (ri.min ());
  1494.         int l = tree_to_mat_idx (ri.max ());
  1495.         if (b < 0 || l >= rows ())
  1496.           {
  1497.         ::error ("A(range,:) = []: row index out of range");
  1498.         return;
  1499.           }
  1500.       }
  1501.     else
  1502.       {
  1503.         ::error ("A(range,:) = X: the number of rows in X must match the");
  1504.         ::error ("number of elements in range, and the number of columns");
  1505.         ::error ("in X must match the number of columns in A");
  1506.         return;
  1507.       }
  1508.  
  1509.     do_matrix_assignment (rhs, ri, magic_colon);
  1510.       }
  1511.       break;
  1512.  
  1513.     default:
  1514.       panic_impossible ();
  1515.       break;
  1516.     }
  1517. }
  1518.  
  1519. /* MA4 */
  1520. void
  1521. TC_REP::do_matrix_assignment (const tree_constant& rhs,
  1522.                   TC_REP::constant_type i,
  1523.                   const tree_constant& j_arg)
  1524. {
  1525.   tree_constant tmp_j = j_arg.make_numeric_or_range_or_magic ();
  1526.  
  1527.   if (error_state)
  1528.     return;
  1529.  
  1530.   TC_REP::constant_type jtype = tmp_j.const_type ();
  1531.  
  1532.   int rhs_nr = rhs.rows ();
  1533.   int rhs_nc = rhs.columns ();
  1534.  
  1535.   switch (jtype)
  1536.     {
  1537.     case complex_scalar_constant:
  1538.     case scalar_constant:
  1539.       {
  1540.     int j = tree_to_mat_idx (tmp_j.double_value ());
  1541.     int nr = rows ();
  1542.     int nc = columns ();
  1543.     if (j == -1 && nc == 1 && rhs_nr == 0 && rhs_nc == 0
  1544.         || index_check (j, "column") < 0)
  1545.       return;
  1546.     if (nr == 0 && nc == 0 && rhs_nc == 1)
  1547.       {
  1548.         if (rhs.is_complex_type ())
  1549.           {
  1550.         complex_matrix = new ComplexMatrix ();
  1551.         type_tag = complex_matrix_constant;
  1552.           }
  1553.         else
  1554.           {
  1555.         matrix = new Matrix ();
  1556.         type_tag = matrix_constant;
  1557.           }
  1558.         maybe_resize (rhs_nr-1, j);
  1559.         if (error_state)
  1560.           return;
  1561.       }
  1562.     else if (indexed_assign_conforms (nr, 1, rhs_nr, rhs_nc))
  1563.       {
  1564.         maybe_resize (nr-1, j);
  1565.         if (error_state)
  1566.           return;
  1567.       }
  1568.     else if (rhs_nr == 0 && rhs_nc == 0)
  1569.       {
  1570.         if (j < 0 || j >= nc)
  1571.           {
  1572.         ::error ("A(:,int) = []: column index out of range");
  1573.         return;
  1574.           }
  1575.       }
  1576.     else
  1577.       {
  1578.         ::error ("A(:,int) = X: X must be a column vector with the same");
  1579.         ::error ("number of rows as A");
  1580.         return;
  1581.       }
  1582.  
  1583.     do_matrix_assignment (rhs, magic_colon, j);
  1584.       }
  1585.       break;
  1586.  
  1587.     case complex_matrix_constant:
  1588.     case matrix_constant:
  1589.       {
  1590.     Matrix mj = tmp_j.matrix_value ();
  1591.     idx_vector jv (mj, user_pref.do_fortran_indexing, "column",
  1592.                columns ());
  1593.     if (! jv)
  1594.       return;
  1595.  
  1596.     int nr = rows ();
  1597.     int new_nr = nr;
  1598.     if (nr == 0)
  1599.       new_nr = rhs_nr;
  1600.  
  1601.     if (indexed_assign_conforms (new_nr, jv.capacity (),
  1602.                      rhs_nr, rhs_nc))
  1603.       {
  1604.         maybe_resize (new_nr-1, jv.max ());
  1605.         if (error_state)
  1606.           return;
  1607.       }
  1608.     else if (rhs_nr == 0 && rhs_nc == 0)
  1609.       {
  1610.         if (jv.max () >= columns ())
  1611.           {
  1612.         ::error ("A(:,matrix) = []: column index out of range");
  1613.         return;
  1614.           }
  1615.       }
  1616.     else
  1617.       {
  1618.         ::error ("A(:,matrix) = X: the number of rows in X must match the");
  1619.         ::error ("number of rows in A, and the number of columns in X must");
  1620.         ::error ("match the number of elements in matrix");
  1621.         return;
  1622.       }
  1623.  
  1624.     do_matrix_assignment (rhs, magic_colon, jv);
  1625.       }
  1626.       break;
  1627.  
  1628.     case string_constant:
  1629.       gripe_string_invalid ();
  1630.       break;
  1631.  
  1632.     case range_constant:
  1633.       {
  1634.     Range rj = tmp_j.range_value ();
  1635.     int nr = rows ();
  1636.     int new_nr = nr;
  1637.     if (nr == 0)
  1638.       new_nr = rhs_nr;
  1639.  
  1640.     if (indexed_assign_conforms (new_nr, rj.nelem (), rhs_nr, rhs_nc))
  1641.       {
  1642.         int nc = columns ();
  1643.         if (nc == 2 && is_zero_one (rj) && rhs_nc == 1)
  1644.           {
  1645.         do_matrix_assignment (rhs, magic_colon, 1);
  1646.           }
  1647.         else if (nc == 2 && is_one_zero (rj) && rhs_nc == 1)
  1648.           {
  1649.         do_matrix_assignment (rhs, magic_colon, 0);
  1650.           }
  1651.         else
  1652.           {
  1653.         if (index_check (rj, "column") < 0)
  1654.           return;
  1655.         maybe_resize (new_nr-1, tree_to_mat_idx (rj.max ()));
  1656.         if (error_state)
  1657.           return;
  1658.           }
  1659.       }
  1660.     else if (rhs_nr == 0 && rhs_nc == 0)
  1661.       {
  1662.         int b = tree_to_mat_idx (rj.min ());
  1663.         int l = tree_to_mat_idx (rj.max ());
  1664.         if (b < 0 || l >= columns ())
  1665.           {
  1666.         ::error ("A(:,range) = []: column index out of range");
  1667.         return;
  1668.           }
  1669.       }
  1670.     else
  1671.       {
  1672.         ::error ("A(:,range) = X: the number of rows in X must match the");
  1673.         ::error ("number of rows in A, and the number of columns in X");
  1674.         ::error ("must match the number of elements in range");
  1675.         return;
  1676.       }
  1677.  
  1678.     do_matrix_assignment (rhs, magic_colon, rj);
  1679.       }
  1680.       break;
  1681.  
  1682.     case magic_colon:
  1683. // a(:,:) = foo is equivalent to a = foo.
  1684.       do_matrix_assignment (rhs, magic_colon, magic_colon);
  1685.       break;
  1686.  
  1687.     default:
  1688.       panic_impossible ();
  1689.       break;
  1690.     }
  1691. }
  1692.  
  1693. // Functions that actually handle assignment to a matrix using two
  1694. // index values.
  1695. //
  1696. //                   idx2
  1697. //            +---+---+----+----+
  1698. //   idx1     | i | v |  r | c  |
  1699. //   ---------+---+---+----+----+
  1700. //   integer  | 1 | 5 |  9 | 13 |
  1701. //   ---------+---+---+----+----+
  1702. //   vector   | 2 | 6 | 10 | 14 |
  1703. //   ---------+---+---+----+----+
  1704. //   range    | 3 | 7 | 11 | 15 |
  1705. //   ---------+---+---+----+----+
  1706. //   colon    | 4 | 8 | 12 | 16 |
  1707. //   ---------+---+---+----+----+
  1708.  
  1709. /* 1 */
  1710. void
  1711. TC_REP::do_matrix_assignment (const tree_constant& rhs, int i, int j)
  1712. {
  1713.   REP_ELEM_ASSIGN (i, j, rhs.double_value (), rhs.complex_value (),
  1714.            rhs.is_real_type ());
  1715. }
  1716.  
  1717. /* 2 */
  1718. void
  1719. TC_REP::do_matrix_assignment (const tree_constant& rhs, int i, idx_vector& jv)
  1720. {
  1721.   REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
  1722.  
  1723.   for (int j = 0; j < jv.capacity (); j++)
  1724.     REP_ELEM_ASSIGN (i, jv.elem (j), rhs_m.elem (0, j),
  1725.              rhs_cm.elem (0, j), rhs.is_real_type ());
  1726. }
  1727.  
  1728. /* 3 */
  1729. void
  1730. TC_REP::do_matrix_assignment (const tree_constant& rhs, int i, Range& rj)
  1731. {
  1732.   REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
  1733.  
  1734.   double b = rj.base ();
  1735.   double increment = rj.inc ();
  1736.  
  1737.   for (int j = 0; j < rj.nelem (); j++)
  1738.     {
  1739.       double tmp = b + j * increment;
  1740.       int col = tree_to_mat_idx (tmp);
  1741.       REP_ELEM_ASSIGN (i, col, rhs_m.elem (0, j), rhs_cm.elem (0, j),
  1742.                rhs.is_real_type ());
  1743.     }
  1744. }
  1745.  
  1746. /* 4 */
  1747. void
  1748. TC_REP::do_matrix_assignment (const tree_constant& rhs, int i,
  1749.                   TC_REP::constant_type mcj)
  1750. {
  1751.   assert (mcj == magic_colon);
  1752.  
  1753.   int nc = columns ();
  1754.  
  1755.   if (rhs.is_zero_by_zero ())
  1756.     {
  1757.       delete_row (i);
  1758.     }
  1759.   else if (rhs.is_matrix_type ())
  1760.     {
  1761.       REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
  1762.  
  1763.       for (int j = 0; j < nc; j++)
  1764.     REP_ELEM_ASSIGN (i, j, rhs_m.elem (0, j), rhs_cm.elem (0, j),
  1765.              rhs.is_real_type ());
  1766.     }
  1767.   else if (rhs.is_scalar_type () && nc == 1)
  1768.     {
  1769.       REP_ELEM_ASSIGN (i, 0, rhs.double_value (),
  1770.                rhs.complex_value (), rhs.is_real_type ());
  1771.     }
  1772.   else
  1773.     panic_impossible ();
  1774. }
  1775.  
  1776. /* 5 */
  1777. void
  1778. TC_REP::do_matrix_assignment (const tree_constant& rhs,
  1779.                   idx_vector& iv, int j)
  1780. {
  1781.   REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
  1782.  
  1783.   for (int i = 0; i < iv.capacity (); i++)
  1784.     {
  1785.       int row = iv.elem (i);
  1786.       REP_ELEM_ASSIGN (row, j, rhs_m.elem (i, 0),
  1787.                rhs_cm.elem (i, 0), rhs.is_real_type ());
  1788.     }
  1789. }
  1790.  
  1791. /* 6 */
  1792. void
  1793. TC_REP::do_matrix_assignment (const tree_constant& rhs,
  1794.                   idx_vector& iv, idx_vector& jv)
  1795. {
  1796.   REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
  1797.  
  1798.   for (int i = 0; i < iv.capacity (); i++)
  1799.     {
  1800.       int row = iv.elem (i);
  1801.       for (int j = 0; j < jv.capacity (); j++)
  1802.     {
  1803.       int col = jv.elem (j);
  1804.       REP_ELEM_ASSIGN (row, col, rhs_m.elem (i, j),
  1805.                rhs_cm.elem (i, j), rhs.is_real_type ());
  1806.     }
  1807.     }
  1808. }
  1809.  
  1810. /* 7 */
  1811. void
  1812. TC_REP::do_matrix_assignment (const tree_constant& rhs,
  1813.                   idx_vector& iv, Range& rj)
  1814. {
  1815.   REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
  1816.  
  1817.   double b = rj.base ();
  1818.   double increment = rj.inc ();
  1819.  
  1820.   for (int i = 0; i < iv.capacity (); i++)
  1821.     {
  1822.       int row = iv.elem (i);
  1823.       for (int j = 0; j < rj.nelem (); j++)
  1824.     {
  1825.       double tmp = b + j * increment;
  1826.       int col = tree_to_mat_idx (tmp);
  1827.       REP_ELEM_ASSIGN (row, col, rhs_m.elem (i, j),
  1828.                rhs_cm.elem (i, j), rhs.is_real_type ());
  1829.     }
  1830.     }
  1831. }
  1832.  
  1833. /* 8 */
  1834. void
  1835. TC_REP::do_matrix_assignment (const tree_constant& rhs,
  1836.                   idx_vector& iv, TC_REP::constant_type mcj)
  1837. {
  1838.   assert (mcj == magic_colon);
  1839.  
  1840.   if (rhs.is_zero_by_zero ())
  1841.     {
  1842.       delete_rows (iv);
  1843.     }
  1844.   else
  1845.     {
  1846.       REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
  1847.  
  1848.       int nc = columns ();
  1849.  
  1850.       for (int j = 0; j < nc; j++)
  1851.     {
  1852.       for (int i = 0; i < iv.capacity (); i++)
  1853.         {
  1854.           int row = iv.elem (i);
  1855.           REP_ELEM_ASSIGN (row, j, rhs_m.elem (i, j),
  1856.                    rhs_cm.elem (i, j), rhs.is_real_type ());
  1857.         }
  1858.     }
  1859.     }
  1860. }
  1861.  
  1862. /* 9 */
  1863. void
  1864. TC_REP::do_matrix_assignment (const tree_constant& rhs, Range& ri, int j)
  1865. {
  1866.   REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
  1867.  
  1868.   double b = ri.base ();
  1869.   double increment = ri.inc ();
  1870.  
  1871.   for (int i = 0; i < ri.nelem (); i++)
  1872.     {
  1873.       double tmp = b + i * increment;
  1874.       int row = tree_to_mat_idx (tmp);
  1875.       REP_ELEM_ASSIGN (row, j, rhs_m.elem (i, 0),
  1876.                rhs_cm.elem (i, 0), rhs.is_real_type ());
  1877.     }
  1878. }
  1879.  
  1880. /* 10 */
  1881. void
  1882. TC_REP::do_matrix_assignment (const tree_constant& rhs,
  1883.                   Range& ri, idx_vector& jv)
  1884. {
  1885.   REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
  1886.  
  1887.   double b = ri.base ();
  1888.   double increment = ri.inc ();
  1889.  
  1890.   for (int j = 0; j < jv.capacity (); j++)
  1891.     {
  1892.       int col = jv.elem (j);
  1893.       for (int i = 0; i < ri.nelem (); i++)
  1894.     {
  1895.       double tmp = b + i * increment;
  1896.       int row = tree_to_mat_idx (tmp);
  1897.       REP_ELEM_ASSIGN (row, col, rhs_m.elem (i, j),
  1898.                rhs_m.elem (i, j), rhs.is_real_type ());
  1899.     }
  1900.     }
  1901. }
  1902.  
  1903. /* 11 */
  1904. void
  1905. TC_REP::do_matrix_assignment (const tree_constant& rhs,
  1906.                   Range& ri, Range& rj)
  1907. {
  1908.   double ib = ri.base ();
  1909.   double iinc = ri.inc ();
  1910.   double jb = rj.base ();
  1911.   double jinc = rj.inc ();
  1912.  
  1913.   REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
  1914.  
  1915.   for (int i = 0; i < ri.nelem (); i++)
  1916.     {
  1917.       double itmp = ib + i * iinc;
  1918.       int row = tree_to_mat_idx (itmp);
  1919.       for (int j = 0; j < rj.nelem (); j++)
  1920.     {
  1921.       double jtmp = jb + j * jinc;
  1922.       int col = tree_to_mat_idx (jtmp);
  1923.       REP_ELEM_ASSIGN (row, col, rhs_m.elem  (i, j),
  1924.                rhs_cm.elem (i, j), rhs.is_real_type ());
  1925.     }
  1926.     }
  1927. }
  1928.  
  1929. /* 12 */
  1930. void
  1931. TC_REP::do_matrix_assignment (const tree_constant& rhs,
  1932.                   Range& ri, TC_REP::constant_type mcj)
  1933. {
  1934.   assert (mcj == magic_colon);
  1935.  
  1936.   if (rhs.is_zero_by_zero ())
  1937.     {
  1938.       delete_rows (ri);
  1939.     }
  1940.   else
  1941.     {
  1942.       REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
  1943.  
  1944.       double ib = ri.base ();
  1945.       double iinc = ri.inc ();
  1946.  
  1947.       int nc = columns ();
  1948.  
  1949.       for (int i = 0; i < ri.nelem (); i++)
  1950.     {
  1951.       double itmp = ib + i * iinc;
  1952.       int row = tree_to_mat_idx (itmp);
  1953.       for (int j = 0; j < nc; j++)
  1954.         REP_ELEM_ASSIGN (row, j, rhs_m.elem (i, j),
  1955.                  rhs_cm.elem (i, j), rhs.is_real_type ());
  1956.     }
  1957.     }
  1958. }
  1959.  
  1960. /* 13 */
  1961. void
  1962. TC_REP::do_matrix_assignment (const tree_constant& rhs,
  1963.                   TC_REP::constant_type mci, int j)
  1964. {
  1965.   assert (mci == magic_colon);
  1966.  
  1967.   int nr = rows ();
  1968.  
  1969.   if (rhs.is_zero_by_zero ())
  1970.     {
  1971.       delete_column (j);
  1972.     }
  1973.   else if (rhs.is_matrix_type ())
  1974.     {
  1975.       REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
  1976.  
  1977.       for (int i = 0; i < nr; i++)
  1978.     REP_ELEM_ASSIGN (i, j, rhs_m.elem (i, 0),
  1979.              rhs_cm.elem (i, 0), rhs.is_real_type ());
  1980.     }
  1981.   else if (rhs.is_scalar_type () && nr == 1)
  1982.     {
  1983.       REP_ELEM_ASSIGN (0, j, rhs.double_value (),
  1984.                rhs.complex_value (), rhs.is_real_type ());
  1985.     }
  1986.   else
  1987.     panic_impossible ();
  1988. }
  1989.  
  1990. /* 14 */
  1991. void
  1992. TC_REP::do_matrix_assignment (const tree_constant& rhs,
  1993.                   TC_REP::constant_type mci, idx_vector& jv)
  1994. {
  1995.   assert (mci == magic_colon);
  1996.  
  1997.   if (rhs.is_zero_by_zero ())
  1998.     {
  1999.       delete_columns (jv);
  2000.     }
  2001.   else
  2002.     {
  2003.       REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
  2004.  
  2005.       int nr = rows ();
  2006.  
  2007.       for (int i = 0; i < nr; i++)
  2008.     {
  2009.       for (int j = 0; j < jv.capacity (); j++)
  2010.         {
  2011.           int col = jv.elem (j);
  2012.           REP_ELEM_ASSIGN (i, col, rhs_m.elem (i, j),
  2013.                    rhs_cm.elem (i, j), rhs.is_real_type ());
  2014.         }
  2015.     }
  2016.     }
  2017. }
  2018.  
  2019. /* 15 */
  2020. void
  2021. TC_REP::do_matrix_assignment (const tree_constant& rhs,
  2022.                   TC_REP::constant_type mci, Range& rj)
  2023. {
  2024.   assert (mci == magic_colon);
  2025.  
  2026.   if (rhs.is_zero_by_zero ())
  2027.     {
  2028.       delete_columns (rj);
  2029.     }
  2030.   else
  2031.     {
  2032.       REP_RHS_MATRIX (rhs, rhs_m, rhs_cm, rhs_nr, rhs_nc);
  2033.  
  2034.       int nr = rows ();
  2035.  
  2036.       double jb = rj.base ();
  2037.       double jinc = rj.inc ();
  2038.  
  2039.       for (int j = 0; j < rj.nelem (); j++)
  2040.     {
  2041.       double jtmp = jb + j * jinc;
  2042.       int col = tree_to_mat_idx (jtmp);
  2043.       for (int i = 0; i < nr; i++)
  2044.         {
  2045.           REP_ELEM_ASSIGN (i, col, rhs_m.elem (i, j),
  2046.                    rhs_cm.elem (i, j), rhs.is_real_type ());
  2047.         }
  2048.     }
  2049.     }
  2050. }
  2051.  
  2052. /* 16 */
  2053. void
  2054. TC_REP::do_matrix_assignment (const tree_constant& rhs,
  2055.                   TC_REP::constant_type mci,
  2056.                   TC_REP::constant_type mcj)
  2057. {
  2058.   assert (mci == magic_colon && mcj == magic_colon);
  2059.  
  2060.   switch (type_tag)
  2061.     {
  2062.     case scalar_constant:
  2063.       break;
  2064.  
  2065.     case matrix_constant:
  2066.       delete matrix;
  2067.       break;
  2068.  
  2069.     case complex_scalar_constant:
  2070.       delete complex_scalar;
  2071.       break;
  2072.  
  2073.     case complex_matrix_constant:
  2074.       delete complex_matrix;
  2075.       break;
  2076.  
  2077.     case string_constant:
  2078.       delete [] string;
  2079.       break;
  2080.  
  2081.     case range_constant:
  2082.       delete range;
  2083.       break;
  2084.  
  2085.     case magic_colon:
  2086.     default:
  2087.       panic_impossible ();
  2088.       break;
  2089.     }
  2090.  
  2091.   type_tag = rhs.const_type ();
  2092.  
  2093.   switch (type_tag)
  2094.     {
  2095.     case scalar_constant:
  2096.       scalar = rhs.double_value ();
  2097.       break;
  2098.  
  2099.     case matrix_constant:
  2100.       matrix = new Matrix (rhs.matrix_value ());
  2101.       break;
  2102.  
  2103.     case string_constant:
  2104.       string = strsave (rhs.string_value ());
  2105.       break;
  2106.  
  2107.     case complex_matrix_constant:
  2108.       complex_matrix = new ComplexMatrix (rhs.complex_matrix_value ());
  2109.       break;
  2110.  
  2111.     case complex_scalar_constant:
  2112.       complex_scalar = new Complex (rhs.complex_value ());
  2113.       break;
  2114.  
  2115.     case range_constant:
  2116.       range = new Range (rhs.range_value ());
  2117.       break;
  2118.  
  2119.     case magic_colon:
  2120.     default:
  2121.       panic_impossible ();
  2122.       break;
  2123.     }
  2124. }
  2125.  
  2126. // Functions for deleting rows or columns of a matrix.  These are used
  2127. // to handle statements like
  2128. //
  2129. //   M (i, j) = []
  2130.  
  2131. void
  2132. TC_REP::delete_row (int idx)
  2133. {
  2134.   if (type_tag == matrix_constant)
  2135.     {
  2136.       int nr = matrix->rows ();
  2137.       int nc = matrix->columns ();
  2138.       Matrix *new_matrix = new Matrix (nr-1, nc);
  2139.       int ii = 0;
  2140.       for (int i = 0; i < nr; i++)
  2141.     {
  2142.       if (i != idx)
  2143.         {
  2144.           for (int j = 0; j < nc; j++)
  2145.         new_matrix->elem (ii, j) = matrix->elem (i, j);
  2146.           ii++;
  2147.         }
  2148.     }
  2149.       delete matrix;
  2150.       matrix = new_matrix;
  2151.     }
  2152.   else if (type_tag == complex_matrix_constant)
  2153.     {
  2154.       int nr = complex_matrix->rows ();
  2155.       int nc = complex_matrix->columns ();
  2156.       ComplexMatrix *new_matrix = new ComplexMatrix (nr-1, nc);
  2157.       int ii = 0;
  2158.       for (int i = 0; i < nr; i++)
  2159.     {
  2160.       if (i != idx)
  2161.         {
  2162.           for (int j = 0; j < nc; j++)
  2163.         new_matrix->elem (ii, j) = complex_matrix->elem (i, j);
  2164.           ii++;
  2165.         }
  2166.     }
  2167.       delete complex_matrix;
  2168.       complex_matrix = new_matrix;
  2169.     }
  2170.   else
  2171.     panic_impossible ();
  2172. }
  2173.  
  2174. void
  2175. TC_REP::delete_rows (idx_vector& iv)
  2176. {
  2177.   iv.sort_uniq ();
  2178.   int num_to_delete = iv.length ();
  2179.  
  2180.   int nr = rows ();
  2181.   int nc = columns ();
  2182.  
  2183. // If deleting all rows of a column vector, make result 0x0.
  2184.   if (nc == 1 && num_to_delete == nr)
  2185.     nc = 0;
  2186.  
  2187.   if (type_tag == matrix_constant)
  2188.     {
  2189.       Matrix *new_matrix = new Matrix (nr-num_to_delete, nc);
  2190.       if (nr > num_to_delete)
  2191.     {
  2192.       int ii = 0;
  2193.       int idx = 0;
  2194.       for (int i = 0; i < nr; i++)
  2195.         {
  2196.           if (i == iv.elem (idx))
  2197.         idx++;
  2198.           else
  2199.         {
  2200.           for (int j = 0; j < nc; j++)
  2201.             new_matrix->elem (ii, j) = matrix->elem (i, j);
  2202.           ii++;
  2203.         }
  2204.         }
  2205.     }
  2206.       delete matrix;
  2207.       matrix = new_matrix;
  2208.     }
  2209.   else if (type_tag == complex_matrix_constant)
  2210.     {
  2211.       ComplexMatrix *new_matrix = new ComplexMatrix (nr-num_to_delete, nc);
  2212.       if (nr > num_to_delete)
  2213.     {
  2214.       int ii = 0;
  2215.       int idx = 0;
  2216.       for (int i = 0; i < nr; i++)
  2217.         {
  2218.           if (i == iv.elem (idx))
  2219.         idx++;
  2220.           else
  2221.         {
  2222.           for (int j = 0; j < nc; j++)
  2223.             new_matrix->elem (ii, j) = complex_matrix->elem (i, j);
  2224.           ii++;
  2225.         }
  2226.         }
  2227.     }
  2228.       delete complex_matrix;
  2229.       complex_matrix = new_matrix;
  2230.     }
  2231.   else
  2232.     panic_impossible ();
  2233. }
  2234.  
  2235. void
  2236. TC_REP::delete_rows (Range& ri)
  2237. {
  2238.   ri.sort ();
  2239.   int num_to_delete = ri.nelem ();
  2240.  
  2241.   int nr = rows ();
  2242.   int nc = columns ();
  2243.  
  2244. // If deleting all rows of a column vector, make result 0x0.
  2245.   if (nc == 1 && num_to_delete == nr)
  2246.     nc = 0;
  2247.  
  2248.   double ib = ri.base ();
  2249.   double iinc = ri.inc ();
  2250.  
  2251.   int max_idx = tree_to_mat_idx (ri.max ());
  2252.  
  2253.   if (type_tag == matrix_constant)
  2254.     {
  2255.       Matrix *new_matrix = new Matrix (nr-num_to_delete, nc);
  2256.       if (nr > num_to_delete)
  2257.     {
  2258.       int ii = 0;
  2259.       int idx = 0;
  2260.       for (int i = 0; i < nr; i++)
  2261.         {
  2262.           double itmp = ib + idx * iinc;
  2263.           int row = tree_to_mat_idx (itmp);
  2264.  
  2265.           if (i == row && row <= max_idx)
  2266.         idx++;
  2267.           else
  2268.         {
  2269.           for (int j = 0; j < nc; j++)
  2270.             new_matrix->elem (ii, j) = matrix->elem (i, j);
  2271.           ii++;
  2272.         }
  2273.         }
  2274.     }
  2275.       delete matrix;
  2276.       matrix = new_matrix;
  2277.     }
  2278.   else if (type_tag == complex_matrix_constant)
  2279.     {
  2280.       ComplexMatrix *new_matrix = new ComplexMatrix (nr-num_to_delete, nc);
  2281.       if (nr > num_to_delete)
  2282.     {
  2283.       int ii = 0;
  2284.       int idx = 0;
  2285.       for (int i = 0; i < nr; i++)
  2286.         {
  2287.           double itmp = ib + idx * iinc;
  2288.           int row = tree_to_mat_idx (itmp);
  2289.  
  2290.           if (i == row && row <= max_idx)
  2291.         idx++;
  2292.           else
  2293.         {
  2294.           for (int j = 0; j < nc; j++)
  2295.             new_matrix->elem (ii, j) = complex_matrix->elem (i, j);
  2296.           ii++;
  2297.         }
  2298.         }
  2299.     }
  2300.       delete complex_matrix;
  2301.       complex_matrix = new_matrix;
  2302.     }
  2303.   else
  2304.     panic_impossible ();
  2305. }
  2306.  
  2307. void
  2308. TC_REP::delete_column (int idx)
  2309. {
  2310.   if (type_tag == matrix_constant)
  2311.     {
  2312.       int nr = matrix->rows ();
  2313.       int nc = matrix->columns ();
  2314.       Matrix *new_matrix = new Matrix (nr, nc-1);
  2315.       int jj = 0;
  2316.       for (int j = 0; j < nc; j++)
  2317.     {
  2318.       if (j != idx)
  2319.         {
  2320.           for (int i = 0; i < nr; i++)
  2321.         new_matrix->elem (i, jj) = matrix->elem (i, j);
  2322.           jj++;
  2323.         }
  2324.     }
  2325.       delete matrix;
  2326.       matrix = new_matrix;
  2327.     }
  2328.   else if (type_tag == complex_matrix_constant)
  2329.     {
  2330.       int nr = complex_matrix->rows ();
  2331.       int nc = complex_matrix->columns ();
  2332.       ComplexMatrix *new_matrix = new ComplexMatrix (nr, nc-1);
  2333.       int jj = 0;
  2334.       for (int j = 0; j < nc; j++)
  2335.     {
  2336.       if (j != idx)
  2337.         {
  2338.           for (int i = 0; i < nr; i++)
  2339.         new_matrix->elem (i, jj) = complex_matrix->elem (i, j);
  2340.           jj++;
  2341.         }
  2342.     }
  2343.       delete complex_matrix;
  2344.       complex_matrix = new_matrix;
  2345.     }
  2346.   else
  2347.     panic_impossible ();
  2348. }
  2349.  
  2350. void
  2351. TC_REP::delete_columns (idx_vector& jv)
  2352. {
  2353.   jv.sort_uniq ();
  2354.   int num_to_delete = jv.length ();
  2355.  
  2356.   int nr = rows ();
  2357.   int nc = columns ();
  2358.  
  2359. // If deleting all columns of a row vector, make result 0x0.
  2360.   if (nr == 1 && num_to_delete == nc)
  2361.     nr = 0;
  2362.  
  2363.   if (type_tag == matrix_constant)
  2364.     {
  2365.       Matrix *new_matrix = new Matrix (nr, nc-num_to_delete);
  2366.       if (nc > num_to_delete)
  2367.     {
  2368.       int jj = 0;
  2369.       int idx = 0;
  2370.       for (int j = 0; j < nc; j++)
  2371.         {
  2372.           if (j == jv.elem (idx))
  2373.         idx++;
  2374.           else
  2375.         {
  2376.           for (int i = 0; i < nr; i++)
  2377.             new_matrix->elem (i, jj) = matrix->elem (i, j);
  2378.           jj++;
  2379.         }
  2380.         }
  2381.     }
  2382.       delete matrix;
  2383.       matrix = new_matrix;
  2384.     }
  2385.   else if (type_tag == complex_matrix_constant)
  2386.     {
  2387.       ComplexMatrix *new_matrix = new ComplexMatrix (nr, nc-num_to_delete);
  2388.       if (nc > num_to_delete)
  2389.     {
  2390.       int jj = 0;
  2391.       int idx = 0;
  2392.       for (int j = 0; j < nc; j++)
  2393.         {
  2394.           if (j == jv.elem (idx))
  2395.         idx++;
  2396.           else
  2397.         {
  2398.           for (int i = 0; i < nr; i++)
  2399.             new_matrix->elem (i, jj) = complex_matrix->elem (i, j);
  2400.           jj++;
  2401.         }
  2402.         }
  2403.     }
  2404.       delete complex_matrix;
  2405.       complex_matrix = new_matrix;
  2406.     }
  2407.   else
  2408.     panic_impossible ();
  2409. }
  2410.  
  2411. void
  2412. TC_REP::delete_columns (Range& rj)
  2413. {
  2414.   rj.sort ();
  2415.   int num_to_delete = rj.nelem ();
  2416.  
  2417.   int nr = rows ();
  2418.   int nc = columns ();
  2419.  
  2420. // If deleting all columns of a row vector, make result 0x0.
  2421.   if (nr == 1 && num_to_delete == nc)
  2422.     nr = 0;
  2423.  
  2424.   double jb = rj.base ();
  2425.   double jinc = rj.inc ();
  2426.  
  2427.   int max_idx = tree_to_mat_idx (rj.max ());
  2428.  
  2429.   if (type_tag == matrix_constant)
  2430.     {
  2431.       Matrix *new_matrix = new Matrix (nr, nc-num_to_delete);
  2432.       if (nc > num_to_delete)
  2433.     {
  2434.       int jj = 0;
  2435.       int idx = 0;
  2436.       for (int j = 0; j < nc; j++)
  2437.         {
  2438.           double jtmp = jb + idx * jinc;
  2439.           int col = tree_to_mat_idx (jtmp);
  2440.  
  2441.           if (j == col && col <= max_idx)
  2442.         idx++;
  2443.           else
  2444.         {
  2445.           for (int i = 0; i < nr; i++)
  2446.             new_matrix->elem (i, jj) = matrix->elem (i, j);
  2447.           jj++;
  2448.         }
  2449.         }
  2450.     }
  2451.       delete matrix;
  2452.       matrix = new_matrix;
  2453.     }
  2454.   else if (type_tag == complex_matrix_constant)
  2455.     {
  2456.       ComplexMatrix *new_matrix = new ComplexMatrix (nr, nc-num_to_delete);
  2457.       if (nc > num_to_delete)
  2458.     {
  2459.       int jj = 0;
  2460.       int idx = 0;
  2461.       for (int j = 0; j < nc; j++)
  2462.         {
  2463.           double jtmp = jb + idx * jinc;
  2464.           int col = tree_to_mat_idx (jtmp);
  2465.  
  2466.           if (j == col && col <= max_idx)
  2467.         idx++;
  2468.           else
  2469.         {
  2470.           for (int i = 0; i < nr; i++)
  2471.             new_matrix->elem (i, jj) = complex_matrix->elem (i, j);
  2472.           jj++;
  2473.         }
  2474.         }
  2475.     }
  2476.       delete complex_matrix;
  2477.       complex_matrix = new_matrix;
  2478.     }
  2479.   else
  2480.     panic_impossible ();
  2481. }
  2482.  
  2483. /*
  2484. ;;; Local Variables: ***
  2485. ;;; mode: C++ ***
  2486. ;;; page-delimiter: "^/\\*" ***
  2487. ;;; End: ***
  2488. */
  2489.