From e6b40ac6d2bcfd70f75b143a6eb65bbffbda8c3a Mon Sep 17 00:00:00 2001 From: Cedric Bastoul Date: Mon, 26 Apr 2010 08:52:50 +0000 Subject: [PATCH] Bastoul branch to OpenScop --- AUTHORS | 11 + COPYING.LESSER | 488 +++++++++ ChangeLog | 107 ++ Makefile.am | 78 ++ NEWS | 2 + README | 23 + THANKS | 8 + autogen.sh | 5 + configure.in | 234 +++++ doc/Doxyfile.in | 1295 +++++++++++++++++++++++ doc/Makefile.am | 92 ++ doc/S4.cloog | 44 + doc/ascii-art.txt | 25 + doc/clan.texi | 2429 +++++++++++++++++++++++++++++++++++++++++++ doc/images/basic.eps | 402 +++++++ doc/images/basic.fig | 100 ++ doc/images/basic.jpg | Bin 0 -> 21180 bytes doc/images/basic.pdf | Bin 0 -> 40073 bytes doc/images/basic.txt | 13 + doc/images/basic1.eps | 332 ++++++ doc/images/basic1.fig | 86 ++ doc/images/basic1.jpg | Bin 0 -> 18353 bytes doc/images/basic1.pdf | Bin 0 -> 7051 bytes doc/images/basic1.txt | 12 + doc/images/basic2.eps | 256 +++++ doc/images/basic2.fig | 62 ++ doc/images/basic2.jpg | Bin 0 -> 12369 bytes doc/images/basic2.pdf | Bin 0 -> 6240 bytes doc/images/basic2.txt | 10 + doc/images/tree.eps | 258 +++++ doc/images/tree.fig | 54 + doc/images/tree.jpg | Bin 0 -> 13713 bytes doc/images/tree.pdf | Bin 0 -> 4558 bytes doc/images/tree.txt | 25 + include/Makefile.am | 56 + include/scoplib/macros.h | 158 +++ include/scoplib/matrix.h | 148 +++ include/scoplib/scop.h.in | 119 +++ include/scoplib/statement.h | 117 +++ include/scoplib/vector.h | 94 ++ source/Makefile.am | 65 ++ source/matrix.c | 1198 +++++++++++++++++++++ source/scop.c | 813 +++++++++++++++ source/statement.c | 518 +++++++++ source/vector.c | 330 ++++++ 45 files changed, 10067 insertions(+) create mode 100644 AUTHORS create mode 100644 COPYING.LESSER create mode 100644 ChangeLog create mode 100644 Makefile.am create mode 100644 NEWS create mode 100644 README create mode 100644 THANKS create mode 100755 autogen.sh create mode 100644 configure.in create mode 100644 doc/Doxyfile.in create mode 100644 doc/Makefile.am create mode 100644 doc/S4.cloog create mode 100644 doc/ascii-art.txt create mode 100644 doc/clan.texi create mode 100644 doc/images/basic.eps create mode 100644 doc/images/basic.fig create mode 100644 doc/images/basic.jpg create mode 100644 doc/images/basic.pdf create mode 100644 doc/images/basic.txt create mode 100644 doc/images/basic1.eps create mode 100644 doc/images/basic1.fig create mode 100644 doc/images/basic1.jpg create mode 100644 doc/images/basic1.pdf create mode 100644 doc/images/basic1.txt create mode 100644 doc/images/basic2.eps create mode 100644 doc/images/basic2.fig create mode 100644 doc/images/basic2.jpg create mode 100644 doc/images/basic2.pdf create mode 100644 doc/images/basic2.txt create mode 100644 doc/images/tree.eps create mode 100644 doc/images/tree.fig create mode 100644 doc/images/tree.jpg create mode 100644 doc/images/tree.pdf create mode 100644 doc/images/tree.txt create mode 100644 include/Makefile.am create mode 100644 include/scoplib/macros.h create mode 100644 include/scoplib/matrix.h create mode 100644 include/scoplib/scop.h.in create mode 100644 include/scoplib/statement.h create mode 100644 include/scoplib/vector.h create mode 100644 source/Makefile.am create mode 100644 source/matrix.c create mode 100644 source/scop.c create mode 100644 source/statement.c create mode 100644 source/vector.c diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..2fa05c7 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,11 @@ +* * * * * * +* Scoplib * +* * * * * * + +Version 0.1.0 + +Current maintainer: +* Louis-Noel Pouchet + +Author of Scoplib: +* Cedric Bastoul diff --git a/COPYING.LESSER b/COPYING.LESSER new file mode 100644 index 0000000..5c49b9f --- /dev/null +++ b/COPYING.LESSER @@ -0,0 +1,488 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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. + + + Copyright (C) + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..b2fa4f1 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,107 @@ +2010-03-08 Louis-Noel Pouchet + + * configure.in: Bump to ScopLib 0.2.0. + * README: Update with build information. + +2010-02-05 Louis-Noel Pouchet + + * include/scoplib/matrix.h, + * source/matrix.c: Add function scoplib_matrix_equal. + +2010-01-26 Louis-Noel Pouchet + + * include/macros.h: Add SCOPVAL_multo macro. + +2009-09-21 Louis-Noel Pouchet + + * source/vector.c, + * source/matrix.c, + * source/scop.c, + * source/statement.c, + * source/Makefile.am, + * include/Makefile.am, + * include/scoplib/scop.h.in, + * include/scoplib/vector.h, + * include/scoplib/macros.h, + * include/scoplib/matrix.h, + * include/scoplib/statement.h, + * COPYING.LESSER, + * configure.in, + * Makefile.am, + * README: Downgrade license from LGPL3+ to LGPL2.1+, to be + compatible with CLooG's license. + +2009-06-24 Louis-Noel Pouchet + + * source/scop.c, + * source/statement.c, + * include/scoplib/statement.h: Add support for control and exit + predicates as statement attributes. Needed for non-static control + code support. + +2009-05-02 Louis-Noel Pouchet + + * source/matrix.c, + * include/scoplib/macros.h, + * include/scoplib/matrix.h, + * configure.in: Fix a few minor problems. + +2009-05-02 Louis-Noel Pouchet + This is the initial checkin of ScopLib, a fork of Clan which + contains only the functions related to the .scop format, and the + main scop/statement/matrix/vector functions. + + clan_*_p types have been renamed scoplib_*_p, similarely for + function calls. + + * AUTHORS, + * autoconf, + * autogen.sh, + * configure.in, + * COPYING.LESSER, + * doc, + * doc/ascii-art.txt, + * doc/clan.texi, + * doc/Doxyfile.in, + * doc/images, + * doc/images/basic.eps, + * doc/images/basic.fig, + * doc/images/basic.jpg, + * doc/images/basic.pdf, + * doc/images/basic.txt, + * doc/images/basic1.eps, + * doc/images/basic1.fig, + * doc/images/basic1.jpg, + * doc/images/basic1.pdf, + * doc/images/basic1.txt, + * doc/images/basic2.eps, + * doc/images/basic2.fig, + * doc/images/basic2.jpg, + * doc/images/basic2.pdf, + * doc/images/basic2.txt, + * doc/images/tree.eps, + * doc/images/tree.fig, + * doc/images/tree.jpg, + * doc/images/tree.pdf, + * doc/images/tree.txt, + * doc/Makefile.am, + * doc/S4.cloog, + * include, + * include/Makefile.am, + * include/scoplib, + * include/scoplib/macros.h, + * include/scoplib/matrix.h, + * include/scoplib/scop.h.in, + * include/scoplib/statement.h, + * include/scoplib/vector.h, + * Makefile.am, + * NEWS, + * README, + * source, + * source/Makefile.am, + * source/matrix.c, + * source/scop.c, + * source/statement.c, + * source/vector.c, + * THANKS: Initial checkin of the project. + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..05d76ac --- /dev/null +++ b/Makefile.am @@ -0,0 +1,78 @@ +# +# /**------- <| --------------------------------------------------------** +# ** A Clan/Scop ** +# **--- /.\ -----------------------------------------------------** +# ** <| [""M# makefile.am ** +# **- A | # -----------------------------------------------------** +# ** /.\ [""M# First version: 30/04/2008 ** +# **- [""M# | # U"U#U -----------------------------------------------** +# | # | # \ .:/ +# | # | #___| # +# ****** | "--' .-" ***************************************************** +# * |"-"-"-"-"-#-#-## Clan : the Chunky Loop Analyser (experimental) * +# **** | # ## ###### **************************************************** +# * \ .::::'/ * +# * \ ::::'/ Copyright (C) 2008 Cedric Bastoul * +# * :8a| # # ## * +# * ::88a ### This is free software; you can redistribute it * +# * ::::888a 8a ##::. and/or modify it under the terms of the GNU * +# * ::::::::888a88a[]::: Lesser General Public License as published by * +# *::8:::::::::SUNDOGa8a::. the Free Software Foundation, either version 2.1 * +# *::::::::8::::888:Y8888:: of the License, or (at your option)* +# *::::':::88::::888::Y88a::::::::::::... any later version. * +# *::'::.. . ..... .. ... . * +# * This software 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 General * +# * Public License for more details. * +# * * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with software; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * +# * * +# * Clan, the Chunky Loop Analyser * +# * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr * +# * * +# *****************************************************************************/ +# +# Makefile.am (or makefile if generated) of Clan, the Chunky Loop Analyser. +# Makefile.am is not a makefile, you must run the 'autogen.sh' THEN the +# configure shellscript to generate the Makefile thanks to this file. + + + +############################################################################# +SUBDIRS = doc source include + + +############################################################################# +ACLOCAL_AMFLAGS = -I autoconf + +m4datadir = $(datadir)/aclocal + + +AUX_DIST = \ + $(ac_aux_dir)/config.guess \ + $(ac_aux_dir)/config.sub \ + $(ac_aux_dir)/install-sh \ + $(ac_aux_dir)/ltmain.sh \ + $(ac_aux_dir)/missing \ + $(ac_aux_dir)/depcomp + + +MAINTAINERCLEANFILES = \ + autoconf/texinfo.tex \ + Makefile.in \ + aclocal.m4 \ + configure \ + source/stamp-h.in \ + $(AUX_DIST) + + +############################################################################# +dist-hook: + (cd $(distdir) && mkdir -p $(ac_aux_dir)) + for file in $(AUX_DIST); do \ + cp $$file $(distdir)/$$file; \ + done +############################################################################# diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..75daa9c --- /dev/null +++ b/NEWS @@ -0,0 +1,2 @@ +Some news... + diff --git a/README b/README new file mode 100644 index 0000000..190642b --- /dev/null +++ b/README @@ -0,0 +1,23 @@ +* * * * * * * * * +* ScopLib 0.2.0 * +* * * * * * * * * + + +Install +------- + +$> ./configure + +$> make + +$> make install + + +Support +------- + + +Please contact both: + Louis-Noel Pouchet , maintainer + Cedric Bastoul , author + diff --git a/THANKS b/THANKS new file mode 100644 index 0000000..74c18ac --- /dev/null +++ b/THANKS @@ -0,0 +1,8 @@ +THANKS +====== + +The author would like to gratefully thank: + +* Louis-Noel Pouchet + For his valuable help in packaging ScopLib. + diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..b67de1f --- /dev/null +++ b/autogen.sh @@ -0,0 +1,5 @@ +#! /bin/sh + +aclocal -I autoconf +libtoolize --force --copy +autoreconf -vfi diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..43a0b16 --- /dev/null +++ b/configure.in @@ -0,0 +1,234 @@ +dnl +dnl /**------- <| --------------------------------------------------------** +dnl ** A Clan/Scop ** +dnl **--- /.\ -----------------------------------------------------** +dnl ** <| [""M# configure.in ** +dnl **- A | # -----------------------------------------------------** +dnl ** /.\ [""M# First version: 30/04/2008 ** +dnl **- [""M# | # U"U#U -----------------------------------------------** +dnl | # | # \ .:/ +dnl | # | #___| # +dnl ****** | "--' .-" *************************************************** +dnl * |"-"-"-"-"-#-#-## Clan : the Chunky Loop Analyser (experimental) * +dnl **** | # ## ###### ************************************************** +dnl * \ .::::'/ * +dnl * \ ::::'/ Copyright (C) 2008 Cedric Bastoul * +dnl * :8a| # # ## * +dnl * ::88a ### This is free software; you can redistribute it * +dnl * ::::888a 8a ##::. and/or modify it under the terms of the GNU * +dnl * ::::::::888a88a[]::: Lesser General Public License as published by * +dnl *::8:::::::::SUNDOGa8a::. the Free Software Foundation, either version 2.1* +dnl *::::::::8::::888:Y8888:: of the License, or (at your * +dnl *::::':::88::::888::Y88a::::::::::::... option) any later version. * +dnl *::'::.. . ..... .. ... . * +dnl * This software is distributed in the hope that it will be useful, but * +dnl * WITHOUT ANY WARRANTY; without even the implied warranty of * +dnl * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +dnl * General Public License for more details. * +dnl * * +dnl * You should have received a copy of the GNU Lesser General Public * +dnl * License along with software; if not, write to the Free Software * +dnl * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +dnl * USA * +dnl * * +dnl * Clan, the Chunky Loop Analyser * +dnl * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr * +dnl * * +dnl ***************************************************************************/ +dnl +dnl Input file for autoconf to build a configuration shellscript. + + +AC_PREREQ(2.13) +dnl Fill here the @bug email adress. +AC_INIT([scoplib], [0.2.0], [cedric.bastoul@inria.fr,pouchet@cse.ohio-state.edu]) +dnl A common file, which serve as a test. +AC_CONFIG_SRCDIR([include/scoplib/macros.h]) +dnl Put as most as possible configuration files to an auxialiry +dnl directory. +AC_CONFIG_AUX_DIR([autoconf]) +dnl Initialize automake. Here, a special tar version that enables +dnl (very) long filenames. +AM_INIT_AUTOMAKE([1.9 tar-ustar no-define foreign dist-bzip2]) + + +dnl default version +BITS="64" +SCOPLIB_INT_T=SCOPLIB_INT_T_IS_LONGLONG + + +dnl /************************************************************************** +dnl * Checking * +dnl **************************************************************************/ + + +dnl Checks for programs. +AC_PROG_CC +AC_PROG_LN_S +AC_PROG_MAKE_SET +AC_CHECK_PROG(CD, cd) +AC_PROG_LIBTOOL +AC_CHECK_PROGS(DOXYGEN,doxygen,doxygen) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_SIZE_T + +dnl Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS([errno.h stddef.h stdlib.h string.h strings.h unistd.h]) + +dnl Checks for library functions. +AC_CHECK_FUNCS(strtol) + + +dnl /************************************************************************** +dnl * Option setting * +dnl **************************************************************************/ + +dnl Some default values cause I'm not sure whether autoconf set them, while +dnl documentation says it does... +gmp_package="yes" +gmp_include_package="yes" +gmp_library_package="yes" + +NEED_MP="no" + +dnl --with-gmp=gmp-path +AC_ARG_WITH(gmp, + [ --with-gmp=DIR DIR where the gmp package is installed], + [ echo "Package gmp : $withval" && + gmp_package=$withval && + GMP_INC=$gmp_package/include && + GMP_LIB=$gmp_package/lib && + SCOPLIB_INT_T=SCOPLIB_INT_T_IS_MP && + NEED_MP="yes"]) + +AC_ARG_WITH(gmp-include, + [ --with-gmp-include=DIR DIR where gmp.h is installed], + [ echo "Package gmp-include : $withval" && + gmp_include_package=$withval && + GMP_INC=$gmp_include_package && + SCOPLIB_INT_T=SCOPLIB_INT_T_IS_MP && + NEED_MP="yes"]) + +AC_ARG_WITH(gmp-library, + [ --with-gmp-library=DIR DIR where the gmp library is installed], + [ echo "Package gmp-library : $withval" && + gmp_library_package=$withval && + GMP_LIB=$gmp_library_package && + SCOPLIB_INT_T=SCOPLIB_INT_T_IS_MP && + NEED_MP="yes"]) + +AC_ARG_ENABLE(int-version, + [ --enable-int-version 'int' (32 bits) version is built], + [ echo "Package int : $enableval" && + BITS="32" && + SCOPLIB_INT_T=SCOPLIB_INT_T_IS_LONG]) + +AC_ARG_ENABLE(llint-version, + [ --enable-llint-version 'long long int' (64 bits) version is built], + [ echo "Package long long int : $enableval" && + BITS="64" && + SCOPLIB_INT_T=SCOPLIB_INT_T_IS_LONGLONG]) + +AC_ARG_ENABLE(mp-version, + [ --enable-mp-version 'MP' (multiple precision) version is built], + [ echo "Package mp : $enableval" && + BITS="MP" && + SCOPLIB_INT_T=SCOPLIB_INT_T_IS_MP && + CPPFLAGS="$CPPFLAGS -DLINEAR_VALUE_IS_MP" + NEED_MP="yes"]) + +dnl FIXME: should be removed... +CPPFLAGS="$CPPFLAGS -D$SCOPLIB_INT_T" + +dnl /************************************************************************** +dnl * Where is GMP? * +dnl **************************************************************************/ + + +dnl Checking for gmp +AC_MSG_CHECKING(whether gmp works) +if test "$gmp_package" = "no"; then + echo "GMP package not defined" + AC_MSG_RESULT(no) + TO_BUILD_MP="" +else + if test "$NEED_MP" = "no"; then + echo "Mode normal GMP" + TO_BUILD="$TO_BUILD MP" + AC_CHECK_HEADER(gmp.h, + [AC_CHECK_LIB(gmp, + __gmpz_init, + [LIBS="$LIBS -lgmp"], + [echo "Can't find gmp library." && + echo "MP version will not be builded." && + TO_BUILD_MP=""])], + [echo "Can't find gmp headers." && + echo "MP version will not be builded." && + TO_BUILD_MP=""]) + else + dnl Default given by --with-X is "yes", --without-X is "no". We also + dnl initialized manually all gmp_package* variables to "yes" (thus they are + dnl supposed to be "yes" except if the user set them himself). + + if test "$gmp_package" != "yes" ; then + echo "(GMP path has been set by user)" + GMP_DIR=$gmp_package + dnl Useful for AC_CHECK_X to find what we want. + CPPFLAGS="-I$GMP_DIR/include $CPPFLAGS" + LDFLAGS="-L$GMP_DIR/lib $LDFLAGS" + fi + + if test "$gmp_include_package" != "yes" ; then + CPPFLAGS="-I$GMP_INC $CPPFLAGS" + fi + + if test "$gmp_library_package" != "yes" ; then + LDFLAGS="-L$GMP_LIB $LDFLAGS" + fi + + AC_CHECK_HEADER(gmp.h, + [], + [AC_MSG_ERROR(Can't find gmp headers.)]) + AC_CHECK_LIB(gmp, + __gmpz_init, + [LIBS="$LIBS -lgmp"], + [AC_MSG_ERROR(Can't find gmp library.)]) + + AC_MSG_RESULT(yes) + fi +fi + + +dnl /************************************************************************** +dnl * Substitutions * +dnl **************************************************************************/ + + +dnl Substitutions to do. +AC_SUBST(BITS) +AC_SUBST(SCOPLIB_INT_T) +AC_SUBST(ac_aux_dir) + +dnl Configure Makefiles. +AC_CONFIG_FILES([ + Makefile + doc/Makefile + doc/Doxyfile + include/Makefile + include/scoplib/scop.h + source/Makefile + ], + [test -z "$CONFIG_HEADERS" || echo timestamp > source/stamp-h.in]) + +AC_OUTPUT + + +echo " /*-----------------------------------------------*" +echo " * Clan/Scop configuration is OK *" +echo " *-----------------------------------------------*/" +echo "It appears that your system is OK to start Clan/Scop compilation. You " +echo "need now to type \"make\". Lastly type \"make install\" to install Clan " +echo "on your system (log as root if necessary)." diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in new file mode 100644 index 0000000..4bafac3 --- /dev/null +++ b/doc/Doxyfile.in @@ -0,0 +1,1295 @@ +# Doxyfile 1.5.3 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file that +# follow. The default is UTF-8 which is also the encoding used for all text before +# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into +# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of +# possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = ScopLib + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = @PACKAGE_VERSION@ + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = htmldoc + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, +# Italian, Japanese, Japanese-en (Japanese with English messages), Korean, +# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, +# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = YES + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = YES + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = YES + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to +# include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be extracted +# and appear in the documentation as a namespace called 'anonymous_namespace{file}', +# where file will be replaced with the base name of the file that contains the anonymous +# namespace. By default anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from the +# version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text " + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = @top_srcdir@/source \ + @top_srcdir@/include/scoplib + +# This tag can be used to specify the character encoding of the source files that +# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default +# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding. +# See http://www.gnu.org/software/libiconv for the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the output. +# The symbol name can be a fully qualified name, a word, or if the wildcard * is used, +# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH +# then you must also enable this option. If you don't then doxygen will produce +# a warning and turn it on anyway + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. Otherwise they will link to the documentstion. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = YES + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to +# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to +# specify the directory where the mscgen tool resides. If left empty the tool is assumed to +# be found in the default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will +# generate a caller dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable caller graphs for selected +# functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = /usr/bin/ + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the number +# of direct children of the root node in a graph is already larger than +# MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, which results in a white background. +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..4bf7dea --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,92 @@ +# +# /**------- <| --------------------------------------------------------** +# ** A Clan/Scop ** +# **--- /.\ -----------------------------------------------------** +# ** <| [""M# makefile.am ** +# **- A | # -----------------------------------------------------** +# ** /.\ [""M# First version: 30/04/2008 ** +# **- [""M# | # U"U#U -----------------------------------------------** +# | # | # \ .:/ +# | # | #___| # +# ****** | "--' .-" ***************************************************** +# * |"-"-"-"-"-#-#-## Clan : the Chunky Loop Analyser (experimental) * +# **** | # ## ###### **************************************************** +# * \ .::::'/ * +# * \ ::::'/ Copyright (C) 2008 Cedric Bastoul * +# * :8a| # # ## * +# * ::88a ### This is free software; you can redistribute it * +# * ::::888a 8a ##::. and/or modify it under the terms of the GNU * +# * ::::::::888a88a[]::: Lesser General Public License as published by * +# *::8:::::::::SUNDOGa8a::. the Free Software Foundation, either version 3 of * +# *::::::::8::::888:Y8888:: the License, or (at your option) * +# *::::':::88::::888::Y88a::::::::::::... any later version. * +# *::'::.. . ..... .. ... . * +# * This software 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 General * +# * Public License for more details. * +# * * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with software; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * +# * * +# * Clan, the Chunky Loop Analyser * +# * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr * +# * * +# *****************************************************************************/ +# +# Makefile.am (or makefile if generated) of Clan, the Chunky Loop Analyser. +# Makefile.am is not a makefile, you must run the 'autogen.sh' THEN the +# configure shellscript to generate the Makefile thanks to this file. + + + +############################################################################# +SUBDIRS = + +############################################################################# + +MAINTAINERCLEANFILES = Makefile.in + +EXTRA_DIST = \ + htmldoc.tar.gz \ + clan.pdf \ + S4.cloog \ + ascii-art.txt \ + images/basic.eps \ + images/basic.fig \ + images/basic.jpg \ + images/basic.pdf \ + images/basic.txt \ + images/basic1.eps \ + images/basic1.fig \ + images/basic1.jpg \ + images/basic1.pdf \ + images/basic1.txt \ + images/basic2.eps \ + images/basic2.fig \ + images/basic2.jpg \ + images/basic2.pdf \ + images/basic2.txt \ + images/tree.eps \ + images/tree.fig \ + images/tree.jpg \ + images/tree.pdf \ + images/tree.txt + + +info_TEXINFOS = clan.texi + +DOCDIR = htmldoc +DOXYFILE = Doxyfile +DOXYGEN = @DOXYGEN@ + +# The following requires a fixed version of the Emacs 19.30 etags. +ETAGS_ARGS = --lang=none \ + --regex='/^@node[ \t]+\([^,]+\)/\1/' $(srcdir)/doc/clan.texi +TAGS_DEPENDENCIES = clan.texi $(DOXYFILE).in + +htmldoc.tar.gz: + mkdir -p $(top_srcdir)/doc/htmldoc + $(DOXYGEN) $(DOXYFILE) + tar czf htmldoc.tar.gz htmldoc diff --git a/doc/S4.cloog b/doc/S4.cloog new file mode 100644 index 0000000..1524381 --- /dev/null +++ b/doc/S4.cloog @@ -0,0 +1,44 @@ +# language: C +c + +# no parameters +0 2 +0 + +1 # One statement + +1 +# D = {i, j | 2<=i<=4 2<=j<=4} +4 4 +# i j 1 +1 1 0 -2 +1 -1 0 4 +1 0 1 -2 +1 0 -1 4 +0 0 0 +0 + +1 # Scattering function + +# T = (j+2,3i+j) +2 6 +# t1 t2 i j 1 +0 1 0 0 -1 0 +0 0 1 -1 0 0 + +1 +t1 t2 + +############################# + + +# T = (j,i) +2 6 +# t1 t2 i j 1 +0 1 0 0 -1 0 +0 0 1 -1 0 0 + +2 6 +# t1 t2 i j 1 +0 1 0 0 -1 -2 +0 0 1 -3 -1 0 diff --git a/doc/ascii-art.txt b/doc/ascii-art.txt new file mode 100644 index 0000000..dd56019 --- /dev/null +++ b/doc/ascii-art.txt @@ -0,0 +1,25 @@ + <| + A + /.\ + <| [""M# + A | # + /.\ [""M# + [""M# | # U"U#U + | # | # \ .:/ + | # | #___| # + | "--' .-" + |"-"-"-"-"-#-#-## + | # ## ###### + \ .::::'/ + \ ::::'/ + :8a| # # ## + ::88a ### + ::::888a 8a ##::. + ::::::888a88a[]:::: + :::::::::SUNDOGa8a::::. .. + :::::8::::888:Y8888:::::::::... +::':::88::::888::Y88a______________________________________________________ +:: ::::88a::::88a:Y88a __---__-- __ +' .: ::Y88a:::::8a:Y88a __----_-- -------_-__ + :' ::::8P::::::::::88aa. _ _- -- --_ --- __ --- __-- +.:: :::::::::::::::::::Y88as88a...s88aa. diff --git a/doc/clan.texi b/doc/clan.texi new file mode 100644 index 0000000..983cabc --- /dev/null +++ b/doc/clan.texi @@ -0,0 +1,2429 @@ +\input texinfo +@c % +@c % /**-----------------------------------------------------------------** +@c % ** Clan ** +@c % **-----------------------------------------------------------------** +@c % ** clan.texi ** +@c % **-----------------------------------------------------------------** +@c % ** First version: september 10th 2006 ** +@c % **-----------------------------------------------------------------**/ +@c % +@c % release 0.0: May 4th 2008 +@c % +@c %/************************************************************************** +@c % * Clan: the Chunky Loop Analyzer (experimental) * +@c % **************************************************************************/ + + +@c % /************************************************************************* +@c % * PART I: HEADER * +@c % *************************************************************************/ +@c %**start of header +@setfilename clan.info +@settitle Clan - a polyhedral representation extractor for high level programs + +@set EDITION 1.0 +@set VERSION 1.0.0 +@set UPDATED May 4th 2008 +@c @set UPDATED Coming soon +@setchapternewpage odd + +@c % This is to ask for A4 instead of Letter size document. +@iftex + @afourpaper +@end iftex + +@c %**end of header + +@c % /************************************************************************* +@c % * PART II: SUMMARY DESCRIPTION AND COPYRIGHT * +@c % *************************************************************************/ + +@copying +This manual is for Clan version @value{VERSION}, a software +which extracts the polyhedral representation of some parts of +high level programs written in C, C++, C# or Java. + +It would be quite kind to refer the following paper in any publication that +results from the use of the Clan software or its library (the reason to cite +it is, amongst many other interesting things, it defines what is a @emph{SCoP}, +or @emph{static control part}): + +@example +@@InProceedings@{Bas03, +@ @ author =@ @ @ @ @{C\'edric Bastoul and Albert Cohen and Sylvain Girbal and +@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ Saurabh Sharma and Olivier Temam@}, +@ @ title =@ @ @ @ @ @{Putting Polyhedral Loop Transformations to Work@}, +@ @ booktitle =@ @{LCPC'16 International Workshop on Languages and +@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ Compilers for Parallel Computers, LNCS 2958@}, +@ @ pages =@ @ @ @ @ @{209--225@}, +@ @ month =@ @ @ @ @ @{october@}, +@ @ year =@ @ @ @ @ @ 2003, +@ @ address =@ @ @ @{College Station, Texas@} +@} +@end example + +Copyright @copyright{} 2008 C@'edric Bastoul. + +@c quotation +Permission is granted to copy, distribute and/or modify this document under +the terms of the GNU Free Documentation License, Version 1.2 +published by the Free Software Foundation. To receive a copy of the +GNU Free Documentation License, write to the Free Software Foundation, Inc., +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +@c end quotation +@end copying + +@c % /************************************************************************* +@c % * PART III: TITLEPAGE, CONTENTS, COPYRIGHT * +@c % *************************************************************************/ +@titlepage +@title Clan +@subtitle A Polyhedral Representation Extractor for High Level Programs +@subtitle Edition @value{EDITION}, for Clan @value{VERSION} +@subtitle @value{UPDATED} +@author C@'edric Bastoul + +@c The following two commands start the copyright page. +@page +@vskip 0pt plus 1filll +@insertcopying +@end titlepage + +@c Output the table of contents at the beginning. +@contents + +@c % /************************************************************************* +@c % * PART IV: TOP NODE AND MASTER MENU * +@c % *************************************************************************/ +@ifnottex +@node Top +@top CLooG + +@insertcopying +@end ifnottex + +@menu +* Introduction:: +* Polyhedral Representation:: +* Clan Software:: +* Clan Library:: +@c * Hacking:: +* Installing:: +* Documentation:: +* References:: +@end menu + + + +@c % /************************************************************************* +@c % * PART V: BODY OF THE DOCUMENT * +@c % *************************************************************************/ + +@c % ****************************** INTRODUCTION ****************************** +@node Introduction +@chapter Introduction +Clan is a free software and library that translates some particular parts of +high level programs written in C, C++, C# or Java into a polyhedral representation. +This representation +may be manipulated by other tools to, e.g., achieve complex program +restructurations (for optimization, parallelization or any other kind of +manipulation). It has been created to avoid tedious and error-prone input +file writing for polyhedral tools (such as CLooG, LeTSeE, Candl etc.). +Using Clan, the user has to deal with source codes based on C grammar only +(as C, C++, C# or Java). + +Clan stands for @emph{Chunky Loop ANalyzer}: it is a part of the Chunky +project, a research tool for data locality improvement (@pxref{Bas03a}). +It is designed to be the front-end of any source-to-source automatic optimizers +and/or parallelizers. + +Clan is a very basic tool since it is only a translator from a given program +representation to another representation. Nevertheless the current version is +still under evaluation, and there is no guarantee that the upward compatibility +will be respected. A lot of reports are necessary to freeze the library +API and the input/output file shapes. The current output file format has been +designed after discussions between several compilation researchers from +various institutions. Thus you are very welcome and encouraged to send reports +on bugs, wishes, critics, comments, suggestions or (please !) successful +experiences to cedric.bastoul@@inria.fr. + + +@c % ******************* POLYHEDRAL REPRESENTATION OF PROGRAMS **************** +@node Polyhedral Representation +@chapter Polyhedral Representation of Programs +If you are reading the Clan's user manual, you probably don't need any +explanation about the Polyhedral Model. It's unlikely someone will read this +manual by chance. However some vicious advisor may ask their poor +engineers/interns/students +to work for the very first time on this exciting topic. Most papers on +Polyhedral Compilation are hard to read. Despite my efforts, +mine are no exception according to some reviewers... Hence I give there a new +try to provide a comprehensive explanation of the polyhedral model without the +size and style limits of a classical research paper. + +Be aware that to be able to understand the Polyhedral Model, there are few +prerequisites. You should not read the following while you still ignore +what is: +@itemize @bullet +@item a @code{for} loop construction in C programs, +@item an @emph{affine expression}, +@item a @emph{vector}, +@item a @emph{matrix}, +@item a @emph{matrix-vector multiply}. +@end itemize + +@menu +* Motivation:: +* Thinking in Polyhedra:: +@end menu + + +@node Motivation +@section Motivation: Program Transformations + +A direct translation of high level programs written, e.g., in C to assembly +then object code is likely to produce (very) inefficient applications. +Architectures are +quite complex, including several levels of cache memory, many cores, deep +pipelines, various number of functionnal units, of registers etc. +The list of such +"architectural features" is growing with each new generation of processors. +To achieve the best performance, the object program must do a smart use +of these features. +Programmers use high level languages for productivity and portability: +typically they do not have to take care of the target architecture but +to ensure they do write programs that produce the right output. Hence, +the problem of mapping the program to the target architecture in the most +efficient way is left to the compiler. + +The compiler may see a high level program as a specification +@emph{of an output}. The program is a list of operations to be executed to +produce the output. As long as the output is guaranteed to be as the +programmer specified in his code, the compiler is free to modify +the program. +For instance, let us imagine we are working on an architecture with only +three registers and we consider the following statements written by +a programmer: + +@example +@group +x = a + b; +y = c + d; +z = a * b; +@end group +@end example + +It is easy to see that we can reorder the three statements in any way without +modifying the semantics (no statement reads or writes a variable that another +statement writes). Because of the lack of registers, the solutions such that +the first and the third statements are one after the other are better +because @code{a} and @code{b} will be put in the processor registers by +one statement and can be reused directly by the other one +without reading to memory (this is called a @emph{data locality +improving} transformation). Hence a better statement order is, e.g.: + +@example +@group +x = a + b; +z = a * b; // a and b are still in processor registers +y = c + d; +@end group +@end example + +We could also notice that it is possible to run the three statements in +parallel and explicit this in the way the compiler and/or the architecture is +able to understand. Here we use OpenMP to describe parallelism. It is +supported in GCC since 4.2 version (this is called a @emph{parallelizing} +transformation): + +@example +@group +#pragma omp parallel sections +@{ + #pragma omp section + @{ + x = a + b; + @} + #pragma omp section + @{ + y = c + d; + @} + #pragma omp section + @{ + z = a * b; + @} +@} +@end group +@end example + +However, the right way to optimize this program is probably a mix of these +two techniques, especially if the target architecture have some limitations +to run too many operations in parallel: + +@example +@group +#pragma omp parallel sections +@{ + #pragma omp section + @{ + x = a + b; + z = a * b; + @} + #pragma omp section + @{ + y = c + d; + @} +@} +@end group +@end example + +Such transformations are quite trivial. The reason is the statements are +executed only once. The real sport begins when we have to deal with loops +as we will see momentarily. However, Clan users have to be conscious that +we @emph{need} to transform programs to achieve the best performance and that +the best transformation that have to be discovered +(with often many, many efforts) and performed may be +quite complex. Hence the need of powerful model and tools +(Who said Polyhedral Model and CLooG ? Right !). + + +@node Thinking in Polyhedra +@section Thinking in Polyhedra + + +Since the very first compilers, the internal representation of programs +is the @emph{Abstract Syntax Tree}, or AST. In such representation, +each statement appears only once even if it is executed many times (e.g., +when it is enclosed inside a loop). + +@noindent @strong{This is a limitation for program analysis.} +For instance if a statement @emph{depends} on another statement (i.e., they +access the same memory location and at least one of these accesses is a +write), we will consider both statements as unique entities while the +dependence relation may involve only few statement executions. + +@noindent @strong{This is a limitation for program transformations.} +Loop transformations operate on statement executions. For instance, +because they consider all statement executions at the same time, present day +production compilers are not able to achieve loop fusion (that tries to +merge the loop bodies of two loops) if the loop bounds +of the two loops do not match. + +@noindent @strong{This is a limitation for program manipulation flexibility.} +Trees are very rigid data structures that are not easy to manipulate. +Program transformation may require very complex transformations that will +imply deep modifications of the control flow. Hence, for complex program +restructuration, the need for a more precise, more flexible representation. + +The Polyhedral Model is a convenient alternative representation which +combines analysis power, expressiveness and high flexibility. The drawback +is it breaks the classical structure of programs that every programmer +is familiar with. It requires some (real) efforts +to be smoothly manipulated, but it definitely worth it. It is based on three +main concepts, @emph{iteration domain}, @emph{scattering function} and +@emph{access function} that are described in depth in the +following sections. + +A program part that can be represented using the Polyhedral Model is called +a @strong{Static Control Part} or @strong{SCoP} for short. + +@menu +* Iteration Domain:: +* Scattering Function:: +* Access Function:: +@end menu + +@node Iteration Domain +@subsection Iteration Domain + +The key aspect of the Polyhedral Model is to consider @emph{statement +instances}. A statement instance is @emph{one} execution of a statement. +A statement +outside a loop has only one instance while those inside loops may have many. +Let us consider the following code with two statements @code{S1} +and @code{S2}: + +@example +@group +pi = 3.14; // S1 +for (i = 0; i < 5; i++) + A[i] = pi; // S2 +@end group +@end example + +The list of statement instances is the following (we just have to fully +unroll the loop): + +@example +@group +pi = 3.14; +A[0] = x; +A[1] = x; +A[2] = x; +A[3] = x; +A[4] = x; +@end group +@end example + +Each instance of a statement which is enclosed inside a loop may be referred +thanks to its outer loop counters (or @emph{iterators}). In the Polyhedral +Model we consider statements as functions of the outer loop counters that may +produce statement instances: +instead of simply "@code{S2}", we use preferably the notation @code{S2(i)}. +For instance we denote the statement instance @code{A[3] = x;} of the +previous example as @code{S2(3)}. This means @emph{instance of +statement @code{S2} for} @code{i = 3}. +If a statement @code{S3} is enclosed inside two loops of iterators @code{i} +(outermost loop) and @code{j} (innermost loop), we would denote it +@code{S3(i,j)}, and so on with more enclosing loops. + +The ordered list +of iterators (ordered from the outermost iterator to the innermost iterator) +is called the @strong{iteration vector}. For instance the iteration vector for +@code{S3} is @code{(i,j)}, for @code{S2} it is @code{(i)}, and for @code{S1} +it is empty since it has no enclosing loop: @code{()}. A more precise reading +at the notation @code{S2(3)} would show that it denotes the instance of +statement @code{S2} for the iteration vector @code{(2)}. + +Obviously, dealing with statement instances does not mean we have to unroll all +loops. First because there would be probably too many instances to deal with, +and second because we probably just don't know how many instances there are. +For instance in the following loop it is not possible to know (at compile time) +how many times the statement @code{S3} will be executed: + +@example +@group +for (i = 2; i <= N; i++) + for (j = 2; j <= N; j++) + A[i] = pi; // S3 +@end group +@end example + +@noindent Such a loop is said to be @emph{parametric}: it depends on +(at least) a value called a @emph{parameter} which is not modified +during the execution of the whole loop, but is unknown at compile time. +Here the only parameter is @code{N}. + +A compact way to represent all the instances of a given statement +is to consider the set of all possible values of its iteration vector. +This set is called the @strong{iteration domain}. It can be conveniently +described thanks to all the constraints on the various iterator the statement +depends on. For instance, let us consider +the statement @code{S3} of the previous program. The iteration domain is the set +of iteration vectors @code{(i,j)}. Because of the parameter, we are not able to +achieve a precise list of all possible values, it would look like this: + +@example +@group +(2,2) (2,3) (2,4) ... (2,N) +(3,2) (3,3) (3,4) ... (3,N) +... ... ... ... ... +(N,2) (N,3) (N,4) ... (N,N) +@end group +@end example + +@noindent A better way is to say it is the set +of iteration vectors @code{(i,j)} such that @code{i} is an integer greater or +equal than 2 and lower or equal than @code{N}, and @code{j} is an integer +greater or equal than 2 and lower or equal than @code{N}. This may be written +in the following mathematical form: + +@tex +$$D _{S3} = \{(i,j) \in Z^2 \; | \; 2 \leq i \leq N \land 2 \leq j \leq N \}$$ +@end tex + +@ifnottex +@example +@group +D_S3 = @{(i,j) in Z^2 | 2 <= i <= N && 2 <= j <= N @} +@end group +@end example +@end ifnottex + +@noindent It is easy to see that this iteration domain is a part of the +2-dimensional space +@tex +$Z^2$. +@end tex +@ifnottex +@example +@group +Z^2. +@end group +@end example +@end ifnottex +We often use in our research papers a graphical representation that gives a +better view of this subspace: + +@image{images/basic1,4cm} + +@noindent Here the iteration domain is specified thanks to a set of +constraints. When those constraints are affine and +depend only on the outer loop counters and some parameters, the set of +constraints defines a @emph{polyhedron} (more precisely this is a +@emph{Z-polyhedron}, but we use @emph{polyhedron} for short). +Hence the Polyhedral Model. + +To facilitate the manipulation of the affine constraints, we use a matrix +representation. To write it, we use the @emph{homogeneous} iteration vector: +it is simply the iteration vector with some additional dimensions to +represent the parameters and the constant. +For instance for the statement @code{S3}, the +iteration vector in homogeneous coordinates is @code{(i,j,N,1)} +(we will now call it @emph{iteration vector} directly for short). +Then we write all the constraints as affine inequalities of the form +@tex +$p(i) \geq 0$. +@end tex +@ifnottex +@code{p(i) >= 0}. +@end ifnottex +For instance for the statement @code{S3} the set of constraints is: + +@tex +$$ +\hbox{$ \cases{ i - 2 &$\geq 0$\cr + -i + N &$\geq 0$\cr + j - 2 &$\geq 0$\cr + -j + N &$\geq 0$}$} +$$ +@end tex + +@ifnottex +@example +@group + i - 2 >= 0 + -i + N >= 0 + j - 2 >= 0 + -j + N >= 0 +@end group +@end example +@end ifnottex + +@noindent Lastly, we translate the constraint system to the form +@strong{domain matrix}@code{ * }@emph{iteration vector}@code{ >= 0} +(please someone show me how to do this in TeX -not LaTeX- for the +texinfo manual !): +@example +@group +[ 1 0 0 -2 ] [ i ] [ 0 ] +[ -1 0 1 0 ] [ j ] [ 0 ] +[ 0 1 0 -2 ] * [ N ] >= [ 0 ] +[ 0 -1 1 0 ] [ 1 ] [ 0 ] +@end group +@end example + +@noindent The domain matrix (along with the iteration vector which +is most of the time an implicit information) will +be used in all our tools to provide the informations on the iteration +domain of a given statement. + +@node Scattering Function +@subsection Scattering Function + +There is no ordering information inside the iteration domain: it only describes +the set of statement instances but @strong{not} the order in which they have +to be executed relatively to each other. In the past the lexicographic order +of the iteration domain was considered, this is no more true +(especially when using CLooG). If we don't give any ordering information, this +means that the statement instances may be executed in any order +(this is useful, e.g., to specify parallelism), but some statement instances +may depend on some others and it may be critical to enforce a given order (or +non-order). Hence we need another information. + +We call @emph{scattering} any kind of ordering information in the Polyhedral +Model. There exists many kind of ordering indeed, as @emph{allocation}, +@emph{scheduling}, @emph{chunking} etc. Nevertheless they are all expressed +in the same way, using @emph{logical stamps} that can have various semantics. + +In the case of @strong{scheduling}, the logical stamps are logical dates that +express at which date a statement instance have to be executed. For instance, +let us consider the following three statements: + +@example +@group +x = a + b; // S1 +y = c + d; // S2 +z = a * b; // S3 +@end group +@end example + +@noindent The scheduling of a statement @code{S} is typically +denoted by +@tex +$\theta_{S}$. +@end tex +@ifnottex +T_S. +@end ifnottex +Let us consider the following logical dates for each statement: + +@tex +@example +@group +$\theta_{S1} = 2$ +$\theta_{S2} = 3$ +$\theta_{S3} = 1$ +@end group +@end example +@end tex + +@ifnottex +@example +@group +T_S1 = 1 +T_S2 = 2 +T_S3 = 3 +@end group +@end example +@end ifnottex + +@noindent It means that statement @code{S3} have to be executed at logical date +@code{1}, statement @code{S1} have to be executed at logical date +@code{2} and statement @code{S2} have to be executed at logical date +@code{3}. The target code have to respect this scheduling (the order of +the logical dates), hence it would look like the following where the +variable @code{t} denotes the time: + +@example +@group +t = 1; +z = a * b; // S3 +t = 2; +x = a + b; // S1 +t = 3; +y = c + d; // S2 +@end group +@end example + +@noindent When some statements share the same logical date, this means that, +once the program reaches this logical date, the two statements can be executed +in any order, or better, in parallel. For instance let us consider the +following scheduling: + +@tex +@example +@group +$\theta_{S1} = 1$ +$\theta_{S2} = 2$ +$\theta_{S3} = 1$ +@end group +@end example +@end tex + +@ifnottex +@example +@group +T_S1 = 1 +T_S2 = 2 +T_S3 = 1 +@end group +@end example +@end ifnottex + +@noindent Statements @code{S1} and @code{S3} have the same logical date, +hence the target code would be: + +@example +@group +t = 1; +#pragma omp parallel sections +@{ + #pragma omp section + @{ + x = a + b; // S1 + @} + #pragma omp section + @{ + z = a * b; // S3 + @} +@} +t = 2; +y = c + d; // S2 +@end group +@end example + +Logical dates may be multidimensional, as clocks: the first dimension +corresponds to days (most significant), next one is hours (less +significant), the third to minutes and so on. For instance we can consider +the following multidimensional schedules for our example: + +@tex +@example +@group +$\theta_{S1} = (1,1)$ +$\theta_{S2} = (2,1)$ +$\theta_{S3} = (1,2)$ +@end group +@end example +@end tex + +@ifnottex +@example +@group +T_S1 = (1,1) +T_S2 = (2,1) +T_S3 = (1,2) +@end group +@end example +@end ifnottex + +@noindent It is not very hard to decypher the meaning of such scheduling. +Because of the first dimension, statements @code{S1} and @code{S3} will be +executed before statement @code{S2} (@code{S1} and @code{S3} are executed at +day 1, while @code{S2} is executed at day 2). The second dimension is not +really useful there for @code{S2} because it is the only statement executed +at day 2. Nevertheless it allows to order @code{S1} and +@code{S3} relatively to each other since @code{S1} is executed at hour 1 of day +1 while @code{S3} is executed at hour 2 of day 1. +The corresponding target code is the following, with some +additional time variables for a better view of the ordering (@code{t1} +corresponds to the first time dimension, @code{t2} to the second one): + +@example +@group +t1 = 1; +t2 = 1; +x = a + b; // S1 +t2 = 2; +z = a * b; // S3 +t1 = 2; +t2 = 1; +y = c + d; // S2 +@end group +@end example + +In the case of @strong{allocation} (in the litterature we can find some +papers that call it @emph{placement}), the logical stamps are a processor +number that expresses on which processor a statement instance has to be +executed. Typically, allocations are written in the same way as scheduling +(hence the general term of @emph{scattering}), here we denote it @math{P_S} for a +statement @code{S}. For instance, let us consider the following +allocation: + +@tex +@example +@group +$P_{S1} = 1$ +$P_{S2} = 2$ +$P_{S3} = 1$ +@end group +@end example +@end tex + +@ifnottex +@example +@group +P_S1 = 1 +P_S2 = 2 +P_S3 = 1 +@end group +@end example +@end ifnottex + +@noindent The corresponding target code have to take into account that both +statements @code{S1} and @code{S3} have to be executed on the same processor +(they have the same logical number 1) and that statement @code{S2} have +to be executed on another processor (logical number 2). A possible target code +is the following: + +@example +@group +#pragma omp parallel sections +@{ + #pragma omp section + @{ + // Logical processor 1 + x = a + b; // S1 + z = a * b; // S3 + @} + #pragma omp section + @{ + // Logical processor 2 + y = c + d; // S2 + @} +@} +@end group +@end example + +@noindent We can note that no order have been specified for the +statements @code{S1} and @code{S3} that are executed on the same processor. +Hence any order is satisfying. For sake of flexibility, it is usual to build +a scattering whose various dimensions do not have the same semantics. A +typical construction is @emph{space/time mapping} where the first @code{n} +dimensions are devoted to allocation, then the last @code{m} +dimensions are devoted to scheduling. Typically, space/time mapping is +written in the same way as scheduling (hence again the general term of +@emph{scattering}), here we denote it for a statement @code{S} as @math{M_S}. +For instance, let us consider the following space/time mapping for our +example where one dimension is devoted for mapping and one dimension is +devoted to scheduling: + +@tex +@example +@group +$M_{S1} = (1,2)$ +$M_{S2} = (2,1)$ +$M_{S3} = (1,1)$ +@end group +@end example +@end tex + +@ifnottex +@example +@group +M_S1 = (1,2) +M_S2 = (2,1) +M_S3 = (1,1) +@end group +@end example +@end ifnottex + +@noindent Here we have the same first dimension as the previous example, thus +the allocation of the statements to processors is the same. The second +dimension precises on a given processor at which logical date a statement +instance has to be executed. Here, the statement @code{S1} is executed at +day 2 on processor 1 while the statement @code{S3} is executed at day 1 onto +the same processor. It follows this space/time mapping corresponds to the +following target code (we added an additional variable to represent the +local logical clocks): + +@example +@group +#pragma omp parallel sections +@{ + #pragma omp section + @{ + // Logical processor 1 + t = 1; + z = a * b; // S3 + t = 2; + x = a + b; // S1 + @} + #pragma omp section + @{ + // Logical processor 2 + t = 1; + y = c + d; // S2 + @} +@} +@end group +@end example + +For the same reason as discussed for iteration domains +(@pxref{Iteration Domain}), it is not possible to define a scattering for +each statement instance, especially if the statement belongs to a +(possibly parametric) loop. The iteration vector fully defines an +instance of a given statement. Thus, a practical way to provide a scattering +for each instance of a given statement is to use a @emph{function} +that depends on the iteration vector. In this way the function may give +for each iteration vector a different scattering. We call these functions +@strong{scattering functions}. Scattering functions are @emph{affine} +functions of the outer loop counter and the global parameters. +For instance, let us consider the following source code: + +@example +@group +for (i = 2; i <= 4; i++) + for (j = 2; j <= 4; j++) + P[i+j] += A[i] + B[j]; // S4 +@end group +@end example + +@noindent The iteration domain of the statement @code{S4} is: + + +@tex +$$D _{S4} = \{(i,j) \in Z^2 \; | \; 2 \leq i \leq 4 \land 2 \leq j \leq 4 \}.$$ +@end tex +@ifnottex +@example +@group +D_S4= @{(i,j) in Z^2 | 2 <= i <= 4 && 2 <= j <= 4 @}. +@end group +@end example +@end ifnottex + +@noindent If you are still not comfortable with the mathematical notation, it +corresponds to the following graphical representation: + +@image{images/basic2,3cm} + +@noindent The list of the statement instances of @code{S4} (the integral +points of its iteration domain) corresponds to the following iteration vectors: + +@example +@group +iteration vector + (2,2) + (2,3) + (2,4) + (3,2) + (3,3) + (3,4) + (4,2) + (4,3) + (4,4) +@end group +@end example + +@noindent Let us suppose we want to schedule the instances of the statement +@code{S4} (the integral points of its iteration domain) using the following +scheduling function: + +@tex +@example +@group +$\theta_{S4}(i,j) = (j+2,3*i+j)$ +@end group +@end example +@end tex + +@ifnottex +@example +@group +T_S4(i,j) = (j+2,3*i+j) +@end group +@end example +@end ifnottex + +@noindent We only have to apply the function to each iteration vector to find +the logical date of each instance: + +@example +@group +iteration vector logical date + (2,2) --> (4,8) + (2,3) --> (5,9) + (2,4) --> (6,10) + (3,2) --> (4,11) + (3,3) --> (5,12) + (3,4) --> (6,13) + (4,2) --> (4,14) + (4,3) --> (5,15) + (4,4) --> (6,16) +@end group +@end example + +Polyhedral Model users do not have to take care about the generation of a +target code that respects the scattering: the CLooG tool is there to +solve the problem quite easily (@code{http://www.cloog.org}). For the previous +example, the target code would be the following (@code{t1} and @code{t2} +corresponds to the two dimensions of the logical date): + +@example +@group +for (t1 = 4; t1 <= 6; t1++) @{ + for (t2 = t1+4; t2 <= t1+10; t2++) @{ + if ((-t1+t2+2)%3 == 0) @{ + i = (-t1+t2+2)/3 ; + j = t1-2 ; + P[i+j] += A[i] + B[j]; // S4 + @} + @} +@} +@end group +@end example + + + +Obviously with such a twisted scheduling, it is hard to see the "meaning" +of the transformation. To name any kind of program transformation as +a magic spell ("tile", "fuse", "skew"...) is an old bad habit that should +be changed in the Polyhedral Model: a scheduling may be an arbitrary complex +sequence of basic-old-good transformations. Nevertheless it is most of the +time quite easy to translate well known transformations to schedules. For +instance, let us consider this new scheduling function: + +@tex +@example +@group +$\theta_{S4}(i,j) = (j,i)$ +@end group +@end example +@end tex + +@ifnottex +@example +@group +T_S4(i,j) = (j,i) +@end group +@end example +@end ifnottex + +@noindent Using CLooG, we can generate the target code: + +@example +@group +for (t1 = 2; t1 <= 4; t1++) @{ + for (t2 = 2; t2 <= 4; t2++) @{ + i = t2; + j = t1; + P[i+j] += A[i] + B[j]; // S4 + @} +@} +@end group +@end example + + +@noindent It is easy to see (and analyze) that it corresponds to a classical +@emph{loop interchange} transformation. + +A very useful example of multi-dimensional scattering functions is +the @strong{scheduling of the original program}. +The method to compute it is quite simple (@pxref{Fea92}). The idea is to +build an abstract syntax tree of the program and to read the scheduling for +each statement. For instance, let us consider the following implementation of +a Cholesky factorization: + +@example +@group +/* A Cholesky factorization kernel. */ +for (i=1;i<=N;i++) @{ + for (j=1;j<=i-1;j++) @{ + a[i][i] -= a[i][j] ; /* S1 */ + @} + a[i][i] = sqrt(a[i][i]) ; /* S2 */ + for (j=i+1;j<=N;j++) @{ + for (k=1;k<=i-1;k++) @{ + a[j][i] -= a[j][k]*a[i][k] ; /* S3 */ + @} + a[j][i] /= a[i][i] ; /* S4 */ + @} + @} +@} +@end group +@end example + +@noindent The corresponding abstract syntax tree is given in the following +figure. It directly gives the scattering functions (schedules) for all the +statements of the program. + +@image{images/tree,6cm} + +@tex +$$ +\hbox{$ \cases{ \theta _{S1}(i,j) &$= (0,i,0,j,0)$\cr + \theta _{S2}(i) &$= (0,i,1)$\cr + \theta _{S3}(i,j,k) &$= (0,i,2,j,0,k,0)$\cr + \theta _{S4}(i,j) &$= (0,i,2,j,1)$}$} +$$ +@end tex + +@ifnottex +@example +@group +T_S1(i,j) = (0,i,0,j,0) +T_S2(i) = (0,i,1) +T_S3(i,j,k) = (0,i,2,j,0,k,0) +T_S4(i,j) = (0,i,2,j,1) +@end group +@end example +@end ifnottex + +@noindent These schedules depend on the iterators and give for each instance +of each statement a unique execution date. Using such scattering functions +allows CLooG to re-generate the input code. + +@noindent To easily manipulate the scattering function of any +statement @code{S}, we translate it to the matrix form: +@tex +@math{\theta_S}(@emph{iteration vector}) +@end tex +@ifnottex +T_S(@emph{iteration vector}) +@end ifnottex +@code{ = }@strong{scattering matrix}@code{ * }@emph{iteration vector}. +For instance let us consider again our previous example +@tex +$\theta_{S4}(i,j) = (j+2,3*i+j).$ +@end tex +@ifnottex +T_S4(i,j) = (j+2,3*i+j). +@end ifnottex +We write it in the following way (again please someone show me how to do +this in TeX -not LaTeX- for the texinfo manual !): +@example +@group + [ i ] [ 0 1 2 ] [ i ] +T_S4([ j ]) = [ 3 1 0 ] * [ j ] + [ 1 ] [ 1 ] +@end group +@end example + +@noindent The scattering matrix (along with the iteration vector which +is most of the time an implicit information) will +be used in all our tools to provide the informations on the scattering +of a given statement. + + +@node Access Function +@subsection Access Function + +Before applying any transformation, it is essential to deeply analyze both the +original program and the transformation to ensure the transformation does not +imply any modification of the original program semantics. In the Polyhedral +Model, we can reach a @strong{total analysis power}: we are able to achieve +an exact analysis when all the memory accesses are made through arrays +(note that variables are a particular case of arrays since they are simply +arrays with only one memory location) with affine subscripts that depend +on outer loop counters and global parameters (note that @emph{subscripts} +are sometimes called @emph{index} or @emph{accesses} in the litterature). + +For instance let us consider the array access @code{A[2*i+j][j][i+N]}. It has +three dimensions, each subscript dimension is an affine form of some outer loop +iterarors (@code{i} and @code{j}) and global parameters (@code{N}) hence +it corresponds to an acceptable array access in the Polyhedral Model. + +Each array access can target a different memory cell depending on the +statement instance, i.e., depending on the iteration vector. +Thus we use access functions (or subscript functions or index functions as you +prefer) depending on the iteration vector to describe an array access. In our +example, the access function would be written +@math{F_A(i,j) = (2*i+j,j,i+N)}. + +@noindent To easily manipulate the access function of any +array @code{A}, we translate it to the matrix form: +@math{F_A}(@emph{iteration vector}) +@code{ = }@strong{access matrix}@code{ * }@emph{iteration vector}. +For instance let us consider again our previous example: we write it in the +following way (again please someone show me how to do this in TeX -not LaTeX- +for the texinfo manual !): +@example +@group + [ i ] [ 2 1 0 0 ] [ i ] +F_A([ j ]) = [ 0 1 0 0 ] * [ j ] + [ N ] [ 1 0 1 0 ] [ N ] + [ 1 ] [ 1 ] +@end group +@end example + +@noindent The access matrix (along with the iteration vector which +is most of the time an implicit information) will +be used in all our tools to provide the informations on the access +of a given statement. + + + +@c % *********************** Using the Clan Software ************************** +@node Clan Software +@chapter Using the Clan Software + + +@menu +* A First Example:: +* Writing The Input File:: +* Reading The Output File:: +* Calling Clan:: +* Clan Options:: +@end menu + +@c %/************************************************************************* +@c % * A FIRST EXAMPLE * +@c % *************************************************************************/ +@node A First Example +@section A First Example +Clan takes as input a source code file than can be written in either C or +C++ or C# or Java (or any other imperative language that is close enough +to C). It is very simple as it only translates a part of a program that can +be represented using the Polyhedral model (@pxref{Polyhedral Representation}) in +a matrix form. Clan does not find itself the program parts that could be +represented using the Polyhedral Model. More complex tools like WRAP-IT for the +ORC compiler (@code{http://www.lri.fr/~girbal/site_wrapit})or the GRAPHITE +branch of GCC (@code{http://gcc.gnu.org/wiki/Graphite}) are devoted to +such a complex, highly technical problem. Using Clan, the user has to specify +thanks to pragmas where begins the SCoP he is interested by, and where it ends. + +For instance, let us consider the following source code in C of a matrix-matrix +multiply program that reads two matrices, achieves the multiply then prints +the result. Let us also consider that the user is only interested in the +matrix-matrix multiply kernel: + +@example +/* matmul.c 128*128 matrix multiply */ +#include +#define N 128 + +int main() @{ + int i,j,k; + float a[N][N], b[N][N], c[N][N]; + + /* We read matrix a then matrix b */ + for (i = 0; i < N; i++) + for (j = 0; j < N; j++) + scanf(" %f",&a[i][j]); + for (i = 0; i < N; i++) + for (j = 0; j < N; j++) + scanf(" %f",&b[i][j]); + + /* c = a * b */ +#pragma scop + for (i = 0; i < N; i++) + for (j = 0; j < N; j++) @{ + c[i][j] = 0.0; + for (k = 0; k < N; k++) + c[i][j] = c[i][j] + a[i][k]*b[k][j]; + @} +#pragma endscop + + /* We print matrix c */ + for (i = 0; i < N; i++) @{ + for (j = 0; j < N; j++) + printf("%6.2f ",c[i][j]); + printf("\n"); + @} + + return 0; +@} +@end example + +The tags to ask Clan to consider a given part of the code are provided thanks +to the pragmas @code{#pragma scop} and @code{#pragma endscop}. It can have +different forms depending on the input language. This is explained in +a further section (@pxref{Writing The Input File}). + +This source code file may be called @samp{matmul.c} +(this example is provided in the Clan distribution as +@code{test/matmul.c}) and we can ask Clan to process it +and to generate the polyhedral representation by a simple call to Clan +with this file as input: @samp{clan matmul.c}. By default, Clan will print +the polyhedral representation in the standard output: + +@example +# [File generated by Clan 1.0.0 64 bits] + +SCoP + +# =============================================== Global +# Language +C + +# Context +0 3 + +# Parameter names are provided +1 +# Parameter names +N + +# Number of statements +2 + +# =============================================== Statement 1 +# ---------------------------------------------- 1.1 Domain +# Iteration domain +1 +4 5 + 1 1 0 0 0 ## i >= 0 + 1 -1 0 1 -1 ## -i+N-1 >= 0 + 1 0 1 0 0 ## j >= 0 + 1 0 -1 1 -1 ## -j+N-1 >= 0 + +# ---------------------------------------------- 1.2 Scattering +# Scattering function is provided +1 +# Scattering function +5 5 + 0 0 0 0 0 ## 0 + 0 1 0 0 0 ## i + 0 0 0 0 0 ## 0 + 0 0 1 0 0 ## j + 0 0 0 0 0 ## 0 + +# ---------------------------------------------- 1.3 Access +# Access informations are provided +1 +# Read access informations +0 5 +# Write access informations +2 5 + 1 1 0 0 0 ## c[i][j] + 0 0 1 0 0 ## + +# ---------------------------------------------- 1.4 Body +# Statement body is provided +1 +# Original iterator names +i j +# Statement body +c[i][j]=0.0; + + +# =============================================== Statement 2 +# ---------------------------------------------- 2.1 Domain +# Iteration domain +1 +6 6 + 1 1 0 0 0 0 ## i >= 0 + 1 -1 0 0 1 -1 ## -i+N-1 >= 0 + 1 0 1 0 0 0 ## j >= 0 + 1 0 -1 0 1 -1 ## -j+N-1 >= 0 + 1 0 0 1 0 0 ## k >= 0 + 1 0 0 -1 1 -1 ## -k+N-1 >= 0 + +# ---------------------------------------------- 2.2 Scattering +# Scattering function is provided +1 +# Scattering function +7 6 + 0 0 0 0 0 0 ## 0 + 0 1 0 0 0 0 ## i + 0 0 0 0 0 0 ## 0 + 0 0 1 0 0 0 ## j + 0 0 0 0 0 1 ## 1 + 0 0 0 1 0 0 ## k + 0 0 0 0 0 0 ## 0 + +# ---------------------------------------------- 2.3 Access +# Access informations are provided +1 +# Read access informations +6 6 + 1 1 0 0 0 0 ## c[i][j] + 0 0 1 0 0 0 ## + 2 1 0 0 0 0 ## a[i][k] + 0 0 0 1 0 0 ## + 3 0 0 1 0 0 ## b[k][j] + 0 0 1 0 0 0 ## +# Write access informations +2 6 + 1 1 0 0 0 0 ## c[i][j] + 0 0 1 0 0 0 ## + +# ---------------------------------------------- 2.4 Body +# Statement body is provided +1 +# Original iterator names +i j k +# Statement body +c[i][j]=c[i][j]+a[i][k]*b[k][j]; + + +# =============================================== Options +@end example + +We will not describe here precisely the structure and the components of this +output, this is described in depth in a further section +(@pxref{Reading The Output File}). This file format, called @code{.scop} has +been designed to be the input file format of most of the polyhedral tools. +If you read the description of the polyhedral representation of programs, +you should already feel familiar with this file format +(@pxref{Polyhedral Representation}). + + +@c %/************************************************************************* +@c % * Input file * +@c % *************************************************************************/ +@node Writing The Input File +@section Writing The Input File + +The input file of Clan is a source code file written in any language based on +C for the @code{for} loop, the @code{if} and for the array accesses. +C, C++, Java and C# are good examples that should work pretty well with Clan. + +The input file may contain a static control part (i.e., a part of the +program that can be represented using the Polyhedral Model as described in +the corresponding chapter, @pxref{Polyhedral Representation}) delimitated +@strong{by the user} thanks to pragmas. Clan trusts the user: it will not check +hardly whether the program part is actually a SCoP or not. It will only try to +translate the program part to a polyhedral representation and will fail with +@emph{syntax error} if it reads something wrong. + +In C, C++ and C#, the pragma to tag the beginning of the SCoP is: +@example +@group +#pragma scop +@end group +@end example +@noindent and the pragma to tag the end of the SCoP is: +@example +@group +#pragma endscop +@end group +@end example + +In Java, the pragma to tag the beginning of the SCoP is: +@example +@group +/*@@ scop */ +@end group +@end example +@noindent and the pragma to tag the end of the SCoP is: +@example +@group +/*@@ end scop */ +@end group +@end example + + + +@c %/************************************************************************* +@c % * Output file * +@c % *************************************************************************/ +@node Reading The Output File +@section Reading The Output File + +The output text file of Clan provides an explicit polyhedral representation of +a static control part. The output file format is called @emph{.scop} format. +It has been designed by various researchers in polyhedral compilation from +various institutions. It builds on previous popular polyhedral file formats +like @emph{.cloog} to provide a unique, extensible file format to every +polyhedral compilation tools (including future versions of CLooG). This file +is composed of two main parts. The first part is devoted to the polyhedral +representation of a SCoP. It contains what is strictly necessary to enter a +complete source-to-source framework in the polyhedral model and to output a +semantically equivalent code for the SCoP, from analysis to code generation. +The second part of the file contains options, i.e. extensions to provide +additional informations to some tools. + +The following grammar describes the structure of the first part of the +.scop file format where terminals are preceeded by "_". Each +relevant part will be explained in more details momentarily. Its looks +long but it has been artificially extended to be easily understood and +it can be easily simplified: + +@example +File ::= SCoP +SCoP ::= "SCoP" Context Statements +Context ::= Language Domain Parameters +Statements ::= Nb_statements Statement_list +String_list ::= _String String_list | (void) +Statement_list ::= Statement Statement_list | (void) +Domain_list ::= Domain Domain_list | (void) +Statement ::= Iteration_domain Scattering Access Body +Iteration_domain ::= Domain_union +Domain_union ::= Nb_domains Domain_list +Scattering ::= "0" | "1" Scattering_function +Access ::= "0" | "1" Read_function Write_function +Parameters ::= "0" | "1" Parameter_list +Body ::= "0" | "1" Iterator_list Body_text +Language ::= "C" | "C++" | "C#" | "Java" | "Toy" +Parameter_list ::= String_list +Iterator_list ::= String_list +Domain ::= _Matrix +Scattering_function ::= _Matrix +Read_function ::= _Matrix +Write_function ::= _Matrix +Nb_statements ::= _Integer +Nb_domains ::= _Integer +Body_text ::= _String +@end example + + +@itemize @bullet +@item @samp{Context} represents the informations that are + shared by all the statements. It consists on + the language used (which can be @samp{C}, @samp{C++}, @samp{C#} + or @samp{Java}), the global constraints on parameters and + optionally the parameter names. The set of constraints on parameters is + essential since it provides the number of parameters. The @samp{Domain} + encoding includes the number of unknown (here the number of parameters) + (@pxref{Domain Representation}). Even if there are no constraints, this + number has to be correct. + After the constraints, it is possible to provide the list of parameter + names (the textual names in the original program). A @samp{0} means + we don't provide the list of parameter names, and a @samp{1} means + the list of parameter names is provided afterward. The original + parameter names + are necessary for the code generator to be able to generate a code + that can replace directly the SCoP in the original program by + copy/paste. In the case of a @samp{0}, parameter names will probably + be generated by the code generator (this is the case when using CLooG) + or will be extracted from another input source. +@item @samp{Statements} represents the informations on the statements. + @samp{Nb_statements} is the number of statements in the program, + i.e. the number of @samp{Statement} items in the @samp{Statement_list}. + @samp{Statement} represents the informations on a given statement. + To each statement is associated four informations, the first one is + mandatory while the three others are optional. The statement iteration + domain @samp{Iteration_domain} is the required information, then one can + provide optionally a scattering function, the access functions and + the statement body, in this order. Each optional information is + preceeded by a boolean that precises whether the optional information is + provided or not. + The iteration domain (@pxref{Iteration Domain}) is represented using a + matrix (@pxref{Domain Representation}). Next, the scattering function + (@pxref{Scattering Function}) is represented using a matrix as well + (@pxref{Scattering Representation}). The access functions + (@pxref{Access Function}) are represented using two matrices, one for read + accesses and another one for write accesses + (@pxref{Access Representation}). The statement body is made of two + parts: first, the list of surrounding loop counters in the original + program and second, the text string of the statement. This + representation allows to apply the substitution of the original + iterators with new iterators in the target program. +@end itemize + +The main terminal parts (domains, scattering and access functions) are +detailed in the next subsections. Lastly, we will describe the option part +(@pxref{Option Part}). + +@menu +* Domain Representation:: +* Scattering Representation:: +* Access Representation:: +* Option Part:: +@end menu + +@node Domain Representation +@subsection Domain Representation +As shown by the grammar, the input file describes the various informations +thanks to strings, integers and domains. Each domain is defined by a set of +constraints in the PolyLib format (@pxref{Wil93}). They have the +following syntax: +@enumerate +@item Some optional comment lines beginning with @samp{#}. +@item The row and column numbers, possibly followed by comments. +@item The constraint rows. Each row corresponds to a constraint the + domain have to satisfy. Each row must be on a single line and is possibly + followed by comments. The constraint is an equality @math{p(x) = 0} if the + first element is 0, an inequality @math{p(x) \geq 0} if the first element + is 1. The next elements are the unknown coefficients, followed by + the parameter coefficients. The last element is the constant factor. +@end enumerate +For instance, assuming that @samp{i}, @samp{j} and @samp{k} are the loop +iterators and @samp{m} and @samp{n} are the parameters, the domain defined by +the following constraints : + +@tex +$$ +\hbox{$ \cases{ -i + m &$\geq 0$\cr + -j + n &$\geq 0$\cr + i + j - k &$\geq 0$}$} +$$ +@end tex +@ifnottex +@example +@group + -i + m >= 0 + -j + n >= 0 +i + j - k >= 0 +@end group +@end example +@end ifnottex + +@noindent can be written in the input file as follows : + +@example +@group +# This is a domain +3 7 # 3 lines and 7 columns +# eq/in i j k m n 1 + 1 -1 0 0 1 0 0 # -i + m >= 0 + 1 0 -1 0 0 1 0 # -j + n >= 0 + 1 1 1 -1 0 0 0 # i + j - k >= 0 +@end group +@end example + +Each iteration domain @samp{Iteration_domain} of a given statement +is a @emph{union} of polyhedra +@samp{Domain_union}. A union is defined by its number of elements +@samp{Nb_domains} and the elements themselves @samp{Domain_list}. +For instance, let us consider the following pseudo-code: + +@example +@group +for (i = 1; i <= n; i++) @{ + if ((i >= m) || (i <= 2*m)) + S1; +@} +@end group +@end example + +@noindent The iteration domain of @samp{S1} can be divided into two +polyhedra and written in the .scop file as follows: + +@example +@group +2 # Number of polyhedra in the union +# First domain +3 5 # 3 lines and 5 columns +# eq/in i m n 1 + 1 1 0 0 -1 # i >= 1 + 1 -1 0 1 0 # i <= n + 1 1 -1 0 0 # i >= m +# Second domain +3 5 # 3 lines and 5 columns +# eq/in i m n 1 + 1 1 0 0 -1 # i >= 1 + 1 -1 0 1 0 # i <= n + 1 -1 2 0 0 # i <= 2*m +@end group +@end example + +@node Scattering Representation +@subsection Scattering Representation +Scattering functions are depicted in the input file thanks a representation +very close to the domain one. The difference is each row do not describe a +constraint but a scattering function dimension (@pxref{Scattering Function}). +By convention, the first element of each row (the one that defines whether +the constraint is an equality or an inequality for domains) +@emph{must be set to 0}. The next elements are the unknown coefficients, +followed by the parameter coefficients. The last element is the constant +factor. For instance, assuming that @samp{i}, @samp{j} and @samp{k} are the loop +iterators and @samp{m} and @samp{n} are the parameters, the scattering +function +@tex +$\theta_{S}(i,j,k) = (j+2,3*i+j,k+n+1)$ +@end tex +@ifnottex +@example +T_@{S@}(i,j,k) = (j+2,3*i+j,k+n+1) +@end example +@end ifnottex +may be written in a .scop file in the following way: + +@example +@group +# A scattering function +3 7 # 3 dimensions and 7 columns +# 0 i j k m n 1 + 0 0 1 0 0 0 2 # j+2 + 0 3 1 0 0 0 0 # 3*i+j + 0 0 0 1 0 1 1 # k+n+1 +@end group +@end example + +Note that this representation is different from the .cloog format: the useless +and error-prone identity matrix part disappeared. + +The scattering function extracted by Clan is the scheduling of the original +program as described in a previous section (@pxref{Scattering Function}). It +allows a code generator (like CLooG) to reconstruct directly the original +program or a dependence analyzer (like Candl) to achieve its data dependence +calculation. + +@node Access Representation +@subsection Access Representation + +Access functions are depicted in the input file thanks a representation +very close to the domain one. The difference is each row do not describe a +constraint but a access function dimension (@pxref{Access Function}). +Moreover, the matrix representation do not describes only one access function +but a set of access functions. Each array accessed in the SCoP has a unique +strictly positive identification number. The first element of each row (the +one that defines whether the constraint is an equality or an inequality for +domains) corresponds to the array identifier iff the row corresponds to the +first dimension of the access function. If the first element is 0, this means +the row corresponds to the next dimension of the access function, with respect +to the previous row. The next elements are the unknown coefficients, +followed by the parameter coefficients. The last element is the constant +factor. For instance, assuming that @samp{i}, @samp{j} and @samp{k} are the loop +iterators and @samp{m} and @samp{n} are the parameters, the set of array +accesses @code{A[2*i+j][j][i+n]}, @code{B[i+j]} and @code{A[k][j][1]} (the +identifier of @code{A} is 1 and the identifier of @code{B} is 2) +may be written in a .scop file in the following way: + +@example +@group +# A set of access functions +7 7 # 7 rows and 7 columns +# id i j k m n 1 + 1 2 1 0 0 0 0 # A[2*i+j][j][i+n] + 0 0 1 0 0 0 0 # + 0 1 0 0 0 1 0 # + 2 1 1 0 0 0 0 # B[i+j] + 1 0 0 1 0 0 0 # A[k][j][1] + 0 0 1 0 0 0 0 # + 0 0 0 0 0 0 1 # +@end group +@end example + + +@node Option Part +@subsection Option Part + +The end of the .scop file is made of a succession of options delimited using +XML-like tags. Each tool will take care of known options and will ignore the +others. There is no specification for the option body as it is +tool-dependent. Nevertheless, authors are invited to put the name of +the tool inside the option name to avoid conflicts. A reserved +option name is @samp{Comments} that allows to put some comments in the second +part of the .scop file. For instance, this could be a possible +second part of a .scop file: + +@example +@group + + Just a comment example. +<\Comments> + + + This is supposed to provide CLooG some interesting + additional informations. +<\CLooG foobar> +@end group +@end example + +A second reserved name is @samp{arrays}, Clan can optionally print a +table of the arrays referenced in the access functions. For instance, for a program referencing first the array @samp{FOO}, then the array @samp{BAR}: + +@example +@group + +# Number of referenced arrays +2 +# First reference +1 FOO +# Second reference +2 BAR + +@end group +@end example + + + +@c %/************************************************************************* +@c % * Calling Clan * +@c % *************************************************************************/ +@node Calling Clan +@section Calling Clan +Clan is called by the following command: +@example + clan [ options | file ] +@end example +The default behavior of Clan is to read the input source code from a file and +to print the generated .scop file on the standard output. +Clan's behavior and the output file are under the user control thanks +to some options which will be detailed momentarily (@pxref{Clan Options}). +@code{file} is the input file. @code{stdin} is a special value: when used, +input is standard input. For instance, we can call Clan to process the +input file @code{basic.c} with default options by typing: +@code{clan basic.c} or @code{more basic.c | clan stdin} +(usual @code{more basic.c | clan -} works too). + + +@c %/************************************************************************* +@c % * Clan Options * +@c % *************************************************************************/ +@node Clan Options +@section Clan Options + +@menu +* Output:: +* Arrays Tag:: +* Help:: +* Version :: +@end menu + +@node Output +@subsection Output @code{-o } + + @code{-o }: this option sets the output file. @code{stdout} is a + special value: when used, output is standard output. + Default value is @code{stdout}. + +@node Arrays Tag +@subsection Arrays Tag @code{-arraystag} + +@code{-arraystag}: this option dumps the table of referenced arrays at +the end of the .scop file, between the @samp{} and +@samp{NbColumns - +nb_iterators - 2}) To represent the statement body, we use +@code{iterators}, an array of @code{nb_iterators} strings for the +surrounding loop counters names in the original program, and +@code{body}, the statement body string in the original program. + +@node clan_scop_t +@subsection clan_scop_t +@example +@group +struct clan_scop +@{ + clan_matrix_p context; /* Constraints on the SCoP parameters */ + int nb_parameters; /* Number of parameters for the SCoP */ + char ** parameters; /* Array of parameter names */ + int nb_arrays; /* Number of arrays accessed in the SCoP */ + char ** arrays; /* Array of array names */ + clan_statement_p statement; /* Statement list of the SCoP */ + char * optiontags; /* The content (as a 0 terminated + string) of the optional tags. */ + void * usr; /* A user-defined field, + not touched by clan. */ +@}; +typedef struct clan_scop clan_scop_t; +typedef struct clan_scop * clan_scop_p; +@end group +@end example + +@noindent @code{clan_scop_t} stores the useful informations of a static +control part of a program to process it within a polyhedral framework. +It contains the informations about the context (what is common to all +statements in the SCoP) and the list of statements @code{statement}. +The context is made of the constraints on the global parameters +@code{context}. The representation of the context using the +@code{clan_matrix_t} data structure is described with the output file +format (this is a domain, @pxref{Reading The Output File}). The list of +parameter names is provided as an array of @code{nb_parameters} strings +called @code{parameters} (@code{nb_parameters} is somewhat redundant as +it is supposed to be equal to @code{context->NbColumns - 2}). The list +of array names is provided as an array of @code{nb_arrays} strings +called @code{arrays}. Each accessed array in the SCoP has a unique +identifier (a strictly positive number, @pxref{Access Representation}), +@code{arrays} provides the correspondance between an identifier and the +real name of the accessed array. If an array has the identifier +@samp{id}, then its real name is @samp{arrays[id - 1]}. The +@code{optiontags} field contains the remainder of the SCoP description +file, as a @code{char*} string. Optional tags specified in the +@samp{Options} section are stored there. Finally, the @code{usr} field +is a pointer for library users convenience. This field is not touched by +Clan. + +As an example, let us consider again the matrix-matrix multiply program +(@pxref{A First Example}). +The next figure gives a possible representation in memory for this +SCoP thanks to the Clan data structures (it has been actually printed +by the @code{clan_scop_print} function, it is also possible to ask Clan to +output the internal representation using the command line option +@code{-structure}): + +@smallexample ++-- clan_scop_t +| | +| +-- clan_matrix_t +| | 0 3 +| | +| +-- Original parameters strings: N +| | +| +-- Accessed array strings: c a b +| | +| +-- clan_statement_t (S1) +| | | +| | +-- clan_matrix_list_t +| | | | +| | | +-- clan_matrix_t +| | | | 4 5 +| | | | [ 1 1 0 0 0 ] +| | | | [ 1 -1 0 1 -1 ] +| | | | [ 1 0 1 0 0 ] +| | | | [ 1 0 -1 1 -1 ] +| | | | +| | | +| | +-- clan_matrix_t +| | | 5 5 +| | | [ 0 0 0 0 0 ] +| | | [ 0 1 0 0 0 ] +| | | [ 0 0 0 0 0 ] +| | | [ 0 0 1 0 0 ] +| | | [ 0 0 0 0 0 ] +| | | +| | +-- NULL matrix +| | | +| | +-- clan_matrix_t +| | | 2 5 +| | | [ 1 1 0 0 0 ] +| | | [ 0 0 1 0 0 ] +| | | +| | +-- Original iterator strings: i j +| | | +| | +-- Original body: c[i][j]=0.0; +| | | +| | V +| | clan_statement_t (S2) +| | | +| | +-- clan_matrix_list_t +| | | | +| | | +-- clan_matrix_t +| | | | 6 6 +| | | | [ 1 1 0 0 0 0 ] +| | | | [ 1 -1 0 0 1 -1 ] +| | | | [ 1 0 1 0 0 0 ] +| | | | [ 1 0 -1 0 1 -1 ] +| | | | [ 1 0 0 1 0 0 ] +| | | | [ 1 0 0 -1 1 -1 ] +| | | | +| | | +| | +-- clan_matrix_t +| | | 7 6 +| | | [ 0 0 0 0 0 0 ] +| | | [ 0 1 0 0 0 0 ] +| | | [ 0 0 0 0 0 0 ] +| | | [ 0 0 1 0 0 0 ] +| | | [ 0 0 0 0 0 1 ] +| | | [ 0 0 0 1 0 0 ] +| | | [ 0 0 0 0 0 0 ] +| | | +| | +-- clan_matrix_t +| | | 6 6 +| | | [ 1 1 0 0 0 0 ] +| | | [ 0 0 1 0 0 0 ] +| | | [ 2 1 0 0 0 0 ] +| | | [ 0 0 0 1 0 0 ] +| | | [ 3 0 0 1 0 0 ] +| | | [ 0 0 1 0 0 0 ] +| | | +| | +-- clan_matrix_t +| | | 2 6 +| | | [ 1 1 0 0 0 0 ] +| | | [ 0 0 1 0 0 0 ] +| | | +| | +-- Original iterator strings: i j k +| | | +| | +-- Original body: c[i][j]=c[i][j]+a[i][k]*b[k][j]; +| | | +| | +| +@end smallexample + + +@node clan_options_t +@subsection clan_options_t +@example +@group +struct clan_options +@{ + char * name ; /* Name of the input file. */ +@}; +typedef struct clan_options clan_options_t; +typedef struct clan_options * clan_options_p; +@end group +@end example + +@noindent The @code{clan_options_t} structure contains all the possible +options to rule Clan's behaviour (@pxref{Calling Clan}). For the moment there +are mainly internal options, but it's going to change in the future. + + +@node Clan Functions +@section Clan Functions Description + +@menu +* clan_scop_extract:: +* clan_scop_print_dot_scop:: +* clan_scop_read:: +* clan_scop_tag_content:: +* Allocation and Initialization Functions:: +* Memory Deallocation Functions:: +* Printing Functions:: +@end menu + + +@node clan_scop_extract +@subsection clan_scop_extract +@example +@group +clan_scop_p clan_scop_extract(FILE * input, clan_options_p options); +@end group +@end example + +@noindent The @code{clan_scop_extract} function extracts the polyhedral +representation of a SCoP in the file provided thanks to the @code{input} +pointer (the file, possibly @code{stdin}, has to be open for reading), +according to some options +provided thanks to the pointer @code{options} to a @code{clan_options_t} +data structure (@pxref{clan_options_t}). It returns a pointer to the +extracted SCoP, translated into +a @code{clan_scop_t} data structure (@pxref{clan_scop_t}). + +@node clan_scop_print_dot_scop +@subsection clan_scop_print_dot_scop +@example +@group +void clan_scop_print_dot_scop +( + FILE * output, + clan_scop_p scop, + clan_options_p options +); +@end group +@end example + +@noindent The function @code{clan_scop_print_dot_scop} is a pretty printer for +@code{clan_scop_t} structures. It dumps the @code{scop} informations in +.scop format (@pxref{Reading The Output File}) in the file provided thanks to +the pointer @code{output} (the file, possibly @code{stdout}, has to be open +for writing), according to some options provided thanks to the pointer +@code{options} to a @code{clan_options_t} data structure +(@pxref{clan_options_t}). + + + +@node clan_scop_read +@subsection clan_scop_read +@example +@group +clan_scop_p clan_scop_read +( + FILE * input, + clan_options_p options +); +@end group +@end example + +@noindent The function @code{clan_scop_read} reads a .scop file from +the standard input, and returns a pointer on a freshly allocated +@code{clan_scop_t} structure containing the SCoP information. + + +@node clan_scop_tag_content +@subsection clan_scop_tag_content +@example +@group +char* clan_scop_tag_content +( + clan_scop_p scop, + char* from, + char* to +); +@end group +@end example + +@noindent The function @code{clan_scop_tag_content} reads the list of +optional tags for the @code{clan_scop_t} (stored in the +@code{optiontags} string), and returns a freshly allocated string of all +characters between the two given strings @code{from} and @code{to}. If +one or the other given strings are not found, or if there was no +optional part specified in the .scop, @code{NULL} is returned. + + +@node Allocation and Initialization Functions +@subsection Allocation and Initialization Functions +@example +clan_structure_p clan_structure_malloc(); +@end example +@noindent Each Clan data structure has an allocation and initialization +function as shown above, where @code{structure} have to +be replaced by the name of the convenient structure (without @samp{clan} +prefix and @samp{_t} suffix) for +instance @code{clan_scop_p clan_scop_malloc();}. These functions return +pointers to an allocated structure with fields set to convenient default +values. @strong{Using those functions is mandatory} to support internal +management fields and to avoid upward compatibility problems if +new fields appear. An exception is @code{clan_matrix_malloc} since the +@code{clan_matrix_t} needs two parameters: +the number of rows and columns of the matrix we want to allocate: +@example +clan_matrix_p clan_matrix_malloc(unsigned nbrows, unsigned nbcolumns); +@end example + + +@node Memory Deallocation Functions +@subsection Memory Deallocation Functions +@example +void clan_structure_free(clan_structure_p); +@end example +@noindent Each Clan data structure has a deallocation function as shown above, +where @code{structure} have to +be replaced by the name of the convenient structure (without @samp{clan} +prefix and @samp{_t} suffix) for +instance @code{void clan_scop_free(clan_scop_p);}. These functions +free the allocated memory for the structure provided as input. They free +memory recursively, i.e. they also free the allocated memory for the internal +structures. +@strong{Using those functions is mandatory} to avoid memory leaks on internal +management fields and to avoid upward compatibility problems if +new fields appear. + + +@node Printing Functions +@subsection Printing Functions +@example +void clan_structure_print(FILE *, clan_structure_p) ; +@end example +@noindent Each Clan data structure has a printing function as shown above, +where @code{structure} have to +be replaced by the name of the convenient structure (without @samp{clan} +prefix and @samp{_t} suffix) for +instance @code{void clan_scop_print(FILE *, clan_scop_p);}. These functions +print the pointed structure (and its fields recursively) to the file provided +as input (the file, possibly @code{stdout}, has to be open +for writing). + + +@node Example of Library Utilization +@section Example of Library Utilization +Here is a basic example showing how it is possible to use the Clan library, +assuming that a standard installation has been done. +The following C program reads a source code input file on the standard input, +then prints the solution on the standard output. +Options are preselected to the default values of the Clan software. +@example +/* example.c */ +# include +# include + +int main() +@{ + clan_scop_p scop; + clan_options_p options; + + /* Default option setting. */ + options = clan_options_malloc() ; + + /* Extraction of the SCoP. */ + scop = clan_scop_extract(stdin, options); + + /* Output of the .scop file. */ + clan_scop_print_dot_scop(stdout, scop, options); + + /* Save the planet. */ + clan_options_free(options); + clan_scop_free(scop); + + return 0; +@} +@end example + +@noindent The compilation command could be: +@example +gcc example.c -lclan -o example +@end example +@noindent A calling command with the input file test.c could be: +@example +more test.c | ./example +@end example + + + +@c % ****************************** INSTALLING ******************************** +@node Installing +@chapter Installing Clan + +@menu +* License:: +* Requirements:: +* Basic Installation:: +* Optional Features:: +* Uninstallation:: +@end menu + +@node License +@section License +First of all, it would be very kind to refer the following paper in any +publication that result from the use of the Clan software or its library, +@pxref{Bas03} (a bibtex entry is provided behind the title page of this +manual, along with copyright notice). + +This program 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 3 of the License, or (at your option) any later version. +This program 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 General Public License for more details. +@code{http://www.gnu.org/copyleft/lgpl.html} + + +@node Requirements +@section Requirements + + +Clan is a stand-alone tool and library. For a basic use, it does not need any +additional tool or library. Anyway, to be able to work in conjunction with +other tools that manipulate multiple precision numbers, the GNU GMP library +can be used as an option. + + +@menu +* GMP Library:: +@end menu + + +@node GMP Library +@subsection GMP Library (optional) + +To be able to deal with insanely large coefficient, the user will need to +install the GNU Multiple Precision Library (GMP for short) version 4.2.2 +or above. It can be freely downloaded from @code{http://www.swox.com/gmp}. +The user can compile it by typing the following commands on the GMP root +directory: + +@itemize @bullet +@item @code{./configure} +@item @code{make} +@item And as root: @code{make install} +@end itemize + +The GMP default installation is @code{/usr/local}. This directory may +not be inside your library path. To fix the problem, the user should set +@example +export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib +@end example +@noindent if your shell is, e.g., bash or +@example +setenv LD_LIBRARY_PATH $LD_LIBRARY_PATH:/usr/local/lib +@end example +@noindent if your shell is, e.g., tcsh. Add the line to your .bashrc or .tcshrc (or +whatever convenient file) to make this change permanent. Another solution +is to ask GMP to install in the standard path by using the prefix +option of the configure script: +@samp{./configure --prefix=/usr}. + +Clan has to be built using the GMP library by specifying the convenient +configure script options to buid the GMP version (@pxref{Optional Features}). + + +@node Basic Installation +@section Clan Basic Installation + +Once downloaded and unpacked +(e.g. using the @samp{tar -zxvf clan-@value{VERSION}.tar.gz} command), +you can compile Clan by typing the following commands on the Clan's root +directory: + +@itemize @bullet +@item @code{./configure} +@item @code{make} +@item And as root: @code{make install} +@end itemize + +The program binaries and object files can be removed from the +source code directory by typing @code{make clean}. To also remove the +files that the @code{configure} script created (so you can compile the +package for a different kind of computer) type @code{make distclean}. + + +@node Optional Features +@section Optional Features +The @code{configure} shell script attempts to guess correct values for +various system-dependent variables and user options used during compilation. +It uses those values to create the @code{Makefile}. Various user options +are provided by the Clan's configure script. They are summarized in the +following list and may be printed by typing @code{./configure --help} in the +Clan top-level directory. + +@itemize @bullet +@item By default, the installation directory is @code{/usr/local}: +@code{make install} will install the package's files in +@code{/usr/local/bin}, @code{/usr/local/lib} and @code{/usr/local/include}. +The user can specify an installation prefix other than @code{/usr/local} by +giving @code{configure} the option @code{--prefix=PATH}. + +@item By default, Clan is built in 64bits version. If the user give to +@code{configure} the option +@code{--enable-int-version}, the 32bits version of Clan will be compiled. +In the same way, the option @code{--enable-mp-version} have to be used to +build the multiple precision version. + +@item By default, @code{configure} will look for the GMP library +(necessary to build the multiple precision version) in standard +locations. If necessary, the user can specify the GMP path by giving +@code{configure} the option @code{--with-gmp=PATH}. +@end itemize + +@node Uninstallation +@section Uninstallation +The user can easily remove the Clan software and library from his system +by typing (as root if necessary) from the Clan top-level directory +@code{make uninstall}. + +@c % **************************** DOCUMENTATION ****************************** +@node Documentation +@chapter Documentation +The Clan distribution provides several documentation sources. First, the +source code itself is as documented as possible. The code comments use a +Doxygen-compatible presentation (something similar to what JavaDoc does for +JAVA). The user may install Doxygen +(see @code{http://www.stack.nl/~dimitri/doxygen}) to automatically +generate a technical documentation by typing @code{make doc} or +@code{doxygen ./autoconf/Doxyfile} at the Clan top-level directory after +running the configure script (@pxref{Installing}). Doxygen will generate +documentation sources (in HTML, LaTeX and man) in the @code{doc/source} +directory of the Clan distribution. + +The Texinfo sources of the present document are also provided in the @code{doc} +directory. You can build it in either DVI format (by typing +@code{texi2dvi cloog.texi}) or PDF format +(by typing @code{texi2pdf cloog.texi}) or HTML format +(by typing @code{makeinfo --html cloog.texi}, using @code{--no-split} +option to generate a single HTML file) or info format +(by typing @code{makeinfo cloog.texi}). + +@c % ****************************** REFERENCES ******************************** +@node References +@chapter References + +@itemize +@item +@anchor{Bas03a}[Bas03a] C. Bastoul, P. Feautrier. Improving data locality +by chunking. CC'12 International Conference on Compiler Construction, +LNCS 2622, pages 320-335, Warsaw, april 2003. + +@item +@anchor{Bas03}[Bas03] C. Bastoul and A. Cohen and S. Girbal and +S. Sharma and O. Temam. Putting Polyhedral Loop Transformations to +Work, LCPC'16 International Workshop on Languages and +Compilers for Parallel Computers, LNCS 2958, pages 209--225, +College Station, Texas, october 2003. + +@item +@anchor{Fea92}[Fea92] P. Feautrier Some efficient solutions to the affine +scheduling problem, part II: multidimensional time. +International Journal of Parallel Programming, 21(6):389--420, December 1992. + +@item +@anchor{Gri04}[Gri04] M. Griebl. Automatic parallelization of loop programs +for distributed memory architectures. Habilitation Thesis. Facult@"at f@"ur +Mathematik und Informatik, Universit@"at Passau, 2004. +@emph{http://www.infosun.fmi.uni-passau.de/cl/loopo/} + +@item +@anchor{Wil93}[Wil93] Doran K. Wilde. +A library for doing polyhedral operations. +Technical Report 785, IRISA, Rennes, France, 1993. + +@end itemize + + + + +@c % /************************************************************************* +@c % * PART VI: END OF THE DOCUMENT * +@c % *************************************************************************/ +@c @unnumbered Index + +@c @printindex cp + +@bye diff --git a/doc/images/basic.eps b/doc/images/basic.eps new file mode 100644 index 0000000..0cc0497 --- /dev/null +++ b/doc/images/basic.eps @@ -0,0 +1,402 @@ +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: basic.fig +%%Creator: fig2dev Version 3.2 Patchlevel 4 +%%CreationDate: Thu Nov 17 16:54:54 2005 +%%For: bastoul@ulysse.futurs.inria.fr (Cedric Bastoul) +%%BoundingBox: 0 0 445 301 +%%Magnification: 1.0000 +%%EndComments +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/col-1 {0 setgray} bind def +/col0 {0.000 0.000 0.000 srgb} bind def +/col1 {0.000 0.000 1.000 srgb} bind def +/col2 {0.000 1.000 0.000 srgb} bind def +/col3 {0.000 1.000 1.000 srgb} bind def +/col4 {1.000 0.000 0.000 srgb} bind def +/col5 {1.000 0.000 1.000 srgb} bind def +/col6 {1.000 1.000 0.000 srgb} bind def +/col7 {1.000 1.000 1.000 srgb} bind def +/col8 {0.000 0.000 0.560 srgb} bind def +/col9 {0.000 0.000 0.690 srgb} bind def +/col10 {0.000 0.000 0.820 srgb} bind def +/col11 {0.530 0.810 1.000 srgb} bind def +/col12 {0.000 0.560 0.000 srgb} bind def +/col13 {0.000 0.690 0.000 srgb} bind def +/col14 {0.000 0.820 0.000 srgb} bind def +/col15 {0.000 0.560 0.560 srgb} bind def +/col16 {0.000 0.690 0.690 srgb} bind def +/col17 {0.000 0.820 0.820 srgb} bind def +/col18 {0.560 0.000 0.000 srgb} bind def +/col19 {0.690 0.000 0.000 srgb} bind def +/col20 {0.820 0.000 0.000 srgb} bind def +/col21 {0.560 0.000 0.560 srgb} bind def +/col22 {0.690 0.000 0.690 srgb} bind def +/col23 {0.820 0.000 0.820 srgb} bind def +/col24 {0.500 0.190 0.000 srgb} bind def +/col25 {0.630 0.250 0.000 srgb} bind def +/col26 {0.750 0.380 0.000 srgb} bind def +/col27 {1.000 0.500 0.500 srgb} bind def +/col28 {1.000 0.630 0.630 srgb} bind def +/col29 {1.000 0.750 0.750 srgb} bind def +/col30 {1.000 0.880 0.880 srgb} bind def +/col31 {1.000 0.840 0.000 srgb} bind def + +end +save +newpath 0 301 moveto 0 0 lineto 445 0 lineto 445 301 lineto closepath clip newpath +-153.0 333.0 translate +1 -1 scale + +/cp {closepath} bind def +/ef {eofill} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/sa {save} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/sh {show} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/rot {rotate} bind def +/sc {scale} bind def +/sd {setdash} bind def +/ff {findfont} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/sw {stringwidth} bind def +/tr {translate} bind def +/tnt {dup dup currentrgbcolor + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} + bind def +/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul + 4 -2 roll mul srgb} bind def +/reencdict 12 dict def /ReEncode { reencdict begin +/newcodesandnames exch def /newfontname exch def /basefontname exch def +/basefontdict basefontname findfont def /newfont basefontdict maxlength dict def +basefontdict { exch dup /FID ne { dup /Encoding eq +{ exch dup length array copy newfont 3 1 roll put } +{ exch newfont 3 1 roll put } ifelse } { pop pop } ifelse } forall +newfont /FontName newfontname put newcodesandnames aload pop +128 1 255 { newfont /Encoding get exch /.notdef put } for +newcodesandnames length 2 idiv { newfont /Encoding get 3 1 roll put } repeat +newfontname newfont definefont pop end } def +/isovec [ +8#055 /minus 8#200 /grave 8#201 /acute 8#202 /circumflex 8#203 /tilde +8#204 /macron 8#205 /breve 8#206 /dotaccent 8#207 /dieresis +8#210 /ring 8#211 /cedilla 8#212 /hungarumlaut 8#213 /ogonek 8#214 /caron +8#220 /dotlessi 8#230 /oe 8#231 /OE +8#240 /space 8#241 /exclamdown 8#242 /cent 8#243 /sterling +8#244 /currency 8#245 /yen 8#246 /brokenbar 8#247 /section 8#250 /dieresis +8#251 /copyright 8#252 /ordfeminine 8#253 /guillemotleft 8#254 /logicalnot +8#255 /hyphen 8#256 /registered 8#257 /macron 8#260 /degree 8#261 /plusminus +8#262 /twosuperior 8#263 /threesuperior 8#264 /acute 8#265 /mu 8#266 /paragraph +8#267 /periodcentered 8#270 /cedilla 8#271 /onesuperior 8#272 /ordmasculine +8#273 /guillemotright 8#274 /onequarter 8#275 /onehalf +8#276 /threequarters 8#277 /questiondown 8#300 /Agrave 8#301 /Aacute +8#302 /Acircumflex 8#303 /Atilde 8#304 /Adieresis 8#305 /Aring +8#306 /AE 8#307 /Ccedilla 8#310 /Egrave 8#311 /Eacute +8#312 /Ecircumflex 8#313 /Edieresis 8#314 /Igrave 8#315 /Iacute +8#316 /Icircumflex 8#317 /Idieresis 8#320 /Eth 8#321 /Ntilde 8#322 /Ograve +8#323 /Oacute 8#324 /Ocircumflex 8#325 /Otilde 8#326 /Odieresis 8#327 /multiply +8#330 /Oslash 8#331 /Ugrave 8#332 /Uacute 8#333 /Ucircumflex +8#334 /Udieresis 8#335 /Yacute 8#336 /Thorn 8#337 /germandbls 8#340 /agrave +8#341 /aacute 8#342 /acircumflex 8#343 /atilde 8#344 /adieresis 8#345 /aring +8#346 /ae 8#347 /ccedilla 8#350 /egrave 8#351 /eacute +8#352 /ecircumflex 8#353 /edieresis 8#354 /igrave 8#355 /iacute +8#356 /icircumflex 8#357 /idieresis 8#360 /eth 8#361 /ntilde 8#362 /ograve +8#363 /oacute 8#364 /ocircumflex 8#365 /otilde 8#366 /odieresis 8#367 /divide +8#370 /oslash 8#371 /ugrave 8#372 /uacute 8#373 /ucircumflex +8#374 /udieresis 8#375 /yacute 8#376 /thorn 8#377 /ydieresis] def +/Times-Bold /Times-Bold-iso isovec ReEncode +/Times-Roman /Times-Roman-iso isovec ReEncode + /DrawEllipse { + /endangle exch def + /startangle exch def + /yrad exch def + /xrad exch def + /y exch def + /x exch def + /savematrix mtrx currentmatrix def + x y tr xrad yrad sc 0 0 1 startangle endangle arc + closepath + savematrix setmatrix + } def + +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +10 setmiterlimit +0 slj 0 slc + 0.06000 0.06000 sc +% +% Fig objects follow +% +% +% here starts figure with depth 51 +% Polyline +n 4200 1500 m 4200 3900 l 8400 3900 l 6000 1500 l + cp gs col7 0.75 shd ef gr +% Ellipse +7.500 slw + [15 45] 45 sd +1 slc +n 5400 3900 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 4800 3900 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 4200 3300 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 4800 3300 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 4200 2700 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 4200 3900 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 6000 3900 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 6600 3900 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 7200 3900 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 7800 3900 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 7200 3300 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 6600 3300 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 6000 3300 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 5400 3300 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 4800 2700 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 5400 2700 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 6000 2700 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 6600 2700 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 6000 2100 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 5400 2100 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 4800 2100 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 4200 2100 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 4200 1500 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 4800 1500 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 5400 1500 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 7800 3300 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 8400 3900 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 7200 2700 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 6600 2100 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 6000 1500 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Polyline +0 slc +gs clippath +9615 5160 m 9615 5040 l 9395 5040 l 9575 5100 l 9395 5160 l cp +eoclip +n 3000 5100 m + 9600 5100 l gs col0 s gr gr + +% arrowhead +15.000 slw +n 9395 5160 m 9575 5100 l 9395 5040 l 9395 5160 l cp gs 0.00 setgray ef gr col0 s +% Polyline +7.500 slw +gs clippath +3060 885 m 2940 885 l 2940 1105 l 3000 925 l 3060 1105 l cp +eoclip +n 3000 5100 m + 3000 900 l gs col0 s gr gr + +% arrowhead +15.000 slw +n 3060 1105 m 3000 925 l 2940 1105 l 3060 1105 l cp gs 0.00 setgray ef gr col0 s +% Polyline +7.500 slw +n 3000 4500 m + 2925 4500 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 3000 3900 m + 2925 3900 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 3000 3300 m + 2925 3300 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 3600 5100 m + 3600 5175 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 4200 5100 m + 4200 5175 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 5400 5100 m + 5400 5175 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 4800 5100 m + 4800 5175 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 6000 5100 m + 6000 5175 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 6600 5100 m + 6600 5175 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 3000 2700 m + 2925 2700 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 3000 1500 m + 2925 1500 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 3000 2100 m + 2925 2100 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline + [15 45] 45 sd +n 3000 1500 m + 9000 1500 l gs col0 s gr [] 0 sd +% Polyline + [15 45] 45 sd +n 8400 5100 m + 8400 900 l gs col0 s gr [] 0 sd +% Polyline +n 7200 5100 m + 7200 5175 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 7800 5100 m + 7800 5175 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 8400 5100 m + 8400 5175 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline + [15 45] 45 sd +n 3000 3900 m + 9000 3900 l gs col0 s gr [] 0 sd +% Polyline + [15 45] 45 sd +n 5400 900 m + 9600 5100 l gs col0 s gr [] 0 sd +% Polyline + [15 45] 45 sd +n 4200 5100 m + 4200 900 l gs col0 s gr [] 0 sd +/Times-Bold-iso ff 390.00 scf sf +2625 4650 m +gs 1 -1 sc (1) col0 sh gr +/Times-Bold-iso ff 390.00 scf sf +2625 4050 m +gs 1 -1 sc (2) col0 sh gr +/Times-Bold-iso ff 390.00 scf sf +3525 5550 m +gs 1 -1 sc (1) col0 sh gr +/Times-Bold-iso ff 390.00 scf sf +2700 1050 m +gs 1 -1 sc (j) col0 sh gr +/Times-Roman-iso ff 390.00 scf sf +8025 825 m +gs 1 -1 sc (i<=n) col0 sh gr +/Times-Bold-iso ff 390.00 scf sf +4125 5550 m +gs 1 -1 sc (2) col0 sh gr +/Times-Bold-iso ff 390.00 scf sf +8325 5550 m +gs 1 -1 sc (n) col0 sh gr +/Times-Bold-iso ff 390.00 scf sf +2550 1575 m +gs 1 -1 sc (m) col0 sh gr +/Times-Roman-iso ff 390.00 scf sf +9075 3975 m +gs 1 -1 sc (j>=2) col0 sh gr +/Times-Roman-iso ff 390.00 scf sf +9075 1575 m +gs 1 -1 sc (j<=m) col0 sh gr +/Times-Bold-iso ff 390.00 scf sf +9450 5475 m +gs 1 -1 sc (i) col0 sh gr +/Times-Roman-iso ff 390.00 scf sf +3825 825 m +gs 1 -1 sc (i>=2) col0 sh gr +/Times-Roman-iso ff 390.00 scf sf +4875 825 m +gs 1 -1 sc (j<=n+2-i) col0 sh gr +% here ends figure; +$F2psEnd +rs +showpage diff --git a/doc/images/basic.fig b/doc/images/basic.fig new file mode 100644 index 0000000..7fe0a97 --- /dev/null +++ b/doc/images/basic.fig @@ -0,0 +1,100 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 5400 3900 75 75 5400 3900 5400 3975 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 4800 3900 75 75 4800 3900 4800 3975 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 4200 3300 75 75 4200 3300 4200 3375 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 4800 3300 75 75 4800 3300 4800 3375 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 4200 2700 75 75 4200 2700 4200 2775 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 4200 3900 75 75 4200 3900 4200 3975 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 6000 3900 75 75 6000 3900 6000 3975 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 6600 3900 75 75 6600 3900 6600 3975 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 7200 3900 75 75 7200 3900 7200 3975 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 7800 3900 75 75 7800 3900 7800 3975 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 7200 3300 75 75 7200 3300 7200 3375 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 6600 3300 75 75 6600 3300 6600 3375 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 6000 3300 75 75 6000 3300 6000 3375 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 5400 3300 75 75 5400 3300 5400 3375 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 4800 2700 75 75 4800 2700 4800 2775 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 5400 2700 75 75 5400 2700 5400 2775 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 6000 2700 75 75 6000 2700 6000 2775 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 6600 2700 75 75 6600 2700 6600 2775 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 6000 2100 75 75 6000 2100 6000 2175 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 5400 2100 75 75 5400 2100 5400 2175 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 4800 2100 75 75 4800 2100 4800 2175 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 4200 2100 75 75 4200 2100 4200 2175 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 4200 1500 75 75 4200 1500 4200 1575 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 4800 1500 75 75 4800 1500 4800 1575 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 5400 1500 75 75 5400 1500 5400 1575 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 7800 3300 75 75 7800 3300 7800 3375 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 8400 3900 75 75 8400 3900 8400 3975 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 7200 2700 75 75 7200 2700 7200 2775 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 6600 2100 75 75 6600 2100 6600 2175 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 6000 1500 75 75 6000 1500 6000 1575 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 120.00 180.00 + 3000 5100 9600 5100 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 120.00 180.00 + 3000 5100 3000 900 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 3000 4500 2925 4500 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 3000 3900 2925 3900 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 3000 3300 2925 3300 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 3600 5100 3600 5175 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 4200 5100 4200 5175 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 5400 5100 5400 5175 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 4800 5100 4800 5175 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 6000 5100 6000 5175 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 6600 5100 6600 5175 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 3000 2700 2925 2700 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 3000 1500 2925 1500 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 3000 2100 2925 2100 +2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 + 3000 1500 9000 1500 +2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 + 8400 5100 8400 900 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 7200 5100 7200 5175 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 7800 5100 7800 5175 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 8400 5100 8400 5175 +2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 + 3000 3900 9000 3900 +2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 + 5400 900 9600 5100 +2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 + 4200 5100 4200 900 +2 3 0 0 0 7 51 -1 15 0.000 0 0 -1 0 0 5 + 4200 1500 4200 3900 8400 3900 6000 1500 4200 1500 +4 0 0 50 -1 2 26 0.0000 0 270 195 2625 4650 1\001 +4 0 0 50 -1 2 26 0.0000 0 270 195 2625 4050 2\001 +4 0 0 50 -1 2 26 0.0000 0 270 195 3525 5550 1\001 +4 0 0 50 -1 2 26 0.0000 0 345 135 2700 1050 j\001 +4 0 0 50 -1 0 26 0.0000 0 270 750 8025 825 i<=n\001 +4 0 0 50 -1 2 26 0.0000 0 270 195 4125 5550 2\001 +4 0 0 50 -1 2 26 0.0000 0 180 225 8325 5550 n\001 +4 0 0 50 -1 2 26 0.0000 0 180 330 2550 1575 m\001 +4 0 0 50 -1 0 26 0.0000 0 360 750 9075 3975 j>=2\001 +4 0 0 50 -1 0 26 0.0000 0 360 855 9075 1575 j<=m\001 +4 0 0 50 -1 2 26 0.0000 0 270 105 9450 5475 i\001 +4 0 0 50 -1 0 26 0.0000 0 270 750 3825 825 i>=2\001 +4 0 0 50 -1 0 26 0.0000 0 360 1410 4875 825 j<=n+2-i\001 diff --git a/doc/images/basic.jpg b/doc/images/basic.jpg new file mode 100644 index 0000000000000000000000000000000000000000..995b1d816207e6585df9c61ea65745d38e0db845 GIT binary patch literal 21180 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 o`^RDa{&AT9)*pxY`KgL;F;~nrBO=$x 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�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 EAG7bfB>(^b literal 0 HcwPel00001 diff --git a/doc/images/basic.txt b/doc/images/basic.txt new file mode 100644 index 0000000..e40913a --- /dev/null +++ b/doc/images/basic.txt @@ -0,0 +1,13 @@ + j^ i>=2 + | | j<=n+2-i + | |\ | i<=n + | | \ | +m-+-****---+-j<=m + | ***** | + | ****** | + | *******| +2-+-********-j>=2 + | | |\ +0-+-+------+--->i + | | | + 0 2 n diff --git a/doc/images/basic1.eps b/doc/images/basic1.eps new file mode 100644 index 0000000..9ff60bc --- /dev/null +++ b/doc/images/basic1.eps @@ -0,0 +1,332 @@ +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: basic1.fig +%%Creator: fig2dev Version 3.2 Patchlevel 5-alpha7 +%%CreationDate: Fri May 9 15:48:25 2008 +%%For: cedb@localhost (Bastoul Cedric) +%%BoundingBox: 0 0 347 303 +%Magnification: 1.0000 +%%EndComments +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/col-1 {0 setgray} bind def +/col0 {0.000 0.000 0.000 srgb} bind def +/col1 {0.000 0.000 1.000 srgb} bind def +/col2 {0.000 1.000 0.000 srgb} bind def +/col3 {0.000 1.000 1.000 srgb} bind def +/col4 {1.000 0.000 0.000 srgb} bind def +/col5 {1.000 0.000 1.000 srgb} bind def +/col6 {1.000 1.000 0.000 srgb} bind def +/col7 {1.000 1.000 1.000 srgb} bind def +/col8 {0.000 0.000 0.560 srgb} bind def +/col9 {0.000 0.000 0.690 srgb} bind def +/col10 {0.000 0.000 0.820 srgb} bind def +/col11 {0.530 0.810 1.000 srgb} bind def +/col12 {0.000 0.560 0.000 srgb} bind def +/col13 {0.000 0.690 0.000 srgb} bind def +/col14 {0.000 0.820 0.000 srgb} bind def +/col15 {0.000 0.560 0.560 srgb} bind def +/col16 {0.000 0.690 0.690 srgb} bind def +/col17 {0.000 0.820 0.820 srgb} bind def +/col18 {0.560 0.000 0.000 srgb} bind def +/col19 {0.690 0.000 0.000 srgb} bind def +/col20 {0.820 0.000 0.000 srgb} bind def +/col21 {0.560 0.000 0.560 srgb} bind def +/col22 {0.690 0.000 0.690 srgb} bind def +/col23 {0.820 0.000 0.820 srgb} bind def +/col24 {0.500 0.190 0.000 srgb} bind def +/col25 {0.630 0.250 0.000 srgb} bind def +/col26 {0.750 0.380 0.000 srgb} bind def +/col27 {1.000 0.500 0.500 srgb} bind def +/col28 {1.000 0.630 0.630 srgb} bind def +/col29 {1.000 0.750 0.750 srgb} bind def +/col30 {1.000 0.880 0.880 srgb} bind def +/col31 {1.000 0.840 0.000 srgb} bind def + +end +save +newpath 0 303 moveto 0 0 lineto 347 0 lineto 347 303 lineto closepath clip newpath +-152.1 333.9 translate +1 -1 scale + +/cp {closepath} bind def +/ef {eofill} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/sa {save} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/sh {show} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/rot {rotate} bind def +/sc {scale} bind def +/sd {setdash} bind def +/ff {findfont} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/sw {stringwidth} bind def +/tr {translate} bind def +/tnt {dup dup currentrgbcolor + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} + bind def +/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul + 4 -2 roll mul srgb} bind def + /DrawEllipse { + /endangle exch def + /startangle exch def + /yrad exch def + /xrad exch def + /y exch def + /x exch def + /savematrix mtrx currentmatrix def + x y tr xrad yrad sc 0 0 1 startangle endangle arc + closepath + savematrix setmatrix + } def + +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +10 setmiterlimit +0 slj 0 slc + 0.06000 0.06000 sc +% +% Fig objects follow +% +% +% here starts figure with depth 51 +% Polyline +0 slj +0 slc +0.000 slw +n 4200 1500 m 4200 3900 l 6675 3900 l 6675 1500 l + cp gs col7 0.75 shd ef gr +% Ellipse +7.500 slw + [15 45] 45 sd +1 slc +n 5400 3900 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 4800 3900 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 4200 3300 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 4800 3300 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 4200 2700 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 4200 3900 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 6000 3900 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 6600 3900 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 6600 3300 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 6000 3300 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 5400 3300 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 4800 2700 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 5400 2700 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 6000 2700 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 6600 2700 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 6000 2100 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 5400 2100 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 4800 2100 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 4200 2100 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 4200 1500 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 4800 1500 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 5400 1500 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 6600 2100 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 6000 1500 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 6653 1522 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Polyline +0 slc +gs clippath +6970 5160 m 7215 5160 l 7215 5040 l 6970 5040 l 6970 5040 l 7150 5100 l 6970 5160 l cp +eoclip +n 3000 5100 m + 7200 5100 l gs col0 s gr gr + +% arrowhead +15.000 slw +n 6970 5160 m 7150 5100 l 6970 5040 l 6970 5160 l cp gs 0.00 setgray ef gr col0 s +% Polyline +7.500 slw +gs clippath +3060 1130 m 3060 885 l 2940 885 l 2940 1130 l 2940 1130 l 3000 950 l 3060 1130 l cp +eoclip +n 3000 5100 m + 3000 900 l gs col0 s gr gr + +% arrowhead +15.000 slw +n 3060 1130 m 3000 950 l 2940 1130 l 3060 1130 l cp gs 0.00 setgray ef gr col0 s +% Polyline +7.500 slw +n 3000 4500 m + 2925 4500 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 3000 3900 m + 2925 3900 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 3000 3300 m + 2925 3300 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 3600 5100 m + 3600 5175 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 4200 5100 m + 4200 5175 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 5400 5100 m + 5400 5175 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 4800 5100 m + 4800 5175 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 6000 5100 m + 6000 5175 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 6600 5100 m + 6600 5175 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 3000 2700 m + 2925 2700 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 3000 1500 m + 2925 1500 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 3000 2100 m + 2925 2100 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline + [15 45] 45 sd +n 3000 1500 m + 7200 1500 l gs col0 s gr [] 0 sd +% Polyline + [15 45] 45 sd +n 3000 3900 m + 7200 3900 l gs col0 s gr [] 0 sd +% Polyline + [15 45] 45 sd +n 4200 5100 m + 4200 900 l gs col0 s gr [] 0 sd +% Polyline + [15 45] 45 sd +n 6675 5100 m + 6675 900 l gs col0 s gr [] 0 sd +/Times-Bold ff 433.33 scf sf +2625 4650 m +gs 1 -1 sc (1) col0 sh gr +/Times-Bold ff 433.33 scf sf +2625 4050 m +gs 1 -1 sc (2) col0 sh gr +/Times-Bold ff 433.33 scf sf +3525 5550 m +gs 1 -1 sc (1) col0 sh gr +/Times-Bold ff 433.33 scf sf +2700 1050 m +gs 1 -1 sc (j) col0 sh gr +/Times-Bold ff 433.33 scf sf +4125 5550 m +gs 1 -1 sc (2) col0 sh gr +/Times-Roman ff 433.33 scf sf +3825 825 m +gs 1 -1 sc (i>=2) col0 sh gr +/Times-Bold ff 433.33 scf sf +2550 1575 m +gs 1 -1 sc (N) col0 sh gr +/Times-Bold ff 433.33 scf sf +6450 5550 m +gs 1 -1 sc (N) col0 sh gr +/Times-Bold ff 433.33 scf sf +7275 5475 m +gs 1 -1 sc (i) col0 sh gr +/Times-Roman ff 433.33 scf sf +6300 900 m +gs 1 -1 sc (i<=N) col0 sh gr +/Times-Roman ff 433.33 scf sf +7350 1575 m +gs 1 -1 sc (j<=N) col0 sh gr +/Times-Roman ff 433.33 scf sf +7350 3975 m +gs 1 -1 sc (j>=2) col0 sh gr +% here ends figure; +$F2psEnd +rs +showpage +%%Trailer +%EOF diff --git a/doc/images/basic1.fig b/doc/images/basic1.fig new file mode 100644 index 0000000..caf0ebd --- /dev/null +++ b/doc/images/basic1.fig @@ -0,0 +1,86 @@ +#FIG 3.2 Produced by xfig version 3.2.5-alpha5 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 5400 3900 75 75 5400 3900 5400 3975 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 4800 3900 75 75 4800 3900 4800 3975 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 4200 3300 75 75 4200 3300 4200 3375 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 4800 3300 75 75 4800 3300 4800 3375 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 4200 2700 75 75 4200 2700 4200 2775 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 4200 3900 75 75 4200 3900 4200 3975 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 6000 3900 75 75 6000 3900 6000 3975 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 6600 3900 75 75 6600 3900 6600 3975 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 6600 3300 75 75 6600 3300 6600 3375 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 6000 3300 75 75 6000 3300 6000 3375 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 5400 3300 75 75 5400 3300 5400 3375 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 4800 2700 75 75 4800 2700 4800 2775 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 5400 2700 75 75 5400 2700 5400 2775 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 6000 2700 75 75 6000 2700 6000 2775 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 6600 2700 75 75 6600 2700 6600 2775 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 6000 2100 75 75 6000 2100 6000 2175 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 5400 2100 75 75 5400 2100 5400 2175 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 4800 2100 75 75 4800 2100 4800 2175 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 4200 2100 75 75 4200 2100 4200 2175 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 4200 1500 75 75 4200 1500 4200 1575 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 4800 1500 75 75 4800 1500 4800 1575 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 5400 1500 75 75 5400 1500 5400 1575 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 6600 2100 75 75 6600 2100 6600 2175 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 6000 1500 75 75 6000 1500 6000 1575 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 6653 1522 75 75 6653 1522 6653 1597 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 120.00 180.00 + 3000 5100 7200 5100 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 120.00 180.00 + 3000 5100 3000 900 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 3000 4500 2925 4500 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 3000 3900 2925 3900 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 3000 3300 2925 3300 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 3600 5100 3600 5175 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 4200 5100 4200 5175 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 5400 5100 5400 5175 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 4800 5100 4800 5175 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 6000 5100 6000 5175 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 6600 5100 6600 5175 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 3000 2700 2925 2700 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 3000 1500 2925 1500 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 3000 2100 2925 2100 +2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 + 3000 1500 7200 1500 +2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 + 3000 3900 7200 3900 +2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 + 4200 5100 4200 900 +2 3 0 0 0 7 51 -1 15 0.000 0 0 -1 0 0 5 + 4200 1500 4200 3900 6675 3900 6675 1500 4200 1500 +2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 + 6675 5100 6675 900 +4 0 0 50 -1 2 26 0.0000 0 285 225 2625 4650 1\001 +4 0 0 50 -1 2 26 0.0000 0 285 225 2625 4050 2\001 +4 0 0 50 -1 2 26 0.0000 0 285 225 3525 5550 1\001 +4 0 0 50 -1 2 26 0.0000 0 375 150 2700 1050 j\001 +4 0 0 50 -1 2 26 0.0000 0 285 225 4125 5550 2\001 +4 0 0 50 -1 0 26 0.0000 0 285 825 3825 825 i>=2\001 +4 0 0 50 -1 2 26 0.0000 0 285 315 2550 1575 N\001 +4 0 0 50 -1 2 26 0.0000 0 285 315 6450 5550 N\001 +4 0 0 50 -1 2 26 0.0000 0 285 120 7275 5475 i\001 +4 0 0 50 -1 0 26 0.0000 0 285 915 6300 900 i<=N\001 +4 0 0 50 -1 0 26 0.0000 0 375 915 7350 1575 j<=N\001 +4 0 0 50 -1 0 26 0.0000 0 375 825 7350 3975 j>=2\001 diff --git a/doc/images/basic1.jpg b/doc/images/basic1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..55830d422b4b1ca0b6cd800fbcb8c2e414df81c3 GIT binary patch literal 18353 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 i<=N + | | | + | | | +N-+-********--j<=N + | ******** + | ******** + | ******** +2-+-********--j>=2 + | | | +0-+-+------+--->i + | | | + 0 2 N diff --git a/doc/images/basic2.eps b/doc/images/basic2.eps new file mode 100644 index 0000000..a3781fe --- /dev/null +++ b/doc/images/basic2.eps @@ -0,0 +1,256 @@ +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: basic2.fig +%%Creator: fig2dev Version 3.2 Patchlevel 5-alpha7 +%%CreationDate: Sat May 10 21:23:40 2008 +%%For: cedb@localhost (Bastoul Cedric) +%%BoundingBox: 0 0 260 235 +%Magnification: 1.0000 +%%EndComments +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/col-1 {0 setgray} bind def +/col0 {0.000 0.000 0.000 srgb} bind def +/col1 {0.000 0.000 1.000 srgb} bind def +/col2 {0.000 1.000 0.000 srgb} bind def +/col3 {0.000 1.000 1.000 srgb} bind def +/col4 {1.000 0.000 0.000 srgb} bind def +/col5 {1.000 0.000 1.000 srgb} bind def +/col6 {1.000 1.000 0.000 srgb} bind def +/col7 {1.000 1.000 1.000 srgb} bind def +/col8 {0.000 0.000 0.560 srgb} bind def +/col9 {0.000 0.000 0.690 srgb} bind def +/col10 {0.000 0.000 0.820 srgb} bind def +/col11 {0.530 0.810 1.000 srgb} bind def +/col12 {0.000 0.560 0.000 srgb} bind def +/col13 {0.000 0.690 0.000 srgb} bind def +/col14 {0.000 0.820 0.000 srgb} bind def +/col15 {0.000 0.560 0.560 srgb} bind def +/col16 {0.000 0.690 0.690 srgb} bind def +/col17 {0.000 0.820 0.820 srgb} bind def +/col18 {0.560 0.000 0.000 srgb} bind def +/col19 {0.690 0.000 0.000 srgb} bind def +/col20 {0.820 0.000 0.000 srgb} bind def +/col21 {0.560 0.000 0.560 srgb} bind def +/col22 {0.690 0.000 0.690 srgb} bind def +/col23 {0.820 0.000 0.820 srgb} bind def +/col24 {0.500 0.190 0.000 srgb} bind def +/col25 {0.630 0.250 0.000 srgb} bind def +/col26 {0.750 0.380 0.000 srgb} bind def +/col27 {1.000 0.500 0.500 srgb} bind def +/col28 {1.000 0.630 0.630 srgb} bind def +/col29 {1.000 0.750 0.750 srgb} bind def +/col30 {1.000 0.880 0.880 srgb} bind def +/col31 {1.000 0.840 0.000 srgb} bind def + +end +save +newpath 0 235 moveto 0 0 lineto 260 0 lineto 260 235 lineto closepath clip newpath +-156.6 333.9 translate +1 -1 scale + +/cp {closepath} bind def +/ef {eofill} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/sa {save} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/sh {show} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/rot {rotate} bind def +/sc {scale} bind def +/sd {setdash} bind def +/ff {findfont} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/sw {stringwidth} bind def +/tr {translate} bind def +/tnt {dup dup currentrgbcolor + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} + bind def +/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul + 4 -2 roll mul srgb} bind def + /DrawEllipse { + /endangle exch def + /startangle exch def + /yrad exch def + /xrad exch def + /y exch def + /x exch def + /savematrix mtrx currentmatrix def + x y tr xrad yrad sc 0 0 1 startangle endangle arc + closepath + savematrix setmatrix + } def + +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +10 setmiterlimit +0 slj 0 slc + 0.06000 0.06000 sc +% +% Fig objects follow +% +% +% here starts figure with depth 51 +% Polyline +0 slj +0 slc +0.000 slw +n 4200 2700 m 4200 3900 l 5400 3900 l 5400 2700 l + cp gs col7 0.75 shd ef gr +% Ellipse +7.500 slw + [15 45] 45 sd +1 slc +n 5400 3900 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 4800 3900 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 4200 3300 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 4800 3300 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 4200 2700 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 4200 3900 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 5400 3300 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 4800 2700 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Ellipse + [15 45] 45 sd +n 5400 2700 75 75 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr + [] 0 sd +% Polyline +0 slc +gs clippath +5770 5160 m 6015 5160 l 6015 5040 l 5770 5040 l 5770 5040 l 5950 5100 l 5770 5160 l cp +eoclip +n 3000 5100 m + 6000 5100 l gs col0 s gr gr + +% arrowhead +15.000 slw +n 5770 5160 m 5950 5100 l 5770 5040 l 5770 5160 l cp gs 0.00 setgray ef gr col0 s +% Polyline +7.500 slw +gs clippath +3060 2330 m 3060 2085 l 2940 2085 l 2940 2330 l 2940 2330 l 3000 2150 l 3060 2330 l cp +eoclip +n 3000 5100 m + 3000 2100 l gs col0 s gr gr + +% arrowhead +15.000 slw +n 3060 2330 m 3000 2150 l 2940 2330 l 3060 2330 l cp gs 0.00 setgray ef gr col0 s +% Polyline +7.500 slw +n 3000 4500 m + 2925 4500 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 3000 3900 m + 2925 3900 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 3000 3300 m + 2925 3300 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 3600 5100 m + 3600 5175 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 4200 5100 m + 4200 5175 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 5400 5100 m + 5400 5175 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 4800 5100 m + 4800 5175 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline +n 3000 2700 m + 2925 2700 l gs 0.00 setgray ef gr gs col0 s gr +% Polyline + [15 45] 45 sd +n 3000 3900 m + 6000 3900 l gs col0 s gr [] 0 sd +% Polyline + [15 45] 45 sd +n 4200 5100 m + 4200 2100 l gs col0 s gr [] 0 sd +% Polyline + [15 45] 45 sd +n 5400 5175 m + 5400 2100 l gs col0 s gr [] 0 sd +% Polyline + [15 45] 45 sd +n 3000 2700 m + 6000 2700 l gs col0 s gr [] 0 sd +/Times-Bold ff 433.33 scf sf +2625 4650 m +gs 1 -1 sc (1) col0 sh gr +/Times-Bold ff 433.33 scf sf +2625 4050 m +gs 1 -1 sc (2) col0 sh gr +/Times-Bold ff 433.33 scf sf +3525 5550 m +gs 1 -1 sc (1) col0 sh gr +/Times-Bold ff 433.33 scf sf +4125 5550 m +gs 1 -1 sc (2) col0 sh gr +/Times-Bold ff 433.33 scf sf +5250 5550 m +gs 1 -1 sc (4) col0 sh gr +/Times-Bold ff 433.33 scf sf +2625 2850 m +gs 1 -1 sc (4) col0 sh gr +/Times-Bold ff 433.33 scf sf +2700 2175 m +gs 1 -1 sc (j) col0 sh gr +/Times-Roman ff 433.33 scf sf +3825 1950 m +gs 1 -1 sc (i>=2) col0 sh gr +/Times-Roman ff 433.33 scf sf +5025 1950 m +gs 1 -1 sc (i<=4) col0 sh gr +/Times-Roman ff 433.33 scf sf +6075 3975 m +gs 1 -1 sc (j>=2) col0 sh gr +/Times-Roman ff 433.33 scf sf +6075 2775 m +gs 1 -1 sc (j<=4) col0 sh gr +/Times-Bold ff 433.33 scf sf +6000 5550 m +gs 1 -1 sc (i) col0 sh gr +% here ends figure; +$F2psEnd +rs +showpage +%%Trailer +%EOF diff --git a/doc/images/basic2.fig b/doc/images/basic2.fig new file mode 100644 index 0000000..c6a4161 --- /dev/null +++ b/doc/images/basic2.fig @@ -0,0 +1,62 @@ +#FIG 3.2 Produced by xfig version 3.2.5-alpha5 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 5400 3900 75 75 5400 3900 5400 3975 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 4800 3900 75 75 4800 3900 4800 3975 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 4200 3300 75 75 4200 3300 4200 3375 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 4800 3300 75 75 4800 3300 4800 3375 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 4200 2700 75 75 4200 2700 4200 2775 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 4200 3900 75 75 4200 3900 4200 3975 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 5400 3300 75 75 5400 3300 5400 3375 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 4800 2700 75 75 4800 2700 4800 2775 +1 3 2 1 0 0 50 -1 20 3.000 1 0.0000 5400 2700 75 75 5400 2700 5400 2775 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 120.00 180.00 + 3000 5100 6000 5100 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 120.00 180.00 + 3000 5100 3000 2100 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 3000 4500 2925 4500 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 3000 3900 2925 3900 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 3000 3300 2925 3300 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 3600 5100 3600 5175 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 4200 5100 4200 5175 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 5400 5100 5400 5175 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 4800 5100 4800 5175 +2 1 0 1 0 0 50 -1 20 3.000 0 0 -1 0 0 2 + 3000 2700 2925 2700 +2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 + 3000 3900 6000 3900 +2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 + 4200 5100 4200 2100 +2 3 0 0 0 7 51 -1 15 0.000 0 0 -1 0 0 5 + 4200 2700 4200 3900 5400 3900 5400 2700 4200 2700 +2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 + 5400 5175 5400 2100 +2 1 2 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 + 3000 2700 6000 2700 +4 0 0 50 -1 2 26 0.0000 0 285 225 2625 4650 1\001 +4 0 0 50 -1 2 26 0.0000 0 285 225 2625 4050 2\001 +4 0 0 50 -1 2 26 0.0000 0 285 225 3525 5550 1\001 +4 0 0 50 -1 2 26 0.0000 0 285 225 4125 5550 2\001 +4 0 0 50 -1 2 26 0.0000 0 285 225 5250 5550 4\001 +4 0 0 50 -1 2 26 0.0000 0 285 225 2625 2850 4\001 +4 0 0 50 -1 2 26 0.0000 0 375 150 2700 2175 j\001 +4 0 0 50 -1 0 26 0.0000 0 285 825 3825 1950 i>=2\001 +4 0 0 50 -1 0 26 0.0000 0 285 825 5025 1950 i<=4\001 +4 0 0 50 -1 0 26 0.0000 0 375 825 6075 3975 j>=2\001 +4 0 0 50 -1 0 26 0.0000 0 375 825 6075 2775 j<=4\001 +4 0 0 50 -1 2 26 0.0000 0 285 120 6000 5550 i\001 diff --git a/doc/images/basic2.jpg b/doc/images/basic2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ab9f0579d4e0490494ff9d912d2a3192717528a5 GIT binary patch literal 12369 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 D)78#a literal 0 HcwPel00001 diff --git a/doc/images/basic2.txt b/doc/images/basic2.txt new file mode 100644 index 0000000..1cbde89 --- /dev/null +++ b/doc/images/basic2.txt @@ -0,0 +1,10 @@ + j^ i>=2 + | | i<=4 + | | | +4-+-***--j<=4 + | *** +2-+-***--j>=2 + | | | +0-+-+-+--->i + | | | + 0 2 4 diff --git a/doc/images/tree.eps b/doc/images/tree.eps new file mode 100644 index 0000000..d80f6e9 --- /dev/null +++ b/doc/images/tree.eps @@ -0,0 +1,258 @@ +%!PS-Adobe-2.0 EPSF-2.0 +%%Title: tree.eps +%%Creator: fig2dev Version 3.2 Patchlevel 3c +%%CreationDate: Fri Sep 6 10:09:40 2002 +%%For: bastoul@whisky (Cedric Bastoul) +%%BoundingBox: 0 0 388 312 +%%Magnification: 1.0000 +%%EndComments +/$F2psDict 200 dict def +$F2psDict begin +$F2psDict /mtrx matrix put +/col-1 {0 setgray} bind def +/col0 {0.000 0.000 0.000 srgb} bind def +/col1 {0.000 0.000 1.000 srgb} bind def +/col2 {0.000 1.000 0.000 srgb} bind def +/col3 {0.000 1.000 1.000 srgb} bind def +/col4 {1.000 0.000 0.000 srgb} bind def +/col5 {1.000 0.000 1.000 srgb} bind def +/col6 {1.000 1.000 0.000 srgb} bind def +/col7 {1.000 1.000 1.000 srgb} bind def +/col8 {0.000 0.000 0.560 srgb} bind def +/col9 {0.000 0.000 0.690 srgb} bind def +/col10 {0.000 0.000 0.820 srgb} bind def +/col11 {0.530 0.810 1.000 srgb} bind def +/col12 {0.000 0.560 0.000 srgb} bind def +/col13 {0.000 0.690 0.000 srgb} bind def +/col14 {0.000 0.820 0.000 srgb} bind def +/col15 {0.000 0.560 0.560 srgb} bind def +/col16 {0.000 0.690 0.690 srgb} bind def +/col17 {0.000 0.820 0.820 srgb} bind def +/col18 {0.560 0.000 0.000 srgb} bind def +/col19 {0.690 0.000 0.000 srgb} bind def +/col20 {0.820 0.000 0.000 srgb} bind def +/col21 {0.560 0.000 0.560 srgb} bind def +/col22 {0.690 0.000 0.690 srgb} bind def +/col23 {0.820 0.000 0.820 srgb} bind def +/col24 {0.500 0.190 0.000 srgb} bind def +/col25 {0.630 0.250 0.000 srgb} bind def +/col26 {0.750 0.380 0.000 srgb} bind def +/col27 {1.000 0.500 0.500 srgb} bind def +/col28 {1.000 0.630 0.630 srgb} bind def +/col29 {1.000 0.750 0.750 srgb} bind def +/col30 {1.000 0.880 0.880 srgb} bind def +/col31 {1.000 0.840 0.000 srgb} bind def + +end +save +newpath 0 312 moveto 0 0 lineto 388 0 lineto 388 312 lineto closepath clip newpath +-165.0 369.0 translate +1 -1 scale + +/cp {closepath} bind def +/ef {eofill} bind def +/gr {grestore} bind def +/gs {gsave} bind def +/sa {save} bind def +/rs {restore} bind def +/l {lineto} bind def +/m {moveto} bind def +/rm {rmoveto} bind def +/n {newpath} bind def +/s {stroke} bind def +/sh {show} bind def +/slc {setlinecap} bind def +/slj {setlinejoin} bind def +/slw {setlinewidth} bind def +/srgb {setrgbcolor} bind def +/rot {rotate} bind def +/sc {scale} bind def +/sd {setdash} bind def +/ff {findfont} bind def +/sf {setfont} bind def +/scf {scalefont} bind def +/sw {stringwidth} bind def +/tr {translate} bind def +/tnt {dup dup currentrgbcolor + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add + 4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb} + bind def +/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul + 4 -2 roll mul srgb} bind def + /DrawEllipse { + /endangle exch def + /startangle exch def + /yrad exch def + /xrad exch def + /y exch def + /x exch def + /savematrix mtrx currentmatrix def + x y tr xrad yrad sc 0 0 1 startangle endangle arc + closepath + savematrix setmatrix + } def + +/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def +/$F2psEnd {$F2psEnteredState restore end} def + +$F2psBegin +%%Page: 1 1 +10 setmiterlimit + 0.06000 0.06000 sc +% +% Fig objects follow +% +7.500 slw +% Ellipse +n 5400 1200 237 237 0 360 DrawEllipse gs col0 s gr + +% Ellipse +n 3000 3600 237 237 0 360 DrawEllipse gs col0 s gr + +% Ellipse +n 7800 3600 237 237 0 360 DrawEllipse gs col0 s gr + +% Ellipse +n 6600 4800 237 237 0 360 DrawEllipse gs col0 s gr + +% Ellipse +n 5400 2325 237 237 0 360 DrawEllipse gs col0 s gr + +% Polyline +gs clippath +5355 2115 m 5445 2115 l 5445 1888 l 5400 2068 l 5355 1888 l cp +eoclip +n 5400 1425 m + 5400 2100 l gs col0 s gr gr + +% arrowhead +15.000 slw +n 5355 1888 m 5400 2068 l 5445 1888 l 5355 1888 l cp gs 0.00 setgray ef gr col0 s +% Polyline +7.500 slw +gs clippath +5355 3390 m 5445 3390 l 5445 3163 l 5400 3343 l 5355 3163 l cp +eoclip +n 5400 2550 m + 5400 3375 l gs col0 s gr gr + +% arrowhead +15.000 slw +n 5355 3163 m 5400 3343 l 5445 3163 l 5355 3163 l cp gs 0.00 setgray ef gr col0 s +% Polyline +7.500 slw +gs clippath +2955 4590 m 3045 4590 l 3045 4363 l 3000 4543 l 2955 4363 l cp +eoclip +n 3000 3825 m + 3000 4575 l gs col0 s gr gr + +% arrowhead +15.000 slw +n 2955 4363 m 3000 4543 l 3045 4363 l 2955 4363 l cp gs 0.00 setgray ef gr col0 s +% Polyline +7.500 slw +gs clippath +6563 4544 m 6611 4621 l 6803 4500 l 6627 4558 l 6755 4424 l cp +eoclip +n 7800 3825 m + 6600 4575 l gs col0 s gr gr + +% arrowhead +15.000 slw +n 6755 4424 m 6627 4558 l 6803 4500 l 6755 4424 l cp gs 0.00 setgray ef gr col0 s +% Polyline +7.500 slw +gs clippath +8988 4621 m 9036 4544 l 8844 4424 l 8973 4558 l 8796 4500 l cp +eoclip +n 7800 3825 m + 9000 4575 l gs col0 s gr gr + +% arrowhead +15.000 slw +n 8796 4500 m 8973 4558 l 8844 4424 l 8796 4500 l cp gs 0.00 setgray ef gr col0 s +% Polyline +7.500 slw +gs clippath +6555 5790 m 6645 5790 l 6645 5563 l 6600 5743 l 6555 5563 l cp +eoclip +n 6600 5025 m + 6600 5775 l gs col0 s gr gr + +% arrowhead +15.000 slw +n 6555 5563 m 6600 5743 l 6645 5563 l 6555 5563 l cp gs 0.00 setgray ef gr col0 s +% Polyline +7.500 slw +gs clippath +7802 3411 m 7831 3326 l 7615 3253 l 7772 3354 l 7587 3338 l cp +eoclip +n 5400 2550 m + 7803 3364 l gs col0 s gr gr + +% arrowhead +15.000 slw +n 7587 3338 m 7772 3354 l 7615 3253 l 7587 3338 l cp gs 0.00 setgray ef gr col0 s +% Polyline +7.500 slw +gs clippath +2971 3337 m 3000 3422 l 3215 3348 l 3031 3364 l 3186 3262 l cp +eoclip +n 5400 2550 m + 3000 3375 l gs col0 s gr gr + +% arrowhead +15.000 slw +n 3186 3262 m 3031 3364 l 3215 3348 l 3186 3262 l cp gs 0.00 setgray ef gr col0 s +/Times-Roman ff 330.00 scf sf +3075 4200 m +gs 1 -1 sc (0) col0 sh gr +/Times-Roman ff 330.00 scf sf +6675 5400 m +gs 1 -1 sc (0) col0 sh gr +/Times-Roman ff 330.00 scf sf +5475 3000 m +gs 1 -1 sc (1) col0 sh gr +/Times-Roman ff 330.00 scf sf +3825 3000 m +gs 1 -1 sc (0) col0 sh gr +/Times-Roman ff 330.00 scf sf +6900 3000 m +gs 1 -1 sc (2) col0 sh gr +/Times-Roman ff 330.00 scf sf +6975 4200 m +gs 1 -1 sc (0) col0 sh gr +/Times-Roman ff 330.00 scf sf +8475 4200 m +gs 1 -1 sc (1) col0 sh gr +/Times-Roman ff 330.00 scf sf +5475 1800 m +gs 1 -1 sc (0) col0 sh gr +/Times-Roman ff 330.00 scf sf +2850 4950 m +gs 1 -1 sc (S1) col0 sh gr +/Times-Roman ff 330.00 scf sf +5250 3750 m +gs 1 -1 sc (S2) col0 sh gr +/Times-Roman ff 330.00 scf sf +6450 6150 m +gs 1 -1 sc (S3) col0 sh gr +/Times-Roman ff 330.00 scf sf +8850 4950 m +gs 1 -1 sc (S4) col0 sh gr +/Times-Roman ff 330.00 scf sf +5355 2430 m +gs 1 -1 sc (i) col0 sh gr +/Times-Roman ff 330.00 scf sf +2963 3667 m +gs 1 -1 sc (j) col0 sh gr +/Times-Roman ff 330.00 scf sf +7763 3675 m +gs 1 -1 sc (j) col0 sh gr +/Times-Roman ff 330.00 scf sf +6533 4890 m +gs 1 -1 sc (k) col0 sh gr +$F2psEnd +rs diff --git a/doc/images/tree.fig b/doc/images/tree.fig new file mode 100644 index 0000000..9c202bb --- /dev/null +++ b/doc/images/tree.fig @@ -0,0 +1,54 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +1 3 0 1 0 7 50 0 -1 0.000 1 0.0000 5400 1200 237 237 5400 1200 5625 1275 +1 3 0 1 0 7 50 0 -1 0.000 1 0.0000 3000 3600 237 237 3000 3600 3225 3675 +1 3 0 1 0 7 50 0 -1 0.000 1 0.0000 7800 3600 237 237 7800 3600 8025 3675 +1 3 0 1 0 7 50 0 -1 0.000 1 0.0000 6600 4800 237 237 6600 4800 6825 4875 +1 3 0 1 0 7 50 0 -1 0.000 1 0.0000 5400 2325 237 237 5400 2325 5625 2400 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 90.00 180.00 + 5400 1425 5400 2100 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 90.00 180.00 + 5400 2550 5400 3375 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 90.00 180.00 + 3000 3825 3000 4575 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 90.00 180.00 + 7800 3825 6600 4575 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 90.00 180.00 + 7800 3825 9000 4575 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 90.00 180.00 + 6600 5025 6600 5775 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 90.00 180.00 + 5400 2550 7803 3364 +2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2 + 1 1 2.00 90.00 180.00 + 5400 2550 3000 3375 +4 0 0 50 0 0 22 0.0000 0 225 150 3075 4200 0\001 +4 0 0 50 0 0 22 0.0000 0 225 150 6675 5400 0\001 +4 0 0 50 0 0 22 0.0000 0 225 150 5475 3000 1\001 +4 0 0 50 0 0 22 0.0000 0 225 150 3825 3000 0\001 +4 0 0 50 0 0 22 0.0000 0 225 150 6900 3000 2\001 +4 0 0 50 0 0 22 0.0000 0 225 150 6975 4200 0\001 +4 0 0 50 0 0 22 0.0000 0 225 150 8475 4200 1\001 +4 0 0 50 0 0 22 0.0000 0 225 150 5475 1800 0\001 +4 0 0 50 0 0 22 0.0000 0 225 345 2850 4950 S1\001 +4 0 0 50 0 0 22 0.0000 0 225 345 5250 3750 S2\001 +4 0 0 50 0 0 22 0.0000 0 225 345 6450 6150 S3\001 +4 0 0 50 0 0 22 0.0000 0 225 345 8850 4950 S4\001 +4 0 0 50 0 0 22 0.0000 0 225 90 5355 2430 i\001 +4 0 0 50 0 0 22 0.0000 0 300 90 2963 3667 j\001 +4 0 0 50 0 0 22 0.0000 0 300 90 7763 3675 j\001 +4 0 0 50 0 0 22 0.0000 0 225 150 6533 4890 k\001 diff --git a/doc/images/tree.jpg b/doc/images/tree.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7329268b65736eafa7d05bbd39135092db60da2d GIT binary patch literal 13713 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 VCx7xMfAS}P@+W`td&F)h{|5s!X0`wT literal 0 HcwPel00001 diff --git a/doc/images/tree.pdf b/doc/images/tree.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7569edebb461590b8208c320a8e109fd4a44c25c GIT binary patch literal 4558 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 literal 0 HcwPel00001 diff --git a/doc/images/tree.txt b/doc/images/tree.txt new file mode 100644 index 0000000..7bcfef2 --- /dev/null +++ b/doc/images/tree.txt @@ -0,0 +1,25 @@ + * + | + |0 + | + V + i + | + +-----+-----+ + | | | + |0 |1 |2 + | | | + V V V + j S2 j + | | + |0 +--+--+ + | | | + V |0 |1 + S1 | | + V V + k S4 + | + |0 + | + V + S3 diff --git a/include/Makefile.am b/include/Makefile.am new file mode 100644 index 0000000..6fc4aec --- /dev/null +++ b/include/Makefile.am @@ -0,0 +1,56 @@ +# +# /**------- <| --------------------------------------------------------** +# ** A Clan/Scop ** +# **--- /.\ -----------------------------------------------------** +# ** <| [""M# makefile.am ** +# **- A | # -----------------------------------------------------** +# ** /.\ [""M# First version: 30/04/2008 ** +# **- [""M# | # U"U#U -----------------------------------------------** +# | # | # \ .:/ +# | # | #___| # +# ****** | "--' .-" ***************************************************** +# * |"-"-"-"-"-#-#-## Clan : the Chunky Loop Analyser (experimental) * +# **** | # ## ###### **************************************************** +# * \ .::::'/ * +# * \ ::::'/ Copyright (C) 2008 Cedric Bastoul * +# * :8a| # # ## * +# * ::88a ### This is free software; you can redistribute it * +# * ::::888a 8a ##::. and/or modify it under the terms of the GNU * +# * ::::::::888a88a[]::: Lesser General Public License as published by * +# *::8:::::::::SUNDOGa8a::. the Free Software Foundation, either version 2.1 * +# *::::::::8::::888:Y8888:: of the License, or (at your option)* +# *::::':::88::::888::Y88a::::::::::::... any later version. * +# *::'::.. . ..... .. ... . * +# * This software 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 General * +# * Public License for more details. * +# * * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with software; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * +# * * +# * Clan, the Chunky Loop Analyser * +# * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr * +# * * +# *****************************************************************************/ +# +# Makefile.am (or makefile if generated) of Clan, the Chunky Loop Analyser. +# Makefile.am is not a makefile, you must run the 'autogen.sh' THEN the +# configure shellscript to generate the Makefile thanks to this file. + + +############################################################################# +SUBDIRS = + +############################################################################# +MAINTAINERCLEANFILES = Makefile.in + +############################################################################# + +pkginclude_HEADERS = \ + scoplib/statement.h \ + scoplib/vector.h \ + scoplib/matrix.h \ + scoplib/macros.h \ + scoplib/scop.h diff --git a/include/scoplib/macros.h b/include/scoplib/macros.h new file mode 100644 index 0000000..b446d90 --- /dev/null +++ b/include/scoplib/macros.h @@ -0,0 +1,158 @@ + + /*+------- <| --------------------------------------------------------** + ** A Clan/Scop ** + **--- /.\ -----------------------------------------------------** + ** <| [""M# macros.h ** + **- A | # -----------------------------------------------------** + ** /.\ [""M# First version: 30/04/2008 ** + **- [""M# | # U"U#U -----------------------------------------------** + | # | # \ .:/ + | # | #___| # + ****** | "--' .-" ****************************************************** + * |"-"-"-"-"-#-#-## Clan : the Chunky Loop Analyzer (experimental) * + **** | # ## ###### ***************************************************** + * \ .::::'/ * + * \ ::::'/ Copyright (C) 2008 Cedric Bastoul * + * :8a| # # ## * + * ::88a ### This is free software; you can redistribute it * + * ::::888a 8a ##::. and/or modify it under the terms of the GNU Lesser * + * ::::::::888a88a[]::: General Public License as published by the Free * + *::8:::::::::SUNDOGa8a::. Software Foundation, either version 2.1 of the * + *::::::::8::::888:Y8888:: License, or (at your option) any later version. * + *::::':::88::::888::Y88a::::::::::::... * + *::'::.. . ..... .. ... . * + * This software 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 General Public License * + * for more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with software; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * * + * Clan, the Chunky Loop Analyzer * + * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr * + * * + ******************************************************************************/ + +#ifndef SCOPLIB_MACROS_H +# define SCOPLIB_MACROS_H + + +# if defined(SCOPLIB_INT_T_IS_LONGLONG) +# define SCOPLIB_FMT "%4lld" +# define SCOPLIB_FMT_TXT "%lld" +# define scoplib_int_t long long + +# elif defined(SCOPLIB_INT_T_IS_LONG) +# define SCOPLIB_FMT "%4ld" +# define SCOPLIB_FMT_TXT "%ld" +# define scoplib_int_t long int + +# elif defined(SCOPLIB_INT_T_IS_MP) /* GNUMP */ +#include +# define SCOPLIB_FMT "%4s" +# define SCOPLIB_FMT_TXT "%s" +# define scoplib_int_t mpz_t + +# else +# error Define SCOPLIB_INT_T_IS_xxx to use this file. + +# endif + +# define SCOPLIB_DEBUG 0 /* Set to 1 for debug mode, + 0 otherwise */ +# define SCOPLIB_MAX_STRING 2048 +# define SCOPLIB_TYPE_ITERATOR 1 +# define SCOPLIB_TYPE_PARAMETER 2 +# define SCOPLIB_TYPE_ARRAY 3 +# define SCOPLIB_TYPE_FUNCTION 4 +# define SCOPLIB_TYPE_DOMAIN 6 +# define SCOPLIB_TYPE_SCATTERING 7 +# define SCOPLIB_TYPE_ACCESS 8 +# define SCOPLIB_TYPE_UNKNOWN 9 +# define SCOPLIB_FAKE_ARRAY "fakearray" + +# define SCOPLIB_SCOP_PRINT_CASTLE 1 +# define SCOPLIB_SCOP_PRINT_ARRAYSTAG 2 + + +/*+**************************************************************************** + * SCOP GMP MACROS * + ******************************************************************************/ +# ifdef SCOPLIB_INT_T_IS_MP +/* Basic Macros */ +# define SCOPVAL_init(val) (mpz_init((val))) +# define SCOPVAL_assign(v1,v2) (mpz_set((v1),(v2))) +# define SCOPVAL_set_si(val,i) (mpz_set_si((val),(i))) +# define SCOPVAL_get_si(val) (mpz_get_si((val))) +# define SCOPVAL_init_set_si(val,i) (mpz_init_set_si((val),(i))) +# define SCOPVAL_clear(val) (mpz_clear((val))) +# define SCOPVAL_print(Dst,fmt,val) { char *str; \ + str = mpz_get_str(0,10,(val)); \ + fprintf((Dst),(fmt),str); free(str); \ + } +# define SCOPVAL_sprint(Dst,fmt,val) { char * str; \ + str = mpz_get_str(0,10,(val)); \ + sprintf((Dst),(fmt),str); free(str); \ + } + +/* Boolean operators on 'scoplib_int_t' */ +# define SCOPVAL_eq(v1,v2) (mpz_cmp((v1),(v2)) == 0) +# define SCOPVAL_ne(v1,v2) (mpz_cmp((v1),(v2)) != 0) + +/* Binary operators on 'scoplib_int_t' */ +# define SCOPVAL_increment(ref,val) (mpz_add_ui((ref),(val),1)) +# define SCOPVAL_addto(ref,val1,val2) (mpz_add((ref),(val1),(val2))) +# define SCOPVAL_multo(ref,val1,val2) (mpz_mul((ref),(val1),(val2))) +# define SCOPVAL_add_int(ref,val,vint) (mpz_add_ui((ref),(val),(long)(vint))) +# define SCOPVAL_subtract(ref,val1,val2) (mpz_sub((ref),(val1),(val2))) +# define SCOPVAL_oppose(ref,val) (mpz_neg((ref),(val))) + +/* Conditional operations on 'scoplib_int_t' */ +# define SCOPVAL_pos_p(val) (mpz_sgn(val) > 0) +# define SCOPVAL_neg_p(val) (mpz_sgn(val) < 0) +# define SCOPVAL_zero_p(val) (mpz_sgn(val) == 0) +# define SCOPVAL_notzero_p(val) (mpz_sgn(val) != 0) +# define SCOPVAL_one_p(val) (mpz_cmp_si(val,1) == 0) +# define SCOPVAL_mone_p(val) (mpz_cmp_si(val,-1) == 0) + +/*+**************************************************************************** + * SCOPVAL BASIC TYPES MACROS * + ******************************************************************************/ +# else +/* Basic Macros */ +# define SCOPVAL_init(val) ((val) = 0) +# define SCOPVAL_assign(v1,v2) ((v1) = (v2)) +# define SCOPVAL_set_si(val,i) ((val) = (scoplib_int_t)(i)) +# define SCOPVAL_get_si(val) ((val)) +# define SCOPVAL_init_set_si(val,i) ((val) = (scoplib_int_t)(i)) +# define SCOPVAL_clear(val) ((val) = 0) +# define SCOPVAL_print(Dst,fmt,val) (fprintf((Dst),(fmt),(val))) +# define SCOPVAL_sprint(Dst,fmt,val) (sprintf((Dst),(fmt),(val))) + +/* Boolean operators on 'scoplib_int_t' */ +# define SCOPVAL_eq(v1,v2) ((v1)==(v2)) +# define SCOPVAL_ne(v1,v2) ((v1)!=(v2)) +# define SCOPVAL_lt(v1,v2) ((v1)<(v2)) +# define SCOPVAL_gt(v1,v2) ((v1)>(v2)) + +/* Binary operators on 'scoplib_int_t' */ +# define SCOPVAL_increment(ref,val) ((ref) = (val)+(scoplib_int_t)(1)) +# define SCOPVAL_addto(ref,val1,val2) ((ref) = (val1)+(val2)) +# define SCOPVAL_multo(ref,val1,val2) ((ref) = (val1)*(val2)) +# define SCOPVAL_add_int(ref,val,vint) ((ref) = (val)+(scoplib_int_t)(vint)) +# define SCOPVAL_subtract(ref,val1,val2) ((ref) = (val1)-(val2)) +# define SCOPVAL_oppose(ref,val) ((ref) = (-(val))) + +/* Conditional operations on 'scoplib_int_t' */ +# define SCOPVAL_pos_p(val) SCOPVAL_gt(val,0) +# define SCOPVAL_neg_p(val) SCOPVAL_lt(val,0) +# define SCOPVAL_zero_p(val) SCOPVAL_eq(val,0) +# define SCOPVAL_notzero_p(val) SCOPVAL_ne(val,0) +# define SCOPVAL_one_p(val) SCOPVAL_eq(val,1) +# define SCOPVAL_mone_p(val) SCOPVAL_eq(val,-1) + +# endif + +#endif /* define SCOPLIB_MACROS_H */ diff --git a/include/scoplib/matrix.h b/include/scoplib/matrix.h new file mode 100644 index 0000000..54117c2 --- /dev/null +++ b/include/scoplib/matrix.h @@ -0,0 +1,148 @@ + + /*+------- <| --------------------------------------------------------** + ** A Clan/Scop ** + **--- /.\ -----------------------------------------------------** + ** <| [""M# matrix.h ** + **- A | # -----------------------------------------------------** + ** /.\ [""M# First version: 30/04/2008 ** + **- [""M# | # U"U#U -----------------------------------------------** + | # | # \ .:/ + | # | #___| # + ****** | "--' .-" ****************************************************** + * |"-"-"-"-"-#-#-## Clan : the Chunky Loop Analyzer (experimental) * + **** | # ## ###### ***************************************************** + * \ .::::'/ * + * \ ::::'/ Copyright (C) 2008 Cedric Bastoul * + * :8a| # # ## * + * ::88a ### This is free software; you can redistribute it * + * ::::888a 8a ##::. and/or modify it under the terms of the GNU Lesser * + * ::::::::888a88a[]::: General Public License as published by the Free * + *::8:::::::::SUNDOGa8a::. Software Foundation, either version 2.1 of the * + *::::::::8::::888:Y8888:: License, or (at your option) any later version. * + *::::':::88::::888::Y88a::::::::::::... * + *::'::.. . ..... .. ... . * + * This software 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 General Public License * + * for more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with software; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * * + * Clan, the Chunky Loop Analyzer * + * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr * + * * + ******************************************************************************/ + + +#ifndef SCOPLIB_MATRIX_H +# define SCOPLIB_MATRIX_H + +# include +# include +# include + + +# if defined(__cplusplus) +extern "C" + { +# endif + + +/** + * The scoplib_matrix_t structure stores a matrix information in the PolyLib + * format (the first entry of each row has a specific meaning). When a row + * describes a linear constraint, a 0 means it is an equality == 0, a 1 means + * an inequality >= 0. When a row describes an array access, a number different + * than 0 is the array identifier (the remainder of the row describes the + * access function of the first dimension of this array), otherwise it means + * the row describes access functions for next array dimensions. + */ +struct scoplib_matrix +{ + unsigned NbRows; /**< The number of rows */ + unsigned NbColumns; /**< The number of columns */ + scoplib_int_t ** p; /**< An array of pointers to the beginning + of each row */ + scoplib_int_t * p_Init;/**< The matrix is stored here, contiguously + in memory */ + int p_Init_size; /**< Needed to free the memory allocated by + mpz_init. */ +}; +typedef struct scoplib_matrix scoplib_matrix_t; +typedef struct scoplib_matrix * scoplib_matrix_p; + + +/** + * The scoplib_matrix_list_t structure describes a (chained) list of + * matrices. It is used to store the list of matrices for the + * iteration domain of a statement (possibly being a union of + * convex domains). + * + */ +struct scoplib_matrix_list +{ + scoplib_matrix_p elt; /**< An element of the list. */ + struct scoplib_matrix_list* next; /**< Pointer to the next element + of the list.*/ +}; +typedef struct scoplib_matrix_list scoplib_matrix_list_t; +typedef struct scoplib_matrix_list * scoplib_matrix_list_p; + + +/*+**************************************************************************** + * Structure display function * + ******************************************************************************/ +void scoplib_matrix_print_structure(FILE *, scoplib_matrix_p, int); +void scoplib_matrix_print(FILE *, scoplib_matrix_p); +void scoplib_matrix_print_dot_scop(FILE *, scoplib_matrix_p, int, + int, char **, int, char **, + int, char **); + +void scoplib_matrix_list_print_structure(FILE *, + scoplib_matrix_list_p, int); +void scoplib_matrix_list_print(FILE *, scoplib_matrix_list_p); +void scoplib_matrix_list_print_dot_scop(FILE *, scoplib_matrix_list_p, + int, int, char **, int, + char **, int, char **); + + +/****************************************************************************** + * Reading function * + ******************************************************************************/ +scoplib_matrix_p scoplib_matrix_read(FILE *); +scoplib_matrix_list_p scoplib_matrix_list_read(FILE *); +scoplib_matrix_p scoplib_matrix_read_arrays(FILE *, char ***, int *); + + +/*+**************************************************************************** + * Memory allocation/deallocation function * + ******************************************************************************/ +scoplib_matrix_p scoplib_matrix_malloc(unsigned, unsigned); +void scoplib_matrix_free_inside(scoplib_matrix_p); +void scoplib_matrix_free(scoplib_matrix_p); + +scoplib_matrix_list_p scoplib_matrix_list_malloc(); +void scoplib_matrix_list_free(scoplib_matrix_list_p); + + +/*+**************************************************************************** + * Processing functions * + ******************************************************************************/ +scoplib_matrix_p scoplib_matrix_ncopy(scoplib_matrix_p, int); +scoplib_matrix_p scoplib_matrix_copy(scoplib_matrix_p); +void scoplib_matrix_replace_vector(scoplib_matrix_p, scoplib_vector_p, int); +void scoplib_matrix_insert_vector(scoplib_matrix_p, scoplib_vector_p, int); +void scoplib_matrix_add_vector(scoplib_matrix_p, scoplib_vector_p, int); +void scoplib_matrix_sub_vector(scoplib_matrix_p, scoplib_vector_p, int); +scoplib_matrix_p scoplib_matrix_from_vector(scoplib_vector_p); +void scoplib_matrix_replace_matrix(scoplib_matrix_p, scoplib_matrix_p, int); +void scoplib_matrix_insert_matrix(scoplib_matrix_p, scoplib_matrix_p, int); +scoplib_matrix_p scoplib_matrix_concat(scoplib_matrix_p, scoplib_matrix_p); +int scoplib_matrix_equal(scoplib_matrix_p, scoplib_matrix_p); + +# if defined(__cplusplus) + } +# endif +#endif /* define SCOPLIB_MATRIX_H */ diff --git a/include/scoplib/scop.h.in b/include/scoplib/scop.h.in new file mode 100644 index 0000000..24fb6d2 --- /dev/null +++ b/include/scoplib/scop.h.in @@ -0,0 +1,119 @@ + + /*+------- <| --------------------------------------------------------** + ** A Clan/Scop ** + **--- /.\ -----------------------------------------------------** + ** <| [""M# scop.h ** + **- A | # -----------------------------------------------------** + ** /.\ [""M# First version: 30/04/2008 ** + **- [""M# | # U"U#U -----------------------------------------------** + | # | # \ .:/ + | # | #___| # + ****** | "--' .-" ****************************************************** + * |"-"-"-"-"-#-#-## Clan : the Chunky Loop Analyzer (experimental) * + **** | # ## ###### ***************************************************** + * \ .::::'/ * + * \ ::::'/ Copyright (C) 2008 Cedric Bastoul * + * :8a| # # ## * + * ::88a ### This is free software; you can redistribute it * + * ::::888a 8a ##::. and/or modify it under the terms of the GNU Lesser * + * ::::::::888a88a[]::: General Public License as published by the Free * + *::8:::::::::SUNDOGa8a::. Software Foundation, either version 2.1 of the * + *::::::::8::::888:Y8888:: License, or (at your option) any later version. * + *::::':::88::::888::Y88a::::::::::::... * + *::'::.. . ..... .. ... . * + * This software 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 General Public License * + * for more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with software; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * * + * Clan, the Chunky Loop Analyzer * + * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr * + * * + ******************************************************************************/ + + +/*+**************************************************************************** + * THIS FILE HAS BEEN AUTOMATICALLY GENERATED FROM scop.h.in BY configure * + ******************************************************************************/ + + +#ifndef SCOPLIB_SCOP_H +# define SCOPLIB_SCOP_H + +# include + +# define SCOPLIB_RELEASE "@PACKAGE_VERSION@" +# define SCOPLIB_VERSION "@BITS@" +# ifndef @SCOPLIB_INT_T@ +# define @SCOPLIB_INT_T@ +# endif + +# include +# include +# include +# include + + +# if defined(__cplusplus) +extern "C" + { +# endif + + +/** + * The scop_t structure stores the useful informations of a static + * control part of a program to process it within a polyhedral framework. + */ +struct scoplib_scop +{ + scoplib_matrix_p context; /**< Constraints on the SCoP parameters */ + int nb_parameters; /**< Number of parameters for the SCoP */ + char ** parameters; /**< Array of (nb_parameters) parameter names */ + int nb_arrays; /**< Number of arrays accessed in the SCoP */ + char ** arrays; /**< Array of (nb_arrays) array names */ + scoplib_statement_p statement;/**< Statement list of the SCoP */ + char* optiontags; /**< The content (as a 0 terminated + string) of the optional tags. */ + void* usr; /**< A user-defined field, not touched + by scop. */ +}; +typedef struct scoplib_scop scoplib_scop_t; +typedef struct scoplib_scop * scoplib_scop_p; + + +/*+**************************************************************************** + * Structure display function * + ******************************************************************************/ +void scoplib_scop_print_structure(FILE *, scoplib_scop_p, int); +void scoplib_scop_print(FILE *, scoplib_scop_p); +void scoplib_scop_print_dot_scop(FILE *, scoplib_scop_p); +void scoplib_scop_print_dot_scop_options(FILE * file, scoplib_scop_p scop, + int options); + + +/****************************************************************************** + * Reading function * + ******************************************************************************/ +scoplib_scop_p scoplib_scop_read(FILE *); +char* scoplib_scop_tag_content(scoplib_scop_p, char*, char*); +char* scoplib_scop_tag_content_from_string(char*, char*, char*); + + +/*+**************************************************************************** + * Memory allocation/deallocation function * + ******************************************************************************/ +scoplib_scop_p scoplib_scop_malloc(); +void scoplib_scop_free(scoplib_scop_p); +scoplib_scop_p scoplib_scop_dup(scoplib_scop_p); + + + +# if defined(__cplusplus) + } +# endif + +#endif /* define SCOPLIB_SCOP_H */ diff --git a/include/scoplib/statement.h b/include/scoplib/statement.h new file mode 100644 index 0000000..9e0a06f --- /dev/null +++ b/include/scoplib/statement.h @@ -0,0 +1,117 @@ + + /*+------- <| --------------------------------------------------------** + ** A Clan/Scop ** + **--- /.\ -----------------------------------------------------** + ** <| [""M# statement.h ** + **- A | # -----------------------------------------------------** + ** /.\ [""M# First version: 30/04/2008 ** + **- [""M# | # U"U#U -----------------------------------------------** + | # | # \ .:/ + | # | #___| # + ****** | "--' .-" ****************************************************** + * |"-"-"-"-"-#-#-## Clan : the Chunky Loop Analyzer (experimental) * + **** | # ## ###### ***************************************************** + * \ .::::'/ * + * \ ::::'/ Copyright (C) 2008 Cedric Bastoul * + * :8a| # # ## * + * ::88a ### This is free software; you can redistribute it * + * ::::888a 8a ##::. and/or modify it under the terms of the GNU Lesser * + * ::::::::888a88a[]::: General Public License as published by the Free * + *::8:::::::::SUNDOGa8a::. Software Foundation, either version 2.1 of the * + *::::::::8::::888:Y8888:: License, or (at your option) any later version. * + *::::':::88::::888::Y88a::::::::::::... * + *::'::.. . ..... .. ... . * + * This software 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 General Public License * + * for more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with software; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * * + * Clan, the Chunky Loop Analyzer * + * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr * + * * + ******************************************************************************/ + + +#ifndef SCOPLIB_STATEMENT_H +# define SCOPLIB_STATEMENT_H + +# include +# include +# include + +# if defined(__cplusplus) +extern "C" + { +# endif + + +/** + * The scoplib_statement_t structure stores the useful informations of a given + * statement to process it within a polyhedral framework. + */ +struct scoplib_statement +{ + scoplib_matrix_list_p domain; /**< Iteration domain of the statement */ + scoplib_matrix_p schedule; /**< Scheduling function for the statement */ + scoplib_matrix_p read; /**< Array read access informations */ + scoplib_matrix_p write; /**< Array write access informations */ + int nb_iterators; /**< Original depth of the statement */ + char ** iterators; /**< Array of (nb_iterators) iterator names */ + char * body; /**< Original statement body */ + + + /** Support for non-static code analysis (See Benabderrahmane's + Research Report #6814). */ + int nb_exit_predicates; + char ** exit_predicates; /**< Array of exit predicats of all + while loops of the statement */ + int nb_control_predicates; + char ** control_predicates; /**< Array of control predicats of all + irregular if of a statement */ + + + struct scoplib_statement * next;/**< Next statement in the linked list */ +}; +typedef struct scoplib_statement scoplib_statement_t; +typedef struct scoplib_statement * scoplib_statement_p; + + +/*+**************************************************************************** + * Structure display function * + ******************************************************************************/ +void scoplib_statement_print_structure(FILE *, scoplib_statement_p, + int); +void scoplib_statement_print(FILE *, scoplib_statement_p); +void scoplib_statement_print_dot_scop(FILE *, scoplib_statement_p, + int, char **, int, char **); + + +/****************************************************************************** + * Reading function * + ******************************************************************************/ +scoplib_statement_p scoplib_statement_read (FILE*, int, char***, int*); + + +/*+**************************************************************************** + * Memory allocation/deallocation function * + ******************************************************************************/ +scoplib_statement_p scoplib_statement_malloc(); +void scoplib_statement_free(scoplib_statement_p); + + +/*+**************************************************************************** + * Processing functions * + ******************************************************************************/ +void scoplib_statement_add(scoplib_statement_p *, scoplib_statement_p); +void scoplib_statement_compact(scoplib_statement_p, int); +int scoplib_statement_number(scoplib_statement_p); + + +# if defined(__cplusplus) + } +# endif +#endif /* define SCOPLIB_STATEMENT_H */ diff --git a/include/scoplib/vector.h b/include/scoplib/vector.h new file mode 100644 index 0000000..2b8ab43 --- /dev/null +++ b/include/scoplib/vector.h @@ -0,0 +1,94 @@ + + /*+------- <| --------------------------------------------------------** + ** A Clan/Scop ** + **--- /.\ -----------------------------------------------------** + ** <| [""M# vector.h ** + **- A | # -----------------------------------------------------** + ** /.\ [""M# First version: 01/05/2008 ** + **- [""M# | # U"U#U -----------------------------------------------** + | # | # \ .:/ + | # | #___| # + ****** | "--' .-" ****************************************************** + * |"-"-"-"-"-#-#-## Clan : the Chunky Loop Analyzer (experimental) * + **** | # ## ###### ***************************************************** + * \ .::::'/ * + * \ ::::'/ Copyright (C) 2008 Cedric Bastoul * + * :8a| # # ## * + * ::88a ### This is free software; you can redistribute it * + * ::::888a 8a ##::. and/or modify it under the terms of the GNU Lesser * + * ::::::::888a88a[]::: General Public License as published by the Free * + *::8:::::::::SUNDOGa8a::. Software Foundation, either version 2.1 of the * + *::::::::8::::888:Y8888:: License, or (at your option) any later version. * + *::::':::88::::888::Y88a::::::::::::... * + *::'::.. . ..... .. ... . * + * This software 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 General Public License * + * for more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with software; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * * + * Clan, the Chunky Loop Analyzer * + * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr * + * * + ******************************************************************************/ + + +#ifndef SCOPLIB_VECTOR_H +# define SCOPLIB_VECTOR_H + +# include +# include + + +# if defined(__cplusplus) +extern "C" + { +# endif + + +/** + * The scoplib_vector_t structure stores a vector information in the PolyLib + * format (the first entry has a specific meaning). When a vector + * describes a linear constraint, a 0 means it is an equality == 0, a 1 means + * an inequality >= 0. When the vector describes an array access, a number + * different than 0 is the array identifier. + */ +struct scoplib_vector +{ + unsigned Size; /**< The number of vector entries */ + scoplib_int_t * p; /**< An array of values */ +}; +typedef struct scoplib_vector scoplib_vector_t; +typedef struct scoplib_vector * scoplib_vector_p; + + +/*+**************************************************************************** + * Structure display function * + ******************************************************************************/ +void scoplib_vector_print_structure(FILE *, scoplib_vector_p, int); +void scoplib_vector_print(FILE *, scoplib_vector_p); + + +/*+**************************************************************************** + * Memory allocation/deallocation function * + ******************************************************************************/ +scoplib_vector_p scoplib_vector_malloc(unsigned); +void scoplib_vector_free(scoplib_vector_p); + + +/*+**************************************************************************** + * Processing functions * + ******************************************************************************/ +scoplib_vector_p scoplib_vector_add_scalar(scoplib_vector_p, int); +scoplib_vector_p scoplib_vector_add(scoplib_vector_p, scoplib_vector_p); +scoplib_vector_p scoplib_vector_sub(scoplib_vector_p, scoplib_vector_p); +void scoplib_vector_tag_inequality(scoplib_vector_p); +void scoplib_vector_tag_equality(scoplib_vector_p); + +# if defined(__cplusplus) + } +# endif +#endif /* define SCOPLIB_VECTOR_H */ diff --git a/source/Makefile.am b/source/Makefile.am new file mode 100644 index 0000000..9a3fe5a --- /dev/null +++ b/source/Makefile.am @@ -0,0 +1,65 @@ +# +# /**------- <| --------------------------------------------------------** +# ** A Clan/Scop ** +# **--- /.\ -----------------------------------------------------** +# ** <| [""M# makefile.am ** +# **- A | # -----------------------------------------------------** +# ** /.\ [""M# First version: 30/04/2008 ** +# **- [""M# | # U"U#U -----------------------------------------------** +# | # | # \ .:/ +# | # | #___| # +# ****** | "--' .-" ***************************************************** +# * |"-"-"-"-"-#-#-## Clan : the Chunky Loop Analyser (experimental) * +# **** | # ## ###### **************************************************** +# * \ .::::'/ * +# * \ ::::'/ Copyright (C) 2008 Cedric Bastoul * +# * :8a| # # ## * +# * ::88a ### This is free software; you can redistribute it * +# * ::::888a 8a ##::. and/or modify it under the terms of the GNU * +# * ::::::::888a88a[]::: Lesser General Public License as published by * +# *::8:::::::::SUNDOGa8a::. the Free Software Foundation, either version 2.1 * +# *::::::::8::::888:Y8888:: of the License, or (at your option)* +# *::::':::88::::888::Y88a::::::::::::... any later version. * +# *::'::.. . ..... .. ... . * +# * This software 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 General * +# * Public License for more details. * +# * * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with software; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * +# * * +# * Clan, the Chunky Loop Analyser * +# * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr * +# * * +# *****************************************************************************/ +# +# Makefile.am (or makefile if generated) of Clan, the Chunky Loop Analyser. +# Makefile.am is not a makefile, you must run the 'autogen.sh' THEN the +# configure shellscript to generate the Makefile thanks to this file. + + + +############################################################################# +SUBDIRS = + +############################################################################# +MAINTAINERCLEANFILES = Makefile.in + +INCLUDES = -I$(top_builddir) -I$(top_srcdir) \ + -I$(top_builddir)/include \ + -I$(top_srcdir)/include + +############################################################################# + +lib_LTLIBRARIES = libscoplib.la + + +libscoplib_la_SOURCES = \ + scop.c \ + statement.c \ + matrix.c \ + vector.c + +AM_CFLAGS = -Wall -fomit-frame-pointer -g diff --git a/source/matrix.c b/source/matrix.c new file mode 100644 index 0000000..19377aa --- /dev/null +++ b/source/matrix.c @@ -0,0 +1,1198 @@ + + /*+------- <| --------------------------------------------------------** + ** A Clan/Scop ** + **--- /.\ -----------------------------------------------------** + ** <| [""M# matrix.c ** + **- A | # -----------------------------------------------------** + ** /.\ [""M# First version: 30/04/2008 ** + **- [""M# | # U"U#U -----------------------------------------------** + | # | # \ .:/ + | # | #___| # + ****** | "--' .-" ****************************************************** + * |"-"-"-"-"-#-#-## Clan : the Chunky Loop Analyzer (experimental) * + **** | # ## ###### ***************************************************** + * \ .::::'/ * + * \ ::::'/ Copyright (C) 2008 Cedric Bastoul * + * :8a| # # ## * + * ::88a ### This is free software; you can redistribute it * + * ::::888a 8a ##::. and/or modify it under the terms of the GNU Lesser * + * ::::::::888a88a[]::: General Public License as published by the Free * + *::8:::::::::SUNDOGa8a::. Software Foundation, either version 2.1 of the * + *::::::::8::::888:Y8888:: License, or (at your option) any later version. * + *::::':::88::::888::Y88a::::::::::::... * + *::'::.. . ..... .. ... . * + * This software 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 General Public License * + * for more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with software; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * * + * Clan, the Chunky Loop Analyzer * + * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr * + * * + ******************************************************************************/ + + +# include +# include +# include +# include +# include + + +/*+**************************************************************************** + * Structure display function * + ******************************************************************************/ + + +/** + * scoplib_matrix_print_structure function: + * Displays a scoplib_matrix_t structure (*matrix) into a file (file, possibly + * stdout) in a way that trends to be understandable without falling in a deep + * depression or, for the lucky ones, getting a headache... It includes an + * indentation level (level) in order to work with others print_structure + * functions. + * \param file File where informations are printed. + * \param matrix The matrix whose information have to be printed. + * \param level Number of spaces before printing, for each line. + ** + * - 30/04/2008: first version (from CLooG 0.14.0). + */ +void +scoplib_matrix_print_structure(FILE * file, scoplib_matrix_p matrix, int level) +{ + int i, j; + + /* Go to the right level. */ + for (j = 0; j < level; j++) + fprintf(file,"|\t"); + + if (matrix != NULL) + { + fprintf(file,"+-- scoplib_matrix_t\n"); + + for(j = 0; j <= level; j++) + fprintf(file,"|\t"); + fprintf(file,"%d %d\n",matrix->NbRows,matrix->NbColumns); + + /* Display the matrix. */ + for (i = 0; i < matrix->NbRows; i++) + { + for (j = 0; j <= level; j++) + fprintf(file,"|\t"); + + fprintf(file,"[ "); + + for (j = 0; j < matrix->NbColumns; j++) + { + SCOPVAL_print(file,SCOPLIB_FMT,matrix->p[i][j]); + fprintf(file," "); + } + + fprintf(file,"]\n"); + } + } + else + fprintf(file,"+-- NULL matrix\n"); + + /* The last line. */ + for (j = 0; j <= level; j++) + fprintf(file,"|\t"); + fprintf(file,"\n"); +} + + +/** + * scoplib_matrix_print function: + * This function prints the content of a scoplib_matrix_t structure + * (*matrix) into a file (file, possibly stdout). + * \param file File where informations are printed. + * \param matrix The matrix whose information have to be printed. + ** + * - 30/04/2008: first version (from CLooG 0.14.0). + */ +void +scoplib_matrix_print(FILE * file, scoplib_matrix_p matrix) +{ + scoplib_matrix_print_structure(file,matrix,0); +} + + + +/** + * scoplib_matrix_expression_element function: + * This function returns a string containing the printing of a value (possibly + * an iterator or a parameter with its coefficient or a constant). + * \param val The coefficient or constant value. + * \param first Pointer to a boolean set to 1 if the current value is the first + * of an expresion, 0 otherwise (this function may update it). + * \param cst A boolean set to 1 if the value is a constant, 0 otherwise. + * \param name String containing the name of the iterator or of the parameter. + ** + * - 03/05/2008: first version (from CLooG 0.14.0, glorious pprint_val). + */ +static +char * +scoplib_matrix_expression_element(scoplib_int_t val, int * first, int cst, + char * name) +{ + char * sval, * body, * temp; + + temp = (char *)malloc(SCOPLIB_MAX_STRING * sizeof(char)); + body = (char *)malloc(SCOPLIB_MAX_STRING * sizeof(char)); + sval = (char *)malloc(SCOPLIB_MAX_STRING * sizeof(char)); + body[0] = '\0'; + sval[0] = '\0'; + + /* statements for the 'normal' processing. */ + if (SCOPVAL_notzero_p(val) && (!cst)) + { + if ((*first) || SCOPVAL_neg_p(val)) + { + if (SCOPVAL_one_p(val)) /* case 1 */ + sprintf(sval,"%s",name); + else + { + if (SCOPVAL_mone_p(val)) /* case -1 */ + sprintf(sval,"-%s",name); + else /* default case */ + { + SCOPVAL_sprint(sval,SCOPLIB_FMT_TXT,val); + sprintf(temp,"*%s",name); + strcat(sval,temp); + } + } + *first = 0; + } + else + { + if (SCOPVAL_one_p(val)) + sprintf(sval,"+%s",name); + else + { + sprintf(sval,"+"); + SCOPVAL_sprint(temp,SCOPLIB_FMT_TXT,val); + strcat(sval,temp); + sprintf(temp,"*%s",name); + strcat(sval,temp); + } + } + } + else + { + if (cst) + { + if ((SCOPVAL_zero_p(val) && (*first)) || SCOPVAL_neg_p(val)) + SCOPVAL_sprint(sval,SCOPLIB_FMT_TXT,val); + if (SCOPVAL_pos_p(val)) + { + if (!(*first)) + { + SCOPVAL_sprint(sval,"+"SCOPLIB_FMT_TXT,val); /* Block macro ! */ + } + else + SCOPVAL_sprint(sval,SCOPLIB_FMT_TXT,val); + } + } + } + free(temp); + free(body); + + return(sval); +} + + +/** + * scoplib_matrix_expression function: + * This function returns a string corresponding to an affine expression + * stored at the "row"^th row of the matrix pointed by "matrix". + * \param matrix A set of linear expressions. + * \param row The row of the matrix corresponding to the expression. + * \param nb_iterators The number of iterators for the considered statement. + * \param iterators An array containing iterator names for the statement. + * \param nb_parameters The number of parameters in the SCoP. + * \param parameters An array containing all parameters names. + ** + * - 03/05/2008: first version (from CLooG 0.14.0, glorious pprint_val). + */ +static +char * +scoplib_matrix_expression(scoplib_matrix_p matrix, int row, + int nb_iterators, char ** iterators, + int nb_parameters, char ** parameters) +{ + int i, first = 1; + char * sline, * sval; + + sline = (char *)malloc(SCOPLIB_MAX_STRING * sizeof(char)) ; + sline[0] = '\0' ; + + /* First the iterator part. */ + for (i = 1; i <= nb_iterators; i++) + { + sval = scoplib_matrix_expression_element(matrix->p[row][i],&first,0, + iterators[i-1]); + strcat(sline,sval); + free(sval); + } + + /* Next the parameter part. */ + for (i = nb_iterators + 1; i <= nb_iterators + nb_parameters; i++) + { + sval = scoplib_matrix_expression_element(matrix->p[row][i],&first,0, + parameters[i - nb_iterators - 1]); + strcat(sline,sval); + free(sval); + } + + /* Finally the constant part (yes, I reused it). */ + sval = scoplib_matrix_expression_element(matrix->p[row][i],&first,1,NULL); + strcat(sline,sval); + free(sval); + + return sline; +} + + +/** + * scoplib_matrix_print_dot_scop function: + * This function prints the content of a scoplib_matrix_t structure + * (*matrix) into a file (file, possibly stdout) for the .scop format. + * \param file File where informations are printed. + * \param matrix The matrix whose information have to be printed. + * \param type A bit of semantic about this matrix (domain, access...). + * \param nb_iterators The number of iterators for the considered statement. + * \param iterators An array containing iterator names for the statement. + * \param nb_parameters The number of parameters in the SCoP. + * \param parameters An array containing all parameters names. + * \param nb_arrays The number of arrays accessed in the SCoP. + * \param arrays An array containing all accessed array names. + ** + * - 02/05/2008: first version. + */ +void +scoplib_matrix_print_dot_scop(FILE * file, scoplib_matrix_p matrix, int type, + int nb_iterators, char ** iterators, + int nb_parameters, char ** parameters, + int nb_arrays, char ** arrays) +{ + int i, j, k; + char * expression; + + if (matrix == NULL) + { + fprintf(file,"0 %d\n",nb_iterators+nb_parameters+2); + return; + } + + fprintf(file,"%d %d\n",matrix->NbRows,matrix->NbColumns); + + for (i = 0; i < matrix->NbRows; i++) + { + for (j = 0; j < matrix->NbColumns; j++) + { + SCOPVAL_print(file,SCOPLIB_FMT,matrix->p[i][j]); + fprintf(file," "); + } + + if (type == SCOPLIB_TYPE_DOMAIN) + { + expression = scoplib_matrix_expression(matrix,i,nb_iterators,iterators, + nb_parameters,parameters); + fprintf(file," ## %s",expression); + free(expression); + if (SCOPVAL_zero_p(matrix->p[i][0])) + fprintf(file," == 0"); + else + fprintf(file," >= 0"); + } + + if (type == SCOPLIB_TYPE_SCATTERING) + { + expression = scoplib_matrix_expression(matrix,i,nb_iterators,iterators, + nb_parameters,parameters); + fprintf(file," ## %s",expression); + free(expression); + } + + if (type == SCOPLIB_TYPE_ACCESS) + { + if (SCOPVAL_notzero_p(matrix->p[i][0])) + { + if (strncmp(arrays[SCOPVAL_get_si(matrix->p[i][0]) - 1], + SCOPLIB_FAKE_ARRAY, strlen(SCOPLIB_FAKE_ARRAY))) + fprintf(file," ## %s",arrays[SCOPVAL_get_si(matrix->p[i][0]) - 1]); + k = i; + do + { + expression = scoplib_matrix_expression(matrix,k,nb_iterators, + iterators, + nb_parameters,parameters); + fprintf(file,"[%s]",expression); + free(expression); + k++; + } + while ((k < matrix->NbRows) && SCOPVAL_zero_p(matrix->p[k][0])); + } + else + fprintf(file," ##"); + } + + fprintf(file,"\n"); + } +} + + +/** + * scoplib_matrix_list_print_structure function: + * Displays a scoplib_matrix_list_t structure (a list of matrices) into a + * file (file, possibly stdout). See scoplib_matrix_print_structure for + * more details. + * \param file File where informations are printed. + * \param l The list of matrices whose information have to be printed. + * \param level Number of spaces before printing, for each line. + */ +void +scoplib_matrix_list_print_structure(FILE * file, scoplib_matrix_list_p l, + int level) +{ + int j, first = 1; + + /* Go to the right level. */ + for (j = 0; j < level; j++) + fprintf(file,"|\t"); + + if (l != NULL) + fprintf(file,"+-- scoplib_matrix_list_t\n"); + else + fprintf(file,"+-- NULL matrix list\n"); + + while (l != NULL) + { + if (!first) + { + /* Go to the right level. */ + for (j = 0; j < level; j++) + fprintf(file,"|\t"); + fprintf(file,"| scoplib_matrix_list_t\n"); + } + else + first = 0; + + /* A blank line. */ + for (j = 0; j <= level+1; j++) + fprintf(file,"|\t"); + fprintf(file,"\n"); + + /* Print a matrix. */ + scoplib_matrix_print_structure(file,l->elt,level+1); + + l = l->next; + + /* Next line. */ + if (l != NULL) + { + for (j = 0; j <= level; j++) + fprintf(file,"|\t"); + fprintf(file,"V\n"); + } + } + + /* The last line. */ + for (j = 0; j <= level; j++) + fprintf(file,"|\t"); + fprintf(file,"\n"); +} + + +/** + * scoplib_matrix_list_print function: + * This function prints the content of a scoplib_matrix_list_t into + * a file (file, possibly stdout). + * \param file File where informations are printed. + * \param list The matrix whose information have to be printed. + ** + * - 30/04/2008: first version (from CLooG 0.14.0). + */ +void +scoplib_matrix_list_print(FILE * file, scoplib_matrix_list_p list) +{ + scoplib_matrix_list_print_structure(file, list, 0); +} + + +/** + * scoplib_matrix_list_print_dot_scop function: + * This function prints the content of a scoplib_matrix_list_t structure into + * a file (file, possibly stdout) for the .scop format. + * \param file File where informations are printed. + * \param list The matrix list whose information have to be printed. + * \param type A bit of semantic about this matrix (domain, access...). + * \param nb_iterators The number of iterators for the considered statement. + * \param iterators An array containing iterator names for the statement. + * \param nb_parameters The number of parameters in the SCoP. + * \param parameters An array containing all parameters names. + * \param nb_arrays The number of arrays accessed in the SCoP. + * \param arrays An array containing all accessed array names. + */ +void +scoplib_matrix_list_print_dot_scop(FILE * file, scoplib_matrix_list_p list, + int type, + int nb_iterators, char ** iterators, + int nb_parameters, char ** parameters, + int nb_arrays, char ** arrays) +{ + int i; + scoplib_matrix_list_p head = list; + + /* Count the number of elements in the list. */ + for (i = 0; list; list = list->next, i++) + ; + /* Print it. */ + fprintf(file,"%d\n", i); + /* Print each element of the matrix list. */ + while (head) + { + scoplib_matrix_print_dot_scop(file, head->elt, type, + nb_iterators, iterators, + nb_parameters, parameters, + nb_arrays, arrays); + head = head->next; + } +} + + +/****************************************************************************** + * Reading function * + ******************************************************************************/ + + +/** + * scoplib_matrix_read function: + * Adaptation from the PolyLib. This function reads a matrix into a file (foo, + * posibly stdin) and returns a pointer this matrix. + * October 18th 2001: first version. + * - April 17th 2005: this function moved from domain.c to here. + * - June 21rd 2005: Adaptation for GMP (based on S. Verdoolaege's version of + * CLooG 0.12.1). + * - July 9th 2008: Grabbed from CLooG and adapted for Scoplib. + */ +scoplib_matrix_p +scoplib_matrix_read(FILE* foo) +{ + unsigned NbRows, NbColumns; + int i, j, n; + char* c, s[SCOPLIB_MAX_STRING], str[SCOPLIB_MAX_STRING]; + scoplib_matrix_p matrix; + scoplib_int_t* p; + + while (fgets(s, SCOPLIB_MAX_STRING, foo) == 0) + ; + while ((*s=='#' || *s=='\n') || + (sscanf(s, " %u %u", &NbRows, &NbColumns) < 2)) + fgets(s, SCOPLIB_MAX_STRING, foo); + + matrix = scoplib_matrix_malloc(NbRows, NbColumns); + + p = matrix->p_Init; + for (i = 0; i < matrix->NbRows; i++) + { + do + { + c = fgets(s, SCOPLIB_MAX_STRING, foo); + while ((c != NULL) && isspace(*c) && (*c != '\n')) + c++; + } + while (c != NULL && (*c == '#' || *c == '\n')); + + if (c == NULL) + { + fprintf(stderr, "[Scoplib] Error: not enough rows\n"); + exit(1); + } + for (j = 0; j < matrix->NbColumns; j++) + { + if (c == NULL || *c == '#' || *c == '\n') + { + fprintf(stderr, "[Scoplib] Error: not enough columns\n"); + exit(1); + } + if (sscanf(c, "%s%n", str, &n) == 0) + { + fprintf(stderr, "[Scoplib] Error: not enough rows\n"); + exit(1); + } +#if defined(SCOPLIB_INT_T_IS_MP) + long long val; + sscanf(str, "%lld", &val); + mpz_set_si(*p++, val); +#else + sscanf(str, SCOPLIB_FMT_TXT, p++); +#endif + c += n; + } + } + + return matrix; +} + + +/** + * scoplib_matrix_list_read function: + * This function reads a list of matrices into a file (foo, + * posibly stdin) and returns a pointer this matrix list. + * \param file File where informations are stored. + */ +scoplib_matrix_list_p +scoplib_matrix_list_read(FILE* file) +{ + char s[SCOPLIB_MAX_STRING]; + int i; + scoplib_matrix_list_p list; + scoplib_matrix_list_p res; + int nb_mat; + + /* Skip blank/commented lines. */ + while (fgets(s, SCOPLIB_MAX_STRING, file) == 0 || s[0] == '#' || + isspace(s[0])) + ; + /* Read the number of matrices to read. */ + sscanf(s, "%d", &nb_mat); + + /* Allocate the header of the list. */ + res = list = scoplib_matrix_list_malloc(); + for (i = 0; i < nb_mat; ++i) + { + list->elt = scoplib_matrix_read(file); + if (i < nb_mat - 1) + list->next = scoplib_matrix_list_malloc(); + list = list->next; + } + + return res; +} + + +/** + * scoplib_matrix_read_arrays function: + * This function reads a matrix into a file (foo, posibly stdin) and + * returns a pointer this matrix. In addition, it reads the arrays as + * comments at the end of the line. + */ +scoplib_matrix_p +scoplib_matrix_read_arrays(FILE* foo, char*** arrays, int* nb_arr) +{ + unsigned NbRows, NbColumns; + int i, j, n; + int count; + char* c, s[SCOPLIB_MAX_STRING], str[SCOPLIB_MAX_STRING], + buff[SCOPLIB_MAX_STRING]; + scoplib_matrix_p matrix; + scoplib_int_t* p; + + while (fgets(s, SCOPLIB_MAX_STRING, foo) == 0) + ; + while ((*s=='#' || *s=='\n') || + (sscanf(s, " %u %u", &NbRows, &NbColumns) < 2)) + fgets(s, SCOPLIB_MAX_STRING, foo); + + matrix = scoplib_matrix_malloc(NbRows, NbColumns); + + p = matrix->p_Init; + for (i = 0; i < matrix->NbRows; i++) + { + do + { + c = fgets(s, SCOPLIB_MAX_STRING, foo); + while ((c != NULL) && isspace(*c) && (*c != '\n')) + c++; + } + while (c != NULL && (*c == '#' || *c == '\n')); + + if (c == NULL) + { + fprintf(stderr, "[Scoplib] Error: not enough rows\n"); + exit(1); + } + + for (j = 0; j < matrix->NbColumns; j++) + { + if (c == NULL || *c == '#' || *c == '\n') + { + fprintf(stderr, "[Scoplib] Error: not enough columns\n"); + exit(1); + } + if (sscanf(c, "%s%n", str, &n) == 0) + { + fprintf(stderr, "[Scoplib] Error: not enough rows\n"); + exit(1); + } +#if defined(SCOPLIB_INT_T_IS_MP) + long long val; + sscanf(str, "%lld", &val); + mpz_set_si(*p++, val); +#else + sscanf(str, SCOPLIB_FMT_TXT, p++); +#endif + c += n; + } + /* Read the array, passed as a comment at the end of the line. */ + if (c) + { + while (c && (isspace(*c) || *c == '#')) + ++c; + for (count = 0; c && *c != '[' && *c != '\n'; ++count) + buff[count] = *(c++); + buff[count] = '\0'; + if (count && SCOPVAL_get_si(matrix->p[i][0])) + { + /* Increase the buffer size if we run out of space. */ + if (SCOPVAL_get_si(matrix->p[i][0]) - 1 > *nb_arr) + { + *nb_arr = SCOPVAL_get_si(matrix->p[i][0]) - 1; + *arrays = (char**) realloc(*arrays, + sizeof(char*) * (*nb_arr + 1)); + } + /* Backup the array name. */ + (*arrays)[SCOPVAL_get_si(matrix->p[i][0]) - 1] = strdup(buff); + } + } + } + + return matrix; +} + + +/*+**************************************************************************** + * Memory allocation/deallocation function * + ******************************************************************************/ + +/** + * scoplib_matrix_malloc function: + * This function allocates the memory space for a scoplib_matrix_t structure and + * sets its fields with default values. Then it returns a pointer to the + * allocated space. + * \param NbRows The number of row of the matrix to allocate. + * \param NbColumns The number of columns of the matrix to allocate. + ** + * - 30/04/2008: first version (from PipLib 1.4.0). + */ +scoplib_matrix_p +scoplib_matrix_malloc(unsigned NbRows, unsigned NbColumns) +{ + scoplib_matrix_p matrix; + scoplib_int_t ** p, * q; + int i, j; + + matrix = (scoplib_matrix_p)malloc(sizeof(scoplib_matrix_t)); + if (matrix == NULL) + { + fprintf(stderr, "[Scoplib] Memory Overflow.\n"); + exit(1); + } + matrix->NbRows = NbRows; + matrix->NbColumns = NbColumns; + matrix->p_Init_size = NbRows * NbColumns; + if (matrix->p_Init_size == 0) + { + matrix->p = NULL; + matrix->p_Init = NULL; + } + else + { + p = (scoplib_int_t **)malloc(NbRows*sizeof(scoplib_int_t *)); + if (p == NULL) + { + fprintf(stderr, "[Scoplib] Memory Overflow.\n"); + exit(1); + } + q = (scoplib_int_t *)malloc(NbRows * NbColumns * sizeof(scoplib_int_t)); + if (q == NULL) + { + fprintf(stderr, "[Scoplib] Memory Overflow.\n"); + exit(1); + } + matrix->p = p; + matrix->p_Init = q; + for (i = 0; i < NbRows; i++) + { + *p++ = q; + for (j = 0; j < NbColumns; j++) + SCOPVAL_init_set_si(*(q+j),0); + q += NbColumns; + } + } + return matrix; +} + + +/** + * scoplib_matrix_free_inside function: + * This function frees the allocated memory for the inside of a + * scoplib_matrix_t structure, i.e. only p and p_Init. + * \param matrix The pointer to the matrix we want to free. + ** + * - 02/05/2008: first version. + */ +void +scoplib_matrix_free_inside(scoplib_matrix_p matrix) +{ + int i; + scoplib_int_t * p; + + if (matrix == NULL) + return; + + p = matrix->p_Init; + for (i = 0; i < matrix->p_Init_size; i++) + SCOPVAL_clear(*p++); + + if (matrix->p_Init != NULL) + free(matrix->p_Init); + + if (matrix->p != NULL) + free(matrix->p); +} + + +/** + * scoplib_matrix_free function: + * This function frees the allocated memory for a scoplib_matrix_t structure. + * \param matrix The pointer to the matrix we want to free. + ** + * - 30/04/2008: first version. + * - 02/05/2008: now uses scoplib_matrix_free_inside. + */ +void +scoplib_matrix_free(scoplib_matrix_p matrix) +{ + if (matrix == NULL) + return; + + scoplib_matrix_free_inside(matrix); + free(matrix); +} + + +/** + * scoplib_matrix_list_malloc function: + * This function allocates the memory space for a scoplib_matrix_list_t + * structure and sets its fields with default values. Then it returns + * a pointer to the allocated space. + */ +scoplib_matrix_list_p +scoplib_matrix_list_malloc() +{ + scoplib_matrix_list_p res = + (scoplib_matrix_list_p) malloc(sizeof(scoplib_matrix_list_t)); + + if (res == NULL) + { + fprintf(stderr, "[Scoplib] Memory Overflow.\n"); + exit(1); + } + + res->elt = NULL; + res->next = NULL; + + return res; +} + + + +/** + * scoplib_matrix_list_free function: + * This function frees the allocated memory for a scoplib_matrix_list_t + * structure, and all the matrices stored in the list. + * \param list The pointer to the matrix list we want to free. + */ +void +scoplib_matrix_list_free(scoplib_matrix_list_p list) +{ + scoplib_matrix_list_p tmp; + + if (list == NULL) + return; + + while (list) + { + if (list->elt) + scoplib_matrix_free(list->elt); + tmp = list->next; + free(list); + list = tmp; + } +} + + +/*+**************************************************************************** + * Processing functions * + ******************************************************************************/ + + +/** + * scoplib_matrix_ncopy function: + * this functions builds and returns a "hard copy" (not a pointer copy) of a + * scoplib_matrix_t data structure such that the copy is restricted to the "n" + * first rows of the matrix. + * \param matrix The pointer to the matrix we want to copy. + * \param n The number of row of the matrix we want to copy. + ** + * - 02/05/2008: first version. + */ +scoplib_matrix_p +scoplib_matrix_ncopy(scoplib_matrix_p matrix, int n) +{ + int i, j; + scoplib_matrix_p copy; + + if (matrix == NULL) + return NULL; + + if (n > matrix->NbRows) + { + fprintf(stderr,"[Scoplib] Error: not enough rows in the matrix\n"); + exit(1); + } + + copy = scoplib_matrix_malloc(n,matrix->NbColumns); + + for (i = 0; i < n; i++) + for (j = 0; j < matrix->NbColumns; j++) + SCOPVAL_assign(copy->p[i][j],matrix->p[i][j]); + + return copy; +} + + +/** + * scoplib_matrix_copy function: + * this functions builds and returns a "hard copy" (not a pointer copy) of a + * scoplib_matrix_t data structure. + * \param matrix The pointer to the matrix we want to copy. + ** + * - 30/04/2008: first version (from CLooG 0.14.0). + * - 02/05/2008: no uses scoplib_matrix_ncopy. + */ +scoplib_matrix_p +scoplib_matrix_copy(scoplib_matrix_p matrix) +{ + if (matrix == NULL) + return NULL; + + return scoplib_matrix_ncopy(matrix,matrix->NbRows); +} + + +/** + * scoplib_matrix_replace_vector function: + * this function replaces the "row"^th row of a matrix "matrix" with the + * vector "vector". It directly updates "matrix". + * \param matrix The matrix we want to change a row. + * \param vector The vector that will replace a row of the matrix. + * \param row The row of the matrix to be replaced. + ** + * - 02/05/2008: first version. + */ +void +scoplib_matrix_replace_vector(scoplib_matrix_p matrix, scoplib_vector_p vector, + int row) +{ + int i; + + if ((matrix == NULL) || (vector == NULL) || + (matrix->NbColumns != vector->Size) || + (row >= matrix->NbRows) || (row < 0)) + { + fprintf(stderr,"[Scoplib] Error: vector cannot replace a matrix row\n"); + exit(1); + } + + for (i = 0; i < vector->Size; i++) + SCOPVAL_assign(matrix->p[row][i],vector->p[i]); +} + + +/** + * scoplib_matrix_add_vector function: + * this function adds the "row"^th row of a matrix "matrix" with the + * vector "vector". It directly updates "matrix". + * \param matrix The matrix we want to change a row. + * \param vector The vector that will replace a row of the matrix. + * \param row The row of the matrix to be replaced. + ** + * - 08/28/2008: first version. + */ +void +scoplib_matrix_add_vector(scoplib_matrix_p matrix, scoplib_vector_p vector, + int row) +{ + int i; + + if ((matrix == NULL) || (vector == NULL) || + (matrix->NbColumns != vector->Size) || + (row >= matrix->NbRows) || (row < 0)) + { + fprintf(stderr,"[Scoplib] Error: vector cannot replace a matrix row\n"); + exit(1); + } + + if (SCOPVAL_get_si(matrix->p[row][0]) == 0) + SCOPVAL_assign(matrix->p[row][0],vector->p[0]); + for (i = 1; i < vector->Size; i++) + SCOPVAL_addto(matrix->p[row][i],matrix->p[row][i],vector->p[i]); +} + + +/** + * scoplib_matrix_sub_vector function: + * this function substracts the vector "vector" to the "row"^th row of + * a matrix "matrix. It directly updates "matrix". + * \param matrix The matrix we want to change a row. + * \param vector The vector that will replace a row of the matrix. + * \param row The row of the matrix to be replaced. + ** + * - 08/28/2008: first version. + */ +void +scoplib_matrix_sub_vector(scoplib_matrix_p matrix, scoplib_vector_p vector, + int row) +{ + int i; + + if ((matrix == NULL) || (vector == NULL) || + (matrix->NbColumns != vector->Size) || + (row >= matrix->NbRows) || (row < 0)) + { + fprintf(stderr,"[Scoplib] Error: vector cannot replace a matrix row\n"); + exit(1); + } + + if (SCOPVAL_get_si(matrix->p[row][0]) == 0) + SCOPVAL_assign(matrix->p[row][0],vector->p[0]); + for (i = 1; i < vector->Size; i++) + SCOPVAL_subtract(matrix->p[row][i],matrix->p[row][i],vector->p[i]); +} + + +/** + * scoplib_matrix_insert_vector function: + * this function adds a new row corresponding to the vector "vector" to + * the matrix "matrix" by inserting it at the "row"^th row. It directly + * updates "matrix". If "vector" (or "matrix") is NULL, the matrix is left + * unmodified. + * \param matrix The matrix we want to extend. + * \param vector The vector that will be added matrix. + * \param row The row where to insert the vector. + ** + * - 02/05/2008: first version. + */ +void +scoplib_matrix_insert_vector(scoplib_matrix_p matrix, scoplib_vector_p vector, + int row) +{ + int i, j; + scoplib_matrix_p new; + + if ((vector == NULL) || (matrix == NULL)) + return; + + if ((matrix->NbColumns != vector->Size) || + (row > matrix->NbRows) || (row < 0)) + { + fprintf(stderr,"[Scoplib] Error: vector cannot be inserted\n"); + exit(1); + } + + /* We use a temporary matrix just to reuse existing functions. Cleaner. */ + new = scoplib_matrix_malloc(matrix->NbRows+1,matrix->NbColumns); + + for (i = 0; i < row; i++) + for (j = 0; j < matrix->NbColumns; j++) + SCOPVAL_assign(new->p[i][j],matrix->p[i][j]); + + scoplib_matrix_replace_vector(new,vector,row); + + for (i = row+1; i < matrix->NbRows; i++) + for (j = 0; j < matrix->NbColumns; j++) + SCOPVAL_assign(new->p[i][j],matrix->p[i-1][j]); + + scoplib_matrix_free_inside(matrix); + + /* Replace the inside of matrix */ + matrix->NbRows = new->NbRows; + matrix->NbColumns = new->NbColumns; + matrix->p = new->p; + matrix->p_Init = new->p_Init; + /* Free the new "shell" */ + free(new); +} + + +/** + * scoplib_matrix_from_vector function: + * this function converts a vector "vector" to a matrix with a single row + * and returns a pointer to that matrix. + * \param vector The vector to convert to a matrix. + ** + * - 02/05/2008: first version. + */ +scoplib_matrix_p +scoplib_matrix_from_vector(scoplib_vector_p vector) +{ + scoplib_matrix_p matrix; + + if (vector == NULL) + return NULL; + + matrix = scoplib_matrix_malloc(1,vector->Size); + scoplib_matrix_replace_vector(matrix,vector,0); + return matrix; +} + + +/** + * scoplib_matrix_replace_matrix function: + * this function replaces some rows of a matrix "m1" with the rows of + * the matrix "m2". It begins at the "row"^th row of "m1". It directly + * updates "m1". + * \param m1 The matrix we want to change some row1. + * \param m2 The matrix containing the new rows. + * \param row The first row of the matrix m1 to be replaced. + ** + * - 02/05/2008: first version. + */ +void +scoplib_matrix_replace_matrix(scoplib_matrix_p m1, scoplib_matrix_p m2, int row) +{ + int i, j; + + if ((m1 == NULL) || (m2 == NULL) || + (m1->NbColumns != m1->NbColumns) || + ((row + m2->NbRows) > m1->NbRows) || (row < 0)) + { + fprintf(stderr,"[Scoplib] Error: vector cannot replace a matrix row\n"); + exit(1); + } + + for (i = 0; i < m2->NbRows; i++) + for (j = 0; j < m2->NbColumns; j++) + SCOPVAL_assign(m1->p[i+row][j],m2->p[i][j]); +} + + +/** + * scoplib_matrix_insert_matrix function: + * this function adds new rows corresponding to the matrix "m1" to + * the matrix "m2" by inserting it at the "row"^th row. It directly + * updates "m1". If "m2" (or "m1") is NULL, the matrix is left + * unmodified. + * \param m1 The matrix we want to extend. + * \param m2 The matrix to be inserted. + * \param row The row where to insert the matrix + ** + * - 02/05/2008: first version. + */ +void +scoplib_matrix_insert_matrix(scoplib_matrix_p m1, scoplib_matrix_p m2, int row) +{ + int i, j; + scoplib_matrix_p new; + + if ((m1 == NULL) || (m2 == NULL)) + return; + + if ((m1->NbColumns != m2->NbColumns) || + (row > m1->NbRows) || (row < 0)) + { + fprintf(stderr,"[Scoplib] Error: matrix cannot be inserted\n"); + exit(1); + } + + /* We use a temporary matrix just to reuse existing functions. Cleaner. */ + new = scoplib_matrix_malloc(m1->NbRows+m2->NbRows,m1->NbColumns); + + for (i = 0; i < row; i++) + for (j = 0; j < m1->NbColumns; j++) + SCOPVAL_assign(new->p[i][j],m1->p[i][j]); + + scoplib_matrix_replace_matrix(new,m2,row); + + for (i = row + m2->NbRows; i < m1->NbRows; i++) + for (j = 0; j < m1->NbColumns; j++) + SCOPVAL_assign(new->p[i][j],m1->p[i-m2->NbRows][j]); + + scoplib_matrix_free_inside(m1); + + /* Replace the inside of matrix */ + m1->NbRows = new->NbRows; + m1->NbColumns = new->NbColumns; + m1->p = new->p; + m1->p_Init = new->p_Init; + + /* Free the new "container" */ + free(new); +} + + +/** + * scoplib_matrix_concat function: + * this function builds a new matrix as the concatenation of the rows of + * two other matrices sent as parameters. + * \param m1 The first matrix. + * \param m2 The second matrix. + ** + * - 02/05/2008: first version. + */ +scoplib_matrix_p +scoplib_matrix_concat(scoplib_matrix_p m1, scoplib_matrix_p m2) +{ + scoplib_matrix_p new; + + if (m1 == NULL) + return scoplib_matrix_copy(m2); + + if (m2 == NULL) + return scoplib_matrix_copy(m1); + + if (m1->NbColumns != m2->NbColumns) + { + fprintf(stderr,"[Scoplib] Error: matrices cannot be concatenated\n"); + exit(1); + } + + new = scoplib_matrix_malloc(m1->NbRows+m2->NbRows,m1->NbColumns); + scoplib_matrix_replace_matrix(new,m1,0); + scoplib_matrix_replace_matrix(new,m2,m1->NbRows); + + return new; +} + + +/** + * scoplib_matrix_equal function: + * this function returns true if the two matrices are the same, false + * otherwise. + * \param m1 The first matrix. + * \param m2 The second matrix. + * + */ +int +scoplib_matrix_equal(scoplib_matrix_p m1, scoplib_matrix_p m2) +{ + if (m1 == m2) + return 1; + if (m1 == NULL || m2 == NULL) + return 0; + if (m1->NbRows != m2->NbRows || m1->NbColumns != m2->NbColumns) + return 0; + int i, j; + for (i = 0; i < m1->NbRows; ++i) + for (j = 0; j < m1->NbColumns; ++j) + if (SCOPVAL_ne(m1->p[i][j], m2->p[i][j])) + return 0; + return 1; +} diff --git a/source/scop.c b/source/scop.c new file mode 100644 index 0000000..d96d59c --- /dev/null +++ b/source/scop.c @@ -0,0 +1,813 @@ + + /*+------- <| --------------------------------------------------------** + ** A Clan/Scop ** + **--- /.\ -----------------------------------------------------** + ** <| [""M# scop.c ** + **- A | # -----------------------------------------------------** + ** /.\ [""M# First version: 30/04/2008 ** + **- [""M# | # U"U#U -----------------------------------------------** + | # | # \ .:/ + | # | #___| # + ****** | "--' .-" ****************************************************** + * |"-"-"-"-"-#-#-## Clan : the Chunky Loop Analyzer (experimental) * + **** | # ## ###### ***************************************************** + * \ .::::'/ * + * \ ::::'/ Copyright (C) 2008 Cedric Bastoul * + * :8a| # # ## * + * ::88a ### This is free software; you can redistribute it * + * ::::888a 8a ##::. and/or modify it under the terms of the GNU Lesser * + * ::::::::888a88a[]::: General Public License as published by the Free * + *::8:::::::::SUNDOGa8a::. Software Foundation, either version 2.1 of the * + *::::::::8::::888:Y8888:: License, or (at your option) any later version. * + *::::':::88::::888::Y88a::::::::::::... * + *::'::.. . ..... .. ... . * + * This software 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 General Public License * + * for more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with software; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * * + * Clan, the Chunky Loop Analyzer * + * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr * + * * + ******************************************************************************/ + + +# include +# include +# include +# include +# include + + +/*+**************************************************************************** + * Structure display functions * + ******************************************************************************/ + + +/** + * scoplib_scop_print_structure function: + * Displays a scoplib_scop_t structure (*scop) into a file (file, possibly + * stdout) in a way that trends to be understandable without falling in a deep + * depression or, for the lucky ones, getting a headache... It includes an + * indentation level (level) in order to work with others print_structure + * functions. + * \param file File where informations are printed. + * \param scop The scop whose information have to be printed. + * \param level Number of spaces before printing, for each line. + ** + * - 30/04/2008: first version. + */ +void +scoplib_scop_print_structure(FILE * file, scoplib_scop_p scop, int level) +{ + int i, j; + + if (scop != NULL) + { + /* Go to the right level. */ + for (j = 0; j < level; j++) + fprintf(file,"|\t"); + fprintf(file,"+-- scoplib_scop_t\n"); + + /* A blank line. */ + for (j = 0; j <= level+1; j++) + fprintf(file,"|\t"); + fprintf(file,"\n"); + + /* Print the context of the scop. */ + scoplib_matrix_print_structure(file,scop->context,level+1); + + /* Print the original parameter names. */ + for (i = 0; i <= level; i++) + fprintf(file,"|\t"); + if (scop->nb_parameters > 0) + { + fprintf(file,"+-- Original parameters strings:"); + for (i = 0; i < scop->nb_parameters; i++) + fprintf(file," %s",scop->parameters[i]); + fprintf(file,"\n"); + } + else + fprintf(file,"+-- No original parameters string\n"); + + /* A blank line. */ + for (j = 0; j <= level+1; j++) + fprintf(file,"|\t"); + fprintf(file,"\n"); + + /* Print the original parameter names. */ + for (i = 0; i <= level; i++) + fprintf(file,"|\t"); + if (scop->nb_arrays > 0) + { + fprintf(file,"+-- Accessed array strings:"); + for (i = 0; i < scop->nb_arrays; i++) + fprintf(file," %s",scop->arrays[i]); + fprintf(file,"\n"); + } + else + fprintf(file,"+-- No accessed array string\n"); + + /* A blank line. */ + for (j = 0; j <= level+1; j++) + fprintf(file,"|\t"); + fprintf(file,"\n"); + + /* Print the statements. */ + scoplib_statement_print_structure(file,scop->statement,level+1); + } + else + { + /* Go to the right level. */ + for (j = 0; j < level; j++) + fprintf(file,"|\t"); + fprintf(file,"+-- NULL scop\n"); + } + + /* The last line. */ + for (j = 0; j <= level; j++) + fprintf(file,"|\t"); + fprintf(file,"\n"); +} + + +/** + * scoplib_scop_print function: + * This function prints the content of a scoplib_scop_t structure (*scop) into + * a file (file, possibly stdout). + * \param file File where informations are printed. + * \param scop The scop whose information have to be printed. + ** + * - 30/04/2008: first version. + */ +void +scoplib_scop_print(FILE * file, scoplib_scop_p scop) +{ + scoplib_scop_print_structure(file,scop,0); +} + + + +static +void +scoplib_scop_print_dot_scop_(FILE * file, scoplib_scop_p scop, + int castle, int arraystag) +{ + int i; + + if (castle) + { + fprintf(file,"# \n"); + fprintf(file,"# <| \n"); + fprintf(file,"# A \n"); + fprintf(file,"# /.\\ \n"); + fprintf(file,"# <| [\"\"M# \n"); + fprintf(file,"# A | # Clan McCloog Castle \n"); + fprintf(file,"# /.\\ [\"\"M# [File generated by ScopLib"); + fprintf(file," %s %s bits]\n",SCOPLIB_RELEASE,SCOPLIB_VERSION); + fprintf(file,"# [\"\"M# | # U\"U#U \n"); + fprintf(file,"# | # | # \\ .:/ \n"); + fprintf(file,"# | # | #___| # \n"); + fprintf(file,"# | \"--' .-\" \n"); + fprintf(file,"# |\"-\"-\"-\"-\"-#-#-## \n"); + fprintf(file,"# | # ## ###### \n"); + fprintf(file,"# \\ .::::'/ \n"); + fprintf(file,"# \\ ::::'/ \n"); + fprintf(file,"# :8a| # # ## \n"); + fprintf(file,"# ::88a ### \n"); + fprintf(file,"# ::::888a 8a ##::. \n"); + fprintf(file,"# ::::::888a88a[]:::: \n"); + fprintf(file,"# :::::::::SUNDOGa8a::::. .. \n"); + fprintf(file,"# :::::8::::888:Y8888:::::::::... \n"); + fprintf(file,"#::':::88::::888::Y88a______________________________"); + fprintf(file,"________________________\n"); + fprintf(file,"#:: ::::88a::::88a:Y88a "); + fprintf(file," __---__-- __\n"); + fprintf(file,"#' .: ::Y88a:::::8a:Y88a "); + fprintf(file,"__----_-- -------_-__\n"); + fprintf(file,"# :' ::::8P::::::::::88aa. _ _- -"); + fprintf(file,"- --_ --- __ --- __--\n"); + fprintf(file,"#.:: :::::::::::::::::::Y88as88a...s88aa.\n"); + } + else + { + fprintf(file,"# [File generated by ScopLib %s %s bits]\n", + SCOPLIB_RELEASE,SCOPLIB_VERSION); + } + + fprintf(file,"\n"); + fprintf(file,"SCoP\n"); + fprintf(file,"\n"); + fprintf(file,"# =============================================== Global\n"); + fprintf(file,"# Language\n"); + fprintf(file,"C\n"); + fprintf(file,"\n"); + + fprintf(file,"# Context\n"); + scoplib_matrix_print_dot_scop(file,scop->context,SCOPLIB_TYPE_DOMAIN, + 0,NULL, + scop->nb_parameters,scop->parameters, + scop->nb_arrays,scop->arrays); + fprintf(file,"\n"); + + if (scop->nb_parameters > 0) + { + fprintf(file,"# Parameter names are provided\n"); + fprintf(file,"1\n"); + fprintf(file,"# Parameter names\n"); + for (i = 0; i < scop->nb_parameters; i++) + fprintf(file,"%s ",scop->parameters[i]); + fprintf(file,"\n"); + fprintf(file,"\n"); + } + else + { + fprintf(file,"# Parameter names are not provided\n"); + fprintf(file,"0\n"); + fprintf(file,"\n"); + } + + fprintf(file,"# Number of statements\n"); + fprintf(file,"%d\n",scoplib_statement_number(scop->statement)); + fprintf(file,"\n"); + + scoplib_statement_print_dot_scop(file,scop->statement, + scop->nb_parameters,scop->parameters, + scop->nb_arrays,scop->arrays); + + fprintf(file,"# =============================================== Options\n"); + if (scop->optiontags) + fprintf(file, "%s", scop->optiontags); + if (arraystag) + { + /* If the tag is present in the option tags, don't dump it. */ + char* content = scoplib_scop_tag_content (scop, "", ""); + if (! content) + { + /* It isn't, so dump the list of arrays. */ + fprintf(file, "\n"); + fprintf(file, "%d\n", scop->nb_arrays); + for (i = 0; i < scop->nb_arrays; ++i) + fprintf(file, "%d %s\n", i + 1, scop->arrays[i]); + fprintf(file, "\n"); + } + else + free(content); + } +} + + +/** + * scoplib_scop_print_dot_scop function: + * This function prints the content of a scoplib_scop_t structure (*scop) + * into a file (file, possibly stdout) for the .scop format. + * \param file File where informations are printed. + * \param scop The scop whose information have to be printed. + ** + * - 02/05/2008: first version. + */ +void +scoplib_scop_print_dot_scop(FILE * file, scoplib_scop_p scop) +{ + scoplib_scop_print_dot_scop_(file, scop, 0, 0); +} + +/** + * scoplib_scop_print_dot_scop_castle function: + * This function prints the content of a scoplib_scop_t structure (*scop) + * into a file (file, possibly stdout) for the .scop format, with the castle. + * \param file File where informations are printed. + * \param scop The scop whose information have to be printed. + ** + * - 02/05/2008: first version. + */ +void +scoplib_scop_print_dot_scop_options(FILE * file, scoplib_scop_p scop, + int options) +{ + int castle = 0; + int arraystag = 0; + if ((options & SCOPLIB_SCOP_PRINT_CASTLE) != 0) + castle = 1; + if ((options & SCOPLIB_SCOP_PRINT_ARRAYSTAG) != 0) + arraystag = 1; + scoplib_scop_print_dot_scop_(file, scop, castle, arraystag); +} + + +/****************************************************************************** + * Reading function * + ******************************************************************************/ + +/** + * Internal function. Read 'nb_strings' strings on the input 'file'. + * + * \FIXME should be placed somewhere else, it's duplicated in statement.c. + */ +static +char** +scoplib_scop_read_strings(FILE* file, int nb_strings) +{ + char str[SCOPLIB_MAX_STRING]; + char tmp[SCOPLIB_MAX_STRING]; + char* s; + char** res = NULL; + int i; + int count; + + /* Skip blank/commented lines. */ + while (fgets(str, SCOPLIB_MAX_STRING, file) == 0 || str[0] == '#' || + isspace(str[0])) + ; + s = str; + + /* Allocate the array of string. Make it NULL-terminated. */ + res = (char**) malloc(sizeof(char*) * (nb_strings + 1)); + res[nb_strings] = NULL; + + /* Read the desired number of strings. */ + for (i = 0; i < nb_strings; ++i) + { + for (count = 0; *s && ! isspace(*s) && *s != '#'; ++count) + tmp[count] = *(s++); + tmp[count] = '\0'; + res[i] = strdup(tmp); + if (*s != '#') + ++s; + } + + return res; +} + + +/** + * Internal function. Read an int on the input 'file'. + * + * \FIXME should be placed somewhere else, it's duplicated in statement.c. + */ +static +int +scoplib_scop_read_int(FILE* file, char** str) +{ + char s[SCOPLIB_MAX_STRING]; + int res; + int i = 0; + int read_int = 0; + + if (file != NULL && str != NULL) + { + fprintf(stderr, "[Scoplib] Error: only one of the two parameters of" + " scop_read_int can be non-NULL\n"); + exit (1); + } + + if (file != NULL) + { + /* Parse from a file. */ + /* Skip blank/commented lines. */ + while (fgets(s, SCOPLIB_MAX_STRING, file) == 0 || s[0] == '#' || + isspace(s[0])) + ; + sscanf(s, "%d", &res); + } + if (str != NULL) + { + /* Parse from a string. */ + /* Skip blank/commented lines. */ + do + { + while (*str && **str && isspace(**str)) + ++(*str); + if (**str == '#') + { + while (**str && **str != '\n') + ++(*str); + } + else + { + /* Build the chain to analyze. */ + while (**str && !isspace(**str) && **str != '\n') + s[i++] = *((*str)++); + s[i] = '\0'; + sscanf(s, "%d", &res); + read_int = 1; + } + } + while (! read_int); + } + + return res; +} + + +/** + * scoplib_scop_generate_names function: + * This function generates an array of size 'nb' of chars of the form + * "seedXX" where XX goes from 1 to nb. + * \param seed The template for the created names + * \param nb The number of created items. + */ +char** +scoplib_scop_generate_names(char* seed, int nb) +{ + char** res = NULL; + char buff[strlen(seed) + 16]; + int i; + + if (nb) + { + res = (char**) malloc(sizeof(char*)* nb); + if (res == NULL) + { + fprintf(stderr, "[Scoplib] Memory Overflow.\n"); + exit(1); + } + for (i = 0; i < nb; ++i) + { + sprintf(buff, "%s%d", seed, i + 1); + res[i] = strdup(buff); + } + } + + return res; +} + + +/** + * scoplib_scop_tag_content function: + * This function returns a freshly allocated string containing the + * content, in the optional tags section, between the tag 'tag' and + * the tag 'endtag'. If the tag 'tag' is not found, returns NULL. + */ +char* +scoplib_scop_tag_content(scoplib_scop_p scop, char* tag, char* endtag) +{ + return scoplib_scop_tag_content_from_string(scop->optiontags, tag, endtag); +} + + +/** + * scoplib_scop_tag_content_from_string function: + * This function returns a freshly allocated string containing the + * content, in the given string 'str', between the tag 'tag' and + * the tag 'endtag'. If the tag 'tag' is not found, returns NULL. + */ +char* +scoplib_scop_tag_content_from_string(char* str, char* tag, char* endtag) +{ + int i; + char* start; + char* stop; + int size = 0; + int lentag; + char* res = NULL; + + if (str) + { + start = str; + lentag = strlen(tag); + for (; start && *start && strncmp(start, tag, lentag); ++start) + ; + /* The tag 'tag' was not found.*/ + if (! *start) + return NULL; + start += lentag; + stop = start; + lentag = strlen(endtag); + for (size = 0; *stop && strncmp(stop, endtag, lentag); ++stop, ++size) + ; + /* the tag 'endtag' was not found. */ + if (! *stop) + return NULL; + res = (char*) malloc((size + 1) * sizeof(char)); + if (res == NULL) + { + fprintf(stderr, "[Scoplib] Error: memory exhausted\n"); + exit(1); + } + /* Copy the chain between the two tags. */ + for (++start, i = 0; start != stop; ++start, ++i) + res[i] = *start; + res[i] = '\0'; + } + + return res; +} + + +/** + * scoplib_scop_read function: + * This function reads a scoplib_scop_t structure from an input stream + * (possibly stdin) corresponding to a scoplib SCoP dump. + * \param file The input stream + */ +scoplib_scop_p +scoplib_scop_read(FILE* file) +{ + char tmpbuff[SCOPLIB_MAX_STRING]; + scoplib_scop_p scop = NULL; + scoplib_statement_p stmt = NULL; + scoplib_statement_p prev = NULL; + int nb_statements; + char** tmp; + int i; + char* content; + + if (file == NULL) + return NULL; + + scop = scoplib_scop_malloc(); + + /* Backup the arrays of the program. Buffer is reajustable. */ + int nb_arr = SCOPLIB_MAX_STRING; + char** arrays = (char**) malloc (sizeof(char*) * nb_arr); + for (i = 0; i < nb_arr; ++i) + arrays[i] = NULL; + + /* Ensure the file is a .scop. */ + tmp = scoplib_scop_read_strings(file, 1); + if (strcmp(*tmp, "SCoP")) + { + fprintf(stderr, "[Scoplib] Error. The file is not a .scop\n"); + exit (1); + } + free(*tmp); + free(tmp); + + /* Read the language. */ + char** language = scoplib_scop_read_strings(file, 1); + if (strcmp(*language, "C") && strcmp(*language, "JAVA") && + strcmp(*language, "C#")) + { + fprintf(stderr, "[Scoplib] Error. The language is not recognized\n"); + exit (1); + } + /* language is not used so far. */ + free(*language); + free(language); + + /* Read the context. */ + scop->context = scoplib_matrix_read (file); + scop->nb_parameters = scop->context->NbColumns - 2; + + /* Read the parameter names, if any. */ + if (scoplib_scop_read_int(file, NULL) > 0) + scop->parameters = scoplib_scop_read_strings (file, scop->nb_parameters); + else + scop->parameters = scoplib_scop_generate_names("M", scop->nb_parameters); + + /* Read the number of statements. */ + nb_statements = scoplib_scop_read_int (file, NULL); + + for (i = 0; i < nb_statements; ++i) + { + /* Read each statement. */ + stmt = scoplib_statement_read (file, scop->nb_parameters, + &arrays, &nb_arr); + if (scop->statement == NULL) + scop->statement = stmt; + else + prev->next = stmt; + prev = stmt; + } + + /* Read the remainder of the file, and store it in the optiontags + field. */ + /* Skip blank lines. */ + while (! feof(file) && + (fgets(tmpbuff, SCOPLIB_MAX_STRING, file) == 0 || + tmpbuff[0] == '#' || isspace(tmpbuff[0]) || tmpbuff[0] != '<')) + ; + /* Store the remainder of the file, if any. */ + if (tmpbuff[0]) + { + int count = strlen(tmpbuff); + int pos = 0; + int bufs = SCOPLIB_MAX_STRING; + scop->optiontags = (char*) malloc(bufs * sizeof(char)); + do + { + scop->optiontags = (char*) realloc + (scop->optiontags, (bufs += count) * sizeof(char)); + for (i = 0; i < count; ++i) + scop->optiontags[pos++] = tmpbuff[i]; + } + while ((count = fread(tmpbuff, sizeof(char), SCOPLIB_MAX_STRING, file)) + > 0); + } + + /* Count the number of referenced arrays/variables. */ + scop->nb_arrays = 0; + for (stmt = scop->statement; stmt; stmt = stmt->next) + { + if (stmt->read) + for (i = 0; i < stmt->read->NbRows; ++i) + if (scop->nb_arrays < SCOPVAL_get_si(stmt->read->p[i][0])) + scop->nb_arrays = SCOPVAL_get_si(stmt->read->p[i][0]); + if (stmt->write) + for (i = 0; i < stmt->write->NbRows; ++i) + if (scop->nb_arrays < SCOPVAL_get_si(stmt->write->p[i][0])) + scop->nb_arrays = SCOPVAL_get_si(stmt->write->p[i][0]); + } + + /* Allocate the array names array. */ + scop->arrays = (char**) malloc(sizeof(char*) * (scop->nb_arrays + 1)); + for (i = 0; i < scop->nb_arrays; ++i) + scop->arrays[i] = NULL; + + /* Populate the array list with referenced in the tag, if + any. */ + if ((content = scoplib_scop_tag_content(scop, "", ""))) + { + char* start = content; + int n_arr = scoplib_scop_read_int(NULL, &content); + char buff2[SCOPLIB_MAX_STRING]; + int idx_array; + i = 0; + while (n_arr--) + { + /* Skip blank or commented lines. */ + while (*content == '#' || *content == '\n') + { + for (; *content != '\n'; ++content) + ; + ++content; + } + /* Get the variable id. */ + for (i = 0; *content && ! isspace(*content); ++i, ++content) + buff2[i] = *content; + buff2[i] = '\0'; + sscanf (buff2, "%d", &idx_array); + /* Get the variable name. */ + while (*content && isspace(*content)) + ++content; + for (i = 0; *content && ! isspace(*content); ++i, ++content) + buff2[i] = *content; + buff2[i] = '\0'; + /* array is in 0-basis. */ + if (arrays[idx_array - 1]) + free(arrays[idx_array - 1]); + arrays[idx_array - 1] = strdup(buff2); + /* Go to the end of line. */ + while (*content && *content != '\n') + ++content; + } + content = start; + } + + /* Fill the array of array names. */ + char** tmparrays = scoplib_scop_generate_names("var", scop->nb_arrays); + for (i = 0; i < scop->nb_arrays; ++i) + { + if (arrays[i] == NULL || arrays[i][0] == '\0') + { + /* Use a generated name in case no array name was parsed. */ + scop->arrays[i] = tmparrays[i]; + if (arrays[i]) + free(arrays[i]); + } + else + { + /* Use the parsed array name. */ + scop->arrays[i] = arrays[i]; + free(tmparrays[i]); + } + } + scop->arrays[i] = NULL; + free(arrays); + free(tmparrays); + + + return scop; +} + + + +/*+**************************************************************************** + * Memory allocation/deallocation functions * + ******************************************************************************/ + + +/** + * scoplib_scop_malloc function: + * This function allocates the memory space for a scoplib_scop_t structure and + * sets its fields with default values. Then it returns a pointer to the + * allocated space. + ** + * - 30/04/2008: first version. + */ +scoplib_scop_p +scoplib_scop_malloc() +{ + scoplib_scop_p scop; + + scop = (scoplib_scop_p)malloc(sizeof(scoplib_scop_t)); + if (scop == NULL) + { + fprintf(stderr, "[Scoplib] Memory Overflow.\n"); + exit(1); + } + + scop->context = NULL; + scop->nb_parameters = 0; + scop->parameters = NULL; + scop->nb_arrays = 0; + scop->arrays = NULL; + scop->statement = NULL; + scop->optiontags = NULL; + scop->usr = NULL; + + return scop; +} + + +/** + * scoplib_scop_free function: + * This function frees the allocated memory for a scoplib_scop_t structure. + * \param scop The pointer to the scop we want to free. + ** + * - 30/04/2008: first version. + */ +void +scoplib_scop_free(scoplib_scop_p scop) +{ + int i; + + if (scop != NULL) + { + scoplib_matrix_free(scop->context); + if (scop->parameters != NULL) + { + for (i = 0; i < scop->nb_parameters; i++) + free(scop->parameters[i]); + free(scop->parameters); + } + if (scop->arrays != NULL) + { + for (i = 0; i < scop->nb_arrays; i++) + free(scop->arrays[i]); + free(scop->arrays); + } + scoplib_statement_free(scop->statement); + free(scop->optiontags); + free(scop); + } +} + + + +/** + * scoplib_scop_dup function: + * This function returns a fresh identical (non shadow) copy of the + * input scop. + * \param scop The scop whose information have to be printed. + ** + */ +scoplib_scop_p +scoplib_scop_dup(scoplib_scop_p scop) +{ + int i; + scoplib_statement_p stm; + scoplib_statement_p tmp = NULL; + scoplib_scop_p ret = scoplib_scop_malloc(); + ret->context = scoplib_matrix_copy(scop->context); + ret->nb_parameters = scop->nb_parameters; + ret->parameters = (char**) malloc(sizeof(char*) * ret->nb_parameters); + for (i = 0; i < ret->nb_parameters; ++i) + ret->parameters[i] = strdup(scop->parameters[i]); + ret->nb_arrays = scop->nb_arrays; + ret->arrays = (char**) malloc(sizeof(char*) * ret->nb_arrays); + for (i = 0; i < ret->nb_arrays; ++i) + ret->arrays[i] = strdup(scop->arrays[i]); + + for (stm = scop->statement; stm; stm = stm->next) + { + scoplib_statement_p newstm = scoplib_statement_malloc(); + newstm->domain = scoplib_matrix_list_malloc(); + newstm->domain->elt = scoplib_matrix_copy(stm->domain->elt); + newstm->schedule = scoplib_matrix_copy(stm->schedule); + newstm->read = scoplib_matrix_copy(stm->read); + newstm->write = scoplib_matrix_copy(stm->write); + newstm->nb_iterators = stm->nb_iterators; + newstm->iterators = (char**) malloc(sizeof(char*) * newstm->nb_iterators); + for (i = 0; i < newstm->nb_iterators; ++i) + newstm->iterators[i] = strdup(stm->iterators[i]); + newstm->body = strdup (stm->body); + if (ret->statement == NULL) + ret->statement = tmp = newstm; + else + { + tmp->next = newstm; + tmp = tmp->next; + } + } + if (scop->optiontags) + ret->optiontags = strdup(scop->optiontags); + ret->usr = scop->usr; + + return ret; +} diff --git a/source/statement.c b/source/statement.c new file mode 100644 index 0000000..226cf32 --- /dev/null +++ b/source/statement.c @@ -0,0 +1,518 @@ + + /*+------- <| --------------------------------------------------------** + ** A Clan/Scop ** + **--- /.\ -----------------------------------------------------** + ** <| [""M# statement.c ** + **- A | # -----------------------------------------------------** + ** /.\ [""M# First version: 30/04/2008 ** + **- [""M# | # U"U#U -----------------------------------------------** + | # | # \ .:/ + | # | #___| # + ****** | "--' .-" ****************************************************** + * |"-"-"-"-"-#-#-## Clan : the Chunky Loop Analyzer (experimental) * + **** | # ## ###### ***************************************************** + * \ .::::'/ * + * \ ::::'/ Copyright (C) 2008 Cedric Bastoul * + * :8a| # # ## * + * ::88a ### This is free software; you can redistribute it * + * ::::888a 8a ##::. and/or modify it under the terms of the GNU Lesser * + * ::::::::888a88a[]::: General Public License as published by the Free * + *::8:::::::::SUNDOGa8a::. Software Foundation, either version 2.1 of the * + *::::::::8::::888:Y8888:: License, or (at your option) any later version. * + *::::':::88::::888::Y88a::::::::::::... * + *::'::.. . ..... .. ... . * + * This software 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 General Public License * + * for more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with software; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * * + * Clan, the Chunky Loop Analyzer * + * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr * + * * + ******************************************************************************/ + + +# include +# include +# include +# include +# include + + +/*+**************************************************************************** + * Structure display functions * + ******************************************************************************/ + + +/** + * scoplib_statement_print_structure function: + * Displays a scoplib_statement_t structure (*statement) into a file (file, + * possibly stdout) in a way that trends to be understandable without falling + * in a deep depression or, for the lucky ones, getting a headache... It + * includes an indentation level (level) in order to work with others + * print_structure functions. + * \param file File where informations are printed. + * \param statement The statement whose information have to be printed. + * \param level Number of spaces before printing, for each line. + ** + * - 30/04/2008: first version. + */ +void +scoplib_statement_print_structure(FILE * file, scoplib_statement_p statement, + int level) +{ + int i, j, first = 1, number = 1; + + /* Go to the right level. */ + for (j = 0; j < level; j++) + fprintf(file,"|\t"); + + if (statement != NULL) + fprintf(file,"+-- scoplib_statement_t (S%d)\n",number); + else + fprintf(file,"+-- NULL statement\n"); + + while (statement != NULL) + { if (!first) + { + /* Go to the right level. */ + for (j = 0; j < level; j++) + fprintf(file,"|\t"); + fprintf(file,"| scoplib_statement_t (S%d)\n",number); + } + else + first = 0; + + /* A blank line. */ + for (j = 0; j <= level+1; j++) + fprintf(file,"|\t"); + fprintf(file,"\n"); + + /* Print the domain of the statement. */ + scoplib_matrix_list_print_structure(file,statement->domain,level+1); + + /* Print the schedule of the statement. */ + scoplib_matrix_print_structure(file,statement->schedule,level+1); + + /* Print the array read access informations of the statement. */ + scoplib_matrix_print_structure(file,statement->read,level+1); + + /* Print the array write access informations of the statement. */ + scoplib_matrix_print_structure(file,statement->write,level+1); + + /* Print the original iterator names. */ + for (i=0; i<=level; i++) + fprintf(file,"|\t"); + if (statement->nb_iterators > 0) + { + fprintf(file,"+-- Original iterator strings:"); + for (i = 0; i < statement->nb_iterators; i++) + fprintf(file," %s",statement->iterators[i]); + fprintf(file,"\n"); + } + else + fprintf(file,"+-- No original iterator string\n"); + + /* A blank line. */ + for (i = 0; i <= level+1; i++) + fprintf(file,"|\t"); + fprintf(file,"\n"); + + /* Print the original statement body. */ + for (i = 0; i <= level; i++) + fprintf(file,"|\t"); + if (statement->body != NULL) + fprintf(file,"+-- Original body: %s\n",statement->body); + else + fprintf(file,"+-- No original body\n"); + + /* Print the control and exit predicates associated to the statement. */ + /** @FIXME: do it! */ + + /* A blank line. */ + for (i = 0; i <= level+1; i++) + fprintf(file,"|\t"); + fprintf(file,"\n"); + + statement = statement->next; + number++; + + /* Next line. */ + if (statement != NULL) + { + for (j = 0; j <= level; j++) + fprintf(file,"|\t"); + fprintf(file,"V\n"); + } + } + + /* The last line. */ + for (j = 0; j <= level; j++) + fprintf(file,"|\t"); + fprintf(file,"\n"); +} + + +/** + * scoplib_statement_print function: + * This function prints the content of a scoplib_statement_t structure + * (*statement) into a file (file, possibly stdout). + * \param file File where informations are printed. + * \param statement The statement whose information have to be printed. + ** + * - 30/04/2008: first version. + */ +void +scoplib_statement_print(FILE * file, scoplib_statement_p statement) +{ + scoplib_statement_print_structure(file, statement, 0); +} + + +/** + * scoplib_statement_print_dot_scop function: + * This function prints the content of a scoplib_statement_t structure + * (*statement) into a file (file, possibly stdout) for the .scop format. + * \param file File where informations are printed. + * \param statement The statement whose information have to be printed. + * \param nb_parameters The number of parameters in the SCoP. + * \param parameters An array containing all parameters names. + * \param nb_arrays The number of arrays accessed in the SCoP. + * \param arrays An array containing all accessed array names. + ** + * - 02/05/2008: first version. + */ +void +scoplib_statement_print_dot_scop(FILE * file, scoplib_statement_p statement, + int nb_parameters, char ** parameters, + int nb_arrays, char ** arrays) +{ + int i, number = 1; + + while (statement != NULL) + { + fprintf(file,"# =============================================== "); + fprintf(file,"Statement %d\n",number); + + fprintf(file,"# ---------------------------------------------- "); + fprintf(file,"%2d.1 Domain\n",number); + fprintf(file,"# Iteration domain\n"); + scoplib_matrix_list_print_dot_scop(file, statement->domain, + SCOPLIB_TYPE_DOMAIN, + statement->nb_iterators, + statement->iterators, + nb_parameters,parameters, + nb_arrays,arrays); + fprintf(file,"\n"); + + fprintf(file,"# ---------------------------------------------- "); + fprintf(file,"%2d.2 Scattering\n",number); + fprintf(file,"# Scattering function is provided\n"); + fprintf(file,"1\n"); + fprintf(file,"# Scattering function\n"); + scoplib_matrix_print_dot_scop(file,statement->schedule, + SCOPLIB_TYPE_SCATTERING, + statement->nb_iterators,statement->iterators, + nb_parameters,parameters, + nb_arrays,arrays); + fprintf(file,"\n"); + + fprintf(file,"# ---------------------------------------------- "); + fprintf(file,"%2d.3 Access\n",number); + fprintf(file,"# Access informations are provided\n"); + fprintf(file,"1\n"); + fprintf(file,"# Read access informations\n"); + scoplib_matrix_print_dot_scop(file,statement->read,SCOPLIB_TYPE_ACCESS, + statement->nb_iterators,statement->iterators, + nb_parameters,parameters, + nb_arrays,arrays); + fprintf(file,"# Write access informations\n"); + scoplib_matrix_print_dot_scop(file,statement->write,SCOPLIB_TYPE_ACCESS, + statement->nb_iterators,statement->iterators, + nb_parameters,parameters, + nb_arrays,arrays); + fprintf(file,"\n"); + + fprintf(file,"# ---------------------------------------------- "); + fprintf(file,"%2d.4 Body\n",number); + fprintf(file,"# Statement body is provided\n"); + fprintf(file,"1\n"); + if (statement->nb_iterators > 0) + { + fprintf(file,"# Original iterator names\n"); + for (i = 0; i < statement->nb_iterators; i++) + fprintf(file,"%s ",statement->iterators[i]); + fprintf(file,"\n"); + } + else + fprintf(file,"# No original iterator names\n"); + fprintf(file,"# Statement body\n"); + fprintf(file,"%s\n",statement->body); + fprintf(file,"\n\n"); + + statement = statement->next; + number++; + } +} + + + +/****************************************************************************** + * Reading function * + ******************************************************************************/ + +/** + * Internal function. Read 'nb_strings' strings on the input 'file'. + * + * \FIXME should be placed somewhere else, it's duplicated in scop.c. + */ +static +char** +scoplib_statement_read_strings(FILE* file, int nb_strings) +{ + char str[SCOPLIB_MAX_STRING]; + char tmp[SCOPLIB_MAX_STRING]; + char* s; + char** res = NULL; + int i; + int count; + + /* Skip blank/commented lines. */ + while (fgets(str, SCOPLIB_MAX_STRING, file) == 0 || str[0] == '#' || + isspace(str[0])) + ; + s = str; + + /* Allocate the array of string. Make it NULL-terminated. */ + res = (char**) malloc(sizeof(char*) * (nb_strings + 1)); + res[nb_strings] = NULL; + + /* Read the desired number of strings. */ + for (i = 0; i < nb_strings; ++i) + { + for (count = 0; *s && ! isspace(*s) && *s != '#'; ++count) + tmp[count] = *(s++); + tmp[count] = '\0'; + res[i] = strdup(tmp); + if (*s != '#') + ++s; + } + + return res; +} + +/** + * Internal function. Read an int on the input 'file'. + * + * \FIXME should be placed somewhere else, it's duplicated in scop.c. + */ +static +int +scoplib_statement_read_int(FILE* file) +{ + char s[SCOPLIB_MAX_STRING]; + int res; + + /* Skip blank/commented lines. */ + while (fgets(s, SCOPLIB_MAX_STRING, file) == 0 || s[0] == '#' || + isspace(s[0])) + ; + sscanf(s, "%d", &res); + + return res; +} + +char** scoplib_scop_generate_names(char*, int); + +/** + * scoplib_statement_read function: + * This function reads a scoplib_statement_t structure from an input stream + * (possibly stdin). + * \param file The input stream + * \param nb_parameters The number of global parameters for the program + * \param arrays The array containing names of arrays of the + * input program + * \param nb_arr The size of the array parameter + */ +scoplib_statement_p +scoplib_statement_read (FILE* file, int nb_parameters, char*** arrays, + int* nb_arr) +{ + scoplib_statement_p stmt = scoplib_statement_malloc(); + char** tmp; + + if (file) + { + /* Read the domain matrices. */ + stmt->domain = scoplib_matrix_list_read(file); + + /* Read the scattering, if any. */ + if (scoplib_statement_read_int(file) > 0) + stmt->schedule = scoplib_matrix_read(file); + + /* Read the access functions, if any. */ + if (scoplib_statement_read_int(file) > 0) + { + stmt->read = scoplib_matrix_read_arrays(file, arrays, nb_arr); + stmt->write = scoplib_matrix_read_arrays(file, arrays, nb_arr); + } + + stmt->nb_iterators = stmt->domain->elt->NbColumns - 2 - nb_parameters; + /* Read the body information, if any. */ + if (scoplib_statement_read_int(file) > 0) + { + if (stmt->nb_iterators > 0) + stmt->iterators = scoplib_statement_read_strings(file, + stmt->nb_iterators); + tmp = scoplib_statement_read_strings(file, 1); + stmt->body = tmp[0]; + free(tmp); + } + else + { + stmt->iterators = scoplib_scop_generate_names("i", + stmt->nb_iterators); + stmt->body = strdup("[undefined]"); + } + } + + return stmt; +} + + +/*+**************************************************************************** + * Memory allocation/deallocation functions * + ******************************************************************************/ + + +/** + * scoplib_statement_malloc function: + * This function allocates the memory space for a scoplib_statement_t structure + * and sets its fields with default values. Then it returns a pointer to the + * allocated space. + ** + * - 30/04/2008: first version. + */ +scoplib_statement_p +scoplib_statement_malloc() +{ + scoplib_statement_p statement; + + statement = (scoplib_statement_p)malloc(sizeof(scoplib_statement_t)); + if (statement == NULL) + { + fprintf(stderr, "[Scoplib] Memory Overflow.\n"); + exit(1); + } + + statement->domain = NULL; + statement->schedule = NULL; + statement->read = NULL; + statement->write = NULL; + statement->nb_iterators = 0; + statement->iterators = NULL; + statement->body = NULL; + statement->next = NULL; + + + /* Non-static code support specifics. */ + statement->exit_predicates = NULL; + statement->nb_exit_predicates = 0; + statement->control_predicates = NULL; + statement->nb_control_predicates = 0; + + return statement; +} + + +/** + * scoplib_statement_free function: + * This function frees the allocated memory for a scoplib_statement_t structure. + * \param statement The pointer to the statement we want to free. + ** + * - 30/04/2008: first version. + */ +void +scoplib_statement_free(scoplib_statement_p statement) +{ + int i; + scoplib_statement_p next; + + while (statement != NULL) + { + next = statement->next; + scoplib_matrix_list_free(statement->domain); + scoplib_matrix_free(statement->schedule); + scoplib_matrix_free(statement->read); + scoplib_matrix_free(statement->write); + if (statement->iterators != NULL) + { + for (i = 0; i < statement->nb_iterators; i++) + free(statement->iterators[i]); + free(statement->iterators); + } + if (statement->body != NULL) + free(statement->body); + + /* Non-static code support specifics. */ + if (statement->exit_predicates != NULL) + free(statement->exit_predicates); + if (statement->control_predicates != NULL) + free(statement->control_predicates); + + free(statement); + statement = next; + } +} + + +/*+**************************************************************************** + * Processing functions * + ******************************************************************************/ + + +/** + * scoplib_statement_add function: + * This function adds a statement "statement" at the end of the statement + * list pointed by "location". + * \param location Address of the first element of the statement list. + * \param statement The statement to add to the list. + ** + * - 30/04/2008: first version. + */ +void +scoplib_statement_add(scoplib_statement_p * location, + scoplib_statement_p statement) +{ + while (*location != NULL) + location = &((*location)->next); + + *location = statement; +} + + + +/** + * scoplib_statement_number function: + * This function returns the number of statements in the statement list + * provided as parameter. + * \param statement The first element of the statement list. + ** + * - 03/05/2008: first version. + */ +int +scoplib_statement_number(scoplib_statement_p statement) +{ + int number = 0; + + while (statement != NULL) + { + number++; + statement = statement->next; + } + return number; +} diff --git a/source/vector.c b/source/vector.c new file mode 100644 index 0000000..e72ad28 --- /dev/null +++ b/source/vector.c @@ -0,0 +1,330 @@ + + /*+------- <| --------------------------------------------------------** + ** A Clan/Scop ** + **--- /.\ -----------------------------------------------------** + ** <| [""M# vector.c ** + **- A | # -----------------------------------------------------** + ** /.\ [""M# First version: 01/05/2008 ** + **- [""M# | # U"U#U -----------------------------------------------** + | # | # \ .:/ + | # | #___| # + ****** | "--' .-" ****************************************************** + * |"-"-"-"-"-#-#-## Clan : the Chunky Loop Analyzer (experimental) * + **** | # ## ###### ***************************************************** + * \ .::::'/ * + * \ ::::'/ Copyright (C) 2008 Cedric Bastoul * + * :8a| # # ## * + * ::88a ### This is free software; you can redistribute it * + * ::::888a 8a ##::. and/or modify it under the terms of the GNU Lesser * + * ::::::::888a88a[]::: General Public License as published by the Free * + *::8:::::::::SUNDOGa8a::. Software Foundation, either version 2.1 of the * + *::::::::8::::888:Y8888:: License, or (at your option) any later version. * + *::::':::88::::888::Y88a::::::::::::... * + *::'::.. . ..... .. ... . * + * This software 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 General Public License * + * for more details. * + * * + * You should have received a copy of the GNU Lesser General Public License * + * along with software; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * * + * Clan, the Chunky Loop Analyzer * + * Written by Cedric Bastoul, Cedric.Bastoul@inria.fr * + * * + ******************************************************************************/ + + +# include +# include +# include +# include + + +/*+**************************************************************************** + * Structure display function * + ******************************************************************************/ + + +/** + * scoplib_vector_print_structure function: + * Displays a scoplib_vector_t structure (*vector) into a file (file, possibly + * stdout) in a way that trends to be understandable without falling in a deep + * depression or, for the lucky ones, getting a headache... It includes an + * indentation level (level) in order to work with others print_structure + * functions. + * \param file File where informations are printed. + * \param vector The vector whose information have to be printed. + * \param level Number of spaces before printing, for each line. + ** + * - 01/05/2008: first version. + */ +void +scoplib_vector_print_structure(FILE * file, scoplib_vector_p vector, int level) +{ + int j; + + if (vector != NULL) + { + /* Go to the right level. */ + for (j = 0; j < level; j++) + fprintf(file,"|\t"); + fprintf(file,"+-- scoplib_vector_t\n"); + + for (j = 0; j <= level; j++) + fprintf(file,"|\t"); + fprintf(file,"%d\n",vector->Size); + + /* Display the vector. */ + for (j = 0; j <= level; j++) + fprintf(file,"|\t"); + + fprintf(file,"[ "); + + for (j = 0; j < vector->Size; j++) + { + SCOPVAL_print(file,SCOPLIB_FMT,vector->p[j]); + fprintf(file," "); + } + + fprintf(file,"]\n"); + } + else + { + /* Go to the right level. */ + for (j = 0; j < level; j++) + fprintf(file,"|\t"); + fprintf(file,"+-- NULL vector\n"); + } + + /* The last line. */ + for (j = 0; j <= level; j++) + fprintf(file,"|\t"); + fprintf(file,"\n"); +} + + +/** + * scoplib_vector_print function: + * This function prints the content of a scoplib_vector_t structure + * (*vector) into a file (file, possibly stdout). + * \param file File where informations are printed. + * \param vector The vector whose information have to be printed. + ** + * - 01/05/2008: first version. + */ +void +scoplib_vector_print(FILE * file, scoplib_vector_p vector) +{ + scoplib_vector_print_structure(file,vector,0); +} + + +/*+**************************************************************************** + * Memory allocation/deallocation function * + ******************************************************************************/ + + +/** + * scoplib_vector_malloc function: + * This function allocates the memory space for a scoplib_vector_t structure and + * sets its fields with default values. Then it returns a pointer to the + * allocated space. + * \param Size The number of entries of the vector to allocate. + ** + * - 01/05/2008: first version. + */ +scoplib_vector_p +scoplib_vector_malloc(unsigned Size) +{ + scoplib_vector_p vector; + scoplib_int_t * p; + int i ; + + vector = (scoplib_vector_p)malloc(sizeof(scoplib_vector_t)); + if (vector == NULL) + { + fprintf(stderr, "[Scoplib] Memory Overflow.\n"); + exit(1); + } + vector->Size = Size; + if (Size == 0) + vector->p = NULL; + else + { + p = (scoplib_int_t *)malloc(Size * sizeof(scoplib_int_t)); + if (p == NULL) + { + fprintf(stderr, "[Scoplib] Memory Overflow.\n"); + exit(1); + } + vector->p = p; + for (i = 0; i < Size; i++) + SCOPVAL_init_set_si(vector->p[i],0); + } + return vector; +} + + +/** + * scoplib_vector_free function: + * This function frees the allocated memory for a scoplib_vector_t structure. + * \param vector The pointer to the vector we want to free. + ** + * - 01/05/2008: first version. + */ +void +scoplib_vector_free(scoplib_vector_p vector) +{ + int i; + scoplib_int_t * p; + + if (vector != NULL) + { + p = vector->p; + for (i = 0; i < vector->Size; i++) + SCOPVAL_clear(*p++); + + free(vector->p); + free(vector); + } +} + + +/*+**************************************************************************** + * Processing functions * + ******************************************************************************/ + +/** + * scoplib_vector_add_scalar function: + * This function adds a scalar to the vector representation of an affine + * expression (this means we add the scalar only to the very last entry of the + * vector). It returns a new vector resulting from this addition. + * \param vector The basis vector. + * \param scalar The scalar to add to the vector. + ** + * - 01/05/2008: first version. + */ +scoplib_vector_p +scoplib_vector_add_scalar(scoplib_vector_p vector, int scalar) +{ + int i; + scoplib_vector_p result; + + if ((vector == NULL) || (vector->Size < 2)) + { + fprintf(stderr,"[Scoplib] Error: incompatible vector for addition\n"); + exit(1); + } + + result = scoplib_vector_malloc(vector->Size); + for (i = 0; i < vector->Size; i++) + SCOPVAL_assign(result->p[i],vector->p[i]); + SCOPVAL_add_int(result->p[vector->Size - 1], + vector->p[vector->Size - 1],scalar); + + return result; +} + + +/** + * scoplib_vector_add function: + * This function achieves the addition of two vectors and returns the + * result as a new vector (the addition means the ith entry of the new vector + * is equal to the ith entry of vector v1 plus the ith entry of vector v2). + * \param v1 The first vector for the addition. + * \param v2 The second vector for the addition (result is v1+v2). + ** + * - 01/05/2008: first version. + */ +scoplib_vector_p +scoplib_vector_add(scoplib_vector_p v1, scoplib_vector_p v2) +{ + int i; + scoplib_vector_p v3; + + if ((v1 == NULL) || (v2 == NULL) || (v1->Size != v2->Size)) + { + fprintf(stderr,"[Scoplib] Error: incompatible vectors for addition\n"); + exit(1); + } + + v3 = scoplib_vector_malloc(v1->Size); + for (i = 0; i < v1->Size; i++) + SCOPVAL_addto(v3->p[i],v1->p[i],v2->p[i]); + + return v3; +} + + +/** + * scoplib_vector_sub function: + * This function achieves the subtraction of two vectors and returns the + * result as a new vector (the addition means the ith entry of the new vector + * is equal to the ith entry of vector v1 minus the ith entry of vector v2). + * \param v1 The first vector for the subtraction. + * \param v2 The second vector for the subtraction (result is v1-v2). + ** + * - 01/05/2008: first version. + */ +scoplib_vector_p +scoplib_vector_sub(scoplib_vector_p v1, scoplib_vector_p v2) +{ + int i; + scoplib_vector_p v3; + + if ((v1 == NULL) || (v2 == NULL) || (v1->Size != v2->Size)) + { + fprintf(stderr,"[Scoplib] Error: incompatible vectors for subtraction\n"); + exit(1); + } + + v3 = scoplib_vector_malloc(v1->Size); + for (i = 0; i < v1->Size; i++) + SCOPVAL_subtract(v3->p[i],v1->p[i],v2->p[i]); + + return v3; +} + + +/** + * scoplib_vector_tag_inequality function: + * This function tags a vector representation of a contraint as being an + * inequality >=0. This means in the PolyLib format, to set to 1 the very first + * entry of the vector. It modifies directly the vector provided as an argument. + * \param vector The vector to be tagged. + ** + * - 01/05/2008: first version. + */ +void +scoplib_vector_tag_inequality(scoplib_vector_p vector) +{ + if ((vector == NULL) || (vector->Size < 1)) + { + fprintf(stderr,"[Scoplib] Error: vector cannot be tagged\n"); + exit(1); + } + SCOPVAL_set_si(vector->p[0],1); +} + + +/** + * scoplib_vector_tag_equality function: + * This function tags a vector representation of a contraint as being an + * equality ==0. This means in the PolyLib format, to set to 0 the very first + * entry of the vector. It modifies directly the vector provided as an argument. + * \param vector The vector to be tagged. + ** + * - 01/05/2008: first version. + */ +void +scoplib_vector_tag_equality(scoplib_vector_p vector) +{ + if ((vector == NULL) || (vector->Size < 1)) + { + fprintf(stderr,"[Scoplib] Error: vector cannot be tagged\n"); + exit(1); + } + SCOPVAL_set_si(vector->p[0],0); +} -- 2.11.4.GIT