summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clangd3
-rw-r--r--.gitignore1
-rw-r--r--COPYING661
-rw-r--r--COPYRIGHT8
-rw-r--r--Makefile31
-rw-r--r--README.md28
-rw-r--r--compile_flags.txt0
-rw-r--r--include/toldef.h147
-rw-r--r--include/tolmacdef.h147
-rw-r--r--src/tolsac.c691
-rw-r--r--structure.txt25
-rw-r--r--tests/Example.csv7
-rw-r--r--tests/Sampled_Example.csv1002
-rw-r--r--tests/hist.r84
14 files changed, 2835 insertions, 0 deletions
diff --git a/.clangd b/.clangd
new file mode 100644
index 0000000..3b87122
--- /dev/null
+++ b/.clangd
@@ -0,0 +1,3 @@
+CompileFlags:
+ Add:
+ - -Iinclude
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3e2fcc7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/bin/
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..ae50619
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,661 @@
+GNU AFFERO GENERAL PUBLIC LICENSE
+ Version 3, 19 November 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU Affero General Public License is a free, copyleft license for
+software and other kinds of works, specifically designed to ensure
+cooperation with the community in the case of network server software.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+our General Public Licenses are 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.
+
+ 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.
+
+ Developers that use our General Public Licenses protect your rights
+with two steps: (1) assert copyright on the software, and (2) offer
+you this License which gives you legal permission to copy, distribute
+and/or modify the software.
+
+ A secondary benefit of defending all users' freedom is that
+improvements made in alternate versions of the program, if they
+receive widespread use, become available for other developers to
+incorporate. Many developers of free software are heartened and
+encouraged by the resulting cooperation. However, in the case of
+software used on network servers, this result may fail to come about.
+The GNU General Public License permits making a modified version and
+letting the public access it on a server without ever releasing its
+source code to the public.
+
+ The GNU Affero General Public License is designed specifically to
+ensure that, in such cases, the modified source code becomes available
+to the community. It requires the operator of a network server to
+provide the source code of the modified version running there to the
+users of that server. Therefore, public use of a modified version, on
+a publicly accessible server, gives the public access to the source
+code of the modified version.
+
+ An older license, called the Affero General Public License and
+published by Affero, was designed to accomplish similar goals. This is
+a different license, not a version of the Affero GPL, but Affero has
+released a new version of the Affero GPL which permits relicensing under
+this license.
+
+ 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 Affero 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. Remote Network Interaction; Use with the GNU General Public License.
+
+ Notwithstanding any other provision of this License, if you modify the
+Program, your modified version must prominently offer all users
+interacting with it remotely through a computer network (if your version
+supports such interaction) an opportunity to receive the Corresponding
+Source of your version by providing access to the Corresponding Source
+from a network server at no charge, through some standard or customary
+means of facilitating copying of software. This Corresponding Source
+shall include the Corresponding Source for any work covered by version 3
+of the GNU General Public License that is incorporated pursuant to the
+following paragraph.
+
+ 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 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 work with which it is combined will remain governed by version
+3 of the GNU General Public License.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU Affero 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 Affero 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 Affero 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 Affero 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 Affero 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If your software can interact with users remotely through a computer
+network, you should also make sure that it provides a way for users to
+get its source. For example, if your program is a web application, its
+interface could display a "Source" link that leads users to an archive
+of the code. There are many ways you could offer source, and different
+solutions will be better for different programs; see section 13 for the
+specific requirements.
+
+ 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 AGPL, see
+<https://www.gnu.org/licenses/>.
diff --git a/COPYRIGHT b/COPYRIGHT
new file mode 100644
index 0000000..dfb4735
--- /dev/null
+++ b/COPYRIGHT
@@ -0,0 +1,8 @@
+Copyright (C) 2025 https://optics-design.com
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+See the COPYING file for the full license text.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..d192768
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,31 @@
+CC=gcc
+#Base Directories
+SRCDIR=src
+BINDIR=bin
+INCDIR=include
+
+#Common flags
+CFLAGS=-I$(INCDIR) -O2 -march=native -flto #-ffast-math
+#tolutils
+TOL_SRCS = $(wildcard $(SRCDIR)/*.c)
+TOL_EXES = $(patsubst $(SRCDIR)/%.c, $(BINDIR)/%.exe, $(TOL_SRCS))
+
+# Setup target
+setup:
+ mkdir -p $(BINDIR) $(INCDIR)
+
+all: setup tolsac structure
+
+tolsac: $(TOL_EXES)
+$(BINDIR)/%.exe: $(SRCDIR)/%.c
+ $(CC) $< $(CFLAGS) -o $@
+
+clean:
+ rm -f $(BINDIR)/*
+ rm -f structure.txt
+
+rebuild: clean all
+
+# Generate project structure
+structure:
+ @powershell -Command "(Get-Item .).Name | Set-Content structure.txt; (tree /a /f | Select-Object -Skip 3) | Add-Content structure.txt"
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..56790bc
--- /dev/null
+++ b/README.md
@@ -0,0 +1,28 @@
+# TolSAC - Tolerance & Sensitivity Analysis in C
+Copyright (C) 2025 https://optics-design.com
+
+## Overview
+Sometimes I need small programs for dealing with tolerances in optical systems. This is the collection of such tools.
+
+## Features
+- Generate random tolerancing samples with various sampling methods and probability distributions.
+
+## License
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
+
+See the [COPYING](COPYING) file for the full license text.
+
+## Third-Party Components
+- xoshiro256** PRNG - Public Domain, by David Blackman and Sebastiano Vigna
+ (http://xoshiro.di.unimi.it/). A fast, high-quality random number generator.
+
+Each component maintains its own license. See respective license files for details.
+
+## Acknowledgements
+The following contributions were assisted by Claude AI (Anthropic):
+- Documentation and README structure.
+- Code optimization suggestions.
+- Interface design recommendations.
diff --git a/compile_flags.txt b/compile_flags.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/compile_flags.txt
diff --git a/include/toldef.h b/include/toldef.h
new file mode 100644
index 0000000..a486054
--- /dev/null
+++ b/include/toldef.h
@@ -0,0 +1,147 @@
+/**
+ * raymacdef.h - header file containing various definition for rayfile manipulations.
+ *
+ * Copyright (C) 2025 https://optics-design.com
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * See the COPYING file for the full license text.
+ */
+#ifndef TOLDEF_H
+#define TOLDEF_H
+
+#include <stdint.h>
+#include <uchar.h>
+#include <time.h>
+/* Type definitions for consistent sizing across platforms. Idea taken from https://nullprogram.com/blog/2023/10/08/ (archive link: ) */
+typedef uint8_t u8;
+typedef char16_t c16;
+typedef int32_t b32;
+typedef int32_t i32;
+typedef uint32_t u32;
+typedef uint64_t u64;
+typedef float f32;
+typedef double f64;
+typedef uintptr_t uptr;
+typedef char byte;
+typedef ptrdiff_t size;
+typedef size_t usize;
+/* Utility macros */
+#define countof(a) (size)(sizeof(a) / sizeof(*(a)))
+#define lengthof(s) (countof(s) - 1)
+// #define new(a, t, n) (t *)alloc(a, sizeof(t), _Alignof(t), n) //From Nullprogram, not using currently
+#define new(t, n) (t *)malloc(n*sizeof(t))
+#define new_arr(t,arr) (t)malloc(sizeof(arr))
+#endif /* TOLDEF_H */
+
+/*
+ * xoshiro256** PRNG algorithm by David Blackman and Sebastiano Vigna
+ * Fast, high-quality random number generator with 256-bit state
+ * Period: 2^256 - 1
+ * References:
+ * - https://prng.di.unimi.it/
+ * - https://vigna.di.unimi.it/ftp/papers/ScrambledLinear.pdf
+ * Implemented by Claude
+ */
+
+// PRNG state structure
+typedef struct {
+ uint64_t s[4];
+} xoshiro256_state;
+
+// Static state for the default global generator
+static xoshiro256_state xoshiro_global_state;
+
+// Left rotation operation (helper function)
+static inline uint64_t rotl(const uint64_t x, int k) {
+ return (x << k) | (x >> (64 - k));
+}
+
+// Main xoshiro256** function: generates a random 64-bit value
+static inline uint64_t xoshiro256_next(xoshiro256_state *state) {
+ const uint64_t result = rotl(state->s[1] * 5, 7) * 9;
+ const uint64_t t = state->s[1] << 17;
+
+ state->s[2] ^= state->s[0];
+ state->s[3] ^= state->s[1];
+ state->s[1] ^= state->s[2];
+ state->s[0] ^= state->s[3];
+
+ state->s[2] ^= t;
+ state->s[3] = rotl(state->s[3], 45);
+
+ return result;
+}
+
+// Jump function - equivalent to 2^128 calls to xoshiro256_next
+// Useful for generating non-overlapping sequences for parallel computations
+static inline void xoshiro256_jump(xoshiro256_state *state) {
+ static const uint64_t JUMP[] = { 0x180ec6d33cfd0aba, 0xd5a61266f0c9392c, 0xa9582618e03fc9aa, 0x39abdc4529b1661c };
+
+ uint64_t s0 = 0;
+ uint64_t s1 = 0;
+ uint64_t s2 = 0;
+ uint64_t s3 = 0;
+ for(int i = 0; i < sizeof JUMP / sizeof *JUMP; i++) {
+ for(int b = 0; b < 64; b++) {
+ if (JUMP[i] & UINT64_C(1) << b) {
+ s0 ^= state->s[0];
+ s1 ^= state->s[1];
+ s2 ^= state->s[2];
+ s3 ^= state->s[3];
+ }
+ xoshiro256_next(state);
+ }
+ }
+
+ state->s[0] = s0;
+ state->s[1] = s1;
+ state->s[2] = s2;
+ state->s[3] = s3;
+}
+
+// Splitmix64 algorithm for initializing the state
+static inline uint64_t splitmix64(uint64_t *x) {
+ uint64_t z = (*x += 0x9e3779b97f4a7c15);
+ z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
+ z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
+ return z ^ (z >> 31);
+}
+
+// Initialize xoshiro256** state with a 64-bit seed
+static inline void xoshiro256_seed(xoshiro256_state *state, uint64_t seed) {
+ uint64_t tmp = seed;
+ state->s[0] = splitmix64(&tmp);
+ state->s[1] = splitmix64(&tmp);
+ state->s[2] = splitmix64(&tmp);
+ state->s[3] = splitmix64(&tmp);
+}
+
+// Initialize the global state with current time or provided seed
+static inline void rng_init(uint64_t seed) {
+ if (seed == 0) {
+ seed = (uint64_t)time(NULL);
+ }
+ xoshiro256_seed(&xoshiro_global_state, seed);
+}
+
+// Generate a random double between 0.0 and 1.0 (inclusive 0.0, exclusive 1.0)
+static inline f64 rng_uniform_f64(void) {
+ // Take the top 53 bits (the precision of a double) to get a value in [0,1)
+ return (xoshiro256_next(&xoshiro_global_state) >> 11) * (1.0 / 9007199254740992.0);
+}
+
+// Generate a random int32 in the range [0, max)
+static inline i32 rng_int32(i32 max) {
+ // Avoid modulo bias by using rejection sampling
+ const uint64_t threshold = (((uint64_t)-1) - ((uint64_t)-1) % max);
+ uint64_t r;
+ do {
+ r = xoshiro256_next(&xoshiro_global_state);
+ } while (r >= threshold);
+ return (i32)(r % max);
+}
+
diff --git a/include/tolmacdef.h b/include/tolmacdef.h
new file mode 100644
index 0000000..d8a5543
--- /dev/null
+++ b/include/tolmacdef.h
@@ -0,0 +1,147 @@
+/**
+ * tolmacdef.h - header file containing various definitions, including the xoshiro256** PRNG algorithm.
+ *
+ * Copyright (C) 2025 https://optics-design.com
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * See the COPYING file for the full license text.
+ */
+#ifndef TOLDEF_H
+#define TOLDEF_H
+
+#include <stdint.h>
+#include <uchar.h>
+#include <time.h>
+/* Type definitions for consistent sizing across platforms. Idea taken from https://nullprogram.com/blog/2023/10/08/ (archive link: ) */
+typedef uint8_t u8;
+typedef char16_t c16;
+typedef int32_t b32;
+typedef int32_t i32;
+typedef uint32_t u32;
+typedef uint64_t u64;
+typedef float f32;
+typedef double f64;
+typedef uintptr_t uptr;
+typedef char byte;
+typedef ptrdiff_t size;
+typedef size_t usize;
+/* Utility macros */
+#define countof(a) (size)(sizeof(a) / sizeof(*(a)))
+#define lengthof(s) (countof(s) - 1)
+// #define new(a, t, n) (t *)alloc(a, sizeof(t), _Alignof(t), n) //From Nullprogram, not using currently
+#define new(t, n) (t *)malloc(n*sizeof(t))
+#define new_arr(t,arr) (t)malloc(sizeof(arr))
+#endif /* TOLDEF_H */
+
+/*
+ * xoshiro256** PRNG algorithm by David Blackman and Sebastiano Vigna
+ * Fast, high-quality random number generator with 256-bit state
+ * Period: 2^256 - 1
+ * References:
+ * - https://prng.di.unimi.it/
+ * - https://vigna.di.unimi.it/ftp/papers/ScrambledLinear.pdf
+ * Implemented by Claude
+ */
+
+// PRNG state structure
+typedef struct {
+ uint64_t s[4];
+} xoshiro256_state;
+
+// Static state for the default global generator
+static xoshiro256_state xoshiro_global_state;
+
+// Left rotation operation (helper function)
+static inline uint64_t rotl(const uint64_t x, int k) {
+ return (x << k) | (x >> (64 - k));
+}
+
+// Main xoshiro256** function: generates a random 64-bit value
+static inline uint64_t xoshiro256_next(xoshiro256_state *state) {
+ const uint64_t result = rotl(state->s[1] * 5, 7) * 9;
+ const uint64_t t = state->s[1] << 17;
+
+ state->s[2] ^= state->s[0];
+ state->s[3] ^= state->s[1];
+ state->s[1] ^= state->s[2];
+ state->s[0] ^= state->s[3];
+
+ state->s[2] ^= t;
+ state->s[3] = rotl(state->s[3], 45);
+
+ return result;
+}
+
+// Jump function - equivalent to 2^128 calls to xoshiro256_next
+// Useful for generating non-overlapping sequences for parallel computations
+static inline void xoshiro256_jump(xoshiro256_state *state) {
+ static const uint64_t JUMP[] = { 0x180ec6d33cfd0aba, 0xd5a61266f0c9392c, 0xa9582618e03fc9aa, 0x39abdc4529b1661c };
+
+ uint64_t s0 = 0;
+ uint64_t s1 = 0;
+ uint64_t s2 = 0;
+ uint64_t s3 = 0;
+ for(int i = 0; i < sizeof JUMP / sizeof *JUMP; i++) {
+ for(int b = 0; b < 64; b++) {
+ if (JUMP[i] & UINT64_C(1) << b) {
+ s0 ^= state->s[0];
+ s1 ^= state->s[1];
+ s2 ^= state->s[2];
+ s3 ^= state->s[3];
+ }
+ xoshiro256_next(state);
+ }
+ }
+
+ state->s[0] = s0;
+ state->s[1] = s1;
+ state->s[2] = s2;
+ state->s[3] = s3;
+}
+
+// Splitmix64 algorithm for initializing the state
+static inline uint64_t splitmix64(uint64_t *x) {
+ uint64_t z = (*x += 0x9e3779b97f4a7c15);
+ z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
+ z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
+ return z ^ (z >> 31);
+}
+
+// Initialize xoshiro256** state with a 64-bit seed
+static inline void xoshiro256_seed(xoshiro256_state *state, uint64_t seed) {
+ uint64_t tmp = seed;
+ state->s[0] = splitmix64(&tmp);
+ state->s[1] = splitmix64(&tmp);
+ state->s[2] = splitmix64(&tmp);
+ state->s[3] = splitmix64(&tmp);
+}
+
+// Initialize the global state with current time or provided seed
+static inline void rng_init(uint64_t seed) {
+ if (seed == 0) {
+ seed = (uint64_t)time(NULL);
+ }
+ xoshiro256_seed(&xoshiro_global_state, seed);
+}
+
+// Generate a random double between 0.0 and 1.0 (inclusive 0.0, exclusive 1.0)
+static inline f64 rng_uniform_f64(void) {
+ // Take the top 53 bits (the precision of a double) to get a value in [0,1)
+ return (xoshiro256_next(&xoshiro_global_state) >> 11) * (1.0 / 9007199254740992.0);
+}
+
+// Generate a random int32 in the range [0, max)
+static inline i32 rng_int32(i32 max) {
+ // Avoid modulo bias by using rejection sampling
+ const uint64_t threshold = (((uint64_t)-1) - ((uint64_t)-1) % max);
+ uint64_t r;
+ do {
+ r = xoshiro256_next(&xoshiro_global_state);
+ } while (r >= threshold);
+ return (i32)(r % max);
+}
+
diff --git a/src/tolsac.c b/src/tolsac.c
new file mode 100644
index 0000000..4a3a0bc
--- /dev/null
+++ b/src/tolsac.c
@@ -0,0 +1,691 @@
+/**
+ * tolsac.c - source file containing creation of samples with various distributions.
+ *
+ * Copyright (C) 2025 https://optics-design.com
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * See the COPYING file for the full license text.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include "tolmacdef.h"
+
+// Enum for sampling methods
+typedef enum {
+ SAMPLING_LHS, // Latin Hypercube Sampling
+ SAMPLING_MCS, // Monte Carlo Sampling
+ SAMPLING_GRID, // Grid Sampling
+ SAMPLING_SENS // Sensitivity Analysis
+} SamplingMethod;
+
+// Enum for probability distribution functions
+typedef enum {
+ PDF_UNIFORM = 'U',
+ PDF_NORMAL = 'N',
+ PDF_TRUNCNORMAL = 'T' // Truncated normal
+} PdfType;
+
+// Parameter data structure for improved memory locality
+typedef struct {
+ byte* pdf_types; // Probability distribution types
+ f64* nominal_values; // Nominal values
+ f64* min_values; // Minimum values
+ f64* max_values; // Maximum values
+ f64* mean_values; // Mean values
+ f64* stddev_values; // Standard deviation values
+} ParameterData;
+
+// Allocate memory for parameter data structure
+ParameterData* allocate_parameter_data(i32 param_count) {
+ ParameterData* data = (ParameterData*)malloc(sizeof(ParameterData));
+ if (!data) return NULL;
+
+ // Single contiguous allocation for all arrays for better cache locality
+ void* buffer = malloc(
+ param_count * sizeof(byte) + // pdf_types
+ param_count * sizeof(f64) * 5 // nominal, min, max, mean, stddev
+ );
+
+ if (!buffer) {
+ free(data);
+ return NULL;
+ }
+
+ // Assign pointers to appropriate sections of the buffer
+ data->pdf_types = (byte*)buffer;
+ data->nominal_values = (f64*)(data->pdf_types + param_count);
+ data->min_values = data->nominal_values + param_count;
+ data->max_values = data->min_values + param_count;
+ data->mean_values = data->max_values + param_count;
+ data->stddev_values = data->mean_values + param_count;
+
+ return data;
+}
+
+// Free parameter data structure
+void free_parameter_data(ParameterData* data) {
+ if (data) {
+ // Only need to free the buffer pointed to by pdf_types (first allocation)
+ free(data->pdf_types);
+ free(data);
+ }
+}
+
+// Normal CDF implementation (cumulative distribution function)
+static inline f64 normal_cdf(f64 x) {
+ // Constants for approximation
+ const f64 a1 = 0.254829592;
+ const f64 a2 = -0.284496736;
+ const f64 a3 = 1.421413741;
+ const f64 a4 = -1.453152027;
+ const f64 a5 = 1.061405429;
+ const f64 p = 0.3275911;
+
+ // Save the sign of x
+ int sign = 1;
+ if (x < 0) {
+ sign = -1;
+ x = -x;
+ }
+
+ // A&S formula 7.1.26
+ f64 t = 1.0 / (1.0 + p * x);
+ f64 y = 1.0 - (((((a5 * t + a4) * t + a3) * t + a2) * t + a1) * t * exp(-x * x));
+
+ return 0.5 * (1 + sign * y);
+}
+
+static inline f64 inverse_normal_cdf(f64 u) {
+ // Use the approximation of the inverse CDF of the normal distribution
+ const f64 a1 = -3.969683028665376e+01;
+ const f64 a2 = 2.209460984245205e+02;
+ const f64 a3 = -2.759285104469687e+02;
+ const f64 a4 = 1.383577518672690e+02;
+ const f64 a5 = -3.066479806614716e+01;
+ const f64 a6 = 2.506628277459239e+00;
+
+ const f64 b1 = -5.447609879822406e+01;
+ const f64 b2 = 1.615858368580409e+02;
+ const f64 b3 = -1.556989798598866e+02;
+ const f64 b4 = 6.680131188771972e+01;
+ const f64 b5 = -1.328068155288572e+01;
+
+ const f64 c1 = -7.784894002430293e-03;
+ const f64 c2 = -3.223964580411365e-01;
+ const f64 c3 = -2.400758277161838e+00;
+ const f64 c4 = -2.549732539343734e+00;
+ const f64 c5 = 4.374664141464968e+00;
+ const f64 c6 = 2.938163982698783e+00;
+
+ const f64 d1 = 7.784695709041462e-03;
+ const f64 d2 = 3.224671290700398e-01;
+ const f64 d3 = 2.445134137142996e+00;
+ const f64 d4 = 3.754408661907416e+00;
+
+ const f64 p_low = 0.02425;
+ const f64 p_high = 1.0 - p_low;
+
+ f64 q, r;
+
+ if (u < p_low) {
+ q = sqrt(-2.0 * log(u));
+ return (((((c1 * q + c2) * q + c3) * q + c4) * q + c5) * q + c6) /
+ ((((d1 * q + d2) * q + d3) * q + d4) * q + 1.0);
+ } else if (u <= p_high) {
+ q = u - 0.5;
+ r = q * q;
+ return (((((a1 * r + a2) * r + a3) * r + a4) * r + a5) * r + a6) * q /
+ (((((b1 * r + b2) * r + b3) * r + b4) * r + b5) * r + 1.0);
+ } else {
+ q = sqrt(-2.0 * log(1.0 - u));
+ return -(((((c1 * q + c2) * q + c3) * q + c4) * q + c5) * q + c6) /
+ ((((d1 * q + d2) * q + d3) * q + d4) * q + 1.0);
+ }
+}
+
+// Generate sample based on distribution type
+static inline f64 generate_sample(byte pdf_type, f64 u, f64 min, f64 max, f64 mean, f64 stddev) {
+ switch (pdf_type) {
+ case PDF_NORMAL: // 'N'
+ // For normal: mean + stddev * inverse_normal_cdf(u)
+ return mean + stddev * inverse_normal_cdf(u);
+
+ case PDF_TRUNCNORMAL: // 'T'
+ // For truncated normal:
+ {
+ // 1. Calculate normalized min and max values
+ f64 z_min = (min - mean) / stddev;
+ f64 z_max = (max - mean) / stddev;
+
+ // 2. Calculate CDF at min and max
+ f64 cdf_min = normal_cdf(z_min);
+ f64 cdf_max = normal_cdf(z_max);
+
+ // 3. Scale u to be between cdf_min and cdf_max
+ f64 u_scaled = cdf_min + u * (cdf_max - cdf_min);
+
+ // 4. Apply inverse CDF to get value in correct range
+ return mean + stddev * inverse_normal_cdf(u_scaled);
+ }
+
+ case PDF_UNIFORM: // 'U'
+ // For uniform: min + u * (max - min)
+ return min + u * (max - min);
+
+ default:
+ // Default to uniform if unknown
+ return min + u * (max - min);
+ }
+}
+
+// Function to display help information
+void display_help(void) {
+ printf("Description:\n"
+ "The program generates random values for parameters based on the "
+ "given range and the probability distribution. "
+ "It is expected that the output is used in another program "
+ "to perform tolerancing.\n\n"
+ "Usage:\n"
+ ".\\tolsamp.exe Input.csv 50 [-o Output.csv]\n"
+ "Where:\n"
+ "Input.csv is a csv input file of a specific form.\n"
+ "50 is the number of iterations produced (not required for the "
+ "grid and sensitivity samplings)\n"
+ "-o Output.csv specifies the output path and filename.\n"
+ "If not provided, output will be named Sampled_[Input.csv] in the current directory.\n"
+ "If you are unsure how the input should look like, "
+ "run the program with the -e option to generate an example "
+ "input file.\n\n"
+ "Options:\n"
+ "-l, -g, -m, -s are used for latin hypercube, grid, Monte Carlo "
+ "(random), and sensitivity samplings.\n"
+ "Use -m only if there are some issues with the LHS. "
+ "LHS usually is the best.\n"
+ "-o specifies the output filename (can include path).\n"
+ "-e is used for example csv generation.\n\n"
+ "Defaults:\n"
+ "In the default case the program runs with -l.\n\n"
+ "Input CSV file info:\n"
+ "CSV file also contains possible probability density functions "
+ "(U-Uniform, N-Normal, T-Truncated Normal) and the associated mean "
+ "and standard deviation parameters.\n"
+ "This program can produce symmetric normal and truncated normal distributions.");
+}
+
+// Function to generate example file
+void generate_example(void) {
+ FILE *writefile = fopen("Example.csv", "w");
+ if (!writefile) {
+ printf("Error creating example file!\n");
+ return;
+ }
+
+ fprintf(writefile, "Iteration Number,Parameter 1 Name,Parameter 2 Name,Parameter 3 Name,Parameter 4 Name\n");
+ fprintf(writefile, "Probability Density Function (U=Uniform; N=Normal/Gaussian; T=Truncated Normal),U,U,N,T\n");
+ fprintf(writefile, "Nominal, 0, 0, 6, 5\n");
+ fprintf(writefile, "Max, 1, 0.1, 10, 7\n");
+ fprintf(writefile, "Min, -1, -0.1, 2, 3\n");
+ fprintf(writefile, "Mean,0.0, 0.0, 6.0, 5.0\n");
+ fprintf(writefile, "Standard Deviation, 0, 0, 1.3, 1.0\n");
+ fclose(writefile);
+
+ printf("Example.csv file generated!\n");
+}
+
+// Optimized LHS interval generation that transposes for better cache locality
+void generate_lhs_intervals(i32 iterations, i32 param_count, i32* intervals) {
+ // Initialize intervals for LHS in column-major order for better cache locality
+ for (i32 i = 0; i < iterations; i++) {
+ for (i32 j = 0; j < param_count; j++) {
+ // Store in transposed form: intervals[i * param_count + j] = i
+ intervals[i * param_count + j] = i;
+ }
+ }
+
+ // Fisher-Yates shuffle for each parameter (each column)
+ for (i32 j = 0; j < param_count; j++) {
+ for (i32 i = iterations - 1; i > 0; i--) {
+ i32 k = rng_int32(i + 1);
+ // Swap intervals[i * param_count + j] and intervals[k * param_count + j]
+ i32 temp = intervals[i * param_count + j];
+ intervals[i * param_count + j] = intervals[k * param_count + j];
+ intervals[k * param_count + j] = temp;
+ }
+ }
+}
+
+i32 main(i32 argc, char *argv[]) {
+ // Initialize variables
+ SamplingMethod sampling_method = SAMPLING_LHS; // Default to LHS
+ i32 iterations = 0;
+ char rfilename[FILENAME_MAX] = {0};
+ char wfilename[FILENAME_MAX] = {0};
+ i32 input_specified = 0;
+ i32 output_specified = 0;
+ i32 expect_output_file = 0;
+
+ // Check for no arguments
+ if (argc == 1) {
+ printf("No input provided. Use -h for help.\n");
+ return 1;
+ }
+
+ // Process all arguments
+ for (i32 i = 1; i < argc; i++) {
+ if (argv[i][0] == '-') {
+ // Process flag arguments
+ switch (argv[i][1]) {
+ case 'h':
+ display_help();
+ return 0;
+ case 'e':
+ generate_example();
+ return 0;
+ case 'm':
+ sampling_method = SAMPLING_MCS;
+ break;
+ case 'g':
+ sampling_method = SAMPLING_GRID;
+ break;
+ case 'l':
+ sampling_method = SAMPLING_LHS;
+ break;
+ case 's':
+ sampling_method = SAMPLING_SENS;
+ break;
+ case 'o':
+ // Next argument should be the output file
+ expect_output_file = 1;
+ break;
+ default:
+ printf("Unknown option: -%c\n", argv[i][1]);
+ break;
+ }
+ } else if (expect_output_file) {
+ // This is the output file specified after -o
+ strcpy(wfilename, argv[i]);
+ output_specified = 1;
+ expect_output_file = 0;
+ } else if (strstr(argv[i], ".csv")) {
+ // This is an input CSV file (we now only allow one)
+ if (!input_specified) {
+ strcpy(rfilename, argv[i]);
+ input_specified = 1;
+ } else {
+ printf("Warning: Multiple input files specified. Using only the first one: %s\n", rfilename);
+ }
+ } else {
+ // Parse iteration count
+ i32 tmp = atoi(argv[i]);
+ if (tmp > 0) {
+ iterations = tmp;
+ }
+ }
+ }
+
+ // Error checks
+ if (!input_specified) {
+ printf("Error! No input CSV provided. Use -e if you want to see how it looks like.\n");
+ return 1;
+ }
+
+ if (expect_output_file) {
+ printf("Error! Expected an output file after -o option.\n");
+ return 1;
+ }
+
+ if (iterations == 0 && sampling_method != SAMPLING_GRID && sampling_method != SAMPLING_SENS) {
+ printf("Error! You didn't provide an integer number of iterations.\n");
+ return 1;
+ }
+
+ // Generate default output filename if not specified
+ if (!output_specified) {
+ // Generate default output filename - handle both Windows and Unix paths
+ char *file_ptr = strrchr(rfilename, '\\');
+ if (!file_ptr) {
+ file_ptr = strrchr(rfilename, '/');
+ }
+
+ strcpy(wfilename, "Sampled_");
+ if (file_ptr) {
+ strcat(wfilename, file_ptr + 1);
+ } else {
+ strcat(wfilename, rfilename);
+ }
+ }
+
+ // Check if input file exists
+ FILE *readfile = fopen(rfilename, "r");
+ if (!readfile) {
+ printf("Error! Input file not found: %s\n", rfilename);
+ return 1;
+ }
+
+ // Open output file
+ FILE *writefile = fopen(wfilename, "w");
+ if (!writefile) {
+ printf("Error! Could not create output file: %s\n", wfilename);
+ fclose(readfile);
+ return 1;
+ }
+
+ // Read the header line
+ char header_line[1024] = {0};
+ if (!fgets(header_line, sizeof(header_line), readfile)) {
+ printf("Error reading header line!\n");
+ fclose(readfile);
+ fclose(writefile);
+ return 1;
+ }
+
+ // Write the header line to output
+ fputs(header_line, writefile);
+
+ // Count parameters (commas)
+ i32 param_count = 0;
+ for (char *p = header_line; *p; p++) {
+ if (*p == ',') param_count++;
+ }
+
+ printf("1. Total of %d parameters detected in %s. Output file is named %s.\n", param_count, rfilename, wfilename);
+
+ // Initialize RNG with current time as seed
+ rng_init(0);
+
+ // Allocate parameter data structure
+ ParameterData* params = allocate_parameter_data(param_count);
+ if (!params) {
+ printf("Error! Memory allocation failed for parameter data.\n");
+ fclose(readfile);
+ fclose(writefile);
+ return 1;
+ }
+
+ // Parse input file - using larger fixed size buffers to avoid potential overflows
+ char buffer[32768]; // 32KB buffer for reading lines
+ char *token, *err_ptr;
+ i32 k = 0;
+
+ // PDFs
+ if (!fgets(buffer, sizeof(buffer), readfile)) {
+ printf("Error reading PDF line from input file!\n");
+ free_parameter_data(params);
+ fclose(readfile);
+ fclose(writefile);
+ return 1;
+ }
+
+ token = strtok(buffer, ",");
+ while ((token = strtok(NULL, ","))) {
+ params->pdf_types[k++] = *token;
+ }
+
+ // Nominal
+ k = 0;
+ if (!fgets(buffer, sizeof(buffer), readfile)) {
+ printf("Error reading nominal values from input file!\n");
+ free_parameter_data(params);
+ fclose(readfile);
+ fclose(writefile);
+ return 1;
+ }
+
+ token = strtok(buffer, ",");
+ while ((token = strtok(NULL, ","))) {
+ params->nominal_values[k++] = strtof(token, &err_ptr);
+ }
+
+ // Maxima
+ k = 0;
+ if (!fgets(buffer, sizeof(buffer), readfile)) {
+ printf("Error reading maximum values from input file!\n");
+ free_parameter_data(params);
+ fclose(readfile);
+ fclose(writefile);
+ return 1;
+ }
+
+ token = strtok(buffer, ",");
+ while ((token = strtok(NULL, ","))) {
+ params->max_values[k++] = strtof(token, &err_ptr);
+ }
+
+ // Minima
+ k = 0;
+ if (!fgets(buffer, sizeof(buffer), readfile)) {
+ printf("Error reading minimum values from input file!\n");
+ free_parameter_data(params);
+ fclose(readfile);
+ fclose(writefile);
+ return 1;
+ }
+
+ token = strtok(buffer, ",");
+ while ((token = strtok(NULL, ","))) {
+ params->min_values[k++] = strtof(token, &err_ptr);
+ }
+
+ // Means
+ k = 0;
+ if (!fgets(buffer, sizeof(buffer), readfile)) {
+ printf("Error reading mean values from input file!\n");
+ free_parameter_data(params);
+ fclose(readfile);
+ fclose(writefile);
+ return 1;
+ }
+
+ token = strtok(buffer, ",");
+ while ((token = strtok(NULL, ","))) {
+ params->mean_values[k++] = strtof(token, &err_ptr);
+ }
+
+ // Standard Deviations
+ k = 0;
+ if (!fgets(buffer, sizeof(buffer), readfile)) {
+ printf("Error reading standard deviation values from input file!\n");
+ free_parameter_data(params);
+ fclose(readfile);
+ fclose(writefile);
+ return 1;
+ }
+
+ token = strtok(buffer, ",");
+ while ((token = strtok(NULL, ","))) {
+ params->stddev_values[k++] = strtof(token, &err_ptr);
+ }
+
+ fclose(readfile);
+ printf("2. Input CSV successfully parsed.\n");
+
+ // Write initial reference row
+ fprintf(writefile, "1");
+ for (i32 j = 0; j < param_count; j++) {
+ fprintf(writefile, ",%g", params->nominal_values[j]);
+ }
+ fprintf(writefile, "\n");
+
+ // Generate and write samples based on sampling method
+ switch (sampling_method) {
+ case SAMPLING_MCS:
+ // Monte Carlo sampling
+ for (i32 i = 0; i < iterations; i++) {
+ // Write row number
+ fprintf(writefile, "%d", i + 2);
+
+ // Generate samples for each parameter
+ for (i32 j = 0; j < param_count; j++) {
+ f64 u = rng_uniform_f64();
+ f64 sample = generate_sample(params->pdf_types[j], u,
+ params->min_values[j], params->max_values[j],
+ params->mean_values[j], params->stddev_values[j]);
+
+ // If truncated normal and out of bounds, use uniform random between min and max
+ if (params->pdf_types[j] == PDF_TRUNCNORMAL &&
+ (sample < params->min_values[j] || sample > params->max_values[j])) {
+ f64 u_uniform = rng_uniform_f64();
+ sample = generate_sample('U', u_uniform,
+ params->min_values[j], params->max_values[j],
+ params->mean_values[j], params->stddev_values[j]);
+ }
+
+ fprintf(writefile, ",%g", sample);
+ }
+
+ fprintf(writefile, "\n");
+ }
+ break;
+
+ case SAMPLING_GRID:
+ // Handle grid sampling iterations for large parameter counts
+ if (param_count >= 30) { // 2^30 would be over a billion iterations
+ printf("Error: Grid sampling with %d parameters would result in too many iterations (2^%d).\n",
+ param_count, param_count);
+ free_parameter_data(params);
+ fclose(writefile);
+ return 1;
+ } else {
+ iterations = 1 << param_count;
+ if (param_count > 17) {
+ char response;
+ printf("You have %d parameters, which corresponds to %d iterations. Are you sure this is what you want? (y/n): ",
+ param_count, iterations);
+ scanf("%c", &response);
+ if (response != 'y') {
+ printf("Quitting.\n");
+ free_parameter_data(params);
+ fclose(writefile);
+ return 1;
+ }
+ }
+ }
+
+ // Grid sampling
+ for (i32 i = 0; i < iterations; i++) {
+ // Write row number
+ fprintf(writefile, "%d", i + 2);
+
+ // Generate samples for each parameter
+ for (i32 j = 0; j < param_count; j++) {
+ f64 sample;
+
+ // Safe bit manipulation even for large parameter counts
+ if ((i >> j) & 1) {
+ sample = params->max_values[j];
+ } else {
+ sample = params->min_values[j];
+ }
+
+ fprintf(writefile, ",%g", sample);
+ }
+
+ fprintf(writefile, "\n");
+ }
+ break;
+
+ case SAMPLING_SENS:
+ // Calculate number of iterations needed: 2 * number of parameters
+ iterations = 2 * param_count;
+
+ // For each parameter
+ for (i32 j = 0; j < param_count; j++) {
+ // Parameter at minimum, others at nominal
+ fprintf(writefile, "%d", j*2 + 2);
+ for (i32 k = 0; k < param_count; k++) {
+ if (k == j) {
+ // This parameter at minimum
+ fprintf(writefile, ",%g", params->min_values[k]);
+ } else {
+ // Others at nominal
+ fprintf(writefile, ",%g", params->nominal_values[k]);
+ }
+ }
+ fprintf(writefile, "\n");
+
+ // Parameter at maximum, others at nominal
+ fprintf(writefile, "%d", j*2 + 3);
+ for (i32 k = 0; k < param_count; k++) {
+ if (k == j) {
+ // This parameter at maximum
+ fprintf(writefile, ",%g", params->max_values[k]);
+ } else {
+ // Others at nominal
+ fprintf(writefile, ",%g", params->nominal_values[k]);
+ }
+ }
+ fprintf(writefile, "\n");
+ }
+ break;
+
+ case SAMPLING_LHS:
+ // Allocate intervals for LHS (transposed for better cache locality)
+ i32 *intervals = (i32*)malloc(iterations * param_count * sizeof(i32));
+ if (!intervals) {
+ printf("Error! Memory allocation failed for intervals.\n");
+ free_parameter_data(params);
+ fclose(writefile);
+ return 1;
+ }
+
+ // Generate LHS intervals with improved cache locality
+ generate_lhs_intervals(iterations, param_count, intervals);
+
+ // Latin Hypercube sampling
+ for (i32 i = 0; i < iterations; i++) {
+ // Write row number
+ fprintf(writefile, "%d", i + 2);
+
+ // Generate samples for each parameter
+ for (i32 j = 0; j < param_count; j++) {
+ // Get interval for this parameter (accessing in transposed form)
+ i32 interval = intervals[i * param_count + j];
+ f64 interval_start = (f64)interval / iterations;
+ f64 interval_end = (f64)(interval + 1) / iterations;
+ f64 u = interval_start + rng_uniform_f64() * (interval_end - interval_start);
+
+ f64 sample = generate_sample(params->pdf_types[j], u,
+ params->min_values[j], params->max_values[j],
+ params->mean_values[j], params->stddev_values[j]);
+
+ // Handle truncated normal out-of-bounds samples with improved approach
+ while (params->pdf_types[j] == PDF_TRUNCNORMAL &&
+ (sample < params->min_values[j] || sample > params->max_values[j])) {
+ // Try a new sample within the same interval for better statistical properties
+ i32 i_rej = rng_int32(iterations);
+ i32 j_rej = rng_int32(param_count);
+ i32 interval_rej = intervals[i_rej * param_count + j_rej];
+ f64 interval_start_rej = (f64)interval_rej / iterations;
+ f64 interval_end_rej = (f64)(interval_rej + 1) / iterations;
+ f64 u_rej = interval_start_rej + rng_uniform_f64() * (interval_end_rej - interval_start_rej);
+ sample = generate_sample(params->pdf_types[j], u_rej,
+ params->min_values[j], params->max_values[j],
+ params->mean_values[j], params->stddev_values[j]);
+ }
+
+ fprintf(writefile, ",%g", sample);
+ }
+
+ fprintf(writefile, "\n");
+ }
+
+ // Free LHS intervals
+ free(intervals);
+ break;
+ }
+
+ // Clean up
+ free_parameter_data(params);
+
+ printf("3. %d rows and %d columns have been written to the file.\nProgram finished! Check the output!\n",
+ iterations + 1, param_count + 1);
+ fclose(writefile);
+
+ return 0;
+}
diff --git a/structure.txt b/structure.txt
new file mode 100644
index 0000000..3b7407e
--- /dev/null
+++ b/structure.txt
@@ -0,0 +1,25 @@
+tolsac
+| .clangd
+| .gitignore
+| compile_flags.txt
+| COPYING
+| COPYRIGHT
+| Makefile
+| README.md
+| structure.txt
+|
++---bin
+| tolsac.exe
+|
++---include
+| toldef.h
+| tolmacdef.h
+|
++---src
+| tolsac.c
+|
+\---tests
+ Example.csv
+ hist.r
+ Sampled_Example.csv
+
diff --git a/tests/Example.csv b/tests/Example.csv
new file mode 100644
index 0000000..2c6ed66
--- /dev/null
+++ b/tests/Example.csv
@@ -0,0 +1,7 @@
+Iteration Number,Parameter 1 Name,Parameter 2 Name,Parameter 3 Name,Parameter 4 Name
+Probability Density Function (U=Uniform; N=Normal/Gaussian; T=Truncated Normal),U,U,N,T
+Nominal, 0, 0, 6, 5
+Max, 1, 0.1, 10, 7
+Min, -1, -0.1, 2, 3
+Mean,0.0, 0.0, 6.0, 5.0
+Standard Deviation, 0, 0, 1.3, 1.5
diff --git a/tests/Sampled_Example.csv b/tests/Sampled_Example.csv
new file mode 100644
index 0000000..4357a72
--- /dev/null
+++ b/tests/Sampled_Example.csv
@@ -0,0 +1,1002 @@
+Iteration Number,Parameter 1 Name,Parameter 2 Name,Parameter 3 Name,Parameter 4 Name
+1,0,0,6,5
+2,-0.447882,-0.0167241,2.57527,4.37054
+3,0.968682,-0.0586998,7.45248,5.06988
+4,-0.842439,-0.0561725,6.52784,5.01692
+5,-0.395612,0.0442927,4.92421,5.38399
+6,0.0420414,0.0584518,8.34442,3.96429
+7,-0.730353,0.00440439,7.07359,4.5874
+8,-0.464467,-0.00851533,6.55851,4.45161
+9,-0.996313,0.0883977,5.48266,3.83068
+10,-0.716747,0.0174173,7.06949,5.65414
+11,-0.218966,0.0199446,7.29352,6.10357
+12,0.716854,-0.00492169,5.5187,4.27839
+13,0.654153,-0.00251044,5.53421,5.51787
+14,0.265945,-0.0634619,8.16951,4.17465
+15,0.736711,-0.0784835,4.87941,4.75171
+16,-0.732259,-0.0571093,5.59827,4.18606
+17,0.826133,-0.0293251,6.51912,6.4991
+18,0.986128,0.014704,5.47865,3.89358
+19,-0.672543,-0.0179533,7.21728,4.71736
+20,0.339959,0.0226431,6.15126,5.12981
+21,0.712746,-0.0704099,5.71231,4.53799
+22,-0.713658,-0.0568181,5.76801,5.43618
+23,0.697891,-0.0548865,5.5665,5.29645
+24,-0.746132,0.0634282,4.62583,4.83363
+25,0.781298,-0.0111269,4.26713,6.79052
+26,0.795403,0.0501854,5.22077,3.26088
+27,0.657083,-0.0880077,3.84039,3.87686
+28,-0.710088,-0.0532829,7.09584,4.47555
+29,0.701074,-0.0691546,8.04346,4.01534
+30,0.650317,-0.0203927,5.82273,3.84334
+31,0.0681637,0.0888699,6.53559,3.81846
+32,-0.900036,0.0988853,5.56396,3.23206
+33,-0.939905,-0.0604353,5.63373,5.726
+34,-0.285908,0.0605226,7.77042,4.78695
+35,0.359812,-0.0106921,6.72127,6.19754
+36,-0.971847,0.0587401,5.84393,5.93756
+37,-0.192236,0.0783495,4.46394,6.07152
+38,0.527827,0.0127592,5.68722,3.761
+39,-0.629812,-0.0360936,4.54711,3.87198
+40,0.955132,0.0494486,5.80461,4.66938
+41,-0.502164,-0.0948897,6.96044,4.406
+42,-0.8638,-0.0364034,5.39141,4.11295
+43,0.456398,-0.0667134,5.74804,5.84887
+44,0.0230029,-0.0822804,6.51306,3.99537
+45,0.678608,0.0979709,6.01203,5.78782
+46,0.52493,-0.0645964,4.84491,3.88287
+47,-0.314555,-0.096328,5.68084,3.67162
+48,-0.57384,0.0377082,5.45966,4.52394
+49,0.964836,0.0856935,8.93762,3.62629
+50,-0.985586,-0.0135407,5.94306,5.71236
+51,-0.17499,0.0588124,4.73971,3.16714
+52,0.453448,-0.0366041,7.23516,6.32631
+53,0.575641,-0.0452107,4.80583,6.09766
+54,-0.561616,0.0203688,6.20688,4.93558
+55,0.413243,0.00117644,5.38056,4.96387
+56,-0.119488,-0.0208496,7.11087,4.70102
+57,0.908748,-0.0554151,6.94175,5.46428
+58,0.436673,-0.076233,6.95583,4.72678
+59,-0.812224,-0.0741759,4.00006,6.54116
+60,-0.213875,0.0815374,3.43701,6.11375
+61,0.0997154,-0.0959217,6.10218,5.54485
+62,-0.182745,-0.0713067,5.2254,4.8262
+63,0.643063,-0.0777787,6.29343,4.97055
+64,-0.657443,-0.0261338,7.44153,5.81302
+65,0.907553,0.0529798,1.21361,4.73027
+66,-0.727405,-0.000964708,6.71294,4.59887
+67,0.991171,0.0410835,4.09214,5.75676
+68,-0.403396,0.0474208,5.73934,3.92465
+69,0.369762,-0.0263021,7.06172,5.55773
+70,-0.535768,0.0908397,6.74394,6.24678
+71,0.470341,0.0117787,5.72393,6.94032
+72,-0.659509,0.0535654,6.79983,5.96893
+73,0.229148,-0.070948,6.24115,6.3896
+74,0.0194076,0.0467775,7.82273,4.99095
+75,-0.565808,0.0381452,7.41394,5.89978
+76,-0.373072,-0.0787176,7.18893,5.5416
+77,0.24659,0.0968746,6.22648,5.49112
+78,-0.139242,-0.0447999,5.50334,4.57077
+79,-0.898432,-0.0510666,5.83581,4.68997
+80,0.0759989,0.0954872,8.25718,3.65297
+81,-0.244209,-0.0922574,4.51292,4.89523
+82,-0.972266,-0.0758223,7.19227,4.32329
+83,-0.488452,-0.079611,5.27467,3.55407
+84,0.923246,0.0957127,4.25643,5.45439
+85,0.353145,0.0213887,7.61903,5.40905
+86,0.706658,0.0825657,3.31347,4.42219
+87,-0.825253,0.0642244,4.94751,4.81509
+88,-0.687673,0.0686716,5.41272,5.11562
+89,-0.83432,-0.0573159,5.39984,4.30768
+90,0.0802876,0.0295784,4.97041,5.38632
+91,-0.549515,-0.0266952,6.4171,4.38665
+92,0.371264,-0.0773921,5.22885,4.33423
+93,0.556976,-0.0151217,3.66933,4.73687
+94,0.932123,-0.0820083,5.44319,5.00806
+95,-0.933178,-0.0678849,6.01781,4.44967
+96,-0.674372,-0.0258927,7.28393,5.05837
+97,-0.735469,-0.0240827,5.82916,5.53068
+98,-0.689544,-0.00692896,6.00083,5.50792
+99,-0.567228,0.0062815,4.17524,3.80887
+100,0.306025,0.0242629,7.91922,6.18336
+101,-0.719473,-0.00370206,7.22046,6.63811
+102,-0.934549,-0.031138,6.53755,4.62173
+103,0.100405,0.0141187,5.82583,6.00714
+104,0.232662,-0.0425564,6.61035,4.986
+105,0.0504862,0.0414032,7.02963,5.01913
+106,0.345798,0.0869024,6.89868,6.26711
+107,0.178741,0.065199,3.95032,6.15243
+108,0.89192,0.0403636,6.50625,5.59484
+109,-0.820973,-0.097744,6.43467,4.20883
+110,-0.756392,-0.0651285,3.89501,3.48304
+111,-0.738683,-0.0363131,5.1808,6.6803
+112,-0.467467,-0.0724549,5.01244,4.96739
+113,0.598525,-0.00785212,5.85621,4.55869
+114,-0.995193,-0.000253996,8.88759,5.56799
+115,0.259586,0.0617719,6.84112,5.89832
+116,0.647481,-0.0710609,4.99052,4.33819
+117,0.301813,0.0855286,7.40323,5.49383
+118,0.604621,0.0160448,5.89458,6.32008
+119,-0.154248,0.0190188,6.10808,6.36604
+120,0.984922,0.099552,9.05249,4.82814
+121,0.682685,0.0666382,5.55203,3.64061
+122,-0.799513,0.0301887,5.21158,3.3093
+123,0.974139,-0.0542228,5.26875,5.31889
+124,-0.937418,-0.0441004,7.57021,4.00431
+125,-0.764542,0.0105609,4.64943,6.41319
+126,0.141831,-0.052722,5.88616,4.89187
+127,-0.897664,-0.0021101,5.90348,3.0079
+128,0.704236,-0.0590139,6.26458,5.77059
+129,-0.208156,-0.0254016,7.17396,5.53251
+130,-0.396605,-0.00350822,5.15711,5.36691
+131,-0.926232,-0.082603,6.20571,5.49721
+132,-0.26272,-0.0022374,5.85127,4.39383
+133,0.884893,0.0810895,6.38736,3.33906
+134,-0.85282,0.0912056,7.40907,5.08187
+135,0.116389,0.0452358,6.13414,3.472
+136,-0.905177,0.00416206,7.04262,5.47137
+137,0.44843,0.0433479,4.87319,6.44758
+138,-0.617761,-0.0488104,6.12911,3.96596
+139,0.174553,-0.09882,5.75764,5.55024
+140,0.988424,-0.0600381,4.00996,3.77518
+141,0.123911,0.00881982,3.53782,3.52492
+142,-0.921843,0.0136343,5.20361,4.03158
+143,0.54157,-0.0331757,6.41406,6.10018
+144,-0.430945,0.0754509,4.50248,3.95513
+145,-0.0910368,0.0159377,6.79227,5.56403
+146,-0.0943865,0.0673901,5.95812,4.19634
+147,-0.660774,0.0850891,4.79937,6.41451
+148,-0.544388,-0.043736,4.64065,3.18219
+149,0.630193,-0.0305334,7.4989,6.53869
+150,-0.786742,0.0138837,5.19373,5.42473
+151,0.54869,0.0438838,5.57561,5.66366
+152,0.46726,0.059771,8.10334,4.99764
+153,-0.78854,-0.00667272,6.29983,6.97996
+154,0.335494,-0.0719047,7.30519,3.3768
+155,-0.220027,0.0644722,3.415,4.88206
+156,0.588577,0.0215093,6.62933,3.12618
+157,0.842895,0.0692282,8.13171,5.64374
+158,-0.819189,0.0972089,7.35688,4.50819
+159,0.614577,-0.0174063,4.21834,3.37839
+160,-0.952023,0.0055239,4.92834,4.79392
+161,-0.833396,0.0680885,4.31944,3.80561
+162,0.173786,-0.0276478,3.74784,5.86632
+163,-0.592177,-0.0199384,4.89485,3.64448
+164,0.740539,0.0274154,3.81028,6.45662
+165,0.360042,-0.0499098,4.93024,4.28887
+166,0.979022,-0.0114882,7.32906,3.09969
+167,-0.517457,0.0394904,4.45691,6.91519
+168,-0.224939,0.0348959,4.21479,4.80894
+169,0.445653,0.0427182,5.81551,6.34243
+170,-0.613498,0.0574911,6.13966,4.67793
+171,0.674897,0.0284446,6.83371,4.03345
+172,0.597087,0.0779726,5.98402,3.42582
+173,0.925651,-0.0314347,6.89272,4.43453
+174,0.255717,0.0471462,6.97478,3.02556
+175,0.518187,0.0131116,7.36307,5.10906
+176,0.952062,0.0925079,6.37074,3.71522
+177,-0.229939,-0.0669795,4.75404,3.13559
+178,0.728821,-0.0152894,6.98833,4.49151
+179,0.761291,-0.0729278,6.9939,4.84006
+180,0.0216248,0.0975493,6.03085,4.78019
+181,-0.837999,0.0553182,6.78562,5.4768
+182,-0.85994,0.0148813,5.80217,5.64577
+183,-0.162013,-0.0902881,8.54107,6.28248
+184,-0.0813104,0.0886957,3.40036,4.54778
+185,0.611182,-0.0229593,4.32705,6.75535
+186,0.380256,0.035328,6.47261,4.15551
+187,0.505778,-0.0834097,6.2971,4.04227
+188,0.570607,0.0684035,6.17184,4.80449
+189,-0.742795,-0.00118026,6.63021,5.03103
+190,0.666085,0.0259659,5.68754,6.65378
+191,-0.587616,-0.00594362,4.95333,5.62173
+192,0.475471,0.0124374,6.06577,4.77336
+193,-0.721046,0.0637672,4.0255,6.90545
+194,0.269683,0.0205119,8.55635,3.71897
+195,0.77679,0.0152585,9.60269,4.98546
+196,0.256514,-0.0535,4.72483,4.89772
+197,0.873463,0.00338909,4.60508,5.14936
+198,0.281765,0.0821528,8.08739,4.90181
+199,0.688119,-0.0225357,6.90892,5.29216
+200,0.765095,0.0337324,7.25798,5.6659
+201,0.889383,-0.0222998,5.4247,4.41416
+202,0.897011,0.0156682,3.3655,3.19315
+203,0.208447,0.0608197,5.01801,4.79494
+204,-0.423545,-0.0505884,6.54883,3.97621
+205,0.158625,0.00944769,6.08214,6.99696
+206,-0.0693748,-0.0556187,6.78096,4.86038
+207,0.133182,0.0712631,5.2789,6.28937
+208,-0.910302,0.0506966,6.93456,3.91164
+209,0.222531,0.0271163,5.70961,5.40393
+210,0.432682,0.0919812,2.82477,4.97308
+211,0.917315,0.0302886,5.07316,4.08406
+212,-0.0824936,-0.0348718,5.04029,5.77685
+213,-0.0293627,-0.037113,7.04671,4.77231
+214,0.930167,0.0335741,8.99116,3.31549
+215,0.328307,-0.086189,6.97263,3.93135
+216,-0.276393,0.0661015,6.96495,3.20922
+217,-0.473442,0.0527808,5.88474,5.86005
+218,-0.185443,0.0674854,6.49477,3.54912
+219,0.253531,0.00236887,5.92409,5.51487
+220,0.823332,0.0031927,6.35539,3.47801
+221,-0.0314977,-0.023755,5.99195,4.06917
+222,0.559419,-0.0415516,5.07394,5.96741
+223,-0.387405,-0.0483364,8.58131,4.72155
+224,0.000938099,-0.0782131,5.96624,6.97783
+225,-0.870667,-0.0852506,7.59355,3.05904
+226,0.882753,-0.0647502,2.88994,5.39605
+227,0.477114,-0.0566438,7.21354,3.79257
+228,0.126349,-0.0925395,6.11935,5.79767
+229,0.276526,-0.0735531,7.31262,6.66461
+230,-0.0561094,0.0496187,5.44242,6.46741
+231,-0.524611,-0.0492514,6.27246,3.40635
+232,0.241191,0.0493998,5.26523,3.43
+233,0.660705,0.0731228,7.52495,4.12086
+234,-0.526091,0.0896358,4.55273,6.21669
+235,0.506942,-0.0632736,5.97479,6.69781
+236,0.910124,-0.0997819,5.13694,6.11498
+237,-0.949761,0.0664112,6.40907,5.27953
+238,-0.359428,0.0398529,7.03676,4.51869
+239,0.881267,-0.097307,6.13182,5.49898
+240,0.425903,0.0520036,4.67988,6.5505
+241,-0.017614,0.0458008,3.11509,5.77312
+242,0.177183,-0.0375532,7.55761,6.43617
+243,-0.413749,0.0668244,5.32521,6.53206
+244,-0.682656,-0.06418,5.09414,5.46825
+245,-0.335924,-0.0404222,5.48525,3.97914
+246,-0.621607,0.0281545,5.97244,3.30292
+247,-0.410954,-0.081589,6.81962,3.70504
+248,-0.131579,0.025133,4.81337,5.91483
+249,-0.643893,0.0571846,6.46175,4.22122
+250,0.137833,-0.0907484,6.24317,4.32529
+251,-0.699381,-0.0194648,7.02091,4.42987
+252,-0.906464,-0.0380112,4.08496,5.61688
+253,-0.109872,0.0976799,6.33594,4.16758
+254,-0.345451,0.0473003,6.53995,6.24834
+255,-0.552631,-0.0806535,5.10951,3.33145
+256,0.114965,-0.077854,7.46491,6.79924
+257,0.510624,-0.0828562,6.50407,6.58315
+258,-0.123538,-0.063637,5.40647,4.92253
+259,0.316427,0.0752851,8.32626,5.65877
+260,-0.306819,-0.0653918,7.50288,6.17207
+261,0.458155,-0.00875415,6.1457,6.7592
+262,0.19638,-0.0353143,5.38342,5.79475
+263,0.303132,0.0544628,5.81288,3.94937
+264,0.617004,-0.0553057,5.46806,4.03044
+265,-0.2895,-0.00771967,4.44776,3.74083
+266,0.866102,-0.0239031,6.70215,5.73104
+267,-0.595586,-0.0932501,5.78692,4.43624
+268,0.216168,0.0424111,5.64751,5.19029
+269,-0.231704,0.0558981,4.90141,5.33625
+270,0.645678,-0.0593946,3.63611,6.47477
+271,-0.584133,-0.0766389,6.94862,5.83625
+272,0.0482031,0.0238402,3.59925,4.27756
+273,-0.281485,-0.00752095,6.16198,5.26941
+274,0.860021,0.0142417,6.42672,5.80516
+275,-0.233452,-0.0904275,6.0539,4.55596
+276,0.994371,-0.0218868,6.72751,6.17783
+277,0.0410687,-0.0580399,5.87293,6.61679
+278,-0.676406,-0.0329075,7.2413,5.45124
+279,-0.633464,0.0513249,6.93616,4.2497
+280,0.797463,0.077395,5.33842,5.24904
+281,0.626169,-0.0983996,5.88137,6.40028
+282,-0.441236,0.0509016,5.6217,4.69873
+283,-0.255037,0.00921438,6.29056,5.16087
+284,0.936719,-0.0597182,6.02341,6.49352
+285,0.215629,-0.0454262,7.65356,4.95031
+286,0.86423,0.0548596,7.08162,4.22542
+287,-0.816846,-0.0521026,4.8167,4.09052
+288,0.82949,-0.00329349,7.20475,6.67813
+289,-0.648816,-0.0626137,7.45065,5.08661
+290,0.0549662,0.0628333,4.58718,6.07945
+291,-0.499267,0.0234465,5.76192,3.34746
+292,-0.361465,-0.029046,5.37334,6.26888
+293,0.501744,0.00961031,7.36609,5.83955
+294,0.724132,0.0253344,6.09187,3.66157
+295,0.29541,0.013509,5.24727,5.58327
+296,-0.630608,-0.0359966,7.24987,6.00026
+297,-0.241374,0.0249721,4.78122,5.15333
+298,-0.391692,-0.0422698,6.80457,4.59099
+299,-0.569316,-0.000751098,8.82007,5.48347
+300,-0.480839,0.0305361,5.01688,5.12234
+301,-0.215622,0.0324984,7.51963,4.65202
+302,-0.144384,-0.0137796,7.79852,5.02624
+303,0.160852,-0.0235047,6.11576,6.8196
+304,-0.0459201,0.00779192,5.52068,4.63473
+305,0.685963,0.048583,5.27151,4.45684
+306,-0.615854,-0.0141622,3.97086,4.63124
+307,0.231453,0.0792219,4.69414,6.45437
+308,0.585943,-0.0217014,4.24678,4.82178
+309,0.245821,0.0894909,8.28076,4.44263
+310,-0.452166,-0.0154468,7.09199,5.72026
+311,-0.363099,-0.0323235,5.41686,4.4803
+312,0.859871,0.0670861,7.14066,4.94039
+313,-0.581503,0.0363407,4.43193,3.85719
+314,-0.650316,0.0487371,4.62326,3.10615
+315,-0.399613,0.00151389,5.42409,3.56217
+316,-0.623515,0.0490866,5.30741,5.18395
+317,0.783009,-0.0665819,4.41966,6.64165
+318,-0.992391,0.000179528,7.16667,5.91732
+319,0.10229,-0.0270928,8.29753,4.55387
+320,0.686166,0.0993995,4.89936,5.60966
+321,0.03456,0.0178079,5.69818,3.5575
+322,0.591913,0.0767356,7.82944,4.87204
+323,-0.00933091,0.0543017,3.45373,4.30853
+324,-0.0497384,-0.0376161,8.63966,6.08434
+325,-0.873749,0.0983233,5.4744,3.89722
+326,-0.236903,0.0905202,5.46204,4.88379
+327,0.184567,-0.0753118,7.66202,4.26859
+328,0.39878,-0.0338946,6.3049,4.87874
+329,-0.479952,0.080193,4.01354,3.94669
+330,-0.543418,-0.0943023,8.47049,5.90547
+331,-0.439032,-0.0702886,5.66299,3.57201
+332,-0.0402448,0.00279236,6.56118,6.71805
+333,-0.40593,0.00138462,5.54612,5.35031
+334,-0.324062,0.0991148,4.57931,6.76916
+335,-0.77795,-0.0356648,5.0478,3.32442
+336,0.59517,-0.0746242,4.72252,5.26569
+337,-0.497067,-0.0227192,6.05114,3.98407
+338,0.747131,0.0610521,3.09424,4.50353
+339,-0.211979,-0.00817785,4.96723,5.65285
+340,-0.529852,-0.00303366,7.33176,4.771
+341,0.0287736,0.0760201,5.35109,4.34441
+342,-0.247779,0.0822478,5.10023,5.73361
+343,0.632293,0.0531918,4.85099,5.94669
+344,-0.0116691,0.0967781,5.95012,6.94889
+345,0.848955,0.0911154,5.60918,6.38924
+346,0.0917821,0.0640931,4.94183,6.13031
+347,-0.982618,0.0211953,4.65753,4.61662
+348,-0.268048,-0.00297396,3.57463,6.28172
+349,0.582139,0.00860731,5.63819,6.78215
+350,-0.0759892,-0.0599111,6.45111,5.62273
+351,-0.107291,-0.0251437,7.27559,5.8695
+352,0.0641808,-0.0191646,8.31377,5.61138
+353,0.383891,-0.0274609,4.78865,4.13383
+354,0.63896,-0.0514747,5.16197,5.19846
+355,-0.293211,-0.0378605,6.48545,5.85016
+356,-0.347835,-0.0283341,3.34977,6.48047
+357,0.778001,-0.0165353,5.39776,5.70961
+358,0.544432,0.0106265,6.21842,5.16637
+359,-0.418403,0.0102214,4.50679,4.31918
+360,-0.23928,0.0330596,4.94599,4.11073
+361,-0.807522,0.0936346,7.75342,5.28549
+362,0.792339,0.0632117,5.28679,5.66883
+363,0.45123,0.0613219,6.44441,4.23577
+364,-0.172954,0.0768933,7.8444,5.4302
+365,0.313298,-0.0692083,5.57291,5.19428
+366,0.13842,0.0218695,6.52972,3.94147
+367,-0.321588,-0.0392394,7.63814,5.13938
+368,-0.917753,0.0451538,5.75724,3.54491
+369,0.0663606,0.0254507,3.78852,5.07646
+370,-0.547309,0.0364548,5.17326,5.69291
+371,0.187332,0.0269347,4.59158,3.43798
+372,-0.421581,0.0947174,6.10598,3.38803
+373,-0.808228,0.0728471,5.24034,5.97069
+374,0.803048,-0.0897571,3.88338,5.89512
+375,0.0163484,0.0428364,4.57387,3.35312
+376,0.402944,-0.0321824,7.00863,4.7881
+377,-0.318217,0.0906388,6.87317,3.16166
+378,0.508925,0.0834661,7.15664,4.75823
+379,-0.437824,0.0123147,4.80041,6.85933
+380,-0.511178,-0.0623559,7.87173,4.55762
+381,-0.33241,0.00616004,6.57141,6.33098
+382,0.798718,-0.00438772,9.21337,4.6276
+383,-0.032534,-0.0844832,7.35084,6.44034
+384,0.393172,0.00525329,3.47903,4.80582
+385,0.567789,0.0808012,8.1386,5.75068
+386,0.512714,-0.051729,6.16729,3.51802
+387,0.814941,-0.0606589,7.50894,6.23457
+388,0.293212,-0.0176001,7.4925,5.78138
+389,-0.186157,-0.0460405,7.48206,5.13134
+390,0.790397,-0.0508458,7.08726,6.42703
+391,-0.541337,-0.0248437,6.19127,3.76707
+392,0.830345,0.0342872,4.70623,4.00569
+393,0.66468,0.0853083,5.49115,4.8173
+394,-0.740067,0.0816044,6.48792,3.7985
+395,-0.0895001,0.0885201,6.60196,4.65711
+396,-0.966493,-0.0564625,7.28157,3.61649
+397,0.602997,0.0812314,5.61954,6.92965
+398,-0.697117,-0.0770692,5.64634,4.67346
+399,0.204999,0.0128247,4.52246,6.06085
+400,0.388844,0.00480167,9.19093,3.22474
+401,0.207337,0.0522494,7.53227,6.65447
+402,-0.954319,-0.0256555,8.02203,4.21984
+403,0.748586,-0.0301821,7.72778,3.72534
+404,-0.267463,-0.0888338,6.34742,4.27441
+405,-0.1806,0.0865655,6.67489,6.18518
+406,0.542814,0.0316725,5.02259,3.4953
+407,-0.199849,0.0638234,5.87099,4.76091
+408,-0.434723,-0.0654511,7.90705,5.15769
+409,-0.201483,-0.0280003,4.68294,3.78385
+410,0.479443,0.0469453,4.5999,6.49783
+411,-0.48335,-0.0547165,5.60491,3.99108
+412,-0.94677,-0.0403818,6.33953,5.70251
+413,-0.0995917,-0.0960379,6.36381,4.58356
+414,-0.759582,0.0121358,7.16275,4.82493
+415,0.996777,0.0457364,5.47614,5.38631
+416,-0.301954,0.0369245,7.31989,4.02271
+417,-0.791738,0.0407898,7.22974,3.19928
+418,0.905175,-0.0347686,4.85403,6.05581
+419,0.181316,0.045568,8.21942,4.84848
+420,0.0855941,0.0877682,5.52726,4.6209
+421,-0.393668,0.0207996,4.79371,4.38223
+422,-0.356479,0.0417326,7.1263,6.58965
+423,-0.329374,-0.032534,7.59972,5.24243
+424,0.58181,-0.0161752,6.58609,6.3526
+425,-0.370638,0.0525331,7.55021,5.40032
+426,0.820049,0.038406,5.70406,6.44769
+427,-0.875578,0.0561351,4.86174,4.64629
+428,-0.364359,-0.0910919,6.96371,4.07667
+429,-0.943819,-0.00968003,6.52327,6.1056
+430,0.463098,0.0838425,5.58189,3.88977
+431,-0.110156,0.00378651,5.89622,5.07373
+432,0.612172,0.0338849,6.72653,3.59391
+433,0.105695,0.0841082,8.11842,4.20609
+434,0.96267,-0.0421921,4.83503,3.37025
+435,-0.282461,0.02609,5.49519,5.2704
+436,-0.892747,0.0849486,8.21582,6.51257
+437,-0.270907,0.0173874,7.62482,5.22567
+438,0.721243,-0.0699674,6.73239,6.36112
+439,0.00283749,-0.0173461,5.66519,5.17206
+440,-0.601342,0.0444921,4.82388,3.08261
+441,0.0577089,-0.0545411,4.35439,6.69224
+442,0.323587,0.0837654,5.58837,3.29778
+443,0.480969,0.00296886,7.7629,4.69717
+444,0.374932,0.0100135,6.54389,5.57432
+445,-0.0382771,0.0949732,5.64284,4.25272
+446,-0.457963,0.0844537,4.066,4.90493
+447,0.786136,0.0431109,6.91438,4.44512
+448,0.405889,-0.00999712,4.1832,3.86163
+449,0.62486,-0.0491397,4.88567,5.11415
+450,0.14816,0.043795,6.91986,4.84443
+451,-0.317443,0.075799,4.71062,4.28647
+452,0.0978568,-0.0794782,6.64646,4.52471
+453,0.670415,-0.026468,7.86306,5.25928
+454,0.468599,-0.0800634,6.74631,3.24641
+455,-0.626834,-0.0398973,5.83872,5.38197
+456,-0.202494,0.0224374,4.41893,3.867
+457,0.348749,-0.0868036,5.12123,3.77186
+458,0.900193,-0.0426021,4.17335,3.70114
+459,-0.748512,-0.0803691,5.03079,3.71145
+460,0.762341,-0.091686,5.77708,6.28181
+461,0.851884,-0.0927373,5.60287,3.96284
+462,-0.468561,0.00713548,4.53302,4.64102
+463,-0.407582,0.0166179,5.45312,5.96282
+464,0.351125,-0.0813509,5.05635,5.99148
+465,0.0702506,0.0842353,5.35841,3.78767
+466,0.564023,-0.0761019,6.31472,3.95563
+467,0.434635,-0.014894,5.49776,3.01764
+468,0.692717,0.0648941,6.22051,3.33056
+469,0.758045,0.0863439,6.38305,3.12703
+470,0.966156,0.00855882,5.8776,3.57503
+471,0.837238,-0.0878692,4.75718,6.03808
+472,-0.0075595,0.078772,5.95465,4.52762
+473,0.94082,-0.0950293,7.20607,6.8102
+474,0.539169,0.0176739,5.79545,6.31791
+475,0.743569,0.0282529,5.28828,5.33248
+476,0.711565,0.0744213,6.09983,3.73122
+477,0.485938,-0.0269474,5.0626,6.82159
+478,0.915705,0.0441107,4.2753,6.22049
+479,0.514101,0.0998842,6.07333,5.35528
+480,0.182719,0.0592243,2.75351,5.32595
+481,-0.684571,-0.0475112,5.11858,5.78901
+482,0.144518,0.0180858,8.46019,4.15149
+483,0.193973,-0.00896704,7.47345,3.53888
+484,0.774095,-0.00401251,6.88302,3.40121
+485,-0.923751,-0.0840488,6.32374,5.13177
+486,0.577043,0.0462565,5.25227,5.58855
+487,-0.0847672,-0.0837984,6.61645,5.04604
+488,0.0821666,0.0830697,5.12566,6.29619
+489,0.628561,0.0351335,5.36924,6.27606
+490,0.731938,0.0646117,6.0863,5.0947
+491,-0.662513,-0.0306837,5.4468,4.84396
+492,0.0779639,0.0928209,6.75789,6.5069
+493,0.397644,-0.0809951,6.15611,4.74509
+494,-0.400087,0.0705417,5.55126,5.83
+495,-0.78212,-0.0854487,6.3759,4.5928
+496,-0.66419,-0.0716704,6.39658,3.12395
+497,0.489042,-0.0428393,7.37796,5.18503
+498,-0.409393,-0.0743604,6.59267,5.81108
+499,-0.769189,0.0594132,4.47239,4.26417
+500,-0.606063,0.049868,6.71003,4.01193
+501,0.621165,0.0892848,4.55923,5.93028
+502,0.00878203,0.0971377,6.26067,4.41964
+503,0.163585,0.0505757,3.21341,5.79326
+504,-0.828652,0.00679444,5.90647,4.63847
+505,0.415548,-0.0182413,2.98397,6.33638
+506,0.128296,-0.0659696,6.09516,3.17492
+507,-0.295343,-0.0384684,4.03602,5.69941
+508,-0.887377,0.0630387,5.13972,6.30143
+509,0.562382,-0.0661419,4.05915,5.08995
+510,0.482313,0.065428,7.11406,6.73786
+511,0.494935,-0.0969903,5.34319,3.97039
+512,-0.0644706,-0.0706471,3.76576,4.15946
+513,-0.644628,0.085826,7.89674,5.92978
+514,0.0453791,-0.0170345,5.24333,5.75461
+515,-0.963038,-0.00181963,6.73839,5.58427
+516,0.200297,0.0676864,5.84265,4.30207
+517,0.816657,0.0390577,5.5161,5.32867
+518,-0.70347,-0.0273254,5.55767,5.7732
+519,0.811589,0.0110693,6.04253,5.98155
+520,0.226695,0.0725527,6.50818,4.95306
+521,-0.745642,0.0355997,4.5255,3.34506
+522,-0.591927,-0.0473839,4.90867,3.28818
+523,0.239019,-0.088574,5.69603,5.17624
+524,0.234896,-0.0344129,6.40517,3.69173
+525,-0.223711,0.0326848,5.5894,3.41256
+526,-0.101152,-0.0187652,9.10725,5.67476
+527,-0.583642,0.0697624,6.23245,5.60533
+528,0.553543,0.0653783,6.64214,4.9177
+529,0.0389811,0.0819441,5.91193,4.7683
+530,-0.915935,-0.0340187,7.1334,4.93174
+531,0.384208,0.0209315,6.20255,5.96695
+532,0.807337,0.0747914,6.25211,4.40438
+533,0.672968,0.0400215,6.18415,4.24649
+534,0.757524,0.00168239,6.58865,3.85111
+535,-0.381866,0.0229169,7.37097,4.61047
+536,-0.830557,0.0714985,4.98493,4.87381
+537,-0.341692,0.0736235,6.20981,4.77813
+538,0.464132,0.0315909,5.30126,3.03283
+539,0.669004,-0.0319115,4.12653,5.60005
+540,0.819434,-0.0793965,6.22404,4.97915
+541,0.491854,0.0246791,8.15391,5.50296
+542,-0.570743,0.0802277,4.56517,5.97474
+543,-0.389368,-0.0221264,5.33511,5.34972
+544,-0.822898,-0.0940023,6.14777,4.71331
+545,0.430352,-0.0201878,6.81405,5.43542
+546,0.652424,-0.0913342,5.33051,4.22942
+547,0.211962,-0.0738739,7.10145,5.94296
+548,0.401728,0.0074323,7.00721,3.75681
+549,-0.458349,-0.0212742,4.49153,4.64723
+550,0.059603,0.0601949,7.48645,5.82023
+551,-0.750896,0.0266349,7.26518,4.14161
+552,0.750557,0.0770946,6.47969,6.34582
+553,-0.486987,-0.0390704,5.67032,6.2838
+554,0.699283,0.058082,7.8379,5.7185
+555,0.406233,-0.0965267,7.38172,3.41174
+556,0.708288,-0.0246066,4.73391,6.92835
+557,-0.792304,0.070705,6.46761,5.1417
+558,-0.20504,0.0796905,5.93078,5.74777
+559,0.695907,-0.0674069,5.97831,5.22917
+560,0.773384,-0.0125768,6.25509,6.37976
+561,0.31533,-0.0577308,7.1475,5.36338
+562,0.999394,0.087488,6.23528,3.58437
+563,0.417339,0.0741649,5.92053,5.9255
+564,0.929848,0.0195636,6.77708,4.8903
+565,-0.714114,0.0827074,7.86001,4.79853
+566,-0.178568,-0.0631679,7.177,5.54344
+567,-0.103323,-0.0886173,4.2003,4.28673
+568,0.170725,-0.0629331,6.75679,5.88646
+569,0.142383,0.0622402,8.0548,3.0442
+570,0.440021,-0.00631069,6.80959,5.20657
+571,0.372584,-0.0649933,4.76048,5.112
+572,0.250818,-0.0685398,5.53067,6.55909
+573,-0.113303,-0.047738,6.84699,5.64566
+574,0.56016,-0.0955253,6.2389,4.54835
+575,-0.866947,-0.0920091,6.17388,3.50128
+576,0.242711,-0.0146621,8.07374,6.37694
+577,-0.679483,0.0196021,6.84891,3.15696
+578,-0.754581,-0.0120654,6.70017,4.04942
+579,-0.608347,-0.0497702,7.58158,6.34348
+580,0.516804,0.0656129,6.09022,5.03544
+581,0.111767,0.0132075,5.09839,5.14583
+582,0.834408,0.0950004,6.84031,4.5634
+583,0.333473,0.0922637,6.27756,4.05363
+584,-0.445729,0.0090344,5.56968,3.28153
+585,-0.968734,0.0320431,9.32438,5.67625
+586,0.529008,-0.0386009,5.39382,5.54687
+587,-0.881349,-0.0673343,7.69818,6.72858
+588,-0.0027237,-0.0825312,4.8311,4.9199
+589,-0.961652,-0.0677917,7.02525,5.40574
+590,-0.0437755,0.0878116,7.63022,4.45884
+591,0.261174,-0.0156299,3.50178,4.60249
+592,-0.471064,0.0880642,3.1929,6.8511
+593,0.378525,-0.0119326,4.77067,4.85753
+594,-0.188387,-0.0196013,4.64479,6.46586
+595,0.635516,0.0784222,7.69358,3.75149
+596,0.663042,0.0662472,4.16333,5.391
+597,0.357785,-0.0299689,6.86191,3.90343
+598,-0.655919,-0.0938072,4.63285,4.35877
+599,0.753439,-0.0789283,2.68078,4.39916
+600,0.93515,-0.0643011,6.06461,5.36797
+601,-0.128047,0.0871991,5.59392,4.18273
+602,-0.539298,0.0739856,4.34068,4.39361
+603,0.289162,-0.0480172,5.06675,6.04927
+604,-0.449393,-0.0915268,6.86955,5.89892
+605,-0.847629,0.0716219,4.86927,3.00039
+606,-0.981232,0.0804618,5.35931,5.32411
+607,-0.05902,0.000702393,3.77008,5.92151
+608,0.395031,-0.0934349,6.12531,6.15779
+609,0.677656,0.00995964,4.37001,4.94178
+610,0.194385,0.0446751,5.05093,3.30103
+611,-0.299815,0.0694613,5.65539,4.21248
+612,-0.577297,-0.0562531,6.36802,4.07728
+613,0.0116277,0.0318512,3.71868,6.22615
+614,0.886302,0.0703535,6.14326,6.98688
+615,-0.170535,0.00576095,8.09945,6.30828
+616,0.44258,-0.0206594,5.35293,6.63313
+617,0.151615,0.0245912,7.43423,5.803
+618,-0.556419,-0.0430822,7.5748,4.69514
+619,-0.512985,-0.068973,5.36464,4.29507
+620,-0.637474,-0.0831121,5.29743,5.48619
+621,-0.161591,-0.0681129,5.90127,3.60267
+622,-0.124166,0.0333306,6.56606,4.97595
+623,-0.794303,-0.0865624,5.78309,4.54743
+624,0.1191,0.0287952,8.23676,4.31252
+625,0.825228,0.0658296,4.9977,4.23816
+626,0.715693,0.0185637,4.1295,4.622
+627,0.275776,0.0183003,5.52392,5.64078
+628,-0.451473,0.0118849,4.34371,4.25941
+629,-0.494931,-0.0126002,5.23486,3.66975
+630,-0.977403,-0.0870259,5.10593,4.49617
+631,0.648046,0.0701644,6.17918,6.56559
+632,-0.811331,-0.0308257,4.86808,5.11521
+633,-0.0258303,0.0373438,6.86843,3.91808
+634,0.755367,0.048161,4.91695,3.58288
+635,0.769974,0.0798691,5.43252,5.68567
+636,-0.374476,-0.075077,5.40867,6.12892
+637,0.659419,0.0418474,5.37445,5.08585
+638,-0.990531,0.000201552,6.94506,5.8576
+639,0.892909,0.0568451,7.39459,5.23803
+640,-0.484425,-0.0745293,5.14819,5.10525
+641,0.0940622,0.015104,7.39167,6.046
+642,-0.884302,-0.0316608,7.03352,6.11194
+643,0.426362,-0.00562234,8.17717,4.12146
+644,0.592392,0.0422186,5.16429,5.69043
+645,-0.454968,0.0806891,5.08982,6.61502
+646,-0.909561,0.0371138,6.0391,5.8911
+647,-0.891986,-0.0289616,5.99508,3.88071
+648,0.722231,0.094143,7.81018,4.54209
+649,-0.800061,-0.0701085,6.8008,5.05359
+650,-0.127042,-0.0799904,6.01532,5.22359
+651,-0.383681,0.0965828,5.88953,5.4158
+652,0.47309,0.0986429,7.051,5.52938
+653,-0.06664,-0.0609715,4.61731,6.39537
+654,0.438713,-0.0501048,6.19451,3.59783
+655,0.284768,-0.0810205,5.9515,4.84458
+656,-0.304438,-0.0683383,3.90171,5.32407
+657,-0.13675,-0.00605947,7.61373,3.91982
+658,-0.959584,0.0421806,4.89039,4.06342
+659,-0.944143,-0.0354491,8.67851,6.37182
+660,0.876737,-0.061517,5.85948,3.61031
+661,-0.635947,0.0750396,4.30767,5.28224
+662,-0.504713,0.00590093,5.774,4.03773
+663,-0.804826,0.019255,6.03918,6.38178
+664,-0.018102,0.0200955,7.71668,5.82858
+665,-0.167075,-0.0443437,3.05278,4.69306
+666,-0.62427,0.0310771,8.71476,5.95915
+667,0.267894,0.0169219,6.06156,3.73814
+668,-0.518219,0.0621315,5.61076,4.15023
+669,-0.27417,-0.0980305,5.50713,4.60799
+670,-0.150221,-0.013254,7.05304,5.55465
+671,-0.046783,-0.0297676,9.35456,4.85828
+672,0.898942,-0.0715337,7.23803,4.09451
+673,-0.501134,-0.000415277,5.74375,5.13757
+674,0.248043,0.0590539,6.82261,6.88137
+675,-0.279701,0.0237219,6.55727,4.65775
+676,0.0617258,0.0829137,3.51959,6.20069
+677,0.496094,-0.0351035,5.28329,5.4435
+678,0.734492,-0.0726292,5.9352,6.01559
+679,-0.0932465,-0.00137002,3.93651,6.56488
+680,0.521124,0.0357582,6.9779,5.68386
+681,0.305437,-0.098485,4.49618,5.00529
+682,0.318189,0.000409147,6.66833,4.14707
+683,0.55083,0.0379717,5.65859,3.95787
+684,-0.700389,0.0626781,4.84229,3.04776
+685,0.0477623,-0.0129973,5.11433,5.95509
+686,0.311785,0.000811977,3.56419,4.52983
+687,-0.778725,-0.0435639,6.31064,6.53099
+688,-0.291044,-0.0558958,4.93764,6.42652
+689,-0.98694,-0.0142408,9.82258,4.34681
+690,0.73331,-0.0947134,9.48592,3.22005
+691,-0.350771,-0.0695994,6.00811,5.70412
+692,-0.520906,-0.066345,7.06405,3.11388
+693,0.681038,-0.0617997,5.8661,6.87499
+694,0.555187,-0.0843271,4.60809,6.60437
+695,0.024257,0.0171616,4.47342,3.50634
+696,0.568121,0.0579973,6.32026,3.95823
+697,-0.522464,-0.0894416,5.58331,6.60424
+698,0.420804,-0.00469771,6.88536,4.53052
+699,0.296157,-0.0588625,5.17777,4.29745
+700,-0.0235208,-0.0410573,6.59421,6.14254
+701,0.326683,-0.0470727,6.05632,4.3581
+702,-0.589975,0.00501098,7.56334,5.15955
+703,-0.367715,-0.0768979,4.82624,3.97611
+704,0.608504,0.091755,5.43739,4.50766
+705,-0.772685,-0.0343163,6.55198,3.99651
+706,0.340461,0.0915266,2.0467,6.79619
+707,-0.0771141,-0.0833148,5.23454,5.41218
+708,0.4283,0.0847235,4.44318,6.70409
+709,0.739605,0.0297553,6.67408,6.77152
+710,0.125684,-0.0732184,6.73999,4.12624
+711,0.365909,0.00649754,5.03201,3.25357
+712,-0.0126156,0.0476963,6.07846,4.98041
+713,0.951558,-0.0373712,6.02819,4.72487
+714,0.785279,-0.0850895,6.66676,4.07365
+715,-0.691102,0.0958281,6.5814,4.04435
+716,-0.474423,-0.00912901,4.40108,4.9087
+717,0.0336678,0.0216089,7.67236,3.27655
+718,0.619895,-0.0139626,5.83105,3.84769
+719,0.993001,-0.0736413,6.76824,4.42519
+720,-0.287169,-0.0890796,6.18911,6.89577
+721,0.134711,0.0577562,6.21391,5.17767
+722,-0.692851,-0.0574307,5.67597,6.82576
+723,-0.17734,-0.0730251,2.97525,4.3205
+724,-0.216062,0.0984007,3.64617,5.46028
+725,-0.0342454,-0.0657766,3.82867,4.38673
+726,0.977713,0.0723957,3.91658,4.34733
+727,0.869598,0.0257374,3.28867,3.30423
+728,-0.753513,0.068395,7.99331,4.66837
+729,-0.191263,-0.0892299,6.89554,5.44597
+730,-0.774611,0.0483416,4.66757,3.09357
+731,0.809332,-0.0551673,4.76501,4.91384
+732,0.0877907,-0.0817161,7.01399,4.55185
+733,-0.13585,0.0691198,5.84946,6.10831
+734,-0.989873,0.027397,5.65293,6.87286
+735,0.273359,-0.0862361,6.61389,5.7351
+736,-0.868551,0.0953571,4.37453,4.512
+737,0.0129135,0.0367664,4.67146,4.5006
+738,0.455984,0.0777132,5.98346,4.77756
+739,-0.796389,-0.0117465,6.85554,5.63409
+740,0.744173,0.0718157,3.70197,5.0995
+741,-0.142053,-0.00160353,6.25872,4.8873
+742,0.331948,0.00210731,5.31134,5.06213
+743,-0.931165,-0.051942,5.80802,6.11966
+744,-0.0711987,0.0931548,5.61511,6.51986
+745,-0.555301,0.0699618,6.2801,5.08047
+746,-0.894273,0.0557824,5.34681,4.66948
+747,0.92753,0.0290459,3.73595,3.51245
+748,-0.425901,-0.0451426,5.13223,4.56866
+749,-0.428373,-0.0918194,5.43073,5.27408
+750,-0.639066,-0.0898141,4.99279,6.13811
+751,-0.336314,-0.0618263,6.18122,3.21696
+752,0.487902,-0.0113113,6.59807,5.43121
+753,0.324154,0.089826,6.68386,5.52705
+754,0.970776,-0.0754456,4.40701,3.90045
+755,0.447983,-0.00440053,8.03922,5.30875
+756,-0.156752,-0.0230555,6.905,4.92819
+757,0.0531236,0.0562521,7.72392,6.90119
+758,0.503163,0.0518663,5.94662,5.63284
+759,-0.331431,-0.0900463,6.36086,4.14454
+760,0.972662,0.0276566,6.82835,5.30293
+761,-0.940563,0.00399979,7.64708,5.34125
+762,-0.618118,-0.0445456,4.38979,6.4859
+763,0.120667,0.0223269,7.96646,6.06405
+764,0.189308,0.0934142,4.96152,5.73609
+765,0.0722468,-0.020403,5.46725,4.16517
+766,-0.25372,0.0735373,4.43749,3.96289
+767,-0.918103,0.0689724,4.53815,5.84208
+768,0.944945,-0.0764415,4.68818,4.48577
+769,-0.670639,0.0903683,7.26794,6.25562
+770,0.83205,0.0567819,3.61273,5.30116
+771,0.156949,-0.0838942,5.69214,3.49084
+772,-0.737993,-0.0284223,7.30119,4.95522
+773,0.199367,0.00837941,7.93749,3.82134
+774,0.0622665,-0.0625728,4.69657,5.2021
+775,0.0887055,0.074234,6.00632,5.37677
+776,0.225683,-0.0945606,6.6876,5.23518
+777,0.320813,-0.0528808,6.57409,4.57471
+778,0.522773,-0.0335976,5.91528,6.38679
+779,-0.533293,-0.0244061,6.63739,4.26079
+780,-0.603201,0.0516845,5.31659,5.31147
+781,-0.725117,0.0448295,6.48311,5.7621
+782,0.423159,-0.0336343,4.28971,4.3815
+783,0.879951,0.0189532,3.16085,4.86528
+784,-0.15919,-0.0313895,6.30604,5.59783
+785,-0.882582,-0.0294432,6.65124,6.50541
+786,-0.249742,0.0606238,8.91957,6.71348
+787,-0.132985,-0.0523952,3.86282,5.45839
+788,-0.652406,-0.0303476,8.40295,4.09807
+789,0.870318,0.067845,7.70639,5.30718
+790,-0.0505713,0.0555841,5.632,6.16253
+791,-0.729368,-0.0418412,8.44165,5.94178
+792,-0.121376,0.00197733,5.91413,4.39184
+793,-0.888929,0.0540055,3.25612,4.66138
+794,-0.0140146,-0.010858,6.11116,6.74328
+795,0.623776,-0.0721996,6.43778,3.44993
+796,-0.00529783,-0.0974514,6.4744,6.57264
+797,0.804483,0.0832017,5.2944,6.4094
+798,0.64168,-0.0469144,5.00776,5.03966
+799,-0.563057,0.0115694,4.04196,5.38042
+800,0.54618,-0.087786,6.38452,5.57096
+801,0.00662737,-0.04493,4.10787,6.59069
+802,-0.763299,0.0546241,7.07916,6.59719
+803,-0.226136,0.0043143,8.74308,6.04341
+804,0.789304,-0.0791651,3.9337,4.59342
+805,-0.7805,-0.0774817,8.76209,3.94229
+806,0.130361,-0.0722945,5.9391,6.23926
+807,0.840825,-0.0538285,6.65675,4.70514
+808,0.949297,-0.000126278,7.11872,4.34068
+809,-0.669464,-0.0531104,4.19882,4.10185
+810,-0.95059,-0.0413466,6.28607,4.37725
+811,-0.343311,-0.0485155,4.66082,5.74244
+812,0.410041,-0.01014,6.26793,3.82932
+813,-0.114924,0.0341628,7.78011,5.51736
+814,-0.148504,-0.0936128,5.79855,3.9087
+815,-0.0200297,0.0435515,7.2517,5.52519
+816,-0.929127,-0.0846247,6.8797,4.26281
+817,-0.925229,-0.0168575,5.19134,5.20335
+818,0.875094,0.0872505,5.86703,6.8438
+819,0.960771,0.0328715,7.53411,4.76269
+820,-0.879262,-0.0867797,5.62549,4.24238
+821,0.947721,0.0393681,5.67263,4.94397
+822,-0.802174,0.0465498,6.82586,5.23228
+823,-0.78528,0.0960253,6.02167,5.63984
+824,-0.323092,-0.00732531,5.54361,5.31171
+825,-0.827088,-0.0585367,8.38761,3.07572
+826,-0.264933,-0.00552647,5.00102,6.66963
+827,0.838733,0.023283,5.30505,4.46905
+828,-0.463708,0.0386732,6.49386,5.21786
+829,-0.903693,-0.0383234,5.49964,3.3861
+830,0.493477,0.0762365,4.7479,3.4513
+831,0.939445,0.0155625,6.68172,5.57626
+832,-0.0263149,0.0710446,6.39162,4.8313
+833,-0.302487,-0.0696456,6.51813,4.57827
+834,-0.844284,-0.0503844,7.29085,4.99467
+835,0.263944,0.0409088,6.3978,5.90301
+836,-0.0530445,-0.0333402,5.19745,3.62557
+837,-0.998391,-0.0494917,4.95814,6.01812
+838,0.202945,-0.0610685,4.28136,4.73957
+839,0.856475,-0.0956092,5.81746,3.45932
+840,0.46187,0.0598813,6.60444,6.62654
+841,-0.490779,-0.050657,5.72619,5.11757
+842,-0.850086,0.0619607,4.71494,6.54435
+843,0.342676,-0.0541091,3.85748,4.6813
+844,-0.536723,-0.013026,5.13034,6.56995
+845,0.213724,0.0515963,6.99811,5.3723
+846,-0.706154,-0.04877,8.00652,4.53438
+847,-0.0370284,-0.00957575,6.98282,5.58967
+848,-0.0629267,-0.0122837,4.29983,4.1766
+849,-0.153381,0.0510216,8.59892,5.31515
+850,0.801767,-0.0188333,7.88958,6.11731
+851,-0.379039,-0.0990548,5.76574,3.63081
+852,0.58655,-0.0433399,5.51146,6.02489
+853,-0.273292,0.00473937,6.91172,3.83579
+854,-0.605531,-0.0874878,7.34476,4.472
+855,0.942247,0.079592,7.74061,6.21466
+856,-0.766859,-0.010262,7.54197,5.87641
+857,-0.147175,0.027938,6.92532,4.74327
+858,-0.165433,-0.0253409,5.72029,3.10117
+859,-0.169552,-0.0416011,5.45472,5.99613
+860,-0.848553,0.0602886,6.33743,6.01249
+861,-0.353136,-0.0602245,6.32944,3.74291
+862,-0.297799,0.0749666,4.48012,5.12335
+863,0.863466,-0.047953,5.75337,5.26118
+864,-0.575182,0.0732694,6.3796,4.69939
+865,-0.257065,-0.0162486,5.92524,6.36949
+866,0.146878,-0.0781223,6.32887,4.48396
+867,-0.000125689,-0.038833,3.96075,3.42103
+868,0.918046,-0.005188,5.73652,3.51085
+869,0.287023,-0.0464874,4.73362,5.2137
+870,0.855093,0.00810487,4.23953,5.35782
+871,0.355618,0.0359837,4.15481,6.42069
+872,0.845715,0.0413306,6.7058,5.82179
+873,-0.416135,0.0461781,6.43031,3.62155
+874,0.0793325,0.0932822,7.60779,6.22808
+875,-0.864437,0.0231277,5.71648,4.3545
+876,-0.443641,-0.0181232,4.98065,6.72242
+877,0.727273,-0.0594136,5.21808,3.63747
+878,-0.369177,0.0187874,6.16388,3.24284
+879,-0.313521,-0.0857057,7.10363,3.83354
+880,-0.857257,-0.0671396,6.40287,3.5648
+881,-0.70474,-0.0995491,6.43992,6.0279
+882,0.113618,-0.0525133,6.42342,3.73423
+883,-0.771972,0.0780207,5.32662,5.91123
+884,-0.196133,-0.0620308,10.7863,4.28216
+885,0.10885,0.0397169,8.49379,6.13231
+886,0.957545,0.0162311,7.97294,4.68648
+887,0.309326,0.0764873,7.95145,4.19987
+888,0.363845,0.0920962,4.91113,5.47081
+889,0.0932878,0.00348162,5.85973,5.00181
+890,-0.461101,-0.0858948,7.74741,4.85365
+891,-0.506687,0.00732457,6.65367,5.93531
+892,-0.0965575,0.0788209,5.0381,3.35857
+893,-0.97983,0.00246105,7.45844,4.36769
+894,-0.338724,-0.0993018,4.11803,3.14479
+895,-0.234553,0.0489848,7.12827,6.68237
+896,-0.854084,0.00781307,4.318,6.12243
+897,0.19089,-0.0462181,4.14421,5.04252
+898,0.00485137,-0.00716309,6.45455,4.27612
+899,0.91361,-0.0193397,5.20198,5.6265
+900,-0.610555,0.0564197,5.78936,5.01608
+901,0.958496,-0.0953318,6.06949,5.25453
+902,0.703016,0.0539233,8.42228,5.03467
+903,-0.206067,0.0867647,5.73116,4.08699
+904,-0.251161,-0.0243522,3.98588,5.42497
+905,-0.680446,-0.0457308,4.38221,3.41938
+906,-0.355423,0.010925,6.27152,6.83071
+907,0.902806,-0.0105134,4.3583,4.93878
+908,-0.261848,0.0346375,5.08392,4.36593
+909,-0.0794762,0.0721642,6.45575,5.16712
+910,0.386618,0.0614697,7.15429,6.09141
+911,-0.51444,0.0726078,6.7169,3.1155
+912,0.16618,0.0289601,6.76175,6.96716
+913,-0.531893,0.0944495,7.80355,5.74384
+914,0.408011,0.0382003,7.33859,6.30917
+915,-0.327231,-0.0408641,6.62391,4.13101
+916,-0.117974,-0.0537461,8.01627,4.18941
+917,0.690734,-0.00827199,5.2095,6.03269
+918,0.498127,0.0532412,6.63479,5.41938
+919,0.336595,0.0996195,7.18139,6.14959
+920,-0.195162,-0.0909495,5.93222,6.59382
+921,0.107309,0.0306457,8.36013,3.81558
+922,-0.723926,-0.0513506,4.57035,6.25902
+923,0.534546,-0.0882461,5.25657,6.16484
+924,-0.597379,-0.021594,7.68675,6.11602
+925,0.376283,0.0901611,5.18538,5.767
+926,-0.243139,-0.0233,6.68922,3.52843
+927,0.366699,-0.0038212,6.19855,3.39191
+928,-0.492344,-0.0757015,5.96865,3.45227
+929,0.766663,-0.0401482,4.77773,5.87958
+930,-0.0605845,-0.00930352,5.74711,5.63139
+931,0.57961,0.0791467,6.92708,4.40855
+932,0.0146754,-0.0144301,6.12138,5.12415
+933,-0.414661,0.0537111,5.77917,5.24727
+934,-0.8395,0.029923,6.44803,5.34435
+935,0.279223,-0.0406373,5.32111,3.26536
+936,-0.376924,0.0573254,5.1535,5.52075
+937,0.601103,0.0709887,6.62137,4.19212
+938,0.531671,-0.0582152,6.28485,6.08119
+939,0.536932,-0.0970463,6.78252,4.3308
+940,-0.309011,0.0963427,6.77115,6.96002
+941,0.346453,0.0264563,4.23091,6.06676
+942,-0.667912,0.0927224,4.26265,4.51634
+943,-0.140741,0.0308698,7.98287,5.2899
+944,0.0361835,-0.039529,6.24758,5.02449
+945,-0.76077,-0.0686738,7.14334,4.46385
+946,-0.349286,0.0503461,7.31639,6.69562
+947,0.981371,0.00699961,6.04639,5.95067
+948,0.2988,-0.0439108,3.80016,4.46322
+949,-0.385463,-0.00536302,8.19362,5.09558
+950,-0.974767,0.0322486,5.67873,4.01858
+951,0.169766,0.0774676,6.03446,4.71045
+952,-0.815403,-0.0849639,6.85795,3.93764
+953,0.23789,-0.0185966,5.98774,6.62837
+954,-0.432744,-0.0998664,6.69458,3.06386
+955,0.221224,-0.0748747,7.675,5.53471
+956,0.165006,-0.0210901,5.17018,5.21077
+957,-0.508319,-0.0967233,5.41967,4.86588
+958,0.154839,0.0360976,8.52607,4.49215
+959,-0.861623,-0.0326443,7.94019,5.74298
+960,0.606466,-0.0396946,5.56003,5.94331
+961,0.270955,0.024117,7.42063,3.20895
+962,-0.311037,-0.0931,6.34295,3.68214
+963,0.391457,-0.0459519,6.99964,6.83821
+964,-0.965011,0.0344026,6.46301,4.23682
+965,-0.0559797,-0.0287417,8.26424,4.06119
+966,0.418002,-0.0986306,7.42933,3.77225
+967,0.921235,-0.0929447,5.72831,3.46718
+968,-0.956646,-0.0979286,5.96212,3.58644
+969,0.0267077,0.0551188,5.70519,6.52888
+970,0.283622,-0.0579239,3.68884,4.10593
+971,0.852563,0.0942635,2.35611,6.19124
+972,0.5321,-0.0278766,5.53959,6.07171
+973,-0.104991,-0.0639874,7.19607,5.0513
+974,-0.694438,-0.0818324,4.97787,5.50976
+975,-0.709881,-0.0368245,5.14535,5.06481
+976,-0.640689,0.0582502,7.91429,4.74846
+977,-0.0872924,0.0891228,6.7527,3.67781
+978,0.982614,0.086089,5.38762,5.55255
+979,0.71854,0.0980083,7.79215,5.67805
+980,-0.558871,-0.0158528,5.25993,5.55002
+981,0.846157,0.0112532,2.51018,5.87282
+982,-0.646593,0.0625478,6.41934,4.26177
+983,-0.912197,-0.0805476,6.65959,5.01095
+984,-0.579414,-0.00153314,5.62982,5.98658
+985,0.219826,0.0758952,8.65167,6.08546
+986,0.637656,-0.00261932,4.0774,3.65467
+987,0.894483,0.0220492,6.3516,6.21094
+988,-0.599582,0.0312658,5.99708,4.95826
+989,-0.477396,0.0478024,5.05813,3.78107
+990,0.77148,0.0263749,5.79275,5.85187
+991,-0.877208,0.0374405,6.49968,6.20805
+992,-0.841083,0.0164645,7.42465,4.08155
+993,0.29179,-0.0466414,6.07588,5.98402
+994,-0.551414,0.0939925,6.57836,5.44054
+995,0.573059,-0.0612158,5.07888,4.60452
+996,0.812209,-0.00642389,6.15946,5.47961
+997,-0.0727279,-0.0872131,6.31868,3.69122
+998,-0.427931,0.0389265,8.83136,3.20849
+999,0.153333,0.0144079,6.79316,5.29992
+1000,-0.259719,0.0292732,6.35644,3.44228
+1001,0.0315253,0.0405276,4.39354,5.4837
diff --git a/tests/hist.r b/tests/hist.r
new file mode 100644
index 0000000..ee20d09
--- /dev/null
+++ b/tests/hist.r
@@ -0,0 +1,84 @@
+#!/usr/bin/env Rscript
+
+# Parse arguments (filename, column number, min, max, bins)
+args <- commandArgs(trailingOnly = TRUE)
+filename <- args[1]
+# start_row <- as.numeric(args[2])
+start_row <- 2
+col_num <- as.numeric(args[2])
+
+# Optional min and max values (positions 3 and 4)
+user_min <- ifelse(length(args) >= 3, as.numeric(args[3]), NA)
+user_max <- ifelse(length(args) >= 4, as.numeric(args[4]), NA)
+
+# Number of bins now at the end (position 5)
+num_bins <- ifelse(length(args) >= 5, as.numeric(args[5]), 20) # Default to 20 bins if not specified
+
+# Read the CSV file (assuming it has a header)
+data <- read.csv(filename, header = TRUE)
+
+# Extract the data
+plot_data <- data[start_row:nrow(data), col_num]
+
+# Convert to numeric
+plot_data <- as.numeric(as.character(plot_data))
+plot_data <- plot_data[!is.na(plot_data)]
+
+# Determine range bounds
+data_min <- min(plot_data)
+data_max <- max(plot_data)
+
+range_min <- ifelse(is.na(user_min), data_min, user_min)
+range_max <- ifelse(is.na(user_max), data_max, user_max)
+
+# Calculate percentage of samples within the range
+count_in_range <- sum(plot_data >= range_min & plot_data <= range_max)
+total_count <- length(plot_data)
+percent_in_range <- (count_in_range / total_count) * 100
+
+# Output to command line
+cat(sprintf("%.2f%% of samples are within the range [%.2f, %.2f]\n",
+ percent_in_range, range_min, range_max))
+
+# Set up graphics
+windows(width = 8, height = 6)
+
+# Create the histogram
+hist(plot_data,
+ breaks = num_bins,
+ main = paste("Histogram of Column", col_num),
+ xlab = "Value",
+ col = "lightblue",
+ border = "black")
+
+# Add vertical lines for min and max if provided by user
+if(!is.na(user_min)) {
+ abline(v = user_min, col = "red", lwd = 2, lty = 2)
+}
+if(!is.na(user_max)) {
+ abline(v = user_max, col = "red", lwd = 2, lty = 2)
+}
+
+# Add basic statistics including standard deviation
+stats_text <- paste0("n = ", length(plot_data), "\n",
+ "min = ", sprintf("%.2f", data_min), "\n",
+ "max = ", sprintf("%.2f", data_max), "\n",
+ "mean = ", sprintf("%.2f", mean(plot_data)), "\n",
+ "median = ", sprintf("%.2f", median(plot_data)), "\n",
+ "sd = ", sprintf("%.2f", sd(plot_data)), "\n",
+ sprintf("%.2f%% in [%.2f, %.2f]",
+ percent_in_range, range_min, range_max))
+
+text_x <- par("usr")[1] + 0.05 * (par("usr")[2] - par("usr")[1])
+text_y <- par("usr")[4] - 0.1 * (par("usr")[4] - par("usr")[3])
+text(text_x, text_y, stats_text, adj = c(0, 1))
+
+# Add text to instruct user
+mtext("Close this window using the X button when done", side = 1, line = 4, col = "red")
+
+# Tell user what to do
+cat("Histogram displayed. Close the window manually when done viewing.\n")
+cat("Usage: Rscript hist.r filename.csv column_number [min] [max] [bins]\n")
+
+# Keep the script running until the window is closed
+Sys.sleep(1000) # Keep script running for a long time
Back to https://optics-design.com