home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / octave-1.1.1p1-base.tgz / octave-1.1.1p1-base.tar / fsf / octave / src / tc-rep.cc < prev    next >
C/C++ Source or Header  |  1995-01-30  |  41KB  |  2,114 lines

  1. // tc-rep.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. static int
  53. any_element_is_complex (const ComplexMatrix& a)
  54. {
  55.   int nr = a.rows ();
  56.   int nc = a.columns ();
  57.   for (int j = 0; j < nc; j++)
  58.     for (int i = 0; i < nr; i++)
  59.       if (imag (a.elem (i, j)) != 0.0)
  60.     return 1;
  61.   return 0;
  62. }
  63.  
  64. // The real representation of constants.
  65.  
  66. TC_REP::tree_constant_rep (void)
  67. {
  68.   type_tag = unknown_constant;
  69.   orig_text = 0;
  70. }
  71.  
  72. TC_REP::tree_constant_rep (double d)
  73. {
  74.   scalar = d;
  75.   type_tag = scalar_constant;
  76.   orig_text = 0;
  77. }
  78.  
  79. TC_REP::tree_constant_rep (const Matrix& m)
  80. {
  81.   if (m.rows () == 1 && m.columns () == 1)
  82.     {
  83.       scalar = m.elem (0, 0);
  84.       type_tag = scalar_constant;
  85.     }
  86.   else
  87.     {
  88.       matrix = new Matrix (m);
  89.       type_tag = matrix_constant;
  90.     }
  91.   orig_text = 0;
  92. }
  93.  
  94. TC_REP::tree_constant_rep (const DiagMatrix& d)
  95. {
  96.   if (d.rows () == 1 && d.columns () == 1)
  97.     {
  98.       scalar = d.elem (0, 0);
  99.       type_tag = scalar_constant;
  100.     }
  101.   else
  102.     {
  103.       matrix = new Matrix (d);
  104.       type_tag = matrix_constant;
  105.     }
  106.   orig_text = 0;
  107. }
  108.  
  109. TC_REP::tree_constant_rep (const RowVector& v, int prefer_column_vector)
  110. {
  111.   int len = v.capacity ();
  112.   if (len == 1)
  113.     {
  114.       scalar = v.elem (0);
  115.       type_tag = scalar_constant;
  116.     }
  117.   else
  118.     {
  119.       int pcv = (prefer_column_vector < 0)
  120.     ? user_pref.prefer_column_vectors
  121.       : prefer_column_vector;
  122.  
  123.       if (pcv)
  124.     {
  125.       Matrix m (len, 1);
  126.       for (int i = 0; i < len; i++)
  127.         m.elem (i, 0) = v.elem (i);
  128.       matrix = new Matrix (m);
  129.       type_tag = matrix_constant;
  130.     }
  131.       else
  132.     {
  133.       Matrix m (1, len);
  134.       for (int i = 0; i < len; i++)
  135.         m.elem (0, i) = v.elem (i);
  136.       matrix = new Matrix (m);
  137.       type_tag = matrix_constant;
  138.     }
  139.     }
  140.   orig_text = 0;
  141. }
  142.  
  143. TC_REP::tree_constant_rep (const ColumnVector& v, int prefer_column_vector)
  144. {
  145.   int len = v.capacity ();
  146.   if (len == 1)
  147.     {
  148.       scalar = v.elem (0);
  149.       type_tag = scalar_constant;
  150.     }
  151.   else
  152.     {
  153.       int pcv = (prefer_column_vector < 0)
  154.     ? user_pref.prefer_column_vectors
  155.       : prefer_column_vector;
  156.  
  157.       if (pcv)
  158.     {
  159.       Matrix m (len, 1);
  160.       for (int i = 0; i < len; i++)
  161.         m.elem (i, 0) = v.elem (i);
  162.       matrix = new Matrix (m);
  163.       type_tag = matrix_constant;
  164.     }
  165.       else
  166.     {
  167.       Matrix m (1, len);
  168.       for (int i = 0; i < len; i++)
  169.         m.elem (0, i) = v.elem (i);
  170.       matrix = new Matrix (m);
  171.       type_tag = matrix_constant;
  172.     }
  173.     }
  174.   orig_text = 0;
  175. }
  176.  
  177. TC_REP::tree_constant_rep (const Complex& c)
  178. {
  179.   complex_scalar = new Complex (c);
  180.   type_tag = complex_scalar_constant;
  181.   orig_text = 0;
  182. }
  183.  
  184. TC_REP::tree_constant_rep (const ComplexMatrix& m)
  185. {
  186.   if (m.rows () == 1 && m.columns () == 1)
  187.     {
  188.       complex_scalar = new Complex (m.elem (0, 0));
  189.       type_tag = complex_scalar_constant;
  190.     }
  191.   else
  192.     {
  193.       complex_matrix = new ComplexMatrix (m);
  194.       type_tag = complex_matrix_constant;
  195.     }
  196.   orig_text = 0;
  197. }
  198.  
  199. TC_REP::tree_constant_rep (const ComplexDiagMatrix& d)
  200. {
  201.   if (d.rows () == 1 && d.columns () == 1)
  202.     {
  203.       complex_scalar = new Complex (d.elem (0, 0));
  204.       type_tag = complex_scalar_constant;
  205.     }
  206.   else
  207.     {
  208.       complex_matrix = new ComplexMatrix (d);
  209.       type_tag = complex_matrix_constant;
  210.     }
  211.   orig_text = 0;
  212. }
  213.  
  214. TC_REP::tree_constant_rep (const ComplexRowVector& v,
  215.                int prefer_column_vector) 
  216. {
  217.   int len = v.capacity ();
  218.   if (len == 1)
  219.     {
  220.       complex_scalar = new Complex (v.elem (0));
  221.       type_tag = complex_scalar_constant;
  222.     }
  223.   else
  224.     {
  225.       int pcv = (prefer_column_vector < 0)
  226.     ? user_pref.prefer_column_vectors
  227.       : prefer_column_vector;
  228.  
  229.       if (pcv)
  230.     {
  231.       ComplexMatrix m (len, 1);
  232.       for (int i = 0; i < len; i++)
  233.         m.elem (i, 0) = v.elem (i);
  234.       complex_matrix = new ComplexMatrix (m);
  235.       type_tag = complex_matrix_constant;
  236.     }
  237.       else
  238.     {
  239.       ComplexMatrix m (1, len);
  240.       for (int i = 0; i < len; i++)
  241.         m.elem (0, i) = v.elem (i);
  242.       complex_matrix = new ComplexMatrix (m);
  243.       type_tag = complex_matrix_constant;
  244.     }
  245.     }
  246.   orig_text = 0;
  247. }
  248.  
  249. TC_REP::tree_constant_rep (const ComplexColumnVector& v, int
  250.                prefer_column_vector)
  251. {
  252.   int len = v.capacity ();
  253.   if (len == 1)
  254.     {
  255.       complex_scalar = new Complex (v.elem (0));
  256.       type_tag = complex_scalar_constant;
  257.     }
  258.   else
  259.     {
  260.       int pcv = (prefer_column_vector < 0)
  261.     ? user_pref.prefer_column_vectors
  262.       : prefer_column_vector;
  263.  
  264.       if (pcv)
  265.     {
  266.       ComplexMatrix m (len, 1);
  267.       for (int i = 0; i < len; i++)
  268.         m.elem (i, 0) = v.elem (i);
  269.       complex_matrix = new ComplexMatrix (m);
  270.       type_tag = complex_matrix_constant;
  271.     }
  272.       else
  273.     {
  274.       ComplexMatrix m (1, len);
  275.       for (int i = 0; i < len; i++)
  276.         m.elem (0, i) = v.elem (i);
  277.       complex_matrix = new ComplexMatrix (m);
  278.       type_tag = complex_matrix_constant;
  279.     }
  280.     }
  281.   orig_text = 0;
  282. }
  283.  
  284. TC_REP::tree_constant_rep (const char *s)
  285. {
  286.   string = strsave (s);
  287.   type_tag = string_constant;
  288.   orig_text = 0;
  289. }
  290.  
  291. TC_REP::tree_constant_rep (double b, double l, double i)
  292. {
  293.   range = new Range (b, l, i);
  294.   int nel = range->nelem ();
  295.   if (nel > 1)
  296.     type_tag = range_constant;
  297.   else
  298.     {
  299.       delete range;
  300.       if (nel == 1)
  301.     {
  302.       scalar = b;
  303.       type_tag = scalar_constant;
  304.     }
  305.       else if (nel == 0)
  306.     {
  307.       matrix = new Matrix ();
  308.       type_tag = matrix_constant;
  309.     }
  310.       else
  311.     {
  312.       type_tag = unknown_constant;
  313.       if (nel == -1)
  314.         ::error ("number of elements in range exceeds INT_MAX");
  315.       else
  316.         ::error ("invalid range");
  317.     }
  318.     }
  319.   orig_text = 0;
  320. }
  321.  
  322. TC_REP::tree_constant_rep (const Range& r)
  323. {
  324.   int nel = r.nelem ();
  325.   if (nel > 1)
  326.     {
  327.       range = new Range (r);
  328.       type_tag = range_constant;
  329.     }
  330.   else if (nel == 1)
  331.     {
  332.       scalar = r.base ();
  333.       type_tag = scalar_constant;
  334.     }
  335.   else if (nel == 0)
  336.     {
  337.       matrix = new Matrix ();
  338.       type_tag = matrix_constant;
  339.     }
  340.   else
  341.     {
  342.       type_tag = unknown_constant;
  343.       if (nel == -1)
  344.     ::error ("number of elements in range exceeds INT_MAX");
  345.       else
  346.     ::error ("invalid range");
  347.     }
  348.  
  349.   orig_text = 0;
  350. }
  351.  
  352. TC_REP::tree_constant_rep (const Octave_map& m)
  353. {
  354.   a_map = new Octave_map (m);
  355.   type_tag = map_constant;
  356.   orig_text = 0;
  357. }
  358.  
  359. TC_REP::tree_constant_rep (TC_REP::constant_type t)
  360. {
  361.   assert (t == magic_colon || t == all_va_args);
  362.   type_tag = t;
  363.   orig_text = 0;
  364. }
  365.  
  366. TC_REP::tree_constant_rep (const tree_constant_rep& t)
  367. {
  368.   type_tag = t.type_tag;
  369.  
  370.   switch (t.type_tag)
  371.     {
  372.     case unknown_constant:
  373.       break;
  374.  
  375.     case scalar_constant:
  376.       scalar = t.scalar;
  377.       break;
  378.  
  379.     case matrix_constant:
  380.       matrix = new Matrix (*(t.matrix));
  381.       break;
  382.  
  383.     case string_constant:
  384.       string = strsave (t.string);
  385.       break;
  386.  
  387.     case complex_matrix_constant:
  388.       complex_matrix = new ComplexMatrix (*(t.complex_matrix));
  389.       break;
  390.  
  391.     case complex_scalar_constant:
  392.       complex_scalar = new Complex (*(t.complex_scalar));
  393.       break;
  394.  
  395.     case range_constant:
  396.       range = new Range (*(t.range));
  397.       break;
  398.  
  399.     case map_constant:
  400.       a_map = new Octave_map (*(t.a_map));
  401.       break;
  402.  
  403.     case magic_colon:
  404.     case all_va_args:
  405.       break;
  406.     }
  407.  
  408.   orig_text = strsave (t.orig_text);
  409. }
  410.  
  411. TC_REP::~tree_constant_rep (void)
  412. {
  413.   switch (type_tag)
  414.     {
  415.     case matrix_constant:
  416.       delete matrix;
  417.       break;
  418.  
  419.     case complex_scalar_constant:
  420.       delete complex_scalar;
  421.       break;
  422.  
  423.     case complex_matrix_constant:
  424.       delete complex_matrix;
  425.       break;
  426.  
  427.     case string_constant:
  428.       delete [] string;
  429.       break;
  430.  
  431.     case range_constant:
  432.       delete range;
  433.       break;
  434.  
  435.     case map_constant:
  436.       delete a_map;
  437.       break;
  438.  
  439.     case unknown_constant:
  440.     case scalar_constant:
  441.     case magic_colon:
  442.     case all_va_args:
  443.       break;
  444.     }
  445.  
  446.   delete [] orig_text;
  447. }
  448.  
  449. #if defined (MDEBUG)
  450. void *
  451. TC_REP::operator new (size_t size)
  452. {
  453.   tree_constant_rep *p = ::new tree_constant_rep;
  454.   cerr << "TC_REP::new(): " << p << "\n";
  455.   return p;
  456. }
  457.  
  458. void
  459. TC_REP::operator delete (void *p, size_t size)
  460. {
  461.   cerr << "TC_REP::delete(): " << p << "\n";
  462.   ::delete p;
  463. }
  464. #endif
  465.  
  466. int
  467. TC_REP::rows (void) const
  468. {
  469.   int retval = -1;
  470.  
  471.   switch (type_tag)
  472.     {
  473.     case scalar_constant:
  474.     case complex_scalar_constant:
  475.       retval = 1;
  476.       break;
  477.  
  478.     case string_constant:
  479.     case range_constant:
  480.       retval = (columns () > 0);
  481.       break;
  482.  
  483.     case matrix_constant:
  484.       retval = matrix->rows ();
  485.       break;
  486.  
  487.     case complex_matrix_constant:
  488.       retval = complex_matrix->rows ();
  489.       break;
  490.  
  491.     default:
  492.       break;
  493.     }
  494.  
  495.   return retval;
  496. }
  497.  
  498. int
  499. TC_REP::columns (void) const
  500. {
  501.   int retval = -1;
  502.  
  503.   switch (type_tag)
  504.     {
  505.     case scalar_constant:
  506.     case complex_scalar_constant:
  507.       retval = 1;
  508.       break;
  509.  
  510.     case matrix_constant:
  511.       retval = matrix->columns ();
  512.       break;
  513.  
  514.     case complex_matrix_constant:
  515.       retval = complex_matrix->columns ();
  516.       break;
  517.  
  518.     case string_constant:
  519.       retval = strlen (string);
  520.       break;
  521.  
  522.     case range_constant:
  523.       retval = range->nelem ();
  524.       break;
  525.  
  526.     default:
  527.       break;
  528.     }
  529.  
  530.   return retval;
  531. }
  532.  
  533. tree_constant
  534. TC_REP::all (void) const
  535. {
  536.   tree_constant retval;
  537.  
  538.   if (error_state)
  539.     return retval;
  540.  
  541.   if (! is_numeric_type ())
  542.     {
  543.       tree_constant tmp = make_numeric ();
  544.  
  545.       if (error_state)
  546.     return retval;
  547.  
  548.       return tmp.all ();
  549.     }
  550.  
  551.   switch (type_tag)
  552.     {
  553.     case scalar_constant:
  554.       {
  555.     double status = (scalar != 0.0);
  556.     retval = tree_constant (status);
  557.       }
  558.       break;
  559.  
  560.     case matrix_constant:
  561.       {
  562.     Matrix m = matrix->all ();
  563.     retval = tree_constant (m);
  564.       }
  565.       break;
  566.  
  567.     case complex_scalar_constant:
  568.       {
  569.     double status = (*complex_scalar != 0.0);
  570.     retval = tree_constant (status);
  571.       }
  572.       break;
  573.  
  574.     case complex_matrix_constant:
  575.       {
  576.     Matrix m = complex_matrix->all ();
  577.     retval = tree_constant (m);
  578.       }
  579.       break;
  580.  
  581.     default:
  582.       gripe_wrong_type_arg ("all", *this);
  583.       break;
  584.     }
  585.  
  586.   return retval;
  587. }
  588.  
  589. tree_constant
  590. TC_REP::any (void) const
  591. {
  592.   tree_constant retval;
  593.  
  594.   if (error_state)
  595.     return retval;
  596.  
  597.   if (! is_numeric_type ())
  598.     {
  599.       tree_constant tmp = make_numeric ();
  600.  
  601.       if (error_state)
  602.     return retval;
  603.  
  604.       return tmp.any ();
  605.     }
  606.  
  607.   switch (type_tag)
  608.     {
  609.     case scalar_constant:
  610.       {
  611.     double status = (scalar != 0.0);
  612.     retval = tree_constant (status);
  613.       }
  614.       break;
  615.  
  616.     case matrix_constant:
  617.       {
  618.     Matrix m = matrix->any ();
  619.     retval = tree_constant (m);
  620.       }
  621.       break;
  622.  
  623.     case complex_scalar_constant:
  624.       {
  625.     double status = (*complex_scalar != 0.0);
  626.     retval = tree_constant (status);
  627.       }
  628.       break;
  629.  
  630.     case complex_matrix_constant:
  631.       {
  632.     Matrix m = complex_matrix->any ();
  633.     retval = tree_constant (m);
  634.       }
  635.       break;
  636.  
  637.     default:
  638.       gripe_wrong_type_arg ("any", *this);
  639.       break;
  640.     }
  641.  
  642.   return retval;
  643. }
  644.  
  645. int
  646. TC_REP::valid_as_scalar_index (void) const
  647. {
  648.   return (type_tag == magic_colon
  649.       || (type_tag == scalar_constant 
  650.           && ! xisnan (scalar)
  651.           && NINT (scalar) == 1)
  652.       || (type_tag == range_constant
  653.           && range->nelem () == 1
  654.           && ! xisnan (range->base ())
  655.           && NINT (range->base ()) == 1));
  656. }
  657.  
  658. int
  659. TC_REP::valid_as_zero_index (void) const
  660. {
  661.   return ((type_tag == scalar_constant
  662.        && ! xisnan (scalar)
  663.        && NINT (scalar) == 0)
  664.       || (type_tag == matrix_constant
  665.           && matrix->rows () == 0
  666.           && matrix->columns () == 0)
  667.       || (type_tag == range_constant
  668.           && range->nelem () == 1
  669.           && ! xisnan (range->base ())
  670.           && NINT (range->base ()) == 0));
  671. }
  672.  
  673. int
  674. TC_REP::is_true (void) const
  675. {
  676.   int retval = 0;
  677.  
  678.   if (error_state)
  679.     return retval;
  680.  
  681.   if (! is_numeric_type ())
  682.     {
  683.       tree_constant tmp = make_numeric ();
  684.  
  685.       if (error_state)
  686.     return retval;
  687.  
  688.       return tmp.is_true ();
  689.     }
  690.  
  691.   switch (type_tag)
  692.     {
  693.     case scalar_constant:
  694.       retval = (scalar != 0.0);
  695.       break;
  696.  
  697.     case matrix_constant:
  698.       {
  699.     Matrix m = (matrix->all ()) . all ();
  700.     retval = (m.rows () == 1
  701.           && m.columns () == 1
  702.           && m.elem (0, 0) != 0.0);
  703.       }
  704.       break;
  705.  
  706.     case complex_scalar_constant:
  707.       retval = (*complex_scalar != 0.0);
  708.       break;
  709.  
  710.     case complex_matrix_constant:
  711.       {
  712.     Matrix m = (complex_matrix->all ()) . all ();
  713.     retval = (m.rows () == 1
  714.           && m.columns () == 1
  715.           && m.elem (0, 0) != 0.0);
  716.       }
  717.       break;
  718.  
  719.     default:
  720.       gripe_wrong_type_arg (0, *this);
  721.       break;
  722.     }
  723.  
  724.   return retval;
  725. }
  726.  
  727. static void
  728. warn_implicit_conversion (const char *from, const char *to)
  729. {
  730.   warning ("implicit conversion from %s to %s", from, to);
  731. }
  732.  
  733. double
  734. TC_REP::double_value (int force_string_conversion) const
  735. {
  736.   double retval = octave_NaN;
  737.  
  738.   switch (type_tag)
  739.     {
  740.     case scalar_constant:
  741.       retval = scalar;
  742.       break;
  743.  
  744.     case matrix_constant:
  745.       {
  746.     if (user_pref.do_fortran_indexing && rows () > 0 && columns () > 0)
  747.       retval = matrix->elem (0, 0);
  748.     else
  749.       gripe_invalid_conversion ("real matrix", "real scalar");
  750.       }
  751.       break;
  752.  
  753.     case complex_matrix_constant:
  754.     case complex_scalar_constant:
  755.       {
  756.     int flag = user_pref.ok_to_lose_imaginary_part;
  757.  
  758.     if (flag < 0)
  759.       warn_implicit_conversion ("complex scalar", "real scalar");
  760.  
  761.     if (flag)
  762.       {
  763.         if (type_tag == complex_scalar_constant)
  764.           retval = ::real (*complex_scalar);
  765.         else if (type_tag == complex_matrix_constant)
  766.           {
  767.         if (user_pref.do_fortran_indexing
  768.             && rows () > 0 && columns () > 0)
  769.           retval = ::real (complex_matrix->elem (0, 0));
  770.         else
  771.           gripe_invalid_conversion ("complex matrix", "real scalar");
  772.           }
  773.         else
  774.           panic_impossible ();
  775.       }
  776.     else
  777.       gripe_invalid_conversion ("complex scalar", "real scalar");
  778.       }
  779.       break;
  780.  
  781.     case string_constant:
  782.       {
  783.     int flag = force_string_conversion;
  784.     if (! flag)
  785.       flag = user_pref.implicit_str_to_num_ok;
  786.  
  787.     if (flag < 0)
  788.       warn_implicit_conversion ("string", "real scalar");
  789.  
  790.     int len = strlen (string);
  791.     if (flag && (len == 1 || (len > 1 && user_pref.do_fortran_indexing)))
  792.       retval = toascii ((int) string[0]);
  793.     else
  794.       gripe_invalid_conversion ("string", "real scalar");
  795.       }
  796.       break;
  797.  
  798.     case range_constant:
  799.       {
  800.     int nel = range->nelem ();
  801.     if (nel == 1 || (nel > 1 && user_pref.do_fortran_indexing))
  802.       retval = range->base ();
  803.     else
  804.       gripe_invalid_conversion ("range", "real scalar");
  805.       }
  806.       break;
  807.  
  808.     default:
  809.       gripe_invalid_conversion (type_as_string (), "real scalar");
  810.       break;
  811.     }
  812.  
  813.   return retval;
  814. }
  815.  
  816. Matrix
  817. TC_REP::matrix_value (int force_string_conversion) const
  818. {
  819.   Matrix retval;
  820.  
  821.   switch (type_tag)
  822.     {
  823.     case scalar_constant:
  824.       retval = Matrix (1, 1, scalar);
  825.       break;
  826.  
  827.     case matrix_constant:
  828.       retval = *matrix;
  829.       break;
  830.  
  831.     case complex_scalar_constant:
  832.     case complex_matrix_constant:
  833.       {
  834.     int flag = user_pref.ok_to_lose_imaginary_part;
  835.     if (flag < 0)
  836.       warn_implicit_conversion ("complex matrix", "real matrix");
  837.  
  838.     if (flag)
  839.       {
  840.         if (type_tag == complex_scalar_constant)
  841.           retval = Matrix (1, 1, ::real (*complex_scalar));
  842.         else if (type_tag == complex_matrix_constant)
  843.           retval = ::real (*complex_matrix);
  844.         else
  845.           panic_impossible ();
  846.       }
  847.     else
  848.       gripe_invalid_conversion ("complex matrix", "real matrix");
  849.       }
  850.       break;
  851.  
  852.     case string_constant:
  853.       {
  854.     int flag = force_string_conversion;
  855.     if (! flag)
  856.       flag = user_pref.implicit_str_to_num_ok;
  857.  
  858.     if (flag < 0)
  859.       warn_implicit_conversion ("string", "real matrix");
  860.  
  861.     if (flag)
  862.       {
  863.         int len = strlen (string);
  864.  
  865.         if (len > 0)
  866.           {
  867.         retval.resize (1, len);
  868.  
  869.         for (int i = 0; i < len; i++)
  870.           retval.elem (0, i) = toascii ((int) string[i]);
  871.           }
  872.         else
  873.           retval = Matrix ();
  874.       }
  875.     else
  876.       gripe_invalid_conversion ("string", "real matrix");
  877.       }
  878.       break;
  879.  
  880.     case range_constant:
  881.       retval = range->matrix_value ();
  882.       break;
  883.  
  884.     default:
  885.       gripe_invalid_conversion (type_as_string (), "real matrix");
  886.       break;
  887.     }
  888.  
  889.   return retval;
  890. }
  891.  
  892. Complex
  893. TC_REP::complex_value (int force_string_conversion) const
  894. {
  895.   Complex retval (octave_NaN, octave_NaN);
  896.  
  897.   switch (type_tag)
  898.     {
  899.     case complex_scalar_constant:
  900.       retval = *complex_scalar;
  901.       break;
  902.  
  903.     case scalar_constant:
  904.       retval = scalar;
  905.       break;
  906.  
  907.     case complex_matrix_constant:
  908.     case matrix_constant:
  909.       {
  910.     if (user_pref.do_fortran_indexing && rows () > 0 && columns () > 0)
  911.       {
  912.         if (type_tag == complex_matrix_constant)
  913.           retval = complex_matrix->elem (0, 0);
  914.         else
  915.           retval = matrix->elem (0, 0);
  916.       }
  917.     else
  918.       gripe_invalid_conversion ("real matrix", "real scalar");
  919.       }
  920.       break;
  921.  
  922.     case string_constant:
  923.       {
  924.     int flag = force_string_conversion;
  925.     if (! flag)
  926.       flag = user_pref.implicit_str_to_num_ok;
  927.  
  928.     if (flag < 0)
  929.       warn_implicit_conversion ("string", "complex scalar");
  930.  
  931.     int len = strlen (string);
  932.     if (flag && (len == 1 || (len > 1 && user_pref.do_fortran_indexing)))
  933.       retval = toascii ((int) string[0]);
  934.     else
  935.       gripe_invalid_conversion ("string", "complex scalar");
  936.       }
  937.       break;
  938.  
  939.     case range_constant:
  940.       {
  941.     int nel = range->nelem ();
  942.     if (nel == 1 || (nel > 1 && user_pref.do_fortran_indexing))
  943.       retval = range->base ();
  944.     else
  945.       gripe_invalid_conversion ("range", "complex scalar");
  946.       }
  947.       break;
  948.  
  949.     default:
  950.       gripe_invalid_conversion (type_as_string (), "complex scalar");
  951.       break;
  952.     }
  953.  
  954.   return retval;
  955. }
  956.  
  957. ComplexMatrix
  958. TC_REP::complex_matrix_value (int force_string_conversion) const
  959. {
  960.   ComplexMatrix retval;
  961.  
  962.   switch (type_tag)
  963.     {
  964.     case scalar_constant:
  965.       retval = ComplexMatrix (1, 1, Complex (scalar));
  966.       break;
  967.  
  968.     case complex_scalar_constant:
  969.       retval = ComplexMatrix (1, 1, *complex_scalar);
  970.       break;
  971.  
  972.     case matrix_constant:
  973.       retval = ComplexMatrix (*matrix);
  974.       break;
  975.  
  976.     case complex_matrix_constant:
  977.       retval = *complex_matrix;
  978.       break;
  979.  
  980.     case string_constant:
  981.       {
  982.     int flag = force_string_conversion;
  983.     if (! flag)
  984.       flag = user_pref.implicit_str_to_num_ok;
  985.  
  986.     if (flag < 0)
  987.       warn_implicit_conversion ("string", "complex matrix");
  988.  
  989.     if (flag)
  990.       {
  991.         int len = strlen (string);
  992.  
  993.         retval.resize (1, len);
  994.  
  995.         if (len > 1)
  996.           {
  997.         for (int i = 0; i < len; i++)
  998.           retval.elem (0, i) = toascii ((int) string[i]);
  999.           }
  1000.         else if (len == 1)
  1001.           retval.elem (0, 0) = toascii ((int) string[0]);
  1002.         else
  1003.           panic_impossible ();
  1004.       }
  1005.     else
  1006.       gripe_invalid_conversion ("string", "real matrix");
  1007.       }
  1008.       break;
  1009.  
  1010.     case range_constant:
  1011.       retval = range->matrix_value ();
  1012.       break;
  1013.  
  1014.     default:
  1015.       gripe_invalid_conversion (type_as_string (), "complex matrix");
  1016.       break;
  1017.     }
  1018.  
  1019.   return retval;
  1020. }
  1021.  
  1022. char *
  1023. TC_REP::string_value (void) const
  1024. {
  1025.   if (type_tag == string_constant)
  1026.     return string;
  1027.   else
  1028.     {
  1029.       gripe_invalid_conversion (type_as_string (), "string");
  1030.       return 0;
  1031.     }
  1032. }
  1033.  
  1034. Range
  1035. TC_REP::range_value (void) const
  1036. {
  1037.   assert (type_tag == range_constant);
  1038.   return *range;
  1039. }
  1040.  
  1041. Octave_map
  1042. TC_REP::map_value (void) const
  1043. {
  1044.   assert (type_tag == map_constant);
  1045.   return *a_map;
  1046. }
  1047.  
  1048. tree_constant&
  1049. TC_REP::lookup_map_element (const char *name, int insert)
  1050. {
  1051.   static tree_constant retval;
  1052.  
  1053.   if (type_tag == map_constant)
  1054.     {
  1055.       Pix idx = a_map->seek (name);
  1056.  
  1057.       if (idx)
  1058.     return a_map->contents (idx);
  1059.       else if (insert)
  1060.     return (*a_map) [name];
  1061.       else
  1062.     error ("structure has no member `%s'", name);
  1063.     }
  1064.   else
  1065.     error ("invalid structure access attempted");
  1066.  
  1067.   return retval;
  1068. }
  1069.  
  1070. // This could be made more efficient by doing all the work here rather
  1071. // than relying on matrix_value() to do any possible type conversions.
  1072.  
  1073. ColumnVector
  1074. TC_REP::vector_value (int force_string_conversion,
  1075.               int force_vector_conversion) const
  1076. {
  1077.   ColumnVector retval;
  1078.  
  1079.   Matrix m = matrix_value (force_string_conversion);
  1080.  
  1081.   if (error_state)
  1082.     return retval;
  1083.  
  1084.   int nr = m.rows ();
  1085.   int nc = m.columns ();
  1086.   if (nr == 1)
  1087.     {
  1088.       retval.resize (nc);
  1089.       for (int i = 0; i < nc; i++)
  1090.     retval.elem (i) = m (0, i);
  1091.     }
  1092.   else if (nc == 1)
  1093.     {
  1094.       retval.resize (nr);
  1095.       for (int i = 0; i < nr; i++)
  1096.     retval.elem (i) = m.elem (i, 0);
  1097.     }
  1098.   else if (nr > 0 && nc > 0
  1099.        && (user_pref.do_fortran_indexing || force_vector_conversion))
  1100.     {
  1101.       retval.resize (nr * nc);
  1102.       int k = 0;
  1103.       for (int j = 0; j < nc; j++)
  1104.     for (int i = 0; i < nr; i++)
  1105.       retval.elem (k++) = m.elem (i, j);
  1106.     }
  1107.   else
  1108.     gripe_invalid_conversion ("real matrix", "real vector");
  1109.  
  1110.   return retval;
  1111. }
  1112.  
  1113. // This could be made more efficient by doing all the work here rather
  1114. // than relying on complex_matrix_value() to do any possible type
  1115. // conversions.
  1116.  
  1117. ComplexColumnVector
  1118. TC_REP::complex_vector_value (int force_string_conversion,
  1119.                   int force_vector_conversion) const
  1120. {
  1121.   ComplexColumnVector retval;
  1122.  
  1123.   ComplexMatrix m = complex_matrix_value (force_string_conversion);
  1124.  
  1125.   if (error_state)
  1126.     return retval;
  1127.  
  1128.   int nr = m.rows ();
  1129.   int nc = m.columns ();
  1130.   if (nr == 1)
  1131.     {
  1132.       retval.resize (nc);
  1133.       for (int i = 0; i < nc; i++)
  1134.     retval.elem (i) = m (0, i);
  1135.     }
  1136.   else if (nc == 1)
  1137.     {
  1138.       retval.resize (nr);
  1139.       for (int i = 0; i < nr; i++)
  1140.     retval.elem (i) = m.elem (i, 0);
  1141.     }
  1142.   else if (nr > 0 && nc > 0
  1143.        && (user_pref.do_fortran_indexing || force_vector_conversion))
  1144.     {
  1145.       retval.resize (nr * nc);
  1146.       int k = 0;
  1147.       for (int j = 0; j < nc; j++)
  1148.     for (int i = 0; i < nr; i++)
  1149.       retval.elem (k++) = m.elem (i, j);
  1150.     }
  1151.   else
  1152.     gripe_invalid_conversion ("complex matrix", "complex vector");
  1153.  
  1154.   return retval;
  1155. }
  1156.  
  1157. tree_constant
  1158. TC_REP::convert_to_str (void) const
  1159. {
  1160.   tree_constant retval;
  1161.  
  1162.   switch (type_tag)
  1163.     {
  1164.     case complex_scalar_constant:
  1165.     case scalar_constant:
  1166.       {
  1167.     double d = double_value ();
  1168.  
  1169.     if (xisnan (d))
  1170.       {
  1171.         ::error ("invalid conversion from NaN to character");
  1172.         return retval;
  1173.       }
  1174.     else
  1175.       {
  1176.         int i = NINT (d);
  1177. // Warn about out of range conversions?
  1178.         char s[2];
  1179.         s[0] = (char) i;
  1180.         s[1] = '\0';
  1181.         retval = tree_constant (s);
  1182.       }
  1183.       }
  1184.       break;
  1185.  
  1186.     case complex_matrix_constant:
  1187.     case matrix_constant:
  1188.       {
  1189.     if (rows () == 0 && columns () == 0)
  1190.       {
  1191.         char s = '\0';
  1192.         retval = tree_constant (&s);
  1193.       }
  1194.     else
  1195.       {
  1196.         ColumnVector v = vector_value ();
  1197.         int len = v.length ();
  1198.         if (len == 0)
  1199.           {
  1200.         char s = '\0';
  1201.         retval = tree_constant (&s);
  1202.           }
  1203.         else
  1204.           {
  1205.         char *s = new char [len+1];
  1206.         s[len] = '\0';
  1207.         for (int i = 0; i < len; i++)
  1208.           {
  1209.             double d = v.elem (i);
  1210.  
  1211.             if (xisnan (d))
  1212.               {
  1213.             ::error ("invalid conversion from NaN to character");
  1214.             delete [] s;
  1215.             return retval;
  1216.               }
  1217.             else
  1218.               {
  1219.             int ival = NINT (d);
  1220. // Warn about out of range conversions?
  1221.             s[i] = (char) ival;
  1222.               }
  1223.           }
  1224.         retval = tree_constant (s);
  1225.         delete [] s;
  1226.           }
  1227.       }
  1228.       }
  1229.       break;
  1230.  
  1231.     case range_constant:
  1232.       {
  1233.     Range r = range_value ();
  1234.     double b = r.base ();
  1235.     double incr = r.inc ();
  1236.     int nel = r.nelem ();
  1237.     char *s = new char [nel+1];
  1238.     s[nel] = '\0';
  1239.     for (int i = 0; i < nel; i++)
  1240.       {
  1241.         double d = b + i * incr;
  1242.  
  1243.         if (xisnan (d))
  1244.           {
  1245.         ::error ("invalid conversion from NaN to character");
  1246.         delete [] s;
  1247.         return retval;
  1248.           }
  1249.         else
  1250.           {
  1251.         int ival = NINT (d);
  1252. // Warn about out of range conversions?
  1253.         s[i] = (char) ival;
  1254.           }
  1255.       }
  1256.     retval = tree_constant (s);
  1257.     delete [] s;
  1258.       }
  1259.       break;
  1260.  
  1261.     case string_constant:
  1262.       retval = string;
  1263.       break;
  1264.  
  1265.     default:
  1266.       gripe_invalid_conversion (type_as_string (), "string");
  1267.       break;
  1268.     }
  1269.  
  1270.   return retval;
  1271. }
  1272.  
  1273. void
  1274. TC_REP::convert_to_row_or_column_vector (void)
  1275. {
  1276.   assert (type_tag == matrix_constant || type_tag == complex_matrix_constant);
  1277.  
  1278.   int nr = rows ();
  1279.   int nc = columns ();
  1280.  
  1281.   if (nr == 1 || nc == 1)
  1282.     return;
  1283.  
  1284.   int len = nr * nc;
  1285.  
  1286.   assert (len > 0);
  1287.  
  1288.   int new_nr = 1;
  1289.   int new_nc = 1;
  1290.  
  1291.   if (user_pref.prefer_column_vectors)
  1292.     new_nr = len;
  1293.   else
  1294.     new_nc = len;
  1295.  
  1296.   if (type_tag == matrix_constant)
  1297.     {
  1298.       Matrix *m = new Matrix (new_nr, new_nc);
  1299.  
  1300.       double *cop_out = matrix->fortran_vec ();
  1301.  
  1302.       for (int i = 0; i < len; i++)
  1303.     {
  1304.       if (new_nr == 1)
  1305.         m->elem (0, i) = *cop_out++;
  1306.       else
  1307.         m->elem (i, 0) = *cop_out++;
  1308.     }
  1309.  
  1310.       delete matrix;
  1311.       matrix = m;
  1312.     }
  1313.   else
  1314.     {
  1315.       ComplexMatrix *cm = new ComplexMatrix (new_nr, new_nc);
  1316.  
  1317.       Complex *cop_out = complex_matrix->fortran_vec ();
  1318.  
  1319.       for (int i = 0; i < len; i++)
  1320.     {
  1321.       if (new_nr == 1)
  1322.         cm->elem (0, i) = *cop_out++;
  1323.       else
  1324.         cm->elem (i, 0) = *cop_out++;
  1325.     }
  1326.  
  1327.       delete complex_matrix;
  1328.       complex_matrix = cm;
  1329.     }
  1330. }
  1331.  
  1332. void
  1333. TC_REP::force_numeric (int force_str_conv)
  1334. {
  1335.   switch (type_tag)
  1336.     {
  1337.     case scalar_constant:
  1338.     case matrix_constant:
  1339.     case complex_scalar_constant:
  1340.     case complex_matrix_constant:
  1341.       break;
  1342.  
  1343.     case string_constant:
  1344.       {
  1345.     if (! force_str_conv && ! user_pref.implicit_str_to_num_ok)
  1346.       {
  1347.         ::error ("failed to convert `%s' to a numeric type --", string);
  1348.         ::error ("default conversion turned off");
  1349.  
  1350.         return;
  1351.       }
  1352.  
  1353.     int len = strlen (string);
  1354.     if (len > 1)
  1355.       {
  1356.         type_tag = matrix_constant;
  1357.         Matrix *tm = new Matrix (1, len);
  1358.         for (int i = 0; i < len; i++)
  1359.           tm->elem (0, i) = toascii ((int) string[i]);
  1360.         matrix = tm;
  1361.       }
  1362.     else if (len == 1)
  1363.       {
  1364.         type_tag = scalar_constant;
  1365.         scalar = toascii ((int) string[0]);
  1366.       }
  1367.     else if (len == 0)
  1368.       {
  1369.         type_tag = matrix_constant;
  1370.         matrix = new Matrix (0, 0);
  1371.       }
  1372.     else
  1373.       panic_impossible ();
  1374.       }
  1375.       break;
  1376.  
  1377.     case range_constant:
  1378.       {
  1379.     int len = range->nelem ();
  1380.     if (len > 1)
  1381.       {
  1382.         type_tag = matrix_constant;
  1383.         Matrix *tm = new Matrix (1, len);
  1384.         double b = range->base ();
  1385.         double increment = range->inc ();
  1386.         for (int i = 0; i < len; i++)
  1387.           tm->elem (0, i) = b + i * increment;
  1388.         matrix = tm;
  1389.       }
  1390.     else if (len == 1)
  1391.       {
  1392.         type_tag = scalar_constant;
  1393.         scalar = range->base ();
  1394.       }
  1395.       }
  1396.       break;
  1397.  
  1398.     default:
  1399.       gripe_invalid_conversion (type_as_string (), "numeric type");
  1400.       break;
  1401.     }
  1402. }
  1403.  
  1404. tree_constant
  1405. TC_REP::make_numeric (int force_str_conv) const
  1406. {
  1407.   tree_constant retval;
  1408.  
  1409.   switch (type_tag)
  1410.     {
  1411.     case scalar_constant:
  1412.       retval = tree_constant (scalar);
  1413.       break;
  1414.  
  1415.     case matrix_constant:
  1416.       retval = tree_constant (*matrix);
  1417.       break;
  1418.  
  1419.     case complex_scalar_constant:
  1420.       retval = tree_constant (*complex_scalar);
  1421.       break;
  1422.  
  1423.     case complex_matrix_constant:
  1424.       retval = tree_constant (*complex_matrix);
  1425.       break;
  1426.  
  1427.     case string_constant:
  1428.       retval = tree_constant (string);
  1429.       retval.force_numeric (force_str_conv);
  1430.       break;
  1431.  
  1432.     case range_constant:
  1433.       retval = tree_constant (*range);
  1434.       retval.force_numeric (force_str_conv);
  1435.       break;
  1436.  
  1437.     default:
  1438.       gripe_invalid_conversion (type_as_string (), "numeric value");
  1439.       break;
  1440.     }
  1441.  
  1442.   return retval;
  1443. }
  1444.  
  1445. void
  1446. TC_REP::bump_value (tree_expression::type etype)
  1447. {
  1448.   switch (etype)
  1449.     {
  1450.     case tree_expression::increment:
  1451.       switch (type_tag)
  1452.     {
  1453.     case scalar_constant:
  1454.       scalar++;
  1455.       break;
  1456.  
  1457.     case matrix_constant:
  1458.       *matrix = *matrix + 1.0;
  1459.       break;
  1460.  
  1461.     case complex_scalar_constant:
  1462.       *complex_scalar = *complex_scalar + 1.0;
  1463.       break;
  1464.  
  1465.     case complex_matrix_constant:
  1466.       *complex_matrix = *complex_matrix + 1.0;
  1467.       break;
  1468.  
  1469.     case range_constant:
  1470.       range->set_base (range->base () + 1.0);
  1471.       range->set_limit (range->limit () + 1.0);
  1472.       break;
  1473.  
  1474.     default:
  1475.       gripe_wrong_type_arg ("operator ++", type_as_string ());
  1476.       break;
  1477.     }
  1478.       break;
  1479.  
  1480.     case tree_expression::decrement:
  1481.       switch (type_tag)
  1482.     {
  1483.     case scalar_constant:
  1484.       scalar--;
  1485.       break;
  1486.  
  1487.     case matrix_constant:
  1488.       *matrix = *matrix - 1.0;
  1489.       break;
  1490.  
  1491.     case range_constant:
  1492.       range->set_base (range->base () - 1.0);
  1493.       range->set_limit (range->limit () - 1.0);
  1494.       break;
  1495.  
  1496.     default:
  1497.       gripe_wrong_type_arg ("operator --", type_as_string ());
  1498.       break;
  1499.     }
  1500.       break;
  1501.  
  1502.     default:
  1503.       panic_impossible ();
  1504.       break;
  1505.     }
  1506. }
  1507.  
  1508. void
  1509. TC_REP::resize (int i, int j)
  1510. {
  1511.   switch (type_tag)
  1512.     {
  1513.     case matrix_constant:
  1514.       matrix->resize (i, j);
  1515.       break;
  1516.  
  1517.     case complex_matrix_constant:
  1518.       complex_matrix->resize (i, j);
  1519.       break;
  1520.  
  1521.     default:
  1522.       gripe_wrong_type_arg ("resize", type_as_string ());
  1523.       break;
  1524.     }
  1525. }
  1526.  
  1527. void
  1528. TC_REP::resize (int i, int j, double val)
  1529. {
  1530.   switch (type_tag)
  1531.     {
  1532.     case matrix_constant:
  1533.       matrix->resize (i, j, val);
  1534.       break;
  1535.  
  1536.     case complex_matrix_constant:
  1537.       complex_matrix->resize (i, j, val);
  1538.       break;
  1539.  
  1540.     default:
  1541.       gripe_wrong_type_arg ("resize", type_as_string ());
  1542.       break;
  1543.     }
  1544. }
  1545.  
  1546. void
  1547. TC_REP::maybe_resize (int i, int j)
  1548. {
  1549.   int nr = rows ();
  1550.   int nc = columns ();
  1551.  
  1552.   i++;
  1553.   j++;
  1554.  
  1555.   assert (i > 0 && j > 0);
  1556.  
  1557.   if (i > nr || j > nc)
  1558.     {
  1559.       if (user_pref.resize_on_range_error)
  1560.     resize (MAX (i, nr), MAX (j, nc), 0.0);
  1561.       else
  1562.     {
  1563.       if (i > nr)
  1564.         ::error ("row index = %d exceeds max row dimension = %d", i, nr);
  1565.  
  1566.       if (j > nc)
  1567.         ::error ("column index = %d exceeds max column dimension = %d",
  1568.              j, nc);
  1569.     }
  1570.     }
  1571. }
  1572.  
  1573. void
  1574. TC_REP::maybe_resize (int i, force_orient f_orient)
  1575. {
  1576.   int nr = rows ();
  1577.   int nc = columns ();
  1578.  
  1579.   i++;
  1580.  
  1581.   assert (i >= 0 && (nr <= 1 || nc <= 1));
  1582.  
  1583. // This function never reduces the size of a vector, and all vectors
  1584. // have dimensions of at least 0x0.  If i is 0, it is either because
  1585. // a vector has been indexed with a vector of all zeros (in which case
  1586. // the index vector is empty and nothing will happen) or a vector has
  1587. // been indexed with 0 (an error which will be caught elsewhere).
  1588.   if (i == 0)
  1589.     return;
  1590.  
  1591.   if (nr <= 1 && nc <= 1 && i >= 1)
  1592.     {
  1593.       if (user_pref.resize_on_range_error)
  1594.     {
  1595.       if (f_orient == row_orient)
  1596.         resize (1, i, 0.0);
  1597.       else if (f_orient == column_orient)
  1598.         resize (i, 1, 0.0);
  1599.       else if (user_pref.prefer_column_vectors)
  1600.         resize (i, 1, 0.0);
  1601.       else
  1602.         resize (1, i, 0.0);
  1603.     }
  1604.       else
  1605.     ::error ("matrix index = %d exceeds max dimension = %d", i, nc);
  1606.     }
  1607.   else if (nr == 1 && i > nc)
  1608.     {
  1609.       if (user_pref.resize_on_range_error)
  1610.     resize (1, i, 0.0);
  1611.       else
  1612.     ::error ("matrix index = %d exceeds max dimension = %d", i, nc);
  1613.     }
  1614.   else if (nc == 1 && i > nr)
  1615.     {
  1616.       if (user_pref.resize_on_range_error)
  1617.     resize (i, 1, 0.0);
  1618.       else
  1619.     ::error ("matrix index = %d exceeds max dimension = ", i, nc);
  1620.     }
  1621. }
  1622.  
  1623. void
  1624. TC_REP::stash_original_text (char *s)
  1625. {
  1626.   orig_text = strsave (s);
  1627. }
  1628.  
  1629. void
  1630. TC_REP::maybe_mutate (void)
  1631. {
  1632.   if (error_state)
  1633.     return;
  1634.  
  1635.   switch (type_tag)
  1636.     {
  1637.     case complex_scalar_constant:
  1638.       if (::imag (*complex_scalar) == 0.0)
  1639.     {
  1640.       double d = ::real (*complex_scalar);
  1641.       delete complex_scalar;
  1642.       scalar = d;
  1643.       type_tag = scalar_constant;
  1644.     }
  1645.       break;
  1646.  
  1647.     case complex_matrix_constant:
  1648.       if (! any_element_is_complex (*complex_matrix))
  1649.     {
  1650.       Matrix *m = new Matrix (::real (*complex_matrix));
  1651.       delete complex_matrix;
  1652.       matrix = m;
  1653.       type_tag = matrix_constant;
  1654.     }
  1655.       break;
  1656.  
  1657.     default:
  1658.       break;
  1659.     }
  1660.  
  1661. // Avoid calling rows() and columns() for things like magic_colon.
  1662.  
  1663.   int nr = 1;
  1664.   int nc = 1;
  1665.   if (type_tag == matrix_constant
  1666.       || type_tag == complex_matrix_constant
  1667.       || type_tag == range_constant)
  1668.     {
  1669.       nr = rows ();
  1670.       nc = columns ();
  1671.     }
  1672.  
  1673.   switch (type_tag)
  1674.     {
  1675.     case matrix_constant:
  1676.       if (nr == 1 && nc == 1)
  1677.     {
  1678.       double d = matrix->elem (0, 0);
  1679.       delete matrix;
  1680.       scalar = d;
  1681.       type_tag = scalar_constant;
  1682.     }
  1683.       break;
  1684.  
  1685.     case complex_matrix_constant:
  1686.       if (nr == 1 && nc == 1)
  1687.     {
  1688.       Complex c = complex_matrix->elem (0, 0);
  1689.       delete complex_matrix;
  1690.       complex_scalar = new Complex (c);
  1691.       type_tag = complex_scalar_constant;
  1692.     }
  1693.       break;
  1694.  
  1695.     case range_constant:
  1696.       if (nr == 1 && nc == 1)
  1697.     {
  1698.       double d = range->base ();
  1699.       delete range;
  1700.       scalar = d;
  1701.       type_tag = scalar_constant;
  1702.     }
  1703.       break;
  1704.  
  1705.     default:
  1706.       break;
  1707.     }
  1708. }
  1709.  
  1710. void
  1711. TC_REP::print (void)
  1712. {
  1713.   if (error_state)
  1714.     return;
  1715.  
  1716.   ostrstream output_buf;
  1717.  
  1718.   switch (type_tag)
  1719.     {
  1720.     case scalar_constant:
  1721.       octave_print_internal (output_buf, scalar);
  1722.       break;
  1723.  
  1724.     case matrix_constant:
  1725.       octave_print_internal (output_buf, *matrix);
  1726.       break;
  1727.  
  1728.     case complex_scalar_constant:
  1729.       octave_print_internal (output_buf, *complex_scalar);
  1730.       break;
  1731.  
  1732.     case complex_matrix_constant:
  1733.       octave_print_internal (output_buf, *complex_matrix);
  1734.       break;
  1735.  
  1736.     case string_constant:
  1737.       output_buf << string << "\n";
  1738.       break;
  1739.  
  1740.     case range_constant:
  1741.       octave_print_internal (output_buf, *range);
  1742.       break;
  1743.  
  1744.     case map_constant:
  1745.       {
  1746.     output_buf << "<structure";
  1747.     int first = 1;
  1748.     for (Pix p = a_map->first (); p != 0; a_map->next (p))
  1749.       {
  1750.         if (first)
  1751.           {
  1752.         output_buf << ":";
  1753.         first = 0;
  1754.           }
  1755.         output_buf << " " << a_map->key (p);
  1756.       }
  1757.     output_buf << ">\n";
  1758.       }
  1759.       break;
  1760.  
  1761.     case unknown_constant:
  1762.     case magic_colon:
  1763.     case all_va_args:
  1764.       panic_impossible ();
  1765.       break;
  1766.     }
  1767.  
  1768.   output_buf << ends;
  1769.   maybe_page_output (output_buf);
  1770. }
  1771.  
  1772. void
  1773. TC_REP::print_code (ostream& os)
  1774. {
  1775.   switch (type_tag)
  1776.     {
  1777.     case scalar_constant:
  1778.       if (orig_text)
  1779.     os << orig_text;
  1780.       else
  1781.     octave_print_internal (os, scalar, 1);
  1782.       break;
  1783.  
  1784.     case matrix_constant:
  1785.       octave_print_internal (os, *matrix, 1);
  1786.       break;
  1787.  
  1788.     case complex_scalar_constant:
  1789.      {
  1790.     double re = complex_scalar->real ();
  1791.     double im = complex_scalar->imag ();
  1792.  
  1793. // If we have the original text and a pure imaginary, just print the
  1794. // original text, because this must be a constant that was parsed as
  1795. // part of a function.
  1796.  
  1797.     if (orig_text && re == 0.0 && im > 0.0)
  1798.       os << orig_text;
  1799.     else
  1800.       octave_print_internal (os, *complex_scalar, 1);
  1801.       }
  1802.       break;
  1803.  
  1804.     case complex_matrix_constant:
  1805.       octave_print_internal (os, *complex_matrix, 1);
  1806.       break;
  1807.  
  1808.     case string_constant:
  1809.       {
  1810.     os << "\"";
  1811.     char *s, *t = string;
  1812.     while (s = undo_string_escape (*t++))
  1813.       os << s;
  1814.     os << "\"";
  1815.       }
  1816.       break;
  1817.  
  1818.     case range_constant:
  1819.       octave_print_internal (os, *range, 1);
  1820.       break;
  1821.  
  1822.     case magic_colon:
  1823.       os << ":";
  1824.       break;
  1825.  
  1826.     case all_va_args:
  1827.       os << "all_va_args";
  1828.       break;
  1829.  
  1830.     case map_constant:
  1831.     case unknown_constant:
  1832.       panic_impossible ();
  1833.       break;
  1834.     }
  1835. }
  1836.  
  1837. void
  1838. TC_REP::gripe_wrong_type_arg (const char *name,
  1839.                   const tree_constant_rep& tcr) const
  1840. {
  1841.   if (name)
  1842.     ::error ("%s: wrong type argument `%s'", name, tcr.type_as_string ());
  1843.   else
  1844.     ::error ("wrong type argument `%s'", name, tcr.type_as_string ());
  1845. }
  1846.  
  1847. char *
  1848. TC_REP::type_as_string (void) const
  1849. {
  1850.   switch (type_tag)
  1851.     {
  1852.     case scalar_constant:
  1853.       return "real scalar";
  1854.  
  1855.     case matrix_constant:
  1856.       return "real matrix";
  1857.  
  1858.     case complex_scalar_constant:
  1859.       return "complex scalar";
  1860.  
  1861.     case complex_matrix_constant:
  1862.       return "complex matrix";
  1863.  
  1864.     case string_constant:
  1865.       return "string";
  1866.  
  1867.     case range_constant:
  1868.       return "range";
  1869.  
  1870.     case map_constant:
  1871.       return "structure";
  1872.  
  1873.     default:
  1874.       return "<unknown type>";
  1875.     }
  1876. }
  1877.  
  1878. tree_constant
  1879. do_binary_op (tree_constant& a, tree_constant& b, tree_expression::type t)
  1880. {
  1881.   tree_constant retval;
  1882.  
  1883.   int first_empty = (a.rows () == 0 || a.columns () == 0);
  1884.   int second_empty = (b.rows () == 0 || b.columns () == 0);
  1885.  
  1886.   if (first_empty || second_empty)
  1887.     {
  1888.       int flag = user_pref.propagate_empty_matrices;
  1889.       if (flag < 0)
  1890.     warning ("binary operation on empty matrix");
  1891.       else if (flag == 0)
  1892.     {
  1893.       ::error ("invalid binary operation on empty matrix");
  1894.       return retval;
  1895.     }
  1896.     }
  1897.  
  1898.   tree_constant tmp_a = a.make_numeric ();
  1899.  
  1900.   if (error_state)
  1901.     return retval;
  1902.  
  1903.   tree_constant tmp_b = b.make_numeric ();
  1904.  
  1905.   if (error_state)
  1906.     return retval;
  1907.  
  1908.   TC_REP::constant_type a_type = tmp_a.const_type ();
  1909.   TC_REP::constant_type b_type = tmp_b.const_type ();
  1910.  
  1911.   double d1, d2;
  1912.   Matrix m1, m2;
  1913.   Complex c1, c2;
  1914.   ComplexMatrix cm1, cm2;
  1915.  
  1916.   switch (a_type)
  1917.     {
  1918.     case TC_REP::scalar_constant:
  1919.  
  1920.       d1 = tmp_a.double_value ();
  1921.  
  1922.       switch (b_type)
  1923.     {
  1924.     case TC_REP::scalar_constant:
  1925.       d2 = tmp_b.double_value ();
  1926.       retval = do_binary_op (d1, d2, t);
  1927.       break;
  1928.  
  1929.     case TC_REP::matrix_constant:
  1930.       m2 = tmp_b.matrix_value ();
  1931.       retval = do_binary_op (d1, m2, t);
  1932.       break;
  1933.  
  1934.     case TC_REP::complex_scalar_constant:
  1935.       c2 = tmp_b.complex_value ();
  1936.       retval = do_binary_op (d1, c2, t);
  1937.       break;
  1938.  
  1939.     case TC_REP::complex_matrix_constant:
  1940.       cm2 = tmp_b.complex_matrix_value ();
  1941.       retval = do_binary_op (d1, cm2, t);
  1942.       break;
  1943.  
  1944.     default:
  1945.       gripe_wrong_type_arg_for_binary_op (tmp_b);
  1946.       break;
  1947.     }
  1948.       break;
  1949.  
  1950.     case TC_REP::matrix_constant:
  1951.  
  1952.       m1 = tmp_a.matrix_value ();
  1953.  
  1954.       switch (b_type)
  1955.     {
  1956.     case TC_REP::scalar_constant:
  1957.       d2 = tmp_b.double_value ();
  1958.       retval = do_binary_op (m1, d2, t);
  1959.       break;
  1960.  
  1961.     case TC_REP::matrix_constant:
  1962.       m2 = tmp_b.matrix_value ();
  1963.       retval = do_binary_op (m1, m2, t);
  1964.       break;
  1965.  
  1966.     case TC_REP::complex_scalar_constant:
  1967.       c2 = tmp_b.complex_value ();
  1968.       retval = do_binary_op (m1, c2, t);
  1969.       break;
  1970.  
  1971.     case TC_REP::complex_matrix_constant:
  1972.       cm2 = tmp_b.complex_matrix_value ();
  1973.       retval = do_binary_op (m1, cm2, t);
  1974.       break;
  1975.  
  1976.     default:
  1977.       gripe_wrong_type_arg_for_binary_op (tmp_b);
  1978.       break;
  1979.     }
  1980.       break;
  1981.  
  1982.     case TC_REP::complex_scalar_constant:
  1983.  
  1984.       c1 = tmp_a.complex_value ();
  1985.  
  1986.       switch (b_type)
  1987.     {
  1988.     case TC_REP::scalar_constant:
  1989.       d2 = tmp_b.double_value ();
  1990.       retval = do_binary_op (c1, d2, t);
  1991.       break;
  1992.  
  1993.     case TC_REP::matrix_constant:
  1994.       m2 = tmp_b.matrix_value ();
  1995.       retval = do_binary_op (c1, m2, t);
  1996.       break;
  1997.  
  1998.     case TC_REP::complex_scalar_constant:
  1999.       c2 = tmp_b.complex_value ();
  2000.       retval = do_binary_op (c1, c2, t);
  2001.       break;
  2002.  
  2003.     case TC_REP::complex_matrix_constant:
  2004.       cm2 = tmp_b.complex_matrix_value ();
  2005.       retval = do_binary_op (c1, cm2, t);
  2006.       break;
  2007.  
  2008.     default:
  2009.       gripe_wrong_type_arg_for_binary_op (tmp_b);
  2010.       break;
  2011.     }
  2012.       break;
  2013.  
  2014.     case TC_REP::complex_matrix_constant:
  2015.  
  2016.       cm1 = tmp_a.complex_matrix_value ();
  2017.  
  2018.       switch (b_type)
  2019.     {
  2020.     case TC_REP::scalar_constant:
  2021.       d2 = tmp_b.double_value ();
  2022.       retval = do_binary_op (cm1, d2, t);
  2023.       break;
  2024.  
  2025.     case TC_REP::matrix_constant:
  2026.       m2 = tmp_b.matrix_value ();
  2027.       retval = do_binary_op (cm1, m2, t);
  2028.       break;
  2029.  
  2030.     case TC_REP::complex_scalar_constant:
  2031.       c2 = tmp_b.complex_value ();
  2032.       retval = do_binary_op (cm1, c2, t);
  2033.       break;
  2034.  
  2035.     case TC_REP::complex_matrix_constant:
  2036.       cm2 = tmp_b.complex_matrix_value ();
  2037.       retval = do_binary_op (cm1, cm2, t);
  2038.       break;
  2039.  
  2040.     default:
  2041.       gripe_wrong_type_arg_for_binary_op (tmp_b);
  2042.       break;
  2043.     }
  2044.       break;
  2045.  
  2046.     default:
  2047.       gripe_wrong_type_arg_for_binary_op (tmp_a);
  2048.       break;
  2049.     }
  2050.  
  2051.   return retval;
  2052. }
  2053.  
  2054. tree_constant
  2055. do_unary_op (tree_constant& a, tree_expression::type t)
  2056. {
  2057.   tree_constant retval;
  2058.  
  2059.   if (a.rows () == 0 || a.columns () == 0)
  2060.     {
  2061.       int flag = user_pref.propagate_empty_matrices;
  2062.       if (flag < 0)
  2063.     warning ("unary operation on empty matrix");
  2064.       else if (flag == 0)
  2065.     {
  2066.       ::error ("invalid unary operation on empty matrix");
  2067.       return retval;
  2068.     }
  2069.     }
  2070.  
  2071.   tree_constant tmp_a = a.make_numeric ();
  2072.  
  2073.   if (error_state)
  2074.     return retval;
  2075.  
  2076.   switch (tmp_a.const_type ())
  2077.     {
  2078.     case TC_REP::scalar_constant:
  2079.       retval = do_unary_op (tmp_a.double_value (), t);
  2080.       break;
  2081.  
  2082.     case TC_REP::matrix_constant:
  2083.       {
  2084.     Matrix m = tmp_a.matrix_value ();
  2085.     retval = do_unary_op (m, t);
  2086.       }
  2087.       break;
  2088.  
  2089.     case TC_REP::complex_scalar_constant:
  2090.       retval = do_unary_op (tmp_a.complex_value (), t);
  2091.       break;
  2092.  
  2093.     case TC_REP::complex_matrix_constant:
  2094.       {
  2095.     ComplexMatrix m = tmp_a.complex_matrix_value ();
  2096.     retval = do_unary_op (m, t);
  2097.       }
  2098.       break;
  2099.  
  2100.     default:
  2101.       gripe_wrong_type_arg_for_unary_op (tmp_a);
  2102.       break;
  2103.     }
  2104.  
  2105.   return retval;
  2106. }
  2107.  
  2108. /*
  2109. ;;; Local Variables: ***
  2110. ;;; mode: C++ ***
  2111. ;;; page-delimiter: "^/\\*" ***
  2112. ;;; End: ***
  2113. */
  2114.