changeset 4915:c638c144d4da

[project @ 2004-07-23 19:01:22 by jwe]
author jwe
date Fri, 23 Jul 2004 19:01:23 +0000
parents 1c0442da75fd
children c45f14873b5e
files liboctave/Array-C.cc liboctave/Array-ch.cc liboctave/Array-d.cc liboctave/Array-i.cc liboctave/Array.cc liboctave/Array.h liboctave/CNDArray.cc liboctave/CNDArray.h liboctave/ChangeLog liboctave/chNDArray.cc liboctave/chNDArray.h liboctave/dNDArray.cc liboctave/dNDArray.h liboctave/dim-vector.h liboctave/int16NDArray.cc liboctave/int16NDArray.h liboctave/int32NDArray.cc liboctave/int32NDArray.h liboctave/int64NDArray.cc liboctave/int64NDArray.h liboctave/int8NDArray.cc liboctave/int8NDArray.h liboctave/intNDArray.cc liboctave/intNDArray.h liboctave/oct-inttypes.h liboctave/uint16NDArray.cc liboctave/uint16NDArray.h liboctave/uint32NDArray.cc liboctave/uint32NDArray.h liboctave/uint64NDArray.cc liboctave/uint64NDArray.h liboctave/uint8NDArray.cc liboctave/uint8NDArray.h scripts/ChangeLog src/Cell.cc src/Cell.h src/ChangeLog src/OPERATORS/op-b-b.cc src/OPERATORS/op-b-bm.cc src/OPERATORS/op-bm-b.cc src/OPERATORS/op-bm-bm.cc src/OPERATORS/op-cell.cc src/OPERATORS/op-chm.cc src/OPERATORS/op-cm-cm.cc src/OPERATORS/op-cm-cs.cc src/OPERATORS/op-cm-m.cc src/OPERATORS/op-cm-s.cc src/OPERATORS/op-cs-cm.cc src/OPERATORS/op-cs-cs.cc src/OPERATORS/op-cs-m.cc src/OPERATORS/op-cs-s.cc src/OPERATORS/op-int.h src/OPERATORS/op-m-cm.cc src/OPERATORS/op-m-cs.cc src/OPERATORS/op-m-m.cc src/OPERATORS/op-m-s.cc src/OPERATORS/op-range.cc src/OPERATORS/op-s-cm.cc src/OPERATORS/op-s-cs.cc src/OPERATORS/op-s-m.cc src/OPERATORS/op-s-s.cc src/OPERATORS/op-str-m.cc src/OPERATORS/op-str-s.cc src/OPERATORS/op-str-str.cc src/TEMPLATE-INST/Array-tc.cc src/bitfcns.cc src/data.cc src/oct-map.cc src/oct-map.h src/ops.h src/ov-base-mat.cc src/ov-base-mat.h src/ov-base.cc src/ov-base.h src/ov-bool.h src/ov-complex.h src/ov-intx.h src/ov-range.h src/ov-scalar.h src/ov-typeinfo.cc src/ov-typeinfo.h src/ov.cc src/ov.h src/pt-mat.cc src/version.h
diffstat 85 files changed, 1490 insertions(+), 555 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/Array-C.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/Array-C.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -33,8 +33,6 @@
 
 INSTANTIATE_ARRAY_AND_ASSIGN (Complex);
 
-INSTANTIATE_ARRAY_CAT (Complex);
-
 INSTANTIATE_ARRAY_ASSIGN (Complex, double);
 INSTANTIATE_ARRAY_ASSIGN (Complex, int);
 INSTANTIATE_ARRAY_ASSIGN (Complex, short);
--- a/liboctave/Array-ch.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/Array-ch.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -31,8 +31,6 @@
 
 INSTANTIATE_ARRAY_AND_ASSIGN (char);
 
-INSTANTIATE_ARRAY_CAT (char);
-
 #include "Array2.h"
 
 template class Array2<char>;
--- a/liboctave/Array-d.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/Array-d.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -31,8 +31,6 @@
 
 INSTANTIATE_ARRAY_AND_ASSIGN (double);
 
-INSTANTIATE_ARRAY_CAT (double);
-
 INSTANTIATE_ARRAY_ASSIGN (double, int);
 INSTANTIATE_ARRAY_ASSIGN (double, short);
 INSTANTIATE_ARRAY_ASSIGN (double, char);
--- a/liboctave/Array-i.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/Array-i.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -46,16 +46,6 @@
 INSTANTIATE_ARRAY_AND_ASSIGN (octave_uint32);
 INSTANTIATE_ARRAY_AND_ASSIGN (octave_uint64);
 
-INSTANTIATE_ARRAY_CAT (octave_int8);
-INSTANTIATE_ARRAY_CAT (octave_int16);
-INSTANTIATE_ARRAY_CAT (octave_int32);
-INSTANTIATE_ARRAY_CAT (octave_int64);
-
-INSTANTIATE_ARRAY_CAT (octave_uint8);
-INSTANTIATE_ARRAY_CAT (octave_uint16);
-INSTANTIATE_ARRAY_CAT (octave_uint32);
-INSTANTIATE_ARRAY_CAT (octave_uint64);
-
 #include "Array2.h"
 
 template class Array2<int>;
--- a/liboctave/Array.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/Array.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -570,8 +570,9 @@
   dim_vector dv_old = dimensions;
   int dv_old_orig_len = dv_old.length ();
   dimensions = dv;
-
-  if (ts > 0 && dv_old_orig_len > 0)
+  int ts_old = get_size (dv_old);
+
+  if (ts > 0 && ts_old > 0 && dv_old_orig_len > 0)
     {
       Array<int> ra_idx (dimensions.length (), 0);
 
@@ -1040,11 +1041,14 @@
 
   if (n == dimensions.length ())
     {
-      dim_vector a_dims = a.dims ();
+      dim_vector dva = a.dims ();
+      dim_vector dv = dims ();
+      int len_a = dva.length ();
 
       for (int i = 0; i < n; i++)
 	{
-	  if (ra_idx(i) < 0 || ra_idx(i) + a_dims(i) > dimensions(i))
+	  if (ra_idx(i) < 0 || (ra_idx(i) + 
+				(i < len_a ? dva(i) : 1)) > dimensions(i))
 	    {
 	      (*current_liboctave_error_handler)
 		("Array<T>::insert: range error for insert");
@@ -1052,15 +1056,39 @@
 	    }
 	}
 
-
-#if 0
-      // XXX FIXME XXX -- need to copy elements
-
-      for (int j = 0; j < a_cols; j++)
-	for (int i = 0; i < a_rows; i++)
-	  elem (r+i, c+j) = a.elem (i, j);
-#endif
-
+      if (dva.numel ())
+        {
+	  const T *a_data = a.data ();   
+	  int numel_to_move = dva (0);
+	  int skip = dv (0);
+	  for (int i = 0; i < len_a - 1; i++)
+	    if (ra_idx(i) == 0 && dva(i) == dv(i))
+	      {
+		numel_to_move *= dva(i+1);
+		skip *= dv(i+1);
+	      }
+	    else
+	      {
+		skip -= dva(i);
+		break;
+	      }
+
+	  int jidx = ra_idx (n - 1);
+	  for (int i = n-2; i >= 0; i--)
+	    {
+	      jidx *= dv (i);
+	      jidx += ra_idx (i);
+	    }
+
+	  int iidx = 0;
+	  int moves = dva.numel () / numel_to_move;
+	  for (int i = 0; i < moves; i++)
+	    {
+	      for (int j = 0; j < numel_to_move; j++)
+		elem (jidx++) = a_data[iidx++];
+	      jidx += skip;
+	    }
+	}
     }
   else
     (*current_liboctave_error_handler)
@@ -3081,29 +3109,6 @@
 }
 
 template <class T>
-int
-cat_ra (Array<T>& ra, const Array<T>& ra_arg, int dim, int idx, int move)
-{
-  dim_vector dv_arg = ra_arg.dims (); 
-  
-  const T *arg_data = ra_arg.data ();
-  
-  int numel_to_move = dv_arg(0);
-
-  int numel_arg = dv_arg.length ();
-
-  int ii_limit = dim+1 > numel_arg ? numel_arg : dim + 1;
-  
-  for (int ii = 1; ii < ii_limit; ii++)
-    numel_to_move *= dv_arg(ii);
-
-  for (int j = 0; j < numel_to_move; j++)
-    ra.elem (idx++) = arg_data[numel_to_move * move + j];
-  
-  return idx;
-}
-
-template <class T>
 void
 Array<T>::print_info (std::ostream& os, const std::string& prefix) const
 {
--- a/liboctave/Array.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/Array.h	Fri Jul 23 19:01:23 2004 +0000
@@ -543,10 +543,6 @@
 // Array<T>::dimensions should be protected, not public, but we can't
 // do that because of bugs in gcc prior to 3.3.
 
-template <class T>
-int 
-cat_ra (Array<T>& ra, const Array<T>& ra_arg, int dim, int idx, int move);
-
 template <class LT, class RT>
 /* friend */ int
 assign (Array<LT>& lhs, const Array<RT>& rhs, const LT& rfv);
@@ -582,10 +578,6 @@
   template class Array<T>; \
   template T resize_fill_value (const T&); \
 
-#define INSTANTIATE_ARRAY_CAT(T) \
-  template int cat_ra (Array<T>& ra, const Array<T>& ra_arg, \
-                       int dim, int idx, int move)
-
 #define INSTANTIATE_ARRAY_AND_ASSIGN(T) \
   INSTANTIATE_ARRAY (T); \
   INSTANTIATE_ARRAY_ASSIGN (T, T)
--- a/liboctave/CNDArray.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/CNDArray.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -653,10 +653,33 @@
   MX_ND_COMPLEX_OP_REDUCTION (+= elem (iter_idx), Complex (0, 0));
 }
 
-int
-ComplexNDArray::cat (const ComplexNDArray& ra_arg, int dim, int iidx, int move)
+ComplexNDArray
+concat (const ComplexNDArray& ra, const ComplexNDArray& rb, 
+	const Array<int>& ra_idx)
+{
+  ComplexNDArray retval (ra);
+  if (ra.numel () > 0)
+    retval.insert (rb, ra_idx);
+  return retval;
+}
+
+ComplexNDArray
+concat (const ComplexNDArray& ra, const NDArray& rb, const Array<int>& ra_idx)
 {
-  return ::cat_ra(*this, ra_arg, dim, iidx, move);
+  ComplexNDArray retval (ra);
+  ComplexNDArray tmp (rb);
+  if (ra.numel () > 0)
+    retval.insert (tmp, ra_idx);
+  return retval;
+}
+
+ComplexNDArray
+concat (const NDArray& ra, const ComplexNDArray& rb, const Array<int>& ra_idx)
+{
+  ComplexNDArray retval (ra);
+  if (ra.numel () > 0)
+    retval.insert (rb, ra_idx);
+  return retval;
 }
 
 static const Complex Complex_NaN_result (octave_NaN, octave_NaN);
@@ -915,6 +938,13 @@
   return *this;
 }
 
+ComplexNDArray&
+ComplexNDArray::insert (const ComplexNDArray& a, const Array<int>& ra_idx)
+{
+  Array<Complex>::insert (a, ra_idx);
+  return *this;
+}
+
 ComplexMatrix
 ComplexNDArray::matrix_value (void) const
 {
--- a/liboctave/CNDArray.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/CNDArray.h	Fri Jul 23 19:01:23 2004 +0000
@@ -79,7 +79,13 @@
   ComplexNDArray prod (int dim = -1) const;
   ComplexNDArray sum (int dim = -1) const;
   ComplexNDArray sumsq (int dim = -1) const;
-  int cat (const ComplexNDArray& ra_arg, int dim, int iidx, int move);
+  friend ComplexNDArray concat (const ComplexNDArray& ra, 
+				const ComplexNDArray& rb, 
+				const Array<int>& ra_idx);
+  friend ComplexNDArray concat (const ComplexNDArray& ra, const NDArray& rb,
+				const Array<int>& ra_idx);
+  friend ComplexNDArray concat (const NDArray& ra, const ComplexNDArray& rb,
+				const Array<int>& ra_idx);
 
   ComplexNDArray max (int dim = 0) const;
   ComplexNDArray max (ArrayN<int>& index, int dim = 0) const;
@@ -88,6 +94,7 @@
 
   ComplexNDArray& insert (const NDArray& a, int r, int c);
   ComplexNDArray& insert (const ComplexNDArray& a, int r, int c);
+  ComplexNDArray& insert (const ComplexNDArray& a, const Array<int>& ra_idx);
   
   NDArray abs (void) const;
 
--- a/liboctave/ChangeLog	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/ChangeLog	Fri Jul 23 19:01:23 2004 +0000
@@ -1,3 +1,36 @@
+2004-07-23  David Bateman  <dbateman@free.fr>
+
+	* Array.cc, Array.h (cat_ra): Delete.
+	* Array.h, Array-C.cc, Array-d.cc, Array-ch.cc, Array-i.cc 
+	(INSTANTIATE_ARRAY_CAT): Delete.
+
+	* dNDArray.cc, dNDArray.h, CNDArray.cc, CNDArray.h, chNDArray.cc, 
+	chNDArray.h, intNDArray.cc, intNDArray.h (cat): Delete.
+	
+	* Array.cc (Array<T>::insert): Copy data in NDArray version.
+
+	* dNDArray.cc, dNDArray.h, CNDArray.cc, CNDArray.h, chNDArray.cc, 
+	chNDArray.h (concat): New function used for concatenation that does
+	an indexed copy of one array into another.
+
+	* dim-vector.h (concat): New function to concatenate dim_vectors.
+
+	* dNDArray.cc, dNDArray.h, CNDArray.cc, CNDArray.h, chNDArray.cc,
+	chNDArray.h, intNDArray.cc, intNDArray.h (insert): New function for 
+	insertion of one NDArray into another.
+
+	* oct-inttype.cc (OCTAVE_INT_CONCAT_FN, OCTAVE_INT_CONCAT_DECL): New
+	macros to define the int/uint concatenation functions.
+
+	* uint8NDArray.cc, uint16NDArray.cc, uint32NDArray.cc, uint64NDArray.cc
+	int8NDArray.cc, int16NDArray.cc, int32NDArray.cc, int64NDArray.cc
+	(OCTAVE_INT_CONCAT_FN): Instantiate the concatenation function .
+
+	* uint8NDArray.h, uint16NDArray.h, uint32NDArray.h, uint64NDArray.h
+	int8NDArray.h, int16NDArray.h, int32NDArray.h, int64NDArray.h
+	(OCTAVE_INT_CONCAT_DECL): Declare the int/uint concatentaion
+	functions.
+
 2004-07-22  David Bateman  <dbateman@free.fr>
 
 	* oct-sort.h: Don't include oct-obj.h.
--- a/liboctave/chNDArray.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/chNDArray.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -33,6 +33,7 @@
 #include "chNDArray.h"
 #include "mx-base.h"
 #include "lo-ieee.h"
+#include "lo-mappers.h"
 
 // XXX FIXME XXX -- this is not quite the right thing.
 
@@ -48,10 +49,97 @@
   MX_ND_ANY_ALL_REDUCTION (MX_ND_ANY_EVAL (elem (iter_idx) != ' '), false);
 }
 
-int
-charNDArray::cat (const charNDArray& ra_arg, int dim, int iidx, int move)
+charNDArray
+concat (const charNDArray& ra, const charNDArray& rb, const Array<int>& ra_idx)
+{
+  charNDArray retval (ra);
+  if (ra.numel () > 0)
+    retval.insert (rb, ra_idx);
+  return retval;
+}
+
+charNDArray
+concat (const charNDArray& ra, const NDArray& rb, const Array<int>& ra_idx)
 {
-  return ::cat_ra(*this, ra_arg, dim, iidx, move);  
+  charNDArray retval (ra);
+  charNDArray tmp (rb.dims ());
+  int nel = rb.numel ();
+
+  if (ra.numel () == 0)
+    return retval;
+
+  for (int i = 0; i < nel; i++)
+    {
+      double d = rb.elem (i);
+
+      if (xisnan (d))
+	{
+	  (*current_liboctave_error_handler)
+	    ("invalid conversion from NaN to character");
+	  return retval;
+	}
+      else
+	{
+	  int ival = NINT (d);
+
+	  if (ival < 0 || ival > UCHAR_MAX)
+	    // XXX FIXME XXX -- is there something
+	    // better we could do? Should we warn the user?
+	    ival = 0;
+
+	  tmp.elem (i) = static_cast<char>(ival);
+	}
+    }
+
+  retval.insert (tmp, ra_idx);
+  return retval;
+}
+
+charNDArray
+concat (const NDArray& ra, const charNDArray& rb, const Array<int>& ra_idx)
+{
+  charNDArray retval (ra.dims ());
+  int nel = ra.numel ();
+
+  for (int i = 0; i < nel; i++)
+    {
+      double d = ra.elem (i);
+
+      if (xisnan (d))
+	{
+	  (*current_liboctave_error_handler)
+	    ("invalid conversion from NaN to character");
+	  return retval;
+	}
+      else
+	{
+	  int ival = NINT (d);
+
+	  if (ival < 0 || ival > UCHAR_MAX)
+	    // XXX FIXME XXX -- is there something
+	    // better we could do? Should we warn the user?
+	    ival = 0;
+
+	  retval.elem (i) = static_cast<char>(ival);
+	}
+    }
+
+  retval.insert (rb, ra_idx);
+  return retval;
+}
+
+charNDArray&
+charNDArray::insert (const charNDArray& a, int r, int c)
+{
+  Array<char>::insert (a, r, c);
+  return *this;
+}
+
+charNDArray&
+charNDArray::insert (const charNDArray& a, const Array<int>& ra_idx)
+{
+  Array<char>::insert (a, ra_idx);
+  return *this;
 }
 
 charMatrix
--- a/liboctave/chNDArray.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/chNDArray.h	Fri Jul 23 19:01:23 2004 +0000
@@ -71,8 +71,16 @@
 
   boolNDArray all (int dim = -1) const;
   boolNDArray any (int dim = -1) const;
-  int cat (const charNDArray& ra_arg, int dim, int iidx, int move);
- 
+  friend charNDArray concat (const charNDArray& ra, const charNDArray& rb, 
+			     const Array<int>& ra_idx);
+  friend charNDArray concat (const charNDArray& ra, const NDArray& rb,
+			     const Array<int>& ra_idx);
+  friend charNDArray concat (const NDArray& ra, const charNDArray& rb,
+			     const Array<int>& ra_idx);
+
+  charNDArray& insert (const charNDArray& a, int r, int c);
+  charNDArray& insert (const charNDArray& a, const Array<int>& ra_idx);
+  
   charMatrix matrix_value (void) const;
 
   charNDArray squeeze (void) const { return ArrayN<char>::squeeze (); }
--- a/liboctave/dNDArray.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/dNDArray.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -792,10 +792,13 @@
   return result;
 }
 
-int
-NDArray::cat (const NDArray& ra_arg, int dim, int iidx, int move)
+NDArray
+concat (const NDArray& ra, const NDArray& rb, const Array<int>& ra_idx)
 {
-  return ::cat_ra (*this, ra_arg, dim, iidx, move);
+  NDArray retval (ra);
+  if (ra.numel () > 0)
+    retval.insert (rb, ra_idx);
+  return retval;
 }
 
 NDArray
@@ -818,6 +821,20 @@
   return retval;
 }
 
+NDArray&
+NDArray::insert (const NDArray& a, int r, int c)
+{
+  Array<double>::insert (a, r, c);
+  return *this;
+}
+
+NDArray&
+NDArray::insert (const NDArray& a, const Array<int>& ra_idx)
+{
+  Array<double>::insert (a, ra_idx);
+  return *this;
+}
+
 NDArray
 NDArray::abs (void) const
 {
--- a/liboctave/dNDArray.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/dNDArray.h	Fri Jul 23 19:01:23 2004 +0000
@@ -84,13 +84,17 @@
   NDArray prod (int dim = -1) const;
   NDArray sum (int dim = -1) const;  
   NDArray sumsq (int dim = -1) const;
-  int cat (const NDArray& ra_arg, int dim, int iidx, int move);
+  friend NDArray concat (const NDArray& ra, const NDArray& rb, 
+			 const Array<int>& ra_idx);
 
   NDArray max (int dim = 0) const;
   NDArray max (ArrayN<int>& index, int dim = 0) const;
   NDArray min (int dim = 0) const;
   NDArray min (ArrayN<int>& index, int dim = 0) const;
   
+  NDArray& insert (const NDArray& a, int r, int c);
+  NDArray& insert (const NDArray& a, const Array<int>& ra_idx);
+
   NDArray abs (void) const;
 
   ComplexNDArray fourier (int dim = 1) const;
--- a/liboctave/dim-vector.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/dim-vector.h	Fri Jul 23 19:01:23 2004 +0000
@@ -357,6 +357,77 @@
  
     return new_dims;
   }
+
+  bool concat (const dim_vector& dvb, int dim = 0)
+  {
+    if (all_zero ())
+      {
+	*this = dvb;
+	return true;
+      }
+
+    if (dvb.all_zero ())
+      return true;
+
+    int na = length ();
+    int nb = dvb.length ();
+  
+    // Find the max and min value of na and nb
+    int n_max = na > nb ? na : nb;
+    int n_min = na < nb ? na : nb;
+  
+    // The elements of the dimension vectors can only differ
+    // if the dim variable differs from the actual dimension
+    // they differ.
+
+    for (int i = 0; i < n_min; i++)
+      {
+	if (elem(i) != dvb(i) && dim != i)
+	    return false;
+      }
+  
+    // Ditto.
+    for (int i = n_min; i < n_max; i++)
+      {
+	if (na > n_min)
+	  {
+	    if (elem(i) != 1 && dim != i)
+	      return false;
+	  }
+	else 
+	  {
+	    if (dvb(i) != 1 && dim != i)
+	      return false;
+	  }
+      }
+    
+    // If we want to add the dimension vectors at a dimension
+    // larger than both, then we need to set n_max to this number
+    // so that we resize *this to the right dimension.
+    
+    n_max = n_max > (dim + 1) ? n_max : (dim + 1);
+    
+    // Resize *this to the appropriate dimensions.
+    
+    if (n_max > na)
+      {
+	dim_vector_rep *old_rep = rep;
+
+	rep = new dim_vector_rep (n_max, old_rep, 1);
+
+	if (--old_rep->count <= 0)
+	  delete old_rep;
+      }
+  
+    // Larger or equal since dim has been decremented by one.
+
+    if (dim >= nb)
+      elem (dim) = elem (dim)++;
+    else
+      elem (dim) += dvb(dim);
+
+    return true;
+  }
 };
 
 static inline bool
--- a/liboctave/int16NDArray.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/int16NDArray.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -43,6 +43,8 @@
 std::istream&
 operator >> (std::istream& is, intNDArray<octave_int16>& a);
 
+OCTAVE_INT_CONCAT_FN (octave_int16)
+
 NDS_CMP_OPS (int16NDArray, , octave_int16, )
 NDS_BOOL_OPS (int16NDArray, octave_int16, octave_int16 (0))
 
--- a/liboctave/int16NDArray.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/int16NDArray.h	Fri Jul 23 19:01:23 2004 +0000
@@ -33,6 +33,8 @@
 
 typedef intNDArray<octave_int16> int16NDArray;
 
+OCTAVE_INT_CONCAT_DECL (octave_int16)
+
 NDS_CMP_OP_DECLS (int16NDArray, octave_int16)
 NDS_BOOL_OP_DECLS (int16NDArray, octave_int16)
 
--- a/liboctave/int32NDArray.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/int32NDArray.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -43,6 +43,8 @@
 std::istream&
 operator >> (std::istream& is, intNDArray<octave_int32>& a);
 
+OCTAVE_INT_CONCAT_FN (octave_int32)
+
 NDS_CMP_OPS (int32NDArray, , octave_int32, )
 NDS_BOOL_OPS (int32NDArray, octave_int32, octave_int32 (0))
 
--- a/liboctave/int32NDArray.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/int32NDArray.h	Fri Jul 23 19:01:23 2004 +0000
@@ -33,6 +33,8 @@
 
 typedef intNDArray<octave_int32> int32NDArray;
 
+OCTAVE_INT_CONCAT_DECL (octave_int32)
+
 NDS_CMP_OP_DECLS (int32NDArray, octave_int32)
 NDS_BOOL_OP_DECLS (int32NDArray, octave_int32)
 
--- a/liboctave/int64NDArray.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/int64NDArray.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -43,6 +43,8 @@
 std::istream&
 operator >> (std::istream& is, intNDArray<octave_int64>& a);
 
+OCTAVE_INT_CONCAT_FN (octave_int64)
+
 NDS_CMP_OPS (int64NDArray, , octave_int64, )
 NDS_BOOL_OPS (int64NDArray, octave_int64, octave_int64 (0))
 
--- a/liboctave/int64NDArray.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/int64NDArray.h	Fri Jul 23 19:01:23 2004 +0000
@@ -33,6 +33,8 @@
 
 typedef intNDArray<octave_int64> int64NDArray;
 
+OCTAVE_INT_CONCAT_DECL (octave_int64)
+
 NDS_CMP_OP_DECLS (int64NDArray, octave_int64)
 NDS_BOOL_OP_DECLS (int64NDArray, octave_int64)
 
--- a/liboctave/int8NDArray.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/int8NDArray.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -43,6 +43,8 @@
 std::istream&
 operator >> (std::istream& is, intNDArray<octave_int8>& a);
 
+OCTAVE_INT_CONCAT_FN (octave_int8)
+
 NDS_CMP_OPS (int8NDArray, , octave_int8, )
 NDS_BOOL_OPS (int8NDArray, octave_int8, octave_int8 (0))
 
--- a/liboctave/int8NDArray.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/int8NDArray.h	Fri Jul 23 19:01:23 2004 +0000
@@ -33,6 +33,8 @@
 
 typedef intNDArray<octave_int8> int8NDArray;
 
+OCTAVE_INT_CONCAT_DECL (octave_int8)
+
 NDS_CMP_OP_DECLS (int8NDArray, octave_int8)
 NDS_BOOL_OP_DECLS (int8NDArray, octave_int8)
 
--- a/liboctave/intNDArray.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/intNDArray.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -64,13 +64,6 @@
 }
 
 template <class T>
-int
-intNDArray<T>::cat (const intNDArray<T>& ra_arg, int dim, int iidx, int move)
-{
-  return ::cat_ra (*this, ra_arg, dim, iidx, move);  
-}
-
-template <class T>
 void
 intNDArray<T>::increment_index (Array<int>& ra_idx,
 			       const dim_vector& dimensions,
@@ -87,6 +80,22 @@
   return ::compute_index (ra_idx, dimensions);
 }
 
+template <class T>
+intNDArray<T>&
+intNDArray<T>::insert (const intNDArray<T>& a, int r, int c)
+{
+  Array<T>::insert (a, r, c);
+  return *this;
+}
+
+template <class T>
+intNDArray<T>&
+intNDArray<T>::insert (const intNDArray<T>& a, const Array<int>& ra_idx)
+{
+  Array<T>::insert (a, ra_idx);
+  return *this;
+}
+
 // This contains no information on the array structure !!!
 
 template <class T>
--- a/liboctave/intNDArray.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/intNDArray.h	Fri Jul 23 19:01:23 2004 +0000
@@ -69,7 +69,6 @@
 
   boolNDArray all (int dim = -1) const;
   boolNDArray any (int dim = -1) const;
-  int cat (const intNDArray<T>& ra_arg, int dim, int iidx, int move);
 
   intNDArray squeeze (void) const
     { return intNDArray<T> (MArrayN<T>::squeeze ()); }
@@ -77,6 +76,9 @@
   intNDArray transpose (void) const
     { return intNDArray<T> (MArrayN<T>::transpose ()); }
 
+  intNDArray& insert (const intNDArray<T>& a, int r, int c);
+  intNDArray& insert (const intNDArray<T>& a, const Array<int>& ra_idx);
+
   static void increment_index (Array<int>& ra_idx,
 			       const dim_vector& dimensions,
 			       int start_dimension = 0);
--- a/liboctave/oct-inttypes.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/oct-inttypes.h	Fri Jul 23 19:01:23 2004 +0000
@@ -313,6 +313,21 @@
 OCTAVE_INT_CMP_OP (==)
 OCTAVE_INT_CMP_OP (!=)
 
+#define OCTAVE_INT_CONCAT_FN(TYPE) \
+intNDArray< TYPE > \
+concat (const intNDArray< TYPE >& ra, const intNDArray< TYPE >& rb, \
+	const Array<int>& ra_idx) \
+{ \
+  intNDArray< TYPE > retval (ra); \
+  retval.insert (rb, ra_idx); \
+  return retval; \
+}
+
+#define OCTAVE_INT_CONCAT_DECL(TYPE) \
+intNDArray< TYPE > \
+concat (const intNDArray< TYPE >& ra, const intNDArray< TYPE >& rb, \
+	const Array<int>& ra_idx);
+
 #undef OCTAVE_INT_TRAIT
 #undef OCTAVE_INT_BINOP_TRAIT
 #undef OCTAVE_INT_MIN_VAL
--- a/liboctave/uint16NDArray.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/uint16NDArray.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -43,6 +43,8 @@
 std::istream&
 operator >> (std::istream& is, intNDArray<octave_uint16>& a);
 
+OCTAVE_INT_CONCAT_FN (octave_uint16)
+
 NDS_CMP_OPS (uint16NDArray, , octave_uint16, )
 NDS_BOOL_OPS (uint16NDArray, octave_uint16, octave_uint16 (0))
 
--- a/liboctave/uint16NDArray.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/uint16NDArray.h	Fri Jul 23 19:01:23 2004 +0000
@@ -33,6 +33,8 @@
 
 typedef intNDArray<octave_uint16> uint16NDArray;
 
+OCTAVE_INT_CONCAT_DECL (octave_uint16)
+
 NDS_CMP_OP_DECLS (uint16NDArray, octave_uint16)
 NDS_BOOL_OP_DECLS (uint16NDArray, octave_uint16)
 
--- a/liboctave/uint32NDArray.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/uint32NDArray.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -43,6 +43,8 @@
 std::istream&
 operator >> (std::istream& is, intNDArray<octave_uint32>& a);
 
+OCTAVE_INT_CONCAT_FN (octave_uint32)
+
 NDS_CMP_OPS (uint32NDArray, , octave_uint32, )
 NDS_BOOL_OPS (uint32NDArray, octave_uint32, octave_uint32 (0))
 
--- a/liboctave/uint32NDArray.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/uint32NDArray.h	Fri Jul 23 19:01:23 2004 +0000
@@ -33,6 +33,8 @@
 
 typedef intNDArray<octave_uint32> uint32NDArray;
 
+OCTAVE_INT_CONCAT_DECL (octave_uint32)
+
 NDS_CMP_OP_DECLS (uint32NDArray, octave_uint32)
 NDS_BOOL_OP_DECLS (uint32NDArray, octave_uint32)
 
--- a/liboctave/uint64NDArray.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/uint64NDArray.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -43,6 +43,8 @@
 std::istream&
 operator >> (std::istream& is, intNDArray<octave_uint64>& a);
 
+OCTAVE_INT_CONCAT_FN (octave_uint64)
+
 NDS_CMP_OPS (uint64NDArray, , octave_uint64, )
 NDS_BOOL_OPS (uint64NDArray, octave_uint64, octave_uint64 (0))
 
--- a/liboctave/uint64NDArray.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/uint64NDArray.h	Fri Jul 23 19:01:23 2004 +0000
@@ -33,6 +33,8 @@
 
 typedef intNDArray<octave_uint64> uint64NDArray;
 
+OCTAVE_INT_CONCAT_DECL (octave_uint64)
+
 NDS_CMP_OP_DECLS (uint64NDArray, octave_uint64)
 NDS_BOOL_OP_DECLS (uint64NDArray, octave_uint64)
 
--- a/liboctave/uint8NDArray.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/uint8NDArray.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -43,6 +43,8 @@
 std::istream&
 operator >> (std::istream& is, intNDArray<octave_uint8>& a);
 
+OCTAVE_INT_CONCAT_FN (octave_uint8)
+
 NDS_CMP_OPS (uint8NDArray, , octave_uint8, )
 NDS_BOOL_OPS (uint8NDArray, octave_uint8, octave_uint8 (0))
 
--- a/liboctave/uint8NDArray.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/liboctave/uint8NDArray.h	Fri Jul 23 19:01:23 2004 +0000
@@ -33,6 +33,8 @@
 
 typedef intNDArray<octave_uint8> uint8NDArray;
 
+OCTAVE_INT_CONCAT_DECL (octave_uint8)
+
 NDS_CMP_OP_DECLS (uint8NDArray, octave_uint8)
 NDS_BOOL_OP_DECLS (uint8NDArray, octave_uint8)
 
--- a/scripts/ChangeLog	Fri Jul 23 16:55:13 2004 +0000
+++ b/scripts/ChangeLog	Fri Jul 23 19:01:23 2004 +0000
@@ -1,3 +1,7 @@
+2004-07-23  David Bateman  <dbateman@free.fr>
+
+	* general/bitcmp.m, general/bitget.m, general/bitset.m: New functions.
+
 2004-07-22  Etienne Grossmann  <etienne@cs.uky.edu>
 
 	* general/sub2ind.m: Make reshaping index list unnecessary.
--- a/src/Cell.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/Cell.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -100,10 +100,26 @@
   return *this;
 }
 
-int
-Cell::cat (const Cell& ra_arg, int dim, int iidx, int move)
+Cell
+concat (const Cell& ra, const Cell& rb, const Array<int>& ra_idx)
 {
-  return ::cat_ra (*this, ra_arg, dim, iidx, move);
+  Cell retval (ra);
+  retval.insert (rb, ra_idx);
+  return retval;
+}
+
+Cell&
+Cell::insert (const Cell& a, int r, int c)
+{
+  Array<octave_value>::insert (a, r, c);
+  return *this;
+}
+
+Cell&
+Cell::insert (const Cell& a, const Array<int>& ra_idx)
+{
+  Array<octave_value>::insert (a, ra_idx);
+  return *this;
 }
 
 /*
--- a/src/Cell.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/Cell.h	Fri Jul 23 19:01:23 2004 +0000
@@ -99,7 +99,10 @@
   // XXX FIXME XXX
   boolMatrix any (int dim = 0) const { return boolMatrix (); }
 
-  int cat (const Cell& ra_arg, int dim, int iidx, int move);
+  friend Cell concat (const Cell& ra, const Cell& rb, const Array<int>& ra_idx);
+
+  Cell& insert (const Cell& a, int r, int c);
+  Cell& insert (const Cell& a, const Array<int>& ra_idx);
 
   // XXX FIXME XXX
   bool is_true (void) const { return false; }
--- a/src/ChangeLog	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/ChangeLog	Fri Jul 23 19:01:23 2004 +0000
@@ -1,3 +1,76 @@
+2004-07-23  David Bateman  <dbateman@free.fr>
+
+	* ov-intx.h (OCTAVE_VALUE_INT_MATRIX_T::array_value,
+	OCTAVE_VALUE_INT_SCALAR_T::array_value): new methods to extract array
+	value from integer types.
+
+	* bitfcns.cc (BITOPX): New Macro renamed from BITOP.
+	(BITOP): Alter to allow different types and call BITOP appropriately.
+	(DO_SBITSHIFT, DO_UBITSHIFT): New macros for signed, unsigned
+	bitshifts.
+
+	(DO_BITSHIFT): Test for shift of more bits than in type, which is
+	undefined.  Generalize to allow double args as well.
+	(Fbitshift): Add int and double types.
+	(Fbitmax): Return 53 bit value which conforms to IEEE754 double
+	mantissa.
+	(Fintmax, Fintmin): New functions.
+	(Fbitget, Fbitset, Fbitcmp): Delete.
+
+	* OPERATORS/op-int.h: Add sm_el_pow function
+
+	* ops.h (CATOPDECL, DEFCATOPX, DEFCATOP, DEFCATOP_FB, DEFNDCATOP_FN, 
+	CATOP_NONCONFORMANT, INSTALL_CATOP): New macros.
+	
+	* OPERATORS/op-b-b.cc, OPERATORS/op-b-bm.cc, OPERATORS/op-bm-b.cc, 
+	OPERATORS/op-bm-bm.cc, OPERATORS/op-cell.cc, OPERATORS/op-chm.cc, 
+	OPERATORS/op-cm-cm.cc, OPERATORS/op-cm-cs.cc, OPERATORS/op-cm-m.cc, 
+	OPERATORS/op-cm-s.cc, OPERATORS/op-cs-cm.cc, OPERATORS/op-cs-cs.cc, 
+	OPERATORS/op-cs-m.cc, OPERATORS/op-cs-s.cc, OPERATORS/op-m-cm.cc, 
+	OPERATORS/op-m-cs.cc, OPERATORS/op-m-m.cc, OPERATORS/op-m-s.cc, 
+	OPERATORS/op-range.cc, OPERATORS/op-s-cm.cc, OPERATORS/op-s-cs.cc, 
+	OPERATORS/op-s-m.cc, OPERATORS/op-s-s.cc, OPERATORS/op-str-str.cc,
+	OPERATORS/op-str-m.cc, OPERATORS/op-str-s.cc (CATOPDECL, DEFCATOPX,
+	DEFCATOP, DEFCATOP_FB, DEFNDCATOP_FN, CATOP_NONCONFORMANT,
+	INSTALL_CATOP): Use them to define concatenation functions.
+
+	* OPERATORS/op-int.h (OCTAVE_CONCAT_FN, OCTAVE_INSTALL_CONCAT_FN):
+	New macros to define and install concatentaion functions for int/uint
+	types.
+	
+	* TEMPLATE-INST/Array-tc.cc (INSTANTIATE_ARRAY_CAT): Delete.
+
+	* pt-mat.cc (tm_row_const::tm_row_const_rep::do_init_element):
+	Also append empty elements to the list of elements to be parsed.
+	(tree_matrix::rvalue): Use new concatenation binary operators.
+
+	* data.cc (cat_add_dims): Delete (now dim_vector::concat).
+	(do_cat): Use new concatenation binary operators.
+
+	* ov-typeinfo.cc (cat_op_fcn): Instantiate the array of cat functions.
+	(register_cat_op, do_register_cat_op, do_lookup_cat_op): New functions.
+	(cat_ops): Lookup table of binary concatentaion operators.
+
+	* ov-typeinfo.h (lookup_cat_op): New function.
+
+	* ov.cc (gripe_cat_op, gripe_cat_op_conv, do_cat_op): New functions.
+
+	* ov.h (cat_op_fcn): Definition.
+	(resize, do_cat_op): New functions.
+
+	* ov-intx.h (resize): New_function
+
+	* version.h (OCTAVE_API_VERSION): Bump version to api-v9.
+
+	* Cell.cc, Cell.h, oct-map.cc, oct-map.h (cat): Delete.
+	(concat): New function.
+
+	* Cell.cc, Cell.h (insert): New function
+
+	* ov-base.cc, ov-base.h, ov-scalar.h, ov-complex.h, ov-bool.h, 
+	ov-range.h, ov-base-mat.h, (resize): New function.
+
+
 2004-07-23  John W. Eaton  <jwe@octave.org>
 
 	* symtab.cc (whos_parameter): Move decl here, from symtab.h.
--- a/src/OPERATORS/op-b-b.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-b-b.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -32,6 +32,8 @@
 #include "oct-obj.h"
 #include "ov.h"
 #include "ov-bool.h"
+#include "ov-scalar.h"
+#include "ov-re-mat.h"
 #include "ov-typeinfo.h"
 #include "ops.h"
 #include "xdiv.h"
@@ -52,6 +54,10 @@
 DEFBINOP_OP (el_and, bool, bool, &&)
 DEFBINOP_OP (el_or, bool, bool, ||)
 
+DEFNDCATOP_FN (b_b, bool, bool, array, array, concat)
+DEFNDCATOP_FN (b_s, bool, scalar, array, array, concat)
+DEFNDCATOP_FN (s_b, scalar, bool, array, array, concat)
+
 void
 install_b_b_ops (void)
 {
@@ -63,6 +69,10 @@
   INSTALL_BINOP (op_ne, octave_bool, octave_bool, ne);
   INSTALL_BINOP (op_el_and, octave_bool, octave_bool, el_and);
   INSTALL_BINOP (op_el_or, octave_bool, octave_bool, el_or);
+
+  INSTALL_CATOP (octave_bool, octave_bool, b_b);
+  INSTALL_CATOP (octave_bool, octave_scalar, b_s);
+  INSTALL_CATOP (octave_scalar, octave_bool, s_b);
 }
 
 /*
--- a/src/OPERATORS/op-b-bm.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-b-bm.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -33,6 +33,8 @@
 #include "ov.h"
 #include "ov-bool.h"
 #include "ov-bool-mat.h"
+#include "ov-scalar.h"
+#include "ov-re-mat.h"
 #include "ov-typeinfo.h"
 #include "ops.h"
 #include "xdiv.h"
@@ -43,11 +45,19 @@
 DEFNDBINOP_FN (el_and, bool, bool_matrix, bool, bool_array, mx_el_and)
 DEFNDBINOP_FN (el_or, bool, bool_matrix, bool, bool_array, mx_el_or)
 
+DEFNDCATOP_FN (b_bm, bool, bool_matrix, array, array, concat)
+DEFNDCATOP_FN (b_m, bool, matrix, array, array, concat)
+DEFNDCATOP_FN (s_bm, scalar, bool_matrix, array, array, concat)
+
 void
 install_b_bm_ops (void)
 {
   INSTALL_BINOP (op_el_and, octave_bool, octave_bool_matrix, el_and);
   INSTALL_BINOP (op_el_or, octave_bool, octave_bool_matrix, el_or);
+
+  INSTALL_CATOP (octave_bool, octave_bool_matrix, b_bm);
+  INSTALL_CATOP (octave_bool, octave_matrix, b_m);
+  INSTALL_CATOP (octave_scalar, octave_bool_matrix, s_bm);
 }
 
 /*
--- a/src/OPERATORS/op-bm-b.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-bm-b.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -33,6 +33,8 @@
 #include "ov.h"
 #include "ov-bool.h"
 #include "ov-bool-mat.h"
+#include "ov-scalar.h"
+#include "ov-re-mat.h"
 #include "ov-typeinfo.h"
 #include "ops.h"
 #include "xdiv.h"
@@ -43,6 +45,10 @@
 DEFNDBINOP_FN (el_and, bool_matrix, bool, bool_array, bool, mx_el_and)
 DEFNDBINOP_FN (el_or, bool_matrix, bool, bool_array, bool, mx_el_or)
 
+DEFNDCATOP_FN (bm_b, bool_matrix, bool, array, array, concat)
+DEFNDCATOP_FN (bm_s, bool_matrix, scalar, array, array, concat)
+DEFNDCATOP_FN (m_b, matrix, bool, array, array, concat)
+
 DEFNDASSIGNOP_FN (assign, bool_matrix, bool, bool_array, assign)
 
 void
@@ -51,6 +57,10 @@
   INSTALL_BINOP (op_el_and, octave_bool_matrix, octave_bool, el_and);
   INSTALL_BINOP (op_el_or, octave_bool_matrix, octave_bool, el_or);
 
+  INSTALL_CATOP (octave_bool_matrix, octave_bool, bm_b);
+  INSTALL_CATOP (octave_bool_matrix, octave_scalar, bm_s);
+  INSTALL_CATOP (octave_matrix, octave_bool, m_b);
+
   INSTALL_ASSIGNOP (op_asn_eq, octave_bool_matrix, octave_bool, assign);
 }
 
--- a/src/OPERATORS/op-bm-bm.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-bm-bm.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -32,6 +32,7 @@
 #include "oct-obj.h"
 #include "ov.h"
 #include "ov-bool-mat.h"
+#include "ov-re-mat.h"
 #include "ov-typeinfo.h"
 #include "ops.h"
 #include "xdiv.h"
@@ -65,6 +66,10 @@
 DEFNDBINOP_FN (el_or,  bool_matrix, bool_matrix, bool_array, bool_array,
 	       mx_el_or)
 
+DEFNDCATOP_FN (bm_bm, bool_matrix, bool_matrix, array, array, concat)
+DEFNDCATOP_FN (bm_m, bool_matrix, matrix, array, array, concat)
+DEFNDCATOP_FN (m_bm, matrix, bool_matrix, array, array, concat)
+
 DEFNDASSIGNOP_FN (assign, bool_matrix, bool_matrix, bool_array, assign)
 
 void
@@ -80,6 +85,10 @@
   INSTALL_BINOP (op_el_and, octave_bool_matrix, octave_bool_matrix, el_and);
   INSTALL_BINOP (op_el_or, octave_bool_matrix, octave_bool_matrix, el_or);
 
+  INSTALL_CATOP (octave_bool_matrix, octave_bool_matrix, bm_bm);
+  INSTALL_CATOP (octave_bool_matrix, octave_matrix, bm_m);
+  INSTALL_CATOP (octave_matrix, octave_bool_matrix, m_bm);
+
   INSTALL_ASSIGNOP (op_asn_eq, octave_bool_matrix, octave_bool_matrix, assign);
 }
 
--- a/src/OPERATORS/op-cell.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-cell.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -52,6 +52,8 @@
     return octave_value (Cell (v.cell_value().transpose ()));
 }
 
+DEFCATOP_FN (c_c, cell, cell, concat)
+
 DEFASSIGNANYOP_FN (assign, cell, assign);
 
 void
@@ -60,6 +62,8 @@
   INSTALL_UNOP (op_transpose, octave_cell, transpose);
   INSTALL_UNOP (op_hermitian, octave_cell, transpose);
 
+  INSTALL_CATOP (octave_cell, octave_cell, c_c);
+
   INSTALL_ASSIGNANYOP (op_asn_eq, octave_cell, assign);
 }
 
--- a/src/OPERATORS/op-chm.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-chm.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -32,6 +32,10 @@
 #include "oct-obj.h"
 #include "ov.h"
 #include "ov-ch-mat.h"
+#include "ov-scalar.h"
+#include "ov-re-mat.h"
+#include "ov-bool.h"
+#include "ov-bool-mat.h"
 #include "ov-typeinfo.h"
 #include "ops.h"
 
@@ -44,11 +48,63 @@
   return octave_value (v.matrix_value().transpose ());
 }
 
+DEFNDCATOP_FN (chm_chm, char_matrix, char_matrix, char_array, char_array, concat)
+
+DEFCATOP (chm_s, char_matrix, scalar)
+{
+  CAST_BINOP_ARGS (const octave_char_matrix&, const octave_scalar&);
+
+  if (Vwarn_num_to_str)
+    gripe_implicit_conversion (v2.type_name (), v1.type_name ());
+
+  return octave_value (concat (v1.char_array_value (), v2.array_value (),
+			       ra_idx));
+}
+
+DEFCATOP (chm_m, char_matrix, matrix)
+{
+  CAST_BINOP_ARGS (const octave_char_matrix&, const octave_matrix&);
+
+  if (Vwarn_num_to_str)
+    gripe_implicit_conversion (v2.type_name (), v1.type_name ());
+
+  return octave_value (concat (v1.char_array_value (), v2.array_value (),
+			       ra_idx));
+}
+
+DEFCATOP (s_chm, scalar, char_matrix)
+{
+  CAST_BINOP_ARGS (const octave_scalar&, const octave_char_matrix&);
+
+  if (Vwarn_num_to_str)
+    gripe_implicit_conversion (v1.type_name (), v2.type_name ());
+
+  return octave_value (concat (v1.array_value (), v2.char_array_value (),
+			       ra_idx));
+}
+
+DEFCATOP (m_chm, matrix, char_matrix)
+{
+  CAST_BINOP_ARGS (const octave_matrix&, const octave_char_matrix&);
+
+  if (Vwarn_num_to_str)
+    gripe_implicit_conversion (v1.type_name (), v2.type_name ());
+
+  return octave_value (concat (v1.array_value (), v2.char_array_value (),
+			       ra_idx));
+}
+
 void
 install_chm_ops (void)
 {
   INSTALL_UNOP (op_transpose, octave_char_matrix, transpose);
   INSTALL_UNOP (op_hermitian, octave_char_matrix, transpose);
+
+  INSTALL_CATOP (octave_char_matrix, octave_char_matrix, chm_chm);
+  INSTALL_CATOP (octave_char_matrix, octave_scalar, chm_s);
+  INSTALL_CATOP (octave_char_matrix, octave_matrix, chm_m);
+  INSTALL_CATOP (octave_scalar, octave_char_matrix, s_chm);
+  INSTALL_CATOP (octave_matrix, octave_char_matrix, m_chm);
 }
 
 /*
--- a/src/OPERATORS/op-cm-cm.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-cm-cm.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -108,6 +108,8 @@
 DEFNDBINOP_FN (el_and, complex_matrix, complex_matrix, complex_array, complex_array, mx_el_and)
 DEFNDBINOP_FN (el_or,  complex_matrix, complex_matrix, complex_array, complex_array, mx_el_or)
 
+DEFNDCATOP_FN (cm_cm, complex_matrix, complex_matrix, complex_array, complex_array, concat)
+
 DEFNDASSIGNOP_FN (assign, complex_matrix, complex_matrix, complex_array, assign)
 
 void
@@ -140,6 +142,8 @@
   INSTALL_BINOP (op_el_and, octave_complex_matrix, octave_complex_matrix, el_and);
   INSTALL_BINOP (op_el_or, octave_complex_matrix, octave_complex_matrix, el_or);
 
+  INSTALL_CATOP (octave_complex_matrix, octave_complex_matrix, cm_cm);
+
   INSTALL_ASSIGNOP (op_asn_eq, octave_complex_matrix, octave_complex_matrix, assign);
 }
 
--- a/src/OPERATORS/op-cm-cs.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-cm-cs.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -101,6 +101,8 @@
 DEFNDBINOP_FN (el_and, complex_matrix, complex, complex_array, complex, mx_el_and)
 DEFNDBINOP_FN (el_or,  complex_matrix, complex, complex_array, complex, mx_el_or)
 
+DEFNDCATOP_FN (cm_cs, complex_matrix, complex, complex_array, complex_array, concat)
+
 DEFNDASSIGNOP_FN (assign, complex_matrix, complex, complex_array, assign)
 
 void
@@ -125,6 +127,8 @@
   INSTALL_BINOP (op_el_and, octave_complex_matrix, octave_complex, el_and);
   INSTALL_BINOP (op_el_or, octave_complex_matrix, octave_complex, el_or);
 
+  INSTALL_CATOP (octave_complex_matrix, octave_complex, cm_cs);
+
   INSTALL_ASSIGNOP (op_asn_eq, octave_complex_matrix, octave_complex, assign);
 }
 
--- a/src/OPERATORS/op-cm-m.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-cm-m.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -80,6 +80,8 @@
 DEFNDBINOP_FN (el_and, complex_matrix, matrix, complex_array, array, mx_el_and)
 DEFNDBINOP_FN (el_or,  complex_matrix, matrix, complex_array, array, mx_el_or)
 
+DEFNDCATOP_FN (cm_m, complex_matrix, matrix, complex_array, array, concat)
+
 DEFNDASSIGNOP_FN (assign, complex_matrix, matrix, complex_array, assign)
 
 void
@@ -104,6 +106,8 @@
   INSTALL_BINOP (op_el_and, octave_complex_matrix, octave_matrix, el_and);
   INSTALL_BINOP (op_el_or, octave_complex_matrix, octave_matrix, el_or);
 
+  INSTALL_CATOP (octave_complex_matrix, octave_matrix, cm_m);
+
   INSTALL_ASSIGNOP (op_asn_eq, octave_complex_matrix, octave_matrix, assign);
 }
 
--- a/src/OPERATORS/op-cm-s.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-cm-s.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -105,6 +105,8 @@
 DEFNDBINOP_FN (el_and, complex_matrix, scalar, complex_array, scalar, mx_el_and)
 DEFNDBINOP_FN (el_or,  complex_matrix, scalar, complex_array, scalar, mx_el_or)
 
+DEFNDCATOP_FN (cm_s, complex_matrix, scalar, complex_array, array, concat)
+
 DEFNDASSIGNOP_FN (assign, complex_matrix, scalar, complex_array, assign)
 
 void
@@ -129,6 +131,8 @@
   INSTALL_BINOP (op_el_and, octave_complex_matrix, octave_scalar, el_and);
   INSTALL_BINOP (op_el_or, octave_complex_matrix, octave_scalar, el_or);
 
+  INSTALL_CATOP (octave_complex_matrix, octave_scalar, cm_s);
+
   INSTALL_ASSIGNOP (op_asn_eq, octave_complex_matrix, octave_scalar, assign);
 }
 
--- a/src/OPERATORS/op-cs-cm.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-cs-cm.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -94,6 +94,8 @@
 DEFNDBINOP_FN (el_and, complex, complex_matrix, complex, complex_array, mx_el_and)
 DEFNDBINOP_FN (el_or,  complex, complex_matrix, complex, complex_array, mx_el_or)
 
+DEFNDCATOP_FN (cs_cm, complex, complex_matrix, complex_array, complex_array, concat)
+
 DEFCONV (complex_matrix_conv, complex, complex_matrix)
 {
   CAST_CONV_ARG (const octave_complex&);
@@ -123,6 +125,8 @@
   INSTALL_BINOP (op_el_and, octave_complex, octave_complex_matrix, el_and);
   INSTALL_BINOP (op_el_or, octave_complex, octave_complex_matrix, el_or);
 
+  INSTALL_CATOP (octave_complex, octave_complex_matrix, cs_cm);
+
   INSTALL_ASSIGNCONV (octave_complex, octave_complex_matrix, octave_complex_matrix);
 
   INSTALL_WIDENOP (octave_complex, octave_complex_matrix, complex_matrix_conv);
--- a/src/OPERATORS/op-cs-cs.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-cs-cs.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -176,6 +176,8 @@
   return v1.complex_value () != 0.0 || v2.complex_value () != 0.0;
 }
 
+DEFNDCATOP_FN (cs_cs, complex, complex, complex_array, complex_array, concat)
+
 void
 install_cs_cs_ops (void)
 {
@@ -206,6 +208,8 @@
   INSTALL_BINOP (op_el_and, octave_complex, octave_complex, el_and);
   INSTALL_BINOP (op_el_or, octave_complex, octave_complex, el_or);
 
+  INSTALL_CATOP (octave_complex, octave_complex, cs_cs);
+
   INSTALL_ASSIGNCONV (octave_complex, octave_complex, octave_complex_matrix);
 }
 
--- a/src/OPERATORS/op-cs-m.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-cs-m.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -100,6 +100,8 @@
 DEFNDBINOP_FN (el_and, complex, matrix, complex, array, mx_el_and)
 DEFNDBINOP_FN (el_or,  complex, matrix, complex, array, mx_el_or)
 
+DEFNDCATOP_FN (cs_m, complex, matrix, complex_array, array, concat)
+
 void
 install_cs_m_ops (void)
 {
@@ -122,6 +124,8 @@
   INSTALL_BINOP (op_el_and, octave_complex, octave_matrix, el_and);
   INSTALL_BINOP (op_el_or, octave_complex, octave_matrix, el_or);
 
+  INSTALL_CATOP (octave_complex, octave_matrix, cs_m);
+
   INSTALL_ASSIGNCONV (octave_complex, octave_matrix, octave_complex_matrix);
 }
 
--- a/src/OPERATORS/op-cs-s.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-cs-s.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -155,6 +155,8 @@
   return v1.complex_value () != 0.0 || v2.double_value ();
 }
 
+DEFNDCATOP_FN (cs_s, complex, scalar, complex_array, array, concat)
+
 void
 install_cs_s_ops (void)
 {
@@ -177,6 +179,8 @@
   INSTALL_BINOP (op_el_and, octave_complex, octave_scalar, el_and);
   INSTALL_BINOP (op_el_or, octave_complex, octave_scalar, el_or);
 
+  INSTALL_CATOP (octave_complex, octave_scalar, cs_s);
+
   INSTALL_ASSIGNCONV (octave_complex, octave_scalar, octave_complex_matrix);
 }
 
--- a/src/OPERATORS/op-int.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-int.h	Fri Jul 23 19:01:23 2004 +0000
@@ -20,6 +20,18 @@
 
 */
 
+#define OCTAVE_CONCAT_FN(TYPE) \
+  DEFNDCATOP_FN (TYPE ## _s_s, TYPE ## _scalar, TYPE ## _scalar, TYPE ## _array, TYPE ## _array, concat) \
+  DEFNDCATOP_FN (TYPE ## _s_m, TYPE ## _scalar, TYPE ## _matrix, TYPE ## _array, TYPE ## _array, concat) \
+  DEFNDCATOP_FN (TYPE ## _m_s, TYPE ## _matrix, TYPE ## _scalar, TYPE ## _array, TYPE ## _array, concat) \
+  DEFNDCATOP_FN (TYPE ## _m_m, TYPE ## _matrix, TYPE ## _matrix, TYPE ## _array, TYPE ## _array, concat)
+
+#define OCTAVE_INSTALL_CONCAT_FN(TYPE) \
+  INSTALL_CATOP (octave_ ## TYPE ## _scalar, octave_ ## TYPE ## _scalar, TYPE ## _s_s) \
+  INSTALL_CATOP (octave_ ## TYPE ## _scalar, octave_ ## TYPE ## _matrix, TYPE ## _s_m) \
+  INSTALL_CATOP (octave_ ## TYPE ## _matrix, octave_ ## TYPE ## _scalar, TYPE ## _m_s) \
+  INSTALL_CATOP (octave_ ## TYPE ## _matrix, octave_ ## TYPE ## _matrix, TYPE ## _m_m)
+
 #define OCTAVE_S_INT_UNOPS(TYPE) \
   /* scalar unary ops. */  \
  \
@@ -148,7 +160,15 @@
  \
   DEFNDBINOP_OP (sm_el_mul, TS ## _scalar, TM ## _matrix, TS ## _scalar, TM ## _array, *) \
   /* DEFNDBINOP_FN (sm_el_div, TS ## _scalar, TM ## _matrix, TS ## _scalar, TM ## _array, x_el_div) */ \
-  /* DEFNDBINOP_FN (sm_el_pow, TS ## _scalar, TM ## _matrix, TS ## _scalar, TM ## _array, elem_xpow) */ \
+  DEFBINOP (sm_el_pow, TS ## _scalar, TM ## _matrix) \
+  { \
+    CAST_BINOP_ARGS (const octave_ ## TS ## _scalar&, const octave_ ## TM ## _matrix&); \
+ \
+    double d = v1.TS ## _scalar_value (); \
+ \
+    /* XXX FIXME XXX Return type wrong */ \
+    return octave_value (elem_xpow (d, v2.array_value()));	\
+  } \
  \
   /* DEFBINOP (sm_el_ldiv, TS ## _scalar, TM ## _matrix) */ \
   /* { */ \
@@ -350,7 +370,8 @@
   OCTAVE_SS_INT_OPS (TYPE) \
   OCTAVE_SM_INT_OPS (TYPE) \
   OCTAVE_MS_INT_OPS (TYPE) \
-  OCTAVE_MM_INT_OPS (TYPE)
+  OCTAVE_MM_INT_OPS (TYPE) \
+  OCTAVE_CONCAT_FN (TYPE)
 
 #define OCTAVE_INSTALL_S_INT_UNOPS(TYPE) \
   INSTALL_UNOP (op_not, octave_ ## TYPE ## _scalar, s_not); \
@@ -406,7 +427,7 @@
   /* INSTALL_BINOP (op_ldiv, octave_ ## T1 ## _scalar, octave_ ## T2 ## _matrix, sm_ldiv); */ \
   INSTALL_BINOP (op_el_mul, octave_ ## T1 ## _scalar, octave_ ## T2 ## _matrix, sm_el_mul); \
   /* INSTALL_BINOP (op_el_div, octave_ ## T1 ## _scalar, octave_ ## T2 ## _matrix, sm_el_div); */ \
-  /* INSTALL_BINOP (op_el_pow, octave_ ## T1 ## _scalar, octave_ ## T2 ## _matrix, sm_el_pow); */ \
+  INSTALL_BINOP (op_el_pow, octave_ ## T1 ## _scalar, octave_ ## T2 ## _matrix, sm_el_pow); \
   /* INSTALL_BINOP (op_el_ldiv, octave_ ## T1 ## _scalar, octave_ ## T2 ## _matrix, sm_el_ldiv); */
 
 #define OCTAVE_INSTALL_SM_INT_CMP_OPS(T1, T2) \
@@ -526,7 +547,8 @@
   OCTAVE_INSTALL_SS_INT_OPS (TYPE) \
   OCTAVE_INSTALL_SM_INT_OPS (TYPE) \
   OCTAVE_INSTALL_MS_INT_OPS (TYPE) \
-  OCTAVE_INSTALL_MM_INT_OPS (TYPE)
+  OCTAVE_INSTALL_MM_INT_OPS (TYPE) \
+  OCTAVE_INSTALL_CONCAT_FN (TYPE)
 
 /*
 ;;; Local Variables: ***
--- a/src/OPERATORS/op-m-cm.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-m-cm.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -80,6 +80,8 @@
 DEFNDBINOP_FN (el_and, matrix, complex_matrix, array, complex_array, mx_el_and)
 DEFNDBINOP_FN (el_or,  matrix, complex_matrix, array, complex_array, mx_el_or)
 
+DEFNDCATOP_FN (m_cm, matrix, complex_matrix, array, complex_array, concat)
+
 DEFCONV (complex_matrix_conv, matrix, complex_matrix)
 {
   CAST_CONV_ARG (const octave_matrix&);
@@ -109,6 +111,8 @@
   INSTALL_BINOP (op_el_and, octave_matrix, octave_complex_matrix, el_and);
   INSTALL_BINOP (op_el_or, octave_matrix, octave_complex_matrix, el_or);
 
+  INSTALL_CATOP (octave_matrix, octave_complex_matrix, m_cm);
+
   INSTALL_ASSIGNCONV (octave_matrix, octave_complex_matrix, octave_complex_matrix);
 
   INSTALL_WIDENOP (octave_matrix, octave_complex_matrix, complex_matrix_conv);
--- a/src/OPERATORS/op-m-cs.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-m-cs.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -107,6 +107,8 @@
 DEFNDBINOP_FN (el_and, matrix, complex, array, complex, mx_el_and)
 DEFNDBINOP_FN (el_or, matrix, complex, array, complex, mx_el_or)
 
+DEFNDCATOP_FN (m_cs, matrix, complex, array, complex_array, concat)
+
 void
 install_m_cs_ops (void)
 {
@@ -129,6 +131,8 @@
   INSTALL_BINOP (op_el_and, octave_matrix, octave_complex, el_and);
   INSTALL_BINOP (op_el_or, octave_matrix, octave_complex, el_or);
 
+  INSTALL_CATOP (octave_matrix, octave_complex, m_cs);
+
   INSTALL_ASSIGNCONV (octave_matrix, octave_complex, octave_complex_matrix);
 }
 
--- a/src/OPERATORS/op-m-m.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-m-m.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -95,6 +95,8 @@
 DEFNDBINOP_FN (el_and, matrix, matrix, array, array, mx_el_and)
 DEFNDBINOP_FN (el_or,  matrix, matrix, array, array, mx_el_or)
 
+DEFNDCATOP_FN (m_m, matrix, matrix, array, array, concat)
+
 DEFNDASSIGNOP_FN (assign, matrix, matrix, array, assign)
 
 void
@@ -127,6 +129,8 @@
   INSTALL_BINOP (op_el_and, octave_matrix, octave_matrix, el_and);
   INSTALL_BINOP (op_el_or, octave_matrix, octave_matrix, el_or);
 
+  INSTALL_CATOP (octave_matrix, octave_matrix, m_m);
+
   INSTALL_ASSIGNOP (op_asn_eq, octave_matrix, octave_matrix, assign);
 }
 
--- a/src/OPERATORS/op-m-s.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-m-s.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -101,6 +101,8 @@
 DEFNDBINOP_FN (el_and, matrix, scalar, array, scalar, mx_el_and)
 DEFNDBINOP_FN (el_or, matrix, scalar, array, scalar, mx_el_or)
 
+DEFNDCATOP_FN (m_s, matrix, scalar, array, array, concat)
+
 DEFNDASSIGNOP_FN (assign, matrix, scalar, array, assign)
 
 void
@@ -131,6 +133,8 @@
   INSTALL_BINOP (op_el_and, octave_matrix, octave_scalar, el_and);
   INSTALL_BINOP (op_el_or, octave_matrix, octave_scalar, el_or);
 
+  INSTALL_CATOP (octave_matrix, octave_scalar, m_s);
+
   INSTALL_ASSIGNOP (op_asn_eq, octave_matrix, octave_scalar, assign);
 }
 
--- a/src/OPERATORS/op-range.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-range.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -32,6 +32,13 @@
 #include "oct-obj.h"
 #include "ov.h"
 #include "ov-range.h"
+#include "ov-ch-mat.h"
+#include "ov-scalar.h"
+#include "ov-re-mat.h"
+#include "ov-complex.h"
+#include "ov-cx-mat.h"
+#include "ov-bool.h"
+#include "ov-bool-mat.h"
 #include "ov-typeinfo.h"
 #include "ops.h"
 
@@ -53,6 +60,22 @@
   return octave_value (v.matrix_value().transpose ());
 }
 
+DEFNDCATOP_FN (r_r, range, range, array, array, concat)
+DEFNDCATOP_FN (r_s, range, scalar, array, array, concat)
+DEFNDCATOP_FN (r_m, range, matrix, array, array, concat)
+DEFNDCATOP_FN (r_cs, range, complex, array, complex_array, concat)
+DEFNDCATOP_FN (r_cm, range, complex_matrix, array, complex_array, concat)
+DEFNDCATOP_FN (r_b, range, bool, array, array, concat)
+DEFNDCATOP_FN (r_bm, range, bool_matrix, array, array, concat)
+DEFNDCATOP_FN (r_chm, range, char_matrix, array, char_array, concat)
+DEFNDCATOP_FN (s_r, scalar, range, array, array, concat)
+DEFNDCATOP_FN (m_r, matrix, range, array, array, concat)
+DEFNDCATOP_FN (cs_r, complex, range, complex_array, array, concat)
+DEFNDCATOP_FN (cm_r, complex_matrix, range, complex_array, array, concat)
+DEFNDCATOP_FN (b_r, bool, range, array, array, concat)
+DEFNDCATOP_FN (bm_r, bool_matrix, range, array, array, concat)
+DEFNDCATOP_FN (chm_r, char_matrix, range, char_array, array, concat)
+
 void
 install_range_ops (void)
 {
@@ -60,6 +83,22 @@
   INSTALL_UNOP (op_uminus, octave_range, uminus);
   INSTALL_UNOP (op_transpose, octave_range, transpose);
   INSTALL_UNOP (op_hermitian, octave_range, transpose);
+
+  INSTALL_CATOP (octave_range, octave_range, r_r);
+  INSTALL_CATOP (octave_range, octave_scalar, r_s);
+  INSTALL_CATOP (octave_range, octave_matrix, r_m);
+  INSTALL_CATOP (octave_range, octave_complex, r_cs);
+  INSTALL_CATOP (octave_range, octave_complex_matrix, r_cm);
+  INSTALL_CATOP (octave_range, octave_bool, r_b);
+  INSTALL_CATOP (octave_range, octave_bool_matrix, r_bm);
+  INSTALL_CATOP (octave_range, octave_char_matrix, r_chm);
+  INSTALL_CATOP (octave_scalar, octave_range, s_r);
+  INSTALL_CATOP (octave_matrix, octave_range, m_r);
+  INSTALL_CATOP (octave_complex, octave_range, cs_r);
+  INSTALL_CATOP (octave_complex_matrix, octave_range, cm_r);
+  INSTALL_CATOP (octave_bool, octave_range, b_r);
+  INSTALL_CATOP (octave_bool_matrix, octave_range, bm_r);
+  INSTALL_CATOP (octave_char_matrix, octave_range, chm_r);
 }
 
 /*
--- a/src/OPERATORS/op-s-cm.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-s-cm.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -111,6 +111,8 @@
   return mx_el_or (v1.double_value (), v2.complex_array_value ());
 }
 
+DEFNDCATOP_FN (s_cm, scalar, complex_matrix, array, complex_array, concat)
+
 DEFCONV (complex_matrix_conv, scalar, complex_matrix)
 {
   CAST_CONV_ARG (const octave_scalar&);
@@ -140,6 +142,8 @@
   INSTALL_BINOP (op_el_and, octave_scalar, octave_complex_matrix, el_and);
   INSTALL_BINOP (op_el_or, octave_scalar, octave_complex_matrix, el_or);
 
+  INSTALL_CATOP (octave_scalar, octave_complex_matrix, s_cm);
+
   INSTALL_ASSIGNCONV (octave_scalar, octave_complex_matrix, octave_complex_matrix);
 
   INSTALL_WIDENOP (octave_scalar, octave_complex_matrix, complex_matrix_conv);
--- a/src/OPERATORS/op-s-cs.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-s-cs.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -155,6 +155,8 @@
   return octave_value (v1.double_value () || (v2.complex_value () != 0.0));
 }
 
+DEFNDCATOP_FN (s_cs, scalar, complex, array, complex_array, concat)
+
 void
 install_s_cs_ops (void)
 {
@@ -177,6 +179,8 @@
   INSTALL_BINOP (op_el_and, octave_scalar, octave_complex, el_and);
   INSTALL_BINOP (op_el_or, octave_scalar, octave_complex, el_or);
 
+  INSTALL_CATOP (octave_scalar, octave_complex, s_cs);
+
   INSTALL_ASSIGNCONV (octave_scalar, octave_complex, octave_complex_matrix);
 }
 
--- a/src/OPERATORS/op-s-m.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-s-m.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -94,6 +94,8 @@
 DEFNDBINOP_FN (el_and, scalar, matrix, scalar, array, mx_el_and)
 DEFNDBINOP_FN (el_or,  scalar, matrix, scalar, array, mx_el_or)
 
+DEFNDCATOP_FN (s_m, scalar, matrix, array, array, concat)
+
 DEFCONV (matrix_conv, scalar, matrix)
 {
   CAST_CONV_ARG (const octave_scalar&);
@@ -123,6 +125,8 @@
   INSTALL_BINOP (op_el_and, octave_scalar, octave_matrix, el_and);
   INSTALL_BINOP (op_el_or, octave_scalar, octave_matrix, el_or);
 
+  INSTALL_CATOP (octave_scalar, octave_matrix, s_m);
+
   INSTALL_ASSIGNCONV (octave_scalar, octave_matrix, octave_matrix);
 
   INSTALL_WIDENOP (octave_scalar, octave_matrix, matrix_conv);
--- a/src/OPERATORS/op-s-s.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-s-s.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -118,6 +118,8 @@
 DEFBINOP_OP (el_and, scalar, scalar, &&)
 DEFBINOP_OP (el_or, scalar, scalar, ||)
 
+DEFNDCATOP_FN (s_s, scalar, scalar, array, array, concat)
+
 void
 install_s_s_ops (void)
 {
@@ -148,6 +150,8 @@
   INSTALL_BINOP (op_el_and, octave_scalar, octave_scalar, el_and);
   INSTALL_BINOP (op_el_or, octave_scalar, octave_scalar, el_or);
 
+  INSTALL_CATOP (octave_scalar, octave_scalar, s_s);
+
   INSTALL_ASSIGNCONV (octave_scalar, octave_scalar, octave_matrix);
 }
 
--- a/src/OPERATORS/op-str-m.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-str-m.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -48,10 +48,37 @@
   return octave_value ();
 }
 
+DEFCATOP (str_m, char_matrix_str, matrix)
+{
+  CAST_BINOP_ARGS (const octave_char_matrix_str&,
+		   const octave_matrix&);
+
+  if (Vwarn_num_to_str)
+    gripe_implicit_conversion (v2.type_name (), v1.type_name ());
+
+  return octave_value (concat (v1.char_array_value (), v2.array_value (), 
+			       ra_idx), true);
+}
+
+DEFCATOP (m_str, matrix, char_matrix_str)
+{
+  CAST_BINOP_ARGS (const octave_matrix&,
+		   const octave_char_matrix_str&);
+
+  if (Vwarn_num_to_str)
+    gripe_implicit_conversion (v1.type_name (), v2.type_name ());
+
+  return octave_value (concat (v1.array_value (), v2.char_array_value (), 
+			       ra_idx), true);
+}
+
 void
 install_str_m_ops (void)
 {
   INSTALL_ASSIGNOP (op_asn_eq, octave_char_matrix_str, octave_matrix, assign);
+
+  INSTALL_CATOP (octave_char_matrix_str, octave_matrix, str_m);
+  INSTALL_CATOP (octave_matrix, octave_char_matrix_str, m_str);
 }
 
 /*
--- a/src/OPERATORS/op-str-s.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-str-s.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -48,10 +48,37 @@
   return octave_value ();
 }
 
+DEFCATOP (str_s, char_matrix_str, scalar)
+{
+  CAST_BINOP_ARGS (const octave_char_matrix_str&,
+		   const octave_scalar&);
+
+  if (Vwarn_num_to_str)
+    gripe_implicit_conversion (v2.type_name (), v1.type_name ());
+
+  return octave_value (concat (v1.char_array_value (), v2.array_value (), 
+			       ra_idx), true);
+}
+
+DEFCATOP (s_str, scalar, char_matrix_str)
+{
+  CAST_BINOP_ARGS (const octave_scalar&,
+		   const octave_char_matrix_str&);
+
+  if (Vwarn_num_to_str)
+    gripe_implicit_conversion (v1.type_name (), v2.type_name ());
+
+  return octave_value (concat (v1.array_value (), v2.char_array_value (), 
+			       ra_idx), true);
+}
+
 void
 install_str_s_ops (void)
 {
   INSTALL_ASSIGNOP (op_asn_eq, octave_char_matrix_str, octave_scalar, assign);
+
+  INSTALL_CATOP (octave_char_matrix_str, octave_scalar, str_s);
+  INSTALL_CATOP (octave_scalar, octave_char_matrix_str, s_str);
 }
 
 /*
--- a/src/OPERATORS/op-str-str.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/OPERATORS/op-str-str.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -117,6 +117,14 @@
   return octave_value ();
 }
 
+DEFCATOP (str_str, char_matrix_str, char_matrix_str)
+{
+  CAST_BINOP_ARGS (const octave_char_matrix_str&,
+		   const octave_char_matrix_str&);
+  return octave_value (concat (v1.char_array_value (), v2.char_array_value (), 
+			       ra_idx), true);
+}
+
 void
 install_str_str_ops (void)
 {
@@ -126,6 +134,8 @@
   INSTALL_BINOP (op_eq, octave_char_matrix_str, octave_char_matrix_str, eq);
   INSTALL_BINOP (op_ne, octave_char_matrix_str, octave_char_matrix_str, ne);
 
+  INSTALL_CATOP (octave_char_matrix_str, octave_char_matrix_str, str_str);
+
   INSTALL_ASSIGNOP (op_asn_eq, octave_char_matrix_str, octave_char_matrix_str, assign);
 }
 
--- a/src/TEMPLATE-INST/Array-tc.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/TEMPLATE-INST/Array-tc.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -51,8 +51,6 @@
 
 INSTANTIATE_ARRAY_ASSIGN (octave_value, octave_value);
 
-INSTANTIATE_ARRAY_CAT (octave_value);
-
 template class Array2<octave_value>;
 
 template class ArrayN<octave_value>;
--- a/src/bitfcns.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/bitfcns.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -31,11 +31,53 @@
 #include "error.h"
 #include "ov.h"
 #include "ov-uint64.h"
-
+#include "ov-uint32.h"
+#include "ov-uint16.h"
+#include "ov-uint8.h"
+#include "ov-int64.h"
+#include "ov-int32.h"
+#include "ov-int16.h"
+#include "ov-int8.h"
+#include "ov-scalar.h"
+#include "ov-re-mat.h"
 
 // XXX FIXME XXX -- could probably eliminate some code duplication by
 // clever use of templates.
 
+#define BITOPX(OP, FNAME, RET) \
+      { \
+	int nelx = x.numel (); \
+	int nely = y.numel (); \
+ \
+	bool is_scalar_op = (nelx == 1 || nely == 1); \
+ \
+	dim_vector dvx = x.dims (); \
+	dim_vector dvy = y.dims (); \
+ \
+	bool is_array_op = (dvx == dvy); \
+ \
+	if (is_array_op || is_scalar_op) \
+	  { \
+	    RET result; \
+ \
+	    if (nelx != 1) \
+	      result.resize (dvx); \
+	    else \
+	      result.resize (dvy); \
+ \
+	    for (int i = 0; i < nelx; i++) \
+	      if (is_scalar_op) \
+		for (int k = 0; k < nely; k++) \
+		  result(i+k) = x(i) OP y(k); \
+	      else \
+		result(i) = x(i) OP y(i); \
+ \
+	      retval = result; \
+	  } \
+	else \
+	  error ("%s: size of x and y must match, or one operand must be a scalar", FNAME); \
+      }
+
 #define BITOP(OP, FNAME) \
  \
   octave_value retval; \
@@ -44,44 +86,175 @@
  \
   if (nargin == 2) \
     { \
-      uint64NDArray x = args(0).uint64_array_value (); \
-      uint64NDArray y = args(1).uint64_array_value (); \
- \
-      if (! error_state) \
+      if (args(0).type_id () == octave_matrix::static_type_id () || \
+	  args(0).type_id () == octave_scalar::static_type_id () || \
+	  args(1).type_id () == octave_matrix::static_type_id () || \
+	  args(1).type_id () == octave_scalar::static_type_id ()) \
 	{ \
-	  int nelx = x.numel (); \
-	  int nely = y.numel (); \
- \
-	  bool is_scalar_op = (nelx == 1 || nely == 1); \
+	  bool arg0_is_int = true; \
+	  bool arg1_is_int = true; \
  \
-	  dim_vector dvx = x.dims (); \
-	  dim_vector dvy = y.dims (); \
- \
-	  bool is_array_op = (dvx == dvy); \
+	  if (args(0).type_id () == octave_matrix::static_type_id () || \
+	      args(0).type_id () == octave_scalar::static_type_id ())	\
+	    arg0_is_int = false; \
  \
-	  if (is_array_op || is_scalar_op) \
-	    { \
-	      uint64NDArray result; \
- \
-	      if (nelx != 1) \
-		result.resize (dvx); \
-	      else \
-		result.resize (dvy); \
+	  if (args(1).type_id () == octave_matrix::static_type_id () || \
+	      args(1).type_id () == octave_scalar::static_type_id ())	\
+	    arg1_is_int = false; \
  \
-	      for (int i = 0; i < nelx; i++) \
-		if (is_scalar_op) \
-		  for (int k = 0; k < nely; k++) \
-		    result(i+k) = x(i) OP y(k); \
-		else \
-		  result(i) = x(i) OP y(i); \
- \
-		retval = result; \
+	  if (!arg0_is_int && !arg1_is_int) \
+	    { \
+	      uint64NDArray x (args(0).array_value ());		\
+	      uint64NDArray y (args(1).array_value ());	\
+	      if (! error_state)				\
+		BITOPX (OP, FNAME, uint64NDArray);		\
+	      retval = retval.array_value ();			\
 	    } \
 	  else \
-	    error ("%s: size of x and y must match, or one operand must be a scalar", FNAME); \
-        } \
+	    { \
+	      int p = (arg0_is_int ? 1 : 0); \
+	      int q = (arg0_is_int ? 0 : 1); \
+	      NDArray dx = args(p).array_value (); \
+ \
+	      if (args(q).type_id () == octave_uint64_matrix::static_type_id () || \
+		  args(q).type_id () == octave_uint64_scalar::static_type_id ()) \
+		{							\
+		  uint64NDArray x (dx);					\
+		  uint64NDArray y = args(q).uint64_array_value ();	\
+		  if (! error_state)					\
+		    BITOPX (OP, FNAME, uint64NDArray);			\
+		 } \
+	      else if (args(q).type_id () == octave_uint32_matrix::static_type_id () || \
+		       args(q).type_id () == octave_uint32_scalar::static_type_id ()) \
+		{							\
+		  uint32NDArray x (dx);					\
+		  uint32NDArray y = args(q).uint32_array_value ();	\
+		  if (! error_state)					\
+		    BITOPX (OP, FNAME, uint32NDArray);			\
+		} \
+	      else if (args(q).type_id () == octave_uint16_matrix::static_type_id () || \
+		       args(q).type_id () == octave_uint16_scalar::static_type_id ()) \
+		{							\
+		  uint16NDArray x (dx);					\
+		  uint16NDArray y = args(q).uint16_array_value ();	\
+		  if (! error_state)					\
+		    BITOPX (OP, FNAME, uint16NDArray);			\
+		} \
+	      else if (args(q).type_id () == octave_uint8_matrix::static_type_id () || \
+		       args(q).type_id () == octave_uint8_scalar::static_type_id ()) \
+		{							\
+		  uint8NDArray x (dx);					\
+		  uint8NDArray y = args(q).uint8_array_value ();	\
+		  if (! error_state)					\
+		    BITOPX (OP, FNAME, uint8NDArray);			\
+		}							\
+	      else if (args(q).type_id () == octave_int64_matrix::static_type_id () || \
+		       args(q).type_id () == octave_int64_scalar::static_type_id ()) \
+		{							\
+		  int64NDArray x (dx);					\
+		  int64NDArray y = args(q).int64_array_value ();	\
+		  if (! error_state)					\
+		    BITOPX (OP, FNAME, int64NDArray);			\
+		}							\
+	      else if (args(q).type_id () == octave_int32_matrix::static_type_id () || \
+		       args(q).type_id () == octave_int32_scalar::static_type_id ()) \
+		{							\
+		  int32NDArray x (dx);					\
+		  int32NDArray y = args(q).int32_array_value ();	\
+		  if (! error_state)					\
+		    BITOPX (OP, FNAME, int32NDArray);			\
+		}							\
+	      else if (args(q).type_id () == octave_int16_matrix::static_type_id () || \
+	      args(q).type_id () == octave_int16_scalar::static_type_id ()) \
+		{							\
+		  int16NDArray x (dx);					\
+		  int16NDArray y = args(q).int16_array_value ();	\
+		  if (! error_state)					\
+		    BITOPX (OP, FNAME, int16NDArray);			\
+		}							\
+	      else if (args(q).type_id () == octave_int8_matrix::static_type_id () || \
+		       args(q).type_id () == octave_int8_scalar::static_type_id ()) \
+		{							\
+		  int8NDArray x (dx);					\
+		  int8NDArray y = args(q).int8_array_value ();		\
+		  if (! error_state)					\
+		    BITOPX (OP, FNAME, int8NDArray);			\
+		}							\
+	      else							\
+		error ("%s: illegal operand type", FNAME);		\
+	    }								\
+	}								\
+      else if (args(0).type_id () == args(1).type_id ())		\
+	{ \
+	  if (args(0).type_id () == octave_uint64_matrix::static_type_id () || \
+	      args(0).type_id () == octave_uint64_scalar::static_type_id ()) \
+	    { \
+	      uint64NDArray x = args(0).uint64_array_value ();	\
+	      uint64NDArray y = args(1).uint64_array_value ();	\
+	      if (! error_state)				\
+		BITOPX (OP, FNAME, uint64NDArray);		\
+	    } \
+	  else if (args(0).type_id () == octave_uint32_matrix::static_type_id () || \
+	      args(0).type_id () == octave_uint32_scalar::static_type_id ()) \
+	    { \
+	      uint32NDArray x = args(0).uint32_array_value ();	\
+	      uint32NDArray y = args(1).uint32_array_value ();	\
+	      if (! error_state)				\
+		BITOPX (OP, FNAME, uint32NDArray);		\
+	    } \
+	  else if (args(0).type_id () == octave_uint16_matrix::static_type_id () || \
+	      args(0).type_id () == octave_uint16_scalar::static_type_id ()) \
+	    { \
+	      uint16NDArray x = args(0).uint16_array_value ();	\
+	      uint16NDArray y = args(1).uint16_array_value ();	\
+	      if (! error_state)				\
+		BITOPX (OP, FNAME, uint16NDArray);		\
+	    } \
+	  else if (args(0).type_id () == octave_uint8_matrix::static_type_id () || \
+	      args(0).type_id () == octave_uint8_scalar::static_type_id ()) \
+	    { \
+	      uint8NDArray x = args(0).uint8_array_value ();	\
+	      uint8NDArray y = args(1).uint8_array_value ();	\
+	      if (! error_state)				\
+		BITOPX (OP, FNAME, uint8NDArray);		\
+	    } \
+	  else if (args(0).type_id () == octave_int64_matrix::static_type_id () || \
+	      args(0).type_id () == octave_int64_scalar::static_type_id ()) \
+	    { \
+	      int64NDArray x = args(0).int64_array_value ();	\
+	      int64NDArray y = args(1).int64_array_value ();	\
+	      if (! error_state)				\
+		BITOPX (OP, FNAME, int64NDArray);		\
+	    } \
+	  else if (args(0).type_id () == octave_int32_matrix::static_type_id () || \
+	      args(0).type_id () == octave_int32_scalar::static_type_id ()) \
+	    { \
+	      int32NDArray x = args(0).int32_array_value ();	\
+	      int32NDArray y = args(1).int32_array_value ();	\
+	      if (! error_state)				\
+		BITOPX (OP, FNAME, int32NDArray);		\
+	    } \
+	  else if (args(0).type_id () == octave_int16_matrix::static_type_id () || \
+	      args(0).type_id () == octave_int16_scalar::static_type_id ()) \
+	    { \
+	      int16NDArray x = args(0).int16_array_value ();	\
+	      int16NDArray y = args(1).int16_array_value ();	\
+	      if (! error_state)				\
+		BITOPX (OP, FNAME, int16NDArray);		\
+	    } \
+	  else if (args(0).type_id () == octave_int8_matrix::static_type_id () || \
+	      args(0).type_id () == octave_int8_scalar::static_type_id ()) \
+	    { \
+	      int8NDArray x = args(0).int8_array_value ();	\
+	      int8NDArray y = args(1).int8_array_value ();	\
+	      if (! error_state)				\
+		BITOPX (OP, FNAME, int8NDArray);		\
+	    } \
+	  else \
+	    error ("%s: illegal operand type", FNAME); \
+	} \
       else \
-        error ("%s: expecting uint64 arguments", FNAME); \
+	error ("%s: must have matching operand types", FNAME); \
     } \
   else \
     print_usage (FNAME); \
@@ -121,73 +294,20 @@
   BITOP (^, "bitxor");
 }
 
-DEFUN (bitcmp, args, ,
-  "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} bitcmp (@var{a}, @var{k})\n\
-returns the @var{k}-bit complement of integers in @var{a}. If\n\
-@var{k} is omitted k = log2(bitmax) is assumed.\n\
-\n\
-@example\n\
-bitcmp (7, 4)\n\
-@result{} 8\n\
-dec2bin (11)\n\
-@result{} 1011\n\
-dec2bin (bitcmp (11))\n\
-@result{} 11111111111111111111111111110100\n\
-@end example\n\
-\n\
-@end deftypefn\n\
-@seealso{bitand, bitor, bitxor, bitset, bitget, bitcmp, bitshift, bitmax}")
+static EIGHT_BYTE_INT
+bitshift (const double& a, int n)
 {
-  octave_value retval;
-  error ("not implemented");
-  return retval;
+  if (n > 0)
+    return static_cast<EIGHT_BYTE_INT> (a) << n;
+  else if (n < 0)
+    return static_cast<EIGHT_BYTE_INT> (a) >> -n;
+  else
+    return static_cast<EIGHT_BYTE_INT> (a);
 }
 
-DEFUN (bitget, args, ,
-  "-*- texinfo -*-\n\
-@deftypefn {Function File} {} bitget (@var{a}, @var{n})\n\
-returns the status of bit(s) @var{n} of unsigned integers in @var{a}\n\
-the lowest significant bit is @var{n} = 1.\n\
-\n\
-@example\n\
-bitget (100,8:-1:1)\n\
-@result{} 0  1  1  0  0  1  0  0\n\
-@end example\n\
-@end deftypefn\n\
-@seealso{bitand, bitor, bitxor, bitset, bitcmp, bitshift, bitmax}")
-{
-  octave_value retval;
-  error ("not implemented");
-  return retval;
-}
-
-DEFUN (bitset, args, ,
-  "-*- texinfo -*-\n\
-@deftypefn {Function File} {} bitset (@var{a}, @var{n})\n\
-@deftypefnx {Function File} {} bitset (@var{a}, @var{n}, @var{v})\n\
-sets or resets bit(s) @var{n} of unsigned integers in @var{a}.\n\
-@var{v} = 0 resets and @var{v} = 1 sets the bits.\n\
-The lowest significant bit is: @var{n} = 1\n\
-\n\
-@example\n\
-dec2bin (bitset (10, 1))\n\
-@result{} 1011\n\
-@end example\n\
-\n\
-@end deftypefn\n\
-@seealso{bitand, bitor, bitxor, bitget, bitcmp, bitshift, bitmax}")
-{
-  octave_value retval;
-  error ("not implemented");
-  return retval;
-}
-
+// Note that the bitshift operators are undefined if shifted by more bits than
+// in the type. Therefore need to test for the size of the shift
 #define DO_BITSHIFT(T) \
-  do \
-    { \
-      T ## NDArray m = m_arg.T ## _array_value (); \
- \
       if (! error_state) \
 	{ \
           double d1, d2; \
@@ -216,9 +336,15 @@
 		  for (int i = 0; i < m_nel; i++) \
 		    if (is_scalar_op) \
 		      for (int k = 0; k < n_nel; k++) \
-			result(i+k) = bitshift (m(i), static_cast<int> (n(k))); \
+			if (static_cast<int> (n(k)) >= bits_in_type) \
+			  result(i+k) = 0; \
+			else \
+			  result(i+k) = bitshift (m(i), static_cast<int> (n(k))) & mask; \
 		    else \
-		      result(i) = bitshift (m(i), static_cast<int> (n(i))); \
+		      if (static_cast<int> (n(i)) >= bits_in_type) \
+			result(i) = 0;					\
+		      else 						\
+			result(i) = bitshift (m(i), static_cast<int> (n(i))) & mask; \
  \
 		  retval = result; \
 		} \
@@ -227,8 +353,34 @@
 	    } \
           else \
             error ("bitshift: expecting second argument to be integer"); \
-        } \
-    } \
+        }
+
+#define DO_UBITSHIFT(T, N)					\
+  do								\
+    {								\
+      int bits_in_type = sizeof (octave_ ## T) << 3;		\
+      T ## NDArray m = m_arg.T ## _array_value ();		\
+	octave_ ## T mask = ~0ULL;				\
+      if ((N) < static_cast<int>(sizeof (octave_ ## T) << 3))	\
+	mask = mask >> ((sizeof (octave_ ## T) << 3) - (N));	\
+      else if ((N) < 1)						\
+	mask = 0;						\
+      DO_BITSHIFT (T);						\
+    }								\
+  while (0)
+
+#define DO_SBITSHIFT(T, N)					\
+  do								\
+    {								\
+      int bits_in_type = sizeof (octave_ ## T) << 3;		\
+      T ## NDArray m = m_arg.T ## _array_value ();		\
+	octave_ ## T mask = -1;					\
+      if ((N) < static_cast<int>(sizeof (octave_ ## T) << 3))	\
+	mask = mask >> ((sizeof (octave_ ## T) << 3) - (N));	\
+      else if ((N) < 1)						\
+	mask = 0;						\
+      DO_BITSHIFT (T);						\
+    }								\
   while (0)
 
 DEFUN (bitshift, args, ,
@@ -237,9 +389,9 @@
 @deftypefnx {Function File} {} bitshift (@var{a}, @var{k}, @var{n})\n\
 return a @var{k} bit shift of @var{n}- digit unsigned\n\
 integers in @var{a}. A positive @var{k} leads to a left shift.\n\
-A negative value to a right shift. If @var{N} is omitted it defaults\n\
+A negative value to a right shift. If @var{n} is omitted it defaults\n\
 to log2(bitmax)+1. \n\
-@var{N} must be in range [1,log2(bitmax)+1] usually [1,33]\n\
+@var{n} must be in range [1,log2(bitmax)+1] usually [1,33]\n\
 \n\
 @example\n\
 bitshift (eye (3), 1))\n\
@@ -263,22 +415,53 @@
 
   int nargin = args.length ();
 
-  if (nargin == 2)
+  if (nargin == 2 || nargin == 3)
     {
       NDArray n = args(1).array_value ();
+      int nbits = 64;
+      
+      if (nargin == 3)
+	{
+	  nbits = args(2).nint_value ();
+	  
+	  if (nbits < 0)
+	    error ("bitshift: number of bits to mask must be positive");
+	}
+
+      if (error_state)
+	return retval;
 
       octave_value m_arg = args(0);
-
       std::string cname = m_arg.class_name ();
 
       if (cname == "uint8")
-	DO_BITSHIFT (uint8);
+	DO_UBITSHIFT (uint8, nbits < 8 ? nbits : 8);
       else if (cname == "uint16")
-	DO_BITSHIFT (uint16);
+	DO_UBITSHIFT (uint16, nbits < 16 ? nbits : 16);
       else if (cname == "uint32")
-	DO_BITSHIFT (uint32);
+	DO_UBITSHIFT (uint32, nbits < 32 ? nbits : 32);
       else if (cname == "uint64")
-	DO_BITSHIFT (uint64);
+	DO_UBITSHIFT (uint64, nbits < 64 ? nbits : 64);
+      else if (cname == "int8")
+	DO_SBITSHIFT (int8, nbits < 8 ? nbits : 8);
+      else if (cname == "int16")
+	DO_SBITSHIFT (int16, nbits < 16 ? nbits : 16);
+      else if (cname == "int32")
+	DO_SBITSHIFT (int32, nbits < 32 ? nbits : 32);
+      else if (cname == "int64")
+	DO_SBITSHIFT (int64, nbits < 64 ? nbits : 64);
+      else if (cname == "double")
+	{
+	  nbits = (nbits < 53 ? nbits : 53);
+	  EIGHT_BYTE_INT mask = 0x1FFFFFFFFFFFFFLL;
+	  if (nbits < 53)
+	    mask = mask >> (53 - nbits);
+	  else if (nbits < 1)
+	    mask = 0;
+	  int bits_in_type = 64;
+	  NDArray m = m_arg.array_value ();
+	  DO_BITSHIFT ( );
+	}
       else
 	error ("bitshift: not defined for %s objects", cname.c_str ());
     }
@@ -290,11 +473,94 @@
 
 DEFUN (bitmax, args, ,
   "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} bitmax (@var{x}, @var{y})\n\
+@deftypefn {Built-in Function} {} bitmax ()\n\
+Returns the largest integer that can be represented as a floating point\n\
+value. That is for IEEE-754 compatiable systems with @code{2^53 - 1}.\n\
+@end deftypefn")
+{
+  octave_value retval;
+  if (args.length() != 0)
+    print_usage ("bitmax");
+  else
+    retval = ((double)0x1FFFFFFFFFFFFFLL);
+  return retval;
+}
+
+DEFUN (intmax, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} intmax (@var{type})\n\
 @end deftypefn")
 {
   octave_value retval;
-  error ("not implemented");
+  std::string cname = "int32";
+  int nargin = args.length ();
+
+  if (nargin == 1 && args(0).is_string())
+    cname = args(0).string_value ();
+  else if (nargin != 0)
+    {
+      print_usage ("intmax");
+      return retval;
+    }
+
+  if (cname == "uint8")
+    retval = octave_uint8 (std::numeric_limits<octave_uint8_t>::max());
+  else if (cname == "uint16")
+    retval = octave_uint16 (std::numeric_limits<octave_uint16_t>::max());
+  else if (cname == "uint32")
+    retval = octave_uint32 (std::numeric_limits<octave_uint32_t>::max());
+  else if (cname == "uint64")
+    retval = octave_uint64 (std::numeric_limits<octave_uint64_t>::max());
+  else if (cname == "int8")
+    retval = octave_int8 (std::numeric_limits<octave_int8_t>::max());
+  else if (cname == "int16")
+    retval = octave_int16 (std::numeric_limits<octave_int16_t>::max());
+  else if (cname == "int32")
+    retval = octave_int32 (std::numeric_limits<octave_int32_t>::max());
+  else if (cname == "int64")
+    retval = octave_int64 (std::numeric_limits<octave_int64_t>::max());
+  else
+    error ("intmax: not defined for '%s' objects", cname.c_str ());
+
+  return retval;
+}
+
+DEFUN (intmin, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Built-in Function} {} intmin (@var{type})\n\
+@end deftypefn")
+{
+  octave_value retval;
+  std::string cname = "int32";
+  int nargin = args.length ();
+
+  if (nargin == 1 && args(0).is_string())
+    cname = args(0).string_value ();
+  else if (nargin != 0)
+    {
+      print_usage ("intmin");
+      return retval;
+    }
+
+  if (cname == "uint8")
+    retval = octave_uint8 (std::numeric_limits<octave_uint8_t>::min());
+  else if (cname == "uint16")
+    retval = octave_uint16 (std::numeric_limits<octave_uint16_t>::min());
+  else if (cname == "uint32")
+    retval = octave_uint32 (std::numeric_limits<octave_uint32_t>::min());
+  else if (cname == "uint64")
+    retval = octave_uint64 (std::numeric_limits<octave_uint64_t>::min());
+  else if (cname == "int8")
+    retval = octave_int8 (std::numeric_limits<octave_int8_t>::min());
+  else if (cname == "int16")
+    retval = octave_int16 (std::numeric_limits<octave_int16_t>::min());
+  else if (cname == "int32")
+    retval = octave_int32 (std::numeric_limits<octave_int32_t>::min());
+  else if (cname == "int64")
+    retval = octave_int64 (std::numeric_limits<octave_int64_t>::min());
+  else
+    error ("intmin: not defined for '%s' objects", cname.c_str ());
+
   return retval;
 }
 
--- a/src/data.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/data.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -42,6 +42,7 @@
 #include "utils.h"
 #include "Cell.h"
 #include "oct-map.h"
+#include "pt-mat.h"
 
 #define ANY_ALL(FCN) \
  \
@@ -667,91 +668,6 @@
   DATA_REDUCTION (prod);
 }
 
-static bool
-cat_add_dims (dim_vector& dv_new, const dim_vector& dv_arg, int dim)
-{
-  // dv_arg is []
-
-  if (dv_arg.all_zero ())
-    return true;
-  
-  // dv_new is []
-
-  if (dv_new.all_zero ())
-    {
-      dv_new = dv_arg;
-      return true;
-    }
-  
-  int n_new  = dv_new.length ();
-  int n_args = dv_arg.length ();
-  
-  // Find the max and min value of n_new and n_args
-
-  int n_max = n_new > n_args ? n_new : n_args;
-  int n_min = n_new < n_args ? n_new : n_args;  
-
-  // The elements of the dimension vectors can only differ
-  // if the dim variable differs from the actual dimension
-  // they differ.
-
-  for (int i = 0; i < n_min; i++)
-    {
-      if (dv_new(i) != dv_arg(i) && dim != i)
-	{
-	  error ("cat: dimension mismatch");
-	  return false;
-	}
-    }
-  
-  // Ditto.
-
-  for (int i = n_min; i < n_max; i++)
-    {
-      if (n_new > n_min)
-	{
-	  if (dv_new(i) != 1 && dim != i)
-	    {
-	      error ("cat: dimension mismatch");
-	      return false;
-	    }
-	}
-      else 
-	{
-	  if (dv_arg(i) != 1 && dim != i)
-	    {
-	      error ("cat: dimension mismatch");
-	      return false;
-	    }
-	}
-    }
-
-  // If we want to add the dimension vectors at a dimension
-  // larger than both, then we need to set n_max to this number
-  // so that we resize dv_new to the right dimension.
-
-  n_max = n_max > (dim + 1) ? n_max : (dim + 1);
-  
-  // Resize dv_new to new the appropriate dimensions.
-
-  if (n_max > n_new)
-    {
-      dv_new.resize (n_max);
-
-      for (int i = n_new; i < n_max; i++)
-	dv_new.elem (i) = 1;
-    }
-  
-  // Larger or equal since dim has been decremented by one.
-
-  if (dim >= n_args)
-    dv_new.elem (dim) = dv_new.elem (dim)++;
-  else
-    dv_new.elem (dim) += dv_arg(dim);
-
-  return true;
-}
-
 static octave_value
 do_cat (const octave_value_list& args, std::string fname)
 {
@@ -771,183 +687,67 @@
   
       if (dim >= 0)
 	{
+ 	  
+ 	  dim_vector  dv = args(1).dims ();
 	  
-	  dim_vector  dv = args(1).dims ();
-  
-	  for (int i = 2; i < args.length (); i++)
-	    {
-	      // add_dims constructs a dimension vector which holds the
+ 	  for (int i = 2; i < args.length (); i++)
+  	    {
+ 	      // add_dims constructs a dimension vector which holds the
 	      // dimensions of the final array after concatenation.
 
-	      if (! cat_add_dims (dv, args(i).dims (), dim))
+	      if (! dv.concat (args(i).dims (), dim))
 		{
 		  // Dimensions do not match. 
-		  // cat_add_dims printed a error msg
+		  error ("cat: dimension mismatch");
 		  return retval;
 		}
 	    }
 
-	  NDArray cat_re;
-	  ComplexNDArray cat_cx;
-	  charNDArray cat_ch;
-	  Cell cat_cell;
-	  Octave_map cat_map;
-
-	  // The final array can be of three types:
+	  // The lines below might seem crazy, since we take a copy
+	  // of the first argument, resize it to be empty and then resize
+	  // it to be full. This is done since it means that there is no
+	  // recopying of data, as would happen if we used a single resize.
+	  // It should be noted that resize operation is also significantly 
+	  // slower than the do_cat_op function, so it makes sense to have an
+	  // empty matrix and copy all data.
 	  //
-	  //       re cx ch c
-	  // ----------------
-	  // re   |re cx ch X
-	  // cx   |cx cx X  X
-	  // ch   |ch X  ch X
-	  // cell |X  X  X  c
-	  // (X means incompatible).
-
-	  enum types { REAL, COMPLEX, CHAR, CELL, MAP} t;      
-
-	  // Initialize t to right value
-	  if (args(1).is_cell ())
-	    {
-	      t = CELL;
-	      cat_cell = Cell (dv);
-	    }
-	  else if (args(1).is_map ())
-	    {
-	      error ("concatenation of structures is not yet implemented");
-	      return retval;
-	      // t = MAP;
-	      // cat_map = Octave_map (dv);
-	    }
-	  else 
-	    {
-	      t = REAL;
-	      cat_re = NDArray (dv, 0);
-	    }
- 
-	  int idx = 0;
-  
-	  dim_vector dv_first = args(1).dims ();
-      
-	  // n_moves tells us how many times we need to
-	  // visit each argument.
-	  //
-	  // If we are concatenating a 2x2x2 array with a 2x2x2 array
-	  // along the second dimensions, we do two iterations
-	  // trough the arguments and move 2x2 elements from each
-	  // of the arguments into the resulting array on each iteration.
-	  int n_moves = 1;
-
-	  for (int i = dim + 1; i < dv_first.length (); i++)
-	    n_moves *= dv_first(i);
-      
-	  for (int move = 0; move < n_moves ; move++)
-	    {     
-	      for (int i = 1; i < n_args; i++)
-		{
-		  octave_value tmp = args (i);
-
-		  if (t == MAP)
-		    {
-		      error ("concatenation of structures is not yet implemented");
-		      return retval;
-		    }
-		  else if (t == CELL)
-		    {
-		      if (! tmp.is_cell ())
-			{
-			  error ("cannot convert argument to cell");
-			  return retval;
-			}
-		      else
-			{
-			  Cell ra_tmp = args(i).cell_value ();
+	  // We might also start with a empty octave_value using
+	  //   tmp = octave_value_typeinfo::lookup_type (args(1).type_name());
+	  // and then directly resize. However, for some types there might be
+	  // some additional setup needed, and so this should be avoided.
+	  octave_value tmp;
+          bool any_strings = false;
+          bool all_strings = true;
+          for (int i = 1; i < n_args; i++)
+	    if (args(i).is_string ())
+	      any_strings = true;
+	    else
+	      all_strings = false;
 	  
-			  if (error_state)
-			    return retval;
+	  if (all_strings)
+	    tmp = octave_value (charNDArray (dv, Vstring_fill_char), true);
+	  else
+	    tmp = args(1).resize (dim_vector (0,0)).resize (dv);
 
-			  idx = cat_cell.cat (ra_tmp, dim, idx, move);
-			}
-		    }
-		  else if (t == REAL)
-		    {
-		      if (tmp.is_complex_type ())
-			{
-			  cat_cx = ComplexNDArray (cat_re);		  
-		  
-			  ComplexNDArray ra_tmp = tmp.complex_array_value ();
-	  
-			  if (error_state)
-			    return retval;
+	  if (error_state)
+	    return retval;
 
-			  idx = cat_cx.cat (ra_tmp, dim, idx, move);
-
-			  t = COMPLEX;
-			}
-		      else if (tmp.is_string ())
-			{
-			  // This is a hack to be able to convert a dNDArray
-			  // to a chNDArray.
-
-			  cat_ch = charNDArray (octave_value (cat_re).char_array_value ());	  
-		  
-			  charNDArray ra_tmp = tmp.char_array_value ();
-	  
-			  if (error_state)
-			    return retval;
+	  Array<int> ra_idx (dv.length (), 0);
+	  for (int i = 1; i < n_args; i++)
+	    {
+	      tmp = do_cat_op (tmp, args (i), ra_idx);
 
-			  idx = cat_ch.cat (ra_tmp, dim, idx, move);
-	
-			  t = CHAR;
-			}
-		      else //if (tmp.is_real_type ())
-			{ 
-			  NDArray ra_tmp = tmp.array_value ();
-	
-			  if (error_state)
-			    return retval;
-		
-			  idx = cat_re.cat (ra_tmp, dim, idx, move);
-			}  
-		    }
-		  else if (t == COMPLEX)
-		    {
-		      ComplexNDArray ra_tmp = tmp.complex_array_value ();
-	  
-		      if (error_state)
-			return retval;
+	      if (error_state)
+		return retval;
 
-		      idx = cat_cx.cat (ra_tmp, dim, idx, move);
-		    }
-		  else if (t == CHAR)
-		    {
-		      if (tmp.is_complex_type ())
-			{
-			  error ("cannot convert complex type to character type");
-			  return retval;
-			}
-		      else
-			{
-			  charNDArray ra_tmp = tmp.char_array_value ();
-	  
-			  if (error_state)
-			    return retval;
+	      dim_vector dv_tmp = args (i).dims ();
+	      ra_idx (dim) += (dim < dv_tmp.length () ? dv_tmp (dim) : 1);
+	    }
 
-			  cat_ch.cat (ra_tmp, dim, idx, move);
-			}
-		    }
-		}
-	    }
-      
-	  if (t == REAL)
-	    retval = octave_value (cat_re);
-	  else if (t == COMPLEX)
-	    retval = octave_value (cat_cx);
-	  else if (t == CHAR)
-	    retval = octave_value (cat_ch);
-	  else if (t == CELL)
-	    retval = octave_value (cat_cell);
-	  else if (t == MAP)
-	    retval = octave_value (cat_map);
+          if (any_strings && !all_strings)
+            retval = tmp.convert_to_str ();
+          else
+	    retval = tmp;
 	}
       else print_usage (fname);
     }
--- a/src/oct-map.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/oct-map.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -88,11 +88,14 @@
   return retval;
 }
 
-int
-Octave_map::cat (const Octave_map& ra_arg, int dim, int iidx, int move)
+Octave_map
+concat (const Octave_map& ra, const Octave_map& rb, const Array<int>& ra_idx)
 {
-  //return ::cat_ra (*this, ra_arg, dim, iidx, move);
-  return 0;
+  // XXX FIXME XXX
+  Octave_map retval;
+  //Octave_map retval (ra);
+  //::concat_ra (retval, rb, dim) 
+  return retval;
 }
 
 static string_vector
--- a/src/oct-map.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/oct-map.h	Fri Jul 23 19:01:23 2004 +0000
@@ -118,7 +118,8 @@
 
   int numel (void) const;
 
-  int cat (const Octave_map& ra_arg, int dim, int iidx, int move);
+  friend Octave_map concat (const Octave_map& ra, const Octave_map& rb, 
+			    const Array<int>& ra_idx);
 
   Octave_map& assign (const octave_value_list& idx, const Octave_map& rhs);
 
--- a/src/ops.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/ops.h	Fri Jul 23 19:01:23 2004 +0000
@@ -40,6 +40,10 @@
     (octave_value::op, t1::static_type_id (), t2::static_type_id (), \
      oct_binop_ ## f);
 
+#define INSTALL_CATOP(t1, t2, f) \
+  octave_value_typeinfo::register_cat_op \
+    (t1::static_type_id (), t2::static_type_id (), oct_catop_ ## f);
+
 #define INSTALL_ASSIGNOP(op, t1, t2, f) \
   octave_value_typeinfo::register_assign_op \
     (octave_value::op, t1::static_type_id (), t2::static_type_id (), \
@@ -306,6 +310,39 @@
 		       a2.rows (), a2.columns ()); \
   return octave_value ()
 
+#define CATOPDECL(name, a1, a2)	\
+  static octave_value \
+  oct_catop_ ## name (const octave_value& a1, const octave_value& a2, \
+		      const Array<int>& ra_idx)
+
+#define DEFCATOPX(name, t1, t2)	\
+  CATOPDECL (name, , )
+
+#define DEFCATOP(name, t1, t2)	\
+  CATOPDECL (name, a1, a2)
+
+// XXX FIXME XXX -- in some cases, the constructor isn't necessary.
+
+#define DEFCATOP_FN(name, t1, t2, f) \
+  CATOPDECL (name, a1, a2)	     \
+  { \
+    CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \
+    return octave_value (f (v1.t1 ## _value (), v2.t2 ## _value (), ra_idx));	\
+  }
+
+#define DEFNDCATOP_FN(name, t1, t2, e1, e2, f)	\
+  CATOPDECL (name, a1, a2)			\
+  { \
+    CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \
+    return octave_value (f (v1.e1 ## _value (), v2.e2 ## _value (), ra_idx));	\
+  }
+
+#define CATOP_NONCONFORMANT(msg) \
+  gripe_nonconformant (msg, \
+		       a1.rows (), a1.columns (), \
+		       a2.rows (), a2.columns ()); \
+  return octave_value ()
+
 #endif
 
 /*
--- a/src/ov-base-mat.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/ov-base-mat.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -211,14 +211,14 @@
   bool retval = false;
   dim_vector dv = matrix.dims ();
   int nel = dv.numel ();
-  
+
   if (nel > 0)
     {
       MT t1 (matrix.reshape (dim_vector (nel, 1)));
 
       boolNDArray t2 = t1.all ();
 
-      retval = t2(0,0);
+      retval = t2(0);
     }
 
   return retval;
--- a/src/ov-base-mat.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/ov-base-mat.h	Fri Jul 23 19:01:23 2004 +0000
@@ -103,6 +103,9 @@
   octave_value permute (const Array<int>& vec, bool inv = false) const
     { return MT (matrix.permute (vec, inv)); }
 
+  octave_value resize (const dim_vector& dv) const
+    { MT retval (matrix); retval.resize (dv); return retval; }
+
   octave_value all (int dim = 0) const { return matrix.all (dim); }
   octave_value any (int dim = 0) const { return matrix.any (dim); }
 
--- a/src/ov-base.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/ov-base.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -191,6 +191,13 @@
 }
 
 octave_value
+octave_base_value::resize (const dim_vector& dv) const
+{
+  gripe_wrong_type_arg ("octave_base_value::resize ()", type_name ());
+  return octave_value ();
+}
+
+octave_value
 octave_base_value::convert_to_str_internal (bool, bool) const
 {
   gripe_wrong_type_arg ("octave_base_value::convert_to_str_internal ()",
--- a/src/ov-base.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/ov-base.h	Fri Jul 23 19:01:23 2004 +0000
@@ -102,6 +102,8 @@
 
   octave_value permute (const Array<int>& vec, bool = false) const;
 
+  octave_value resize (const dim_vector& dv) const;
+
   bool is_defined (void) const { return false; }
 
   bool is_cell (void) const { return false; }
--- a/src/ov-bool.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/ov-bool.h	Fri Jul 23 19:01:23 2004 +0000
@@ -111,6 +111,9 @@
   boolNDArray bool_array_value (void) const
     { return boolNDArray (dim_vector (1, 1), scalar); }
 
+  octave_value resize (const dim_vector& dv) const
+    { boolNDArray retval (dv); if (dv.numel()) retval(0) = scalar; return retval; }
+
   octave_value convert_to_str_internal (bool pad, bool force) const;
 
   bool save_ascii (std::ostream& os, bool& infnan_warned,
--- a/src/ov-complex.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/ov-complex.h	Fri Jul 23 19:01:23 2004 +0000
@@ -95,6 +95,9 @@
 
   NDArray array_value (bool = false) const;
 
+  octave_value resize (const dim_vector& dv) const
+    { ComplexNDArray retval (dv); if (dv.numel()) retval(0) = scalar; return retval; }
+
   Complex complex_value (bool = false) const;
 
   ComplexMatrix complex_matrix_value (bool = false) const;
--- a/src/ov-intx.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/ov-intx.h	Fri Jul 23 19:01:23 2004 +0000
@@ -61,6 +61,16 @@
   OCTAVE_VALUE_INT_NDARRAY_EXTRACTOR_FUNCTION (void) const
     { return matrix; }
 
+  NDArray
+  array_value (bool = false) const
+    { 
+      NDArray retval (matrix.dims ()); 
+      int nel = matrix.numel ();
+      for (int i = 0; i < nel; i++)
+        retval (i) = double (matrix(i));
+      return retval;
+    }
+
 private:
 
   DECLARE_OCTAVE_ALLOCATOR
@@ -98,6 +108,17 @@
   OCTAVE_VALUE_INT_NDARRAY_EXTRACTOR_FUNCTION (void) const
     { return OCTAVE_INT_NDARRAY_T (dim_vector (1, 1), scalar); }
 
+  octave_value resize (const dim_vector& dv) const
+    { OCTAVE_INT_NDARRAY_T retval (dv); if (dv.numel()) retval(0) = scalar; return retval; }
+
+  NDArray
+  array_value (bool = false) const
+    { 
+      NDArray retval (dim_vector (1,1)); 
+      retval (0) = double (scalar);
+      return retval;
+    }
+
 private:
 
   DECLARE_OCTAVE_ALLOCATOR
--- a/src/ov-range.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/ov-range.h	Fri Jul 23 19:01:23 2004 +0000
@@ -108,6 +108,9 @@
       return dim_vector (n > 0, n);
     }
 
+  octave_value resize (const dim_vector& dv) const
+    { NDArray retval = array_value (); retval.resize (dv); return retval; }
+
   size_t byte_size (void) const { return 3 * sizeof (double); }
 
   octave_value reshape (const dim_vector& new_dims) const
--- a/src/ov-scalar.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/ov-scalar.h	Fri Jul 23 19:01:23 2004 +0000
@@ -97,6 +97,9 @@
   NDArray array_value (bool = false) const
     { return NDArray (dim_vector (1, 1), scalar); }
 
+  octave_value resize (const dim_vector& dv) const
+    { NDArray retval (dv); if (dv.numel()) retval(0) = scalar; return retval; }
+
   Complex complex_value (bool = false) const { return scalar; }
 
   ComplexMatrix complex_matrix_value (bool = false) const
--- a/src/ov-typeinfo.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/ov-typeinfo.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -56,6 +56,9 @@
 template class Array2<binary_op_fcn>;
 template class Array3<binary_op_fcn>;
 
+INSTANTIATE_ARRAY (cat_op_fcn);
+template class Array2<cat_op_fcn>;
+
 INSTANTIATE_ARRAY (assign_op_fcn);
 template class Array2<assign_op_fcn>;
 template class Array3<assign_op_fcn>;
@@ -116,6 +119,13 @@
 }
 
 bool
+octave_value_typeinfo::register_cat_op (int t1, int t2, cat_op_fcn f)
+{
+  return (instance_ok ())
+    ? instance->do_register_cat_op (t1, t2, f) : false;
+}
+
+bool
 octave_value_typeinfo::register_assign_op (octave_value::assign_op op,
 					   int t_lhs, int t_rhs,
 					   assign_op_fcn f)
@@ -190,6 +200,8 @@
       binary_ops.resize (static_cast<int> (octave_value::num_binary_ops),
 			 len, len, static_cast<binary_op_fcn> (0));
 
+      cat_ops.resize (len, len, static_cast<cat_op_fcn> (0));
+
       assign_ops.resize (static_cast<int> (octave_value::num_assign_ops),
 			 len, len, static_cast<assign_op_fcn> (0));
 
@@ -269,6 +281,23 @@
 }
 
 bool
+octave_value_typeinfo::do_register_cat_op (int t1, int t2, cat_op_fcn f)
+{
+  if (lookup_cat_op (t1, t2))
+    {
+      std::string t1_name = types(t1);
+      std::string t2_name = types(t2);
+
+      warning ("duplicate concatenation operator for types `%s' and `%s'",
+	       t1_name.c_str (), t1_name.c_str ());
+    }
+
+  cat_ops.checkelem (t1, t2) = f;
+
+  return false;
+}
+
+bool
 octave_value_typeinfo::do_register_assign_op (octave_value::assign_op op,
 					      int t_lhs, int t_rhs,
 					      assign_op_fcn f)
@@ -398,6 +427,12 @@
   return binary_ops.checkelem (static_cast<int> (op), t1, t2);
 }
 
+cat_op_fcn
+octave_value_typeinfo::do_lookup_cat_op (int t1, int t2)
+{
+  return cat_ops.checkelem (t1, t2);
+}
+
 assign_op_fcn
 octave_value_typeinfo::do_lookup_assign_op (octave_value::assign_op op,
 					    int t_lhs, int t_rhs)
--- a/src/ov-typeinfo.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/ov-typeinfo.h	Fri Jul 23 19:01:23 2004 +0000
@@ -55,6 +55,8 @@
   static bool register_binary_op (octave_value::binary_op, int, int,
 				  binary_op_fcn);
 
+  static bool register_cat_op (int, int, cat_op_fcn);
+
   static bool register_assign_op (octave_value::assign_op, int, int,
 				  assign_op_fcn);
 
@@ -91,6 +93,12 @@
     return instance->do_lookup_binary_op (op, t1, t2);
   }
 
+  static cat_op_fcn
+  lookup_cat_op (int t1, int t2)
+  {
+    return instance->do_lookup_cat_op (t1, t2);
+  }
+
   static assign_op_fcn
   lookup_assign_op (octave_value::assign_op op, int t_lhs, int t_rhs)
   {
@@ -137,6 +145,7 @@
 			   (non_const_unary_op_fcn) 0),
       binary_ops (octave_value::num_binary_ops, init_tab_sz,
 		  init_tab_sz, (binary_op_fcn) 0),
+      cat_ops (init_tab_sz, init_tab_sz, (cat_op_fcn) 0),
       assign_ops (octave_value::num_assign_ops, init_tab_sz,
 		  init_tab_sz, (assign_op_fcn) 0),
       assignany_ops (octave_value::num_assign_ops, init_tab_sz,
@@ -163,6 +172,8 @@
 
   Array3<binary_op_fcn> binary_ops;
 
+  Array2<cat_op_fcn> cat_ops;
+
   Array3<assign_op_fcn> assign_ops;
 
   Array2<assign_op_fcn> assignany_ops;
@@ -184,6 +195,8 @@
   bool do_register_binary_op (octave_value::binary_op, int, int,
 			      binary_op_fcn);
 
+  bool do_register_cat_op (int, int, cat_op_fcn);
+
   bool do_register_assign_op (octave_value::assign_op, int, int,
 			      assign_op_fcn);
 
@@ -205,6 +218,8 @@
 
   binary_op_fcn do_lookup_binary_op (octave_value::binary_op, int, int);
 
+  cat_op_fcn do_lookup_cat_op (int, int);
+
   assign_op_fcn do_lookup_assign_op (octave_value::assign_op, int, int);
 
   assign_op_fcn do_lookup_assignany_op (octave_value::assign_op, int);
--- a/src/ov.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/ov.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -1662,6 +1662,92 @@
   return retval;
 }
 
+static void
+gripe_cat_op (const std::string& tn1, const std::string& tn2)
+{
+  error ("concatenation operator not implemented for `%s' by `%s' operations",
+	 tn1.c_str (), tn2.c_str ());
+}
+
+static void
+gripe_cat_op_conv (void)
+{
+  error ("type conversion failed for concatenation operator");
+}
+
+octave_value
+do_cat_op (const octave_value& v1, const octave_value& v2, 
+	   const Array<int>& ra_idx)
+{
+  octave_value retval;
+
+  int t1 = v1.type_id ();
+  int t2 = v2.type_id ();
+
+  cat_op_fcn f = octave_value_typeinfo::lookup_cat_op (t1, t2);
+
+  if (f)
+    retval = f (*v1.rep, *v2.rep, ra_idx);
+  else
+    {
+      octave_value tv1;
+      type_conv_fcn cf1 = v1.numeric_conversion_function ();
+
+      if (cf1)
+	{
+	  octave_value *tmp = cf1 (*v1.rep);
+
+	  if (tmp)
+	    {
+	      tv1 = octave_value (tmp);
+	      t1 = tv1.type_id ();
+	    }
+	  else
+	    {
+	      gripe_cat_op_conv ();
+	      return retval;
+	    }
+	}
+      else
+	tv1 = v1;
+
+      octave_value tv2;
+      type_conv_fcn cf2 = v2.numeric_conversion_function ();
+
+      if (cf2)
+	{
+	  octave_value *tmp = cf2 (*v2.rep);
+
+	  if (tmp)
+	    {
+	      tv2 = octave_value (tmp);
+	      t2 = tv2.type_id ();
+	    }
+	  else
+	    {
+	      gripe_cat_op_conv ();
+	      return retval;
+	    }
+	}
+      else
+	tv2 = v2;
+
+      if (cf1 || cf2)
+	{
+	  f = octave_value_typeinfo::lookup_cat_op (t1, t2);
+
+	  if (f)
+	    retval = f (*tv1.rep, *tv2.rep, ra_idx);
+	  else
+	    gripe_cat_op (v1.type_name (), v2.type_name ());
+	}
+      else
+	gripe_cat_op (v1.type_name (), v2.type_name ());
+    }
+
+  return retval;
+}
+
 void
 octave_value::print_info (std::ostream& os, const std::string& prefix) const
 {
--- a/src/ov.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/ov.h	Fri Jul 23 19:01:23 2004 +0000
@@ -84,6 +84,9 @@
 typedef octave_value (*binary_op_fcn)
   (const octave_value&, const octave_value&);
 
+typedef octave_value (*cat_op_fcn)
+  (const octave_value&, const octave_value&, const Array<int>& ra_idx);
+
 typedef octave_value (*assign_op_fcn)
   (octave_value&, const octave_value_list&, const octave_value&);
 
@@ -367,6 +370,9 @@
   octave_value ipermute (const Array<int>& vec) const
     { return rep->permute (vec, true); }
 
+  virtual octave_value resize (const dim_vector& dv) const
+     { return rep->resize (dv);}
+
   // Does this constant have a type?  Both of these are provided since
   // it is sometimes more natural to write is_undefined() instead of
   // ! is_defined().
@@ -711,6 +717,10 @@
 				    const octave_value& a,
 				    const octave_value& b);
 
+  friend octave_value do_cat_op (const octave_value& a,
+				 const octave_value& b,
+				 const Array<int>& ra_idx);
+
   const octave_value& get_rep (void) const { return *rep; }
 
   virtual void print_info (std::ostream& os,
--- a/src/pt-mat.cc	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/pt-mat.cc	Fri Jul 23 19:01:23 2004 +0000
@@ -215,12 +215,13 @@
 	}
       dv.elem (1) = dv.elem (1) + this_elt_nc;
 
-      append (val);
     }
   else if (Vwarn_empty_list_elements)
     eval_warning ("empty matrix found in matrix list",
 		  elt->line (), elt->column ());
 
+  append (val);
+
   if (all_str && ! val.is_string ())
     all_str = false;
 
@@ -491,10 +492,6 @@
   return true;
 }
 
-// Just about as ugly as it gets.
-// Less ugly than before, anyway.
-// Looking better all the time.
-
 octave_value_list
 tree_matrix::rvalue (int nargout)
 {
@@ -515,123 +512,84 @@
 {
   octave_value retval;
 
-  tm_const tmp (*this);
+  bool all_strings_p = false;
+  bool all_empty_p = false;
+  bool frc_str_conv = false;
 
-  bool all_strings_p = false;
-  bool some_strings_p = false;
-  bool all_empty_p = false;
-
-  bool frc_str_conv = false;
+  tm_const tmp (*this);
 
   if (tmp)
     {
       dim_vector dv = tmp.dims ();
+      all_strings_p = tmp.all_strings_p ();
+      all_empty_p = tmp.all_empty_p ();
+      frc_str_conv = tmp.some_strings_p ();
 
-      NDArray nd;
-      ComplexNDArray cnd;
-      charNDArray chnd;
+      // XXX FIXME XX
+      // The previous version of this code obtained the return type and 
+      // initialized an array of the correct type. However the return type
+      // is now built-up from the return types of do_cat_op. Should we special
+      // case the situation where there are only NDArray and ComplexNDArray
+      // elements, or things like boolMatrix that widen to them, and do the
+      // correct initialization? How to do this? Will it be faster? Check against
+      // version 2.1.57
+
+
+      // The line below might seem crazy, since we take a copy
+      // of the first argument, resize it to be empty and then resize
+      // it to be full. This is done since it means that there is no
+      // recopying of data, as would happen if we used a single resize.
+      // It should be noted that resize operation is also significantly 
+      // slower than the do_cat_op function, so it makes sense to have an
+      // empty matrix and copy all data.
+      //
+      // We might also start with a empty octave_value using
+      //    ctmp = octave_value_typeinfo::lookup_type
+      //          (tmp.begin() -> begin() -> type_name());
+      // and then directly resize. However, for some types there might be
+      // some additional setup needed, and so this should be avoided.
+
+      octave_value ctmp;
+      if (all_strings_p)
+	if (all_empty_p)
+	  ctmp = octave_value (charNDArray (), true);
+	else
+	  ctmp = octave_value (charNDArray (dv, Vstring_fill_char), true);
+      else
+	{
+	  if (all_empty_p)
+	    ctmp = (*(tmp.begin() -> begin()));
+	  else
+	    ctmp = (*(tmp.begin() -> begin())).resize (dim_vector (0,0)).resize (dv);
+	}
+
+      if (error_state)
+	goto done;
 
       // Now, extract the values from the individual elements and
       // insert them in the result matrix.
-
-      bool found_complex = tmp.complex_p ();
-
-      all_strings_p = tmp.all_strings_p ();
-      some_strings_p = tmp.some_strings_p ();
-      all_empty_p = tmp.all_empty_p ();
-
-      frc_str_conv = some_strings_p;
-
-      if (all_strings_p)
-	chnd.resize_and_fill (dv, Vstring_fill_char);
-      else if (found_complex)
-	cnd.resize_and_fill (dv, 0.0);
-      else
-	nd.resize_and_fill (dv, 0.0);
-
-      int put_row = 0;
-
+      Array<int> ra_idx (dv.length (), 0);
       for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++)
 	{
-	  int put_col = 0;
-
 	  tm_row_const row = *p;
-
 	  for (tm_row_const::iterator q = row.begin (); q != row.end (); q++)
 	    {
 	      octave_value elt = *q;
 
-	      if (found_complex)
-		{
-		  if (elt.is_real_scalar ())
-		    cnd (put_row, put_col) = elt.double_value ();
-		  else if (elt.is_real_matrix () || elt.is_range ())
-		    cnd.insert (elt.array_value (), put_row, put_col);
-		  else if (elt.is_complex_scalar ())
-		    cnd (put_row, put_col) = elt.complex_value ();
-		  else
-		    {
-		      ComplexNDArray cnd_elt = elt.complex_array_value ();
-
-		      if (error_state)
-			goto done;
-
-		      cnd.insert (cnd_elt, put_row, put_col);
-		    }
-		}
-	      else
-		{
-		  if (elt.is_real_scalar ())
-		    nd (put_row, put_col) = elt.double_value ();
-		  else if (elt.is_string () && all_strings_p)
-		    {
-		      charNDArray chnd_elt = elt.char_array_value ();
-
-		      if (error_state)
-			goto done;
-
-		      chnd.insert (chnd_elt, put_row, put_col);
-		    }
-		  else
-		    {
-		      NDArray nd_elt = elt.array_value (frc_str_conv);
-
-		      if (error_state)
-			goto done;
-
-		      nd.insert (nd_elt, put_row, put_col);
-		    }
-		}
-
-	      if (all_strings_p && chnd.rows () > 0 && chnd.cols () > 0)
-		retval = octave_value (chnd, true);
-	      else if (found_complex)
-		retval = cnd;
-	      else
-		retval = nd;
-
-	      put_col += elt.columns ();
+	      ctmp = do_cat_op (ctmp, elt, ra_idx);
+	      if (error_state)
+		goto done;
+	      ra_idx (1) += elt.columns ();
 	    }
-
-	  put_row += row.rows ();
+	  ra_idx (0) += row.rows ();
+	  ra_idx (1) = 0;
 	}
+      retval = ctmp;
+      if (frc_str_conv && ! retval.is_string ())
+	retval = retval.convert_to_str ();
     }
 
 done:
-
-  if (! error_state)
-    {
-      if (retval.is_undefined () && all_empty_p)
-	{
-	  if (all_strings_p)
-	    retval = "";
-	  else
-	    retval = NDArray ();
-	}
-      else if (frc_str_conv && ! retval.is_string ())
-	retval = retval.convert_to_str ();
-    }
-
   return retval;
 }
 
--- a/src/version.h	Fri Jul 23 16:55:13 2004 +0000
+++ b/src/version.h	Fri Jul 23 19:01:23 2004 +0000
@@ -25,7 +25,7 @@
 
 #define OCTAVE_VERSION "2.1.57"
 
-#define OCTAVE_API_VERSION "api-v8"
+#define OCTAVE_API_VERSION "api-v9"
 
 #define OCTAVE_COPYRIGHT \
   "Copyright (C) 2004 John W. Eaton."