octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Help with [] for defined types


From: David Bateman
Subject: Re: Help with [] for defined types
Date: Mon, 5 Jul 2004 16:50:08 +0200
User-agent: Mutt/1.4.1i

According to Andy Adler <address@hidden> (on 07/05/04):
> OK, I understand why it is so hard now.
> 
> For stuff like your galois field types, which inherit from NDMatrix,
> they don't need to add to the conversion table in data.cc. However,
> doing this with sparse would need to add a new row and column.
> I suppose it would be (after testing with Matlab)
> 
>         //       re   cx   ch c  spre spcx
>         // --------------------
>         // re   |re   cx   ch X  spre spcx
>         // cx   |cx   cx   X  X  spcx spcx
>         // ch   |ch   X    ch X   X    X
>         // cell |X    X    X  c   X    X
>              spre  spre spcx X  X   spre spcx
>              spcx  spcx spcx X  X   spcx spcx
>         // (X means incompatible).
> 
> This appears to be a significant pain right now. I think I've
> decided to leave it for the moment (after all, the functions
> sphcat and spvcat exist)

Andy,

Galois inherits from octave_base_value, but even if it did inherit
from octave_base_matrix, the way Fcat is written wouldn't be compatiable.
It is hard-coded for real and complex arrays, cell arrays and character
arrays.

In any case I'd suggest if there is no crossover to the Fcat function
between "spre and spcx" and "re and cx" as you suggest it would be
better to treat the compatiablity with Fcat by writing a function
spcat and overloading it using dispatch. You should probably do the
same to horzcat and vertcat at the same time. The only case that
might cause problems is if for instance you wanted to concatenate
sparse and full matrices like "cat(sparse(...), rand(...))"

In any case the function Fcat doesn't get you the "[]" operator which
is defined in tree_matrix::rvalue in pt-mat.cc, and there is no way to
overload. The correct solution would be to create a function lookup
like BINOP, but perhaps called CATOP, which takes a dim argument as
well as the two arbitrary args.  The basic changes are something like

ov.h ->
typedef octave_value (*cat_op_fcn)
  (const octave_value&, const octave_value&, int dim);

friend octave_value do_cat_op (const octave_value& a,
                               const octave_value& b, int dim = 0);

ov.cc ->
octave_value
do_cat_op (const octave_value& v1, const octave_value& v2, int dim)
{
  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, dim);
  else
    // Need widening ops, eg for dNDArray -> CNDArray
    gripe_cat_op (v1.type_name (), v2.type_name ());

  return retval;
}

ov-typeinfo.h ->
class
octave_value_typeinfo
{
  static bool register_cat_op (int, int, cat_op_fcn);

  static cat_op_fcn
  lookup_cat_op (int t1, int t2)
  {
    return instance->do_lookup_cat_op (t1, t2);
  }

      cat_ops (init_tab_sz, init_tab_sz, (cat_op_fcn) 0),

  Array3<cat_op_fcn> cat_ops;

  bool do_register_cat_op (int, int, cat_op_fcn);

  cat_op_fcn do_lookup_cat_op (int, int);

}

ov-typeinfo.cc ->
INSTANTIATE_ARRAY (cat_op_fcn);
template class Array2<cat_op_fcn>;
template class Array3<cat_op_fcn>;

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;
}

int
octave_value_typeinfo::do_register_type(..)
{
...

      cat_ops.resize (len, len, static_cast<cat_op_fcn> (0));
...
}

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 cat operator for types `%s' and `%s'",
               t1_name.c_str (), t1_name.c_str ());
    }

  cat_ops.checkelem (t1, t2) = f;

  return false;
}

cat_op_fcn
octave_value_typeinfo:do_lookup_cat_op (int t1, int t2)
{
  return cat_ops.checkelem (t1, t2);
}


ops.h ->
#define INSTALL_CATOP(t1, t2, f) \
  octave_value_typeinfo::register_cat_op \
    (t1::static_type_id (), t2::static_type_id (), \
     oct_catop_ ## f);

#define CATOPDECL(name, a1, a2) \
  static octave_value \
  oct_catop_ ## name (const octave_value& a1, const octave_value& a2, \
                        int dim = 0)

#define DEFCATOPX(name, t1, t2) \
  CATOPDECL (name, , )

#define DEFCATOP(name, t1, t2) \
  CATOPDECL (name, a1, a2)

#define DEFCATOP_FN(name, t1, t2, f) \
  CATOPDECL (name, a1, a2) \
  { \
    CAST_CATOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \
    return octave_value (f (v1.t1 ## _value (), v2.t2 ## _value (), dim)); \
  }

#define DEFNDCATOP_FN(name, t1, t2, e1, e2, f) \
  CATOPDECL (name, a1, a2) \
  { \
    CAST_CATOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \
    return octave_value (f (v1.e1 ## _value (), v2.e2 ## _value (), dim)); \
  }

then in OPERATORS/*.cc need to define the concatenation operators in terms
of cat_ra, and then also alter Fcat to use the CATOP lookups and do something
similar in tree_matrix::rvalue... 

Anyway, this is something that's annoyed me for a long time, and if
someone doesn't get to it first I might get myself interested in it
enough to do something about it...

Cheers
David

-- 
David Bateman                                address@hidden
Motorola CRM                                 +33 1 69 35 48 04 (Ph) 
Parc Les Algorithmes, Commune de St Aubin    +33 1 69 35 77 01 (Fax) 
91193 Gif-Sur-Yvette FRANCE

The information contained in this communication has been classified as: 

[x] General Business Information 
[ ] Motorola Internal Use Only 
[ ] Motorola Confidential Proprietary



reply via email to

[Prev in Thread] Current Thread [Next in Thread]