help-octave
[Top][All Lists]
Advanced

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

Re: octave and image processing


From: Al Niessner
Subject: Re: octave and image processing
Date: 21 Dec 2002 23:22:07 -0500

On Sat, 2002-12-21 at 13:00, John W. Eaton wrote:
> On 21-Dec-2002, Al Niessner <address@hidden> wrote:
> 
> | 3) The mutability of the data in an image
> |   a) in-place operations allowed via .oct files only
> |   b) nominal -- as done normally in octave
> 
> | [...]
> 
> | Lastly, there
> | is (3). This is a little more difficult. It would allow reference to be
> | passed within .oct files causing the original data to change. However,
> | the user would have to explicitly choose this option and accept all the
> | pitfalls that come with it.
> 
> Unfortunately(?) you can't do this without some other changes to
> Octave.  There are a couple of levels of reference counting.  One is
> in the Matrix object itself and the other is in the octave_value
> object.  If you look at the octave_scalar object, you will see that it
> is just a container for a double (or complex) number.  Neither of
> those objects implements reference counting, but Octave does not allow
> functions to modify scalar arguments either.  For example, if you do
> something like
> 
>   function f (x) x = 2; end
>   x = 1;
>   f (x)
>   x
> 
> you will find that x still has a value of 1 after the function.  The
> reference counting you need to modify is the overall reference
> counting scheme for octave_value objects.  You can't change that by
> defining a new sub-type like octave_image.
> 
> Sorry, but what you want to do will require some fundamental changes
> to the way Octave works.  You mentioned before that you didn't want to
> do that because it would introduce some maintenance problems for you.
> That's only true if you make the modifications and they are not
> included in the "standard" Octave sources, but if we can come up with
> a reasonable way to introduce "pass-by-reference" semantics for
> functions in Octave, I'd be happy to try to implement that (or help
> you do it).  The primary problem that I see is that whatever we come
> up with will probably not be compatible with whatever the MathWorks
> does for Matlab if they choose to implement similar functionality.
> 
> jwe

All changes and modifications to octave are based on the 2.1.40
development release.

I made some very simple changes (incomplete I am sure) to give you an
idea of what I mean. There are two patches to octave (Array.h and
Array.cc) which allow me to do exactly what I have been trying to say.
The patches are at the end of the email. Basically I added a protected
(should be private but I was in a hurry) boolean field which represents
the state of mutability of the array representation at line 93 of
Array.h. I then added a public (should be protected) method which gives
me access to that field at line 127 Array.h. I did this out of habit and
realize that I could have just put the field there instead. The last
significant change was in Array::make_unique to test this field as well
as the rep->count. Trivial change, but I do not think it is 100%
complete -- making it public etc. for this example makes Array<T> more
vulnerable to reference counting errors than it would be if it were
protected and limited to use by 'image'. The rest of the patches to
Array.{h,cc} are to set the mutability state to false in the
constructors. That way Array<T> behaves as it always did.

I then ran this test program:

#include <octave/oct.h>

DEFUN_DLD (testDynamicFunc, args, orgs, "Test Dynamic Functions.")
{
  Matrix test1 = args(0).matrix_value();

  test1.setMutability (true);
  for (int r = 0 ; r < test1.rows() ; r++)
    for (int c = 0 ; c < test1.cols() ; c++)
      {
        test1(r,c) = test1(r,c)*2.0;
      }
  test1.setMutability (false);

  return octave_value(test1);
}

It should not surprise anyone that in octave I get this:

octave-2.1.40:2> x = [1 2 3 4]
x =

  1  2  3  4

octave-2.1.40:3> testDynamicFunc(x)
ans =

  2  4  6  8

octave-2.1.40:4> x
x =

  2  4  6  8

octave-2.1.40:5> 

It behaves exactly like I want it to -- an M-file will always see it as
an octave matrix, but the OCT files have in-place operation capability.
Now, the real trick is to push this back into a new type that extends
Array<T> and sets the variable for Array when needed -- like a call to
fortran_ref_vec() or something. It can then extract the array without
getting a copy. Hence, reference passing instead of by value in OCT
files.

I think this minimizes the changes to octave because it limits the
reference passing to OCT files where it is natural and the octave's
grammar does not have to change at all.


Al Niessner


Here is the patch to Array.h:

*** Array.h.orig        2002-11-20 11:03:06.000000000 -0800
--- Array.h     2002-12-21 19:16:06.000000000 -0800
*************** protected:
*** 92,100 ****
        }
    };
  
    void make_unique (void)
      {
!       if (rep->count > 1)
        {
          --rep->count;
          rep = new ArrayRep (*rep);
--- 92,101 ----
        }
    };
  
+   bool mutableRep;
    void make_unique (void)
      {
!       if (rep->count > 1 && !mutableRep)
        {
          --rep->count;
          rep = new ArrayRep (*rep);
*************** protected:
*** 114,120 ****
    Array (T *d, int l)
      {
        rep = new typename Array<T>::ArrayRep (d, l);
! 
  #ifdef HEAVYWEIGHT_INDEXING
        idx = 0;
        max_indices = 1;
--- 115,121 ----
    Array (T *d, int l)
      {
        rep = new typename Array<T>::ArrayRep (d, l);
!       mutableRep = false;
  #ifdef HEAVYWEIGHT_INDEXING
        idx = 0;
        max_indices = 1;
*************** protected:
*** 123,132 ****
--- 124,135 ----
      }
  
  public:
+   void setMutability (bool state) { mutableRep = state; }
  
    Array (void)
      {
        rep = new typename Array<T>::ArrayRep ();
+       mutableRep = false;
  
  #ifdef HEAVYWEIGHT_INDEXING
        idx = 0;
*************** public:
*** 138,143 ****
--- 141,147 ----
    explicit Array (int n)
      {
        rep = new typename Array<T>::ArrayRep (n);
+       mutableRep = false;
  
  #ifdef HEAVYWEIGHT_INDEXING
        idx = 0;
*************** public:
*** 152,157 ****
--- 156,162 ----
      {
        rep = a.rep;
        rep->count++;
+       mutableRep = a.mutableRep;
  
  #ifdef HEAVYWEIGHT_INDEXING
        max_indices = a.max_indices;


Here is the patch to Array.cc

*** Array.cc.orig       2002-11-20 11:03:06.000000000 -0800
--- Array.cc    2002-12-21 19:14:17.000000000 -0800
*************** template <class T>
*** 49,54 ****
--- 49,55 ----
  Array<T>::Array (int n, const T& val)
  {
    rep = new typename Array<T>::ArrayRep (n);
+   mutableRep = false;
  
    for (int i = 0; i < n; i++)
      rep->data[i] = val;




-------------------------------------------------------------
Octave is freely available under the terms of the GNU GPL.

Octave's home on the web:  http://www.octave.org
How to fund new projects:  http://www.octave.org/funding.html
Subscription information:  http://www.octave.org/archive.html
-------------------------------------------------------------



reply via email to

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