diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,675 @@
+              GNU GENERAL PUBLIC LICENSE
+                Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                     Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+ 
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+  
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+              END OF TERMS AND CONDITIONS
+
+     How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+
diff --git a/NumberTheory.cabal b/NumberTheory.cabal
new file mode 100644
--- /dev/null
+++ b/NumberTheory.cabal
@@ -0,0 +1,26 @@
+-- Initial NumberTheory.cabal generated by cabal init.  For further 
+-- documentation, see http://haskell.org/cabal/users-guide/
+
+name:                NumberTheory
+version:             0.1.0.0
+synopsis:            A library for number theoretic computations, written in Haskell.
+-- description:         
+license:             GPL-3
+license-file:        LICENSE
+author:              Chris Fredrickson
+maintainer:          chris.p.fredrickson@gmail.com
+-- copyright:           
+category:            Math
+build-type:          Simple
+cabal-version:       >=1.8
+
+library
+  exposed-modules:     NumberTheory
+  -- other-modules:       
+  build-depends:       base ==4.*, containers ==0.5.*, primes ==0.2.*
+  ghc-options:         -Wall
+
+Test-Suite NumberTheory_Tests
+  type:              exitcode-stdio-1.0
+  Main-Is:           NumberTheory_Tests.hs
+  build-depends:     base == 4.*, containers == 0.5.*, HUnit ==1.3.1.*, primes == 0.2.*
diff --git a/NumberTheory.hs b/NumberTheory.hs
new file mode 100644
--- /dev/null
+++ b/NumberTheory.hs
@@ -0,0 +1,677 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+-- |A library for doing number-theoretic computations. This includes computations
+-- in Z mod m (henceforth also written Zm), Z, Z x Zi (the Gaussian integers),
+-- and some computations with continued fractions.
+module NumberTheory (
+    -- pythagorean triples
+    pythSide,
+    pythLeg,
+    pythHyp,
+    primPythHyp,
+    primPythLeg,
+    -- Functions in Z mod m
+    canon,
+    evalPoly,
+    polyCong,
+    exponentiate,
+    rsaGenKeys,
+    rsaEval,
+    units,
+    nilpotents,
+    idempotents,
+    roots,
+    almostRoots,
+    order,
+    orders,
+    expressAsRoots,
+    powerCong,
+    ilogBM,
+    -- functions in Z
+    divisors,
+    factorize,
+    nonUnitFactorize,
+    primes,
+    isPrime,
+    areCoprime,
+    legendre,
+    kronecker,
+    -- arithmetic functions
+    totient,
+    tau,
+    sigma,
+    mobius,
+    littleOmega,
+    bigOmega,
+    -- Gaussian Integer functions
+    GaussInt((:+)),
+    real,
+    imag,
+    conjugate,
+    magnitude,
+    (.+),
+    (.-),
+    (.*),
+    (./),
+    (.%),
+    gIsPrime,
+    gPrimes,
+    gGCD,
+    gFindPrime,
+    gExponentiate,
+    gFactorize,
+    -- assorted combinatorics
+    factorial,
+    fibonacci,
+    permute,
+    choose,
+    enumerate,
+    asSumOfSquares,
+    -- Continued fraction functions
+    ContinuedFraction(Finite, Infinite),
+    continuedFractionFromDouble,
+    continuedFractionFromRational,
+    continuedFractionFromQuadratic,
+    continuedFractionToRational,
+    continuedFractionToFractional
+) where
+
+import           Data.List                      ((\\), elemIndex, genericLength, nub, sort)
+import qualified Data.Map             as Map    (fromListWith, toList)
+import           Data.Monoid
+import qualified Data.Numbers.Primes  as Primes (primes)
+import           Data.Ratio                     ((%), denominator, numerator, Ratio)
+import qualified Data.Set             as Set    (fromList, Set, size, toList)
+
+-- |The canonical representation of x in Z mod m.
+canon :: Integral a => a -> a -> a
+canon x m
+    | x < 0     = canon (x + m) m
+    | otherwise = x `mod` m
+
+-- square root of an integral value, for brevity elsewhere
+sqrti :: Integral a => a -> Double
+sqrti = (sqrt :: Double -> Double) . fromIntegral
+
+isIntegral :: Double -> Bool
+isIntegral x = (floor :: Double -> Integer) x == ceiling x
+
+-- |List all pythagorean triples that include a given length (either as a leg
+-- or hypotenuse).
+pythSide :: Integral a => a -> [(a, a, a)]
+pythSide s = sort $ pythLeg s ++ pythHyp s
+
+-- |List all pythagorean triples that include a given leg length.
+pythLeg :: Integral a => a -> [(a, a, a)]
+pythLeg leg = sort [ (k * a, k * b, k * c)
+                   | k <- divisors leg
+                   , (a, b, c) <- primPythLeg $ leg `quot` k
+                   ]
+
+-- |List all primitive pythagorean triples that include a given leg length.
+primPythLeg :: Integral a => a -> [(a, a, a)]
+primPythLeg leg = -- (a, b, c) = (m^2-n^2, 2mn, m^2+n^2) for some integers m, n
+    sort [ (a, b, c)
+         | (m, n) <- findMN
+         , let (a, b, c) = generatePythTriple m n
+         ]
+    where
+    findMN
+        | leg `mod` 2 == 0 =
+            [ (m, n)
+            | n <- divisors leg
+            , let m = quot leg (2 * n)
+            , areLegalParametersForPythTriple m n
+            ]
+        | otherwise =
+            [ (m, n)
+            | n <- [1 .. leg]
+            , let x = sqrti $ leg + n * n
+            , isIntegral x
+            , let m = floor x
+            , areLegalParametersForPythTriple m n
+            ]
+
+-- |List all pythagorean triples with a given hypotenuse.
+pythHyp :: Integral a => a -> [(a, a, a)]
+pythHyp hypotenuse = sort [ (k * a, k * b, k * c)
+                          | k <- divisors hypotenuse
+                          , (a, b, c) <- primPythHyp $ hypotenuse `quot` k
+                          ]
+
+-- |List all primitive pythagorean triples with a given hypotenuse.
+primPythHyp :: Integral a => a -> [(a, a, a)]
+primPythHyp hypotenuse =
+    sort [ (a, b, c)
+         | n <- [1 .. floor $ sqrti hypotenuse]
+         , let x = sqrti (hypotenuse - n * n)
+         , isIntegral x
+         , let m = floor x
+         , areLegalParametersForPythTriple m n
+         , let (a, b, c) = generatePythTriple m n
+         ]
+
+generatePythTriple :: Integral a => a -> a -> (a, a, a)
+generatePythTriple m n =
+        let a = m * m - n * n
+            b = 2 * m * n
+            c = m * m + n * n
+        in (a, b, c)
+
+areLegalParametersForPythTriple :: Integral a => a -> a -> Bool
+areLegalParametersForPythTriple m n =
+    0 < n &&
+    n < m &&
+    gcd m n == 1 && -- m and n must be coprime
+    even (m*n) -- exactly 1 of m and n is divisible by 2 (this test is sufficient since they are coprime)
+
+-- |List all divisors of n (not just proper divisors).
+divisors :: Integral a => a -> [a]
+divisors n
+    | n == 0    = []
+    | n == 1    = [1]
+    | n < 0     = divisors (-n)
+    | otherwise = let divisorPairs = [nub [x, quot n x] | x <- [2 .. limit], n `mod` x == 0]
+                      limit        = floor $ sqrti n
+                  in sort . ([1, n] ++) $ concat divisorPairs
+
+-- |List the prime factors of n, and their multiplicities.
+factorize :: (Integral a) => a -> [(a, a)]
+factorize n
+    | n == 0    = []
+    | n < 0     = (-1, 1) : nonUnitFactorize (-n)
+    | otherwise = (1, 1) : nonUnitFactorize n
+
+nonUnitFactorize :: (Integral a) => a -> [(a, a)]
+nonUnitFactorize n
+    | n == 0    = []
+    | n < 0     = nonUnitFactorize (-n)
+    | otherwise = let findFactors :: Integral a => a -> [a] -> [a]
+                      findFactors 1 acc = sort acc
+                      findFactors k acc =
+                          let d = head . tail $ divisors k
+                          in findFactors (quot k d) (d : acc)
+                  in collapseMultiplicities $ findFactors n []
+
+-- collapse a list of elements to (elt, multiplicity) pairs
+collapseMultiplicities :: (Ord a, Num b) => [a] -> [(a, b)]
+collapseMultiplicities list = Map.toList (Map.fromListWith (+) [(x, 1)| x <- list])
+
+-- | Compute Euler's phi. This is equal to the number of integers <= n that are
+-- relatively prime to n.
+totient :: Integral a => a -> a
+totient n
+    | n <  0    = totient (-n)
+    | n == 0    = 0
+    | n == 1    = 1
+    | otherwise = let primeList = primes n
+                      offset = n ^ (genericLength primeList - (1 :: Integer))
+                      diffList = map ((`subtract` n) . quot n) primeList
+                    in product diffList `quot` offset
+
+-- |List the unique prime factors of n.
+primes :: Integral a => a -> [a]
+primes = map fst . nonUnitFactorize
+
+
+-- |Compute if n is prime.
+isPrime :: Integral a => a -> Bool
+isPrime n = n `elem` takeWhile (<= n) (dropWhile (< n) Primes.primes)
+
+-- |Compute whether two integers are relatively prime to each other. That is, if
+-- their GCD == 1.
+areCoprime :: Integral a => a -> a -> Bool
+areCoprime = ((1 ==) .) . gcd
+
+-- |Evaluate a polynomial (in Zm) with given coefficients at a given point
+-- using Horner's method.
+evalPoly :: forall a. Integral a => a -> a -> [a] -> a
+evalPoly m x cs = evalPolyHelper . reverse $ map (`canon` m) cs
+    where
+    evalPolyHelper :: [a] -> a
+    evalPolyHelper []       = 0
+    evalPolyHelper [c]      = c `mod` m
+    evalPolyHelper (c : ct) = let val = evalPolyHelper ct
+                              in (val * x + c) `mod` m
+
+-- |Find the zeros to a given polynomial in Zm, where the coefficients are
+-- given in order of descending degree.
+polyCong :: Integral a => a -> [a] -> [a]
+polyCong m cs = filter (\x -> evalPoly m x cs == 0) [0 .. m - 1]
+
+-- |Raise a to the power of e in Zm.
+exponentiate :: (Integral a) => a -> a -> a -> a
+exponentiate a e m
+    | e < 0 && a `elem` us = exponentiate a (canon (ul + e) m) m
+    | e < 0                = error "a is not invertible in Z mod m"
+    | e == 0               = 1
+    | even e               = canon (s * s) m
+    | otherwise            = canon (q * a) m
+    where
+    s = exponentiate a (quot e 2) m
+    q = exponentiate a (e - 1) m
+    us = units m
+    ul = genericLength us
+
+-- |A type to represent a public or private key.
+type Key a = (a, a)
+-- |Given primes p and q, generate all pairs of public/private keys derived
+-- from those values.
+rsaGenKeys :: Integral a => a -> a -> [(Key a, Key a)]
+rsaGenKeys p q
+    | not (isPrime p && isPrime q) = error "p and q must both be prime"
+    | otherwise                    =
+        [ ((e, n), (d, n))
+        | let n = p * q
+              phi = totient n
+        , e <- filter (areCoprime phi) [2 .. phi - 1]
+        , d <- polyCong phi [e, -1]
+        ]
+
+-- |Use the given key to encode/decode the message or ciphertext.
+rsaEval :: (Integral a) => Key a -> a -> a
+rsaEval (k, n) text = exponentiate text k n
+
+-- |Compute the group of units of Zm.
+units :: Integral a => a -> [a]
+units n = filter (areCoprime n) [1 .. n - 1]
+
+-- |Compute the nilpotent elements of Zm.
+nilpotents :: (Integral a) => a -> [a]
+nilpotents m
+    | r == 0    = []
+    | otherwise = [ n
+                  | n <- [0 .. m - 1]
+                  , let powers = map (\e -> exponentiate n e m) [1 .. r]
+                  , 0 `elem` powers
+                  ]
+    where r = genericLength $ units m
+
+-- |Compute the idempotent elements of Zm.
+idempotents :: Integral a => a -> [a]
+idempotents = flip polyCong [1, -1, 0]
+
+-- |Compute the primitive roots of Zm.
+roots :: (Integral a) => a -> [a]
+roots m
+    | null us   = []
+    | otherwise = [ u | u <- us, order u m == genericLength us]
+    where us = units m
+
+-- |Compute the "almost roots" of Zm. An almost root is a unit, is not a
+-- primitive root, and generates the whole group of units when exponentiated.
+almostRoots :: forall a. (Integral a) => a -> [a]
+almostRoots m = let unitCount = genericLength $ units m
+                    expList = [1 .. unitCount + 1]
+                    generateUnits :: a -> Set.Set a
+                    generateUnits u = Set.fromList $ concat
+                                        [ [k, canon (-k) m]
+                                        | e <- expList
+                                        , let k = exponentiate u e m
+                                        ]
+                in sort [ u
+                        | u <- units m \\ roots m
+                        , unitCount == (fromIntegral . Set.size $ generateUnits u)
+                        ]
+
+-- |Compute the order of x in Zm.
+order :: (Integral a) => a -> a -> a
+order x m = head [ ord
+                 | ord <- [1 .. genericLength $ units m]
+                 , exponentiate (canon x m) ord m == 1
+                 ]
+
+-- |Computes the orders of all units in Zm.
+orders :: (Integral a) => a -> [a]
+orders m = map (`order` m) $ units m
+
+rootsOrAlmostRoots :: (Integral a) => a -> [a]
+rootsOrAlmostRoots m =
+    case roots m of
+        [] -> almostRoots m
+        rs -> rs
+
+-- |Find powers of all the primitive roots of Zm that are equal to x.
+-- Equivalently, express x as powers of roots (almost or primitive) in Zm.
+expressAsRoots :: (Integral a) => a -> a -> [(a, a)]
+expressAsRoots x m =
+    let rs = rootsOrAlmostRoots m
+    in  [ (r', e)
+        | r <- rs
+        , e <- [1 .. order r m]
+        , let k = exponentiate r e m
+        , r' <- [ r | k == x ]
+             ++ [ -r | canon (-k) m == x ]
+        ]
+
+-- |Solve the power congruence for x, given e, k, m: x^e = k (mod m)
+powerCong :: (Integral a) => a -> a -> a -> [a]
+powerCong e k m = [ x
+                  | x <- [1 .. m]
+                  , exponentiate x e m == canon k m
+                  ]
+
+-- |Compute the integer log base B of k in Zm.
+-- Equivalently, given 2 elements of Zm, find what powers of b produce k, if any.
+ilogBM :: (Integral a) => a -> a -> a -> [a]
+ilogBM b k m = let bc = canon b m
+                   kc = canon k m
+               in [ e
+                  | e <- [1 .. order bc m]
+                  , exponentiate bc e m == kc
+                  ]
+
+-- |Compute the Legendre symbol of p and q.
+legendre :: (Integral a) => a -> a -> a
+legendre q p
+    | not $ isPrime p = error "p is not prime"
+    | p == 2          = error "p must be odd"
+    | otherwise = let r = exponentiate q (quot (p - 1) 2) p
+                   in if r > 1 then (-1) else r
+
+-- |Compute the Kronecker symbol (a|n).
+kronecker :: (Integral a) => a -> a -> a
+kronecker a n
+    | n == (-1) && a < 0             = -1
+    | n == (-1)                      = 1
+    | n == 0 && abs a == 1           = 1
+    | n == 0                         = 0
+    | n == 1                         = 1
+    | n == 2 && even a               = 0
+    | n == 2 && abs (a `mod` 8) == 1 = 1
+    | n == 2                         = -1
+    | isPrime n                      = legendre a n
+    | otherwise                      = kronecker a u * product [ kronecker a p ^ e | (p, e) <- nonUnitFactorize n]
+    where u = if a < 0 then -1 else 1
+
+
+-- |Compute tau(n), the number of divisors of n.
+tau :: Integral a => a -> a
+tau = genericLength . divisors
+
+-- |Compute sigma(n), the sum of powers of divisors of n.
+sigma :: Integral a => a -> a -> a
+sigma k = sum . map (^ k) . divisors
+
+-- |Compute mobius(n): (-1)^littleOmega(n) if n is square-free, 0 otherwise.
+mobius :: (Integral a) => a -> a
+mobius n
+    | isSquareFree n = (-1) ^ littleOmega n
+    | otherwise      = 0
+    where
+    isSquareFree :: Integral a => a -> Bool
+    isSquareFree = all (odd . snd) . nonUnitFactorize
+
+-- |Compute littleOmega(n), the number of unique prime factors.
+littleOmega :: Integral a => a -> a
+littleOmega = genericLength . nonUnitFactorize
+
+-- |Compute bigOmega(n), the number of prime factors of n (including multiplicities).
+bigOmega :: Integral a => a -> a
+bigOmega = sum . map snd . nonUnitFactorize
+
+---------------------------------------------------------------------------------
+infix 6 :+
+-- |A Gaussian integer is a+bi, where a and b are both integers.
+data GaussInt a = a :+ a deriving (Ord, Eq)
+
+instance (Show a, Ord a, Num a) => Show (GaussInt a) where
+    show (a :+ b) = show a ++ op ++ b' ++ "i"
+        where op = if b > 0 then "+" else "-"
+              b' = if abs b /= 1 then show (abs b) else ""
+
+instance (Monoid a) => Monoid (GaussInt a) where
+    mempty = (mempty :: a) :+ (mempty :: a)
+    (c :+ d) `mappend` (e :+ f) = (c `mappend` e) :+ (d `mappend` f)
+
+-- |The real part of a Gaussian integer.
+real :: GaussInt a -> a
+real (x :+ _) = x
+
+-- |The imaginary part of a Gaussian integer.
+imag :: GaussInt a -> a
+imag (_ :+ y) = y
+
+-- |Conjugate a Gaussian integer.
+conjugate :: Num a => GaussInt a -> GaussInt a
+conjugate (r :+ i) = r :+ (-i)
+
+-- |The square of the magnitude of a Gaussian integer.
+magnitude :: Num a => GaussInt a -> a
+magnitude (x :+ y) = x * x + y * y
+
+-- |Add two Gaussian integers together.
+(.+) :: Num a => GaussInt a -> GaussInt a -> GaussInt a
+(gr :+ gi) .+ (hr :+ hi) = (gr + hr) :+ (gi + hi)
+
+-- |Subtract one Gaussian integer from another.
+(.-) :: Num a => GaussInt a -> GaussInt a -> GaussInt a
+(gr :+ gi) .- (hr :+ hi) = (gr - hr) :+ (gi - hi)
+
+-- |Multiply two Gaussian integers.
+(.*) :: Num a => GaussInt a -> GaussInt a -> GaussInt a
+(gr :+ gi) .* (hr :+ hi) = (gr * hr - hi * gi) :+ (gr * hi + gi * hr)
+
+-- "div" truncates toward -infinity, "quot" truncates toward 0, but we need
+-- something that truncates toward the nearest integer. I.e., we want to
+-- truncate with "round".
+divToNearest :: (Integral a, Integral b) => a -> a -> b
+divToNearest x y = round ((x % 1) / (y % 1))
+
+-- |Divide one Gaussian integer by another.
+(./) :: Integral a => GaussInt a -> GaussInt a -> GaussInt a
+g ./ h =
+    let nr :+ ni = g .* conjugate h
+        denom    = magnitude h
+    in divToNearest nr denom :+ divToNearest ni denom
+
+-- |Compute the remainder when dividing one Gaussian integer by another.
+(.%) :: Integral a => GaussInt a -> GaussInt a -> GaussInt a
+g .% m =
+    let q = g ./ m
+        p = m .* q
+    in g .- p
+
+-- |Compute whether a given Gaussian integer is prime.
+gIsPrime :: Integral a => GaussInt a -> Bool
+gIsPrime = isPrime . magnitude
+
+-- |An infinte list of the Gaussian primes. This list is in order of ascending magnitude.
+gPrimes :: Integral a => [GaussInt a]
+gPrimes = [ a' :+ b'
+            | mag <- Primes.primes
+            , let radius = floor $ sqrti mag
+            , a <- [0 .. radius]
+            , let y = sqrti $ mag - a*a
+            , isIntegral y
+            , let b = floor y
+            , a' <- [-a, a]
+            , b' <- [-b, b]
+            ]
+
+-- |Compute the GCD of two Gaussian integers.
+gGCD :: Integral a => GaussInt a -> GaussInt a -> GaussInt a
+gGCD g h
+    | h == 0 :+ 0 = g --done recursing
+    | otherwise = gGCD h (g .% h)
+
+-- |Find a Gaussian integer whose magnitude squared is the given prime number.
+gFindPrime :: (Integral a) => a -> [GaussInt a]
+gFindPrime 2 = [1 :+ 1]
+gFindPrime p
+    | p `mod` 4 == 1 && isPrime p =
+        let r = head $ roots p
+            z = exponentiate r (quot (p - 1) 4) p
+        in [gGCD (p :+ 0) (z :+ 1)]
+    | otherwise = []
+
+-- |Raise a Gaussian integer to a given power.
+gExponentiate :: (Integral a) => GaussInt a -> a -> GaussInt a
+gExponentiate a e
+    | e < 0     = error "Cannot exponentiate Gaussian Int to negative power"
+    | e == 0    = 1 :+ 0
+    | even e    = s .* s
+    | otherwise = a .* m
+    where
+    s = gExponentiate a (quot e 2)
+    m = gExponentiate a (e - 1)
+
+-- |Compute the prime factorization of a Gaussian integer. This is unique up to units (+/- 1, +/- i).
+gFactorize :: forall a. (Integral a) => GaussInt a -> [(GaussInt a, a)]
+gFactorize g
+    | g == 0 :+ 0   = [(0 :+ 0, 1)]
+    | otherwise     =
+    let nonUnits       = concatMap processPrime . nonUnitFactorize $ magnitude g
+        nonUnitProduct = foldr ((.*) . uncurry gExponentiate) (1 :+ 0) nonUnits
+        remainderUnit  = (g ./ nonUnitProduct, 1)
+    in remainderUnit : nonUnits
+    where
+    processPrime :: (a, a) -> [(GaussInt a, a)]
+    processPrime (p, e)
+        --deal with primes congruent to 3 (mod 4)
+        | p `mod` 4 == 3 = [(p :+ 0, quot e 2)]
+        --deal with all other primes
+        | otherwise      = collapseMultiplicities $ processGaussPrime g []
+        where
+        processGaussPrime :: GaussInt a -> [GaussInt a] -> [GaussInt a]
+        processGaussPrime g' acc = do
+            gp <- gFindPrime p -- find a GaussInt whose magnitude is p
+            let fs = filter (\f -> g' .% f == 0 :+ 0) [gp, conjugate gp] --find the list of even divisors
+            case fs of
+                [] -> acc                                                 -- Couldn't find a factor, so stop recursing
+                f : _ -> processGaussPrime (g' ./ f) (f : acc)    -- add this factor to the list, and keep looking
+
+---------------------------------------------------------------------------------
+--Combinatorics and other fun things
+
+-- |Compute the factorial of a given integer.
+factorial :: Integral a => a -> a
+factorial n = product [1 .. n]
+
+-- |The Fibonacci sequence.
+fibonacci :: Num a => [a]
+fibonacci = 0 : 1 : zipWith (+) fibonacci (tail fibonacci)
+
+-- |Given a set of n elements, compute the number of ways to arrange k elements of it.
+permute :: Integral a => a -> a -> a
+permute n k = factorial n `quot` factorial (n - k)
+
+-- |Given a set of n elements, compute the number of ways to choose r elements of it.
+choose :: Integral a => a -> a -> a
+choose n r = (n `permute` r) `quot` factorial r
+
+-- |Given a list of spots, where each spot is a list of its possible values,
+-- enumerate all possible assignments of values to spots.
+enumerate :: [[a]] -> [[a]]
+enumerate []     = [[]]
+enumerate (c:cs) = [ a : as
+                   | a <- c
+                   , as <- enumerate cs
+                   ]
+
+-- |Given an integer n, find all ways of expressing n as the sum of two squares.
+asSumOfSquares :: Integral a => a -> [(a, a)]
+asSumOfSquares n = Set.toList . Set.fromList $
+                     [ (x', y')
+                     | x <- [1 .. floor $ sqrti n]
+                     , let d = n - x * x
+                     , d > 0
+                     , let sd = sqrti d
+                     , isIntegral sd
+                     , let y = floor sd
+                           [x', y'] = sort [x, y]
+                     ]
+
+---------------------------------------------------------------------------------
+-- Continued fractions
+
+-- |A (simple) continued fraction can be represented as a list of coefficients.
+-- This list is either finite (in the case of rational numbers), or infinite (in
+-- the case of irrational numbers. If the fraction represents a quadratic number
+-- (that is, a number that can be the root of some quadratic polynomial), then
+-- the infinite list of coefficients consists of a finite sequence of coefficients
+-- followed by a (finite) sequence of coefficients that repeats indefinitely.
+data ContinuedFraction a = Finite [a] | Infinite ([a], [a])
+
+instance (Show a) => Show (ContinuedFraction a) where
+    show (Finite as) = "Finite " ++ show as
+    show (Infinite (as, ps)) = "Infinite " ++ show as ++ show ps ++ "..."
+
+-- |Convert a Double to a (finite) continued fraction. This is inherently lossy.
+continuedFractionFromDouble :: forall a. (Integral a) => Double -> a -> ContinuedFraction a
+continuedFractionFromDouble x precision
+    | precision < 1 = Finite []
+    | otherwise     =
+        let ts = getTs (fractionalPart x) precision
+        in Finite $ integralPart x : map (integralPart . recip) (filter (/= 0) ts)
+    where
+    integralPart :: Double -> a
+    integralPart n = fst $ (properFraction :: Double -> (a, Double)) n
+    fractionalPart :: Double -> Double
+    fractionalPart 0 = 0
+    fractionalPart n = snd $ (properFraction :: Double -> (Integer, Double)) n
+    getTs :: Integral a => Double -> a -> [Double]
+    getTs y n = reverse $ tRunner [y] n
+        where
+        tRunner [] _ = error "improper call of tRunner. This should never happen."
+        tRunner ts 0 = ts
+        tRunner ts@(t : _) m
+            | tn == 0   = ts
+            | otherwise = tRunner (tn : ts) (m - 1)
+            where tn = fractionalPart $ recip t
+
+-- |Convert the quadratic number (m0 + sqrt(d)) / q0 to its continued fraction
+-- representation.
+continuedFractionFromQuadratic :: forall a. (Integral a) => a -> a -> a -> ContinuedFraction a
+continuedFractionFromQuadratic m0 d q0
+    | q0 == 0                           = error "Cannot divide by 0"
+    | isIntegral $ sqrti d              = continuedFractionFromRational ((m0 + (floor . sqrti $ d)) % q0)
+    | not . isIntegral $ getNextQ m0 q0 = continuedFractionFromQuadratic (m0 * q0) (d * q0 * q0) (q0 * q0)
+    | otherwise                         =
+        let a0 = truncate $ (fromIntegral m0 + sqrti d) / fromIntegral q0
+        in helper [(m0, q0, a0)]
+    where
+    helper :: [(a, a, a)] -> ContinuedFraction a
+    helper [] = error "improper call to helper function. This will never happen."
+    helper ts@((mp, qp, ap) : _) =
+        let mn = ap * qp - mp
+            qn = (truncate :: Double -> a) $ getNextQ mn qp
+            an = truncate ((fromIntegral mn + sqrti d) / fromIntegral qn)
+            ts' = reverse ts
+            as' = map third ts'
+        in case elemIndex (mn, qn, an) ts' of
+            -- We've hit the first repetition of the period
+            Just idx -> Infinite (take idx as', drop idx as')
+            -- Haven't hit the end of the period yet, keep going as usual
+            Nothing  -> helper $ (mn, qn, an) : ts
+    getNextQ :: a -> a -> Double
+    getNextQ mp qp = fromIntegral (d - mp * mp) / fromIntegral qp
+    third :: (a, b, c) -> c
+    third (_, _, x) = x
+
+-- |Convert a continued fraction to a rational number. If the fraction is finite,
+-- then this is an exact conversion. If the fraction is infinite, this conversion
+-- is necessarily lossy, since the fraction does not represent a rational number.
+continuedFractionToRational :: (Integral a) => ContinuedFraction a -> Ratio a
+continuedFractionToRational frac =
+    let list = case frac of
+            Finite as              -> as
+            Infinite (as, periods) -> as ++ take 35 (cycle periods)
+    in foldr (\ai rat -> (ai % 1) + (1 / rat)) (last list % 1) (init list)
+
+-- |Convert a rational number to a continued fraction. This is an exact conversion.
+continuedFractionFromRational :: Integral a => Ratio a -> ContinuedFraction a
+continuedFractionFromRational rat
+    | denominator rat == 1    = Finite [numerator rat]
+    | numerator fracPart == 1 = Finite [intPart, denominator fracPart]
+    | otherwise               =
+        let Finite trail = continuedFractionFromRational (1 / fracPart)
+        in Finite (intPart : trail)
+    where
+    intPart = numerator rat `div` denominator rat
+    fracPart = rat - (intPart % 1)
+
+-- |Convert a continued fraction to a Fractional type. This is lossy due to
+-- precision in the Fractional type, and due to conversion of irrational continued
+-- fractions to rational types.
+continuedFractionToFractional :: (Fractional a) => ContinuedFraction Integer -> a
+continuedFractionToFractional = fromRational . continuedFractionToRational
diff --git a/NumberTheory_Tests.hs b/NumberTheory_Tests.hs
new file mode 100644
--- /dev/null
+++ b/NumberTheory_Tests.hs
@@ -0,0 +1,225 @@
+module Main where
+
+import Data.List
+import qualified Data.Numbers.Primes as Primes
+import NumberTheory
+import Test.HUnit
+
+main :: IO Counts
+main = runTestTT tests
+
+tests :: Test
+tests = TestList
+    [ TestLabel "Continued Fraction Tests" continuedFractionTests
+    , TestLabel "Pythagorean Triples Tests" pythTests
+    , TestLabel "Z mod M Tests" zModMTests
+    , TestLabel "Z Tests" zTests
+    , TestLabel "Arithmetic Functions tests" arithmeticFnsTests
+    , TestLabel "Gaussian Integer Tests" gaussianIntTests
+    ]
+
+limit :: [a] -> [a]
+limit = take 20000
+--limit = id
+
+pythTests :: Test
+pythTests = TestList
+    [ TestCase $ assertEqual "test pythSide" [(35, 12, 37),(37, 684, 685)] (pythSide (37 :: Int))
+    , TestCase $ assertEqual "test pythLeg" [(15, 8, 17),(15, 20, 25),(15, 36, 39),(15, 112, 113)] (pythLeg (15 :: Int))
+    , TestCase $ assertEqual "test pythHyp" [(7, 24, 25),(15, 20, 25)] (pythHyp (25 :: Int))
+    ]
+
+-- Note: don't use any functions from NumberTheory to define these (e.g. isPrime).
+sampleMixed :: [Integer]
+sampleMixed = [1 .. 100]
+samplePrimes :: [Integer]
+samplePrimes = takeWhile (<= last sampleMixed) Primes.primes
+sampleComposites :: [Integer]
+sampleComposites = filter (not . flip elem samplePrimes) sampleMixed
+sampleMixedGaussInts :: [GaussInt Integer]
+sampleMixedGaussInts = [a :+ b | a <- [-25 .. 25], b <- [-25 .. 25]]
+
+zTests :: Test
+zTests = TestList
+    [ TestList $ limit [ TestCase $ assertEqual "divisors divide evenly" 0 remainder
+                | n <- sampleMixed
+                , let divs = divisors n
+                , d <- divs
+                , let remainder = n `mod` d
+                ]
+    , TestList $ limit [ TestCase $ assertEqual "primes are only divisible by themselves and 1" [1, p] divs
+                | p <- samplePrimes
+                , let divs = divisors p
+                ]
+    , TestList $ limit [ TestCase $ assertBool "each divisor has a mate to produce n" found
+                | n <- sampleMixed
+                , let divs = divisors n
+                , d <- divs
+                , let found = any (\d' -> d * d' == n) divs
+                ]
+    , TestList $ limit [ TestCase $ assertEqual "product of factors from factorize is original" n prod
+                | n <- sampleMixed
+                , let facs = (factorize :: Integer -> [(Integer, Integer)]) n
+                , let prod = product $ map (uncurry (^)) facs
+                ]
+    , TestList $ limit [ TestCase $ assertEqual "test primes on primes" [p] ps
+                | p <- samplePrimes
+                , let ps = primes p
+                ]
+    , TestList $ limit [ TestCase $ assertBool "test primes on composites" res
+                | n <- sampleMixed
+                , let res = all isPrime $ primes n
+                ]
+    , TestList $ limit [ TestCase $ assertBool "test isPrime on primes" (isPrime p)
+                | p <- samplePrimes
+                ]
+    , TestList $ limit [ TestCase $ assertBool "test isPrime on composites" (not $ isPrime n)
+                | n <- sampleComposites
+                ]
+    , TestList $ limit [ TestCase $ assertBool "test areCoprime on common multiples" res
+                | x <- [1 .. 10] :: [Integer]
+                , let res = not $ areCoprime 5 (5 * x)
+                ]
+    , TestList $ limit [ TestCase $ assertBool "test areCoprime on primes" res
+                | p <- delete 3 samplePrimes
+                , let res = areCoprime 3 p
+                ]
+    ]
+
+zModMTests :: Test
+zModMTests = TestList
+    [ TestList $ limit [ TestCase $ assertBool
+                    ("test canon bounds: " ++ show n ++ " mod " ++ show m)
+                    (n' >= 0 && n' < m && n `mod` m == n')
+                    | m <- sampleMixed
+                    , n <- sampleMixed ++ map negate sampleMixed
+                    , let n' = canon n m
+                ]
+    , TestCase $ assertEqual "test evalPoly" 2 (evalPoly 5 3 [4, 5, 6 :: Integer])
+    , TestCase $ assertEqual "test polyCong" [1, 4] (polyCong 5 [4, 5, 6 :: Integer])
+    , TestCase $ assertEqual "test exponentiate" 3 (exponentiate 9 12 (6 :: Integer))
+    , TestCase $ assertEqual "test exponentiate negative" 3 (exponentiate (-9) 12 (6 :: Integer))
+    , TestList $ limit [ TestCase $ assertEqual ("test inverses with exponentiation (" ++ show x ++ "^" ++ show e ++ " mod " ++ show n ++ ")") 1 p
+                | n <- sampleMixed
+                , let us = units n
+                , u <- us
+                , e <- [1 .. genericLength us]
+                , let x = exponentiate u e n
+                , let y = exponentiate u (-e) n
+                , let p = canon (x * y) n
+                ]
+    , TestList $ limit [ TestCase $ assertBool "test rsaGenKeys (ed == 1 mod phi(n))" (canon (privk * pubk) (totient n) == (1 :: Integer) && n == n')
+                | p <- samplePrimes
+                , q <- delete p samplePrimes
+                , let keys = rsaGenKeys p q
+                , ((pubk, n), (privk, n')) <- keys
+                ]
+    , TestList $ limit [ TestCase $ assertEqual "test rsaGenKeys (inverses)" text plain
+                | text <- sampleMixed
+                , p <- samplePrimes
+                , q <- delete p samplePrimes
+                , let keys = rsaGenKeys p q
+                , (pub, priv) <- keys
+                , let cipher = rsaEval pub text
+                , let plain = rsaEval priv cipher
+                ]
+    , TestList $ limit [ TestCase $ assertBool
+                    ("test units invertibility: " ++ show n)
+                    (all (\u -> any (\u' -> canon (u * u') n == 1) us) us)
+                | n <- sampleMixed
+                , let us = units n
+                ]
+    , TestList $ limit [ TestCase $ assertBool
+                    ("test nilpotents: " ++ show n)
+                    (all (\xs ->  0 `elem` xs) iteratedLists)
+                | n <- sampleMixed
+                , let ns = map fromIntegral $ nilpotents n
+                , let iteratedLists = map (\x -> take (fromIntegral n) $ iterate (\l -> canon (l * x) n) x) ns
+                ]
+    , TestList $ limit [ TestCase $ assertBool
+                    ("test idempotents: " ++ show n)
+                    (all (\i -> canon (i * i) n == i) is)
+                | n <- sampleMixed
+                , let is = idempotents n
+                ]
+    , TestCase $ assertEqual "test roots" [3, 5, 6, 7, 10, 11, 12, 14] (roots (17 :: Integer))
+    , TestCase $ assertEqual "test almostRoots" [2, 7, 8, 13] (almostRoots (15 :: Integer))
+    , TestCase $ assertEqual "test orders" [1, 4, 2, 4, 4, 2, 4, 2] (orders (15 :: Integer))
+    , TestCase $ assertEqual "test expressAsRoots" [(-2, 1), (7, 3), (-8, 3), (13, 1)] (expressAsRoots 13 (15 :: Integer))
+    , TestCase $ assertEqual "test powerCong" [2] (powerCong 11 3 (5 :: Integer))
+    ]
+
+arithmeticFnsTests :: Test
+arithmeticFnsTests = TestList
+    [ TestList $ limit [ TestCase $ assertEqual "totient counts number of coprimes <=n" c c'
+                | n <- sampleMixed
+                , let c = totient n
+                , let c' = genericLength $ filter (areCoprime n) [1 .. n]
+                ]
+    , TestCase $ assertEqual "legendre 3 5" (-1 :: Integer) (legendre 3 5)
+    , TestCase $ assertEqual "kronecker 6 5" (1 :: Integer) (kronecker 6 5)
+    , TestCase $ assertEqual "tau 60" (12 :: Integer) (tau 60)
+    , TestCase $ assertEqual "sigma 1 60" (168 :: Integer) (sigma 1 60)
+    , TestCase $ assertEqual "sigma 4 60" (14013636 :: Integer) (sigma 4 60)
+    , TestCase $ assertEqual "mobius 9 (non-squarefree)" (0 :: Integer) (mobius 9)
+    , TestCase $ assertEqual "mobius 5" (-1 :: Integer) (mobius 5)
+    , TestCase $ assertEqual "littleOmega 60" (3 :: Integer) (littleOmega 60)
+    , TestCase $ assertEqual "bigOmega 60" (4 :: Integer) (bigOmega 60)
+    ]
+
+gaussianIntTests :: Test
+gaussianIntTests = TestList
+    [ TestList $ limit [ TestCase $ assertEqual "conjugate with 0i" g g'
+                | n <- sampleMixed
+                , let g = n :+ 0
+                , let g' = conjugate g
+                ]
+    , TestList $ limit [ TestCase $ assertEqual "conjugate mixed ints" (a :+ b) (a' :+ (-b'))
+                | g@(a :+ b) <- sampleMixedGaussInts
+                , let (a' :+ b') = conjugate g
+                ]
+    , TestCase $ assertEqual "Gaussian int multiplication" ((2 :: Integer) :+ 42) ((5 :+ 3) .* (4 :+ 6))
+    , TestCase $ assertEqual "Gaussian div on even division" ((4 :: Integer) :+ 6) ((2 :+ 42) ./ (5 :+ 3))
+    , TestCase $ assertEqual "Gaussian div on uneven division" ((4 :: Integer) :+ 6) ((2 :+ 43) ./ (5 :+ 3))
+    , TestCase $ assertEqual "Gaussian div on negative divisor" ((4 :: Integer) :+ 6) (((-2) :+ (-43)) ./ ((-5) :+ (-3)))
+    , TestCase $ assertEqual "Gaussian mod on positive case" ((0 :: Integer) :+ 1) ((2 :+ 43) .% (5 :+ 3))
+    , TestCase $ assertEqual "Gaussian mod on negative case" ((0 :: Integer) :+ (-1)) (((-2) :+ (-43)) .% (5 :+ 3))
+    , TestCase $ assertEqual "magnitude on integer case" (25 :: Integer) (magnitude (5 :+ 0))
+    , TestCase $ assertEqual "magnitude on 5 :+ 3" (34 :: Integer) (magnitude (5 :+ 3))
+    , TestCase $ assertBool "gIsPrime on prime" (gIsPrime ((2 :: Integer) :+ 5))
+    , TestCase $ assertBool "gIsPrime on composite" (not $ gIsPrime ((3 :: Integer) :+ 5))
+    , TestList $ limit [ TestCase $ assertBool "gPrimes generates primes" (gIsPrime p)
+                | p <- take 100 (gPrimes :: [GaussInt Integer])
+                ]
+    , TestCase $ assertEqual "gGCD on even multiple" ((2 :: Integer) :+ 4) (gGCD (2 :+ 4) (12 :+ 24))
+    , TestCase $ assertEqual "gGCD on uneven multiple" ((1 :: Integer) :+ 1) (gGCD (2 :+ 4) (5 :+ 3))
+    , TestCase $ assertBool "gGCD on uneven multiple (division rounding test)"
+            (gGCD ((12::Int) :+ 23) (23 :+ 34) `elem` [x :+ y | x <- [(-1)..1], y <- [(-1)..1], abs x + abs y == 1])
+    , TestCase $ assertBool "gFindPrime 5" (head (gFindPrime (5::Int)) `elem` [ a :+ b | a <- [2, -2], b <- [1, -1]])
+    , TestCase $ assertEqual "gFindPrime 7" [] (gFindPrime (7::Int))
+    , TestList $ limit [ TestCase $ assertEqual "gExponentiate on real ints" ((a ^ pow) :+ 0) (gExponentiate g pow)
+                | a <- sampleMixed
+                , pow <- [1 .. 5] :: [Integer]
+                , let g = a :+ 0
+                ]
+    , TestCase $ assertEqual "gExponentiate on 1st complex int" ((-119 :: Integer) :+ (-120)) (gExponentiate (2 :+ 3) (4 :: Integer))
+    , TestCase $ assertEqual "gExponentiate on 2nd complex int" ((122 :: Integer) :+ (-597)) (gExponentiate (2 :+ 3) (5 :: Integer))
+    , TestList $ limit [ TestCase $ assertEqual "gFactorize, gMultiply, gExponentiate recover original GaussInt"
+                        g prod
+                | g <- sampleMixedGaussInts
+                , let factors = gFactorize g
+                , let condensedFactors = map (uncurry gExponentiate) factors
+                , let prod = foldl (.*) (1 :+ 0) condensedFactors
+                ]
+    ]
+
+continuedFractionTests :: Test
+continuedFractionTests = TestList
+    [ TestCase $ assertBool ("Test conversion to and from continued fraction: (" ++ show m ++ "+ sqrt(" ++ show d ++ "))/" ++ show q)
+       (abs (((fromIntegral m + (sqrt :: Double -> Double) (fromIntegral d)) / fromIntegral q) -
+        (fromRational . continuedFractionToRational $ continuedFractionFromQuadratic m d q))
+        < 0.00000000000001)
+    | m <- [0 .. 20]
+    , d <- [0 .. 20]
+    , q <- [1 .. 20]
+    ]
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
