diff options
author | IOhannes m zmölnig <zmoelnig@users.sourceforge.net> | 2005-03-21 14:33:31 +0000 |
---|---|---|
committer | IOhannes m zmölnig <zmoelnig@users.sourceforge.net> | 2005-03-21 14:33:31 +0000 |
commit | 10b474fba485e9a93157c7fa534bb66e7bcc6fde (patch) | |
tree | 73e9e02738ea62179a1722b37ef49a9e91cfcbad |
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
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(); +} |