star-schiff

Library for estimating radiative properties
git clone git://git.meso-star.com/star-schiff.git
Log | Files | Refs | README | LICENSE

commit 99ef5ec9c665b0e259deb46f727e38722fb82186
parent 11ad465f0df73b0ec623558656ea9b9b2741a61c
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 30 Mar 2016 14:31:11 +0200

Merge remote-tracking branch 'gitlab/phase_function'

Diffstat:
ACOPYING | 674+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DCOPYING.en | 519-------------------------------------------------------------------------------
DCOPYING.fr | 550-------------------------------------------------------------------------------
MREADME.md | 23+++++++++++++----------
Mcmake/CMakeLists.txt | 51++++++++++++++++++++++-----------------------------
Msrc/sschiff.h | 194+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Msrc/sschiff_device.c | 49+++++++++++++++++++++++++------------------------
Msrc/sschiff_device.h | 46++++++++++++++++++++++------------------------
Msrc/sschiff_estimator.c | 1811+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
Asrc/sschiff_scattering_angles_distributions.c | 35+++++++++++++++++++++++++++++++++++
Msrc/test_sschiff_device.c | 35+++++++++++------------------------
Msrc/test_sschiff_estimator_cylinder.c | 237+++++++++++++++----------------------------------------------------------------
Asrc/test_sschiff_estimator_rhodo.c | 2847+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/test_sschiff_estimator_sphere.c | 413++++++++++++++++++++++++++++---------------------------------------------------
Msrc/test_sschiff_utils.h | 349+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
15 files changed, 5714 insertions(+), 2119 deletions(-)

diff --git a/COPYING b/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + 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. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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 <http://www.gnu.org/licenses/>. + +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: + + <program> Copyright (C) <year> <name of author> + 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 +<http://www.gnu.org/licenses/>. + + 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 +<http://www.gnu.org/philosophy/why-not-lgpl.html>. diff --git a/COPYING.en b/COPYING.en @@ -1,519 +0,0 @@ - - CeCILL FREE SOFTWARE LICENSE AGREEMENT - -Version 2.1 dated 2013-06-21 - - - Notice - -This Agreement is a Free Software license agreement that is the result -of discussions between its authors in order to ensure compliance with -the two main principles guiding its drafting: - - * firstly, compliance with the principles governing the distribution - of Free Software: access to source code, broad rights granted to users, - * secondly, the election of a governing law, French law, with which it - is conformant, both as regards the law of torts and intellectual - property law, and the protection that it offers to both authors and - holders of the economic rights over software. - -The authors of the CeCILL (for Ce[a] C[nrs] I[nria] L[ogiciel] L[ibre]) -license are: - -Commissariat à l'énergie atomique et aux énergies alternatives - CEA, a -public scientific, technical and industrial research establishment, -having its principal place of business at 25 rue Leblanc, immeuble Le -Ponant D, 75015 Paris, France. - -Centre National de la Recherche Scientifique - CNRS, a public scientific -and technological establishment, having its principal place of business -at 3 rue Michel-Ange, 75794 Paris cedex 16, France. - -Institut National de Recherche en Informatique et en Automatique - -Inria, a public scientific and technological establishment, having its -principal place of business at Domaine de Voluceau, Rocquencourt, BP -105, 78153 Le Chesnay cedex, France. - - - Preamble - -The purpose of this Free Software license agreement is to grant users -the right to modify and redistribute the software governed by this -license within the framework of an open source distribution model. - -The exercising of this right is conditional upon certain obligations for -users so as to preserve this status for all subsequent redistributions. - -In consideration of access to the source code and the rights to copy, -modify and redistribute granted by the license, users are provided only -with a limited warranty and the software's author, the holder of the -economic rights, and the successive licensors only have limited liability. - -In this respect, the risks associated with loading, using, modifying -and/or developing or reproducing the software by the user are brought to -the user's attention, given its Free Software status, which may make it -complicated to use, with the result that its use is reserved for -developers and experienced professionals having in-depth computer -knowledge. Users are therefore encouraged to load and test the -suitability of the software as regards their requirements in conditions -enabling the security of their systems and/or data to be ensured and, -more generally, to use and operate it in the same conditions of -security. This Agreement may be freely reproduced and published, -provided it is not altered, and that no provisions are either added or -removed herefrom. - -This Agreement may apply to any or all software for which the holder of -the economic rights decides to submit the use thereof to its provisions. - -Frequently asked questions can be found on the official website of the -CeCILL licenses family (http://www.cecill.info/index.en.html) for any -necessary clarification. - - - Article 1 - DEFINITIONS - -For the purpose of this Agreement, when the following expressions -commence with a capital letter, they shall have the following meaning: - -Agreement: means this license agreement, and its possible subsequent -versions and annexes. - -Software: means the software in its Object Code and/or Source Code form -and, where applicable, its documentation, "as is" when the Licensee -accepts the Agreement. - -Initial Software: means the Software in its Source Code and possibly its -Object Code form and, where applicable, its documentation, "as is" when -it is first distributed under the terms and conditions of the Agreement. - -Modified Software: means the Software modified by at least one -Contribution. - -Source Code: means all the Software's instructions and program lines to -which access is required so as to modify the Software. - -Object Code: means the binary files originating from the compilation of -the Source Code. - -Holder: means the holder(s) of the economic rights over the Initial -Software. - -Licensee: means the Software user(s) having accepted the Agreement. - -Contributor: means a Licensee having made at least one Contribution. - -Licensor: means the Holder, or any other individual or legal entity, who -distributes the Software under the Agreement. - -Contribution: means any or all modifications, corrections, translations, -adaptations and/or new functions integrated into the Software by any or -all Contributors, as well as any or all Internal Modules. - -Module: means a set of sources files including their documentation that -enables supplementary functions or services in addition to those offered -by the Software. - -External Module: means any or all Modules, not derived from the -Software, so that this Module and the Software run in separate address -spaces, with one calling the other when they are run. - -Internal Module: means any or all Module, connected to the Software so -that they both execute in the same address space. - -GNU GPL: means the GNU General Public License version 2 or any -subsequent version, as published by the Free Software Foundation Inc. - -GNU Affero GPL: means the GNU Affero General Public License version 3 or -any subsequent version, as published by the Free Software Foundation Inc. - -EUPL: means the European Union Public License version 1.1 or any -subsequent version, as published by the European Commission. - -Parties: mean both the Licensee and the Licensor. - -These expressions may be used both in singular and plural form. - - - Article 2 - PURPOSE - -The purpose of the Agreement is the grant by the Licensor to the -Licensee of a non-exclusive, transferable and worldwide license for the -Software as set forth in Article 5 <#scope> hereinafter for the whole -term of the protection granted by the rights over said Software. - - - Article 3 - ACCEPTANCE - -3.1 The Licensee shall be deemed as having accepted the terms and -conditions of this Agreement upon the occurrence of the first of the -following events: - - * (i) loading the Software by any or all means, notably, by - downloading from a remote server, or by loading from a physical medium; - * (ii) the first time the Licensee exercises any of the rights granted - hereunder. - -3.2 One copy of the Agreement, containing a notice relating to the -characteristics of the Software, to the limited warranty, and to the -fact that its use is restricted to experienced users has been provided -to the Licensee prior to its acceptance as set forth in Article 3.1 -<#accepting> hereinabove, and the Licensee hereby acknowledges that it -has read and understood it. - - - Article 4 - EFFECTIVE DATE AND TERM - - - 4.1 EFFECTIVE DATE - -The Agreement shall become effective on the date when it is accepted by -the Licensee as set forth in Article 3.1 <#accepting>. - - - 4.2 TERM - -The Agreement shall remain in force for the entire legal term of -protection of the economic rights over the Software. - - - Article 5 - SCOPE OF RIGHTS GRANTED - -The Licensor hereby grants to the Licensee, who accepts, the following -rights over the Software for any or all use, and for the term of the -Agreement, on the basis of the terms and conditions set forth hereinafter. - -Besides, if the Licensor owns or comes to own one or more patents -protecting all or part of the functions of the Software or of its -components, the Licensor undertakes not to enforce the rights granted by -these patents against successive Licensees using, exploiting or -modifying the Software. If these patents are transferred, the Licensor -undertakes to have the transferees subscribe to the obligations set -forth in this paragraph. - - - 5.1 RIGHT OF USE - -The Licensee is authorized to use the Software, without any limitation -as to its fields of application, with it being hereinafter specified -that this comprises: - - 1. permanent or temporary reproduction of all or part of the Software - by any or all means and in any or all form. - - 2. loading, displaying, running, or storing the Software on any or all - medium. - - 3. entitlement to observe, study or test its operation so as to - determine the ideas and principles behind any or all constituent - elements of said Software. This shall apply when the Licensee - carries out any or all loading, displaying, running, transmission or - storage operation as regards the Software, that it is entitled to - carry out hereunder. - - - 5.2 ENTITLEMENT TO MAKE CONTRIBUTIONS - -The right to make Contributions includes the right to translate, adapt, -arrange, or make any or all modifications to the Software, and the right -to reproduce the resulting software. - -The Licensee is authorized to make any or all Contributions to the -Software provided that it includes an explicit notice that it is the -author of said Contribution and indicates the date of the creation thereof. - - - 5.3 RIGHT OF DISTRIBUTION - -In particular, the right of distribution includes the right to publish, -transmit and communicate the Software to the general public on any or -all medium, and by any or all means, and the right to market, either in -consideration of a fee, or free of charge, one or more copies of the -Software by any means. - -The Licensee is further authorized to distribute copies of the modified -or unmodified Software to third parties according to the terms and -conditions set forth hereinafter. - - - 5.3.1 DISTRIBUTION OF SOFTWARE WITHOUT MODIFICATION - -The Licensee is authorized to distribute true copies of the Software in -Source Code or Object Code form, provided that said distribution -complies with all the provisions of the Agreement and is accompanied by: - - 1. a copy of the Agreement, - - 2. a notice relating to the limitation of both the Licensor's warranty - and liability as set forth in Articles 8 and 9, - -and that, in the event that only the Object Code of the Software is -redistributed, the Licensee allows effective access to the full Source -Code of the Software for a period of at least three years from the -distribution of the Software, it being understood that the additional -acquisition cost of the Source Code shall not exceed the cost of the -data transfer. - - - 5.3.2 DISTRIBUTION OF MODIFIED SOFTWARE - -When the Licensee makes a Contribution to the Software, the terms and -conditions for the distribution of the resulting Modified Software -become subject to all the provisions of this Agreement. - -The Licensee is authorized to distribute the Modified Software, in -source code or object code form, provided that said distribution -complies with all the provisions of the Agreement and is accompanied by: - - 1. a copy of the Agreement, - - 2. a notice relating to the limitation of both the Licensor's warranty - and liability as set forth in Articles 8 and 9, - -and, in the event that only the object code of the Modified Software is -redistributed, - - 3. a note stating the conditions of effective access to the full source - code of the Modified Software for a period of at least three years - from the distribution of the Modified Software, it being understood - that the additional acquisition cost of the source code shall not - exceed the cost of the data transfer. - - - 5.3.3 DISTRIBUTION OF EXTERNAL MODULES - -When the Licensee has developed an External Module, the terms and -conditions of this Agreement do not apply to said External Module, that -may be distributed under a separate license agreement. - - - 5.3.4 COMPATIBILITY WITH OTHER LICENSES - -The Licensee can include a code that is subject to the provisions of one -of the versions of the GNU GPL, GNU Affero GPL and/or EUPL in the -Modified or unmodified Software, and distribute that entire code under -the terms of the same version of the GNU GPL, GNU Affero GPL and/or EUPL. - -The Licensee can include the Modified or unmodified Software in a code -that is subject to the provisions of one of the versions of the GNU GPL, -GNU Affero GPL and/or EUPL and distribute that entire code under the -terms of the same version of the GNU GPL, GNU Affero GPL and/or EUPL. - - - Article 6 - INTELLECTUAL PROPERTY - - - 6.1 OVER THE INITIAL SOFTWARE - -The Holder owns the economic rights over the Initial Software. Any or -all use of the Initial Software is subject to compliance with the terms -and conditions under which the Holder has elected to distribute its work -and no one shall be entitled to modify the terms and conditions for the -distribution of said Initial Software. - -The Holder undertakes that the Initial Software will remain ruled at -least by this Agreement, for the duration set forth in Article 4.2 <#term>. - - - 6.2 OVER THE CONTRIBUTIONS - -The Licensee who develops a Contribution is the owner of the -intellectual property rights over this Contribution as defined by -applicable law. - - - 6.3 OVER THE EXTERNAL MODULES - -The Licensee who develops an External Module is the owner of the -intellectual property rights over this External Module as defined by -applicable law and is free to choose the type of agreement that shall -govern its distribution. - - - 6.4 JOINT PROVISIONS - -The Licensee expressly undertakes: - - 1. not to remove, or modify, in any manner, the intellectual property - notices attached to the Software; - - 2. to reproduce said notices, in an identical manner, in the copies of - the Software modified or not. - -The Licensee undertakes not to directly or indirectly infringe the -intellectual property rights on the Software of the Holder and/or -Contributors, and to take, where applicable, vis-à-vis its staff, any -and all measures required to ensure respect of said intellectual -property rights of the Holder and/or Contributors. - - - Article 7 - RELATED SERVICES - -7.1 Under no circumstances shall the Agreement oblige the Licensor to -provide technical assistance or maintenance services for the Software. - -However, the Licensor is entitled to offer this type of services. The -terms and conditions of such technical assistance, and/or such -maintenance, shall be set forth in a separate instrument. Only the -Licensor offering said maintenance and/or technical assistance services -shall incur liability therefor. - -7.2 Similarly, any Licensor is entitled to offer to its licensees, under -its sole responsibility, a warranty, that shall only be binding upon -itself, for the redistribution of the Software and/or the Modified -Software, under terms and conditions that it is free to decide. Said -warranty, and the financial terms and conditions of its application, -shall be subject of a separate instrument executed between the Licensor -and the Licensee. - - - Article 8 - LIABILITY - -8.1 Subject to the provisions of Article 8.2, the Licensee shall be -entitled to claim compensation for any direct loss it may have suffered -from the Software as a result of a fault on the part of the relevant -Licensor, subject to providing evidence thereof. - -8.2 The Licensor's liability is limited to the commitments made under -this Agreement and shall not be incurred as a result of in particular: -(i) loss due the Licensee's total or partial failure to fulfill its -obligations, (ii) direct or consequential loss that is suffered by the -Licensee due to the use or performance of the Software, and (iii) more -generally, any consequential loss. In particular the Parties expressly -agree that any or all pecuniary or business loss (i.e. loss of data, -loss of profits, operating loss, loss of customers or orders, -opportunity cost, any disturbance to business activities) or any or all -legal proceedings instituted against the Licensee by a third party, -shall constitute consequential loss and shall not provide entitlement to -any or all compensation from the Licensor. - - - Article 9 - WARRANTY - -9.1 The Licensee acknowledges that the scientific and technical -state-of-the-art when the Software was distributed did not enable all -possible uses to be tested and verified, nor for the presence of -possible defects to be detected. In this respect, the Licensee's -attention has been drawn to the risks associated with loading, using, -modifying and/or developing and reproducing the Software which are -reserved for experienced users. - -The Licensee shall be responsible for verifying, by any or all means, -the suitability of the product for its requirements, its good working -order, and for ensuring that it shall not cause damage to either persons -or properties. - -9.2 The Licensor hereby represents, in good faith, that it is entitled -to grant all the rights over the Software (including in particular the -rights set forth in Article 5 <#scope>). - -9.3 The Licensee acknowledges that the Software is supplied "as is" by -the Licensor without any other express or tacit warranty, other than -that provided for in Article 9.2 <#good-faith> and, in particular, -without any warranty as to its commercial value, its secured, safe, -innovative or relevant nature. - -Specifically, the Licensor does not warrant that the Software is free -from any error, that it will operate without interruption, that it will -be compatible with the Licensee's own equipment and software -configuration, nor that it will meet the Licensee's requirements. - -9.4 The Licensor does not either expressly or tacitly warrant that the -Software does not infringe any third party intellectual property right -relating to a patent, software or any other property right. Therefore, -the Licensor disclaims any and all liability towards the Licensee -arising out of any or all proceedings for infringement that may be -instituted in respect of the use, modification and redistribution of the -Software. Nevertheless, should such proceedings be instituted against -the Licensee, the Licensor shall provide it with technical and legal -expertise for its defense. Such technical and legal expertise shall be -decided on a case-by-case basis between the relevant Licensor and the -Licensee pursuant to a memorandum of understanding. The Licensor -disclaims any and all liability as regards the Licensee's use of the -name of the Software. No warranty is given as regards the existence of -prior rights over the name of the Software or as regards the existence -of a trademark. - - - Article 10 - TERMINATION - -10.1 In the event of a breach by the Licensee of its obligations -hereunder, the Licensor may automatically terminate this Agreement -thirty (30) days after notice has been sent to the Licensee and has -remained ineffective. - -10.2 A Licensee whose Agreement is terminated shall no longer be -authorized to use, modify or distribute the Software. However, any -licenses that it may have granted prior to termination of the Agreement -shall remain valid subject to their having been granted in compliance -with the terms and conditions hereof. - - - Article 11 - MISCELLANEOUS - - - 11.1 EXCUSABLE EVENTS - -Neither Party shall be liable for any or all delay, or failure to -perform the Agreement, that may be attributable to an event of force -majeure, an act of God or an outside cause, such as defective -functioning or interruptions of the electricity or telecommunications -networks, network paralysis following a virus attack, intervention by -government authorities, natural disasters, water damage, earthquakes, -fire, explosions, strikes and labor unrest, war, etc. - -11.2 Any failure by either Party, on one or more occasions, to invoke -one or more of the provisions hereof, shall under no circumstances be -interpreted as being a waiver by the interested Party of its right to -invoke said provision(s) subsequently. - -11.3 The Agreement cancels and replaces any or all previous agreements, -whether written or oral, between the Parties and having the same -purpose, and constitutes the entirety of the agreement between said -Parties concerning said purpose. No supplement or modification to the -terms and conditions hereof shall be effective as between the Parties -unless it is made in writing and signed by their duly authorized -representatives. - -11.4 In the event that one or more of the provisions hereof were to -conflict with a current or future applicable act or legislative text, -said act or legislative text shall prevail, and the Parties shall make -the necessary amendments so as to comply with said act or legislative -text. All other provisions shall remain effective. Similarly, invalidity -of a provision of the Agreement, for any reason whatsoever, shall not -cause the Agreement as a whole to be invalid. - - - 11.5 LANGUAGE - -The Agreement is drafted in both French and English and both versions -are deemed authentic. - - - Article 12 - NEW VERSIONS OF THE AGREEMENT - -12.1 Any person is authorized to duplicate and distribute copies of this -Agreement. - -12.2 So as to ensure coherence, the wording of this Agreement is -protected and may only be modified by the authors of the License, who -reserve the right to periodically publish updates or new versions of the -Agreement, each with a separate number. These subsequent versions may -address new issues encountered by Free Software. - -12.3 Any Software distributed under a given version of the Agreement may -only be subsequently distributed under the same version of the Agreement -or a subsequent version, subject to the provisions of Article 5.3.4 -<#compatibility>. - - - Article 13 - GOVERNING LAW AND JURISDICTION - -13.1 The Agreement is governed by French law. The Parties agree to -endeavor to seek an amicable solution to any disagreements or disputes -that may arise during the performance of the Agreement. - -13.2 Failing an amicable solution within two (2) months as from their -occurrence, and unless emergency proceedings are necessary, the -disagreements or disputes shall be referred to the Paris Courts having -jurisdiction, by the more diligent Party. - diff --git a/COPYING.fr b/COPYING.fr @@ -1,550 +0,0 @@ - - CONTRAT DE LICENCE DE LOGICIEL LIBRE CeCILL - -Version 2.1 du 2013-06-21 - - - Avertissement - -Ce contrat est une licence de logiciel libre issue d'une concertation -entre ses auteurs afin que le respect de deux grands principes préside à -sa rédaction: - - * d'une part, le respect des principes de diffusion des logiciels - libres: accès au code source, droits étendus conférés aux utilisateurs, - * d'autre part, la désignation d'un droit applicable, le droit - français, auquel elle est conforme, tant au regard du droit de la - responsabilité civile que du droit de la propriété intellectuelle et - de la protection qu'il offre aux auteurs et titulaires des droits - patrimoniaux sur un logiciel. - -Les auteurs de la licence CeCILL (Ce[a] C[nrs] I[nria] L[ogiciel] L[ibre]) -sont: - -Commissariat à l'énergie atomique et aux énergies alternatives - CEA, -établissement public de recherche à caractère scientifique, technique et -industriel, dont le siège est situé 25 rue Leblanc, immeuble Le Ponant -D, 75015 Paris. - -Centre National de la Recherche Scientifique - CNRS, établissement -public à caractère scientifique et technologique, dont le siège est -situé 3 rue Michel-Ange, 75794 Paris cedex 16. - -Institut National de Recherche en Informatique et en Automatique - -Inria, établissement public à caractère scientifique et technologique, -dont le siège est situé Domaine de Voluceau, Rocquencourt, BP 105, 78153 -Le Chesnay cedex. - - - Préambule - -Ce contrat est une licence de logiciel libre dont l'objectif est de -conférer aux utilisateurs la liberté de modification et de -redistribution du logiciel régi par cette licence dans le cadre d'un -modèle de diffusion en logiciel libre. - -L'exercice de ces libertés est assorti de certains devoirs à la charge -des utilisateurs afin de préserver ce statut au cours des -redistributions ultérieures. - -L'accessibilité au code source et les droits de copie, de modification -et de redistribution qui en découlent ont pour contrepartie de n'offrir -aux utilisateurs qu'une garantie limitée et de ne faire peser sur -l'auteur du logiciel, le titulaire des droits patrimoniaux et les -concédants successifs qu'une responsabilité restreinte. - -A cet égard l'attention de l'utilisateur est attirée sur les risques -associés au chargement, à l'utilisation, à la modification et/ou au -développement et à la reproduction du logiciel par l'utilisateur étant -donné sa spécificité de logiciel libre, qui peut le rendre complexe à -manipuler et qui le réserve donc à des développeurs ou des -professionnels avertis possédant des connaissances informatiques -approfondies. Les utilisateurs sont donc invités à charger et tester -l'adéquation du logiciel à leurs besoins dans des conditions permettant -d'assurer la sécurité de leurs systèmes et/ou de leurs données et, plus -généralement, à l'utiliser et l'exploiter dans les mêmes conditions de -sécurité. Ce contrat peut être reproduit et diffusé librement, sous -réserve de le conserver en l'état, sans ajout ni suppression de clauses. - -Ce contrat est susceptible de s'appliquer à tout logiciel dont le -titulaire des droits patrimoniaux décide de soumettre l'exploitation aux -dispositions qu'il contient. - -Une liste de questions fréquemment posées se trouve sur le site web -officiel de la famille des licences CeCILL -(http://www.cecill.info/index.fr.html) pour toute clarification qui -serait nécessaire. - - - Article 1 - DEFINITIONS - -Dans ce contrat, les termes suivants, lorsqu'ils seront écrits avec une -lettre capitale, auront la signification suivante: - -Contrat: désigne le présent contrat de licence, ses éventuelles versions -postérieures et annexes. - -Logiciel: désigne le logiciel sous sa forme de Code Objet et/ou de Code -Source et le cas échéant sa documentation, dans leur état au moment de -l'acceptation du Contrat par le Licencié. - -Logiciel Initial: désigne le Logiciel sous sa forme de Code Source et -éventuellement de Code Objet et le cas échéant sa documentation, dans -leur état au moment de leur première diffusion sous les termes du Contrat. - -Logiciel Modifié: désigne le Logiciel modifié par au moins une -Contribution. - -Code Source: désigne l'ensemble des instructions et des lignes de -programme du Logiciel et auquel l'accès est nécessaire en vue de -modifier le Logiciel. - -Code Objet: désigne les fichiers binaires issus de la compilation du -Code Source. - -Titulaire: désigne le ou les détenteurs des droits patrimoniaux d'auteur -sur le Logiciel Initial. - -Licencié: désigne le ou les utilisateurs du Logiciel ayant accepté le -Contrat. - -Contributeur: désigne le Licencié auteur d'au moins une Contribution. - -Concédant: désigne le Titulaire ou toute personne physique ou morale -distribuant le Logiciel sous le Contrat. - -Contribution: désigne l'ensemble des modifications, corrections, -traductions, adaptations et/ou nouvelles fonctionnalités intégrées dans -le Logiciel par tout Contributeur, ainsi que tout Module Interne. - -Module: désigne un ensemble de fichiers sources y compris leur -documentation qui permet de réaliser des fonctionnalités ou services -supplémentaires à ceux fournis par le Logiciel. - -Module Externe: désigne tout Module, non dérivé du Logiciel, tel que ce -Module et le Logiciel s'exécutent dans des espaces d'adressage -différents, l'un appelant l'autre au moment de leur exécution. - -Module Interne: désigne tout Module lié au Logiciel de telle sorte -qu'ils s'exécutent dans le même espace d'adressage. - -GNU GPL: désigne la GNU General Public License dans sa version 2 ou -toute version ultérieure, telle que publiée par Free Software Foundation -Inc. - -GNU Affero GPL: désigne la GNU Affero General Public License dans sa -version 3 ou toute version ultérieure, telle que publiée par Free -Software Foundation Inc. - -EUPL: désigne la Licence Publique de l'Union européenne dans sa version -1.1 ou toute version ultérieure, telle que publiée par la Commission -Européenne. - -Parties: désigne collectivement le Licencié et le Concédant. - -Ces termes s'entendent au singulier comme au pluriel. - - - Article 2 - OBJET - -Le Contrat a pour objet la concession par le Concédant au Licencié d'une -licence non exclusive, cessible et mondiale du Logiciel telle que -définie ci-après à l'article 5 <#etendue> pour toute la durée de -protection des droits portant sur ce Logiciel. - - - Article 3 - ACCEPTATION - -3.1 L'acceptation par le Licencié des termes du Contrat est réputée -acquise du fait du premier des faits suivants: - - * (i) le chargement du Logiciel par tout moyen notamment par - téléchargement à partir d'un serveur distant ou par chargement à - partir d'un support physique; - * (ii) le premier exercice par le Licencié de l'un quelconque des - droits concédés par le Contrat. - -3.2 Un exemplaire du Contrat, contenant notamment un avertissement -relatif aux spécificités du Logiciel, à la restriction de garantie et à -la limitation à un usage par des utilisateurs expérimentés a été mis à -disposition du Licencié préalablement à son acceptation telle que -définie à l'article 3.1 <#acceptation-acquise> ci dessus et le Licencié -reconnaît en avoir pris connaissance. - - - Article 4 - ENTREE EN VIGUEUR ET DUREE - - - 4.1 ENTREE EN VIGUEUR - -Le Contrat entre en vigueur à la date de son acceptation par le Licencié -telle que définie en 3.1 <#acceptation-acquise>. - - - 4.2 DUREE - -Le Contrat produira ses effets pendant toute la durée légale de -protection des droits patrimoniaux portant sur le Logiciel. - - - Article 5 - ETENDUE DES DROITS CONCEDES - -Le Concédant concède au Licencié, qui accepte, les droits suivants sur -le Logiciel pour toutes destinations et pour la durée du Contrat dans -les conditions ci-après détaillées. - -Par ailleurs, si le Concédant détient ou venait à détenir un ou -plusieurs brevets d'invention protégeant tout ou partie des -fonctionnalités du Logiciel ou de ses composants, il s'engage à ne pas -opposer les éventuels droits conférés par ces brevets aux Licenciés -successifs qui utiliseraient, exploiteraient ou modifieraient le -Logiciel. En cas de cession de ces brevets, le Concédant s'engage à -faire reprendre les obligations du présent alinéa aux cessionnaires. - - - 5.1 DROIT D'UTILISATION - -Le Licencié est autorisé à utiliser le Logiciel, sans restriction quant -aux domaines d'application, étant ci-après précisé que cela comporte: - - 1. - - la reproduction permanente ou provisoire du Logiciel en tout ou - partie par tout moyen et sous toute forme. - - 2. - - le chargement, l'affichage, l'exécution, ou le stockage du Logiciel - sur tout support. - - 3. - - la possibilité d'en observer, d'en étudier, ou d'en tester le - fonctionnement afin de déterminer les idées et principes qui sont à - la base de n'importe quel élément de ce Logiciel; et ceci, lorsque - le Licencié effectue toute opération de chargement, d'affichage, - d'exécution, de transmission ou de stockage du Logiciel qu'il est en - droit d'effectuer en vertu du Contrat. - - - 5.2 DROIT D'APPORTER DES CONTRIBUTIONS - -Le droit d'apporter des Contributions comporte le droit de traduire, -d'adapter, d'arranger ou d'apporter toute autre modification au Logiciel -et le droit de reproduire le logiciel en résultant. - -Le Licencié est autorisé à apporter toute Contribution au Logiciel sous -réserve de mentionner, de façon explicite, son nom en tant qu'auteur de -cette Contribution et la date de création de celle-ci. - - - 5.3 DROIT DE DISTRIBUTION - -Le droit de distribution comporte notamment le droit de diffuser, de -transmettre et de communiquer le Logiciel au public sur tout support et -par tout moyen ainsi que le droit de mettre sur le marché à titre -onéreux ou gratuit, un ou des exemplaires du Logiciel par tout procédé. - -Le Licencié est autorisé à distribuer des copies du Logiciel, modifié ou -non, à des tiers dans les conditions ci-après détaillées. - - - 5.3.1 DISTRIBUTION DU LOGICIEL SANS MODIFICATION - -Le Licencié est autorisé à distribuer des copies conformes du Logiciel, -sous forme de Code Source ou de Code Objet, à condition que cette -distribution respecte les dispositions du Contrat dans leur totalité et -soit accompagnée: - - 1. - - d'un exemplaire du Contrat, - - 2. - - d'un avertissement relatif à la restriction de garantie et de - responsabilité du Concédant telle que prévue aux articles 8 - <#responsabilite> et 9 <#garantie>, - -et que, dans le cas où seul le Code Objet du Logiciel est redistribué, -le Licencié permette un accès effectif au Code Source complet du -Logiciel pour une durée d'au moins 3 ans à compter de la distribution du -logiciel, étant entendu que le coût additionnel d'acquisition du Code -Source ne devra pas excéder le simple coût de transfert des données. - - - 5.3.2 DISTRIBUTION DU LOGICIEL MODIFIE - -Lorsque le Licencié apporte une Contribution au Logiciel, les conditions -de distribution du Logiciel Modifié en résultant sont alors soumises à -l'intégralité des dispositions du Contrat. - -Le Licencié est autorisé à distribuer le Logiciel Modifié, sous forme de -code source ou de code objet, à condition que cette distribution -respecte les dispositions du Contrat dans leur totalité et soit -accompagnée: - - 1. - - d'un exemplaire du Contrat, - - 2. - - d'un avertissement relatif à la restriction de garantie et de - responsabilité du Concédant telle que prévue aux articles 8 - <#responsabilite> et 9 <#garantie>, - -et, dans le cas où seul le code objet du Logiciel Modifié est redistribué, - - 3. - - d'une note précisant les conditions d'accès effectif au code source - complet du Logiciel Modifié, pendant une période d'au moins 3 ans à - compter de la distribution du Logiciel Modifié, étant entendu que le - coût additionnel d'acquisition du code source ne devra pas excéder - le simple coût de transfert des données. - - - 5.3.3 DISTRIBUTION DES MODULES EXTERNES - -Lorsque le Licencié a développé un Module Externe les conditions du -Contrat ne s'appliquent pas à ce Module Externe, qui peut être distribué -sous un contrat de licence différent. - - - 5.3.4 COMPATIBILITE AVEC D'AUTRES LICENCES - -Le Licencié peut inclure un code soumis aux dispositions d'une des -versions de la licence GNU GPL, GNU Affero GPL et/ou EUPL dans le -Logiciel modifié ou non et distribuer l'ensemble sous les conditions de -la même version de la licence GNU GPL, GNU Affero GPL et/ou EUPL. - -Le Licencié peut inclure le Logiciel modifié ou non dans un code soumis -aux dispositions d'une des versions de la licence GNU GPL, GNU Affero -GPL et/ou EUPL et distribuer l'ensemble sous les conditions de la même -version de la licence GNU GPL, GNU Affero GPL et/ou EUPL. - - - Article 6 - PROPRIETE INTELLECTUELLE - - - 6.1 SUR LE LOGICIEL INITIAL - -Le Titulaire est détenteur des droits patrimoniaux sur le Logiciel -Initial. Toute utilisation du Logiciel Initial est soumise au respect -des conditions dans lesquelles le Titulaire a choisi de diffuser son -oeuvre et nul autre n'a la faculté de modifier les conditions de -diffusion de ce Logiciel Initial. - -Le Titulaire s'engage à ce que le Logiciel Initial reste au moins régi -par le Contrat et ce, pour la durée visée à l'article 4.2 <#duree>. - - - 6.2 SUR LES CONTRIBUTIONS - -Le Licencié qui a développé une Contribution est titulaire sur celle-ci -des droits de propriété intellectuelle dans les conditions définies par -la législation applicable. - - - 6.3 SUR LES MODULES EXTERNES - -Le Licencié qui a développé un Module Externe est titulaire sur celui-ci -des droits de propriété intellectuelle dans les conditions définies par -la législation applicable et reste libre du choix du contrat régissant -sa diffusion. - - - 6.4 DISPOSITIONS COMMUNES - -Le Licencié s'engage expressément: - - 1. - - à ne pas supprimer ou modifier de quelque manière que ce soit les - mentions de propriété intellectuelle apposées sur le Logiciel; - - 2. - - à reproduire à l'identique lesdites mentions de propriété - intellectuelle sur les copies du Logiciel modifié ou non. - -Le Licencié s'engage à ne pas porter atteinte, directement ou -indirectement, aux droits de propriété intellectuelle du Titulaire et/ou -des Contributeurs sur le Logiciel et à prendre, le cas échéant, à -l'égard de son personnel toutes les mesures nécessaires pour assurer le -respect des dits droits de propriété intellectuelle du Titulaire et/ou -des Contributeurs. - - - Article 7 - SERVICES ASSOCIES - -7.1 Le Contrat n'oblige en aucun cas le Concédant à la réalisation de -prestations d'assistance technique ou de maintenance du Logiciel. - -Cependant le Concédant reste libre de proposer ce type de services. Les -termes et conditions d'une telle assistance technique et/ou d'une telle -maintenance seront alors déterminés dans un acte séparé. Ces actes de -maintenance et/ou assistance technique n'engageront que la seule -responsabilité du Concédant qui les propose. - -7.2 De même, tout Concédant est libre de proposer, sous sa seule -responsabilité, à ses licenciés une garantie, qui n'engagera que lui, -lors de la redistribution du Logiciel et/ou du Logiciel Modifié et ce, -dans les conditions qu'il souhaite. Cette garantie et les modalités -financières de son application feront l'objet d'un acte séparé entre le -Concédant et le Licencié. - - - Article 8 - RESPONSABILITE - -8.1 Sous réserve des dispositions de l'article 8.2 -<#limite-responsabilite>, le Licencié a la faculté, sous réserve de -prouver la faute du Concédant concerné, de solliciter la réparation du -préjudice direct qu'il subirait du fait du Logiciel et dont il apportera -la preuve. - -8.2 La responsabilité du Concédant est limitée aux engagements pris en -application du Contrat et ne saurait être engagée en raison notamment: -(i) des dommages dus à l'inexécution, totale ou partielle, de ses -obligations par le Licencié, (ii) des dommages directs ou indirects -découlant de l'utilisation ou des performances du Logiciel subis par le -Licencié et (iii) plus généralement d'un quelconque dommage indirect. En -particulier, les Parties conviennent expressément que tout préjudice -financier ou commercial (par exemple perte de données, perte de -bénéfices, perte d'exploitation, perte de clientèle ou de commandes, -manque à gagner, trouble commercial quelconque) ou toute action dirigée -contre le Licencié par un tiers, constitue un dommage indirect et -n'ouvre pas droit à réparation par le Concédant. - - - Article 9 - GARANTIE - -9.1 Le Licencié reconnaît que l'état actuel des connaissances -scientifiques et techniques au moment de la mise en circulation du -Logiciel ne permet pas d'en tester et d'en vérifier toutes les -utilisations ni de détecter l'existence d'éventuels défauts. L'attention -du Licencié a été attirée sur ce point sur les risques associés au -chargement, à l'utilisation, la modification et/ou au développement et à -la reproduction du Logiciel qui sont réservés à des utilisateurs avertis. - -Il relève de la responsabilité du Licencié de contrôler, par tous -moyens, l'adéquation du produit à ses besoins, son bon fonctionnement et -de s'assurer qu'il ne causera pas de dommages aux personnes et aux biens. - -9.2 Le Concédant déclare de bonne foi être en droit de concéder -l'ensemble des droits attachés au Logiciel (comprenant notamment les -droits visés à l'article 5 <#etendue>). - -9.3 Le Licencié reconnaît que le Logiciel est fourni "en l'état" par le -Concédant sans autre garantie, expresse ou tacite, que celle prévue à -l'article 9.2 <#bonne-foi> et notamment sans aucune garantie sur sa -valeur commerciale, son caractère sécurisé, innovant ou pertinent. - -En particulier, le Concédant ne garantit pas que le Logiciel est exempt -d'erreur, qu'il fonctionnera sans interruption, qu'il sera compatible -avec l'équipement du Licencié et sa configuration logicielle ni qu'il -remplira les besoins du Licencié. - -9.4 Le Concédant ne garantit pas, de manière expresse ou tacite, que le -Logiciel ne porte pas atteinte à un quelconque droit de propriété -intellectuelle d'un tiers portant sur un brevet, un logiciel ou sur tout -autre droit de propriété. Ainsi, le Concédant exclut toute garantie au -profit du Licencié contre les actions en contrefaçon qui pourraient être -diligentées au titre de l'utilisation, de la modification, et de la -redistribution du Logiciel. Néanmoins, si de telles actions sont -exercées contre le Licencié, le Concédant lui apportera son expertise -technique et juridique pour sa défense. Cette expertise technique et -juridique est déterminée au cas par cas entre le Concédant concerné et -le Licencié dans le cadre d'un protocole d'accord. Le Concédant dégage -toute responsabilité quant à l'utilisation de la dénomination du -Logiciel par le Licencié. Aucune garantie n'est apportée quant à -l'existence de droits antérieurs sur le nom du Logiciel et sur -l'existence d'une marque. - - - Article 10 - RESILIATION - -10.1 En cas de manquement par le Licencié aux obligations mises à sa -charge par le Contrat, le Concédant pourra résilier de plein droit le -Contrat trente (30) jours après notification adressée au Licencié et -restée sans effet. - -10.2 Le Licencié dont le Contrat est résilié n'est plus autorisé à -utiliser, modifier ou distribuer le Logiciel. Cependant, toutes les -licences qu'il aura concédées antérieurement à la résiliation du Contrat -resteront valides sous réserve qu'elles aient été effectuées en -conformité avec le Contrat. - - - Article 11 - DISPOSITIONS DIVERSES - - - 11.1 CAUSE EXTERIEURE - -Aucune des Parties ne sera responsable d'un retard ou d'une défaillance -d'exécution du Contrat qui serait dû à un cas de force majeure, un cas -fortuit ou une cause extérieure, telle que, notamment, le mauvais -fonctionnement ou les interruptions du réseau électrique ou de -télécommunication, la paralysie du réseau liée à une attaque -informatique, l'intervention des autorités gouvernementales, les -catastrophes naturelles, les dégâts des eaux, les tremblements de terre, -le feu, les explosions, les grèves et les conflits sociaux, l'état de -guerre... - -11.2 Le fait, par l'une ou l'autre des Parties, d'omettre en une ou -plusieurs occasions de se prévaloir d'une ou plusieurs dispositions du -Contrat, ne pourra en aucun cas impliquer renonciation par la Partie -intéressée à s'en prévaloir ultérieurement. - -11.3 Le Contrat annule et remplace toute convention antérieure, écrite -ou orale, entre les Parties sur le même objet et constitue l'accord -entier entre les Parties sur cet objet. Aucune addition ou modification -aux termes du Contrat n'aura d'effet à l'égard des Parties à moins -d'être faite par écrit et signée par leurs représentants dûment habilités. - -11.4 Dans l'hypothèse où une ou plusieurs des dispositions du Contrat -s'avèrerait contraire à une loi ou à un texte applicable, existants ou -futurs, cette loi ou ce texte prévaudrait, et les Parties feraient les -amendements nécessaires pour se conformer à cette loi ou à ce texte. -Toutes les autres dispositions resteront en vigueur. De même, la -nullité, pour quelque raison que ce soit, d'une des dispositions du -Contrat ne saurait entraîner la nullité de l'ensemble du Contrat. - - - 11.5 LANGUE - -Le Contrat est rédigé en langue française et en langue anglaise, ces -deux versions faisant également foi. - - - Article 12 - NOUVELLES VERSIONS DU CONTRAT - -12.1 Toute personne est autorisée à copier et distribuer des copies de -ce Contrat. - -12.2 Afin d'en préserver la cohérence, le texte du Contrat est protégé -et ne peut être modifié que par les auteurs de la licence, lesquels se -réservent le droit de publier périodiquement des mises à jour ou de -nouvelles versions du Contrat, qui posséderont chacune un numéro -distinct. Ces versions ultérieures seront susceptibles de prendre en -compte de nouvelles problématiques rencontrées par les logiciels libres. - -12.3 Tout Logiciel diffusé sous une version donnée du Contrat ne pourra -faire l'objet d'une diffusion ultérieure que sous la même version du -Contrat ou une version postérieure, sous réserve des dispositions de -l'article 5.3.4 <#compatibilite>. - - - Article 13 - LOI APPLICABLE ET COMPETENCE TERRITORIALE - -13.1 Le Contrat est régi par la loi française. Les Parties conviennent -de tenter de régler à l'amiable les différends ou litiges qui -viendraient à se produire par suite ou à l'occasion du Contrat. - -13.2 A défaut d'accord amiable dans un délai de deux (2) mois à compter -de leur survenance et sauf situation relevant d'une procédure d'urgence, -les différends ou litiges seront portés par la Partie la plus diligente -devant les Tribunaux compétents de Paris. - - diff --git a/README.md b/README.md @@ -1,7 +1,7 @@ # Star Schiff The purpose of this library is to numericaly solve the radiative properties of -micro organism with respect to an "Approximation Method for Short Wavelength or +soft particles with respect to an "Approximation Method for Short Wavelength or High-Energy Scattering" (L. Schiff, 1956). It will estimate total cross-sections (absorption, scattering and @@ -23,22 +23,25 @@ computation time in order to obtain more accurate results if needed. ## How to build -The *Star-Schiff* library relies on the [CMake](http://www.cmake.org) and the +The Star-Schiff library relies on the [CMake](http://www.cmake.org) and the [RCMake](https://gitlab.com/vaplv/rcmake/) package to build. It also depends on the +[GNU Scientific Library](http://www.gnu.org/software/gsl/), [RSys](https://gitlab.com/vaplv/rsys/), [Star-3D](https://gitlab.com/meso-star/star-3d/) and [Star-SP](https://gitlab.com/meso-star/star-sp/) libraries. First ensure that CMake is installed on your system. Then install the RCMake -package as well as all the *Star-Schiff* prerequisites. Then generate the -project from the `cmake/CMakeLists.txt` file by appending to the +package as well as all the aforementioned Star-Schiff prerequisites. Then +generate the project from the `cmake/CMakeLists.txt` file by appending to the `CMAKE_PREFIX_PATH` variable the install directories of its dependencies and -the RCMake package. +the one of the RCMake package. -## Licenses +## License -*Star-Schiff* is Copyright (C) |Meso|Star> 2015 (<contact@meso-star.com>). It is a -free software released under the [OSI](http://opensource.org)-approved CeCILL -license. You are welcome to redistribute it under certain conditions; refer to -the COPYING files for details. +Star-Schiff is developped by [|Meso|Star>](http://www.meso-star.com) for the +the [National Center for Scientific Research](http://www.cnrs.fr/index.php) +(CNRS). It is a free software copyright (C) CNRS 2015-2016 released under the +[OSI](http://opensource.org)-approved GPL v3.0 license. You are welcome to +redistribute it under certain conditions; refer to the COPYING file for +details. diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -1,30 +1,17 @@ -# Copyright (C) |Meso|Star> 2015 (contact@meso-star.com) +# Copyright (C) 2015-2016 CNRS # -# This software is governed by the CeCILL license under French law and -# abiding by the rules of distribution of free software. You can use, -# modify and/or redistribute the software under the terms of the CeCILL -# license as circulated by CEA, CNRS and INRIA at the following URL -# "http://www.cecill.info". +# 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. # -# As a counterpart to the access to the source code and rights to copy, -# modify and redistribute granted by the license, users are provided only -# with a limited warranty and the software's author, the holder of the -# economic rights, and the successive licensors have only limited -# liability. +# 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. # -# In this respect, the user's attention is drawn to the risks associated -# with loading, using, modifying and/or developing or reproducing the -# software by the user in light of its specific status of free software, -# that may mean that it is complicated to manipulate, and that also -# therefore means that it is reserved for developers and experienced -# professionals having in-depth computer knowledge. Users are therefore -# encouraged to load and test the software's suitability as regards their -# requirements in conditions enabling the security of their systems and/or -# data to be ensured and, more generally, to use and operate it in the -# same conditions as regards security. -# -# The fact that you are presently reading this means that you have had -# knowledge of the CeCILL license and that you accept its terms. +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. cmake_minimum_required(VERSION 2.8) project(star-schiff C) @@ -41,11 +28,13 @@ find_package(RSys 0.3 REQUIRED) find_package(StarSP 0.3 REQUIRED) find_package(Star3D 0.3 REQUIRED) find_package(OpenMP 1.2 REQUIRED) +find_package(GSL REQUIRED) include_directories( ${RSys_INCLUDE_DIR} ${StarSP_INCLUDE_DIR} - ${Star3D_INCLUDE_DIR}) + ${Star3D_INCLUDE_DIR} + ${GSL_INCLUDE_DIRS}) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${RCMAKE_SOURCE_DIR}) include(rcmake) @@ -59,10 +48,13 @@ set(VERSION_MINOR 3) set(VERSION_PATCH 0) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) -set(SSCHIFF_FILES_SRC sschiff_device.c sschiff_estimator.c) +set(SSCHIFF_FILES_SRC + sschiff_device.c + sschiff_estimator.c + sschiff_scattering_angles_distributions.c) set(SSCHIFF_FILES_INC_API sschiff.h) set(SSCHIFF_FILES_INC sschiff_device.h) -set(SSCHIFF_FILES_DOC COPYING.en COPYING.fr README.md) +set(SSCHIFF_FILES_DOC COPYING README.md) # Prepend each file in the `SSCHIFF_FILES_<SRC|INC>' list by `SSCHIFF_SOURCE_DIR' rcmake_prepend_path(SSCHIFF_FILES_SRC ${SSCHIFF_SOURCE_DIR}) @@ -76,12 +68,12 @@ set_target_properties(sschiff PROPERTIES VERSION ${VERSION} SOVERSION ${VERSION_MAJOR}) -target_link_libraries(sschiff RSys Star3D StarSP) +target_link_libraries(sschiff RSys Star3D StarSP GSL::gsl) if(CMAKE_COMPILER_IS_GNUCC) target_link_libraries(sschiff m) endif() -set_target_properties(sschiff PROPERTIES +set_target_properties(sschiff PROPERTIES COMPILE_FLAGS ${OpenMP_C_FLAGS} COMPILE_DEFINITIONS SSCHIFF_USE_OPENMP) if(CMAKE_COMPILER_IS_GNUCC) @@ -102,6 +94,7 @@ if(NOT NO_TEST) new_test(test_sschiff_device) new_test(test_sschiff_estimator_sphere) new_test(test_sschiff_estimator_cylinder) + new_test(test_sschiff_estimator_rhodo) rcmake_copy_runtime_libraries(test_sschiff_device) endif() diff --git a/src/sschiff.h b/src/sschiff.h @@ -1,30 +1,17 @@ -/* Copyright (C) |Meso|Star> 2015 (contact@meso-star.com) +/* Copyright (C) 2015-2016 CNRS * - * This software is governed by the CeCILL license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/or redistribute the software under the terms of the CeCILL - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". + * 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. * - * As a counterpart to the access to the source code and rights to copy, - * modify and redistribute granted by the license, users are provided only - * with a limited warranty and the software's author, the holder of the - * economic rights, and the successive licensors have only limited - * liability. + * 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. * - * In this respect, the user's attention is drawn to the risks associated - * with loading, using, modifying and/or developing or reproducing the - * software by the user in light of its specific status of free software, - * that may mean that it is complicated to manipulate, and that also - * therefore means that it is reserved for developers and experienced - * professionals having in-depth computer knowledge. Users are therefore - * encouraged to load and test the software's suitability as regards their - * requirements in conditions enabling the security of their systems and/or - * data to be ensured and, more generally, to use and operate it in the - * same conditions as regards security. - * - * The fact that you are presently reading this means that you have had - * knowledge of the CeCILL license and that you accept its terms. */ + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifndef SSCHIFF_H #define SSCHIFF_H @@ -58,15 +45,6 @@ struct s3d_device; struct s3d_shape; struct ssp_rng; -/* Type of estimated data */ -enum sschiff_data { - SSCHIFF_EXTINCTION_CROSS_SECTION, - SSCHIFF_ABSORPTION_CROSS_SECTION, - SSCHIFF_SCATTERING_CROSS_SECTION, - SSCHIFF_AVERAGE_PROJECTED_AREA, - SSCHIFF_DATA_COUNT__ -}; - /* Optical properties of a material handled by the Schiff integrator */ struct sschiff_material_properties { double medium_refractive_index; @@ -89,35 +67,51 @@ static const struct sschiff_material SSCHIFF_NULL_MATERIAL = { NULL, NULL }; /* User defined distribution of the geometries. The unit of the geometry is the * micron, i.e. 1.0f == 1 micron */ struct sschiff_geometry_distribution { + struct sschiff_material material; /* Material of the geometry distribution */ + double characteristic_length; res_T (*sample) /* Sample a geometry i.e. a shape and its material */ (struct ssp_rng* rng, - struct sschiff_material* mtl, /* Sampled material */ struct s3d_shape* shape, /* Sampled shape */ void* context); void* context; }; static const struct sschiff_geometry_distribution -SSCHIFF_NULL_GEOMETRY_DISTRIBUTION = { NULL, NULL }; +SSCHIFF_NULL_GEOMETRY_DISTRIBUTION = { {NULL, NULL}, -1.0, NULL, NULL }; /* State of the Monte Carlo estimation */ -struct sschiff_estimator_state { - double wavelength; /* Estimated wavelength in micron */ - struct sschiff_estimator_value { /* Values of the estimation */ - double E; /* Expected value */ - double V; /* Variance */ - double SE; /* Standard error */ - } values[SSCHIFF_DATA_COUNT__]; +struct sschiff_state { + double E; /* Expected value */ + double V; /* Variance */ + double SE; /* Standard error */ +}; + +struct sschiff_cross_section { + struct sschiff_state extinction; + struct sschiff_state absorption; + struct sschiff_state scattering; + struct sschiff_state average_projected_area; }; +/* Type of the function use to distribute the scattering angles in [0, PI]. + * nangles is assumed to be greater than or equal to 2 and the angles is + * ensured to have `nangles' entries. */ +typedef void (*sschiff_scattering_angles_distribution_T) + (double angles[], const size_t nangles); + /* Opaque types */ struct sschiff_device; struct sschiff_estimator; +BEGIN_DECLS + +/* Built-in uniform distribution of scattering angles */ +SSCHIFF_API const sschiff_scattering_angles_distribution_T +sschiff_uniform_scattering_angles; + /******************************************************************************* * Star Schiff API ******************************************************************************/ -BEGIN_DECLS SSCHIFF_API res_T sschiff_device_create @@ -141,9 +135,11 @@ sschiff_integrate (struct sschiff_device* dev, struct ssp_rng* rng, struct sschiff_geometry_distribution* distribution, - const double* wavelengths, /* list of wavelengths to estimate in micron */ + /* Wavelengths to estimate in micron. Must be sorted in ascending order. */ + const double* wavelengths, const size_t wavelengths_count, /* # wavelengths to estimate */ - const size_t scattering_angles_count, /* # of scattering angles to handle */ + const sschiff_scattering_angles_distribution_T angles, /* angles distrib */ + const size_t scattering_angles_count, /* # scattering angles. Must be >= 3 */ const size_t sampled_geometries_count, /* # geometries to sample */ const size_t sampled_directions_count, /* # directions to sample per geometry */ struct sschiff_estimator** estimator); @@ -156,11 +152,19 @@ SSCHIFF_API res_T sschiff_estimator_ref_put (struct sschiff_estimator* estimator); -/* Return the number of estimated wavelength */ +/* Return the list of estimated wavelengths. */ SSCHIFF_API res_T -sschiff_estimator_get_wavelengths_count +sschiff_estimator_get_wavelengths (const struct sschiff_estimator* estimator, - size_t* count); + const double** wavelengths, /* May be NULL, i.e. do not return this list */ + size_t* count); /* May be NULL, i.e. do not return the # wavelengths */ + +/* Return the list of scattering angles. */ +SSCHIFF_API res_T +sschiff_estimator_get_scattering_angles + (const struct sschiff_estimator* estimator, + const double** angles, /* May be NULL, i.e. do not return the angles */ + size_t* count); /* May be NULL, i.e. do not return the # scattering angles */ /* Return the number of Monte Carlo realisations */ SSCHIFF_API res_T @@ -168,21 +172,95 @@ sschiff_estimator_get_realisations_count (const struct sschiff_estimator* estimator, size_t* count); -/* Retrieve the estimation state of a given wavelength */ +/* Retrieve the estimation state of a given wavelength. */ +SSCHIFF_API res_T +sschiff_estimator_get_cross_section + (const struct sschiff_estimator* estimator, + const size_t wavelength_index, /* Id of the wavelengths */ + struct sschiff_cross_section* cross_section); + +/* Retrieve the estimated cross sections of all wavelengths. The length of + * `cross_sections' must be at least equal to the count of integrated + * wavelengths. One can use the sschiff_estimator_get_wavelengths function to + * retrieve this information. */ +SSCHIFF_API res_T +sschiff_estimator_get_cross_sections + (const struct sschiff_estimator* estimator, + struct sschiff_cross_section cross_sections[]); + +/* Retrieve a pointer onto the estimated phase function for the scattering + * angles of the estimator. Use the sschiff_estimator_get_scattering_angles + * function to retrieve these scattering angles. Return RES_BAD_OP if the phase + * function couldn't be estimated for this wavelength */ +SSCHIFF_API res_T +sschiff_estimator_get_phase_function + (const struct sschiff_estimator* estimator, + const size_t wavelength_index, + const struct sschiff_state** states); + +/* Retrieve a pointer onto the estimated phase function cumulative for the + * scattering angles of the estimator. Use the + * sschiff_estimator_get_scattering_angles function to retrieve these + * scattering angles. Return RES_BAD_OP if the phase function couldn't be + * estimated for this wavelength */ +SSCHIFF_API res_T +sschiff_estimator_get_phase_function_cumulative + (const struct sschiff_estimator* estimator, + const size_t wavelength_index, + const struct sschiff_state** states); + +/* Compute the inverse cumulative of the estimated phase function. The inverse + * cumulative is computed for a set of `nthetas' values distributed in [0, 1] + * as [0, 1*S, 2*S, ..., i*S, ..., (nthetas-1)*S] with S=1/(nthetas-1). The + * ouput array `thetas' stored the angles corresponding to these cumulative + * values. Its length must be at least equal to `nthetas'. Return RES_BAD_OP of + * the cumulative phase function cannot be inverted. */ +SSCHIFF_API res_T +sschiff_estimator_inverse_cumulative_phase_function + (const struct sschiff_estimator* estimator, + const size_t wavelength_index, + double thetas[], + const size_t nthetas); /* Must be >= 2 */ + + +/* Retrieve, for the submitted wavelength, the index of the last small + * scattering angle, i.e. the last angle from which the phase function + * [cumulative] is estimated by Monte Carlo. One can use this index to get the + * value of the limit angle from the scattering angles returned by the + * sschiff_estimator_get_scattering_angles function. Return RES_BAD_OP if the + * phase function is not computable for this wavelength. */ +SSCHIFF_API res_T +sschiff_estimator_get_limit_scattering_angle_index + (const struct sschiff_estimator* estimator, + const size_t wavelength_index, + size_t* scattering_angle_index); + +/* Return the `n' parameter of the model used to compute the phase function of + * the wide scattering angles for a given wavelength. Return RES_BAD_OP if the + * phase function is not computable for this wavelength */ +SSCHIFF_API res_T +sschiff_estimator_get_wide_scattering_angle_model_parameter + (const struct sschiff_estimator* estimator, + const size_t wavelength_index, + double* n); + +/* Return the estimated differential cross section for a wavelength at a given + * scattering angle. Return RES_BAD_OP if it was not computable. */ SSCHIFF_API res_T -sschiff_estimator_get_wavelength_state +sschiff_estimator_get_differential_cross_section (const struct sschiff_estimator* estimator, - const double wavelength, /* In micron */ - struct sschiff_estimator_state* state); + const size_t wavelength_index, + const size_t scattering_angle_index, + struct sschiff_state* state); -/* Retrieve the estimation state of all wavelengths. The length of `states' - * must be at least equal to the count of integrated wavelengths. One can use - * the sschiff_estimator_get_wavelengths_count function to retrieve this - * information. */ +/* Return the estimated differential cross section cumulative for a wavelength + * at a given scattering angle. Return RES_BAD_OP if it was not computable. */ SSCHIFF_API res_T -sschiff_estimator_get_states +sschiff_estimator_get_differential_cross_section_cumulative (const struct sschiff_estimator* estimator, - struct sschiff_estimator_state states[]); + const size_t wavelength_index, + const size_t scanttering_angle_index, + struct sschiff_state* state); END_DECLS diff --git a/src/sschiff_device.c b/src/sschiff_device.c @@ -1,30 +1,17 @@ -/* Copyright (C) |Meso|Star> 2015 (contact@meso-star.com) +/* Copyright (C) 2015-2016 CNRS * - * This software is governed by the CeCILL license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/or redistribute the software under the terms of the CeCILL - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". + * 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. * - * As a counterpart to the access to the source code and rights to copy, - * modify and redistribute granted by the license, users are provided only - * with a limited warranty and the software's author, the holder of the - * economic rights, and the successive licensors have only limited - * liability. + * 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. * - * In this respect, the user's attention is drawn to the risks associated - * with loading, using, modifying and/or developing or reproducing the - * software by the user in light of its specific status of free software, - * that may mean that it is complicated to manipulate, and that also - * therefore means that it is reserved for developers and experienced - * professionals having in-depth computer knowledge. Users are therefore - * encouraged to load and test the software's suitability as regards their - * requirements in conditions enabling the security of their systems and/or - * data to be ensured and, more generally, to use and operate it in the - * same conditions as regards security. - * - * The fact that you are presently reading this means that you have had - * knowledge of the CeCILL license and that you accept its terms. */ + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "sschiff.h" #include "sschiff_device.h" @@ -75,6 +62,20 @@ log_error(struct sschiff_device* dev, const char* msg, ...) } } +void +log_warning(struct sschiff_device* dev, const char* msg, ...) +{ + va_list vargs_list; + ASSERT(dev && msg); + if(dev->verbose) { + res_T res; (void)res; + va_start(vargs_list, msg); + res = logger_vprint(dev->logger, LOG_WARNING, msg, vargs_list); + ASSERT(res == RES_OK); + va_end(vargs_list); + } +} + /******************************************************************************* * API functions ******************************************************************************/ diff --git a/src/sschiff_device.h b/src/sschiff_device.h @@ -1,30 +1,17 @@ -/* Copyright (C) |Meso|Star> 2015 (contact@meso-star.com) +/* Copyright (C) 2015-2016 CNRS * - * This software is governed by the CeCILL license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/or redistribute the software under the terms of the CeCILL - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". + * 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. * - * As a counterpart to the access to the source code and rights to copy, - * modify and redistribute granted by the license, users are provided only - * with a limited warranty and the software's author, the holder of the - * economic rights, and the successive licensors have only limited - * liability. + * 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. * - * In this respect, the user's attention is drawn to the risks associated - * with loading, using, modifying and/or developing or reproducing the - * software by the user in light of its specific status of free software, - * that may mean that it is complicated to manipulate, and that also - * therefore means that it is reserved for developers and experienced - * professionals having in-depth computer knowledge. Users are therefore - * encouraged to load and test the software's suitability as regards their - * requirements in conditions enabling the security of their systems and/or - * data to be ensured and, more generally, to use and operate it in the - * same conditions as regards security. - * - * The fact that you are presently reading this means that you have had - * knowledge of the CeCILL license and that you accept its terms. */ + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifndef SSCHIFF_DEVICE_H #define SSCHIFF_DEVICE_H @@ -54,5 +41,16 @@ log_error __attribute((format(printf, 2, 3))) #endif ; + +extern LOCAL_SYM void +log_warning + (struct sschiff_device* dev, + const char* msg, + ...) +#ifdef COMPILER_GCC + __attribute((format(printf, 2, 3))) +#endif +; + #endif /* SSCHIFF_DEVICE_H */ diff --git a/src/sschiff_estimator.c b/src/sschiff_estimator.c @@ -1,36 +1,24 @@ -/* Copyright (C) |Meso|Star> 2015 (contact@meso-star.com) +/* Copyright (C) 2015-2016 CNRS * - * This software is governed by the CeCILL license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/or redistribute the software under the terms of the CeCILL - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". + * 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. * - * As a counterpart to the access to the source code and rights to copy, - * modify and redistribute granted by the license, users are provided only - * with a limited warranty and the software's author, the holder of the - * economic rights, and the successive licensors have only limited - * liability. + * 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. * - * In this respect, the user's attention is drawn to the risks associated - * with loading, using, modifying and/or developing or reproducing the - * software by the user in light of its specific status of free software, - * that may mean that it is complicated to manipulate, and that also - * therefore means that it is reserved for developers and experienced - * professionals having in-depth computer knowledge. Users are therefore - * encouraged to load and test the software's suitability as regards their - * requirements in conditions enabling the security of their systems and/or - * data to be ensured and, more generally, to use and operate it in the - * same conditions as regards security. - * - * The fact that you are presently reading this means that you have had - * knowledge of the CeCILL license and that you accept its terms. */ + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #define _POSIX_C_SOURCE 200112L /* nextafterf support */ #include "sschiff.h" #include "sschiff_device.h" +#include <rsys/algorithm.h> #include <rsys/float2.h> #include <rsys/float3.h> #include <rsys/image.h> @@ -45,44 +33,97 @@ #include <math.h> #include <omp.h> +#include <gsl/gsl_sf.h> +#include <gsl/gsl_multiroots.h> + #define MAX_FAILURES 10 +#define INVALID_LIMIT_ANGLE SIZE_MAX /* Accumulator of double precision values */ -struct accum { double weights[SSCHIFF_DATA_COUNT__]; }; +struct accum { + double extinction_cross_section; + double absorption_cross_section; + double scattering_cross_section; + double avg_projected_area; + + /* Per scattering angles weights */ + double* differential_cross_section; + double* differential_cross_section_cumulative; +}; /* Monte carlo data */ struct mc_data { double weight; double sqr_weight; }; - static const struct mc_data MC_DATA_NULL = { 0.0, 0.0 }; /* Accumulator of Monte Carlo data */ -struct mc_accum { struct mc_data mc_data[SSCHIFF_DATA_COUNT__]; }; +struct mc_accum { + struct mc_data extinction_cross_section; + struct mc_data absorption_cross_section; + struct mc_data scattering_cross_section; + struct mc_data avg_projected_area; + + /* Per scattering angles weight */ + struct mc_data* differential_cross_section; + struct mc_data* differential_cross_section_cumulative; +}; + +/* Estimated phase function */ +struct phase_function { + /* Per angle values */ + struct sschiff_state* values; + struct sschiff_state* cumulative; +}; -static const struct mc_accum MC_ACCUM_NULL = -{{{0.0, 0.0}, {0.0, 0.0}, {0.0, 0.0}, {0.0, 0.0}}}; +/* The integrator context stores per thread data */ +struct integrator_context { + /* Geometry of the micro particle */ + struct s3d_shape* shape; + struct s3d_scene* scene; + + struct ssp_rng* rng; /* Random Number Generator */ + size_t nwavelengths; /* #wavelengths */ + size_t nangles; /* #scattering angles */ + + /* Per wavelengths data */ + struct accum* accums; /* Temporary accumulators */ + struct mc_accum* mc_accums; /* Monte Carlo accumulators */ + + /* Pointer toward the estimator */ + struct sschiff_estimator* estimator; +}; + +/* Store per thread data of the post integration process */ +struct solver_context { + gsl_multiroot_fdfsolver* solver; + gsl_vector* init_val; +}; struct sschiff_estimator { - double* wavelengths; - struct mc_accum* accums; + double* wavelengths; /* List of wavelengths in vacuum */ + double* angles; /* List of scattering angles */ + + /* Per wavelength index of the scattering angle from which the MC estimation + * of the phase function is no more valid. Must be < nangles. */ + size_t* limit_angles; + double* wide_angles_parameter; + + double* wavenumbers; + struct sschiff_material_properties* properties; /* Material properties */ + + /* Per wavelength results */ + struct phase_function* phase_functions; + struct mc_accum* accums; /* Monte Carlo estimation */ + + size_t nrealisations; /* # realisation used by MC estimations */ + int no_phase_function; /* Set to 1 when no phase function is computed */ + struct sschiff_device* dev; - size_t nrealisations; ref_T ref; }; /******************************************************************************* * Helper functions ******************************************************************************/ -static FINLINE uint16_t -morton2D_decode(const uint32_t u32) -{ - uint32_t x = u32 & 0x55555555; - x = (x | (x >> 1)) & 0x33333333; - x = (x | (x >> 2)) & 0x0F0F0F0F; - x = (x | (x >> 4)) & 0x00FF00FF; - x = (x | (x >> 8)) & 0x0000FFFF; - return (uint16_t)x; -} - static FINLINE int cmp_double(const void* a, const void* b) { @@ -92,6 +133,15 @@ cmp_double(const void* a, const void* b) return i; } +static FINLINE int +cmp_schiff_state(const void* a, const void* b) +{ + const struct sschiff_state* op0 = a; + const struct sschiff_state* op1 = b; + const int i = op0->E < op1->E ? -1 : (op0->E > op1->E ? 1 : 0); + return i; +} + /* Compute an orthonormal basis where `dir' is the Z axis. */ static void build_basis(const float dir[3], float basis[9]) @@ -140,78 +190,55 @@ build_transform transform[11] = -f3_dot(basis+6, pos); } -/* Dump a thumbnail of the sampled geometry in given sampled direction */ -static INLINE void -draw_thumbnail - (struct s3d_scene* scn, - const float basis[9], /* World space basis of the RT volume */ - const float pos[3], /* World space centroid of the RT volume */ - const float lower[3], /* Lower boundary of the RT volume */ - const float upper[3], /* Upper boundary of the RT volume */ - const char* name) /* Filename of the thumbnail */ +static FINLINE double +expected_value(const struct mc_data* data, const size_t nrealisations) { -#define DEFINITION 128 - STATIC_ASSERT(IS_POW2(DEFINITION), Invalid_thumbnail_definition); - const float range[2] = { 0, FLT_MAX }; - const float pixel_size = 1.f/(float)DEFINITION; - float axis_x[3], axis_y[3], axis_z[3]; - float plane_size[2]; - float ray_org[3]; - float org[3]; - uint32_t npixels = (uint32_t)(DEFINITION * DEFINITION); - uint32_t mcode; - unsigned char* img = NULL; - ASSERT(basis && pos && lower && upper); - - /* Allocate the thumbnail buffer */ - img = sa_add(img, DEFINITION*DEFINITION); - ASSERT(img != NULL); + return data->weight / (double)nrealisations; +} - /* Define the projection axis */ - f2_sub(plane_size, upper, lower); - f3_mulf(axis_x, basis + 0, plane_size[0] * 0.5f); - f3_mulf(axis_y, basis + 3, plane_size[1] * 0.5f); - f3_set(axis_z, basis + 6); +static INLINE void +get_mc_value + (const struct mc_data* data, + const size_t nrealisations, + struct sschiff_state* value) +{ + ASSERT(data && value); + value->E = expected_value(data, nrealisations); + value->V = data->sqr_weight / (double)nrealisations + - (data->weight * data->weight) / (double)(nrealisations * nrealisations); + value->SE = sqrt(value->V / (double)nrealisations); +} - /* Compute the origin of the projection plane */ - f3_add(org, pos, f3_mulf(org, axis_z, lower[2])); +static FINLINE int +hit_on_edge(const struct s3d_hit* hit) +{ + const float on_edge_eps = 1.e-4f; + float w; + ASSERT(hit && !S3D_HIT_NONE(hit)); + w = 1.f - hit->uv[0] - hit->uv[1]; + return eq_epsf(hit->uv[0], 0.f, on_edge_eps) + || eq_epsf(hit->uv[0], 1.f, on_edge_eps) + || eq_epsf(hit->uv[1], 0.f, on_edge_eps) + || eq_epsf(hit->uv[1], 1.f, on_edge_eps) + || eq_epsf(w, 0.f, on_edge_eps) + || eq_epsf(w, 1.f, on_edge_eps); +} - FOR_EACH(mcode, 0, npixels) { - struct s3d_hit hit; - size_t ipixel; - float sample[2], x[3], y[3]; - uint16_t ipixel_x, ipixel_y; - - /* Compute the sample position in [0, 1)^2 onto the projection plane */ - ipixel_x = morton2D_decode(mcode); - ipixel_y = morton2D_decode(mcode>>1); - sample[0] = ((float)ipixel_x + 0.5f) * pixel_size; - sample[1] = ((float)ipixel_y + 0.5f) * pixel_size; - - /* Compute the ray origin */ - f3_mulf(x, axis_x, sample[0]*2.f - 1.f); - f3_mulf(y, axis_y, sample[1]*2.f - 1.f); - f3_add(ray_org, f3_add(ray_org, x, y), org); - - S3D(scene_trace_ray(scn, ray_org, axis_z, range, &hit)); - - /* Simple shading */ - ipixel = (size_t)(ipixel_y * DEFINITION + ipixel_x); - if(S3D_HIT_NONE(&hit)) { - img[ipixel] = 0; - } else { - float N[3] = {0.f,0.f,0.f}; - float cosine; - f3_normalize(N, hit.normal); - if(0 > (cosine = f3_dot(N, axis_z))) { - cosine = f3_dot(f3_minus(N, N), axis_z); - } - img[ipixel] = (unsigned char)(cosine*255.f + 0.5f/*Round*/); - } - } - image_ppm_write(name, DEFINITION, DEFINITION, 1, img); - sa_release(img); -#undef DEFINITION +static FINLINE int +self_hit + (const struct s3d_hit* hit_from, + const struct s3d_hit* hit_to, + const float epsilon) +{ + ASSERT(hit_from && hit_to); + + if(S3D_HIT_NONE(hit_from) || S3D_HIT_NONE(hit_to)) + return 0; + if(S3D_PRIMITIVE_EQ(&hit_from->prim, &hit_to->prim)) + return 1; + if(eq_epsf(hit_to->distance - hit_from->distance, 0.f, epsilon)) + return hit_on_edge(hit_from) && hit_on_edge(hit_to); + return 0; } /* Compute the length in micron of the ray part that traverses the scene */ @@ -225,38 +252,35 @@ compute_path_length double* length) { float range[2] = { 0, FLT_MAX }; - struct s3d_primitive prim_from; - struct s3d_hit hit; + struct s3d_hit hit_from, hit; double len = 0; float dst; ASSERT(scn && first_hit && ray_org && ray_dir && !S3D_HIT_NONE(first_hit)); + (void)dev; dst = range[0] = first_hit->distance; - prim_from = first_hit->prim; + hit_from = *first_hit; + do { do { range[0] = nextafterf(range[0], range[1]); S3D(scene_trace_ray(scn, ray_org, ray_dir, range, &hit)); - } while(S3D_PRIMITIVE_EQ(&hit.prim, &prim_from) /* Self-intersection */ - || hit.distance < range[0]); /* Precision issue */ + } while(hit.distance < range[0] || self_hit(&hit_from, &hit, 1.e-6f)); - if(S3D_HIT_NONE(&hit)) { - log_error(dev, "Error in computing the radiative path length.\n"); - return RES_BAD_ARG; - } + if(S3D_HIT_NONE(&hit)) + return RES_BAD_OP; len += hit.distance - dst; dst = range[0] = hit.distance; - prim_from = hit.prim; + hit_from = hit; do { range[0] = nextafterf(range[0], range[1]); S3D(scene_trace_ray(scn, ray_org, ray_dir, range, &hit)); - } while(S3D_PRIMITIVE_EQ(&hit.prim, &prim_from) /* Self-intersection */ - || hit.distance < range[0]); /* Precision issue */ + } while(hit.distance < range[0] || self_hit(&hit_from, &hit, 1.e-6f)); range[0] = hit.distance; - prim_from = hit.prim; + hit_from = hit; } while(!S3D_HIT_NONE(&hit)); @@ -264,19 +288,117 @@ compute_path_length return RES_OK; } +static INLINE void +accum_cross_section + (struct integrator_context* ctx, + const double plane_area, + const double path_length) +{ + size_t iwlen; + ASSERT(ctx && plane_area > 0 && path_length > 0); + + FOR_EACH(iwlen, 0, ctx->nwavelengths) { + double n_r, k_r; + double k_e; + double w_extinction, w_absorption, w_scattering; + + k_e = ctx->estimator->wavenumbers[iwlen]; + n_r = ctx->estimator->properties[iwlen].relative_real_refractive_index; + k_r = ctx->estimator->properties[iwlen].relative_imaginary_refractive_index; + + /* Extinction cross section */ + w_extinction = 2.0 * plane_area * + (1.0 - exp(-k_e*k_r*path_length) * cos(k_e*(n_r - 1.0)*path_length)); + ctx->accums[iwlen].extinction_cross_section += w_extinction; + + /* Absorption cross section */ + w_absorption = plane_area * (1.0 - exp(-2.0*k_e*k_r*path_length)); + ctx->accums[iwlen].absorption_cross_section += w_absorption; + + /* Scattering cross section */ + w_scattering = w_extinction - w_absorption; + ctx->accums[iwlen].scattering_cross_section += w_scattering; + + /* Average projected area */ + ctx->accums[iwlen].avg_projected_area += plane_area; + } +} + +static INLINE void +accum_differential_cross_section + (struct integrator_context* ctx, + const double plane_area, + const double path_length[2], + float ray_org[2][3]) +{ + double delta_r; + size_t iwlen; + float vec[3]; + + /* Compute the length between the 2 ray starting points in footprint space */ + delta_r = f3_len(f3_sub(vec, ray_org[0], ray_org[1])); + + FOR_EACH(iwlen, 0, ctx->nwavelengths) { + double k_e_delta_r; + double n_r, k_r; + double k_e; + double beta_r[2]; + double beta_i[2]; + double tmp; + size_t iangle; + + /* Avoid evaluating the differential cross sections for wavelengths with no + * valid limit scattering angle */ + if(ctx->estimator->limit_angles[iwlen] == INVALID_LIMIT_ANGLE) continue; + + /* Fetch optical properties */ + k_e = ctx->estimator->wavenumbers[iwlen]; + n_r = ctx->estimator->properties[iwlen].relative_real_refractive_index; + k_r = ctx->estimator->properties[iwlen].relative_imaginary_refractive_index; + + /* Precompute some values. TODO can be stored on the context */ + k_e_delta_r = k_e * delta_r; + beta_r[0] = k_e * (n_r - 1) * path_length[0]; + beta_r[1] = k_e * (n_r - 1) * path_length[1]; + beta_i[0] = k_e * k_r * path_length[0]; + beta_i[1] = k_e * k_r * path_length[1]; + tmp = (k_e * plane_area) / (2*PI); + tmp *= tmp; + tmp *= (1 + + exp(-(beta_i[0] + beta_i[1])) * cos(beta_r[0] - beta_r[1]) + - exp(-beta_i[0]) * cos(beta_r[0]) + - exp(-beta_i[1]) * cos(beta_r[1])); + + /* Compute and accumulate the MC weights of the differential cross section + * and its cumulative. Note that ctx->limit_angles store the index of the + * first scattering angle whos phase function is not estimated by + * Monte-Carlo */ + FOR_EACH(iangle, 0, ctx->estimator->limit_angles[iwlen]) { + double bessel_j0, bessel_j1; + double weight; + double k_e_angle_delta_r; + + k_e_angle_delta_r = ctx->estimator->angles[iangle] * k_e_delta_r; + + bessel_j0 = gsl_sf_bessel_J0(k_e_angle_delta_r); + weight = bessel_j0 * tmp; + ctx->accums[iwlen].differential_cross_section[iangle] += weight; + + bessel_j1 = gsl_sf_bessel_J1(k_e_angle_delta_r); + weight = 2*PI*ctx->estimator->angles[iangle]*bessel_j1/k_e_delta_r*tmp; + ctx->accums[iwlen].differential_cross_section_cumulative[iangle] += weight; + } + } +} + static res_T accum_monte_carlo_weight (struct sschiff_device* dev, - struct s3d_scene* scn, - struct ssp_rng* rng, - const struct sschiff_material_properties* props, - const double* wavelengths, /* In micron */ - const size_t nwavelengths, + struct integrator_context* ctx, const float basis[9], /* World space basis of the RT volume */ const float pos[3], /* World space centroid of the RT volume */ const float lower[3], /* Lower boundary of the RT volume */ - const float upper[3], /* Upper boundary of the RT volume */ - struct accum* accums) + const float upper[3]) /* Upper boundary of the RT volume */ { struct s3d_hit hit; double sample[2]; @@ -284,16 +406,15 @@ accum_monte_carlo_weight size_t nfailures = 0; float axis_x[3], axis_y[3], axis_z[3]; float plane_size[2]; - float ray_org[3]; + float ray_org[2][3]; float org[3]; float x[3], y[3]; - float rcp_pdf; + float plane_area; res_T res = RES_OK; - ASSERT(scn && rng && props && wavelengths && accums && basis && pos); - ASSERT(lower && upper); + ASSERT(dev && ctx && basis && pos && lower && upper); f2_sub(plane_size, upper, lower); /* In micron */ - rcp_pdf = plane_size[0] * plane_size[1]; + plane_area = plane_size[0] * plane_size[1]; /* Define the projection axis */ f3_mulf(axis_x, basis + 0, plane_size[0] * 0.5f); @@ -304,58 +425,60 @@ accum_monte_carlo_weight f3_add(org, pos, f3_mulf(org, axis_z, lower[2])); do { + double path_length[2]; + /* Uniformly sample a position onto the projection plane and use it as the - * origin of the ray to trace */ - sample[0] = ssp_rng_uniform_double(rng, -1.0, 1.0); - sample[1] = ssp_rng_uniform_double(rng, -1.0, 1.0); + * origin of the 1st ray to trace */ + sample[0] = ssp_rng_uniform_double(ctx->rng, -1.0, 1.0); + sample[1] = ssp_rng_uniform_double(ctx->rng, -1.0, 1.0); f3_mulf(x, axis_x, (float)sample[0]); f3_mulf(y, axis_y, (float)sample[1]); - f3_add(ray_org, f3_add(ray_org, x, y), org); + f3_add(ray_org[0], f3_add(ray_org[0], x, y), org); - S3D(scene_trace_ray(scn, ray_org, axis_z, range, &hit)); + S3D(scene_trace_ray(ctx->scene, ray_org[0], axis_z, range, &hit)); + /* NULL cross section and differential cross section weight */ + if(S3D_HIT_NONE(&hit)) + break; - if(!S3D_HIT_NONE(&hit)) { - double path_length; - size_t iwlen; - - res = compute_path_length(dev, scn, &hit, ray_org, axis_z, &path_length); - if(res != RES_OK) { /* Handle numerical/geometry issues */ - ++nfailures; - continue; - } - - FOR_EACH(iwlen, 0, nwavelengths) { - double n_r, k_r; - double n_e, k_e, lambda_e; - double w_extinction, w_absorption, w_scattering; - - n_e = props[iwlen].medium_refractive_index; - n_r = props[iwlen].relative_real_refractive_index; - k_r = props[iwlen].relative_imaginary_refractive_index; - - lambda_e = wavelengths[iwlen] / n_e; - k_e = 2.0 * PI / lambda_e; + res = compute_path_length + (dev, ctx->scene, &hit, ray_org[0], axis_z, &path_length[0]); + if(res != RES_OK) { /* Handle numerical/geometry issues */ + ++nfailures; + continue; + } + /* Compute and accumulate the cross section weight */ + accum_cross_section(ctx, plane_area, path_length[0]); - /* Extinction cross section */ - w_extinction = 2.0 * rcp_pdf * - (1.0 - exp(-k_e*k_r*path_length) * cos(k_e*(n_r - 1.0)*path_length)); - accums[iwlen].weights[SSCHIFF_EXTINCTION_CROSS_SECTION] += w_extinction; + /* Avoid the estimation of the phase function */ + if(ctx->estimator->no_phase_function) break; - /* Absorption cross section */ - w_absorption = rcp_pdf * (1.0 - exp(-2.0*k_e*k_r*path_length)); - accums[iwlen].weights[SSCHIFF_ABSORPTION_CROSS_SECTION] += w_absorption; + /* Uniformly sample a position onto the projection plane and use it as the + * origin of the 2nd ray to trace */ + sample[0] = ssp_rng_uniform_double(ctx->rng, -1.0, 1.0); + sample[1] = ssp_rng_uniform_double(ctx->rng, -1.0, 1.0); + f3_mulf(x, axis_x, (float)sample[0]); + f3_mulf(y, axis_y, (float)sample[1]); + f3_add(ray_org[1], f3_add(ray_org[1], x, y), org); - /* Scattering cross section */ - w_scattering = w_extinction - w_absorption; - accums[iwlen].weights[SSCHIFF_SCATTERING_CROSS_SECTION] += w_scattering; + S3D(scene_trace_ray(ctx->scene, ray_org[1], axis_z, range, &hit)); + if(S3D_HIT_NONE(&hit)) /* NULL differential cross section weight */ + break; - /* Average projected area */ - accums[iwlen].weights[SSCHIFF_AVERAGE_PROJECTED_AREA] += rcp_pdf; - } + res = compute_path_length + (dev, ctx->scene, &hit, ray_org[1], axis_z, &path_length[1]); + if(res != RES_OK) { /* Handle numerical/geometry issues */ + ++nfailures; + continue; } + /* Compute and accumulate the per scattering angle differential cross + * section weight */ + accum_differential_cross_section(ctx, plane_area, path_length, ray_org); + } while(res != RES_OK && nfailures < MAX_FAILURES); - if(res != RES_OK) { + if(nfailures < MAX_FAILURES) { + res = RES_OK; + } else { log_error(dev, "Too many failures in computing the radiative path length. The sampled geometry\n" "might not defined a closed volume.\n"); @@ -366,15 +489,9 @@ accum_monte_carlo_weight static res_T radiative_properties (struct sschiff_device* dev, - struct ssp_rng* rng, const int istep, - const double* wavelengths, /* Sorted in ascending order */ - const size_t nwavelengths, const size_t ndirs, - struct s3d_scene* scene, - const struct sschiff_material_properties* props, - struct mc_accum* mc_accums, - struct accum* accums) + struct integrator_context* ctx) { float lower[3], upper[3]; float aabb_pt[8][3]; @@ -383,11 +500,10 @@ radiative_properties size_t iwlen; int i; res_T res = RES_OK; - ASSERT(dev && rng && wavelengths && nwavelengths && ndirs && props); - ASSERT(mc_accums && accums); + ASSERT(dev && ndirs && ctx); (void)istep; - S3D(scene_get_aabb(scene, lower, upper)); + S3D(scene_get_aabb(ctx->scene, lower, upper)); /* AABB vertex layout * 6-------7 @@ -407,14 +523,30 @@ radiative_properties f3_mulf(centroid, f3_add(centroid, lower, upper), 0.5f); - memset(accums, 0, sizeof(struct accum)*nwavelengths); + /* Clear direction accumulators */ + FOR_EACH(iwlen, 0, ctx->nwavelengths) { + ctx->accums[iwlen].extinction_cross_section = 0; + ctx->accums[iwlen].absorption_cross_section = 0; + ctx->accums[iwlen].scattering_cross_section = 0; + ctx->accums[iwlen].avg_projected_area = 0; + + /* Do not clean up accumulators of invalid differential cross section */ + if(ctx->estimator->limit_angles[iwlen] == INVALID_LIMIT_ANGLE) continue; + + /* Clean up to "limit_angle" since great angles are analytically computed */ + memset(ctx->accums[iwlen].differential_cross_section, 0, + sizeof(double)*ctx->estimator->limit_angles[iwlen]); + memset(ctx->accums[iwlen].differential_cross_section_cumulative, 0, + sizeof(double)*ctx->estimator->limit_angles[iwlen]); + } + FOR_EACH(idir, 0, ndirs) { float dir[4]; float basis[9]; float transform[12]; float pt[8][3]; - ssp_ran_sphere_uniform(rng, dir); + ssp_ran_sphere_uniform(ctx->rng, dir); /* Build the transformation matrix from world to footprint space. Use the * AABB centroid as the origin of the footprint space. */ @@ -433,52 +565,630 @@ radiative_properties f3_max(upper, upper, pt[i]); } - res = accum_monte_carlo_weight(dev, scene, rng, props, wavelengths, - nwavelengths, basis, centroid, lower, upper, accums); + res = accum_monte_carlo_weight(dev, ctx, basis, centroid, lower, upper); if(res != RES_OK) goto error; + } + /* Compute the Monte Carlo weight of the temporary accumulator */ + FOR_EACH(iwlen, 0, ctx->nwavelengths) { + size_t iangle; + + #define MC_ACCUM(Data) { \ + const double w = ctx->accums[iwlen].Data / (double)ndirs; \ + ctx->mc_accums[iwlen].Data.weight += w; \ + ctx->mc_accums[iwlen].Data.sqr_weight += w*w; \ + } (void)0 + + MC_ACCUM(extinction_cross_section); + MC_ACCUM(absorption_cross_section); + MC_ACCUM(scattering_cross_section); + MC_ACCUM(avg_projected_area); + + if(ctx->estimator->limit_angles[iwlen] == INVALID_LIMIT_ANGLE) + continue; -#if 0 - { - /* Compute an image of the shape transformed in the footprint space */ - char thumb_name[64]; - sprintf(thumb_name, "%d_%lu.ppm", istep, idir); - draw_thumbnail(scene, basis, centroid, lower, upper, thumb_name); + /* Accum up to "limit angle" since great angles are analitically computed */ + FOR_EACH(iangle, 0, ctx->estimator->limit_angles[iwlen]) { + MC_ACCUM(differential_cross_section[iangle]); + MC_ACCUM(differential_cross_section_cumulative[iangle]); } -#endif + + #undef MC_ACCUM } - FOR_EACH(iwlen, 0, nwavelengths) { - int iweight; - FOR_EACH(iweight, 0, SSCHIFF_DATA_COUNT__) { - const double w = accums[iwlen].weights[iweight] / (double)ndirs; - mc_accums[iwlen].mc_data[iweight].weight += w; - mc_accums[iwlen].mc_data[iweight].sqr_weight += w * w; +exit: + return res; +error: + FOR_EACH(iwlen, 0, ctx->nwavelengths) { + ctx->mc_accums[iwlen].extinction_cross_section = MC_DATA_NULL; + ctx->mc_accums[iwlen].absorption_cross_section = MC_DATA_NULL; + ctx->mc_accums[iwlen].scattering_cross_section = MC_DATA_NULL; + ctx->mc_accums[iwlen].avg_projected_area = MC_DATA_NULL; + + if(ctx->estimator->limit_angles[iwlen] == INVALID_LIMIT_ANGLE) + continue; + + memset(ctx->mc_accums[iwlen].differential_cross_section, 0, + sizeof(double)*ctx->estimator->limit_angles[iwlen]); + memset(ctx->mc_accums[iwlen].differential_cross_section_cumulative, 0, + sizeof(double)*ctx->estimator->limit_angles[iwlen]); + } + goto exit; +} + +struct function_arg { + double scattering_cross_section; + double angle; + double differential_cross_section; + double differential_cross_section_cumulative; + + /* Precomputed values */ + double cos_2_angle; + double cos_angle; + double cos_half_angle; + double sin_half_angle; + double sqr_cos_angle; + double sqr_sin_half_angle; +}; + +static int +function_fdf(const gsl_vector* vec, void* params, gsl_vector* res, gsl_matrix* J) +{ + struct function_arg* arg = params; + const double n = gsl_vector_get(vec, 0); + double u, u_prime; + double v, v_prime; + double coef; + double f, df; + + if(n==2 || n==4 || n==6) + return GSL_EDOM; + + coef = (4*PI * arg->differential_cross_section) / (1+arg->sqr_cos_angle); + + u = ( arg->sqr_sin_half_angle + * ( (n*n - 6*n + 8) * arg->cos_2_angle + + 3*n*n + - 8*(n - 2) * arg->cos_angle + - 26*n + 72 ) + - pow(arg->sin_half_angle, n) * (4*n*n - 24*n + 64) ); + v = ((n - 2) * (n - 4) * (n - 6)); + + u_prime = arg->sqr_sin_half_angle + * ((2*n - 6) * arg->cos_2_angle + 6*n - 8*arg->cos_angle - 26) + - pow(arg->sin_half_angle, n) + * (log(arg->sin_half_angle) * (4*n*n - 24*n + 64) + 8*n-24); + v_prime = (n-4)*(n-6) + (n-2)*(n-6) + (n-2)*(n-4); + + f = arg->differential_cross_section_cumulative + - arg->scattering_cross_section + + coef * u / v; + df = (v*u_prime - u*v_prime) / (v*v); + df = df * coef; + + gsl_vector_set(res, 0, f); + gsl_matrix_set(J, 0, 0, df); + return GSL_SUCCESS; +} + +/* Solve the parameters used to connect the Monte-Carlo estimation of the + * [cumulative] differential cross sections for small angles with their + * analytical estimation for wide angles */ +static res_T +solve_wide_angles_phase_function_model_parameters + (struct sschiff_device* dev, + struct solver_context* ctx, + const double angle, + const double sin_half_angle, + const double cos_angle, + const double cos_2_angle, + const double scattering_cross_section, + const double differential_cross_section, + const double differential_cross_section_cumulative, + double* n, + double* r) +{ + gsl_multiroot_function_fdf func; + gsl_vector* root = NULL; + struct function_arg arg; + int status; + int iter; + const int max_iter = 1000; /* Maximum number of Newton iterations */ + res_T res = RES_OK; + ASSERT(dev && n && r); + ASSERT(eq_eps(sin(angle*0.5), sin_half_angle, 1.e-6)); + ASSERT(eq_eps(cos(angle), cos_angle, 1.e-6)); + ASSERT(eq_eps(cos(2.0*angle), cos_2_angle, 1.e-6)); + + /* Fill system arguments */ + arg.angle = angle; + arg.scattering_cross_section = scattering_cross_section; + arg.differential_cross_section = differential_cross_section; + arg.differential_cross_section_cumulative = differential_cross_section_cumulative; + + /* Precompute some values to speed up Newton iterations */ + arg.cos_2_angle = cos_2_angle; + arg.cos_angle = cos_angle; + arg.cos_half_angle = cos(angle * 0.5); + arg.sin_half_angle = sin_half_angle; + arg.sqr_cos_angle = arg.cos_angle * arg.cos_angle; + arg.sqr_sin_half_angle = arg.sin_half_angle * arg.sin_half_angle; + + /* Setup system functions */ + func.f = NULL; + func.df = NULL; + func.fdf = function_fdf; /* Compute the function *and* its derivative */ + func.n = 1; /* Number of equations */ + func.params = &arg; /* System parameters */ + + /* Initialise the solver. TODO perform this in an initialisation step of a + * phase_function context */ + gsl_multiroot_fdfsolver_set(ctx->solver, &func, ctx->init_val); + gsl_set_error_handler_off(); + + /* Launch the Newton estimation. Iterate up to `max_iter'or until the + * estimation is "good enough". */ + iter = 0; + do { + status = gsl_multiroot_fdfsolver_iterate(ctx->solver); + if(status == GSL_SUCCESS) { + status = gsl_multiroot_test_residual(ctx->solver->f, 1.e-6); } + } while(status == GSL_CONTINUE && ++iter < max_iter); + + /* Retrieve the estimated "n" value */ + root = gsl_multiroot_fdfsolver_root(ctx->solver); + *n = gsl_vector_get(root, 0); + + if(status != GSL_SUCCESS) { + log_error(dev, +"Cannot estimate the parameters of the wide scattering phase function model.\n" +"GSL error: %s - %d.\n", + gsl_strerror(status), iter); + res = RES_BAD_OP; + goto error; } + + if(*n < 0) { + log_error(dev, +"The estimated parameter `n' of the wide scattering angles phase function\n" +"model cannot be negative.\n" +"n = %g\n", *n); + res = RES_BAD_OP; + goto error; + } + + /* Compute r from the estimated n */ + *r = 2 * arg.differential_cross_section * pow(arg.sin_half_angle, *n) + / (1 + arg.sqr_cos_angle); + exit: return res; error: - memset(mc_accums, 0, sizeof(struct mc_accum)*nwavelengths); goto exit; } -static void -get_mc_value - (const struct mc_data* data, - const size_t nrealisations, - struct sschiff_estimator_value* value) +/* Helper function used to compute one term of the analytic evaluation of the + * cumulative differential cross section */ +static FINLINE double +compute_differential_cross_section_cumulative_term + (const double sin_half_angle, + const double cos_angle, + const double cos_2_angle, + const double n) { - ASSERT(data && value); - value->E = data->weight / (double)nrealisations; - value->V = data->sqr_weight / (double)nrealisations - - (data->weight * data->weight) / (double)(nrealisations * nrealisations); - value->SE = sqrt(value->V / (double)nrealisations); + return + -pow(sin_half_angle, 2-n) + * ((n*n - 6*n + 8)*cos_2_angle + 3*n*n - 8*(n-2)*cos_angle - 26*n + 72) + / ((n-2)*(n-4)*(n-6)); +} + +static res_T +compute_phase_function + (struct sschiff_device* dev, + struct solver_context* ctx, + const size_t iwlen, + const size_t nangles, + struct sschiff_estimator* estimator) +{ + double limit_angle; + double sin_half_limit_angle; + double cos_limit_angle; + double cos_2_limit_angle; + double coef_limit; + double n, r; /* Connector values */ + double rcp_scattering_cross_section; + double rcp_sqr_scattering_cross_section; + struct sschiff_state scattering_cross_section; + struct sschiff_state limit_differential_cross_section; + struct sschiff_state limit_differential_cross_section_cumulative; + size_t ilimit_angle; /* Index of the limit angle of the current wavelength */ + size_t iangle; + res_T res = RES_OK; + ASSERT(dev && estimator && iwlen < sa_size(estimator->wavelengths) && ctx); + + /* Fetch the limit angle and precompute some values */ + ilimit_angle = estimator->limit_angles[iwlen]-1; + limit_angle = estimator->angles[ilimit_angle]; + sin_half_limit_angle = sin(0.5*limit_angle); + cos_limit_angle = cos(limit_angle); + cos_2_limit_angle = cos(2.0*limit_angle); + + get_mc_value + (&estimator->accums[iwlen].scattering_cross_section, + estimator->nrealisations, + &scattering_cross_section); + get_mc_value + (&estimator->accums[iwlen].differential_cross_section[ilimit_angle], + estimator->nrealisations, + &limit_differential_cross_section); + get_mc_value + (&estimator->accums[iwlen].differential_cross_section_cumulative[ilimit_angle], + estimator->nrealisations, + &limit_differential_cross_section_cumulative); + + /* Find the connector values between small and wide angles */ + res = solve_wide_angles_phase_function_model_parameters + (dev, + ctx, + limit_angle, + sin_half_limit_angle, + cos_limit_angle, + cos_2_limit_angle, + scattering_cross_section.E, + limit_differential_cross_section.E, + limit_differential_cross_section_cumulative.E, + &n, &r); + if(res != RES_OK) { + log_error(estimator->dev, +"Couldn't estimate the parameters of the phase function for wide scattering\n" +"angles. The phase function is thus not computed.\n" +"Wavelength = %g micron\n", + estimator->wavelengths[iwlen]); + + goto error; + } + + if(n < 2 || n > 4) { + log_warning(estimator->dev, +"The wide scattering angles phase function model parameter `n' is not in\n" +"[2, 4]. One might increase the number of realisations.\n" +" wavelength = %g micron\n" +" n = %g\n" +" scattering cross section = %g +/- %g\n" +" differential cross section = %g +/- %g\n" +" differential cross section cumulative = %g +/- %g\n", + estimator->wavelengths[iwlen], + n, + scattering_cross_section.E, + scattering_cross_section.SE, + limit_differential_cross_section.E, + limit_differential_cross_section.SE, + limit_differential_cross_section_cumulative.E, + limit_differential_cross_section_cumulative.SE); + } + + /* Save the `n' wide angle parameter */ + estimator->wide_angles_parameter[iwlen] = n; + + /* Precomputed vlaue */ + coef_limit = compute_differential_cross_section_cumulative_term + (sin_half_limit_angle, cos_limit_angle, cos_2_limit_angle, n); + + /* Fill the [cumulative] differential cross sections of wide angles with the + * analytic model */ + FOR_EACH(iangle, ilimit_angle+1, nangles) { + struct mc_accum* accum = estimator->accums + iwlen; + double angle, sin_half_angle, cos_angle, cos_2_angle; + double coef; + + /* Precompute some values */ + angle = estimator->angles[iangle]; + cos_angle = cos(angle); + cos_2_angle = cos(2.0*angle); + sin_half_angle = sin(angle*0.5); + + /* Analytically compute the differential cross section */ + accum->differential_cross_section[iangle].sqr_weight = -1.f; + accum->differential_cross_section[iangle].weight = + r * (1+cos_angle*cos_angle) / (2.0*pow(sin_half_angle, n)); + + /* Analytically compute the differential cross section cumulative */ + coef = compute_differential_cross_section_cumulative_term + (sin_half_angle, cos_angle, cos_2_angle, n); + accum->differential_cross_section_cumulative[iangle].sqr_weight = -1.f; + accum->differential_cross_section_cumulative[iangle].weight = + limit_differential_cross_section_cumulative.E + 2*PI*r*(coef-coef_limit); + } + + /* Check the post condition of the cumulative differential cross section */ + /*ASSERT(eq_eps + (estimator->accums[iwlen].differential_cross_section_cumulative[nangles-1].weight, + scattering_cross_section.E, 1.e-3));*/ + + /* Compute the [cumulative] phase function for small angles */ + rcp_scattering_cross_section = 1.0/scattering_cross_section.E; + rcp_sqr_scattering_cross_section = + rcp_scattering_cross_section * rcp_scattering_cross_section; + FOR_EACH(iangle, 0, ilimit_angle+1) { + struct mc_data mc_data; + + mc_data = estimator->accums[iwlen].differential_cross_section[iangle]; + mc_data.weight *= rcp_scattering_cross_section; + mc_data.sqr_weight *= rcp_sqr_scattering_cross_section; + get_mc_value(&mc_data, estimator->nrealisations, + &estimator->phase_functions[iwlen].values[iangle]); + + mc_data = estimator->accums[iwlen].differential_cross_section_cumulative[iangle]; + mc_data.weight *= rcp_scattering_cross_section; + mc_data.sqr_weight *= rcp_sqr_scattering_cross_section; + get_mc_value(&mc_data, estimator->nrealisations, + &estimator->phase_functions[iwlen].cumulative[iangle]); + } + /* Compute the [cumulative] phase function for wide angles */ + FOR_EACH(iangle, ilimit_angle + 1, nangles) { + estimator->phase_functions[iwlen].values[iangle].E = + estimator->accums[iwlen].differential_cross_section[iangle].weight + * rcp_scattering_cross_section; + + estimator->phase_functions[iwlen].cumulative[iangle].E = + estimator->accums[iwlen].differential_cross_section_cumulative[iangle].weight + * rcp_scattering_cross_section; + + /* The phase function for wide angles is analitically computed, i.e. there + * is no variance or standard error */ + estimator->phase_functions[iwlen].values[iangle].V = 0; + estimator->phase_functions[iwlen].values[iangle].SE = 0; + estimator->phase_functions[iwlen].cumulative[iangle].V = 0; + estimator->phase_functions[iwlen].cumulative[iangle].SE = 0; + } + +exit: + return res; +error: + FOR_EACH(iangle, 0, nangles) { + estimator->phase_functions[iwlen].values[iangle].E = -1; + estimator->phase_functions[iwlen].values[iangle].V = -1; + estimator->phase_functions[iwlen].values[iangle].SE = -1; + estimator->phase_functions[iwlen].cumulative[iangle].E = -1; + estimator->phase_functions[iwlen].cumulative[iangle].V = -1; + estimator->phase_functions[iwlen].cumulative[iangle].SE = -1; + } + goto exit; +} + + +static res_T +inverse_cumulative_phase_function + (const struct sschiff_estimator* estimator, + const double* cumulative_small_angles, + const size_t iwlen, + const double cumulative, + double* theta) +{ + double u, lower, upper; + size_t iangle, nsmall_angles; + ASSERT(estimator && cumulative_small_angles && theta); + ASSERT(cumulative >= 0.0 && cumulative <= 1.0); + ASSERT(iwlen < sa_size(estimator->phase_functions)); + + nsmall_angles = estimator->limit_angles[iwlen]; + if(cumulative < cumulative_small_angles[nsmall_angles-1]) { + /* Look for the cumulative in the filtered small angles array */ + double* found = search_lower_bound(&cumulative, cumulative_small_angles, + nsmall_angles, sizeof(double), cmp_double); + if(!found) { + log_error(estimator->dev, + "Error in inverting the phase function cumulative for small angles.\n"); + return RES_BAD_OP; + } + iangle = (size_t)(found - cumulative_small_angles); + upper = cumulative_small_angles[iangle]; + lower = cumulative_small_angles[iangle-1]; + } else { + /* Look for the cumulative in the wide angles cumulative */ + struct sschiff_state cumul; + struct sschiff_state* found = NULL; + size_t nangles; + cumul.E = cumulative; + + nangles = sa_size(estimator->angles); + found = search_lower_bound + (&cumul, + estimator->phase_functions[iwlen].cumulative + nsmall_angles, + nangles - nsmall_angles, + sizeof(struct sschiff_state), cmp_schiff_state); + if(!found) { + log_error(estimator->dev, + "Error in inverting the phase function cumulative for wide angles.\n"); + return RES_BAD_OP; + } + iangle = (size_t)(found - estimator->phase_functions[iwlen].cumulative); + ASSERT(iangle >= nsmall_angles); + upper = estimator->phase_functions[iwlen].cumulative[iangle].E; + if(iangle == nsmall_angles) { + lower = cumulative_small_angles[nsmall_angles-1]; + } else { + lower = estimator->phase_functions[iwlen].cumulative[iangle-1].E; + } + } + + /* Use the cumulative bounds to linearly interpolate the angles */ + u = (cumulative - lower) / (upper - lower); + *theta = u*estimator->angles[iangle] + (1.0 - u)*estimator->angles[iangle-1]; + + return RES_OK; } static char check_distribution(struct sschiff_geometry_distribution* distrib) { ASSERT(distrib); - return distrib->sample != NULL; + return distrib->sample != NULL && distrib->characteristic_length > 0; +} + +static void +integrator_context_release(struct integrator_context* ctx) +{ + size_t iwlen; + ASSERT(ctx); + + if(ctx->rng) SSP(rng_ref_put(ctx->rng)); + if(ctx->estimator) SSCHIFF(estimator_ref_put(ctx->estimator)); + if(ctx->shape) S3D(shape_ref_put(ctx->shape)); + if(ctx->scene) S3D(scene_ref_put(ctx->scene)); + + #define RELEASE(Data) if(Data) sa_release(Data) + if(ctx->accums) { + FOR_EACH(iwlen, 0, ctx->nwavelengths) { + RELEASE(ctx->accums[iwlen].differential_cross_section); + RELEASE(ctx->accums[iwlen].differential_cross_section_cumulative); + } + sa_release(ctx->accums); + } + if(ctx->mc_accums) { + FOR_EACH(iwlen, 0, ctx->nwavelengths) { + RELEASE(ctx->mc_accums[iwlen].differential_cross_section); + RELEASE(ctx->mc_accums[iwlen].differential_cross_section_cumulative); + } + sa_release(ctx->mc_accums); + } + #undef RELEASE +} + +static res_T +integrator_context_init + (struct integrator_context* ctx, + struct s3d_device* s3d, + struct ssp_rng* rng, + struct sschiff_estimator* estimator, + const size_t nwavelengths, + const size_t nangles) +{ + size_t iwlen; + res_T res = RES_OK; + ASSERT(ctx && s3d && rng && nwavelengths && nangles >= 3); + + memset(ctx, 0, sizeof(struct integrator_context)); + + if(RES_OK!=(res = s3d_shape_create_mesh(s3d, &ctx->shape))) goto error; + if(RES_OK!=(res = s3d_scene_create(s3d, &ctx->scene))) goto error; + if(RES_OK!=(res = s3d_scene_attach_shape(ctx->scene, ctx->shape))) goto error; + + #define RESIZE(Data, N) { \ + if(!sa_add((Data), (N))) { \ + res = RES_MEM_ERR; \ + goto error; \ + } \ + memset((Data), 0, sizeof((Data)[0])*(N)); \ + } (void)0 + RESIZE(ctx->accums, nwavelengths); + FOR_EACH(iwlen, 0, nwavelengths) { + /* Do not allocate the accumulators if no limit angle was found */ + if(estimator->limit_angles[iwlen] == INVALID_LIMIT_ANGLE) continue; + RESIZE(ctx->accums[iwlen].differential_cross_section, nangles); + RESIZE(ctx->accums[iwlen].differential_cross_section_cumulative, nangles); + } + + RESIZE(ctx->mc_accums, nwavelengths); + FOR_EACH(iwlen, 0, nwavelengths) { + /* Do not allocate the accumulators if no limit angle was found */ + if(estimator->limit_angles[iwlen] == INVALID_LIMIT_ANGLE) continue; + RESIZE(ctx->mc_accums[iwlen].differential_cross_section, nangles); + RESIZE(ctx->mc_accums[iwlen].differential_cross_section_cumulative, nangles); + } + #undef RESIZE + + SSP(rng_ref_get(rng)); + ctx->rng = rng; + SSCHIFF(estimator_ref_get(estimator)); + ctx->estimator = estimator; + ctx->nwavelengths = nwavelengths; + ctx->nangles = nangles; + +exit: + return res; +error: + integrator_context_release(ctx); + goto exit; +} + +static void +solver_context_release(struct solver_context* ctx) +{ + ASSERT(ctx); + if(ctx->solver) gsl_multiroot_fdfsolver_free(ctx->solver); + if(ctx->init_val) gsl_vector_free(ctx->init_val); +} + +static res_T +solver_context_init(struct sschiff_device* dev, struct solver_context* ctx) +{ + res_T res = RES_OK; + ASSERT(ctx); + memset(ctx, 0, sizeof(*ctx)); + + /* Create a Newton-Raphson nonlinear solver with derivatives */ + ctx->solver = gsl_multiroot_fdfsolver_alloc(gsl_multiroot_fdfsolver_newton, 1); + if(!ctx->solver) { + log_error(dev, + "Not enough memory. Couldn't allocate the GSL Newton solver.\n"); + res = RES_MEM_ERR; + goto error; + } + + /* Allocate the initial value vector */ + ctx->init_val = gsl_vector_alloc(1); + if(!ctx->init_val) { + log_error(dev, + "Not enough memory. Couldn't allocate the GSL init vector.\n"); + res = RES_MEM_ERR; + goto error; + } + gsl_vector_set(ctx->init_val, 0, 3); + +exit: + return res; +error: + solver_context_release(ctx); + goto exit; +} + +static res_T +begin_realisation + (struct sschiff_device* dev, + struct sschiff_geometry_distribution* distrib, + struct integrator_context* ctx) +{ + res_T res = RES_OK; + ASSERT(dev && distrib && ctx); + + /* Sample a particle */ + res = distrib->sample(ctx->rng, ctx->shape, distrib->context); + if(res != RES_OK) { + log_error(dev, "Error in sampling a particle.\n"); + goto error; + } + + /* Build the Star-3D representation of the sampled shape */ + S3D(scene_begin_session(ctx->scene, S3D_TRACE)); + +exit: + return res; +error: + { + /* Disable active session if necessary */ + int mask; + if(S3D(scene_get_session_mask(ctx->scene, &mask)), mask) { + S3D(scene_end_session(ctx->scene)); + } + } + goto exit; +} + +static FINLINE void +end_realisation(struct integrator_context* ctx) +{ + ASSERT(ctx); + S3D(scene_end_session(ctx->scene)); } static void @@ -486,11 +1196,37 @@ estimator_release(ref_T* ref) { struct sschiff_estimator* estimator; struct sschiff_device* dev; + size_t nwavelengths; + size_t i; ASSERT(ref); + estimator = CONTAINER_OF(ref, struct sschiff_estimator, ref); dev = estimator->dev; - if(estimator->wavelengths) sa_release(estimator->wavelengths); - if(estimator->accums) sa_release(estimator->accums); + nwavelengths = sa_size(estimator->accums); + + #define RELEASE(Data) if(Data) sa_release(Data) + RELEASE(estimator->wavelengths); + RELEASE(estimator->angles); + RELEASE(estimator->limit_angles); + RELEASE(estimator->wide_angles_parameter); + RELEASE(estimator->wavenumbers); + RELEASE(estimator->properties); + if(estimator->accums) { + FOR_EACH(i, 0, nwavelengths) { + RELEASE(estimator->accums[i].differential_cross_section); + RELEASE(estimator->accums[i].differential_cross_section_cumulative); + } + sa_release(estimator->accums); + } + if(estimator->phase_functions) { + FOR_EACH(i, 0, nwavelengths) { + RELEASE(estimator->phase_functions[i].values); + RELEASE(estimator->phase_functions[i].cumulative); + } + sa_release(estimator->phase_functions); + } + #undef RELEASE + MEM_RM(dev->allocator, estimator); SSCHIFF(device_ref_put(dev)); } @@ -498,17 +1234,25 @@ estimator_release(ref_T* ref) static res_T estimator_create (struct sschiff_device* dev, + struct sschiff_geometry_distribution* distrib, + const double* wavelengths, const size_t nwavelengths, + sschiff_scattering_angles_distribution_T angles_distrib, + const size_t nangles, struct sschiff_estimator** out_estimator) { struct sschiff_estimator* estimator = NULL; + double rcp_PI_Lc; + size_t i; + int hold_valid_limit_angle = 0; res_T res = RES_OK; - ASSERT(dev && out_estimator); + ASSERT(dev && distrib && wavelengths && nwavelengths); + ASSERT(angles_distrib && nangles && out_estimator); estimator = MEM_CALLOC(dev->allocator, 1, sizeof(struct sschiff_estimator)); if(!estimator) { log_error - (dev, "Not enough memory: couldn't allocate the Star-Schiff estimator.\n"); + (dev, "Couldn't allocate the Star-Schiff estimator.\n"); res = RES_MEM_ERR; goto error; } @@ -516,18 +1260,144 @@ estimator_create SSCHIFF(device_ref_get(dev)); estimator->dev = dev; - if(!sa_add(estimator->wavelengths, nwavelengths)) { - log_error(dev, - "Not enough memory: couldn't allocate the list of estimated wavelengths.\n"); - res = RES_MEM_ERR; - goto error; + #define RESIZE(Array, Count, ErrMsg) { \ + if(!sa_add(Array, Count)) { \ + log_error(dev, ErrMsg); \ + res = RES_MEM_ERR; \ + goto error; \ + } \ + memset(Array, 0, sizeof(Array[0])*Count); \ + } (void)0 + + /* Check the wavelengths */ + FOR_EACH(i, 1, nwavelengths) { + if(wavelengths[i] <= wavelengths[i-1]) { + log_error(dev, + "The submitted wavelengths are not sorted in ascending order.\n"); + res = RES_BAD_ARG; + goto error; + } } - if(!sa_add(estimator->accums, nwavelengths)) { - log_error(dev, - "Not enough memory: couldn't allocate the Monte Carlo accumulator.\n"); - res = RES_MEM_ERR; + /* Copy the wavelengths */ + RESIZE(estimator->wavelengths, nwavelengths, + "Couldn't allocate the list of estimated wavelengths.\n"); + memcpy(estimator->wavelengths, wavelengths, nwavelengths*sizeof(double)); + + /* Generate the scattering angles */ + RESIZE(estimator->angles, nangles, + "Couldn't allocate the list of scattering angles.\n"); + angles_distrib(estimator->angles, nangles); + if(estimator->angles[0] != 0.f + || !eq_eps(estimator->angles[nangles-1], PI, 1.e-6)) { + log_error(dev, "Invalid scattering angle distribution.\n"); + log_error(dev, "The first and last angles must be 0 and PI, respectively.\n"); + res = RES_BAD_ARG; goto error; } + FOR_EACH(i, 1, nangles) { + if(estimator->angles[i] <= estimator->angles[i-1]) { + log_error(dev, "Invalid scattering angle distribution.\n"); + log_error(dev, "Angles must be sorted in ascending order in [0, PI]\n"); + res = RES_BAD_ARG; + goto error; + } + } + + /* Allocate miscellaneous array of temporary/precomputed data */ + RESIZE(estimator->limit_angles, nwavelengths, + "Couldn't allocate the per wavelength indices of the limit scattering angle.\n"); + RESIZE(estimator->wide_angles_parameter, nwavelengths, + "Couldn't allocate the per wavelength `n' parameter of the wide scattering\n" + "angles model.\n"); + RESIZE(estimator->wavenumbers, nwavelengths, + "Couldn't allocate the list of wavenumbers.\n"); + RESIZE(estimator->properties, nwavelengths, + "Couldn't allocate the per wavelength optical properties.\n"); + + rcp_PI_Lc = 1.0 / (PI*distrib->characteristic_length); + FOR_EACH(i, 0, nwavelengths) { + double lambda_e, theta_l; + double* angle; + + /* Fetch the particle optical properties */ + distrib->material.get_property + (distrib->material.material, + estimator->wavelengths[i], + &estimator->properties[i]); + + /* Precompute the wavenumbers */ + lambda_e = + estimator->wavelengths[i] + / estimator->properties[i].medium_refractive_index; + estimator->wavenumbers[i] = 2.0*PI/lambda_e; + + /* Search for limit scattering angle */ + theta_l = sqrt(lambda_e * rcp_PI_Lc); + if(theta_l <= 0 || theta_l >= PI) { + log_warning(dev, +"Invalid theta limit, i.e. angle between small and wide scattering angles\n" +"`%g'. The phase function for the wavelengths `%g' and its [inverse]\n" +"cumulative will be not computed.\n", + theta_l, estimator->wavelengths[i]); + estimator->limit_angles[i] = INVALID_LIMIT_ANGLE; + } else { + angle = search_lower_bound(&theta_l, estimator->angles, nangles, + sizeof(double), cmp_double); + if(!angle) { + log_error(dev, +"Can't find a limit scattering angle for theta limit `%g'.\n", theta_l); + res = RES_BAD_ARG; + goto error; + } + if(eq_eps(*angle, PI, 1.e-6)) { + log_error(dev, "Invalid limit scattering angle `%g'.\n", *angle); + res = RES_BAD_ARG; + goto error; + } + /* Define the index of the first "wide scattering angle" */ + estimator->limit_angles[i] = (size_t)(angle - estimator->angles); + ASSERT(estimator->limit_angles[i] < nangles); + hold_valid_limit_angle = 1; + } + } + estimator->no_phase_function = !hold_valid_limit_angle; + if(estimator->no_phase_function) { + /* No phase function => scattering angles and wide angle parameter are + * useless */ + sa_release(estimator->angles); + sa_release(estimator->wide_angles_parameter); + estimator->angles = NULL; + estimator->wide_angles_parameter = NULL; + } + + /* Allocate the estimator accumulators */ + RESIZE(estimator->accums, nwavelengths, + "Couldn't allocate the Monte Carlo accumulator of the estimator.\n"); + if(!estimator->no_phase_function) { + FOR_EACH(i, 0, nwavelengths) { + /* Do not allocate the MC accumulator if no limit angle was found */ + if(estimator->limit_angles[i] == INVALID_LIMIT_ANGLE) continue; + RESIZE(estimator->accums[i].differential_cross_section, nangles, + "Couldn't allocate the differential cross sections to estimate.\n"); + RESIZE(estimator->accums[i].differential_cross_section_cumulative, nangles, + "Couldn't allocate the cumulative differential cross sections to estimate.\n"); + } + } + + if(!estimator->no_phase_function) { + /* Allocate the phase function data */ + RESIZE(estimator->phase_functions, nwavelengths, + "Couldn't allocate the per wavelength phase functions data.\n"); + FOR_EACH(i, 0, nwavelengths) { + /* Do not allocate the phase functions data if no limit angle was found */ + if(estimator->limit_angles[i] == INVALID_LIMIT_ANGLE) continue; + RESIZE(estimator->phase_functions[i].values, nangles, + "Couldn't allocate the per angle phase function values.\n"); + RESIZE(estimator->phase_functions[i].cumulative, nangles, + "Couldn't allocate the per angle cumulative phase function.\n"); + } + } + #undef RESIZE exit: *out_estimator = estimator; @@ -550,212 +1420,161 @@ sschiff_integrate struct sschiff_geometry_distribution* distrib, const double* wavelengths, const size_t nwavelengths, + const sschiff_scattering_angles_distribution_T angles_distrib, const size_t nangles, const size_t ngeoms, const size_t ndirs, struct sschiff_estimator** out_estimator) { - struct sschiff_material_properties** mtls = NULL; - struct accum** accums = NULL; - struct mc_accum** mc_accums = NULL; + struct integrator_context* ctxs = NULL; + struct solver_context* solver_ctxs = NULL; struct sschiff_estimator* estimator = NULL; - struct s3d_shape** shapes = NULL; - struct s3d_scene** scenes = NULL; struct ssp_rng** rngs = NULL; struct ssp_rng_proxy* rng_proxy = NULL; size_t i; + int iwlen; int igeom; ATOMIC res = (ATOMIC)RES_OK; - (void)nangles; - if(!dev || !rng || !distrib || !wavelengths || !nwavelengths || !nangles - || !ngeoms || !ndirs || !out_estimator || !check_distribution(distrib)) { + if(!dev || !rng || !distrib || !wavelengths || !nwavelengths + || !angles_distrib || nangles < 3 || !ngeoms || !ndirs || !out_estimator + || !check_distribution(distrib)) { return RES_BAD_ARG; } - res = estimator_create(dev, nwavelengths, &estimator); + /* Create the Schiff estimator */ + res = estimator_create(dev, distrib, wavelengths, nwavelengths, + angles_distrib, nangles, &estimator); if(res != RES_OK) goto error; estimator->nrealisations = ngeoms; + /* Create a RNG proxy from the submitted RNG state */ res = ssp_rng_proxy_create_from_rng (dev->allocator, rng, dev->nthreads, &rng_proxy); if(res != RES_OK) { log_error(dev, "Couldn't create the proxy allocator\n"); goto error; } - /* Create the containers of per thread data structures */ - if(!sa_add(mtls, dev->nthreads)) { - log_error(dev, - "No enough memory: couldn't allocate the list of optical properties.\n"); - res = RES_MEM_ERR; - goto error; - } - if(!sa_add(accums, dev->nthreads)) { - log_error(dev, - "No enough memory: couldn't allocate the list of temporary accumulators.\n"); + + /* Create per thread data structures */ + if(!sa_add(ctxs, dev->nthreads)) { + log_error(dev, "Couldn't allocate the integrator contexts.\n"); res = RES_MEM_ERR; goto error; } - if(!sa_add(mc_accums, dev->nthreads)) { - log_error(dev, - "Not enough memory: couldn't allocate the list Monte Carlo accumulators.\n"); + if(!sa_add(solver_ctxs, dev->nthreads)) { + log_error(dev, "Couldn'nt allocate the solver contexts.\n"); res = RES_MEM_ERR; goto error; } if(!sa_add(rngs, dev->nthreads)) { - log_error(dev, - "Not enough memory: couldn't allocate the list of RNGs.\n"); - } - if(!sa_add(scenes, dev->nthreads)) { - log_error(dev, - "Not enough memory: couldn't allocate the list of Star-3D scenes.\n"); + log_error(dev, "Couldn't allocate the list of RNGs.\n"); res = RES_MEM_ERR; goto error; } - if(!sa_add(shapes, dev->nthreads)) { - log_error(dev, - "Not enough memory: couldn't allocate the list of Star-3D shapes.\n"); - res = RES_MEM_ERR; - goto error; - } - memset(mtls, 0, sizeof(struct sschiff_material_properties*)*dev->nthreads); - memset(accums, 0, sizeof(struct accum*)*dev->nthreads); - memset(mc_accums, 0, sizeof(struct mc_accum*)*dev->nthreads); - memset(rngs, 0, sizeof(struct ssp_rng*)*dev->nthreads); - memset(scenes, 0, sizeof(struct s3d_scene*)*dev->nthreads); - memset(shapes, 0, sizeof(struct s3d_shape*)*dev->nthreads); + memset(ctxs, 0, sizeof(ctxs[0])*dev->nthreads); + memset(solver_ctxs, 0, sizeof(solver_ctxs[0])*dev->nthreads); + memset(rngs, 0, sizeof(rngs[0])*dev->nthreads); - /* Create the per thread data structures */ + /* Init the per thread data structures */ FOR_EACH(i, 0, dev->nthreads) { - if(!sa_add(mtls[i], nwavelengths)) { - log_error(dev, - "Not enough memory: couldn't allocate the optical properties.\n"); - res = RES_MEM_ERR; - goto error; - } - if(!sa_add(accums[i], nwavelengths)) { - log_error(dev, - "Not enough memory: couldn't allocate the temporary accumulator.\n"); - res = RES_MEM_ERR; - goto error; - } - if(!sa_add(mc_accums[i], nwavelengths)) { - log_error(dev, - "Not enough memory: couldn't allocate the Monte Carlo accumulator.\n"); - res = RES_MEM_ERR; - goto error; - } - memset(mc_accums[i], 0, sizeof(struct mc_accum)*nwavelengths); - res = ssp_rng_proxy_create_rng(rng_proxy, i, rngs + i); if(res != RES_OK) { - log_error(dev, "Couldn't create the RNG.\n"); - goto error; - } - res = s3d_shape_create_mesh(dev->s3d[i], shapes + i); - if(res != RES_OK) { - log_error(dev, "Couldn't create the Star-3D shape.\n"); + log_error(dev, + "Couldn't create the RNG of the thread \"%lu\".\n", (unsigned long)i); goto error; } - res = s3d_scene_create(dev->s3d[i], scenes + i); + res = integrator_context_init(ctxs + i, dev->s3d[i], rngs[i], estimator, + nwavelengths, nangles); if(res != RES_OK) { - log_error(dev, "Couldn't create the Star-3D scene.\n"); + log_error(dev, + "Couldn't initialise the integrator context of the thread \"%lu\".\n", + (unsigned long)i); goto error; } - res = s3d_scene_attach_shape(scenes[i], shapes[i]); + res = solver_context_init(dev, solver_ctxs + i); if(res != RES_OK) { log_error(dev, - "Couldn't attach the Star-3D Schiff shape to the Star-3D Schiff scene.\n"); + "Couldn't initialise the solver context of the thread \"%lu\".\n", + (unsigned long)i); goto error; } } - /* Clear the accumulators */ - memset(estimator->accums, 0, sizeof(struct mc_accum)*nwavelengths); - - /* Setup and sort the wavelengths */ - FOR_EACH(i, 0, nwavelengths) estimator->wavelengths[i] = wavelengths[i]; - qsort(estimator->wavelengths, nwavelengths, sizeof(double), cmp_double); - /* Paralell Schiff integration */ #pragma omp parallel for schedule(static) for(igeom=0; igeom < (int)ngeoms; ++igeom) { - const double* wlengths = estimator->wavelengths; - struct sschiff_material material = SSCHIFF_NULL_MATERIAL; - size_t iwavelength; const int ithread = omp_get_thread_num(); - ATOMIC res_local; + ATOMIC res_local = RES_OK; if(ATOMIC_GET(&res) != RES_OK) continue; - /* Sample a geometry, i.e. a shape and its associated material */ - res_local = distrib->sample - (rngs[ithread], &material, shapes[ithread], distrib->context); + /* Setup the data for the current realisation */ + res_local = begin_realisation(dev, distrib, ctxs + ithread); if(res_local != RES_OK) { - log_error(dev, "Error in sampling a Schiff geometry.\n"); - ATOMIC_SET(&res, res_local); + ATOMIC_CAS(&res, res_local, RES_OK); continue; } - /* Fetch the per wavelength material properties */ - FOR_EACH(iwavelength, 0, nwavelengths) { - material.get_property(material.material, wavelengths[iwavelength], - mtls[ithread] + iwavelength); - } - - /* Build the Star-3D representation of the sampled shape */ - S3D(scene_begin_session(scenes[ithread], S3D_TRACE)); /* Schiff Estimation */ - res_local = radiative_properties(dev, rngs[ithread], igeom, wlengths, - nwavelengths, ndirs, scenes[ithread], mtls[ithread], mc_accums[ithread], - accums[ithread]); - if(res != RES_OK) ATOMIC_SET(&res, res_local); + res_local = radiative_properties(dev, igeom, ndirs, ctxs+ithread); + if(res_local != RES_OK) ATOMIC_CAS(&res, res_local, RES_OK); - S3D(scene_end_session(scenes[ithread])); + end_realisation(ctxs + ithread); } if(res != RES_OK) goto error; /* Handle integration error */ - /* Merge the per thread integration ressults */ + /* Merge the per thread integration results */ FOR_EACH(i, 0, dev->nthreads) { size_t iwlen; FOR_EACH(iwlen, 0, nwavelengths) { - size_t idata; - FOR_EACH(idata, 0, SSCHIFF_DATA_COUNT__) { - estimator->accums[iwlen].mc_data[idata].weight += - mc_accums[i][iwlen].mc_data[idata].weight; - estimator->accums[iwlen].mc_data[idata].sqr_weight += - mc_accums[i][iwlen].mc_data[idata].sqr_weight; + size_t iangle; + #define MC_ACCUM(Data) { \ + const struct mc_accum* mc_accum = ctxs[i].mc_accums + iwlen; \ + estimator->accums[iwlen].Data.weight += mc_accum->Data.weight; \ + estimator->accums[iwlen].Data.sqr_weight += mc_accum->Data.sqr_weight; \ + } (void)0 + MC_ACCUM(extinction_cross_section); + MC_ACCUM(absorption_cross_section); + MC_ACCUM(scattering_cross_section); + MC_ACCUM(avg_projected_area); + + /* Discard differential cross section accumulation for invalid angle */ + if(estimator->limit_angles[iwlen] == INVALID_LIMIT_ANGLE) continue; + + /* Accum up to "limit angle"; Great angles are analitically computed */ + FOR_EACH(iangle, 0, estimator->limit_angles[iwlen]) { + MC_ACCUM(differential_cross_section[iangle]); + MC_ACCUM(differential_cross_section_cumulative[iangle]); } } } + /* Static scheduling is not necessary to ensure the reproductability; + * computations are purely analytics */ + #pragma omp parallel for + for(iwlen=0; iwlen < (int)nwavelengths; ++iwlen) { + const int ithread = omp_get_thread_num(); + if(estimator->limit_angles[iwlen] == INVALID_LIMIT_ANGLE) continue; + /* Do not handle phase function errors */ + compute_phase_function + (dev, &solver_ctxs[ithread], (size_t)iwlen, nangles, estimator); + } + exit: if(rng_proxy) SSP(rng_proxy_ref_put(rng_proxy)); - /* Release per thread data */ - if(mtls) { - FOR_EACH(i, 0, dev->nthreads) if(mtls[i]) sa_release(mtls[i]); - sa_release(mtls); - } - if(accums) { - FOR_EACH(i, 0, dev->nthreads) if(accums[i]) sa_release(accums[i]); - sa_release(accums); + if(ctxs) { + FOR_EACH(i, 0, dev->nthreads) integrator_context_release(ctxs+i); + sa_release(ctxs); } - if(mc_accums) { - FOR_EACH(i, 0, dev->nthreads) if(mc_accums[i]) sa_release(mc_accums[i]); - sa_release(mc_accums); + if(solver_ctxs) { + FOR_EACH(i, 0, dev->nthreads) solver_context_release(solver_ctxs+i); + sa_release(solver_ctxs); } if(rngs) { FOR_EACH(i, 0, dev->nthreads) if(rngs[i]) SSP(rng_ref_put(rngs[i])); sa_release(rngs); } - if(shapes) { - FOR_EACH(i, 0, dev->nthreads) if(shapes[i]) S3D(shape_ref_put(shapes[i])); - sa_release(shapes); - } - if(scenes) { - FOR_EACH(i, 0, dev->nthreads) if(scenes[i]) S3D(scene_ref_put(scenes[i])); - sa_release(scenes); - } if(out_estimator) *out_estimator = estimator; return (res_T)res; error: @@ -783,11 +1602,26 @@ sschiff_estimator_ref_put(struct sschiff_estimator* estimator) } res_T -sschiff_estimator_get_wavelengths_count - (const struct sschiff_estimator* estimator, size_t* count) +sschiff_estimator_get_wavelengths + (const struct sschiff_estimator* estimator, + const double** wavelengths, + size_t* count) { - if(!estimator || !count) return RES_BAD_ARG; - *count = sa_size(estimator->wavelengths); + if(!estimator) return RES_BAD_ARG; + if(wavelengths) *wavelengths = estimator->wavelengths; + if(count) *count = sa_size(estimator->wavelengths); + return RES_OK; +} + +res_T +sschiff_estimator_get_scattering_angles + (const struct sschiff_estimator* estimator, + const double** angles, + size_t* count) +{ + if(!estimator) return RES_BAD_ARG; + if(angles) *angles = estimator->angles; + if(count) *count = sa_size(estimator->angles); return RES_OK; } @@ -801,62 +1635,247 @@ sschiff_estimator_get_realisations_count } res_T -sschiff_estimator_get_wavelength_state +sschiff_estimator_get_cross_section (const struct sschiff_estimator* estimator, - const double wavelength, - struct sschiff_estimator_state* state) + const size_t iwlen, + struct sschiff_cross_section* cross_section) { - const struct mc_accum* accum; - const double* wavelengths; - const double* find; - size_t iwavelength; - size_t nwavelengths; - int i; + const struct mc_accum* acc; + size_t N; - if(!estimator || !state) + if(!estimator || !cross_section || iwlen >= sa_size(estimator->wavelengths)) return RES_BAD_ARG; - wavelengths = estimator->wavelengths; - nwavelengths = sa_size(estimator->wavelengths); - find = bsearch - (&wavelength, wavelengths, nwavelengths, sizeof(double), cmp_double); - if(!find) return RES_BAD_ARG; - - iwavelength = (size_t)(find - wavelengths); - accum = estimator->accums + iwavelength; - - FOR_EACH(i, 0, SSCHIFF_DATA_COUNT__) { - get_mc_value(accum->mc_data+i, estimator->nrealisations, state->values+i); - } - state->wavelength = wavelength; + acc = estimator->accums + iwlen; + N = estimator->nrealisations; + get_mc_value(&acc->extinction_cross_section, N, &cross_section->extinction); + get_mc_value(&acc->absorption_cross_section, N, &cross_section->absorption); + get_mc_value(&acc->scattering_cross_section, N, &cross_section->scattering); + get_mc_value(&acc->avg_projected_area, N, + &cross_section->average_projected_area); return RES_OK; } res_T -sschiff_estimator_get_states +sschiff_estimator_get_cross_sections (const struct sschiff_estimator* estimator, - struct sschiff_estimator_state* states) + struct sschiff_cross_section* cross_sections) { - const double* wavelengths; - const struct mc_accum* accums; size_t nwavelengths; size_t iwlen; - int i; - if(!estimator || !states) return RES_BAD_ARG; + size_t N; + if(!estimator || !cross_sections) return RES_BAD_ARG; nwavelengths = sa_size(estimator->wavelengths); - wavelengths = estimator->wavelengths; - accums = estimator->accums; - + N = estimator->nrealisations; FOR_EACH(iwlen, 0, nwavelengths) { - states[iwlen].wavelength = wavelengths[iwlen]; - FOR_EACH(i, 0, SSCHIFF_DATA_COUNT__) { - get_mc_value - (accums[iwlen].mc_data + i, - estimator->nrealisations, - states[iwlen].values + i); + const struct mc_accum* acc = estimator->accums + iwlen; + get_mc_value(&acc->extinction_cross_section, N, &cross_sections->extinction); + get_mc_value(&acc->absorption_cross_section, N, &cross_sections->absorption); + get_mc_value(&acc->scattering_cross_section, N, &cross_sections->scattering); + get_mc_value(&acc->avg_projected_area, N, + &cross_sections->average_projected_area); + } + return RES_OK; +} + +res_T +sschiff_estimator_get_phase_function + (const struct sschiff_estimator* estimator, + const size_t iwlen, + const struct sschiff_state** states) +{ + if(!estimator || !states || iwlen >= sa_size(estimator->wavelengths)) + return RES_BAD_ARG; + /* No phase function was computed */ + if(estimator->limit_angles[iwlen] == INVALID_LIMIT_ANGLE) + return RES_BAD_OP; + /* Invalid phase function */ + if(estimator->phase_functions[iwlen].values[0].V < 0) + return RES_BAD_OP; + *states = estimator->phase_functions[iwlen].values; + return RES_OK; +} + +/* Retrieve a pointer onto the estimated phase function cumulative. */ +SSCHIFF_API res_T +sschiff_estimator_get_phase_function_cumulative + (const struct sschiff_estimator* estimator, + const size_t iwlen, + const struct sschiff_state** states) +{ + if(!estimator || !states || iwlen >= sa_size(estimator->wavelengths)) + return RES_BAD_ARG; + /* No phase function cumulative was computed */ + if(estimator->limit_angles[iwlen] == INVALID_LIMIT_ANGLE) + return RES_BAD_OP; + /* Invalid cumulative phase function */ + if(estimator->phase_functions[iwlen].cumulative[0].V < 0) + return RES_BAD_OP; + *states = estimator->phase_functions[iwlen].cumulative; + return RES_OK; +} + +res_T +sschiff_estimator_inverse_cumulative_phase_function + (const struct sschiff_estimator* estimator, + const size_t iwlen, + double* thetas, + const size_t nthetas) +{ + struct sschiff_state* cumul[2]; + double* cumulative_small_angles = NULL; + double cumulative; + double step; + size_t itheta; + size_t iangle, nsmall_angles; + res_T res = RES_OK; + + if(!estimator + || nthetas < 2 + || !thetas + || iwlen >= sa_size(estimator->wavelengths)) { + res = RES_BAD_ARG; + goto error; + } + + /* No phase function cumulative is computed => nothing to inverse */ + if(estimator->limit_angles[iwlen] == INVALID_LIMIT_ANGLE) { + res = RES_BAD_OP; + goto error; + } + + /* Allocate the "filtered" phase function cumulative of small angles, i.e. + * the increasing cumulative defined from the Monte-Carlo estimation. */ + nsmall_angles = estimator->limit_angles[iwlen]; + if(!sa_add(cumulative_small_angles, nsmall_angles)) { + log_error(estimator->dev, +"Couldn't allocate the filtered phase function cumulative of small angles.\n"); + res = RES_MEM_ERR; + goto error; + } + + /* Fill the phase function cumulative for small angles. Ensure that the + * resulting array is sorted in increasing order, i.e. increasing function */ + cumul[0] = &estimator->phase_functions[iwlen].cumulative[0]; + cumulative_small_angles[0] = cumul[0]->E; + FOR_EACH(iangle, 1, nsmall_angles) { + cumul[1] = &estimator->phase_functions[iwlen].cumulative[iangle]; + + if(cumul[0]->E <= cumul[1]->E) { + cumulative_small_angles[iangle] = cumul[1]->E; + } else { + /* Numerical imprecisions may lead to a cumulative that is not an + * increasing function. In such case, check that the standard-error + * ensure at least a threshold between the decreasing entry an the + * previous one. If not, return an error */ + cumulative = MMIN(cumul[1]->E + cumul[1]->SE, cumul[0]->E); + if(cumulative < cumul[0]->E) { + log_error(estimator->dev, +"The phase function cumulative of small angles is not an increasing function.\n" +"This may be due to numerical imprecisions.\n"); + res = RES_BAD_OP; + goto error; + } + cumulative_small_angles[iangle] = cumulative; } + cumul[0] = cumul[1]; + } + + /* Inverse the phase function cumulative */ + thetas[0] = 0.0; + thetas[nthetas-1] = PI; + cumulative = step = 1.0/(double)(nthetas-1); + FOR_EACH(itheta, 1, nthetas-1) { + /* TODO since the submitted cumulative are strictly increasing, one can + * speed up the inversion by using the previous search result to reduce the + * search domain in the cumulative arrays */ + res = inverse_cumulative_phase_function + (estimator, cumulative_small_angles, iwlen, cumulative, &thetas[itheta]); + if(res != RES_OK) goto error; + cumulative += step; } + +exit: + if(cumulative_small_angles) sa_release(cumulative_small_angles); + return res; +error: + goto exit; +} + +res_T +sschiff_estimator_get_limit_scattering_angle_index + (const struct sschiff_estimator* estimator, + const size_t iwlen, + size_t* iangle) +{ + size_t limit_angle; + if(!estimator || iwlen >= sa_size(estimator->wavelengths) || !iangle) + return RES_BAD_ARG; + limit_angle = estimator->limit_angles[iwlen]; + if(limit_angle == INVALID_LIMIT_ANGLE) + return RES_BAD_OP; + *iangle = limit_angle - 1/*<=>index of the last small angle*/; + return RES_OK; +} + +res_T +sschiff_estimator_get_wide_scattering_angle_model_parameter + (const struct sschiff_estimator* estimator, + const size_t iwlen, + double* out_n) +{ + if(!estimator || iwlen >= sa_size(estimator->wavelengths) || !out_n) + return RES_BAD_ARG; + if(estimator->limit_angles[iwlen] == INVALID_LIMIT_ANGLE) + return RES_BAD_OP; + *out_n = estimator->wide_angles_parameter[iwlen]; + return RES_OK; +} + +res_T +sschiff_estimator_get_differential_cross_section + (const struct sschiff_estimator* estimator, + const size_t iwlen, + const size_t iangle, + struct sschiff_state* state) +{ + if(!estimator + || iwlen >= sa_size(estimator->wavelengths) + || iangle >= sa_size(estimator->angles) + || !state) + return RES_BAD_ARG; + + if(estimator->limit_angles[iwlen] == INVALID_LIMIT_ANGLE) + return RES_BAD_OP; + + get_mc_value + (&estimator->accums[iwlen].differential_cross_section[iangle], + estimator->nrealisations, + state); + return RES_OK; +} + +res_T +sschiff_estimator_get_differential_cross_section_cumulative + (const struct sschiff_estimator* estimator, + const size_t iwlen, + const size_t iangle, + struct sschiff_state* state) +{ + if(!estimator + || iwlen >= sa_size(estimator->wavelengths) + || iangle >= sa_size(estimator->angles) + || !state) + return RES_BAD_ARG; + + if(estimator->limit_angles[iwlen] == INVALID_LIMIT_ANGLE) + return RES_BAD_OP; + + get_mc_value + (&estimator->accums[iwlen].differential_cross_section_cumulative[iangle], + estimator->nrealisations, + state); return RES_OK; } diff --git a/src/sschiff_scattering_angles_distributions.c b/src/sschiff_scattering_angles_distributions.c @@ -0,0 +1,35 @@ +/* Copyright (C) 2015-2016 CNRS + * + * 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 <http://www.gnu.org/licenses/>. */ + +#include "sschiff.h" +#include <rsys/math.h> + +static void +uniform(double* angles, const size_t nangles) +{ + size_t iangle; + const double step = PI / (double)(nangles - 1); + ASSERT(nangles >= 2); + + angles[0] = 0.0; + FOR_EACH(iangle, 1, nangles-1) { + angles[iangle] = angles[iangle-1] + step; + } + angles[nangles-1] = PI; +} + +const sschiff_scattering_angles_distribution_T +sschiff_uniform_scattering_angles = uniform; + diff --git a/src/test_sschiff_device.c b/src/test_sschiff_device.c @@ -1,30 +1,17 @@ -/* Copyright (C) |Meso|Star> 2015 (contact@meso-star.com) +/* Copyright (C) 2015-2016 CNRS * - * This software is governed by the CeCILL license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/or redistribute the software under the terms of the CeCILL - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". + * 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. * - * As a counterpart to the access to the source code and rights to copy, - * modify and redistribute granted by the license, users are provided only - * with a limited warranty and the software's author, the holder of the - * economic rights, and the successive licensors have only limited - * liability. + * 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. * - * In this respect, the user's attention is drawn to the risks associated - * with loading, using, modifying and/or developing or reproducing the - * software by the user in light of its specific status of free software, - * that may mean that it is complicated to manipulate, and that also - * therefore means that it is reserved for developers and experienced - * professionals having in-depth computer knowledge. Users are therefore - * encouraged to load and test the software's suitability as regards their - * requirements in conditions enabling the security of their systems and/or - * data to be ensured and, more generally, to use and operate it in the - * same conditions as regards security. - * - * The fact that you are presently reading this means that you have had - * knowledge of the CeCILL license and that you accept its terms. */ + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "sschiff.h" #include "test_sschiff_utils.h" diff --git a/src/test_sschiff_estimator_cylinder.c b/src/test_sschiff_estimator_cylinder.c @@ -1,30 +1,17 @@ -/* Copyright (C) |Meso|Star> 2015 (contact@meso-star.com) +/* Copyright (C) 2015-2016 CNRS * - * This software is governed by the CeCILL license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/or redistribute the software under the terms of the CeCILL - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". + * 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. * - * As a counterpart to the access to the source code and rights to copy, - * modify and redistribute granted by the license, users are provided only - * with a limited warranty and the software's author, the holder of the - * economic rights, and the successive licensors have only limited - * liability. + * 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. * - * In this respect, the user's attention is drawn to the risks associated - * with loading, using, modifying and/or developing or reproducing the - * software by the user in light of its specific status of free software, - * that may mean that it is complicated to manipulate, and that also - * therefore means that it is reserved for developers and experienced - * professionals having in-depth computer knowledge. Users are therefore - * encouraged to load and test the software's suitability as regards their - * requirements in conditions enabling the security of their systems and/or - * data to be ensured and, more generally, to use and operate it in the - * same conditions as regards security. - * - * The fact that you are presently reading this means that you have had - * knowledge of the CeCILL license and that you accept its terms. */ + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "sschiff.h" #include "test_sschiff_utils.h" @@ -47,11 +34,6 @@ struct result { double avg_proj_area_SE; }; -struct geometry { - float* vertices; - unsigned* indices; -}; - struct sampler_context { struct geometry geometry; double aspect_ratio; @@ -59,12 +41,6 @@ struct sampler_context { double sigma; }; -struct cylinder { - struct geometry* geometry; - float radius; - float height; -}; - static void get_material_property (void* mtl, @@ -78,66 +54,13 @@ get_material_property props->relative_real_refractive_index = 1.01; } -static void -get_indices(const unsigned itri, unsigned ids[3], void* ctx) -{ - struct cylinder* cylinder = ctx; - const size_t i = itri * 3; - - CHECK(sa_size(cylinder->geometry->indices) % 3, 0); - CHECK(itri < sa_size(cylinder->geometry->indices) / 3, 1); - ids[0] = cylinder->geometry->indices[i + 0]; - ids[1] = cylinder->geometry->indices[i + 1]; - ids[2] = cylinder->geometry->indices[i + 2]; -} - -static void -get_position(const unsigned ivert, float vertex[3], void* ctx) -{ - struct cylinder* cylinder = ctx; - const size_t i = ivert * 3; - - CHECK(sa_size(cylinder->geometry->vertices) % 3, 0); - CHECK(ivert < sa_size(cylinder->geometry->vertices) / 3, 1); - vertex[0] = cylinder->geometry->vertices[i + 0] * cylinder->radius; - vertex[1] = cylinder->geometry->vertices[i + 1] * cylinder->radius; - vertex[2] = cylinder->geometry->vertices[i + 2] * cylinder->height; -} - -static FINLINE void -dump_geometry(struct geometry* geom) -{ - size_t i; - NCHECK(geom, NULL); - CHECK(sa_size(geom->vertices)%3, 0); - CHECK(sa_size(geom->indices)%3, 0); - - FOR_EACH(i, 0, sa_size(geom->vertices)/3) { - printf("v %f %f %f\n", - geom->vertices[i*3+0], - geom->vertices[i*3+1], - geom->vertices[i*3+2]); - } - FOR_EACH(i, 0, sa_size(geom->indices)/3) { - printf("f %d %d %d\n", - geom->indices[i*3+0] + 1, - geom->indices[i*3+1] + 1, - geom->indices[i*3+2] + 1); - } -} - static res_T sample_cylinder - (struct ssp_rng* rng, - struct sschiff_material* mtl, - struct s3d_shape* shape, - void* sampler_context) + (struct ssp_rng* rng, struct s3d_shape* shape, void* sampler_context) { - struct s3d_vertex_data attrib; struct sampler_context* sampler_ctx = sampler_context; struct cylinder cylinder; double sample; - size_t nverts, nprims; (void)rng, (void)sampler_context; sample = ssp_ran_lognormal(rng, log(sampler_ctx->mean_radius), log(sampler_ctx->sigma)); @@ -145,85 +68,7 @@ sample_cylinder cylinder.radius = (float)(sample / pow(3.0 / (2.0*sampler_ctx->aspect_ratio), 1.0/3.0)); cylinder.height = (float)(2.f * cylinder.radius / sampler_ctx->aspect_ratio); - attrib.usage = S3D_POSITION; - attrib.type = S3D_FLOAT3; - attrib.get = get_position; - - mtl->get_property = get_material_property; - mtl->material = sampler_ctx; - - nverts = sa_size(cylinder.geometry->vertices) / 3/*#coords*/; - nprims = sa_size(cylinder.geometry->indices) / 3/*#indices per prim*/; - - return s3d_mesh_setup_indexed_vertices(shape, (unsigned)nprims, - get_indices, (unsigned)nverts, &attrib, 1, &cylinder); -} - -static void -cylinder_init(struct geometry* geometry, const unsigned nsteps) -{ - const double step = 2*PI / (double)nsteps; - unsigned istep; - - NCHECK(geometry, NULL); - NCHECK(nsteps, 0); - - geometry->vertices = NULL; - geometry->indices = NULL; - - /* Generate the vertex coordinates */ - FOR_EACH(istep, 0, nsteps) { - const float theta = (float)(istep * step); - const float x = (float)cos(theta); - const float y = (float)sin(theta); - f3(sa_add(geometry->vertices, 3), x, y, -1.f); - f3(sa_add(geometry->vertices, 3), x, y, 0.f); - } - - /* "Polar" vertices */ - f3(sa_add(geometry->vertices, 3), 0.f, 0.f, -1.f); - f3(sa_add(geometry->vertices, 3), 0.f, 0.f, 0.f); - - /* Contour primitives */ - FOR_EACH(istep, 0, nsteps) { - const unsigned id = istep * 2; - unsigned* iprim; - - iprim = sa_add(geometry->indices, 3); - iprim[0] = (id + 0); - iprim[1] = (id + 1); - iprim[2] = (id + 2) % (nsteps*2); - - iprim = sa_add(geometry->indices, 3); - iprim[0] = (id + 2) % (nsteps*2); - iprim[1] = (id + 1); - iprim[2] = (id + 3) % (nsteps*2); - } - - /* Cap primitives */ - FOR_EACH(istep, 0, nsteps) { - const unsigned id = istep * 2; - unsigned* iprim; - - iprim = sa_add(geometry->indices, 3); - iprim[0] = (nsteps * 2); - iprim[1] = (id + 0); - iprim[2] = (id + 2) % (nsteps*2); - - iprim = sa_add(geometry->indices, 3); - iprim[0] = (nsteps * 2) + 1; - iprim[1] = (id + 3) % (nsteps*2); - iprim[2] = (id + 1); - } -} - -static void -cylinder_release(struct geometry* geometry) -{ - sa_release(geometry->vertices); - sa_release(geometry->indices); - geometry->vertices = NULL; - geometry->indices = NULL; + return cylinder_setup_s3d_shape(&cylinder, shape); } static INLINE void @@ -559,9 +404,9 @@ main(int argc, char** argv) 2.010619438e+2, 2.018997018e+2, 2.027374599e+2 }; const size_t nx = sizeof(x)/sizeof(double); - const size_t nscatt_angles = 1; + const size_t nscatt_angles = 1000; const size_t ngeoms = 100; - const size_t ndirs = 10; + const size_t ndirs = 100; size_t i; (void)argc, (void)argv; @@ -569,64 +414,72 @@ main(int argc, char** argv) CHECK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng), RES_OK); CHECK(sschiff_device_create - (NULL, &allocator, SSCHIFF_NTHREADS_DEFAULT, 0, NULL, &dev), RES_OK); + (NULL, &allocator, SSCHIFF_NTHREADS_DEFAULT, 1, NULL, &dev), RES_OK); - cylinder_init(&sampler_ctx.geometry, 64); + geometry_init_cylinder(&sampler_ctx.geometry, 64); FOR_EACH(i, 0, nx) { const double wavelength = 0.6; /* In micron */ - struct sschiff_estimator_state state; + struct sschiff_cross_section cross_section; double interval[2]; - struct sschiff_estimator_value* val; + struct sschiff_state* val; + struct sschiff_state result; sampler_ctx.aspect_ratio = 0.837; sampler_ctx.mean_radius = (x[i] * 0.450) / (2*PI); sampler_ctx.sigma = 1.18; + distrib.characteristic_length = sampler_ctx.mean_radius; + distrib.material.get_property = get_material_property; + distrib.material.material = &sampler_ctx; distrib.sample = sample_cylinder; distrib.context = &sampler_ctx; time_current(&t0); - CHECK(sschiff_integrate(dev, rng, &distrib, &wavelength, 1, nscatt_angles, - ngeoms, ndirs, &estimator), RES_OK); + CHECK(sschiff_integrate(dev, rng, &distrib, &wavelength, 1, + sschiff_uniform_scattering_angles, nscatt_angles, ngeoms, ndirs, + &estimator), RES_OK); time_current(&t1); time_sub(&t0, &t1, &t0); time_dump(&t0, TIME_MIN|TIME_SEC|TIME_MSEC, NULL, buf, sizeof(buf)); - CHECK(sschiff_estimator_get_wavelength_state - (estimator, wavelength, &state), RES_OK); - CHECK(eq_eps(state.wavelength, wavelength, 1.e-6), 1); + CHECK(sschiff_estimator_get_cross_section + (estimator, 0, &cross_section), RES_OK); printf("%u - x = %g - Wavelength = %g micron - %s\n", (unsigned)i, x[i], wavelength, buf); - val = state.values + SSCHIFF_EXTINCTION_CROSS_SECTION; - compute_intersection(interval, results[i].extinction_E, - results[i].extinction_SE, val->E, val->SE); + val = &cross_section.extinction; + result.E = results[i].extinction_E; + result.SE = results[i].extinction_SE; + compute_estimation_intersection(interval, 4, &result, val); printf(" Extinction ~ %9.3g +/- %9.3g ~ %9.3g +/- %9.3g (%9.3g)\n", results[i].extinction_E, results[i].extinction_SE, val->E, val->SE, interval[1] - interval[0]); CHECK(interval[0] <= interval[1], 1); - val = state.values + SSCHIFF_ABSORPTION_CROSS_SECTION; - compute_intersection(interval, results[i].absorption_E, - results[i].absorption_SE, val->E, val->SE); + val = &cross_section.absorption; + result.E = results[i].absorption_E; + result.SE = results[i].absorption_SE; + compute_estimation_intersection(interval, 4, &result, val); printf(" Absorption ~ %9.3g +/- %9.3g ~ %9.3g +/- %9.3g (%9.3g)\n", results[i].absorption_E, results[i].absorption_SE, val->E, val->SE, interval[1] - interval[0]); CHECK(interval[0] <= interval[1], 1); - val = state.values + SSCHIFF_SCATTERING_CROSS_SECTION; - compute_intersection(interval, results[i].scattering_E, - results[i].scattering_SE, val->E, val->SE); + val = &cross_section.scattering; + result.E = results[i].scattering_E; + result.SE = results[i].scattering_SE; + compute_estimation_intersection(interval, 4, &result, val); printf(" Scattering ~ %9.3g +/- %9.3g ~ %9.3g +/- %9.3g (%9.3g)\n", results[i].scattering_E, results[i].scattering_SE, val->E, val->SE, interval[1] - interval[0]); CHECK(interval[0] <= interval[1], 1); - val = state.values + SSCHIFF_AVERAGE_PROJECTED_AREA; - compute_intersection(interval, results[i].avg_proj_area_E, - results[i].avg_proj_area_SE, val->E, val->SE); + val = &cross_section.average_projected_area; + result.E = results[i].avg_proj_area_E; + result.SE = results[i].avg_proj_area_SE; + compute_estimation_intersection(interval, 4, &result, val); printf(" Proj Area ~ %9.3g +/- %9.3g ~ %9.3g +/- %9.3g (%9.3g)\n", results[i].avg_proj_area_E, results[i].avg_proj_area_SE, val->E, val->SE, interval[1] - interval[0]); @@ -638,7 +491,7 @@ main(int argc, char** argv) CHECK(sschiff_device_ref_put(dev), RES_OK); CHECK(ssp_rng_ref_put(rng), RES_OK); - cylinder_release(&sampler_ctx.geometry); + geometry_release(&sampler_ctx.geometry); check_memory_allocator(&allocator); mem_shutdown_proxy_allocator(&allocator); CHECK(mem_allocated_size(), 0); diff --git a/src/test_sschiff_estimator_rhodo.c b/src/test_sschiff_estimator_rhodo.c @@ -0,0 +1,2847 @@ +/* Copyright (C) 2015-2016 CNRS + * + * 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 <http://www.gnu.org/licenses/>. */ + +#include "sschiff.h" +#include "test_sschiff_utils.h" + +#include <rsys/stretchy_array.h> + +#include <star/s3d.h> +#include <star/ssp.h> + +static const double phase_func[][2] = { /* Expected-value Standard-error */ + { 27.8639012515142, 0.0104219265037484 }, + { 27.8097473381001, 0.010397871478357 }, + { 27.6481328692231, 0.0103270459457762 }, + { 27.3815769133766, 0.0102133666109714 }, + { 27.0142029259005, 0.0100630267526927 }, + { 26.5516291165535, 0.0098840133305036 }, + { 26.0008205445445, 0.00968547152934431 }, + { 25.3699082222265, 0.00947696290217467 }, + { 24.6679816078446, 0.00926768196113287 }, + { 23.904861689194, 0.00906571349748875 }, + { 23.0908623729002, 0.00887742227325763 }, + { 22.2365480829303, 0.00870705960655899 }, + { 21.3524953373762, 0.00855664223656603 }, + { 20.4490656308234, 0.00842611046725715 }, + { 19.5361962309318, 0.00831371794844758 }, + { 18.6232145449251, 0.0082165629257017 }, + { 17.7186805765593, 0.00813115454554301 }, + { 16.8302607352971, 0.00805392036869873 }, + { 15.9646349386728, 0.00798159357252883 }, + { 15.1274376275275, 0.00791145628249234 }, + { 14.3232320502063, 0.0078414472105489 }, + { 13.5555160178292, 0.00777016148089376 }, + { 12.8267563319888, 0.00769677804502422 }, + { 12.1384482720108, 0.00762094853040654 }, + { 11.4911959234416, 0.00754267468605382 }, + { 10.8848087432756, 0.00746219314898021 }, + { 10.318409589964, 0.0073798783006216 }, + { 9.79054948640664, 0.00729616765465551 }, + { 9.29932461192675, 0.00721150982105626 }, + { 8.84249140741701, 0.00712633241407738 }, + { 8.41757619406262, 0.00704102588511451 }, + { 8.02197631475114, 0.0069559387428905 }, + { 7.65305047210333, 0.00687137968007232 }, + { 7.30819662250046, 0.00678762261045772 }, + { 6.98491645884851, 0.00670491147231578 }, + { 6.68086614748023, 0.00662346280295104 }, + { 6.39389355304139, 0.00654346539386561 }, + { 6.1220626717808, 0.00646507756644009 }, + { 5.86366638663766, 0.0063884235033138 }, + { 5.61722895118534, 0.00631359042621706 }, + { 5.38149980357944, 0.00624062816413725 }, + { 5.15544041078256, 0.00616955192267286 }, + { 4.93820585607353, 0.00610034811055088 }, + { 4.72912282078604, 0.00603298222447669 }, + { 4.52766548799073, 0.00596740730435197 }, + { 4.33343072605244, 0.00590357146623586 }, + { 4.14611370844303, 0.0058414234415159 }, + { 3.96548490696357, 0.00578091570025391 }, + { 3.79136917142595, 0.00572200536717062 }, + { 3.62362739093223, 0.00566465355149385 }, + { 3.46214102912589, 0.00560882382511788 }, + { 3.30679964498747, 0.00555448044539151 }, + { 3.15749135650642, 0.00550158666572009 }, + { 3.01409607943379, 0.00545010326020052 }, + { 2.87648127803476, 0.00539998730363449 }, + { 2.74449989849243, 0.00535119129972995 }, + { 2.61799011631235, 0.0053036628609894 }, + { 2.49677651380392, 0.00525734520318185 }, + { 2.38067230891331, 0.00521217864216896 }, + { 2.26948227854277, 0.0051681030593242 }, + { 2.16300605407113, 0.00512506100131097 }, + { 2.06104151033916, 0.00508300081750709 }, + { 1.96338801834785, 0.00504187912789507 }, + { 1.86984938322351, 0.00500166201653721 }, + { 1.78023633989709, 0.00496232464181974 }, + { 1.6943685272102, 0.00492384935312064 }, + { 1.61207590499642, 0.00488622277664308 }, + { 1.53319961678277, 0.00484943256480007 }, + { 1.4575923322178, 0.0048134645299754 }, + { 1.38511812767801, 0.00477830071161003 }, + { 1.31565198060704, 0.00474391862457846 }, + { 1.24907896323038, 0.00471029160926755 }, + { 1.18529322486208, 0.00467738994865887 }, + { 1.12419684983762, 0.00464518229961856 }, + { 1.06569867111887, 0.00461363701891924 }, + { 1.0097131089113, 0.00458272311577593 }, + { 0.95615909037997, 0.00455241076684375 }, + { 0.904959091921401, 0.00452267151344723 }, + { 0.856038330573855, 0.00449347836559986 }, + { 0.809324117034655, 0.00446480603508896 }, + { 0.764745370236995, 0.00443663141967281 }, + { 0.722232283151437, 0.00440893430408208 }, + { 0.681716121804176, 0.00438169809177785 }, + { 0.64312913459013, 0.00435491029408095 }, + { 0.606404546714079, 0.00432856251880684 }, + { 0.571476614719875, 0.0043026498214007 }, + { 0.538280718116107, 0.00427716947120289 }, + { 0.506753468517307, 0.0042521193789479 }, + { 0.476832820899294, 0.00422749655789089 }, + { 0.448458175944596, 0.00420329599933904 }, + { 0.421570466526901, 0.00417951022413797 }, + { 0.396112224784657, 0.00415612956220942 }, + { 0.372027628727257, 0.00413314298493553 }, + { 0.34926252883483, 0.00411053915086031 }, + { 0.327764455725817, 0.00408830728225869 }, + { 0.307482609868524, 0.00406643758196836 }, + { 0.288367833779875, 0.00404492108980586 }, + { 0.27037256649635, 0.00402374909389535 }, + { 0.253450779616592, 0.00400291237536915 }, + { 0.237557894145684, 0.00398240061935438 }, + { 0.222650677869614, 0.003962202258034 }, + { 0.208687124098142, 0.00394230485464946 }, + { 0.195626314261759, 0.00392269595151553 }, + { 0.183428268856779, 0.00390336415514364 }, + { 0.172053793343728, 0.00388430016205827 }, + { 0.161464327517107, 0.00386549745148821 }, + { 0.151621808273235, 0.00384695246621416 }, + { 0.142488556341787, 0.00382866423283275 }, + { 0.134027197225246, 0.00381063349888717 }, + { 0.126200625223001, 0.00379286155980179 }, + { 0.118972017036516, 0.0037753490020576 }, + { 0.11230489821309, 0.00375809460082263 }, + { 0.106163261847014, 0.00374109458462931 }, + { 0.100511734859306, 0.00372434242006628 }, + { 0.095315783202815, 0.00370782917879917 }, + { 0.0905419438730762, 0.00369154443527497 }, + { 0.0861580689923781, 0.00367547752398726 }, + { 0.0821335657418107, 0.00365961888847036 }, + { 0.0784396157059796, 0.00364396121204173 }, + { 0.0750493583057482, 0.0036285000555342 }, + { 0.0719380253389912, 0.00361323384121503 }, + { 0.0690830170243102, 0.00359816318900595 }, + { 0.0664639140507078, 0.00358328978320089 }, + { 0.0640624246178966, 0.00356861507072045 }, + { 0.061862269921658, 0.00355413912448753 }, + { 0.059849015624047, 0.00353985993644454 }, + { 0.0580098602245617, 0.00352577325807623 }, + { 0.0563333936678203, 0.00351187293334816 }, + { 0.0548093408342655, 0.00349815152948963 }, + { 0.0534283047171724, 0.00348460101113133 }, + { 0.0521815231483196, 0.00347121323876327 }, + { 0.0510606510442706, 0.003457980183939 }, + { 0.0500575775233974, 0.00344489389509226 }, + { 0.0491642841540651, 0.00343194636437493 }, + { 0.0483727473169407, 0.00341912949411207 }, + { 0.0476748844702159, 0.00340643532428257 }, + { 0.0470625412328754, 0.00339385657428759 }, + { 0.0465275138354938, 0.00338138741289236 }, + { 0.0460615997555366, 0.00336902425037735 }, + { 0.0456566683158406, 0.00335676629114717 }, + { 0.0453047426791992, 0.00334461561705969 }, + { 0.0449980849641331, 0.00333257668679761 }, + { 0.0447292770407506, 0.00332065530249377 }, + { 0.0444912908175968, 0.00330885726117436 }, + { 0.0442775433639401, 0.00329718702177206 }, + { 0.0440819338898934, 0.00328564673822858 }, + { 0.0438988613015472, 0.00327423592232077 }, + { 0.0437232226492196, 0.00326295182644977 }, + { 0.0435503942040859, 0.00325179042651057 }, + { 0.0433761980640087, 0.00324074770352933 }, + { 0.0431968580574175, 0.00322982083041083 }, + { 0.0430089492580248, 0.00321900890111767 }, + { 0.0428093456345139, 0.00320831298813106 }, + { 0.042595170245328, 0.00319773553345556 }, + { 0.0423637519708264, 0.00318727929518009 }, + { 0.042112592088644, 0.00317694621031335 }, + { 0.0418393430917898, 0.00316673654568404 }, + { 0.0415418010837461, 0.00315664858814309 }, + { 0.0412179119330498, 0.00314667891819218 }, + { 0.0408657902127377, 0.00313682309621684 }, + { 0.0404837488732303, 0.00312707645060109 }, + { 0.0400703366859101, 0.00311743464668489 }, + { 0.0396243798257329, 0.00310789383843362 }, + { 0.0391450235969651, 0.0030984504105761 }, + { 0.0386317702858619, 0.00308910052232553 }, + { 0.0380845094590404, 0.00307983977734889 }, + { 0.0375035376952539, 0.00307066331484325 }, + { 0.0368895656870136, 0.00306156644672417 }, + { 0.0362437117927368, 0.0030525457174005 }, + { 0.0355674823518726, 0.00304360003281617 }, + { 0.0348627402726544, 0.00303473139084071 }, + { 0.0341316644409644, 0.00302594480339155 }, + { 0.0333767032667836, 0.00301724722687405 }, + { 0.0326005260937293, 0.00300864564314919 }, + { 0.0318059761943847, 0.00300014474906579 }, + { 0.0309960286497157, 0.00299174490672025 }, + { 0.0301737556012419, 0.00298344100396871 }, + { 0.0293423002504574, 0.00297522266399672 }, + { 0.0299516429908675, 0.000938723060011486 }, + { 0.029268188588675, 0.000917302718963749 }, + { 0.0286037110947699, 0.000896477138658268 }, + { 0.0279575872542805, 0.000876226785484804 }, + { 0.0273292174927134, 0.00085653286800666 }, + { 0.026718024894305, 0.000837377304940913 }, + { 0.0261234542296794, 0.000818742694683954 }, + { 0.0255449710301824, 0.000800612286299926 }, + { 0.0249820607064155, 0.00078296995189444 }, + { 0.0244342277086368, 0.000765800160300474 }, + { 0.023900994726832, 0.000749087952007545 }, + { 0.0233819019283824, 0.000732818915269257 }, + { 0.0228765062313778, 0.000716979163327987 }, + { 0.0223843806117313, 0.000701555312698977 }, + { 0.0219051134423594, 0.000686534462459374 }, + { 0.0214383078627848, 0.000671904174490787 }, + { 0.0209835811776166, 0.000657652454626869 }, + { 0.0205405642824433, 0.000643767734660066 }, + { 0.0201089011157586, 0.000630238855164271 }, + { 0.0196882481356153, 0.000617055049092481 }, + { 0.0192782738197732, 0.000604205926110789 }, + { 0.0188786581881761, 0.000591681457632193 }, + { 0.018489092346654, 0.000579471962515645 }, + { 0.0181092780508085, 0.000567568093397652 }, + { 0.0177389272890942, 0.000555960823625504 }, + { 0.0173777618841613, 0.000544641434762855 }, + { 0.0170255131115766, 0.000533601504639927 }, + { 0.0166819213350833, 0.000522832895922104 }, + { 0.0163467356576088, 0.000512327745172049 }, + { 0.0160197135872668, 0.000502078452381789 }, + { 0.0157006207176422, 0.000492077670952433 }, + { 0.0153892304216842, 0.000482318298100376 }, + { 0.0150853235585655, 0.000472793465669904 }, + { 0.0147886881929018, 0.00046349653133317 }, + { 0.0144991193257556, 0.000454421070159487 }, + { 0.0142164186368751, 0.000445560866536796 }, + { 0.0139403942376528, 0.000436909906429038 }, + { 0.0136708604343077, 0.000428462369954001 }, + { 0.0134076375008253, 0.000420212624266957 }, + { 0.0131505514612099, 0.000412155216736174 }, + { 0.0128994338806274, 0.000404284868397054 }, + { 0.0126541216650364, 0.000396596467672326 }, + { 0.0124144568689274, 0.000389085064346334 }, + { 0.0121802865108059, 0.00038174586378205 }, + { 0.0119514623960758, 0.000374574221370002 }, + { 0.0117278409469938, 0.000367565637198829 }, + { 0.0115092830393834, 0.000360715750937685 }, + { 0.0112956538458104, 0.000354020336921174 }, + { 0.0110868226849391, 0.000347475299427951 }, + { 0.0108826628767972, 0.000341076668144559 }, + { 0.010683051603695, 0.000334820593806455 }, + { 0.0104878697765545, 0.000328703344008578 }, + { 0.0102970019064142, 0.000322721299178161 }, + { 0.0101103359808899, 0.000316870948702849 }, + { 0.00992776334537916, 0.000311148887207481 }, + { 0.00974917858880738, 0.000305551810973246 }, + { 0.00957447943372507, 0.000300076514493174 }, + { 0.00940356663057152, 0.000294719887158227 }, + { 0.00923634385593102, 0.000289478910068523 }, + { 0.00907271761461473, 0.000284350652964449 }, + { 0.008912597145409, 0.000279332271272696 }, + { 0.00875589433033843, 0.000274421003262447 }, + { 0.00860252360729873, 0.000269614167307174 }, + { 0.00845240188592081, 0.000264909159247715 }, + { 0.00830544846653409, 0.000260303449852477 }, + { 0.0081615849621028, 0.00025579458237082 }, + { 0.00802073522301435, 0.000251380170175828 }, + { 0.00788282526460502, 0.00024705789449287 }, + { 0.00774778319731221, 0.000242825502210483 }, + { 0.00761553915934852, 0.000238680803770287 }, + { 0.00748602525179653, 0.000234621671132778 }, + { 0.00735917547602825, 0.000230646035815968 }, + { 0.00723492567335711, 0.000226751887004003 }, + { 0.00711321346683437, 0.000222937269722988 }, + { 0.00699397820510569, 0.000219200283081375 }, + { 0.00687716090824715, 0.000215539078572402 }, + { 0.00676270421550374, 0.000211951858436143 }, + { 0.00665055233485605, 0.000208436874078866 }, + { 0.00654065099434482, 0.000204992424547482 }, + { 0.00643294739508526, 0.000201616855056953 }, + { 0.00632739016590651, 0.000198308555568634 }, + { 0.00622392931955386, 0.000195065959417593 }, + { 0.00612251621039432, 0.000191887541987052 }, + { 0.00602310349356846, 0.00018877181942815 }, + { 0.00592564508553371, 0.000185717347423321 }, + { 0.00583009612594681, 0.000182722719991641 }, + { 0.00573641294083507, 0.000179786568334568 }, + { 0.00564455300700834, 0.000176907559720564 }, + { 0.00555447491766526, 0.000174084396407155 }, + { 0.00546613834914974, 0.000171315814599036 }, + { 0.00537950402881485, 0.000168600583440879 }, + { 0.00529453370395352, 0.000165937504043588 }, + { 0.00521119011175673, 0.000163325408542745 }, + { 0.00512943695026177, 0.000160763159188091 }, + { 0.00504923885025431, 0.000158249647462906 }, + { 0.00497056134808973, 0.000155783793232187 }, + { 0.00489337085940047, 0.00015336454391861 }, + { 0.0048176346536574, 0.000150990873705245 }, + { 0.00474332082955456, 0.000148661782764082 }, + { 0.00467039829118774, 0.000146376296509442 }, + { 0.00459883672499868, 0.000144133464875374 }, + { 0.00452860657745758, 0.0001419323616162 }, + { 0.00445967903345784, 0.000139772083629371 }, + { 0.00439202599539782, 0.000137651750299873 }, + { 0.00432562006292552, 0.000135570502865389 }, + { 0.0042604345133229, 0.000133527503801526 }, + { 0.00419644328250756, 0.000131521936226379 }, + { 0.00413362094663017, 0.000129553003323771 }, + { 0.00407194270424716, 0.000127619927784523 }, + { 0.00401138435904859, 0.000125721951265126 }, + { 0.00395192230312223, 0.00012385833386321 }, + { 0.00389353350073536, 0.000122028353609248 }, + { 0.00383619547261662, 0.000120231305973929 }, + { 0.00377988628072077, 0.000118466503390666 }, + { 0.00372458451346011, 0.000116733274792729 }, + { 0.00367026927138658, 0.000115030965164504 }, + { 0.00361692015330938, 0.000113358935106399 }, + { 0.00356451724283362, 0.000111716560412954 }, + { 0.00351304109530554, 0.00011010323166368 }, + { 0.00346247272515112, 0.00010851835382624 }, + { 0.00341279359359459, 0.000106961345871528 }, + { 0.00336398559674452, 0.000105431640400276 }, + { 0.00331603105403517, 0.000103928683280785 }, + { 0.00326891269701145, 0.000102451933297436 }, + { 0.00322261365844611, 0.000101000861809609 }, + { 0.00317711746177841, 9.9574952420671e-05 }, + { 0.00313240801086364, 9.8173700656721e-05 }, + { 0.0030884695800234, 9.67966136547482e-05 }, + { 0.00304528680438698, 9.54432098599192e-05 }, + { 0.00300284467051429, 9.41130187316882e-05 }, + { 0.00296112850729126, 9.28055804584489e-05 }, + { 0.00292012397708914, 9.15204456804534e-05 }, + { 0.00287981706717899, 9.02571752207328e-05 }, + { 0.0028401940813934, 8.90153398237637e-05 }, + { 0.00280124163202747, 8.77945199016352e-05 }, + { 0.00276294663197147, 8.65943052874766e-05 }, + { 0.00272529628706795, 8.54142949959177e-05 }, + { 0.00268827808868602, 8.42540969903592e-05 }, + { 0.00265187980650613, 8.31133279568381e-05 }, + { 0.00261608948150882, 8.1991613084284e-05 }, + { 0.00258089541916074, 8.08885858509633e-05 }, + { 0.00254628618279223, 7.98038878169218e-05 }, + { 0.00251225058716016, 7.87371684222365e-05 }, + { 0.00247877769219047, 7.76880847908989e-05 }, + { 0.00244585679689484, 7.6656301540155e-05 }, + { 0.00241347743345604, 7.56414905951341e-05 }, + { 0.00238162936147699, 7.46433310086049e-05 }, + { 0.00235030256238827, 7.36615087857006e-05 }, + { 0.00231948723400942, 7.26957167134633e-05 }, + { 0.00228917378525928, 7.17456541950598e-05 }, + { 0.00225935283101098, 7.08110270885279e-05 }, + { 0.00223001518708693, 6.98915475499161e-05 }, + { 0.00220115186538994, 6.89869338806842e-05 }, + { 0.00217275406916611, 6.80969103792372e-05 }, + { 0.00214481318839565, 6.72212071964682e-05 }, + { 0.00211732079530787, 6.63595601951913e-05 }, + { 0.0020902686400165, 6.55117108133474e-05 }, + { 0.0020636486462719, 6.46774059308727e-05 }, + { 0.00203745290732659, 6.385639774012e-05 }, + { 0.00201167368191087, 6.30484436197282e-05 }, + { 0.00198630339031517, 6.22533060118395e-05 }, + { 0.00196133461057614, 6.14707523025647e-05 }, + { 0.00193676007476325, 6.07005547056026e-05 }, + { 0.00191257266536322, 5.99424901489212e-05 }, + { 0.00188876541175914, 5.91963401644111e-05 }, + { 0.00186533148680185, 5.84618907804258e-05 }, + { 0.0018422642034706, 5.77389324171247e-05 }, + { 0.00181955701162071, 5.70272597845384e-05 }, + { 0.00179720349481546, 5.63266717832776e-05 }, + { 0.00177519736723997, 5.56369714078103e-05 }, + { 0.00175353247069473, 5.49579656522334e-05 }, + { 0.00173220277166633, 5.42894654184677e-05 }, + { 0.00171120235847343, 5.36312854268074e-05 }, + { 0.00169052543848568, 5.29832441287579e-05 }, + { 0.00167016633541353, 5.23451636220957e-05 }, + { 0.00165011948666707, 5.17168695680901e-05 }, + { 0.00163037944078177, 5.10981911108226e-05 }, + { 0.00161094085490937, 5.0488960798549e-05 }, + { 0.00159179849237209, 4.98890145070441e-05 }, + { 0.0015729472202783, 4.92981913648749e-05 }, + { 0.00155438200719808, 4.87163336805491e-05 }, + { 0.00153609792089693, 4.81432868714853e-05 }, + { 0.00151809012612593, 4.75788993947567e-05 }, + { 0.00150035388246704, 4.70230226795576e-05 }, + { 0.00148288454223177, 4.64755110613457e-05 }, + { 0.00146567754841189, 4.59362217176149e-05 }, + { 0.00144872843268072, 4.54050146052539e-05 }, + { 0.00143203281344369, 4.48817523994458e-05 }, + { 0.00141558639393662, 4.43663004340691e-05 }, + { 0.00139938496037074, 4.38585266435572e-05 }, + { 0.00138342438012291, 4.33583015061792e-05 }, + { 0.00136770059996992, 4.28654979887006e-05 }, + { 0.00135220964436576, 4.23799914923901e-05 }, + { 0.00133694761376057, 4.19016598003337e-05 }, + { 0.00132191068296025, 4.14303830260224e-05 }, + { 0.00130709509952559, 4.09660435631794e-05 }, + { 0.00129249718220989, 4.05085260367932e-05 }, + { 0.0012781133194341, 4.00577172553251e-05 }, + { 0.00126393996779831, 3.96135061640598e-05 }, + { 0.00124997365062891, 3.9175783799569e-05 }, + { 0.00123621095656017, 3.87444432452578e-05 }, + { 0.00122264853814957, 3.83193795879675e-05 }, + { 0.0012092831105259, 3.79004898756041e-05 }, + { 0.00119611145006925, 3.74876730757688e-05 }, + { 0.00118313039312213, 3.70808300353618e-05 }, + { 0.00117033683473081, 3.66798634411354e-05 }, + { 0.00115772772741624, 3.62846777811718e-05 }, + { 0.00114530007997364, 3.58951793072608e-05 }, + { 0.00113305095630004, 3.55112759981554e-05 }, + { 0.0011209774742492, 3.51328775236806e-05 }, + { 0.001109076804513, 3.47598952096767e-05 }, + { 0.00109734616952874, 3.43922420037521e-05 }, + { 0.00108578284241168, 3.40298324418276e-05 }, + { 0.00107438414591214, 3.36725826154507e-05 }, + { 0.00106314745139656, 3.33204101398608e-05 }, + { 0.00105207017785192, 3.29732341227861e-05 }, + { 0.00104114979091287, 3.26309751339534e-05 }, + { 0.0010303838019111, 3.2293555175293e-05 }, + { 0.0010197697669463, 3.1960897651822e-05 }, + { 0.00100930528597817, 3.16329273431872e-05 }, + { 0.000998988001939045, 3.13095703758526e-05 }, + { 0.000988815599866506, 3.09907541959151e-05 }, + { 0.000978785806055534, 3.06764075425315e-05 }, + { 0.000968896387229724, 3.03664604219435e-05 }, + { 0.000959145149731077, 3.00608440820846e-05 }, + { 0.000949529938727894, 2.97594909877547e-05 }, + { 0.000940048637440358, 2.94623347963484e-05 }, + { 0.000930699166383331, 2.91693103341238e-05 }, + { 0.000921479482625972, 2.88803535729977e-05 }, + { 0.000912387579067751, 2.85954016078549e-05 }, + { 0.000903421483730461, 2.83143926343592e-05 }, + { 0.000894579259065824, 2.80372659272524e-05 }, + { 0.000885859001278342, 2.77639618191322e-05 }, + { 0.000877258839662987, 2.74944216796941e-05 }, + { 0.000868776935957397, 2.72285878954284e-05 }, + { 0.000860411483708211, 2.69664038497609e-05 }, + { 0.000852160707651214, 2.67078139036249e-05 }, + { 0.00084402286310495, 2.64527633764569e-05 }, + { 0.000835996235377483, 2.62011985276038e-05 }, + { 0.000828079139185996, 2.59530665381319e-05 }, + { 0.000820269918088911, 2.5708315493029e-05 }, + { 0.000812566943930242, 2.54668943637901e-05 }, + { 0.000804968616295881, 2.52287529913762e-05 }, + { 0.000797473361981547, 2.49938420695392e-05 }, + { 0.000790079634472097, 2.47621131285032e-05 }, + { 0.000782785913431966, 2.45335185189939e-05 }, + { 0.00077559070420644, 2.43080113966077e-05 }, + { 0.000768492537333525, 2.40855457065136e-05 }, + { 0.000761489968066167, 2.38660761684785e-05 }, + { 0.00075458157590456, 2.36495582622094e-05 }, + { 0.00074776596413834, 2.34359482130049e-05 }, + { 0.000741041759398393, 2.32252029777084e-05 }, + { 0.000734407611218095, 2.30172802309569e-05 }, + { 0.000727862191603729, 2.28121383517175e-05 }, + { 0.000721404194613896, 2.26097364101048e-05 }, + { 0.000715032335947696, 2.2410034154475e-05 }, + { 0.000708745352541474, 2.22129919987866e-05 }, + { 0.000702542002173954, 2.20185710102252e-05 }, + { 0.00069642106307954, 2.18267328970838e-05 }, + { 0.000690381333569628, 2.16374399968941e-05 }, + { 0.000684421631661716, 2.14506552648026e-05 }, + { 0.000678540794716163, 2.12663422621856e-05 }, + { 0.000672737679080397, 2.1084465145499e-05 }, + { 0.000667011159740422, 2.09049886553553e-05 }, + { 0.000661360129979451, 2.07278781058255e-05 }, + { 0.000655783501043505, 2.05530993739577e-05 }, + { 0.00065028020181382, 2.03806188895107e-05 }, + { 0.00064484917848591, 2.02104036248949e-05 }, + { 0.000639489394255141, 2.00424210853179e-05 }, + { 0.000634199829008657, 1.98766392991293e-05 }, + { 0.000628979479023536, 1.97130268083601e-05 }, + { 0.000623827356671021, 1.95515526594535e-05 }, + { 0.000618742490126692, 1.93921863941806e-05 }, + { 0.000613723923086461, 1.92348980407398e-05 }, + { 0.000608770714488245, 1.90796581050338e-05 }, + { 0.000603881938239195, 1.892643756212e-05 }, + { 0.000599056682948373, 1.8775207847833e-05 }, + { 0.000594294051664734, 1.86259408505718e-05 }, + { 0.000589593161620314, 1.84786089032519e-05 }, + { 0.000584953143978502, 1.8333184775415e-05 }, + { 0.00058037314358729, 1.8189641665496e-05 }, + { 0.000575852318737385, 1.80479531932419e-05 }, + { 0.000571389840925085, 1.79080933922796e-05 }, + { 0.000566984894619811, 1.77700367028307e-05 }, + { 0.000562636677036195, 1.76337579645681e-05 }, + { 0.000558344397910626, 1.74992324096125e-05 }, + { 0.000554107279282155, 1.73664356556661e-05 }, + { 0.000549924555277676, 1.72353436992794e-05 }, + { 0.000545795471901266, 1.71059329092494e-05 }, + { 0.000541719286827633, 1.69781800201454e-05 }, + { 0.000537695269199542, 1.68520621259607e-05 }, + { 0.000533722699429167, 1.6727556673886e-05 }, + { 0.000529800869003272, 1.66046414582044e-05 }, + { 0.000525929080292131, 1.64832946143017e-05 }, + { 0.000522106646362129, 1.63634946127941e-05 }, + { 0.000518332890791946, 1.62452202537662e-05 }, + { 0.000514607147492258, 1.61284506611209e-05 }, + { 0.000510928760528883, 1.60131652770363e-05 }, + { 0.000507297083949286, 1.58993438565282e-05 }, + { 0.000503711481612393, 1.57869664621162e-05 }, + { 0.000500171327021625, 1.56760134585908e-05 }, + { 0.000496676003161098, 1.55664655078795e-05 }, + { 0.000493224902334915, 1.54583035640105e-05 }, + { 0.000489817426009489, 1.53515088681704e-05 }, + { 0.000486452984658838, 1.52460629438558e-05 }, + { 0.000483130997612775, 1.51419475921154e-05 }, + { 0.000479850892907955, 1.50391448868813e-05 }, + { 0.000476612107141704, 1.49376371703883e-05 }, + { 0.000473414085328574, 1.48374070486777e-05 }, + { 0.000470256280759579, 1.47384373871861e-05 }, + { 0.00046713815486404, 1.46407113064147e-05 }, + { 0.000464059177074002, 1.45442121776806e-05 }, + { 0.000461018824691157, 1.44489236189459e-05 }, + { 0.000458016582756232, 1.43548294907237e-05 }, + { 0.000455051943920786, 1.42619138920607e-05 }, + { 0.000452124408321363, 1.41701611565924e-05 }, + { 0.000449233483455972, 1.40795558486721e-05 }, + { 0.000446378684062815, 1.39900827595705e-05 }, + { 0.000443559532001252, 1.3901726903744e-05 }, + { 0.000440775556134931, 1.38144735151727e-05 }, + { 0.000438026292217057, 1.37283080437642e-05 }, + { 0.000435311282777744, 1.36432161518233e-05 }, + { 0.000432630077013417, 1.35591837105854e-05 }, + { 0.000429982230678222, 1.34761967968133e-05 }, + { 0.000427367305977398, 1.33942416894556e-05 }, + { 0.000424784871462578, 1.33133048663648e-05 }, + { 0.000422234501928979, 1.32333730010754e-05 }, + { 0.000419715778314438, 1.31544329596398e-05 }, + { 0.000417228287600268, 1.30764717975203e-05 }, + { 0.000414771622713892, 1.29994767565382e-05 }, + { 0.000412345382433211, 1.29234352618764e-05 }, + { 0.000409949171292692, 1.28483349191357e-05 }, + { 0.000407582599491127, 1.27741635114443e-05 }, + { 0.000405245282801027, 1.2700908996618e-05 }, + { 0.000402936842479638, 1.26285595043711e-05 }, + { 0.000400656905181522, 1.2557103333577e-05 }, + { 0.000398405102872699, 1.24865289495766e-05 }, + { 0.000396181072746295, 1.24168249815354e-05 }, + { 0.000393984457139683, 1.23479802198462e-05 }, + { 0.000391814903453081, 1.22799836135776e-05 }, + { 0.000389672064069582, 1.22128242679683e-05 }, + { 0.000387555596276584, 1.21464914419639e-05 }, + { 0.0003854651621886, 1.20809745457982e-05 }, + { 0.00038340042867141, 1.20162631386158e-05 }, + { 0.000381361067267545, 1.19523469261366e-05 }, + { 0.000379346754123059, 1.18892157583609e-05 }, + { 0.000377357169915582, 1.18268596273145e-05 }, + { 0.000375391999783619, 1.17652686648327e-05 }, + { 0.000373450933257068, 1.17044331403827e-05 }, + { 0.000371533664188946, 1.16443434589237e-05 }, + { 0.000369639890688292, 1.15849901588044e-05 }, + { 0.000367769315054221, 1.15263639096957e-05 }, + { 0.00036592164371112, 1.14684555105598e-05 }, + { 0.000364096587144948, 1.14112558876539e-05 }, + { 0.000362293859840633, 1.13547560925679e-05 }, + { 0.000360513180220536, 1.1298947300296e-05 }, + { 0.000358754270583972, 1.12438208073413e-05 }, + { 0.000357016857047753, 1.11893680298519e-05 }, + { 0.000355300669487747, 1.11355805017896e-05 }, + { 0.000353605441481433, 1.10824498731296e-05 }, + { 0.000351930910251424, 1.10299679080902e-05 }, + { 0.000350276816609946, 1.09781264833928e-05 }, + { 0.000348642904904262, 1.09269175865515e-05 }, + { 0.000347028922963007, 1.08763333141909e-05 }, + { 0.000345434622043434, 1.0826365870393e-05 }, + { 0.000343859756779542, 1.07770075650714e-05 }, + { 0.000342304085131077, 1.07282508123729e-05 }, + { 0.000340767368333383, 1.06800881291056e-05 }, + { 0.0003392493708481, 1.06325121331942e-05 }, + { 0.000337749860314675, 1.05855155421596e-05 }, + { 0.000336268607502685, 1.05390911716252e-05 }, + { 0.000334805386264957, 1.04932319338474e-05 }, + { 0.00033335997349146, 1.04479308362705e-05 }, + { 0.000331932149063961, 1.04031809801057e-05 }, + { 0.000330521695811445, 1.03589755589337e-05 }, + { 0.000329128399466246, 1.031530785733e-05 }, + { 0.000327752048620931, 1.02721712495132e-05 }, + { 0.000326392434685867, 1.02295591980159e-05 }, + { 0.000325049351847507, 1.01874652523763e-05 }, + { 0.000323722597027346, 1.01458830478526e-05 }, + { 0.000322411969841556, 1.01048063041576e-05 }, + { 0.000321117272561279, 1.00642288242143e-05 }, + { 0.000319838310073571, 1.00241444929318e-05 }, + { 0.000318574889842977, 9.98454727600101e-06 }, + { 0.000317326821873739, 9.94543121871019e-06 }, + { 0.000316093918672612, 9.90679044477957e-06 }, + { 0.00031487599521228, 9.8686191552149e-06 }, + { 0.000313672868895378, 9.83091162717957e-06 }, + { 0.000312484359519081, 9.79366221288498e-06 }, + { 0.000311310289240269, 9.75686533849879e-06 }, + { 0.000310150482541258, 9.72051550307075e-06 }, + { 0.000309004766196076, 9.68460727747586e-06 }, + { 0.000307872969237287, 9.64913530337444e-06 }, + { 0.000306754922923335, 9.61409429218892e-06 }, + { 0.000305650460706426, 9.57947902409697e-06 }, + { 0.000304559418200915, 9.54528434704075e-06 }, + { 0.000303481633152193, 9.51150517575191e-06 }, + { 0.000302416945406082, 9.47813649079224e-06 }, + { 0.000301365196878701, 9.44517333760943e-06 }, + { 0.000300326231526829, 9.41261082560791e-06 }, + { 0.000299299895318719, 9.3804441272344e-06 }, + { 0.000298286036205384, 9.34866847707793e-06 }, + { 0.000297284504092342, 9.31727917098405e-06 }, + { 0.00029629515081179, 9.28627156518308e-06 }, + { 0.000295317830095233, 9.25564107543203e-06 }, + { 0.000294352397546534, 9.22538317617001e-06 }, + { 0.000293398710615389, 9.19549339968696e-06 }, + { 0.000292456628571222, 9.16596733530536e-06 }, + { 0.000291526012477477, 9.13680062857472e-06 }, + { 0.00029060672516633, 9.10798898047873e-06 }, + { 0.000289698631213778, 9.07952814665475e-06 }, + { 0.000288801596915122, 9.0514139366254e-06 }, + { 0.000287915490260838, 9.02364221304217e-06 }, + { 0.000287040180912813, 8.99620889094078e-06 }, + { 0.000286175540180955, 8.969109937008e-06 }, + { 0.000285321441000161, 8.9423413688599e-06 }, + { 0.000284477757907645, 8.91589925433124e-06 }, + { 0.000283644367020616, 8.88977971077577e-06 }, + { 0.000282821146014292, 8.86397890437735e-06 }, + { 0.000282007974100266, 8.83849304947175e-06 }, + { 0.000281204732005191, 8.81331840787865e-06 }, + { 0.000280411301949796, 8.78845128824411e-06 }, + { 0.000279627567628232, 8.76388804539298e-06 }, + { 0.000278853414187717, 8.73962507969124e-06 }, + { 0.000278088728208509, 8.71565883641806e-06 }, + { 0.000277333397684169, 8.69198580514747e-06 }, + { 0.000276587312002138, 8.66860251913942e-06 }, + { 0.000275850361924599, 8.64550555474003e-06 }, + { 0.000275122439569634, 8.62269153079109e-06 }, + { 0.000274403438392663, 8.60015710804828e-06 }, + { 0.000273693253168171, 8.57789898860844e-06 }, + { 0.000272991779971702, 8.55591391534531e-06 }, + { 0.00027229891616213, 8.53419867135382e-06 }, + { 0.000271614560364196, 8.51275007940282e-06 }, + { 0.000270938612451306, 8.49156500139591e-06 }, + { 0.000270270973528589, 8.4706403378405e-06 }, + { 0.000269611545916208, 8.44997302732471e-06 }, + { 0.000268960233132921, 8.42956004600218e-06 }, + { 0.000268316939879889, 8.40939840708456e-06 }, + { 0.000267681572024721, 8.38948516034154e-06 }, + { 0.000267054036585764, 8.36981739160835e-06 }, + { 0.00026643424171662, 8.35039222230062e-06 }, + { 0.000265822096690896, 8.33120680893638e-06 }, + { 0.000265217511887183, 8.31225834266522e-06 }, + { 0.00026462039877425, 8.29354404880439e-06 }, + { 0.000264030669896463, 8.27506118638174e-06 }, + { 0.000263448238859422, 8.25680704768544e-06 }, + { 0.000262873020315798, 8.23877895782036e-06 }, + { 0.000262304929951393, 8.22097427427094e-06 }, + { 0.000261743884471393, 8.2033903864705e-06 }, + { 0.000261189801586834, 8.18602471537687e-06 }, + { 0.000260642600001254, 8.16887471305427e-06 }, + { 0.000260102199397551, 8.1519378622613e-06 }, + { 0.000259568520425027, 8.13521167604492e-06 }, + { 0.000259041484686624, 8.1186936973404e-06 }, + { 0.000258521014726347, 8.10238149857707e-06 }, + { 0.000258007034016864, 8.08627268128983e-06 }, + { 0.000257499466947295, 8.07036487573632e-06 }, + { 0.00025699823881117, 8.05465574051958e-06 }, + { 0.000256503275794569, 8.03914296221629e-06 }, + { 0.000256014504964425, 8.02382425501026e-06 }, + { 0.000255531854257008, 8.00869736033135e-06 }, + { 0.000255055252466562, 7.99376004649949e-06 }, + { 0.000254584629234115, 7.97901010837388e-06 }, + { 0.000254119915036445, 7.96444536700726e-06 }, + { 0.000253661041175211, 7.95006366930512e-06 }, + { 0.00025320793976623, 7.93586288768977e-06 }, + { 0.000252760543728917, 7.9218409197693e-06 }, + { 0.000252318786775872, 7.90799568801124e-06 }, + { 0.000251882603402616, 7.89432513942084e-06 }, + { 0.000251451928877473, 7.88082724522403e-06 }, + { 0.000251026699231597, 7.86750000055481e-06 }, + { 0.000250606851249143, 7.85434142414719e-06 }, + { 0.000250192322457572, 7.84134955803137e-06 }, + { 0.000249783051118102, 7.82852246723438e-06 }, + { 0.000249378976216284, 7.81585823948488e-06 }, + { 0.000248980037452722, 7.80335498492211e-06 }, + { 0.000248586175233917, 7.79101083580909e-06 }, + { 0.000248197330663242, 7.77882394624965e-06 }, + { 0.000247813445532044, 7.7667924919097e-06 }, + { 0.000247434462310875, 7.75491466974223e-06 }, + { 0.000247060324140839, 7.74318869771626e-06 }, + { 0.000246690974825069, 7.73161281454955e-06 }, + { 0.000246326358820315, 7.7201852794452e-06 }, + { 0.000245966421228658, 7.70890437183165e-06 }, + { 0.000245611107789332, 7.69776839110668e-06 }, + { 0.000245260364870666, 7.68677565638466e-06 }, + { 0.000244914139462137, 7.67592450624751e-06 }, + { 0.000244572379166531, 7.66521329849911e-06 }, + { 0.000244235032192219, 7.65464040992306e-06 }, + { 0.00024390204734553, 7.64420423604383e-06 }, + { 0.000243573374023243, 7.6339031908913e-06 }, + { 0.000243248962205172, 7.62373570676844e-06 }, + { 0.000242928762446859, 7.61370023402224e-06 }, + { 0.000242612725872367, 7.60379524081794e-06 }, + { 0.000242300804167173, 7.59401921291612e-06 }, + { 0.000241992949571156, 7.58437065345312e-06 }, + { 0.000241689114871685, 7.5748480827243e-06 }, + { 0.000241389253396802, 7.56545003797038e-06 }, + { 0.000241093319008495, 7.55617507316665e-06 }, + { 0.000240801266096067, 7.54702175881514e-06 }, + { 0.000240513049569594, 7.53798868173957e-06 }, + { 0.000240228624853473, 7.52907444488312e-06 }, + { 0.000239947947880057, 7.52027766710902e-06 }, + { 0.000239670975083379, 7.51159698300375e-06 }, + { 0.000239397663392959, 7.50303104268302e-06 }, + { 0.0002391279702277, 7.49457851160037e-06 }, + { 0.000238861853489856, 7.4862380703583e-06 }, + { 0.000238599271559098, 7.47800841452205e-06 }, + { 0.000238340183286646, 7.46988825443591e-06 }, + { 0.00023808454798949, 7.46187631504191e-06 }, + { 0.000237832325444681, 7.45397133570105e-06 }, + { 0.000237583475883706, 7.44617207001697e-06 }, + { 0.000237337959986938, 7.43847728566188e-06 }, + { 0.000237095738878156, 7.43088576420496e-06 }, + { 0.000236856774119144, 7.42339630094302e-06 }, + { 0.000236621027704358, 7.41600770473338e-06 }, + { 0.000236388462055669, 7.4087187978291e-06 }, + { 0.000236159040017174, 7.40152841571632e-06 }, + { 0.000235932724850077, 7.39443540695386e-06 }, + { 0.000235709480227638, 7.3874386330149e-06 }, + { 0.000235489270230188, 7.38053696813082e-06 }, + { 0.000235272059340217, 7.37372929913705e-06 }, + { 0.000235057812437519, 7.36701452532112e-06 }, + { 0.000234846494794405, 7.36039155827256e-06 }, + { 0.000234638072070982, 7.35385932173491e-06 }, + { 0.000234432510310492, 7.34741675145965e-06 }, + { 0.000234229775934714, 7.34106279506207e-06 }, + { 0.000234029835739425, 7.33479641187909e-06 }, + { 0.000233832656889924, 7.32861657282887e-06 }, + { 0.000233638206916612, 7.32252226027239e-06 }, + { 0.000233446453710633, 7.31651246787674e-06 }, + { 0.000233257365519571, 7.31058620048032e-06 }, + { 0.000233070910943204, 7.30474247395975e-06 }, + { 0.000232887058929314, 7.29898031509851e-06 }, + { 0.000232705778769551, 7.29329876145742e-06 }, + { 0.000232527040095355, 7.28769686124665e-06 }, + { 0.000232350812873926, 7.28217367319956e-06 }, + { 0.000232177067404248, 7.27672826644812e-06 }, + { 0.000232005774313171, 7.27135972039995e-06 }, + { 0.000231836904551536, 7.26606712461701e-06 }, + { 0.000231670429390354, 7.26084957869582e-06 }, + { 0.000231506320417039, 7.25570619214929e-06 }, + { 0.000231344549531681, 7.25063608429008e-06 }, + { 0.000231185088943374, 7.24563838411543e-06 }, + { 0.000231027911166592, 7.24071223019354e-06 }, + { 0.000230872989017609, 7.23585677055142e-06 }, + { 0.000230720295610964, 7.23107116256415e-06 }, + { 0.00023056980435598, 7.22635457284561e-06 }, + { 0.000230421488953316, 7.22170617714064e-06 }, + { 0.000230275323391574, 7.21712516021853e-06 }, + { 0.000230131281943947, 7.21261071576797e-06 }, + { 0.000229989339164902, 7.20816204629325e-06 }, + { 0.000229849469886921, 7.2037783630119e-06 }, + { 0.00022971164921727, 7.19945888575361e-06 }, + { 0.000229575852534817, 7.19520284286036e-06 }, + { 0.000229442055486887, 7.19100947108804e-06 }, + { 0.000229310233986165, 7.18687801550907e-06 }, + { 0.000229180364207623, 7.18280772941651e-06 }, + { 0.000229052422585508, 7.17879787422921e-06 }, + { 0.000228926385810346, 7.17484771939831e-06 }, + { 0.000228802230826003, 7.17095654231483e-06 }, + { 0.000228679934826769, 7.16712362821851e-06 }, + { 0.000228559475254493, 7.16334827010778e-06 }, + { 0.000228440829795738, 7.15962976865087e-06 }, + { 0.000228323976378991, 7.15596743209809e-06 }, + { 0.000228208893171893, 7.15236057619517e-06 }, + { 0.000228095558578508, 7.14880852409773e-06 }, + { 0.000227983951236635, 7.14531060628687e-06 }, + { 0.000227874050015145, 7.14186616048574e-06 }, + { 0.000227765834011349, 7.13847453157724e-06 }, + { 0.000227659282548415, 7.13513507152274e-06 }, + { 0.000227554375172797, 7.13184713928183e-06 }, + { 0.000227451091651713, 7.12861010073307e-06 }, + { 0.000227349411970649, 7.12542332859577e-06 }, + { 0.000227249316330887, 7.12228620235266e-06 }, + { 0.000227150785147081, 7.11919810817373e-06 }, + { 0.000227053799044843, 7.11615843884078e-06 }, + { 0.00022695833885838, 7.11316659367312e-06 }, + { 0.000226864385628144, 7.1102219784541e-06 }, + { 0.000226771920598518, 7.10732400535858e-06 }, + { 0.000226680925215536, 7.10447209288133e-06 }, + { 0.000226591381124622, 7.10166566576629e-06 }, + { 0.000226503270168361, 7.09890415493677e-06 }, + { 0.000226416574384305, 7.09618699742645e-06 }, + { 0.000226331276002794, 7.09351363631131e-06 }, + { 0.000226247357444811, 7.09088352064235e-06 }, + { 0.000226164801319867, 7.08829610537922e-06 }, + { 0.000226083590423903, 7.08575085132458e-06 }, + { 0.000226003707737228, 7.08324722505939e-06 }, + { 0.000225925136422475, 7.08078469887889e-06 }, + { 0.000225847859822588, 7.07836275072949e-06 }, + { 0.000225771861458829, 7.07598086414632e-06 }, + { 0.000225697125028814, 7.07363852819168e-06 }, + { 0.00022562363440457, 7.07133523739415e-06 }, + { 0.000225551373630622, 7.06907049168853e-06 }, + { 0.000225480326922091, 7.06684379635645e-06 }, + { 0.000225410478662832, 7.06465466196781e-06 }, + { 0.000225341813403584, 7.06250260432282e-06 }, + { 0.000225274315860142, 7.0603871443949e-06 }, + { 0.000225207970911563, 7.05830780827414e-06 }, + { 0.000225142763598378, 7.05626412711159e-06 }, + { 0.000225078679120841, 7.0542556370641e-06 }, + { 0.000225015702837188, 7.05228187923999e-06 }, + { 0.000224953820261928, 7.05034239964525e-06 }, + { 0.000224893017064143, 7.0484367491305e-06 }, + { 0.00022483327906582, 7.04656448333854e-06 }, + { 0.000224774592240197, 7.04472516265258e-06 }, + { 0.00022471694271013, 7.0429183521451e-06 }, + { 0.000224660316746486, 7.04114362152733e-06 }, + { 0.000224604700766543, 7.03940054509932e-06 }, + { 0.000224550081332424, 7.0376887017007e-06 }, + { 0.000224496445149543, 7.03600767466198e-06 }, + { 0.000224443779065066, 7.03435705175644e-06 }, + { 0.000224392070066399, 7.03273642515265e-06 }, + { 0.000224341305279693, 7.03114539136756e-06 }, + { 0.00022429147196836, 7.02958355122011e-06 }, + { 0.000224242557531616, 7.02805050978552e-06 }, + { 0.000224194549503038, 7.02654587635001e-06 }, + { 0.000224147435549135, 7.02506926436614e-06 }, + { 0.000224101203467946, 7.02362029140872e-06 }, + { 0.000224055841187646, 7.02219857913119e-06 }, + { 0.000224011336765172, 7.02080375322257e-06 }, + { 0.000223967678384865, 7.01943544336494e-06 }, + { 0.000223924854357133, 7.01809328319141e-06 }, + { 0.000223882853117125, 7.01677691024464e-06 }, + { 0.000223841663223422, 7.01548596593582e-06 }, + { 0.000223801273356745, 7.01422009550419e-06 }, + { 0.000223761672318679, 7.01297894797702e-06 }, + { 0.000223722849030413, 7.0117621761301e-06 }, + { 0.000223684792531494, 7.01056943644869e-06 }, + { 0.000223647491978595, 7.00940038908897e-06 }, + { 0.000223610936644299, 7.00825469783991e-06 }, + { 0.000223575115915903, 7.00713203008568e-06 }, + { 0.000223540019294225, 7.00603205676844e-06 }, + { 0.000223505636392438, 7.00495445235162e-06 }, + { 0.000223471956934907, 7.00389889478363e-06 }, + { 0.000223438970756052, 7.00286506546206e-06 }, + { 0.000223406667799211, 7.0018526491982e-06 }, + { 0.000223375038115529, 7.00086133418212e-06 }, + { 0.000223344071862854, 6.99989081194811e-06 }, + { 0.000223313759304649, 6.99894077734052e-06 }, + { 0.000223284090808912, 6.99801092848006e-06 }, + { 0.000223255056847118, 6.99710096673047e-06 }, + { 0.000223226647993168, 6.99621059666565e-06 }, + { 0.000223198854922349, 6.99533952603709e-06 }, + { 0.000223171668410312, 6.99448746574181e-06 }, + { 0.000223145079332057, 6.9936541297906e-06 }, + { 0.000223119078660938, 6.9928392352767e-06 }, + { 0.000223093657467669, 6.99204250234482e-06 }, + { 0.000223068806919352, 6.99126365416057e-06 }, + { 0.000223044518278512, 6.99050241688022e-06 }, + { 0.000223020782902146, 6.98975851962088e-06 }, + { 0.000222997592240777, 6.98903169443101e-06 }, + { 0.000222974937837531, 6.98832167626126e-06 }, + { 0.000222952811327217, 6.98762820293573e-06 }, + { 0.000222931204435415, 6.98695101512352e-06 }, + { 0.00022291010897759, 6.98628985631068e-06 }, + { 0.000222889516858196, 6.98564447277244e-06 }, + { 0.000222869420069809, 6.98501461354579e-06 }, + { 0.000222849810692261, 6.98440003040248e-06 }, + { 0.000222830680891787, 6.98380047782221e-06 }, + { 0.000222812022920181, 6.98321571296625e-06 }, + { 0.000222793829113966, 6.98264549565134e-06 }, + { 0.000222776091893569, 6.9820895883239e-06 }, + { 0.000222758803762509, 6.98154775603461e-06 }, + { 0.000222741957306598, 6.9810197664132e-06 }, + { 0.000222725545193143, 6.98050538964365e-06 }, + { 0.000222709560170165, 6.98000439843966e-06 }, + { 0.000222693995065629, 6.97951656802032e-06 }, + { 0.000222678842786674, 6.97904167608631e-06 }, + { 0.000222664096318863, 6.97857950279612e-06 }, + { 0.000222649748725436, 6.97812983074274e-06 }, + { 0.000222635793146573, 6.97769244493061e-06 }, + { 0.000222622222798669, 6.97726713275278e-06 }, + { 0.000222609030973612, 6.97685368396842e-06 }, + { 0.000222596211038079, 6.97645189068058e-06 }, + { 0.000222583756432828, 6.97606154731424e-06 }, + { 0.000222571660672013, 6.97568245059462e-06 }, + { 0.000222559917342496, 6.97531439952571e-06 }, + { 0.000222548520103175, 6.97495719536918e-06 }, + { 0.000222537462684313, 6.97461064162342e-06 }, + { 0.000222526738886884, 6.97427454400296e-06 }, + { 0.000222516342581918, 6.97394871041804e-06 }, + { 0.000222506267709865, 6.97363295095449e-06 }, + { 0.000222496508279953, 6.97332707785385e-06 }, + { 0.000222487058369568, 6.97303090549378e-06 }, + { 0.000222477912123634, 6.97274425036857e-06 }, + { 0.000222469063753997, 6.97246693107012e-06 }, + { 0.000222460507538829, 6.97219876826893e-06 }, + { 0.000222452237822028, 6.97193958469549e-06 }, + { 0.000222444249012631, 6.97168920512181e-06 }, + { 0.000222436535584233, 6.97144745634325e-06 }, + { 0.000222429092074413, 6.97121416716051e-06 }, + { 0.00022242191308417, 6.97098916836191e-06 }, + { 0.000222414993277359, 6.97077229270584e-06 }, + { 0.000222408327380145, 6.97056337490348e-06 }, + { 0.000222401910180452, 6.9703622516017e-06 }, + { 0.000222395736527431, 6.97016876136623e-06 }, + { 0.000222389801330924, 6.96998274466495e-06 }, + { 0.000222384099560941, 6.96980404385152e-06 }, + { 0.000222378626247142, 6.96963250314908e-06 }, + { 0.000222373376478328, 6.96946796863433e-06 }, + { 0.000222368345401933, 6.96931028822161e-06 }, + { 0.000222363528223529, 6.96915931164736e-06 }, + { 0.000222358920206333, 6.96901489045469e-06 }, + { 0.000222354516670721, 6.96887687797819e-06 }, + { 0.000222350312993751, 6.96874512932889e-06 }, + { 0.000222346304608691, 6.9686195013795e-06 }, + { 0.000222342487004547, 6.96849985274972e-06 }, + { 0.000222338855725611, 6.96838604379187e-06 }, + { 0.000222335406371001, 6.96827793657665e-06 }, + { 0.000222332134594212, 6.96817539487904e-06 }, + { 0.00022232903610268, 6.9680782841645e-06 }, + { 0.000222326106657339, 6.96798647157525e-06 }, + { 0.000222323342072192, 6.96789982591681e-06 }, + { 0.00022232073821389, 6.96781821764464e-06 }, + { 0.000222318291001307, 6.96774151885102e-06 }, + { 0.000222315996405131, 6.96766960325212e-06 }, + { 0.000222313850447455, 6.9676023461752e-06 }, + { 0.000222311849201372, 6.96753962454597e-06 }, + { 0.000222309988790583, 6.96748131687619e-06 }, + { 0.000222308265389002, 6.96742730325142e-06 }, + { 0.00022230667522037, 6.96737746531884e-06 }, + { 0.000222305214557877, 6.96733168627542e-06 }, + { 0.000222303879723785, 6.96728985085609e-06 }, + { 0.000222302667089056, 6.96725184532218e-06 }, + { 0.00022230157307299, 6.96721755744993e-06 }, + { 0.000222300594142867, 6.96718687651929e-06 }, + { 0.000222299726813584, 6.96715969330272e-06 }, + { 0.000222298967647317, 6.96713590005431e-06 }, + { 0.000222298313253165, 6.96711539049893e-06 }, + { 0.000222297760286819, 6.96709805982159e-06 }, + { 0.000222297305450222, 6.96708380465697e-06 }, + { 0.000222296945491244, 6.96707252307908e-06 }, + { 0.000222296677203351, 6.96706411459103e-06 }, + { 0.000222296497425289, 6.96705848011506e-06 }, + { 0.000222296403040767, 6.96705552198261e-06 }, + { 0.000222296390978148, 6.96705514392459e-06 }, + { 0.00022229645821014, 6.9670572510618e-06 }, + { 0.000222296601753497, 6.96706174989544e-06 }, + { 0.00022229681866872, 6.96706854829785e-06 }, + { 0.000222297106059767, 6.96707755550335e-06 }, + { 0.000222297461073765, 6.96708868209918e-06 }, + { 0.000222297880900723, 6.96710184001666e-06 }, + { 0.000222298362773258, 6.96711694252242e-06 }, + { 0.000222298903966318, 6.96713390420982e-06 }, + { 0.000222299501796913, 6.96715264099048e-06 }, + { 0.000222300153623846, 6.96717307008593e-06 }, + { 0.000222300856847458, 6.96719511001945e-06 }, + { 0.000222301608909363, 6.96721868060799e-06 }, + { 0.000222302407292202, 6.96724370295423e-06 }, + { 0.000222303249519389, 6.96727009943883e-06 }, + { 0.000222304133154872, 6.9672977937127e-06 }, + { 0.000222305055802884, 6.96732671068952e-06 }, + { 0.000222306015107718, 6.96735677653831e-06 }, + { 0.000222307008753485, 6.96738791867615e-06 }, + { 0.00022230803446389, 6.96742006576105e-06 }, + { 0.000222309090002009, 6.96745314768489e-06 }, + { 0.000222310173170065, 6.96748709556656e-06 }, + { 0.000222311281809216, 6.96752184174516e-06 }, + { 0.000222312413799341, 6.96755731977334e-06 }, + { 0.000222313567058831, 6.9675934644108e-06 }, + { 0.000222314739544384, 6.96763021161786e-06 }, + { 0.000222315929250809, 6.9676674985492e-06 }, + { 0.000222317134210823, 6.96770526354765e-06 }, + { 0.000222318352494862, 6.96774344613821e-06 }, + { 0.00022231958221089, 6.96778198702204e-06 }, + { 0.000222320821504217, 6.96782082807073e-06 }, + { 0.000222322068557312, 6.96785991232055e-06 }, + { 0.00022232332158963, 6.96789918396693e-06 }, + { 0.000222324578857435, 6.96793858835893e-06 }, + { 0.000222325838653631, 6.96797807199396e-06 }, + { 0.000222327099307595, 6.96801758251253e-06 }, + { 0.000222328359185012, 6.96805706869312e-06 }, + { 0.000222329616687717, 6.96809648044717e-06 }, + { 0.000222330870253539, 6.96813576881426e-06 }, + { 0.000222332118356149, 6.96817488595722e-06 }, + { 0.000222333359504908, 6.96821378515757e-06 }, + { 0.000222334592244728, 6.9682524208109e-06 }, + { 0.000222335815155921, 6.96829074842245e-06 }, + { 0.000222337026854071, 6.96832872460277e-06 }, + { 0.000222338225989891, 6.96836630706349e-06 }, + { 0.000222339411249095, 6.96840345461321e-06 }, + { 0.000222340581352271, 6.96844012715348e-06 }, + { 0.000222341735054754, 6.9684762856749e-06 }, + { 0.000222342871146506, 6.96851189225336e-06 }, + { 0.000222343988452, 6.96854691004629e-06 }, + { 0.000222345085830103, 6.96858130328914e-06 }, + { 0.000222346162173967, 6.96861503729185e-06 }, + { 0.000222347216410921, 6.96864807843553e-06 }, + { 0.000222348247502366, 6.96868039416915e-06 }, + { 0.000222349254443676, 6.96871195300643e-06 }, + { 0.000222350236264097, 6.96874272452272e-06 }, + { 0.000222351192026658, 6.96877267935211e-06 }, + { 0.000222352120828075, 6.96880178918454e-06 }, + { 0.000222353021798667, 6.96883002676308e-06 }, + { 0.00022235389410227, 6.96885736588125e-06 }, + { 0.000222354736936155, 6.96888378138053e-06 }, + { 0.000222355549530953, 6.96890924914787e-06 }, + { 0.000222356331150578, 6.96893374611341e-06 }, + { 0.000222357081092156, 6.96895725024817e-06 }, + { 0.000222357798685959, 6.968979740562e-06 }, + { 0.000222358483295338, 6.96900119710148e-06 }, + { 0.000222359134316659, 6.96902160094803e-06 }, + { 0.000222359751179253, 6.96904093421604e-06 }, + { 0.00022236033334535, 6.96905918005118e-06 }, + { 0.000222360880310035, 6.96907632262873e-06 }, + { 0.000222361391601196, 6.9690923471521e-06 }, + { 0.000222361866779477, 6.96910723985132e-06 }, + { 0.00022236230543824, 6.9691209879818e-06 }, + { 0.000222362707203519, 6.96913357982301e-06 }, + { 0.000222363071733991, 6.96914500467741e-06 }, + { 0.000222363398720938, 6.96915525286938e-06 }, + { 0.000222363687888218, 6.9691643157443e-06 }, + { 0.000222363938992241, 6.96917218566772e-06 }, + { 0.000222364151821941, 6.96917885602458e-06 }, + { 0.00022236432619876, 6.96918432121863e-06 }, + { 0.000222364461976628, 6.96918857667186e-06 }, + { 0.000222364559041949, 6.96919161882402e-06 }, + { 0.000222364617313593, 6.96919344513236e-06 }, + { 0.000222364636742882, 6.96919405407131e-06 } +}; + +static const double cumulative[][2] = { /* Expected-value Standard-error */ + { 0, 0 }, + { 0.000864844260437307, 3.2341771480318e-07 }, + { 0.00344930442295799, 1.28922086184407e-06 }, + { 0.00772342489639333, 2.88440311042538e-06 }, + { 0.0136381440658139, 5.08839733657585e-06 }, + { 0.0211265568432882, 7.87462036133179e-06 }, + { 0.030105615859244, 1.12124077014868e-05 }, + { 0.0404782086271475, 1.50691397344185e-05 }, + { 0.0521355351853953, 1.94123434019322e-05 }, + { 0.064959701316185, 2.42115614276198e-05 }, + { 0.0788264368270804, 2.94398141358595e-05 }, + { 0.0936078467237508, 3.50745339582566e-05 }, + { 0.109175105365968, 4.10979224905411e-05 }, + { 0.125401009650726, 4.74967542955343e-05 }, + { 0.142162316497224, 5.42617187953981e-05 }, + { 0.159341801859359, 6.13864407185916e-05 }, + { 0.176829992489236, 6.88663433171346e-05 }, + { 0.194526536975521, 7.66975149621118e-05 }, + { 0.212341198407353, 8.4875712520328e-05 }, + { 0.230194466607499, 9.33955923107457e-05 }, + { 0.24801780252962, 0.000102250211571378 }, + { 0.265753540505306, 0.000111430799564632 }, + { 0.283354485055534, 0.000120926764190608 }, + { 0.300783247582665, 0.000130725880067631 }, + { 0.318011374214993, 0.000140814596964091 }, + { 0.335018319317342, 0.000151178410498962 }, + { 0.351790319779196, 0.000161802246533291 }, + { 0.368319223346885, 0.000172670823165794 }, + { 0.384601320283121, 0.00018376896701735 }, + { 0.400636221901663, 0.000195081871806809 }, + { 0.416425822478427, 0.000206595296209532 }, + { 0.431973373145809, 0.000218295704393061 }, + { 0.447282688098255, 0.000230170356552949 }, + { 0.462357495207975, 0.000242207358540825 }, + { 0.477200935359891, 0.000254395679712666 }, + { 0.491815207784957, 0.000266725146938042 }, + { 0.506201352653573, 0.000279186420862364 }, + { 0.520359157352388, 0.000291770958567995 }, + { 0.534287169299197, 0.000304470965219102 }, + { 0.547982795865094, 0.000317279336409391 }, + { 0.56144247091594, 0.000330189592836309 }, + { 0.574661867547176, 0.000343195809435291 }, + { 0.587636137613502, 0.000356292541885506 }, + { 0.600360160462158, 0.000369474754049006 }, + { 0.612828785672205, 0.000382737750106708 }, + { 0.625037057372635, 0.000396077114756507 }, + { 0.63698041067509, 0.000409488663894224 }, + { 0.648654833727208, 0.000422968406925844 }, + { 0.660056991728365, 0.000436512520552392 }, + { 0.67118431182307, 0.00045011733278923 }, + { 0.682035030008706, 0.000463779315283788 }, + { 0.692608203010149, 0.000477495081697928 }, + { 0.702903689447356, 0.00049126138993707 }, + { 0.712922105558505, 0.000505075146206906 }, + { 0.722664761256772, 0.000518933409153025 }, + { 0.732133582433861, 0.000532833392642378 }, + { 0.741331025230595, 0.000546772466092471 }, + { 0.750259987532168, 0.000560748151683091 }, + { 0.75892372228239, 0.000574758118312188 }, + { 0.767325756405806, 0.000588800172740126 }, + { 0.77546981824811, 0.000602872248904067 }, + { 0.783359775543789, 0.000616972396742587 }, + { 0.790999585049822, 0.000631098771943508 }, + { 0.798393254182973, 0.000645249627770496 }, + { 0.805544814298637, 0.000659423309594575 }, + { 0.812458304673771, 0.000673618252086996 }, + { 0.819137765816567, 0.000687832978404178 }, + { 0.825587240428692, 0.00070206610027095 }, + { 0.831810780184676, 0.000716316317748075 }, + { 0.837812456461413, 0.000730582417656064 }, + { 0.843596373230034, 0.000744863270040965 }, + { 0.849166680493882, 0.000759157822573074 }, + { 0.85452758689938, 0.000773465093222372 }, + { 0.859683370431826, 0.000787784161846291 }, + { 0.864638386419449, 0.000802114161410069 }, + { 0.869397072377219, 0.00081645426946008 }, + { 0.873963949511423, 0.000830803700256753 }, + { 0.878343620960373, 0.000845161697746157 }, + { 0.882540767052266, 0.000859527529385224 }, + { 0.88656013801421, 0.000873900480786482 }, + { 0.890406544662638, 0.000888279851206406 }, + { 0.894084847647596, 0.000902664950019421 }, + { 0.8975999458178, 0.000917055094424582 }, + { 0.900956764229264, 0.000931449608650079 }, + { 0.904160242246884, 0.000945847824815999 }, + { 0.907215322098614, 0.000960249085393435 }, + { 0.910126938145628, 0.000974652746914947 }, + { 0.912900007038343, 0.000989058184337327 }, + { 0.91553941884556, 0.00100346479531913 }, + { 0.918050029175696, 0.00101787200371079 }, + { 0.920436652259082, 0.00103227926176418 }, + { 0.922704054924983, 0.00104668605089567 }, + { 0.924856951387888, 0.00106109188118045 }, + { 0.926899998747835, 0.00107549629001193 }, + { 0.928837793104644, 0.0010898988404525 }, + { 0.930674866185846, 0.00110429911971198 }, + { 0.932415682382857, 0.00111869673796555 }, + { 0.934064636084289, 0.00113309132745234 }, + { 0.935626049185173, 0.00114748254158513 }, + { 0.937104168637491, 0.00116187005372508 }, + { 0.938503163898304, 0.00117625355535994 }, + { 0.939827124123015, 0.00119063275363397 }, + { 0.941080054954988, 0.00120500736843739 }, + { 0.942265874777131, 0.00121937712948441 }, + { 0.943388410319858, 0.00123374177391474 }, + { 0.944451391565877, 0.00124810104491599 }, + { 0.945458445950797, 0.00126245469169204 }, + { 0.946413091930008, 0.00127680247084348 }, + { 0.947318732058611, 0.00129114414894445 }, + { 0.948178645806433, 0.00130547950586069 }, + { 0.94899598239924, 0.00131980833819983 }, + { 0.9497737540286, 0.00133413046224784 }, + { 0.950514829803614, 0.0013484457158288 }, + { 0.951221930820914, 0.00136275395871461 }, + { 0.95189762670444, 0.00137705507147841 }, + { 0.952544333909601, 0.00139134895298305 }, + { 0.953164316006814, 0.00140563551696505 }, + { 0.953759686055019, 0.00141991468835756 }, + { 0.954332411060469, 0.001434186400043 }, + { 0.954884318395864, 0.00144845059061537 }, + { 0.955417103938939, 0.00146270720348639 }, + { 0.955932341589961, 0.00147695618733997 }, + { 0.956431493748457, 0.00149119749761648 }, + { 0.956915922280999, 0.00150543109847399 }, + { 0.957386899494419, 0.00151965696459107 }, + { 0.957845618645373, 0.00153387508226248 }, + { 0.958293203564012, 0.00154808544945412 }, + { 0.95873071704446, 0.00156228807476128 }, + { 0.959159167748055, 0.00157648297545728 }, + { 0.959579515472819, 0.00159067017496462 }, + { 0.95999267475144, 0.00160484970009607 }, + { 0.96039951684733, 0.00161902157831515 }, + { 0.960800870309794, 0.00163318583511642 }, + { 0.961197520325387, 0.00164734249149334 }, + { 0.961590207155522, 0.0016614915614119 }, + { 0.961979623978106, 0.00167563304925737 }, + { 0.962366414455474, 0.00168976694735972 }, + { 0.962751170331964, 0.0017038932338655 }, + { 0.963134429327794, 0.00171801187134215 }, + { 0.963516673542005, 0.00173212280651286 }, + { 0.963898328518127, 0.00174622597139297 }, + { 0.964279763058726, 0.00176032128585476 }, + { 0.964661289811319, 0.00177440866134504 }, + { 0.965043166589692, 0.00178848800520305 }, + { 0.965425598343577, 0.00180255922486943 }, + { 0.96580873965189, 0.00181662223129111 }, + { 0.966192697589875, 0.00183067694102797 }, + { 0.966577534807986, 0.00184472327690428 }, + { 0.966963272662575, 0.00185876116742914 }, + { 0.967349894252373, 0.00187279054552704 }, + { 0.967737347237796, 0.00188681134727247 }, + { 0.968125546352698, 0.0019008235112651 }, + { 0.96851437555474, 0.00191482697903286 }, + { 0.968903689799959, 0.00192882169648674 }, + { 0.969293316467073, 0.0019428076160933 }, + { 0.969683056490542, 0.00195678469919398 }, + { 0.970072685294235, 0.00197075291785552 }, + { 0.97046195363683, 0.00198471225579347 }, + { 0.970850588493419, 0.00199866270820161 }, + { 0.971238294099558, 0.00201260428063239 }, + { 0.971624753273908, 0.00202653698729763 }, + { 0.972009629116019, 0.00204046084921118 }, + { 0.972392567148178, 0.00205437589247977 }, + { 0.972773197934457, 0.00206828214682375 }, + { 0.973151140171804, 0.00208217964419359 }, + { 0.973526004209467, 0.00209606841724322 }, + { 0.973897395918181, 0.00210994849749593 }, + { 0.974264920800317, 0.00212381991326614 }, + { 0.974628188214181, 0.00213768268769865 }, + { 0.974986815577298, 0.00215153683750943 }, + { 0.975340432417114, 0.00216538237304278 }, + { 0.975688684153943, 0.00217921930003463 }, + { 0.976031235527663, 0.00219304762302002 }, + { 0.976367773611921, 0.00220686734977916 }, + { 0.976698010398196, 0.00222067849575036 }, + { 0.977021684966998, 0.00223448108713146 }, + { 0.977338565297302, 0.0022482751615428 }, + { 0.977648449785131, 0.00226206076563903 }, + { 0.976959698305536, 0.000719254180160381 }, + { 0.977271116580268, 0.000729014429903263 }, + { 0.977576967188632, 0.000738600181812663 }, + { 0.977877374606276, 0.000748015337115725 }, + { 0.978172459910358, 0.00075726369052647 }, + { 0.978462340889919, 0.000766348933705155 }, + { 0.978747132152104, 0.000775274658587222 }, + { 0.979026945224402, 0.000784044360587866 }, + { 0.979301888653079, 0.000792661441686746 }, + { 0.979572068097951, 0.000801129213398638 }, + { 0.979837586423683, 0.000809450899634553 }, + { 0.980098543787712, 0.000817629639457557 }, + { 0.980355037724988, 0.000825668489738588 }, + { 0.980607163229618, 0.000833570427715265 }, + { 0.980855012833574, 0.000841338353458721 }, + { 0.981098676682566, 0.000848975092251657 }, + { 0.981338242609211, 0.00085648339688133 }, + { 0.981573796203589, 0.000863865949851062 }, + { 0.98180542088131, 0.00087112536551353 }, + { 0.982033197949185, 0.000878264192128858 }, + { 0.982257206668591, 0.000885284913850685 }, + { 0.982477524316635, 0.000892189952643032 }, + { 0.982694226245188, 0.000898981670130554 }, + { 0.982907385937888, 0.000905662369385131 }, + { 0.983117075065182, 0.000912234296650864 }, + { 0.983323363537495, 0.000918699643010445 }, + { 0.983526319556571, 0.000925060545994409 }, + { 0.983726009665104, 0.000931319091136429 }, + { 0.983922498794673, 0.000937477313475817 }, + { 0.984115850312084, 0.000943537199009889 }, + { 0.984306126064161, 0.000949500686097735 }, + { 0.984493386421052, 0.000955369666817512 }, + { 0.984677690318101, 0.000961145988278837 }, + { 0.984859095296345, 0.000966831453891858 }, + { 0.985037657541685, 0.000972427824595134 }, + { 0.985213431922783, 0.000977936820043089 }, + { 0.985386472027721, 0.000983360119755297 }, + { 0.985556830199487, 0.000988699364228364 }, + { 0.985724557570317, 0.000993956156012382 }, + { 0.98588970409493, 0.000999132060752665 }, + { 0.986052318582724, 0.0010042286081985 }, + { 0.986212448728929, 0.00100924729317987 }, + { 0.986370141144792, 0.00101418957655327 }, + { 0.986525441386809, 0.00101905688611793 }, + { 0.986678393985039, 0.00102385061750325 }, + { 0.986829042470546, 0.00102857213502882 }, + { 0.986977429401977, 0.00103322277253745 }, + { 0.987123596391332, 0.00103780383420282 }, + { 0.987267584128935, 0.00104231659531205 }, + { 0.987409432407642, 0.00104676230302451 }, + { 0.987549180146316, 0.00105114217710745 }, + { 0.987686865412579, 0.00105545741064923 }, + { 0.987822525444893, 0.00105970917075113 }, + { 0.987956196673962, 0.00106389859919834 }, + { 0.9880879147435, 0.00106802681311081 }, + { 0.988217714530384, 0.0010720949055747 }, + { 0.988345630164196, 0.00107610394625509 }, + { 0.988471695046199, 0.00108005498199061 }, + { 0.988595941867753, 0.00108394903737053 }, + { 0.988718402628182, 0.00108778711529487 }, + { 0.98883910865213, 0.00109157019751832 }, + { 0.988958090606404, 0.00109529924517815 }, + { 0.989075378516341, 0.00109897519930698 }, + { 0.989191001781683, 0.00110259898133069 }, + { 0.989304989192021, 0.00110617149355206 }, + { 0.989417368941773, 0.00110969361962051 }, + { 0.989528168644758, 0.00111316622498862 }, + { 0.989637415348332, 0.00111659015735544 }, + { 0.989745135547152, 0.00111996624709756 }, + { 0.989851355196528, 0.00112329530768784 }, + { 0.989956099725412, 0.00112657813610242 }, + { 0.99005939404903, 0.00112981551321654 }, + { 0.99016126258115, 0.0011330082041891 }, + { 0.990261729246017, 0.00113615695883677 }, + { 0.990360817489959, 0.00113926251199766 }, + { 0.99045855029267, 0.00114232558388501 }, + { 0.990554950178194, 0.00114534688043129 }, + { 0.990650039225593, 0.00114832709362277 }, + { 0.990743839079339, 0.00115126690182508 }, + { 0.990836370959422, 0.0011541669701 }, + { 0.990927655671178, 0.00115702795051361 }, + { 0.991017713614864, 0.00115985048243618 }, + { 0.991106564794969, 0.00116263519283417 }, + { 0.99119422882928, 0.00116538269655429 }, + { 0.991280724957704, 0.00116809359660001 }, + { 0.991366072050863, 0.00117076848440093 }, + { 0.991450288618456, 0.00117340794007482 }, + { 0.991533392817405, 0.00117601253268302 }, + { 0.991615402459787, 0.00117858282047892 }, + { 0.991696335020556, 0.00118111935115014 }, + { 0.991776207645073, 0.00118362266205435 }, + { 0.991855037156432, 0.00118609328044894 }, + { 0.9919328400626, 0.00118853172371494 }, + { 0.992009632563381, 0.00119093849957497 }, + { 0.992085430557186, 0.00119331410630576 }, + { 0.992160249647646, 0.00119565903294519 }, + { 0.992234105150049, 0.00119797375949411 }, + { 0.992307012097616, 0.00120025875711301 }, + { 0.992378985247617, 0.00120251448831374 }, + { 0.992450039087337, 0.00120474140714645 }, + { 0.992520187839886, 0.00120693995938176 }, + { 0.992589445469873, 0.0012091105826885 }, + { 0.992657825688932, 0.00121125370680688 }, + { 0.992725341961112, 0.00121336975371758 }, + { 0.992792007508136, 0.00121545913780642 }, + { 0.992857835314529, 0.00121752226602515 }, + { 0.992922838132623, 0.00121955953804822 }, + { 0.992987028487434, 0.0012215713464258 }, + { 0.993050418681426, 0.00122355807673295 }, + { 0.993113020799156, 0.00122552010771523 }, + { 0.993174846711807, 0.00122745781143084 }, + { 0.993235908081614, 0.00122937155338921 }, + { 0.993296216366182, 0.00123126169268645 }, + { 0.9933557828227, 0.00123312858213733 }, + { 0.993414618512052, 0.00123497256840423 }, + { 0.993472734302838, 0.00123679399212309 }, + { 0.993530140875295, 0.00123859318802623 }, + { 0.993586848725121, 0.00124037048506238 }, + { 0.993642868167216, 0.00124212620651376 }, + { 0.993698209339333, 0.00124386067011062 }, + { 0.99375288220564, 0.00124557418814286 }, + { 0.993806896560208, 0.00124726706756919 }, + { 0.993860262030405, 0.00124893961012378 }, + { 0.993912988080223, 0.00125059211242032 }, + { 0.993965084013522, 0.00125222486605376 }, + { 0.9940165589772, 0.00125383815769967 }, + { 0.994067421964295, 0.0012554322692114 }, + { 0.994117681817007, 0.0012570074777149 }, + { 0.994167347229659, 0.00125856405570149 }, + { 0.994216426751589, 0.00126010227111839 }, + { 0.994264928789975, 0.00126162238745739 }, + { 0.994312861612596, 0.00126312466384133 }, + { 0.99436023335053, 0.00126460935510872 }, + { 0.994407052000802, 0.0012660767118965 }, + { 0.99445332542895, 0.00126752698072088 }, + { 0.994499061371561, 0.00126896040405639 }, + { 0.994544267438729, 0.00127037722041322 }, + { 0.994588951116471, 0.00127177766441277 }, + { 0.994633119769087, 0.00127316196686163 }, + { 0.99467678064146, 0.00127453035482384 }, + { 0.994719940861321, 0.00127588305169161 }, + { 0.994762607441448, 0.00127722027725448 }, + { 0.994804787281832, 0.00127854224776702 }, + { 0.994846487171783, 0.00127984917601494 }, + { 0.994887713791997, 0.00128114127137991 }, + { 0.994928473716582, 0.00128241873990287 }, + { 0.994968773415028, 0.00128368178434604 }, + { 0.995008619254151, 0.00128493060425356 }, + { 0.995048017499979, 0.00128616539601086 }, + { 0.99508697431961, 0.00128738635290273 }, + { 0.995125495783026, 0.0012885936651702 }, + { 0.995163587864865, 0.00128978752006616 }, + { 0.995201256446165, 0.00129096810190985 }, + { 0.995238507316058, 0.00129213559214017 }, + { 0.99527534617344, 0.00129329016936787 }, + { 0.995311778628603, 0.00129443200942669 }, + { 0.995347810204827, 0.00129556128542332 }, + { 0.995383446339943, 0.00129667816778648 }, + { 0.995418692387872, 0.00129778282431483 }, + { 0.995453553620112, 0.00129887542022398 }, + { 0.995488035227215, 0.00129995611819249 }, + { 0.995522142320221, 0.00130102507840694 }, + { 0.995555879932066, 0.00130208245860602 }, + { 0.995589253018962, 0.00130312841412382 }, + { 0.99562226646175, 0.00130416309793215 }, + { 0.995654925067221, 0.00130518666068202 }, + { 0.995687233569411, 0.00130619925074427 }, + { 0.995719196630878, 0.00130720101424941 }, + { 0.99575081884394, 0.00130819209512664 }, + { 0.995782104731899, 0.00130917263514205 }, + { 0.995813058750234, 0.00131014277393611 }, + { 0.995843685287773, 0.00131110264906034 }, + { 0.995873988667842, 0.00131205239601332 }, + { 0.995903973149389, 0.00131299214827596 }, + { 0.995933642928086, 0.00131392203734602 }, + { 0.995963002137409, 0.00131484219277203 }, + { 0.995992054849703, 0.00131575274218644 }, + { 0.996020805077213, 0.00131665381133823 }, + { 0.996049256773109, 0.0013175455241248 }, + { 0.996077413832479, 0.00131842800262325 }, + { 0.996105280093311, 0.00131930136712107 }, + { 0.996132859337453, 0.00132016573614622 }, + { 0.996160155291551, 0.0013210212264966 }, + { 0.996187171627975, 0.001321867953269 }, + { 0.996213911965722, 0.00132270602988748 }, + { 0.996240379871305, 0.00132353556813114 }, + { 0.996266578859623, 0.00132435667816142 }, + { 0.996292512394815, 0.00132516946854891 }, + { 0.996318183891097, 0.00132597404629953 }, + { 0.996343596713584, 0.0013267705168803 }, + { 0.996368754179095, 0.00132755898424465 }, + { 0.996393659556946, 0.00132833955085711 }, + { 0.996418316069724, 0.0013291123177177 }, + { 0.996442726894046, 0.00132987738438574 }, + { 0.996466895161311, 0.00133063484900327 }, + { 0.996490823958429, 0.00133138480831802 }, + { 0.99651451632854, 0.00133212735770592 }, + { 0.996537975271721, 0.00133286259119325 }, + { 0.996561203745678, 0.00133359060147833 }, + { 0.996584204666426, 0.00133431147995281 }, + { 0.996606980908954, 0.00133502531672257 }, + { 0.996629535307884, 0.00133573220062829 }, + { 0.996651870658108, 0.00133643221926551 }, + { 0.996673989715425, 0.00133712545900449 }, + { 0.996695895197154, 0.00133781200500953 }, + { 0.996717589782748, 0.00133849194125813 }, + { 0.996739076114386, 0.00133916535055958 }, + { 0.996760356797563, 0.00133983231457342 }, + { 0.99678143440166, 0.00134049291382743 }, + { 0.996802311460516, 0.00134114722773534 }, + { 0.996822990472979, 0.00134179533461424 }, + { 0.996843473903448, 0.00134243731170162 }, + { 0.996863764182414, 0.00134307323517218 }, + { 0.996883863706982, 0.00134370318015424 }, + { 0.996903774841386, 0.00134432722074599 }, + { 0.996923499917498, 0.00134494543003131 }, + { 0.996943041235328, 0.0013455578800954 }, + { 0.996962401063505, 0.0013461646420401 }, + { 0.996981581639767, 0.00134676578599895 }, + { 0.997000585171427, 0.00134736138115199 }, + { 0.997019413835838, 0.00134795149574025 }, + { 0.997038069780848, 0.00134853619708009 }, + { 0.997056555125248, 0.00134911555157714 }, + { 0.997074871959213, 0.00134968962474014 }, + { 0.99709302234473, 0.00135025848119448 }, + { 0.997111008316029, 0.00135082218469548 }, + { 0.997128831879991, 0.00135138079814143 }, + { 0.997146495016567, 0.00135193438358652 }, + { 0.997163999679176, 0.0013524830022534 }, + { 0.9971813477951, 0.00135302671454561 }, + { 0.997198541265877, 0.00135356558005975 }, + { 0.997215581967679, 0.00135409965759752 }, + { 0.997232471751692, 0.00135462900517744 }, + { 0.997249212444483, 0.00135515368004645 }, + { 0.997265805848362, 0.00135567373869132 }, + { 0.997282253741743, 0.00135618923684981 }, + { 0.997298557879491, 0.00135670022952165 }, + { 0.99731471999327, 0.00135720677097941 }, + { 0.99733074179188, 0.00135770891477908 }, + { 0.997346624961591, 0.00135820671377056 }, + { 0.997362371166473, 0.00135870022010791 }, + { 0.997377982048715, 0.00135918948525947 }, + { 0.997393459228944, 0.00135967456001779 }, + { 0.997408804306538, 0.00136015549450941 }, + { 0.99742401885993, 0.00136063233820447 }, + { 0.99743910444691, 0.00136110513992612 }, + { 0.997454062604925, 0.0013615739478599 }, + { 0.997468894851365, 0.00136203880956278 }, + { 0.997483602683853, 0.00136249977197222 }, + { 0.997498187580529, 0.00136295688141498 }, + { 0.997512651000322, 0.00136341018361582 }, + { 0.99752699438323, 0.00136385972370609 }, + { 0.997541219150581, 0.00136430554623207 }, + { 0.997555326705303, 0.00136474769516333 }, + { 0.997569318432181, 0.00136518621390082 }, + { 0.997583195698114, 0.00136562114528491 }, + { 0.997596959852367, 0.00136605253160325 }, + { 0.997610612226813, 0.00136648041459855 }, + { 0.997624154136186, 0.00136690483547618 }, + { 0.997637586878312, 0.00136732583491172 }, + { 0.997650911734349, 0.00136774345305833 }, + { 0.997664129969019, 0.00136815772955396 }, + { 0.997677242830833, 0.00136856870352863 }, + { 0.99769025155232, 0.00136897641361135 }, + { 0.997703157350246, 0.00136938089793712 }, + { 0.99771596142583, 0.00136978219415371 }, + { 0.997728664964961, 0.00137018033942841 }, + { 0.997741269138407, 0.00137057537045457 }, + { 0.997753775102023, 0.0013709673234582 }, + { 0.997766183996954, 0.00137135623420426 }, + { 0.997778496949839, 0.00137174213800304 }, + { 0.997790715073005, 0.00137212506971632 }, + { 0.997802839464665, 0.0013725050637635 }, + { 0.997814871209107, 0.00137288215412757 }, + { 0.997826811376886, 0.00137325637436108 }, + { 0.997838661025005, 0.00137362775759191 }, + { 0.997850421197104, 0.00137399633652903 }, + { 0.997862092923634, 0.00137436214346816 }, + { 0.997873677222041, 0.00137472521029731 }, + { 0.997885175096933, 0.00137508556850223 }, + { 0.99789658754026, 0.00137544324917186 }, + { 0.997907915531475, 0.00137579828300356 }, + { 0.997919160037707, 0.00137615070030844 }, + { 0.997930322013926, 0.00137650053101638 }, + { 0.997941402403097, 0.0013768478046812 }, + { 0.997952402136348, 0.00137719255048561 }, + { 0.99796332213312, 0.00137753479724613 }, + { 0.997974163301328, 0.00137787457341793 }, + { 0.997984926537508, 0.00137821190709959 }, + { 0.997995612726967, 0.00137854682603784 }, + { 0.998006222743936, 0.00137887935763213 }, + { 0.998016757451707, 0.00137920952893922 }, + { 0.998027217702786, 0.00137953736667767 }, + { 0.998037604339025, 0.00137986289723225 }, + { 0.998047918191767, 0.0013801861466583 }, + { 0.998058160081979, 0.00138050714068603 }, + { 0.998068330820393, 0.00138082590472476 }, + { 0.998078431207631, 0.00138114246386705 }, + { 0.998088462034341, 0.00138145684289283 }, + { 0.998098424081326, 0.00138176906627344 }, + { 0.998108318119668, 0.00138207915817561 }, + { 0.998118144910857, 0.00138238714246542 }, + { 0.998127905206912, 0.0013826930427121 }, + { 0.998137599750504, 0.00138299688219193 }, + { 0.998147229275075, 0.0013832986838919 }, + { 0.998156794504957, 0.00138359847051352 }, + { 0.998166296155486, 0.00138389626447637 }, + { 0.998175734933122, 0.00138419208792176 }, + { 0.998185111535555, 0.00138448596271626 }, + { 0.998194426651824, 0.00138477791045518 }, + { 0.99820368096242, 0.00138506795246602 }, + { 0.998212875139399, 0.00138535610981187 }, + { 0.998222009846487, 0.00138564240329474 }, + { 0.998231085739184, 0.00138592685345889 }, + { 0.998240103464871, 0.00138620948059404 }, + { 0.99824906366291, 0.00138649030473861 }, + { 0.998257966964743, 0.00138676934568283 }, + { 0.998266813993996, 0.00138704662297191 }, + { 0.998275605366572, 0.00138732215590909 }, + { 0.998284341690753, 0.00138759596355864 }, + { 0.998293023567288, 0.00138786806474889 }, + { 0.998301651589494, 0.00138813847807512 }, + { 0.998310226343345, 0.00138840722190251 }, + { 0.998318748407564, 0.00138867431436896 }, + { 0.998327218353711, 0.00138893977338796 }, + { 0.998335636746276, 0.0013892036166513 }, + { 0.998344004142763, 0.00138946586163188 }, + { 0.998352321093777, 0.00138972652558637 }, + { 0.998360588143109, 0.0013899856255579 }, + { 0.998368805827821, 0.00139024317837868 }, + { 0.998376974678328, 0.00139049920067259 }, + { 0.99838509521848, 0.00139075370885775 }, + { 0.998393167965641, 0.00139100671914903 }, + { 0.998401193430769, 0.00139125824756055 }, + { 0.998409172118498, 0.00139150830990812 }, + { 0.998417104527209, 0.00139175692181167 }, + { 0.99842499114911, 0.00139200409869764 }, + { 0.998432832470311, 0.00139224985580131 }, + { 0.998440628970895, 0.00139249420816918 }, + { 0.998448381124998, 0.00139273717066119 }, + { 0.998456089400872, 0.00139297875795302 }, + { 0.998463754260965, 0.00139321898453833 }, + { 0.998471376161982, 0.00139345786473094 }, + { 0.998478955554965, 0.00139369541266698 }, + { 0.998486492885351, 0.00139393164230709 }, + { 0.998493988593046, 0.00139416656743848 }, + { 0.99850144311249, 0.00139440020167702 }, + { 0.998508856872721, 0.00139463255846934 }, + { 0.998516230297441, 0.0013948636510948 }, + { 0.998523563805079, 0.00139509349266753 }, + { 0.998530857808857, 0.00139532209613839 }, + { 0.998538112716847, 0.00139554947429694 }, + { 0.998545328932037, 0.00139577563977332 }, + { 0.998552506852391, 0.0013960006050402 }, + { 0.998559646870905, 0.00139622438241462 }, + { 0.99856674937567, 0.00139644698405984 }, + { 0.99857381474993, 0.00139666842198719 }, + { 0.998580843372135, 0.00139688870805785 }, + { 0.998587835616004, 0.0013971078539846 }, + { 0.998594791850576, 0.00139732587133364 }, + { 0.99860171244027, 0.00139754277152627 }, + { 0.998608597744933, 0.00139775856584062 }, + { 0.998615448119901, 0.0013979732654133 }, + { 0.998622263916045, 0.00139818688124114 }, + { 0.998629045479829, 0.00139839942418276 }, + { 0.998635793153361, 0.00139861090496021 }, + { 0.99864250727444, 0.0013988213341606 }, + { 0.998649188176612, 0.00139903072223766 }, + { 0.998655836189216, 0.00139923907951329 }, + { 0.998662451637433, 0.00139944641617912 }, + { 0.998669034842338, 0.00139965274229802 }, + { 0.998675586120944, 0.00139985806780559 }, + { 0.998682105786251, 0.00140006240251168 }, + { 0.998688594147294, 0.00140026575610181 }, + { 0.998695051509186, 0.00140046813813864 }, + { 0.998701478173166, 0.0014006695580634 }, + { 0.998707874436645, 0.00140087002519728 }, + { 0.998714240593246, 0.00140106954874283 }, + { 0.99872057693285, 0.00140126813778533 }, + { 0.998726883741643, 0.00140146580129416 }, + { 0.998733161302152, 0.00140166254812412 }, + { 0.998739409893293, 0.00140185838701677 }, + { 0.998745629790408, 0.00140205332660173 }, + { 0.998751821265312, 0.00140224737539795 }, + { 0.998757984586326, 0.00140244054181503 }, + { 0.998764120018323, 0.00140263283415441 }, + { 0.998770227822767, 0.00140282426061069 }, + { 0.99877630825775, 0.00140301482927281 }, + { 0.99878236157803, 0.00140320454812524 }, + { 0.998788388035074, 0.00140339342504925 }, + { 0.99879438787709, 0.00140358146782403 }, + { 0.998800361349069, 0.00140376868412787 }, + { 0.998806308692817, 0.00140395508153934 }, + { 0.998812230146997, 0.00140414066753839 }, + { 0.998818125947161, 0.00140432544950751 }, + { 0.998823996325784, 0.00140450943473283 }, + { 0.998829841512304, 0.00140469263040522 }, + { 0.998835661733154, 0.00140487504362135 }, + { 0.998841457211795, 0.00140505668138479 }, + { 0.998847228168752, 0.00140523755060708 }, + { 0.998852974821647, 0.00140541765810874 }, + { 0.998858697385229, 0.00140559701062034 }, + { 0.998864396071411, 0.00140577561478348 }, + { 0.9988700710893, 0.00140595347715183 }, + { 0.998875722645229, 0.00140613060419214 }, + { 0.998881350942787, 0.00140630700228517 }, + { 0.998886956182854, 0.00140648267772672 }, + { 0.998892538563627, 0.00140665763672855 }, + { 0.998898098280653, 0.00140683188541938 }, + { 0.998903635526858, 0.00140700542984578 }, + { 0.99890915049258, 0.00140717827597309 }, + { 0.99891464336559, 0.00140735042968641 }, + { 0.998920114331131, 0.00140752189679142 }, + { 0.99892556357194, 0.00140769268301534 }, + { 0.998930991268277, 0.00140786279400777 }, + { 0.998936397597955, 0.00140803223534159 }, + { 0.998941782736366, 0.00140820101251383 }, + { 0.998947146856509, 0.00140836913094649 }, + { 0.998952490129017, 0.00140853659598742 }, + { 0.998957812722183, 0.00140870341291114 }, + { 0.998963114801987, 0.00140886958691965 }, + { 0.998968396532119, 0.00140903512314329 }, + { 0.998973658074012, 0.00140920002664148 }, + { 0.998978899586859, 0.00140936430240358 }, + { 0.998984121227642, 0.00140952795534964 }, + { 0.99898932315116, 0.00140969099033118 }, + { 0.998994505510046, 0.00140985341213198 }, + { 0.998999668454797, 0.00141001522546881 }, + { 0.999004812133799, 0.00141017643499223 }, + { 0.999009936693344, 0.00141033704528726 }, + { 0.99901504227766, 0.00141049706087418 }, + { 0.999020129028932, 0.00141065648620924 }, + { 0.999025197087324, 0.00141081532568536 }, + { 0.999030246591001, 0.00141097358363284 }, + { 0.999035277676155, 0.0014111312643201 }, + { 0.999040290477024, 0.00141128837195431 }, + { 0.999045285125915, 0.00141144491068214 }, + { 0.999050261753224, 0.0014116008845904 }, + { 0.99905522048746, 0.00141175629770673 }, + { 0.999060161455266, 0.00141191115400023 }, + { 0.999065084781436, 0.00141206545738217 }, + { 0.999069990588942, 0.00141221921170659 }, + { 0.999074878998948, 0.00141237242077097 }, + { 0.999079750130834, 0.00141252508831683 }, + { 0.999084604102217, 0.00141267721803041 }, + { 0.999089441028966, 0.00141282881354325 }, + { 0.999094261025228, 0.00141297987843281 }, + { 0.999099064203442, 0.00141313041622307 }, + { 0.999103850674359, 0.00141328043038515 }, + { 0.999108620547065, 0.0014134299243379 }, + { 0.999113373928994, 0.00141357890144846 }, + { 0.999118110925949, 0.00141372736503288 }, + { 0.999122831642124, 0.00141387531835665 }, + { 0.999127536180115, 0.00141402276463531 }, + { 0.999132224640943, 0.00141416970703497 }, + { 0.999136897124069, 0.00141431614867291 }, + { 0.999141553727416, 0.00141446209261808 }, + { 0.999146194547378, 0.00141460754189169 }, + { 0.999150819678847, 0.00141475249946771 }, + { 0.999155429215223, 0.00141489696827342 }, + { 0.999160023248433, 0.00141504095118993 }, + { 0.999164601868947, 0.00141518445105272 }, + { 0.999169165165795, 0.00141532747065211 }, + { 0.999173713226586, 0.0014154700127338 }, + { 0.999178246137516, 0.00141561207999939 }, + { 0.999182763983395, 0.00141575367510684 }, + { 0.999187266847651, 0.00141589480067096 }, + { 0.999191754812356, 0.00141603545926396 }, + { 0.999196227958234, 0.00141617565341585 }, + { 0.999200686364681, 0.00141631538561497 }, + { 0.999205130109776, 0.00141645465830845 }, + { 0.999209559270299, 0.00141659347390267 }, + { 0.999213973921745, 0.00141673183476372 }, + { 0.999218374138337, 0.00141686974321787 }, + { 0.999222759993043, 0.00141700720155202 }, + { 0.999227131557588, 0.00141714421201412 }, + { 0.99923148890247, 0.00141728077681367 }, + { 0.999235832096973, 0.0014174168981221 }, + { 0.999240161209179, 0.00141755257807323 }, + { 0.999244476305986, 0.0014176878187637 }, + { 0.999248777453117, 0.00141782262225338 }, + { 0.999253064715139, 0.00141795699056582 }, + { 0.999257338155468, 0.00141809092568863 }, + { 0.99926159783639, 0.00141822442957392 }, + { 0.99926584381907, 0.00141835750413868 }, + { 0.999270076163568, 0.0014184901512652 }, + { 0.999274294928845, 0.00141862237280149 }, + { 0.999278500172784, 0.00141875417056161 }, + { 0.999282691952196, 0.00141888554632615 }, + { 0.999286870322837, 0.00141901650184251 }, + { 0.999291035339416, 0.00141914703882539 }, + { 0.999295187055611, 0.00141927715895711 }, + { 0.999299325524078, 0.00141940686388796 }, + { 0.999303450796465, 0.00141953615523665 }, + { 0.99930756292342, 0.0014196650345906 }, + { 0.999311661954608, 0.00141979350350635 }, + { 0.999315747938718, 0.00141992156350989 }, + { 0.999319820923479, 0.00142004921609706 }, + { 0.999323880955664, 0.00142017646273383 }, + { 0.999327928081108, 0.00142030330485674 }, + { 0.999331962344717, 0.00142042974387316 }, + { 0.999335983790477, 0.00142055578116168 }, + { 0.999339992461466, 0.00142068141807244 }, + { 0.999343988399866, 0.00142080665592747 }, + { 0.999347971646972, 0.00142093149602099 }, + { 0.999351942243203, 0.00142105593961979 }, + { 0.999355900228111, 0.0014211799879635 }, + { 0.999359845640395, 0.00142130364226497 }, + { 0.999363778517906, 0.00142142690371053 }, + { 0.999367698897662, 0.00142154977346033 }, + { 0.999371606815854, 0.00142167225264869 }, + { 0.999375502307859, 0.00142179434238434 }, + { 0.999379385408247, 0.00142191604375077 }, + { 0.999383256150793, 0.00142203735780652 }, + { 0.999387114568486, 0.0014221582855855 }, + { 0.999390960693537, 0.00142227882809723 }, + { 0.999394794557389, 0.00142239898632722 }, + { 0.999398616190729, 0.00142251876123719 }, + { 0.999402425623492, 0.00142263815376539 }, + { 0.999406222884875, 0.00142275716482686 }, + { 0.999410008003344, 0.00142287579531377 }, + { 0.999413781006642, 0.00142299404609562 }, + { 0.9994175419218, 0.00142311191801959 }, + { 0.999421290775143, 0.00142322941191076 }, + { 0.999425027592302, 0.00142334652857243 }, + { 0.999428752398221, 0.00142346326878633 }, + { 0.999432465217163, 0.00142357963331296 }, + { 0.999436166072722, 0.00142369562289178 }, + { 0.999439854987832, 0.00142381123824153 }, + { 0.99944353198477, 0.00142392648006044 }, + { 0.999447197085171, 0.00142404134902654 }, + { 0.99945085031003, 0.00142415584579787 }, + { 0.999454491679713, 0.00142426997101273 }, + { 0.999458121213966, 0.00142438372528998 }, + { 0.999461738931922, 0.00142449710922923 }, + { 0.999465344852105, 0.0014246101234111 }, + { 0.999468938992444, 0.00142472276839749 }, + { 0.999472521370276, 0.00142483504473178 }, + { 0.999476092002357, 0.00142494695293909 }, + { 0.999479650904866, 0.00142505849352651 }, + { 0.999483198093414, 0.00142516966698334 }, + { 0.999486733583054, 0.0014252804737813 }, + { 0.999490257388284, 0.00142539091437477 }, + { 0.999493769523054, 0.00142550098920105 }, + { 0.999497270000779, 0.00142561069868051 }, + { 0.99950075883434, 0.00142572004321686 }, + { 0.999504236036093, 0.00142582902319741 }, + { 0.999507701617878, 0.00142593763899318 }, + { 0.999511155591023, 0.0014260458909592 }, + { 0.999514597966351, 0.00142615377943473 }, + { 0.999518028754189, 0.0014262613047434 }, + { 0.999521447964373, 0.00142636846719348 }, + { 0.999524855606255, 0.00142647526707807 }, + { 0.999528251688709, 0.00142658170467531 }, + { 0.999531636220139, 0.00142668778024857 }, + { 0.999535009208483, 0.00142679349404666 }, + { 0.999538370661222, 0.00142689884630404 }, + { 0.999541720585385, 0.00142700383724101 }, + { 0.999545058987556, 0.0014271084670639 }, + { 0.999548385873878, 0.00142721273596527 }, + { 0.999551701250063, 0.0014273166441241 }, + { 0.999555005121394, 0.00142742019170599 }, + { 0.999558297492733, 0.00142752337886335 }, + { 0.999561578368529, 0.00142762620573556 }, + { 0.999564847752819, 0.0014277286724492 }, + { 0.999568105649239, 0.00142783077911818 }, + { 0.999571352061026, 0.00142793252584398 }, + { 0.999574586991025, 0.00142803391271578 }, + { 0.999577810441698, 0.00142813493981068 }, + { 0.999581022415122, 0.00142823560719385 }, + { 0.999584222913003, 0.0014283359149187 }, + { 0.999587411936675, 0.0014284358630271 }, + { 0.999590589487111, 0.0014285354515495 }, + { 0.999593755564924, 0.00142863468050511 }, + { 0.999596910170374, 0.0014287335499021 }, + { 0.999600053303375, 0.00142883205973773 }, + { 0.999603184963496, 0.00142893020999856 }, + { 0.999606305149971, 0.00142902800066056 }, + { 0.999609413861703, 0.00142912543168932 }, + { 0.999612511097266, 0.00142922250304018 }, + { 0.999615596854915, 0.00142931921465842 }, + { 0.999618671132586, 0.00142941556647937 }, + { 0.999621733927906, 0.00142951155842864 }, + { 0.999624785238193, 0.00142960719042221 }, + { 0.999627825060466, 0.00142970246236661 }, + { 0.999630853391445, 0.00142979737415908 }, + { 0.99963387022756, 0.0014298919256877 }, + { 0.999636875564953, 0.00142998611683157 }, + { 0.999639869399485, 0.00143007994746093 }, + { 0.999642851726736, 0.00143017341743733 }, + { 0.999645822542017, 0.00143026652661376 }, + { 0.999648781840369, 0.00143035927483479 }, + { 0.999651729616569, 0.00143045166193676 }, + { 0.999654665865136, 0.00143054368774783 }, + { 0.999657590580332, 0.00143063535208823 }, + { 0.999660503756171, 0.00143072665477033 }, + { 0.999663405386421, 0.00143081759559877 }, + { 0.999666295464607, 0.00143090817437066 }, + { 0.999669173984018, 0.00143099839087567 }, + { 0.99967204093771, 0.00143108824489614 }, + { 0.99967489631851, 0.00143117773620729 }, + { 0.999677740119022, 0.00143126686457729 }, + { 0.999680572331628, 0.0014313556297674 }, + { 0.999683392948495, 0.00143144403153212 }, + { 0.999686201961578, 0.00143153206961931 }, + { 0.999688999362625, 0.00143161974377031 }, + { 0.999691785143178, 0.00143170705372008 }, + { 0.99969455929458, 0.00143179399919731 }, + { 0.99969732180798, 0.00143188057992455 }, + { 0.999700072674333, 0.00143196679561834 }, + { 0.999702811884406, 0.00143205264598932 }, + { 0.999705539428784, 0.00143213813074236 }, + { 0.999708255297868, 0.00143222324957667 }, + { 0.999710959481885, 0.00143230800218595 }, + { 0.999713651970889, 0.00143239238825846 }, + { 0.999716332754765, 0.00143247640747715 }, + { 0.99971900182323, 0.00143256005951981 }, + { 0.999721659165843, 0.00143264334405915 }, + { 0.999724304772002, 0.00143272626076292 }, + { 0.999726938630952, 0.00143280880929403 }, + { 0.999729560731786, 0.00143289098931064 }, + { 0.99973217106345, 0.0014329728004663 }, + { 0.999734769614746, 0.00143305424241006 }, + { 0.999737356374334, 0.00143313531478654 }, + { 0.99973993133074, 0.00143321601723607 }, + { 0.999742494472354, 0.00143329634939478 }, + { 0.999745045787435, 0.00143337631089474 }, + { 0.999747585264116, 0.00143345590136401 }, + { 0.999750112890407, 0.00143353512042679 }, + { 0.999752628654196, 0.0014336139677035 }, + { 0.999755132543256, 0.00143369244281086 }, + { 0.999757624545242, 0.00143377054536207 }, + { 0.999760104647703, 0.00143384827496681 }, + { 0.999762572838077, 0.00143392563123141 }, + { 0.999765029103698, 0.00143400261375891 }, + { 0.9997674734318, 0.00143407922214919 }, + { 0.999769905809518, 0.00143415545599902 }, + { 0.99977232622389, 0.00143423131490221 }, + { 0.999774734661864, 0.00143430679844967 }, + { 0.999777131110298, 0.00143438190622949 }, + { 0.999779515555963, 0.00143445663782708 }, + { 0.999781887985548, 0.00143453099282524 }, + { 0.999784248385659, 0.00143460497080421 }, + { 0.999786596742827, 0.00143467857134184 }, + { 0.999788933043508, 0.00143475179401362 }, + { 0.999791257274084, 0.00143482463839279 }, + { 0.99979356942087, 0.0014348971040504 }, + { 0.999795869470113, 0.00143496919055546 }, + { 0.999798157407999, 0.00143504089747496 }, + { 0.999800433220649, 0.00143511222437399 }, + { 0.999802696894131, 0.00143518317081583 }, + { 0.999804948414453, 0.001435253736362 }, + { 0.999807187767573, 0.00143532392057239 }, + { 0.999809414939397, 0.00143539372300528 }, + { 0.999811629915785, 0.00143546314321751 }, + { 0.999813832682551, 0.00143553218076446 }, + { 0.999816023225468, 0.00143560083520021 }, + { 0.999818201530266, 0.00143566910607759 }, + { 0.999820367582641, 0.00143573699294824 }, + { 0.999822521368252, 0.00143580449536273 }, + { 0.999824662872727, 0.00143587161287058 }, + { 0.999826792081663, 0.00143593834502041 }, + { 0.999828908980629, 0.00143600469135994 }, + { 0.999831013555171, 0.00143607065143613 }, + { 0.999833105790809, 0.00143613622479521 }, + { 0.999835185673046, 0.00143620141098276 }, + { 0.999837253187364, 0.00143626620954382 }, + { 0.99983930831923, 0.00143633062002291 }, + { 0.9998413510541, 0.00143639464196414 }, + { 0.999843381377414, 0.00143645827491126 }, + { 0.999845399274607, 0.00143652151840773 }, + { 0.999847404731106, 0.00143658437199682 }, + { 0.999849397732332, 0.00143664683522163 }, + { 0.999851378263706, 0.00143670890762521 }, + { 0.999853346310646, 0.00143677058875058 }, + { 0.999855301858575, 0.00143683187814082 }, + { 0.999857244892917, 0.00143689277533915 }, + { 0.999859175399105, 0.00143695327988898 }, + { 0.999861093362577, 0.00143701339133397 }, + { 0.999862998768784, 0.00143707310921809 }, + { 0.999864891603188, 0.00143713243308571 }, + { 0.999866771851266, 0.00143719136248164 }, + { 0.999868639498509, 0.00143724989695121 }, + { 0.999870494530429, 0.00143730803604032 }, + { 0.999872336932558, 0.00143736577929548 }, + { 0.999874166690448, 0.00143742312626394 }, + { 0.999875983789677, 0.00143748007649365 }, + { 0.999877788215849, 0.00143753662953343 }, + { 0.999879579954594, 0.00143759278493293 }, + { 0.999881358991574, 0.00143764854224275 }, + { 0.999883125312482, 0.00143770390101448 }, + { 0.999884878903043, 0.00143775886080075 }, + { 0.999886619749018, 0.0014378134211553 }, + { 0.999888347836206, 0.00143786758163303 }, + { 0.999890063150444, 0.00143792134179004 }, + { 0.999891765677609, 0.00143797470118373 }, + { 0.99989345540362, 0.00143802765937279 }, + { 0.999895132314442, 0.00143808021591731 }, + { 0.999896796396084, 0.00143813237037881 }, + { 0.999898447634603, 0.00143818412232028 }, + { 0.999900086016104, 0.00143823547130626 }, + { 0.999901711526744, 0.00143828641690288 }, + { 0.999903324152731, 0.00143833695867789 }, + { 0.999904923880328, 0.00143838709620075 }, + { 0.999906510695853, 0.00143843682904266 }, + { 0.999908084585682, 0.00143848615677659 }, + { 0.999909645536248, 0.00143853507897736 }, + { 0.999911193534045, 0.00143858359522168 }, + { 0.99991272856563, 0.00143863170508819 }, + { 0.99991425061762, 0.00143867940815751 }, + { 0.9999157596767, 0.00143872670401229 }, + { 0.99991725572962, 0.00143877359223726 }, + { 0.999918738763197, 0.00143882007241926 }, + { 0.999920208764318, 0.0014388661441473 }, + { 0.99992166571994, 0.00143891180701262 }, + { 0.999923109617092, 0.00143895706060869 }, + { 0.999924540442878, 0.00143900190453128 }, + { 0.999925958184474, 0.00143904633837852 }, + { 0.999927362829134, 0.00143909036175092 }, + { 0.999928754364188, 0.0014391339742514 }, + { 0.999930132777047, 0.00143917717548538 }, + { 0.9999314980552, 0.00143921996506077 }, + { 0.999932850186219, 0.00143926234258802 }, + { 0.999934189157757, 0.00143930430768022 }, + { 0.999935514957552, 0.00143934585995303 }, + { 0.999936827573428, 0.00143938699902483 }, + { 0.999938126993294, 0.0014394277245167 }, + { 0.999939413205148, 0.00143946803605245 }, + { 0.999940686197075, 0.00143950793325869 }, + { 0.999941945957253, 0.00143954741576486 }, + { 0.99994319247395, 0.00143958648320326 }, + { 0.999944425735524, 0.00143962513520908 }, + { 0.999945645730432, 0.00143966337142045 }, + { 0.99994685244722, 0.00143970119147848 }, + { 0.999948045874534, 0.00143973859502727 }, + { 0.999949226001115, 0.00143977558171397 }, + { 0.999950392815803, 0.0014398121511888 }, + { 0.999951546307537, 0.0014398483031051 }, + { 0.999952686465356, 0.00143988403711934 }, + { 0.999953813278401, 0.00143991935289117 }, + { 0.999954926735915, 0.00143995425008344 }, + { 0.999956026827243, 0.00143998872836226 }, + { 0.999957113541838, 0.001440022787397 }, + { 0.999958186869253, 0.00144005642686033 }, + { 0.999959246799153, 0.00144008964642826 }, + { 0.999960293321307, 0.00144012244578017 }, + { 0.999961326425593, 0.00144015482459881 }, + { 0.999962346101998, 0.00144018678257039 }, + { 0.99996335234062, 0.00144021831938454 }, + { 0.999964345131669, 0.00144024943473441 }, + { 0.999965324465463, 0.00144028012831661 }, + { 0.999966290332437, 0.00144031039983133 }, + { 0.999967242723139, 0.0014403402489823 }, + { 0.999968181628229, 0.00144036967547687 }, + { 0.999969107038487, 0.00144039867902599 }, + { 0.999970018944804, 0.00144042725934424 }, + { 0.999970917338193, 0.00144045541614991 }, + { 0.999971802209782, 0.00144048314916496 }, + { 0.999972673550819, 0.00144051045811507 }, + { 0.99997353135267, 0.00144053734272967 }, + { 0.999974375606823, 0.00144056380274197 }, + { 0.999975206304887, 0.00144058983788897 }, + { 0.999976023438591, 0.00144061544791148 }, + { 0.999976826999788, 0.00144064063255415 }, + { 0.999977616980455, 0.0014406653915655 }, + { 0.999978393372691, 0.00144068972469794 }, + { 0.99997915616872, 0.00144071363170775 }, + { 0.999979905360893, 0.00144073711235519 }, + { 0.999980640941686, 0.00144076016640443 }, + { 0.9999813629037, 0.00144078279362362 }, + { 0.999982071239665, 0.0014408049937849 }, + { 0.99998276594244, 0.00144082676666443 }, + { 0.99998344700501, 0.00144084811204238 }, + { 0.999984114420491, 0.00144086902970297 }, + { 0.999984768182127, 0.0014408895194345 }, + { 0.999985408283294, 0.00144090958102933 }, + { 0.999986034717498, 0.00144092921428395 }, + { 0.999986647478377, 0.00144094841899893 }, + { 0.999987246559699, 0.00144096719497902 }, + { 0.999987831955368, 0.00144098554203309 }, + { 0.999988403659418, 0.0014410034599742 }, + { 0.999988961666017, 0.00144102094861957 }, + { 0.999989505969469, 0.00144103800779063 }, + { 0.999990036564209, 0.00144105463731305 }, + { 0.999990553444811, 0.00144107083701668 }, + { 0.99999105660598, 0.00144108660673566 }, + { 0.999991546042562, 0.00144110194630836 }, + { 0.999992021749534, 0.00144111685557744 }, + { 0.999992483722013, 0.00144113133438981 }, + { 0.999992931955252, 0.00144114538259672 }, + { 0.999993366444643, 0.00144115900005371 }, + { 0.999993787185713, 0.00144117218662063 }, + { 0.999994194174129, 0.00144118494216168 }, + { 0.999994587405698, 0.0014411972665454 }, + { 0.999994966876362, 0.00144120915964467 }, + { 0.999995332582207, 0.00144122062133677 }, + { 0.999995684519455, 0.00144123165150332 }, + { 0.99999602268447, 0.00144124225003034 }, + { 0.999996347073756, 0.00144125241680826 }, + { 0.999996657683955, 0.00144126215173188 }, + { 0.999996954511853, 0.00144127145470043 }, + { 0.999997237554376, 0.00144128032561758 }, + { 0.999997506808591, 0.0014412887643914 }, + { 0.999997762271707, 0.00144129677093441 }, + { 0.999998003941074, 0.00144130434516356 }, + { 0.999998231814184, 0.00144131148700027 }, + { 0.999998445888673, 0.00144131819637042 }, + { 0.999998646162317, 0.00144132447320431 }, + { 0.999998832633036, 0.00144133031743676 }, + { 0.999999005298892, 0.00144133572900703 }, + { 0.999999164158091, 0.00144134070785888 }, + { 0.99999930920898, 0.00144134525394053 }, + { 0.999999440450052, 0.00144134936720471 }, + { 0.99999955787994, 0.00144135304760864 }, + { 0.999999661497424, 0.00144135629511401 }, + { 0.999999751301425, 0.00144135910968703 }, + { 0.999999827291008, 0.00144136149129841 }, + { 0.999999889465382, 0.00144136343992335 }, + { 0.9999999378239, 0.00144136495554157 }, + { 0.999999972366058, 0.00144136603813729 }, + { 0.999999993091496, 0.00144136668769923 }, + { 1, 0.00144136690422063 } +}; + +static const double inverse_cumulative[] = { + 0, 0.00181900412026957, 0.00330980182852486, 0.00391849965097171, + 0.00452719747341855, 0.00513589529586539, 0.00574459311831223, 0.00632806291282084, + 0.00669612817511386, 0.00706419343740688, 0.0074322586996999, 0.00780032396199292, + 0.00816838922428594, 0.00853645448657896, 0.00890451974887198, 0.00927258501116501, + 0.00958338938434283, 0.00984936232879981, 0.0101153352732568, 0.0103813082177138, + 0.0106472811621708, 0.0109132541066277, 0.0111792270510847, 0.0114451999955417, + 0.0117111729399987, 0.0119771458844557, 0.0122431188289126, 0.0125090917733696, + 0.0127338510223064, 0.0129439296223883, 0.0131540082224701, 0.013364086822552, + 0.0135741654226339, 0.0137842440227157, 0.0139943226227976, 0.0142044012228795, + 0.0144144798229613, 0.0146245584230432, 0.0148346370231251, 0.0150447156232069, + 0.0152547942232888, 0.0154648728233706, 0.0156749514234525, 0.0158582448740068, + 0.0160334475617641, 0.0162086502495214, 0.0163838529372787, 0.0165590556250361, + 0.0167342583127934, 0.0169094610005507, 0.017084663688308, 0.0172598663760653, + 0.0174350690638226, 0.0176102717515799, 0.0177854744393372, 0.0179606771270945, + 0.0181358798148518, 0.0183110825026092, 0.0184862851903665, 0.0186614878781238, + 0.0188366905658811, 0.0189926185390339, 0.0191442831525329, 0.019295947766032, + 0.019447612379531, 0.01959927699303, 0.0197509416065291, 0.0199026062200281, + 0.0200542708335271, 0.0202059354470262, 0.0203576000605252, 0.0205092646740242, + 0.0206609292875233, 0.0208125939010223, 0.0209642585145213, 0.0211159231280204, + 0.0212675877415194, 0.0214192523550184, 0.0215709169685174, 0.0217225815820165, + 0.0218742461955155, 0.0220245057558316, 0.0221594556746887, 0.0222944055935459, + 0.0224293555124031, 0.0225643054312602, 0.0226992553501174, 0.0228342052689745, + 0.0229691551878317, 0.0231041051066889, 0.023239055025546, 0.0233740049444032, + 0.0235089548632603, 0.0236439047821175, 0.0237788547009747, 0.0239138046198318, + 0.024048754538689, 0.0241837044575461, 0.0243186543764033, 0.0244536042952605, + 0.0245885542141176, 0.0247235041329748, 0.0248584540518319, 0.0249934039706891, + 0.0251283538895463, 0.0252537132938116, 0.0253763844489637, 0.0254990556041159, + 0.025621726759268, 0.0257443979144202, 0.0258670690695723, 0.0259897402247245, + 0.0261124113798766, 0.0262350825350287, 0.0263577536901809, 0.026480424845333, + 0.0266030960004852, 0.0267257671556373, 0.0268484383107894, 0.0269711094659416, + 0.0270937806210937, 0.0272164517762459, 0.027339122931398, 0.0274617940865502, + 0.0275844652417023, 0.0277071363968544, 0.0278298075520066, 0.0279524787071587, + 0.0280751498623109, 0.028197821017463, 0.0283191496967392, 0.0284325978310814, + 0.0285460459654235, 0.0286594940997656, 0.0287729422341078, 0.0288863903684499, + 0.0289998385027921, 0.0291132866371342, 0.0292267347714763, 0.0293401829058185, + 0.0294536310401606, 0.0295670791745027, 0.0296805273088449, 0.029793975443187, + 0.0299074235775291, 0.0300208717118713, 0.0301343198462134, 0.0302477679805556, + 0.0303612161148977, 0.0304746642492398, 0.030588112383582, 0.0307015605179241, + 0.0308150086522662, 0.0309284567866084, 0.0310419049209505, 0.0311553530552927, + 0.0312688011896348, 0.0313822493239769, 0.0314927071947135, 0.0315991351528125, + 0.0317055631109115, 0.0318119910690105, 0.0319184190271095, 0.0320248469852085, + 0.0321312749433075, 0.0322377029014065, 0.0323441308595055, 0.0324505588176045, + 0.0325569867757035, 0.0326634147338025, 0.0327698426919015, 0.0328762706500005, + 0.0329826986080995, 0.0330891265661985, 0.0331955545242975, 0.0333019824823965, + 0.0334084104404955, 0.0335148383985945, 0.0336212663566935, 0.0337276943147925, + 0.0338341222728914, 0.0339405502309904, 0.0340469781890894, 0.0341534061471884, + 0.0342598341052874, 0.0343662620633864, 0.0344726900214854, 0.0345791179795844, + 0.0346808292760102, 0.0347818846582893, 0.0348829400405684, 0.0349839954228475, + 0.0350850508051266, 0.0351861061874057, 0.0352871615696848, 0.0353882169519639, + 0.035489272334243, 0.0355903277165221, 0.0356913830988012, 0.0357924384810803, + 0.0358934938633594, 0.0359945492456386, 0.0360956046279177, 0.0361966600101968, + 0.0362977153924759, 0.036398770774755, 0.0364998261570341, 0.0366008815393132, + 0.0367019369215923, 0.0368029923038714, 0.0369040476861505, 0.0370051030684296, + 0.0371061584507087, 0.0372072138329878, 0.0373082692152669, 0.037409324597546, + 0.0375103799798251, 0.0376114353621042, 0.0377124907443833, 0.0378104328067266, + 0.0379073861256615, 0.0380043394445963, 0.0381012927635312, 0.0381982460824661, + 0.038295199401401, 0.0383921527203359, 0.0384891060392707, 0.0385860593582056, + 0.0386830126771405, 0.0387799659960754, 0.0388769193150103, 0.0389738726339452, + 0.03907082595288, 0.0391677792718149, 0.0392647325907498, 0.0393616859096847, + 0.0394586392286196, 0.0395555925475544, 0.0396525458664893, 0.0397494991854242, + 0.0398464525043591, 0.039943405823294, 0.0400403591422289, 0.0401373124611637, + 0.0402342657800986, 0.0403312190990335, 0.0404281724179684, 0.0405251257369033, + 0.0406220790558382, 0.040719032374773, 0.0408159856937079, 0.0409119375132289, + 0.0410057938746412, 0.0410996502360535, 0.0411935065974657, 0.041287362958878, + 0.0413812193202903, 0.0414750756817026, 0.0415689320431148, 0.0416627884045271, + 0.0417566447659394, 0.0418505011273517, 0.041944357488764, 0.0420382138501762, + 0.0421320702115885, 0.0422259265730008, 0.0423197829344131, 0.0424136392958253, + 0.0425074956572376, 0.0426013520186499, 0.0426952083800622, 0.0427890647414744, + 0.0428829211028867, 0.042976777464299, 0.0430706338257113, 0.0431644901871235, + 0.0432583465485358, 0.0433522029099481, 0.0434460592713604, 0.0435399156327726, + 0.0436337719941849, 0.0437276283555972, 0.0438214847170095, 0.0439153410784217, + 0.044009197439834, 0.0441011860517888, 0.0441927577863295, 0.0442843295208702, + 0.0443759012554109, 0.0444674729899515, 0.0445590447244922, 0.0446506164590329, + 0.0447421881935736, 0.0448337599281142, 0.0449253316626549, 0.0450169033971956, + 0.0451084751317363, 0.045200046866277, 0.0452916186008176, 0.0453831903353583, + 0.045474762069899, 0.0455663338044397, 0.0456579055389803, 0.045749477273521, + 0.0458410490080617, 0.0459326207426024, 0.046024192477143, 0.0461157642116837, + 0.0462073359462244, 0.0462989076807651, 0.0463904794153058, 0.0464820511498464, + 0.0465736228843871, 0.0466651946189278, 0.0467567663534685, 0.0468483380880092, + 0.0469399098225498, 0.0470314815570905, 0.0471230532916312, 0.0472138560223102, + 0.0473038113130788, 0.0473937666038474, 0.047483721894616, 0.0475736771853846, + 0.0476636324761531, 0.0477535877669217, 0.0478435430576903, 0.0479334983484589, + 0.0480234536392275, 0.0481134089299961, 0.0482033642207646, 0.0482933195115332, + 0.0483832748023018, 0.0484732300930704, 0.048563185383839, 0.0486531406746076, + 0.0487430959653761, 0.0488330512561447, 0.0489230065469133, 0.0490129618376819, + 0.0491029171284505, 0.0491928724192191, 0.0492828277099876, 0.0493727830007562, + 0.0494627382915248, 0.0495526935822934, 0.049642648873062, 0.0497326041638306, + 0.0498225594545991, 0.0499125147453677, 0.0500024700361363, 0.0500924253269049, + 0.0501823806176735, 0.0502723359084421, 0.0503617438051086, 0.0504506399890131, + 0.0505395361729176, 0.0506284323568221, 0.0507173285407266, 0.0508062247246311, + 0.0508951209085356, 0.0509840170924401, 0.0510729132763446, 0.0511618094602491, + 0.0512507056441536, 0.0513396018280581, 0.0514284980119626, 0.0515173941958671, + 0.0516062903797716, 0.0516951865636761, 0.0517840827475806, 0.0518729789314851, + 0.0519618751153896, 0.052050771299294, 0.0521396674831985, 0.052228563667103, + 0.0523174598510075, 0.052406356034912, 0.0524952522188165, 0.052584148402721, + 0.0526730445866255, 0.05276194077053, 0.0528508369544345, 0.052939733138339, + 0.0530286293222435, 0.053117525506148, 0.0532064216900525, 0.053295317873957, + 0.0533842140578615, 0.0534730268681487, 0.0535613336417097, 0.0536496404152707, + 0.0537379471888318, 0.0538262539623928, 0.0539145607359538, 0.0540028675095148, + 0.0540911742830758, 0.0541794810566368, 0.0542677878301979, 0.0543560946037589, + 0.0544444013773199, 0.0545327081508809, 0.0546210149244419, 0.0547093216980029, + 0.054797628471564, 0.054885935245125, 0.054974242018686, 0.055062548792247, + 0.055150855565808, 0.055239162339369, 0.0553274691129301, 0.0554157758864911, + 0.0555040826600521, 0.0555923894336131, 0.0556806962071741, 0.0557690029807351, + 0.0558573097542961, 0.0559456165278572, 0.0560339233014182, 0.0561222300749792, + 0.0562105368485402, 0.0562988436221012, 0.0563871503956622, 0.0564754571692233, + 0.0565637639427843, 0.0566519695187876, 0.056740085333522, 0.0568282011482563, + 0.0569163169629907, 0.0570044327777251, 0.0570925485924594, 0.0571806644071938, + 0.0572687802219281, 0.0573568960366625, 0.0574450118513969, 0.0575331276661312, + 0.0576212434808656, 0.0577093592955999, 0.0577974751103343, 0.0578855909250687, + 0.057973706739803, 0.0580618225545374, 0.0581499383692718, 0.0582380541840061, + 0.0583261699987405, 0.0584142858134749, 0.0585024016282092, 0.0585905174429436, + 0.0586786332576779, 0.0587667490724123, 0.0588548648871467, 0.058942980701881, + 0.0590310965166154, 0.0591192123313497, 0.0592073281460841, 0.0592954439608185, + 0.0593835597755528, 0.0594716755902872, 0.0595597914050216, 0.0596479072197559, + 0.0597360230344903, 0.0598242633395279, 0.059912527134813, 0.0600007909300981, + 0.0600890547253831, 0.0601773185206682, 0.0602655823159533, 0.0603538461112383, + 0.0604421099065234, 0.0605303737018084, 0.0606186374970935, 0.0607069012923786, + 0.0607951650876636, 0.0608834288829487, 0.0609716926782338, 0.0610599564735188, + 0.0611482202688039, 0.0612364840640889, 0.061324747859374, 0.0614130116546591, + 0.0615012754499441, 0.0615895392452292, 0.0616778030405143, 0.0617660668357993, + 0.0618543306310844, 0.0619425944263694, 0.0620308582216545, 0.0621191220169396, + 0.0622073858122246, 0.0622956496075097, 0.0623839134027948, 0.0624721771980798, + 0.0625604409933649, 0.0626487047886499, 0.062736968583935, 0.0628252323792201, + 0.0629135887738314, 0.0630022885096577, 0.0630909882454839, 0.0631796879813101, + 0.0632683877171364, 0.0633570874529626, 0.0634457871887889, 0.0635344869246152, + 0.0636231866604414, 0.0637118863962677, 0.0638005861320939, 0.0638892858679202, + 0.0639779856037464, 0.0640666853395727, 0.0641553850753989, 0.0642440848112252, + 0.0643327845470514, 0.0644214842828777, 0.0645101840187039, 0.0645988837545302, + 0.0646875834903564, 0.0647762832261827, 0.0648649829620089, 0.0649536826978352, + 0.0650423824336614, 0.0651310821694877, 0.0652197819053139, 0.0653084816411402, + 0.0653971813769664, 0.0654858811127927, 0.0655745808486189, 0.0656632805844452, + 0.0657519803202714, 0.0658406800560977, 0.0659293797919239, 0.0660180795277502, + 0.0661072946220499, 0.0661966736476265, 0.066286052673203, 0.0663754316987796, + 0.0664648107243562, 0.0665541897499328, 0.0666435687755094, 0.066732947801086, + 0.0668223268266626, 0.0669117058522391, 0.0670010848778157, 0.0670904639033923, + 0.0671798429289689, 0.0672692219545455, 0.0673586009801221, 0.0674479800056987, + 0.0675373590312753, 0.0676267380568518, 0.0677161170824284, 0.067805496108005, + 0.0678948751335816, 0.0679842541591582, 0.0680736331847348, 0.0681630122103114, + 0.068252391235888, 0.0683417702614646, 0.0684311492870411, 0.0685205283126177, + 0.0686099073381943, 0.0686992863637709, 0.0687886653893475, 0.0688780444149241, + 0.0689674234405007, 0.0690568024660772, 0.0691461814916538, 0.0692360676941551, + 0.0693263297119362, 0.0694165917297173, 0.0695068537474984, 0.0695971157652796, + 0.0696873777830607, 0.0697776398008418, 0.069867901818623, 0.0699581638364041, + 0.0700484258541852, 0.0701386878719663, 0.0702289498897475, 0.0703192119075286, + 0.0704094739253097, 0.0704997359430908, 0.070589997960872, 0.0706802599786531, + 0.0707705219964342, 0.0708607840142153, 0.0709510460319965, 0.0710413080497776, + 0.0711315700675587, 0.0712218320853398, 0.071312094103121, 0.0714023561209021, + 0.0714926181386832, 0.0715828801564643, 0.0716731421742455, 0.0717634041920266, + 0.0718536662098077, 0.0719439282275889, 0.07203419024537, 0.0721244522631511, + 0.0722147142809322, 0.0723049762987134, 0.0723960101828217, 0.0724873233770361, + 0.0725786365712504, 0.0726699497654648, 0.0727612629596791, 0.0728525761538934, + 0.0729438893481078, 0.0730352025423221, 0.0731265157365365, 0.0732178289307508, + 0.0733091421249651, 0.0734004553191795, 0.0734917685133938, 0.0735830817076082, + 0.0736743949018225, 0.0737657080960368, 0.0738570212902512, 0.0739483344844655, + 0.0740396476786799, 0.0741309608728942, 0.0742222740671085, 0.0743135872613229, + 0.0744049004555372, 0.0744962136497516, 0.0745875268439659, 0.0746788400381802, + 0.0747701532323946, 0.0748614664266089, 0.0749527796208233, 0.0750440928150376, + 0.0751354060092519, 0.0752267192034663, 0.0753180323976806, 0.075409345591895, + 0.0755010094289928, 0.0755935101846347, 0.0756860109402766, 0.0757785116959184, + 0.0758710124515603, 0.0759635132072022, 0.076056013962844, 0.0761485147184859, + 0.0762410154741277, 0.0763335162297696, 0.0764260169854115, 0.0765185177410533, + 0.0766110184966952, 0.0767035192523371, 0.0767960200079789, 0.0768885207636208, + 0.0769810215192626, 0.0770735222749045, 0.0771660230305464, 0.0772585237861882, + 0.0773510245418301, 0.0774435252974719, 0.0775360260531138, 0.0776285268087557, + 0.0777210275643975, 0.0778135283200394, 0.0779060290756813, 0.0779985298313231, + 0.078091030586965, 0.0781835313426068, 0.0782760320982487, 0.0783685328538906, + 0.0784610336095324, 0.0785535343651743, 0.078646421750512, 0.0787402182702954, + 0.0788340147900788, 0.0789278113098621, 0.0790216078296455, 0.0791154043494289, + 0.0792092008692122, 0.0793029973889956, 0.079396793908779, 0.0794905904285623, + 0.0795843869483457, 0.0796781834681291, 0.0797719799879124, 0.0798657765076958, + 0.0799595730274791, 0.0800533695472625, 0.0801471660670459, 0.0802409625868293, + 0.0803347591066126, 0.080428555626396, 0.0805223521461793, 0.0806161486659627, + 0.0807099451857461, 0.0808037417055294, 0.0808975382253128, 0.0809913347450962, + 0.0810851312648795, 0.0811789277846629, 0.0812727243044463, 0.0813665208242296, + 0.081460317344013, 0.0815541138637964, 0.0816479103835797, 0.0817417069033631, + 0.0818365672265629, 0.0819317432475666, 0.0820269192685703, 0.0821220952895741, + 0.0822172713105778, 0.0823124473315815, 0.0824076233525853, 0.082502799373589, + 0.0825979753945927, 0.0826931514155965, 0.0827883274366002, 0.0828835034576039, + 0.0829786794786076, 0.0830738554996114, 0.0831690315206151, 0.0832642075416188, + 0.0833593835626226, 0.0834545595836263, 0.08354973560463, 0.0836449116256338, + 0.0837400876466375, 0.0838352636676412, 0.0839304396886449, 0.0840256157096487, + 0.0841207917306524, 0.0842159677516561, 0.0843111437726599, 0.0844063197936636, + 0.0845014958146673, 0.0845966718356711, 0.0846918478566748, 0.0847870238776785, + 0.0848821998986822, 0.0849784289019381, 0.085075047616302, 0.0851716663306659, + 0.0852682850450297, 0.0853649037593936, 0.0854615224737575, 0.0855581411881213, + 0.0856547599024852, 0.0857513786168491, 0.0858479973312129, 0.0859446160455768, + 0.0860412347599407, 0.0861378534743045, 0.0862344721886684, 0.0863310909030323, + 0.0864277096173961, 0.08652432833176, 0.0866209470461239, 0.0867175657604877, + 0.0868141844748516, 0.0869108031892155, 0.0870074219035793, 0.0871040406179432, + 0.0872006593323071, 0.0872972780466709, 0.0873938967610348, 0.0874905154753987, + 0.0875871341897625, 0.0876837529041264, 0.0877803716184903, 0.0878769903328541, + 0.087973609047218, 0.0880704987888095, 0.0881686069849526, 0.0882667151810957, + 0.0883648233772388, 0.0884629315733819, 0.088561039769525, 0.088659147965668, + 0.0887572561618111, 0.0888553643579542, 0.0889534725540973, 0.0890515807502404, + 0.0891496889463834, 0.0892477971425265, 0.0893459053386696, 0.0894440135348127, + 0.0895421217309558, 0.0896402299270989, 0.0897383381232419, 0.089836446319385, + 0.0899345545155281, 0.0900326627116712, 0.0901307709078143, 0.0902288791039574, + 0.0903269873001004, 0.0904250954962435, 0.0905232036923866, 0.0906213118885297, + 0.0907194200846728, 0.0908175282808159, 0.0909156364769589, 0.091013744673102, + 0.0911118528692451, 0.0912101564524853, 0.091309788819085, 0.0914094211856847, + 0.0915090535522844, 0.0916086859188841, 0.0917083182854838, 0.0918079506520835, + 0.0919075830186832, 0.0920072153852829, 0.0921068477518826, 0.0922064801184823, + 0.092306112485082, 0.0924057448516817, 0.0925053772182814, 0.0926050095848811, + 0.0927046419514808, 0.0928042743180805, 0.0929039066846802, 0.0930035390512799, + 0.0931031714178795, 0.0932028037844792, 0.0933024361510789, 0.0934020685176786, + 0.0935017008842783, 0.093601333250878, 0.0937009656174777, 0.0938005979840774, + 0.0939002303506771, 0.0939998627172768, 0.0940994950838765, 0.0941991274504762, + 0.0942987598170759, 0.0943992682225221, 0.0945004517019513, 0.0946016351813804, + 0.0947028186608096, 0.0948040021402388, 0.0949051856196679, 0.0950063690990971, + 0.0951075525785263, 0.0952087360579554, 0.0953099195373846, 0.0954111030168138, + 0.095512286496243, 0.0956134699756721, 0.0957146534551013, 0.0958158369345305, + 0.0959170204139596, 0.0960182038933888, 0.0961193873728179, 0.0962205708522471, + 0.0963217543316763, 0.0964229378111054, 0.0965241212905346, 0.0966253047699638, + 0.096726488249393, 0.0968276717288221, 0.0969288552082513, 0.0970300386876805, + 0.0971312221671096, 0.0972324056465388, 0.097333589125968, 0.0974347726053971, + 0.0975367201066298, 0.0976394781515203, 0.0977422361964109, 0.0978449942413014, + 0.0979477522861919, 0.0980505103310825, 0.098153268375973, 0.0982560264208636, + 0.0983587844657541, 0.0984615425106447, 0.0985643005555352, 0.0986670586004257, + 0.0987698166453163, 0.0988725746902068, 0.0989753327350974, 0.0990780907799879, + 0.0991808488248785, 0.099283606869769, 0.0993863649146595, 0.0994891229595501, + 0.0995918810044406, 0.0996946390493312, 0.0997973970942217, 0.0999001551391123, + 0.100002913184003, 0.100105671228893, 0.100208429273784, 0.100311187318674, + 0.100413945363565, 0.100516703408456, 0.100619461453346, 0.100723629254328, + 0.100827985831608, 0.100932342408888, 0.101036698986168, 0.101141055563448, + 0.101245412140728, 0.101349768718008, 0.101454125295288, 0.101558481872568, + 0.101662838449848, 0.101767195027128, 0.101871551604408, 0.101975908181688, + 0.102080264758968, 0.102184621336248, 0.102288977913528, 0.102393334490808, + 0.102497691068088, 0.102602047645368, 0.102706404222648, 0.102810760799928, + 0.102915117377208, 0.103019473954489, 0.103123830531769, 0.103228187109049, + 0.103332543686329, 0.103436900263609, 0.103541256840889, 0.103645613418169, + 0.103749969995449, 0.103855542256336, 0.103961525455448, 0.10406750865456, + 0.104173491853672, 0.104279475052784, 0.104385458251896, 0.104491441451008, + 0.10459742465012, 0.104703407849232, 0.104809391048344, 0.104915374247456, + 0.105021357446568, 0.10512734064568, 0.105233323844792, 0.105339307043904, + 0.105445290243016, 0.105551273442128, 0.10565725664124, 0.105763239840352, + 0.105869223039463, 0.105975206238575, 0.106081189437687, 0.106187172636799, + 0.106293155835911, 0.106399139035023, 0.106505122234135, 0.106611105433247, + 0.106717088632359, 0.106823071831471, 0.106929180224288, 0.107036825355525, + 0.107144470486762, 0.107252115617999, 0.107359760749236, 0.107467405880472, + 0.107575051011709, 0.107682696142946, 0.107790341274183, 0.10789798640542, + 0.108005631536657, 0.108113276667893, 0.10822092179913, 0.108328566930367, + 0.108436212061604, 0.108543857192841, 0.108651502324078, 0.108759147455314, + 0.108866792586551, 0.108974437717788, 0.109082082849025, 0.109189727980262, + 0.109297373111499, 0.109405018242735, 0.109512663373972, 0.109620308505209, + 0.109727953636446, 0.109835598767683, 0.109943243898919, 0.110050889030156, + 0.110160004550903, 0.110269356659303, 0.110378708767703, 0.110488060876102, + 0.110597412984502, 0.110706765092902, 0.110816117201301, 0.110925469309701, + 0.111034821418101, 0.111144173526501, 0.1112535256349, 0.1113628777433, + 0.1114722298517, 0.111581581960099, 0.111690934068499, 0.111800286176899, + 0.111909638285299, 0.112018990393698, 0.112128342502098, 0.112237694610498, + 0.112347046718897, 0.112456398827297, 0.112565750935697, 0.112675103044096, + 0.112784455152496, 0.112893807260896, 0.113003159369296, 0.113112511477695, + 0.113222046117384, 0.113333161880498, 0.113444277643611, 0.113555393406725, + 0.113666509169839, 0.113777624932953, 0.113888740696067, 0.113999856459181, + 0.114110972222295, 0.114222087985409, 0.114333203748523, 0.114444319511637, + 0.114555435274751, 0.114666551037865, 0.114777666800979, 0.114888782564093, + 0.114999898327207, 0.115111014090321, 0.115222129853435, 0.115333245616548, + 0.115444361379662, 0.115555477142776, 0.11566659290589, 0.115777708669004, + 0.115888824432118, 0.115999940195232, 0.116111055958346, 0.11622217172146, + 0.116333287484574, 0.116445873599659, 0.116558822617734, 0.116671771635809, + 0.116784720653884, 0.116897669671959, 0.117010618690034, 0.117123567708109, + 0.117236516726183, 0.117349465744258, 0.117462414762333, 0.117575363780408, + 0.117688312798483, 0.117801261816558, 0.117914210834633, 0.118027159852708, + 0.118140108870782, 0.118253057888857, 0.118366006906932, 0.118478955925007, + 0.118591904943082, 0.118704853961157, 0.118817802979232, 0.118930751997306, + 0.119043701015381, 0.119156650033456, 0.119269599051531, 0.119382548069606, + 0.119495497087681, 0.119610285849454, 0.119725151369885, 0.119840016890317, + 0.119954882410748, 0.12006974793118, 0.120184613451611, 0.120299478972043, + 0.120414344492474, 0.120529210012906, 0.120644075533337, 0.120758941053769, + 0.1208738065742, 0.120988672094632, 0.121103537615063, 0.121218403135495, + 0.121333268655926, 0.121448134176358, 0.121562999696789, 0.121677865217221, + 0.121792730737652, 0.121907596258083, 0.122022461778515, 0.122137327298946, + 0.122252192819378, 0.122367058339809, 0.122481923860241, 0.122596789380672, + 0.122712827616384, 0.122829706758501, 0.122946585900619, 0.123063465042737, + 0.123180344184855, 0.123297223326972, 0.12341410246909, 0.123530981611208, + 0.123647860753326, 0.123764739895444, 0.123881619037561, 0.123998498179679, + 0.124115377321797, 0.124232256463915, 0.124349135606032, 0.12446601474815, + 0.124582893890268, 0.124699773032386, 0.124816652174504, 0.124933531316621, + 0.125050410458739, 0.125167289600857, 0.125284168742975, 0.125401047885093, + 0.12551792702721, 0.125634806169328, 0.125751685311446, 0.125870001624282, + 0.125989005185262, 0.126108008746242, 0.126227012307222, 0.126346015868202, + 0.126465019429183, 0.126584022990163, 0.126703026551143, 0.126822030112123, + 0.126941033673104, 0.127060037234084, 0.127179040795064, 0.127298044356044, + 0.127417047917024, 0.127536051478005, 0.127655055038985, 0.127774058599965, + 0.127893062160945, 0.128012065721925, 0.128131069282906, 0.128250072843886, + 0.128369076404866, 0.128488079965846, 0.128607083526826, 0.128726087087807, + 0.128845090648787, 0.128964658385504, 0.12908591031452, 0.129207162243537, + 0.129328414172554, 0.129449666101571, 0.129570918030588, 0.129692169959604, + 0.129813421888621, 0.129934673817638, 0.130055925746655, 0.130177177675671, + 0.130298429604688, 0.130419681533705, 0.130540933462722, 0.130662185391739, + 0.130783437320756, 0.130904689249772, 0.131025941178789, 0.131147193107806, + 0.131268445036823, 0.131389696965839, 0.131510948894856, 0.131632200823873, + 0.13175345275289, 0.131874704681907, 0.131995956610923, 0.132117960580623, + 0.132241597208114, 0.132365233835605, 0.132488870463096, 0.132612507090587, + 0.132736143718078, 0.132859780345569, 0.13298341697306, 0.133107053600551, + 0.133230690228042, 0.133354326855533, 0.133477963483024, 0.133601600110515, + 0.133725236738006, 0.133848873365497, 0.133972509992989, 0.13409614662048, + 0.134219783247971, 0.134343419875462, 0.134467056502953, 0.134590693130444, + 0.134714329757935, 0.134837966385426, 0.134961603012917, 0.135085239640408, + 0.135208876267899, 0.135334741574242, 0.135460910678424, 0.135587079782606, + 0.135713248886787, 0.135839417990969, 0.13596558709515, 0.136091756199332, + 0.136217925303513, 0.136344094407695, 0.136470263511876, 0.136596432616058, + 0.136722601720239, 0.136848770824421, 0.136974939928602, 0.137101109032784, + 0.137227278136966, 0.137353447241147, 0.137479616345329, 0.13760578544951, + 0.137731954553692, 0.137858123657873, 0.137984292762055, 0.138110461866236, + 0.138236630970418, 0.138362800074599, 0.13849153947217, 0.13862039925771, + 0.13874925904325, 0.138878118828789, 0.139006978614329, 0.139135838399868, + 0.139264698185408, 0.139393557970948, 0.139522417756487, 0.139651277542027, + 0.139780137327567, 0.139908997113106, 0.140037856898646, 0.140166716684185, + 0.140295576469725, 0.140424436255265, 0.140553296040804, 0.140682155826344, + 0.140811015611884, 0.140939875397423, 0.141068735182963, 0.141197594968502, + 0.141326454754042, 0.141455314539582, 0.141585749009815, 0.141717467065314, + 0.141849185120812, 0.14198090317631, 0.142112621231808, 0.142244339287306, + 0.142376057342804, 0.142507775398303, 0.142639493453801, 0.142771211509299, + 0.142902929564797, 0.143034647620295, 0.143166365675793, 0.143298083731292, + 0.14342980178679, 0.143561519842288, 0.143693237897786, 0.143824955953284, + 0.143956674008782, 0.144088392064281, 0.144220110119779, 0.144351828175277, + 0.144483546230775, 0.144615264286273, 0.1447490339688, 0.144883786261577, + 0.145018538554355, 0.145153290847132, 0.145288043139909, 0.145422795432687, + 0.145557547725464, 0.145692300018242, 0.145827052311019, 0.145961804603797, + 0.146096556896574, 0.146231309189352, 0.146366061482129, 0.146500813774907, + 0.146635566067684, 0.146770318360462, 0.146905070653239, 0.147039822946016, + 0.147174575238794, 0.147309327531571, 0.147444079824349, 0.147578832117126, + 0.147713584409904, 0.147849427450957, 0.147987397410062, 0.148125367369167, + 0.148263337328272, 0.148401307287377, 0.148539277246481, 0.148677247205586, + 0.148815217164691, 0.148953187123796, 0.149091157082901, 0.149229127042006, + 0.149367097001111, 0.149505066960216, 0.14964303691932, 0.149781006878425, + 0.14991897683753, 0.150056946796635, 0.15019491675574, 0.150332886714845, + 0.15047085667395, 0.150608826633055, 0.150746796592159, 0.150884766551264, + 0.15102459740471, 0.151165975136252, 0.151307352867794, 0.151448730599335, + 0.151590108330877, 0.151731486062418, 0.15187286379396, 0.152014241525502, + 0.152155619257043, 0.152296996988585, 0.152438374720127, 0.152579752451668, + 0.15272113018321, 0.152862507914751, 0.153003885646293, 0.153145263377835, + 0.153286641109376, 0.153428018840918, 0.15356939657246, 0.153710774304001, + 0.153852152035543, 0.153993529767084, 0.154135997909478, 0.154280979582231, + 0.154425961254984, 0.154570942927738, 0.154715924600491, 0.154860906273244, + 0.155005887945997, 0.15515086961875, 0.155295851291504, 0.155440832964257, + 0.15558581463701, 0.155730796309763, 0.155875777982516, 0.156020759655269, + 0.156165741328023, 0.156310723000776, 0.156455704673529, 0.156600686346282, + 0.156745668019035, 0.156890649691789, 0.157035631364542, 0.157180613037295, + 0.15732792374043, 0.157476711173768, 0.157625498607107, 0.157774286040445, + 0.157923073473783, 0.158071860907122, 0.15822064834046, 0.158369435773798, + 0.158518223207137, 0.158667010640475, 0.158815798073813, 0.158964585507152, + 0.15911337294049, 0.159262160373828, 0.159410947807167, 0.159559735240505, + 0.159708522673843, 0.159857310107182, 0.16000609754052, 0.160154884973858, + 0.160303672407197, 0.160454370862285, 0.160607171342644, 0.160759971823002, + 0.16091277230336, 0.161065572783718, 0.161218373264077, 0.161371173744435, + 0.161523974224793, 0.161676774705151, 0.16182957518551, 0.161982375665868, + 0.162135176146226, 0.162287976626584, 0.162440777106943, 0.162593577587301, + 0.162746378067659, 0.162899178548017, 0.163051979028376, 0.163204779508734, + 0.163357579989092, 0.16351038046945, 0.163666965317135, 0.163823991662984, + 0.163981018008832, 0.164138044354681, 0.16429507070053, 0.164452097046379, + 0.164609123392228, 0.164766149738077, 0.164923176083925, 0.165080202429774, + 0.165237228775623, 0.165394255121472, 0.165551281467321, 0.16570830781317, + 0.165865334159018, 0.166022360504867, 0.166179386850716, 0.166336413196565, + 0.166493439542414, 0.166650465888263, 0.166811353257257, 0.166972824145877, + 0.167134295034498, 0.167295765923119, 0.16745723681174, 0.167618707700361, + 0.167780178588982, 0.167941649477603, 0.168103120366224, 0.168264591254845, + 0.168426062143466, 0.168587533032087, 0.168749003920708, 0.168910474809329, + 0.16907194569795, 0.169233416586571, 0.169394887475191, 0.169556358363812, + 0.169717829252433, 0.169881135986996, 0.170047276549132, 0.170213417111268, + 0.170379557673404, 0.17054569823554, 0.170711838797676, 0.170877979359812, + 0.171044119921948, 0.171210260484084, 0.17137640104622, 0.171542541608356, + 0.171708682170492, 0.171874822732628, 0.172040963294764, 0.1722071038569, + 0.172373244419036, 0.172539384981172, 0.172705525543308, 0.172871666105445, + 0.173040085999429, 0.173211128680302, 0.173382171361174, 0.173553214042047, + 0.17372425672292, 0.173895299403793, 0.174066342084665, 0.174237384765538, + 0.174408427446411, 0.174579470127283, 0.174750512808156, 0.174921555489029, + 0.175092598169902, 0.175263640850774, 0.175434683531647, 0.17560572621252, + 0.175776768893392, 0.175947811574265, 0.176119261994817, 0.17629544767239, + 0.176471633349963, 0.176647819027536, 0.176824004705109, 0.177000190382682, + 0.177176376060256, 0.177352561737829, 0.177528747415402, 0.177704933092975, + 0.177881118770548, 0.178057304448121, 0.178233490125694, 0.178409675803267, + 0.17858586148084, 0.178762047158413, 0.178938232835986, 0.179114418513559, + 0.179291846271207, 0.179473425615275, 0.179655004959343, 0.179836584303412, + 0.18001816364748, 0.180199742991548, 0.180381322335617, 0.180562901679685, + 0.180744481023753, 0.180926060367821, 0.18110763971189, 0.181289219055958, + 0.181470798400026, 0.181652377744095, 0.181833957088163, 0.182015536432231, + 0.182197115776299, 0.182378695120368, 0.182565429521855, 0.182752664571132, + 0.182939899620409, 0.183127134669687, 0.183314369718964, 0.183501604768241, + 0.183688839817518, 0.183876074866796, 0.184063309916073, 0.18425054496535, + 0.184437780014627, 0.184625015063905, 0.184812250113182, 0.184999485162459, + 0.185186720211736, 0.185373955261014, 0.185561877182958, 0.185755043112146, + 0.185948209041333, 0.18614137497052, 0.186334540899708, 0.186527706828895, + 0.186720872758082, 0.186914038687269, 0.187107204616457, 0.187300370545644, + 0.187493536474831, 0.187686702404018, 0.187879868333206, 0.188073034262393, + 0.18826620019158, 0.188459366120767, 0.188652532049955, 0.188850897795331, + 0.189050284840682, 0.189249671886032, 0.189449058931383, 0.189648445976733, + 0.189847833022084, 0.190047220067434, 0.190246607112785, 0.190445994158135, + 0.190645381203486, 0.190844768248836, 0.191044155294186, 0.191243542339537, + 0.191442929384887, 0.191642316430238, 0.191842120048372, 0.192048035558685, + 0.192253951068997, 0.19245986657931, 0.192665782089623, 0.192871697599936, + 0.193077613110249, 0.193283528620561, 0.193489444130874, 0.193695359641187, + 0.1939012751515, 0.194107190661812, 0.194313106172125, 0.194519021682438, + 0.194724937192751, 0.194930852703063, 0.195142196260036, 0.195354966840488, + 0.195567737420939, 0.195780508001391, 0.195993278581843, 0.196206049162294, + 0.196418819742746, 0.196631590323197, 0.196844360903649, 0.1970571314841, + 0.197269902064552, 0.197482672645003, 0.197695443225455, 0.197908213805906, + 0.198121069994851, 0.198341043713548, 0.198561017432244, 0.198780991150941, + 0.199000964869638, 0.199220938588335, 0.199440912307032, 0.199660886025729, + 0.199880859744426, 0.200100833463123, 0.20032080718182, 0.200540780900516, + 0.200760754619213, 0.20098072833791, 0.201200702056607, 0.201426098778158, + 0.201653647409568, 0.201881196040977, 0.202108744672387, 0.202336293303797, + 0.202563841935207, 0.202791390566617, 0.203018939198027, 0.203246487829437, + 0.203474036460846, 0.203701585092256, 0.203929133723666, 0.204156682355076, + 0.204384230986486, 0.204618921911524, 0.204854443196773, 0.205089964482023, + 0.205325485767273, 0.205561007052523, 0.205796528337772, 0.206032049623022, + 0.206267570908272, 0.206503092193521, 0.206738613478771, 0.206974134764021, + 0.207209656049271, 0.20744517733452, 0.207685264164212, 0.207929184075172, + 0.208173103986132, 0.208417023897092, 0.208660943808051, 0.208904863719011, + 0.209148783629971, 0.209392703540931, 0.209636623451891, 0.20988054336285, + 0.21012446327381, 0.21036838318477, 0.21061230309573, 0.210861988612869, + 0.211114763614686, 0.211367538616503, 0.21162031361832, 0.211873088620137, + 0.212125863621954, 0.212378638623771, 0.212631413625588, 0.212884188627405, + 0.213136963629222, 0.213389738631039, 0.213642513632856, 0.21389725328031, + 0.21415937259508, 0.214421491909849, 0.214683611224619, 0.214945730539388, + 0.215207849854158, 0.215469969168927, 0.215732088483697, 0.215994207798466, + 0.216256327113236, 0.216518446428005, 0.216780565742775, 0.217044786070963, + 0.217316773953234, 0.217588761835504, 0.217860749717775, 0.218132737600046, + 0.218404725482316, 0.218676713364587, 0.218948701246858, 0.219220689129129, + 0.219492677011399, 0.21976466489367, 0.220036652775941, 0.220315429127038, + 0.220597847169457, 0.220880265211875, 0.221162683254294, 0.221445101296713, + 0.221727519339132, 0.222009937381551, 0.222292355423969, 0.222574773466388, + 0.222857191508807, 0.223139609551226, 0.22342771767927, 0.223721167173466, + 0.224014616667663, 0.224308066161859, 0.224601515656055, 0.224894965150251, + 0.225188414644448, 0.225481864138644, 0.22577531363284, 0.226068763127036, + 0.226362212621233, 0.226664994482626, 0.226970118866384, 0.227275243250142, + 0.2275803676339, 0.227885492017658, 0.228190616401416, 0.228495740785174, + 0.228800865168932, 0.22910598955269, 0.229411113936448, 0.229722332589382, + 0.23003982001567, 0.230357307441958, 0.230674794868246, 0.230992282294534, + 0.231309769720823, 0.231627257147111, 0.231944744573399, 0.232262231999687, + 0.232579719425975, 0.232904907091642, 0.233235493158276, 0.233566079224911, + 0.233896665291545, 0.234227251358179, 0.234557837424813, 0.234888423491448, + 0.235219009558082, 0.235549595624716, 0.23588122654071, 0.23622569722098, + 0.236570167901249, 0.236914638581519, 0.237259109261789, 0.237603579942058, + 0.237948050622328, 0.238292521302597, 0.238636991982867, 0.238981462663137, + 0.239339863330258, 0.239699058144633, 0.240058252959007, 0.240417447773382, + 0.240776642587756, 0.241135837402131, 0.241495032216506, 0.24185422703088, + 0.242216406978558, 0.242591222445708, 0.242966037912857, 0.243340853380006, + 0.243715668847156, 0.244090484314305, 0.244465299781455, 0.244840115248604, + 0.245214930715753, 0.245603025218856, 0.245994418620466, 0.246385812022076, + 0.246777205423686, 0.247168598825296, 0.247559992226905, 0.247951385628515, + 0.248342779030125, 0.248747659098606, 0.249156652587053, 0.2495656460755, + 0.249974639563947, 0.250383633052394, 0.250792626540841, 0.251201620029289, + 0.251612058698921, 0.252039743769879, 0.252467428840838, 0.252895113911796, + 0.253322798982754, 0.253750484053712, 0.25417816912467, 0.254605854195628, + 0.255047923667439, 0.255495466011053, 0.255943008354667, 0.256390550698281, + 0.256838093041895, 0.257285635385509, 0.257733177729124, 0.258195443386208, + 0.258664088120685, 0.259132732855161, 0.259601377589638, 0.260070022324114, + 0.260538667058591, 0.261007311793068, 0.261498107058485, 0.261989184339014, + 0.262480261619543, 0.262971338900072, 0.263462416180601, 0.26395349346113, + 0.264458493569672, 0.264973424553304, 0.265488355536937, 0.266003286520569, + 0.266518217504202, 0.267033148487834, 0.267560171105367, 0.268100474238653, + 0.268640777371939, 0.269181080505224, 0.26972138363851, 0.270261686771796, + 0.270819705028464, 0.271387002608867, 0.271954300189269, 0.272521597769672, + 0.273088895350075, 0.273659435845581, 0.274255460789027, 0.274851485732473, + 0.275447510675919, 0.276043535619365, 0.276639560562811, 0.27726116998853, + 0.277887772713072, 0.278514375437614, 0.279140978162156, 0.279767580886698, + 0.280420811353434, 0.281079966661232, 0.281739121969031, 0.282398277276829, + 0.283059066113607, 0.283752879919502, 0.284446693725398, 0.285140507531294, + 0.28583432133719, 0.286547124650447, 0.287277840363085, 0.288008556075722, + 0.28873927178836, 0.28947827559471, 0.290248279904922, 0.291018284215134, + 0.291788288525346, 0.292563600337405, 0.293375428108293, 0.294187255879181, + 0.294999083650069, 0.295822183677325, 0.296678521560245, 0.297534859443166, + 0.298391197326086, 0.299275043092916, 0.300178731417868, 0.301082419742821, + 0.301991195383678, 0.302945227793297, 0.303899260202916, 0.304853292612535, + 0.305850371610192, 0.306857891831609, 0.307865412053027, 0.308911739467469, + 0.30997603455584, 0.311040329644211, 0.3121484923185, 0.313272981669674, + 0.314397471020849, 0.315581367988403, 0.316769587425637, 0.317977043703226, + 0.319232624005811, 0.320488204308396, 0.321799279628635, 0.323125919008203, + 0.324483261263213, 0.325884691519315, 0.327299200035216, 0.328779146439744, + 0.330262517515396, 0.331824652884333, 0.333389238077772, 0.335037131964496, + 0.336695746759716, 0.338432811211082, 0.340198496730592, 0.342027930528006, + 0.343913675793935, 0.345838409480119, 0.347856846578894, 0.3499197798127, + 0.352042579297134, 0.354259302490772, 0.356536561493589, 0.358881109319561, + 0.361313671166056, 0.363836817926778, 0.366439748491679, 0.369127446160857, + 0.371904231534573, 0.374773682388992, 0.377738570378694, 0.380800810162814, + 0.383961415989582, 0.387220461700673, 0.390577042394362, 0.394029239174462, + 0.397574091869165, 0.401207587569535, 0.404924674602348, 0.40871931155475, + 0.412593091812825, 0.416529405960117, 0.420518172148167, 0.424550658028915, + 0.428622797503118, 0.432718860047201, 0.43683110495589, 0.440952990102399, + 0.445076899215516, 0.449197788292571, 0.453311201371651, 0.45741409960577, + 0.461505869878849, 0.46558559365979, 0.469652236896929, 0.473708637399971, + 0.477756372989858, 0.481796989922385, 0.48583413706365, 0.48987125467134, + 0.493912219101465, 0.497962736080536, 0.502026812075268, 0.506109594319579, + 0.510221399822655, 0.514366957318452, 0.518552310031674, 0.522793051201349, + 0.527095750969031, 0.531466650081574, 0.535935589143574, 0.540497859381824, + 0.54518677008268, 0.55000657107477, 0.55499781241368, 0.570387005978552, + 0.575784020390147, 0.581355522358758, 0.587107695883691, 0.593047270300356, + 0.599186533270629, 0.605538121640565, 0.612115028481841, 0.61893061023499, + 0.626001861804575, 0.633353622260075, 0.640990719796521, 0.648946229610552, + 0.657230965238893, 0.665888971698384, 0.674935579636987, 0.68440554485823, + 0.694335038623836, 0.704766859548509, 0.71575271257307, 0.727336811019529, + 0.739584089095298, 0.752568375665671, 0.766367354784415, 0.781079093721498, + 0.79681569276495, 0.813711227439116, 0.831930890200451, 0.85166548254417, + 0.873163787875069, 0.896719943817702, 0.922723548624586, 0.951660429762437, + 0.984178161492999, 1.02116199287154, 1.06381685448612, 1.11388721526635, + 1.1739726045265, 1.2481155622603, 1.34292501514454, 1.46959617817339, + 1.64691705586599, 1.9024633637756, 2.27273568577832, 3.14159265358979 +}; + +struct sampler_context { + struct geometry geometry; + double aspect_ratio; + double mean_radius; + double sigma; +}; + +static void +get_material_property + (void* mtl, + const double wavelength, + struct sschiff_material_properties* props) +{ + (void)mtl, (void)wavelength; + props->medium_refractive_index = 1.33; + props->relative_imaginary_refractive_index = 1.7e-3/1.33; + props->relative_real_refractive_index = 1.39/1.33; +} + +static res_T +sample_cylinder + (struct ssp_rng* rng, struct s3d_shape* shape, void* sampler_context) +{ + struct sampler_context* sampler_ctx = sampler_context; + struct cylinder cylinder; + double sample; + (void)rng, (void)sampler_context; + + sample = ssp_ran_lognormal(rng, log(sampler_ctx->mean_radius), log(sampler_ctx->sigma)); + cylinder.geometry = &sampler_ctx->geometry; + cylinder.radius = (float)(sample / pow(3.0 / (2.0*sampler_ctx->aspect_ratio), 1.0/3.0)); + cylinder.height = (float)(2.f * cylinder.radius / sampler_ctx->aspect_ratio); + + return cylinder_setup_s3d_shape(&cylinder, shape); +} + +struct cross_section_result { + double absorption_E; + double absorption_SE; + double extinction_E; + double extinction_SE; + double scattering_E; + double scattering_SE; +}; + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct sampler_context sampler_ctx; + struct sschiff_device* dev; + struct sschiff_geometry_distribution distrib = SSCHIFF_NULL_GEOMETRY_DISTRIBUTION; + struct sschiff_estimator* estimator; + struct sschiff_cross_section cross_section; + struct ssp_rng* rng; + struct sschiff_state result, result2; + const struct sschiff_state* val; + const struct sschiff_state* func = NULL; + const struct sschiff_state* cumul = NULL; + struct cross_section_result cross_section_result; + double* thetas = NULL; + double interval[2]; + double n; + const double* angles = NULL; + const double wavelength = 0.5; /* In micron */ + const size_t nscatt_angles = 1000; + const size_t ngeoms = 1000; + const size_t ndirs = 1000; + size_t count; + size_t ilimit_angle; + size_t i; + (void)argc, (void)argv; + + mem_init_proxy_allocator(&allocator, &mem_default_allocator); + CHECK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng), RES_OK); + CHECK(sschiff_device_create + (NULL, &allocator, SSCHIFF_NTHREADS_DEFAULT, 1, NULL, &dev), RES_OK); + + geometry_init_cylinder(&sampler_ctx.geometry, 64); + + cross_section_result.extinction_E = 2.81307852441391; + cross_section_result.extinction_SE = 7.86230094748024e-4; + cross_section_result.scattering_E = 2.63488155160904; + cross_section_result.scattering_SE = 7.53366332231861e-4; + cross_section_result.absorption_E = 1.78192486614360e-1; + cross_section_result.absorption_SE = 3.44690633379987e-5; + + sampler_ctx.aspect_ratio = 0.263; + sampler_ctx.mean_radius = 0.983; + sampler_ctx.sigma = 1.1374; + + distrib.characteristic_length = 0.38190884533484676025; + distrib.material.get_property = get_material_property; + distrib.material.material = &sampler_ctx; + distrib.sample = sample_cylinder; + distrib.context = &sampler_ctx; + + CHECK(sschiff_integrate(dev, rng, &distrib, &wavelength, 1, + sschiff_uniform_scattering_angles, nscatt_angles, ngeoms, ndirs, + &estimator), RES_OK); + + CHECK(sschiff_estimator_get_cross_section + (estimator, 0, &cross_section), RES_OK); + + printf("Wavelength = %g micron\n", wavelength); + + result.E = cross_section_result.extinction_E; + result.SE = cross_section_result.extinction_SE; + val = &cross_section.extinction; + compute_estimation_intersection(interval, 4, &result, val); + printf(" Extinction = %9.3g +/- %9.3g ~ %9.3g +/- %9.3g (%9.3g)\n", + result.E, result.SE, val->E, val->SE, interval[1]-interval[0]); + CHECK(interval[0] <= interval[1], 1); + + result.E = cross_section_result.absorption_E; + result.SE = cross_section_result.absorption_SE; + val = &cross_section.absorption; + compute_estimation_intersection(interval, 4, &result, val); + printf(" Absorption = %9.3g +/- %9.3g ~ %9.3g +/- %9.3g (%9.3g)\n", + result.E, result.SE, val->E, val->SE, interval[1]-interval[0]); + CHECK(interval[0] <= interval[1], 1); + + result.E = cross_section_result.scattering_E; + result.SE = cross_section_result.scattering_SE; + val = &cross_section.scattering; + compute_estimation_intersection(interval, 4, &result, val); + printf(" Scattering = %9.3g +/- %9.3g ~ %9.3g +/- %9.3g (%9.3g)\n", + result.E, result.SE, val->E, val->SE, interval[1]-interval[0]); + CHECK(interval[0] <= interval[1], 1); + + printf(" Proj area ~ %9.3g +/- %9.3g\n", + cross_section.average_projected_area.E, + cross_section.average_projected_area.SE); + + CHECK(sschiff_estimator_get_scattering_angles(estimator, &angles, &count), RES_OK); + CHECK(count, nscatt_angles); + + #define LIMIT_ANGLE sschiff_estimator_get_limit_scattering_angle_index + CHECK(LIMIT_ANGLE(NULL, 1, NULL), RES_BAD_ARG); + CHECK(LIMIT_ANGLE(estimator, 1, NULL), RES_BAD_ARG); + CHECK(LIMIT_ANGLE(NULL, 0, NULL), RES_BAD_ARG); + CHECK(LIMIT_ANGLE(estimator, 0, NULL), RES_BAD_ARG); + CHECK(LIMIT_ANGLE(NULL, 1, &ilimit_angle), RES_BAD_ARG); + CHECK(LIMIT_ANGLE(estimator, 1, &ilimit_angle), RES_BAD_ARG); + CHECK(LIMIT_ANGLE(NULL, 0, &ilimit_angle), RES_BAD_ARG); + CHECK(LIMIT_ANGLE(estimator, 0, &ilimit_angle), RES_OK); + #undef LIMIT_ANGLE + CHECK(ilimit_angle < count, 1); + printf(" Limit angle = %g radians; ", angles[ilimit_angle]); + + #define GET_N sschiff_estimator_get_wide_scattering_angle_model_parameter + CHECK(GET_N(NULL, 1, NULL), RES_BAD_ARG); + CHECK(GET_N(estimator, 1, NULL), RES_BAD_ARG); + CHECK(GET_N(NULL, 0, NULL), RES_BAD_ARG); + CHECK(GET_N(estimator, 0, NULL), RES_BAD_ARG); + CHECK(GET_N(NULL, 1, &n), RES_BAD_ARG); + CHECK(GET_N(estimator, 1, &n), RES_BAD_ARG); + CHECK(GET_N(NULL, 0, &n), RES_BAD_ARG); + CHECK(GET_N(estimator, 0, &n), RES_OK); + #undef GET_N + printf("n = %g\n", n); + + #define DIFF_XSECTION sschiff_estimator_get_differential_cross_section + i = ilimit_angle; + CHECK(DIFF_XSECTION(NULL, 1, nscatt_angles, NULL), RES_BAD_ARG); + CHECK(DIFF_XSECTION(estimator, 1, nscatt_angles, NULL), RES_BAD_ARG); + CHECK(DIFF_XSECTION(NULL, 0, nscatt_angles, NULL), RES_BAD_ARG); + CHECK(DIFF_XSECTION(estimator, 0, nscatt_angles, NULL), RES_BAD_ARG); + CHECK(DIFF_XSECTION(NULL, 1, i, NULL), RES_BAD_ARG); + CHECK(DIFF_XSECTION(estimator, 1, i, NULL), RES_BAD_ARG); + CHECK(DIFF_XSECTION(NULL, 0, i, NULL), RES_BAD_ARG); + CHECK(DIFF_XSECTION(estimator, 0, i, NULL), RES_BAD_ARG); + CHECK(DIFF_XSECTION(NULL, 1, nscatt_angles, &result), RES_BAD_ARG); + CHECK(DIFF_XSECTION(estimator, 1, nscatt_angles, &result), RES_BAD_ARG); + CHECK(DIFF_XSECTION(NULL, 0, nscatt_angles, &result), RES_BAD_ARG); + CHECK(DIFF_XSECTION(estimator, 0, nscatt_angles, &result), RES_BAD_ARG); + CHECK(DIFF_XSECTION(NULL, 1, i, &result), RES_BAD_ARG); + CHECK(DIFF_XSECTION(estimator, 1, i, &result), RES_BAD_ARG); + CHECK(DIFF_XSECTION(NULL, 0, i, &result), RES_BAD_ARG); + CHECK(DIFF_XSECTION(estimator, 0, i, &result), RES_OK); + #undef DIFF_XSECTION + + result2.E = 7.89191057312786e-2; + result2.SE = 2.47342639761112e-03; + compute_estimation_intersection(interval, 4, &result2, &result); + printf(" Ws = %9.3g +/- %9.3g ~ %9.3g +/- %9.3g (%9.3g)\n", + result2.E, result2.SE, result.E, result.SE, interval[1] - interval[0]); + CHECK(interval[0] <= interval[1], 1); + + #define DIFF_XSECTION_CUMUL \ + sschiff_estimator_get_differential_cross_section_cumulative + CHECK(DIFF_XSECTION_CUMUL(NULL, 1, nscatt_angles, NULL), RES_BAD_ARG); + CHECK(DIFF_XSECTION_CUMUL(estimator, 1, nscatt_angles, NULL), RES_BAD_ARG); + CHECK(DIFF_XSECTION_CUMUL(NULL, 0, nscatt_angles, NULL), RES_BAD_ARG); + CHECK(DIFF_XSECTION_CUMUL(estimator, 0, nscatt_angles, NULL), RES_BAD_ARG); + CHECK(DIFF_XSECTION_CUMUL(NULL, 1, i, NULL), RES_BAD_ARG); + CHECK(DIFF_XSECTION_CUMUL(estimator, 1, i, NULL), RES_BAD_ARG); + CHECK(DIFF_XSECTION_CUMUL(NULL, 0, i, NULL), RES_BAD_ARG); + CHECK(DIFF_XSECTION_CUMUL(estimator, 0, i, NULL), RES_BAD_ARG); + CHECK(DIFF_XSECTION_CUMUL(NULL, 1, nscatt_angles, &result), RES_BAD_ARG); + CHECK(DIFF_XSECTION_CUMUL(estimator, 1, nscatt_angles, &result), RES_BAD_ARG); + CHECK(DIFF_XSECTION_CUMUL(NULL, 0, nscatt_angles, &result), RES_BAD_ARG); + CHECK(DIFF_XSECTION_CUMUL(estimator, 0, nscatt_angles, &result), RES_BAD_ARG); + CHECK(DIFF_XSECTION_CUMUL(NULL, 1, i, &result), RES_BAD_ARG); + CHECK(DIFF_XSECTION_CUMUL(estimator, 1, i, &result), RES_BAD_ARG); + CHECK(DIFF_XSECTION_CUMUL(NULL, 0, i, &result), RES_BAD_ARG); + CHECK(DIFF_XSECTION_CUMUL(estimator, 0, i, &result), RES_OK); + #undef DIFF_XSECTION_CUMUL + + result2.E = 2.57417550513944; + result2.SE = 1.89515135143166e-3; + compute_estimation_intersection(interval, 4, &result2, &result); + printf(" Wc = %9.3g +/- %9.3g ~ %9.3g +/- %9.3g (%9.3g)\n", + result2.E, result2.SE, result.E, result.SE, interval[1] - interval[0]); + CHECK(interval[0] <= interval[1], 1); + + #define PHASE_FUNCTION sschiff_estimator_get_phase_function + CHECK(PHASE_FUNCTION(NULL, 1, NULL), RES_BAD_ARG); + CHECK(PHASE_FUNCTION(estimator, 1, NULL), RES_BAD_ARG); + CHECK(PHASE_FUNCTION(NULL, 0, NULL), RES_BAD_ARG); + CHECK(PHASE_FUNCTION(estimator, 0, NULL), RES_BAD_ARG); + CHECK(PHASE_FUNCTION(NULL, 1, &func), RES_BAD_ARG); + CHECK(PHASE_FUNCTION(estimator, 1, &func), RES_BAD_ARG); + CHECK(PHASE_FUNCTION(NULL, 0, &func), RES_BAD_ARG); + CHECK(PHASE_FUNCTION(estimator, 0, &func), RES_OK); + #undef PHASE_FUNCTION + + printf("\n# Phase function\n"); + FOR_EACH(i, 0, 1000) { + result.E = phase_func[i][0]; + result.SE = phase_func[i][1]; + compute_estimation_intersection(interval, 4, &result, &func[i]); + printf("PF(%9.3g) = %9.3g +/- %9.3g ~ %9.3g +/- %9.3g (%9.3g)\n", + (double)i*(PI/999.0), result.E, result.SE, func[i].E, func[i].SE, + interval[1] - interval[0]); + /* Check up to the limit angle only. Wide angles are analytically computed + * and thus are widely affected by the estimation of the `n' parameter that + * is not sufficiently well estimated due to a limited number of + * realisations. */ + if(i <= ilimit_angle) { + CHECK(interval[0] <= interval[1], 1); + } + } + + #define CUMULATIVE sschiff_estimator_get_phase_function_cumulative + CHECK(CUMULATIVE(NULL, 1, NULL), RES_BAD_ARG); + CHECK(CUMULATIVE(estimator, 1, NULL), RES_BAD_ARG); + CHECK(CUMULATIVE(NULL, 0, NULL), RES_BAD_ARG); + CHECK(CUMULATIVE(estimator, 0, NULL), RES_BAD_ARG); + CHECK(CUMULATIVE(NULL, 1, &cumul), RES_BAD_ARG); + CHECK(CUMULATIVE(estimator, 1, &cumul), RES_BAD_ARG); + CHECK(CUMULATIVE(NULL, 0, &cumul), RES_BAD_ARG); + CHECK(CUMULATIVE(estimator, 0, &cumul), RES_OK); + #undef CUMULATIVE + + printf("\n# Cumulative phase function\n"); + FOR_EACH(i, 0, 1000) { + result.E = cumulative[i][0]; + result.SE = cumulative[i][1]; + compute_estimation_intersection(interval, 4, &result, &cumul[i]); + printf("CDF(%9.3g) = %9.3g +/- %9.3g ~ %9.3g +/- %9.3g (%9.3g)\n", + (double)i*(PI/999.0), result.E, result.SE, cumul[i].E, cumul[i].SE, + interval[1] - interval[0]); + /* Check up to the limit angle only. Wide angles are analytically computed + * and thus are widely affected by the estimation of the `n' parameter that + * is not sufficiently well estimated due to a limited number of + * realisations. */ + if(i <= ilimit_angle) { + CHECK(interval[0] <= interval[1], 1); + } + } + + NCHECK(sa_add(thetas, 2000), NULL); + #define INV_CUMULATIVE sschiff_estimator_inverse_cumulative_phase_function + CHECK(INV_CUMULATIVE(NULL, 1, NULL, 0), RES_BAD_ARG); + CHECK(INV_CUMULATIVE(estimator, 1, NULL, 0), RES_BAD_ARG); + CHECK(INV_CUMULATIVE(NULL, 0, NULL, 0), RES_BAD_ARG); + CHECK(INV_CUMULATIVE(estimator, 0, NULL, 0), RES_BAD_ARG); + CHECK(INV_CUMULATIVE(NULL, 1, thetas, 0), RES_BAD_ARG); + CHECK(INV_CUMULATIVE(estimator, 1, thetas, 0), RES_BAD_ARG); + CHECK(INV_CUMULATIVE(NULL, 0, thetas, 0), RES_BAD_ARG); + CHECK(INV_CUMULATIVE(estimator, 0, thetas, 0), RES_BAD_ARG); + CHECK(INV_CUMULATIVE(NULL, 1, NULL, 2), RES_BAD_ARG); + CHECK(INV_CUMULATIVE(estimator, 1, NULL, 2), RES_BAD_ARG); + CHECK(INV_CUMULATIVE(NULL, 0, NULL, 2), RES_BAD_ARG); + CHECK(INV_CUMULATIVE(estimator, 0, NULL, 2), RES_BAD_ARG); + CHECK(INV_CUMULATIVE(NULL, 1, thetas, 2), RES_BAD_ARG); + CHECK(INV_CUMULATIVE(estimator, 1, thetas, 2), RES_BAD_ARG); + CHECK(INV_CUMULATIVE(NULL, 0, thetas, 2), RES_BAD_ARG); + CHECK(INV_CUMULATIVE(estimator, 0, thetas, 2), RES_OK); + CHECK(eq_eps(thetas[0], 0, 1.e-6), 1); + CHECK(eq_eps(thetas[1], PI, 1.e-6), 1); + CHECK(INV_CUMULATIVE(estimator, 0, thetas, sa_size(thetas)), RES_OK); + #undef INV_CUMULATIVE + + printf("\n# Inverse cumulative phase function\n"); + FOR_EACH(i, 0, 2000) { + double error; + error = fabs(thetas[i] - inverse_cumulative[i]) / inverse_cumulative[i]; + printf("CDF^-1(%9.3g) = %9.3g ~ %9.3g; err = %.3f%%\n", + (double)i*(1.0/1999.0), thetas[i], inverse_cumulative[i], error*100); + CHECK(interval[0] <= interval[1], 1); + } + sa_release(thetas); + + CHECK(sschiff_estimator_ref_put(estimator), RES_OK); + CHECK(sschiff_device_ref_put(dev), RES_OK); + CHECK(ssp_rng_ref_put(rng), RES_OK); + + geometry_release(&sampler_ctx.geometry); + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHECK(mem_allocated_size(), 0); + return 0; +} diff --git a/src/test_sschiff_estimator_sphere.c b/src/test_sschiff_estimator_sphere.c @@ -1,30 +1,17 @@ -/* Copyright (C) |Meso|Star> 2015 (contact@meso-star.com) +/* Copyright (C) 2015-2016 CNRS * - * This software is governed by the CeCILL license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/or redistribute the software under the terms of the CeCILL - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". + * 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. * - * As a counterpart to the access to the source code and rights to copy, - * modify and redistribute granted by the license, users are provided only - * with a limited warranty and the software's author, the holder of the - * economic rights, and the successive licensors have only limited - * liability. + * 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. * - * In this respect, the user's attention is drawn to the risks associated - * with loading, using, modifying and/or developing or reproducing the - * software by the user in light of its specific status of free software, - * that may mean that it is complicated to manipulate, and that also - * therefore means that it is reserved for developers and experienced - * professionals having in-depth computer knowledge. Users are therefore - * encouraged to load and test the software's suitability as regards their - * requirements in conditions enabling the security of their systems and/or - * data to be ensured and, more generally, to use and operate it in the - * same conditions as regards security. - * - * The fact that you are presently reading this means that you have had - * knowledge of the CeCILL license and that you accept its terms. */ + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "sschiff.h" #include "test_sschiff_utils.h" @@ -43,11 +30,6 @@ struct result { double extinction_cross_section; }; -struct geometry { - float* vertices; /* List of float[3] */ - unsigned* indices; /* List of unsigned[3] */ -}; - struct sampler_context { struct geometry geometry; double wavelength; /* In micron */ @@ -58,11 +40,6 @@ struct sampler_context { double sigma; }; -struct sphere { - struct geometry* geometry; - float radius; /* In micron */ -}; - static void get_material_property (void* mtl, @@ -82,153 +59,22 @@ get_material_property ctx->relative_imaginary_refractive_index; } -static void -get_indices(const unsigned itri, unsigned ids[3], void* ctx) -{ - struct sphere* sphere = ctx; - const size_t i = itri * 3; - - CHECK(sa_size(sphere->geometry->indices) % 3, 0); - CHECK(itri < sa_size(sphere->geometry->indices) / 3, 1); - ids[0] = sphere->geometry->indices[i + 0]; - ids[1] = sphere->geometry->indices[i + 1]; - ids[2] = sphere->geometry->indices[i + 2]; -} - -static INLINE void -get_position(const unsigned ivert, float vertex[3], void* ctx) -{ - struct sphere* sphere = ctx; - const size_t i = ivert * 3; - - CHECK(sa_size(sphere->geometry->vertices) % 3, 0); - CHECK(ivert < sa_size(sphere->geometry->vertices) / 3, 1); - vertex[0] = sphere->geometry->vertices[i + 0] * sphere->radius; - vertex[1] = sphere->geometry->vertices[i + 1] * sphere->radius; - vertex[2] = sphere->geometry->vertices[i + 2] * sphere->radius; -} - static res_T sample_sphere (struct ssp_rng* rng, - struct sschiff_material* mtl, struct s3d_shape* shape, void* sampler_context) { - struct s3d_vertex_data attrib; struct sampler_context* sampler_ctx = sampler_context; struct sphere sphere; - size_t nverts, nprims; NCHECK(rng, NULL); - NCHECK(mtl, NULL); - NCHECK(shape, NULL); sphere.geometry = &sampler_ctx->geometry; sphere.radius = (float)ssp_ran_lognormal (rng, log(sampler_ctx->mean_radius), log(sampler_ctx->sigma)); - attrib.usage = S3D_POSITION; - attrib.type = S3D_FLOAT3; - attrib.get = get_position; - - mtl->get_property = get_material_property; - mtl->material = sampler_ctx; - - nverts = sa_size(sphere.geometry->vertices) / 3/*#coords*/; - nprims = sa_size(sphere.geometry->indices) / 3/*#indices per prim*/; - - return s3d_mesh_setup_indexed_vertices(shape, (unsigned)nprims, - get_indices, (unsigned)nverts, &attrib, 1, &sphere); -} - -static void -sphere_init(struct geometry* sphere, const unsigned ntheta) -{ - const unsigned nphi = (unsigned)(((double)ntheta + 0.5) / 2.0); - const double step_theta = 2*PI / (double)ntheta; - const double step_phi = PI / (double)nphi; - double* cos_theta = NULL; - double* sin_theta = NULL; - double* cos_phi = NULL; - double* sin_phi = NULL; - unsigned itheta, iphi; - - NCHECK(sphere, NULL); - NCHECK(ntheta, 0); - - sphere->vertices = NULL; - sphere->indices = NULL; - - /* Precompute the cosine/sinus of the theta/phi angles */ - FOR_EACH(itheta, 0, ntheta) { - const double theta = -PI + (double)itheta * step_theta; - sa_push(cos_theta, cos(theta)); - sa_push(sin_theta, sin(theta)); - } - FOR_EACH(iphi, 1, nphi) { - const double phi = -PI/2 + (double)iphi * step_phi; - sa_push(cos_phi, cos(phi)); - sa_push(sin_phi, sin(phi)); - } - /* Compute the contour vertices */ - FOR_EACH(itheta, 0, ntheta) { - FOR_EACH(iphi, 0, nphi-1) { - sa_push(sphere->vertices, (float)(cos_theta[itheta]*cos_phi[iphi])); - sa_push(sphere->vertices, (float)(sin_theta[itheta]*cos_phi[iphi])); - sa_push(sphere->vertices, (float)sin_phi[iphi]); - } - } - /* Compute the polar vertices */ - f3(sa_add(sphere->vertices, 3), 0.f, 0.f,-1.f); - f3(sa_add(sphere->vertices, 3), 0.f, 0.f, 1.f); - - /* Define the indices of the contour primitives */ - FOR_EACH(itheta, 0, ntheta) { - const unsigned itheta0 = itheta * (nphi - 1); - const unsigned itheta1 = ((itheta + 1) % ntheta) * (nphi - 1); - FOR_EACH(iphi, 0, nphi-2) { - const unsigned iphi0 = iphi + 0; - const unsigned iphi1 = iphi + 1; - - sa_push(sphere->indices, itheta0 + iphi0); - sa_push(sphere->indices, itheta0 + iphi1); - sa_push(sphere->indices, itheta1 + iphi0); - - sa_push(sphere->indices, itheta1 + iphi0); - sa_push(sphere->indices, itheta0 + iphi1); - sa_push(sphere->indices, itheta1 + iphi1); - } - } - - /* Define the indices of the polar primitives */ - FOR_EACH(itheta, 0, ntheta) { - const unsigned itheta0 = itheta * (nphi - 1); - const unsigned itheta1 = ((itheta + 1) % ntheta) * (nphi - 1); - - sa_push(sphere->indices, ntheta * (nphi - 1)); - sa_push(sphere->indices, itheta0); - sa_push(sphere->indices, itheta1); - - sa_push(sphere->indices, ntheta * (nphi - 1) + 1); - sa_push(sphere->indices, itheta1 + (nphi - 2)); - sa_push(sphere->indices, itheta0 + (nphi - 2)); - } - - /* Release the intermediary data structure */ - sa_release(cos_theta); - sa_release(sin_theta); - sa_release(cos_phi); - sa_release(sin_phi); -} - -static void -sphere_release(struct geometry* sphere) -{ - sa_release(sphere->vertices); - sa_release(sphere->indices); - sphere->vertices = NULL; - sphere->indices = NULL; + return sphere_setup_s3d_shape(&sphere, shape); } static void @@ -242,11 +88,11 @@ check_schiff_estimation char buf[64]; struct sschiff_estimator* estimator; struct sschiff_geometry_distribution distrib = SSCHIFF_NULL_GEOMETRY_DISTRIBUTION; - struct sschiff_estimator_state state; + struct sschiff_cross_section cross_section; struct time t0, t1; size_t i; - const size_t nscatt_angles = 1; + const size_t nscatt_angles = 1000; const size_t ngeoms = 100; const size_t ndirs = 100; const double wavelength = sampler_ctx->wavelength; @@ -255,6 +101,8 @@ check_schiff_estimation NCHECK(results, NULL); NCHECK(results, 0); + distrib.material.get_property = get_material_property; + distrib.material.material = sampler_ctx; distrib.sample = sample_sphere; distrib.context = sampler_ctx; @@ -265,45 +113,42 @@ check_schiff_estimation sampler_ctx->medium_refractive_index); FOR_EACH(i, 0, nresults) { - const struct sschiff_estimator_value* val; + const struct sschiff_state* val; double dst; sampler_ctx->mean_radius = results[i].mean_radius; + distrib.characteristic_length = sampler_ctx->mean_radius * 2.0; time_current(&t0); - CHECK(sschiff_integrate(dev, rng, &distrib, &wavelength, 1, nscatt_angles, - ngeoms, ndirs, &estimator), RES_OK); + CHECK(sschiff_integrate(dev, rng, &distrib, &wavelength, 1, + sschiff_uniform_scattering_angles, nscatt_angles, ngeoms, ndirs, &estimator), RES_OK); time_current(&t1); time_sub(&t0, &t1, &t0); time_dump(&t0, TIME_MIN|TIME_SEC|TIME_MSEC, NULL, buf, sizeof(buf)); printf("%d - mean radius: %5.2f micron - %s: \n", (int)i, results[i].mean_radius, buf); - CHECK(sschiff_estimator_get_states(estimator, &state), RES_OK); - CHECK(eq_eps(state.wavelength, wavelength, 1.e-12), 1); + CHECK(sschiff_estimator_get_cross_sections(estimator, &cross_section), RES_OK); - val = state.values + SSCHIFF_EXTINCTION_CROSS_SECTION ; + val = &cross_section.extinction; dst = val->E - results[i].extinction_cross_section; printf(" Extinction cross section = %7.2f ~ %12.7f +/- %12.7f (%6.2f)\n", results[i].extinction_cross_section, val->E, val->SE, dst / val->SE); CHECK(eq_eps(val->E, results[i].extinction_cross_section, 4*val->SE), 1); - val = state.values + SSCHIFF_ABSORPTION_CROSS_SECTION ; + val = &cross_section.absorption; dst = val->E - results[i].absorption_cross_section; printf(" Absorption cross section = %7.2f ~ %12.7f +/- %12.7f (%6.2f)\n", results[i].absorption_cross_section, val->E, val->SE, dst / val->SE); CHECK(eq_eps(val->E, results[i].absorption_cross_section, 4*val->SE), 1); - val = state.values + SSCHIFF_SCATTERING_CROSS_SECTION; + val = &cross_section.scattering; dst = val->E - results[i].scattering_cross_section; printf(" Scattering cross section = %7.2f ~ %12.7f +/- %12.7f (%6.2f)\n", results[i].scattering_cross_section, val->E, val->SE, dst / val->SE); CHECK(eq_eps(val->E, results[i].scattering_cross_section, 4*val->SE), 1); - /*s = log(sampler_ctx->sigma); - r = sampler_ctx->mean_radius * exp(2.5 * s * s); - r = PI * r * r * 1.e-12 */ /* Meter^2 to micron^2*/; - val = state.values + SSCHIFF_AVERAGE_PROJECTED_AREA; - printf(" Averavege projected area = %12.6g +/- %12.7g\n", val->E, val->SE); + val = &cross_section.average_projected_area; + printf(" Averavege projected area = %12.7g +/- %12.7g\n", val->E, val->SE); CHECK(sschiff_estimator_ref_put(estimator), RES_OK); } @@ -317,7 +162,7 @@ main(int argc, char** argv) struct sschiff_device* dev; struct sschiff_geometry_distribution distrib = SSCHIFF_NULL_GEOMETRY_DISTRIBUTION; struct sschiff_estimator* estimator; - struct sschiff_estimator_state state; + struct sschiff_cross_section cross_section; struct ssp_rng* rng; const struct result results_n_r_1_01[] = { { 1.00, 0.484, 0.159, 0.643 }, @@ -344,16 +189,18 @@ main(int argc, char** argv) { 21.0, 1350, 1580, 2930 } }; const double wlen = 0.6; /* Micron */ - size_t count; + double wlens[3] = { 0, 0, 0 }; + const double* dbls = NULL; + size_t i, count; (void)argc, (void)argv; mem_init_proxy_allocator(&allocator, &mem_default_allocator); CHECK(ssp_rng_create(&allocator, &ssp_rng_threefry, &rng), RES_OK); CHECK(sschiff_device_create - (NULL, &allocator, SSCHIFF_NTHREADS_DEFAULT, 0, NULL, &dev), RES_OK); + (NULL, &allocator, SSCHIFF_NTHREADS_DEFAULT, 1, NULL, &dev), RES_OK); - sphere_init(&sampler_ctx.geometry, 64); + geometry_init_sphere(&sampler_ctx.geometry, 64); sampler_ctx.wavelength = wlen; sampler_ctx.relative_real_refractive_index = 1.1; @@ -362,95 +209,124 @@ main(int argc, char** argv) sampler_ctx.mean_radius = 1.0; sampler_ctx.sigma = 1.18; + distrib.material.get_property = get_material_property; + distrib.material.material = &sampler_ctx; + distrib.characteristic_length = 1; distrib.sample = sample_sphere; distrib.context = &sampler_ctx; - CHECK(sschiff_integrate(NULL, NULL, NULL, NULL, 0, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, NULL, NULL, NULL, 0, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, rng, NULL, NULL, 0, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, rng, NULL, NULL, 0, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, NULL, &distrib, NULL, 0, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, NULL, &distrib, NULL, 0, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, rng, &distrib, NULL, 0, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, rng, &distrib, NULL, 0, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, NULL, NULL, &wlen, 0, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, NULL, NULL, &wlen, 0, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, rng, NULL, &wlen, 0, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, rng, NULL, &wlen, 0, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, NULL, &distrib, &wlen, 0, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, NULL, &distrib, &wlen, 0, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, rng, &distrib, &wlen, 0, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, rng, &distrib, &wlen, 0, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, NULL, NULL, NULL, 1, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, NULL, NULL, NULL, 1, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, rng, NULL, NULL, 1, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, rng, NULL, NULL, 1, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, NULL, &distrib, NULL, 1, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, NULL, &distrib, NULL, 1, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, rng, &distrib, NULL, 1, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, rng, &distrib, NULL, 1, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, NULL, NULL, &wlen, 1, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, NULL, NULL, &wlen, 1, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, rng, NULL, &wlen, 1, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, rng, NULL, &wlen, 1, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, NULL, &distrib, &wlen, 1, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, NULL, &distrib, &wlen, 1, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, rng, &distrib, &wlen, 1, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, rng, &distrib, &wlen, 1, 1, 1, 1, NULL), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, NULL, NULL, NULL, 0, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, NULL, NULL, NULL, 0, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, rng, NULL, NULL, 0, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, rng, NULL, NULL, 0, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, NULL, &distrib, NULL, 0, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, NULL, &distrib, NULL, 0, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, rng, &distrib, NULL, 0, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, rng, &distrib, NULL, 0, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, NULL, NULL, &wlen, 0, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, NULL, NULL, &wlen, 0, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, rng, NULL, &wlen, 0, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, rng, NULL, &wlen, 0, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, NULL, &distrib, &wlen, 0, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, NULL, &distrib, &wlen, 0, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, rng, &distrib, &wlen, 0, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, rng, &distrib, &wlen, 0, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, NULL, NULL, NULL, 1, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, NULL, NULL, NULL, 1, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, rng, NULL, NULL, 1, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, rng, NULL, NULL, 1, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, NULL, &distrib, NULL, 1, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, NULL, &distrib, NULL, 1, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, rng, &distrib, NULL, 1, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, rng, &distrib, NULL, 1, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, NULL, NULL, &wlen, 1, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, NULL, NULL, &wlen, 1, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, rng, NULL, &wlen, 1, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, rng, NULL, &wlen, 1, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, NULL, &distrib, &wlen, 1, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, NULL, &distrib, &wlen, 1, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(NULL, rng, &distrib, &wlen, 1, 1, 1, 1, &estimator), RES_BAD_ARG); - CHECK(sschiff_integrate(dev, rng, &distrib, &wlen, 1, 1, 1, 1, &estimator), RES_OK); - - CHECK(sschiff_estimator_get_wavelengths_count(NULL, NULL), RES_BAD_ARG); - CHECK(sschiff_estimator_get_wavelengths_count(estimator, NULL), RES_BAD_ARG); - CHECK(sschiff_estimator_get_wavelengths_count(NULL, &count), RES_BAD_ARG); - CHECK(sschiff_estimator_get_wavelengths_count(estimator, &count), RES_OK); + CHECK(sschiff_integrate(NULL, NULL, NULL, NULL, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, NULL, NULL, NULL, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, rng, NULL, NULL, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, rng, NULL, NULL, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, NULL, &distrib, NULL, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, NULL, &distrib, NULL, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, rng, &distrib, NULL, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, rng, &distrib, NULL, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, NULL, NULL, &wlen, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, NULL, NULL, &wlen, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, rng, NULL, &wlen, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, rng, NULL, &wlen, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, NULL, &distrib, &wlen, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, NULL, &distrib, &wlen, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, rng, &distrib, &wlen, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, rng, &distrib, &wlen, 0, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, NULL, NULL, NULL, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, NULL, NULL, NULL, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, rng, NULL, NULL, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, rng, NULL, NULL, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, NULL, &distrib, NULL, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, NULL, &distrib, NULL, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, rng, &distrib, NULL, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, rng, &distrib, NULL, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, NULL, NULL, &wlen, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, NULL, NULL, &wlen, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, rng, NULL, &wlen, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, rng, NULL, &wlen, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, NULL, &distrib, &wlen, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, NULL, &distrib, &wlen, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, rng, &distrib, &wlen, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, rng, &distrib, &wlen, 1, NULL, 1, 1, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, NULL, NULL, NULL, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, NULL, NULL, NULL, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, rng, NULL, NULL, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, rng, NULL, NULL, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, NULL, &distrib, NULL, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, NULL, &distrib, NULL, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, rng, &distrib, NULL, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, rng, &distrib, NULL, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, NULL, NULL, &wlen, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, NULL, NULL, &wlen, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, rng, NULL, &wlen, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, rng, NULL, &wlen, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, NULL, &distrib, &wlen, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, NULL, &distrib, &wlen, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, rng, &distrib, &wlen, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, rng, &distrib, &wlen, 0, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, NULL, NULL, NULL, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, NULL, NULL, NULL, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, rng, NULL, NULL, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, rng, NULL, NULL, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, NULL, &distrib, NULL, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, NULL, &distrib, NULL, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, rng, &distrib, NULL, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, rng, &distrib, NULL, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, NULL, NULL, &wlen, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, NULL, NULL, &wlen, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, rng, NULL, &wlen, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, rng, NULL, &wlen, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, NULL, &distrib, &wlen, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, NULL, &distrib, &wlen, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(NULL, rng, &distrib, &wlen, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, rng, &distrib, &wlen, 1, NULL, 1, 1, 1, &estimator), RES_BAD_ARG); + + CHECK(sschiff_integrate(dev, rng, &distrib, &wlen, 1, + sschiff_uniform_scattering_angles, 1, 1, 1, &estimator), RES_BAD_ARG); + CHECK(sschiff_integrate(dev, rng, &distrib, &wlen, 1, + sschiff_uniform_scattering_angles, 10, 1000, 1, &estimator), RES_OK); + + CHECK(sschiff_estimator_get_wavelengths(NULL, NULL, NULL), RES_BAD_ARG); + CHECK(sschiff_estimator_get_wavelengths(estimator, NULL, NULL), RES_OK);/*Useless*/ + CHECK(sschiff_estimator_get_wavelengths(NULL, NULL, &count), RES_BAD_ARG); + CHECK(sschiff_estimator_get_wavelengths(estimator, NULL, &count), RES_OK); + CHECK(count, 1); + CHECK(sschiff_estimator_get_wavelengths(NULL, &dbls, NULL), RES_BAD_ARG); + CHECK(sschiff_estimator_get_wavelengths(estimator, &dbls, NULL), RES_OK); + CHECK(dbls[0], wlen); + CHECK(sschiff_estimator_get_wavelengths(NULL, &dbls, &count), RES_BAD_ARG); + CHECK(sschiff_estimator_get_wavelengths(estimator, &dbls, &count), RES_OK); + CHECK(dbls[0], wlen); CHECK(count, 1); + CHECK(sschiff_estimator_get_scattering_angles(NULL, NULL, NULL), RES_BAD_ARG); + CHECK(sschiff_estimator_get_scattering_angles(estimator, NULL, NULL), RES_OK); /* Useless */ + CHECK(sschiff_estimator_get_scattering_angles(NULL, NULL, &count), RES_BAD_ARG); + CHECK(sschiff_estimator_get_scattering_angles(estimator, NULL, &count), RES_OK); + CHECK(count, 10); + CHECK(sschiff_estimator_get_scattering_angles(NULL, &dbls, NULL), RES_BAD_ARG); + CHECK(sschiff_estimator_get_scattering_angles(estimator, &dbls, NULL), RES_OK); /* Useless */ + FOR_EACH(i, 0, count) + CHECK(eq_eps(dbls[i], (double)i*PI/((double)count-1), 1.e-6), 1); + CHECK(sschiff_estimator_get_scattering_angles(NULL, &dbls, &count), RES_BAD_ARG); + CHECK(sschiff_estimator_get_scattering_angles(estimator, &dbls, &count), RES_OK); + FOR_EACH(i, 0, count) + CHECK(eq_eps(dbls[i], (double)i*PI/((double)count-1), 1.e-6), 1); + CHECK(count, 10); + CHECK(sschiff_estimator_get_realisations_count(NULL, NULL), RES_BAD_ARG); CHECK(sschiff_estimator_get_realisations_count(estimator, NULL), RES_BAD_ARG); CHECK(sschiff_estimator_get_realisations_count(NULL, &count), RES_BAD_ARG); CHECK(sschiff_estimator_get_realisations_count(estimator, &count), RES_OK); - CHECK(count, 1); + CHECK(count, 1000); - CHECK(sschiff_estimator_get_wavelength_state(NULL, 0, NULL), RES_BAD_ARG); - CHECK(sschiff_estimator_get_wavelength_state(estimator, 0, NULL), RES_BAD_ARG); - CHECK(sschiff_estimator_get_wavelength_state(NULL, wlen, NULL), RES_BAD_ARG); - CHECK(sschiff_estimator_get_wavelength_state(estimator, wlen, NULL), RES_BAD_ARG); - CHECK(sschiff_estimator_get_wavelength_state(NULL, 0, &state), RES_BAD_ARG); - CHECK(sschiff_estimator_get_wavelength_state(estimator, 0, &state), RES_BAD_ARG); - CHECK(sschiff_estimator_get_wavelength_state(NULL, wlen, &state), RES_BAD_ARG); - CHECK(sschiff_estimator_get_wavelength_state(estimator, wlen, &state), RES_OK); - CHECK(eq_eps(wlen, state.wavelength, 1.e-12), 1); + CHECK(sschiff_estimator_get_cross_section(NULL, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_estimator_get_cross_section(estimator, 1, NULL), RES_BAD_ARG); + CHECK(sschiff_estimator_get_cross_section(NULL, 1, &cross_section), RES_BAD_ARG); + CHECK(sschiff_estimator_get_cross_section(estimator, 1, &cross_section), RES_BAD_ARG); + CHECK(sschiff_estimator_get_cross_section(NULL, 0, NULL), RES_BAD_ARG); + CHECK(sschiff_estimator_get_cross_section(estimator, 0, NULL), RES_BAD_ARG); + CHECK(sschiff_estimator_get_cross_section(NULL, 0, &cross_section), RES_BAD_ARG); + CHECK(sschiff_estimator_get_cross_section(estimator, 0, &cross_section), RES_OK); CHECK(sschiff_estimator_ref_get(NULL), RES_BAD_ARG); CHECK(sschiff_estimator_ref_get(estimator), RES_OK); @@ -458,10 +334,9 @@ main(int argc, char** argv) CHECK(sschiff_estimator_ref_put(estimator), RES_OK); CHECK(sschiff_estimator_ref_put(estimator), RES_OK); - CHECK(sschiff_integrate(dev, rng, &distrib, &wlen, 1, 1, 10, 1, &estimator), RES_OK); - CHECK(sschiff_estimator_get_realisations_count(estimator, &count), RES_OK); - CHECK(count, 10); - CHECK(sschiff_estimator_ref_put(estimator), RES_OK); + wlens[0] = 0.2, wlens[1] = 0.6, wlens[2] = 0.4; + CHECK(sschiff_integrate(dev, rng, &distrib, wlens, 3, + sschiff_uniform_scattering_angles, 10, 1000, 1, &estimator), RES_BAD_ARG); sampler_ctx.relative_real_refractive_index = 1.1; check_schiff_estimation(dev, rng, &sampler_ctx, results_n_r_1_1, @@ -475,7 +350,7 @@ main(int argc, char** argv) CHECK(sschiff_device_ref_put(dev), RES_OK); CHECK(ssp_rng_ref_put(rng), RES_OK); - sphere_release(&sampler_ctx.geometry); + geometry_release(&sampler_ctx.geometry); check_memory_allocator(&allocator); mem_shutdown_proxy_allocator(&allocator); CHECK(mem_allocated_size(), 0); diff --git a/src/test_sschiff_utils.h b/src/test_sschiff_utils.h @@ -1,36 +1,337 @@ -/* Copyright (C) |Meso|Star> 2015 (contact@meso-star.com) +/* Copyright (C) 2015-2016 CNRS * - * This software is governed by the CeCILL license under French law and - * abiding by the rules of distribution of free software. You can use, - * modify and/or redistribute the software under the terms of the CeCILL - * license as circulated by CEA, CNRS and INRIA at the following URL - * "http://www.cecill.info". + * 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. * - * As a counterpart to the access to the source code and rights to copy, - * modify and redistribute granted by the license, users are provided only - * with a limited warranty and the software's author, the holder of the - * economic rights, and the successive licensors have only limited - * liability. + * 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. * - * In this respect, the user's attention is drawn to the risks associated - * with loading, using, modifying and/or developing or reproducing the - * software by the user in light of its specific status of free software, - * that may mean that it is complicated to manipulate, and that also - * therefore means that it is reserved for developers and experienced - * professionals having in-depth computer knowledge. Users are therefore - * encouraged to load and test the software's suitability as regards their - * requirements in conditions enabling the security of their systems and/or - * data to be ensured and, more generally, to use and operate it in the - * same conditions as regards security. - * - * The fact that you are presently reading this means that you have had - * knowledge of the CeCILL license and that you accept its terms. */ + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifndef TEST_SSCHIFF_UTILS_H #define TEST_SSCHIFF_UTILS_H +#include <rsys/float3.h> +#include <rsys/stretchy_array.h> #include <rsys/mem_allocator.h> +#include <star/s3d.h> + +/******************************************************************************* + * Helper geometry data structure + ******************************************************************************/ +struct geometry { + float* vertices; /* List of float[3] */ + unsigned* indices; /* List of unsigned[3] */ +}; + +static INLINE void +geometry_init_sphere(struct geometry* sphere, const unsigned ntheta) +{ + const unsigned nphi = (unsigned)(((double)ntheta + 0.5) / 2.0); + const double step_theta = 2*PI / (double)ntheta; + const double step_phi = PI / (double)nphi; + double* cos_theta = NULL; + double* sin_theta = NULL; + double* cos_phi = NULL; + double* sin_phi = NULL; + unsigned itheta, iphi; + + NCHECK(sphere, NULL); + NCHECK(ntheta, 0); + + sphere->vertices = NULL; + sphere->indices = NULL; + + /* Precompute the cosine/sinus of the theta/phi angles */ + FOR_EACH(itheta, 0, ntheta) { + const double theta = -PI + (double)itheta * step_theta; + sa_push(cos_theta, cos(theta)); + sa_push(sin_theta, sin(theta)); + } + FOR_EACH(iphi, 1, nphi) { + const double phi = -PI/2 + (double)iphi * step_phi; + sa_push(cos_phi, cos(phi)); + sa_push(sin_phi, sin(phi)); + } + /* Compute the contour vertices */ + FOR_EACH(itheta, 0, ntheta) { + FOR_EACH(iphi, 0, nphi-1) { + sa_push(sphere->vertices, (float)(cos_theta[itheta]*cos_phi[iphi])); + sa_push(sphere->vertices, (float)(sin_theta[itheta]*cos_phi[iphi])); + sa_push(sphere->vertices, (float)sin_phi[iphi]); + } + } + /* Compute the polar vertices */ + f3(sa_add(sphere->vertices, 3), 0.f, 0.f,-1.f); + f3(sa_add(sphere->vertices, 3), 0.f, 0.f, 1.f); + + /* Define the indices of the contour primitives */ + FOR_EACH(itheta, 0, ntheta) { + const unsigned itheta0 = itheta * (nphi - 1); + const unsigned itheta1 = ((itheta + 1) % ntheta) * (nphi - 1); + FOR_EACH(iphi, 0, nphi-2) { + const unsigned iphi0 = iphi + 0; + const unsigned iphi1 = iphi + 1; + + sa_push(sphere->indices, itheta0 + iphi0); + sa_push(sphere->indices, itheta0 + iphi1); + sa_push(sphere->indices, itheta1 + iphi0); + + sa_push(sphere->indices, itheta1 + iphi0); + sa_push(sphere->indices, itheta0 + iphi1); + sa_push(sphere->indices, itheta1 + iphi1); + } + } + + /* Define the indices of the polar primitives */ + FOR_EACH(itheta, 0, ntheta) { + const unsigned itheta0 = itheta * (nphi - 1); + const unsigned itheta1 = ((itheta + 1) % ntheta) * (nphi - 1); + + sa_push(sphere->indices, ntheta * (nphi - 1)); + sa_push(sphere->indices, itheta0); + sa_push(sphere->indices, itheta1); + + sa_push(sphere->indices, ntheta * (nphi - 1) + 1); + sa_push(sphere->indices, itheta1 + (nphi - 2)); + sa_push(sphere->indices, itheta0 + (nphi - 2)); + } + + /* Release the intermediary data structure */ + sa_release(cos_theta); + sa_release(sin_theta); + sa_release(cos_phi); + sa_release(sin_phi); +} + +static INLINE void +geometry_init_cylinder(struct geometry* geometry, const unsigned nsteps) +{ + const double step = 2*PI / (double)nsteps; + unsigned istep; + + NCHECK(geometry, NULL); + NCHECK(nsteps, 0); + + geometry->vertices = NULL; + geometry->indices = NULL; + + /* Generate the vertex coordinates */ + FOR_EACH(istep, 0, nsteps) { + const float theta = (float)(istep * step); + const float x = (float)cos(theta); + const float y = (float)sin(theta); + f3(sa_add(geometry->vertices, 3), x, y, -1.f); + f3(sa_add(geometry->vertices, 3), x, y, 0.f); + } + + /* "Polar" vertices */ + f3(sa_add(geometry->vertices, 3), 0.f, 0.f, -1.f); + f3(sa_add(geometry->vertices, 3), 0.f, 0.f, 0.f); + + /* Contour primitives */ + FOR_EACH(istep, 0, nsteps) { + const unsigned id = istep * 2; + unsigned* iprim; + + iprim = sa_add(geometry->indices, 3); + iprim[0] = (id + 0); + iprim[1] = (id + 1); + iprim[2] = (id + 2) % (nsteps*2); + + iprim = sa_add(geometry->indices, 3); + iprim[0] = (id + 2) % (nsteps*2); + iprim[1] = (id + 1); + iprim[2] = (id + 3) % (nsteps*2); + } + + /* Cap primitives */ + FOR_EACH(istep, 0, nsteps) { + const unsigned id = istep * 2; + unsigned* iprim; + + iprim = sa_add(geometry->indices, 3); + iprim[0] = (nsteps * 2); + iprim[1] = (id + 0); + iprim[2] = (id + 2) % (nsteps*2); + + iprim = sa_add(geometry->indices, 3); + iprim[0] = (nsteps * 2) + 1; + iprim[1] = (id + 3) % (nsteps*2); + iprim[2] = (id + 1); + } + +} + +static INLINE void +geometry_release(struct geometry* geometry) +{ + NCHECK(geometry, NULL); + sa_release(geometry->vertices); + sa_release(geometry->indices); + geometry->vertices = NULL; + geometry->indices = NULL; +} + +static INLINE void +geometry_dump(struct geometry* geom, FILE* file) +{ + size_t i; + NCHECK(geom, NULL); + NCHECK(file, NULL); + + CHECK(sa_size(geom->vertices)%3, 0); /* Ensure 3D position */ + CHECK(sa_size(geom->indices)%3, 0); /* Ensure triangular primitives */ + + FOR_EACH(i, 0, sa_size(geom->vertices)/3) { + fprintf(file, "v %f %f %f\n", + geom->vertices[i*3+0], + geom->vertices[i*3+1], + geom->vertices[i*3+2]); + } + FOR_EACH(i, 0, sa_size(geom->indices)/3) { + fprintf(file, "f %d %d %d\n", + geom->indices[i*3+0] + 1, + geom->indices[i*3+1] + 1, + geom->indices[i*3+2] + 1); + } +} + +/******************************************************************************* + * Cylinder shape + ******************************************************************************/ +struct cylinder { + struct geometry* geometry; + float radius; + float height; +}; + +static INLINE void +cylinder_get_indices(const unsigned itri, unsigned ids[3], void* ctx) +{ + struct cylinder* cylinder = ctx; + const size_t i = itri * 3; + + CHECK(sa_size(cylinder->geometry->indices) % 3, 0); + CHECK(itri < sa_size(cylinder->geometry->indices) / 3, 1); + ids[0] = cylinder->geometry->indices[i + 0]; + ids[1] = cylinder->geometry->indices[i + 1]; + ids[2] = cylinder->geometry->indices[i + 2]; +} + +static INLINE void +cylinder_get_position(const unsigned ivert, float vertex[3], void* ctx) +{ + struct cylinder* cylinder = ctx; + const size_t i = ivert * 3; + + CHECK(sa_size(cylinder->geometry->vertices) % 3, 0); + CHECK(ivert < sa_size(cylinder->geometry->vertices) / 3, 1); + vertex[0] = cylinder->geometry->vertices[i + 0] * cylinder->radius; + vertex[1] = cylinder->geometry->vertices[i + 1] * cylinder->radius; + vertex[2] = cylinder->geometry->vertices[i + 2] * cylinder->height; +} + +static INLINE res_T +cylinder_setup_s3d_shape(struct cylinder* cylinder, struct s3d_shape* shape) +{ + struct s3d_vertex_data attrib; + size_t nverts, nprims; + + NCHECK(cylinder, NULL); + NCHECK(shape, NULL); + + attrib.usage = S3D_POSITION; + attrib.type = S3D_FLOAT3; + attrib.get = cylinder_get_position; + + nverts = sa_size(cylinder->geometry->vertices) / 3/*#coords*/; + nprims = sa_size(cylinder->geometry->indices) / 3/*#indices per prim*/; + + return s3d_mesh_setup_indexed_vertices(shape, (unsigned)nprims, + cylinder_get_indices, (unsigned)nverts, &attrib, 1, cylinder); +} + +/******************************************************************************* + * Spherical shape + ******************************************************************************/ +struct sphere { + struct geometry* geometry; + float radius; +}; + +static INLINE void +sphere_get_indices(const unsigned itri, unsigned ids[3], void* ctx) +{ + struct sphere* sphere = ctx; + const size_t i = itri * 3; + + CHECK(sa_size(sphere->geometry->indices) % 3, 0); + CHECK(itri < sa_size(sphere->geometry->indices) / 3, 1); + ids[0] = sphere->geometry->indices[i + 0]; + ids[1] = sphere->geometry->indices[i + 1]; + ids[2] = sphere->geometry->indices[i + 2]; +} + +static INLINE void +sphere_get_position(const unsigned ivert, float vertex[3], void* ctx) +{ + struct sphere* sphere = ctx; + const size_t i = ivert * 3; + + CHECK(sa_size(sphere->geometry->vertices) % 3, 0); + CHECK(ivert < sa_size(sphere->geometry->vertices) / 3, 1); + vertex[0] = sphere->geometry->vertices[i + 0] * sphere->radius; + vertex[1] = sphere->geometry->vertices[i + 1] * sphere->radius; + vertex[2] = sphere->geometry->vertices[i + 2] * sphere->radius; +} + +static INLINE res_T +sphere_setup_s3d_shape(struct sphere* sphere, struct s3d_shape* shape) +{ + struct s3d_vertex_data attrib; + size_t nverts, nprims; + + NCHECK(sphere, NULL); + NCHECK(shape, NULL); + + attrib.usage = S3D_POSITION; + attrib.type = S3D_FLOAT3; + attrib.get = sphere_get_position; + + nverts = sa_size(sphere->geometry->vertices) / 3/*#coords*/; + nprims = sa_size(sphere->geometry->indices) / 3/*#indices per prim*/; + + return s3d_mesh_setup_indexed_vertices(shape, (unsigned)nprims, + sphere_get_indices, (unsigned)nverts, &attrib, 1, sphere); +} + +/******************************************************************************* + * Miscellaneous functions + ******************************************************************************/ +static INLINE void +compute_estimation_intersection + (double intersection[2], + const double scale, + const struct sschiff_state* state0, + const struct sschiff_state* state1) +{ + double interval0[2], interval1[2]; + CHECK(scale > 0, 1); + interval0[0] = state0->E - scale*state0->SE; + interval0[1] = state0->E + scale*state0->SE; + interval1[0] = state1->E - scale*state1->SE; + interval1[1] = state1->E + scale*state1->SE; + intersection[0] = MMAX(interval0[0], interval1[0]); + intersection[1] = MMIN(interval0[1], interval1[1]); +} + static void check_memory_allocator(struct mem_allocator* allocator) {