octave-maintainers
[Top][All Lists]
Advanced

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

Re: mapper functions for 3.1


From: John W. Eaton
Subject: Re: mapper functions for 3.1
Date: Mon, 11 Feb 2008 16:04:28 -0500

On 11-Feb-2008, David Bateman wrote:

| David Bateman wrote:
| > Ok, first hitch. As an example std::sin can accept both double and
| > Complex arguments. Therefore in you example
| >
| >   
| >>  DEFUN (sin, args, , "...")
| >>   {
| >>     octave_value retval;
| >>     if (args.length () == 1)
| >>       retval = args(0).map (std::sin);
| >>     else
| >>       print_usage ();
| >>
| >>     return retval;
| >>   }
| >>
| >>     
| >
| > how is the map method supposed to know which version of the sin function
| > we are referring to? The current implemented gets around this by storing
| > a version of both and then picking the appropriate version when the
| > apply method is called?

I had forgotten that some mappers return different types depending on
argument values, so maybe the octave_value class is not the right
place for a mapper function.

What about writing something like this instead:

  DEFUN (sqrt, args, "...")
  {
    octave_value retval;
    if (args.length () == 1)
      retval = args(0).sqrt ();
    else
      print_usage ();
    return retval;
  }

  octave_value octave_value::sqrt (void) const { return rep->sqrt (); }

  octave_value octave_base_value::sqrt (void) const
  {
    gripe_wrong_type_argument ("octave_base_value::sqrt", type_name ());
    return octave_value ();
  }

  octave_value octave_matrix::sqrt (void) const
  {
    static NDArray::cmapper csqrt = std::sqrt;
    static NDArray::dmapper dsqrt = std::sqrt;

    return matrix.any_element_less_than (0)
      ? matrix.map (csqrt) : matrix.map (dsqrt);
  }

with

  class NDArray
  {
    ...
    typedef double (*dmapper) (double);
    typedef Complex (*cmapper) (const Complex&);
    ...

    NDArray map (dmapper fcn) const { ... }

    ComplexNDArray map (cmapper fcn) const
    {
      // do type conversion from double to complex for each element
      // for the call to the cmapper function.
    }
  }

?

I chose an example with a special case above, but many of these
functions would be the same form, so could be handled with a macro,
maybe something like this:

  #define MAPPER_FUNCTION(NAME, FCN) \
    octave_value \
    NAME (void) const \
    { \
      NDArray::ddmapper dfcn = FCN; \
      return matrix.map (dfcn); \
    }

  class octave_matrix
  {
    ...
    MAPPER_FUNCTION (sin, std::sin)
    MAPPER_FUNCTION (cos, std::cos)
    MAPPER_FUNCTION (tan, std::tan)
    ...
  }


Using the approach above avoids the awkwardness of the mapper functions
with multiple function pointer arguments, but has the disadvantage of
requiring more functions to be defined.  However, I think each of the
functions defined above are more straightforward.  Imagine some future
mapper function with with more complex rules than just lower/upper
bounds for real/complex return values.  With the approach above, I
think it would be clear how to handle such a case.

jwe


reply via email to

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