[PATCH] Add min/max tests. (4/4)

classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] Add min/max tests. (4/4)

Edward Jason Riedy
This adds a bunch of regression test cases for the previous code.
It also adds one more that checks that the same comparison is used
throughout a complex matrix.  Previously, Octave would magically
revert back to the real comparison (directed rather than magnitude)
if a column contained only real numbers.  That's surprising.

Jason

test/ChangeLog
        * octave.test/arith/arith.exp: Add tests max-5.m through max-9.m,
        min-5.m through min-9.m.  All tests succeed with "ans = 1"
        * octave.test/arith/max-5.m: Test (CMatrix, 'ignore-nan') parameters.
        * octave.test/arith/max-6.m: Test (dMatrix, 'prefer-nan') parameters.
        * octave.test/arith/max-7.m: Test (scalar, scalar, opt) parameters.
        * octave.test/arith/max-8.m: Test (CMatrix, CMatrix, opt) parameters.
        * octave.test/arith/max-9.m: Test that the same comparison criteria
        are used across an entire complex matrix.
        * octave.test/arith/min-5.m: Equivalent to max-5.m.
        * octave.test/arith/min-6.m: Equivalent to max-6.m.
        * octave.test/arith/min-7.m: Equivalent to max-7.m.
        * octave.test/arith/min-8.m: Equivalent to max-8.m.
        * octave.test/arith/min-9.m: Equivalent to max-9.m.

--- octave.orig/test/octave.test/arith/arith.exp Fri Oct 23 19:56:25 1998
+++ octave.2/test/octave.test/arith/arith.exp Sat Sep  2 20:09:46 2000
@@ -172,6 +172,26 @@
 set prog_output "\n... max:.*"
 do_test max-4.m
 
+set test max-5
+set prog_output "ans = 1"
+do_test max-5.m
+
+set test max-6
+set prog_output "ans = 1"
+do_test max-6.m
+
+set test max-7
+set prog_output "ans = 1"
+do_test max-7.m
+
+set test max-8
+set prog_output "ans = 1"
+do_test max-8.m
+
+set test max-9
+set prog_output "ans = 1"
+do_test max-9.m
+
 set test min-1
 set prog_output "ans = 1"
 do_test min-1.m
@@ -187,6 +207,26 @@
 set test min-4
 set prog_output "\n... min:.*"
 do_test min-4.m
+
+set test min-5
+set prog_output "ans = 1"
+do_test min-5.m
+
+set test min-6
+set prog_output "ans = 1"
+do_test min-6.m
+
+set test min-7
+set prog_output "ans = 1"
+do_test min-7.m
+
+set test min-8
+set prog_output "ans = 1"
+do_test min-8.m
+
+set test min-9
+set prog_output "ans = 1"
+do_test min-9.m
 
 set test pow2-1
 set prog_output "ans = 1"
diff --new-file -r -u octave.orig/test/octave.test/arith/max-5.m octave.2/test/octave.test/arith/max-5.m
--- octave.orig/test/octave.test/arith/max-5.m Wed Dec 31 16:00:00 1969
+++ octave.2/test/octave.test/arith/max-5.m Sat Sep  2 20:09:08 2000
@@ -0,0 +1,3 @@
+# test complex matrix max for ignore-nan
+# see comments in min-5.m
+all(max ([1, NaN; -2i, 3], 'ignore-nan') == [-2i, 3])
diff --new-file -r -u octave.orig/test/octave.test/arith/max-6.m octave.2/test/octave.test/arith/max-6.m
--- octave.orig/test/octave.test/arith/max-6.m Wed Dec 31 16:00:00 1969
+++ octave.2/test/octave.test/arith/max-6.m Sat Sep  2 20:09:08 2000
@@ -0,0 +1,3 @@
+# test double matrix max for prefer-nan
+a = max ([1, NaN; 2, 3], 'prefer-nan');
+a(1) == 2 && isnan(a(2))
diff --new-file -r -u octave.orig/test/octave.test/arith/max-7.m octave.2/test/octave.test/arith/max-7.m
--- octave.orig/test/octave.test/arith/max-7.m Wed Dec 31 16:00:00 1969
+++ octave.2/test/octave.test/arith/max-7.m Sat Sep  2 20:09:08 2000
@@ -0,0 +1,2 @@
+# test double scalar max
+isnan(max (1, NaN, 'prefer-nan')) && !isnan(max (1, NaN, 'ignore-nan'))
diff --new-file -r -u octave.orig/test/octave.test/arith/max-8.m octave.2/test/octave.test/arith/max-8.m
--- octave.orig/test/octave.test/arith/max-8.m Wed Dec 31 16:00:00 1969
+++ octave.2/test/octave.test/arith/max-8.m Sat Sep  2 20:09:08 2000
@@ -0,0 +1,5 @@
+# test matrix-matrix max, complex
+all(all(isnan(max([1, -1; 0, 3i], [NaN, NaN; NaN, NaN], \
+  'prefer-nan')))) && \
+all(all(!isnan(max([1, -1; 0, 3i], [NaN, NaN; NaN, NaN], \
+   'ignore-nan'))))
diff --new-file -r -u octave.orig/test/octave.test/arith/max-9.m octave.2/test/octave.test/arith/max-9.m
--- octave.orig/test/octave.test/arith/max-9.m Wed Dec 31 16:00:00 1969
+++ octave.2/test/octave.test/arith/max-9.m Sat Sep  2 20:09:08 2000
@@ -0,0 +1,2 @@
+# check that the definition of max is consistent across a complex matrix
+all(max([i, 1; 0, -5]) == [i, -5])
\ No newline at end of file
diff --new-file -r -u octave.orig/test/octave.test/arith/min-5.m octave.2/test/octave.test/arith/min-5.m
--- octave.orig/test/octave.test/arith/min-5.m Wed Dec 31 16:00:00 1969
+++ octave.2/test/octave.test/arith/min-5.m Sat Sep  2 20:09:08 2000
@@ -0,0 +1,6 @@
+# test complex matrix min for ignore-nan
+# (If this fails, check liboctave/mx-reductions.h::PredReducer.  Ensure
+# either tmp_val is initialized to an identity for the predicate in
+# begin() or that apply() has appropriate isnan checks to catch the
+# case where tmp_val is initialized to NaN.)
+all(min ([1, NaN; 2i, 3], 'ignore-nan') == [1, 3])
diff --new-file -r -u octave.orig/test/octave.test/arith/min-6.m octave.2/test/octave.test/arith/min-6.m
--- octave.orig/test/octave.test/arith/min-6.m Wed Dec 31 16:00:00 1969
+++ octave.2/test/octave.test/arith/min-6.m Sat Sep  2 20:09:08 2000
@@ -0,0 +1,3 @@
+# test double matrix min for prefer-nan
+a = min ([1, NaN; 2, 3], 'prefer-nan');
+a(1) == 1 && isnan(a(2))
diff --new-file -r -u octave.orig/test/octave.test/arith/min-7.m octave.2/test/octave.test/arith/min-7.m
--- octave.orig/test/octave.test/arith/min-7.m Wed Dec 31 16:00:00 1969
+++ octave.2/test/octave.test/arith/min-7.m Sat Sep  2 20:09:08 2000
@@ -0,0 +1,2 @@
+# test double scalar min
+isnan(min (1, NaN, 'prefer-nan')) && !isnan(min (1, NaN, 'ignore-nan'))
diff --new-file -r -u octave.orig/test/octave.test/arith/min-8.m octave.2/test/octave.test/arith/min-8.m
--- octave.orig/test/octave.test/arith/min-8.m Wed Dec 31 16:00:00 1969
+++ octave.2/test/octave.test/arith/min-8.m Sat Sep  2 20:09:08 2000
@@ -0,0 +1,5 @@
+# test matrix-matrix min, complex
+all(all(isnan(min([1, -1; 0, 3i], [NaN, NaN; NaN, NaN], \
+  'prefer-nan')))) && \
+all(all(!isnan(min([1, -1; 0, 3i], [NaN, NaN; NaN, NaN], \
+   'ignore-nan'))))
diff --new-file -r -u octave.orig/test/octave.test/arith/min-9.m octave.2/test/octave.test/arith/min-9.m
--- octave.orig/test/octave.test/arith/min-9.m Wed Dec 31 16:00:00 1969
+++ octave.2/test/octave.test/arith/min-9.m Sat Sep  2 20:09:08 2000
@@ -0,0 +1,2 @@
+# check that the definition of min is consistent across a complex matrix
+all(min([i, 1; 3, -5]) == [i, 1])
\ No newline at end of file


Reply | Threaded
Open this post in threaded view
|

[PATCH] Add min/max tests. (4/4)

John W. Eaton-6
On  3-Sep-2000, Edward Jason Riedy <[hidden email]> wrote:

| This adds a bunch of regression test cases for the previous code.
| It also adds one more that checks that the same comparison is used
| throughout a complex matrix.  Previously, Octave would magically
| revert back to the real comparison (directed rather than magnitude)
| if a column contained only real numbers.  That's surprising.

I think that

  octave:4> x = [1+i, -2; -1+i, 1]
  x =

     1 + 1i  -2 + 0i
    -1 + 1i   1 + 0i

  octave:5> min(x)
  ans =

    -1 + 1i  -2 + 0i

is much less surprising than

  octave:5> min(x)
  ans =

    -1 + 1i   1 + 0i

since -2 is smaller than 1 but I can also see the case for not
applying special cases like this.  (Instead, Octave should perform
data type conversions when appropriate so that the special cases are
not necessary, but that's not possible here since matrices can only be
real or complex, not both.)

How hard would it be to allow either behavior (given an option to min/max)?

jwe


Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Add min/max tests. (4/4)

Edward Jason Riedy
And "John W. Eaton" writes:
 - I think that
[...]
 - is much less surprising than
[...]
 - since -2 is smaller than 1 [...]

Not in magnitude.  I suppose that's the key.  

I just realized the behavior I want to avoid still occurs.  Imagine
a nice long calculation intended for complex matrices and magnitude
comparisons written with min / max.  Now imagine that a column just
happens to become all real...  I wouldn't want to try to debug that
problem.

Unfortunately, it still happens when a matrix becomes all real ``by
accident,'' so there does need to be a way to specify magnitude
comparisons to min / max.

 - How hard would it be to allow either behavior (given an option to
 - min/max)?

hmmm...  The simplest way seems to be

  * Change CMatrix::{row,column}_{min,max} back to using the odd (imho)
    comparisons: medium effort.  Making them keep _both_ magnitude and
    value tmps until they encounter a complex number would be the
    easiest (and most cache-friendly).
  * Add {d,C}Matrix::{row,column}_{min_mag,max_mag} to do the magnitude
    comparisons in _both_ cases: mostly just typing.
  * Add another optional argument to src/DLD-FUNCTIONS/minmax.cc: not
    too bad, just ugly.

In all, not too bad, but the semester's started.  ;)  Might take me
another month to find the time, to be honest.  I have lots of house
work to keep me busy on the weekends for the next few weeks.

There are better ways, but they might take a hefty re-working of
the matrix member functions.  Might be more worth-while to look into
replacing them with the MTL than re-inventing it.

Jason


Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Add min/max tests. (4/4)

John W. Eaton-6
On  4-Sep-2000, Edward Jason Riedy <[hidden email]> wrote:

| And "John W. Eaton" writes:
|  - I think that
| [...]
|  - is much less surprising than
| [...]
|  - since -2 is smaller than 1 [...]
|
| Not in magnitude.  I suppose that's the key.  
|
| I just realized the behavior I want to avoid still occurs.  Imagine
| a nice long calculation intended for complex matrices and magnitude
| comparisons written with min / max.  Now imagine that a column just
| happens to become all real...  I wouldn't want to try to debug that
| problem.
|
| Unfortunately, it still happens when a matrix becomes all real ``by
| accident,'' so there does need to be a way to specify magnitude
| comparisons to min / max.

How about

  min (abs (x), abs (y))

?

If I recall correctly, it doesn't really make sense to ask whether one
complex number is `less than' another.  That Matlab overloads the
relational operators to mean X op Y == abs(X) op abs(Y) is, I believe,
just a convention.  Someone (presumably Cleve Moler) thought it would
be a convenient shorthand.  I suppose it is in some cases, but it also
introduces some ambiguity and surprising results (something of a
running theme in the design of Matlab, if you ask me).

If it were up to me (or if I could do it over again) I'd say that min,
max, <, <=, >, >= have no meaning for complex numbers in Octave, and
that if you want to compare magnitudes, you have to state that
explicitly.

jwe


Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Add min/max tests. (4/4)

John W. Eaton-6
On  5-Sep-2000, I wrote

| How about
|
|   min (abs (x), abs (y))
|
| ?

as a suggestion for how to explicitly state that you want to find the
numbers with the minimum magnitudes.  After sending it, I realized
that this is not really what you want, since it returns the minimum
magnitudes, not the NUMBERS with the minimum magnitudes.  So, I think
what is really needed is some way to tell the min and max funtions
what comparison operation (or function) to use.  That would allow the
programmer to clearly state his intention instead of relying on some
convention that can cause trouble when there are mixed types or the
potential for automatic data type conversions to occur.

Also, if it were up to me (or if I could do it over again) I would
want to avoid the problem that results from min, max, and other
functions working on columns of a matrix except when the matrix
happens to have only one row.

jwe


Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Add min/max tests. (4/4)

Paul Kienzle-5
In reply to this post by Edward Jason Riedy
John W. Eaton <[hidden email]> writes:

>On  5-Sep-2000, I wrote
>
>| How about
>|
>|   min (abs (x), abs (y))
>|
>| ?
>
>as a suggestion for how to explicitly state that you want to find the
>numbers with the minimum magnitudes.  After sending it, I realized
>that this is not really what you want, since it returns the minimum
>magnitudes, not the NUMBERS with the minimum magnitudes.  So, I think
>what is really needed is some way to tell the min and max funtions
>what comparison operation (or function) to use.  That would allow the
>programmer to clearly state his intention instead of relying on some
>convention that can cause trouble when there are mixed types or the
>potential for automatic data type conversions to occur.

For the cases where you need a nonstandard comparison, you could easily
write a specialized function.  For example, for magnitude:

        function z=minmag(x,y)
           z=x(:);
           zi=find(abs(x)>abs(y));
           do_fortran_indexing = 1;
           z(zi) = y(zi);
           z = reshape(z,size(x));
        endfunction

To make it completely proper is a bit more work.  You must protect the
do_fortran_indexing state.  You must handle 0, 1, 2, or many arguments,
and for one argument, you must handle row/column vectors separately from
matrices.  The following should do it (though more testing is required):

function [z, zi] = minmag(x, y, ...)
  if nargin == 0
    usage("[z,zi]=minmag(x) or z=minmag(x1,x2,...)");
  elseif nargin == 1
    [z, zi] = min(abs(x));
    [nr, nc] = size(x);
    if (nr == 1 || nc == 1)
      z(zi) = x(zi);
    else
      dfi = do_fortran_indexing;
      unwind_protect
        do_fortran_indexing = 1;
        z = x(zi + [0:nc-1]*nr);
      unwind_protect_cleanup
        do_fortran_indexing = dfi;
      end_unwind_protect
    endif
  else
    dfi = do_fortran_indexing;
    unwind_protect
      do_fortran_indexing = 1;
      z = x(:);
      idx = find(abs(x) > abs(y));
      z(idx) = y(idx);
      z = reshape(z, size(x));
    unwind_protect_cleanup
      do_fortran_indexing = dfi;
    end_unwind_protect
    if nargin > 2
      z = minmag(z, all_va_args);
    endif
  endif
endfunction

>
>Also, if it were up to me (or if I could do it over again) I would
>want to avoid the problem that results from min, max, and other
>functions working on columns of a matrix except when the matrix
>happens to have only one row.

No arguments there.

>
>jwe
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Add min/max tests. (4/4)

John W. Eaton-6
On  8-Sep-2000, Paul Kienzle <[hidden email]> wrote:

| To make it completely proper is a bit more work.  You must protect the
| do_fortran_indexing state.

For the (relatively common) case where a single matrix index is the
result of a call to find(), it seems like it would make more sense to
return a special `indexing object' that could be used on a matrix of
the same shape as the one passed to find() without having to worry
about do_fortran_indexing.  Would that make sense, or do you think it
would also be too restrictive?

jwe


Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Add min/max tests. (4/4)

Paul Kienzle-5
On Thu, Sep 07, 2000 at 08:53:42PM -0500, John W. Eaton wrote:

> On  8-Sep-2000, Paul Kienzle <[hidden email]> wrote:
>
> | To make it completely proper is a bit more work.  You must protect the
> | do_fortran_indexing state.
>
> For the (relatively common) case where a single matrix index is the
> result of a call to find(), it seems like it would make more sense to
> return a special `indexing object' that could be used on a matrix of
> the same shape as the one passed to find() without having to worry
> about do_fortran_indexing.  Would that make sense, or do you think it
> would also be too restrictive?
>
> jwe
>
>

Actually, in this case I should have coded it without the find() as:

    z = x;
    idx = abs(x) > abs(y);
    z(idx) = y(idx);

which gives the same result 2-3 times faster (at least with 2.1.31).  
Since this will work in almost all cases, it doesn't make sense to
create a data type just for the return from find.  Compatibility with
matlab is more compelling, but you get that just by setting
do_fortran_indexing = 1.  

Note that you still need do_fortran_indexing == 1 to handle the nargin==1
case:

    [z, zi] = min(abs(x));
    [nr, nc] = size(x);
    if (nr == 1 || nc == 1)
      z(zi) = x(zi);
    else
      dfi = do_fortran_indexing;
      unwind_protect
        do_fortran_indexing = 1;
        z = x(zi + [0:nc-1]*nr);
      unwind_protect_cleanup
        do_fortran_indexing = dfi;
      end_unwind_protect
    endif

A counter question: why would you ever want do_fortran_index == 0?

        - Paul


Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Add min/max tests. (4/4)

John W. Eaton-6
On  8-Sep-2000, Paul Kienzle <[hidden email]> wrote:

| A counter question: why would you ever want do_fortran_index == 0?

I believe I originally thought that using a single index to select
elements in column-major ordering might be exposing too much of the
underlying implementation.  Now I'm not so sure.  I'm willing to
reconsider, and perhaps just turn it into an optional warning.

jwe


Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Add min/max tests. (4/4)

Edward Jason Riedy
In reply to this post by John W. Eaton-6
And "John W. Eaton" writes:
 -
 - So, I think what is really needed is some way to tell the min and
 - max funtions what comparison operation (or function) to use.

Sorry for the long delay.  This is the right thing, but it's
terribly painful in a Matlab-like language.  And if you're
not tied to a Matlab-like language, why not use Python?  ;)

BTW, my patch makes Octave work pretty much like Matlab, which
is also somewhat broken.  If that's not what you want, no big
deal.

 - Also, if it were up to me (or if I could do it over again) I would
 - want to avoid the problem that results from min, max, and other
 - functions working on columns of a matrix except when the matrix
 - happens to have only one row.

Or define a generalized reduction method (which is how I re-
worked column_min and family in the C++ code) and certain
reduction op selectors (e.g. by type of matrix (Matlab), by
type of the to-be-reduced slice (Octave's treatment of
different columns differently), etc.).  The former is handled
by `ufuncs' in Numpy, but I don't think anyone's quite
approached the latter.  The strange selection by dynamically
determined slice type doesn't sit well with my mental model
of what's going on, so I'm not too enthusiastic about it.

Jason


Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Add min/max tests. (4/4)

John W. Eaton-6
On 13-Sep-2000, Edward Jason Riedy <[hidden email]> wrote:

| And "John W. Eaton" writes:
|  -
|  - So, I think what is really needed is some way to tell the min and
|  - max funtions what comparison operation (or function) to use.
|
| Sorry for the long delay.  This is the right thing, but it's
| terribly painful in a Matlab-like language.  And if you're
| not tied to a Matlab-like language, why not use Python?  ;)

Why Python in particular and not some other scripting language?  This
is a serious question.  I am not interested in starting a language
war.  But if I didn't want Matlab (or Octave), why would I choose
Python?

jwe


Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] Add min/max tests. (4/4)

Edward Jason Riedy
And "John W. Eaton" writes:
 -
 - Why Python in particular and not some other scripting language?  

My reasons:
 * The core developers have expressed an interest in good
   (ieee754) fp support.
 * The FFI is nice, expecially from C++.
 * More of the people who will use the code I'm writing know
   Python than other full-featured scripting languages.
 * The implementation is still simple enough for me to twiddle
   without a huge investment.
 * A good deal of effort by others is going into making Python
   easy to use / understand.
 * Introspective enough that I may be able to get a distributed
   version to work.  Maybe.
 * Code looks pretty.

Why other, not entirely dissimilar languages don't immediately
appeal to me for my current numerical work:
  Dylan:    Unstable implementation I'd have to port myself.  I'd love
            to use a good Dylan, or a Dylan-Python hybrid.
  Erlang:   Nice, but doesn't fit the problem domain.
  Perl:     The FFI is a mess, it's currently experiencing
            Ada-disease, and bad experiences with its development
            process.
  Scheme:   Inherent, mostly unjustified prejudice against it in
            my target audience.
  CL:       Same.
  ML:       Likewise, plus my general dislike of strict static
            typing at that level.  Has odd FP operators due to
            lack of polymorphism in the right places.
  Haskell:  Laziness doesn't mix well with tight memory
            requirements, and monads are, well, monads.
  APL:      Heh.  Yes, I know APL.
  Lua:      Too little infrastructure in the language.  
  Ruby:     I don't know.  Something about it doesn't feel right.
  Forth, Smalltalk, other one-paradigm-fits-all-languages:
            My main work (parallel, unsymmetric sparse matrix
            factorization and associated problems) doesn't fit
            into a single paradigm sanely.
  Java:     Don't get me started.
  Pike, ElastiC, etc.:
            If I want C, I'll use C.
  The other 203983792039734920 languages out there:
            No time to learn more right now.
  Matlab-esque:
            I need a good many general-purpose language features.
            Matlab may have added them, but they feel foreign.

Obviously, many of these reasons are highly subjective.  I'm not
going to pretend otherwise.

 - But if I didn't want Matlab (or Octave), why would I choose
 - Python?                                            

To be honest, I'd really love to see a general mathematical        
library that can be used in many quick-writing languages.  
Octave's is a bit too tilted towards Matlab's way of thinking,
and the license would require my target audience to think
about licensing rather than science.

The library would have to be surprisingly low-level to allow
each language to layer its own way of thinking on it.  I'm not
sure how much sense that makes, though.

Jason


Reply | Threaded
Open this post in threaded view
|

Python (was: Re: [PATCH] Add min/max tests. (4/4))

John W. Eaton-6
On 13-Sep-2000, Edward Jason Riedy <[hidden email]> wrote:

| And "John W. Eaton" writes:
|  -
|  - Why Python in particular and not some other scripting language?  
|
| My reasons:
|  * The core developers have expressed an interest in good
|    (ieee754) fp support.

Where have they expressed this interest?  In the version of Python
that I looked at (1.5.x?), Inf and NaN were not supported very well at
all.  Has the situation changed in any released version of Python?

|  * The FFI is nice, expecially from C++.

Sorry, I'm dense.  What is FFI?

|  * More of the people who will use the code I'm writing know
|    Python than other full-featured scripting languages.

OK.  I believed the same thing about Matlab when I started writing
Octave.  That was the primary reason for choosing the Matlab syntax.
It was not because I really liked it more than anything else.  Now,
after some years of experience, I'm not sure that popularity is a good
reason for choosing a language for the long term.  Short term it is
probably OK, but favor for one language over another tends to shift.

|  * The implementation is still simple enough for me to twiddle
|    without a huge investment.

This will probably change.  The new print>> and op= stuff seems to be
making Python less consistent, which usually means trouble.

Related to the problem of these new operators adding complexity is the
push from some people for new operators for specific numerical tasks.
I'm not sure that is a good idea.  You can't please everyone with a
given set of operators and precedence levels for them.  I don't think
that it is reasonable to expect one language to meet the needs of
everyone.

What would be nice (IMO) is to be able to easily share data between
languages.  One way to do this would be to have a language-neutral
interpreter plus front ends that have syntax and semantics appropriate
for specific problem domains.  Then someone could write numerical code
with nice infix operators and someone else could write AI stuff with
lispy syntax and someone else could write GUI stuff in some OO
friendly syntax.  If this sort of thing has been tried somewhere and
rejected as unworkable, I'd like to know about it.  As it is, we still
seem to be in the one-size-fits-all era of computer language design.

|  * A good deal of effort by others is going into making Python
|    easy to use / understand.

OK.

|  * Introspective enough that I may be able to get a distributed
|    version to work.  Maybe.

I'm not sure I understand what you mean by this.

|  * Code looks pretty.

Quite subjective (as you admit below).

| Why other, not entirely dissimilar languages don't immediately
| appeal to me for my current numerical work:

I agree with most of your comments here.  I don't understand why there
are so many Lisp/Scheme haters out there.

|  - But if I didn't want Matlab (or Octave), why would I choose
|  - Python?                                            
|
| To be honest, I'd really love to see a general mathematical        
| library that can be used in many quick-writing languages.  

| Octave's is a bit too tilted towards Matlab's way of thinking,

Can you be more specific?  The stuff in liboctave does have some
features that are there only to support Matlab-like things, but you
are not forced to use them if you want to use liboctave from some
other interpreter.

| and the license would require my target audience to think
| about licensing rather than science.

I also don't want to start a license war, but is the GPL a problem for
you now?  If so, how?

If NumPy were rewritten to use parts of Octave and to avoid some of
the mistakes of Matlab, do you think the average Python user would
object to parts of it being covered by the GPL?

| The library would have to be surprisingly low-level to allow
| each language to layer its own way of thinking on it.  I'm not
| sure how much sense that makes, though.

I think we already have some very low level libraries out there
(blas, lapack, etc.) and they are generally hard to use.  Maybe that
is why there are not interfaces to these libraries for all the popular
scripting languages.  But perhaps you are looking for something at a
slightly higher level, for example, one that doesn't require that you
pass A, LDA, M, and N when you just want to pass a matrix, or one that
doesn't require the programmer to size and pass in work arrays?

jwe


Reply | Threaded
Open this post in threaded view
|

Re: Python (was: Re: [PATCH] Add min/max tests. (4/4))

Edward Jason Riedy
And "John W. Eaton" writes:
 -
 - Where have they expressed this interest?

On comp.lang.python.  It's a matter of having time to do it,
and having the patience to battle the n! different fp variations.
It's my next evening project (maybe, I might try decimal
arithmetic first, just to avoid the I/O).

 - |  * The FFI is nice, expecially from C++.
 -
 - Sorry, I'm dense.  What is FFI?

Sorry: Foreign Function Interface.  See cxx.sourceforge.net.
Very nice.

 - Now, after some years of experience, I'm not sure that popularity is
 - a good reason for choosing a language for the long term.  Short term
 - it is probably OK, but favor for one language over another tends to
 - shift.

Agreed.  Python is about half-way up the acceptance curve in
general, and some parts of the scientific community have already
accepted it.  I see it as a step towards introducing high-level
language ideas more fully in scientific computing.

 - This will probably change.  The new print>> and op= stuff seems to be
 - making Python less consistent, which usually means trouble.

Yup.  They're adding features when they should be sitting back
to find the easier pieces behind them.  A few lessons from CLOS
(meta-object protocols) and Scheme (extensible syntax) would make
much of Python suddenly simple again.

 - Related to the problem of these new operators adding complexity is the
 - push from some people for new operators for specific numerical tasks.
 - I'm not sure that is a good idea.

Again, I agree.  I liked one idea that came up on c.l.py:  Have
an embedded language.  It's not too terribly difficult to do in
Python.  Just have statements like
  Matlabish.exec("x = A \ B;")
and do whatever you wan between quotes, just like the regular
expression support in Python.  Also means you can optimize
temporaries out of expressions like D=A+B+C.

 - What would be nice (IMO) is to be able to easily share data between
 - languages.

MS's .NET.  Unfortunately, they've screwed up the FP support.
Went completely NaN happy...  The resources under
  http://msdn.microsoft.com/net/
don't really go into enough detail without a big time investment.
I have StarOffice-converted PostScript files of some of the low-
level docs, but they aren't really worth reading if you're not
into compiler intermediate languages.

_Everyone_ seems to be having this idea right now.  Unfortunately,
I don't see very many folks looking at the `right' implementation.
But I'm obviously rather opinionated.

 - As it is, we still seem to be in the one-size-fits-all era of
 - computer language design.

The pendulum swings back and forth between general purpose
languages and domain specific languages.  It always will.  Each
learns from the other.  With C++ and Java, we're currently in the
general purpose regime, but it's swinging back with the `scripting'
languages and multi-language environments.

 - |  * Introspective enough that I may be able to get a distributed
 - |    version to work.  Maybe.
 -
 - I'm not sure I understand what you mean by this.

It's pretty easy to grab the bytecode and throw it to another
node.  (The type of thing you get for free in Erlang, think
you're supposed to get in Java, etc.)

 - | Octave's is a bit too tilted towards Matlab's way of thinking,
 -
 - Can you be more specific?

Not off the top of my head...  ;)  

It also hurt my head when I started digging through the dMatrix ->
MArray2<> -> Array2<> -> Array<> hierarchy with all sorts of
non-virtual member functions that are used different ways in
different places.  I understand why it was done...  It just
seems convoluted to me.

 - I also don't want to start a license war, but is the GPL a problem for
 - you now?  If so, how?

Me, personally, not really.  I'm just so sick of all the lawyers
that I'd prefer a new-BSD-style license.  (The only reason I don't
say public domain is because I'd need to check that disclaimers of
warranty still apply on PD things.)

 - If NumPy were rewritten to use parts of Octave and to avoid some of
 - the mistakes of Matlab, do you think the average Python user would
 - object to parts of it being covered by the GPL?

A few would throw a complete fit, especially with the current
not-GPL-compatible situation.  Personally, I don't mind.  I've
been bitten by the types of situations the GPL prevents, so I
certainly understand its worldview.

The code I'm writing has a pluggable system for the dense matrix
pieces so I can use Numpy, pdl, Matlab, Octave, Blitz++, MTL,
whatever.  Or at least I'm trying to write it that way.  Keeps
changing under me.  sigh...

 - I think we already have some very low level libraries out there
 - (blas, lapack, etc.) and they are generally hard to use.

I consider those easy to use...  I'm also thinking lower level,
not necessarily specific to linear algebra.  Basic array
manipulations, slicing, etc.  A large amount of Matlab software,
like the image processing tools, just uses those operations.  
They're the types of things I need inside a sparse matrix routine.  
Well, and GEMM.  I can't really use much more.  I need tiny
changes to GETRF, etc.

 - Maybe that is why there are not interfaces to these libraries for
 - all the popular scripting languages.

Um, there are for many.  ;)  Many of the languages I listed have
some package that provides linear algebra, and many of those just
call the BLAS and LAPACK on appropriately packed data.  Even
Matlab has finally switched to using them.

Jason