Reply by robert bristow-johnson July 7, 20102010-07-07

because i copied some of this stuff from a decade old post, and
evidently, Google Groups has changed the number of characters per line
and we cannot control word wrapping in our posts in Google Groups, i
have edited the line endings (and we'll let the lines wrap
naturally).   this should be much more readable than my previous post.

Steven Lord and others at TMW, can you *please* read this carefully,
with enough of an open mind, and *then* respond with questions, legit
criticisms, suggestions and fixes.  and please be straight with us
about the definition of "backward compatible".  if *old* code works
with this, (without making use of any calls to "reorigin()" or
"rebase()" or whatever it would be named), it *is* "backward
compatible", no?

________________________________________________________________

(here are the quotes from old MATLAB manuals that *should* be the
uncompromized vision of the use of the product.  just because TMW no
longer prints these exact statements in their current manuals does not
remove that vision for what MATLAB should be.)

"MATLAB integrates numerical analysis, matrix computation, signal
processing, and graphics in an easy-to-use environment where problems
and solutions are expressed just as they are written
mathematically..."

"MATLAB is a high-performance language for technical computing.  It
integrates computation, visualization, and programming in an easy-to-
use environment where problems and solutions are expressed in familiar
mathematical notation."

note the phrases in claims: "familiar mathematical notation" and "just
as they are written mathematically".  i submit that those claims are
false in a sense that is salient particularly for those of use who use
MATLAB for (digital) signal processing.  and i suspect the claims are
false for some other users that also deal with data that are naturally
sequenced with subscripts or indices that are non-positive.


________________________________________________________________

(this is the foundation of the solution to this indexing problem that
i am asking TMW people to read carefully and not reject due to red
herrings.)




enum MATLAB_class {text, real, complex};
// I don't wanna cloud the issue considering other classes.

typedef struct
   {
   void* data;     // pointer to actual array data
   char* name;     // pointer to the variable's name
   enum MATLAB_class type; // class of MATLAB variable (real, etc.
   int num_dimensions;  // number of array dimensions >= 2
   long* size;    // vector with the number of rows, columns, etc.
   } MATLAB_variable;

char name[32];    // suppose MATLAB names are unique to 31 chars
long size[num_dimensions];

if (type == text)
   {
   char data[size[0]*size[1]*...*size[num_dimensions-1]];
   }
  else if (type == real)
   {
   double data[size[0]*size[1]*...*size[num_dimensions-1];
   }
  else if (type == complex)
   {
   double data[size[0]*size[1]*...*size[num_dimensions-1][2];
   }

The above is sorta C-like pseudocode.  I'm writing it as if the
declarations can allocated like malloc() does.

Currently, when an element, A(n,k), of a 2-dimensional MATLAB array A
is accessed, first n and k are confirmed to be integer value (not a
problem in C), then confirmed to be at least 1 and less than or equal
to size[0] and size[1], respectively.  If those constraints are
satisfied, the value of that element is accessed as:

  data[(n-1)*size[0] + (k-1)];

For a 3 dimensional array, A(m,n,k), it would be the same but now:

  data[((m-1)*size[1] + (n-1))*size[0] + (k-1)];



What is proposed is to first add a new member to the MATLAB variable
structure called "origin" which is a vector of the very same length
(num_dimensions) as the "size" vector.  The default value for all
elements of the origin[] vector would be 1 with only the exceptions
outlined below.  This is what makes this backwards compatible, in the
strictest sense of the term.

typedef struct
   {
   void* data;
   char* name;
   enum MATLAB_class type;
   int num_dimensions;
   long* size;
   long* origin;  // points to a vector with origin for each dimension
   } MATLAB_variable;

char name[32];
long size[num_dimensions];
long origin[num_dimensions];

Now before each index is used, it is checked against the bounds for
that dimension ( origin[dim] <= index < size[dim]+origin[dim] where 0
<= dim < num_dimensions).  Since the default for origin[dim] is 1,
this will have no effect, save for the teeny amount of processing time
need to look up the origin, on existing MATLAB legacy code.

So to access a single element of an array, A(n,k), this C array index
would look like:

  data[(n-origin[1])*size[0] + (k-origin[0])];

For a 3 dimensional array, A(m,n,k), it would look like:

  data[((m-origin[2])*size[1] + (n-origin[1])*size[0] + (k-
origin[0])];



Okay, how someone like myself would use this to do something different
is that there would be at least two new MATLAB facilities similar to
size() and reshape() that I might call "origin()" and "reorigin()",
respectively.  Just like the MATLAB size() function returns the
contents of the size[] vector, origin() would return, in MATLAB
format, the contents of the origin[] vector.

And just like reshape() changes (under proper conditions) the contents
of the size[] vector, reorigin() would change the contents of the
origin[] vector.  Since reorigin() does not exist in legacy MATLAB
code (oh, I suppose someone could have created a function named that,
but that's a naming problem that need not be considered here), then
there is no way for existing MATLAB programs to change the origins
from their default values of 1 making this fix perfectly backward
compatible.



Now, just as there are dimension compatibility rules that exist now
for MATLAB operations, there would be a few natural rules that would
be added so that "reorigined" MATLAB arrays could have operations
applied to them in a sensible way.




ARRAY ADDITION ("+") and SUBTRACTION ("-") and element-by-element
ARRAY MULTIPLICATION (".*"), DIVISION ("./"), POWER (".^"), and
ELEMENTARY FUNCTIONS:

Currently MATLAB insists that the number of dimensions are equal and
the size of each dimension are equal (that is the same "shape") before
adding or subtracting matrices or arrays.  The one exception to that
is adding a scaler to an array, in which a hypothetical array of equal
size and shape with all elements equal to the scaler, is added to the
array.  The resulting array has the same size and shape as the
argument arrays.

The proposed system would, of course, continue this constraint and add
a new constraint in that index origins for each dimension (the
origin[] vector) would have to be equal for two arrays to be added or
subtracted or element-by-element multiplied, etc.  The resulting array
would have the same size[] vector and origin[] vector as the input
arrays.




"MATRIX" MULTIPLICATION ("*"):

    A = B*C;

Currently MATLAB appropriately insists that the number of columns of B
are equal to the number of rows of C (we shall call that number K).
The resulting array has the number of rows of B and the number of
columns of C.  The value of a particular element of A would be:

              K
    A(m,n) = SUM{ B(m,k) * C(k,n) }
             k=1

The proposed system would, of course, continue this constraint and add
a new constraint in that index origins must be equal for each
dimension where the lengths must be equal.  That is the number of
columns of B are equal to the number of rows of C and the origin index
of the columns of B is equal to the origin index of the rows of C.
The resulting array, A, has the number of rows of B and the number of
columns of C and the origin index of the rows of B and the origin
index of the columns of C would also be the same as for A.  The value
of a particular element of A would be:

             org-1+K
     A(m,n) = SUM{ B(m,k) * C(k,n) }
            k=org

where org = origin[0] for the B array and origin[1] for the C array
which must be the same number.  In the same manner as the present
MATLAB K would be size[0] for the B array and size[1] for the C array
and would have to be the same number, otherwise a diagnostic error
would be returned.

Both of these definitions are degenerations of the more general case
where:

             +inf
    A(m,n) = SUM{ B(m,k) * C(k,n) }
            k=-inf

where here you consider B and C to be zero-extended to infinity in all
four directions (up, down, left, and right).  It's just that the zero
element pairs do not have to be multiplied and summed.

Matrix powers and exponentials (on square matrices) can be defined to
be consistent with this extension of the matrix multiply.




MATRIX DIVISION ("/" and "\"):

Like the current matrix division, it would invert the operation of

    A = B*C

that is

    C = B\A

and

    B = A/C

The same size (or shape) requirements and index origin requirements of
the "*" operator would apply to "\" and "/".   Given A and B, whatever
shape and origin requirement for B and C and whatever shape and origin
returned in A in the statement:

    A = B*C;

would be the same requirements for B and A and define the resulting
shape and origin for C in the statement:

    C = B\A




CONCATINATION:

This would also be a simple and straight-forward extension of how
MATLAB presently concatinates arrays.  When we say:

    A = [B C];

The number of rows of B and C must be equal, but the number of columns
of B and C can be anything.  The first columns of A are identical with
the columns of B and then also must the indices of those columns.  And
independent of what the column indices of C are, they just pick up
where the column index of B left off.  This rule extension defaults to
what MATLAB presently does if B and C are both arrays with origin 1.
A similar rule extension can be made for A = [B ; C];  In all cases
the upper left corner of A is identical to the upper left corner of B,
both in value but also in subscripts (so A(1,1) becomes B(1,1) just
like it does now in MATLAB).



FUNCTIONS THAT RETURN INDICES (min(), max(), find(), sort(),
ind2sub(), and any others that I don't know about):

It must be internally consistent (and certainly can be made to be).
The indices returned would be exactly like the 1-based indices
returned presently in MATLAB except that the origin for the
corresponding dimension (that defaults to 1) would be added to each C-
like (0-based) index.  That is, just like now in MATLAB:

   [max_value, max_index] = max(A);

This must mean that A(max_index) is equal to max_value.

I think that this is easy enough to define.  The only hard part is to
identify all MATLAB functions that search through an array and modify
them to start and end at indices that might be different than 1 and
size[dim] as are the search bounds today.  It would instead search
from origin[dim] to size[dim]+origin[dim]-1 which would default to the
current operation if the origin equals 1.



FOR ALL OTHER MATLAB OPERATIONS, until a reasonable extended
definition for arrays with origins not 1 is thought up, MATLAB could
either bomb out with an illegal operation error if the base is not 1
or could, perhaps, ignore the origin.  Either way, it's still
backwards compatible.


Reply by robert bristow-johnson July 6, 20102010-07-06
On Jul 6, 3:38&#4294967295;pm, "Steven Lord" <sl...@mathworks.com> wrote:
> "robert bristow-johnson" <r...@audioimagination.com> wrote in message > news:2f984955-7c2c-4414-8b5b-5843e314a8d7@b35g2000yqi.googlegroups.com... > > > > > On Jul 4, 12:42 pm, Walter Roberson <rober...@hushmail.com> wrote: > > > robert bristow-johnson wrote: > > > > On Jun 27, 8:09 am, Rune Allnor <all...@tele.ntnu.no> wrote: > > > >> Changing this would undermine nearly 30 years worth of code base. > > > > > no it wouldn't. it could be perfectly backward compatible, because > > > > newly-created arrays would have default origin of 1 for every > > > > dimension of the array. the user would have to call a not-yet- > > > > existing function to change the origin. > > > > Robert, your enthusiasm for this idea has led you to neglect thinking > > > the problems through. > > > that might be a premature judgment. &#4294967295;you don't know how much i have > > thought this through for more than a decade. &#4294967295;if you can get Google > > Groups to search adequately, you might find the places where the > > objections (similar to yours) were brought up and i swatted them > > down. &#4294967295;even Cleve eventually admitted that it was, from the strict > > definition of the term, backward compatible. > > > > Suppose I have a mex file written to the current API. > > > as long as no one applies your MEX function (written under the old > > assumptions) to any array with any origin not 1, there would be no > > problem. &#4294967295;still backward compatible. &#4294967295;no one's code breaks. > > Except for the person who DOES apply an older MEX function to a non-1 based > array.
the definition of "backward compatible" that i am using is (from Wikipedia): "a product or a technology is said to be backward compatible when it is able to fully take the place of an older product... Backward compatibility is a relationship between two components, rather than being an attribute of just one of them. More generally, a new component is said to be backward compatible if it provides all of the functionality of the old component." what i am and had been proposing for a decade is backward compatible in that meaning. if people try to use the "new feature" (non-1 based arrays) and misuse them and get error messages, that does not mean that it fails backward compatibility. if a MEX function was unaware of this (and old ones *would* be unaware), it would treat any array argument as if it had origin 1 for every dimension. it would be wrong, but that would be a misuse (to use a function never written to deal with other origins on a non-1 based array). and nothing would blow up.
> Robert, when you've brought this type of system up in the past I've > seriously thought about how it could work, but based on the potential > problems I called out above, speaking personally I do not think it would be > a good idea to modify MATLAB indexing to use your proposed system. > > I think your best option would be to create your own 0-based (or > variable-based) object and overload those functions with which you want to > work as well as subscripted indexing and assignment -- that way you can > control the behavior of indexing for your object.
here's the deal: i am a DSP person, not an OOP person. MATLAB has marketed itself (falsely) making claims (in the v4 and v5 user manuals) as: "MATLAB integrates numerical analysis, matrix computation, signal processing, and graphics in an easy-to-use environment where problems and solutions are expressed just as they are written mathematically - ... " "MATLAB is a high-performance language for technical computing. It integrates computation, visualization, and programming in an easy-to- use environment where problems and solutions are expressed in familiar mathematical notation." note the phrases in claims: "familiar mathematical notation" and "just as they are written mathematically". i submit that those claims are false in a sense that is salient particularly for those of use who use MATLAB for (digital) signal processing. and i suspect the claims are false for some other users that also deal with data that are naturally sequenced with subscripts or indices that are non-positive. now, what i want is for MATLAB to live up to that. MATLAB is not C++ where, if i complain that C doesn't give me a complex variable type, the first response from someone is that i should use C++ and a library with a complex class. MATLAB *does* have an OOP capability and with those two subscript calls (i think they're called subsref() and subsasgn()) to make it possible to insert a shim that intercepts the indices. so, what you say Steven is true, a class can be done, but what i need to use MATLAB (or Octave) for is to do DSP. i should not have to become an OOPs programmer just to do basic DSP with equations that are recognizable in the DSP lit. i remember that Thomas Krauss once told me (a decade ago) that he brought this up early before the Sig Proc Toolbox (the very first MATLAB toolbox) was completed and released. this is really when you guys should have fixed the problem. you have forced people to adopt non-standard non-natural indexing for the problems they work on. besides the FFT (where it should be obvious) i think TMW blew it with the definitions of polyval() and related functions like polyfit(). they should have used 0-based arrays of coefficients with a(n) being the coefficient for x^n. similarly TMW also screwed up the definitions of conv() and related functions. when polynomials are multiplied to each other, we know it's like their coefficient sequences are convolved and the FFT can be used to convolve large coefficient sequences. but the order of coefficients (and the index values associated) are just plain wrong in MATLAB. besides missing the proper 0-based counting, TMW put the order wrong.
> &#4294967295;You can even make use of > the built-in functions (rather than having to reimplement them) by using the > BUILTIN function to call them on the 1-based data that's stored inside the > array as a private data member, and adjust the indices afterward (if > necessary.)
if we were to do it that way, what the object converter (i would call it "rebase" or "reorigin") should do, is check to see if the origins for all dimensions in the output array are all 1, then it should return a regular MATLAB matrix variable and not one of this "rebase" type) so that all of the existing MATLAB functions can work on this 1- based array.
> &#4294967295;Indeed, Nabeel posted an object to do just this to the File > Exchange several years ago:
i remember. and i remember i was unable to use it (because much more needed to be done).
> http://www.mathworks.com/matlabcentral/fileexchange/1168-varbase > > If you wanted to write a classdef-based version of this object then the > Object-Oriented Programming section of the documentation will contain the > information you'll need to become familiar with this style of object. &#4294967295;In > particular, since indexing will be a major component of this object, the > following page will be of special interest: > > http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_oop/br09...
again, you're requiring me to be an OOPs programmer when what i need MATLAB for is to do signal processing. this is something *you*guys* should fix. i would be happy to help in specification (and i had and i'll dig up the old text) but this is a deficit in MATLAB and it's sorta non-responsible for TMW to require users to fix such deficits in their product. that varbase class should be renamed "reorigin" and, to begin with, the following operators should be overloaded according to the following spec, and if a resulting "reorigin" object happens to have only 1 for the origins of every dimension, then a regular 1-based MATLAB variable should be returned. i know it's a little bit to read, but i would ask that you read it. to make that class work, this is the minimum that is needed to make it work usefully and correctly (and backward compatible). i am, of course, guessing at what the C-like date structure is for a MATLAB variable, but whatever it is, the pointer to the origin[] vector should be appended to the end or use an existing *unused* field. then it would be backward compatible with MEX files. r b-j ________________________________________________ enum MATLAB_class {text, real, complex}; // I don't wanna cloud the issue considering other classes. typedef struct { void* data; // pointer to actual array data char* name; // pointer to the variable's name enum MATLAB_class type; // class of MATLAB variable (real, complex,...) int num_dimensions; // number of array dimensions >= 2 long* size; // points to a vector with the number of rows, columns, etc. } MATLAB_variable; char name[32]; // suppose MATLAB names are unique to 31 chars long size[num_dimensions]; if (type == text) { char data[size[0]*size[1]*...*size[num_dimensions-1]]; } else if (type == real) { double data[size[0]*size[1]*...*size[num_dimensions-1]; } else if (type == complex) { double data[size[0]*size[1]*...*size[num_dimensions-1][2]; } The above is sorta C-like pseudocode. I'm writing it as if the declarations can allocated like malloc() does. Currently, when an element, A(n,k), of a 2 dimensional MATLAB array A is accessed, first n and k are confirmed to be integer value (not a problem in C), then confirmed to be at least 1 and less than or equal to size[0] and size[1], respectively. It those constraints are satisfied, the value of that element is accessed as: data[(n-1)*size[0] + (k-1)]; For a 3 dimensional array, A(m,n,k), it would be the same but now: data[((m-1)*size[1] + (n-1))*size[0] + (k-1)]; What is proposed is to first add a new member to the MATLAB variable structure called "origin" which is a vector of the very same length (num_dimensions) as the "size" vector. The default value for all elements of the origin[] vector would be 1 with only the exceptions outlined below. This is what makes this backwards compatible, in the strictest sense of the term. typedef struct { void* data; char* name; enum MATLAB_class type; int num_dimensions; long* size; long* origin; // points to a vector with index origin for each dimension } MATLAB_variable; char name[32]; long size[num_dimensions]; long origin[num_dimensions]; Now before each index is used, it is checked against the bounds for that dimension ( origin[dim] <= index < size[dim]+origin[dim] where 0 <= dim < num_dimensions), Since the default for origin[dim] is 1, this will have no effect, save for the teeny amount of processing time need to look up the origin, on existing MATLAB legacy code. So to access a single element of an array A, this C array index would look like: data[(n-origin[1])*size[0] + (k-origin[0])]; For a 3 dimensional array, A(m,n,k), it would look like: data[((m-origin[2])*size[1] + (n-origin[1])*size[0] + (k-origin[0])]; Okay, how someone like myself would use this to do something different is that there would be at least two new MATLAB facilities similar to size() and reshape() that I might call "origin()" and "reorigin()", respectively. Just like MATLAB size() function returns the contents of the size[] vector, origin() would return, in MATLAB format, the contents of the origin[] vector. And just like reshape() changes (under proper conditions) the contents of the size[] vector, reorigin() would change the contents of the origin[] vector. Since reorigin() does not exist in legacy MATLAB code (oh, I suppose someone could have created a function named that, but that's a naming problem that need not be considered here), then there is no way for existing MATLAB programs to change the origins from their default values of 1 making this fix perfectly backward compatible. Now, just as there are dimension compatibility rules that exist now for MATLAB operations, there would be a few natural rules that would be added so that "reorigined" MATLAB arrays could have operations applied to them in a sensible way. ARRAY ADDITION ("+") and SUBTRACTION ("-") and element-by-element ARRAY MULTIPLICATION (".*"), DIVISION ("./"), POWER (".^"), and ELEMENTARY FUNCTIONS: Currently MATLAB insists that the number of dimensions are equal and the size of each dimension are equal (that is the same "shape") before adding or subtracting matrices or arrays. The one exception to that is adding a scaler to an array, in which a hypothetical array of equal size and shape with all elements equal to the scaler, is added to the array. The resulting array has the same size and shape as the argument arrays. The proposed system would, of course, continue this constraint and add a new constraint in that index origins for each dimension (the origin[] vector) would have to be equal for two arrays to be added or subtracted or element- by-element multiplied, etc. The resulting array would have the same shape and origin[] vector as the input arrays. "MATRIX" MULTIPLICATION ("*"): A = B*C; Currently MATLAB appropriately insists that the number of columns of B are equal to the number of rows of C (we shall call that number K). The resulting array has the number of rows of B and the number of columns of C. The value of a particular element of A would be: K A(m,n) = SUM{ B(m,k) * C(k,n) } k=1 The proposed system would, of course, continue this constraint and add a new constraint in that index origins must be equal for each dimension where the lengths must be equal. That is the number of columns of B are equal to the number of rows of C and the origin index of the columns of B are equal to the origin index of the rows of C. The resulting array has the number of rows of B and the number of columns of C and the origin index of the rows of B and the origin index of the columns of C. The value of a particular element of A would be: org-1+K A(m,n) = SUM{ B(m,k) * C(k,n) } k=org where org = origin[0] for the B array and origin[1] for the C array which must be the same number. In the same manner as the present MATLAB K would be size[0] for the B array and size[1] for the C array and would have to be the same number, otherwize a diagnostic error would be returned. Both of these definitions are degenerations of the more general case where: +inf A(m,n) = SUM{ B(m,k) * C(k,n) } k=-inf where here you consider B and C to be zero-extended to infinity in all four directions (up, down, left, and right). It's just that the zero element pairs do not have to be multiplied and summed. Matrix powers and exponentials (on square matrices) can be defined to be consistent with this extension of the matrix multiply. MATRIX DIVISION ("/" and "\"): Like the current matrix division, it would invert the operation of A = B*C that is C = B\A and B = A/C The same size (or shape) requirements and index origin requirements of the "*" operator would apply to "\" and "/". Given A and B, whatever shape and origin requirement for B and C and whatever shape and origin returned in A in the statement: A = B*C; would be the same requirements for B and A and define the resulting shape and origin for C in the statement: C = B\A CONCATINATION: This would also be a simple and straight-forward extension of how MATLAB presently concatinates arrays. When we say: A = [B C]; The number of rows of B and C must be equal, but the number of columns of B and C can be anything. The first columns of A are identical with the columns of B and then also must the indices of those columns. And independent of what the column indices of C are, they just pick up where the column index of B left off. This rule extension defaults to what MATLAB presently does if B and C are both arrays with origin 1. A similar rule extension can be made for A = [B ; C]; In all cases the upper left corner of A is identical to the upper left corner of B, both in value but also in subscripts (so A(1,1) becomes B(1,1) just like it does now in MATLAB). FUNCTIONS THAT RETURN INDICES (min(), max(), find(), sort(), ind2sub(), and any others that I don't know about): It must be internally consistent (and certainly can be made to be). The indices returned would be exactly like the 1-based indices returned presently in MATLAB except that the origin for the corresponding dimension (that defaults to 1) would be added to each C-like index. That is, just like now in MATLAB: [max_value, max_index] = max(A); This must mean that A(max_index) is equal to max_value. I think that this is easy enough to define. The only hard part is to identify all MATLAB functions that search through an array and modify them to start and end at indices that might be different than 1 and size[dim] as are the search bounds today. It would instead search from origin[dim] to size[dim]+origin[dim]-1 which would default to the current operation if the origin equals 1. FOR ALL OTHER MATLAB OPERATIONS, until a reasonable extended definition for arrays with origins not 1 is thought up, MATLAB could either bomb out with an illegal operation error if the base is not 1 or could, perhaps, ignore the origin. Either way, it's still backwards compatible.
Reply by Steven Lord July 6, 20102010-07-06
"robert bristow-johnson" <rbj@audioimagination.com> wrote in message 
news:2f984955-7c2c-4414-8b5b-5843e314a8d7@b35g2000yqi.googlegroups.com...
> On Jul 4, 12:42 pm, Walter Roberson <rober...@hushmail.com> wrote: > > robert bristow-johnson wrote: > > > On Jun 27, 8:09 am, Rune Allnor <all...@tele.ntnu.no> wrote: > > >> Changing this would undermine nearly 30 years worth of code base. > > > > > > no it wouldn't. it could be perfectly backward compatible, because > > > newly-created arrays would have default origin of 1 for every > > > dimension of the array. the user would have to call a not-yet- > > > existing function to change the origin. > > > > Robert, your enthusiasm for this idea has led you to neglect thinking > > the problems through. > > that might be a premature judgment. you don't know how much i have > thought this through for more than a decade. if you can get Google > Groups to search adequately, you might find the places where the > objections (similar to yours) were brought up and i swatted them > down. even Cleve eventually admitted that it was, from the strict > definition of the term, backward compatible. > > > Suppose I have a mex file written to the current API. > > as long as no one applies your MEX function (written under the old > assumptions) to any array with any origin not 1, there would be no > problem. still backward compatible. no one's code breaks.
Except for the person who DOES apply an older MEX function to a non-1 based array. People often need/want to reuse their old code, and I've found people tend to get a wee bit upset if you tell them "Sorry, don't do that." unless there's a major benefit they can immediately see (and sometimes even then.) While some (including yourself) may see 0-based indexing as such a major benefit, there are also many who would not.
> if this extension or enhancement to MATLAB were adopted and you wanted > your .mex function to work with arrays of origin different than 1, you > would have to modify the .mex function to look for the origins (using > the new API). otherwise your function would work as if all of the > origins were 1 when they may not be.
And that is an incompatibility. Let's take a look at a few others. 1) Let's say that a user had a function that needs to loop over the columns of their matrix. This is not a contrived example; I've seen plenty of code that does something similar. for whichcolumn = 1:size(A, 2) % process column A(:, whichcolumn) end If A is a 1-based array, then everything works as it did before. If A was a 0-based array, then this would error with an error message like "Index exceeds matrix dimension" or something similar. Code that used to work no longer works. That's an incompatibility. Even worse, let's say the user's code, for whatever reason, only needed to process all but the final column of A. for whichcolumn = 1:size(A, 2)-1 % process column A(:, whichcolumn) end Now this code can SILENTLY GIVE THE WRONG ANSWER if A is a 0-based array, as it will process all but the _first_ column of A. 2) What happens if I SAVE a 0-based array in a MAT-file and LOAD it in a version prior to the introduction of this change? Would you expect that to work? 3) Suppose A is a 0-based array and B is a 1-based array. What happens if I ask for A+B? A.*B? [Assume all the sizes match; just consider the based-ness for this scenario.] I'm guessing you're going to say that A+B and A.*B both error; operating under that assumption, let's take a look at one more example. What should the command pi+A do? Does the pi built-in function return a 0-based array or a 1-based array? Seems to me that users would expect pi+A to add pi to each element of A -- but for backwards compatibility, and to agree with your own proposal from earlier in this thread, PI would _have_ to return a 1-based array and so pi+A would ERROR. If you say that PI should be "smart enough" to know with what it's going to be combined and return the appropriate-indexed scalar: x = pi; y = A+x; z = B+x; _One_ of the latter two operations must error unless scalars are treated as a special case. If they are treated specially, x = 1:10; will encounter the same problem assuming A and B are both 10-element vectors, since x must have a specified base when it is created.
> it's no different than with any other extension or enhancement to a > language. the issue you brought up is not a violation of backward > compatibility. old code (with old .mex files) would still work the > same way they did before.
Robert, when you've brought this type of system up in the past I've seriously thought about how it could work, but based on the potential problems I called out above, speaking personally I do not think it would be a good idea to modify MATLAB indexing to use your proposed system. I think your best option would be to create your own 0-based (or variable-based) object and overload those functions with which you want to work as well as subscripted indexing and assignment -- that way you can control the behavior of indexing for your object. You can even make use of the built-in functions (rather than having to reimplement them) by using the BUILTIN function to call them on the 1-based data that's stored inside the array as a private data member, and adjust the indices afterward (if necessary.) Indeed, Nabeel posted an object to do just this to the File Exchange several years ago: http://www.mathworks.com/matlabcentral/fileexchange/1168-varbase If you wanted to write a classdef-based version of this object then the Object-Oriented Programming section of the documentation will contain the information you'll need to become familiar with this style of object. In particular, since indexing will be a major component of this object, the following page will be of special interest: http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_oop/br09eqz.html -- Steve Lord slord@mathworks.com comp.soft-sys.matlab (CSSM) FAQ: http://matlabwiki.mathworks.com/MATLAB_FAQ To contact Technical Support use the Contact Us link on http://www.mathworks.com
Reply by Manny July 4, 20102010-07-04
On Jun 27, 9:53&#4294967295;pm, Rune Allnor <all...@tele.ntnu.no> wrote:
> On 27 Jun, 22:03, robert bristow-johnson <r...@audioimagination.com> > wrote: > > > > > > Ought to be a piece of cake, provided matlab's OO is half decent. > > > if you see it as a piece of cake, i would invite you to collaborate > > since i am shit-for-brains regarding the nasty details of setting this > > up. > > Sorry, can't help with that. I've never really progressed > from how I started using matlab some 20 years ago, as an > algorithm testbed and general prototyping tool. Once things > turn 'real' I tend to switch to C++ rather quickly. But in > C++ what you want is trivial. For instance, switching from > a base 0 vector indexing to base 1 would be something like > (allowing for the element dereference operator being [] rather > than () in C++) > > template<class T> > class base1vector : public std::vector<T>{ > public: > &#4294967295; &#4294967295;T& operator[](size_t i){return this->operator[](i-1);}; > > }; > > You would probably need a few variations over this theme, > and some constructors, but the gist is a simple as this. > > Rune
Yes. Things have turned real for few months now for me. I even tried to write a "number crunching manager" that would regularily write down data to disk to free up matlab workspace but didn't get me too far with my 22hours processing time. I highly recommend the "templated" C+ + approach. You can use generics to even move down from floating-point to fixed-point using SystemC headers. What more could you possibly ask for? -Momo
Reply by robert bristow-johnson July 4, 20102010-07-04
On Jul 4, 12:42&#4294967295;pm, Walter Roberson <rober...@hushmail.com> wrote:
> robert bristow-johnson wrote: > > On Jun 27, 8:09 am, Rune Allnor <all...@tele.ntnu.no> wrote: > >> Changing this would undermine nearly 30 years worth of code base. > > > > no it wouldn't. &#4294967295;it could be perfectly backward compatible, because > > newly-created arrays would have default origin of 1 for every > > dimension of the array. &#4294967295;the user would have to call a not-yet- > > existing function to change the origin. > > Robert, your enthusiasm for this idea has led you to neglect thinking > the problems through.
that might be a premature judgment. you don't know how much i have thought this through for more than a decade. if you can get Google Groups to search adequately, you might find the places where the objections (similar to yours) were brought up and i swatted them down. even Cleve eventually admitted that it was, from the strict definition of the term, backward compatible.
> Suppose I have a mex file written to the current API.
as long as no one applies your MEX function (written under the old assumptions) to any array with any origin not 1, there would be no problem. still backward compatible. no one's code breaks. if this extension or enhancement to MATLAB were adopted and you wanted your .mex function to work with arrays of origin different than 1, you would have to modify the .mex function to look for the origins (using the new API). otherwise your function would work as if all of the origins were 1 when they may not be. it's no different than with any other extension or enhancement to a language. the issue you brought up is not a violation of backward compatibility. old code (with old .mex files) would still work the same way they did before. r b-j
Reply by Walter Roberson July 4, 20102010-07-04
robert bristow-johnson wrote:
> On Jun 27, 8:09 am, Rune Allnor <all...@tele.ntnu.no> wrote:
>> Changing this would undermine nearly 30 years worth of code base.
> no it wouldn't. it could be perfectly backward compatible, because > newly-created arrays would have default origin of 1 for every > dimension of the array. the user would have to call a not-yet- > existing function to change the origin.
Robert, your enthusiasm for this idea has led you to neglect thinking the problems through. Suppose I have a mex file written to the current API. One or more of the arguments to the function are array indices. Now introduce your proposed new indexing scheme and have the user create such an array and pass it in to the existing mex file. Your claim that the proposed change "could be perfectly backwards compatible" implies that the indices the user passes in must not rely on the new indexing scheme, because "perfectly backwards compatible" means that old code must work UNCHANGED. Now *without changing the API for existing routines*, how is Matlab going to know if a (say) 5 being passed in as a numeric value is already adjusted to be 1-relative or needs to be silently re-biased by Matlab to the appropriate basis in order to preserve backwards compatibility? What if the dimension to be indexed is itself is a parameter so that the unbiasing that needs to take place is not constant? What if the dimension number is not an _obvious_ parameter, such as if you had some encoding such as the mesh encoding that mixes control values and data values in the same array? What if the indices that have to be rebiased have been packed, such as two 8-bit indices numerically jammed into a 16 bit number -- how is Matlab going to know the jamming algorithm to know how to rebias and construct the appropriate new index? As long as indices are computable data then in order to support different index biases you MUST break backwards compatibility, in that the existing code would have to be enhanced to know about and take into account the new indexing scheme for any parameter that is not provably an old-style matrix.
Reply by robert bristow-johnson June 27, 20102010-06-27
On Jun 27, 3:22&#4294967295;pm, Richard Owlett <rowl...@pcnetinc.com> wrote:
> Apologies to those who might think I'm stealing their thread. > > *CAVEAT LECTOR* Though I've *NEVER* supported myself by any trade > normally associated with DSP, my avocations regularly deal with > topics covered by this group. > > I've dealt with problems best expressed with a 0 base index. > I've dealt with problems best expressed with a 1 base index. > > For problems involving a FFT (or inverse) I use Scilab 4.x > Choice NOT based on indexing - couldn't afford MATLAB and at the > time Octave had installation problems on *my* Windows setup. > > I think it is foolish for for any purported "GENERAL PURPOSE" > package to not address the index base issue. > > A before I get really sarcastic comments - If I'm not old enough > to have changed their diapers/wipes, I'm more than old enough to > have been their "sitter" ;}
with me, Richard, you're preaching to the choir. i find this deficit in MATLAB to be astonishing. particularly so long after multiple people have pointed it out (including an early developer for the Sig Proc toolbox). r b-j
Reply by Rune Allnor June 27, 20102010-06-27
On 27 Jun, 22:03, robert bristow-johnson <r...@audioimagination.com>
wrote:
> > > Ought to be a piece of cake, provided matlab's OO is half decent. > > if you see it as a piece of cake, i would invite you to collaborate > since i am shit-for-brains regarding the nasty details of setting this > up.
Sorry, can't help with that. I've never really progressed from how I started using matlab some 20 years ago, as an algorithm testbed and general prototyping tool. Once things turn 'real' I tend to switch to C++ rather quickly. But in C++ what you want is trivial. For instance, switching from a base 0 vector indexing to base 1 would be something like (allowing for the element dereference operator being [] rather than () in C++) template<class T> class base1vector : public std::vector<T>{ public: T& operator[](size_t i){return this->operator[](i-1);}; }; You would probably need a few variations over this theme, and some constructors, but the gist is a simple as this. Rune
Reply by robert bristow-johnson June 27, 20102010-06-27
On Jun 27, 2:16&#4294967295;pm, Rune Allnor <all...@tele.ntnu.no> wrote:
> On 27 Jun, 20:06, robert bristow-johnson <r...@audioimagination.com> > wrote: > > > On Jun 27, 8:09&#4294967295;am, Rune Allnor <all...@tele.ntnu.no> wrote: > > > > On 27 Jun, 07:56, eric.jacob...@ieee.org (Eric Jacobsen) wrote: > > > > > IMHO the most plausible explanation for why this has never been > > > > addressed is that a conscious decision has been made within the > > > > MathWorks that Matlab should not have flexible or zero-based indexing > > > > capability. > > > > The reason why it has never been addressed is that MATLAB is > > > an acronym for MATrix LABoratory. In linear algebra the numerical > > > arrays are - like it or not - indexed base 1. > > > whether it's 0 or 1 is not the issue. &#4294967295;whether the user can define it > > for a particular array *is* the issue. > > In that case, why can't you just use the OO capabilities of > matlab and declare your own array class, say, RBJarray, and > overload the () operator?
i think this is described in subsref() and subsasgn() and in this page http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_oop/br09eqz.html i had thought about it before. i think i would call the class "rebase" or "reorigin", because a call to something that looks like a function called that would be what creates an object in that class (with a regular MATLAB array as an argument as well as the new origin values). this psuedo-function would look like a counterpart to "reshape". then there would be another basic function called "base" or "origin" that would return a vector with the origins (just like "size" returns the values set with "reshape"). the issue is "just". never marketed myself as an OOPs person. i have asked people at comp.soft-sys.matlab about this, oh, maybe 5 or 8 years ago. can't remember what came of it. speed is an issue. and cleanliness (much cleaner done at the root level since MATLAB has to subtract 1 from indices (at least for arrays having more than one dimension) for individual to assemble a net pointer into the array.
> Ought to be a piece of cake, provided matlab's OO is half decent.
if you see it as a piece of cake, i would invite you to collaborate since i am shit-for-brains regarding the nasty details of setting this up. a decade ago, i posted to comp.soft-sys.matlab a description on how array arithmetic would also have to be modified (by overloading "+", "-", "*", ".*", "\", "/", "./", "^", ".^" and all of the simple math functions that work on a straight-forward element-by-element basis). the array created would have the origins defined in the correct manner (not always at 1). Google Groups doesn't work as good as it used to but i could try to dig up those posts. that would be a beginning. a different fft (i would call them "dft" and "idft") that would look at the origins and apply the proper phase modification (or rearrange what goes in, similarly to fftshift). different functions for ployval() (and related functions like polyfit()) that get the order of coefficients wrong (should be the 0th- order or constant coef first, at the 0th index). it would be a task, but doable to start. still should instead be done at the fundamental level, just like "complex" should be a basic type in C. it might be a piece of cake for a seasoned MATLAB programmer who's used their OO (and maybe subsref and subsasgn) before, but i just want to be able to do DSP and translate the common equations directly from the lit to MATLAB without having to fiddle with the addition or subtraction of 1 for the fft or some other constant if i want to model a non-causal impulse response. i should be able to just do that directly. if this is a piece of cake, i'd be interested in collaboration. (but it would still be better if it were done at the fundamental level, without having to create a class.) r b-j
Reply by Richard Owlett June 27, 20102010-06-27
Apologies to those who might think I'm stealing their thread.

*CAVEAT LECTOR* Though I've *NEVER* supported myself by any trade 
normally associated with DSP, my avocations regularly deal with 
topics covered by this group.

I've dealt with problems best expressed with a 0 base index.
I've dealt with problems best expressed with a 1 base index.

For problems involving a FFT (or inverse) I use Scilab 4.x
Choice NOT based on indexing - couldn't afford MATLAB and at the 
time Octave had installation problems on *my* Windows setup.

I think it is foolish for for any purported "GENERAL PURPOSE" 
package to not address the index base issue.

A before I get really sarcastic comments - If I'm not old enough 
to have changed their diapers/wipes, I'm more than old enough to 
have been their "sitter" ;}