From dubois@kristen.llnl.gov Wed Nov 1 02:56:19 1995 From: dubois@kristen.llnl.gov (P. Dubois) Date: Wed, 1 Nov 1995 10:56:19 +0800 Subject: [PYTHON MATRIX-SIG] Some notes on the matrix class Message-ID: <9511011856.AA29129@kristen.llnl.gov> This is a very nice facility already and has an amazing amount of functionality. What follows are some notes I made on it. Other members of the MATRIX-SIG have probably played enough before with the idea to realize what the examples don't show: the subscript notation for multiple dimensions works perfectly...I'm stunned. a. The already implemented list of functions/reduction operators is impressive. We have also found useful: 1. A function equal to max(m) - min(m), often used as a reduction operator in higher dimensions. We call it ptp (peak-to-peak). 2. ranf(m) fills m with uniform random numbers on (0.0, 1.0) 3. A function reshape(x,n,m,...) equal to a copy of x reshaped as (n,m,...) The decision to make reshape a status-altering method is fine, but often the need for a reshape is in the context of some temporary value needed in an expression. Some of the clever rank stuff mitigates this need but I bet this still comes in very useful. Actually, our function of this kind also duplicates copies of x as needed provided length(x) divides the new size. 4. The existing ones(n,m) will return a matrix of shape (n,m) filled with 1.0; equally useful would be one where the i,j element is 1.0 iff i==j, 0.0 otherwise. b. compress(condition, x) = those elements of x corresponding to those elements of condition that are "true". condition and x must have the same length (or x scalar), result is a one-dimensional vector with length equal to the number of true elements in condition. Naturally this is most useful if x < y returns a vector instead of a scalar. Most used form however is with a condition of the form x > 0. or some similar comparison to a scalar, which are expressible already in Python if we take "true" in this sense to be the normal Python meaning. c. My Basis users love: where(condition,x,y) is shaped like condition and has elements of x and y where condition is respectively true or false; we allow broadcast of scalars x or y, so some thought about ranks should reveal the equivalent notion here. Often used in the form where(z, x/z, 1.e99); in this case we rely on a convention that something/0.0 = Infinity, where Infinity is some variable the users can set to suit them, but anyway the idea is that the computation x/z goes at compiled speed and does not cause an exception. We haven't found this perfect and of course would prefer that the computation is simply not done at components where z is false. Given the genius you guys have already displayed ... (Yes, you can do this with a for loop, this is just a speed-freak need). d. One curiosity is the notation something[(a,b,c)]. This is required because something[a,b,c] is a syntax error. But perhaps Python could allow the latter interpreted as the former. For if you do x=[1.,2.,3.] then trying x[(0,1,2)] produces a perfectly sensible error message. And it would be in the spirit of tuples not always needing the parentheses. (That sound you hear is the shot of a large caliber weapon as Guido justifiably shoots a newbie for making a suggested language change before he can even use half the language yet; in fact, I'm tempted to shoot myself, but I'm enjoying Python too much to die yet.) ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From guido@CNRI.Reston.VA.US Wed Nov 1 19:09:26 1995 From: guido@CNRI.Reston.VA.US (Guido van Rossum) Date: Wed, 01 Nov 1995 14:09:26 -0500 Subject: [PYTHON MATRIX-SIG] Some notes on the matrix class In-Reply-To: Your message of "Wed, 01 Nov 1995 10:56:19 +0800." <9511011856.AA29129@kristen.llnl.gov> References: <9511011856.AA29129@kristen.llnl.gov> Message-ID: <199511011909.OAA04346@monty> > d. One curiosity is the notation something[(a,b,c)]. This is required > because something[a,b,c] is a syntax error. But perhaps Python could > allow the latter interpreted as the former. For if you do x=[1.,2.,3.] > then trying x[(0,1,2)] produces a perfectly sensible error message. > And it would be in the spirit of tuples not always needing the parentheses. > (That sound you hear is the shot of a large caliber weapon as Guido > justifiably shoots a newbie for making a suggested language change before > he can even use half the language yet; in fact, I'm tempted to shoot > myself, but I'm enjoying Python too much to die yet.) Am I known to shoot newbies? Only in my dreams :-) This is actually a very reasonable request that has come up in this context before. It's a tad complicated to implement because there some interference with the syntax for x[i:j], but should be possible. If someone could contribute patches I'd be willing to review them and add them to the next release; otherwise it may happen slower. I expect that changes are needed only to Grammar and compile.c... --Guido van Rossum URL: ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From jjh@mama-bear.lcs.mit.edu Wed Nov 1 20:28:58 1995 From: jjh@mama-bear.lcs.mit.edu (James Hugunin) Date: Wed, 1 Nov 95 15:28:58 -0500 Subject: [PYTHON MATRIX-SIG] Some notes on the matrix class References: <9511011856.AA29129@kristen.llnl.gov> Message-ID: <9511012028.AA00472@nineveh.lcs.mit.edu.LCS.MIT.EDU> > Date: Wed, 1 Nov 1995 10:56:19 +0800 > From: "P. Dubois" > > This is a very nice facility already and has an amazing amount of > functionality. Thanks for the compliment and the feedback. > 1. A function equal to max(m) - min(m), often used as a reduction operator > in higher dimensions. We call it ptp (peak-to-peak). I'll add the following to the standard functions def ptp(m): return max(m)-min(m) where within Matrix.py, max(m) <--> maximum.reduce(m) > 2. ranf(m) fills m with uniform random numbers on (0.0, 1.0) I just added a function for this, (I needed to initialize a weight matrix for a NN) it has the form, m = rand(d1,...,dn). where m will be a new matrix with the given dimensions. It uses whrandom.py for getting its random numbers so is slow. If somebody with a good random number generator in C would like to add this to matrixmodule.c as a new instantiation method in C, I'd use it. > 3. A function reshape(x,n,m,...) equal to a copy of x reshaped as (n,m,...) Already in my working copy of Matrix.py (requested by Konrad Hinsen). I use the syntax reshape(x, (d1,...dn)) so that reshape(a, b.shape) works. I don't like the idea of automatically making copies of the matrix in calls to reshape, but I have added the method m.copy(n=1) to make an arbitray number of copies of a matrix (this is much like the multiply operator for lists). (I also added a concat method noticing that I was missing this other functionality of lists). > 4. The existing ones(n,m) will return a matrix of shape (n,m) > filled with 1.0; equally useful would be one where the i,j element is > 1.0 iff i==j, 0.0 otherwise. This is now given by the eye(n,m,k=0) function (stolen from matlab), where the i,j element is 1.0 iff i-j==k, 0.0 otherwise. This is easy enough to contruct yourself out of outer products (which is what eye does). ie. identity = equal.outer(mrange(n), mrange(m)) Aren't outer products cool? > b. compress(condition, x) = those elements of x corresponding to those > elements of condition that are "true". condition and x must have > the same length (or x scalar), result is a one-dimensional vector with > length equal to the number of true elements in condition. Naturally this > is most useful if x < y returns a vector instead of a scalar. > Most used form however is with a condition of the form x > 0. or some > similar comparison to a scalar, which are expressible already in Python > if we take "true" in this sense to be the normal Python meaning. This can be expressed as reshape(x, None)[condition.nonzero()]. My personal take on this is that if condition is not a vector, then this function is meaningless. If it is a vector, it should be able to be applied to any dimension of x. I'll add the following to Matrix.py to support this: def compress(condition, m, dimension=-1): if dimension < 0: dimension = len(m.shape)+dimension if len(condition.shape)!=1 or len(condition)!=m.shape[dimension]: raise ValueError index = [All]*len(m.shape) index[dimension] = condition.nonzero() print index return m[index] BTW - while x < y returns a (meaningless) scalar, Matrix.less(x, y) returns a matrix of booleans. There has been a small amount of talk about the possibilty of having "boolean types" in addition to number, sequence, and mapping types that would support >, <, ==, etc. After writing a lot of code with matrices, I feel that many things could be expressed a lot more elegantly if this was allowed. Unfortunately, Guido appears to be skeptical of this proposal, so don't hold your breath. I've run into particular collisions with and, or, and not. These functions when applied to matrices are renamed to the ugly "Matrix.andBoolean", etc. The problem is that the former are reserved words in python, so you can't create functions with those names (even in the "safe" context of a module). > c. My Basis users love: > where(condition,x,y) is shaped like condition and has elements of x and > y where condition is respectively true or false; we allow broadcast of > scalars x or y, so some thought about ranks should reveal the equivalent > notion here. Often used in the form where(z, x/z, 1.e99); in this case > we rely on a convention that something/0.0 = Infinity, where Infinity is > some variable the users can set to suit them, but anyway the idea is that > the computation x/z goes at compiled speed and does not cause an exception. I had something like this in my original matrix proposal, but was advised that it could be expressed as without any extra C-code: def where(condition, x, y): c = notEqual(condition, 0) return c*x+(1-c)*y where the I am relying on the fact that all comparision operators return 1 for true. This is in fact about 1/5th the speed of writing a where function in C, so it should be dropped to compiled code at some time. I'll add this to the standard set of functions in Matrix.py. > We haven't found this perfect and of course would prefer that the > computation is simply not done at components where z is false. Given > the genius you guys have already displayed ... (Yes, you can do this > with a for loop, this is just a speed-freak need). I'm a speed freak too, if you ever have to use a for loop to iterate over the contents of a matrix, feel free to report it as a bug in the matrix package. -- You raise another interesting issue here that I've completely ignored in the matrix object so far. Numeric exceptions are not handled at all; in return, matrix math executes at the speed of compiled code. However, it wouldn't be too hard to add functions like safeDivide to the ofunc collection that would signal exceptions if someone considers this important. I don't even have the hack that x/0.0 = some user settable Infinity. x/0.0 is set to the IEEE value for Infinity. > d. One curiosity is the notation something[(a,b,c)]. This is required > because something[a,b,c] is a syntax error. But perhaps Python could > allow the latter interpreted as the former. Guido beat me to this one. I'd like to add that if anybody decides to go rummaging around in Grammer and compile.c, Guido also mentioned that he'd be willing to let a**b <--> pow(a, b) into the syntax. This also seems like an easy hack for someone with the right know-how, and would be a nice bonus for numerical code. There have been so many things added to the matrix object this week, that it seems I should get a new version out to those interested testers (so you won't need to ask me for features that are already there). I'll put out a new object on Friday (if all goes well). It will have all of the above additions (and many more), slightly different syntax for specifying the rank of an operator, working complex numbers, possibly working generic Python Objects as matrix elements and almost all of the memory leaks that I identified as clearly belonging to my code squashed (thanks to Purify). There are still a few memory leaks that appear to be in the python internals, and not due to my code (I think). I'll check those out when I have more time. -Jim ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From guido@CNRI.Reston.VA.US Wed Nov 1 20:31:19 1995 From: guido@CNRI.Reston.VA.US (Guido van Rossum) Date: Wed, 01 Nov 1995 15:31:19 -0500 Subject: [PYTHON MATRIX-SIG] Some notes on the matrix class In-Reply-To: Your message of "Wed, 01 Nov 1995 15:28:58 EST." <9511012028.AA00472@nineveh.lcs.mit.edu.LCS.MIT.EDU> References: <9511011856.AA29129@kristen.llnl.gov> <9511012028.AA00472@nineveh.lcs.mit.edu.LCS.MIT.EDU> Message-ID: <199511012031.PAA04571@monty> > There has been a small amount of talk about the possibilty of having > "boolean types" in addition to number, sequence, and mapping types that > would support >, <, ==, etc. After writing a lot of code with matrices, I > feel that many things could be expressed a lot more elegantly if this was > allowed. Unfortunately, Guido appears to be skeptical of this proposal, so > don't hold your breath. Couldn't this be done by implementing a "numeric" type (at the C level) that has a range of [0..1]? It could have two objects... Also, what exactly is the advantage of having a Boolean type? (Am I showing my age here? :-) Re a**b for pow(a, b): yes, that's also an acceptable addition. --Guido van Rossum URL: ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From jjh@mama-bear.lcs.mit.edu Wed Nov 1 21:02:31 1995 From: jjh@mama-bear.lcs.mit.edu (James Hugunin) Date: Wed, 1 Nov 95 16:02:31 -0500 Subject: [PYTHON MATRIX-SIG] Some notes on the matrix class References: <9511011856.AA29129@kristen.llnl.gov> <9511012028.AA00472@nineveh.lcs.mit.edu.LCS.MIT.EDU> <199511012031.PAA04571@monty> Message-ID: <9511012102.AA00485@nineveh.lcs.mit.edu.LCS.MIT.EDU> > Couldn't this be done by implementing a "numeric" type (at the C > level) that has a range of [0..1]? It could have two objects... > > Also, what exactly is the advantage of having a Boolean type? (Am I > showing my age here? :-) What I'm asking for is to be able to create a new python object in C, and to include boolean methods for that object. So, just like I can implement my matrix_add function for the syntax "a+b" when a and b are matrices (modulo coercion), I'd really like to be able to implement a matrix_greater function for the syntax "a>b" when a and b are matrices (still modulo coercion). This seems completely in the original spirit of the language. The reason for this is that if a = [1,2,3], and b = [2,2,2], I'd like to define a>b = [0,0,1]. (where all of the above are matrices). This is useful in an astounding range of matrix computations, and there is no sensible definition of a>b for matrices that returns a scalar boolean value. ie. the traditional discrete delta function is elegantly expressed as def delta(i): return i==0 delta([-2,-1,0,1,2,3,4]) -> [0,0,1,0,0,0,0] It's also useful for "vectorizing" traditional operations like filter. If x is a vector, filter(lambda x: x<2 and x>0, x) <--> x.filter(x<2 and x>0) except the second is orders of magnitude faster for matrices. I understand that this is a major change to some of the more complicated parts of python, so there are good practical reasons that it won't be done anytime soon. Nevertheless, I would love though to have you agree that this would be a good feature if somebody ever has the time to add it. -Jim ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From guido@CNRI.Reston.VA.US Wed Nov 1 21:08:06 1995 From: guido@CNRI.Reston.VA.US (Guido van Rossum) Date: Wed, 01 Nov 1995 16:08:06 -0500 Subject: [PYTHON MATRIX-SIG] Some notes on the matrix class In-Reply-To: Your message of "Wed, 01 Nov 1995 16:02:31 EST." <9511012102.AA00485@nineveh.lcs.mit.edu.LCS.MIT.EDU> References: <9511011856.AA29129@kristen.llnl.gov> <9511012028.AA00472@nineveh.lcs.mit.edu.LCS.MIT.EDU> <199511012031.PAA04571@monty> <9511012102.AA00485@nineveh.lcs.mit.edu.LCS.MIT.EDU> Message-ID: <199511012108.QAA06690@monty> > The reason for this is that if a = [1,2,3], and b = [2,2,2], I'd > like to define a>b = [0,0,1]. (where all of the above are > matrices). This is useful in an astounding range of matrix > computations, and there is no sensible definition of a>b for > matrices that returns a scalar boolean value. I see that I misunderstood your question. I'm not sure I like subsuming the ">" operator (and its companions "<", "<=" etc.) for this purpose. In Python it's quite common (well, at least it's possible) to use comparisons between objects of unknown type. If I write def spam(a, b): if a < b: ...do something... else: ...do something else... and a and b can be anything. If for certain types ab is true). Currently, it is not possible for comparisons to raise exceptions. This may change in the future, however, and then matrices (like complex numbers) should raise some exception to indicate that comparing them doesn't make. There is also the comparison chaining (a URL: ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From jfulton@usgs.gov Wed Nov 1 21:54:58 1995 From: jfulton@usgs.gov (Jim Fulton, U.S. Geological Survey) Date: Wed, 01 Nov 1995 16:54:58 -0500 Subject: [PYTHON MATRIX-SIG] Some notes on the matrix class In-Reply-To: <9511012102.AA00485@nineveh.lcs.mit.edu.LCS.MIT.EDU> Message-ID: <199511012149.VAA04206@qvarsx.er.usgs.GOV> On Wed, 1 Nov 95 16:02:31 -0500 James Hugunin said: > > > Couldn't this be done by implementing a "numeric" type (at the C > > level) that has a range of [0..1]? It could have two objects... > > > > Also, what exactly is the advantage of having a Boolean type? (Am I > > showing my age here? :-) > > What I'm asking for is to be able to create a new python object in C, and > to include boolean methods for that object. So, just like I can implement > my matrix_add function for the syntax "a+b" when a and b are matrices > (modulo coercion), I'd really like to be able to implement a matrix_greater > function for the syntax "a>b" when a and b are matrices (still modulo > coercion). This seems completely in the original spirit of the language. > > The reason for this is that if a = [1,2,3], and b = [2,2,2], I'd like to > define a>b = [0,0,1]. (where all of the above are matrices). This is > useful in an astounding range of matrix computations, and there is no > sensible definition of a>b for matrices that returns a scalar boolean value. > > > ie. the traditional discrete delta function is elegantly expressed as > def delta(i): return i==0 > > delta([-2,-1,0,1,2,3,4]) -> [0,0,1,0,0,0,0] > > It's also useful for "vectorizing" traditional operations like filter. If > x is a vector, > > filter(lambda x: x<2 and x>0, x) <--> x.filter(x<2 and x>0) > > except the second is orders of magnitude faster for matrices. > > I understand that this is a major change to some of the more complicated > parts of python, so there are good practical reasons that it won't be done > anytime soon. Nevertheless, I would love though to have you agree that this > would be a good feature if somebody ever has the time to add it. I think what you want to do is best done with a separate function. I'm against having comparison operators return non-boolean values. I think comparison operators should always either return boolean, or raise an exception if an operation is not supported. With your proposal, would [1,2,3]==[0,2,3] return [0,1,1]? Then you would lose the ability to say: "if a == b:" I'd much rather be able to say a particular type supports == and != and does not support <, <=, >, and >=. Jim ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From hinsenk@ere.umontreal.ca Thu Nov 2 14:33:16 1995 From: hinsenk@ere.umontreal.ca (Hinsen Konrad) Date: Thu, 2 Nov 1995 09:33:16 -0500 Subject: [PYTHON MATRIX-SIG] Who wants to test my complex number module? Message-ID: <199511021433.JAA13755@cyclone.ERE.UMontreal.CA> This does not directly relate to matrices, but I suppose that most of use are also interested in other numerical applications of Python. I have written a C module that implements complex numbers, including the standard arithmetic function, and another C module that is the analogue of math for complex numbers. Before releasing these to a larger public, I'd like some others to test them for a while. Any volunteers? The modules work with 1.2 as well as 1.3. ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hinsenk@ere.umontreal.ca Departement de chimie | Tel.: +1-514-343-6111 ext. 3953 Universite de Montreal | Fax: +1-514-343-7586 C.P. 6128, succ. Centre-Ville | Deutsch/Esperanto/English/Nederlands/ Montreal (QC) H3C 3J7 | Francais (phase experimentale) ------------------------------------------------------------------------------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From hinsenk@ere.umontreal.ca Thu Nov 2 14:46:55 1995 From: hinsenk@ere.umontreal.ca (Hinsen Konrad) Date: Thu, 2 Nov 1995 09:46:55 -0500 Subject: [PYTHON MATRIX-SIG] Some notes on the matrix class In-Reply-To: <9511011856.AA29129@kristen.llnl.gov> (dubois@kristen.llnl.gov) Message-ID: <199511021446.JAA14200@cyclone.ERE.UMontreal.CA> 2. ranf(m) fills m with uniform random numbers on (0.0, 1.0) I'd prefer a matrix constructor (similar to mrange) that creates a random matrix with a given shape. b. compress(condition, x) = those elements of x corresponding to those elements of condition that are "true". condition and x must have A useful generalization of this, especially since booleans are just integers in Python, would be a function that replicates each item of x n times, where n is the corresponding item in the "condition" argument. the same length (or x scalar), result is a one-dimensional vector with length equal to the number of true elements in condition. Naturally this Why should this be restricted to one-dimensional arguments? Of course the "condition" argument must be one-dimensional, but the compression (or copying, in the sense outlined above) can occur along any axis of a multidimensional array. is most useful if x < y returns a vector instead of a scalar. Indeed... c. My Basis users love: where(condition,x,y) is shaped like condition and has elements of x and y where condition is respectively true or false; we allow broadcast of If Python had a selection operator similar to C's ?:, this would be its generalization to array arguments. And in fact I'd love to have such an operator in Python in general... (That sound you hear is the shot of a large caliber weapon as Guido justifiably shoots a newbie for making a suggested language change before he can even use half the language yet; in fact, I'm tempted to shoot myself, but I'm enjoying Python too much to die yet.) It would be more in the spirit of Python to use poisonous snakes instead of guns ;-) ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hinsenk@ere.umontreal.ca Departement de chimie | Tel.: +1-514-343-6111 ext. 3953 Universite de Montreal | Fax: +1-514-343-7586 C.P. 6128, succ. Centre-Ville | Deutsch/Esperanto/English/Nederlands/ Montreal (QC) H3C 3J7 | Francais (phase experimentale) ------------------------------------------------------------------------------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From hinsenk@ere.umontreal.ca Thu Nov 2 15:10:08 1995 From: hinsenk@ere.umontreal.ca (Hinsen Konrad) Date: Thu, 2 Nov 1995 10:10:08 -0500 Subject: [PYTHON MATRIX-SIG] Some notes on the matrix class In-Reply-To: <9511012028.AA00472@nineveh.lcs.mit.edu.LCS.MIT.EDU> (message from James Hugunin on Wed, 1 Nov 95 15:28:58 -0500) Message-ID: <199511021510.KAA15138@cyclone.ERE.UMontreal.CA> random numbers so is slow. If somebody with a good random number generator in C would like to add this to matrixmodule.c as a new instantiation method in C, I'd use it. There is no shortage of random number generators in C, although I can't find one right now on my disk... (I also added a concat method noticing that I was missing this other functionality of lists). Good. I was just about to ask for it... There has been a small amount of talk about the possibilty of having "boolean types" in addition to number, sequence, and mapping types that I don't see the advantage in a language like Python. In a type-checked compiled language, a boolean type makes sense, but in Python integers are just as good and even more useful since you can use the results of logical operations in arithmetic expressions. On the other hand, I agree it would be nice (*very* nice) to be able to define comparison operators that return matrix objects... You raise another interesting issue here that I've completely ignored in the matrix object so far. Numeric exceptions are not handled at all; in return, matrix math executes at the speed of compiled code. However, it I must say that I am not entirely happy with the fact tht Python uses exceptions for floating point operations at all. In terms of speed and versatility, I prefer to have IEEE-style operations that simply return NaN or one of the infinities as the result of an "impossible" operation. Of course there should be functions to check for these special results. Such a strategy would be easily generalizable to matrices, and on systems with IEEE implementations in hardware (practically all computers on the market now) it would not cause any speed penalty. rummaging around in Grammer and compile.c, Guido also mentioned that he'd be willing to let a**b <--> pow(a, b) into the syntax. This also seems like an easy hack for someone with the right know-how, and would be a nice bonus for numerical code. I'd love that. And once we are discussing syntax, I'd also love to have a concise input notation for complex numbers... ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hinsenk@ere.umontreal.ca Departement de chimie | Tel.: +1-514-343-6111 ext. 3953 Universite de Montreal | Fax: +1-514-343-7586 C.P. 6128, succ. Centre-Ville | Deutsch/Esperanto/English/Nederlands/ Montreal (QC) H3C 3J7 | Francais (phase experimentale) ------------------------------------------------------------------------------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From hinsenk@ere.umontreal.ca Thu Nov 2 15:27:10 1995 From: hinsenk@ere.umontreal.ca (Hinsen Konrad) Date: Thu, 2 Nov 1995 10:27:10 -0500 Subject: [PYTHON MATRIX-SIG] Some notes on the matrix class In-Reply-To: <199511012108.QAA06690@monty> (message from Guido van Rossum on Wed, 01 Nov 1995 16:08:06 -0500) Message-ID: <199511021527.KAA15740@cyclone.ERE.UMontreal.CA> You can always define methods equal, greater and less, where a.greater(b) = [0,0,1] in your example. But more complicated logical expressions with such a syntax become impossible to read. In fact, I'd rather write a comparison using map() and a lambda form if it weren't so inefficient. The current state of comparisons in Python is extremely dangerous, because comparisons always succeed even if they don't make any sense. The worst consequence is that max() and min() always return a result of the expected type, but which is usually not what the user thinks it is. A perfect source for hard-to-find user errors. Of course that could be fixed by just disallowing comparisons of non-comparable objects, which however still does not solve the matrix comparison problem. Just an unfinished idea: would it be possible to construct a "matrix expression evaluator" similar in syntax to map(), but efficient? ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hinsenk@ere.umontreal.ca Departement de chimie | Tel.: +1-514-343-6111 ext. 3953 Universite de Montreal | Fax: +1-514-343-7586 C.P. 6128, succ. Centre-Ville | Deutsch/Esperanto/English/Nederlands/ Montreal (QC) H3C 3J7 | Francais (phase experimentale) ------------------------------------------------------------------------------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From friedric@rose.rsoc.rockwell.com Thu Nov 2 16:14:05 1995 From: friedric@rose.rsoc.rockwell.com (Robin Friedrich) Date: Thu, 2 Nov 1995 10:14:05 -0600 Subject: [PYTHON MATRIX-SIG] Some notes on the matrix class Message-ID: <9511021614.AA23987@darwin.rsoc.rockwell.com> > From: hinsenk@ere.umontreal.ca (Hinsen Konrad) |> It would be more in the spirit of Python to use poisonous snakes instead |> of guns ;-) A 16-ton weight actually. (sorry for the noise but this list has way too much signal!) keep up the good work. ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From dubois@kristen.llnl.gov Thu Nov 2 01:57:44 1995 From: dubois@kristen.llnl.gov (P. Dubois) Date: Thu, 2 Nov 1995 09:57:44 +0800 Subject: [PYTHON MATRIX-SIG] floating point handling In-Reply-To: <199511021510.KAA15138@cyclone.ERE.UMontreal.CA> (hinsenk@ere.umontreal.ca) Message-ID: <9511021757.AA03825@kristen.llnl.gov> (1) I disagree with Konrad's remarks on floating point. I know of no production code that allows the generation of NaNs or any of the other IEEE nonsense. If such a thing occurs in one of our codes it is an error and we need to hear about it immediately. Knowing *where* the problem first occurred is crucial. We use whatever facilities are provided on a given platform (and sometimes there aren't any) to make sure that: a. Any floating point problems signal FPE (which we then catch), except: b. Fast-underflow-to-zero is turned on (Can make a real speed difference: if you don't do something about it, underflows result in system calls.) There is no standardization in this area. (2) I will supply a module that is equivalent to the Cray random number generator. Stand by. ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From P.S.Craig@durham.ac.uk Fri Nov 3 09:38:16 1995 From: P.S.Craig@durham.ac.uk (P.S.Craig@durham.ac.uk) Date: Fri, 3 Nov 1995 09:38:16 +0000 (GMT) Subject: [PYTHON MATRIX-SIG] floating point handling In-Reply-To: <9511021757.AA03825@kristen.llnl.gov> from "P. Dubois" at Nov 2, 95 09:57:44 am Message-ID: <26057.9511030939@markov> P. Dubois writes: > > > (1) I disagree with Konrad's remarks on floating point. > > I know of no production code that allows the generation of NaNs or any > of the other IEEE nonsense. If such a thing occurs in one of our codes > it is an error and we need to hear about it immediately. Knowing *where* > the problem first occurred is crucial. > This is getting a bit silly. Whether the IEEE `nonsense' is appropriate or not is context dependent. I make heavy use of S-Plus (a statistics package with some APL like matrix addressing) and Matlab (a widely used matrix arithmetic package with many practical applications). Both of these return Inf for 1/0 and Nan for 0/0 and I don't think they have to generate exceptions to do it. It seems quite sensible to me that python should allow both modes of operation, i.e. IEEE extended arithmetic or exceptions. And if that means significant changes to the base language, I have to apologise to Guido for creating work. The problem for me is that python is a much better programming language than S-Plus or Matlab but that I need this matrix/tensor class to be as like them as possible before I switch to using it instead of them for my research. Cheers, Peter Craig ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From guido@CNRI.Reston.VA.US Fri Nov 3 13:20:58 1995 From: guido@CNRI.Reston.VA.US (Guido van Rossum) Date: Fri, 03 Nov 1995 08:20:58 -0500 Subject: [PYTHON MATRIX-SIG] floating point handling In-Reply-To: Your message of "Fri, 03 Nov 1995 09:38:16 GMT." <26057.9511030939@markov> References: <26057.9511030939@markov> Message-ID: <199511031320.IAA16812@monty> > It seems quite sensible to me that python should allow both modes of > operation, i.e. IEEE extended arithmetic or exceptions. And if that > means significant changes to the base language, I have to apologise to > Guido for creating work. The problem for me is that python is a much > better programming language than S-Plus or Matlab but that I need this > matrix/tensor class to be as like them as possible before I switch to > using it instead of them for my research. If you insist on having "Inf" for infinity and "NaN" for 1/0, all you probably need to do is hack the floatobject.c module a wee bit, to include representations for them and to return them in appropriate cases. I don't mind work but I have about 1,000,000 different projects to attend to (two of them are due today :-) and things go faster if people contribute patches instead of requesating changes. (Not that a contributed patch will automatically end up in the language -- that depends on the quality of the code and how well your feel for what's "right" in Python agrees with mine...) --Guido van Rossum URL: ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From hinsenk@ere.umontreal.ca Fri Nov 3 14:59:13 1995 From: hinsenk@ere.umontreal.ca (Hinsen Konrad) Date: Fri, 3 Nov 1995 09:59:13 -0500 Subject: [PYTHON MATRIX-SIG] floating point handling In-Reply-To: <199511031320.IAA16812@monty> (message from Guido van Rossum on Fri, 03 Nov 1995 08:20:58 -0500) Message-ID: <199511031459.JAA18261@cyclone.ERE.UMontreal.CA> If you insist on having "Inf" for infinity and "NaN" for 1/0, all you probably need to do is hack the floatobject.c module a wee bit, to include representations for them and to return them in appropriate Indeed I don't think this is much work, having looked at the float implementation quite a bit before writing the complex module. But obviously there must be a way to enable or disable floating point exceptions (I thing everyone agrees they are useful). I am not quite sure what the appropriate way to do that would be - a variable in the sys module would be nice, but probably expensive to check after each float operation. A function with a boolean argument that sets a C variable might be better. Or maybe there is a better way that I just can't think of... The same flag could then be used in the complex and matrix modules. ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hinsenk@ere.umontreal.ca Departement de chimie | Tel.: +1-514-343-6111 ext. 3953 Universite de Montreal | Fax: +1-514-343-7586 C.P. 6128, succ. Centre-Ville | Deutsch/Esperanto/English/Nederlands/ Montreal (QC) H3C 3J7 | Francais (phase experimentale) ------------------------------------------------------------------------------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From guido@CNRI.Reston.VA.US Fri Nov 3 15:08:39 1995 From: guido@CNRI.Reston.VA.US (Guido van Rossum) Date: Fri, 03 Nov 1995 10:08:39 -0500 Subject: [PYTHON MATRIX-SIG] floating point handling In-Reply-To: Your message of "Fri, 03 Nov 1995 09:59:13 EST." <199511031459.JAA18261@cyclone.ERE.UMontreal.CA> References: <199511031459.JAA18261@cyclone.ERE.UMontreal.CA> Message-ID: <199511031508.KAA17260@monty> > If you insist on having "Inf" for infinity and "NaN" for 1/0, all you > probably need to do is hack the floatobject.c module a wee bit, to > include representations for them and to return them in appropriate > > Indeed I don't think this is much work, having looked at the float > implementation quite a bit before writing the complex module. But > obviously there must be a way to enable or disable floating point > exceptions (I thing everyone agrees they are useful). I am not quite > sure what the appropriate way to do that would be - a variable in the > sys module would be nice, but probably expensive to check after each > float operation. A function with a boolean argument that sets a C > variable might be better. Or maybe there is a better way that I just > can't think of... The same flag could then be used in the complex and > matrix modules. Hmm... Globals that affect the behavior of low-level objects are rarely a good idea. For instance, some non-compute-intensive module may be using floats and expecting exceptions -- it will break if it is used in your program that turns off exceptions... How about introducing a new type, say ieeefloat, with the desired behavior? Its casting behavior could easily be designed to force mixed-mode arithmetic (between standard and ieee floats) to be done in ieee mode. --Guido van Rossum URL: ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From jjh@mama-bear.lcs.mit.edu Fri Nov 3 15:37:02 1995 From: jjh@mama-bear.lcs.mit.edu (James Hugunin) Date: Fri, 3 Nov 95 10:37:02 -0500 Subject: [PYTHON MATRIX-SIG] IEEE exceptions, casting, matrix multiplies, and default types References: <199511031459.JAA18261@cyclone.ERE.UMontreal.CA> Message-ID: <9511031537.AA03746@nineveh.lcs.mit.edu.LCS.MIT.EDU> I'd like to generalize this discussion a little bit. I've noticed four areas where the easiest solution would be to add a user-settable global variable to indicate a "desired" mode, yet I agree with Guido that as a general rule this is an extremely bad idea. 1) 1/0. returns Inf or raises exception [Note: Matrix_i creates a matrix of ints, Matrix_d creates one of doubles] 2) Matrix_i(1,2,3) * Matrix_d(1.,2.,3.) == Matrix_d(1.,4.,6.) or raises exception 3) a * b is element-wise or is linear algebra style multiply 4) add([1,2,3], [4,5,6]) == Matrix_?(5,7,9) where the question is what the ? should be. I'm busy this morning getting the 0.11 release of the matrixobject together, so I don't have time for much more comment, I just wanted to point out that this is a very general question (in particular when thinking about matrices), and if we're really lucky there might be a nice general purpose answer. -Jim ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From hinsenk@ere.umontreal.ca Fri Nov 3 17:00:14 1995 From: hinsenk@ere.umontreal.ca (Hinsen Konrad) Date: Fri, 3 Nov 1995 12:00:14 -0500 Subject: [PYTHON MATRIX-SIG] floating point handling In-Reply-To: <199511031508.KAA17260@monty> (message from Guido van Rossum on Fri, 03 Nov 1995 10:08:39 -0500) Message-ID: <199511031700.MAA25356@cyclone.ERE.UMontreal.CA> Hmm... Globals that affect the behavior of low-level objects are rarely a good idea. For instance, some non-compute-intensive module may be using floats and expecting exceptions -- it will break if it is used in your program that turns off exceptions... That's indeed a problem. In fact this is a well-known problem for APL users, since APL has a range of global variables that affect the meaning of all functions (i.e. the index origin can be set to zero or one). The solution that APL offers is that these variables can be made local and thereby changed for an individual function, but that is far from an ideal solution. How about introducing a new type, say ieeefloat, with the desired behavior? Its casting behavior could easily be designed to force mixed-mode arithmetic (between standard and ieee floats) to be done in ieee mode. I am sure two float types would create quite a bit of confusion for users, especially those who don't care about error handling and don't even want to understand the difference. For example, there would have to be two different input and output notations to make clear which version is used. ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hinsenk@ere.umontreal.ca Departement de chimie | Tel.: +1-514-343-6111 ext. 3953 Universite de Montreal | Fax: +1-514-343-7586 C.P. 6128, succ. Centre-Ville | Deutsch/Esperanto/English/Nederlands/ Montreal (QC) H3C 3J7 | Francais (phase experimentale) ------------------------------------------------------------------------------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From dubois@kristen.llnl.gov Fri Nov 3 01:42:46 1995 From: dubois@kristen.llnl.gov (P. Dubois) Date: Fri, 3 Nov 1995 09:42:46 +0800 Subject: [PYTHON MATRIX-SIG] Who wants to test my complex number module? In-Reply-To: <199511031505.KAA18617@cyclone.ERE.UMontreal.CA> (hinsenk@ERE.UMontreal.CA) Message-ID: <9511031742.AA09062@kristen.llnl.gov> (This is the middle of a conversation about the complex module that Hinsen has developed, but some issues I wanted to mention to everyone). a. It is a surprising thing (to me) that while tan is in the Fortran standard, cot isn't. We put one in Basis because it drove us crazy. b. The conjugation function in Fortran is called conjg, not conj. We probably should have a functional equivalent, too, conjg(c). Actually, the conjugate not really an attribute of the object, it is a transform, and so I'd rather see a method which conjugates the given object and a conjg(c) which returns copy(c).conjg(). c. However, that leads us to the whole discussion of naming. I think if you read "Reusable Software" by Bertrand Meyer, and have some experience with constructing large scale reusable component libraries (which is what Python is generating on a frightening scale) it turns out that a consistent naming convention is very, very important. Some of the lessons the Eiffel community has learned are: 1. Abbreviations should be avoided. Basically, if you don't abbreviate you can't forget which abbreviation to use. So in the immediate case, I would favor conjugate rather than conjg. This tends to be against the traditions in a rapid prototyping language but the components we are building aren't the rapid prototype they are elements of the reusable software library. (Although, you can make a case that conjg isn't an abbreviation, it is the Fortran name which everyone knows!) 2. It is more important for the names to be consistent than traditional. For example, the size of an object like a list, stack, or queue is invariably called count, and the operation to place an element at a certain position is put. In stacks, put might more traditionally be called "push" and the top item "top" or "first" but an Eiffel user will know without looking that the top item is going to be called "item", as is the current item in a list. Fortunately, Python's name scoping mitigates quite a bit of the worry about name clashes, but the problem of a user learning a large body of components is still there. d. In the matrix class, one ought to worry about putting a name like "pp". Not only are some users going to accidentally call one of their variables pp, when you read it you haven't a clue what it is. PrintMatrix ? (Unless, has pp become a standard Python abbreviation for PrettyPrint?) e. About the printed representation of a complex: shouldn't it be complex(1.0, 1.1) not 1j1.1 ? There are two components to this thought. One is that the two parts should be presented with equal precision. Second is that it might come in handy if the printed form was readable back into Python, and there seems to be some "tradition" of this sort of convention in Python components already. The Fortran representation for code literals is (1.0, 1.1) which is also suggestive. f. Note to ourselves: the printing of large matrices needs to be more orderly and labeled. An example follows from Basis. Note the control variable available to change the printing precision on a "class-wide" basis. kristen[51] basis Basis (basis, Version 951101) Run at 09:20:46 on 11/03/95 on the sun4m machine, suffix 8544x Initializing Basis System Basis 11.0 Initializing 3-D Surface Plotting Routine Initializing 3-D Isosurface Plotting Routine Initializing Device Package EZD Graphics Devices 3.4 NCAR Initializing EZCURVE/NCAR Graphics EZN Graphics Interface Version 5.5 Initializing Singular Value Decomposition Initializing Polynomial Fitting Initializing PFB Interface PFB 4.1 Basis> real x = ones(5, 20) Basis> x x shape: (5,20) row col = 1 2 3 4 1: 1.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 2: 0.00000E+00 1.00000E+00 0.00000E+00 0.00000E+00 3: 0.00000E+00 0.00000E+00 1.00000E+00 0.00000E+00 4: 0.00000E+00 0.00000E+00 0.00000E+00 1.00000E+00 5: 0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 row col = 5 6 7 8 1: 0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 2: 0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 3: 0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 4: 0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 5: 1.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 row col = 9 10 11 12 1: 0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 2: 0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 3: 0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 4: 0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 5: 0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 row col = 13 14 15 16 1: 0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 2: 0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 3: 0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 4: 0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 5: 0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 row col = 17 18 19 20 1: 0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 2: 0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 3: 0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 4: 0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 5: 0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 Basis> [x, x+2.] [x,x+2.] shape: (5,20,2) Number of dimensions: 3, lengths: 5 20 2 INDEX(row,col,1) row col = 1 2 3 4 1: 1.00000D+00 0.00000D+00 0.00000D+00 0.00000D+00 2: 0.00000D+00 1.00000D+00 0.00000D+00 0.00000D+00 3: 0.00000D+00 0.00000D+00 1.00000D+00 0.00000D+00 4: 0.00000D+00 0.00000D+00 0.00000D+00 1.00000D+00 5: 0.00000D+00 0.00000D+00 0.00000D+00 0.00000D+00 row col = 5 6 7 8 1: 0.00000D+00 0.00000D+00 0.00000D+00 0.00000D+00 2: 0.00000D+00 0.00000D+00 0.00000D+00 0.00000D+00 3: 0.00000D+00 0.00000D+00 0.00000D+00 0.00000D+00 4: 0.00000D+00 0.00000D+00 0.00000D+00 0.00000D+00 5: 1.00000D+00 0.00000D+00 0.00000D+00 0.00000D+00 row col = 9 10 11 12 1: 0.00000D+00 0.00000D+00 0.00000D+00 0.00000D+00 2: 0.00000D+00 0.00000D+00 0.00000D+00 0.00000D+00 3: 0.00000D+00 0.00000D+00 0.00000D+00 0.00000D+00 4: 0.00000D+00 0.00000D+00 0.00000D+00 0.00000D+00 5: 0.00000D+00 0.00000D+00 0.00000D+00 0.00000D+00 row col = 13 14 15 16 1: 0.00000D+00 0.00000D+00 0.00000D+00 0.00000D+00 2: 0.00000D+00 0.00000D+00 0.00000D+00 0.00000D+00 3: 0.00000D+00 0.00000D+00 0.00000D+00 0.00000D+00 4: 0.00000D+00 0.00000D+00 0.00000D+00 0.00000D+00 5: 0.00000D+00 0.00000D+00 0.00000D+00 0.00000D+00 row col = 17 18 19 20 1: 0.00000D+00 0.00000D+00 0.00000D+00 0.00000D+00 2: 0.00000D+00 0.00000D+00 0.00000D+00 0.00000D+00 3: 0.00000D+00 0.00000D+00 0.00000D+00 0.00000D+00 4: 0.00000D+00 0.00000D+00 0.00000D+00 0.00000D+00 5: 0.00000D+00 0.00000D+00 0.00000D+00 0.00000D+00 INDEX(row,col,2) row col = 1 2 3 4 1: 3.00000D+00 2.00000D+00 2.00000D+00 2.00000D+00 2: 2.00000D+00 3.00000D+00 2.00000D+00 2.00000D+00 3: 2.00000D+00 2.00000D+00 3.00000D+00 2.00000D+00 4: 2.00000D+00 2.00000D+00 2.00000D+00 3.00000D+00 5: 2.00000D+00 2.00000D+00 2.00000D+00 2.00000D+00 row col = 5 6 7 8 1: 2.00000D+00 2.00000D+00 2.00000D+00 2.00000D+00 2: 2.00000D+00 2.00000D+00 2.00000D+00 2.00000D+00 3: 2.00000D+00 2.00000D+00 2.00000D+00 2.00000D+00 4: 2.00000D+00 2.00000D+00 2.00000D+00 2.00000D+00 5: 3.00000D+00 2.00000D+00 2.00000D+00 2.00000D+00 row col = 9 10 11 12 1: 2.00000D+00 2.00000D+00 2.00000D+00 2.00000D+00 2: 2.00000D+00 2.00000D+00 2.00000D+00 2.00000D+00 3: 2.00000D+00 2.00000D+00 2.00000D+00 2.00000D+00 4: 2.00000D+00 2.00000D+00 2.00000D+00 2.00000D+00 5: 2.00000D+00 2.00000D+00 2.00000D+00 2.00000D+00 row col = 13 14 15 16 1: 2.00000D+00 2.00000D+00 2.00000D+00 2.00000D+00 2: 2.00000D+00 2.00000D+00 2.00000D+00 2.00000D+00 3: 2.00000D+00 2.00000D+00 2.00000D+00 2.00000D+00 4: 2.00000D+00 2.00000D+00 2.00000D+00 2.00000D+00 5: 2.00000D+00 2.00000D+00 2.00000D+00 2.00000D+00 row col = 17 18 19 20 1: 2.00000D+00 2.00000D+00 2.00000D+00 2.00000D+00 2: 2.00000D+00 2.00000D+00 2.00000D+00 2.00000D+00 3: 2.00000D+00 2.00000D+00 2.00000D+00 2.00000D+00 4: 2.00000D+00 2.00000D+00 2.00000D+00 2.00000D+00 5: 2.00000D+00 2.00000D+00 2.00000D+00 2.00000D+00 ================================================ Basis> fuzz=14; x x shape: (5,20) row col = 1 2 1: 1.00000000000000E+00 0.00000000000000E+00 2: 0.00000000000000E+00 1.00000000000000E+00 3: 0.00000000000000E+00 0.00000000000000E+00 4: 0.00000000000000E+00 0.00000000000000E+00 5: 0.00000000000000E+00 0.00000000000000E+00 row col = 3 4 1: 0.00000000000000E+00 0.00000000000000E+00 2: 0.00000000000000E+00 0.00000000000000E+00 3: 1.00000000000000E+00 0.00000000000000E+00 4: 0.00000000000000E+00 1.00000000000000E+00 5: 0.00000000000000E+00 0.00000000000000E+00 row col = 5 6 1: 0.00000000000000E+00 0.00000000000000E+00 2: 0.00000000000000E+00 0.00000000000000E+00 3: 0.00000000000000E+00 0.00000000000000E+00 4: 0.00000000000000E+00 0.00000000000000E+00 5: 1.00000000000000E+00 0.00000000000000E+00 row col = 7 8 1: 0.00000000000000E+00 0.00000000000000E+00 2: 0.00000000000000E+00 0.00000000000000E+00 3: 0.00000000000000E+00 0.00000000000000E+00 4: 0.00000000000000E+00 0.00000000000000E+00 5: 0.00000000000000E+00 0.00000000000000E+00 row col = 9 10 1: 0.00000000000000E+00 0.00000000000000E+00 2: 0.00000000000000E+00 0.00000000000000E+00 3: 0.00000000000000E+00 0.00000000000000E+00 4: 0.00000000000000E+00 0.00000000000000E+00 5: 0.00000000000000E+00 0.00000000000000E+00 row col = 11 12 1: 0.00000000000000E+00 0.00000000000000E+00 2: 0.00000000000000E+00 0.00000000000000E+00 3: 0.00000000000000E+00 0.00000000000000E+00 4: 0.00000000000000E+00 0.00000000000000E+00 5: 0.00000000000000E+00 0.00000000000000E+00 row col = 13 14 1: 0.00000000000000E+00 0.00000000000000E+00 2: 0.00000000000000E+00 0.00000000000000E+00 3: 0.00000000000000E+00 0.00000000000000E+00 4: 0.00000000000000E+00 0.00000000000000E+00 5: 0.00000000000000E+00 0.00000000000000E+00 row col = 15 16 1: 0.00000000000000E+00 0.00000000000000E+00 2: 0.00000000000000E+00 0.00000000000000E+00 3: 0.00000000000000E+00 0.00000000000000E+00 4: 0.00000000000000E+00 0.00000000000000E+00 5: 0.00000000000000E+00 0.00000000000000E+00 row col = 17 18 1: 0.00000000000000E+00 0.00000000000000E+00 2: 0.00000000000000E+00 0.00000000000000E+00 3: 0.00000000000000E+00 0.00000000000000E+00 4: 0.00000000000000E+00 0.00000000000000E+00 5: 0.00000000000000E+00 0.00000000000000E+00 row col = 19 20 1: 0.00000000000000E+00 0.00000000000000E+00 2: 0.00000000000000E+00 0.00000000000000E+00 3: 0.00000000000000E+00 0.00000000000000E+00 4: 0.00000000000000E+00 0.00000000000000E+00 5: 0.00000000000000E+00 0.00000000000000E+00 "Compression" is also useful, can be turned off by user: Basis> real x= [1.,2.,3] // ones(1000) Basis> x x shape: (1003) 1: 1.00000000000000E+00 2.00000000000000E+00 3: 3.00000000000000E+00 1.00000000000000E+00 5:1000 1.00000000000000E+00 1.00000000000000E+00 1001: 1.00000000000000E+00 1.00000000000000E+00 1003: 1.00000000000000E+00 Basis> [x,x/2.] [x,x/2.] shape: (1003,2) row col = 1 2 1: 1.00000000000000D+00 5.00000000000000D-01 2: 2.00000000000000D+00 1.00000000000000D+00 3: 3.00000000000000D+00 1.50000000000000D+00 4:1003 1.00000000000000D+00 5.00000000000000D-01 Basis> ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From jjh@mama-bear.lcs.mit.edu Fri Nov 3 18:07:04 1995 From: jjh@mama-bear.lcs.mit.edu (James Hugunin) Date: Fri, 3 Nov 95 13:07:04 -0500 Subject: [PYTHON MATRIX-SIG] Naming conventions References: <9511031742.AA09062@kristen.llnl.gov> Message-ID: <9511031807.AA08561@nineveh.lcs.mit.edu.LCS.MIT.EDU> > a. It is a surprising thing (to me) that while tan is in the Fortran standard, > cot isn't. We put one in Basis because it drove us crazy. I completely agree that we should expand upon the basic mathematical functions, not feeling limited by the current math.h C-library. > c. However, that leads us to the whole discussion of naming. I think if > you read "Reusable Software" by Bertrand Meyer, and have some experience > with constructing large scale reusable component libraries (which is > what Python is generating on a frightening scale) it turns out that > a consistent naming convention is very, very important. Some of the > lessons the Eiffel community has learned are: > > 1. Abbreviations should be avoided. Basically, if you don't abbreviate > you can't forget which abbreviation to use. So in the immediate case, > I would favor conjugate rather than conjg. This tends to be against > the traditions in a rapid prototyping language but the components > we are building aren't the rapid prototype they are elements of > the reusable software library. (Although, you can make a case that > conjg isn't an abbreviation, it is the Fortran name which everyone > knows!) As somebody who hates FORTRAN, I'd really like to argue strongly against assuming that everybody knows a FORTRAN name. I'd like to second your motion for "conjugate". I've been trying to follow exactly the convention that you mention for naming my basic ofuncs, thus I have "multiply", "divide", "leftShift", "andBoolean", "andLogical", and even things like "absolute", and "power" though I can see arguments for "pow" and "abs". > e. About the printed representation of a complex: shouldn't it be > complex(1.0, 1.1) not 1j1.1 ? There are two components to this thought. > One is that the two parts should be presented with equal precision. > Second is that it might come in handy if the printed form was readable > back into Python, and there seems to be some "tradition" of this sort > of convention in Python components already. The Fortran representation > for code literals is (1.0, 1.1) which is also suggestive. I believe that what's going on here is that Konrad is hoping that something like 1.0j1.0 (note the reasonable precision) will become acceptable as an input form to python for creating complex numbers. I know that printing out a matrix that has a lot of complex(1.0, 1.0) entries is hideous, so I'm in favor of this idea. > d. In the matrix class, one ought to worry about putting a name like > "pp". Not only are some users going to accidentally call one of their > variables pp, when you read it you haven't a clue what it is. > PrintMatrix ? (Unless, has pp become a standard Python abbreviation for > PrettyPrint?) > f. Note to ourselves: the printing of large matrices needs to be more > orderly and labeled. I agree, pp is hideous. It was only a hack so that I could easily write sample code and have the matrices printed out looking half-way decent. The whole issue of printing matrices needs to be addressed. One part of this issue is the desire that the basic printed representation of an object should correspond to a command that could be used to recreate that object, on the other hand, the well-labeled format you show from BASIS is generally what a user wants to see. I'm ambivalent on this issue. If somebody gives me a good routine for printing a matrix I'd love to add it to my code. -Jim ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From hinsenk@ere.umontreal.ca Fri Nov 3 18:54:51 1995 From: hinsenk@ere.umontreal.ca (Hinsen Konrad) Date: Fri, 3 Nov 1995 13:54:51 -0500 Subject: [PYTHON MATRIX-SIG] Who wants to test my complex number module? In-Reply-To: <9511031742.AA09062@kristen.llnl.gov> (dubois@kristen.llnl.gov) Message-ID: <199511031854.NAA02955@cyclone.ERE.UMontreal.CA> a. It is a surprising thing (to me) that while tan is in the Fortran standard, cot isn't. We put one in Basis because it drove us crazy. I haven't ever had a pressing need for cot(), but since it costs virtually nothing to add such simple functions, there is little reason not to do so. I already added the inverse hyperbolic functions to my cmath module, because it seemed silly not to have them. I am perfectly willing to add more functions, also to the float math module. This leads to the question of what functions would be desirable. In addition to the full set of angular functions, I'd like to see the error function and the gamma function. Anything else? b. The conjugation function in Fortran is called conjg, not conj. We probably should have a functional equivalent, too, conjg(c). Actually, the conjugate not really an attribute of the object, it is a transform, and so I'd rather see a method which conjugates the given object and a conjg(c) which returns copy(c).conjg(). I had already expected that objection. In fact the only reason why I implemented conjugation as an attribute (which indeed it should not be) is that I didn't want to add functions to the complex module. I envisioned that maybe one day one could make complex numbers a standard part of Python, like floats, with their proper input notation, and then there would be no more complex module. It could be put into cmath, but it doesn't really belong there. I am open to any suggestion on where to put this function... 1. Abbreviations should be avoided. Basically, if you don't abbreviate you can't forget which abbreviation to use. So in the immediate case, That is also the position of Mathematica, and it works well in practice. The only "safe" abbreviations are those long established in mathematical notation, like "sin" or "log". On the other hand, does anyone really want SquareRoot()? Even Mathematica uses Sqrt[]. I think one needs a certain (very small) set of accepted abbreviations. The point is not just ease of typing, but also keeping moderately complex expressions short enough to be legible. the reusable software library. (Although, you can make a case that conjg isn't an abbreviation, it is the Fortran name which everyone knows!) I'd rather not make the assumption that everyone knows Fortran! In fact, I'd be happy if I could one day forget Fortran. e. About the printed representation of a complex: shouldn't it be complex(1.0, 1.1) not 1j1.1 ? There are two components to this thought. For my taste complex(1.0,1.1) is too long, especially in matrices. One is that the two parts should be presented with equal precision. Why? I find 3.1415926j0 much nicer than 3.1415926j0.0000000 (and shorter too). Second is that it might come in handy if the printed form was readable back into Python, and there seems to be some "tradition" of this sort Of course. My hope is that the output notation I use (which by the way is stolen from APL2 and J) could become the accepted input notation one day. of convention in Python components already. The Fortran representation for code literals is (1.0, 1.1) which is also suggestive. But it can never become an input notation, since (1.0, 1.1) is read as a tuple in Python. Even for output only it would be confusing. For flexible output, there should be some kind of formatting option, as it exists for floating point numbers. But that can't be implemented in a module, so it doesn't exist for now. f. Note to ourselves: the printing of large matrices needs to be more orderly and labeled. Definitely. Again APL is a good example to copy. Basis> real x = ones(5, 20) Basis> x x shape: (5,20) row col = 1 2 3 4 1: 1.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 2: 0.00000E+00 1.00000E+00 0.00000E+00 0.00000E+00 3: 0.00000E+00 0.00000E+00 1.00000E+00 0.00000E+00 4: 0.00000E+00 0.00000E+00 0.00000E+00 1.00000E+00 5: 0.00000E+00 0.00000E+00 0.00000E+00 0.00000E+00 ... I am not sure I'd like this to be the default output format. The labels are nice for big matrices, but for small matrices I'd prefer just the elements. Also, I'd prefer non-exponential notations as long as it is reasonable for all elements (as in this case). APL systems tend to choose the optimal output format based on many properties of the matrix, and I have really come to appreciate that. Unfortunately, J doesn't follow this tradition. ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hinsenk@ere.umontreal.ca Departement de chimie | Tel.: +1-514-343-6111 ext. 3953 Universite de Montreal | Fax: +1-514-343-7586 C.P. 6128, succ. Centre-Ville | Deutsch/Esperanto/English/Nederlands/ Montreal (QC) H3C 3J7 | Francais (phase experimentale) ------------------------------------------------------------------------------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From hinsenk@ere.umontreal.ca Fri Nov 3 19:02:33 1995 From: hinsenk@ere.umontreal.ca (Hinsen Konrad) Date: Fri, 3 Nov 1995 14:02:33 -0500 Subject: [PYTHON MATRIX-SIG] Naming conventions In-Reply-To: <9511031807.AA08561@nineveh.lcs.mit.edu.LCS.MIT.EDU> (message from James Hugunin on Fri, 3 Nov 95 13:07:04 -0500) Message-ID: <199511031902.OAA03346@cyclone.ERE.UMontreal.CA> whole issue of printing matrices needs to be addressed. One part of this issue is the desire that the basic printed representation of an object should correspond to a command that could be used to recreate that object, on the other hand, the well-labeled format you show from BASIS is generally what a user wants to see. I'm ambivalent on this issue. If somebody gives Python has repr() and str(), so we can have both. My suggestion is an input-like notation for repr(), and a human-readable one for str() and therefore print. The fact is that for matrices it doesn't make sense to use the same format for input and output. Matrix constants will only be used for small matrices, and they must consist of some linear arrangement. But much larger matrices will be generated by other means, and they have to be printed in a readable way. ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hinsenk@ere.umontreal.ca Departement de chimie | Tel.: +1-514-343-6111 ext. 3953 Universite de Montreal | Fax: +1-514-343-7586 C.P. 6128, succ. Centre-Ville | Deutsch/Esperanto/English/Nederlands/ Montreal (QC) H3C 3J7 | Francais (phase experimentale) ------------------------------------------------------------------------------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From dubois@kristen.llnl.gov Fri Nov 3 03:49:54 1995 From: dubois@kristen.llnl.gov (P. Dubois) Date: Fri, 3 Nov 1995 11:49:54 +0800 Subject: [PYTHON MATRIX-SIG] printing complexes Message-ID: <9511031949.AA13959@kristen.llnl.gov> That was an excellent point you just made about str() and repr(). I think. I'm so new to Python I'm not sure which is which (:-> The reason I was worried about the precision being the same on the two sides (and controllable) is simply the issue of making nice output where you want things to line up for comparison. It is jarring if you have a list and successive elements are all different in appearance, and it makes it harder to make a nice table. I didn't know about the J/APL2 convention, thanks for explaining it. FYI, in Basis I don't have complex constants, just IMAGINARY ones. You do things like: 1i 1i = ( 0.00000D+00, 1.00000D+00) Basis> 3 + 2.5i 3+2.5i = ( 3.00000D+00, 2.50000D+00) Basis> As you see, I use the Fortran printing convention which is, of course, unacceptable in Python. But in array printing I don't, I use spacing: iota(10) + 2i iota(10)+2i shape: (10) 1: 1.00000D+00, 2.00000D+00 2.00000D+00, 2.00000D+00 3: 3.00000D+00, 2.00000D+00 4.00000D+00, 2.00000D+00 5: 5.00000D+00, 2.00000D+00 6.00000D+00, 2.00000D+00 7: 7.00000D+00, 2.00000D+00 8.00000D+00, 2.00000D+00 9: 9.00000D+00, 2.00000D+00 1.00000D+01, 2.00000D+00 Basis> ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From hinsenk@ere.umontreal.ca Fri Nov 3 21:12:53 1995 From: hinsenk@ere.umontreal.ca (Hinsen Konrad) Date: Fri, 3 Nov 1995 16:12:53 -0500 Subject: [PYTHON MATRIX-SIG] printing complexes In-Reply-To: <9511031949.AA13959@kristen.llnl.gov> (dubois@kristen.llnl.gov) Message-ID: <199511032112.QAA10966@cyclone.ERE.UMontreal.CA> The reason I was worried about the precision being the same on the two sides (and controllable) is simply the issue of making nice output where you want things to line up for comparison. It is jarring if you have a list and successive elements are all different in appearance, and it makes it harder to make a nice table. For matrices (and possibly sequence types in general) this is indeed an issue. But what should be equal is not the precision of the real and imaginary part of each number, but the real parts of all numbers and the imaginary parts of all numbers. My suggestion for formatting float and complex numbers in matrices is the following: Define an "order" of output formats as 1) integer 2) non-exponential floating point 3) exponential notation Next, determine the appropriate format for each entry of the matrix, using the same criterion as for %g-format in C to distinguish between 2 and 3. Then find the highest "order" used in the matrix (and the widest output field if the order is 1 (integer)) and apply it to all elements. For complex numbers, do this procedure independently for the real and imaginary parts. The result is a format in which all columns are lined up properly and have equal widths, but which also is the most compact possible. FYI, in Basis I don't have complex constants, just IMAGINARY ones. That's an alternative I have considered, and if there is a general preference for it, I am perfectly happy with it. But it should be used equally for input and output. Still I prefer the APL2/J notation because it can never give the impression of an arithmetic impression. Consider printing an expression with complex constants and multiplications in it. I am sure some people would read 2+3i * 1-7i as equivalent to 2-4i, so you'd have to print all complex numbers in parentheses (which of course would also be obligatory for input). ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hinsenk@ere.umontreal.ca Departement de chimie | Tel.: +1-514-343-6111 ext. 3953 Universite de Montreal | Fax: +1-514-343-7586 C.P. 6128, succ. Centre-Ville | Deutsch/Esperanto/English/Nederlands/ Montreal (QC) H3C 3J7 | Francais (phase experimentale) ------------------------------------------------------------------------------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From dubois@kristen.llnl.gov Fri Nov 3 05:25:07 1995 From: dubois@kristen.llnl.gov (P. Dubois) Date: Fri, 3 Nov 1995 13:25:07 +0800 Subject: [PYTHON MATRIX-SIG] printing complexes In-Reply-To: <199511032112.QAA10966@cyclone.ERE.UMontreal.CA> (hinsenk@ERE.UMontreal.CA) Message-ID: <9511032125.AA16768@kristen.llnl.gov> Actually, allow me to admit that the notation 3 + 4i in Basis *is* arithmetic, so that indeed 2 + 3i * 1 - 7i is 2-4i. While I think I know more about how to right a parser now, back in 1984 I didn't, so I took this very lazy way of introducing complex numbers. That said, it should be noted that the overwhelming percentage of all our matrices and complex numbers are created by users accessing compiled variables in common blocks that have been filled by compiled routines. So actual occurrence of a complex literal AS INPUT is rare. I think that would be true for most Python users too. You get complex numbers by reading some data and doing an FFT or eigenproblem or calculating some field, usually. So the question of how to represent complex literals in Python input is probably not very important as long as you don't end up screwing something up, like making the scanner twice as costly etc. ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From dubois@kristen.llnl.gov Fri Nov 3 05:37:46 1995 From: dubois@kristen.llnl.gov (P. Dubois) Date: Fri, 3 Nov 1995 13:37:46 +0800 Subject: [PYTHON MATRIX-SIG] the imaginary constant idea is not good Message-ID: <9511032137.AA17068@kristen.llnl.gov> I think I'd better say that I didn't mean to suggest that the imaginary constants idea in Basis was a good idea; it isn't. It made it easy on me at the time, and as I said it has worked o.k. because it really isn't used much. Anybody know what is in Matlab or IDL? Paul ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From hinsenk@ere.umontreal.ca Fri Nov 3 21:44:41 1995 From: hinsenk@ere.umontreal.ca (Hinsen Konrad) Date: Fri, 3 Nov 1995 16:44:41 -0500 Subject: [PYTHON MATRIX-SIG] printing complexes In-Reply-To: <9511032125.AA16768@kristen.llnl.gov> (dubois@kristen.llnl.gov) Message-ID: <199511032144.QAA13884@cyclone.ERE.UMontreal.CA> know more about how to right a parser now, back in 1984 I didn't, so I took this very lazy way of introducing complex numbers. It's not bad at all for input. I just don't think it is the best for output. But it's certainly good enough. So actual occurrence of a complex literal AS INPUT is rare. True enough... ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hinsenk@ere.umontreal.ca Departement de chimie | Tel.: +1-514-343-6111 ext. 3953 Universite de Montreal | Fax: +1-514-343-7586 C.P. 6128, succ. Centre-Ville | Deutsch/Esperanto/English/Nederlands/ Montreal (QC) H3C 3J7 | Francais (phase experimentale) ------------------------------------------------------------------------------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From hinsenk@ere.umontreal.ca Fri Nov 3 22:03:30 1995 From: hinsenk@ere.umontreal.ca (Hinsen Konrad) Date: Fri, 3 Nov 1995 17:03:30 -0500 Subject: [PYTHON MATRIX-SIG] the imaginary constant idea is not good In-Reply-To: <9511032137.AA17068@kristen.llnl.gov> (dubois@kristen.llnl.gov) Message-ID: <199511032203.RAA15034@cyclone.ERE.UMontreal.CA> Anybody know what is in Matlab or IDL? Matlab uses the same notation you chose for BASIS, for input and output. ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hinsenk@ere.umontreal.ca Departement de chimie | Tel.: +1-514-343-6111 ext. 3953 Universite de Montreal | Fax: +1-514-343-7586 C.P. 6128, succ. Centre-Ville | Deutsch/Esperanto/English/Nederlands/ Montreal (QC) H3C 3J7 | Francais (phase experimentale) ------------------------------------------------------------------------------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From chris.chase@jhuapl.edu Fri Nov 3 22:36:48 1995 From: chris.chase@jhuapl.edu (Chris Chase S1A) Date: Fri, 3 Nov 1995 17:36:48 -0500 Subject: [PYTHON MATRIX-SIG] the imaginary constant idea is not good In-Reply-To: <9511032137.AA17068@kristen.llnl.gov> References: <9511032137.AA17068@kristen.llnl.gov> Message-ID: <199511032233.RAA29802@python.org> Paul> Anybody know what is in Matlab or IDL? IDL uses a function: complex(real, imaginary). Output is "(real, imaginary)" without the quotes. Arrays of complex numbers are easily formed by using arrays for the real and imaginary parts. Matlab uses a complex constant i or j (actually functions) with the special notation that allows affixing i or j to a numeric constant, i.e. 2i = 2*i. Thus, 2 + 3i * 1 - 7i is 2-4i. Parentheses must be used to obtain the other interpretation. The use of i or j as functions can be hidden by a local variable of the same name. Output uses the i suffix. Chris ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From hinsenk@ere.umontreal.ca Fri Nov 3 17:04:24 1995 From: hinsenk@ere.umontreal.ca (Hinsen Konrad) Date: Fri, 3 Nov 1995 12:04:24 -0500 Subject: [PYTHON MATRIX-SIG] IEEE exceptions, casting, matrix multiplies, and default types In-Reply-To: <9511031537.AA03746@nineveh.lcs.mit.edu.LCS.MIT.EDU> (message from James Hugunin on Fri, 3 Nov 95 10:37:02 -0500) Message-ID: <199511031704.MAA26533@cyclone.ERE.UMontreal.CA> [Note: Matrix_i creates a matrix of ints, Matrix_d creates one of doubles] 2) Matrix_i(1,2,3) * Matrix_d(1.,2.,3.) == Matrix_d(1.,4.,6.) or raises exception I see no reason why matrices should have different coercion rules (or even none at all) than scalar numbers. So the result should be a float matrix. 4) add([1,2,3], [4,5,6]) == Matrix_?(5,7,9) where the question is what the ? should be. The rule should be that first the lists get transformed into matrices of a certain type, and then addition proceeds using the normal coercion rules. My suggestion for determining the global type of a list is that it should be complex if at least one element is complex, else float if at least one element is float, or otherwise integer. That of course leaves two of your points as starting points for extensive ideological fights ;-) ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hinsenk@ere.umontreal.ca Departement de chimie | Tel.: +1-514-343-6111 ext. 3953 Universite de Montreal | Fax: +1-514-343-7586 C.P. 6128, succ. Centre-Ville | Deutsch/Esperanto/English/Nederlands/ Montreal (QC) H3C 3J7 | Francais (phase experimentale) ------------------------------------------------------------------------------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From dubois@kristen.llnl.gov Mon Nov 6 01:14:09 1995 From: dubois@kristen.llnl.gov (P. Dubois) Date: Mon, 6 Nov 1995 09:14:09 +0800 Subject: [PYTHON MATRIX-SIG] casting and default types In-Reply-To: <199511031704.MAA26533@cyclone.ERE.UMontreal.CA> (hinsenk@ere.umontreal.ca) Message-ID: <9511061714.AA17004@kristen.llnl.gov> I agree with Konrad's view: the type of the matrix to be created from a list should be the least type conforming to all the components, and the same should go for the result of an expression. One could have the Matrix_? operators which strictly required the correct kind of list as an argument, and just plain Matrix(list) would be the creation routine which was "clever" at figuring this out. In Basis, [1,2,3] is an integer array, [1,2,3.] is a real array. Combined with the expression rule, this works well. I think no coercion is probably workable but less desireable. Related to this is what such "coercion" means for characters. If you have a list [a,b,c] where a,b,c are all strings, Basis interprets the "type" of the resulting matrix to be "strings of length max(len(a),len(b), len(c)), and the component strings are copied into the new structure with right blank fill to this new length. (I keep mentioning Basis simply as a way of letting you all know what one way is that users found acceptable; this is a set of semantics that has 10 years of intensive user testing. When there is something the users didn't like about it, I'll tell you that too. In this area, there are no complaints whatsoever.) ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From dubois@kristen.llnl.gov Mon Nov 6 01:35:16 1995 From: dubois@kristen.llnl.gov (P. Dubois) Date: Mon, 6 Nov 1995 09:35:16 +0800 Subject: [PYTHON MATRIX-SIG] A related idea Message-ID: <9511061735.AA17513@kristen.llnl.gov> Suppose we have the matrix class working. Suppose there is a Fortran or C array in the program which you would like to "adopt" as a matrix in Python. The only difference between this and a matrix created a normal way is that you have to remember never to free the memory. So it seems you might be able to do this if you had a method of creation (from C) which took a pointer,size,type kind of description. You could then increment the reference counter one extra, so that the memory is never freed, or a "don't free" flag could be in the header. ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From jjh@mama-bear.lcs.mit.edu Tue Nov 7 14:56:39 1995 From: jjh@mama-bear.lcs.mit.edu (James Hugunin) Date: Tue, 7 Nov 95 09:56:39 -0500 Subject: [PYTHON MATRIX-SIG] A related idea References: <9511061735.AA17513@kristen.llnl.gov> Message-ID: <9511071456.AA11707@nineveh.lcs.mit.edu.LCS.MIT.EDU> > Suppose we have the matrix class working. What do you mean suppose ;) ? > Suppose there is a Fortran > or C array in the program which you would like to "adopt" as a > matrix in Python. The only difference between this and a matrix created a > normal way is that you have to remember never to free the memory. > So it seems you might be able to do this if you had a method > of creation (from C) which took a pointer,size,type kind of > description. You could then increment the reference counter one extra, so > that the memory is never freed, or a "don't free" flag could be in the > header. I agree that there should be a function to create a new matrix object from an existing array in C (or FORTRAN). What we disagree about is the semantics. I played around a while with the idea of "sharing" an array between python and C. I found that as a general rule I ran into memory leak problems (or worse). Using your scheme, python is never responsible for freeing the allocated memory, this means that the C code must be responsible for it, but the C code can't know when it is safe to free the memory because even when it's done with it there might still be a python reference to the memory. Let me know if I'm completely missing something here, and this memory leak issue isn't really a problem. I made the general decision to completely avoid these sorts of issues by (almost) never returning arrays that are references to other arrays. I found that doing a malloc and a memcpy is usually sufficiently faster than any operation I'm going to perform on the array that it could be ignored. In order for this to be a valid assumption, I need to be working on a system where I have "more than enough" memory hanging around. This is always true for me, but I'm interested in cases where it's not. Note: the following will be completely meaningless to you if you haven't played with the alpha matrix object, so please ignore. --- I'd add the following function to do what you're suggesting, but using my semantics (this is off the top of my head, so there're no guarantees it will work). PyObject *PyMatrix_FromDimsAndData(int nd, int *dimensions, char type, void *data) { PyMatrixObject *ret = PyMatrix_FromDims(nd, dimensions, type); memcpy(ret->data, data, NBYTES(ret)); return (PyObject *)ret; } I'll add something like this to the next release. -Jim ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From jjh@mama-bear.lcs.mit.edu Tue Nov 7 15:12:44 1995 From: jjh@mama-bear.lcs.mit.edu (James Hugunin) Date: Tue, 7 Nov 95 10:12:44 -0500 Subject: [PYTHON MATRIX-SIG] casting and default types References: <9511061714.AA17004@kristen.llnl.gov> Message-ID: <9511071512.AA11715@nineveh.lcs.mit.edu.LCS.MIT.EDU> I've had a couple of discussions with Jim Fulton about exactly this issue when I first grabbed his matrix object. If he's reading this, I would really like to get his opinion. I agree with you, and for my uses full automatic coercion as well as reasonable choices for matrix type in instantiation is a good idea. The current instantiation (and lack of coercion) system is Jim Fulton's (more or less) and he could do a much better job of defending it than me. The principle issue is that automatic type coercions can hide bugs. The other issue is that automatic coercion can hide efficiency problems. If I have a vector of ints that I'm frequently going to have to multiply by different vectors of floats, then it would be much more efficient for me to convert it to a vector of floats one time. If I have automatic type coercion, I might never even notice this problem (except that my multiply operation would be something like a factor of two slower). This is why I mentioned this issue as something that might be amenable to some sort of flag in the same way that IEEE exceptions could be (I was just noticing that a system of this sort is enabled on the DEC alpha's). If I want to be really careful, I'd insist that adding floats to ints raised an exception, and simlarly that dividing by zero would do the same. If I was willing to play fast and loose then I could disable these forms of "error checking" and I'd be off. Still not sure what's the "right" way, Jim ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From hinsenk@ere.umontreal.ca Tue Nov 7 19:43:37 1995 From: hinsenk@ere.umontreal.ca (Hinsen Konrad) Date: Tue, 7 Nov 1995 14:43:37 -0500 Subject: [PYTHON MATRIX-SIG] casting and default types In-Reply-To: <9511071512.AA11715@nineveh.lcs.mit.edu.LCS.MIT.EDU> (message from James Hugunin on Tue, 7 Nov 95 10:12:44 -0500) Message-ID: <199511071943.OAA23753@cyclone.ERE.UMontreal.CA> The current instantiation (and lack of coercion) system is Jim Fulton's (more or less) and he could do a much better job of defending it than me. The principle issue is that automatic type coercions can hide bugs. The Whether or not coercion is a good idea is an old argument, but for Python it has long been decided: Python has coercion, and not having it for matrices would be simply inconsistent. other issue is that automatic coercion can hide efficiency problems. If I have a vector of ints that I'm frequently going to have to multiply by different vectors of floats, then it would be much more efficient for me to convert it to a vector of floats one time. If I have automatic type I'd suppose that people who need the highest possible performance are aware of this problem and are watching out for it. There is a profiler for Python that can help find such problems. I don't see this as a valid reason Python inconsistent and most users' life more difficult. This is why I mentioned this issue as something that might be amenable to some sort of flag in the same way that IEEE exceptions could be (I was just That's of course a possible solution, if someone thinks this is really important. ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hinsenk@ere.umontreal.ca Departement de chimie | Tel.: +1-514-343-6111 ext. 3953 Universite de Montreal | Fax: +1-514-343-7586 C.P. 6128, succ. Centre-Ville | Deutsch/Esperanto/English/Nederlands/ Montreal (QC) H3C 3J7 | Francais (phase experimentale) ------------------------------------------------------------------------------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From jfulton@usgs.gov Tue Nov 7 20:46:35 1995 From: jfulton@usgs.gov (Jim Fulton, U.S. Geological Survey) Date: Tue, 07 Nov 1995 15:46:35 -0500 Subject: [PYTHON MATRIX-SIG] casting and default types In-Reply-To: <199511071943.OAA23753@cyclone.ERE.UMontreal.CA> Message-ID: <199511072041.UAA21889@qvarsx.er.usgs.GOV> First of all, I want to apologize for not participating in this list much lately. I've been buried in a project here and haven't had time to keep up. On Tue, 7 Nov 1995 14:43:37 -0500 Hinsen Konrad said: > > The current instantiation (and lack of coercion) system is Jim Fulton's > (more or less) and he could do a much better job of defending it than me. > The principle issue is that automatic type coercions can hide bugs. The > > Whether or not coercion is a good idea is an old argument, but > for Python it has long been decided: Python has coercion, and > not having it for matrices would be simply inconsistent. Actually, this is not true. There are some places where coersion takes place automatically, but there are lot's of places where it doesn't. In the case of numbers, witness the float() and int() functions. Similarly, lists are not automatically converted to tuples in many places where tuples are required. And so on. > other issue is that automatic coercion can hide efficiency problems. If I > have a vector of ints that I'm frequently going to have to multiply by > different vectors of floats, then it would be much more efficient for me to > convert it to a vector of floats one time. If I have automatic type > > I'd suppose that people who need the highest possible performance > are aware of this problem and are watching out for it. There > is a profiler for Python that can help find such problems. I don't > see this as a valid reason Python inconsistent and most users' > life more difficult. It's not just a matter of performance. It is also a matter of correctness in some cases. > This is why I mentioned this issue as something that might be amenable to > some sort of flag in the same way that IEEE exceptions could be (I was just > > That's of course a possible solution, if someone thinks this > is really important. Global variables are evil. I'd be much more in favor of having different kinds of matrices that automagically coerce, if people really want this. I have to bring myself up to date on the in's and outs of this coersion issue. I think my objection to Jim's original coersion proposal had to do with ranks, more than the actual data types. There are certainly situations where coersion makes sense. For example, in my Fortran interface, FIDL, I automatically convert between argument and expected numeric element types. Jim ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From hinsenk@ere.umontreal.ca Tue Nov 7 21:02:56 1995 From: hinsenk@ere.umontreal.ca (Hinsen Konrad) Date: Tue, 7 Nov 1995 16:02:56 -0500 Subject: [PYTHON MATRIX-SIG] casting and default types In-Reply-To: <199511072041.UAA21889@qvarsx.er.usgs.GOV> (jfulton@wrdmail.er.usgs.gov) Message-ID: <199511072102.QAA29127@cyclone.ERE.UMontreal.CA> Actually, this is not true. There are some places where coersion takes place automatically, but there are lot's of places where it doesn't. In the case of numbers, witness the float() and int() functions. Similarly, lists are not automatically converted to tuples I can't imagine a need for float() and int() except in order to "downgrade" a number. In all mathematical operations where floats are required, I can just as well use ints. Lists and tuples are another problem, of course. My point of view is that as far as coercion is concerned, matrices should behave just like scalars of the same type(s). It's not just a matter of performance. It is also a matter of correctness in some cases. I don't understand. The choice is automatic coercion or none at all, i.e. throwing an exception for mixed-type operations. I don't see how one or the other can lead to a wrong result; it's either the correct result or no result. Of course there is some chance of making a mistake and not noticing it due to automatic coercion, but then you already have the same risk with scalars. Besides, I just can't think of a reasonable example... Also, I'd expect users to be familiar with coercion. I haven't made a survey, but I'd claim that most languages have coercion between numerical types, similar to Python. That's certainly true for the languages most used for numerical work. I'd be much more in favor of having different kinds of matrices that automagically coerce, if people really want this. Which creates some question and probably a lot of confusion. What happens if coercing and non-coercing matrices are combined? What happens if a function written for one type of matrices is used with the other? How can the matrices be distinguished in output? ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hinsenk@ere.umontreal.ca Departement de chimie | Tel.: +1-514-343-6111 ext. 3953 Universite de Montreal | Fax: +1-514-343-7586 C.P. 6128, succ. Centre-Ville | Deutsch/Esperanto/English/Nederlands/ Montreal (QC) H3C 3J7 | Francais (phase experimentale) ------------------------------------------------------------------------------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From jfulton@usgs.gov Wed Nov 8 14:01:11 1995 From: jfulton@usgs.gov (Jim Fulton, U.S. Geological Survey) Date: Wed, 08 Nov 1995 09:01:11 -0500 Subject: [PYTHON MATRIX-SIG] casting and default types In-Reply-To: <199511072102.QAA29127@cyclone.ERE.UMontreal.CA> Message-ID: <199511081356.NAA14836@qvarsx.er.usgs.GOV> On Tue, 7 Nov 1995 16:02:56 -0500 Hinsen Konrad said: > > Actually, this is not true. There are some places where coersion > takes place automatically, but there are lot's of places where it > doesn't. In the case of numbers, witness the float() and int() > functions. Similarly, lists are not automatically converted to tuples > > I can't imagine a need for float() and int() except in order to > "downgrade" a number. In all mathematical operations where floats > are required, I can just as well use ints. Lists and tuples are > another problem, of course. > > My point of view is that as far as coercion is concerned, matrices > should behave just like scalars of the same type(s). But what you are unwilling to believe is that scalars do not always coerce automatically. Try: spam = '0' * 20 and spam = '0' * 20.0 > It's not just a matter of performance. It is also a matter of > correctness in some cases. > > I don't understand. The choice is automatic coercion or none at all, > i.e. throwing an exception for mixed-type operations. I don't see > how one or the other can lead to a wrong result; it's either the > correct result or no result. No, another choice is generating an incorrect result. > Of course there is some chance of making a mistake and not noticing > it due to automatic coercion, but then you already have the same > risk with scalars. Besides, I just can't think of a reasonable > example... OK, how about this: 1 / 2 * 2 as opposed to: 1 / 2.0 * 2 These two expressions generate different results. If I wanted the first algorithm, I would need to explicitly force 2.0 to be an integer, but coersion has instead forced the first sub-expression to be a floating-point expression. There was discussion in the Python list a while back about problems caused by a new feature that automatically coerced floating point values passed to functions expecting integer arguments. Guido even expressed regret at being talked into adding the feature. Check the list archive for details. Even if an error is raised, it may be raised far from where the coersion that ultimately caused the error was done, making debugging of the error difficult. As I said in my other note, I object less to coersion of element types that to coersion of ranks. > Also, I'd expect users to be familiar with coercion. I haven't > made a survey, but I'd claim that most languages have coercion > between numerical types, similar to Python. That's certainly > true for the languages most used for numerical work. Again, user's familiar with Python should not expect coersion everywhere. User's familiar with Fortran should certianly not expect coersion everywhere. > I'd be much more in favor of having different kinds of matrices that > automagically coerce, if people really want this. > > Which creates some question and probably a lot of confusion. > What happens if coercing and non-coercing matrices are combined? > What happens if a function written for one type of matrices > is used with the other? How can the matrices be distinguished > in output? These are certainly valid points. Of course, the situation would be much worse with a global variable. Jim ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From hinsenk@ere.umontreal.ca Wed Nov 8 14:32:01 1995 From: hinsenk@ere.umontreal.ca (Hinsen Konrad) Date: Wed, 8 Nov 1995 09:32:01 -0500 Subject: [PYTHON MATRIX-SIG] casting and default types In-Reply-To: <199511081356.NAA14836@qvarsx.er.usgs.GOV> (jfulton@wrdmail.er.usgs.gov) Message-ID: <199511081432.JAA15432@cyclone.ERE.UMontreal.CA> > My point of view is that as far as coercion is concerned, matrices > should behave just like scalars of the same type(s). But what you are unwilling to believe is that scalars do not always coerce automatically. Not at all. I am just saying that if coercion is applied to a certain combination of scalar types, then the same coercion should be applied to arrays of the same type. As to which coercions should occur automatically, I'd say that int -> float -> complex should be automatic, but the reverse not, because it leads to an essential loss of information (int ->float can occasionally lead to a loss of precision, depending on how long the representations of int and float are, but I can live with that). > Of course there is some chance of making a mistake and not noticing > it due to automatic coercion, but then you already have the same > risk with scalars. Besides, I just can't think of a reasonable > example... OK, how about this: 1 / 2 * 2 as opposed to: 1 / 2.0 * 2 That's indeed a problem, but (in my point of view) not one caused by coercion, but by the unfortunate fact that / denotes quite different operations for integers and for floats. There was discussion in the Python list a while back about problems caused by a new feature that automatically coerced floating point values passed to functions expecting integer arguments. Guido even expressed regret at being talked into adding the feature. Check the list archive for details. I didn't know about that feature, and I certainly don't like it (see above). As I said in my other note, I object less to coersion of element types that to coersion of ranks. What exactly do you mean by "coercion of ranks"? ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hinsenk@ere.umontreal.ca Departement de chimie | Tel.: +1-514-343-6111 ext. 3953 Universite de Montreal | Fax: +1-514-343-7586 C.P. 6128, succ. Centre-Ville | Deutsch/Esperanto/English/Nederlands/ Montreal (QC) H3C 3J7 | Francais (phase experimentale) ------------------------------------------------------------------------------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From jjh@mama-bear.lcs.mit.edu Wed Nov 8 15:06:28 1995 From: jjh@mama-bear.lcs.mit.edu (James Hugunin) Date: Wed, 8 Nov 95 10:06:28 -0500 Subject: [PYTHON MATRIX-SIG] casting and default types References: <199511081432.JAA15432@cyclone.ERE.UMontreal.CA> Message-ID: <9511081506.AA13100@nineveh.lcs.mit.edu.LCS.MIT.EDU> > What exactly do you mean by "coercion of ranks"? I'm responsible for this poor phrase. My initial matrix proposal had the phrase "dimension coercion" for the J-style rank concept (of which I was unaware at the time). The issue in a nutshell is that everybody (I think) agrees that: a = Matrix((1,2,3),(11,12,13)) b = Matrix(100,200,300) a+1 = Matrix((2,3,4),(12,13,14)) One question is should a+b be an error, or should it be a+b = Matrix((101,202,203),(111,212,313)) I believe that the second is correct, and this can be elegantly expressed by the concept of ranks. I don't think there's much disagreement on this either. Now the question comes, what if I ask for inverse( Matrix(((1,2),(11,12)), ((3,4),(13,14))) ). Using the rank notions in J, the argument should be considered a 1-frame of 2-cells. The result should be a 1-frame containing the inverse of each of these 2-cells. However, for a case like this one, the arguments in favor of treating this as an error (you can't take the inverse of a 3d matrix) seem worth considering. My current solution to this is that my optimized ofuncs use the J-style rank system, but only work on operations with unbounded rank like +, *, etc. This is as much an implementation issue as anything else. Other functions on matrices, like inverse (or my favorite, fft) are completely free to implement a rank system, or not as they see fit. So for the fft function, when given a matrix, it will return the fft of every 1-cell. The question is whether or not we should adopt such a system as a standard for matrix functions. Under the current setup there would be no way to enforce such a standard. -Jim ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From hinsenk@ere.umontreal.ca Wed Nov 8 15:47:35 1995 From: hinsenk@ere.umontreal.ca (Hinsen Konrad) Date: Wed, 8 Nov 1995 10:47:35 -0500 Subject: [PYTHON MATRIX-SIG] casting and default types In-Reply-To: <9511081506.AA13100@nineveh.lcs.mit.edu.LCS.MIT.EDU> (message from James Hugunin on Wed, 8 Nov 95 10:06:28 -0500) Message-ID: <199511081547.KAA19928@cyclone.ERE.UMontreal.CA> Using the rank notions in J, the argument should be considered a 1-frame of 2-cells. The result should be a 1-frame containing the inverse of each of these 2-cells. However, for a case like this one, the arguments in favor of treating this as an error (you can't take the inverse of a 3d matrix) seem worth considering. In my opinion, the experience of the APL/J community shows that using rank extension everywhere is the better solution. Although in principle that can hide errors, such errors don't seem to occur in practice. It happens that by some mistake you create an array with the wrong length (typically off by 1), but you never create an array of the wrong rank. Besides, you could always locate such a mistake after a rank-3 inversion, as the result is still rank-3 and could not be confused with the inverse of a rank-2 matrix. On the other hand, there are applications where rank extension on inverses etc. is useful. Of course you could always get the same effect with explicit loops, but the speed difference is enormous (e.g. for inverting 1000 4x4 matrices). My current solution to this is that my optimized ofuncs use the J-style rank system, but only work on operations with unbounded rank like +, *, etc. That includes all binary operations, which are the most complicated. Other functions on matrices, like inverse (or my favorite, fft) are completely free to implement a rank system, or not as they see fit. So for There should be some provision in the matrix module for applying a unary function with a given rank to an array of higher rank, which could also be applied to user-written Python functions. the fft function, when given a matrix, it will return the fft of every 1-cell. The question is whether or not we should adopt such a system as a FFT is a good example for an operation where the rank system is useful. There are of course many applications for rank-1 FFT with extension to higher ranks, i.e. what you implemented. But it also makes sense to have multidimensional FFTs. In the J system, FFT would be unbounded and therefore n-dimensional for a rank-n array. You could then specify a lower rank to get lower-dimensional FFTs. standard for matrix functions. Under the current setup there would be no way to enforce such a standard. I think it should be standard (i.e. provided for all built-in functions). It shouldn't be enforced for user-defined function, but it should be made easy. ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hinsenk@ere.umontreal.ca Departement de chimie | Tel.: +1-514-343-6111 ext. 3953 Universite de Montreal | Fax: +1-514-343-7586 C.P. 6128, succ. Centre-Ville | Deutsch/Esperanto/English/Nederlands/ Montreal (QC) H3C 3J7 | Francais (phase experimentale) ------------------------------------------------------------------------------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From dubois@kristen.llnl.gov Thu Nov 9 19:10:44 1995 From: dubois@kristen.llnl.gov (P. Dubois) Date: Thu, 9 Nov 1995 11:10:44 -0800 Subject: [PYTHON MATRIX-SIG] A related idea In-Reply-To: <9511071456.AA11707@nineveh.lcs.mit.edu.LCS.MIT.EDU> (message from James Hugunin on Tue, 7 Nov 95 09:56:39 -0500) Message-ID: <9511091910.AA08047@kristen.llnl.gov> Jim Hugunin replied, in response to my suggestion for providing an "adoption" method for compiled arrays: > Suppose we have the matrix class working. What do you mean suppose ;) ? Hey, I'm a mathematician, all my sentences start with suppose! > Suppose there is a Fortran > or C array in the program which you would like to "adopt" as a > matrix in Python. The only difference between this and a matrix created a > normal way is that you have to remember never to free the memory. > So it seems you might be able to do this if you had a method > of creation (from C) which took a pointer,size,type kind of > description. You could then increment the reference counter one extra, so > that the memory is never freed, or a "don't free" flag could be in the > header. I agree that there should be a function to create a new matrix object from an existing array in C (or FORTRAN). What we disagree about is the semantics. I played around a while with the idea of "sharing" an array between python and C. I found that as a general rule I ran into memory leak problems (or worse). Using your scheme, python is never responsible for freeing the allocated memory, this means that the C code must be responsible for it, but the C code can't know when it is safe to free the memory because even when it's done with it there might still be a python reference to the memory. Let me know if I'm completely missing something here, and this memory leak issue isn't really a problem. This is a good point which I hadn't thought of because the way I intend to use this "adopting" the arrays are the permanent state of a calculation and are never "released" by the compiled code. I was aware that if I wanted to ever change size etc. I would somehow need to tell Python about it. Some careful thinking is required in that case. The point isn't that I want to save memory but that I want to MODIFY the array the compiled code is using, such as an array in a Fortran common block. I don't have a problem copying it when I'm going to do something with it. But to use it as a method of input to a code, I need to be able to do something like: import phys1 #load up physics code phys1.x = # or phys1.x[3] = 1. Here I'm assuming x is created by the initialization of the module such that it has the "real" x in the compiled code as a data area. Obviously, one could instead provide methods (e.g., set_x, set_y, set_z) but it dispels the illusion that x is really a matrix attribute of a physics package. Maybe I'm not taking the right approach here. Suggestions appreciated. ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From dubois@kristen.llnl.gov Fri Nov 10 16:40:40 1995 From: dubois@kristen.llnl.gov (P. Dubois) Date: Fri, 10 Nov 1995 08:40:40 -0800 Subject: [PYTHON MATRIX-SIG] [munro@icf.llnl.gov: Re: Python Matrix extension tutorial] Message-ID: <9511101640.AA18754@kristen.llnl.gov> Dear Matrix-SIGers, Yesterday at LLNL Brian Yang taught a tutorial on the matrix extension to about 20 people. I asked that people give me comments to forward to the SIG. In general, we concluded that the extension does what we need it to do. Here are some of the comments for your consideration. I will send them as separate messages so as to compartmentalize the discussion a little. The first is from Dave Munro. Dave is a physicist who has developed his own interpreted language for postprocessing called Yorick. The code this is most often used to postprocess, Lasnex, is a Fortran program with lots of arrays, so Yorick has facilities especially devoted to manipulating arrays easily. Here is Dave's suggestion: ------- Start of forwarded message ------- In the handout at the meeting on page 7 is an example of the heavily used Yorick feature I mentioned: You have two arrays b with shape (2,3) c with shape (2,2,3) and you want to produce: d[i][j][k]= b[i][k] + c[i][j][k] {The example would be much clearer if the ranks were given as (2,3) and (2,4,3), so it only made sense one way.} In Python, this common operation is carried out by the expression: d= add[1,2](b,c) Yorick has a special syntax for this same operation: d= b(,-,) + c which I find much clearer; the "-" in an index list is a place holder indicating that the result is to have an additional dimension in the slot where the "-" was. Thus b(,-,) is a rank-3 array which can be directly compared with c. With this notation, b(,,-)+c is the same as b[j][k]+c[i][j][k] (the default), while b(,-,)+c produces b[i][k]+c[i][j][k] and b(-,,)+c produces b[i][j]+c[i][j][k]. I call the "-" a "pseudo-index" in Yorick. In order for this to work, you need to broaden the definition of when two arrays are conformable; instead of requiring an exact match for the shape of the largest common cells of the two operands, you need to treat 1-length dimensions as "wildcards" matching any length. Thus, if b has shape (2,3) then b(,-,) has shape (2,1,3) -- exactly the same as reshape(b, (2,1,3)) -- which you can consider conformable to the (2,4,3) array c by the rule that [i][0][k] matches [i][j][k]. Ordinary scalar broadcasting is just a specific case of this general conformability rule. ----- I have the impression that the syntax would present very little difficulty in Python; on the model of the All and Reverse index objects, it would be easy to introduce a Pseudo object which did the reshape: d= b[(All,Pseudo,All)] + c However, I imagine that the implementor will be loathe to change his notion of array conformability at this late date. Nevertheless, you might as well ask to see what he says; probably the change wouldn't actually break any existing correct code, but merely give meaning to what would previously have produced a runtime error. That "1-length wildcard" rule has been a tremendous winner for Yorick; if you can convince the Python guys to use it, I doubt they would ever regret it. In Yorick, the combination of the relaxed conformability rule, pseudo-indices and a general transpose operator that can produce any permutation of dimensions allows for nearly all meaningful combinations of arrays. ----- Yorick has one other indexing syntax which has proven useful, which I call "rubber indices". They address the problem of writing interpreted code which extracts slices of arrays when you don't know beforehand how many dimensions the array has. An example is an opacity array for which you know that the most slowly varying index represents photon wavelength, but there might be zero, one, two, or three faster varying dimensions representing position in space. These situations can probably be handled with Python's reshape operator, so again this is a question of ease of use. ------- End of forwarded message ------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From dubois@kristen.llnl.gov Fri Nov 10 16:53:01 1995 From: dubois@kristen.llnl.gov (P. Dubois) Date: Fri, 10 Nov 1995 08:53:01 -0800 Subject: [PYTHON MATRIX-SIG] [tbyang@icf.llnl.gov: Some subtlety in reaching items of a matrix] Message-ID: <9511101653.AA18832@kristen.llnl.gov> The following comment by Brian Yang is not a surprise, as the difference in returning reference vs. returning copy was documented, but I thought I'd pass it on. ------- Start of forwarded message ------- I just found something about the matrix module which I was not aware of earlier: For a rank-3 matrix `c', there are some subtle difference between C[0][1] and c[(0,1)]. The following example illustrates this: -----------------------------------------> >>> c [[[4.0, 5.0, 6.0], [0.0, 4.0, 5.0]], [[1.0, 6.0, 5.0], [8.0, 5.0, 2.0]]] >>> c2=c[(0,1)] >>> c2 [0.0, 4.0, 5.0] >>> c1=c[0][1] >>> c1 [0.0, 4.0, 5.0] >>> c[(0,1,2)]=6 >>> c [[[4.0, 5.0, 6.0], [0.0, 4.0, 6.0]], [[1.0, 6.0, 5.0], [8.0, 5.0, 2.0]]] >>> c1 [0.0, 4.0, 6.0] >>> c2 [0.0, 4.0, 5.0] <-------------------------------------- Notice when c changes, c1 changes also, but not c2. The difference occurs because in `c1=c[0][1]' c is treated as a sequence, while in `c2=c[(0,1)]' c is treated as a mapping. And it just so happened that in the implementation of the methods, Hugunin decided to create a new matrix in the latter case, while for the former case he just created some new pointers pointing to the same data area as c. It appears very confusing to me. If we can have enough feed-back about this, maybe we can suggest him to change to one way or the other. ------- End of forwarded message ------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From jjh@mama-bear.lcs.mit.edu Fri Nov 10 17:08:37 1995 From: jjh@mama-bear.lcs.mit.edu (James Hugunin) Date: Fri, 10 Nov 95 12:08:37 -0500 Subject: [PYTHON MATRIX-SIG] [tbyang@icf.llnl.gov: Some subtlety in reaching items of a matrix] References: <9511101653.AA18832@kristen.llnl.gov> Message-ID: <9511101708.AA00801@ling-ling.lcs.mit.edu.LCS.MIT.EDU> > For a rank-3 matrix `c', there are some subtle difference between > C[0][1] and c[(0,1)]. The following example illustrates this: First, I agree completely, this is terrible. Nevertheless, here's my justification: Returning a matrix by-copy is always the best thing to do conceptually (I guess I've played with too many functional languages). I find it a lot easier to think about my matrix code if I don't have to worry about references to objects. On the other hand, if you want to allow python indexing of the style a[i][j] to function with any sort of reasonable efficiency, then you need to have a[i] return by reference. I'm perfectly willing to be convinced to change over to always returning matrices by reference (with the understanding that the code will have many more bugs, and the understanding that if a = Matrix(1,2,3) then a[0] will return not a python float, but a 0d matrix with the same sort of reference style semantics) or to always returning arrays by copy with the understanding that a[i][j] will potentially be an incredibly inefficient way of accessing an array element. I'm not happy with my chosen compromise. I just can't come up with a better solution. -Jim ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From dubois@kristen.llnl.gov Fri Nov 10 17:20:09 1995 From: dubois@kristen.llnl.gov (P. Dubois) Date: Fri, 10 Nov 1995 09:20:09 -0800 Subject: [PYTHON MATRIX-SIG] [tbyang@icf.llnl.gov: Some subtlety in reaching items of a matrix] In-Reply-To: <9511101708.AA00801@ling-ling.lcs.mit.edu.LCS.MIT.EDU> (message from James Hugunin on Fri, 10 Nov 95 12:08:37 -0500) Message-ID: <9511101720.AA19051@kristen.llnl.gov> I think we will sooner or later get time to make the change discussed before so that c[0,1] is a euphemism for c[(0,1)]. Assuming that, allowing c[0][1] to be a reference while c[0,1] is a copy doesn't seem too hard to explain to people. And I think the latter will be used much more than the former for use in expressions. I think the compromise adopted is far better than the alternatives; this class has to have good performance and we certainly want easy ways to assign values to row and columns at vector speed. ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From jjh@mama-bear.lcs.mit.edu Fri Nov 10 17:45:43 1995 From: jjh@mama-bear.lcs.mit.edu (James Hugunin) Date: Fri, 10 Nov 95 12:45:43 -0500 Subject: [PYTHON MATRIX-SIG] [tbyang@icf.llnl.gov: Some subtlety in reaching items of a matrix] References: <9511101737.AA00683@garion.llnl.gov.llnl.gov> Message-ID: <9511101745.AA00962@ling-ling.lcs.mit.edu.LCS.MIT.EDU> > If c[0,1] becomes a euphemism for c[(0,1)]. I will be very confused in > interpreting c[0], as it can correpond to both c[0,1] and c[0][1], if > they do different things. This is in a very good point! Just so you know how things will work (if no changes are made). c[0] will be a reference to the data in c, and c[0,] will be a copy of the data in c. This is incredibly ugly, but again, I don't know what to do about it. -Jim ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From jjh@mama-bear.lcs.mit.edu Fri Nov 10 20:18:59 1995 From: jjh@mama-bear.lcs.mit.edu (James Hugunin) Date: Fri, 10 Nov 95 15:18:59 -0500 Subject: [PYTHON MATRIX-SIG] [munro@icf.llnl.gov: Re: Python Matrix extension tutorial] References: <9511101640.AA18754@kristen.llnl.gov> Message-ID: <9511102019.AA01218@ling-ling.lcs.mit.edu.LCS.MIT.EDU> First off, I want to mention that I've looked at Yorick and find it a very impressive language for matrix manipulation. If I was still trying to choose between languages like octave or matlab I'd find Yorick a clear winner. The point of this python extension is to put these sorts of features within the python language so that so that we can simultaneously have access to the full power of that programming language (I know of no other "matrix" language in which you can write a full-scale web browser). > In the handout at the meeting on page 7 is an example of the heavily > used Yorick feature I mentioned: You have two arrays > > b with shape (2,3) > c with shape (2,2,3) > > and you want to produce: > > d[i][j][k]= b[i][k] + c[i][j][k] > > {The example would be much clearer if the ranks were given as (2,3) > and (2,4,3), so it only made sense one way.} In Python, this common > operation is carried out by the expression: > > d= add[1,2](b,c) > > Yorick has a special syntax for this same operation: > > d= b(,-,) + c > > which I find much clearer I think that Dave has a different concept of the operation being indicated by add[1,2](b,c) than I do, and than is really suggested by the notion of ranks. add[1,2] means add the vectors in b to the matrices in c. The notion of producing d[i][j][k]= b[i][k] + c[i][j][k] is conceptually different. Nevertheless, I am intrigued by the idea of adding this to the language. > I have the impression that the syntax would present very little > difficulty in Python; on the model of the All and Reverse index > objects, it would be easy to introduce a Pseudo object which did the > reshape: > > d= b[(All,Pseudo,All)] + c > > However, I imagine that the implementor will be loathe to change his > notion of array conformability at this late date. Nevertheless, you > might as well ask to see what he says; probably the change wouldn't > actually break any existing correct code, but merely give meaning to > what would previously have produced a runtime error. That "1-length > wildcard" rule has been a tremendous winner for Yorick; if you can > convince the Python guys to use it, I doubt they would ever regret it. I think that this makes sense, and I'll have a go at implementing it for my next release. The current version of the matrix object is 0.11 for a reason. I'm perfectly happy to consider any and all suggested changes to the language. I think I need to play with this one a little bit to see if I like it (for most of the things that I do ranks really are the right conceptual model), and I'll throw it out so that other people can begin playing with it and form their own opinions. > Yorick has one other indexing syntax which has proven useful, which I > call "rubber indices". They address the problem of writing > interpreted code which extracts slices of arrays when you don't know > beforehand how many dimensions the array has. An example is an > opacity array for which you know that the most slowly varying index > represents photon wavelength, but there might be zero, one, two, or > three faster varying dimensions representing position in space. These > situations can probably be handled with Python's reshape operator, so > again this is a question of ease of use. I think that I like this idea. Let me know if this is what you mean. Currently I have (for c being a 3d array): c[[0,]] <--> c[[0,All, All]] Are you suggesting something like: c[[Rubber, 0]] <--> c[[All, All, 0]]? If you're in fact suggesting something else, I'd like to hear more. -Jim ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From hinsenk@ere.umontreal.ca Fri Nov 10 21:36:20 1995 From: hinsenk@ere.umontreal.ca (Hinsen Konrad) Date: Fri, 10 Nov 1995 16:36:20 -0500 Subject: [PYTHON MATRIX-SIG] [munro@icf.llnl.gov: Re: Python Matrix extension tutorial] In-Reply-To: <9511101640.AA18754@kristen.llnl.gov> (dubois@kristen.llnl.gov) Message-ID: <199511102136.QAA24733@cyclone.ERE.UMontreal.CA> Yorick has one other indexing syntax which has proven useful, which I call "rubber indices". They address the problem of writing interpreted code which extracts slices of arrays when you don't know beforehand how many dimensions the array has. An example is an opacity array for which you know that the most slowly varying index represents photon wavelength, but there might be zero, one, two, or three faster varying dimensions representing position in space. These situations can probably be handled with Python's reshape operator, so again this is a question of ease of use. Maybe it helps to point out how this is handled in J and in my Array module. There indexing is not seen as something special, but just as one of many structural functions. Consequently it has no special syntax (in my array module I have added bracket indexing as a kind of syntactic sugar for the function take()), but is an ordinary function with two arguments: the array to be indexed from, and an index array. Accessing the first (or second etc.) dimension of an array of arbitrary rank is then done by specifying a negative rank for the indexing function. Negative function ranks basically mean that you do not specify the rank of the cells that the function operates on, but the rank of the frames of these cells. Maybe something similar could be implemented in Python, although I don't see with what kind of syntax one could indicate negative ranks for bracket indexing. Personally, I'd like to see an additional indexing function similar in spirit to the J version. I realise it can't replace bracket indexing, since you can't assign to parts of a matrix this way, but it would be a useful addition for many cases. ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hinsenk@ere.umontreal.ca Departement de chimie | Tel.: +1-514-343-6111 ext. 3953 Universite de Montreal | Fax: +1-514-343-7586 C.P. 6128, succ. Centre-Ville | Deutsch/Esperanto/English/Nederlands/ Montreal (QC) H3C 3J7 | Francais (phase experimentale) ------------------------------------------------------------------------------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From chris.chase@jhuapl.edu Fri Nov 10 22:20:00 1995 From: chris.chase@jhuapl.edu (Chris Chase S1A) Date: Fri, 10 Nov 1995 17:20:00 -0500 Subject: [PYTHON MATRIX-SIG] Yorick, Python and Array.py Message-ID: <199511102212.RAA00670@python.org> >>>>> "D" == Dave Munro D> Here is Dave's suggestion: [deleted material about pseudo indexes and comformability in Yorick] Two weeks ago someone pointed me toward the Yorick language for its array capabilities. After studying it, I found that Yorick has the most flexible array subscripting syntax of any language that I have seen. The advantages of Yorick can be added to Python but it requires some major work on some internals. In a reply to one of my previous posts, Guido already said he doesn't mind someone submitting internal changes that keep the language backward compatible. I have been working on these modifications and hope to finish them soon (I don't have much time available for this SIG and tinkering around with Python). I will post a summary of the changes in a separate message that I attempting to get some immediate feedback before I finish my mods. D> In order for this to work, you need to broaden the definition of when D> two arrays are conformable; instead of requiring an exact match for D> the shape of the largest common cells of the two operands, you need to D> treat 1-length dimensions as "wildcards" matching any length. I already have tried this by making a small modification to Array.py, the prototype from Konrad Hinsen . If anyone is interested I can send you the modified version. Array.py already has a concept of wildcard for extending a shorter frame for one argument to match a longer frame of another argument. It does this by combining the lower-rank array will then be combined with each matching ranked cell in the higher ranked array. Yorick calls this broadcasting because the lower ranked cell is "broadcasted" or replicated along the missing higher dimensions. Yorick extends this one step further. Yorick will broadcast along any size 1 dimension to match the common dimension of the other arguments. When combining a lower rank array with a higher rank we can think of the missing higher dimensions as being size 1. (i.e. equivalent to appending 1's to the shape of the shorter frame). Then the broadcasting method will have the same behavior already exhibited by Array.py. However, it has the additional benefit of broadcasting other unit dimensions (a simple viewpoint unit dimensions have similar behave like a scalar.) As an example, using the modified Array.py: b = Array([ [2,3,7], [9,8,2] ]) d = Array([1,2,3]) e = Array([[1],[2]]) # This could already be done. It adds to each row. >>> b+d 3 5 10 10 10 5 # This is new. It adds a column vector containing 1,2 to each column. >>> b+e 3 4 8 11 10 4 It makes outer products extremely simple: >>> d+e 2 3 4 3 4 5 >>> d*e 1 2 3 2 4 6 Pseudo indexes make this type of thing even easier. In the above if e=Array([1,2]) then I could have added e along the columns using: b+e(-,) This is more useful in even higher dimensions. It saves pairs of transposition operators and/or reshaping which can be confusing. D> However, I imagine that the implementor will be loathe to change his D> notion of array conformability at this late date. Nevertheless, you D> might as well ask to see what he says; probably the change wouldn't D> actually break any existing correct code. There is no single "implementor" here. My understanding is that the Matrix module concept is still in flux - hence the need for this SIG. There have been several implementations and design concepts suggested on this list. I have not seen any proposal to accept as a standard a particular Array module yet. D> In Yorick, the combination of the relaxed conformability rule, D> pseudo-indices and a general transpose operator that can produce any D> permutation of dimensions allows for nearly all meaningful D> combinations of arrays. I do like Yorick's completely general transpose() operator which uses a list of permutation cycles combined with circular shifts and negative dimension numbers (taken relative to the rank) to conveniently specify any arbitrary transposition on dimensions. D> Yorick has one other indexing syntax which has proven useful, which I D> call "rubber indices". This is another very useful feature. The idea is that you can have left or right justified index lists relative to array rank. Unspecified dimensions indexes default to the entire dimension. Optionally, the unspecified dimensions can be collapsed into a single dimension that is the product of the collapsed dimensions. Yorick provides a very nice syntax for a rubber index ".." and "*" to collapse the missing indexes. This becomes very useful when the dimension is unknown to the user and provides much simpler and clearer code than a complex sequence of take() and reshape() operators. b(..,2,3) or b(*,2,3) index along the last two dimensions. b(1,..,5) indexes along the first and last dimension. Indexes before the rubber index are left-justified while those following the rubber index are right-justified with respect to the shape of the indexed array. One other subscripting feature that Yorick (Matlab has this also) has is the ability to specify a stride with slice notation. E.g. 1:10:2 specifies a range the has increments of 2. The stride can also be negative. This is like the range() function. I list the additions that I am experimenting with in another post. Chris ------- end ------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From jjh@mama-bear.lcs.mit.edu Fri Nov 10 22:33:52 1995 From: jjh@mama-bear.lcs.mit.edu (James Hugunin) Date: Fri, 10 Nov 95 17:33:52 -0500 Subject: [PYTHON MATRIX-SIG] Yorick, Python and Array.py References: <199511102212.RAA00670@python.org> Message-ID: <9511102233.AA01268@ling-ling.lcs.mit.edu.LCS.MIT.EDU> > The advantages of Yorick can be added to Python but it requires some > major work on some internals. In a reply to one of my previous posts, > Guido already said he doesn't mind someone submitting internal changes > that keep the language backward compatible. I'm not sure that this is true. I've found that for my matrix object (on which I have received almost entirely good reviews from the testers) that this sort of indexing can be added very easily to python using mapping semantics (as Dave mentioned): ie. a[[All,Empty,All]] <--> a(,-,) I do think that it would be nice to remove that extra set of brackets, which Guido is also in favor of; however, I'm just not convinced that any further modifications are needed. For your other examples: a[[Star,2,3]] <--> a(*,2,3) a[[Slice(1,10,2)]] <--> a(1:10:2) I realize that the syntax in Yorick is a little bit more consise, but I'm just not convinced that such fundamental changes to the python core are in fact necessary. Just my two cents worth, Jim ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From hinsenk@ere.umontreal.ca Thu Nov 9 19:47:10 1995 From: hinsenk@ere.umontreal.ca (Hinsen Konrad) Date: Thu, 9 Nov 1995 14:47:10 -0500 Subject: [PYTHON MATRIX-SIG] A related idea In-Reply-To: <9511091910.AA08047@kristen.llnl.gov> (dubois@kristen.llnl.gov) Message-ID: <199511091947.OAA14508@cyclone.ERE.UMontreal.CA> The point isn't that I want to save memory but that I want to MODIFY the array the compiled code is using, such as an array in a Fortran common block. We should make a difference between Fortran and C interfacing (C standing for all languages that can handle dynamic memory management in a reasonable way). Fortran arrays are always static, so there is no memory leak problem. Increasing the reference count to make sure Python never tries to free the memory should be sufficient. As for C, the best way would be to leave allocation completely to Python. The matrix module would provide functions to allocate and free matrices that can be called from the C code just like malloc() and free(). These functions would take care of the reference from the C code. Of course the C code is also free to handle its own matrices and manage them completely (e.g. workspace in library functions). These would never be accessed from Python; in fact, Python wouldn't even know about their existence. ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hinsenk@ere.umontreal.ca Departement de chimie | Tel.: +1-514-343-6111 ext. 3953 Universite de Montreal | Fax: +1-514-343-7586 C.P. 6128, succ. Centre-Ville | Deutsch/Esperanto/English/Nederlands/ Montreal (QC) H3C 3J7 | Francais (phase experimentale) ------------------------------------------------------------------------------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From chris.chase@jhuapl.edu Sat Nov 11 06:01:27 1995 From: chris.chase@jhuapl.edu (Chris Chase S1A) Date: Sat, 11 Nov 1995 01:01:27 -0500 Subject: [PYTHON MATRIX-SIG] Yorick, Python and Array.py In-Reply-To: <9511102233.AA01268@ling-ling.lcs.mit.edu.LCS.MIT.EDU> References: <199511102212.RAA00670@python.org> <9511102233.AA01268@ling-ling.lcs.mit.edu.LCS.MIT.EDU> Message-ID: <199511110601.BAA02636@python.org> >>>>> "JH" == James Hugunin writes: JH> I'm not sure that this is true. I've found that for my matrix object (on JH> which I have received almost entirely good reviews from the testers) that JH> this sort of indexing can be added very easily to python using mapping JH> semantics (as Dave mentioned): JH> ie. a[[All,Empty,All]] <--> a(,-,) I guess I am not clear on this. Are All and Empty special objects defined by your matrix module? Aside: Actually, if the additions I had in mind were made (like slice notation) I would write the righthand side as a[:,-,:] or a[:,None,:], avoiding a new syntactic element for an empty argument (not seen elsewhere in the language). If you are concerned about too many extras added to the language, I would suggest that None be equivalent to "-", removing the requirement for your Empty object. JH> I do think that it would be nice to remove that extra set of brackets, JH> which Guido is also in favor of; however, I'm just not convinced that any JH> further modifications are needed. As you have indicated, there are clever workarounds that can accomplish the Yorick type of additions without internal language changes. However, I do not think that we should rule out internal Python additions if they are beneficial but don't break, limit, or violate the spirit/flavor of the language. JH> a[[Star,2,3]] <--> a(*,2,3) Okay. This is good. Would you use something like Dot for the Yorick ".." pseudo index? How do you keep the definitions of Star and Dot from being hidden inadvertently by other definitions in the users code (like an imported star catalog module that defines a Star object)? JH> a[[Slice(1,10,2)]] <--> a(1:10:2) Would the following also work? a[::2,:-4,::-1] <--> a[[Slice(None,None,2),Slice(None,-4),Slice(None,None,-1)]] This is product indexing on a, i.e. the indexes of the resulting elements are taken from the Cartesian product of the index vectors. This example takes every other on the first dimension, up to the fourth from the last on the second dimension, and reverses the last dimension. Of course one may want to mix scalars, slices, and matrices as indexes in the same subscripting expression: a[(1,2,3),5,::-1,b] <--> a[[[1,2,3],5,Slice(None,None,-1),b]] Are you also considering supporting indexing a multi-dimensional array in flattened form when only a single index vector is given? E.g. for the rank 3 a: a[[Slice(1,None,2)]] accessing every other element of a in flattened form. This is useful and common in other array languages. The danger here is that a[[[1,2,3]]] could be mistaken for a[[1,2,3]], where the first is a one-dimensional 3 element vector index into a flattened array and the second is a multi-dimensional index using a scalar for each dimension. (Dropping the extra grouping, the difference a[(1,2,3)] and a[1,2,3] is slightly more evident). JH> I realize that the syntax in Yorick is a little bit more consise, but I'm JH> just not convinced that such fundamental changes to the python core are in JH> fact necessary. Necessary, perhaps not. Worthwhile, I would definitely say yes. (Especially if someone volunteers the work for the changes). At the least, I feel the following would be worthwhile: 1) drop the extra grouping inside [] for multi-dimensional subscripts. 2) support slice expressions with strides wherever a 'test' syntactical element is possible. This internalizes your Slice() functionality. It is a natural extension of slice syntax already available. But requires a special check for calling the current __slice__ functionality for sequences. Mabye: 3?) '-' for pseudo index [not a big benefit but it only takes 3 lines of code, one in Grammar and 2 in compile.c] I have already started implementing these. I think that your workaround for the rubber indexes is just as good as what I had started to implement (probably better in the how it fits into the language philosophy). Aside: It would have been useful if the Python methods for sequence and dictionary types (e.g. __slice__) had originally been defined to take variable length argument lists instead of defined length and type argument lists. Then additions for slices with strides and multi-dimensional indexing would have been easier to add without breaking existing code (argument checking would be up to the method. If more arguments then desired were passed, e.g. 3 instead of 2 for a slice, then either the extra arguments would be ignored or an exception signaled. Similarly for subscripting.). Chris Chase ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From jjh@mama-bear.lcs.mit.edu Sat Nov 11 17:17:10 1995 From: jjh@mama-bear.lcs.mit.edu (James Hugunin) Date: Sat, 11 Nov 95 12:17:10 -0500 Subject: [PYTHON MATRIX-SIG] Yorick, Python and Array.py References: <199511102212.RAA00670@python.org> <9511102233.AA01268@ling-ling.lcs.mit.edu.LCS.MIT.EDU> <9511110559.AA08773@mama-bear.LCS.MIT.EDU> Message-ID: <9511111717.AA01573@ling-ling.lcs.mit.edu.LCS.MIT.EDU> I almost completely agree with your comments (now that I think I better understand what you're talking about). Here is how I see things. Please shout out if there are any major errors. I'm creating special objects All, Empty, Star, and Dot in order to capture the capabilities of Yorick for array subscripting. I've created a slice object to generalize the notion of start:stop:step indexing. Right now, my indexing system can take any combination of arbitrary sequences of ints, slices, or single ints as a full product form index into the matrix. The principle problems with this system are potential naming conflicts (or really ugly names like Matrix.Star) and the ugliness of Slice(None,None,2) vs. ::2. You are working on an extension to the python grammar to remove the extra brackets, make ::2 <--> some builtin python slice object, and "-" equivalent to some builtin python pseudo index object. I'd love to see all of these things happen, and I think that they'd fit in perfectly with my existing matrix object. I'm curious as to how you're implementing your slices. Are you creating a new python C object? This is actually the next step for me with my matrix object, and I'd love to see what you've done so far so that I can try and keep my work compatible with yours (and not duplicate too much effort). -Jim ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From hinsenk@ere.umontreal.ca Sun Nov 12 17:22:18 1995 From: hinsenk@ere.umontreal.ca (Hinsen Konrad) Date: Sun, 12 Nov 1995 12:22:18 -0500 Subject: [PYTHON MATRIX-SIG] Yorick, Python and Array.py In-Reply-To: <9511111717.AA01573@ling-ling.lcs.mit.edu.LCS.MIT.EDU> (message from James Hugunin on Sat, 11 Nov 95 12:17:10 -0500) Message-ID: <199511121722.MAA19828@cyclone.ERE.UMontreal.CA> I'm creating special objects All, Empty, Star, and Dot in order to capture the capabilities of Yorick for array subscripting. I confess that I have not yet completely studied all the discussion about indexing, but let's not get carried away to fast with implementations. We are not creating matrices for Yorick users, but for Python, so the notation we introduce should make sense without referring to Yorick. "All" and "Empty" are fine, but how should anyone make sense of "Star" and "Dot" without learning Yorick first? We should first agree on what features we want (preferably based on real use in other matrix languages) and then think about a notation for them that fits into Pythons general structure. For example, I don't like the idea of having '-' standing for anything else than a mathematical operation; once we start with this, we'll soon have a Perl-compatible letter soup. I've created a slice object to generalize the notion of start:stop:step indexing. That's not the worst solution, but maybe there is a better one. How about permitting lists of indices? That would include the generalized slices if range() is used to create the list. But it would also allow much more general indexing schemes without any further effort. It is probably a bit less efficient, but are generalized slices really used in time-critical parts of matrix algorithms? (Honest question, I don't know!) The principle problems with this system are potential naming conflicts (or really ugly names like Matrix.Star) and the ugliness of Slice(None,None,2) vs. ::2. Indeed. It would not be too difficult to allow ::2 as valid syntax, but that raises the question of what this means for other Python objects. For consistency it should be implemented everywhere. Is anyone volunteering to do that? ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hinsenk@ere.umontreal.ca Departement de chimie | Tel.: +1-514-343-6111 ext. 3953 Universite de Montreal | Fax: +1-514-343-7586 C.P. 6128, succ. Centre-Ville | Deutsch/Esperanto/English/Nederlands/ Montreal (QC) H3C 3J7 | Francais (phase experimentale) ------------------------------------------------------------------------------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From jjh@mama-bear.lcs.mit.edu Sun Nov 12 18:30:58 1995 From: jjh@mama-bear.lcs.mit.edu (James Hugunin) Date: Sun, 12 Nov 95 13:30:58 -0500 Subject: [PYTHON MATRIX-SIG] Yorick, Python and Array.py References: <199511121722.MAA19828@cyclone.ERE.UMontreal.CA> Message-ID: <9511121830.AA01870@ling-ling.lcs.mit.edu.LCS.MIT.EDU> > I'm creating special objects All, Empty, Star, and Dot in order to capture > the capabilities of Yorick for array subscripting. > > I confess that I have not yet completely studied all the discussion > about indexing, but let's not get carried away to fast with > implementations. We are not creating matrices for Yorick users, but > for Python, so the notation we introduce should make sense without > referring to Yorick. "All" and "Empty" are fine, but how should > anyone make sense of "Star" and "Dot" without learning Yorick first? I love the discussions that this list has generated, nonetheless I have found that sometimes they remain a little bit too divorced from actual implementations. I'm trying to implement some of the more interesting ideas in the hopes of myself and others being able to play with them, not as an attempt to impose a standard! > We should first agree on what features we want (preferably based on > real use in other matrix languages) and then think about a notation > for them that fits into Pythons general structure. For example, I > don't like the idea of having '-' standing for anything else than > a mathematical operation; once we start with this, we'll soon have > a Perl-compatible letter soup. This is a very good point. > I've created a slice object to generalize the notion of start:stop:step indexing. > > That's not the worst solution, but maybe there is a better one. How > about permitting lists of indices? That would include the generalized > slices if range() is used to create the list. But it would also allow > much more general indexing schemes without any further effort. It is > probably a bit less efficient, but are generalized slices really used > in time-critical parts of matrix algorithms? (Honest question, I don't > know!) Gee Konrad, I thought you had been playing with my matrices. I already allow lists of indices, and it's true, you can create generalized slices using range. The slice object is there in order to make things a lot easier. One thing that I really like about slices is that you can leave off the start or end points, and have them assigned appropriately for the array (just as in normal python slice indexing). This is a LOT easier to use than range. -Jim ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From hinsenk@ere.umontreal.ca Sun Nov 12 18:47:31 1995 From: hinsenk@ere.umontreal.ca (Hinsen Konrad) Date: Sun, 12 Nov 1995 13:47:31 -0500 Subject: [PYTHON MATRIX-SIG] Yorick, Python and Array.py In-Reply-To: <9511121830.AA01870@ling-ling.lcs.mit.edu.LCS.MIT.EDU> (message from James Hugunin on Sun, 12 Nov 95 13:30:58 -0500) Message-ID: <199511121847.NAA22095@cyclone.ERE.UMontreal.CA> implementations. I'm trying to implement some of the more interesting ideas in the hopes of myself and others being able to play with them, not as an attempt to impose a standard! Fine, but there is always the danger that the first working implementation sets a de-facto standard. That's how we got "industry standards" like DOS, Windows, or the IBM PC architecture. Maybe it would be a good idea to use very complicated names for things that are just experimental. That way noone would want to keep them ;-) Gee Konrad, I thought you had been playing with my matrices. I already Not as much as I would like... easier. One thing that I really like about slices is that you can leave off the start or end points, and have them assigned appropriately for the array (just as in normal python slice indexing). This is a LOT easier to use than range. True. So how about allowing three-argument slices? Fixing the parser is easy; implementing the feature for other sequence types is probably some more work, but feasible. There is one semantic problem, which also exists for your Slice() objects: how is assignment to such generalized slices defined if the number of elements in the new-value object doesn't match the number of elements in the slice? Assigning to "traditional" slices simply changes the length of a sequence. Of course there is always the possibility of raising an error, but maybe there is some useful interpretation of this. ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hinsenk@ere.umontreal.ca Departement de chimie | Tel.: +1-514-343-6111 ext. 3953 Universite de Montreal | Fax: +1-514-343-7586 C.P. 6128, succ. Centre-Ville | Deutsch/Esperanto/English/Nederlands/ Montreal (QC) H3C 3J7 | Francais (phase experimentale) ------------------------------------------------------------------------------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From et@appl-math.tu-muenchen.de Mon Nov 13 11:57:32 1995 From: et@appl-math.tu-muenchen.de (Thomas Schwaller) Date: Mon, 13 Nov 1995 12:57:32 +0100 Subject: [PYTHON MATRIX-SIG] Speed...cg...and more! Message-ID: <9511131257.ZM15259@piranha.appl-math.tu-muenchen.de> Hi all. Unfortunately I missed the first 5 weeks or so :-( of the very interesting but sometimes quite heavy discussion! So let me begin slow.... ;-) 1) The ofunc object is very interesting, but I miss a feature which I always missed also in the mathmodule.c of the Python distribution. When I want to use e.g. sin(a) of an not predefined type (the new math functions in Matrix just extend the standard ones by comples numbers, matrices,..) I would like that sin (and all the other ones) test at last if the object has a sin attribute and execute it. In Mathmodule.c this was just a minor hack but here I don't now. Why do I want that behaviour. I write a lot of math stuff (ince contributes a 1D automatic differentiation module) and I also want to be able to call sin(a) of these types. In case of the Matrix objects one problem we will ultimately be faced with is the problem of using e.g. exp(A) but not in the pointwise sense but in the mathematical sense (defined by power series for example) So what to do then. Extending exp in python is done very eay: from Matrix import * Matrix_sin=sin def sin(x): """uses builtin sin function or attribute sin""" try: return Matrix_sin(x) except AttributeError: if hasattr(x, 'sin'): return x.sin() else: raise AttributeError, 'sin not available for this type' but I think this should be in the python code, so I just can do something like class dummy: def __init__(self, x) self.x=x def sin(self): return sin(x), sin(x-1) a=dummy() print sin(a) This is a thing which should be there once and for all. 2) When writing mathematical stuff with matrices one uses very often the multiplication (in the Matrix sense) with transposed matrices. Something like: s = Multiply(A.transpose(), r) Is it possible to write that directly with the available methods. When doing this kind of operation you don't really need to trnaspose the matrix, just switch the order of the the loops. When you do a lot of mulitplications with a lot of transposed matrices this is quite important. Please tell me when I'm missing something here. As far as I understand, at the moment you can influence the indices, but can you also influence the order of execution whitout producing a new matrix on the fly? As a goodie here's a simple conjugate gradient method for testing: (Hope it' correct!) from Matrix import * import sys def cg(A, b, x=None, eps=1e-12, k=None, printer=None): m, n = A.shape if k == None: k = m*2 # indeed much too high! if x == None: x, r = zeros(n,1), b else : r = b - Multiply(A, x) p = Multiply(A.transpose(), r) gamma = dot(p, p) for j in range(k): q = Multiply(A, p) alpha = gamma / dot(q, q) x = x + alpha*p r = r - alpha*q s = Multiply(A.transpose(), r) gamma_new = dot(s, s) beta = gamma_new / gamma gamma = gamma_new if gamma[0] <= eps*eps: return x p = s + beta*p if printer: printer(x, r, s, p, q, beta, gamma) raise error,'cg-method diverges with %d iterations and eps = %.0e' % (k,eps) def cg_test(): def pr(x, r, s, p, q, beta, gamma): print gamma[0] n =20 b= ones(n, 1) for i in range(100): a = rand(n, n) a=0.5*(a+a.transpose()) x = cg(a, b) sys.stdout.write('.') sys.stdout.flush() cg_test() 3) As a matter of style, perhaps we should discuss how to write such things. I guess as soon as the matrixmodule will be in the standard distribution there will be a lot of matlab style writing. We should try to keep the procedures, classes ... as uniform as possible, so that everybody can rely on a certain behaviour. We want to be better than Matlab with such a powerfull Language as Python, don't we? 4) Last but not least I need a simple example how to use matrixobjects writing own extension. Suppose I have a method for comuting the first eigenvalue of a sqaure matrix: int n=1000; double **a=....; double lambda1=first_eigenvalue(a, n); What is the standard way of using that in python? a=Matrix_(n,n) lambda1=first_eigenvalue(a) I mean how should I produce (access) a double** having a matrixobject? (this is not a question about how to write an extenssion, just about how to use the matrixobject :-)) 5) Are the handouts of the mentionned talk about the matrix module available for all? Would be nice! Tom ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From hinsenk@ere.umontreal.ca Mon Nov 13 13:29:33 1995 From: hinsenk@ere.umontreal.ca (Hinsen Konrad) Date: Mon, 13 Nov 1995 08:29:33 -0500 Subject: [PYTHON MATRIX-SIG] Speed...cg...and more! In-Reply-To: <9511131257.ZM15259@piranha.appl-math.tu-muenchen.de> (et@appl-math.tu-muenchen.de) Message-ID: <199511131329.IAA29436@cyclone.ERE.UMontreal.CA> 1) The ofunc object is very interesting, but I miss a feature which I always missed also in the mathmodule.c of the Python distribution. When I want to use e.g. sin(a) of an not predefined type (the new math functions in Matrix just extend the standard ones by comples numbers, matrices,..) I am working on a "general" math module that provides all the standard functions for arbitrary objects. It calls functions from math for ints and floats, functions from cmath for complex numbers, functions from matrix for matrices, and looks for a method in all other objects. Originally I wanted to do that in Python, but that turned out to detetriorate performance drastically. The C module I am working on now should have no noticeable overhead. ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hinsenk@ere.umontreal.ca Departement de chimie | Tel.: +1-514-343-6111 ext. 3953 Universite de Montreal | Fax: +1-514-343-7586 C.P. 6128, succ. Centre-Ville | Deutsch/Esperanto/English/Nederlands/ Montreal (QC) H3C 3J7 | Francais (phase experimentale) ------------------------------------------------------------------------------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From et@appl-math.tu-muenchen.de Mon Nov 13 14:40:36 1995 From: et@appl-math.tu-muenchen.de (Thomas Schwaller) Date: Mon, 13 Nov 1995 15:40:36 +0100 Subject: [PYTHON MATRIX-SIG] Speed...cg...and more! Message-ID: <9511131540.ZM16801@piranha.appl-math.tu-muenchen.de> Sorry for the typos in my last message. Here are some other things I forgot there. 1) What about a Matrix constructor which can use constant values and functions for initailising. e.g. from math import * from Matrix import * f=lambda i, j: sin(i)*cos(j) a=Matrix(1000,1000, func=f) #square 1000x1000 matrix b=a=Matrix_d(10,10,10, func=lambda i, j, k: sin(i)*cos(j)*exp(k) #10x10x10 tensor If we do that in the standard way it will not be fast enough. I nearly always have this problem when using some procedure which need functions as input. I C-code it's no problem at all and after introducing it in python it's just to slow (e.g. minimize a function...). Imagine that the function is evaluated 100000 times! What to do. If we could compile simple functions on the fly this would be just fine. Not a general Python Compiler, but just a tiny one for certain things. Other possibility: Dynamic loading (not really acceptable for such things (interactivity is lost a little bit) Or write some new module for that type of work (Some Parser thigs!) The above example would go as b=Matrix(1000,1000, "sin(i)*cos(j)") or Matrix(1000,1000, "i,j->sin(i)*cos(j)") Comments? Tom ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From jjh@mama-bear.lcs.mit.edu Mon Nov 13 15:51:04 1995 From: jjh@mama-bear.lcs.mit.edu (James Hugunin) Date: Mon, 13 Nov 95 10:51:04 -0500 Subject: [PYTHON MATRIX-SIG] Speed...cg...and more! References: <199511131329.IAA29436@cyclone.ERE.UMontreal.CA> Message-ID: <9511131551.AA02186@ling-ling.lcs.mit.edu.LCS.MIT.EDU> > 1) The ofunc object is very interesting, but I miss a feature which I always > missed also in the mathmodule.c of the Python distribution. When I want to > use e.g. sin(a) of an not predefined type (the new math functions in > Matrix just extend the standard ones by comples numbers, matrices,..) > > I am working on a "general" math module that provides all the standard > functions for arbitrary objects. It calls functions from math for ints > and floats, functions from cmath for complex numbers, functions from > matrix for matrices, and looks for a method in all other objects. > > Originally I wanted to do that in Python, but that turned out to > detetriorate performance drastically. The C module I am working on now > should have no noticeable overhead. And here I've been working on adding these very same features to my ofuncobjects. I'm really think that this is the "right" place to do this, and then to produce a single omathmodule.c that does the right thing efficiently for all object types. Let's talk off-line about this Konrad so we don't end up duplicating each others efforts here. -Jim ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From jjh@mama-bear.lcs.mit.edu Mon Nov 13 16:20:16 1995 From: jjh@mama-bear.lcs.mit.edu (James Hugunin) Date: Mon, 13 Nov 95 11:20:16 -0500 Subject: [PYTHON MATRIX-SIG] Speed...cg...and more! References: <9511131257.ZM15259@piranha.appl-math.tu-muenchen.de> Message-ID: <9511131620.AA02200@ling-ling.lcs.mit.edu.LCS.MIT.EDU> > 1) See my previous post. > 2) When writing mathematical stuff with matrices one uses very often > the multiplication (in the Matrix sense) with transposed matrices. > Something like: > s = Multiply(A.transpose(), r) The current implementation of matrix multiply sucks! I do very little linear algebra work, so I haven't gotten around to doing this properly yet. I'll bear this in mind when I do get around to doing things right. The following is the current implementation of matrix multiplication. def Multiply(a,b): return add.inner(multiply, a, b.transpose()) You should be able to use: s = add.inner(multiply, A, r).transpose() I'm sure that the extra transpose at the end will add very little overhead to your code (compared to the matrix multiplication itself). Thanks for the CG code, this is exactly the sort of stuff I'd love to have people start building into standard libraries! > 3) As a matter of style, perhaps we should discuss how to write such things. > I guess as soon as the matrixmodule will be in the standard distribution > there will be a lot of matlab style writing. We should try to keep the > procedures, classes ... as uniform as possible, so that everybody can > rely on a certain behaviour. We want to be better than Matlab with such a > powerfull Language as Python, don't we? Good point. I'd love to see people out there write some proposed style guides for matrix functions! > 4) Last but not least I need a simple example how to use matrixobjects > writing own extension. This is currently very poorly supported in the current 0.11 alpha release (expect this to change in later releases). Look at matrixmodule.c matrix_sort() for a much more complicated example than your own. Also, matrices are stored as contiguous memory blocks with a single pointer, to get the traditional C **, you need to generate it yourself (this too will be supported in a friendly way when I have time). > 5) Are the handouts of the mentionned talk about the matrix module available > for all? Would be nice! I agree! And from your followup: > f=lambda i, j: sin(i)*cos(j) > a=Matrix(1000,1000, func=f) #square 1000x1000 matrix Here's how I'd do that using ofuncs i = mrange(1000) j = mrange(1000) a = multiply.outer(sin(i), cos(j)) > b=a=Matrix_d(10,10,10, func=lambda i, j, k: sin(i)*cos(j)*exp(k) i = mrange(10) j = mrange(10) k = mrange(10) a1 = multiply.outer(sin(i), cos(j)) #note, this tempory is only needed for clarity b = a = multiply.outer(a1, exp(k)) Okay, I admit that this is uglier than you'd like, but it runs nearly as fast as the hand-coded C would. It might be possible to write some sort of matrix constructor function that could "compile" to this ofunc form on the fly. -Jim ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From jjh@mama-bear.lcs.mit.edu Mon Nov 13 20:05:10 1995 From: jjh@mama-bear.lcs.mit.edu (James Hugunin) Date: Mon, 13 Nov 95 15:05:10 -0500 Subject: [PYTHON MATRIX-SIG] Matrix multiplies and syntactic nits Message-ID: <9511132005.AA02648@ling-ling.lcs.mit.edu.LCS.MIT.EDU> I'm working on putting out the 0.2 version of my matrix object, and I'm having a surprisingly hard time resolving some very silly naming issues. 1) There is a single python file currently called Matrix.py which imports everything you could ever want for basic functions on matrix objects. This module has a similar role as Tkinter does in the Tk module system. It defines functions and a number of useful constants. Should I rename this module to Mx.py, or something similar so that people will be more inclined to use "import Mx" rather than "from Matrix import *" (which is what I use all the time). This idea comes directly from Tkinter related discussions on the main list. 2) I have two possible ways to implement matrix multiplies: a) a % b I personally never need the modulo operator for matrices, and it does have enough of a resemblence to X to be reasonably mnemonic. However, this breaks the current conceptual elegance of the system where every operator works on matrices (more or less) exactly the way it works on python scalars. b) a.matrixMultiply(b) This is the obvious solution, however it does make matrix equations extremely ugly to type. Possibly an abbreviation is called for in this particular case? Any opinions? Note: There seem to be enough people with very reasonable objections to the idea of controlling "*" with a global variable that I don't consider this one of the possible solutions. 3) String representations of matrices I'm not talking about the normally printed representation here, that's a major issue, not a nit. I'm trying to decide between two string representations and again I just wanted some feedback. The following are 2x3 matrices of integers. a) Matrix_i((1,2,3),(4,5,6)) b) matrix([[1,2,3],[4,5,6]], 'i') Opinions on which you should get with str(M)? Thanks for the feedback - Jim ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From hinsenk@ere.umontreal.ca Mon Nov 13 20:51:13 1995 From: hinsenk@ere.umontreal.ca (Hinsen Konrad) Date: Mon, 13 Nov 1995 15:51:13 -0500 Subject: [PYTHON MATRIX-SIG] Matrix multiplies and syntactic nits In-Reply-To: <9511132005.AA02648@ling-ling.lcs.mit.edu.LCS.MIT.EDU> (message from James Hugunin on Mon, 13 Nov 95 15:05:10 -0500) Message-ID: <199511132051.PAA25492@cyclone.ERE.UMontreal.CA> defines functions and a number of useful constants. Should I rename this module to Mx.py, or something similar so that people will be more inclined to use "import Mx" rather than "from Matrix import *" (which is what I use I don't see any need to do this. Anyone can always define a shorter name by writing import Matrix Mx = Matrix So I'd keep the "official" name understandable. 2) I have two possible ways to implement matrix multiplies: a) a % b NOOOOOOOOOO! enough of a resemblence to X to be reasonably mnemonic. However, this breaks the current conceptual elegance of the system where every operator works on matrices (more or less) exactly the way it works on python scalars. It's not just a matter of conceptual elegance, but of being able to write code that works identically with matrices and scalars. And of easily understanding what a certain piece of code does. b) a.matrixMultiply(b) This is the obvious solution, however it does make matrix equations extremely ugly to type. Possibly an abbreviation is called for in this particular case? Probably yes. But I'd still keep the long name for those who want to write clear code. The following are 2x3 matrices of integers. a) Matrix_i((1,2,3),(4,5,6)) b) matrix([[1,2,3],[4,5,6]], 'i') Opinions on which you should get with str(M)? I'd prefer the first. In fact, I'd prefer a name like "IntMatrix" instead of "Matrix_i". It is not at all obvious that the attached letter indicates the type. I don't like the second notation at all; it somehow implies that 'i' is a string argument that could have any value. If you want a notation that indicates the type as an argument, why not use types.IntType instead of 'i'? ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hinsenk@ere.umontreal.ca Departement de chimie | Tel.: +1-514-343-6111 ext. 3953 Universite de Montreal | Fax: +1-514-343-7586 C.P. 6128, succ. Centre-Ville | Deutsch/Esperanto/English/Nederlands/ Montreal (QC) H3C 3J7 | Francais (phase experimentale) ------------------------------------------------------------------------------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From chris.chase@jhuapl.edu Mon Nov 13 23:12:44 1995 From: chris.chase@jhuapl.edu (Chris Chase S1A) Date: Mon, 13 Nov 1995 18:12:44 -0500 Subject: [PYTHON MATRIX-SIG] flattened array indexing Message-ID: <199511132308.SAA03218@python.org> I had suggested before that the "[]" syntax support both multi-dimensional product indexing and flattened array indexing. However, with the proposed M[i,j] <-> M[(i,j)] trying to also implement flattened indexing with the same syntax could cause some problems. Instead it might be better to have a separate M.flat(i) method for flattened indexing. I would then assume when i is a scalar M[i] is "hierarchical" indexing like Jim Fulton has suggested (i.e. M[i] returns a one lower dimensional array) I assume that if M has 3 dimensions then M[1,2] would be an error for not specifying the correct number of indexes. A question: M 1-dimensional. i = (1,2,3) Is the following a "wrong number of indexes" error or will 1D arrays be treated differently? M[i] <-> M[(1,2,3)] Would one have to resort to: M[(i,)] <-> M[((1,2,3))] ? Chris Chase ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From et@appl-math.tu-muenchen.de Thu Nov 16 13:57:24 1995 From: et@appl-math.tu-muenchen.de (Thomas Schwaller) Date: Thu, 16 Nov 1995 14:57:24 +0100 Subject: No subject Message-ID: <9511161457.ZM27141@piranha.appl-math.tu-muenchen.de> Hi all, when writing my first matrix algorithms I faced a "problem" of "inconsistency" concerning matrices and vectors. Suppose a naive user being used to Matlab, Scilab or octave. He/she want's to to his/her first matrix computations: a=Matrix([1,2,3],[2,3,4],[4,5,6]) b=ones(3) Multiply(a,b) Traceback (innermost last): File "", line 1, in ? File "/home/et/Python-1.3/Lib/Matrix.py", line 114, in Multiply return add.inner(multiply, a, b.transpose()) Matrix.error: 1st dimension invalid Aha he/she thinks, b ia a row vector. So let's transpose it b=ones(3).transpose() Traceback (innermost last): File "", line 1, in ? Matrix.error: 1st dimension invalid So wat the hell is going on here, (s)he thinks. So let's try b=ones(3, 1) Multiply(a,b) [[6.0], [9.0], [15.0]] Ah yes, well let's compute a dot product of b and compare it with something: if dot(b,b) == 3.0: print 'ok' else : print 'not ok' not ok Hm.. print dot(b,b) [3.0] Ah, I see.. if dot(b,b)[0] == 3.0: print 'ok' else : print 'not ok' ok At this point our potential user who heard really hot things about the python matrix class will probably not use it anymore. What can we do to change his/her opinion, because WE know it's still a very hot topic and we all love it, don't we? :-) ### END OF THE NIGHTMARE TALE ;;;;-)) TOM ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From hinsenk@ere.umontreal.ca Thu Nov 16 14:34:26 1995 From: hinsenk@ere.umontreal.ca (Hinsen Konrad) Date: Thu, 16 Nov 1995 09:34:26 -0500 Subject: No subject In-Reply-To: <9511161457.ZM27141@piranha.appl-math.tu-muenchen.de> (et@appl-math.tu-muenchen.de) Message-ID: <199511161434.JAA21776@cyclone.ERE.UMontreal.CA> a=Matrix([1,2,3],[2,3,4],[4,5,6]) b=ones(3) Multiply(a,b) Traceback (innermost last): File "", line 1, in ? File "/home/et/Python-1.3/Lib/Matrix.py", line 114, in Multiply return add.inner(multiply, a, b.transpose()) Matrix.error: 1st dimension invalid This ought to work, but Multiply() is still a bit broken. Try add.inner(multiply, a, b) which does what you want. Multiply does the same, but first transposes b (don't ask me why!), which produces the error message. Aha he/she thinks, b ia a row vector. So let's transpose it b=ones(3).transpose() This ought to work, and return b. So transpose() is also broken... At this point our potential user who heard really hot things about the python matrix class will probably not use it anymore. At this point the matrix class is still in its early stages! Patience... ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hinsenk@ere.umontreal.ca Departement de chimie | Tel.: +1-514-343-6111 ext. 3953 Universite de Montreal | Fax: +1-514-343-7586 C.P. 6128, succ. Centre-Ville | Deutsch/Esperanto/English/Nederlands/ Montreal (QC) H3C 3J7 | Francais (phase experimentale) ------------------------------------------------------------------------------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From jjh@mama-bear.lcs.mit.edu Thu Nov 16 16:58:15 1995 From: jjh@mama-bear.lcs.mit.edu (James Hugunin) Date: Thu, 16 Nov 95 11:58:15 -0500 Subject: [PYTHON MATRIX-SIG] Linear Algebra References: <9511161457.ZM27141@piranha.appl-math.tu-muenchen.de> Message-ID: <9511161658.AA01382@ling-ling.lcs.mit.edu.LCS.MIT.EDU> Warning, I spend almost all of my time doing signal processing type work, so you should expect that the linear algebra side of my matrix object is not quite right. Please keep sending these sorts of comments so that I can figure out what the linear algebra types want (except for * <--> matrixMultiply) and implement it properly. Konrad summed up most of my response in the following lines: > This ought to work, but Multiply() is still a bit broken. > This ought to work, and return b. So transpose() is also broken... > At this point the matrix class is still in its early stages! > Patience... I'll fix both of these for the next release (I'd been hoping for this evening, but Friday is looking more likely). Keep the bug reports coming! -Jim ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From jjh@mama-bear.lcs.mit.edu Thu Nov 16 16:58:15 1995 From: jjh@mama-bear.lcs.mit.edu (James Hugunin) Date: Thu, 16 Nov 95 11:58:15 -0500 Subject: [PYTHON MATRIX-SIG] Linear Algebra References: <9511161457.ZM27141@piranha.appl-math.tu-muenchen.de> Message-ID: <9511161658.AA01382@ling-ling.lcs.mit.edu.LCS.MIT.EDU> Warning, I spend almost all of my time doing signal processing type work, so you should expect that the linear algebra side of my matrix object is not quite right. Please keep sending these sorts of comments so that I can figure out what the linear algebra types want (except for * <--> matrixMultiply) and implement it properly. Konrad summed up most of my response in the following lines: > This ought to work, but Multiply() is still a bit broken. > This ought to work, and return b. So transpose() is also broken... > At this point the matrix class is still in its early stages! > Patience... I'll fix both of these for the next release (I'd been hoping for this evening, but Friday is looking more likely). Keep the bug reports coming! -Jim ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From hinsenk@ere.umontreal.ca Thu Nov 16 17:25:04 1995 From: hinsenk@ere.umontreal.ca (Hinsen Konrad) Date: Thu, 16 Nov 1995 12:25:04 -0500 Subject: [PYTHON MATRIX-SIG] Linear Algebra In-Reply-To: <9511161658.AA01382@ling-ling.lcs.mit.edu.LCS.MIT.EDU> (message from James Hugunin on Thu, 16 Nov 95 11:58:15 -0500) Message-ID: <199511161725.MAA03038@cyclone.ERE.UMontreal.CA> quite right. Please keep sending these sorts of comments so that I can figure out what the linear algebra types want (except for * <--> matrixMultiply) and implement it properly. Let's start with something easy: transpose(). It should work for arrays of any rank and reverse the shape. A useful addition would be an optional argument that is a list (or tuple or array) representing a permutation of range(len(x.shape)). That would allow an arbitrary reshuffling of axes. I'll send some comments on multiplication later. For now just that: Multiply() and Dot() are really one and the same function, if done correctly. ------------------------------------------------------------------------------- Konrad Hinsen | E-Mail: hinsenk@ere.umontreal.ca Departement de chimie | Tel.: +1-514-343-6111 ext. 3953 Universite de Montreal | Fax: +1-514-343-7586 C.P. 6128, succ. Centre-Ville | Deutsch/Esperanto/English/Nederlands/ Montreal (QC) H3C 3J7 | Francais (phase experimentale) ------------------------------------------------------------------------------- ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From dubois@kristen.llnl.gov Fri Nov 17 17:43:42 1995 From: dubois@kristen.llnl.gov (P. Dubois) Date: Fri, 17 Nov 1995 09:43:42 -0800 Subject: [PYTHON MATRIX-SIG] Matrix multiplies and syntactic nits In-Reply-To: <9511132005.AA02648@ling-ling.lcs.mit.edu.LCS.MIT.EDU> (message from James Hugunin on Mon, 13 Nov 95 15:05:10 -0500) Message-ID: <9511171743.AA29337@kristen.llnl.gov> Jim Hugunin wrote: > The following are 2x3 matrices of integers. > a) Matrix_i((1,2,3),(4,5,6)) > b) matrix([[1,2,3],[4,5,6]], 'i') > Opinions on which you should get with str(M)? I prefer Matrix_i. I would really prefer something explicit like IntegerMatrix, CharacterMatrix, etc, with Matrix reserved as euphemism for RealMatrix or as a "smart" constructor as I discussed before. It turns out you just don't use this kind of constructor much anyway, as most matrices are produced by array functions/operators, not literal lists. In the particular case of python there is some history having to do with using characters to represent popular types, so the present choice is reasonable and I don't feel strongly about this. "If it isn't an abbreviation, you don't have to remember which abbreviation it is." Paul ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From jjh@mama-bear.lcs.mit.edu Fri Nov 17 21:31:14 1995 From: jjh@mama-bear.lcs.mit.edu (James Hugunin) Date: Fri, 17 Nov 95 16:31:14 -0500 Subject: [PYTHON MATRIX-SIG] prototype release status report Message-ID: <9511172131.AA01814@ling-ling.lcs.mit.edu.LCS.MIT.EDU> Just to keep people informed of the current status of the next release of my matrix object (which I had been claiming would be ready last night). I read Tom's message yesterday and realized that I really need to get my matrixMultiply and transpose operators working properly ASAP. I spent most of the day today crunching code to make this happen, and it's still not quite working. The challenge is to support APL style matrixMultiply[1,2] (and permutations of that) to multiply an array of vectors by an array of matrices in the proper fashion. I should have this working sometime this weekend and then I'll make the new release available. Sorry to keep people waiting. -Jim ---------- Quick preview of the most exciting things in the next release: type coercion is implemented for matrices, ie. Matrix_i(1,2,3)*Matrix_f(1.,2.,3.) = Matrix_f(1.,4.,9.) matrix printing is now controlled by a callback to a user-settable python function for prettier matrix printing. a**b works for pow(a,b) (Thanks to Konrad) a[1,2,3] works for multidimensional indexing (Thanks to Konrad) pickling matrices works and much more. ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From et@appl-math.tu-muenchen.de Mon Nov 20 15:07:08 1995 From: et@appl-math.tu-muenchen.de (Thomas Schwaller) Date: Mon, 20 Nov 1995 16:07:08 +0100 Subject: [PYTHON MATRIX-SIG] Matrix Plot module (small announcement) Message-ID: <9511201607.ZM10265@piranha.appl-math.tu-muenchen.de> Hi folks, I promised to rewrite the plmodule for use with the matrixmodule. The next message will contain the first test version of the module. This one contains a test script and 'HOW TO BUILD' remarks. Trivial for most of us, but nevertheless... GENERAL REMARKS on plplot: (read also plmodule.c) PlPlot is certainly not the last word on Plotting (somebody should do an OpenGL plotting module!), but as a starting point it might be useful. I like it because it has a Tk widget with it. John Interrante and myself wrote it as the same time but he will not support it anymore, that's why I am doing this job... :-) I put both distributions together, but this new version is a really a new thing. All List inputs are now replaced by matrix inputs (Not backward compatible !) Could have made boths inputs (matrix and python lists ) possible, but matrix input is much faster and is the first choice here (MatLab style), so why people should use the slower lists instead? Further I added __doc__ strings everywhere (this where the previous C-comments available now with python! :-)) The Input is not realy tested. At the moment it assumes that you are doing the right thing. Comments are welcome here... I hope I well get feedback from people using that module (which was done quite fast, but I don't want let you wait! :-)) Send me as much scripts using that stuff (perhaps some Matlab alike procedures) I some people want to do the missing things, you are welcome. Mai place will be ftp://ftp.appl-math.tu-muenchen.de/pub/et/plmodule.tgz Enjoy it... Tom HOW TO BUILD: 1) PLplot is available by anonymous ftp from dino.ph.utexas.edu in the plplot/ directory. 2) Install plplot (configure it with double precision and tk support) You will get a libplplotdtk.a (or build a shared library) 3) Rebuid python with Tk and add extern int Pltk_Init(Tcl_Interp*); if (Pltk_Init(interp) == TCL_ERROR) return TCL_ERROR; in tkappinit.c and add -lplplotdtk (+ perhaps appropriate path) in Setup at the right place. 3a) Build the plmodule as shared library or as built in module. 4) Add the following to your TKinter.py class PLWin(Widget): def __init__(self, master=None, cnf={}, **kw): Widget.__init__(self, master, 'plframe', cnf, kw) class PLXWin(Widget): def __init__(self, master=None, cnf={}, **kw): Widget.__init__(self, master, 'PLXWin', cnf, kw) #! /usr/local/bin/python from pl import * from Matrix import * from Tkinter import * class Test: def plot0(self): pladv(0) plcol(1) plvpor(0.0, 1.0, 0.0, 1.0) plwind(0.0, 1.0, 0.0, 1.0) plbox("bc", 0.0, 0, "bc", 0.0, 0) plsvpa(50.0, 150.0, 100.0, 150.0) plwind(0.0, 1.0, 0.0, 1.0) plbox("bc", 0.0, 0, "bc", 0.0, 0) plptex(0.5, 0.5, 1.0, 0.0, 0.5, "BOX at (50,150,100,150)") pleop() def plot1(self): x = mrange(0.1, 6.1, 0.1) y = pow(x, 2) xs1 = zeros(6) ys1 = zeros(6) xmin, xmax = x[0], x[59] ymin, ymax = y[0], y[59] for i in range(6): xs1[i] = x[i * 10 + 3] ys1[i] = y[i * 10 + 3] plcol(1) plenv(xmin, xmax, ymin, ymax, 0, 0) plcol(2) pllab("(x)", "(y)", "#frPlot Example 1 : y=x#u2") plcol(9) plpoin(xs1, ys1, 10) plcol(4) plline(x, y) pleop() def plot2(self): plcol(1) plenv(0.0, 2*pi, -1.0, 1.0, 0, 1) plcol(2) pllab("(x)", "sin(x)", "#frPlot Example 2 : Sin Function") plcol(3) x = mrange(0, 2*pi, 2*pi/500) plline(x, sin(x)) pleop() def plot5(self): n = 2047 data = sin(mrange(0, 2*pi, 2*pi/n)) plcol(1) plhist(data, -1.1, 1.1, 44, 0) plcol(2) pllab("#frValue", "#frFrequency", "#frPlot Example 5 : Probability function of Oscillator") pleop() def plot8(self): m, n = 35, 46 x=mrange(-1, 1, 2.0/m) y=mrange(-1, 1, 2.0/n) r=sqrt(add.outer(x*x, y*y)) z=exp(-r*r)*cos(2*pi*r) pladv(0) plvpor(0.0, 1.0, 0.0, 0.9) plwind(-1.0, 1.0, -0.9, 1.1) plcol(1) plw3d(1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 60.0, 120) plbox3('bnstu', 'x axis', 0.0, 0, 'bnstu', 'y axis', 0.0, 0, 'bcdmnstuv', 'z axis', 0.0, 0) plcol(2) plplot3d(x, y, z, 3, 0) plcol(3) plmtex('t', 1.0, 0.5, 0.5, '#frPlot Example 8 : Alt=60, Az=120') pleop() def plot9(self): mypltr = lambda x, y: (2.0/34 * x -1.0, 2.0/34 * y -1.0) nx, ny = 35, 46 mark, space = 1500, 1500 clevel = Matrix(-1.0, -0.8, -0.6, -0.4, -0.2, 0.0, 0.2, 0.4, 0.6, 0.8, 1.0) x=mrange(-1, 1, 2.0/nx) y=mrange(-1, 1, 2.0/ny)-1.0 z=subtract.outer(x*x, y*y) w=multiply.outer(2*x, y) plenv(-1.0, 1.0, -1.0, 1.0, 0, 0) plcol(2) plcont(z, 1, nx, 1, ny, clevel, mypltr) plstyl(1, mark, space) plcol(3) plcont(w, 1, nx, 1, ny, clevel, mypltr) plstyl(0, mark, space) plcol(1) pllab("X Coordinate", "Y Coordinate", "Streamlines of flow") pleop() def makePlotMenu(self, mBar): Plot = Menubutton(mBar, text='Plot', underline='0') Plot.pack(side='left', padx='2m') Plot.menu = Menu(Plot) Plot.menu.add('command', label='Example0', command=self.plot0) Plot.menu.add('command', label='Example1', command=self.plot1) Plot.menu.add('command', label='Example2', command=self.plot2) #Plot.menu.add('command', label='Example3', command=self.plot3) Plot.menu.add('command', label='Example5', command=self.plot5) Plot.menu.add('command', label='Example8', command=self.plot8) Plot.menu.add('command', label='Example9', command=self.plot9) Plot.menu.add_separator() Plot.menu.add('command', label='Quit', underline='0', background='red', activebackground='green', command='exit') Plot['menu'] = Plot.menu return Plot def __init__(self, master, width=550, height=412, bg='black', relief='raised'): self.mBar = Frame(master, relief=relief, bd='2') self.mBar.pack(side='top', fill='x') self.Plot = self.makePlotMenu(self.mBar) self.glx = PLWin(master, width=`width`, height=`height`, bg=bg) self.glx.pack() self.QUIT = Button(master, text='QUIT', fg='red', command=master.quit, relief=relief) self.QUIT.pack(side='bottom', fill='both') if __name__ == '__main__': root=Tk() test = Test(root, 600, 600, 'black', 'raised') root.mainloop() ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From dubois@kristen.llnl.gov Mon Nov 20 18:18:38 1995 From: dubois@kristen.llnl.gov (P. Dubois) Date: Mon, 20 Nov 1995 10:18:38 -0800 Subject: [PYTHON MATRIX-SIG] Uniform Random Number Generator extension class Message-ID: <9511201818.AA07428@kristen.llnl.gov> On the matrix extension site I have posted URNG.tar. It has been tested with the 0.11 version of the matrix extension. This class supplies two modules: URNGmodule.c Uniform random number generator objects can be created with either a seed initialized from the clock or a seed supplied by the creating call. The random number generator objects contain methods to return either a single random number or a vector of random numbers (i.e., a Matrix of shape (n,)). The individual generators are completely independent and do not affect the stream produced by other generators. The generator is a Cray ranf() compatible generator. Ranf.py This is the interface intended for users. Here is the entire text: import URNG import Matrix # x=CreateGenerator(seed) creates an random number generator stream # seed < 0 ==> Use the default initial seed value. # seed = 0 ==> Set a "random" value for the seed from the system clock. # seed > 0 ==> Set seed directly (32 bits only). # x.ranf() samples from that stream. # x.sample(n) returns a vector from that stream. # # ranf() returns a stream of random numbers # random_sample(n) returns a vector of length n filled with random numbers # random_matrix(n,m,...) returns an arbitrarily shaped matrix filled with # random numbers. CreateGenerator = URNG.CreateGenerator standard_generator = CreateGenerator(-1) def ranf(): "Returns a single random number from the standard generator." return standard_generator.ranf() def random_sample(n): """Returns a vector of length n of random numbers from the standard generator.""" return standard_generator.sample(n) def random_matrix(*n): """Returns a matrix with shape given by n of random numbers from the standard generator.""" if not n: raise 'random_matrix cannot be an empty shape' m = 1 for i in n: m = m * i x = Matrix.reshape(random_sample(m),n) return x ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From da@maigret.cog.brown.edu Tue Nov 21 03:14:39 1995 From: da@maigret.cog.brown.edu (David Ascher) Date: Mon, 20 Nov 1995 22:14:39 -0500 (EST) Subject: [PYTHON MATRIX-SIG] Matrix Plot module (small announcement) In-Reply-To: <9511201607.ZM10265@piranha.appl-math.tu-muenchen.de> from "Thomas Schwaller" at Nov 20, 95 04:07:08 pm Message-ID: <199511210314.WAA07337@maigret> >3a) Build the plmodule as shared library or as built in module. NOTE: It is important to add the -DPL_DOUBLE flag to the plmodule line in the Setup file. Otherwise you'll end up w/ a module which works very very strangely, as I found out. =) --david ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org ================= From et@appl-math.tu-muenchen.de Mon Nov 27 17:30:28 1995 From: et@appl-math.tu-muenchen.de (Thomas Schwaller) Date: Mon, 27 Nov 1995 18:30:28 +0100 Subject: [PYTHON MATRIX-SIG] plotmodule (Matrix version 0.2) Message-ID: <9511271830.ZM22003@piranha.appl-math.tu-muenchen.de> Hi everybody, I'm just putting plplot0.2.tgz at the same place where the matrixmodule is located. Inputs are now transformed to matrices if this is possible. I really didnt test that feature up to know, because I'm just using matrices for the moment. There's also a GIF of pltest.py running on my Linux box. For that demo you need the Tix widget set. If you don't have it just use the older demo I posted to the SIG, I just love this Notebook widgets! :-) Still hoping somebody will send me some other stuff written with the matrix- and pl-modules. plplot0.2.tgz still isn't transferred! If you have a faster connection to me, you can also get it at ftp://ftp.appl-math.tu-muenchen.de/pub/et/plplot0.2.tgz Tom ================= MATRIX-SIG - SIG on Matrix Math for Python send messages to: matrix-sig@python.org administrivia to: matrix-sig-request@python.org =================