aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIOhannes m zmölnig <zmoelnig@users.sourceforge.net>2005-03-21 14:33:31 +0000
committerIOhannes m zmölnig <zmoelnig@users.sourceforge.net>2005-03-21 14:33:31 +0000
commit10b474fba485e9a93157c7fa534bb66e7bcc6fde (patch)
tree73e9e02738ea62179a1722b37ef49a9e91cfcbad
This commit was generated by cvs2svn to compensate for changes in r2637,svn2git-root
which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/iem/iemmatrix/; revision=2638
-rw-r--r--AUTHORS.txt3
-rw-r--r--CHANGES.txt3
-rw-r--r--LICENSE.txt510
-rw-r--r--VERSION.txt1
-rw-r--r--doc/matrix.pd133
-rw-r--r--doc/matrix~.pd58
-rw-r--r--doc/mtx_binops.pd142
-rw-r--r--doc/mtx_element.pd64
-rw-r--r--doc/mtx_inverse.pd18
-rw-r--r--doc/mtx_mean.pd13
-rw-r--r--doc/mtx_rand.pd20
-rw-r--r--doc/mtx_size.pd44
-rw-r--r--doc/mtx_special.pd60
-rw-r--r--doc/mtx_trace.pd24
-rw-r--r--doc/mtx_transpose.pd66
-rw-r--r--src/Makefile.in80
-rw-r--r--src/configure.in193
-rw-r--r--src/iemmatrix.c77
-rw-r--r--src/iemmatrix.h95
-rw-r--r--src/make.source1
-rw-r--r--src/mtx_binops.c680
-rw-r--r--src/mtx_check.c76
-rw-r--r--src/mtx_col.c129
-rw-r--r--src/mtx_diag.c59
-rw-r--r--src/mtx_diegg.c56
-rw-r--r--src/mtx_egg.c58
-rw-r--r--src/mtx_element.c118
-rw-r--r--src/mtx_eye.c60
-rw-r--r--src/mtx_inverse.c118
-rw-r--r--src/mtx_matrix.c606
-rw-r--r--src/mtx_mean.c61
-rw-r--r--src/mtx_ones.c56
-rw-r--r--src/mtx_pivot.c171
-rw-r--r--src/mtx_print.c60
-rw-r--r--src/mtx_rand.c93
-rw-r--r--src/mtx_resize.c103
-rw-r--r--src/mtx_roll.c73
-rw-r--r--src/mtx_row.c120
-rw-r--r--src/mtx_scroll.c59
-rw-r--r--src/mtx_size.c54
-rw-r--r--src/mtx_tilde.c413
-rw-r--r--src/mtx_trace.c57
-rw-r--r--src/mtx_transpose.c67
-rw-r--r--src/mtx_zeros.c56
44 files changed, 5008 insertions, 0 deletions
diff --git a/AUTHORS.txt b/AUTHORS.txt
new file mode 100644
index 0000000..8829584
--- /dev/null
+++ b/AUTHORS.txt
@@ -0,0 +1,3 @@
+iohannes m zmoelnig <zmoelnig@iem.at>
+thomas musil <musilt@iem.at>
+
diff --git a/CHANGES.txt b/CHANGES.txt
new file mode 100644
index 0000000..6786aaf
--- /dev/null
+++ b/CHANGES.txt
@@ -0,0 +1,3 @@
+0.1: (jmz, 21.03.2005)
+ * forked from zexy
+
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..b124cf5
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,510 @@
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations
+below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it
+becomes a de-facto standard. To achieve this, non-free programs must
+be allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control
+compilation and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at least
+ three years, to give the same user the materials specified in
+ Subsection 6a, above, for a charge no more than the cost of
+ performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply, and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License
+may add an explicit geographical distribution limitation excluding those
+countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms
+of the ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library.
+It is safest to attach them to the start of each source file to most
+effectively convey the exclusion of warranty; and each file should
+have at least the "copyright" line and a pointer to where the full
+notice is found.
+
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or
+your school, if any, to sign a "copyright disclaimer" for the library,
+if necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James
+ Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/VERSION.txt b/VERSION.txt
new file mode 100644
index 0000000..49d5957
--- /dev/null
+++ b/VERSION.txt
@@ -0,0 +1 @@
+0.1
diff --git a/doc/matrix.pd b/doc/matrix.pd
new file mode 100644
index 0000000..a1c6332
--- /dev/null
+++ b/doc/matrix.pd
@@ -0,0 +1,133 @@
+#N canvas 94 0 1118 745 10;
+#X obj 258 -23 matrix;
+#X obj 61 187 mtx_check;
+#X obj 61 216 mtx_print;
+#X obj 544 -21 mtx;
+#X obj 30 535 mtx_print;
+#X obj 30 513 matrix;
+#X msg 42 372 zeros 5;
+#X msg 30 353 eye 3;
+#X msg 49 390 ones 4;
+#X msg 55 411 diag 1 2 3 4;
+#X obj 369 531 matrix;
+#X obj 471 496 loadbang;
+#X obj 471 516 mtx_diag 4 3 1 2;
+#X obj 369 553 print;
+#X msg 369 364 row;
+#X msg 539 497 bang;
+#X msg 379 404 row \$1;
+#X floatatom 379 385 4 0 0;
+#X floatatom 391 424 4 0 0;
+#X msg 391 443 row \$1 1 2 3 4;
+#X floatatom 498 382 4 0 0;
+#X floatatom 510 421 4 0 0;
+#X msg 488 362 col;
+#X msg 498 401 col \$1;
+#X msg 510 440 col \$1 1 2 3 4;
+#X msg 592 364 element;
+#X msg 623 406 element \$1;
+#X floatatom 643 428 4 0 0;
+#X msg 643 447 element 3 \$1;
+#X floatatom 623 386 4 0 0;
+#X msg 61 162 matrix 3 3 1 2 3 4 5 6 7;
+#X msg 39 136 matrix 3 3 1 2 3 4 5 6 7;
+#X text 43 79 this is \, how a matrix really looks...;
+#X text 216 134 an "illegal" matrix;
+#X text 122 187 make the "illegal" matrix consistent;
+#X text 216 103 a "legal" matrix;
+#X msg 40 103 matrix 3 3 1 2 3 1 2 4 7 6 5;
+#X obj 590 218 mtx_print;
+#X obj 590 196 matrix;
+#X obj 655 174 mtx_ones 10;
+#X msg 655 154 bang;
+#X text 121 218 print to stderr (like "print");
+#X msg 590 64 bang;
+#X floatatom 615 103 4 0 0;
+#X msg 604 85 matrix 2 3 10 10 30 20 -5 8;
+#X msg 627 126 1 2 3 1 2 3 10 20 30;
+#X text 758 118 a list of elements;
+#X text 759 132 has to fit the size of the "current" matrix;
+#X text 651 104 set all elements of the current matrix to a value;
+#X text 366 345 get/set rows;
+#X text 479 344 get/set columns;
+#X text 5 564 create various matrices;
+#X text 356 -21 matrix operations;
+#X text 636 197 ==;
+#X obj 660 197 mtx;
+#X msg 335 398 bang;
+#X text 586 344 get/set elements;
+#X msg 654 486 element \$1 2 10;
+#X floatatom 654 468 4 0 0;
+#X msg 702 406 element \$1 \$1;
+#X text 687 406 ==;
+#X obj 161 479 matrix 3 2;
+#X obj 161 525 mtx_print;
+#X msg 161 357 bang;
+#X text 143 542 an "empty" [3 \, 2] matrix;
+#X msg 73 433 egg 4;
+#X msg 75 455 diegg 3 2 1;
+#X obj 126 671 mtx_element;
+#X obj 225 646 mtx_size;
+#X obj 225 669 mtx_transpose;
+#X obj 427 650 mtx_mean;
+#X obj 427 669 mtx_rand;
+#X obj 338 670 mtx_inverse;
+#X obj 126 646 mtx_eye;
+#X obj 338 645 mtx_+;
+#X text 127 620 see also help for:;
+#X msg 912 383 write /tmp/my_matrix.mtx;
+#X msg 912 406 read /tmp/my_matrix.mtx;
+#X obj 810 412 mtx_rand;
+#X msg 810 390 4 5;
+#X msg 858 389 bang;
+#X obj 858 464 mtx_print;
+#X text 848 351 load and save matrices;
+#X obj 858 440 matrix test.mtx;
+#X connect 1 0 2 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 0;
+#X connect 7 0 5 0;
+#X connect 8 0 5 0;
+#X connect 9 0 5 0;
+#X connect 10 0 13 0;
+#X connect 11 0 12 0;
+#X connect 12 0 10 1;
+#X connect 14 0 10 0;
+#X connect 15 0 12 0;
+#X connect 16 0 10 0;
+#X connect 17 0 16 0;
+#X connect 18 0 19 0;
+#X connect 19 0 10 0;
+#X connect 20 0 23 0;
+#X connect 21 0 24 0;
+#X connect 22 0 10 0;
+#X connect 23 0 10 0;
+#X connect 24 0 10 0;
+#X connect 25 0 10 0;
+#X connect 26 0 10 0;
+#X connect 27 0 28 0;
+#X connect 28 0 10 0;
+#X connect 29 0 26 0;
+#X connect 30 0 1 0;
+#X connect 31 0 2 0;
+#X connect 36 0 2 0;
+#X connect 38 0 37 0;
+#X connect 39 0 38 1;
+#X connect 40 0 39 0;
+#X connect 42 0 38 0;
+#X connect 43 0 38 0;
+#X connect 44 0 38 0;
+#X connect 45 0 38 0;
+#X connect 55 0 10 0;
+#X connect 57 0 10 0;
+#X connect 58 0 57 0;
+#X connect 61 0 62 0;
+#X connect 63 0 61 0;
+#X connect 65 0 5 0;
+#X connect 66 0 5 0;
+#X connect 76 0 83 0;
+#X connect 77 0 83 0;
+#X connect 78 0 83 0;
+#X connect 79 0 78 0;
+#X connect 80 0 83 0;
+#X connect 83 0 81 0;
diff --git a/doc/matrix~.pd b/doc/matrix~.pd
new file mode 100644
index 0000000..5b0fa07
--- /dev/null
+++ b/doc/matrix~.pd
@@ -0,0 +1,58 @@
+#N canvas 59 -12 889 589 12;
+#X obj 68 271 osc~ 100;
+#X obj 68 297 *~ 0.2;
+#X obj 112 320 osc~ 1000;
+#X obj 112 346 *~ 1.5;
+#X obj 157 295 osc~ 432;
+#X obj 68 411 env~;
+#X floatatom 68 435 4 0 0;
+#X obj 127 410 env~;
+#X floatatom 127 434 4 0 0;
+#X obj 187 410 env~;
+#X floatatom 187 434 4 0 0;
+#X obj 247 409 env~;
+#X floatatom 247 433 4 0 0;
+#X floatatom 284 350 4 0 0;
+#X text 332 353 fade time in [ms];
+#X msg 265 100 bang;
+#X obj 265 127 mtx_eye 3 4;
+#X msg 362 100 bang;
+#X obj 362 127 mtx_egg 3 4;
+#X msg 261 179 bang;
+#X msg 362 178 bang;
+#X obj 261 206 mtx_ones 3 4;
+#X obj 362 205 mtx_zeros 3 4;
+#X obj 68 371 matrix~ 3 4 100 .......;
+#X obj 98 32 matrix~;
+#X text 174 24 matrix-multiply m IN~signals to n OUT~signals;
+#X text 174 37 matrices are interpolated a la line~;
+#X text 473 91 the one-before-last inlet eats;
+#X text 476 104 matrix-messages to control the gains;
+#X text 475 117 of the matrix~;
+#X text 484 333 the last inlet gets the fade-time between two matrix-messages.
+;
+#X obj 78 505 matrix~;
+#X text 154 503 creation: "matrix~ [<num_in> [<num_out> [<fade_time>]]]
+;
+#X connect 0 0 1 0;
+#X connect 1 0 23 0;
+#X connect 2 0 3 0;
+#X connect 3 0 23 1;
+#X connect 4 0 23 2;
+#X connect 5 0 6 0;
+#X connect 7 0 8 0;
+#X connect 9 0 10 0;
+#X connect 11 0 12 0;
+#X connect 13 0 23 4;
+#X connect 15 0 16 0;
+#X connect 16 0 23 3;
+#X connect 17 0 18 0;
+#X connect 18 0 23 3;
+#X connect 19 0 21 0;
+#X connect 20 0 22 0;
+#X connect 21 0 23 3;
+#X connect 22 0 23 3;
+#X connect 23 0 5 0;
+#X connect 23 1 7 0;
+#X connect 23 2 9 0;
+#X connect 23 3 11 0;
diff --git a/doc/mtx_binops.pd b/doc/mtx_binops.pd
new file mode 100644
index 0000000..a0ae6d0
--- /dev/null
+++ b/doc/mtx_binops.pd
@@ -0,0 +1,142 @@
+#N canvas 79 32 859 673 10;
+#X obj 87 360 mtx_mul;
+#X obj 157 360 mtx_*;
+#X obj 88 163 mtx_add;
+#X obj 167 166 mtx_+;
+#X obj 155 134 mtx_diag 1 2 3 4 5;
+#X obj 88 134 mtx_ones 5;
+#X obj 88 111 t b b;
+#X obj 88 185 mtx_print;
+#X msg 88 92 bang;
+#X text 142 165 ==;
+#X obj 305 134 mtx_eye 4;
+#X obj 305 159 mtx_add 10;
+#X msg 305 107 bang;
+#X obj 305 186 mtx_print;
+#X floatatom 374 101 4 0 0 0 - - -;
+#X obj 374 119 t b f;
+#X obj 392 160 mtx_+ 10;
+#X text 371 161 ==;
+#X obj 87 394 mtx_print;
+#X msg 87 270 bang;
+#X obj 133 332 mtx_diag 1 2;
+#X obj 87 297 t b b;
+#X obj 87 332 mtx_+ 3;
+#X text 137 361 ==;
+#X obj 87 314 mtx_eye 3 2;
+#X obj 249 399 mtx_print;
+#X obj 249 292 t b f;
+#X floatatom 249 274 4 0 0 0 - - -;
+#X msg 249 315 4 2 1 3;
+#X obj 249 335 mtx_diag;
+#X obj 249 363 mtx_mul 2;
+#X obj 328 363 mtx_* 2;
+#X obj 393 363 mtx_.* 2;
+#X text 310 363 ==;
+#X text 376 364 ==;
+#X obj 522 366 mtx_.*;
+#X obj 522 401 mtx_print;
+#X obj 522 304 mtx_diag 1 2 3;
+#X obj 553 322 mtx_ones 3;
+#X obj 522 283 t b b;
+#X msg 522 264 bang;
+#X obj 553 341 mtx_* 2;
+#X text 80 214 add 2 matrices;
+#X text 274 218 add an offset to a matrix;
+#X text 70 423 multiply 2 matrices;
+#X text 245 422 multiply a matrix with a scalar;
+#X text 506 425 multiply 2 matrices element by element;
+#X text 334 19 matrix arithmetic;
+#X obj 88 599 mtx_print;
+#X obj 88 492 t b f;
+#X floatatom 88 474 4 0 0 0 - - -;
+#X msg 88 515 4 2 1 3;
+#X obj 88 535 mtx_diag;
+#X obj 323 600 mtx_print;
+#X obj 323 503 mtx_diag 1 2 3;
+#X obj 354 521 mtx_ones 3;
+#X obj 354 540 mtx_* 2;
+#X text 84 622 divide a matrix by a scalar;
+#X obj 88 563 mtx_./ 2;
+#X obj 323 565 mtx_./;
+#X text 307 624 divide 2 matrices element by element;
+#X obj 323 482 t b b f;
+#X floatatom 323 463 4 0 0 0 - - -;
+#X obj 709 538 matrix;
+#X text 592 538 see also help for;
+#X obj 550 141 mtx_diag 1 2 3 4 5;
+#X obj 483 141 mtx_ones 5;
+#X obj 483 118 t b b;
+#X obj 483 192 mtx_print;
+#X msg 483 99 bang;
+#X text 537 172 ==;
+#X obj 700 141 mtx_eye 4;
+#X msg 700 114 bang;
+#X obj 700 193 mtx_print;
+#X floatatom 769 108 4 0 0 0 - - -;
+#X obj 769 126 t b f;
+#X text 762 168 ==;
+#X obj 483 170 mtx_sub;
+#X obj 562 173 mtx_-;
+#X obj 779 169 mtx_sub 10;
+#X obj 700 166 mtx_- 10;
+#X text 481 221 subtract 2 matrices;
+#X text 669 225 subtract an offset from a matrix;
+#X connect 0 0 18 0;
+#X connect 2 0 7 0;
+#X connect 4 0 2 1;
+#X connect 5 0 2 0;
+#X connect 6 0 5 0;
+#X connect 6 1 4 0;
+#X connect 8 0 6 0;
+#X connect 10 0 11 0;
+#X connect 11 0 13 0;
+#X connect 12 0 10 0;
+#X connect 14 0 15 0;
+#X connect 15 0 10 0;
+#X connect 15 1 11 1;
+#X connect 19 0 21 0;
+#X connect 20 0 0 1;
+#X connect 21 0 24 0;
+#X connect 21 1 20 0;
+#X connect 22 0 0 0;
+#X connect 24 0 22 0;
+#X connect 26 0 28 0;
+#X connect 26 1 30 1;
+#X connect 27 0 26 0;
+#X connect 28 0 29 0;
+#X connect 29 0 30 0;
+#X connect 30 0 25 0;
+#X connect 35 0 36 0;
+#X connect 37 0 35 0;
+#X connect 38 0 41 0;
+#X connect 39 0 37 0;
+#X connect 39 1 38 0;
+#X connect 40 0 39 0;
+#X connect 41 0 35 1;
+#X connect 49 0 51 0;
+#X connect 49 1 58 1;
+#X connect 50 0 49 0;
+#X connect 51 0 52 0;
+#X connect 52 0 58 0;
+#X connect 54 0 59 0;
+#X connect 55 0 56 0;
+#X connect 56 0 59 1;
+#X connect 58 0 48 0;
+#X connect 59 0 53 0;
+#X connect 61 0 54 0;
+#X connect 61 1 55 0;
+#X connect 61 2 56 1;
+#X connect 62 0 61 0;
+#X connect 65 0 77 1;
+#X connect 66 0 77 0;
+#X connect 67 0 66 0;
+#X connect 67 1 65 0;
+#X connect 69 0 67 0;
+#X connect 71 0 80 0;
+#X connect 72 0 71 0;
+#X connect 74 0 75 0;
+#X connect 75 0 71 0;
+#X connect 75 1 80 1;
+#X connect 77 0 68 0;
+#X connect 80 0 73 0;
diff --git a/doc/mtx_element.pd b/doc/mtx_element.pd
new file mode 100644
index 0000000..a69e642
--- /dev/null
+++ b/doc/mtx_element.pd
@@ -0,0 +1,64 @@
+#N canvas 220 134 544 776 10;
+#X obj 53 302 mtx_print;
+#X obj 53 283 mtx_element 4 3;
+#X obj 64 260 mtx_ones 5 3;
+#X msg 64 241 bang;
+#X floatatom 53 191 4 0 0;
+#X msg 138 184 3 2;
+#X msg 144 202 2 0;
+#X msg 144 219 0 1;
+#X msg 145 237 0 0;
+#X text 179 184 set element [3 \, 2];
+#X text 179 202 set all elements in row [2];
+#X text 177 217 set all elements in column [1];
+#X text 178 236 set all elements of matrix;
+#X text 153 285 creation: mtx_element [<row> <col> [<posR> <posC>]];
+#X obj 53 469 mtx_print;
+#X obj 64 427 mtx_ones 5 3;
+#X msg 64 408 bang;
+#X obj 53 450 mtx_row 4 3;
+#X msg 122 405 0;
+#X text 153 405 set all rows;
+#X msg 114 383 2;
+#X text 154 380 set row [2];
+#X msg 53 356 -1 2 3 4 5;
+#X obj 50 658 mtx_print;
+#X obj 61 616 mtx_ones 5 3;
+#X msg 61 597 bang;
+#X msg 131 592 0;
+#X msg 123 570 2;
+#X msg 50 545 -1 2 3 4 5;
+#X obj 50 639 mtx_col 4 3 3;
+#X text 163 567 set column [2];
+#X text 162 593 set all columns;
+#X text 137 640 creation: mtx_col [<row> <col> [<posC>]];
+#X text 133 452 creation: mtx_row [<row> <col> [<posR>]];
+#X text 52 163 set matrix elements;
+#X text 55 339 set matrix rows;
+#X text 49 529 set matrix columns;
+#X text 187 50 get/set elements/rows/columns of a matrix;
+#X obj 90 33 mtx_element;
+#X obj 89 53 mtx_row;
+#X obj 90 75 mtx_col;
+#X obj 210 738 matrix;
+#X text 98 737 see also help for;
+#X connect 1 0 0 0;
+#X connect 2 0 1 0;
+#X connect 3 0 2 0;
+#X connect 4 0 1 0;
+#X connect 5 0 1 1;
+#X connect 6 0 1 1;
+#X connect 7 0 1 1;
+#X connect 8 0 1 1;
+#X connect 15 0 17 0;
+#X connect 16 0 15 0;
+#X connect 17 0 14 0;
+#X connect 18 0 17 1;
+#X connect 20 0 17 1;
+#X connect 22 0 17 0;
+#X connect 24 0 29 0;
+#X connect 25 0 24 0;
+#X connect 26 0 29 1;
+#X connect 27 0 29 1;
+#X connect 28 0 29 0;
+#X connect 29 0 23 0;
diff --git a/doc/mtx_inverse.pd b/doc/mtx_inverse.pd
new file mode 100644
index 0000000..9cca9fe
--- /dev/null
+++ b/doc/mtx_inverse.pd
@@ -0,0 +1,18 @@
+#N canvas 50 156 465 427 10;
+#X obj 92 208 mtx_inverse;
+#X obj 92 292 mtx_print;
+#X msg 103 140 matrix 3 3 1 2 3 2 3 4 3 4 5;
+#X text 280 142 singular;
+#X msg 92 108 matrix 3 3 1 2 4 2 3 4 3 4 5;
+#X text 265 107 regular;
+#X text 85 310 get the inverse of a matrix;
+#X text 286 158 regular;
+#X text 287 168 but badly conditioned;
+#X msg 111 164 matrix 3 3 1 2 3 2 4 4 3 4 5;
+#X text 82 26 get the inverse of a matrix;
+#X obj 233 381 matrix;
+#X text 116 381 see also help for;
+#X connect 0 0 1 0;
+#X connect 2 0 0 0;
+#X connect 4 0 0 0;
+#X connect 9 0 0 0;
diff --git a/doc/mtx_mean.pd b/doc/mtx_mean.pd
new file mode 100644
index 0000000..02b02fb
--- /dev/null
+++ b/doc/mtx_mean.pd
@@ -0,0 +1,13 @@
+#N canvas 128 104 450 300 10;
+#X obj 57 146 mtx_mean;
+#X obj 63 91 mtx_print;
+#X obj 57 201 print mean_row;
+#X obj 57 76 mtx_rand;
+#X msg 57 52 4 5;
+#X text 55 229 get the mean value of each column;
+#X obj 175 275 matrix;
+#X text 58 275 see also help for;
+#X connect 0 0 2 0;
+#X connect 3 0 1 0;
+#X connect 3 0 0 0;
+#X connect 4 0 3 0;
diff --git a/doc/mtx_rand.pd b/doc/mtx_rand.pd
new file mode 100644
index 0000000..491d6de
--- /dev/null
+++ b/doc/mtx_rand.pd
@@ -0,0 +1,20 @@
+#N canvas 120 116 450 300 10;
+#X obj 59 148 mtx_rand;
+#X obj 59 194 mtx_print;
+#X obj 83 100 mtx_ones 6 3;
+#X msg 83 82 bang;
+#X msg 74 58 5 7;
+#X msg 59 35 3;
+#X msg 115 133 seed 12;
+#X text 51 219 get a matrix containing;
+#X text 51 232 random elements (0..1];
+#X text 165 131 set seed;
+#X obj 357 274 matrix;
+#X text 240 274 see also help for;
+#X text 129 11 fill a matrix with random values;
+#X connect 0 0 1 0;
+#X connect 2 0 0 0;
+#X connect 3 0 2 0;
+#X connect 4 0 0 0;
+#X connect 5 0 0 0;
+#X connect 6 0 0 0;
diff --git a/doc/mtx_size.pd b/doc/mtx_size.pd
new file mode 100644
index 0000000..85d7747
--- /dev/null
+++ b/doc/mtx_size.pd
@@ -0,0 +1,44 @@
+#N canvas 161 60 833 285 10;
+#X obj 386 214 mtx_print;
+#X obj 386 106 mtx_ones;
+#X msg 386 83 3 5;
+#X obj 386 192 mtx_resize;
+#X text 383 67 resize a matrix;
+#X msg 441 91 3 2;
+#X msg 447 109 2 0;
+#X msg 448 144 0 0;
+#X text 482 91 resize to [3 \, 2];
+#X text 482 109 resize to 2 rows \, leave row-length unchanged;
+#X text 481 143 don't resize;
+#X msg 452 169 2;
+#X text 484 171 resize to [2 \, 2];
+#X text 458 192 creation: mtx_resize [<rows> [<cols>]];
+#X msg 447 126 0 4;
+#X text 482 124 resize to 4 columns \, leave column-length unchanged;
+#X floatatom 81 178 4 0 0;
+#X text 78 68 get the size of a matrix;
+#X obj 81 140 mtx_size;
+#X msg 115 91 3 2;
+#X msg 81 91 7;
+#X obj 81 115 mtx_ones;
+#X floatatom 124 178 4 0 0;
+#X text 122 194 columns;
+#X text 82 195 rows;
+#X obj 150 22 mtx_size;
+#X obj 421 23 mtx_resize;
+#X text 223 24 get/set the size of a matrix;
+#X obj 306 252 matrix;
+#X text 189 252 see also help for;
+#X connect 1 0 3 0;
+#X connect 2 0 1 0;
+#X connect 3 0 0 0;
+#X connect 5 0 3 1;
+#X connect 6 0 3 1;
+#X connect 7 0 3 1;
+#X connect 11 0 3 1;
+#X connect 14 0 3 1;
+#X connect 18 0 16 0;
+#X connect 18 1 22 0;
+#X connect 19 0 21 0;
+#X connect 20 0 21 0;
+#X connect 21 0 18 0;
diff --git a/doc/mtx_special.pd b/doc/mtx_special.pd
new file mode 100644
index 0000000..b230a0f
--- /dev/null
+++ b/doc/mtx_special.pd
@@ -0,0 +1,60 @@
+#N canvas 113 77 498 667 10;
+#X obj 117 136 mtx_eye 5;
+#X obj 117 162 mtx_print;
+#X msg 117 65 bang;
+#X msg 147 109 3 5;
+#X msg 133 85 10;
+#X obj 120 332 mtx_print;
+#X msg 120 234 bang;
+#X msg 150 279 3 5;
+#X msg 136 255 10;
+#X obj 311 337 mtx_print;
+#X msg 311 239 bang;
+#X msg 341 284 3 5;
+#X msg 327 260 10;
+#X obj 120 306 mtx_ones 5;
+#X obj 311 311 mtx_zeros 5;
+#X obj 124 496 mtx_print;
+#X msg 136 417 1 2 3 4 5;
+#X msg 124 395 bang;
+#X obj 124 468 mtx_diag 7 6 5 4;
+#X text 93 181 identity matrix;
+#X text 104 358 all matrix elements=1;
+#X text 290 359 all matrix elements=0;
+#X text 113 522 diagonal-matrix;
+#X obj 333 162 mtx_print;
+#X msg 333 65 bang;
+#X msg 363 109 3 5;
+#X msg 349 85 10;
+#X obj 333 136 mtx_egg 5;
+#X obj 316 491 mtx_print;
+#X msg 328 412 1 2 3 4 5;
+#X msg 316 390 bang;
+#X obj 316 463 mtx_diegg 7 6 5 4;
+#X text 305 517 turned diagonal-matrix;
+#X text 309 181 turned identity matrix;
+#X text 173 19 create special matrices;
+#X obj 245 612 matrix;
+#X text 128 612 see also help for;
+#X connect 0 0 1 0;
+#X connect 2 0 0 0;
+#X connect 3 0 0 0;
+#X connect 4 0 0 0;
+#X connect 6 0 13 0;
+#X connect 7 0 13 0;
+#X connect 8 0 13 0;
+#X connect 10 0 14 0;
+#X connect 11 0 14 0;
+#X connect 12 0 14 0;
+#X connect 13 0 5 0;
+#X connect 14 0 9 0;
+#X connect 16 0 18 0;
+#X connect 17 0 18 0;
+#X connect 18 0 15 0;
+#X connect 24 0 27 0;
+#X connect 25 0 27 0;
+#X connect 26 0 27 0;
+#X connect 27 0 23 0;
+#X connect 29 0 31 0;
+#X connect 30 0 31 0;
+#X connect 31 0 28 0;
diff --git a/doc/mtx_trace.pd b/doc/mtx_trace.pd
new file mode 100644
index 0000000..ad48fd8
--- /dev/null
+++ b/doc/mtx_trace.pd
@@ -0,0 +1,24 @@
+#N canvas 137 140 916 465 10;
+#X obj 79 361 mtx_diag;
+#X obj 79 389 print;
+#X obj 79 308 mtx_ones 7;
+#X msg 79 288 bang;
+#X obj 84 106 mtx_ones 7;
+#X msg 84 83 bang;
+#X obj 84 147 mtx_trace;
+#X floatatom 84 189 4 0 0 0 - - -;
+#X text 86 68 get trace of a matrix;
+#X text 79 271 get diagonal of a matrix;
+#X text 81 204 trace = sum(diagonal elements);
+#X text 243 28 get information of the diagonale of a matrix;
+#X text 440 176 see also help for;
+#X obj 571 175 matrix;
+#X obj 699 269 mtx_eye;
+#X text 332 270 to create diagonale matrices with [mtx_diag] \, see
+;
+#X connect 0 0 1 0;
+#X connect 2 0 0 0;
+#X connect 3 0 2 0;
+#X connect 4 0 6 0;
+#X connect 5 0 4 0;
+#X connect 6 0 7 0;
diff --git a/doc/mtx_transpose.pd b/doc/mtx_transpose.pd
new file mode 100644
index 0000000..afe5c7b
--- /dev/null
+++ b/doc/mtx_transpose.pd
@@ -0,0 +1,66 @@
+#N canvas 199 -133 718 600 10;
+#X obj 48 162 mtx_print;
+#X obj 48 134 mtx_transpose;
+#X obj 48 81 mtx_ones;
+#X msg 48 59 3 5;
+#X text 45 42 transpose a matrix;
+#X text 188 7 tranpose/shift matrices;
+#X obj 37 349 mtx_print;
+#X msg 37 246 1 2 3 4 5;
+#X text 33 229 shift rows of a matrix;
+#X floatatom 104 301 4 0 0 0 - - -;
+#X obj 37 321 mtx_scroll 1;
+#X obj 37 268 mtx_diag;
+#X obj 414 333 mtx_print;
+#X msg 414 230 1 2 3 4 5;
+#X floatatom 481 285 4 0 0 0 - - -;
+#X obj 414 252 mtx_diag;
+#X text 410 213 shift columns of a matrix;
+#X obj 414 306 mtx_roll 1;
+#X text 517 286 shift amount (0=no-shift \; 1=1-column-right \; -2=2-columns-left
+\; ...);
+#X text 143 299 shift amount (0=no-shift \; 1=1-row-down \; -2=2-rows-up
+\; ...);
+#X text 29 419 pivot-transform a matrix;
+#X obj 33 494 mtx_pivot;
+#N canvas 352 114 190 367 rand-matrix 0;
+#X obj 74 163 inlet;
+#X obj 74 270 outlet;
+#X obj 74 195 mtx_rand;
+#X obj 74 215 mtx_* 10;
+#X obj 74 237 l2i;
+#X connect 0 0 2 0;
+#X connect 2 0 3 0;
+#X connect 3 0 4 0;
+#X connect 4 0 1 0;
+#X restore 33 458 pd rand-matrix;
+#X msg 33 436 4 3;
+#X obj 82 515 mtx_print post;
+#X obj 57 535 mtx_print pre;
+#X obj 33 575 mtx_print pivot;
+#X obj 485 95 matrix;
+#X text 435 77 see also help for;
+#X text 280 494 the first outlet is the pivot-transformed matrix.;
+#X text 279 520 the other outlets are the 1/0-matrices that have to
+be pre-multiplied (row-tranform) and post-multiplied (column-tranform)
+to the original matrix to get the pivot-tranformation. this is useful
+for de-pivoting.;
+#X text 281 445 this will tranform the columns and rows \, so that
+the result will have all maximum values in the diagonale. the maximum
+of the matrix will be located at the upper-left corner.;
+#X connect 1 0 0 0;
+#X connect 2 0 1 0;
+#X connect 3 0 2 0;
+#X connect 7 0 11 0;
+#X connect 9 0 10 1;
+#X connect 10 0 6 0;
+#X connect 11 0 10 0;
+#X connect 13 0 15 0;
+#X connect 14 0 17 1;
+#X connect 15 0 17 0;
+#X connect 17 0 12 0;
+#X connect 21 0 26 0;
+#X connect 21 1 25 0;
+#X connect 21 2 24 0;
+#X connect 22 0 21 0;
+#X connect 23 0 22 0;
diff --git a/src/Makefile.in b/src/Makefile.in
new file mode 100644
index 0000000..bbb76c5
--- /dev/null
+++ b/src/Makefile.in
@@ -0,0 +1,80 @@
+LIBNAME =iemmatrix
+
+PREFIX =@prefix@@PDLIBDIR@
+
+INSTALL_BIN=$(PREFIX)/extra
+INSTALL_DOC=$(PREFIX)/@REFERENCEPATH@$(LIBNAME)
+
+EXT = @EXT@
+DEFS = @DFLAGS@
+IFLAGS = -I. @INCLUDES@
+
+CC = @CC@
+LD = @LD@
+AFLAGS =
+LFLAGS = @LFLAGS@
+WFLAGS =
+
+TARNAME = $(LIBNAME)-@IEMMATRIX_VERSION@.tgz
+
+.SUFFIXES: .$(EXT)
+
+PDCFLAGS = -g -O2 $(DEFS) $(IFLAGS) $(WFLAGS) $(LFLAGS) $(AFLAGS)
+CFLAGS = -g -O2 $(DEFS) $(IFLAGS) $(WFLAGS)
+
+LIBS = @LIBS@
+#LIBS = -lpthread -lm -lc
+include Make.source
+TARGETS = $(SOURCES:.c=.o)
+
+
+all: $(LIBNAME)
+ cp $(LIBNAME).$(EXT) ..
+
+$(LIBNAME): $(TARGETS)
+ $(LD) $(LFLAGS) -o $(LIBNAME).$(EXT) *.o $(LIBS)
+ strip @STRIPFLAGS@ $(LIBNAME).$(EXT)
+
+.c.o:
+ $(CC) -c -o $@ $(CFLAGS) -DPD $*.c
+
+# cp $@ $*_stat.o
+
+.o.$(EXT):
+ $(CC) -o $@ $(PDCFLAGS) -DPD $*.o
+
+
+clean:
+ -rm -f *.$(EXT) *.o
+
+cleaner: clean
+ -rm -f *~ _* config.*
+
+cleanest: cleaner
+ -rm -f Makefile ../*.$(EXT) Make.source
+
+distclean: cleanest newmakefile
+
+install: install-bin install-doc
+
+install-bin:
+ -install -d $(INSTALL_BIN)
+ -install -m 644 $(LIBNAME).$(EXT) $(INSTALL_BIN)
+
+install-doc:
+ -install -d $(INSTALL_DOC)
+ -install -m 644 ../doc/*.pd $(INSTALL_DOC)
+
+dist: all cleaner
+ (cd ../..;tar czvf $(TARNAME) $(LIBNAME))
+
+everything: clean all install distclean
+
+newmakefile:
+ echo "current:">Makefile
+ echo " ./configure && make">>Makefile
+
+source:
+ echo "SOURCES = \\"> Make.source
+ echo `ls mtx_*.c $(LIBNAME).c` >> Make.source
+ echo >> Make.source
diff --git a/src/configure.in b/src/configure.in
new file mode 100644
index 0000000..9afbf9e
--- /dev/null
+++ b/src/configure.in
@@ -0,0 +1,193 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(iemmatrix.c)
+
+dnl Checks for programs.
+AC_PROG_CC
+
+AC_SUBST(STK)
+AC_SUBST(DFLAGS)
+AC_SUBST(LFLAGS)
+AC_SUBST(EXT)
+AC_SUBST(LD)
+AC_SUBST(STRIPFLAGS)
+AC_SUBST(IEMMATRIX_VERSION)
+AC_SUBST(REFERENCEPATH)
+AC_SUBST(PDLIBDIR)
+AC_SUBST(INCLUDES)
+AC_SUBST(SOURCES)
+
+
+AC_ARG_WITH(pdversion, [ --with-pdversion=<ver> enforce a certain pd-version (e.g. 0.37)])
+
+if test $includedir
+then
+ for id in $includedir
+ do
+ if test -d $id
+ then
+ INCLUDES="-I$id $INCLUDES"
+ fi
+ done
+fi
+
+dnl Checks for libraries.
+dnl Replace `main' with a function in -lc:
+AC_CHECK_LIB(c, main)
+dnl Replace `main' with a function in -lm:
+AC_CHECK_LIB(m, main)
+dnl Replace `main' with a function in -lpthread:
+dnl AC_CHECK_LIB(pthread, main)
+dnl Replace `main' with a function in -lstk:
+dnl AC_CHECK_LIB(stk, main, STK=yes)
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS(stdlib.h stdio.h string.h math.h time.h sys/time.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_HEADER_TIME
+
+dnl Checks for library functions.
+AC_FUNC_MMAP
+AC_CHECK_FUNCS(select socket strerror)
+
+
+LD=ld
+DFLAGS=""
+
+dnl
+dnl OK, checks for machines are here now
+dnl
+if test `uname -s` = Linux;
+then
+ LFLAGS="-export_dynamic -shared"
+ EXT=pd_linux
+ STRIPFLAGS="--strip-unneeded"
+fi
+
+dnl This should use '-bundle_loader /path/to/pd/bin/pd' instead of'-undefined suppress'
+dnl then strip might do something
+if test `uname -s` = Darwin;
+then
+ LD=cc
+ LFLAGS="-bundle -undefined suppress -flat_namespace"
+ EXT=pd_darwin
+ STRIPFLAGS=
+ if test "$enable_lpt" = "yes"; then
+ AC_MSG_ERROR("lpt not supported on this platform");
+ fi
+ if test "$enable_lpt" = ""; then
+ AC_MSG_WARN("lpt not supported on this platform - disabling");
+ enable_lpt="no";
+ fi
+fi
+if test `uname | sed -e 's/^MINGW.*/NT/'` = NT;
+then
+ LD=gcc
+ INCLUDES="-I@prefix@/src"
+ DFLAGS="-DMSW -DNT"
+ LFLAGS="-shared @prefix@/bin/pd.dll"
+ EXT=dll
+else
+ PDLIBDIR="/lib/pd"
+ LIBS="-lc -lm"
+fi
+if test `uname -s` = IRIX64;
+then
+ LFLAGS="-n32 -DUNIX -DIRIX -DN32 -woff 1080,1064,1185 \
+ -OPT:roundoff=3 -OPT:IEEE_arithmetic=3 -OPT:cray_ivdep=true \
+ -shared -rdata_shared"
+ EXT=pd_irix6
+ dnl DFLAGS="-DUNIX -DIRIX6"
+ STRIPFLAGS="--strip-unneeded"
+ if test "$enable_lpt" = "yes"; then
+ AC_MSG_ERROR("lpt not supported on this platform");
+ fi
+ if test "$enable_lpt" = ""; then
+ AC_MSG_WARN("lpt not supported on this platform - disabling");
+ enable_lpt="no";
+ fi
+fi
+
+if test `uname -s` = IRIX32;
+then
+ LFLAGS="-o32 -DUNIX -DIRIX -O2
+ -shared -rdata_shared"
+ EXT=pd_irix5
+ dnl DFLAGS="-DUNIX -DIRIX5"
+ STRIPFLAGS="--strip-unneeded"
+ if test "$enable_lpt" = "yes"; then
+ AC_MSG_ERROR("lpt not supported on this platform");
+ fi
+ if test "$enable_lpt" = ""; then
+ AC_MSG_WARN("lpt not supported on this platform - disabling");
+ enable_lpt="no";
+ fi
+fi
+
+dnl Checks for pd-version, to set the correct help-path
+AC_MSG_CHECKING("pd\>=0.37")
+
+if test "$with_pdversion" != ""
+then
+echo -n "($with_pdversion)... "
+ PD_VERSION="$with_pdversion"
+else
+cat > conftest.c << EOF
+#include <stdio.h>
+#include "m_pd.h"
+int main(){
+ printf("%d.%d\n", PD_MAJOR_VERSION, PD_MINOR_VERSION);
+ return 0;
+}
+EOF
+ if $CC $INCLUDES -o conftest.o conftest.c > /dev/null 2>&1
+ then
+ PD_VERSION=`./conftest.o`
+ else
+ PD_VERSION=""
+ fi
+fi
+
+let PD_MAJORVERSION=`echo $PD_VERSION | cut -d"." -f1`+0
+let PD_MINORVERSION=`echo $PD_VERSION | cut -d"." -f2`+0
+
+if test "$PD_MAJORVERSION" -gt 0 || test "$PD_MINORVERSION" -ge 37
+then
+ REFERENCEPATH=extra/help-
+ echo "yes"
+else
+ REFERENCEPATH=doc/5.reference/
+ echo "no"
+fi
+
+dnl check for iemmatrix-version (but why...)
+AC_MSG_CHECKING("iemmatrix-version")
+cat > conftest.c << EOF
+#include <stdio.h>
+#include "iemmatrix.h"
+int main(){
+ printf("%s\n", VERSION);
+ return 0;
+}
+EOF
+
+if $CC $INCLUDES -o conftest.o conftest.c > /dev/null 2>&1
+then
+ IEMMATRIX_VERSION=`./conftest.o`
+ echo "$IEMMATRIX_VERSION"
+else
+ IEMMATRIX_VERSION=""
+ echo "(unknown)"
+fi
+
+echo "SOURCES = \\"> Make.source
+for i in `ls mtx_*.c iemmatrix.c`
+do
+ echo " $i\\">> Make.source
+done
+echo >> Make.source
+
+AC_OUTPUT(Makefile)
+
+rm -f conftest.*
diff --git a/src/iemmatrix.c b/src/iemmatrix.c
new file mode 100644
index 0000000..384f54a
--- /dev/null
+++ b/src/iemmatrix.c
@@ -0,0 +1,77 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * (c) IOhannes m zmölnig, forum::für::umläute
+ *
+ * IEM, Graz
+ *
+ * this code is published under the LGPL
+ *
+ */
+#include "iemmatrix.h"
+
+void mtx_binops_setup();
+void mtx_col_setup();
+void mtx_diag_setup();
+void mtx_diegg_setup();
+void mtx_egg_setup();
+void mtx_element_setup();
+void mtx_eye_setup();
+void mtx_inverse_setup();
+void mtx_matrix_setup();
+void mtx_mean_setup();
+void mtx_check_setup();
+void mtx_print_setup();
+void mtx_ones_setup();
+void mtx_pivot_setup();
+void mtx_rand_setup();
+void mtx_resize_setup();
+void mtx_roll_setup();
+void mtx_row_setup();
+void mtx_scroll_setup();
+void mtx_size_setup();
+void mtx_trace_setup();
+void mtx_transpose_setup();
+void mtx_zeros_setup();
+void mtx_tilde_setup();
+
+void iemtx_setup(){
+ mtx_binops_setup();
+ mtx_col_setup();
+ mtx_diag_setup();
+ mtx_diegg_setup();
+ mtx_egg_setup();
+ mtx_element_setup();
+ mtx_eye_setup();
+ mtx_inverse_setup();
+ mtx_matrix_setup();
+ mtx_mean_setup();
+ mtx_check_setup();
+ mtx_print_setup();
+ mtx_ones_setup();
+ mtx_pivot_setup();
+ mtx_rand_setup();
+ mtx_resize_setup();
+ mtx_roll_setup();
+ mtx_row_setup();
+ mtx_scroll_setup();
+ mtx_size_setup();
+ mtx_trace_setup();
+ mtx_transpose_setup();
+ mtx_zeros_setup();
+ mtx_tilde_setup();
+}
+
+void iemmatrix_setup(){
+ post("");
+ post("iemmatrix "VERSION);
+ post("\tobjects for manipulating 2d-matrices");
+ post("\t(c) IOhannes m zmölnig, Thomas Musil :: iem, 2001-2005");
+ post("\tcompiled "__DATE__" : "__TIME__);
+ post("");
+
+ iemtx_setup();
+}
diff --git a/src/iemmatrix.h b/src/iemmatrix.h
new file mode 100644
index 0000000..aeaec85
--- /dev/null
+++ b/src/iemmatrix.h
@@ -0,0 +1,95 @@
+/* ************************************* */
+/* iemmatrix */
+/* ************************************* */
+/* objects for simple matrix operations */
+/* ************************************* */
+
+/* IEMMATRIX is a runtime-library for miller s. puckette's realtime-computermusic-software "pure data"
+ * therefore you NEED "pure data" to make any use of the IEMMATRIX external
+ * (except if you want to use the code for other things)
+ * download "pure data" at
+ *
+ * http://pd.iem.at
+ * ftp://iem.at/pd
+ *
+ *
+ * IEMMATRIX is published under the Lesser GNU GeneralPublicLicense (LGPL),
+ * that must be shipped with IEMMATRIX.
+ * if you are using Debian GNU/linux,
+ * the lesser GNU-GPL can be found under /usr/share/common-licenses/LGPL
+ * if you still haven't found a copy of the lesser GNU-GPL, have a look at http://www.gnu.org
+ *
+ * "pure data" has it's own license, that comes shipped with "pure data".
+ *
+ * there are ABSOLUTELY NO WARRANTIES for anything
+ */
+
+#ifndef INCLUDE_IEMMATRIX_H__
+#define INCLUDE_IEMMATRIX_H__
+
+#include "m_pd.h"
+
+#define VERSION "0.1"
+
+#ifdef NT
+# pragma warning( disable : 4244 )
+# pragma warning( disable : 4305 )
+#endif
+
+#include <math.h>
+#include <stdio.h>
+
+#include <string.h>
+#include <memory.h>
+
+#ifdef NT
+# define fabsf fabs
+#endif
+
+typedef long double t_matrixfloat;
+
+
+/* the main class...*/
+typedef struct _matrix
+{
+ t_object x_obj;
+
+ int row;
+ int col;
+
+ t_atom *atombuffer;
+
+ int current_row, current_col; /* this makes things easy for the mtx_row & mtx_col...*/
+ t_float f;
+
+ t_canvas *x_canvas;
+} t_matrix;
+
+void matrix_free(t_matrix*x);
+
+/* utility function */
+void setdimen(t_matrix *x, int row, int col);
+void adjustsize(t_matrix *x, int desiredRow, int desiredCol);
+void debugmtx(int argc, t_float *buf, int id);
+t_matrixfloat *matrix2float(t_atom *ap);
+void float2matrix(t_atom *ap, t_matrixfloat *buffer);
+
+/* basic I/O functions */
+void matrix_bang(t_matrix *x); /* output the matrix stored in atombuffer */
+void matrix_matrix2(t_matrix *x, t_symbol *s, int argc, t_atom *argv); /* store the matrix in atombuffer */
+
+/* set data */
+void matrix_set(t_matrix *x, t_float f); /* set the entire matrix to "f" */
+void matrix_zeros(t_matrix *x, t_symbol *s, int argc, t_atom *argv);
+void matrix_ones(t_matrix *x, t_symbol *s, int argc, t_atom *argv);
+void matrix_eye(t_matrix *x, t_symbol *s, int argc, t_atom *argv);
+void matrix_egg(t_matrix *x, t_symbol *s, int argc, t_atom *argv);
+void matrix_diag(t_matrix *x, t_symbol *s, int argc, t_atom *argv);
+void matrix_diegg(t_matrix *x, t_symbol *s, int argc, t_atom *argv);
+
+/* get/set data */
+void matrix_row(t_matrix *x, t_symbol *s, int argc, t_atom *argv);
+void matrix_col(t_matrix *x, t_symbol *s, int argc, t_atom *argv);
+void matrix_element(t_matrix *x, t_symbol *s, int argc, t_atom *argv);
+
+#endif
diff --git a/src/make.source b/src/make.source
new file mode 100644
index 0000000..dc22aae
--- /dev/null
+++ b/src/make.source
@@ -0,0 +1 @@
+SOURCES = \
diff --git a/src/mtx_binops.c b/src/mtx_binops.c
new file mode 100644
index 0000000..5625667
--- /dev/null
+++ b/src/mtx_binops.c
@@ -0,0 +1,680 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * (c) IOhannes m zmölnig, forum::für::umläute
+ *
+ * IEM, Graz
+ *
+ * this code is published under the LGPL
+ *
+ */
+#include "iemmatrix.h"
+
+/*
+ mtx_add
+ mtx_+
+ mtx_mul
+ mtx_*
+ mtx_.*
+ mtx_./
+*/
+
+/* -­------------------------------------------------------------- */
+/* matrix math */
+
+typedef struct _mtx_binscalar
+{
+ t_object x_obj;
+
+ t_matrix m; // the output matrix
+ t_float f; // the second input
+} t_mtx_binscalar;
+
+typedef struct _mtx_binmtx
+{
+ t_object x_obj;
+
+ t_matrix m; // the output matrix
+ t_matrix m2; // the second input
+} t_mtx_binmtx;
+
+static void mtx_bin_matrix2(t_mtx_binmtx *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int row = atom_getfloat(argv);
+ int col = atom_getfloat(argv+1);
+ if (argc<2){post("mtx_bin2: crippled matrix"); return;}
+ if ((col<1)||(row<1)) {post("mtx_bin2: invalid dimensions %dx%d", row,col); return;}
+ if (col*row+2>argc){ post("mtx_bin2: sparse matrix not yet supported : use \"mtx_check\""); return;}
+
+ if (row*col!=x->m2.row*x->m2.col) {
+ freebytes(x->m2.atombuffer, (x->m2.row*x->m2.col+2)*sizeof(t_atom));
+ x->m2.atombuffer=copybytes(argv,(row*col+2)*sizeof(t_atom));
+ }else memcpy(x->m2.atombuffer, argv, (row*col+2)*sizeof(t_atom));
+ setdimen(&x->m2, row, col);
+}
+
+static void mtx_binmtx_bang(t_mtx_binmtx *x)
+{
+ if((&x->m)&&(x->m.atombuffer))
+ outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), x->m.col*x->m.row+2, x->m.atombuffer);
+}
+
+
+static void mtx_binmtx_free(t_mtx_binmtx *x)
+{
+ matrix_free(&x->m);
+ matrix_free(&x->m2);
+}
+static void mtx_binscalar_bang(t_mtx_binscalar *x)
+{
+ if((&x->m)&&(x->m.atombuffer))
+ outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), x->m.col*x->m.row+2, x->m.atombuffer);
+}
+static void mtx_binscalar_free(t_mtx_binscalar *x)
+{
+ matrix_free(&x->m);
+}
+
+
+
+/* mtx_add */
+static t_class *mtx_add_class, *mtx_addscalar_class;
+
+static void mtx_addscalar_matrix(t_mtx_binscalar *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int n=argc-2;
+ int row=atom_getfloat(argv), col=atom_getfloat(argv+1);
+
+ t_float offset=x->f;
+ t_atom *buf;
+ t_atom *ap=argv+2;
+
+ if(argc<2){post("mtx_add: crippled matrix");return; }
+ adjustsize(&x->m, row, col);
+
+ buf=x->m.atombuffer+2;
+
+ while(n--){
+ buf->a_type = A_FLOAT;
+ buf++->a_w.w_float = atom_getfloat(ap++) + offset;
+ }
+ outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, x->m.atombuffer);
+}
+static void mtx_addscalar_list(t_mtx_binscalar *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int n=argc;
+ t_atom *m;
+ t_float offset = x->f;
+ adjustsize(&x->m, 1, argc);
+ m = x->m.atombuffer;
+
+ while(n--){
+ m->a_type = A_FLOAT;
+ (m++)->a_w.w_float = atom_getfloat(argv++) + offset;
+ }
+ outlet_list(x->x_obj.ob_outlet, gensym("list"), argc, x->m.atombuffer);
+}
+
+static void mtx_add_matrix(t_mtx_binmtx *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int row=atom_getfloat(argv);
+ int col=atom_getfloat(argv+1);
+ t_atom *m;
+ t_atom *m1 = argv+2;
+ t_atom *m2 = x->m2.atombuffer+2;
+ int n = argc-2;
+
+ if (argc<2){ post("mtx_add: crippled matrix"); return; }
+ if ((col<1)||(row<1)) { post("mtx_add: invalid dimensions"); return; }
+ if (col*row>argc-2){ post("sparse matrix not yet supported : use \"mtx_check\""); return; }
+
+ if (!(x->m2.col*x->m2.row)) {
+ outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, argv);
+ return;
+ }
+
+ if ((col!=x->m2.col)||(row!=x->m2.row)){
+ post("mtx_add: matrix dimensions do not match");
+ /* LATER SOLVE THIS */
+ return;
+ }
+ adjustsize(&x->m, row, col);
+ m = x->m.atombuffer+2;
+
+ while(n--){
+ t_float f = atom_getfloat(m1++)+atom_getfloat(m2++);
+ SETFLOAT(m, f);
+ m++;
+ }
+
+ outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, x->m.atombuffer);
+}
+static void mtx_add_float(t_mtx_binmtx *x, t_float f)
+{
+ t_matrix *m=&x->m, *m2=&x->m2;
+ t_atom *ap, *ap2=m2->atombuffer+2;
+ int row2, col2, n;
+
+ if (!m2->atombuffer){ post("mulitply with what ?"); return; }
+
+ row2=atom_getfloat(m2->atombuffer);
+ col2=atom_getfloat(m2->atombuffer+1);
+ adjustsize(m, row2, col2);
+ ap=m->atombuffer+2;
+
+ n=row2*col2;
+
+ while(n--){
+ SETFLOAT(ap, f+atom_getfloat(ap2++));
+ ap++;
+ }
+
+ outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), m->row*m->col+2, m->atombuffer);
+}
+static void *mtx_add_new(t_symbol *s, int argc, t_atom *argv)
+{
+ if (argc>1) post("mtx_add : extra arguments ignored");
+ if (argc) {
+ t_mtx_binscalar *x = (t_mtx_binscalar *)pd_new(mtx_addscalar_class);
+ floatinlet_new(&x->x_obj, &x->f);
+ x->f = atom_getfloatarg(0, argc, argv);
+ outlet_new(&x->x_obj, 0);
+ return(x);
+ } else {
+ t_mtx_binmtx *x = (t_mtx_binmtx *)pd_new(mtx_add_class);
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("matrix"), gensym(""));
+ outlet_new(&x->x_obj, 0);
+ x->m.col = x->m.row = x->m2.col = x->m2.row = 0;
+ x->m.atombuffer = x->m2.atombuffer = 0;
+ return(x);
+ }
+}
+
+static void mtx_add_setup(void)
+{
+ mtx_add_class = class_new(gensym("mtx_add"), (t_newmethod)mtx_add_new, (t_method)mtx_binmtx_free,
+ sizeof(t_mtx_binmtx), 0, A_GIMME, 0);
+ class_addcreator((t_newmethod)mtx_add_new, gensym("mtx_+"), A_GIMME,0);
+ class_addmethod(mtx_add_class, (t_method)mtx_add_matrix, gensym("matrix"), A_GIMME, 0);
+ class_addmethod(mtx_add_class, (t_method)mtx_bin_matrix2, gensym(""), A_GIMME, 0);
+ class_addfloat (mtx_add_class, mtx_add_float);
+ class_addbang (mtx_add_class, mtx_binmtx_bang);
+
+ mtx_addscalar_class = class_new(gensym("mtx_add"), 0, (t_method)mtx_binscalar_free,
+ sizeof(t_mtx_binscalar), 0, 0);
+ class_addcreator(0, gensym("mtx_+"), 0, 0);
+ class_addmethod(mtx_addscalar_class, (t_method)mtx_addscalar_matrix, gensym("matrix"), A_GIMME, 0);
+ class_addlist (mtx_addscalar_class, mtx_addscalar_list);
+ class_addbang (mtx_addscalar_class, mtx_binscalar_bang);
+
+ class_sethelpsymbol(mtx_add_class, gensym("iemmatrix/mtx_binops"));
+ class_sethelpsymbol(mtx_addscalar_class, gensym("iemmatrix/mtx_binops"));
+}
+
+/* mtx_sub */
+static t_class *mtx_sub_class, *mtx_subscalar_class;
+
+static void mtx_subscalar_matrix(t_mtx_binscalar *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int n=argc-2;
+ int row=atom_getfloat(argv), col=atom_getfloat(argv+1);
+
+ t_float offset=x->f;
+ t_atom *buf;
+ t_atom *ap=argv+2;
+
+ if(argc<2){post("mtx_sub: crippled matrix");return; }
+ adjustsize(&x->m, row, col);
+
+ buf=x->m.atombuffer+2;
+
+ while(n--){
+ buf->a_type = A_FLOAT;
+ buf++->a_w.w_float = atom_getfloat(ap++) - offset;
+ }
+ outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, x->m.atombuffer);
+}
+static void mtx_subscalar_list(t_mtx_binscalar *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int n=argc;
+ t_atom *m;
+ t_float offset = x->f;
+ adjustsize(&x->m, 1, argc);
+ m = x->m.atombuffer;
+
+ while(n--){
+ m->a_type = A_FLOAT;
+ (m++)->a_w.w_float = atom_getfloat(argv++) - offset;
+ }
+ outlet_list(x->x_obj.ob_outlet, gensym("list"), argc, x->m.atombuffer);
+}
+
+static void mtx_sub_matrix(t_mtx_binmtx *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int row=atom_getfloat(argv);
+ int col=atom_getfloat(argv+1);
+ t_atom *m;
+ t_atom *m1 = argv+2;
+ t_atom *m2 = x->m2.atombuffer+2;
+ int n = argc-2;
+
+ if (argc<2){ post("mtx_sub: crippled matrix"); return; }
+ if ((col<1)||(row<1)) { post("mtx_sub: invalid dimensions"); return; }
+ if (col*row>argc-2){ post("sparse matrix not yet supported : use \"mtx_check\""); return; }
+
+ if (!(x->m2.col*x->m2.row)) {
+ outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, argv);
+ return;
+ }
+
+ if ((col!=x->m2.col)||(row!=x->m2.row)){
+ post("mtx_sub: matrix dimensions do not match");
+ /* LATER SOLVE THIS */
+ return;
+ }
+ adjustsize(&x->m, row, col);
+ m = x->m.atombuffer+2;
+
+ while(n--){
+ t_float f = atom_getfloat(m1++)-atom_getfloat(m2++);
+ SETFLOAT(m, f);
+ m++;
+ }
+
+ outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, x->m.atombuffer);
+}
+static void mtx_sub_float(t_mtx_binmtx *x, t_float f)
+{
+ t_matrix *m=&x->m, *m2=&x->m2;
+ t_atom *ap, *ap2=m2->atombuffer+2;
+ int row2, col2, n;
+
+ if (!m2->atombuffer){ post("mulitply with what ?"); return; }
+
+ row2=atom_getfloat(m2->atombuffer);
+ col2=atom_getfloat(m2->atombuffer+1);
+ adjustsize(m, row2, col2);
+ ap=m->atombuffer+2;
+
+ n=row2*col2;
+
+ while(n--){
+ SETFLOAT(ap, f-atom_getfloat(ap2++));
+ ap++;
+ }
+
+ outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), m->row*m->col+2, m->atombuffer);
+}
+static void *mtx_sub_new(t_symbol *s, int argc, t_atom *argv)
+{
+ if (argc>1) post("mtx_sub : extra arguments ignored");
+ if (argc) {
+ t_mtx_binscalar *x = (t_mtx_binscalar *)pd_new(mtx_subscalar_class);
+ floatinlet_new(&x->x_obj, &x->f);
+ x->f = atom_getfloatarg(0, argc, argv);
+ outlet_new(&x->x_obj, 0);
+ return(x);
+ } else {
+ t_mtx_binmtx *x = (t_mtx_binmtx *)pd_new(mtx_sub_class);
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("matrix"), gensym(""));
+ outlet_new(&x->x_obj, 0);
+ x->m.col = x->m.row = x->m2.col = x->m2.row = 0;
+ x->m.atombuffer = x->m2.atombuffer = 0;
+ return(x);
+ }
+}
+
+static void mtx_sub_setup(void)
+{
+ mtx_sub_class = class_new(gensym("mtx_sub"), (t_newmethod)mtx_sub_new, (t_method)mtx_binmtx_free,
+ sizeof(t_mtx_binmtx), 0, A_GIMME, 0);
+ class_addcreator((t_newmethod)mtx_sub_new, gensym("mtx_-"), A_GIMME,0);
+ class_addmethod(mtx_sub_class, (t_method)mtx_sub_matrix, gensym("matrix"), A_GIMME, 0);
+ class_addmethod(mtx_sub_class, (t_method)mtx_bin_matrix2, gensym(""), A_GIMME, 0);
+ class_addfloat (mtx_sub_class, mtx_sub_float);
+ class_addbang (mtx_sub_class, mtx_binmtx_bang);
+
+ mtx_subscalar_class = class_new(gensym("mtx_sub"), 0, (t_method)mtx_binscalar_free,
+ sizeof(t_mtx_binscalar), 0, 0);
+ class_addcreator(0, gensym("mtx_-"), 0, 0);
+ class_addmethod(mtx_subscalar_class, (t_method)mtx_subscalar_matrix, gensym("matrix"), A_GIMME, 0);
+ class_addlist (mtx_subscalar_class, mtx_subscalar_list);
+ class_addbang (mtx_subscalar_class, mtx_binscalar_bang);
+
+ class_sethelpsymbol(mtx_sub_class, gensym("iemmatrix/mtx_binops"));
+ class_sethelpsymbol(mtx_subscalar_class, gensym("iemmatrix/mtx_binops"));
+}
+
+
+/* mtx_mul */
+static t_class *mtx_mul_class, *mtx_mulelement_class, *mtx_mulscalar_class;
+
+static void mtx_mul_matrix(t_mtx_binmtx *x, t_symbol *s, int argc, t_atom *argv)
+{
+ t_matrix *m=&x->m, *m2=&x->m2;
+ t_atom *ap, *ap1=argv+2, *ap2=m2->atombuffer+2;
+ int row=atom_getfloat(argv), col=atom_getfloat(argv+1);
+ int row2, col2, n, r, c;
+
+ if (!m2->atombuffer){ post("mulitply with what ?"); return; }
+ if (argc<2){ post("mtx_mul: crippled matrix"); return; }
+ if ((col<1)||(row<1)){post("mtx_mul: invalid dimensions"); return; }
+ if (col*row>argc-2){ post("sparse matrix not yet supported : use \"mtx_check\""); return; }
+
+ row2=atom_getfloat(m2->atombuffer);
+ col2=atom_getfloat(m2->atombuffer+1);
+
+ if (col!=row2) { post("mtx_mul: matrix dimensions do not match !"); return; }
+
+ adjustsize(m, row, col2);
+ ap=m->atombuffer+2;
+
+ for(r=0;r<row;r++)
+ for(c=0;c<col2;c++) {
+ t_matrixfloat sum = 0.f;
+ for(n=0;n<col;n++)sum+=(t_matrixfloat)atom_getfloat(ap1+col*r+n)*atom_getfloat(ap2+col2*n+c);
+ SETFLOAT(ap+col2*r+c,sum);
+ }
+ outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), m->row*m->col+2, m->atombuffer);
+}
+
+static void mtx_mul_float(t_mtx_binmtx *x, t_float f)
+{
+ t_matrix *m=&x->m, *m2=&x->m2;
+ t_atom *ap, *ap2=m2->atombuffer+2;
+ int row2, col2, n;
+
+ if (!m2->atombuffer){ post("mulitply with what ?"); return; }
+
+ row2=atom_getfloat(m2->atombuffer);
+ col2=atom_getfloat(m2->atombuffer+1);
+ adjustsize(m, row2, col2);
+ ap=m->atombuffer+2;
+
+ n=row2*col2;
+
+ while(n--){
+ SETFLOAT(ap, f*atom_getfloat(ap2++));
+ ap++;
+ }
+
+ outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), m->row*m->col+2, m->atombuffer);
+}
+
+static void mtx_mulelement_matrix(t_mtx_binmtx *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int row=atom_getfloat(argv++);
+ int col=atom_getfloat(argv++);
+ t_atom *m;
+ t_atom *m2 = x->m2.atombuffer+2;
+ int n = argc-2;
+
+ if (argc<2){ post("mtx_mul: crippled matrix"); return; }
+ if ((col<1)||(row<1)) { post("mtx_mul: invalid dimensions"); return; }
+ if (col*row>argc-2){ post("sparse matrix not yet supported : use \"mtx_check\""); return; }
+ if (!(x->m2.col*x->m2.row)) {
+ adjustsize(&x->m, row, col);
+ matrix_set(&x->m, 0);
+ outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, x->m.atombuffer);
+ return;
+ }
+ if ((col!=x->m2.col)||(row!=x->m2.row)){ post("matrix dimension do not match"); /* LATER SOLVE THIS */ return; }
+
+ adjustsize(&x->m, row, col);
+ m = x->m.atombuffer+2;
+
+ while(n--){
+ t_float f = atom_getfloat(argv++)*atom_getfloat(m2++);
+ SETFLOAT(m, f);
+ m++;
+ }
+
+ outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, x->m.atombuffer);
+}
+
+static void mtx_mulscalar_matrix(t_mtx_binscalar *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int n=argc-2;
+ t_atom *m;
+ t_float factor = x->f;
+ int row=atom_getfloat(argv++);
+ int col=atom_getfloat(argv++);
+
+ if (argc<2){
+ post("mtx_mul: crippled matrix");
+ return;
+ }
+ adjustsize(&x->m, row, col);
+ m = x->m.atombuffer+2;
+
+ while(n--){
+ m->a_type = A_FLOAT;
+ (m++)->a_w.w_float = atom_getfloat(argv++)*factor;
+ }
+
+ outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, x->m.atombuffer);
+}
+static void mtx_mulscalar_list(t_mtx_binscalar *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int n=argc;
+ t_atom *m;
+ t_float factor = x->f;
+ adjustsize(&x->m, 1, argc);
+ m = x->m.atombuffer;
+
+ while(n--){
+ m->a_type = A_FLOAT;
+ (m++)->a_w.w_float = atom_getfloat(argv++)*factor;
+ }
+ outlet_list(x->x_obj.ob_outlet, gensym("list"), argc, x->m.atombuffer);
+}
+
+static void *mtx_mul_new(t_symbol *s, int argc, t_atom *argv)
+{
+ if (argc>1) post("mtx_mul : extra arguments ignored");
+ if (argc) {
+ t_mtx_binscalar *x = (t_mtx_binscalar *)pd_new(mtx_mulscalar_class);
+ floatinlet_new(&x->x_obj, &x->f);
+ x->f = atom_getfloatarg(0, argc, argv);
+ outlet_new(&x->x_obj, 0);
+ return(x);
+ } else {
+ if (s->s_name[4]=='.') {
+ /* element mul */
+
+ t_matrix *x = (t_matrix *)pd_new(mtx_mulelement_class);
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("matrix"), gensym(""));
+ outlet_new(&x->x_obj, 0);
+ x->col = x->row = 0;
+ x->atombuffer = 0;
+ return(x);
+ } else {
+ t_mtx_binmtx *x = (t_mtx_binmtx *)pd_new(mtx_mul_class);
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("matrix"), gensym(""));
+ outlet_new(&x->x_obj, 0);
+ x->m.col = x->m.row = x->m2.col = x->m2.row = 0;
+ x->m.atombuffer = x->m2.atombuffer = 0;
+ return (x);
+ }
+ }
+}
+
+static void mtx_mul_setup(void)
+{
+ mtx_mul_class = class_new(gensym("mtx_mul"), (t_newmethod)mtx_mul_new, (t_method)mtx_binmtx_free,
+ sizeof(t_mtx_binmtx), 0, A_GIMME, 0);
+ class_addcreator((t_newmethod)mtx_mul_new, gensym("mtx_*"), A_GIMME,0);
+ class_addmethod(mtx_mul_class, (t_method)mtx_mul_matrix, gensym("matrix"), A_GIMME, 0);
+ class_addmethod(mtx_mul_class, (t_method)mtx_bin_matrix2, gensym(""), A_GIMME, 0);
+ class_addfloat (mtx_mul_class, mtx_mul_float);
+ class_addbang (mtx_mul_class, mtx_binmtx_bang);
+
+ mtx_mulelement_class = class_new(gensym("mtx_.*"), (t_newmethod)mtx_mul_new, (t_method)mtx_binmtx_free,
+ sizeof(t_mtx_binmtx), 0, A_GIMME, 0);
+ class_addmethod(mtx_mulelement_class, (t_method)mtx_mulelement_matrix, gensym("matrix"), A_GIMME, 0);
+ class_addmethod(mtx_mulelement_class, (t_method)mtx_bin_matrix2, gensym(""), A_GIMME, 0);
+ class_addfloat (mtx_mulelement_class, mtx_mul_float);
+ class_addbang (mtx_mulelement_class, mtx_binmtx_bang);
+
+ mtx_mulscalar_class = class_new(gensym("mtx_mul"), 0, (t_method)mtx_binscalar_free,
+ sizeof(t_mtx_binscalar), 0, 0);
+ class_addcreator(0, gensym("mtx_*"), 0, 0);
+ class_addcreator(0, gensym("mtx_.*"), 0, 0);
+ class_addmethod(mtx_mulscalar_class, (t_method)mtx_mulscalar_matrix, gensym("matrix"), A_GIMME, 0);
+ class_addlist (mtx_mulscalar_class, mtx_mulscalar_list);
+ class_addbang (mtx_mulscalar_class, mtx_binscalar_bang);
+
+ class_sethelpsymbol(mtx_mul_class, gensym("iemmatrix/mtx_binops"));
+ class_sethelpsymbol(mtx_mulelement_class, gensym("iemmatrix/mtx_binops"));
+ class_sethelpsymbol(mtx_mulscalar_class, gensym("iemmatrix/mtx_binops"));
+}
+
+
+/* mtx_div */
+static t_class *mtx_divelement_class, *mtx_divscalar_class;
+
+static void mtx_divelement_matrix(t_mtx_binmtx *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int row=atom_getfloat(argv++);
+ int col=atom_getfloat(argv++);
+ t_atom *m;
+ t_atom *m2 = x->m2.atombuffer+2;
+ int n = argc-2;
+
+ if (argc<2){ post("mtx_div: crippled matrix"); return; }
+ if ((col<1)||(row<1)) { post("mtx_div: invalid dimensions"); return; }
+ if (col*row>argc-2){ post("sparse matrix not yet supported : use \"mtx_check\""); return; }
+ if (!(x->m2.col*x->m2.row)) {
+ adjustsize(&x->m, row, col);
+ matrix_set(&x->m, 0);
+ outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, x->m.atombuffer);
+ return;
+ }
+ if ((col!=x->m2.col)||(row!=x->m2.row)){ post("matrix dimension do not match"); /* LATER SOLVE THIS */ return; }
+
+ adjustsize(&x->m, row, col);
+ m = x->m.atombuffer+2;
+
+ while(n--){
+ t_float f = atom_getfloat(argv++)/atom_getfloat(m2++);
+ SETFLOAT(m, f);
+ m++;
+ }
+
+ outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, x->m.atombuffer);
+}
+static void mtx_divelement_float(t_mtx_binmtx *x, t_float f)
+{
+ t_matrix *m=&x->m, *m2=&x->m2;
+ t_atom *ap, *ap2=m2->atombuffer+2;
+ int row2, col2, n;
+
+ if (!m2->atombuffer){ post("divide by what ?"); return; }
+
+ row2=atom_getfloat(m2->atombuffer);
+ col2=atom_getfloat(m2->atombuffer+1);
+ adjustsize(m, row2, col2);
+ ap=m->atombuffer+2;
+
+ n=row2*col2;
+
+ while(n--){
+ SETFLOAT(ap, f/atom_getfloat(ap2++));
+ ap++;
+ }
+
+ outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), m->row*m->col+2, m->atombuffer);
+}
+static void mtx_divscalar_matrix(t_mtx_binscalar *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int n=argc-2;
+ t_atom *m;
+ t_float factor = 1.0/x->f;
+ int row=atom_getfloat(argv++);
+ int col=atom_getfloat(argv++);
+
+ if (argc<2){
+ post("mtx_div: crippled matrix");
+ return;
+ }
+ adjustsize(&x->m, row, col);
+ m = x->m.atombuffer+2;
+
+ while(n--){
+ m->a_type = A_FLOAT;
+ (m++)->a_w.w_float = atom_getfloat(argv++)*factor;
+ }
+
+ outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, x->m.atombuffer);
+}
+static void mtx_divscalar_list(t_mtx_binscalar *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int n=argc;
+ t_atom *m;
+ t_float factor = 1.0/x->f;
+
+ adjustsize(&x->m, 1, argc);
+ m = x->m.atombuffer;
+
+ while(n--){
+ m->a_type = A_FLOAT;
+ (m++)->a_w.w_float = atom_getfloat(argv++)*factor;
+ }
+
+ outlet_list(x->x_obj.ob_outlet, gensym("list"), argc, x->m.atombuffer);
+}
+
+static void *mtx_div_new(t_symbol *s, int argc, t_atom *argv)
+{
+ if (argc>1) post("mtx_div : extra arguments ignored");
+ if (argc) {
+ /* scalar division */
+ t_mtx_binscalar *x = (t_mtx_binscalar *)pd_new(mtx_divscalar_class);
+ floatinlet_new(&x->x_obj, &x->f);
+ x->f = atom_getfloatarg(0, argc, argv);
+ outlet_new(&x->x_obj, 0);
+ return(x);
+ } else {
+ /* element division */
+ t_matrix *x = (t_matrix *)pd_new(mtx_divelement_class);
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("matrix"), gensym(""));
+ outlet_new(&x->x_obj, 0);
+ x->col = x->row = 0;
+ x->atombuffer = 0;
+ return(x);
+ }
+}
+
+static void mtx_div_setup(void)
+{
+ mtx_divelement_class = class_new(gensym("mtx_./"), (t_newmethod)mtx_div_new, (t_method)mtx_binmtx_free,
+ sizeof(t_mtx_binmtx), 0, A_GIMME, 0);
+ class_addmethod(mtx_divelement_class, (t_method)mtx_divelement_matrix, gensym("matrix"), A_GIMME, 0);
+ class_addmethod(mtx_divelement_class, (t_method)mtx_bin_matrix2, gensym(""), A_GIMME, 0);
+ class_addfloat (mtx_divelement_class, mtx_divelement_float);
+ class_addbang (mtx_divelement_class, mtx_binmtx_bang);
+
+ mtx_divscalar_class = class_new(gensym("mtx_./"), 0, (t_method)mtx_binscalar_free,
+ sizeof(t_mtx_binscalar), 0, 0);
+ class_addmethod(mtx_divscalar_class, (t_method)mtx_divscalar_matrix, gensym("matrix"), A_GIMME, 0);
+ class_addlist (mtx_divscalar_class, mtx_divscalar_list);
+ class_addbang (mtx_divscalar_class, mtx_binscalar_bang);
+
+ class_sethelpsymbol(mtx_divelement_class, gensym("iemmatrix/mtx_binops"));
+ class_sethelpsymbol(mtx_divscalar_class, gensym("iemmatrix/mtx_binops"));
+}
+
+void mtx_binops_setup(void)
+{
+ mtx_add_setup();
+ mtx_sub_setup();
+ mtx_mul_setup();
+ mtx_div_setup();
+}
+void iemtx_binops_setup(void)
+{
+ mtx_binops_setup();
+}
diff --git a/src/mtx_check.c b/src/mtx_check.c
new file mode 100644
index 0000000..0e2eda1
--- /dev/null
+++ b/src/mtx_check.c
@@ -0,0 +1,76 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * (c) IOhannes m zmölnig, forum::für::umläute
+ *
+ * IEM, Graz
+ *
+ * this code is published under the LGPL
+ *
+ */
+#include "iemmatrix.h"
+
+/* mtx_check */
+static t_class *mtx_check_class;
+
+static void mtx_check_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int row=atom_getfloat(argv);
+ int col=atom_getfloat(argv+1);
+ t_atom *ap;
+ int length=row*col, n;
+ argc-=2;
+
+ if(length>argc) {
+ /* sparse matrix */
+ adjustsize(x, row, col);
+ matrix_set(x, 0);
+ argv+=2;
+ ap=x->atombuffer+2;
+ n=argc;
+ while(n--){
+ t_float f = atom_getfloat(argv++);
+ SETFLOAT(ap, f);
+ ap++;
+ }
+ matrix_bang(x);
+ } else {
+ SETFLOAT(argv, row);
+ SETFLOAT(argv+1, col);
+ ap=argv+2;
+ n=length;
+ while(n--){
+ t_float f = atom_getfloat(ap);
+ SETFLOAT(ap, f);
+ ap++;
+ }
+ outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), length+2, argv);
+ }
+}
+
+static void *mtx_check_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_matrix *x = (t_matrix *)pd_new(mtx_check_class);
+ outlet_new(&x->x_obj, 0);
+ x->col=x->row=0;
+ x->atombuffer=0;
+ return (x);
+}
+
+void mtx_check_setup(void)
+{
+ mtx_check_class = class_new(gensym("mtx_check"), (t_newmethod)mtx_check_new,
+ (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0);
+ class_addbang (mtx_check_class, matrix_bang);
+ class_addmethod(mtx_check_class, (t_method)mtx_check_matrix, gensym("matrix"), A_GIMME, 0);
+ class_sethelpsymbol(mtx_check_class, gensym("iemmatrix/matrix"));
+}
+
+
+void iemtx_check_setup(void)
+{
+ mtx_check_setup();
+}
diff --git a/src/mtx_col.c b/src/mtx_col.c
new file mode 100644
index 0000000..1ee3dbb
--- /dev/null
+++ b/src/mtx_col.c
@@ -0,0 +1,129 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * (c) IOhannes m zmölnig, forum::für::umläute
+ *
+ * IEM, Graz
+ *
+ * this code is published under the LGPL
+ *
+ */
+#include "iemmatrix.h"
+
+/* mtx_col */
+static t_class *mtx_col_class;
+
+static void mtx_col_float(t_matrix *x, t_floatarg f)
+{
+ int i = f;
+ if(i<0)i=0;
+ x->current_col = i;
+}
+static void mtx_col_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int row, col;
+ if (argc<2){ post("matrix : corrupt matrix passed"); return; }
+ row = atom_getfloat(argv);
+ col = atom_getfloat(argv+1);
+ if ((row<1)||(col<1)){ post("matrix : corrupt matrix passed"); return; }
+ if (row*col > argc-2){ post("matrix: sparse matrices not yet supported : use \"mtx_check\""); return; }
+ matrix_matrix2(x, s, argc, argv);
+ matrix_bang(x);
+}
+static void mtx_col_list(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ if (argc==1){
+ t_float f=atom_getfloat(argv);
+ t_atom *ap=x->atombuffer+1+x->current_col;
+ if (x->current_col>x->col){
+ post("mtx_col : too high a column is to be set");
+ return;
+ }
+ if (x->current_col){
+ int n=x->row;
+ while(n--){
+ SETFLOAT(ap, f);
+ ap+=x->row+1;
+ }
+ }
+ matrix_bang(x);
+ return;
+ }
+
+ if (argc<x->row){
+ post("mtx_col : column length is too small for %dx%d-matrix", x->row, x->col);
+ return;
+ }
+ if (x->current_col>x->col){
+ post("mtx_col : too high a column is to be set");
+ return;
+ }
+ if(x->current_col) {
+ int r=x->row;
+ t_atom *ap=x->atombuffer+1+x->current_col;
+ while(r--)SETFLOAT(&ap[(x->row-r-1)*x->col], atom_getfloat(argv++));
+ } else {
+ int r=x->row;
+ t_atom *ap=x->atombuffer+2;
+ while (r--) {
+ t_float f=atom_getfloat(argv++);
+ int c=x->col;
+ while(c--){
+ SETFLOAT(ap, f);
+ ap++;
+ }
+ }
+ }
+ matrix_bang(x);
+}
+static void *mtx_col_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_matrix *x = (t_matrix *)pd_new(mtx_col_class);
+ int i, j, q;
+ outlet_new(&x->x_obj, 0);
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym(""));
+ x->current_col=0;
+ x->col=x->row=0;
+ x->atombuffer=0;
+ switch (argc) {
+ case 0:break;
+ case 1:
+ i = atom_getfloat(argv);
+ if (i<0)i=0;
+ if(i)adjustsize(x, i, i);
+ matrix_set(x, 0);
+ break;
+ case 2:
+ i = atom_getfloat(argv++);if(i<0)i=0;
+ j = atom_getfloat(argv++);if(j<0)j=0;
+ if(i*j)adjustsize(x, i, j);
+ matrix_set(x, 0);
+ break;
+ default:
+ i = atom_getfloat(argv++);if(i<0)i=0;
+ j = atom_getfloat(argv++);if(j<0)j=0;
+ q = atom_getfloat(argv++);if(q<0)q=0;
+ if(i*j)adjustsize(x, i, j);
+ matrix_set(x, 0);
+ x->current_col=q;
+ }
+ return (x);
+}
+void mtx_col_setup(void)
+{
+ mtx_col_class = class_new(gensym("mtx_col"), (t_newmethod)mtx_col_new,
+ (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0);
+ class_addbang (mtx_col_class, matrix_bang);
+ class_addlist (mtx_col_class, mtx_col_list);
+ class_addmethod(mtx_col_class, (t_method)mtx_col_matrix, gensym("matrix"), A_GIMME, 0);
+ class_addmethod(mtx_col_class, (t_method)mtx_col_float, gensym(""), A_FLOAT, 0);
+ class_sethelpsymbol(mtx_col_class, gensym("iemmatrix/mtx_element"));
+}
+
+void iemmtx_col_setup(void)
+{
+ mtx_col_setup();
+}
diff --git a/src/mtx_diag.c b/src/mtx_diag.c
new file mode 100644
index 0000000..65acff2
--- /dev/null
+++ b/src/mtx_diag.c
@@ -0,0 +1,59 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * (c) IOhannes m zmölnig, forum::für::umläute
+ *
+ * IEM, Graz
+ *
+ * this code is published under the LGPL
+ *
+ */
+#include "iemmatrix.h"
+
+/* mtx_diag */
+static t_class *mtx_diag_class;
+static void mtx_diag_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int row=atom_getfloat(argv++);
+ int col=atom_getfloat(argv++);
+ int length=(col<row)?col:row, n=length;
+ t_atom *ap = (t_atom *)getbytes(length * sizeof(t_atom)), *dummy=ap;
+ if(row*col>argc-2)post("mtx_diag: sparse matrices not yet supported : use \"mtx_check\"");
+ else {
+ for(n=0;n<length;n++, dummy++)SETFLOAT(dummy, atom_getfloat(argv+n*(col+1)));
+ outlet_list(x->x_obj.ob_outlet, gensym("diag"), length, ap);
+ }
+ freebytes(ap, (length * sizeof(t_atom)));
+}
+
+static void *mtx_diag_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_matrix *x = (t_matrix *)pd_new(mtx_diag_class);
+ outlet_new(&x->x_obj, 0);
+ x->row = x->col = 0;
+ x->atombuffer = 0;
+
+ if(!argc)return(x);
+ x->atombuffer = (t_atom *)getbytes((argc*argc+2)*sizeof(t_atom));
+ setdimen(x, argc, argc);
+ matrix_set(x, 0);
+ argv+=argc-1;
+ while(argc--)SETFLOAT(x->atombuffer+2+argc*(1+x->col), atom_getfloat(argv--));
+
+ return (x);
+}
+void mtx_diag_setup(void)
+{
+ mtx_diag_class = class_new(gensym("mtx_diag"), (t_newmethod)mtx_diag_new,
+ (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0);
+ class_addlist (mtx_diag_class, matrix_diag);
+ class_addbang (mtx_diag_class, matrix_bang);
+ class_addmethod(mtx_diag_class, (t_method)mtx_diag_matrix, gensym("matrix"), A_GIMME, 0);
+ class_sethelpsymbol(mtx_diag_class, gensym("iemmatrix/mtx_trace"));
+}
+void iemtx_diag_setup(void){
+ void mtx_diag_setup(void);
+}
diff --git a/src/mtx_diegg.c b/src/mtx_diegg.c
new file mode 100644
index 0000000..658471f
--- /dev/null
+++ b/src/mtx_diegg.c
@@ -0,0 +1,56 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * (c) IOhannes m zmölnig, forum::für::umläute
+ *
+ * IEM, Graz
+ *
+ * this code is published under the LGPL
+ *
+ */
+#include "iemmatrix.h"
+static t_class *mtx_diegg_class;
+static void mtx_diegg_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int row=atom_getfloat(argv++);
+ int col=atom_getfloat(argv++);
+ int length=(col<row)?col:row, n=length;
+ t_atom *ap = (t_atom *)getbytes(length * sizeof(t_atom)), *dummy=ap;
+ if(row*col>argc-2)post("mtx_diegg: sparse matrices not yet supported : use \"mtx_check\"");
+ else {
+ for(n=0;n<length;n++, dummy++)SETFLOAT(dummy, atom_getfloat(argv+(n-1)*(col-1)));
+ outlet_list(x->x_obj.ob_outlet, gensym("diegg"), length, ap);
+ }
+ freebytes(ap, (length * sizeof(t_atom)));
+}
+static void *mtx_diegg_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_matrix *x = (t_matrix *)pd_new(mtx_diegg_class);
+ outlet_new(&x->x_obj, 0);
+ x->row = x->col = 0;
+ x->atombuffer = 0;
+
+ if(!argc)return(x);
+ x->atombuffer = (t_atom *)getbytes((argc*argc+2)*sizeof(t_atom));
+ setdimen(x, argc, argc);
+ matrix_set(x, 0);
+ argv+=argc-1;
+ while(argc--)SETFLOAT(x->atombuffer+2+argc*(1+x->col), atom_getfloat(argv--));
+
+ return (x);
+}
+void mtx_diegg_setup(void)
+{
+ mtx_diegg_class = class_new(gensym("mtx_diegg"), (t_newmethod)mtx_diegg_new,
+ (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0);
+ class_addlist (mtx_diegg_class, matrix_diegg);
+ class_addbang (mtx_diegg_class, matrix_bang);
+ class_addmethod(mtx_diegg_class, (t_method)mtx_diegg_matrix, gensym("matrix"), A_GIMME, 0);
+ class_sethelpsymbol(mtx_diegg_class, gensym("iemmatrix/mtx_special"));
+}
+void iemtx_diegg_setup(void){
+ mtx_diegg_setup();
+}
diff --git a/src/mtx_egg.c b/src/mtx_egg.c
new file mode 100644
index 0000000..a44894c
--- /dev/null
+++ b/src/mtx_egg.c
@@ -0,0 +1,58 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * (c) IOhannes m zmölnig, forum::für::umläute
+ *
+ * IEM, Graz
+ *
+ * this code is published under the LGPL
+ *
+ */
+#include "iemmatrix.h"
+
+/* mtx_egg */
+static t_class *mtx_egg_class;
+static void *mtx_egg_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_matrix *x = (t_matrix *)pd_new(mtx_egg_class);
+ int col=0, row=0;
+ outlet_new(&x->x_obj, 0);
+ x->row = x->col = 0;
+ x->atombuffer = 0;
+ switch(argc) {
+ case 0:
+ break;
+ case 1:
+ col=row=atom_getfloat(argv);
+ break;
+ default:
+ row=atom_getfloat(argv++);
+ col=atom_getfloat(argv);
+ }
+ if(col<0)col=0;
+ if(row<0)row=0;
+ if (col*row){
+ int n = (col<row)?col:row;
+ x->atombuffer = (t_atom *)getbytes((col*row+2)*sizeof(t_atom));
+ setdimen(x, row, col);
+ matrix_set(x, 0);
+ while(n--)SETFLOAT(x->atombuffer+2+(n+1)*(col-1), 1);
+ }
+ return (x);
+}
+void mtx_egg_setup(void)
+{
+ mtx_egg_class = class_new(gensym("mtx_egg"), (t_newmethod)mtx_egg_new,
+ (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0);
+ class_addlist(mtx_egg_class, matrix_egg);
+ class_addbang(mtx_egg_class, matrix_bang);
+ class_addmethod(mtx_egg_class, (t_method)matrix_egg, gensym("matrix"), A_GIMME, 0);
+
+ class_sethelpsymbol(mtx_egg_class, gensym("iemmatrix/mtx_special"));
+}
+void iemtx_egg_setup(void){
+ mtx_egg_setup();
+}
diff --git a/src/mtx_element.c b/src/mtx_element.c
new file mode 100644
index 0000000..10d9664
--- /dev/null
+++ b/src/mtx_element.c
@@ -0,0 +1,118 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * (c) IOhannes m zmölnig, forum::für::umläute
+ *
+ * IEM, Graz
+ *
+ * this code is published under the LGPL
+ *
+ */
+#include "iemmatrix.h"
+
+
+/* mtx_element */
+static t_class *mtx_element_class;
+
+static void mtx_element_list2(t_matrix *x, t_floatarg f1, t_floatarg f2)
+{
+ int r = f1, c= f2;
+ if(r<0)r=0;
+ if(c<0)c=0;
+ x->current_row = r;
+ x->current_col = c;
+}
+static void mtx_element_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int row, col;
+ if (argc<2){ post("matrix : corrupt matrix passed"); return; }
+ row = atom_getfloat(argv);
+ col = atom_getfloat(argv+1);
+ if ((row<1)||(col<1)){ post("matrix : corrupt matrix passed"); return; }
+ if (row*col > argc-2){ post("matrix: sparse matrices not yet supported : use \"mtx_check\""); return; }
+ matrix_matrix2(x, s, argc, argv);
+ matrix_bang(x);
+}
+static void mtx_element_float(t_matrix *x, t_floatarg f)
+{
+ if(x->current_col>x->col || x->current_row>x->row){
+ error("mtx_element: element position exceeds matrix dimensions");
+ return;
+ }
+ if(x->current_row == 0 && x->current_col == 0){
+ matrix_set(x, f);
+ matrix_bang(x);
+ return;
+ }
+ if(x->current_row*x->current_col)SETFLOAT(x->atombuffer+1+(x->current_row-1)*x->col+x->current_col, f);
+ else {
+ t_atom *ap=x->atombuffer+2;
+ int count;
+ if (!x->current_col){
+ ap+=x->col*(x->current_row-1);
+ count=x->col;
+ while(count--)SETFLOAT(&ap[count], f);
+ } else { // x->current_row==0
+ ap+=x->current_col-1;
+ count=x->row;
+ while(count--)SETFLOAT(&ap[count*x->col], f);
+ }
+ }
+ matrix_bang(x);
+}
+
+static void *mtx_element_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_matrix *x = (t_matrix *)pd_new(mtx_element_class);
+ int i, j, q;
+ outlet_new(&x->x_obj, 0);
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym(""));
+ x->current_row=x->current_col=0;
+ x->col=x->row=0;
+ x->atombuffer=0;
+ switch (argc) {
+ case 1:
+ i = atom_getfloat(argv);
+ if (i<0)i=0;
+ if(i)adjustsize(x, i, i);
+ matrix_set(x, 0);
+ break;
+ case 2:
+ i = atom_getfloat(argv++);if(i<0)i=0;
+ j = atom_getfloat(argv++);if(j<0)j=0;
+ if(i*j)adjustsize(x, i, j);
+ matrix_set(x, 0);
+ break;
+ case 4:
+ i = atom_getfloat(argv++);if(i<0)i=0;
+ j = atom_getfloat(argv++);if(j<0)j=0;
+ if(i*j)adjustsize(x, i, j);
+ matrix_set(x, 0);
+ q = atom_getfloat(argv++);if(q<0)q=0;
+ x->current_row=q;
+ q = atom_getfloat(argv++);if(q<0)q=0;
+ x->current_col=q;
+ break;
+ default:;
+ }
+ return (x);
+}
+void mtx_element_setup(void)
+{
+ mtx_element_class = class_new(gensym("mtx_element"), (t_newmethod)mtx_element_new,
+ (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0);
+ class_addbang (mtx_element_class, matrix_bang);
+ class_addfloat (mtx_element_class, mtx_element_float);
+ class_addmethod(mtx_element_class, (t_method)mtx_element_matrix, gensym("matrix"), A_GIMME, 0);
+ class_addmethod(mtx_element_class, (t_method)mtx_element_list2, gensym(""), A_FLOAT, A_FLOAT, 0);
+ class_sethelpsymbol(mtx_element_class, gensym("iemmatrix/mtx_element"));
+}
+
+
+void iemmtx_element_setup(void)
+{
+ mtx_element_setup();
+}
diff --git a/src/mtx_eye.c b/src/mtx_eye.c
new file mode 100644
index 0000000..e416ac4
--- /dev/null
+++ b/src/mtx_eye.c
@@ -0,0 +1,60 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * (c) IOhannes m zmölnig, forum::für::umläute
+ *
+ * IEM, Graz
+ *
+ * this code is published under the LGPL
+ *
+ */
+#include "iemmatrix.h"
+
+/* ------------------------------------------------------------------------------------- */
+
+/* mtx_eye */
+static t_class *mtx_eye_class;
+static void *mtx_eye_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_matrix *x = (t_matrix *)pd_new(mtx_eye_class);
+ int col=0, row=0;
+ outlet_new(&x->x_obj, 0);
+ x->row = x->col = 0;
+ x->atombuffer = 0;
+ switch(argc) {
+ case 0:
+ break;
+ case 1:
+ col=row=atom_getfloat(argv);
+ break;
+ default:
+ row=atom_getfloat(argv++);
+ col=atom_getfloat(argv);
+ }
+ if(col<0)col=0;
+ if(row<0)row=0;
+ if (col*row){
+ int n = (col<row)?col:row;
+ x->atombuffer = (t_atom *)getbytes((col*row+2)*sizeof(t_atom));
+ setdimen(x, row, col);
+ matrix_set(x, 0);
+ while(n--)SETFLOAT(x->atombuffer+2+n*(1+col), 1);
+ }
+ return (x);
+}
+void mtx_eye_setup(void)
+{
+ mtx_eye_class = class_new(gensym("mtx_eye"), (t_newmethod)mtx_eye_new,
+ (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0);
+ class_addlist(mtx_eye_class, matrix_eye);
+ class_addbang(mtx_eye_class, matrix_bang);
+ class_addmethod(mtx_eye_class, (t_method)matrix_eye, gensym("matrix"), A_GIMME, 0);
+
+ class_sethelpsymbol(mtx_eye_class, gensym("iemmatrix/mtx_special"));
+}
+void iemtx_eye_setup(void){
+ mtx_eye_setup();
+}
diff --git a/src/mtx_inverse.c b/src/mtx_inverse.c
new file mode 100644
index 0000000..400f734
--- /dev/null
+++ b/src/mtx_inverse.c
@@ -0,0 +1,118 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * (c) IOhannes m zmölnig, forum::für::umläute
+ *
+ * IEM, Graz
+ *
+ * this code is published under the LGPL
+ *
+ */
+#include "iemmatrix.h"
+
+/* mtx_inverse */
+static t_class *mtx_inverse_class;
+
+static void mtx_inverse_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ /* maybe we should do this in double or long double ? */
+ int row=atom_getfloat(argv);
+ int col=atom_getfloat(argv+1);
+ int i, k, row2=row*row;
+
+ t_matrixfloat *original, *inverted;
+ t_matrixfloat *a1, *a2, *b1, *b2; // dummy pointers
+
+ int ok = 0;
+
+ if(row*col+2>argc){
+ post("mtx_print : sparse matrices not yet supported : use \"mtx_check\"");
+ return;
+ }
+ if (row!=col){
+ post("mtx_inverse: only square matrices can be inverted");
+ return;
+ }
+
+ // reserve memory for outputting afterwards
+ adjustsize(x, row, row);
+ // 1. get the 2 matrices : orig; invert (create as eye, but will be orig^(-1))
+ inverted = (t_matrixfloat *)getbytes(sizeof(t_matrixfloat)*row2);
+ // 1a extract values of A to float-buf
+ original=matrix2float(argv);
+ // 1b make an eye-shaped float-buf for B
+ i=row2;
+ b1=inverted;
+ while(i--)*b1++=0;
+ i=row;
+ b1=inverted;
+ while(i--)b1[i*(row+1)]=1;
+
+ // 2. do the Gauss-Jordan
+ for (k=0;k<row;k++) {
+ // 2. adjust current row
+ t_matrixfloat diagel = original[k*(col+1)];
+ t_matrixfloat i_diagel = diagel?1./diagel:0;
+ if (!diagel)ok++;
+
+
+ /* normalize current row (set the diagonal-element to 1 */
+ a2=original+k*col;
+ b2=inverted+k*col;
+ i=row;
+ while(i--){
+ *a2++*=i_diagel;
+ *b2++*=i_diagel;
+ }
+ /* eliminate the k-th element in each row by adding the weighted normalized row */
+
+ a2=original+k*row;
+ b2=inverted+k*row;
+ for(i=0;i<row;i++)
+ if (i-k) {
+ t_matrixfloat f=-*(original+i*row+k);
+ int j = row;
+ a1=original+i*row;
+ b1=inverted+i*row;
+ while (j--) {
+ *(a1+j)+=f**(a2+j);
+ *(b1+j)+=f**(b2+j);
+ }
+ }
+ }
+ // 3. output the matrix
+ // 3a convert the floatbuf to an atombuf;
+ float2matrix(x->atombuffer, inverted);
+ // 3b destroy the buffers
+ freebytes(original, sizeof(t_matrixfloat)*row2);
+
+ if (ok)post("mtx_inverse: couldn't really invert the matrix !!! %d error%c", ok, (ok-1)?'s':0);
+
+ // 3c output the atombuf;
+ matrix_bang(x);
+}
+
+static void *mtx_inverse_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_matrix *x = (t_matrix *)pd_new(mtx_inverse_class);
+ outlet_new(&x->x_obj, 0);
+ x->col=x->row=0;
+ x->atombuffer=0;
+
+ return (x);
+}
+void mtx_inverse_setup(void)
+{
+ mtx_inverse_class = class_new(gensym("mtx_inverse"), (t_newmethod)mtx_inverse_new,
+ (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0);
+ class_addbang (mtx_inverse_class, matrix_bang);
+ class_addmethod(mtx_inverse_class, (t_method)mtx_inverse_matrix, gensym("matrix"), A_GIMME, 0);
+ class_sethelpsymbol(mtx_inverse_class, gensym("iemmatrix/mtx_inverse"));
+}
+
+void iemtx_inverse_setup(void){
+ mtx_inverse_setup();
+}
diff --git a/src/mtx_matrix.c b/src/mtx_matrix.c
new file mode 100644
index 0000000..98df0d2
--- /dev/null
+++ b/src/mtx_matrix.c
@@ -0,0 +1,606 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * (c) IOhannes m zmölnig, forum::für::umläute
+ *
+ * IEM, Graz
+ *
+ * this code is published under the LGPL
+ *
+ */
+
+/*
+ matrix : basic object : create and store matrices
+ mtx : alias for matrix
+*/
+
+#include "iemmatrix.h"
+
+/* -------------------- matrix ------------------------------ */
+
+static t_class *matrix_class;
+
+/* intern utility functions */
+
+void setdimen(t_matrix *x, int row, int col)
+{
+ x->col = col;
+ x->row = row;
+ SETFLOAT(x->atombuffer, row);
+ SETFLOAT(x->atombuffer+1, col);
+}
+
+void adjustsize(t_matrix *x, int desiredRow, int desiredCol)
+{
+ int col=x->col, row=x->row;
+
+ if (desiredRow<1){
+ post("cannot make less than 1 rows");
+ desiredRow=1;
+ }
+ if (desiredCol<1){
+ post("cannot make less than 1 columns");
+ desiredCol=1;
+ }
+
+ if (col*row!=desiredRow*desiredCol){
+ if(x->atombuffer)freebytes(x->atombuffer, (col*row+2)*sizeof(t_atom));
+ x->atombuffer=(t_atom *)getbytes((desiredCol*desiredRow+2)*sizeof(t_atom));
+ }
+
+ setdimen(x, desiredRow, desiredCol);
+ return;
+}
+
+void debugmtx(int argc, t_float *buf, int id)
+{
+ int i=argc;
+ while(i--){
+ int j=argc;
+ startpost("debug%d: ", id);
+ while(j--)
+ startpost("%f ", *buf++);
+ endpost();
+ }
+}
+t_matrixfloat *matrix2float(t_atom *ap)
+{
+ int row = atom_getfloat(ap++);
+ int col=atom_getfloat(ap++);
+ int length = row * col;
+ t_matrixfloat *buffer = (t_matrixfloat *)getbytes(sizeof(t_matrixfloat)*length);
+ t_matrixfloat *buf = buffer;
+ while(length--)*buf++=atom_getfloat(ap++);
+ return buffer;
+}
+void float2matrix(t_atom *ap, t_matrixfloat *buffer)
+{
+ int row=atom_getfloat(ap++);
+ int col=atom_getfloat(ap++);
+ int length = row * col;
+ t_matrixfloat*buf= buffer;
+ while(length--){
+ SETFLOAT(ap, *buf++);
+ ap++;
+ }
+ freebytes(buffer, row*col*sizeof(t_matrixfloat));
+}
+
+/* core functions */
+void matrix_bang(t_matrix *x)
+{
+ /* output the matrix */
+ if (x->atombuffer)outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), x->col*x->row+2, x->atombuffer);
+}
+
+void matrix_matrix2(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int row, col;
+
+ if (argc<2){
+ post("matrix : corrupt matrix passed");
+ return;
+ }
+ row = atom_getfloat(argv);
+ col = atom_getfloat(argv+1);
+ if ((row<1)||(col<1)){
+ post("matrix : corrupt matrix passed");
+ return;
+ }
+ if (row*col > argc-2){
+ post("matrix: sparse matrices not yet supported : use \"mtx_check\"");
+ return;
+ }
+
+ /* this is fast and dirty, MAYBE make it slow and clean */
+ /* or, to clean matrices, use the mtx_check object */
+ if (row*col != x->row*x->col) {
+ freebytes(x->atombuffer, x->row*x->col*sizeof(t_atom));
+ x->atombuffer = copybytes(argv, (row*col+2)*sizeof(t_atom));
+ } else memcpy(x->atombuffer, argv, (row*col+2)*sizeof(t_atom));
+
+ setdimen(x, row, col);
+}
+
+static void matrix_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int row, col;
+
+ if (argc<2){
+ post("matrix : corrupt matrix passed");
+ return;
+ }
+ row = atom_getfloat(argv);
+ col = atom_getfloat(argv+1);
+ if ((row<1)||(col<1)){
+ post("matrix : corrupt matrix passed");
+ return;
+ }
+ if (row*col > argc-2){
+ post("matrix: sparse matrices not yet supported : use \"mtx_check\"");
+ return;
+ }
+
+ matrix_matrix2(x, s, argc, argv);
+ matrix_bang(x);
+}
+
+
+/* basic functions */
+
+void matrix_set(t_matrix *x, t_float f)
+{
+ int size = x->col * x->row;
+ t_atom *buf=x->atombuffer+2;
+ if(x->atombuffer)while(size--)SETFLOAT(&buf[size], f);
+}
+
+void matrix_zeros(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int col, row;
+
+ switch(argc) {
+ case 0: /* zero out the actual matrix */
+ matrix_set(x, 0);
+ break;
+ case 1:
+ row=atom_getfloat(argv);
+ adjustsize(x, row, row);
+ matrix_set(x, 0);
+ break;
+ default:
+ row=atom_getfloat(argv++);
+ col=atom_getfloat(argv);
+ adjustsize(x, row, col);
+
+ matrix_set(x, 0);
+ }
+
+ matrix_bang(x);
+}
+
+void matrix_ones(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int col, row;
+
+ switch(argc) {
+ case 0: /* zero out the actual matrix */
+ matrix_set(x, 1);
+ break;
+ case 1:
+ row=atom_getfloat(argv);
+ adjustsize(x, row, row);
+ matrix_set(x, 1);
+ break;
+ default:
+ row=atom_getfloat(argv++);
+ col=atom_getfloat(argv);
+ adjustsize(x, row, col);
+
+ matrix_set(x, 1);
+ }
+
+ matrix_bang(x);
+}
+
+void matrix_eye(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int col, row;
+ int n;
+
+ switch(argc) {
+ case 0: /* zero out the actual matrix */
+ matrix_set(x, 0);
+ break;
+ case 1:
+ row=atom_getfloat(argv);
+ adjustsize(x, row, row);
+ matrix_set(x, 0);
+ break;
+ default:
+ row=atom_getfloat(argv++);
+ col=atom_getfloat(argv);
+ adjustsize(x, row, col);
+ matrix_set(x, 0);
+ }
+
+ col=x->col;
+ row=x->row;
+ n = (col<row)?col:row;
+ while(n--)SETFLOAT(x->atombuffer+2+n*(1+col), 1);
+
+ matrix_bang(x);
+}
+void matrix_egg(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int col, row;
+ int n;
+
+ switch(argc) {
+ case 0: /* zero out the actual matrix */
+ matrix_set(x, 0);
+ break;
+ case 1:
+ row=atom_getfloat(argv);
+ adjustsize(x, row, row);
+ matrix_set(x, 0);
+ break;
+ default:
+ row=atom_getfloat(argv++);
+ col=atom_getfloat(argv);
+ adjustsize(x, row, col);
+ matrix_set(x, 0);
+ }
+
+ col=x->col;
+ row=x->row;
+ n = (col<row)?col:row;
+ while(n--)SETFLOAT(x->atombuffer+2+(n+1)*(col-1), 1);
+
+ matrix_bang(x);
+}
+
+void matrix_diag(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int col=argc;
+ argv+=argc-1;
+ if (argc<1) {
+ post("matrix: no diagonale present");
+ return;
+ }
+ adjustsize(x, argc, argc);
+ matrix_set(x, 0);
+
+ while(argc--)SETFLOAT(x->atombuffer+2+argc*(1+col), atom_getfloat(argv--));
+
+ matrix_bang(x);
+}
+void matrix_diegg(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int col=argc;
+ argv+=argc-1;
+ if (argc<1) {
+ post("matrix: no dieggonale present");
+ return;
+ }
+ adjustsize(x, argc, argc);
+ matrix_set(x, 0);
+
+ while(argc--){
+ t_atom *ap=x->atombuffer+2+(argc+1)*(col-1);
+ SETFLOAT(ap, atom_getfloat(argv--));
+ }
+
+ matrix_bang(x);
+}
+/* the rest */
+
+void matrix_row(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ t_atom *ap;
+ int row=x->row, col=x->col;
+ int r;
+ t_float f;
+
+ switch (argc){
+ case 0:
+ for (r=0;r<row;r++)outlet_list(x->x_obj.ob_outlet, gensym("row"), col, x->atombuffer+r*col+2);
+ break;
+ case 1:
+ r=atom_getfloat(argv)-1;
+ if ((r<0)||(r>=row)){
+ post("matrix: row index %d is out of range", r+1);
+ return;
+ }
+ outlet_list(x->x_obj.ob_outlet, gensym("row"), col, x->atombuffer+r*col+2);
+ break;
+ case 2:
+ r=atom_getfloat(argv)-1;
+ f=atom_getfloat(argv+1);
+ if ((r<0)||(r>=row)){
+ post("matrix: row index %d is out of range", r+1);
+ return;
+ }
+
+
+ default:
+ r=atom_getfloat(argv++)-1;
+ if (argc--<col){
+ post("matrix: sparse rows not yet supported : use \"mtx_check\"");
+ return;
+ }
+ if ((r<0)||(r>=row)){
+ post("matrix: row index %d is out of range", r+1);
+ return;
+ }
+ if (r==row) {
+ } else {
+ ap=x->atombuffer+2+col*r;
+ memcpy(ap, argv, col*sizeof(t_atom));
+ }
+ }
+}
+
+void matrix_col(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ t_atom *ap;
+ int row=x->row, col=x->col;
+ int c, r;
+
+ switch (argc){
+ case 0:
+ ap=(t_atom *)getbytes(row*sizeof(t_atom));
+ for (c=0;c<col;c++) {
+ for (r=0;r<row;r++)SETFLOAT(&ap[r], atom_getfloat(x->atombuffer+2+c+col*r));
+ outlet_list(x->x_obj.ob_outlet, gensym("col"), row, ap);
+ }
+ freebytes(ap, row*sizeof(t_atom));
+ break;
+ case 1:
+ ap=(t_atom *)getbytes(row*sizeof(t_atom));
+ c=atom_getfloat(argv)-1;
+ if ((c<0)||(c>=col)){
+ post("matrix: col index %d is out of range", c+1);
+ return;
+ }
+ for (r=0;r<row;r++)SETFLOAT(&ap[r], atom_getfloat(x->atombuffer+2+c+col*r));
+ outlet_list(x->x_obj.ob_outlet, gensym("col"), row, ap);
+ freebytes(ap, row*sizeof(t_atom));
+ break;
+ default:
+ c=atom_getfloat(argv++)-1;
+ if (argc--<row){
+ post("matrix: sparse cols not yet supported : use \"mtx_check\"");
+ return;
+ }
+ if ((c<0)||(c>=col)){
+ post("matrix: col index %d is out of range", c+1);
+ return;
+ }
+ argv+=argc-1;
+ if (argc>row)argc=row;
+ while(argc--){
+ ap=x->atombuffer+2+c+col*argc;
+ SETFLOAT(ap, atom_getfloat(argv--));
+ }
+ }
+}
+
+void matrix_element(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ t_atom *ap=x->atombuffer+2;
+ int row=x->row, col=x->col;
+ int r, c, i=row*col;
+
+ switch (argc){
+ case 0:
+ while(i--)outlet_float(x->x_obj.ob_outlet, atom_getfloat(ap++));
+ break;
+ case 1:
+ r=c=atom_getfloat(argv)-1;
+ if ((r<0)||(r>=row)){
+ post("matrix: row index %d is out of range", r+1);
+ return;
+ }
+ if ((c<0)||(c>=col)){
+ post("matrix: col index %d is out of range", c+1);
+ return;
+ }
+ outlet_float(x->x_obj.ob_outlet, atom_getfloat(x->atombuffer+2+c+r*col));
+ break;
+ case 2:
+ r=atom_getfloat(argv++)-1;
+ c=atom_getfloat(argv++)-1;
+ if ((r<0)||(r>=row)){ post("matrix: row index %d is out of range", r+1); return; }
+ if ((c<0)||(c>=col)){ post("matrix: col index %d is out of range", c+1); return; }
+ outlet_float(x->x_obj.ob_outlet, atom_getfloat(x->atombuffer+2+c+r*col));
+ break;
+ default:
+ r=atom_getfloat(argv++)-1;
+ c=atom_getfloat(argv++)-1;
+ if ((r<0)||(r>=row)){ post("matrix: row index %d is out of range", r+1); return; }
+ if ((c<0)||(c>=col)){ post("matrix: col index %d is out of range", c+1); return; }
+ SETFLOAT(x->atombuffer+2+c+r*col, atom_getfloat(argv));
+ }
+}
+
+static void matrix_float(t_matrix *x, t_float f)
+{
+ matrix_set(x, f);
+ matrix_bang(x);
+}
+
+/* ------------- file I/O ------------------ */
+
+static void matrix_read(t_matrix *x, t_symbol *filename)
+{
+ t_binbuf *bbuf = binbuf_new();
+ t_atom *ap;
+ int n;
+
+ if (binbuf_read_via_path(bbuf, filename->s_name, canvas_getdir(x->x_canvas)->s_name, 0))
+ error("matrix: failed to read %s", filename->s_name);
+
+ ap=binbuf_getvec(bbuf);
+ n =binbuf_getnatom(bbuf)-1;
+
+ if ((ap->a_type == A_SYMBOL) &&
+ (!strcmp(ap->a_w.w_symbol->s_name,"matrix") || !strcmp(ap->a_w.w_symbol->s_name,"#matrix")) ){
+ matrix_matrix2(x, gensym("matrix"), n, ap+1);
+ }
+
+ binbuf_free(bbuf);
+}
+static void matrix_write(t_matrix *x, t_symbol *filename)
+{
+ t_atom *ap=x->atombuffer+2;
+ char filnam[MAXPDSTRING];
+ int rows = x->row, cols = x->col;
+ FILE *f=0;
+
+ sys_bashfilename(filename->s_name, filnam);
+
+ /* open file */
+ if (!(f = fopen(filnam, "w"))) {
+ error("matrix : failed to open %s", filnam);
+ } else {
+ char *text=(char *)getbytes(sizeof(char)*MAXPDSTRING);
+ int textlen;
+
+ /* header:
+ * we now write "#matrix" instead of "matrix",
+ * so that these files can easily read by other
+ * applications such as octave
+ */
+ sprintf(text, "#matrix %d %d\n", rows, cols);
+ textlen = strlen(text);
+ if (fwrite(text, textlen*sizeof(char), 1, f) < 1) {
+ error("matrix : failed to write %s", filnam); goto end;
+ }
+
+ while(rows--) {
+ int c = cols;
+ while (c--) {
+ t_float val = atom_getfloat(ap++);
+ sprintf(text, "%.15f ", val);
+ textlen=strlen(text);
+ if (fwrite(text, textlen*sizeof(char), 1, f) < 1) {
+ error("matrix : failed to write %s", filnam); goto end;
+ }
+ }
+ if (fwrite("\n", sizeof(char), 1, f) < 1) {
+ error("matrix : failed to write %s", filnam); goto end;
+ }
+ }
+ freebytes(text, sizeof(char)*MAXPDSTRING);
+ }
+
+ end:
+ /* close file */
+ if (f) fclose(f);
+}
+
+void matrix_free(t_matrix *x)
+{
+ freebytes(x->atombuffer, (x->col*x->row+2)*sizeof(t_atom));
+ x->atombuffer=0;
+ x->col=x->row=0;
+}
+static void matrix_list(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ /* like matrix, but without col/row information, so the previous size is kept */
+ int row=x->row, col=x->col;
+
+ if(!row*col){
+ post("matrix : unknown matrix dimensions");
+ return;
+ }
+ if (argc<row*col){
+ post("matrix: sparse matrices not yet supported : use \"mtx_check\" !");
+ return;
+ }
+
+ memcpy(x->atombuffer+2, argv, row*col*sizeof(t_atom));
+ matrix_bang(x);
+}
+
+static void *matrix_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_matrix *x = (t_matrix *)pd_new(matrix_class);
+ int row, col;
+
+
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("matrix"), gensym(""));
+ outlet_new(&x->x_obj, 0);
+
+ x->atombuffer = 0;
+ x->x_canvas = canvas_getcurrent();
+
+ switch (argc) {
+ case 0:
+ row = col = 0;
+ break;
+ case 1:
+ if (argv->a_type == A_SYMBOL) {
+ matrix_read(x, argv->a_w.w_symbol);
+ return(x);
+ }
+ row = col = atom_getfloat(argv);
+ break;
+ default:
+ row = atom_getfloat(argv++);
+ col = atom_getfloat(argv++);
+ }
+
+ if(row*col){
+ adjustsize(x, row, col);
+ matrix_set(x, 0);
+ }
+
+ return (x);
+}
+
+void matrix_setup(void)
+{
+ matrix_class = class_new(gensym("matrix"), (t_newmethod)matrix_new,
+ (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0);
+ class_addcreator((t_newmethod)matrix_new, gensym("mtx"), A_GIMME, 0);
+
+ /* the core : functions for matrices */
+ class_addmethod (matrix_class, (t_method)matrix_matrix, gensym("matrix"), A_GIMME, 0);
+ class_addmethod (matrix_class, (t_method)matrix_matrix2, gensym(""), A_GIMME, 0);
+
+ /* the basics : functions for creation */
+ class_addmethod (matrix_class, (t_method)matrix_eye, gensym("eye"), A_GIMME, 0);
+ class_addmethod (matrix_class, (t_method)matrix_diag, gensym("diag"), A_GIMME, 0);
+ class_addmethod (matrix_class, (t_method)matrix_ones, gensym("ones"), A_GIMME, 0);
+ class_addmethod (matrix_class, (t_method)matrix_zeros, gensym("zeros"), A_GIMME, 0);
+ class_addmethod (matrix_class, (t_method)matrix_egg, gensym("egg"), A_GIMME, 0);
+ class_addmethod (matrix_class, (t_method)matrix_diegg, gensym("diegg"), A_GIMME, 0);
+
+ /* the rest : functions for anything */
+ class_addbang (matrix_class, matrix_bang);
+ class_addfloat (matrix_class, matrix_float);
+ class_addlist (matrix_class, matrix_list);
+ class_addmethod (matrix_class, (t_method)matrix_row, gensym("row"), A_GIMME, 0);
+ class_addmethod (matrix_class, (t_method)matrix_col, gensym("column"), A_GIMME, 0);
+ class_addmethod (matrix_class, (t_method)matrix_col, gensym("col"), A_GIMME, 0);
+ class_addmethod (matrix_class, (t_method)matrix_element, gensym("element"), A_GIMME, 0);
+
+ /* the file functions */
+ class_addmethod (matrix_class, (t_method)matrix_write, gensym("write"), A_SYMBOL, 0);
+ class_addmethod (matrix_class, (t_method)matrix_read , gensym("read") , A_SYMBOL, 0);
+
+ class_sethelpsymbol(matrix_class, gensym("iemmatrix/matrix"));
+}
+
+void iemmtx_matrix_setup(void){
+ matrix_setup();
+}
+
+void mtx_matrix_setup(void){
+ matrix_setup();
+}
diff --git a/src/mtx_mean.c b/src/mtx_mean.c
new file mode 100644
index 0000000..bb0d870
--- /dev/null
+++ b/src/mtx_mean.c
@@ -0,0 +1,61 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * (c) IOhannes m zmölnig, forum::für::umläute
+ *
+ * IEM, Graz
+ *
+ * this code is published under the LGPL
+ *
+ */
+#include "iemmatrix.h"
+
+
+/* mtx_mean */
+static t_class *mtx_mean_class;
+
+static void mtx_mean_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int row=atom_getfloat(argv++);
+ int col=atom_getfloat(argv++);
+ t_atom *ip, *op;
+ int c=col, r;
+ t_float sum;
+ t_float factor=1./row;
+ adjustsize(x, 1, col);
+ op=x->atombuffer;
+
+ while(c--){
+ sum=0;
+ ip=argv+col-c-1;
+ r=row;
+ while(r--)sum+=atom_getfloat(ip+col*r);
+ SETFLOAT(op, sum*factor);
+ op++;
+ }
+ outlet_list(x->x_obj.ob_outlet, gensym("row"), col, x->atombuffer);
+}
+
+static void *mtx_mean_new(void)
+{
+ t_matrix *x = (t_matrix *)pd_new(mtx_mean_class);
+ outlet_new(&x->x_obj, 0);
+ x->col=x->row=0;
+ x->atombuffer=0;
+ return (x);
+}
+void mtx_mean_setup(void)
+{
+ mtx_mean_class = class_new(gensym("mtx_mean"), (t_newmethod)mtx_mean_new,
+ (t_method)matrix_free, sizeof(t_matrix), 0, 0, 0);
+ class_addmethod(mtx_mean_class, (t_method)mtx_mean_matrix, gensym("matrix"), A_GIMME, 0);
+ class_sethelpsymbol(mtx_mean_class, gensym("iemmatrix/mtx_mean"));
+}
+
+void iemtx_mean_setup(void)
+{
+ mtx_mean_setup();
+}
diff --git a/src/mtx_ones.c b/src/mtx_ones.c
new file mode 100644
index 0000000..c3dccf5
--- /dev/null
+++ b/src/mtx_ones.c
@@ -0,0 +1,56 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * (c) IOhannes m zmölnig, forum::für::umläute
+ *
+ * IEM, Graz
+ *
+ * this code is published under the LGPL
+ *
+ */
+#include "iemmatrix.h"
+
+/* mtx_ones */
+static t_class *mtx_ones_class;
+static void *mtx_ones_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_matrix *x = (t_matrix *)pd_new(mtx_ones_class);
+ int col=0, row=0;
+ outlet_new(&x->x_obj, 0);
+ x->row = x->col = 0;
+ x->atombuffer = 0;
+ switch(argc) {
+ case 0:
+ break;
+ case 1:
+ col=row=atom_getfloat(argv);
+ break;
+ default:
+ row=atom_getfloat(argv++);
+ col=atom_getfloat(argv);
+ }
+ if(col<0)col=0;
+ if(row<0)row=0;
+ if (col*row){
+ x->atombuffer = (t_atom *)getbytes((col*row+2)*sizeof(t_atom));
+ setdimen(x, row, col);
+ matrix_set(x, 1);
+ }
+ return (x);
+}
+void mtx_ones_setup(void)
+{
+ mtx_ones_class = class_new(gensym("mtx_ones"), (t_newmethod)mtx_ones_new,
+ (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0);
+ class_addlist(mtx_ones_class, matrix_ones);
+ class_addbang(mtx_ones_class, matrix_bang);
+ class_addmethod(mtx_ones_class, (t_method)matrix_ones, gensym("matrix"), A_GIMME, 0);
+
+ class_sethelpsymbol(mtx_ones_class, gensym("iemmatrix/mtx_special"));
+}
+void iemtx_ones_setup(void){
+ mtx_ones_setup();
+}
diff --git a/src/mtx_pivot.c b/src/mtx_pivot.c
new file mode 100644
index 0000000..1ac4804
--- /dev/null
+++ b/src/mtx_pivot.c
@@ -0,0 +1,171 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * (c) IOhannes m zmölnig, forum::für::umläute
+ *
+ * IEM, Graz
+ *
+ * this code is published under the LGPL
+ *
+ */
+#include "iemmatrix.h"
+
+
+/* mtx_pivot */
+static t_class *mtx_pivot_class;
+
+typedef struct _mtx_pivot
+{
+ t_object x_obj;
+
+ t_matrix m; // the output matrix
+ t_matrix m_pre; // the pre -multiply matrix
+ t_matrix m_post; // the post-multiply matrix
+
+ t_outlet *pivo, *pre, *post;
+
+} t_mtx_pivot;
+
+static void mtx_pivot_matrix(t_mtx_pivot *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int row=atom_getfloat(argv);
+ int col=atom_getfloat(argv+1);
+ t_atom *m_pre, *m_post;
+ int i, j, k;
+ int min_rowcol = (row<col)?row:col;
+ t_matrixfloat *buffer, *buf;
+ int *i_pre, *i_post, *i_buf;
+
+ int pivot_row, pivot_col;
+
+ if (argc<2){ post("mtx_pivot: crippled matrix"); return; }
+ if ((col<1)||(row<1)) { post("mtx_pivot: invalid dimensions"); return; }
+ if (col*row>argc-2){ post("sparse matrix not yet supported : use \"mtx_check\""); return; }
+
+ adjustsize(&x->m, row, col);
+ adjustsize(&x->m_pre, row, row);
+ adjustsize(&x->m_post,col, col);
+ matrix_set(&x->m_pre, 0);
+ matrix_set(&x->m_post, 0);
+
+ buffer = matrix2float(argv);
+ i_pre = (int *)getbytes(sizeof(int)*row);
+ i_post = (int *)getbytes(sizeof(int)*col);
+
+ /* clear pre&post matrices */
+ i=row;
+ i_buf=i_pre;
+ while(i--)*i_buf++=row-i-1;
+ i=col;
+ i_buf=i_post;
+ while(i--)*i_buf++=col-i-1;
+
+ /* do the pivot thing */
+
+ for (k=0; k<min_rowcol-1; k++){
+ // 1. find max_element
+ t_matrixfloat max = 0;
+ pivot_row = pivot_col = k;
+
+ for(i=k; i<row; i++){
+ buf=buffer+col*i+k;
+
+ j=col-k;
+ while(j--){
+ t_matrixfloat f = fabsf(*buf++);
+ if (f>max) {
+ max=f;
+ pivot_row = i;
+ pivot_col = col-j-1;
+ }
+ }
+ }
+ // 2. move max el to [k,k]
+ // 2a swap rows
+ if (k-pivot_row) {
+ t_matrixfloat *oldrow=buffer+col*k;
+ t_matrixfloat *newrow=buffer+col*pivot_row;
+
+ i=col;
+ while(i--){
+ t_matrixfloat f=*oldrow;
+ *oldrow++=*newrow;
+ *newrow++=f;
+ }
+ i=i_pre[k];
+ i_pre[k]=i_pre[pivot_row];
+ i_pre[pivot_row]=i;
+ }
+ // 2b swap columns
+ if (k-pivot_col) {
+ t_matrixfloat *oldcol=buffer+k;
+ t_matrixfloat *newcol=buffer+pivot_col;
+
+ i=row;
+ while(i--){
+ t_matrixfloat f=*oldcol;
+ *oldcol=*newcol;
+ *newcol=f;
+ oldcol+=col;
+ newcol+=col;
+ }
+ i=i_post[k];
+ i_post[k]=i_post[pivot_col];
+ i_post[pivot_col]=i;
+ }
+ }
+
+ float2matrix(x->m.atombuffer, buffer);
+
+ i=col;
+ m_post = x->m_post.atombuffer+2;
+ while(i--){
+ SETFLOAT(m_post+i_post[i]*col+i, 1);
+ }
+ i=row;
+ m_pre = x->m_pre.atombuffer+2;
+ while(i--)SETFLOAT(m_pre+i_pre[i]+i*col, 1);
+
+
+ outlet_anything(x->post, gensym("matrix"), 2+col*col, x->m_post.atombuffer);
+ outlet_anything(x->pre, gensym("matrix"), 2+row*row, x->m_pre.atombuffer);
+ outlet_anything(x->pivo , gensym("matrix"), 2+row*col, x->m.atombuffer );
+}
+
+static void mtx_pivot_free(t_mtx_pivot *x)
+{
+ matrix_free(&x->m);
+ matrix_free(&x->m_pre);
+ matrix_free(&x->m_post);
+}
+
+static void *mtx_pivot_new(void)
+{
+ t_mtx_pivot *x = (t_mtx_pivot *)pd_new(mtx_pivot_class);
+
+ x->pivo = outlet_new(&x->x_obj, 0);
+ x->pre = outlet_new(&x->x_obj, 0);
+ x->post = outlet_new(&x->x_obj, 0);
+
+ x->m.atombuffer = x->m_pre.atombuffer = x->m_post.atombuffer = 0;
+ x->m.row = x->m.col = x->m_pre.row = x->m_pre.col = x->m_post.row = x->m_post.col = 0;
+
+ return(x);
+}
+
+void mtx_pivot_setup(void)
+{
+ mtx_pivot_class = class_new(gensym("mtx_pivot"), (t_newmethod)mtx_pivot_new, (t_method)mtx_pivot_free,
+ sizeof(t_mtx_pivot), 0, 0, 0);
+ class_addmethod(mtx_pivot_class, (t_method)mtx_pivot_matrix, gensym("matrix"), A_GIMME, 0);
+
+ class_sethelpsymbol(mtx_pivot_class, gensym("iemmatrix/mtx_transpose"));
+}
+
+void iemtx_pivot_setup(void)
+{
+ mtx_pivot_setup();
+}
diff --git a/src/mtx_print.c b/src/mtx_print.c
new file mode 100644
index 0000000..3b1d028
--- /dev/null
+++ b/src/mtx_print.c
@@ -0,0 +1,60 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * (c) IOhannes m zmölnig, forum::für::umläute
+ *
+ * IEM, Graz
+ *
+ * this code is published under the LGPL
+ *
+ */
+#include "iemmatrix.h"
+
+
+#include "iemmatrix.h"
+
+/* mtx_print */
+static t_class *mtx_print_class;
+static void mtx_print(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int col, row;
+ if (argc<2){
+ post("mtx_print : crippled matrix");
+ return;
+ }
+ row = atom_getfloat(argv++);
+ col = atom_getfloat(argv++);
+ if(row*col>argc-2){
+ post("mtx_print : sparse matrices not yet supported : use \"mtx_check\"");
+ return;
+ }
+ post("matrix:");
+ while(row--){
+ postatom(col, argv);
+ argv+=col;
+ endpost();
+ }
+ endpost();
+}
+static void *mtx_print_new(void)
+{
+ t_matrix *x = (t_matrix *)pd_new(mtx_print_class);
+ x->row = x->col = 0;
+ x->atombuffer = 0;
+ return (x);
+}
+void mtx_print_setup(void)
+{
+ mtx_print_class = class_new(gensym("mtx_print"), (t_newmethod)mtx_print_new,
+ 0, sizeof(t_matrix), 0, 0, 0);
+ class_addmethod (mtx_print_class, (t_method)mtx_print, gensym("matrix"), A_GIMME, 0);
+ class_sethelpsymbol(mtx_print_class, gensym("iemmatrix/matrix"));
+}
+
+void iemtx_print_setup(void){
+ mtx_print_setup();
+}
+
diff --git a/src/mtx_rand.c b/src/mtx_rand.c
new file mode 100644
index 0000000..dee481a
--- /dev/null
+++ b/src/mtx_rand.c
@@ -0,0 +1,93 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * (c) IOhannes m zmölnig, forum::für::umläute
+ *
+ * IEM, Graz
+ *
+ * this code is published under the LGPL
+ *
+ */
+#include "iemmatrix.h"
+
+/* mtx_rand */
+static t_class *mtx_rand_class;
+
+static void mtx_rand_seed(t_matrix *x, t_float f)
+{
+ x->current_row=f;
+}
+static int makeseed(void)
+{
+ static unsigned int random_nextseed = 1489853723;
+ random_nextseed = random_nextseed * 435898247 + 938284287;
+ return (random_nextseed & 0x7fffffff);
+}
+static void mtx_rand_random(t_matrix *x)
+{
+ long size = x->row * x->col;
+ t_atom *ap=x->atombuffer+2;
+ int val = x->current_row;
+ while(size--)SETFLOAT(ap+size, ((float)(((val=val*435898247+382842987)&0x7fffffff)-0x40000000))*(float)(0.5/0x40000000)+0.5);
+ x->current_row=val;
+}
+
+static void mtx_rand_list(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int row = atom_getfloat(argv++);
+ int col = atom_getfloat(argv++);
+
+ if(!argv)return;
+ if(argc==1)col=row;
+
+ adjustsize(x, row, col);
+ mtx_rand_random(x);
+ matrix_bang(x);
+}
+static void mtx_rand_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ matrix_matrix2(x, s, argc, argv);
+ mtx_rand_random(x);
+ matrix_bang(x);
+}
+static void mtx_rand_bang(t_matrix *x)
+{
+ mtx_rand_random(x);
+ matrix_bang(x);
+}
+static void *mtx_rand_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_matrix *x = (t_matrix *)pd_new(mtx_rand_class);
+ int row, col;
+ outlet_new(&x->x_obj, 0);
+ x->col=x->row=0;
+ x->atombuffer=0;
+ x->current_row=makeseed();
+
+ if (argc) {
+ row=atom_getfloat(argv);
+ col=(argc>1)?atom_getfloat(argv+1):row;
+ adjustsize(x, row, col);
+ mtx_rand_random(x);
+ }
+ return (x);
+}
+void mtx_rand_setup(void)
+{
+ mtx_rand_class = class_new(gensym("mtx_rand"), (t_newmethod)mtx_rand_new,
+ (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0);
+ class_addmethod(mtx_rand_class, (t_method)mtx_rand_matrix, gensym("matrix"), A_GIMME, 0);
+ class_addlist (mtx_rand_class, mtx_rand_list);
+ class_addbang (mtx_rand_class, mtx_rand_bang);
+
+ class_addmethod(mtx_rand_class, (t_method)mtx_rand_seed, gensym("seed"), A_FLOAT, 0);
+ class_sethelpsymbol(mtx_rand_class, gensym("iemmatrix/mtx_rand"));
+}
+
+void iemmtx_rand_setup(void){
+ mtx_rand_setup();
+}
+
diff --git a/src/mtx_resize.c b/src/mtx_resize.c
new file mode 100644
index 0000000..edc2e17
--- /dev/null
+++ b/src/mtx_resize.c
@@ -0,0 +1,103 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * (c) IOhannes m zmölnig, forum::für::umläute
+ *
+ * IEM, Graz
+ *
+ * this code is published under the LGPL
+ *
+ */
+#include "iemmatrix.h"
+
+/* mtx_resize */
+
+static t_class *mtx_resize_class;
+static void mtx_resize_list2(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int r, c;
+ if (argc<1)return;
+ if (argc>2)error("mtx_resize : only rows & cols are needed, skipping the rest");
+ if (argc==1)r=c=atom_getfloat(argv++);
+ else{
+ r=atom_getfloat(argv++);
+ c=atom_getfloat(argv++);
+ }
+
+ if (r<0)r=0;
+ if (c<0)c=0;
+
+ x->current_row = r;
+ x->current_col = c;
+}
+
+static void mtx_resize_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int row=atom_getfloat(argv);
+ int col=atom_getfloat(argv+1);
+ int r = x->current_row, c = x->current_col;
+ int R=0, ROW, COL;
+
+ if (argc<2){ post("mtx_add: crippled matrix"); return; }
+ if ((col<1)||(row<1)) { post("mtx_add: invalid dimensions"); return; }
+ if (col*row>argc-2){ post("sparse matrix not yet supported : use \"mtx_check\""); return; }
+
+ if (!r)r=row;
+ if (!c)c=col;
+
+ if (r==row && c==col) { // no need to change
+ outlet_anything(x->x_obj.ob_outlet, gensym("matrix"), argc, argv);
+ return;
+ }
+
+ x->atombuffer=(t_atom *)getbytes((c*r+2)*sizeof(t_atom));
+ setdimen(x, r, c);
+ matrix_set(x, 0);
+
+ ROW=(r<row)?r:row;
+ COL=(c<col)?c:col;
+ R=ROW;
+ while(R--)memcpy(x->atombuffer+2+(ROW-R-1)*c, argv+2+(ROW-R-1)*col, COL*sizeof(t_atom));
+
+ matrix_bang(x);
+
+ freebytes(x->atombuffer, (c*r+2)*sizeof(t_atom));
+}
+
+static void *mtx_resize_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_matrix *x = (t_matrix *)pd_new(mtx_resize_class);
+ int c=0, r=0;
+
+ if(argc){
+ if(argc-1){
+ r=atom_getfloat(argv);
+ c=atom_getfloat(argv+1);
+ } else r=c=atom_getfloat(argv);
+ if(c<0)c=0;
+ if(r<0)r=0;
+ }
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym(""));
+ outlet_new(&x->x_obj, 0);
+ x->current_row = r;
+ x->current_col = c;
+ x->row = x->col= 0;
+ x->atombuffer = 0;
+
+ return (x);
+}
+void mtx_resize_setup(void)
+{
+ mtx_resize_class = class_new(gensym("mtx_resize"), (t_newmethod)mtx_resize_new,
+ 0, sizeof(t_matrix), 0, A_GIMME, 0);
+ class_addmethod (mtx_resize_class, (t_method)mtx_resize_matrix, gensym("matrix"), A_GIMME, 0);
+ class_addmethod (mtx_resize_class, (t_method)mtx_resize_list2, gensym(""), A_GIMME, 0);
+ class_sethelpsymbol(mtx_resize_class, gensym("iemmatrix/mtx_size"));
+}
+void iemtx_resize_setup(void){
+ mtx_resize_setup();
+}
+
diff --git a/src/mtx_roll.c b/src/mtx_roll.c
new file mode 100644
index 0000000..a437b06
--- /dev/null
+++ b/src/mtx_roll.c
@@ -0,0 +1,73 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * (c) IOhannes m zmölnig, forum::für::umläute
+ *
+ * IEM, Graz
+ *
+ * this code is published under the LGPL
+ *
+ */
+#include "iemmatrix.h"
+
+/* mtx_roll */
+/* roll the rows */
+static t_class *mtx_roll_class;
+
+static void mtx_roll_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int row=atom_getfloat(argv++);
+ int col=atom_getfloat(argv++);
+ t_atom *ap;
+ int colroll = ((int)x->f%col+col)%col;
+ int c;
+
+ if(row*col>argc-2) {
+ post("mtx_roll: sparse matrices not yet supported : use \"mtx_check\"");
+ return;
+ }
+
+ adjustsize(x, row, col);
+ ap = x->atombuffer+2;
+
+ c=col;
+ while(c--){
+ t_atom *in = argv+col-c-1;
+ t_atom *out = ap +(col-c-1+colroll)%col;
+ int r = row;
+ while (r--){
+ SETFLOAT(out, atom_getfloat(in));
+ out+=col;
+ in+=col;
+ }
+
+ }
+
+ matrix_bang(x);
+}
+
+static void *mtx_roll_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_matrix *x = (t_matrix *)pd_new(mtx_roll_class);
+ floatinlet_new(&x->x_obj, &(x->f));
+ outlet_new(&x->x_obj, 0);
+
+ x->f=argc?atom_getfloat(argv):0;
+ x->col=x->row=0;
+ x->atombuffer=0;
+ return (x);
+}
+void mtx_roll_setup(void)
+{
+ mtx_roll_class = class_new(gensym("mtx_roll"), (t_newmethod)mtx_roll_new,
+ (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0);
+ class_addbang (mtx_roll_class, matrix_bang);
+ class_addmethod(mtx_roll_class, (t_method)mtx_roll_matrix, gensym("matrix"), A_GIMME, 0);
+ class_sethelpsymbol(mtx_roll_class, gensym("iemmatrix/mtx_transpose"));
+}
+void iemtx_roll_setup(void){
+ mtx_roll_setup();
+}
diff --git a/src/mtx_row.c b/src/mtx_row.c
new file mode 100644
index 0000000..e88aae8
--- /dev/null
+++ b/src/mtx_row.c
@@ -0,0 +1,120 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * (c) IOhannes m zmölnig, forum::für::umläute
+ *
+ * IEM, Graz
+ *
+ * this code is published under the LGPL
+ *
+ */
+#include "iemmatrix.h"
+
+/* mtx_row */
+static t_class *mtx_row_class;
+
+static void mtx_row_float(t_matrix *x, t_floatarg f)
+{
+ int i = f;
+ if(i<0)i=0;
+ x->current_row = i;
+}
+static void mtx_row_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int row, col;
+ if (argc<2){ post("matrix : corrupt matrix passed"); return; }
+ row = atom_getfloat(argv);
+ col = atom_getfloat(argv+1);
+ if ((row<1)||(col<1)){ post("matrix : corrupt matrix passed"); return; }
+ if (row*col > argc-2){ post("matrix: sparse matrices not yet supported : use \"mtx_check\""); return; }
+ matrix_matrix2(x, s, argc, argv);
+ matrix_bang(x);
+}
+static void mtx_row_list(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ if (argc==1){
+ t_float f=atom_getfloat(argv);
+ t_atom *ap=x->atombuffer+2+(x->current_row-1)*x->col;
+ if (x->current_row>x->row){
+ post("mtx_row : too high a row is to be set");
+ return;
+ }
+ if (x->current_row){
+ int n=x->col;
+ while(n--){
+ SETFLOAT(ap, f);
+ ap++;
+ }
+ }
+ matrix_bang(x);
+ return;
+ }
+
+ if (argc<x->col){
+ post("mtx_row : row length is too small for %dx%d-matrix", x->row, x->col);
+ return;
+ }
+ if (x->current_row>x->row){
+ post("mtx_row : too high a row is to be set");
+ return;
+ }
+ if(x->current_row) {memcpy(x->atombuffer+2+(x->current_row-1)*x->col, argv, x->col*sizeof(t_atom));
+ } else {
+ int r=x->row;
+ while(r--)memcpy(x->atombuffer+2+r*x->col, argv, x->col*sizeof(t_atom));
+ }
+ matrix_bang(x);
+}
+static void *mtx_row_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_matrix *x = (t_matrix *)pd_new(mtx_row_class);
+ int i, j, q;
+
+ outlet_new(&x->x_obj, 0);
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym(""));
+ x->current_row=0;
+ x->col=x->row=0;
+ x->atombuffer=0;
+ switch (argc) {
+ case 0:break;
+ case 1:
+ i = atom_getfloat(argv);
+ if (i<0)i=0;
+ if(i)adjustsize(x, i, i);
+ matrix_set(x, 0);
+ break;
+ case 2:
+ i = atom_getfloat(argv++);if(i<0)i=0;
+ j = atom_getfloat(argv++);if(j<0)j=0;
+ if(i*j)adjustsize(x, i, j);
+ matrix_set(x, 0);
+ break;
+ default:
+ i = atom_getfloat(argv++);if(i<0)i=0;
+ j = atom_getfloat(argv++);if(j<0)j=0;
+ q = atom_getfloat(argv++);if(q<0)q=0;
+ if(i*j)adjustsize(x, i, j);
+ matrix_set(x, 0);
+ x->current_row=q;
+ }
+ return (x);
+}
+void mtx_row_setup(void)
+{
+ mtx_row_class = class_new(gensym("mtx_row"), (t_newmethod)mtx_row_new,
+ (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0);
+ class_addbang (mtx_row_class, matrix_bang);
+ class_addlist (mtx_row_class, mtx_row_list);
+ class_addmethod(mtx_row_class, (t_method)mtx_row_matrix, gensym("matrix"), A_GIMME, 0);
+ class_addmethod(mtx_row_class, (t_method)mtx_row_float, gensym(""), A_FLOAT, 0);
+ class_sethelpsymbol(mtx_row_class, gensym("iemmatrix/mtx_element"));
+}
+
+
+void iemmtx_row_setup(void)
+{
+ mtx_row_setup();
+}
diff --git a/src/mtx_scroll.c b/src/mtx_scroll.c
new file mode 100644
index 0000000..5b4fffa
--- /dev/null
+++ b/src/mtx_scroll.c
@@ -0,0 +1,59 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * (c) IOhannes m zmölnig, forum::für::umläute
+ *
+ * IEM, Graz
+ *
+ * this code is published under the LGPL
+ *
+ */
+#include "iemmatrix.h"
+
+/* mtx_scroll */
+/* scroll the rows */
+static t_class *mtx_scroll_class;
+
+static void mtx_scroll_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int row=atom_getfloat(argv++);
+ int col=atom_getfloat(argv++);
+ int rowscroll = ((int)x->f%row+row)%row;
+
+ if(row*col>argc-2) {
+ post("mtx_scroll: sparse matrices not yet supported : use \"mtx_check\"");
+ return;
+ }
+ adjustsize(x, row, col);
+
+ memcpy(x->atombuffer+2, argv+(row-rowscroll)*col, rowscroll*col*sizeof(t_atom));
+ memcpy(x->atombuffer+2+rowscroll*col, argv, (row-rowscroll)*col*sizeof(t_atom));
+
+ matrix_bang(x);
+}
+
+static void *mtx_scroll_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_matrix *x = (t_matrix *)pd_new(mtx_scroll_class);
+ floatinlet_new(&x->x_obj, &(x->f));
+ outlet_new(&x->x_obj, 0);
+
+ x->f=argc?atom_getfloat(argv):0;
+ x->col=x->row=0;
+ x->atombuffer=0;
+ return (x);
+}
+void mtx_scroll_setup(void)
+{
+ mtx_scroll_class = class_new(gensym("mtx_scroll"), (t_newmethod)mtx_scroll_new,
+ (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0);
+ class_addbang (mtx_scroll_class, matrix_bang);
+ class_addmethod(mtx_scroll_class, (t_method)mtx_scroll_matrix, gensym("matrix"), A_GIMME, 0);
+ class_sethelpsymbol(mtx_scroll_class, gensym("iemmatrix/mtx_transpose"));
+}
+void iemtx_scroll_setup(void){
+ mtx_scroll_setup();
+}
diff --git a/src/mtx_size.c b/src/mtx_size.c
new file mode 100644
index 0000000..43dbba1
--- /dev/null
+++ b/src/mtx_size.c
@@ -0,0 +1,54 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * (c) IOhannes m zmölnig, forum::für::umläute
+ *
+ * IEM, Graz
+ *
+ * this code is published under the LGPL
+ *
+ */
+#include "iemmatrix.h"
+
+/* mtx_size */
+static t_class *mtx_size_class;
+typedef struct _mtx_size
+{
+ t_object x_obj;
+
+ int row;
+ int col;
+
+ t_outlet *left, *right;
+} t_mtx_size;
+
+static void mtx_size_matrix(t_mtx_size *x, t_symbol *s, int argc, t_atom *argv)
+{
+ if(argc<2)return;
+ outlet_float(x->right, atom_getfloat(argv+1));
+ outlet_float(x->left, atom_getfloat(argv));
+
+}
+
+static void *mtx_size_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_mtx_size *x = (t_mtx_size *)pd_new(mtx_size_class);
+ x->left = outlet_new(&x->x_obj, 0);
+ x->right = outlet_new(&x->x_obj, 0);
+
+ return (x);
+}
+void mtx_size_setup(void)
+{
+ mtx_size_class = class_new(gensym("mtx_size"), (t_newmethod)mtx_size_new,
+ 0, sizeof(t_mtx_size), 0, A_GIMME, 0);
+ class_addmethod(mtx_size_class, (t_method)mtx_size_matrix, gensym("matrix"), A_GIMME, 0);
+ class_sethelpsymbol(mtx_size_class, gensym("iemmatrix/mtx_size"));
+}
+
+void iemtx_size_setup(void){
+ mtx_size_setup();
+}
diff --git a/src/mtx_tilde.c b/src/mtx_tilde.c
new file mode 100644
index 0000000..88dc5f9
--- /dev/null
+++ b/src/mtx_tilde.c
@@ -0,0 +1,413 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * (c) IOhannes m zmölnig, forum::für::umläute
+ *
+ * IEM, Graz
+ *
+ * this code is published under the LGPL
+ *
+ */
+#include "iemmatrix.h"
+
+
+/*
+ the sigmatrix objects ::
+ mtx_*~ : multiply a n-vector of in~ with a matrix to get a m-vector of out~
+ line~ between the 2 matrices, to make it useable as a mixer
+*/
+
+
+/* --------------------------- matrix~ ----------------------------------
+ *
+ * multiply a n-vector of signals with a (n*m) matrix, to get m output-streams.
+ * make the (n*m)-matrix of scalars to be liny~
+ *
+ * 1703:forum::für::umläute:2001
+ */
+
+static t_class *mtx_multilde_class;
+
+typedef struct _mtx_multilde {
+ t_object x_obj;
+
+ t_float time;
+ int ticksleft;
+ int retarget;
+ t_float msec2tick;
+
+ t_float**value;
+ t_float**target;
+ t_float**increment; /* single precision is really a bad, especially when doing long line~s.
+ * but the biginc (like in msp's line~ (d_ctl.c) is far too expensive... */
+ t_float**sigIN;
+ t_float**sigOUT;
+ t_float *sigBUF;
+
+ int n_sigIN; /* columns */
+ int n_sigOUT; /* rows */
+
+ int compatibility; /* 0=default; 1=zexy; 2=iemlib */
+} t_mtx_multilde;
+
+/* the message thing */
+
+static void mtx_multilde_matrix_default(t_mtx_multilde *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int col, row, c=0, r=0;
+
+ if (argc<2){
+ post("matrix~ : bad matrix !");
+ return;
+ }
+
+ row = atom_getfloat(argv++);
+ col = atom_getfloat(argv++);
+ argc-=2;
+
+ if((col!=x->n_sigOUT)||(row!=x->n_sigIN)){
+ post("matrix~ : matrix dimensions do not match !!");
+ return;
+ }
+ if(argc<row*col){
+ post("matrix~ : reduced matrices not yet supported");
+ return;
+ }
+
+ if (x->time<=0) {
+ for(r=0; r<row; r++)
+ for(c=0; c<col; c++)
+ x->target[c][r]=x->value[c][r]=atom_getfloat(argv++);
+ x->time=x->ticksleft=x->retarget=0;
+ } else {
+ for(r=0; r<row; r++)
+ for(c=0; c<col; c++)
+ x->target[c][r]=atom_getfloat(argv++);
+ x->retarget=1;
+ }
+}
+
+static void mtx_multilde_matrix_zexy(t_mtx_multilde *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int col, row, c=0, r=0;
+
+ if (argc<2){
+ post("matrix~ : bad matrix !");
+ return;
+ }
+
+ row = atom_getfloat(argv++);
+ col = atom_getfloat(argv++);
+ argc-=2;
+
+ if((col!=x->n_sigOUT)||(row!=x->n_sigIN)){
+ post("matrix~ : matrix dimensions do not match !!");
+ return;
+ }
+ if(argc<row*col){
+ post("matrix~ : reduced matrices not yet supported");
+ return;
+ }
+
+ if (x->time<=0) {
+ for(r=0; r<row; r++)
+ for(c=0; c<col; c++)
+ x->target[c][r]=x->value[c][r]=atom_getfloat(argv++);
+ x->time=x->ticksleft=x->retarget=0;
+ } else {
+ for(r=0; r<row; r++)
+ for(c=0; c<col; c++)
+ x->target[c][r]=atom_getfloat(argv++);
+ x->retarget=1;
+ }
+}
+
+static void mtx_multilde_matrix_iemlib(t_mtx_multilde *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int col, row, c=0, r=0;
+
+ if (argc<2){
+ post("matrix~ : bad matrix !");
+ return;
+ }
+
+ row = atom_getfloat(argv++);
+ col = atom_getfloat(argv++);
+ argc-=2;
+
+ if((col!=x->n_sigOUT)||(row!=x->n_sigIN)){
+ post("matrix~ : matrix dimensions do not match !!");
+ return;
+ }
+ if(argc<row*col){
+ post("matrix~ : reduced matrices not yet supported");
+ return;
+ }
+
+ if (x->time<=0) {
+ for(r=0; r<row; r++)
+ for(c=0; c<col; c++)
+ x->target[c][r]=x->value[c][r]=atom_getfloat(argv++);
+ x->time=x->ticksleft=x->retarget=0;
+ } else {
+ for(r=0; r<row; r++)
+ for(c=0; c<col; c++)
+ x->target[c][r]=atom_getfloat(argv++);
+ x->retarget=1;
+ }
+}
+static void mtx_multilde_matrix(t_mtx_multilde *x, t_symbol *s, int argc, t_atom *argv){
+ switch (x->compatibility){
+ default:mtx_multilde_matrix_default(x,s,argc,argv);
+ break;
+ case 1:mtx_multilde_matrix_zexy(x,s,argc,argv);
+ break;
+ case 2:mtx_multilde_matrix_iemlib(x,s,argc,argv);
+ break;
+ }
+}
+
+static void mtx_multilde_stop(t_mtx_multilde *x)
+{
+ int c = x->n_sigOUT, r;
+ t_float *tgt, *val;
+ while(c--){
+ tgt=x->target[c];
+ val=x->value [c];
+ r=x->n_sigIN;
+ while(r--)*tgt++=*val++;
+ }
+ x->ticksleft = x->retarget = 0;
+}
+
+
+/* the dsp thing */
+
+static t_int *mtx_multilde_perform(t_int *w)
+{
+ t_mtx_multilde *x = (t_mtx_multilde *)(w[1]);
+ int n = (int)(w[2]);
+
+ int r, c;
+
+ t_float **out = x->sigOUT;
+ t_float **in = x->sigIN;
+
+ t_float *buf = x->sigBUF, *sigBUF = buf;
+
+ t_float **value = x->value;
+ t_float **target = x->target;
+ t_float **increment = x->increment;
+
+ t_float *inc, *val, *tgt;
+
+ int n_IN=x->n_sigIN, n_OUT=x->n_sigOUT;
+
+ if (x->retarget) {
+ int nticks = x->time * x->msec2tick;
+ t_float oneovernos;
+
+ if (!nticks) nticks = 1;
+ oneovernos = 1./(nticks*n);
+ x->ticksleft = nticks;
+
+ c = n_OUT;
+ while(c--) {
+ inc=increment[c];
+ val=value[c];
+ tgt=target[c];
+ r=n_IN;
+ while(r--)*inc++=(*tgt++-*val++)*oneovernos;
+ }
+
+ x->retarget = 0;
+ }
+
+ if (x->ticksleft) {
+ int N=n-1;
+ n=-1;
+ // while (n--) {
+ while(n++<N){
+ c = n_OUT;
+ while(c--) {
+ t_float sum = 0;
+ val = value[c]+n_IN-1;
+ inc = increment[c]+n_IN-1;
+ r=n_IN;
+
+ while(r--)sum+=in[r][n]*(*val--+=*inc--);
+
+ sigBUF[c]=sum;
+ }
+ buf = sigBUF;
+ c = n_OUT;
+ while(c--)out[c][n]=*buf++;
+ }
+ if (!--x->ticksleft) {
+ c = n_OUT;
+ while(c--){
+ val=value[c];
+ tgt=target[c];
+ r=n_IN;
+ while(r--)*val++=*tgt++;
+ }
+ }
+ } else { /* no ticks left */
+ while (n--) {
+ c = n_OUT;
+ while(c--) {
+ t_float sum = 0;
+ val = value[c]+n_IN-1;
+ r = n_IN;
+ while(r--)sum+=in[r][n]**val--;
+ sigBUF[c]=sum;
+ }
+ buf = sigBUF;
+ c = n_OUT;
+ while(c--)out[c][n]=*buf++;
+ }
+ }
+ return (w+3);
+}
+
+static void mtx_multilde_dsp(t_mtx_multilde *x, t_signal **sp)
+{
+ int o = x->n_sigOUT, i=x->n_sigIN, n=0;
+ t_float **dummy = x->sigIN;
+
+ while(i--)*dummy++=sp[n++]->s_vec;
+
+ dummy =x->sigOUT;
+ while(o--)dummy[o]=sp[n++]->s_vec;
+
+ x->msec2tick = sp[0]->s_sr / (1000.f * sp[0]->s_n);
+ dsp_add(mtx_multilde_perform, 2, x, sp[0]->s_n);
+}
+
+
+/* setup/setdown things */
+
+static void mtx_multilde_free(t_mtx_multilde *x)
+{
+ int i = x->n_sigOUT;
+ while(i--) {
+ freebytes(x->value [i], x->n_sigOUT * sizeof(t_float *));
+ freebytes(x->target [i], x->n_sigOUT * sizeof(t_float *));
+ freebytes(x->increment[i], x->n_sigOUT * sizeof(t_float *));
+ }
+
+ freebytes(x->value, sizeof(x->value));
+ freebytes(x->target, sizeof(x->target));
+ freebytes(x->increment, sizeof(x->increment));
+
+ freebytes(x->sigIN, x->n_sigIN * sizeof(t_float *));
+ freebytes(x->sigOUT, x->n_sigOUT * sizeof(t_float *));
+ freebytes(x->sigBUF, x->n_sigOUT * sizeof(t_float ));
+}
+
+static void *mtx_multilde_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_mtx_multilde *x = (t_mtx_multilde *)pd_new(mtx_multilde_class);
+ int i;
+ int InOut=0;
+ x->compatibility=0;
+
+ if(s==gensym("matrix~")){ // zexy-compat
+ error("[matrix~] is deprecated");//; use [mtx_*~] instead");
+ x->compatibility=1;
+ InOut=1;
+ }
+
+ if(s==gensym("matrix_mul~")){ // iemlib-compat
+ error("[matrix_mul~] is deprecated; use [mtx_*~] instead");
+ x->compatibility=2;
+ InOut=1;
+ }
+
+ x->time = 0;
+
+ switch (argc) {
+ case 0:
+ x->n_sigIN = x->n_sigOUT = 1;
+ break;
+ case 1:
+ x->n_sigIN = x->n_sigOUT = atom_getfloat(argv);
+ break;
+ default:
+ x->time= atom_getfloat(argv+2);
+ case 2:
+ if(InOut){
+ x->n_sigIN = atom_getfloat(argv);
+ x->n_sigOUT = atom_getfloat(argv+1);
+ } else {
+ x->n_sigOUT = atom_getfloat(argv);
+ x->n_sigIN = atom_getfloat(argv+1);
+ }
+ break;
+ }
+
+ if (x->time<0) x->time=0;
+ if (x->n_sigIN <1) x->n_sigIN =1;
+ if (x->n_sigOUT<1) x->n_sigOUT=1;
+
+ /* the inlets */
+ i=x->n_sigIN-1;
+ while(i--)inlet_new(&x->x_obj,&x->x_obj.ob_pd,&s_signal,&s_signal);
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("matrix"), gensym(""));
+ floatinlet_new(&x->x_obj, &x->time);
+
+ /* the outlets */
+ i=x->n_sigOUT;
+ while(i--)outlet_new(&x->x_obj,&s_signal);
+
+ /* make all the buffers */
+ x->sigIN = (t_float**)getbytes(x->n_sigIN * sizeof(t_float*));
+ x->sigOUT = (t_float**)getbytes(x->n_sigOUT * sizeof(t_float*));
+ x->sigBUF = (t_float *)getbytes(x->n_sigOUT * sizeof(t_float ));
+
+ x->value = (t_float **)getbytes(x->n_sigOUT * sizeof(t_float));
+ x->target = (t_float **)getbytes(x->n_sigOUT * sizeof(t_float));
+ x->increment = (t_float **)getbytes(x->n_sigOUT * sizeof(t_float));
+
+ i = x->n_sigOUT;
+ while(i--){
+ int j = x->n_sigIN;
+ x->sigOUT [i] = 0;
+ x->value [i] = (t_float *)getbytes(x->n_sigIN * sizeof(t_float));
+ x->target [i] = (t_float *)getbytes(x->n_sigIN * sizeof(t_float));
+ x->increment[i] = (t_float *)getbytes(x->n_sigIN * sizeof(t_float));
+
+ while(j--)x->value[i][j]=x->target[i][j]=x->increment[i][j]=0;
+ }
+
+ i = x->n_sigIN;
+ while(i--)x->sigIN[i] = 0;
+
+ x->msec2tick = x->ticksleft = x->retarget = 0;
+ return (x);
+}
+
+static void mtx_multilde_setup(void)
+{
+ mtx_multilde_class = class_new(gensym("mtx_*~"), (t_newmethod)mtx_multilde_new,
+ (t_method)mtx_multilde_free,
+ sizeof(t_mtx_multilde), 0, A_GIMME, 0);
+
+ class_addcreator((t_newmethod)mtx_multilde_new, gensym("matrix~"), A_GIMME,0);
+
+ class_addmethod(mtx_multilde_class, (t_method)mtx_multilde_dsp, gensym("dsp"), 0);
+ class_addmethod(mtx_multilde_class, nullfn, gensym("signal"), 0);
+
+ class_addmethod(mtx_multilde_class, (t_method)mtx_multilde_matrix, gensym(""), A_GIMME, 0);
+ class_addmethod(mtx_multilde_class, (t_method)mtx_multilde_stop, gensym("stop"), 0);
+
+ class_sethelpsymbol(mtx_multilde_class, gensym("iemmatrix/matrix~"));
+}
+
+void mtx_tilde_setup(void)
+{
+ mtx_multilde_setup();
+}
diff --git a/src/mtx_trace.c b/src/mtx_trace.c
new file mode 100644
index 0000000..ba5b3db
--- /dev/null
+++ b/src/mtx_trace.c
@@ -0,0 +1,57 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * (c) IOhannes m zmölnig, forum::für::umläute
+ *
+ * IEM, Graz
+ *
+ * this code is published under the LGPL
+ *
+ */
+#include "iemmatrix.h"
+
+/* mtx_trace */
+static t_class *mtx_trace_class;
+typedef struct _mtx_trace
+{
+ t_object x_obj;
+ t_float trace;
+} t_mtx_trace;
+static void mtx_trace_bang(t_mtx_trace *x)
+{
+ outlet_float(x->x_obj.ob_outlet, x->trace);
+}
+static void mtx_trace_matrix(t_mtx_trace *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int row=atom_getfloat(argv++);
+ int col=atom_getfloat(argv++);
+ int length=(col<row)?col:row;
+ t_float trace = 0;
+ if(row*col>argc-2)post("mtx_trace: sparse matrices not yet supported : use \"mtx_check\"");
+ else while(length--)trace+=atom_getfloat(argv+length*(col+1));
+ x->trace=trace;
+ mtx_trace_bang(x);
+}
+static void *mtx_trace_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_mtx_trace *x = (t_mtx_trace *)pd_new(mtx_trace_class);
+ outlet_new(&x->x_obj, 0);
+ x->trace=0;
+ return (x);
+}
+void mtx_trace_setup(void)
+{
+ mtx_trace_class = class_new(gensym("mtx_trace"), (t_newmethod)mtx_trace_new,
+ 0, sizeof(t_mtx_trace), 0, A_GIMME, 0);
+ class_addbang (mtx_trace_class, mtx_trace_bang);
+ class_addmethod(mtx_trace_class, (t_method)mtx_trace_matrix, gensym("matrix"), A_GIMME, 0);
+ class_sethelpsymbol(mtx_trace_class, gensym("iemmatrix/mtx_trace"));
+}
+
+void iemtx_trace_setup(void)
+{
+ mtx_trace_setup();
+}
diff --git a/src/mtx_transpose.c b/src/mtx_transpose.c
new file mode 100644
index 0000000..7034cae
--- /dev/null
+++ b/src/mtx_transpose.c
@@ -0,0 +1,67 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * (c) IOhannes m zmölnig, forum::für::umläute
+ *
+ * IEM, Graz
+ *
+ * this code is published under the LGPL
+ *
+ */
+#include "iemmatrix.h"
+
+/* mtx_transpose */
+static t_class *mtx_transpose_class;
+
+static void mtx_transpose_matrix(t_matrix *x, t_symbol *s, int argc, t_atom *argv)
+{
+ int row=atom_getfloat(argv++);
+ int col=atom_getfloat(argv++);
+ t_atom *ap;
+ int r, c;
+
+ if(row*col>argc-2) {
+ post("mtx_transpose: sparse matrices not yet supported : use \"mtx_check\"");
+ return;
+ }
+ if (col*row!=x->col*x->row) {
+ freebytes(x->atombuffer, (x->col*x->row+2)*sizeof(t_atom));
+ x->atombuffer = (t_atom *)getbytes((row*col+2)*sizeof(t_atom));
+ }
+ ap = x->atombuffer+2;
+ setdimen(x, col, row);
+ r = row;
+ while(r--){
+ c=col;
+ while(c--) {
+ t_float f = atom_getfloat(argv+r*col+c);
+ SETFLOAT(ap+c*row+r, f);
+ }
+ }
+
+ matrix_bang(x);
+}
+
+static void *mtx_transpose_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_matrix *x = (t_matrix *)pd_new(mtx_transpose_class);
+ outlet_new(&x->x_obj, 0);
+ x->col=x->row=0;
+ x->atombuffer=0;
+ return (x);
+}
+void mtx_transpose_setup(void)
+{
+ mtx_transpose_class = class_new(gensym("mtx_transpose"), (t_newmethod)mtx_transpose_new,
+ (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0);
+ class_addbang (mtx_transpose_class, matrix_bang);
+ class_addmethod(mtx_transpose_class, (t_method)mtx_transpose_matrix, gensym("matrix"), A_GIMME, 0);
+ class_sethelpsymbol(mtx_transpose_class, gensym("iemmatrix/mtx_transpose"));
+}
+
+void iemtx_transpose_setup(void){
+ mtx_transpose_setup();
+}
diff --git a/src/mtx_zeros.c b/src/mtx_zeros.c
new file mode 100644
index 0000000..a340967
--- /dev/null
+++ b/src/mtx_zeros.c
@@ -0,0 +1,56 @@
+/*
+ * iemmatrix
+ *
+ * objects for manipulating simple matrices
+ * mostly refering to matlab/octave matrix functions
+ *
+ * (c) IOhannes m zmölnig, forum::für::umläute
+ *
+ * IEM, Graz
+ *
+ * this code is published under the LGPL
+ *
+ */
+#include "iemmatrix.h"
+
+/* mtx_zeros */
+static t_class *mtx_zeros_class;
+static void *mtx_zeros_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_matrix *x = (t_matrix *)pd_new(mtx_zeros_class);
+ int col=0, row=0;
+ outlet_new(&x->x_obj, 0);
+ x->row = x->col = 0;
+ x->atombuffer = 0;
+ switch(argc) {
+ case 0:
+ break;
+ case 1:
+ col=row=atom_getfloat(argv);
+ break;
+ default:
+ row=atom_getfloat(argv++);
+ col=atom_getfloat(argv);
+ }
+ if(col<0)col=0;
+ if(row<0)row=0;
+ if (col*row){
+ x->atombuffer = (t_atom *)getbytes((col*row+2)*sizeof(t_atom));
+ setdimen(x, row, col);
+ matrix_set(x, 0);
+ }
+ return (x);
+}
+void mtx_zeros_setup(void)
+{
+ mtx_zeros_class = class_new(gensym("mtx_zeros"), (t_newmethod)mtx_zeros_new,
+ (t_method)matrix_free, sizeof(t_matrix), 0, A_GIMME, 0);
+ class_addlist(mtx_zeros_class, matrix_zeros);
+ class_addbang(mtx_zeros_class, matrix_bang);
+ class_addmethod(mtx_zeros_class, (t_method)matrix_zeros, gensym("matrix"), A_GIMME, 0);
+
+ class_sethelpsymbol(mtx_zeros_class, gensym("iemmatrix/mtx_special"));
+}
+void iemmtx_zeros_setup(void){
+ mtx_zeros_setup();
+}