diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bd186a6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +# Emacs auto save files +*~ +# Generated files by autotools +*.in +aclocal.m4 +autom4te.cache/ +build/ +build-aux/ +configure +m4/ diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..b88804f --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +Johan Oudinet diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, 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 +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state 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 program is free software: you can redistribute it and/or modify + it under the terms of the GNU 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..2d77e2d --- /dev/null +++ b/ChangeLog @@ -0,0 +1,232 @@ +2012-11-12 Johan Oudinet + + Fix a bug in simplification rule 5. + * include/qdft/manager.hxx: Do not apply simplification rule 5 if + u2 has children or other parents than u and s. + * src/example.cc: test for the DAG issue with simplification rule + 5. + +2012-09-25 Johan Oudinet + + Provide a simulator for file transfers. + * src/test_lib.cc: small program to simulate file transfers among + sensitive and non-sensitive containers. + +2012-09-10 Johan Oudinet + + Fix reverting a transfer (c2v mapping was incorrect afterward) and + reverting a simplification rule attached to the source (use + current_src_ instead of src_). + * include/qdft/action.hh: Fix two bugs while reverting a transfer + or a simplification rule 1. + +2012-09-07 Johan Oudinet + + Apply simplification rules on demand. Call max-flow algorithm only + when necessary. + * include/qdft/manager.hxx: Call max-flow only when transferring + to an existing container. Apply simplification rules only if the + SIMPLIFY variable is set. + +2012-09-06 Johan Oudinet + + Implement simplification rule 5 and fix reverting simplification + rule 3 when the child has other parents. + * include/qdft/manager.hxx: Implement simplification rule 5 + * include/qdft/action.hh: Add the rollback for simplification rule + 5 and fix the rollback for simplification rule 3. + * src/example.cc (main): Test rollback for simplification rule 3 + and 5. + +2012-07-27 Johan Oudinet + + Add support for reverting any action (with possibility several + simplification rules). + * include/qdft/qdft.hh, + * include/qdft/qdft.hxx, + * include/qdft/manager.hh, + * include/qdft/manager.hxx: Rename revert_last_transfer into + revert_last_action. + * include/qdft/action.hh: Add the rollback for every + simplification rule. + * src/example.cc: Test rollback of every simplification rule. + +2012-07-25 Johan Oudinet + + Add simplification rules 3 and 4. + * include/qdft/manager.hxx: Add simplification rules. + +2012-07-24 Johan Oudinet + + New rollback system to revert the last action. + * include/qdft/qdft.hh, + * include/qdft/qdft.hxx, + * include/qdft/manager.hh, + * include/qdft/manager.hxx: Remove deprecated remove method (has + been replaced by truncate). Use a stack of actions to record the + previous actions in case a rollback is needed. + * include/Makefile.am, + * include/qdft/action.hh: New. + * src/example.cc: Test the rollback feature. + +2012-07-23 Johan Oudinet + + Provide a new (correct) behavior for transferring and add the + truncate method. + * include/qdft/qdft.hh, + * include/qdft/qdft.hxx, + * include/qdft/manager.hh, + * include/qdft/manager.hxx: Change the transfer behavior and add + the truncate method. + * src/example.cc: Test the new interface. + +2012-07-03 Johan Oudinet + + Fix priority issue in a check for self loop. + * include/qdft/manager.hxx (qdft): Add parentheses. + +2012-06-27 Johan Oudinet + + Avoid self loops in the graph. Otherwise, the maxflow algorithm + will fail. + * include/qdft/manager.hh, + * include/qdft/manager.hxx: do not transfer if src == dst. + +2011-12-02 Johan Oudinet + + Fix the bug that leads to a chain of fake sources. + * include/qdft/manager.hxx (set_data_amount): Call + remove_vertex_rec_ on the old source every time. + * src/test_lib.cc: Test that the bug, which appeared in last mode, + disappear. + +2011-11-25 Johan Oudinet + + Provide a third mode for updating the total amount of data. + * include/qdft/manager.hxx: Three modes for updating amount of data. + * include/qdft/types.hh: Rename the two previous modes and add the + third one. + * src/test_lib.cc: Test for the three modes. + * script/qdftgraph_pp.sh: Add the index to src_ nodes in order to + distinguish them. + +2011-11-23 Johan Oudinet + + Pretty printing for graphs. + * include/qdft/qdft.hh, + * include/qdft/qdft.hxx, + * include/qdft/manager.hh, + * include/qdft/manager.hxx: Provide save method for saving into a file. + * src/test_lib.cc: Tests for pretty printing. + * script/qdftgraph_pp.sh: New. + +2011-11-22 Johan Oudinet + + Add the possibility to assign a specific name when creating a new + data. + * include/qdft/qdft.hh, + * include/qdft/qdft.hxx: Can assign a specific name when creating + a new data. + * src/test_lib.cc: Tests for updating the amount of data. + +2011-11-21 Johan Oudinet + + Provide interface for updating the amount of data. + * include/qdft/qdft.hh, + * include/qdft/qdft.hxx, + * include/qdft/manager.hh, + * include/qdft/manager.hxx: Two modes for updating amount of data. + * include/qdft/types.hh: Two modes as a enum type. + * src/test_lib.cc: Tests for updating the amount of data. + +2011-11-11 Johan Oudinet + + New method for reverting the last transfer. + * include/qdft/qdft.hh, + * include/qdft/qdft.hxx, + * include/qdft/manager.hh, + * include/qdft/manager.hxx: New revert_last_transfer method. + * src/test_lib.cc: Tests for this method. + +2011-11-11 Johan Oudinet + + Provide a method to get the initial amount of data. + * include/qdft/qdft.hh, + * include/qdft/qdft.hxx, + * include/qdft/manager.hh, + * include/qdft/manager.hxx: Add get_initial_quantity method. + * src/test_lib.cc: Tests for this method. + +2011-11-11 Johan Oudinet + + New interface for handling multiple data and the library is now + available as a shared library too. + * include/qdft/qdft.hxx: New interface for handling multiple data. + * src/test_lib.cc: Tests for the new interface. + * configure.ac, + * include/Makefile.am, + * Makefile.am, + * src/Makefile.am: Use libtool for shared library. + * include/qdft/types.hh: New dname_type (std::string). + +2011-09-01 Johan Oudinet + + Provide API to set the capacity of an edge. + * include/qdft/manager.hh, + * include/qdft/manager.hxx: New set_edge_capacity method. transfer + returns the previous edge capacity. + +2011-09-01 Johan Oudinet + + Recursively delete fake vertices after removing one vertex. + * include/qdft/manager.hxx (remove): Use real_out_degree instead + of out_degree. Try to delete the father if the child was deleted. + +2011-08-30 Johan Oudinet + + Update the vertex indexes after deleting a vertex. + * include/qdft/manager.hh, + * include/qdft/manager.hxx (remove_vertex_): Handle the deletion + of a vertex in this private method. + +2011-08-29 Johan Oudinet + + Use Doxygen for the documentation. + * doc/Doxyfile.in: New. + * doc/Makefile.am: New. + +2011-08-29 Johan Oudinet + + Fix a bug that could appear when a container is removed. + * include/qdft/manager.hxx (remove): Fix bug when deleting nodes. + +2011-08-29 Johan Oudinet + + Container's name are now represented by strings instead of size_t. + * include/qdft/types.hh: Change cname_type to std::string. + * include/qdft/manager.hh: Provide a hash function for const + string and use const type as the hash_map key. + * src/example.cc: Adapt the example to use strings for container's + names. + +2011-08-10 Johan Oudinet + + Initial version. + * AUTHORS: New. + * bootstrap.sh: New. + * ChangeLog: New. + * configure.ac: New. + * COPYING: New. + * include/Makefile.am: New. + * include/qdft/graph.hh: New. + * include/qdft/manager.hh: New. + * include/qdft/manager.hxx: New. + * include/qdft/qdft.hh: New. + * include/qdft/types.hh: New. + * INSTALL: New. + * m4/boost.m4: New. + * Makefile.am: New. + * NEWS: New. + * README: New. + * src/example.cc: New. + * src/Makefile.am: New. diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..a1e89e1 --- /dev/null +++ b/INSTALL @@ -0,0 +1,370 @@ +Installation Instructions +************************* + +Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation, +Inc. + + Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. This file is offered as-is, +without warranty of any kind. + +Basic Installation +================== + + Briefly, the shell commands `./configure; make; make install' should +configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. Some packages provide this +`INSTALL' file but do not implement all of the features documented +below. The lack of an optional feature in a given package is not +necessarily a bug. More recommendations for GNU packages can be found +in *note Makefile Conventions: (standards)Makefile Conventions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. Caching is +disabled by default to prevent problems with accidental use of stale +cache files. + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You need `configure.ac' if +you want to change it or regenerate `configure' using a newer version +of `autoconf'. + + The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. + + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package, generally using the just-built uninstalled binaries. + + 4. Type `make install' to install the programs and any data files and + documentation. When installing into a prefix owned by root, it is + recommended that the package be configured and built as a regular + user, and only the `make install' phase executed with root + privileges. + + 5. Optionally, type `make installcheck' to repeat any self-tests, but + this time using the binaries in their final installed location. + This target does not install anything. Running this target as a + regular user, particularly if the prior `make install' required + root privileges, verifies that the installation completed + correctly. + + 6. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + + 7. Often, you can also type `make uninstall' to remove the installed + files again. In practice, not all packages have tested that + uninstallation works correctly, even though it is required by the + GNU Coding Standards. + + 8. Some packages, particularly those that use Automake, provide `make + distcheck', which can by used by developers to test that all other + targets like `make install' and `make uninstall' work correctly. + This target is generally not run by end users. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c99 CFLAGS=-g LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you can use GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. This +is known as a "VPATH" build. + + With a non-GNU `make', it is safer to compile the package for one +architecture at a time in the source code directory. After you have +installed the package for one architecture, use `make distclean' before +reconfiguring for another architecture. + + On MacOS X 10.5 and later systems, you can create libraries and +executables that work on multiple system types--known as "fat" or +"universal" binaries--by specifying multiple `-arch' options to the +compiler but only a single `-arch' option to the preprocessor. Like +this: + + ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CPP="gcc -E" CXXCPP="g++ -E" + + This is not guaranteed to produce working output in all cases, you +may have to build one architecture at a time and combine the results +using the `lipo' tool if you have problems. + +Installation Names +================== + + By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX', where PREFIX must be an +absolute file name. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. In general, the +default for these options is expressed in terms of `${prefix}', so that +specifying just `--prefix' will affect all of the other directory +specifications that were not explicitly provided. + + The most portable way to affect installation locations is to pass the +correct locations to `configure'; however, many packages provide one or +both of the following shortcuts of passing variable assignments to the +`make install' command line to change installation locations without +having to reconfigure or recompile. + + The first method involves providing an override variable for each +affected directory. For example, `make install +prefix=/alternate/directory' will choose an alternate location for all +directory configuration variables that were expressed in terms of +`${prefix}'. Any directories that were specified during `configure', +but not in terms of `${prefix}', must each be overridden at install +time for the entire installation to be relocated. The approach of +makefile variable overrides for each directory variable is required by +the GNU Coding Standards, and ideally causes no recompilation. +However, some platforms have known limitations with the semantics of +shared libraries that end up requiring recompilation when using this +method, particularly noticeable in packages that use GNU Libtool. + + The second method involves providing the `DESTDIR' variable. For +example, `make install DESTDIR=/alternate/directory' will prepend +`/alternate/directory' before all installation names. The approach of +`DESTDIR' overrides is not required by the GNU Coding Standards, and +does not work on platforms that have drive letters. On the other hand, +it does better at avoiding recompilation issues, and works well even +when some directory options were not specified in terms of `${prefix}' +at `configure' time. + +Optional Features +================= + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + + Some packages offer the ability to configure how verbose the +execution of `make' will be. For these packages, running `./configure +--enable-silent-rules' sets the default to minimal output, which can be +overridden with `make V=1'; while running `./configure +--disable-silent-rules' sets the default to verbose, which can be +overridden with `make V=0'. + +Particular systems +================== + + On HP-UX, the default C compiler is not ANSI C compatible. If GNU +CC is not installed, it is recommended to use the following options in +order to use an ANSI C compiler: + + ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" + +and if that doesn't work, install pre-built binaries of GCC for HP-UX. + + HP-UX `make' updates targets which have the same time stamps as +their prerequisites, which makes it generally unusable when shipped +generated files such as `configure' are involved. Use GNU `make' +instead. + + On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot +parse its `' header file. The option `-nodtk' can be used as +a workaround. If GNU CC is not installed, it is therefore recommended +to try + + ./configure CC="cc" + +and if that doesn't work, try + + ./configure CC="cc -nodtk" + + On Solaris, don't put `/usr/ucb' early in your `PATH'. This +directory contains several dysfunctional programs; working variants of +these programs are available in `/usr/bin'. So, if you need `/usr/ucb' +in your `PATH', put it _after_ `/usr/bin'. + + On Haiku, software installed for all users goes in `/boot/common', +not `/usr/local'. It is recommended to use the following options: + + ./configure --prefix=/boot/common + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS + KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the option `--target=TYPE' to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). + +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf bug. Until the bug is fixed you can use this workaround: + + CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of all of the options to `configure', and exit. + +`--help=short' +`--help=recursive' + Print a summary of the options unique to this package's + `configure', and exit. The `short' variant lists options used + only in the top level, while the `recursive' variant lists options + also present in any nested packages. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--prefix=DIR' + Use DIR as the installation prefix. *note Installation Names:: + for more details, including other options available for fine-tuning + the installation locations. + +`--no-create' +`-n' + Run the configure checks, but stop before creating any output + files. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..cb83cf2 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,19 @@ +# Copyright (C) 2011 Johan Oudinet +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 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. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +ACLOCAL_AMFLAGS = -I m4 + +SUBDIRS = include src doc diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..cf373bd --- /dev/null +++ b/NEWS @@ -0,0 +1,13 @@ +2011-11-21: + Provide interface for updating the amount of data. + +2011-08-29: + Containers are represented by strings instead of unsigned int. + +2011-08-10: + Initial version. + + * qdft/Manager.hh: Provide the main functionalities for data flow + tracking of the same data. + + * src/example.cc: Shows an example how to use the library. \ No newline at end of file diff --git a/README b/README new file mode 100644 index 0000000..cba73a9 --- /dev/null +++ b/README @@ -0,0 +1,49 @@ + ________ ______________________ .__ + _____\______ \ \_ _____/\__ ___/_______________ ______ | |__ + / ____/| | \ | __) | | / ___\_ __ \__ \ \____ \| | \ +< <_| || ` \| \ | |/ /_/ > | \// __ \| |_> > Y \ + \__ /_______ /\___ / |____|\___ /|__| (____ / __/|___| / + |__| \/ \/ /_____/ \/|__| \/ + +---------------------------------------------------------------------- + +Quantitive Data Flow Tracking graph (qDFTgraph) library. + +1) How to install +2) How to use it + +*** HOW TO INSTALL *** + + For general free software install rules, please refer to INSTALL + file. This C++ library is based on Boost Graph Library (BGL). You + need a recent installation of this library and in case of a manual + installation you might need to tell to qDFTgraph where is located + your Boost installation. For example: + + If you've installed one of the required libraries in a non classical + path, you may need to tell to configure how to find it. For example, + assume BGL headers are in $HOME/include and BGL libraries are in + $HOME/lib, the following command tell to configure where they are: + ./configure --with-boost=$HOME + +** Tips on manual installation of Boost library ** + + under a Unix-like system: + extract boost archive then go in it and enter the two following + commands: + $ ./bootstrap.sh --prefix=$HOME + $ ./b2 install + $ sudo ldconfig $HOME/lib + + Now Boost is correctly installed in your $HOME directory. You just + have to tell to configure where to look for (as explained + previously). + +*** HOW TO USE IT *** + + qDFTgraph is a header library, then it does not need to be compiled + first. The only thing needed is to include qdft.hh header in your + program. A example is provided inside src directory. Look at + src/example.cc for further information. + + src/test_lib.cc is a file transfer simulator. It simulates transfers + of different sizes between a set of files. \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index 7781d01..0000000 --- a/README.md +++ /dev/null @@ -1,4 +0,0 @@ -qdftgraph -========= - -Provenance graph for quantitative data-flow tracking diff --git a/bootstrap.sh b/bootstrap.sh new file mode 100755 index 0000000..17989c5 --- /dev/null +++ b/bootstrap.sh @@ -0,0 +1,3 @@ +#! /bin/sh + +autoreconf -fvi diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..05487e5 --- /dev/null +++ b/configure.ac @@ -0,0 +1,56 @@ +# Copyright (C) KIT, Johan Oudinet - 2011 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 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. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +AC_PREREQ(2.61) +AC_INIT([qdftgraph], [0.3], [oudinet@kit.edu]) +AC_CONFIG_AUX_DIR([build-aux]) +AC_CONFIG_MACRO_DIR([m4]) +AM_INIT_AUTOMAKE([1.10 -Wall -Werror tar-ustar no-define dist-bzip2 nostdinc]) +LT_INIT([disable-static]) + +# Checks for programs. +AC_PROG_CXX + +# Documentation +AC_CHECK_PROGS([DOXYGEN], [doxygen]) +if test -z "$DOXYGEN"; + then AC_MSG_WARN([Doxygen not found - continuing without Doxygen support]) +fi + +# Attempt to use strict language conformance checking. +AC_CXX_FLAGS + +# Use libtool +AC_PROG_LIBTOOL +AC_LIBTOOL_WIN32_DLL + +# Test for BOOST graph library using Tsuna's boost.m4 macro file +BOOST_REQUIRE([1.47.0]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST + +AM_CONDITIONAL([HAVE_DOXYGEN], [test -n "$DOXYGEN"]) +AM_COND_IF([HAVE_DOXYGEN], [AC_CONFIG_FILES([doc/Doxyfile])]) + +AC_CONFIG_FILES([ + Makefile + include/Makefile + src/Makefile + doc/Makefile +]) + +AC_OUTPUT diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in new file mode 100644 index 0000000..b7e9d1a --- /dev/null +++ b/doc/Doxyfile.in @@ -0,0 +1,1630 @@ +# Doxyfile 1.7.1 + +# 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 = @PACKAGE_NAME@ + +# 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 = + +# 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, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +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 = NO + +# 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 = NO + +# 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 = @top_srcdir@/include/ + +# 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 = YES + +# 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 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 + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# 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 = YES + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# 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 + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penality. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will rougly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# 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 = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# 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 FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# 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_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = 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 + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# 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 = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# 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 = NO + +# 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@/include/ + +# 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 *.f90 + +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 = YES + +# 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 = YES + +# 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. + +SOURCE_BROWSER = YES + +# 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 +# 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 +# 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 documentation. + +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 = YES + +# 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 = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the stylesheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# 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 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_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# 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 compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = 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 CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# 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 + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# 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 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value 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 (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = 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 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvances is that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# 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. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +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 = YES + +# 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 = YES + +# 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 + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = 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 = NO + +# 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 = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans.ttf + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# 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 and HAVE_DOT options 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 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 = + +# 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 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 +# DOT_GRAPH_MAX_NODES 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, because dot on Windows does not +# seem to support this out of the box. 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 = YES + +# 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 diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..0d5b147 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,18 @@ +if HAVE_DOXYGEN +directory = $(top_srcdir)/doc/man/man3/ + +dist_man_MANS = $(directory)/man_page_1.3 $(directory)/man_page_2.3 +$(directory)/man_page_1.3: doxyfile.stamp +$(directory)/man_page_2.3: doxyfile.stamp + +doxyfile.stamp: + $(DOXYGEN) Doxyfile + touch doxyfile.stamp + +CLEANFILES = doxyfile.stamp + +all-local: doxyfile.stamp +clean-local: + rm -rf $(top_srcdir)/doc/man + rm -f doxyfile.stamp +endif diff --git a/include/Makefile.am b/include/Makefile.am new file mode 100644 index 0000000..8ab5f66 --- /dev/null +++ b/include/Makefile.am @@ -0,0 +1,40 @@ +# Copyright (C) 2011, 2012 Johan Oudinet +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 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. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + +AM_CPPFLAGS = -I$(srcdir)/../include $(BOOST_CPPFLAGS) + +lib_LTLIBRARIES = libqdftgraph.la + +libqdftgraph_la_SOURCES = \ +qdft/action.hh \ +qdft/graph.hh \ +qdft/manager.hh \ +qdft/manager.hxx \ +qdft/qdft.hh \ +qdft/qdft.hxx \ +qdft/types.hh \ +qdft/qdft_wrap.cxx + +libqdftgraph_la_LDFLAGS = -no-undefined + +nobase_include_HEADERS = \ +qdft/qdft.i \ +qdft/libqdftgraph.cs \ +qdft/libqdftgraphPINVOKE.cs \ +qdft/dataManagers.cs \ +qdft/mode_type.cs \ +qdft/SWIGTYPE_p_std__ostream.cs diff --git a/include/qdft/action.hh b/include/qdft/action.hh new file mode 100644 index 0000000..899b905 --- /dev/null +++ b/include/qdft/action.hh @@ -0,0 +1,466 @@ +// Copyright (C) 2012 Johan Oudinet +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 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. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +#ifndef QDFT_ACTION_HH +# define QDFT_ACTION_HH +# include +# include +# include +# include +# include + +namespace qdft { + namespace action { + struct init {}; + + struct transfer + { + transfer (const cname_type& c1, const cname_type& c2): c_src(c1), c_dst(c2) {} + cname_type c_src, c_dst; + }; + + struct truncate + { + truncate (const cname_type& u, + const quantity_type& qold, + const quantity_type& qnew): + u_(u), qold_(qold), qnew_(qnew) {} + cname_type u_; + quantity_type qold_, qnew_; + }; + + struct simplify1 + { + typedef std::pair fakeparent_type; + typedef std::map fakeparents_type; + typedef std::vector > realparents_type; + simplify1 (const cname_type& ui, + const quantity_type& qi, + const realparents_type& real_parentsi, + const fakeparents_type& fake_parentsi): + u(ui), q(qi), realparents(real_parentsi), fakeparents(fake_parentsi) {} + cname_type u; + quantity_type q; + realparents_type realparents; + fakeparents_type fakeparents; + }; + + struct simplify2 + { + simplify2 (const cname_type& c1, + const cname_type& c2, + const cname_type& u, + const quantity_type& q, + const quantity_type& n1, + const quantity_type& n2, + const quantity_type& n3): + src(c1), dst(c2), u_name(u), u_q(q), e1(n1), e2(n2), e3(n3) {} + cname_type src, dst; + cname_type u_name; + quantity_type u_q; + quantity_type e1, e2, e3; + }; + + struct simplify3 + { + typedef std::vector< std::pair > parents_type; + typedef std::vector< std::pair > capacities_type; + simplify3 (const cname_type& ci, + const cname_type& ui, + const quantity_type& qi, + const parents_type& parentsi, + const capacities_type& capacitiesi): + c(ci), u(ui), q(qi), parents(parentsi), capacities(capacitiesi) {} + cname_type c, u; + quantity_type q; + parents_type parents; + capacities_type capacities; + }; + + struct simplify4 + { + typedef std::pair fakechild_type; + typedef std::map > fakechildren_type; + typedef std::map > realchildren_type; + typedef boost::graph_traits::vertex_descriptor vertex_descriptor; + simplify4(vertex_descriptor s, + const quantity_type& x, + const cname_type& u, + const quantity_type& q, + const realchildren_type& realchildren, + const fakechildren_type& fakechildren): + s_(s), x_(x), u_(u), q_(q), realchildren_(realchildren), fakechildren_(fakechildren) {} + vertex_descriptor s_; + quantity_type x_; + cname_type u_; + quantity_type q_; + realchildren_type realchildren_; + fakechildren_type fakechildren_; + }; + + struct simplify5 + { + typedef boost::graph_traits::vertex_descriptor vertex_descriptor; + simplify5 (const vertex_descriptor& u2i, + const cname_type& ui, + const quantity_type& qi, + const quantity_type& n1, + const quantity_type& n2): + u2(u2i), u_n(ui), u_q(qi), e1(n1), e2(n2) {} + vertex_descriptor u2; + cname_type u_n; + quantity_type u_q; + quantity_type e1, e2; + }; + + template + class revert : public boost::static_visitor + { + typedef boost::graph_traits Traits; + typedef typename Traits::vertex_descriptor vertex_descriptor; + typedef typename Traits::edge_descriptor edge_descriptor; + // typedef typename Traits::in_edge_iterator in_edge_iterator; + // typedef typename boost::inv_adjacency_iterator_generator::type inv_adjacency_iterator; + public: + revert (Graph& g, Map& m, vertex_descriptor src): g_(g), c2v_(m), src_(src) {} + + void operator() (const init& action) const + { + assert (false); + } + + void operator() (const transfer& action) const + { + vertex_descriptor u, v, vold; + bool vold_ok = false; + std::cerr << "[QDFTgraph] Reverting last transfer from " << action.c_src + << " to " << action.c_dst << std::endl; + typename Map::const_iterator it = c2v_.find (action.c_src); + typename Map::iterator jt = c2v_.find (action.c_dst); + assert (it != c2v_.end ()); + assert (jt != c2v_.end ()); + u = it->second; + v = jt->second; + // look for vold from v + BGL_FORALL_INEDGES_T(v, e, g_, Graph) + { + if (g_[e].transfered > 0) + { + vold = source (e, g_); + if (g_[vold].fake && (g_[vold].name == g_[v].name)) + { + vold_ok = true; + break; + } + } + } + if (vold_ok) + { + g_[vold].fake = false; + jt->second = vold; + } + else + { + c2v_.erase(jt); + } + clear_vertex (v, g_); + remove_vertex (v, g_); + } + + void operator() (const truncate& action) const + { + std::cerr << "[QDFTgraph] Reverting last truncate of " << action.u_ + << " (old=" << action.qold_ << ", new=" << action.qnew_ << ")" + << std::endl; + if (action.qnew_ > 0) + { + vertex_descriptor u, uold; + typename Map::iterator it = c2v_.find (action.u_); + assert (it != c2v_.end ()); + u = it->second; + // look for uold from u + BGL_FORALL_INEDGES_T(u, e, g_, Graph) + { + if (g_[e].transfered == action.qnew_ && g_[u].name == g_[source (e, g_)].name) + { + uold = source (e, g_); + g_[uold].fake = false; + it->second = uold; + break; + } + } + clear_vertex (u, g_); + remove_vertex (u, g_); + } + else + { // container has been deleted + BGL_FORALL_VERTICES_T(u, g_, Graph) + { + if (g_[u].fake && (g_[u].name == action.u_) && (g_[u].amount == action.qold_)) + { + g_[u].fake = false; + c2v_[action.u_] = u; + break; + } + } + } + } + + void operator() (const simplify1& action) const + { + // From s,s' + // To s,s'-> u + std::cerr << "[QDFTgraph] Reverting last simplify1 of " << action.u + << " (" << action.q << ")" << std::endl; + vertex_descriptor s, u; + u = add_vertex (detail::node (41, // must be updated afterward + action.q, action.u, true), g_); + // Reconnect u to its (real) parents + for (simplify1::realparents_type::const_iterator rp = action.realparents.begin (); + rp != action.realparents.end (); ++rp) + { + typename Map::const_iterator it = c2v_.find (rp->first); + if (it != c2v_.end ()) + s = it->second; + else + { + assert (rp->first == "src_"); + s = src_; + } + add_edge (s, u, detail::transition (rp->second), g_); + add_edge (u, s, g_); // fake edge for max_flow algo + } + // Reconnect u to its (fake) parents + if (!action.fakeparents.empty ()) + { + // make a mutable copy of action.fakeparents + simplify1::fakeparents_type fakeparents (action.fakeparents); + BGL_FORALL_VERTICES_T(v, g_, Graph) + { + if (g_[v].fake) + { + simplify1::fakeparents_type::iterator fp + = fakeparents.find (std::make_pair (g_[v].name, + g_[v].amount)); + if (fp != fakeparents.end ()) + { + // v is one of the fakeparents of u + add_edge (v, u, detail::transition (fp->second), g_); + add_edge (u, v, g_); // fake edge for max_flow algo + fakeparents.erase (fp); + } + } + } + } + } + + void operator() (const simplify2& action) const + { + // from s --x-->t + // to s --e1-> u --e2-> t (and may also have s --e3-> t) + // s could be equal to t! + vertex_descriptor s, t, u; + bool s_ok = false; + std::cerr << "[QDFTgraph] Reverting last simplify2 from " << action.src + << " to " << action.dst << std::endl; + typename Map::const_iterator jt = c2v_.find (action.dst); + assert (jt != c2v_.end ()); + t = jt->second; + u = add_vertex (detail::node (42, // must be updated afterward + action.u_q, action.u_name, true), g_); + // look for s from t + BGL_FORALL_INEDGES_T(t, e, g_, Graph) + { + if (g_[e].transfered > 0) + { + s = source (e, g_); + if (g_[s].name == action.src) + { + s_ok = true; + break; + } + } + } + if (!s_ok) + { + assert(action.src == action.dst); + assert(action.e3 == 0); + s = t; + } + add_edge (s, u, detail::transition (action.e1), g_); + add_edge (u, s, g_); // fake edge for max_flow algo + add_edge (u, t, detail::transition (action.e2), g_); + add_edge (t, u, g_); // fake edge for max_flow algo + edge_descriptor e3, e3_back; + bool ok; + boost::tie(e3, ok) = edge (s, t, g_); + assert (ok); + boost::tie(e3_back, ok) = edge (t, s, g_); + assert (ok); + g_[e3].transfered = action.e3; + if ((action.e3 == 0) && (g_[e3_back].transfered == 0)) + { + remove_edge(e3, g_); + remove_edge(e3_back, g_); + } + } + + void operator() (const simplify3& action) const + { + // From s,s' --> c + // To s,s' --> u --> c + std::cerr << "[QDFTgraph] Reverting rule3: [" + << action.c << ", " << action.u << ", " + << action.q; + simplify3::parents_type::const_iterator + it = action.parents.begin (); + for (size_t i = 0; it != action.parents.end (); ++it, ++i) + std::cerr << ", " << "(" << it->first << ", " << it->second + << ", " << action.capacities[i].first + << ", " << action.capacities[i].second + << ")"; + std::cerr << "]" << std::endl; + vertex_descriptor s, t, u; + typename Map::const_iterator jt = c2v_.find (action.c); + assert (jt != c2v_.end ()); + t = jt->second; + u = add_vertex (detail::node (43, // must be updated afterward + action.q, action.u, true), g_); + BGL_FORALL_INEDGES_T(t, e, g_, Graph) + { + if (g_[e].transfered > 0) + { + s = source (e, g_); + // look for s in the parent list + size_t i = 0; + simplify3::parents_type::value_type + v = std::make_pair (g_[s].name, g_[s].amount); + simplify3::parents_type::const_iterator + it = action.parents.begin (); + for (; (it != action.parents.end()) && (*it != v); ++it) + ++i; + if (it != action.parents.end ()) + { + add_edge (s, u, detail::transition (action.capacities[i].first), g_); + add_edge (u, s, g_); // fake edge for max_flow algo + g_[e].transfered = action.capacities[i].second; + // may remove e but this would invalidate the current edge iterator + } + } + } + add_edge (u, t, detail::transition (action.q), g_); + add_edge (t, u, g_); // fake edge for max_flow algo + } + + void operator() (const simplify4& action) const + { + std::cerr << "[QDFTgraph] Reverting rule4: (" + << g_[action.s_].name << ", " << action.x_ << ", " + << action.u_ << ", " << action.q_ << ", ...)" + << std::endl; + vertex_descriptor s = action.s_; + vertex_descriptor u = add_vertex + (detail::node (44, // must be updated afterward + action.q_, action.u_, true), g_); + vertex_descriptor t; + BGL_FORALL_OUTEDGES_T(s, e, g_, Graph) + { + if (g_[e].transfered > 0) + { + t = target (e, g_); + quantity_type q1, q2; + // look for t in the (fake/real) child list + if (g_[t].fake) + { + simplify4::fakechildren_type::const_iterator it + = action.fakechildren_.find + (std::make_pair (g_[t].name, g_[t].amount)); + assert (it != action.fakechildren_.end ()); + boost::tie (q1, q2) = it->second; + } + else + { + simplify4::realchildren_type::const_iterator it + = action.realchildren_.find (g_[t].name); + assert (it != action.realchildren_.end ()); + boost::tie (q1, q2) = it->second; + } + // Add link from u to t + add_edge (u, t, detail::transition (q1), g_); + add_edge (t, u, g_); // fake edge for max_flow algo + g_[e].transfered = q2; + } + } + add_edge (s, u, detail::transition (action.x_), g_); + add_edge (u, s, g_); // fake edge for max_flow algo + } + + void operator() (const simplify5& action) const + { + // from s --> u2 --b-> t + // to s --e1-> u --b-> t (and s --e2-> u2) + // \bug s could be equal to t! + vertex_descriptor s, u, u2, t; + quantity_type b = 0; + u2 = action.u2; + u = add_vertex + (detail::node (45, // must be updated afterward + action.u_q, action.u_n, true), g_); + // assert (detail::real_out_degree (u2, g_) == 1); + // assert (detail::real_in_degree (u2, g_) == 1); + BGL_FORALL_OUTEDGES_T(u2, e, g_, Graph) + { + if (g_[e].transfered > 0) + { + t = target(e, g_); + b = g_[e].transfered; + break; + } + } + BGL_FORALL_INEDGES_T(u2, e, g_, Graph) + { + if (g_[e].transfered > 0) + { + s = source(e, g_); + break; + } + } + add_edge (s, u, detail::transition (action.e1), g_); + add_edge (u, s, g_); // fake edge for max_flow algo + add_edge (u, u2, detail::transition (action.u_q), g_); + add_edge (u2, u, g_); // fake edge for max_flow algo + add_edge (u, t, detail::transition (b), g_); + add_edge (t, u, g_); // fake edge for max_flow algo + edge_descriptor e3, e3_back; + bool ok; + boost::tie(e3, ok) = edge (u2, t, g_); + assert (ok); + boost::tie(e3_back, ok) = edge (t, u2, g_); + assert (ok && (g_[e3_back].transfered == 0)); + remove_edge(e3, g_); + remove_edge(e3_back, g_); + } + private: + Graph& g_; + Map& c2v_; + vertex_descriptor src_; + }; + } +} + +#endif // ! QDFT_ACTION_HH diff --git a/include/qdft/graph.hh b/include/qdft/graph.hh new file mode 100644 index 0000000..f17b47d --- /dev/null +++ b/include/qdft/graph.hh @@ -0,0 +1,54 @@ +// Copyright (C) 2011 Johan Oudinet +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 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. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +#ifndef QDFT_GRAPH_HH +# define QDFT_GRAPH_HH +# include +# include + +namespace qdft { + + namespace detail { + // node type + struct node { + node (const size_t& i = 0, + const quantity_type& q = quantity_type (), + const cname_type& n = cname_type (), + const bool& f = true) + : id(i), name(n), amount(q), fake(f) {} + size_t id; + quantity_type amount; + cname_type name; + bool fake; + }; + + // transition type + struct transition { + transition (const quantity_type& qi = 0): transfered(qi), residual(0) {} + quantity_type transfered; + quantity_type residual; + }; + } // end namespace detail + + typedef boost::adjacency_list< + boost::vecS, + boost::listS, + boost::bidirectionalS, + detail::node, + detail::transition> qdft_graph; + +} // end namespace qdft +#endif // ! QDFT_GRAPH_HH diff --git a/include/qdft/manager.hh b/include/qdft/manager.hh new file mode 100644 index 0000000..eaa789b --- /dev/null +++ b/include/qdft/manager.hh @@ -0,0 +1,201 @@ +// Copyright (C) 2011, 2012 Johan Oudinet +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 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. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +#ifndef QDFT_MANAGER_HH +# define QDFT_MANAGER_HH +# include +# include +# include +# include +# include +# include +# include + +namespace qdft { + namespace detail { + class simple_counter { + public: + simple_counter(): n_(0) {} + size_t operator()() { assert(n_ != std::numeric_limits::max()); return n_++; } + void reset() { n_ = 0; } + private: + size_t n_; + }; + } // end namespace detail + + template + class data_manager { + public: + typedef boost::graph_traits Traits; + typedef typename Traits::vertex_descriptor vertex_descriptor; + typedef typename Traits::edge_descriptor edge_descriptor; + typedef typename Traits::in_edge_iterator in_edge_iterator; + typedef typename Traits::out_edge_iterator out_edge_iterator; + typedef boost::unordered_map c2v_type; + + /** + * Create a new data manager with q amount of data + * + * @param q the amount of data + * @param m the mode for further updates (dyn or static) + */ + data_manager (const quantity_type& q = 0, + const mode_type& m = unknown, + const dname_type& d = ""); + + /** + * Set the amount of data + * + * @param q the actual amount of data + */ + void set_data_amount (const quantity_type& q); + + /** + * Initialize the container c with qi amount of data + * + * @param qi the initial amount of data + * @param c the container's name + */ + void init (const quantity_type& qi, const cname_type& c); + + /** + * Transfer q amount of data from c_src to c_dst + * + * @param qa the transfered size that may be greater than q + * @param c_src source container of the data transfer (ignore the + * transfer if c_src does not exist) + * @param c_dst destination container of the data transfer (might + * be new but must be different from c_src) + * + * @return the old capacity of the edge c_src -> c_dst + */ + quantity_type + transfer (const quantity_type& qa, + const cname_type& c_src, + const cname_type& c_dst); + + /** + * Truncate the amount of data in c to n + * if n is greater than the amount of data + * or c does not exist just do nothing + * + * @param c container's name + * @param n new size of c + */ + void + truncate (const cname_type& c, const quantity_type& n); + + // /** + // * Remove q amount of data from c + // * q might be greater than the amount of data + // * if c does not exist just do nothing + // * + // * @param q amount of data to remove + // * @param c container's name + // */ + // void + // remove (const quantity_type& q, const cname_type& c); + + /** + * Set the transfered edge value to a specific quantity. This is + * usefull to revert a previous transfer. + * + * @param q amount of data to set as the edge quantity + * @param c_src source container + * @param c_dst destination container + */ + void + set_edge_quantity (const quantity_type& q, + const cname_type& c_src, + const cname_type& c_dst); + + /** + * Revert the effect of the last action to the graph. + */ + void + revert_last_action (); + + /** + * Get amount of data in c + * + * @param c container's name + * + * @return the amount of data in c (0 if c is not in the graph) + */ + quantity_type + get_quantity (const cname_type& c) const; + + /** + * Get the total amount of data + * + * @return the total amount of data + */ + quantity_type + get_data_amount () const; + + /** + * Print out the graph in GraphViz format + * + * @param out the ouput stream (default is std::out) + */ + void show_graph (std::ostream& out = std::cout) const; + + private: + mutable Graph g_; + c2v_type c2v_; // Mapping from container's name to vertex descriptor + detail::simple_counter next_id_; // Used to maintain the vertex indexes + vertex_descriptor src_; // source node for max flow algorithm + vertex_descriptor current_src_; // change when updating the amount of data + mode_type m_; // Mode for updating the amount of data + typedef boost::variant< + action::init, + action::transfer, + action::truncate, + action::simplify1, + action::simplify2, + action::simplify3, + action::simplify4, + action::simplify5 + > action_type; + std::stack last_actions_; + + /** + * Remove vertex u from the internal graph and update the vertex indexes + * + * @param u the vertex to remove + */ + void remove_vertex_ (vertex_descriptor u); + + /** + * Apply simplfification rules on vertex u and continues recursively + * + * @param u the vertex to remove + */ + void apply_simplification_rules_ (vertex_descriptor u); + + /** + * Update the amount of data in u + * + * @param u the vertex to update + */ + void update_data_of_ (vertex_descriptor u); + + }; +} // end namespace qdft + +# include "manager.hxx" + +#endif // ! QDFT_MANAGER_HH diff --git a/include/qdft/manager.hxx b/include/qdft/manager.hxx new file mode 100644 index 0000000..91a5cfe --- /dev/null +++ b/include/qdft/manager.hxx @@ -0,0 +1,767 @@ +// Copyright (C) 2011, 2012 Johan Oudinet +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 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. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +#ifndef QDFT_MANAGER_HXX +# define QDFT_MANAGER_HXX +# include +# include +# include +# include +# include +# include "manager.hh" + +namespace qdft { + namespace detail { + + // Map that assume reverse edge are already present in G + template + class reverse_edge_map : + public boost::put_get_helper::edge_descriptor&, + reverse_edge_map > + { + public: + typedef boost::graph_traits Traits; + typedef typename Traits::edge_descriptor edge_descriptor; + + typedef edge_descriptor key_type; + typedef edge_descriptor value_type; + typedef edge_descriptor& reference; + typedef boost::lvalue_property_map_tag category; + + reverse_edge_map (const Graph& g) : g_(g) {} + + reference operator[] (const key_type& e) const + { + bool ok; + boost::tie (rev_, ok) = edge (target(e, g_), source(e, g_), g_); + assert (ok); // reverse edge must exist + return rev_; + } + + private: + const Graph& g_; + mutable value_type rev_; + + }; + + // Adaptor to create easily a Lvalue map + template + reverse_edge_map + make_reverse_edge_map (const Graph& g) + { + return reverse_edge_map (g); + } + + /** + * Compute the out_degree without counting edges with 0 capacity + * + * @param u vertex descriptor + * @param g graph + * + * @return the number of edges starting from u + */ + template + inline typename boost::graph_traits::degree_size_type + real_out_degree(const typename boost::graph_traits::vertex_descriptor u, + const BidirectionalGraph& g) + { + typedef boost::graph_traits Traits; + typename Traits::degree_size_type res = 0; + typename Traits::out_edge_iterator ei, ei_end; + for (boost::tie (ei, ei_end) = out_edges (u, g); + ei != ei_end; ++ei) + if (g[*ei].transfered > 0) + ++res; + return res; + } + + /** + * Compute the in_degree without counting edges with 0 capacity + * + * @param u vertex descriptor + * @param g graph + * + * @return the number of edges ending in u + */ + template + inline typename boost::graph_traits::degree_size_type + real_in_degree(const typename boost::graph_traits::vertex_descriptor u, + const BidirectionalGraph& g) + { + typedef boost::graph_traits Traits; + typename Traits::degree_size_type res = 0; + typename Traits::in_edge_iterator ei, ei_end; + for (boost::tie (ei, ei_end) = in_edges (u, g); + ei != ei_end; ++ei) + if (g[*ei].transfered > 0) + ++res; + return res; + } + + } // end namespace detail + + // Create a new data manager with q amount of data + template + data_manager::data_manager (const quantity_type& q, + const mode_type& m, + const dname_type& d) + { + m_ = m; + // has_just_transfered_ = false; + src_ = add_vertex (detail::node (next_id_ (), q, d), g_); + current_src_ = add_vertex (detail::node (next_id_ (), q, + "src_", false), g_); + add_edge (src_, current_src_, detail::transition (q), g_); + add_edge (current_src_, src_, g_); // reverse edge for max flow + } + + // Set the amount of data + template + void + data_manager::set_data_amount (const quantity_type& q) + { + vertex_descriptor s; + g_[current_src_].fake = true; + s = add_vertex (detail::node (next_id_ (), q, "src_", false), g_); + switch (m_) + { + case unknown: + add_edge (src_, s, + detail::transition (q), + g_); + add_edge (s, src_, g_); // reverse edge for max flow + g_[src_].amount += q; + break; + case max: + add_edge (current_src_, s, + detail::transition (std::min(g_[current_src_].amount,q)), + g_); + add_edge (s, current_src_, g_); // reverse edge for max flow + if (q > g_[current_src_].amount) + { + add_edge (src_, s, + detail::transition (q - g_[current_src_].amount), + g_); + add_edge (s, src_, g_); // reverse edge for max flow + g_[src_].amount += q - g_[current_src_].amount; + } + break; + case last: + add_edge (s, current_src_, + detail::transition (std::min(g_[current_src_].amount,q)), + g_); + add_edge (current_src_, s, g_); // reverse edge for max flow + remove_edge (src_, current_src_, g_); + remove_edge (current_src_, src_, g_); + add_edge (src_, s, detail::transition (q), g_); + add_edge (s, src_, g_); // reverse edge for max flow + if (q < g_[current_src_].amount) // cut amount of data greater than q + { + BGL_FORALL_VERTICES_T(v, g_, Graph) + if (!g_[v].fake && g_[v].amount > q) + g_[v].amount = q; + } + g_[src_].amount = q; + break; + default: + throw std::domain_error ("Do not know how to update data in this mode"); + } + bool ok; + edge_descriptor e; + boost::tie(e, ok) = edge (src_, current_src_, g_); + if (ok) + g_[src_].amount -= g_[e].transfered; + apply_simplification_rules_(current_src_); + current_src_ = s; + } + + // Initialize the container c with qi amount of data + template + void + data_manager::init (const quantity_type& qi, const cname_type& c) + { + vertex_descriptor s; + if (qi > g_[current_src_].amount) + throw std::domain_error ("init: qi must be lower than the current amount of data"); + typename c2v_type::const_iterator it = c2v_.find (c); + if (it != c2v_.end ()) // c must be new + throw std::invalid_argument ("init: c must be new"); + s = add_vertex (detail::node (next_id_ (), qi, c, false), g_); + c2v_[c] = s; // reverse mapping from c to vertex + add_edge (current_src_, s, detail::transition (qi), g_); + // Add also the reverse edge for max_flow algorithms + add_edge (s, current_src_, g_); + } + + // Transfer q amount of data from c_src to c_dst + template + quantity_type + data_manager::transfer (const quantity_type& qa, + const cname_type& c_src, + const cname_type& c_dst) + { + // Reset the stack of last actions + while (!last_actions_.empty()) + last_actions_.pop (); + // c_src must exist (otherwise no transfer) but c_dst can be new + vertex_descriptor u, v, vold; + bool ok = false; + bool vold_ok = false; + edge_descriptor e; + typename c2v_type::const_iterator it = c2v_.find (c_src); + typename c2v_type::const_iterator jt = c2v_.find (c_dst); + // if c_src doesn't exist or is equal to c_dst, then no transfer + if ((it == c2v_.end ()) || (it == jt)) + return 0; + u = it->second; + if (jt != c2v_.end ()) + { + vold_ok = true; + vold = jt->second; + } + if (qa == 0) + { // no need for a transfer just return the edge capacity + if (vold_ok) + boost::tie (e, ok) = edge (u, vold, g_); + return ok? g_[e].transfered : 0; + } + quantity_type qcs = g_[u].amount; + quantity_type n = std::min (qcs, qa); + + // Log the action in case of a rollback + last_actions_.push (action::transfer (c_src, c_dst)); + // create new node for c_dst + v = add_vertex (detail::node (next_id_ (), n, c_dst, false), g_); + c2v_[c_dst] = v; // reverse mapping from c to vertex + + // Add a new edge from c_src to c_dst + add_edge (u, v, detail::transition (n), g_); + // And also its reverse edge for max_flow algorithms + add_edge (v, u, g_); + if (vold_ok) + { + // Add a new edge from c_old to c_dst + add_edge (vold, v, detail::transition (g_[vold].amount), g_); + // And also its reverse edge for max_flow algorithms + add_edge (v, vold, g_); + g_[vold].fake = true; + // Compute the amount of data in c_dst + update_data_of_ (v); + // Apply simplification rules on vold + apply_simplification_rules_ (vold); + } + } + + // Truncate amount of data in c to n + template + void + data_manager::truncate (const cname_type& c, const quantity_type& n) + { + // Reset the stack of last actions + while (!last_actions_.empty()) + last_actions_.pop (); + vertex_descriptor u; + typename c2v_type::iterator it = c2v_.find (c); + if (it == c2v_.end ()) { // c does not exist, do nothing + return; + } + u = it->second; + if (g_[u].amount <= n) { // n is greater than the amount of data, do nothing + return; + } + g_[u].fake = true; + if (n > 0) + { + vertex_descriptor u_new; + u_new = add_vertex (detail::node (next_id_ (), + n, + g_[u].name, false), + g_); + add_edge (u, u_new, detail::transition (n), g_); + add_edge (u_new, u, g_); // fake edge for max_flow algorithm + it->second = u_new; // update reference to c + } + else // no more data in c + c2v_.erase (c); + // Log the action in case of a rollback + last_actions_.push (action::truncate (g_[u].name, g_[u].amount, n)); + // Try to apply simplification rules on u + apply_simplification_rules_ (u); + } + + // Set the edge capacity to a specific value + template + void + data_manager::set_edge_quantity (const quantity_type& q, + const cname_type& c_src, + const cname_type& c_dst) + { + vertex_descriptor u, v; + bool ok; + edge_descriptor e; + typename c2v_type::const_iterator it = c2v_.find (c_src); + typename c2v_type::const_iterator jt = c2v_.find (c_dst); + if (it == c2v_.end () || jt == c2v_.end ()) + return; + u = it->second; + v = jt->second; + boost::tie(e, ok) = edge (u, v, g_); + if (ok && q != g_[e].transfered) + { + // set new capacity to q + g_[e].transfered = q; + // update max flow + update_data_of_ (target (e, g_)); + } + } + + // Revert the effect of the last action to the graph. + template + void + data_manager::revert_last_action () + { + bool deleted = false; + while (!last_actions_.empty ()) + { + deleted = true; + boost::apply_visitor (action::revert (g_, c2v_, current_src_), + last_actions_.top ()); + last_actions_.pop (); + } + if (deleted) + { + // need to update indexes + next_id_.reset (); + BGL_FORALL_VERTICES_T(v, g_, Graph) + { + g_[v].id = next_id_ (); + } + } + + // vertex_descriptor u, v; + // edge_descriptor re; + // bool ok; + + // assert (has_just_transfered_); + // std::cerr << "olde_: " << olde_ << " " + // << "oldq_: " << oldq_ << std::endl; + // std::cerr << "newq: " << g_[olde_].transfered << std::endl; + // u = source (olde_, g_); + // v = target (olde_, g_); + // boost::tie (re, ok) = edge(v, u, g_); + // assert (ok); + // if (oldq_ == 0 && g_[re].transfered == 0) + // { // Remove these two edges + // remove_edge (u, v, g_); + // remove_edge (v, u, g_); + // } + // else + // g_[olde_].transfered = oldq_; + // // update max flow + // update_data_of_ (v); + } + + // Get amount of data in c + template + quantity_type + data_manager::get_quantity (const cname_type& c) const + { + typename c2v_type::const_iterator it = c2v_.find (c); + if (it == c2v_.end ()) // container is not inside the graph + return 0; + else + return g_[it->second].amount; + } + + // Get the total amount of data + template + quantity_type + data_manager::get_data_amount () const + { + quantity_type res = 0; + BGL_FORALL_OUTEDGES_T(src_, e, g_, Graph) + { + res += g_[e].transfered; + } + g_[src_].amount = res; + return res; + } + + // Function to print out the internal graph + template + void data_manager::show_graph (std::ostream& out) const + { + boost::dynamic_properties dp; + // vertex_index works only with vecS vertex container + // dp.property ("node_id", boost::get (boost::vertex_index, g_)); + dp.property ("node_id", boost::get (&::qdft::detail::node::id, g_)); + dp.property ("name", boost::get (&::qdft::detail::node::name, g_)); + dp.property ("amount", boost::get (&::qdft::detail::node::amount, g_)); + dp.property ("fake", boost::get (&::qdft::detail::node::fake, g_)); + dp.property ("transfered", + boost::get (&::qdft::detail::transition::transfered, g_)); + write_graphviz_dp(out, g_, dp); + } + + // Remove vertex u from the internal graph + template + void data_manager::remove_vertex_ (vertex_descriptor u) + { + // has_just_transfered_ = false; + clear_vertex (u, g_); + remove_vertex (u, g_); + } + + // Apply simplification rules on vertex u and continue recursively + template + void + data_manager::apply_simplification_rules_ (vertex_descriptor u) + { +#ifndef NO_SIMPLIFY + std::queue qv; + qv.push (u); + bool deleted = false; // True if at least one vertex is deleted + do { + // Consider deleting u + u = qv.front (); + qv.pop (); + // \bug Cannot rely on in/out_degree because of fake edges added for maxFlow + vertex_descriptor u_pred; // u's father + if (detail::real_out_degree (u, g_) == 0) + { // simplification rule 1 +#ifdef DEBUG + std::cerr << "[QDFTgraph] Apply simplification rule 1 on " << g_[u].name << std::endl; +#endif + action::simplify1::realparents_type realparents; + action::simplify1::fakeparents_type fakeparents; + // Consider u's parents for removing + BGL_FORALL_INEDGES_T(u, e, g_, Graph) + { + if (g_[e].transfered > 0) + { + if (g_[source (e, g_)].fake) + { + qv.push (source (e, g_)); + fakeparents.insert (std::make_pair + (std::make_pair (g_[source (e, g_)].name, + g_[source (e, g_)].amount), + g_[e].transfered)); + } + else + realparents.push_back (std::make_pair (g_[source (e, g_)].name, + g_[e].transfered)); + } + } + // Log the action in case of a rollback + last_actions_.push (action::simplify1 (g_[u].name, g_[u].amount, + realparents, + fakeparents)); + // Safely remove u from g_ + remove_vertex_ (u); + deleted = true; + } + else if (detail::real_out_degree (u, g_) == 1 + && detail::real_in_degree (u, g_) == 1) + { // simplification rule 2 +#ifdef DEBUG + std::cerr << "[QDFTgraph] Apply simplification rule 2 on " << g_[u].name << std::endl; +#endif + // s --e1-> u --e2-> t (and may also have s --e3-> t) + in_edge_iterator ei, ei_end; + boost::tie (ei, ei_end) = in_edges (u, g_); + while (g_[*ei].transfered == 0) + ++ei; + u_pred = source (*ei, g_); + edge_descriptor e1, e2, e3; + vertex_descriptor s, t; + // find e2 + out_edge_iterator ei2, ei2_end; + boost::tie (ei2, ei2_end) = out_edges (u, g_); + while (g_[*ei2].transfered == 0) + ++ei2; + e2 = *ei2; + t = target (e2, g_); + // find e1 + in_edge_iterator ei1, ei1_end; + boost::tie (ei1, ei1_end) = in_edges (u, g_); + while (g_[*ei1].transfered == 0) + ++ei1; + e1 = *ei1; + // define s + s = source (e1, g_); + bool ok; + boost::tie (e3, ok) = edge (s, target (e2, g_), g_); + // Log the action in case of a rollback + last_actions_.push (action::simplify2 (g_[s].name, g_[t].name, + g_[u].name, g_[u].amount, + g_[e1].transfered, + g_[e2].transfered, + (ok? g_[e3].transfered : 0))); + if (ok) // Update e3 + { + g_[e3].transfered = std::min (g_[e2].transfered + g_[e3].transfered, g_[s].amount); + } + else // Create e3 only if s != t + { + if (s != t) + { + add_edge (s, t, + detail::transition (std::min(g_[e2].transfered, + g_[s].amount)), + g_); + add_edge (t, s, g_); // fake edge for max_flow algo + } + } + // And remove u from g_ + remove_vertex_ (u); + if (g_[u_pred].fake) + qv.push (u_pred); + deleted = true; + } // end else if + else if (detail::real_out_degree (u, g_) == 1) + { // simplification rule 3 + bool apply_rule = true; + quantity_type x = g_[u].amount; + vertex_descriptor s, t; + BGL_FORALL_OUTEDGES_T(u, e, g_, Graph) + { + if (g_[e].transfered > 0) + { + if (g_[e].transfered != x) + apply_rule = false; + else + t = target (e, g_); + break; + } + } + if (apply_rule) + { +#ifdef DEBUG + std::cerr << "[QDFTgraph] Apply simplification rule 3 on " << g_[u].name << std::endl; +#endif + action::simplify3::parents_type parents; + action::simplify3::capacities_type capacities; + BGL_FORALL_INEDGES_T(u, e, g_, Graph) + { + if (g_[e].transfered > 0) + { + s = source (e, g_); + parents.push_back (std::make_pair (g_[s].name, + g_[s].amount)); + if (g_[s].fake) // Consider u's parents for removing + qv.push (s); + edge_descriptor e2; + bool ok; + boost::tie (e2, ok) = edge (s, t, g_); + capacities.push_back + (std::make_pair (g_[e].transfered, ok?g_[e2].transfered:0)); + if (ok) + { // update e2 with e + g_[e2].transfered = + std::min(g_[e2].transfered + g_[e].transfered, + g_[s].amount); + } + else + { // create an edge between s and t + add_edge (s, t, + detail::transition (g_[e].transfered), + g_); + add_edge (t, s, g_); // fake edge for max_flow algo + } + } + } + // Log the action in case of a rollback + last_actions_.push (action::simplify3 (g_[t].name, + g_[u].name, + g_[u].amount, + parents, + capacities)); + // And remove u from g_ + remove_vertex_ (u); + deleted = true; + } + } + else if (detail::real_in_degree (u, g_) == 1) + { // simplification rule 4 + bool apply_rule = true; + vertex_descriptor s, t; + quantity_type x = 0; + BGL_FORALL_INEDGES_T(u, e, g_, Graph) + { + if (g_[e].transfered > 0) + { + s = source (e, g_); + x = g_[e].transfered; + break; + } + } + quantity_type sum = 0; + BGL_FORALL_OUTEDGES_T(u, e, g_, Graph) + { + sum += g_[e].transfered; + if (sum > x) + { + apply_rule = false; + break; + } + } + if (apply_rule) + { +#ifdef DEBUG + std::cerr << "[QDFTgraph] Apply simplification rule 4 on " << g_[u].name << std::endl; +#endif + action::simplify4::realchildren_type realchildren; + action::simplify4::fakechildren_type fakechildren; + BGL_FORALL_OUTEDGES_T(u, e, g_, Graph) + { + if (g_[e].transfered > 0) + { + t = target (e, g_); + edge_descriptor e2; + bool ok; + boost::tie (e2, ok) = edge (s, t, g_); + if (g_[t].fake) + { + fakechildren.insert (std::make_pair + (std::make_pair (g_[t].name, + g_[t].amount), + std::make_pair (g_[e].transfered, + ok? g_[e2].transfered: 0))); + } + else + { + realchildren.insert + (std::make_pair (g_[t].name, + std::make_pair (g_[e].transfered, + ok? g_[e2].transfered: 0))); + } + if (ok) + { // update e2 with e + g_[e2].transfered = + std::min(g_[e2].transfered + g_[e].transfered, + g_[s].amount); + } + else + { // create an edge between s and t + add_edge (s, t, + detail::transition (g_[e].transfered), + g_); + add_edge (t, s, g_); // fake edge for max_flow algo + } + } + } + // Log the action in case of a rollback + last_actions_.push (action::simplify4 (s, x, + g_[u].name, g_[u].amount, + realchildren, + fakechildren)); + // And remove u from g_ + remove_vertex_ (u); + deleted = true; + } + else if (detail::real_out_degree (u, g_) == 2) + { // simplification rule 5 may also apply here + vertex_descriptor v, u2; + bool u2_ok = false; + quantity_type b = 0; + BGL_FORALL_OUTEDGES_T(u, e, g_, Graph) + { + if (g_[e].transfered > 0) + { + v = target (e, g_); + if ((g_[v].name == g_[u].name) + && (g_[e].transfered == g_[u].amount)) + { + u2 = v; + u2_ok = true; + } + else + { + t = v; + b = g_[e].transfered; + } + } + } + if (u2_ok) + { + edge_descriptor e2, e3; + bool ok2, ok3; + boost::tie (e2, ok2) = edge (s, u2, g_); + boost::tie (e3, ok3) = edge (u2, t, g_); + // e2 should be the last transfer from s to u.name + if (!ok3 && ok2 && g_[e2].transfered > 0 + && detail::real_in_degree(u2, g_) == 2 + && detail::real_out_degree(u2, g_) == 0) + { +#ifdef DEBUG + std::cerr << "[QDFTgraph] Apply simplification rule 5 on " + << g_[u].name << std::endl; +#endif + // Update e2 + quantity_type y = g_[e2].transfered; + g_[e2].transfered = + std::min(g_[e2].transfered + x, + g_[s].amount); + add_edge (u2, t, + detail::transition (b), + g_); + add_edge (t, u2, g_); // fake edge for max_flow algo + // Log the action in case of a rollback + last_actions_.push (action::simplify5 (u2, + g_[u].name, g_[u].amount, + x, y)); + // And remove u from g_ + remove_vertex_ (u); + deleted = true; + } + } + } + } + } while (!qv.empty ()); + if (deleted) // at least one vertex was deleted + { + // need to update indexes + next_id_.reset (); + BGL_FORALL_VERTICES_T(v, g_, Graph) + { + g_[v].id = next_id_ (); + } + } +#endif // ! NO_SIMPLIFY + } + + // Compute max flow from source to u + template + void data_manager::update_data_of_ (vertex_descriptor u) + { + g_[u].amount = + boykov_kolmogorov_max_flow(g_, + // CapacityEdgeMap + boost::get (&::qdft::detail::transition::transfered, g_), + // ResidualCapacityEdgeMap, + boost::get (&::qdft::detail::transition::residual, g_), + // ReverseEdgeMap + detail::make_reverse_edge_map (g_), + // IndexMap + boost::get (&::qdft::detail::node::id, g_), + boost::vertex(0, g_), + u); + if (g_[u].amount == 0) + apply_simplification_rules_ (u); + } +} // end namespace qdft + +#endif // ! QDFT_MANAGER_HXX diff --git a/include/qdft/qdft.hh b/include/qdft/qdft.hh new file mode 100644 index 0000000..bee69f1 --- /dev/null +++ b/include/qdft/qdft.hh @@ -0,0 +1,185 @@ +// Copyright (C) 2011, 2012 Johan Oudinet +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 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. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +#ifndef QDFT_QDFT_HH +# define QDFT_QDFT_HH +# include +# include +# include +# include +# include +# include +# include + +namespace qdft { + + /** + * @file qdft.hh + * @author Johan Oudinet + * @date Thu Nov 10 12:00:56 2011 + * + * @brief This file contains the main interface for the QDFTgraph library + * + * + */ + + template + class data_managers { + typedef qdft::data_manager data_manager_t; + typedef boost::shared_ptr< data_manager_t > data_manager_ptr; + public: + typedef boost::unordered_map< + dname_type, data_manager_ptr> data_managers_t; + + /** + * Create a new data of size q (and set mode m for further updates) + * + * @param q the amount of data + * @param m the mode for further updates (dyn or static) + * @param dname a unique name to identify the new data + * + * @return a unique name to identify the newly created data + */ + dname_type new_data (const quantity_type& q, const mode_type& m, + const dname_type& dname = + boost::lexical_cast (boost::uuids::random_generator()())); + + /** + * Set the amount of data d + * + * @param d the data name + * @param q the actual amount of data + */ + void set_data_amount (const dname_type& d, const quantity_type& q); + + /** + * Initialize the container c with qi amount of d + * + * @param d the data name + * @param qi the initial amount of data in c + * @param c the container's name + */ + void init (const dname_type& d, + const quantity_type& qi, const cname_type& c); + + /** + * Transfer q amount of data d from c_src to c_dst + * + * @param d the data name + + * @param qa the transfered size that may be greater than q + * @param c_src source container of the data transfer (ignore the + * transfer if c_src does not exist) + * @param c_dst destination container of the data transfer (might be new) + * + * @return the old capacity of the edge c_src -> c_dst + */ + quantity_type + transfer (const dname_type& d, + const quantity_type& qa, + const cname_type& c_src, + const cname_type& c_dst); + + /** + * Truncate the amount of data d in c to n + * if n is greater than the amount of data in c + * or c does not exist just do nothing + * + * @param d the data name + * @param c container's name + * @param n new size of c + */ + void + truncate (const dname_type& d, const cname_type& c, const quantity_type& n); + + // /** + // * Remove q amount of data d from c + // * q might be greater than the amount of data + // * if c does not exist just do nothing + // * + // * @param d the data name + // * @param q amount of data to remove + // * @param c container's name + // */ + // void + // remove (const dname_type& d, const quantity_type& q, const cname_type& c); + + /** + * Set the transfered edge value to a specific quantity. This is + * usefull to revert a previous transfer. + * + * @param d the data name + * @param q amount of data to set as the edge quantity + * @param c_src source container + * @param c_dst destination container + */ + void + set_edge_quantity (const dname_type& d, + const quantity_type& q, + const cname_type& c_src, + const cname_type& c_dst); + + /** + * Revert the effect of the last action to the graph. + * + * @param d the data name + */ + void + revert_last_action (const dname_type& d); + + /** + * Get amount of data d in c + * + * @param d the data name + * @param c container's name + * + * @return the amount of data d in c (0 if c is not in the graph) + */ + quantity_type + get_quantity (const dname_type& d, const cname_type& c) const; + + /** + * Get the total amount of data d + * + * @param d the data name + * + * @return the amount of data d + */ + quantity_type + get_data_amount (const dname_type& d) const; + + /** + * Print out each data graph in GraphViz format + * + * @param out the ouput stream (default is std::out) + */ + void show_graphs (std::ostream& out = std::cout) const; + + /** + * Save graphs in fname file for pretty printing them + * + * @param fname file name + */ + void save (const std::string& fname) const; + + private: + data_managers_t dm_; + }; +} // end namespace qdft + +# include "qdft.hxx" + +#endif // ! QDFT_QDFT_HH diff --git a/include/qdft/qdft.hxx b/include/qdft/qdft.hxx new file mode 100644 index 0000000..5173764 --- /dev/null +++ b/include/qdft/qdft.hxx @@ -0,0 +1,213 @@ +// Copyright (C) 2011, 2012 Johan Oudinet +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 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. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +#ifndef QDFT_QDFT_HXX +# define QDFT_QDFT_HXX +# include +# include +# include +# include +# include "qdft.hh" + +namespace qdft { + + // Create a new data of size q (and set mode m for further updates) + // Make use of UUID library + template + dname_type + data_managers::new_data (const quantity_type& q, const mode_type& m, + const dname_type& dname) + { + typename data_managers_t::iterator it = dm_.find (dname); + if (it != dm_.end ()) // dname must be new + { + throw std::invalid_argument ("data_managers::new_data: dname must be new"); + } + data_manager_ptr pdm (new data_manager_t (q, m, dname)); + dm_[dname] = pdm; + return dname; + } + + // Set the amount of data d + template + void + data_managers::set_data_amount (const dname_type& d, + const quantity_type& q) + { + typename data_managers_t::iterator it = dm_.find (d); + if (it == dm_.end ()) // New data + { + // d must exist + throw std::invalid_argument ("data_managers::set_data_amount: d must exist"); + } + else // Update data + { + it->second->set_data_amount (q); + } + } + + // Initialize the container c with qi amount of d + template + void + data_managers::init (const dname_type& d, + const quantity_type& qi, const cname_type& c) + { + typename data_managers_t::iterator it = dm_.find (d); + if (it == dm_.end ()) // New data + { + // d must exist + throw std::invalid_argument ("data_managers::init: d must exist"); + } + else + { + it->second->init (qi, c); + } + } + + // Transfer q amount of data d from c_src to c_dst + template + quantity_type + data_managers::transfer (const dname_type& d, + const quantity_type& qa, + const cname_type& c_src, + const cname_type& c_dst) + { + typename data_managers_t::iterator it = dm_.find (d); + if (it == dm_.end ()) + { + // d must exist + throw std::invalid_argument ("data_managers::transfer: d must exist"); + } + return it->second->transfer (qa, c_src, c_dst); + } + + // truncate amount of data d in c to n + template + void + data_managers::truncate (const dname_type& d, + const cname_type& c, + const quantity_type& n) + { + typename data_managers_t::iterator it = dm_.find (d); + if (it == dm_.end ()) + { + // d must exist + throw std::invalid_argument ("data_managers::transfer: d must exist"); + } + it->second->truncate (c, n); + } + + // // Remove q amount of data d from c + // template + // void + // data_managers::remove (const dname_type& d, + // const quantity_type& q, + // const cname_type& c) + // { + // typename data_managers_t::iterator it = dm_.find (d); + // if (it == dm_.end ()) + // { + // // d must exist + // throw std::invalid_argument ("data_managers::transfer: d must exist"); + // } + // it->second->remove (q, c); + // } + + // Set the transfered edge value to a specific quantity. This is + template + void + data_managers::set_edge_quantity (const dname_type& d, + const quantity_type& q, + const cname_type& c_src, + const cname_type& c_dst) + { + typename data_managers_t::iterator it = dm_.find (d); + if (it == dm_.end ()) + { + // d must exist + throw std::invalid_argument ("data_managers::transfer: d must exist"); + } + it->second->set_edge_quantity (q, c_src, c_dst); + } + + // Revert the effect of the last action to the graph. + template + void + data_managers::revert_last_action (const dname_type& d) + { + typename data_managers_t::iterator it = dm_.find (d); + if (it == dm_.end ()) + { + // d must exist + throw std::invalid_argument ("data_managers::transfer: d must exist"); + } + it->second->revert_last_action (); + } + + // Get amount of data d in c + template + quantity_type + data_managers::get_quantity (const dname_type& d, + const cname_type& c) const + { + typename data_managers_t::const_iterator it = dm_.find (d); + if (it == dm_.end ()) + { + // d must exist + throw std::invalid_argument ("data_managers::transfer: d must exist"); + } + return it->second->get_quantity (c); + } + + // Get the total amount of data d + template + quantity_type + data_managers::get_data_amount (const dname_type& d) const + { + typename data_managers_t::const_iterator it = dm_.find (d); + if (it == dm_.end ()) + { + // d must exist + throw std::invalid_argument ("data_managers::transfer: d must exist"); + } + return it->second->get_data_amount (); + } + + + // Print out each data graph in GraphViz format + template + void + data_managers::show_graphs (std::ostream& out) const + { + BOOST_FOREACH(typename data_managers_t::value_type i, dm_) { + i.second->show_graph (out); + } + } + + // Save graphs in fname file for pretty printing them + template + void + data_managers::save (const std::string& fname) const + { + std::fstream fs; + fs.open (fname.c_str (), std::fstream::out); + show_graphs (fs); + fs.close (); + } + +} // end namespace qdft + +#endif // ! QDFT_QDFT_HXX diff --git a/include/qdft/qdft.i b/include/qdft/qdft.i new file mode 100644 index 0000000..83260dd --- /dev/null +++ b/include/qdft/qdft.i @@ -0,0 +1,15 @@ +%module libqdftgraph +%{ + /* Includes the header in the wrapper code */ +#include "types.hh" +#include "qdft.hh" + using namespace qdft; +%} + +%include +%include "stl.i" +/* Parse the header file to generate wrappers */ +%include "types.hh" +%include "qdft.hh" + +%template(dataManagers) qdft::data_managers<>; diff --git a/include/qdft/types.hh b/include/qdft/types.hh new file mode 100644 index 0000000..ce3e863 --- /dev/null +++ b/include/qdft/types.hh @@ -0,0 +1,30 @@ +// Copyright (C) 2011 Johan Oudinet +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 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. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +#ifndef QDFT_TYPES_HH +# define QDFT_TYPES_HH +# include + +namespace qdft { + + typedef size_t quantity_type; // value type for amount of data + typedef std::string cname_type; // Container's name type + typedef std::string dname_type; // Data's name type + + enum mode_type {unknown, max, last}; // Mode to update the amount of data + +} // end namespace qdft +#endif // ! QDFT_TYPES_HH diff --git a/m4/boost.m4 b/m4/boost.m4 new file mode 100644 index 0000000..3934095 --- /dev/null +++ b/m4/boost.m4 @@ -0,0 +1,1133 @@ +# boost.m4: Locate Boost headers and libraries for autoconf-based projects. +# Copyright (C) 2007, 2008, 2009, 2010, 2011 Benoit Sigoure +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Additional permission under section 7 of the GNU General Public +# License, version 3 ("GPLv3"): +# +# If you convey this file as part of a work that contains a +# configuration script generated by Autoconf, you may do so under +# terms of your choice. +# +# 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +m4_define([_BOOST_SERIAL], [m4_translit([ +# serial 16 +], [# +], [])]) + +# Original sources can be found at http://github.com/tsuna/boost.m4 +# You can fetch the latest version of the script by doing: +# wget http://github.com/tsuna/boost.m4/raw/master/build-aux/boost.m4 + +# ------ # +# README # +# ------ # + +# This file provides several macros to use the various Boost libraries. +# The first macro is BOOST_REQUIRE. It will simply check if it's possible to +# find the Boost headers of a given (optional) minimum version and it will +# define BOOST_CPPFLAGS accordingly. It will add an option --with-boost to +# your configure so that users can specify non standard locations. +# If the user's environment contains BOOST_ROOT and --with-boost was not +# specified, --with-boost=$BOOST_ROOT is implicitly used. +# For more README and documentation, go to http://github.com/tsuna/boost.m4 +# Note: THESE MACROS ASSUME THAT YOU USE LIBTOOL. If you don't, don't worry, +# simply read the README, it will show you what to do step by step. + +m4_pattern_forbid([^_?(BOOST|Boost)_]) + + +# _BOOST_SED_CPP(SED-PROGRAM, PROGRAM, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# -------------------------------------------------------- +# Same as AC_EGREP_CPP, but leave the result in conftest.i. +# +# SED-PROGRAM is *not* overquoted, as in AC_EGREP_CPP. It is expanded +# in double-quotes, so escape your double quotes. +# +# It could be useful to turn this into a macro which extracts the +# value of any macro. +m4_define([_BOOST_SED_CPP], +[AC_LANG_PREPROC_REQUIRE()dnl +AC_REQUIRE([AC_PROG_SED])dnl +AC_LANG_CONFTEST([AC_LANG_SOURCE([[$2]])]) +AS_IF([dnl eval is necessary to expand ac_cpp. +dnl Ultrix and Pyramid sh refuse to redirect output of eval, so use subshell. +dnl Beware of Windows end-of-lines, for instance if we are running +dnl some Windows programs under Wine. In that case, boost/version.hpp +dnl is certainly using "\r\n", but the regular Unix shell will only +dnl strip `\n' with backquotes, not the `\r'. This results in +dnl boost_cv_lib_version='1_37\r' for instance, which breaks +dnl everything else. +dnl Cannot use 'dnl' after [$4] because a trailing dnl may break AC_CACHE_CHECK +(eval "$ac_cpp conftest.$ac_ext") 2>&AS_MESSAGE_LOG_FD | + tr -d '\r' | + $SED -n -e "$1" >conftest.i 2>&1], + [$3], + [$4]) +rm -rf conftest* +])# AC_EGREP_CPP + + + +# BOOST_REQUIRE([VERSION], [ACTION-IF-NOT-FOUND]) +# ----------------------------------------------- +# Look for Boost. If version is given, it must either be a literal of the form +# "X.Y.Z" where X, Y and Z are integers (the ".Z" part being optional) or a +# variable "$var". +# Defines the value BOOST_CPPFLAGS. This macro only checks for headers with +# the required version, it does not check for any of the Boost libraries. +# On # success, defines HAVE_BOOST. On failure, calls the optional +# ACTION-IF-NOT-FOUND action if one was supplied. +# Otherwise aborts with an error message. +AC_DEFUN([BOOST_REQUIRE], +[AC_REQUIRE([AC_PROG_CXX])dnl +AC_REQUIRE([AC_PROG_GREP])dnl +echo "$as_me: this is boost.m4[]_BOOST_SERIAL" >&AS_MESSAGE_LOG_FD +boost_save_IFS=$IFS +boost_version_req=$1 +IFS=. +set x $boost_version_req 0 0 0 +IFS=$boost_save_IFS +shift +boost_version_req=`expr "$[1]" '*' 100000 + "$[2]" '*' 100 + "$[3]"` +boost_version_req_string=$[1].$[2].$[3] +AC_ARG_WITH([boost], + [AS_HELP_STRING([--with-boost=DIR], + [prefix of Boost $1 @<:@guess@:>@])])dnl +AC_ARG_VAR([BOOST_ROOT],[Location of Boost installation])dnl +# If BOOST_ROOT is set and the user has not provided a value to +# --with-boost, then treat BOOST_ROOT as if it the user supplied it. +if test x"$BOOST_ROOT" != x; then + if test x"$with_boost" = x; then + AC_MSG_NOTICE([Detected BOOST_ROOT; continuing with --with-boost=$BOOST_ROOT]) + with_boost=$BOOST_ROOT + else + AC_MSG_NOTICE([Detected BOOST_ROOT=$BOOST_ROOT, but overridden by --with-boost=$with_boost]) + fi +fi +AC_SUBST([DISTCHECK_CONFIGURE_FLAGS], + ["$DISTCHECK_CONFIGURE_FLAGS '--with-boost=$with_boost'"])dnl +boost_save_CPPFLAGS=$CPPFLAGS + AC_CACHE_CHECK([for Boost headers version >= $boost_version_req_string], + [boost_cv_inc_path], + [boost_cv_inc_path=no +AC_LANG_PUSH([C++])dnl +m4_pattern_allow([^BOOST_VERSION$])dnl + AC_LANG_CONFTEST([AC_LANG_PROGRAM([[#include +#if !defined BOOST_VERSION +# error BOOST_VERSION is not defined +#elif BOOST_VERSION < $boost_version_req +# error Boost headers version < $boost_version_req +#endif +]])]) + # If the user provided a value to --with-boost, use it and only it. + case $with_boost in #( + ''|yes) set x '' /opt/local/include /usr/local/include /opt/include \ + /usr/include C:/Boost/include;; #( + *) set x "$with_boost/include" "$with_boost";; + esac + shift + for boost_dir + do + # Without --layout=system, Boost (or at least some versions) installs + # itself in /include/boost-. This inner loop helps to + # find headers in such directories. + # + # Any ${boost_dir}/boost-x_xx directories are searched in reverse version + # order followed by ${boost_dir}. The final '.' is a sentinel for + # searching $boost_dir" itself. Entries are whitespace separated. + # + # I didn't indent this loop on purpose (to avoid over-indented code) + boost_layout_system_search_list=`cd "$boost_dir" 2>/dev/null \ + && ls -1 | "${GREP}" '^boost-' | sort -rn -t- -k2 \ + && echo .` + for boost_inc in $boost_layout_system_search_list + do + if test x"$boost_inc" != x.; then + boost_inc="$boost_dir/$boost_inc" + else + boost_inc="$boost_dir" # Uses sentinel in boost_layout_system_search_list + fi + if test x"$boost_inc" != x; then + # We are going to check whether the version of Boost installed + # in $boost_inc is usable by running a compilation that + # #includes it. But if we pass a -I/some/path in which Boost + # is not installed, the compiler will just skip this -I and + # use other locations (either from CPPFLAGS, or from its list + # of system include directories). As a result we would use + # header installed on the machine instead of the /some/path + # specified by the user. So in that precise case (trying + # $boost_inc), make sure the version.hpp exists. + # + # Use test -e as there can be symlinks. + test -e "$boost_inc/boost/version.hpp" || continue + CPPFLAGS="$CPPFLAGS -I$boost_inc" + fi + AC_COMPILE_IFELSE([], [boost_cv_inc_path=yes], [boost_cv_version=no]) + if test x"$boost_cv_inc_path" = xyes; then + if test x"$boost_inc" != x; then + boost_cv_inc_path=$boost_inc + fi + break 2 + fi + done + done +AC_LANG_POP([C++])dnl + ]) + case $boost_cv_inc_path in #( + no) + boost_errmsg="cannot find Boost headers version >= $boost_version_req_string" + m4_if([$2], [], [AC_MSG_ERROR([$boost_errmsg])], + [AC_MSG_NOTICE([$boost_errmsg])]) + $2 + ;;#( + yes) + BOOST_CPPFLAGS= + ;;#( + *) + AC_SUBST([BOOST_CPPFLAGS], ["-I$boost_cv_inc_path"])dnl + ;; + esac + if test x"$boost_cv_inc_path" != xno; then + AC_DEFINE([HAVE_BOOST], [1], + [Defined if the requested minimum BOOST version is satisfied]) + AC_CACHE_CHECK([for Boost's header version], + [boost_cv_lib_version], + [m4_pattern_allow([^BOOST_LIB_VERSION$])dnl + _BOOST_SED_CPP([/^boost-lib-version = /{s///;s/\"//g;p;q;}], + [#include +boost-lib-version = BOOST_LIB_VERSION], + [boost_cv_lib_version=`cat conftest.i`])]) + # e.g. "134" for 1_34_1 or "135" for 1_35 + boost_major_version=`echo "$boost_cv_lib_version" | sed 's/_//;s/_.*//'` + case $boost_major_version in #( + '' | *[[!0-9]]*) + AC_MSG_ERROR([invalid value: boost_major_version=$boost_major_version]) + ;; + esac +fi +CPPFLAGS=$boost_save_CPPFLAGS +])# BOOST_REQUIRE + +# BOOST_STATIC() +# -------------- +# Add the "--enable-static-boost" configure argument. If this argument is given +# on the command line, static versions of the libraries will be looked up. +AC_DEFUN([BOOST_STATIC], + [AC_ARG_ENABLE([static-boost], + [AC_HELP_STRING([--enable-static-boost], + [Prefer the static boost libraries over the shared ones [no]])], + [enable_static_boost=yes], + [enable_static_boost=no])])# BOOST_STATIC + +# BOOST_FIND_HEADER([HEADER-NAME], [ACTION-IF-NOT-FOUND], [ACTION-IF-FOUND]) +# -------------------------------------------------------------------------- +# Wrapper around AC_CHECK_HEADER for Boost headers. Useful to check for +# some parts of the Boost library which are only made of headers and don't +# require linking (such as Boost.Foreach). +# +# Default ACTION-IF-NOT-FOUND: Fail with a fatal error unless Boost couldn't be +# found in the first place, in which case by default a notice is issued to the +# user. Presumably if we haven't died already it's because it's OK to not have +# Boost, which is why only a notice is issued instead of a hard error. +# +# Default ACTION-IF-FOUND: define the preprocessor symbol HAVE_ in +# case of success # (where HEADER-NAME is written LIKE_THIS, e.g., +# HAVE_BOOST_FOREACH_HPP). +AC_DEFUN([BOOST_FIND_HEADER], +[AC_REQUIRE([BOOST_REQUIRE])dnl +if test x"$boost_cv_inc_path" = xno; then + m4_default([$2], [AC_MSG_NOTICE([Boost not available, not searching for $1])]) +else +AC_LANG_PUSH([C++])dnl +boost_save_CPPFLAGS=$CPPFLAGS +CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" +AC_CHECK_HEADER([$1], + [m4_default([$3], [AC_DEFINE(AS_TR_CPP([HAVE_$1]), [1], + [Define to 1 if you have <$1>])])], + [m4_default([$2], [AC_MSG_ERROR([cannot find $1])])]) +CPPFLAGS=$boost_save_CPPFLAGS +AC_LANG_POP([C++])dnl +fi +])# BOOST_FIND_HEADER + + +# BOOST_FIND_LIB([LIB-NAME], [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST], +# [CXX-PROLOGUE]) +# ------------------------------------------------------------------------- +# Look for the Boost library LIB-NAME (e.g., LIB-NAME = `thread', for +# libboost_thread). Check that HEADER-NAME works and check that +# libboost_LIB-NAME can link with the code CXX-TEST. The optional argument +# CXX-PROLOGUE can be used to include some C++ code before the `main' +# function. +# +# Invokes BOOST_FIND_HEADER([HEADER-NAME]) (see above). +# +# Boost libraries typically come compiled with several flavors (with different +# runtime options) so PREFERRED-RT-OPT is the preferred suffix. A suffix is one +# or more of the following letters: sgdpn (in that order). s = static +# runtime, d = debug build, g = debug/diagnostic runtime, p = STLPort build, +# n = (unsure) STLPort build without iostreams from STLPort (it looks like `n' +# must always be used along with `p'). Additionally, PREFERRED-RT-OPT can +# start with `mt-' to indicate that there is a preference for multi-thread +# builds. Some sample values for PREFERRED-RT-OPT: (nothing), mt, d, mt-d, gdp +# ... If you want to make sure you have a specific version of Boost +# (eg, >= 1.33) you *must* invoke BOOST_REQUIRE before this macro. +AC_DEFUN([BOOST_FIND_LIB], +[AC_REQUIRE([BOOST_REQUIRE])dnl +AC_REQUIRE([_BOOST_FIND_COMPILER_TAG])dnl +AC_REQUIRE([BOOST_STATIC])dnl +AC_REQUIRE([_BOOST_GUESS_WHETHER_TO_USE_MT])dnl +if test x"$boost_cv_inc_path" = xno; then + AC_MSG_NOTICE([Boost not available, not searching for the Boost $1 library]) +else +dnl The else branch is huge and wasn't intended on purpose. +AC_LANG_PUSH([C++])dnl +AS_VAR_PUSHDEF([Boost_lib], [boost_cv_lib_$1])dnl +AS_VAR_PUSHDEF([Boost_lib_LDFLAGS], [boost_cv_lib_$1_LDFLAGS])dnl +AS_VAR_PUSHDEF([Boost_lib_LDPATH], [boost_cv_lib_$1_LDPATH])dnl +AS_VAR_PUSHDEF([Boost_lib_LIBS], [boost_cv_lib_$1_LIBS])dnl +BOOST_FIND_HEADER([$3]) +boost_save_CPPFLAGS=$CPPFLAGS +CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" +# Now let's try to find the library. The algorithm is as follows: first look +# for a given library name according to the user's PREFERRED-RT-OPT. For each +# library name, we prefer to use the ones that carry the tag (toolset name). +# Each library is searched through the various standard paths were Boost is +# usually installed. If we can't find the standard variants, we try to +# enforce -mt (for instance on MacOSX, libboost_threads.dylib doesn't exist +# but there's -obviously- libboost_threads-mt.dylib). +AC_CACHE_CHECK([for the Boost $1 library], [Boost_lib], + [Boost_lib=no + case "$2" in #( + mt | mt-) boost_mt=-mt; boost_rtopt=;; #( + mt* | mt-*) boost_mt=-mt; boost_rtopt=`expr "X$2" : 'Xmt-*\(.*\)'`;; #( + *) boost_mt=; boost_rtopt=$2;; + esac + if test $enable_static_boost = yes; then + boost_rtopt="s$boost_rtopt" + fi + # Find the proper debug variant depending on what we've been asked to find. + case $boost_rtopt in #( + *d*) boost_rt_d=$boost_rtopt;; #( + *[[sgpn]]*) # Insert the `d' at the right place (in between `sg' and `pn') + boost_rt_d=`echo "$boost_rtopt" | sed 's/\(s*g*\)\(p*n*\)/\1\2/'`;; #( + *) boost_rt_d='-d';; + esac + # If the PREFERRED-RT-OPT are not empty, prepend a `-'. + test -n "$boost_rtopt" && boost_rtopt="-$boost_rtopt" + $boost_guess_use_mt && boost_mt=-mt + # Look for the abs path the static archive. + # $libext is computed by Libtool but let's make sure it's non empty. + test -z "$libext" && + AC_MSG_ERROR([the libext variable is empty, did you invoke Libtool?]) + boost_save_ac_objext=$ac_objext + # Generate the test file. + AC_LANG_CONFTEST([AC_LANG_PROGRAM([#include <$3> +$5], [$4])]) +dnl Optimization hacks: compiling C++ is slow, especially with Boost. What +dnl we're trying to do here is guess the right combination of link flags +dnl (LIBS / LDFLAGS) to use a given library. This can take several +dnl iterations before it succeeds and is thus *very* slow. So what we do +dnl instead is that we compile the code first (and thus get an object file, +dnl typically conftest.o). Then we try various combinations of link flags +dnl until we succeed to link conftest.o in an executable. The problem is +dnl that the various TRY_LINK / COMPILE_IFELSE macros of Autoconf always +dnl remove all the temporary files including conftest.o. So the trick here +dnl is to temporarily change the value of ac_objext so that conftest.o is +dnl preserved accross tests. This is obviously fragile and I will burn in +dnl hell for not respecting Autoconf's documented interfaces, but in the +dnl mean time, it optimizes the macro by a factor of 5 to 30. +dnl Another small optimization: the first argument of AC_COMPILE_IFELSE left +dnl empty because the test file is generated only once above (before we +dnl start the for loops). + AC_COMPILE_IFELSE([], + [ac_objext=do_not_rm_me_plz], + [AC_MSG_ERROR([cannot compile a test that uses Boost $1])]) + ac_objext=$boost_save_ac_objext + boost_failed_libs= +# Don't bother to ident the 6 nested for loops, only the 2 innermost ones +# matter. +for boost_tag_ in -$boost_cv_lib_tag ''; do +for boost_ver_ in -$boost_cv_lib_version ''; do +for boost_mt_ in $boost_mt '' -mt; do +for boost_rtopt_ in $boost_rtopt '' -d; do + for boost_lib in \ + boost_$1$boost_tag_$boost_mt_$boost_rtopt_$boost_ver_ \ + boost_$1$boost_tag_$boost_rtopt_$boost_ver_ \ + boost_$1$boost_tag_$boost_mt_$boost_ver_ \ + boost_$1$boost_tag_$boost_ver_ + do + # Avoid testing twice the same lib + case $boost_failed_libs in #( + *@$boost_lib@*) continue;; + esac + # If with_boost is empty, we'll search in /lib first, which is not quite + # right so instead we'll try to a location based on where the headers are. + boost_tmp_lib=$with_boost + test x"$with_boost" = x && boost_tmp_lib=${boost_cv_inc_path%/include} + for boost_ldpath in "$boost_tmp_lib/lib" '' \ + /opt/local/lib* /usr/local/lib* /opt/lib* /usr/lib* \ + "$with_boost" C:/Boost/lib /lib* + do + test -e "$boost_ldpath" || continue + boost_save_LDFLAGS=$LDFLAGS + # Are we looking for a static library? + case $boost_ldpath:$boost_rtopt_ in #( + *?*:*s*) # Yes (Non empty boost_ldpath + s in rt opt) + Boost_lib_LIBS="$boost_ldpath/lib$boost_lib.$libext" + test -e "$Boost_lib_LIBS" || continue;; #( + *) # No: use -lboost_foo to find the shared library. + Boost_lib_LIBS="-l$boost_lib";; + esac + boost_save_LIBS=$LIBS + LIBS="$Boost_lib_LIBS $LIBS" + test x"$boost_ldpath" != x && LDFLAGS="$LDFLAGS -L$boost_ldpath" +dnl First argument of AC_LINK_IFELSE left empty because the test file is +dnl generated only once above (before we start the for loops). + _BOOST_AC_LINK_IFELSE([], + [Boost_lib=yes], [Boost_lib=no]) + ac_objext=$boost_save_ac_objext + LDFLAGS=$boost_save_LDFLAGS + LIBS=$boost_save_LIBS + if test x"$Boost_lib" = xyes; then + Boost_lib_LDFLAGS="-L$boost_ldpath -Wl,-R$boost_ldpath" + Boost_lib_LDPATH="$boost_ldpath" + break 6 + else + boost_failed_libs="$boost_failed_libs@$boost_lib@" + fi + done + done +done +done +done +done +rm -f conftest.$ac_objext +]) +case $Boost_lib in #( + no) _AC_MSG_LOG_CONFTEST + AC_MSG_ERROR([cannot find the flags to link with Boost $1]) + ;; +esac +AC_SUBST(AS_TR_CPP([BOOST_$1_LDFLAGS]), [$Boost_lib_LDFLAGS])dnl +AC_SUBST(AS_TR_CPP([BOOST_$1_LDPATH]), [$Boost_lib_LDPATH])dnl +AC_SUBST([BOOST_LDPATH], [$Boost_lib_LDPATH])dnl +AC_SUBST(AS_TR_CPP([BOOST_$1_LIBS]), [$Boost_lib_LIBS])dnl +CPPFLAGS=$boost_save_CPPFLAGS +AS_VAR_POPDEF([Boost_lib])dnl +AS_VAR_POPDEF([Boost_lib_LDFLAGS])dnl +AS_VAR_POPDEF([Boost_lib_LDPATH])dnl +AS_VAR_POPDEF([Boost_lib_LIBS])dnl +AC_LANG_POP([C++])dnl +fi +])# BOOST_FIND_LIB + + +# --------------------------------------- # +# Checks for the various Boost libraries. # +# --------------------------------------- # + +# List of boost libraries: http://www.boost.org/libs/libraries.htm +# The page http://beta.boost.org/doc/libs is useful: it gives the first release +# version of each library (among other things). + +# BOOST_DEFUN(LIBRARY, CODE) +# -------------------------- +# Define BOOST_ as a macro that runs CODE. +# +# Use indir to avoid the warning on underquoted macro name given to AC_DEFUN. +m4_define([BOOST_DEFUN], +[m4_indir([AC_DEFUN], + m4_toupper([BOOST_$1]), +[m4_pushdef([BOOST_Library], [$1])dnl +$2 +m4_popdef([BOOST_Library])dnl +]) +]) + +# BOOST_ARRAY() +# ------------- +# Look for Boost.Array +BOOST_DEFUN([Array], +[BOOST_FIND_HEADER([boost/array.hpp])]) + + +# BOOST_ASIO() +# ------------ +# Look for Boost.Asio (new in Boost 1.35). +BOOST_DEFUN([Asio], +[AC_REQUIRE([BOOST_SYSTEM])dnl +BOOST_FIND_HEADER([boost/asio.hpp])]) + + +# BOOST_BIND() +# ------------ +# Look for Boost.Bind +BOOST_DEFUN([Bind], +[BOOST_FIND_HEADER([boost/bind.hpp])]) + + +# BOOST_CONVERSION() +# ------------------ +# Look for Boost.Conversion (cast / lexical_cast) +BOOST_DEFUN([Conversion], +[BOOST_FIND_HEADER([boost/cast.hpp]) +BOOST_FIND_HEADER([boost/lexical_cast.hpp]) +])# BOOST_CONVERSION + + +# BOOST_DATE_TIME([PREFERRED-RT-OPT]) +# ----------------------------------- +# Look for Boost.Date_Time. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Date_Time], +[BOOST_FIND_LIB([date_time], [$1], + [boost/date_time/posix_time/posix_time.hpp], + [boost::posix_time::ptime t;]) +])# BOOST_DATE_TIME + + +# BOOST_FILESYSTEM([PREFERRED-RT-OPT]) +# ------------------------------------ +# Look for Boost.Filesystem. For the documentation of PREFERRED-RT-OPT, see +# the documentation of BOOST_FIND_LIB above. +# Do not check for boost/filesystem.hpp because this file was introduced in +# 1.34. +BOOST_DEFUN([Filesystem], +[# Do we have to check for Boost.System? This link-time dependency was +# added as of 1.35.0. If we have a version <1.35, we must not attempt to +# find Boost.System as it didn't exist by then. +if test $boost_major_version -ge 135; then +BOOST_SYSTEM([$1]) +fi # end of the Boost.System check. +boost_filesystem_save_LIBS=$LIBS +boost_filesystem_save_LDFLAGS=$LDFLAGS +m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl +LIBS="$LIBS $BOOST_SYSTEM_LIBS" +LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" +BOOST_FIND_LIB([filesystem], [$1], + [boost/filesystem/path.hpp], [boost::filesystem::path p;]) +if test $enable_static_boost = yes && test $boost_major_version -ge 135; then + AC_SUBST([BOOST_FILESYSTEM_LIBS], ["$BOOST_FILESYSTEM_LIBS $BOOST_SYSTEM_LIBS"]) +fi +LIBS=$boost_filesystem_save_LIBS +LDFLAGS=$boost_filesystem_save_LDFLAGS +])# BOOST_FILESYSTEM + + +# BOOST_FOREACH() +# --------------- +# Look for Boost.Foreach +BOOST_DEFUN([Foreach], +[BOOST_FIND_HEADER([boost/foreach.hpp])]) + + +# BOOST_FORMAT() +# -------------- +# Look for Boost.Format +# Note: we can't check for boost/format/format_fwd.hpp because the header isn't +# standalone. It can't be compiled because it triggers the following error: +# boost/format/detail/config_macros.hpp:88: error: 'locale' in namespace 'std' +# does not name a type +BOOST_DEFUN([Format], +[BOOST_FIND_HEADER([boost/format.hpp])]) + + +# BOOST_FUNCTION() +# ---------------- +# Look for Boost.Function +BOOST_DEFUN([Function], +[BOOST_FIND_HEADER([boost/function.hpp])]) + + +# BOOST_GRAPH([PREFERRED-RT-OPT]) +# ------------------------------- +# Look for Boost.Graphs. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Graph], +[BOOST_FIND_LIB([graph], [$1], + [boost/graph/adjacency_list.hpp], [boost::adjacency_list<> g;]) +])# BOOST_GRAPH + + +# BOOST_IOSTREAMS([PREFERRED-RT-OPT]) +# ----------------------------------- +# Look for Boost.IOStreams. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([IOStreams], +[BOOST_FIND_LIB([iostreams], [$1], + [boost/iostreams/device/file_descriptor.hpp], + [boost::iostreams::file_descriptor fd; fd.close();]) +])# BOOST_IOSTREAMS + + +# BOOST_HASH() +# ------------ +# Look for Boost.Functional/Hash +BOOST_DEFUN([Hash], +[BOOST_FIND_HEADER([boost/functional/hash.hpp])]) + + +# BOOST_LAMBDA() +# -------------- +# Look for Boost.Lambda +BOOST_DEFUN([Lambda], +[BOOST_FIND_HEADER([boost/lambda/lambda.hpp])]) + + +# BOOST_LOG([PREFERRED-RT-OPT]) +# ----------------------------- +# Look for Boost.Log For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Log], +[BOOST_FIND_LIB([log], [$1], + [boost/log/core/core.hpp], + [boost::log::attribute a; a.get_value();]) +])# BOOST_LOG + + +# BOOST_LOG_SETUP([PREFERRED-RT-OPT]) +# ----------------------------------- +# Look for Boost.Log For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Log_Setup], +[AC_REQUIRE([BOOST_LOG])dnl +BOOST_FIND_LIB([log_setup], [$1], + [boost/log/utility/init/from_settings.hpp], + [boost::log::basic_settings bs; bs.empty();]) +])# BOOST_LOG_SETUP + + +# BOOST_MATH() +# ------------ +# Look for Boost.Math +# TODO: This library isn't header-only but it comes in multiple different +# flavors that don't play well with BOOST_FIND_LIB (e.g, libboost_math_c99, +# libboost_math_c99f, libboost_math_c99l, libboost_math_tr1, +# libboost_math_tr1f, libboost_math_tr1l). This macro must be fixed to do the +# right thing anyway. +BOOST_DEFUN([Math], +[BOOST_FIND_HEADER([boost/math/special_functions.hpp])]) + + +# BOOST_MULTIARRAY() +# ------------------ +# Look for Boost.MultiArray +BOOST_DEFUN([MultiArray], +[BOOST_FIND_HEADER([boost/multi_array.hpp])]) + + +# BOOST_NUMERIC_CONVERSION() +# -------------------------- +# Look for Boost.NumericConversion (policy-based numeric conversion) +BOOST_DEFUN([Numeric_Conversion], +[BOOST_FIND_HEADER([boost/numeric/conversion/converter.hpp]) +])# BOOST_NUMERIC_CONVERSION + + +# BOOST_OPTIONAL() +# ---------------- +# Look for Boost.Optional +BOOST_DEFUN([Optional], +[BOOST_FIND_HEADER([boost/optional.hpp])]) + + +# BOOST_PREPROCESSOR() +# -------------------- +# Look for Boost.Preprocessor +BOOST_DEFUN([Preprocessor], +[BOOST_FIND_HEADER([boost/preprocessor/repeat.hpp])]) + + +# BOOST_UNORDERED() +# ----------------- +# Look for Boost.Unordered +BOOST_DEFUN([Unordered], +[BOOST_FIND_HEADER([boost/unordered_map.hpp])]) + + +# BOOST_UUID() +# ------------ +# Look for Boost.Uuid +BOOST_DEFUN([Uuid], +[BOOST_FIND_HEADER([boost/uuid/uuid.hpp])]) + + +# BOOST_PROGRAM_OPTIONS([PREFERRED-RT-OPT]) +# ----------------------------------------- +# Look for Boost.Program_options. For the documentation of PREFERRED-RT-OPT, +# see the documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Program_Options], +[BOOST_FIND_LIB([program_options], [$1], + [boost/program_options.hpp], + [boost::program_options::options_description d("test");]) +])# BOOST_PROGRAM_OPTIONS + + + +# _BOOST_PYTHON_CONFIG(VARIABLE, FLAG) +# ------------------------------------ +# Save VARIABLE, and define it via `python-config --FLAG`. +# Substitute BOOST_PYTHON_VARIABLE. +m4_define([_BOOST_PYTHON_CONFIG], +[AC_SUBST([BOOST_PYTHON_$1], + [`python-config --$2 2>/dev/null`])dnl +boost_python_save_$1=$$1 +$1="$$1 $BOOST_PYTHON_$1"]) + + +# BOOST_PYTHON([PREFERRED-RT-OPT]) +# -------------------------------- +# Look for Boost.Python. For the documentation of PREFERRED-RT-OPT, +# see the documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Python], +[_BOOST_PYTHON_CONFIG([CPPFLAGS], [includes]) +_BOOST_PYTHON_CONFIG([LDFLAGS], [ldflags]) +_BOOST_PYTHON_CONFIG([LIBS], [libs]) +m4_pattern_allow([^BOOST_PYTHON_MODULE$])dnl +BOOST_FIND_LIB([python], [$1], + [boost/python.hpp], + [], [BOOST_PYTHON_MODULE(empty) {}]) +CPPFLAGS=$boost_python_save_CPPFLAGS +LDFLAGS=$boost_python_save_LDFLAGS +LIBS=$boost_python_save_LIBS +])# BOOST_PYTHON + + +# BOOST_REF() +# ----------- +# Look for Boost.Ref +BOOST_DEFUN([Ref], +[BOOST_FIND_HEADER([boost/ref.hpp])]) + + +# BOOST_REGEX([PREFERRED-RT-OPT]) +# ------------------------------- +# Look for Boost.Regex. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Regex], +[BOOST_FIND_LIB([regex], [$1], + [boost/regex.hpp], + [boost::regex exp("*"); boost::regex_match("foo", exp);]) +])# BOOST_REGEX + + +# BOOST_SERIALIZATION([PREFERRED-RT-OPT]) +# --------------------------------------- +# Look for Boost.Serialization. For the documentation of PREFERRED-RT-OPT, see +# the documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Serialization], +[BOOST_FIND_LIB([serialization], [$1], + [boost/archive/text_oarchive.hpp], + [std::ostream* o = 0; // Cheap way to get an ostream... + boost::archive::text_oarchive t(*o);]) +])# BOOST_SIGNALS + + +# BOOST_SIGNALS([PREFERRED-RT-OPT]) +# --------------------------------- +# Look for Boost.Signals. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Signals], +[BOOST_FIND_LIB([signals], [$1], + [boost/signal.hpp], + [boost::signal s;]) +])# BOOST_SIGNALS + + +# BOOST_SMART_PTR() +# ----------------- +# Look for Boost.SmartPtr +BOOST_DEFUN([Smart_Ptr], +[BOOST_FIND_HEADER([boost/scoped_ptr.hpp]) +BOOST_FIND_HEADER([boost/shared_ptr.hpp]) +]) + + +# BOOST_STATICASSERT() +# -------------------- +# Look for Boost.StaticAssert +BOOST_DEFUN([StaticAssert], +[BOOST_FIND_HEADER([boost/static_assert.hpp])]) + + +# BOOST_STRING_ALGO() +# ------------------- +# Look for Boost.StringAlgo +BOOST_DEFUN([String_Algo], +[BOOST_FIND_HEADER([boost/algorithm/string.hpp]) +]) + + +# BOOST_SYSTEM([PREFERRED-RT-OPT]) +# -------------------------------- +# Look for Boost.System. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. This library was introduced in Boost +# 1.35.0. +BOOST_DEFUN([System], +[BOOST_FIND_LIB([system], [$1], + [boost/system/error_code.hpp], + [boost::system::error_code e; e.clear();]) +])# BOOST_SYSTEM + + +# BOOST_TEST([PREFERRED-RT-OPT]) +# ------------------------------ +# Look for Boost.Test. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Test], +[m4_pattern_allow([^BOOST_CHECK$])dnl +BOOST_FIND_LIB([unit_test_framework], [$1], + [boost/test/unit_test.hpp], [BOOST_CHECK(2 == 2);], + [using boost::unit_test::test_suite; + test_suite* init_unit_test_suite(int argc, char ** argv) + { return NULL; }]) +])# BOOST_TEST + + +# BOOST_THREADS([PREFERRED-RT-OPT]) +# --------------------------------- +# Look for Boost.Thread. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +# FIXME: Provide an alias "BOOST_THREAD". +BOOST_DEFUN([Threads], +[dnl Having the pthread flag is required at least on GCC3 where +dnl boost/thread.hpp would complain if we try to compile without +dnl -pthread on GNU/Linux. +AC_REQUIRE([_BOOST_PTHREAD_FLAG])dnl +boost_threads_save_LIBS=$LIBS +boost_threads_save_CPPFLAGS=$CPPFLAGS +LIBS="$LIBS $boost_cv_pthread_flag" +# Yes, we *need* to put the -pthread thing in CPPFLAGS because with GCC3, +# boost/thread.hpp will trigger a #error if -pthread isn't used: +# boost/config/requires_threads.hpp:47:5: #error "Compiler threading support +# is not turned on. Please set the correct command line options for +# threading: -pthread (Linux), -pthreads (Solaris) or -mthreads (Mingw32)" +CPPFLAGS="$CPPFLAGS $boost_cv_pthread_flag" +BOOST_FIND_LIB([thread], [$1], + [boost/thread.hpp], [boost::thread t; boost::mutex m;]) +BOOST_THREAD_LIBS="$BOOST_THREAD_LIBS $boost_cv_pthread_flag" +BOOST_CPPFLAGS="$BOOST_CPPFLAGS $boost_cv_pthread_flag" +LIBS=$boost_threads_save_LIBS +CPPFLAGS=$boost_threads_save_CPPFLAGS +])# BOOST_THREADS + + +# BOOST_TOKENIZER() +# ----------------- +# Look for Boost.Tokenizer +BOOST_DEFUN([Tokenizer], +[BOOST_FIND_HEADER([boost/tokenizer.hpp])]) + + +# BOOST_TRIBOOL() +# --------------- +# Look for Boost.Tribool +BOOST_DEFUN([Tribool], +[BOOST_FIND_HEADER([boost/logic/tribool_fwd.hpp]) +BOOST_FIND_HEADER([boost/logic/tribool.hpp]) +]) + + +# BOOST_TUPLE() +# ------------- +# Look for Boost.Tuple +BOOST_DEFUN([Tuple], +[BOOST_FIND_HEADER([boost/tuple/tuple.hpp])]) + + +# BOOST_TYPETRAITS() +# -------------------- +# Look for Boost.TypeTraits +BOOST_DEFUN([TypeTraits], +[BOOST_FIND_HEADER([boost/type_traits.hpp])]) + + +# BOOST_UTILITY() +# --------------- +# Look for Boost.Utility (noncopyable, result_of, base-from-member idiom, +# etc.) +BOOST_DEFUN([Utility], +[BOOST_FIND_HEADER([boost/utility.hpp])]) + + +# BOOST_VARIANT() +# --------------- +# Look for Boost.Variant. +BOOST_DEFUN([Variant], +[BOOST_FIND_HEADER([boost/variant/variant_fwd.hpp]) +BOOST_FIND_HEADER([boost/variant.hpp])]) + + +# BOOST_WAVE([PREFERRED-RT-OPT]) +# ------------------------------ +# NOTE: If you intend to use Wave/Spirit with thread support, make sure you +# call BOOST_THREADS first. +# Look for Boost.Wave. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Wave], +[AC_REQUIRE([BOOST_FILESYSTEM])dnl +AC_REQUIRE([BOOST_DATE_TIME])dnl +boost_wave_save_LIBS=$LIBS +boost_wave_save_LDFLAGS=$LDFLAGS +m4_pattern_allow([^BOOST_((FILE)?SYSTEM|DATE_TIME|THREAD)_(LIBS|LDFLAGS)$])dnl +LIBS="$LIBS $BOOST_SYSTEM_LIBS $BOOST_FILESYSTEM_LIBS $BOOST_DATE_TIME_LIBS\ +$BOOST_THREAD_LIBS" +LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS $BOOST_FILESYSTEM_LDFLAGS\ +$BOOST_DATE_TIME_LDFLAGS $BOOST_THREAD_LDFLAGS" +BOOST_FIND_LIB([wave], [$1], + [boost/wave.hpp], + [boost::wave::token_id id; get_token_name(id);]) +LIBS=$boost_wave_save_LIBS +LDFLAGS=$boost_wave_save_LDFLAGS +])# BOOST_WAVE + + +# BOOST_XPRESSIVE() +# ----------------- +# Look for Boost.Xpressive (new since 1.36.0). +BOOST_DEFUN([Xpressive], +[BOOST_FIND_HEADER([boost/xpressive/xpressive.hpp])]) + + +# ----------------- # +# Internal helpers. # +# ----------------- # + + +# _BOOST_PTHREAD_FLAG() +# --------------------- +# Internal helper for BOOST_THREADS. Based on ACX_PTHREAD: +# http://autoconf-archive.cryp.to/acx_pthread.html +AC_DEFUN([_BOOST_PTHREAD_FLAG], +[AC_REQUIRE([AC_PROG_CXX])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_LANG_PUSH([C++])dnl +AC_CACHE_CHECK([for the flags needed to use pthreads], [boost_cv_pthread_flag], +[ boost_cv_pthread_flag= + # The ordering *is* (sometimes) important. Some notes on the + # individual items follow: + # (none): in case threads are in libc; should be tried before -Kthread and + # other compiler flags to prevent continual compiler warnings + # -lpthreads: AIX (must check this before -lpthread) + # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # -llthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + # -pthread: GNU Linux/GCC (kernel threads), BSD/GCC (userland threads) + # -pthreads: Solaris/GCC + # -mthreads: MinGW32/GCC, Lynx/GCC + # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it + # doesn't hurt to check since this sometimes defines pthreads too; + # also defines -D_REENTRANT) + # ... -mt is also the pthreads flag for HP/aCC + # -lpthread: GNU Linux, etc. + # --thread-safe: KAI C++ + case $host_os in #( + *solaris*) + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (We need to link with -pthreads/-mt/ + # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather + # a function called by this macro, so we could check for that, but + # who knows whether they'll stub that too in a future libc.) So, + # we'll just look for -pthreads and -lpthread first: + boost_pthread_flags="-pthreads -lpthread -mt -pthread";; #( + *) + boost_pthread_flags="-lpthreads -Kthread -kthread -llthread -pthread \ + -pthreads -mthreads -lpthread --thread-safe -mt";; + esac + # Generate the test file. + AC_LANG_CONFTEST([AC_LANG_PROGRAM([#include ], + [pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0);])]) + for boost_pthread_flag in '' $boost_pthread_flags; do + boost_pthread_ok=false +dnl Re-use the test file already generated. + boost_pthreads__save_LIBS=$LIBS + LIBS="$LIBS $boost_pthread_flag" + AC_LINK_IFELSE([], + [if grep ".*$boost_pthread_flag" conftest.err; then + echo "This flag seems to have triggered warnings" >&AS_MESSAGE_LOG_FD + else + boost_pthread_ok=:; boost_cv_pthread_flag=$boost_pthread_flag + fi]) + LIBS=$boost_pthreads__save_LIBS + $boost_pthread_ok && break + done +]) +AC_LANG_POP([C++])dnl +])# _BOOST_PTHREAD_FLAG + + +# _BOOST_gcc_test(MAJOR, MINOR) +# ----------------------------- +# Internal helper for _BOOST_FIND_COMPILER_TAG. +m4_define([_BOOST_gcc_test], +["defined __GNUC__ && __GNUC__ == $1 && __GNUC_MINOR__ == $2 && !defined __ICC @ gcc$1$2"])dnl + + +# _BOOST_FIND_COMPILER_TAG() +# -------------------------- +# Internal. When Boost is installed without --layout=system, each library +# filename will hold a suffix that encodes the compiler used during the +# build. The Boost build system seems to call this a `tag'. +AC_DEFUN([_BOOST_FIND_COMPILER_TAG], +[AC_REQUIRE([AC_PROG_CXX])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_CACHE_CHECK([for the toolset name used by Boost for $CXX], [boost_cv_lib_tag], +[boost_cv_lib_tag=unknown +if test x$boost_cv_inc_path != xno; then + AC_LANG_PUSH([C++])dnl + # The following tests are mostly inspired by boost/config/auto_link.hpp + # The list is sorted to most recent/common to oldest compiler (in order + # to increase the likelihood of finding the right compiler with the + # least number of compilation attempt). + # Beware that some tests are sensible to the order (for instance, we must + # look for MinGW before looking for GCC3). + # I used one compilation test per compiler with a #error to recognize + # each compiler so that it works even when cross-compiling (let me know + # if you know a better approach). + # Known missing tags (known from Boost's tools/build/v2/tools/common.jam): + # como, edg, kcc, bck, mp, sw, tru, xlc + # I'm not sure about my test for `il' (be careful: Intel's ICC pre-defines + # the same defines as GCC's). + for i in \ + _BOOST_gcc_test(4, 6) \ + _BOOST_gcc_test(4, 5) \ + _BOOST_gcc_test(4, 4) \ + _BOOST_gcc_test(4, 3) \ + _BOOST_gcc_test(4, 2) \ + _BOOST_gcc_test(4, 1) \ + _BOOST_gcc_test(4, 0) \ + "defined __GNUC__ && __GNUC__ == 3 && !defined __ICC \ + && (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw" \ + _BOOST_gcc_test(3, 4) \ + _BOOST_gcc_test(3, 3) \ + "defined _MSC_VER && _MSC_VER >= 1500 @ vc90" \ + "defined _MSC_VER && _MSC_VER == 1400 @ vc80" \ + _BOOST_gcc_test(3, 2) \ + "defined _MSC_VER && _MSC_VER == 1310 @ vc71" \ + _BOOST_gcc_test(3, 1) \ + _BOOST_gcc_test(3, 0) \ + "defined __BORLANDC__ @ bcb" \ + "defined __ICC && (defined __unix || defined __unix__) @ il" \ + "defined __ICL @ iw" \ + "defined _MSC_VER && _MSC_VER == 1300 @ vc7" \ + _BOOST_gcc_test(2, 95) \ + "defined __MWERKS__ && __MWERKS__ <= 0x32FF @ cw9" \ + "defined _MSC_VER && _MSC_VER < 1300 && !defined UNDER_CE @ vc6" \ + "defined _MSC_VER && _MSC_VER < 1300 && defined UNDER_CE @ evc4" \ + "defined __MWERKS__ && __MWERKS__ <= 0x31FF @ cw8" + do + boost_tag_test=`expr "X$i" : 'X\([[^@]]*\) @ '` + boost_tag=`expr "X$i" : 'X[[^@]]* @ \(.*\)'` + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#if $boost_tag_test +/* OK */ +#else +# error $boost_tag_test +#endif +]])], [boost_cv_lib_tag=$boost_tag; break], []) + done +AC_LANG_POP([C++])dnl + case $boost_cv_lib_tag in #( + # Some newer (>= 1.35?) versions of Boost seem to only use "gcc" as opposed + # to "gcc41" for instance. + *-gcc | *'-gcc ') :;; #( Don't re-add -gcc: it's already in there. + gcc*) + boost_tag_x= + case $host_os in #( + darwin*) + if test $boost_major_version -ge 136; then + # The `x' added in r46793 of Boost. + boost_tag_x=x + fi;; + esac + # We can specify multiple tags in this variable because it's used by + # BOOST_FIND_LIB that does a `for tag in -$boost_cv_lib_tag' ... + boost_cv_lib_tag="$boost_tag_x$boost_cv_lib_tag -${boost_tag_x}gcc" + ;; #( + unknown) + AC_MSG_WARN([[could not figure out which toolset name to use for $CXX]]) + boost_cv_lib_tag= + ;; + esac +fi])dnl end of AC_CACHE_CHECK +])# _BOOST_FIND_COMPILER_TAG + + +# _BOOST_GUESS_WHETHER_TO_USE_MT() +# -------------------------------- +# Compile a small test to try to guess whether we should favor MT (Multi +# Thread) flavors of Boost. Sets boost_guess_use_mt accordingly. +AC_DEFUN([_BOOST_GUESS_WHETHER_TO_USE_MT], +[# Check whether we do better use `mt' even though we weren't ask to. +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#if defined _REENTRANT || defined _MT || defined __MT__ +/* use -mt */ +#else +# error MT not needed +#endif +]])], [boost_guess_use_mt=:], [boost_guess_use_mt=false]) +]) + +# _BOOST_AC_LINK_IFELSE(PROGRAM, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) +# ------------------------------------------------------------------- +# Fork of _AC_LINK_IFELSE that preserves conftest.o across calls. Fragile, +# will break when Autoconf changes its internals. Requires that you manually +# rm -f conftest.$ac_objext in between to really different tests, otherwise +# you will try to link a conftest.o left behind by a previous test. +# Used to aggressively optimize BOOST_FIND_LIB (see the big comment in this +# macro). +# +# Don't use "break" in the actions, as it would short-circuit some code +# this macro runs after the actions. +m4_define([_BOOST_AC_LINK_IFELSE], +[m4_ifvaln([$1], [AC_LANG_CONFTEST([$1])])dnl +rm -f conftest$ac_exeext +boost_save_ac_ext=$ac_ext +boost_use_source=: +# If we already have a .o, re-use it. We change $ac_ext so that $ac_link +# tries to link the existing object file instead of compiling from source. +test -f conftest.$ac_objext && ac_ext=$ac_objext && boost_use_source=false && + _AS_ECHO_LOG([re-using the existing conftest.$ac_objext]) +AS_IF([_AC_DO_STDERR($ac_link) && { + test -z "$ac_[]_AC_LANG_ABBREV[]_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_executable_p conftest$ac_exeext +dnl FIXME: use AS_TEST_X instead when 2.61 is widespread enough. + }], + [$2], + [if $boost_use_source; then + _AC_MSG_LOG_CONFTEST + fi + $3]) +ac_objext=$boost_save_ac_objext +ac_ext=$boost_save_ac_ext +dnl Delete also the IPA/IPO (Inter Procedural Analysis/Optimization) +dnl information created by the PGI compiler (conftest_ipa8_conftest.oo), +dnl as it would interfere with the next link command. +rm -f core conftest.err conftest_ipa8_conftest.oo \ + conftest$ac_exeext m4_ifval([$1], [conftest.$ac_ext])[]dnl +])# _BOOST_AC_LINK_IFELSE + +# Local Variables: +# mode: autoconf +# End: diff --git a/m4/cxxflags.m4 b/m4/cxxflags.m4 new file mode 100644 index 0000000..4008fbe --- /dev/null +++ b/m4/cxxflags.m4 @@ -0,0 +1,96 @@ +AC_PREREQ([2.60]) + +# AC_CXX_FLAGS +# ------------ +# Attempts to recognize specific compilers to set, if availables, extra +# flags for debugging, optimization and strict conformance to language +# specifications. + +# This macro checks for the following compilers : +# - GNU C++ (g++) +# - Sun WorkShop C++ (Sun/CC) +# - Intel C++ (icc) +# - Comeau C++ (como) +# and sets the following autoconf variables: +# CXXFLAGS_DEBUG +# CXXFLAGS_STRICT +# CXXFLAGS_STRICT_ERRORS +# CXXFLAGS_OPTIMIZE +AC_DEFUN([AC_CXX_FLAGS], +[dnl + AC_REQUIRE([AC_PROG_CXX]) + AC_LANG_PUSH([C++]) + AC_CACHE_CHECK([for C++ compiler-specific extra flags], + [ac_cv_cxx_style], + [ac_cv_cxx_style=unknown + if $CXX -V 2>&1 | grep -i "Intel(R) C++">/dev/null 2>&1; + then + ac_cv_cxx_style=Intel + elif test "x$ac_compiler_gnu" != xno; then + if $CXX --version | grep '^2\.' >/dev/null ; then + ac_cv_cxx_style=weakGNU + else + ac_cv_cxx_style=GNU + fi + elif $CXX -V 2>&1 | grep -i "WorkShop">/dev/null 2>&1; then + ac_cv_cxx_style=Sun + else + echo "int main() {}" >conftest.cc + if $CXX --version conftest.cc 2>&1 \ + | grep -i "Comeau C/C++" >/dev/null 2>&1; then + ac_cv_cxx_style=Comeau + fi + rm -f conftest.* + fi]) + AC_LANG_POP([C++]) + + case $ac_cv_cxx_style in + GNU) + _CXXFLAGS_DEBUG="-g" + _CXXFLAGS_OPTIMIZE="-O3 -finline-limit-1500" + _CXXFLAGS_STRICT="-W -Wall" + _CXXFLAGS_STRICT_ERRORS="-W -Wall -Werror" + ;; + weakGNU) + _CXXFLAGS_DEBUG="-g" + _CXXFLAGS_OPTIMIZE="-O2 -felide-constructors -funroll-loops" + _CXXFLAGS_STRICT="-W -Wall" + _CXXFLAGS_STRICT_ERRORS="-W -Wall -Werror" + ;; + Sun) + _CXXFLAGS_DEBUG="-g" + _CXXFLAGS_OPTIMIZE="-fast" + _CXXFLAGS_STRICT="-v" + _CXXFLAGS_STRICT_ERRORS="-v -xwe" + ;; + Comeau) + _CXXFLAGS_DEBUG="-g" + _CXXFLAGS_STRICT="-r" + _CXXFLAGS_STRICT_ERRORS="-r" + ;; + Intel) + _CXXFLAGS_OPTIMIZE="-O3" + _CXXFLAGS_DEBUG="-g" + _CXXFLAGS_STRICT="-wd111,193,279,383,444,654,810,981,1418,327" + _CXXFLAGS_STRICT_ERRORS="-wd111,193,279,383,444,654,810,981,1418,327" + ;; + esac + + if test "x$CXXFLAGS_OPTIMIZE" = "x"; then + CXXFLAGS_OPTIMIZE=$_CXXFLAGS_OPTIMIZE + fi + if test "x$CXXFLAGS_DEBUG" = "x"; then + CXXFLAGS_DEBUG=$_CXXFLAGS_DEBUG + fi + if test "x$CXXFLAGS_STRICT" = "x"; then + CXXFLAGS_STRICT=$_CXXFLAGS_STRICT + fi + if test "x$CXXFLAGS_STRICT_ERRORS" = "x"; then + CXXFLAGS_STRICT_ERRORS=$_CXXFLAGS_STRICT_ERRORS + fi + + AC_SUBST([CXXFLAGS_DEBUG]) + AC_SUBST([CXXFLAGS_OPTIMIZE]) + AC_SUBST([CXXFLAGS_STRICT]) + AC_SUBST([CXXFLAGS_STRICT_ERRORS]) +]) diff --git a/m4/m4_ax_pkg_swig.m4 b/m4/m4_ax_pkg_swig.m4 new file mode 100644 index 0000000..e112f3d --- /dev/null +++ b/m4/m4_ax_pkg_swig.m4 @@ -0,0 +1,135 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_pkg_swig.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_PKG_SWIG([major.minor.micro], [action-if-found], [action-if-not-found]) +# +# DESCRIPTION +# +# This macro searches for a SWIG installation on your system. If found, +# then SWIG is AC_SUBST'd; if not found, then $SWIG is empty. If SWIG is +# found, then SWIG_LIB is set to the SWIG library path, and AC_SUBST'd. +# +# You can use the optional first argument to check if the version of the +# available SWIG is greater than or equal to the value of the argument. It +# should have the format: N[.N[.N]] (N is a number between 0 and 999. Only +# the first N is mandatory.) If the version argument is given (e.g. +# 1.3.17), AX_PKG_SWIG checks that the swig package is this version number +# or higher. +# +# As usual, action-if-found is executed if SWIG is found, otherwise +# action-if-not-found is executed. +# +# In configure.in, use as: +# +# AX_PKG_SWIG(1.3.17, [], [ AC_MSG_ERROR([SWIG is required to build..]) ]) +# AX_SWIG_ENABLE_CXX +# AX_SWIG_MULTI_MODULE_SUPPORT +# AX_SWIG_PYTHON +# +# LICENSE +# +# Copyright (c) 2008 Sebastian Huber +# Copyright (c) 2008 Alan W. Irwin +# Copyright (c) 2008 Rafael Laboissiere +# Copyright (c) 2008 Andrew Collier +# Copyright (c) 2011 Murray Cumming +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2 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. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see . +# +# As a special exception, the respective Autoconf Macro's copyright owner +# gives unlimited permission to copy, distribute and modify the configure +# scripts that are the output of Autoconf when processing the Macro. You +# need not follow the terms of the GNU General Public License when using +# or distributing such scripts, even though portions of the text of the +# Macro appear in them. The GNU General Public License (GPL) does govern +# all other use of the material that constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the Autoconf +# Macro released by the Autoconf Archive. When you make and distribute a +# modified version of the Autoconf Macro, you may extend this special +# exception to the GPL to apply to your modified version as well. + +#serial 8 + +AC_DEFUN([AX_PKG_SWIG],[ + # Ubuntu has swig 2.0 as /usr/bin/swig2.0 + AC_PATH_PROGS([SWIG],[swig swig2.0]) + if test -z "$SWIG" ; then + m4_ifval([$3],[$3],[:]) + elif test -n "$1" ; then + AC_MSG_CHECKING([SWIG version]) + [swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`] + AC_MSG_RESULT([$swig_version]) + if test -n "$swig_version" ; then + # Calculate the required version number components + [required=$1] + [required_major=`echo $required | sed 's/[^0-9].*//'`] + if test -z "$required_major" ; then + [required_major=0] + fi + [required=`echo $required | sed 's/[0-9]*[^0-9]//'`] + [required_minor=`echo $required | sed 's/[^0-9].*//'`] + if test -z "$required_minor" ; then + [required_minor=0] + fi + [required=`echo $required | sed 's/[0-9]*[^0-9]//'`] + [required_patch=`echo $required | sed 's/[^0-9].*//'`] + if test -z "$required_patch" ; then + [required_patch=0] + fi + # Calculate the available version number components + [available=$swig_version] + [available_major=`echo $available | sed 's/[^0-9].*//'`] + if test -z "$available_major" ; then + [available_major=0] + fi + [available=`echo $available | sed 's/[0-9]*[^0-9]//'`] + [available_minor=`echo $available | sed 's/[^0-9].*//'`] + if test -z "$available_minor" ; then + [available_minor=0] + fi + [available=`echo $available | sed 's/[0-9]*[^0-9]//'`] + [available_patch=`echo $available | sed 's/[^0-9].*//'`] + if test -z "$available_patch" ; then + [available_patch=0] + fi + # Convert the version tuple into a single number for easier comparison. + # Using base 100 should be safe since SWIG internally uses BCD values + # to encode its version number. + required_swig_vernum=`expr $required_major \* 10000 \ + \+ $required_minor \* 100 \+ $required_patch` + available_swig_vernum=`expr $available_major \* 10000 \ + \+ $available_minor \* 100 \+ $available_patch` + + if test $available_swig_vernum -lt $required_swig_vernum; then + AC_MSG_WARN([SWIG version >= $1 is required. You have $swig_version.]) + SWIG='' + m4_ifval([$3],[$3],[]) + else + AC_MSG_CHECKING([for SWIG library]) + SWIG_LIB=`$SWIG -swiglib` + AC_MSG_RESULT([$SWIG_LIB]) + m4_ifval([$2],[$2],[]) + fi + else + AC_MSG_WARN([cannot determine SWIG version]) + SWIG='' + m4_ifval([$3],[$3],[]) + fi + fi + AC_SUBST([SWIG_LIB]) +]) diff --git a/script/precision.sh b/script/precision.sh new file mode 100755 index 0000000..97e2c07 --- /dev/null +++ b/script/precision.sh @@ -0,0 +1,22 @@ +#!/bin/bash +[ $# -eq 1 ] || { echo "wrong number of parameters"; exit 1; } +TRACE_PATH=$(pwd) +SCRIPT_HOME=$(cd `dirname $(readlink -e $0)` && pwd) + +mkdir -p precision +# rm -f precision/* +for i in `find $TRACE_PATH | grep trace | shuf`; +do + echo $i; + suff=`echo ${i##*/} | cut -d '.' -f 2-`; + path=`dirname $i`; + echo "$TRACE_PATH/precision/res.$suff $(test -f ./precision/res.$suff && echo OK)" + if [ ! -e $TRACE_PATH/precision/res.$suff ]; then + touch $TRACE_PATH/precision/res.$suff + if [ -f $path/graph_simplified.$suff ]; then + $SCRIPT_HOME/run_trace.sh -p 10000 -s 50000 -g $path/graph_simplified.$suff -t $i -v > $TRACE_PATH/precision/res.$suff + else + $SCRIPT_HOME/run_trace.sh -p 10000 -s 50000 -g $path/graph_not_simplified.$suff -t $i -v > $TRACE_PATH/precision/res.$suff + fi + fi +done diff --git a/script/qdftgraph_pp.sh b/script/qdftgraph_pp.sh new file mode 100755 index 0000000..df8c9ac --- /dev/null +++ b/script/qdftgraph_pp.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +n=96 +echo "digraph G {" +echo "rankdir=LR" +grep -v "transfered=0" | +sed -e "s/^0 \[amount=\([0-9]*\),.*name=\"*\([^\"]*\)\"*\]/0 [style=dotted, label=\"\2\\\\\\\n\1\"]/g" \ + -e "s/\([0-9]*\) \[amount=\([0-9]*\), fake=0, name=src_\]/\1 [style=filled, label=\"src_\1\\\\\\\n\2\"]/g" \ + -e "s/\([0-9]*\) \[amount=\([0-9]*\), fake=1, name=src_\]/\1 [label=\"src_\1\\\\\\\n\2\"]/g" \ + -e "s/\([0-9]*\) \[amount=\([0-9]*\), fake=0, name=\"*\([^\"]*\)\"*\]/\1 [shape=box, style=filled, label=\"\3\\\\\\\n\2\"]/g" \ + -e "s/\([0-9]*\) \[amount=\([0-9]*\), fake=1, name=\"*\([^\"]*\)\"*\]/\1 [shape=box, label=\"\3\\\\\\\n\2\"]/g" \ + -e "s/transfered/label/g" | \ +while read line; do + echo $line | grep -q "digraph" + if [ $? -eq 0 ]; then + let ++n + c=`printf "\x$(printf %x $n)"` + echo $line | sed -e "s/digraph \(.*\) {/subgraph \1$c {/" + else + c=`printf "\x$(printf %x $n)"` + echo $line | sed -e "s/\([0-9][0-9]*\)/$c\1/" -e "s/->\([0-9]*\)/->$c\1/" + fi +done +echo "}" diff --git a/script/run_trace.sh b/script/run_trace.sh new file mode 100755 index 0000000..7fd2eca --- /dev/null +++ b/script/run_trace.sh @@ -0,0 +1,182 @@ +#! /usr/bin/env bash +LANG=C +XP_PATH="/tmp/xp" +CACHE_PATH="/tmp/ex.pu$PUBLIC_LINES.se$SENSITIVE_LINES" #useless here, variables not assigned +NS=6 +NC=9 + +# print log information w.r.t the verbosity level +log() { + [[ $# -ge 2 ]] || die "log INFO|ERROR|DEBUG msg" + local level="$1" + shift + local msg="$*" + case $level in + INFO ) [[ $VERBOSE -ge 1 ]] && echo "[INFO] $msg" 1>&2 ;; + ERROR ) [[ $VERBOSE -ge 1 ]] && echo "[ERROR] $msg" 1>&2 ;; + DEBUG ) [[ $VERBOSE -ge 2 ]] && echo "[DEBUG] $msg" 1>&2 ;; + esac + mode=$level +} + +# Print error message and exit +die() { + echo $* + exit 1 +} + +reset() { + CACHE_PATH="/tmp/ex.pu$PUBLIC_LINES.se$SENSITIVE_LINES" + rm -rf "$XP_PATH" + if [ $CACHE -eq 1 -a -d "$CACHE_PATH" ]; then + cp -r "$CACHE_PATH" "$XP_PATH" + else + log INFO "Initializing the structure for $XP_PATH..." + sum=0 + rm -rf "$CACHE_PATH" + mkdir -p "$XP_PATH" + # Create sensitive specifications + for f in $(seq 0 $NS); do + fname="$XP_PATH/s$f" + rm -f "$fname"; + touch "$fname"; + for l in $(seq $SENSITIVE_LINES); do + echo sensitive_spec${f}_${l} >> "$fname"; + done + done + for f in $(seq 0 $NC); do + fname="$XP_PATH/c$f" + rm -f "$fname"; + touch "$fname"; + for l in $(seq $PUBLIC_LINES); do + echo public_$l >> "$fname"; + done + done + cp -r "$XP_PATH" "$CACHE_PATH" + fi +} + +run() { + trace="$1" + log INFO "Executing the traces from $trace..." + [[ -f "$trace" ]] || die "$trace must be a regular file" + while read line; do + log DEBUG "Line [$line]" + local n=$(echo $line | cut -d' ' -f3) + local c1="$XP_PATH/$(echo $line | cut -d' ' -f5)" + local c2="$XP_PATH/$(echo $line | cut -d' ' -f7)" + local size=$(wc -l $c1 | cut -d' ' -f1) + if [ $size -ne 0 ]; then + let r=n/size+1 + cat $(for i in $(seq $r); do echo -n "$c1 "; done) | shuf | head -n$n >> $c2 + else + touch $c2 + fi + done < $trace +} + +show_results() { + [[ -f "$GRAPH" ]] || die "$GRAPH must be a regular file" + echo "========================================" + printf '%10s | %6s | %6s | %6s | %5s\n' "filename" "lines" "qdft" "ulines" "PERF" + local dests=($XP_PATH/c*) + for f in ${dests[@]}; do + local size=$(wc -l $f | cut -d' ' -f1) + # grep sensitive $f | sort | uniq > /tmp/f.uniq + local usize=$(grep sensitive $f | sort | uniq | wc -l) + local cname=${f##*/} + pdp=$(grep "name=$cname]" $GRAPH | grep "fake=0" | cut -d '=' -f2 | cut -d ',' -f1) + if [ -z "$pdp" ]; then + pdp=0 + fi + if [ $size -gt $usize ]; then + perf=$(echo "($size - $pdp) / ($size - $usize)" | bc -l 2>/dev/null) + else + perf=1 + fi + printf '%10s | %6d | %6d | %6d | %.3f\n' "${f##*/}" $size $pdp $usize $perf + done +} + +# Usage +usage() { + echo "Usage: $0 [OPTIONS]" + echo "Run transfers described the trace file" + echo "Options are:" + echo " -c, --no-cache do not use the cache folder" + echo " -g, --graph FILE set the file that contains the graph (default is $GRAPH)" + echo " -h, --help display this help and exit" + echo " -p, --plines N set the initial number of public lines (default is $PUBLIC_LINES)" + echo " -s, --slines N set the initial number of sensitive lines (default is $SENSITIVE_LINES)" + echo " -t, --trace FILE set the file which contains the trace (default is $TRACEFILE)" + echo " -v, --verbose be verbose, use several times to be even more verbose" +} + +# SCRIPT STARTS HERE +INTERACTIVE=0 +TRACEFILE=transfers.log +GRAPH=graph.dot +VERBOSE=0 +PUBLIC_LINES=1000 +SENSITIVE_LINES=50000 +CACHE=1 +while [ "$1" != "" ]; do + case $1 in + -c | --no-cache ) + CACHE=0 + ;; + -g | --graph ) + shift + GRAPH="$1" + ;; + -h | --help ) + usage + exit + ;; + -p | --plines ) + shift + PUBLIC_LINES="$1" + ;; + -s | --slines ) + shift + SENSITIVE_LINES="$1" + ;; + -t | --trace ) + shift + TRACEFILE="$1" + ;; + -v | --verbose ) + VERBOSE=$((VERBOSE + 1)) + ;; + # Special cases + --) + break + ;; + --*) + echo "Error unknown (long) option $1" + usage + exit + ;; + -?) + echo "Error unknown (short) option $1" + usage + exit + ;; + # Split apart combined short options + -*) + split=$1 + shift + set -- $(echo "$split" | cut -c 2- | sed 's/./-& /g') "$@" + continue + ;; + # Done with options + *) + break + ;; + esac + shift +done + +reset +run $TRACEFILE +show_results diff --git a/script/time.sh b/script/time.sh new file mode 100755 index 0000000..1afe95b --- /dev/null +++ b/script/time.sh @@ -0,0 +1,66 @@ + +#!/bin/bash +T_SEP="," +H_SEP="," + +PS="0 20 40 60 80 100" #remember to change the field in the last command if you change the size of PS. f=PS+2 +PN="20 60 100" + +#no dots in the output name +OUTPUT="time_pn20-60_ps0-100" + +TYPE="not_simplified" + + +for l in 2 4 8 16 32 64 128 256 512 1024; do + TITLE="LENGTH $l\n" + TABLE="" + for ps in $PS; do + TABLE=$TABLE"${H_SEP}$ps" + done + TABLE=$TABLE"${H_SEP}AV${H_SEP}\n"; + AVCOLAV="" + for pn in $PN; do + ROW="$pn${T_SEP}"; + ROWAV=""; + for ps in $PS; do + VAL="`cat ./length.$l/$l.pn$pn.ps$ps/results.$l.$pn.$ps.$TYPE | grep . | cut -f 2 -d ':' | awk '{sum+=$1} END {printf "%5.4f", sum/NR}'`"; + ROWAV=$ROWAV"\n"$VAL + ROW=$ROW$VAL"${H_SEP}" + done; + ROWAV=`echo -e $ROWAV | sed '/^$/d' | awk '{sum+=$1} END {printf "%5.4f", sum/NR}'`; + AVCOLAV=$AVCOLAV"\n"$ROWAV + ROW=$ROW$ROWAV"\n" + TABLE=$TABLE$ROW + done + ROW="AV${H_SEP}" + for ps in $PS; do + COLAV="" + for pn in $PN; do + VAL="`cat ./length.$l/$l.pn$pn.ps$ps/results.$l.$pn.$ps.$TYPE | grep . | cut -f 2 -d ':' | awk '{sum+=$1} END {printf "%5.4f", sum/NR}'`"; + COLAV=$COLAV"\n"$VAL + done + COLAV=`echo -e $COLAV | sed '/^$/d' | awk '{sum+=$1} END {printf "%5.4f", sum/NR}'`; + ROW=$ROW$COLAV"${H_SEP}" + done + AVCOLAV=`echo -e $AVCOLAV | sed '/^$/d' | awk '{sum+=$1} END {printf "%5.4f", sum/NR}'`; + TABLE=$TABLE$ROW$AVCOLAV + echo -e "$TITLE$TABLE" | tee $OUTPUT.$l +done + +for i in `ls ${OUTPUT}*`; do + NUM=`echo -n $i | cut -d '.' -f 2`; + echo -n $NUM$H_SEP`tail -n 1 $i | cut -d ',' -f 2-` ; + echo; +done > total.ps$OUTPUT + + +# for i in `ls ${OUTPUT}*`; do +# IND=2 +# echo -n $i | cut -d '.' -f 2; +# for ps in $PS; do +# echo -n " `tail -n 1 $i | cut -d ',' -f $IND` " ; +# let IND=$IND+1; +# done +# echo; +# done > total.ps$OUTPUT \ No newline at end of file diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..0760059 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,26 @@ +# Copyright (C) 2011 Johan Oudinet +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 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. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + +AM_CPPFLAGS = -I$(srcdir)/../include $(BOOST_CPPFLAGS) + +bin_PROGRAMS = example testlib + +example_SOURCES = example.cc +example_LDADD = ../include/libqdftgraph.la + +testlib_SOURCES = test_lib.cc +testlib_LDADD = ../include/libqdftgraph.la diff --git a/src/example.cc b/src/example.cc new file mode 100644 index 0000000..d6a0643 --- /dev/null +++ b/src/example.cc @@ -0,0 +1,169 @@ +// Copyright (C) 2011, 2012 Johan Oudinet +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 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. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +#ifndef QDFT_EXAMPLE_CC +# define QDFT_EXAMPLE_CC +// # include +# include +# include + +typedef qdft::data_managers<> data_managers_t; + +// Simulate a transfer per blocks of a fized size +// Transfer n from src to dst +void block_transfer(data_managers_t& dmanagers, + const qdft::dname_type& d, + const std::string& src, const std::string& dst, + unsigned int n, unsigned int block_size = 512) { + std::string tmp = boost::lexical_cast(std::rand()); + while (n > block_size) + { + dmanagers.transfer (d, block_size, src, tmp); + dmanagers.transfer (d, block_size, tmp, dst); + n -= block_size; + } + if (n > 0) + { + dmanagers.transfer (d, n, src, tmp); + dmanagers.transfer (d, n, tmp, dst); + } + dmanagers.truncate (d, tmp, 0); +} + + +int main() { + data_managers_t dmanagers; + + std::cerr << "*** Test for reverting truncate ***" << std::endl; + qdft::dname_type dt1 = dmanagers.new_data (50, qdft::last, "dt1"); + dmanagers.init (dt1, 50, "c1"); + dmanagers.truncate (dt1, "c1", 10); + dmanagers.revert_last_action (dt1); + + std::cerr << "*** Test for reverting simplification rule 1 ***" << std::endl; + qdft::dname_type ds1 = dmanagers.new_data (50, qdft::last, "ds1"); + dmanagers.init (ds1, 50, "c1"); + dmanagers.truncate (ds1, "c1", 0); + dmanagers.revert_last_action (ds1); + dmanagers.truncate (ds1, "c1", 0); + + std::cerr << "*** Test for reverting simplification rule 2 ***" << std::endl; + qdft::dname_type ds2 = dmanagers.new_data (50, qdft::last, "ds2"); + dmanagers.init (ds2, 50, "c1"); + dmanagers.transfer (ds2, 10, "c1", "c2"); + dmanagers.transfer (ds2, 5, "c2", "c3"); + dmanagers.transfer (ds2, 5, "c2", "c3"); + dmanagers.revert_last_action (ds2); + + std::cerr << "*** Test for reverting simplification rule 3 ***" << std::endl; + qdft::dname_type ds3 = dmanagers.new_data (50, qdft::last, "ds3"); + dmanagers.init (ds3, 50, "c1"); + dmanagers.transfer (ds3, 10, "c1", "c2"); + dmanagers.transfer (ds3, 20, "c2", "c3"); + dmanagers.transfer (ds3, 7, "c2", "c4"); + dmanagers.transfer (ds3, 5, "c1", "c2"); + dmanagers.transfer (ds3, 11, "c1", "c5"); + dmanagers.transfer (ds3, 8, "c5", "c2"); + dmanagers.revert_last_action (ds3); + dmanagers.transfer (ds3, 8, "c5", "c2"); + + std::cerr << "*** Test for reverting simplification rule 4 ***" << std::endl; + qdft::dname_type ds4 = dmanagers.new_data (50, qdft::last, "ds4"); + dmanagers.init (ds4, 50, "c1"); + dmanagers.transfer (ds4, 10, "c1", "c2"); + dmanagers.truncate (ds4, "c1", 10); + dmanagers.revert_last_action (ds4); + dmanagers.transfer (ds4, 10, "c1", "c2"); + + std::cerr << "*** Test for reverting simplification rule 5 ***" << std::endl; + qdft::dname_type ds5 = dmanagers.new_data (50, qdft::last, "ds5"); + dmanagers.init (ds5, 50, "c1"); + dmanagers.transfer (ds5, 10, "c1", "c2"); + dmanagers.transfer (ds5, 10, "c2", "c3"); + dmanagers.transfer (ds5, 10, "c1", "c2"); + dmanagers.revert_last_action (ds5); + dmanagers.transfer (ds5, 10, "c1", "c2"); + + std::cerr << "*** Test for reverting several simplification rules in a row ***" << std::endl; + qdft::dname_type dm1 = dmanagers.new_data (50, qdft::last, "dm1"); + dmanagers.init (dm1, 50, "c1"); + dmanagers.transfer (dm1, 10, "c1", "c2"); + dmanagers.transfer (dm1, 10, "c1", "c3"); + dmanagers.transfer (dm1, 10, "c2", "c4"); + dmanagers.transfer (dm1, 10, "c3", "c4"); + dmanagers.truncate (dm1, "c1", 9); + dmanagers.truncate (dm1, "c2", 9); + dmanagers.truncate (dm1, "c3", 9); + dmanagers.truncate (dm1, "c4", 0); + dmanagers.revert_last_action (dm1); + dmanagers.truncate (dm1, "c4", 0); + + std::cerr << "*** Test for transferring again after reverting simplification rule 2 ***" << std::endl; + qdft::dname_type dt2 = dmanagers.new_data (50, qdft::last, "dt2"); + dmanagers.init (dt2, 50, "c1"); + dmanagers.transfer (dt2, 10, "c1", "c2"); + dmanagers.transfer (dt2, 5, "c2", "c3"); + dmanagers.revert_last_action (dt2); + dmanagers.transfer (dt2, 5, "c2", "c3"); + + std::cerr << "*** Test for Enrico ***" << std::endl; + qdft::dname_type en1 = dmanagers.new_data (50, qdft::last, "en1"); + dmanagers.init (en1, 50, "c1"); + dmanagers.transfer (en1, 20, "c1", "c2"); + dmanagers.transfer (en1, 20, "c1", "c3"); + // dmanagers.revert_last_action (en1); + dmanagers.transfer (en1, 10, "c2", "c3"); + dmanagers.transfer (en1, 10, "c3", "c2"); + + std::cerr << "*** Test for DAG issue ***" << std::endl; + qdft::dname_type en2 = dmanagers.new_data (35000, qdft::last, "en2"); + dmanagers.init (en2, 5000, "s1"); + dmanagers.init (en2, 5000, "s2"); + dmanagers.init (en2, 5000, "s3"); + dmanagers.init (en2, 5000, "s4"); + dmanagers.init (en2, 5000, "s5"); + dmanagers.init (en2, 5000, "s6"); + dmanagers.init (en2, 5000, "s7"); + block_transfer (dmanagers, en2, "c8", "c3", 5145, 200); + block_transfer (dmanagers, en2, "c2", "c7", 848, 200); + block_transfer (dmanagers, en2, "s3", "c2", 2623, 200); + block_transfer (dmanagers, en2, "s3", "c6", 5487, 200); + block_transfer (dmanagers, en2, "s1", "c6", 5380, 200); + block_transfer (dmanagers, en2, "s5", "c8", 8830, 200); + block_transfer (dmanagers, en2, "c8", "c0", 5596, 200); + block_transfer (dmanagers, en2, "c4", "c0", 1569, 200); + block_transfer (dmanagers, en2, "s2", "c7", 8104, 200); + std::cerr << "Should apply rule 5" << std::endl; + block_transfer (dmanagers, en2, "s5", "c8", 6602, 200); + // dmanagers.transfer (en2, 200, "s5", "tmp"); + // dmanagers.transfer (en2, 200, "tmp", "c8"); + // dmanagers.transfer (en2, 200, "s5", "tmp"); + // dmanagers.transfer (en2, 200, "tmp", "c8"); + // dmanagers.truncate (en2, "tmp", 0); + std::cerr << "SO FAR, SO GOOD" << std::endl; + block_transfer (dmanagers, en2, "c0", "c8", 8939, 200); + // dmanagers.transfer (en2, 200, "c0", "tmp"); + // dmanagers.transfer (en2, 200, "tmp", "c8"); + block_transfer (dmanagers, en2, "c0", "c3", 2543, 200); + block_transfer (dmanagers, en2, "c5", "c7", 4869, 200); + block_transfer (dmanagers, en2, "s1", "c7", 2503, 200); + block_transfer (dmanagers, en2, "s5", "c5", 5685, 200); + block_transfer (dmanagers, en2, "c5", "c8", 8176, 200); + + dmanagers.show_graphs (); +} + +#endif // ! QDFT_EXAMPLE_CC diff --git a/src/test_lib.cc b/src/test_lib.cc new file mode 100644 index 0000000..27262ff --- /dev/null +++ b/src/test_lib.cc @@ -0,0 +1,176 @@ +// Copyright (C) 2011, 2012 Johan Oudinet +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 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. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +#ifndef QDFT_TEST_LIB_CC +# define QDFT_TEST_LIB_CC +# include +# include +# define NO_SIMPLIFY +# include +#include +#include +#include +#include +#define NS (7) +#define NC (10) + +using namespace boost::posix_time; + +typedef qdft::data_managers<> data_managers_t; + +int overwrite=0; +std::ofstream ftime; + +// Simulate a transfer per blocks of a fized size +// Transfer n from src to dst +void block_transfer(data_managers_t& dmanagers, + const qdft::dname_type& d, + const std::string& src, const std::string& dst, + unsigned int n, unsigned int block_size = 512, bool btime = false, unsigned i = 0) { + std::string tmp = boost::lexical_cast(std::rand()); + if (overwrite==1) dmanagers.truncate (d, dst, 0); + while (n > block_size) + { + ptime before (microsec_clock::local_time()); + // transfer src -> tmp + dmanagers.transfer (d, block_size, src, tmp); + ptime after (microsec_clock::local_time()); + time_duration td = after - before; + if (btime) ftime << i << ": " << td.total_microseconds () << std::endl; + before = microsec_clock::local_time(); + // transfer tmp -> dst + dmanagers.transfer (d, block_size, tmp, dst); + after = microsec_clock::local_time(); + td = after - before; + if (btime) ftime << i << ": " << td.total_microseconds () << std::endl; + n -= block_size; + } + if (n > 0) + { + ptime before (microsec_clock::local_time()); + // transfer src -> tmp + dmanagers.transfer (d, n, src, tmp); + ptime after (microsec_clock::local_time()); + time_duration td = after - before; + if (btime) ftime << i << ": " << td.total_microseconds () << std::endl; + before = microsec_clock::local_time(); + // transfer tmp -> dst + dmanagers.transfer (d, n, tmp, dst); + after = microsec_clock::local_time(); + td = after - before; + if (btime) ftime << i << ": " << td.total_microseconds () << std::endl; + } + ptime before (microsec_clock::local_time()); + // truncate tmp + dmanagers.truncate (d, tmp, 0); + ptime after (microsec_clock::local_time()); + time_duration td = after - before; + if (btime) ftime << i << ": " << td.total_microseconds () << std::endl; +} + +int main(int argc, char* argv[]) { + + if ((argc < 5)||(argc > 10)) + { +#ifndef NO_SIMPLIFY + std::cerr << "Simplification rules: activated\n"; +#else + std::cerr << "Simplification rules: deactivated\n"; +#endif + + std::cerr << "Usage: " << argv[0] << " n block_size p_src p_new [seed] [sensitive_size] [public_size] [overwrite]\n" + << "\t n \t" << "number of transfers\n" + << "\t block_size \t" << "size of atomic transfers\n" + << "\t p_src \t" << "percentage of transfer sources that are initial containers\n" + << "\t p_new \t" << "percentage of transfer destinations that are new reports\n" + << "\t seed \t" << "seed for randomize\n" + << "\t sensitive_size \t" << "size of sensitive source (default:500)\n" + << "\t public_size \t" << "maximal initial containers size, public content (default:100)\n" + << "\t overwrite \t" << "overwrite report upon update 0=NO, 1=YES (default:0)\n" + << "\t time \t" << "save time measurement to this file (default: no time measurement)\n" + << std::endl; + exit (1); + } + + unsigned sensitive_size=500; + unsigned public_size=100; + if (argc>6) sensitive_size = boost::lexical_cast(argv[6]); + if (argc>7) public_size = boost::lexical_cast(argv[7]); + if (argc>8) overwrite = boost::lexical_cast(argv[8]); + if (argc>9) ftime.open (argv[9]); + + data_managers_t dmanagers; + qdft::dname_type d = dmanagers.new_data (NS * sensitive_size, qdft::unknown, "phones"); + + typedef std::vector strings_t; + strings_t sources (NS); + strings_t containers (NC); + + int i=0; + for (strings_t::iterator it = sources.begin(); it != sources.end(); ++it) + { + *it = std::string("s") + boost::lexical_cast(i++); + dmanagers.init (d, sensitive_size, *it); + } + + i=0; + for (strings_t::iterator it = containers.begin(); it != containers.end(); ++it) + { + *it = std::string("c") + boost::lexical_cast(i++); + } + + if (argc>=6) + std::srand(boost::lexical_cast(boost::lexical_cast(argv[5]))); + else + std::srand(boost::lexical_cast(std::time(NULL))); + unsigned n = boost::lexical_cast(argv[1]); + unsigned block_size = boost::lexical_cast(argv[2]); + unsigned p_src = boost::lexical_cast(argv[3]); + unsigned p_new = boost::lexical_cast(argv[4]); + + for (unsigned i = 0; i < n; ++i) + { + std::string c1; + if (std::rand() % 100 < p_src) + c1 = sources[std::rand() % NS]; + else + c1 = containers[std::rand() % containers.size ()]; + std::string c2; + if (std::rand() % 100 < p_new) + { + c2 = std::string("c") + boost::lexical_cast(containers.size ()); + containers.push_back (c2); + } + else + { + do { + c2 = containers[std::rand() % containers.size ()]; + } while (c2 == c1); + } + unsigned r = (std::rand() % public_size) + 1; + std::cerr << i << ": transferring " << r << " from " << c1 << " to " << c2 << std::endl; + // block_transfer (dmanagers, d, c1, c2, r, block_size, (argc > 9), i); + ptime before (microsec_clock::local_time()); + dmanagers.transfer (d, r, c1, c2); + ptime after (microsec_clock::local_time()); + time_duration td = after - before; + if (argc>9) ftime << i << ": " << td.total_microseconds () << std::endl; + } + if (argc>9) ftime.close (); + dmanagers.show_graphs (); +} + +#endif // ! QDFT_TEST_LIB_CC