quaternion/0000755000076500000240000000000012505453300012242 5ustar lukasstaffquaternion/COPYING0000644000076500000240000010451312505453300013301 0ustar lukasstaff GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . quaternion/DESCRIPTION0000644000076500000240000000054312505453357013766 0ustar lukasstaffName: quaternion Version: 2.4.0 Date: 2015-03-21 Author: Lukas Reichlin Maintainer: Lukas Reichlin Title: Quaternion Description: Quaternion package for GNU Octave, includes a quaternion class with overloaded operators Depends: octave (>= 3.8.0) Autoload: no License: GPLv3+ Url: http://octave.sf.net quaternion/doc/0000755000076500000240000000000012505453300013007 5ustar lukasstaffquaternion/doc/functions.texi0000644000076500000240000006115612505453300015723 0ustar lukasstaff@chapter Quaternion Constructors @section quaternion @findex quaternion @deftypefn {Function File} {@var{q} =} quaternion (@var{w}) @deftypefnx {Function File} {@var{q} =} quaternion (@var{x}, @var{y}, @var{z}) @deftypefnx {Function File} {@var{q} =} quaternion (@var{w}, @var{x}, @var{y}, @var{z}) Constructor for quaternions - create or convert to quaternion. @example q = w + x*i + y*j + z*k @end example Arguments @var{w}, @var{x}, @var{y} and @var{z} can be scalars, matrices or n-dimensional arrays, but they must be real-valued and of equal size. If scalar part @var{w} or components @var{x}, @var{y} and @var{z} of the vector part are not specified, zero matrices of appropriate size are assumed. @strong{Example} @example @group octave:1> q = quaternion (2) q = 2 + 0i + 0j + 0k octave:2> q = quaternion (3, 4, 5) q = 0 + 3i + 4j + 5k octave:3> q = quaternion (2, 3, 4, 5) q = 2 + 3i + 4j + 5k @end group @end example @example @group octave:4> w = [2, 6, 10; 14, 18, 22]; octave:5> x = [3, 7, 11; 15, 19, 23]; octave:6> y = [4, 8, 12; 16, 20, 24]; octave:7> z = [5, 9, 13; 17, 21, 25]; octave:8> q = quaternion (w, x, y, z) q.w = 2 6 10 14 18 22 q.x = 3 7 11 15 19 23 q.y = 4 8 12 16 20 24 q.z = 5 9 13 17 21 25 octave:9> @end group @end example @end deftypefn @section qi @findex qi @deftypefn {Function File} {} qi Create x-component of a quaternion's vector part. @example q = w + x*qi + y*qj + z*qk @end example @strong{Example} @example @group octave:1> q1 = quaternion (1, 2, 3, 4) q1 = 1 + 2i + 3j + 4k octave:2> q2 = 1 + 2*qi + 3*qj + 4*qk q2 = 1 + 2i + 3j + 4k octave:3> @end group @end example @end deftypefn @section qj @findex qj @deftypefn {Function File} {} qj Create y-component of a quaternion's vector part. @example q = w + x*qi + y*qj + z*qk @end example @strong{Example} @example @group octave:1> q1 = quaternion (1, 2, 3, 4) q1 = 1 + 2i + 3j + 4k octave:2> q2 = 1 + 2*qi + 3*qj + 4*qk q2 = 1 + 2i + 3j + 4k octave:3> @end group @end example @end deftypefn @section qk @findex qk @deftypefn {Function File} {} qk Create z-component of a quaternion's vector part. @example q = w + x*qi + y*qj + z*qk @end example @strong{Example} @example @group octave:1> q1 = quaternion (1, 2, 3, 4) q1 = 1 + 2i + 3j + 4k octave:2> q2 = 1 + 2*qi + 3*qj + 4*qk q2 = 1 + 2i + 3j + 4k octave:3> @end group @end example @end deftypefn @chapter Conversions @section q2rot @findex q2rot @deftypefn {Function File} {[@var{axis}, @var{angle}] =} q2rot (@var{q}) @deftypefnx {Function File} {[@var{axis}, @var{angle}, @var{qn}] =} q2rot (@var{q}) Extract vector/angle form of a unit quaternion @var{q}. @strong{Inputs} @table @var @item q Unit quaternion describing the rotation. Quaternion @var{q} can be a scalar or an array. In the latter case, @var{q} is reshaped to a row vector and the return values @var{axis} and @var{angle} are concatenated horizontally, accordingly. @end table @strong{Outputs} @table @var @item axis Eigenaxis as a 3-d unit vector @code{[x; y; z]}. If input argument @var{q} is a quaternion array, @var{axis} becomes a matrix where @var{axis(:,i)} corresponds to @var{q(i)}. @item angle Rotation angle in radians. The positive direction is determined by the right-hand rule applied to @var{axis}. The angle lies in the interval [0, 2*pi]. If input argument @var{q} is a quaternion array, @var{angle} becomes a row vector where @var{angle(i)} corresponds to @var{q(i)}. @item qn Optional output of diagnostic nature. @code{qn = reshape (q, 1, [])} or, if needed, @code{qn = reshape (unit (q), 1, [])}. @end table @strong{Example} @example @group octave:1> axis = [0; 0; 1] axis = 0 0 1 octave:2> angle = pi/4 angle = 0.78540 octave:3> q = rot2q (axis, angle) q = 0.9239 + 0i + 0j + 0.3827k octave:4> [vv, th] = q2rot (q) vv = 0 0 1 th = 0.78540 octave:5> theta = th*180/pi theta = 45.000 octave:6> @end group @end example @end deftypefn @section rot2q @findex rot2q @deftypefn {Function File} {@var{q} =} rot2q (@var{axis}, @var{angle}) Create unit quaternion @var{q} which describes a rotation of @var{angle} radians about the vector @var{axis}. This function uses the active convention where the vector @var{axis} is rotated by @var{angle} radians. If the coordinate frame should be rotated by @var{angle} radians, also called the passive convention, this is equivalent to rotating the @var{axis} by @var{-angle} radians. @strong{Inputs} @table @var @item axis Vector @code{[x, y, z]} or @code{[x; y; z]} describing the axis of rotation. @item angle Rotation angle in radians. The positive direction is determined by the right-hand rule applied to @var{axis}. If @var{angle} is a real-valued array, a quaternion array @var{q} of the same size is returned. @end table @strong{Outputs} @table @var @item q Unit quaternion describing the rotation. If @var{angle} is an array, @var{q(i,j)} corresponds to the rotation angle @var{angle(i,j)}. @end table @strong{Example} @example @group octave:1> axis = [0, 0, 1]; octave:2> angle = pi/4; octave:3> q = rot2q (axis, angle) q = 0.9239 + 0i + 0j + 0.3827k octave:4> v = quaternion (1, 1, 0) v = 0 + 1i + 1j + 0k octave:5> vr = q * v * conj (q) vr = 0 + 0i + 1.414j + 0k octave:6> @end group @end example @end deftypefn @section rotm2q @findex rotm2q @deftypefn {Function File} {@var{q} =} rotm2q (@var{R}) Convert 3x3 rotation matrix @var{R} to unit quaternion @var{q}. @end deftypefn @chapter Quaternion Methods @section @@quaternion/abs @findex abs @deftypefn {Function File} {@var{qabs} =} abs (@var{q}) Modulus of a quaternion. @example q = w + x*i + y*j + z*k abs (q) = sqrt (w.^2 + x.^2 + y.^2 + z.^2) @end example @end deftypefn @section @@quaternion/arg @findex arg @deftypefn {Function File} {@var{theta} =} arg (@var{q}) Compute the argument or phase of quaternion @var{q} in radians. @var{theta} is defined as @code{atan2 (sqrt (q.x.^2 + q.y.^2 + q.z.^2), q.w)}. The argument @var{theta} lies in the range (0, pi). @end deftypefn @section @@quaternion/blkdiag @findex blkdiag @deftypefn {Function File} {@var{q} =} blkdiag (@var{q1}, @var{q2}, @dots{}) Block-diagonal concatenation of quaternions. @end deftypefn @section @@quaternion/cast @findex cast @deftypefn {Function File} {@var{q} =} cast (@var{q}, @var{'type'}) Convert the components of quaternion @var{q} to data type @var{type}. Valid types are int8, uint8, int16, uint16, int32, uint32, int64, uint64, double, single and logical. @end deftypefn @section @@quaternion/cat @findex cat @deftypefn {Function File} {@var{q} =} cat (@var{dim}, @var{q1}, @var{q2}, @dots{}) Concatenation of quaternions along dimension @var{dim}. @end deftypefn @section @@quaternion/ceil @findex ceil @deftypefn {Function File} {@var{q} =} ceil (@var{q}) Round quaternion @var{q} towards positive infinity. @end deftypefn @section @@quaternion/columns @findex columns @deftypefn {Function File} {@var{nc} =} columns (@var{q}) Return number of columns @var{nc} of quaternion array @var{q}. @end deftypefn @section @@quaternion/conj @findex conj @deftypefn {Function File} {@var{q} =} conj (@var{q}) Return conjugate of a quaternion. @example q = w + x*i + y*j + z*k conj (q) = w - x*i - y*j - z*k @end example @end deftypefn @section @@quaternion/cumsum @findex cumsum @deftypefn {Function File} {@var{q} =} cumsum (@var{q}) @deftypefnx {Function File} {@var{q} =} cumsum (@var{q}, @var{dim}) @deftypefnx {Function File} {@var{q} =} cumsum (@dots{}, @var{'native'}) @deftypefnx {Function File} {@var{q} =} cumsum (@dots{}, @var{'double'}) @deftypefnx {Function File} {@var{q} =} cumsum (@dots{}, @var{'extra'}) Cumulative sum of elements along dimension @var{dim}. If @var{dim} is omitted, it defaults to the first non-singleton dimension. See @code{help cumsum} for more information. @end deftypefn @section @@quaternion/diag @findex diag @deftypefn {Function File} {@var{q} =} diag (@var{v}) @deftypefnx {Function File} {@var{q} =} diag (@var{v}, @var{k}) Return a diagonal quaternion matrix with quaternion vector V on diagonal K. The second argument is optional. If it is positive, the vector is placed on the K-th super-diagonal. If it is negative, it is placed on the -K-th sub-diagonal. The default value of K is 0, and the vector is placed on the main diagonal. Given a matrix argument, instead of a vector, @command{diag} extracts the @var{K}-th diagonal of the matrix. @end deftypefn @section @@quaternion/diff @findex diff @deftypefn {Function File} {@var{qdot} =} diff (@var{q}, @var{omega}) Derivative of a quaternion. Let Q be a quaternion to transform a vector from a fixed frame to a rotating frame. If the rotating frame is rotating about the [x, y, z] axes at angular rates [wx, wy, wz], then the derivative of Q is given by @example Q' = diff(Q, omega) @end example If the passive convention is used (rotate the frame, not the vector), then @example Q' = diff(Q,-omega) @end example @end deftypefn @section @@quaternion/exp @findex exp @deftypefn {Function File} {@var{qexp} =} exp (@var{q}) Exponential of a quaternion. @end deftypefn @section @@quaternion/fix @findex fix @deftypefn {Function File} {@var{q} =} fix (@var{q}) Round quaternion @var{q} towards zero. @end deftypefn @section @@quaternion/floor @findex floor @deftypefn {Function File} {@var{q} =} floor (@var{q}) Round quaternion @var{q} towards negative infinity. @end deftypefn @section @@quaternion/full @findex full @deftypefn {Function File} {@var{fq} =} full (@var{sq}) Return a full storage quaternion representation @var{fq} from sparse or diagonal quaternion @var{sq}. @end deftypefn @section @@quaternion/get @findex get @deftypefn {Function File} {} get (@var{q}) @deftypefnx {Function File} {@var{value} =} get (@var{q}, @var{"key"}) @deftypefnx {Function File} {[@var{val1}, @var{val2}, @dots{}] =} get (@var{q}, @var{"key1"}, @var{"key2"}, @dots{}) Access key values of quaternion objects. @strong{Keys} @table @var @item w Return scalar part @var{w} of quaternion @var{q} as a built-in type. @item x, y, z Return component @var{x}, @var{y} or @var{z} of the vector part of quaternion @var{q} as a built-in type. @item s Return scalar part of quaternion @var{q}. The vector part of @var{q} is set to zero. @item v Return vector part of quaternion @var{q}. The scalar part of @var{q} is set to zero. @end table @end deftypefn @section @@quaternion/inv @findex inv @deftypefn {Function File} {@var{qinv} =} inv (@var{q}) Return inverse of a quaternion. @end deftypefn @section @@quaternion/isempty @findex isempty @deftypefn {Function File} {@var{bool} =} isempty (@var{q}) Return true if quaternion @var{q} is empty and false otherwise. @end deftypefn @section @@quaternion/isfinite @findex isfinite @deftypefn {Function File} {@var{bool} =} isfinite (@var{q}) Return a logical array which is true where the elements of @var{q} are finite values and false where they are not. @end deftypefn @section @@quaternion/isinf @findex isinf @deftypefn {Function File} {@var{bool} =} isinf (@var{q}) Return a logical array which is true where the elements of @var{q} are infinite and false where they are not. @end deftypefn @section @@quaternion/isnan @findex isnan @deftypefn {Function File} {@var{bool} =} isnan (@var{q}) Return a logical array which is true where the elements of @var{q} are NaN values and false where they are not. @end deftypefn @section @@quaternion/ispure @findex ispure @deftypefn {Function File} {@var{bool} =} ispure (@var{q}) Return true if scalar part of quaternion is zero, otherwise return false. @end deftypefn @section @@quaternion/isreal @findex isreal @deftypefn {Function File} {@var{bool} =} isreal (@var{q}) Return true if the vector part of quaternion @var{q} is zero and false otherwise. @end deftypefn @section @@quaternion/length @findex length @deftypefn {Function File} {@var{l} =} length (@var{q}) Return the "length" @var{l} of the quaternion array @var{q}. For quaternion matrices, the length is the number of rows or columns, whichever is greater (this odd definition is used for compatibility with @acronym{MATLAB}). @end deftypefn @section @@quaternion/log @findex log @deftypefn {Function File} {@var{qlog} =} log (@var{q}) Logarithmus naturalis of a quaternion. @end deftypefn @section @@quaternion/mean @findex mean @deftypefn {Function File} {@var{q} =} mean (@var{q}) @deftypefnx {Function File} {@var{q} =} mean (@var{q}, @var{dim}) @deftypefnx {Function File} {@var{q} =} mean (@var{q}, @var{opt}) @deftypefnx {Function File} {@var{q} =} mean (@var{q}, @var{dim}, @var{opt}) Compute the mean of the elements of the quaternion array @var{q}. @example mean (q) = mean (q.w) + mean (q.x)*i + mean (q.y)*j + mean (q.z)*k @end example See @code{help mean} for more information and a description of the parameters @var{dim} and @var{opt}. @end deftypefn @section @@quaternion/ndims @findex ndims @deftypefn {Function File} {@var{n} =} ndims (@var{q}) Return the number of dimensions of quaternion @var{q}. For any array, the result will always be larger than or equal to 2. Trailing singleton dimensions are not counted. @end deftypefn @section @@quaternion/norm @findex norm @deftypefn {Function File} {@var{n} =} norm (@var{q}) Norm of a quaternion. @end deftypefn @section @@quaternion/numel @findex numel @deftypefn {Function File} {@var{n} =} numel (@var{q}) @deftypefnx {Function File} {@var{n} =} numel (@var{q}, @var{idx1}, @var{idx2}, @dots{}) For internal use only, use @code{prod(size(q))} or @code{numel (q.w)} instead. For technical reasons, this method must return the number of elements which are returned from cs-list indexing, no matter whether it is called with one or more arguments. @end deftypefn @section @@quaternion/repmat @findex repmat @deftypefn {Function File} {@var{qret} =} repmat (@var{q}, @var{m}) @deftypefnx {Function File} {@var{qret} =} repmat (@var{q}, @var{m}, @var{n}) @deftypefnx {Function File} {@var{qret} =} repmat (@var{q}, [@var{m} @var{n}]) @deftypefnx {Function File} {@var{qret} =} repmat (@var{q}, [@var{m} @var{n} @var{p} @dots{}]) Form a block quaternion matrix @var{qret} of size @var{m} by @var{n}, with a copy of quaternion matrix @var{q} as each element. If @var{n} is not specified, form an @var{m} by @var{m} block matrix. @end deftypefn @section @@quaternion/reshape @findex reshape @deftypefn {Function File} {@var{q} =} reshape (@var{q}, @var{m}, @var{n}, @dots{}) @deftypefnx {Function File} {@var{q} =} reshape (@var{q}, [@var{m} @var{n} @dots{}]) @deftypefnx {Function File} {@var{q} =} reshape (@var{q}, @dots{}, [], @dots{}) @deftypefnx {Function File} {@var{q} =} reshape (@var{q}, @var{size}) Return a quaternion array with the specified dimensions (@var{m}, @var{n}, @dots{}) whose elements are taken from the quaternion array @var{q}. The elements of the quaternion are accessed in column-major order (like Fortran arrays are stored). @end deftypefn @section @@quaternion/round @findex round @deftypefn {Function File} {@var{q} =} round (@var{q}) Round the components of quaternion @var{q} towards the nearest integers. @end deftypefn @section @@quaternion/rows @findex rows @deftypefn {Function File} {@var{nr} =} rows (@var{q}) Return number of rows @var{nr} of quaternion array @var{q}. @end deftypefn @section @@quaternion/set @findex set @deftypefn {Function File} {} set (@var{q}) @deftypefnx {Function File} {} set (@var{q}, @var{"key"}, @var{value}, @dots{}) @deftypefnx {Function File} {@var{qret} =} set (@var{q}, @var{"key"}, @var{value}, @dots{}) Set or modify properties of quaternion objects. If no return argument @var{qret} is specified, the modified quaternion object is stored in input argument @var{q}. @command{set} can handle multiple keys in one call: @code{set (q, 'key1', val1, 'key2', val2, 'key3', val3)}. @code{set (q)} prints a list of the object's key names. @strong{Keys} @table @var @item w Assign real-valued array @var{val} to scalar part @var{w} of quaternion @var{q}. @item x, y, z Assign real-valued array @var{val} to component @var{x}, @var{y} or @var{z} of the vector part of quaternion @var{q}. @item s Assign scalar part of quaternion @var{val} to scalar part of quaternion @var{q}. The vector part of @var{q} is left untouched. @item v Assign vector part of quaternion @var{val} to vector part of quaternion @var{q}. The scalar part of @var{q} is left untouched. @end table @end deftypefn @section @@quaternion/size @findex size @deftypefn {Function File} {@var{nvec} =} size (@var{q}) @deftypefnx {Function File} {@var{n} =} size (@var{q}, @var{dim}) @deftypefnx {Function File} {[@var{nx}, @var{ny}, @dots{}] =} size (@var{q}) Return size of quaternion arrays. @strong{Inputs} @table @var @item q Quaternion object. @item dim If given a second argument, @command{size} will return the size of the corresponding dimension. @end table @strong{Outputs} @table @var @item nvec Row vector. The first element is the number of rows and the second element the number of columns. If @var{q} is an n-dimensional array of quaternions, the n-th element of @var{nvec} corresponds to the size of the n-th dimension of @var{q}. @item n Scalar value. The size of the dimension @var{dim}. @item nx Number of rows. @item ny Number of columns. @item @dots{} Sizes of the 3rd to n-th dimensions. @end table @end deftypefn @section @@quaternion/size_equal @findex size_equal @deftypefn {Function File} {@var{bool} =} size_equal (@var{a}, @var{b}, @dots{}) Return true if quaternions (and matrices) @var{a}, @var{b}, @dots{} are of equal size and false otherwise. @end deftypefn @section @@quaternion/sparse @findex sparse @deftypefn {Function File} {@var{sq} =} sparse (@var{fq}) Return a sparse quaternion representation @var{sq} from full quaternion @var{fq}. @end deftypefn @section @@quaternion/squeeze @findex squeeze @deftypefn {Function File} {@var{qret} =} squeeze (@var{q}) Remove singleton dimensions from quaternion @var{q} and return the result. Note that for compatibility with @acronym{MATLAB}, all objects have a minimum of two dimensions and row vectors are left unchanged. @end deftypefn @section @@quaternion/sum @findex sum @deftypefn {Function File} {@var{q} =} sum (@var{q}) @deftypefnx {Function File} {@var{q} =} sum (@var{q}, @var{dim}) @deftypefnx {Function File} {@var{q} =} sum (@dots{}, @var{'native'}) @deftypefnx {Function File} {@var{q} =} sum (@dots{}, @var{'double'}) @deftypefnx {Function File} {@var{q} =} sum (@dots{}, @var{'extra'}) Sum of elements along dimension @var{dim}. If @var{dim} is omitted, it defaults to the first non-singleton dimension. See @code{help sum} for more information. @end deftypefn @section @@quaternion/tril @findex tril @deftypefn {Function File} {@var{q} =} tril (@var{q}) @deftypefnx {Function File} {@var{q} =} tril (@var{q}, @var{k}) @deftypefnx {Function File} {@var{q} =} tril (@var{q}, @var{k}, @var{'pack'}) Return a new quaternion matrix formed by extracting the lower triangular part of the quaternion @var{q}, and setting all other elements to zero. The second argument @var{k} is optional, and specifies how many diagonals above or below the main diagonal should also be included. Default value for @var{k} is zero. If the option "pack" is given as third argument, the extracted elements are not inserted into a matrix, but rather stacked column-wise one above other. @end deftypefn @section @@quaternion/triu @findex triu @deftypefn {Function File} {@var{q} =} triu (@var{q}) @deftypefnx {Function File} {@var{q} =} triu (@var{q}, @var{k}) @deftypefnx {Function File} {@var{q} =} triu (@var{q}, @var{k}, @var{'pack'}) Return a new quaternion matrix formed by extracting the upper triangular part of the quaternion @var{q}, and setting all other elements to zero. The second argument @var{k} is optional, and specifies how many diagonals above or below the main diagonal should also be included. Default value for @var{k} is zero. If the option "pack" is given as third argument, the extracted elements are not inserted into a matrix, but rather stacked column-wise one above other. @end deftypefn @section @@quaternion/unit @findex unit @deftypefn {Function File} {@var{qn} =} unit (@var{q}) Normalize quaternion to length 1 (unit quaternion). @example q = w + x*i + y*j + z*k unit (q) = q ./ sqrt (w.^2 + x.^2 + y.^2 + z.^2) @end example @end deftypefn @chapter Overloaded Quaternion Operators @section @@quaternion/ctranspose @findex ctranspose Conjugate transpose of a quaternion. Used by Octave for "q'". @section @@quaternion/end @findex end End indexing for quaternions. Used by Octave for "q(1:end)". @section @@quaternion/eq @findex eq Equal to operator for two quaternions. Used by Octave for "q1 == q2". @section @@quaternion/ge @findex ge Greater-than-or-equal-to operator for two quaternions. Used by Octave for "q1 >= q2". The ordering is lexicographic. @section @@quaternion/gt @findex gt Greater-than operator for two quaternions. Used by Octave for "q1 > q2". The ordering is lexicographic. @section @@quaternion/horzcat @findex horzcat Horizontal concatenation of quaternions. Used by Octave for "[q1, q2]". @section @@quaternion/ldivide @findex ldivide Element-wise left division for quaternions. Used by Octave for "q1 .\ q2". @section @@quaternion/le @findex le Less-than-or-equal-to operator for two quaternions. Used by Octave for "q1 <= q2". The ordering is lexicographic. @section @@quaternion/lt @findex lt Less-than operator for two quaternions. Used by Octave for "q1 < q2". The ordering is lexicographic. @section @@quaternion/minus @findex minus Subtraction of two quaternions. Used by Octave for "q1 - q2". @section @@quaternion/mldivide @findex mldivide Matrix left division for quaternions. Used by Octave for "q1 \ q2". @section @@quaternion/mpower @findex mpower Matrix power operator of quaternions. Used by Octave for "q^x". @section @@quaternion/mrdivide @findex mrdivide Matrix right division for quaternions. Used by Octave for "q1 / q2". @section @@quaternion/mtimes @findex mtimes Matrix multiplication of two quaternions. Used by Octave for "q1 * q2". @section @@quaternion/ne @findex ne Not-equal-to operator for two quaternions. Used by Octave for "q1 != q2". @section @@quaternion/plus @findex plus Addition of two quaternions. Used by Octave for "q1 + q2". @section @@quaternion/power @findex power Power operator of quaternions. Used by Octave for "q.^x". Exponent x can be scalar or of appropriate size. @section @@quaternion/rdivide @findex rdivide Element-wise right division for quaternions. Used by Octave for "q1 ./ q2". @section @@quaternion/subsasgn @findex subsasgn Subscripted assignment for quaternions. Used by Octave for "q.key = value". @strong{Subscripts} @table @var @item q.w Assign real-valued array @var{val} to scalar part @var{w} of quaternion @var{q}. @item q.x, q.y, q.z Assign real-valued array @var{val} to component @var{x}, @var{y} or @var{z} of the vector part of quaternion @var{q}. @item q.s Assign scalar part of quaternion @var{val} to scalar part of quaternion @var{q}. The vector part of @var{q} is left untouched. @item q.v Assign vector part of quaternion @var{val} to vector part of quaternion @var{q}. The scalar part of @var{q} is left untouched. @item q(@dots{}) Assign @var{val} to certain elements of quaternion array @var{q}, e.g. @code{q(3, 2:end) = val}. @end table @section @@quaternion/subsref @findex subsref Subscripted reference for quaternions. Used by Octave for "q.w". @strong{Subscripts} @table @var @item q.w Return scalar part @var{w} of quaternion @var{q} as a built-in type. @item q.x, q.y, q.z Return component @var{x}, @var{y} or @var{z} of the vector part of quaternion @var{q} as a built-in type. @item q.s Return scalar part of quaternion @var{q}. The vector part of @var{q} is set to zero. @item q.v Return vector part of quaternion @var{q}. The scalar part of @var{q} is set to zero. @item q(@dots{}) Extract certain elements of quaternion array @var{q}, e.g. @code{q(3, 2:end)}. @end table @section @@quaternion/times @findex times Element-wise multiplication of two quaternions. Used by Octave for "q1 .* q2". @section @@quaternion/transpose @findex transpose Transpose of a quaternion. Used by Octave for "q.'". @section @@quaternion/uminus @findex uminus Unary minus of a quaternion. Used by Octave for "-q". @section @@quaternion/uplus @findex uplus Unary plus of a quaternion. Used by Octave for "+q". @section @@quaternion/vertcat @findex vertcat Vertical concatenation of quaternions. Used by Octave for "[q1; q2]". quaternion/doc/quaternion.pdf0000644000076500000240000060127612505453300015703 0ustar lukasstaff%PDF-1.5 % 1 0 obj << /Length 587 /Filter /FlateDecode >> stream xmTM@+z&?tBL$d4*.<_fW_wիrc;`GUOV&ʮ[v6W7TvbuYt/N.5=S> stream xmTM@+z&?tBL0d4*.<̿~UfW_uvc;Z̫MfG} I]/ޭmޯo⣩0^'^x]fkn{EK{*ʇupg6;ލ$4;gZ8, M[TPRJGeWxmE7 "/7j;{Yʋ"1tm|oirI ɑc׺>[TқEnn#bBSEV嶭mzsg)gR133w xAb;aGL6K&0+}&"?(Ҧa/ c,!-f3*Ix {asIC%hS7}H=ŤIY(jŧ Z4{SO5Z ekxvKǬ@2a> stream xmSn0+$z"aKU^CvF^p=!94gB˥0pދ s#P~k@hZ+vQڦ(A,Rf5Ħq8>K_X NH3$Ǟ{<0*5c~Pʯ5W42^!0^#rqxƘE3x z)cgl1BҰ?Xq!NAWA*d1)iȧΰО 9璆NVfkVaUJ?%͚5ػbTW=ј52f&p2pjV^cHMcVYxLS7E=1j g endstream endobj 6 0 obj << /Length 313 /Filter /FlateDecode >> stream xڅOO1)zl;^5BBYOCYD ~~[c 22 j}ԩ/Y)uXCS&D`1. P,lL+pYxNxU=1~m$oJ<5꺩_ ^`ȕR%cjV2TT $"}+w( ] ZX+] ǷsbVdq&Dd@=Iz_7ǵp<#('U+Hjt:ǝy;SA|+׫ϣ5n~]+C}O~ endstream endobj 14 0 obj << /Length 771 /Filter /FlateDecode >> stream xڍTn0+t D(aߊM"遑h%wKʏa"G١xÏE6n[-K3Tð(K2e[?dYc<,/`WïqlWG,)$ɖJ0z>*]"lZcշoRlY—f>Gh&?x2m"HsIݲr9/'=#.q/$Lbpԓ6SZLt`*J#yr/^2nGH9)CR'5̀I^tp 沗$Zg:~H]]a+"yW@iAMަv$7NmҎbQTRumpS,*Y@k_(n'-=0`h'9|"VYnkD'4zas;AW} q3GRԸO0Mz&}k'Gv佡WYUPS@AgvbMqv91r\fC.lJRUWHBrne_չ{ON뚆씿/`,urxkkm?; endstream endobj 19 0 obj << /Length 1492 /Filter /FlateDecode >> stream xڭWKo6WV-P1MQ $ML҆v}g8V ZrfH㛇OxYey(Thŕprq$`bA&V.ux"cHbfg SqWyoRmy:Q ^^Np*X) %Q Vk7j<ޔ܄ $ WmC,y;iC-0H[`Q!]M~5t%JuzA1^ "&Auqd~kz_ۡ#:"/8aAW[,Vn'YvE@xQg:h͜hUrR4PM.@q8ZƗ6u'GE*8k . u)bt}ƢRhL ,ITΆ(\)bB 0{BCs-{<#~Q;b[C,}-DlٟuvhZm:U>H!΁Բ5rfU֚IN3պԽ H5XeDHb$"ёQj{{~QѥQ?Py¿G9/jj0^Sg1ۨ=:g厌82ʕKGah9Ma_Ģꗛj endstream endobj 71 0 obj << /Length 2219 /Filter /FlateDecode >> stream xKo7{>,h(C xգO_,)3Ilo[宬f2SNϺ`D0|nv|/TWE/>ƹ]9Sf<짋/߽z@%qT-@hh 29Lne||m] gr93\g3^IJ-;UWߙ~ؽYLJYRt6n3mMĝ 'j|=z]eq5E޶6(O״1S4AᎧOK}{f4'{;U~snBS~{t_O= ֏Mo}݉ Ns.w)ߥ273|(+XW7N+i%`.\N/΋|W_w/cY"x!Ο hojk]Ⱥ= }…)%?>3_"xb\O>M'5O s9TfFo2|+/:JP>עw]J=L|");\<3ē ^5v7M'r @RG]35\^ ̸$+*|ʧLE9aDj`zԵ"= ( h@m6Um'"\_3A< ]Wvj_Mc pr~ όd47Yw+.֛ ֪hWXM/y eŢxnpr{ όd4WJ8׶T&]I3L|")όdt T2ghW=0a/ 'P褞H|;,w7ֶ@dMt4.hVPD&6}%2k> stream xIo7?inå@S4 oA5IHr%)Kܤϯqzd"@aohauXy FzyF=|/g]‹򧫳7}1J,j}ޞ|R C#F+e{K,тu~(ow^oV6qJ %L}̇|Q"ur µp-ޗ΅SIxoOfpg^QZbw*A|U&|{cL%Gꋬ7x߀ᾑh}K͗z33;7w/J!9/@6.;l!I)ɾ ]:߉5t*LӸhCGӶdz,zf(8tkƽ Tϡq8SM|QFΉaGFPq`r{.ˎl]YINY]!؋n'b8سr8jؑ;F(;/`߭j^%"O\e̾ OջS@~`aΆ}/hYo[#?Js&#y6D ڜs|L1DҐ_f%Wc݅ĜD1#f8;`6S9`^j t{MXjTaq4LkFdW1T L.jTΑ1Yˎ7DnFd=ٸTw' NS9:WeG`v-{h@!wj6s3:Cs[k\vd f%q+/MH٭rr;Csdo\v fc2?^0n?sϏmzϏu*\׸(/~m}͹z_j6U|s?}NpʁwP`}M"7| endstream endobj 9 0 obj << /Type /ObjStm /N 100 /First 826 /Length 2082 /Filter /FlateDecode >> stream xڵێP,ցX$  Ya3Xؼ}~5cK#L㡚U,$x āQ Yՠ)%+CI3 2*BhVM Adh+Pw(*#< SZ1C X 50$Lsh+j*Z=-  ^1J荴hTTCqT"A[ՊX2TAcUQPp_PUq;b0jheU^*0@9E=trP3 :ʢNEǭÀUBhEmu pPK( AXG`4Y;P`1Ҥs[1QTCB6@TF٩?l3&RպҞ4a4A)AiMTDŽ^?[D{=Q1n5tV5`hUybۇ3 n D7eo4/_|Z?7aa}Ojfs{?ov?aR߯rߗ=5D˗a`6OZwyyWhǫanCxTdI>n!vU[4Zs>_uQoZ,21+)hV=ʽ}^a7^t}a?^ǻ?>nC{ov?}q<58aLjAO| Wth׶s28AJl;k, {ܛ{s\_zopW] w*UHW"]Et*UHWѮ]Ev*UhWѮ]źu*UXW1_}=>B(pqp#1c 4kTۜAWݻ]YdN .Qt@U}*Rs4 bIBH`hAJu*tĄ/L%$_ !X𞐈"z=i9/D&Fʅq4Xo)ȧ9Jl0:=zN&IO[tH W|8֩@kYLG0YL* u5̄/qX!\Meb'#&]Y!]fa… >ΧfͦPP?ɛdD>I- <4S .sGVV: Z2 l4LfDe8̰gO.pbdX&'3EL(4NaS2Sن)*eJ-;IJ)ޟ_Y8IX e6/B4`şM)l@bq.. DO> apJF\2’40 >e2vJIs*8Sɕ2`'֤35;Ô 1Uᨪe"Ϊ#e"40q+Mf"#Nrx r96ueS?>7MΥV_:Hn{-Iv{yuʿU>-EnϽG:M endstream endobj 137 0 obj << /Type /ObjStm /N 100 /First 838 /Length 803 /Filter /FlateDecode >> stream xڍMFu9MW7 BA=Z&>oC L[]GbD \,yp HYL,0=>:r;{|H >hhL`!Ij;FmԹcl#c3rD&j[rZct䔋q2L/6tѝӇp}y7,0OUy{u7/|rwoeW̏e{C-&0m5\m|imd$Buo&8|k󼴑2<mZW#{a+0ɩ˾_J_izt^čQø2X_e)th$\WjdS'+qn/ƾ4RR_f{\!}U?m|C9 ǧKYm^w#ט endstream endobj 367 0 obj << /Length 1143 /Filter /FlateDecode >> stream xXMs6WH& ,d6w[;9>0їIʖ !SgLX{}|-fe >> /DK10D6F,FmsjjJ)f*>[L rQ7z,z1y~נVL)]t-øst0F:C8ZsDj>bRp8bfd:$bm*HHmW%2Tr\7L&ŸWf:+|cB\: ܯ}(Q_B1û2ά׼]1PO}y k:iD_8> CaEa1"Aݷ7C+& I~W%2ƮA<_ef'e5tlP1 (9 !ٴxes9D/ ,RV}}`%|,Q+AK*ʡً98wbҗk周4E |&Ŭ+̋ϵ&Y)Ʀ3?UTU ׍n>[3w9Mc` TtNgPˉ;yv8s@<1hlںF{ѠÑ+ E1Y>ʐWK2`[+chM!9Ah Ih2mD]Se@޽4mDT4Ч Ԕ_G~x !d|| endstream endobj 373 0 obj << /Length 547 /Filter /FlateDecode >> stream xo0+|)GLT+7Pnc(dvM4z>$m"ԃS_9@$FTD@lg>c6u"$cHrM|"WTLaIM4:`J) gZbZ8?.USWunp4hD6:Ԛ+ʖZ\- %17\B{W`Ț]/m~lk6we,$D:ra ʅc\Z#Zymܪ F8T;_0NgXuÿvbFV.=+/q m7݉a5M< /u &],oc\VBr)^fMzVZuΚQYQQEpe⦅z~߸Ke,_\/`߅ݣV5-=:Bb9nZmɥselxXnvz/x=ۧ07MN=uNwl7?p=目{~sܺ endstream endobj 377 0 obj << /Length 1546 /Filter /FlateDecode >> stream xXMs6WH"o$fNz4\ʤDQ_v&,vbf3 ?lY lV>\P7p RL'?__\Sj()hfwSUMve6}S!D_S)Umcdp͗W šTZm=Cc C뤢3nu ]vV7 \#j.l] ]bSzn ҚznY^e*]1Htq7,ytܴQ:l+gY#)B&=8+Yx$9'acdpq}ˏao]_8sU$YrF4gQJE7bvcIeU!ce\0i{1a3Z _# L`6e=^!f uT۲7K?0&p0B8/eDe(&N((oEx+|Fp?cj=_L =*pQ'?U7 Z<>z<*};"~=>$?A" z3U&p_`9Աݡ%4愷߸5I4B &Lˁ_uPq endstream endobj 380 0 obj << /Length 1420 /Filter /FlateDecode >> stream xXKs6WH"7xC=I'tƣHEG"%>; |d;>߾& dB L-+ܝV X 﫫_XajY<V7dl 07e8x ˢW^}^ 2Hpv! J(9b\% nPRDHHTeC\/q@\,huȍf_]voH %Bt"6w{)H֓j}$b bqS eVp2ei%zDRO|LtD"TYd`FMC[8 mct,vu%(:궆&U-t ,?|j] W[PO-gG4qzĤZoS]VC\diB5?8jaOǓ3g%>Yh1 aâvq#1ΆG BX^  뭏DTw_99{FQC4{aevocP9@kk=v=ZO>[P>O endstream endobj 383 0 obj << /Length 1361 /Filter /FlateDecode >> stream xX[o6~ϯ[4bŻ4`b0 تFl]~<")Y,";ߡg$3QQ9[nZgج `%38le(j}$&R_1}h5WdeߧM$򖵺(?<}+#艖̕\̚K aR?>6JnmlTiI Q&H g#BD﷭`w 6QY}#Ţug-@(3!Bwu#WkE%虵BNif^vJ@D<@0XcAF@E_0ok[h %H%V .sx/ο:締r>B=0m;':mߡt<O|Wй XdA[Vς&mIJ$T h ( MriT97:-|F?*+dsBv,cUER+ ahPSňخ -JYRhJ&g(r*!\ j-x~ 1+ҥ񸞪.[&) =Ԋ"Xv4akShNQ5eaJ"EwAa޼K$n"d2FSB"nYj @QUR}HB \@MbZ1c/j:] U=A_hLtTюUjT[{ZUl/$%%H h8JPMA( 郤qz\768E\,br[$6=z{ cܰi, "&f*|>vZAjvdo>?X J帩t R8kPDt( T~0z̑f#nu5,'ہR58[ҫhΝ6;dvHDx<[:BIj3^;P* Bw"xU +nEa%flf,֝޲l XK=l}AH6)F$p6meO4]\D7.Qd [çSUIwH%WYwTw]AR1DpU|}iқe'0]%M(g~_yQ#%>1 L< endstream endobj 386 0 obj << /Length 1721 /Filter /FlateDecode >> stream xY[o6~ϯ[e byea][t{iڴ#̖InCRp/YC"xw6&) H'r:o^1.`寗gO_(5a4gŐ|6J1O<]Mki,OXJ]l5̕EU?M{],7ӫϞ_WDIvN\W|GLc=m&(֡ydsA@YGi&m9k{^+s$Ʉ1+eň; \F'JnS1B::J)$=wTgIlt!U|3Ab?T~! 0J"( HSiN&!Vib]#aM9Io'nIP J8' (2¤1<ھ_ooٵPB~"\ymBǞ+*S-YS⪶qzUKŔ CSmcXB"UѫE ڸ33J:F;` Q:T z?T:C ,BN m'YuP /v\}?!e|r9 HVr~s`Fv? 6GLVz;HljZ~v%^zQnrlZ h7K~"Udu.)>cBbֺӍ%e~G %݌Y֑yA\ǔ%+f.kp M.>Mci 2x,5P Fľz'!y$)|3pqj!v{4 GE? F}" ׼wp5#L-ذu@E!~"#j~ Vx;0XzmƔjA?[vN=;aO] >^նuc*y;wHq?]];iOK(k7f'sѹ!G40,9?qmp9Fg ;> [z.(Ź>Ay{5F mt?X}Wf{p:IK>[aמ98{nWY_tOTZ~}b+9&=0a`u4kP,oƈ‹0:|5Wv18Kŝ[GvG[gYH*E-}I t,qbD)zⓩ#G J3GXaN c;UtPC2;sFYM l2gPagXlWqE F<輠kk~Q{pR#0 y_MHzi8fSi-ԙA"p(ph6n|I= Nt؄ySBeN$0, endstream endobj 389 0 obj << /Length 1466 /Filter /FlateDecode >> stream x͙[o6+>@Ċwj]ذ+AuZ#%=lʗ6 N0!LpުKmF8zoU .ainKX!!@r%A_ n 򋶪ƌ9PIF} :x9l"9N|Cdj_M&d:sN]xQA]gH}W&wbN|j";)N"ёNC`dTdn)EUDuǔq8*hg;|aPg??cPV?>W?ۄ` 6:P2&Sp`%uJ}Dݷså;fVgmX S0\[-+M=<6ѝhgbT4MAPΦNP>,!-z˶M_j`b0> stream xZo6_aI"V8`b6b3VYr$IH2'MnPx1x?<,N(Jh<[lN"3Zf' 0P>;;y$] Y-god8xN!4Cx."+ ;J5He=wOgpzOe2AD3+.EC.H?e/\kC#C\ud")컍87I"Yz wBO$̮Z -~*6nP`vS.__K6¬fժEl&;vY^&L3lꩶ˧|aBCYq b%J0?F"C.FtK#v0 搗*&Lw:)ջbWy֎ Iߩ~;iaﰍJح~/ӇW|_*౿HS1,l'(!$a*XnGFf<&~o8(ϡlea nc>3x7rQ4a2:d܄H8wd ޖ &ԪA{XFI?zךFi>^?Q(B 2PKD%sY|k-~hMt۱@㼁tbj|0"1'#'Dw0B$?y t(n $A|$GDy3v "X{=a *j0Y=.El*lOx"`,'^JջWYW YAg{cXhRZNLNjG}d5gZ*rmbe-W AMJnw|Q6vdQlVW˻.4(SOoZQ)בIpɜt* &/?VQdkͭ߉  à}PW ^(>sC[#m Qe"IA(&.oInrSgT3KDzA$X]&([]dEݨys-Z lLP.u|қmBM{!vvr5_:\('LJs)?\eu[C-EUn Ku tԋtֶmo@A3W2~*W-6L 5MkaWt ޥpSx|(l|fy;,&n}6] H ٶ/^!"rN9oW i:1b=x]^ǝ|֤EC_B} %@;LR>s{?h{=_U起q9F3.S[ at;d<Q7-7 ^ẓ>ѣGYuŷE)/: endstream endobj 396 0 obj << /Length 2048 /Filter /FlateDecode >> stream xZ[o~_1jbIn}o?(3Gɖ4:"e%76X`š(\s ?Rt22V;7+7wįKaa:Zw_bE0XxS]~ۚz2:\$80WUn]NilxLD./ $8[Hi qI{rDXpG.CS!i:%@׵i$ndKݔwfrٜ %r~(m IΟ," %߮- Py$S%SN?acGsDOsuJ+.b{H$pn|r))*~2/fη5/Qr v,$L$,TM{AT$܍"m7]{P;7vl0f^o)ئqNbIh 6H+2"5Bq+8UqfZM^{7ݡ5A" z]W "XLd^ ᏀLh FSP\i!vv綻 Ӥ`1McUk?)M?"WU;QBmY$ '6;0h+:/}M[fk}J0&Y=>@$hձΧeMΉ!HL/q:lryBd'8ؑ1@Tk*J /+:xs3/5D aIi(M~sc&OΡe iC&)(b2Q1=MGN5VeǃU`7Pj& К' (1'yj:г^vFa'qXѴTgAL@t)PP1 7iA$E*čl-Wa }r5z0 99 5   ) JCg  R&+݋ۺE.a&IwnnnAͦmlEõܒF0cG)x')bʥhrJU.Ic&bZpA_A1e+1`ش0›[q&鱟+/c{q'l$7'u۽qC0Ͱ䳍ۦ+ {N(o\!=qL.\^p/y/y:g쬋kq m] D¦vh3I6d#+`QwD}v*.9 2|(λeQ)4}7>&ߧk{߶/;SGABmruԀPGe%Ta?IY@Vbsa~S:T@fUA.P <`uayƛU}E5a)"E-[Hf˼\K%t C]ь!bުK(d4!v92hf٪A뒺n.MhTCx =9'Hn{+?jf Kh (XlPC߻nZKuםzzSյ (o|w3K" '|o;#% endstream endobj 399 0 obj << /Length 2182 /Filter /FlateDecode >> stream xY[ܶ~_1ȋ5ňw)@&m]hR73պu{CiYgS`<;7+V:$zn7ޯo0Q~w{ )W4!Ynv::fg:>?]ǜяCcu8 |Fn7K&ԏsySE5"(0?gsd3F(5H3OD7ec@oMKֱ2ݯidp򧄊Ŕ2GGveQDN$w`:Y#ۉf-rllqpd;P*L91MScj 6M9TuIB֤Bǐ 1(vFfu-@~ms+/Kqк0L;]c*(ay QaW ",弆 &KHitgF؈]owCNS M(2?fwI!UI .A jTeQ^p `]w[T+WFI WJh>'S6,|MǤ|2- Q|#xT6 ?|͒9~6n-Xdڏ;A̎i!ɦ)c;Sd WZ|8n8Ld 3*lBx&YmaQ<]=8j%`-(ի1m,eb\ANQ* ȔAwZu5g/)zO(\@qDpĴwM32ZЁ?mtql*Y$;yOLBazyh Ebֈy& \8I\YtiǛYk?Km1݌2&ivn(+XZ&%Erh1ph @L`VDz ^> 'Q3!eF6W!GQfR-&%zLη;HɯBUkB(T5)|r$K$j" ^mSy e׳ ɲy5 Ɉ}X&3qO#C|xؚ8leSUQ9ED^/M"V۾ QߗwFI,m{;px`n -4jT Kp;A:փn~hz?ִɦb,5[}W+ʢ[&'`F2Ŕt^￵׷߅t9LA["7skvl p$ǟ v=60bwu؇SM QyrJ97۰s('d]u~<(ҧ7)WoBT ;]T/NY>]KFdYJ`KW"'qJg5e4l8YRMFyVCL{gjl74m|Yϼ?=Al|g]uC~P6zXsu7 }:mO.1^$PW(fW/jf3{b=ơ0WKl8;G8eJ0 ~0mc3ex5Km[ɐi:O oC$K"Z {ޒMaӞ0A7M(ts?ݏm.7Y8w8i3o-M_v_ps xFqUPn85zS[?\qZ*w1MJ?j e*]Ӻ!> stream xW[o6~ϯR)*ia -vcӎuP ~\xH  R'O"&@/b#)9AXU:.p VaU7wUWP.neV.p2kݕ-}:3)\"B/;'c`sHeo֨s&ԬF% r13uɎu ~$mYf_+Ss|A֟#mbQm"[h-Tn&\'rJ6W8Z\5Bl!<ΟUmm|(oX4"MQ14 ob󘲳W!<_'N_{_SGBO.e䳰<n;)mW<}'sG "Y*Pa:b2s21}&~KrcGMI+OBSE( endstream endobj 405 0 obj << /Length 1196 /Filter /FlateDecode >> stream xX]F}_aX*{&VUmU}J@llSya l^0.]U+Y0;ssΙ{/YtLN ׳MT m01iqg)g4"6tXٻy"Lj?iP%<<Bo?aFRx"1"K}H8)X[tI&|>'ѰM S$;܌Rq~ZG -h \( N` 6΂HPbY1𖕈ȂL1T:Wy&F;׎'_eGFe-iMHHVZ7%L3` L!>Cfu 򈨨0?Izf]rOU%66j|%>a,1+ǬeVHٿdD_¾ %gs4sbŐe>~ 1qHȺ9Z$3"yV+`ցw{D|BV=AE$Dx]$ qE(ae'zRCá@1OhP}Up~*0ó(.( ΁HYsr@e`h0*bZLZ:/ ,M?l钌c;;TgWC ]Hj[@KXWZT!+X-Bwŧ:vtFY+hLDVFx o)%/үP@KīK]}Y\!]&~Na!Aē5Ѱ^CIB%<STVt5%~NˤMm ʮqpyI}I%$ރ9 %pHuI\(kR2*<ɡ0re4ִ9Vu9Ԡ$!TTNRgSETkB=4 *%WTbݛs94T=Â*qruNE/ ~zxwk#bX E'PLՋ)PS#h *6@Zm^aSc"{Vyi  v#/.XZ= A:mS7C/W!Ǐ|=^U"6R{zTӫ|2DRyg(~? endstream endobj 408 0 obj << /Length 1563 /Filter /FlateDecode >> stream xYn6}W}#n"9iS@cˉPr$9q)Z)[R%9w9$?<d"$Ety7o뉹"uF~{uq=#+ޅDY(Y63Ia*/V:Ai]1 Õ['qFG:Ў>B Q 3COHmr ˤ8(BwR +O"BOi][ЈX{dz3[C4,2X೶`q֩~cݼhtI0"9‘ nĭ nC6d;b{u 3bC *꘤L.eƷ6k y˚-=CD`8cB"I܈[l]UC1geV?K fQE>Mk=sR*Ӄ Wiu+ N.]ثqA#)? v*BbH =ygtq$U4ĚvJ7Xٝx\QYmϤ8bikFt~`:bv&kQ 6,ȋ5e]z% MQAsT$-B Q(q:]:i/!PB|pkQ/Sr\V=u{!nx g}SFM 6w@$>5 7@eC;Cx\Viҹ?=LޠyAds3bTWNmK6b-ɨOP1r| %̅w^_ds۾6&wT_onf}7 &|i  ϒ27F.60bsf9..1m3q%XE\0!|GƃgF&%ܚYY=vnw ̷DՂtk?;xR6[e3o *q. ,@⣲OQV;q2F{ $-4/\՛r5^BtNC)W}R~|/(_uNd졡j_Tv'!,nGWB-%4$=4;NԿ;詑CMX鉶M_ endstream endobj 411 0 obj << /Length 834 /Filter /FlateDecode >> stream xŖMs0L.( i'L/f^T$]! 1N~mS#:bbH"l1kTݭ RWe\j [J]os|aB޸HpX Krzm@K4V6\3 L >^b:/]ڹrW9o1"Bx!6Ɇ1LmYfK6Ar; Dx16F:+CWJ]u.*5lNz:3.y֐.UQ(c/yc$?m<Ik 궐3͆ۆ&L,&s,9gB)C!qmƲjԽzT| 3|nƖfa endstream endobj 489 0 obj << /Length 131 /Filter /FlateDecode >> stream x3T0BCs#s c= cs\.hQeU T)KT@P!$ ٨h 7M cҼ> stream xM۸:ڇAOeͦTqrIRcg]$_HD {m}\P{Z~W~h_?(Ţ$dx~U_+twVx(y7i/>aܼ?-dř(_M%_}s'|C|:(_}vB3$zKK&VaowU]JKVŤ2bq'9^#b1IG߿*Pp70}sK!Fp#FTJ/LUX 5 GjD#SI-ƽzb<ɾnLt HuO!BAEqHxLɊqݛ~3ޭ~~X'Bd~0d6NT5NV/ \]'XZ0)L9owSD*^e4]Q"Q@s6-6'FmlU'*i'ƛM *R^#FGh HEaZf 0qa"L&:;6"E 9/ C4t" :R3.% &/a D4" L–]wn7fYT$Brҹ@@c}Tly+: vN3_,&/ǓKKD4"ɚ_Yw]t/kW}[Iy6lJg4(p9 K),=>fnR*J')*8N,\)\i] g}M]&UZfrLEu"I*l^f|@RJ *R^#RDg@*rMN˙ͧYBA9:!ΈTcTl<06̉OA*f y{K ǡs]d&ovOx*@^h E~ @ny9PK 1Oeʹpc1͇5'<]ymiKq^/LKTܒܵM7]hC[Ks6f^}'\pa"]Xʂڡ^B7tfPGi[\H;τҩ#5@Ds ߼F[~R7TVg% Vh+se'D㚡/M\I3)_8q*>^KOGڗ (jΜjRYr0b'X9DIVDŔr nn9\6ո8>aOCs뱢`p}Ϳίڇz~ڟa?tejB, 1М^Qmq*Y06? &@&Qp$FtX͌q9t0~@S^0x"Pq(m5)Y3}*I^'h $EJo*ٝEɴ6KUgB/gB ins2qUpwʝwaܩy9Qќ"dR`|zf͏JWu~ cP֨Ǝ8,nb~Y&V<.~i  p1FP8 ,ZSfl5q`\k+[K8+s\Pr08ZDc`+2Ne˿Zek[GeޠR8%a8J (%sz?ɓ+eNZMwG]ffGtbTF0Ym3]N] <1Ar4Ab=QdHÏpD r}ݾr*>^FF!>qřR6;Lk0SIr0 %h $EIٲ$(x*D^Ch EIߠm_bȍ>$/I OlDc )2N D/ۼS*N)*X&{ Wc Eq sS1QO4;bTdrMNcOc*P^h @EITL6/]N7-I7ĎW 0D@ hmdHsL$=ݶ[.zFA<y'rN#73ۗ}|OA.ƚ ;y'rNs M8hݿo|\O`xx9J1y`%rNRhyIBIƍ5/ wNׇ5F~9w/rч (P=!nJVv%G~Dk8' 8gNs>!:Eĥ3w}}ޤfJ1&R8%aNPBs(H83uU>v>%/Q zbb9(EIWZkF(YR䜬jS|n M5˚U%yj/'h@Wdfʭ$rT?k@_C'p!3y~۾UymvSOojvGWMR(]5| endstream endobj 288 0 obj << /Type /ObjStm /N 100 /First 839 /Length 1329 /Filter /FlateDecode >> stream x՘Mo7+\$3IZ Hrh[Wr}g5Jc$E!ߗCһdrJ)TORPJ Hi5Z/%;G>U|I ;.أD((3Ͻ>֙8j=yVkþJ"x0TPLqA(*3Ũ E尣t OɃLI.PqT0?Δs`8ʂ”csbh/S%a-E5x1P 5j{*[n6Y/G4}E4}N<v#ߏ9j\?g#.ff#gp56nfz92_bdb/j]F2#{KrvyG/w0.v~a#_ߕ>bxGvڹ}N h?nѳ鋳˶~7VmZe3}.ybvlNbIo@1NA MW܈i*:Pz ;rNpM l?VH^nu@/6o1}jWt OhO"qMs r9!rXկ EcW>̬.ì.fu OCrס|r 7߽Pm/B*z=R^GSsK&腸磼7r^C|~`ae(,+,oe)*(n+m}L'+U9e ~Ȱf*tx{~ViAϚU_qLb96B(2XTD??R' {SInGLy?#U ~$!&; endstream endobj 511 0 obj << /Length1 1703 /Length2 9567 /Length3 0 /Length 10650 /Filter /FlateDecode >> stream xڍT.\ܥ=XqP] !;ŭSܭ"SGg̽{+k%۾YaU䐲C.ܜ@a47r7&Z@<0xl` w=O~Gx\J >УHRo$$\ GB_WKdߊD#[\Ǣ`v-| p9 p9 >&rp >vyL/_:9=V,$x!sv  npX`\McujqEKft!ׁ*|.9GsX֔˭ϝi̙Q]Oߨ0(9$7|}tlZs]q ܻ<>}+ Z%]8GvQ@$cywR:T*tgGxrFh0}y ~\Zqn#c 3 B:68[z+Edڻ8jIl:[ "w.+K27Neb* m9 'x9'tRJR,J==f[K;uށv+޵Ԩ)ɓZE ٖ7䷂L"c.9j6f4_2bBW?vNyE9:>:H%ɒ*]YZWmNV))H~zb$b/,m.LǃwhX5%X=6i$lcWO1Pv],,k'\TM[@`TH:Nrٜy_;MSIaθ s\G>ۦNܖ*ՠfwƾo6v9bDJ-쥏UP]W >sFS W&@:P b7<ܿ@ǩr՘3͖wq4 K?d!&; #d*pq7z uh.ct}FQҐ'v?ƬM3|.NiBއ!m`:ӵP9Nkk^4Fɞ`qvը1V߅ԿA̲S9KC%*Eo}-ۙːϲC $|P~PL/F@kảdZ*ڒ#[oJQ24yntzOuS&YC.*:C@e|xYΒDJCK}z5i`&GeS9sܒ*دӓeK0׶ǖVrC ' dEuHm Ǝm d6i(ܠ41 >ښͿ.P"sXIכ_*N!1hlyC^SڕnkT?]'e=9/T,svWFjHCBᘞ/Laź<[xp^ Kirxae=n@7˩v)rBSW6$~'vQF]x;H5_r?ی.E0È9K``[5Ɨ4uuԁMV LTjg?[eu)]r#*J&36tcڻ1Ɲ=U{žNV=, \8TRE/°36rjȡbYdu_Ǘ|r CwB6=SL>.0$ZsUs%\dKAE]}8Qg'(ܘϟUR1*"T.'m-GOX_qh4^L4A'v+6Ӷe ;aY NٶƳ (S+Y׵üջf>l7od)#u.Sﭠ?Q HT8gsΆ~}jc˅{T ebj1H-lC}-oj7V|ke4T.gd|3|̣BF5xD?BԖqhf9x(&l][ KkS  jz M}(*Hӓ|iS]ҥ] ȥ 0I|7%fK<Oyz?grh8g>ScV={j`Bxj|Q)l.9aӚĵhsffw_ R:BĔIowth"NDXܾJR$ Tnuc 4QBiHh_YFb;OnB+_ڣbҾ_*N.A.@: tugUpXˬ4ڋ90M`Φ !z +(5xK]o;]Bgr>ïV.O0?.wfo s@H#_b' R=/G;\@:3l VB'P$jB_x8Z%%~_0^ %^]-4JIdB-0Yie=V| ٺPP ;< s W{|>1VÁIfZxs0n#ag{XR{ɨNKΩ!E" |>Zhv =`'|)n9VݚUD|39C* 8֩zCr+I V=CrP2篽G5.R6>.am(M:ܣhZdU=xG®pP7䈺zKE7?93l"'%ɟ>Y -l} ?{9$F.Cm+`)Ds8Dvr:Z]Q O-=r0fƧWMi6i}RRGubmGF!qzo@f=6?"qvxȈL{(c 5`u*LfRmf"dz6%)_,(δ!hGe T a:ɘWs~˗ذ_2`*,A^R;Ř;Ǘ<~MԬ-'ɷoP+7[T W?3U񦱜rI?0#.a7_Y26^0]`1ASv2ؙa2oz[Ԝ6P@3 uؾ4gӭIvM(b\ $wdQO)Aڢ7^ ZH߼a>Rߟ?OٖX3Emlž-EZh_S}eugM FL.:em6b+6&}.?n_}͘ ُ1z`wD,c[>RFg~OmMQ)n^Zǽ&pG0/mؠFԸ(!k$lKhV'j8'ƒP!\OY0\vb3LEM -X0E3p>x?zc̝`ѕRK(ɰS3:뉍O~\u7-%:D<{[:F2O74PW$`hYiRM,s0ה-{dwx nl?&WO栱 z&XepO>2[̨Yu$ bIg1NJ?۔I׾c"J#甗g^5?'P7Ox|.*x>@BHuT5:T#.2RFe)>f;5YK`C”xX͠PD*i-QzN@,`kB`Km%mp(/OQF8/fr~acąVߋ t?!-e[Ȱ mNtg;e͓fS(z]WR ;d 3l{Z/;h4}PŞEb!Sz^ BlצK r_}s խXdޒ(:LTĆ礫؃_fM]NYF` ,wyʚ|j h_&n'3M-ئdI_ܪ#@&BZKdO.o"O *Mρ.uG\qLa"q Gһz d0ׂ0boŏ({z0Sw ˧$m+c*H;4)M6R'J N}b_.,D CV;BIz>S"vf[.)UZR!<\n<! \ 8 z}mֱvki#cÒmwxf /:fh @j0E!<5 u&Hƥ##0ڱ^G>N 1KZx]j{l)5(L(B*A}`q_)[`o _-?*ihޝd&5rYol? V@hlACt!2w$uGDሷ׽!Kl nF 2<硯w\Ek#Z:|8 HkOYtwE?FVM}q{. m8v̘{$ITx=LEP" ʧa fI9Yh{p*SbNEWqW z<:JmR bƩ҄ji X8kyxu wYFead7 ^TLݮcB F^}r'-PpM{ vI+3eTAc.$4I++*C{""56-?)xVpl&^z!!l0^Tm֋lUxǒ "X֯k|p]Y[Y!.]ni)P mg)2hU(U3P%Brn~/^^C&=g|rfWwOg|A5lqg "侻mr /ˢXuѦ/ w<9uE9(BzLo?Q0OYQgg}EV$@g1T޳f#V͑|C^V๺o݂s TNb0V)%ݗ@u+k 4<#~yɯHK٥AyBݡ# \SX}0`bu2ڻ[踣m,Ēwq~ϵsZ*v}TX}-+p!=1#f{CD8$RJqjr2{逊?BBQ{RtUvse ։8Y_hd}{)G6چ@A j1Z)po押7g!Q$W72fFpMeg)n^ cvr}HE[߸V6";48ߞqeo}0WS%K]F`q+ElU3o|!:jŶ5TWes&Vܷ>?rsBTjS 3"z<ܾ򐫑w*x.E;%PM?CH+2r8F38ҍ1&O;yDF'c7T?yڄg ˏ-m 4w4;&3V^XɩfS ꈉ'l8Xk=L7l%ɫdY "al7Ng^vQngF>cР9 L%:P&#M/x &۸䱺Q'3C (쳓1m`|)4b܎V4XGӾ]unЪӢf[E7upL<:Olˎ?N߼,X"u.uHk~߸!=;Ip%ʛNLpc޶Lp|- ;>.wE26cbW"&p#cU!?0iw6YZOSbkt7A*% ] >;;φ<]6/ 8\}@[aWfDĄI1^<9xB/=[cJ_Cx# Q#=>cF}).2;] Chq9hͶ=i#G-wH5kT ׷%wjXo`Д QATD̵pu>R^V{Tۂ&2ɋv0))3 ^SL1MrLaČuOl10#&h#l |H{$!o&Ax!甉[Lyu "z5<-YEM% ]MaUM(xp÷Vf?4|reU<ەYbbD]#rMTĸA!FgڂUSm Xs^}iĺ6Q[r8{9YAD]UKgʛ!xa |KjsT T~8+R>?ga~b`ZUURJ읾b^F={IMC+!p|,l4D7QQ698)d endstream endobj 513 0 obj << /Length1 2303 /Length2 17322 /Length3 0 /Length 18661 /Filter /FlateDecode >> stream xڌP\Ҁ ` wwBpwww }w7-`ާ dDJF6@QkGZF:.:# Ls2U5_B@}3a}wEk%`b`=@X C: غٛ:G!%_+5@FhPdchttܦ\...tVt6&43GS"h 4. owit0deS3J6Ǝ.@!hxPQGֿYXV`lf ȉJ9:~+[:ؼ;Y++u}@`hof@`fFn,bm$dcevt=n\ kk2lU윀y?sft200qv)n akc 0~/ef | 8;</02 @3k?ߏۛ4Ǐ翟'^ KPPA ebe022sY^G^y06p{g B __6 Pt-V__&A:YZKN\26`UՀI8h j 47s44g\9Whf@yO ޷px!E m~o+@^ }XYhtmMyma~(+^?Cz?Cz;^1^1% ^GCe{t?]]GWC{t?]wB_|EOv K/|O_|1{]/-4cc}`G[/ &{!{XU[e[{y7~YލmG{"O_]_^_u2W'o:J]o,j{?p; ]l2x/|/寋|v ݻIݓ;PN_z_o@W!✍@J\1i]DJZE6G8ʊTu[nm%ZX'g c^x{/v~@;$28Q]z\kzGv*ؤ`h#Ti̐ebC:CS"NdJPx``|u_-Ufr&p22C ^sޣ0?J28<_g Qߎcxx|sPOq{28PaLpR) %`Q7A}=l&>D)$wK >y^N)o>1 LY]'`^b_Nx'@IM2>CꝤ YELITKv#M?6 [{ۘSu \0*NF&sIvYK=0)eWj8M4@) f(ύ&i 1., {hT!hsRx4H\ by8DX1Y-63ndCm|;Q[fqo=v?zzP-!@84`QB 0y 5gq#5h劳"]ҫ(u%Z 4Ҫj}s%t񇪰mE|WyҌڒTm]ivc}]q #zL)у~'v܀}o+SP4<Ū{̽̕t!N -[wne;g:γ 4HG3& _dvFX˥rvjr7G7^ 3Qe>nsUxAݖB,%'BBĶsT%N -yiĽuJ@Ux+Qּ)912htgB [A~]jGrlkZDCX' 5xw1UsO)4b^Sg)haE%:SJ!,io@ZVBj'-Oy^jWGˋg;~(Tۿ/]oypSbĘ;E0!Ai[BP>dV)DXo}&u+8|gNo?1/DRi,LY|.Ie3F'Ć5m9gI ) l;x r;{ ʃCOQy:'2ꣾ.c$+(U~&E O2;'B5KNH2Q)="x݆7bnZU;s#k(H3)%-S:I˵z>J~|fȃUsw(=r֋Y-n'fOjpzr&t֣$cZ܋"F9 aNZu&ٲ1׭ _;bXU+&MXKYS|\!u6Z@Y5$d{]3x-%>ԎR^uSR  ǧv}>#ׄ8XGz5RF)EQ 5V#ђFbY -_Ag--1[T4B~Fԝכ %􂔱jBvV%f N훲%o3F4?ʇ'*N'j4ZF"CiX{eIHM.R1砽o|j2TfgWƢ3|9 #?lFtG2Wo0S J~('ٳc<ĉ̋ Y#/}j5:G l@#+Ǥci?Œ#1y)b'/eEYw EMeΑgҦ4޷)GW;H&+6>vx@}|kS^kof*WŎ)uX|Di' X2vL7Oyśses(D,6^0 h,aD*Te'?kO,3dX޼T5%3(a=%c.IbH gJ ȷU/w ek`hsG$@ Y |X 5oð(Ep."u7㤲-K/o_!Z>,TJ~&> EeEB"3>GnjҹFOtudv0n)3 >v]f .Ug=KzkN9Msɝb*tt^NZ%X(H'R%BhWp\jh-@58uU\Ss.$ʊGPX\:45W_ecbXjq˵$rkJqވ(^i$-gګc H1/%R}OMz '37?ѣ5۟LhM=^TkBn|r, (\[qU"ځS4!R6 F8ͿF2֌YtFJ-SxZN{]ӦJ6, We<9Pe=9)Uc;V]Lؿ6^2c? e䭅ʖZX.`0Ջʰw2]|g$~c#;dhq#2~Oh<>Kɔ}a d^KF>l) +I I9w :Bgn+dxdjr h2HIne>h3Wvm'EKfA~B)TŽOׄf,) 3V~ 1KrO~7& fM0d`*}ƕ3t8A!~*_iL8dYƏ>prmlZ;ߤ_G~τ6ulֽkؓV\Py=Ί8Oa| tUb4 =0뽰m_sHT%c2囱|MÉo49M"). }dш~d;CplN9µoi;-)SRp.wY%IU7?3@DCJcxSzsn}ܵF NκcAv__i,bkqęoߗO6N<{K m`m7)1KrfәǕ&FlFM~سm+kuskc 8+BE1 /A9oiRHa\=DŽ|agt |d~֭DTۗYhha+NiGɌpN : $$}K#}/4 ̜FtG . fb5zϧ[Ts~#b' G/ /µ$,EZH󐌆2GGDmcw nWt1AEDVX;5K }}-$-B \>pơz[a)PL~ JN`yag_&^yJy}P_q8q[>ܖi7+"Aѩj)K󢑌ofg #-'e\vչSa=;\HZ<'ZֲY*f,/%AD"g.B+ h5]67$nIc6t?2s EyS%+8j }cݢsZXv6O=.2y_-VQOv5m r9t+[\ƌS}4(X3L6sj͸MWxDGMleX0yH4&I] *$(hҢ{aiPifS]&y&Y,ƚj@OO"e߸-xxU yq0޳K)REfyS.F4bՉbmOö}xձCRҳFni1k6f67Q=)g8zJ0ߐz{B/=,KAK<́dUMDIBAH7ج&*qm/f&R8(ԡ9[@؍$,~$QW&/T @m&v{|LHBW7yS%(%禗dPZ6m#?[Kc/ϸ>{%C*{ ^SDWF̛ZM?q> =giVu7ʰk▓,Ʌ!&DŽinwYKpfɱB{qm(D *0')T l17[:2SnObFM7xlDdRk14ֶ]jԞCFjblnP%hP,Rby$=̳HH1,cW(qAfAWl5'>^c=v[uu&l2:a a:k0̞S-ߙ*HlH+7c?2ӚBBTՀ6(wܶz]|(Zd:q̜aGA-[x-0i8E)>>5R/YFGw{OvpBȜ/euLAmzbr/XJΎ{q:VdgMڲAhsgj&?3?֞Md چy=03 oNRD ms-JT@֯`^=zMCL{%{UbOqiO(/t\zJyy:A^4D{WV@_NHճH0u9znj'eOF6cGI7:%5^+W5|;>rmL2 ΢-lh2JMqF=,f$$ĸ2\R>jS26ƙH0'#LC@VQ~:;尛6]L+Bi~>dɭ dB(1ކծb4An0mk=QNW6/a|_d~}4;~YƑ?j2 <&:r? a_ɋVj@66Ql$ѵgi=YAE(v#}.ݼk-mIֿK[HP^lȯ G:? }ns8 *_e`dњhAo.hv|Lt^%{ozaqSvW(VlOl$ZO3xFMK ]%oY'>)FvŰ|bXv uȂ!qيZƁ9*XfO25#3S' D}mN݀s0ͯ9P蜼J/m4A1:6z+-: ޤqj!閘5Ocw./H΅8B|Mdy\~Y@w_)Zg:q|e;Tjk{|T]c[Uu&J `g-JHP&vբo} I- Nj j;+f0}qbW,ܣWlV Z8ߡ?L$E:jiXQ=z@8́| g݉[zΪӮ,(k_Õh"}5Z^H!_| w;*3*T^!:GX`5 4f bMn8Acb=h6Y~%6xfBB/l ~)pcmBS Xl Sgтܵ:Aå 7?gyFq QNP$œsO-Wy*c #]O0]CJk~4P,ͬjUKNA,{ZUݥ9ԏ窕4QiJeq)+E>%xǦ{Eo>wX),(QptX#XTs&>&%ۚ8sp5 (|򟢁M +ȟ5TːgPwkN=Tcƾfȋ=񨣎wwS_Vq7Q@M4}l 1]'FA"뗗uZg"s0w[=q-QDh1+6bNx On'Vj`$xY%NB[jH/5.hK4Ag.ɣػ40cRK|YM۷#La+ƌ ^U>lQۻCj3@ت:.;]<%\(\G)cKǁ*uIFԍy,>(D-r◒O} QO.&GYL}8,:k[.DUQ|ǪgLZ{!"lpV;ڨE'ف; ~#Ε3FEs(_zZƁ:,'!,^-~{qkf+jl3P.r~`WiuIcdL-՚~ 0T$Y 5)Ђw QB5(-F՚i\_2 4!/ݯE'ZK͝_w`ꇳ(|43P XUV~vq>ꐩȞ-.m@LY~9Dx&X$?ʞBr*XZ$}@̛Q˫1?U'dʂV"گ9rf5binu`:ו1 m{r)!wjg)c*Cj@#)cumR]T8MXbR/E"oT8#N_>Ja\C\즃K}Бy_瞩(, ]?&s9PQ98u(1^b .)2:=xQ_~iƛElbEBN]wοdz!b D%qZ[ؖ!L]L%S?\Ťwh.2sFoQL83 RcY& ӏ"\ bO]|.㾢SP6s+C;y4R ^ ַ[. =Qx^olM'? 94/I(>vHZZs;)X,z &5$MK}|>5Xf1- U4iIr p#VNmb@I4ˤc[~Cf IS(mhTb\?yBbO Mry@͜Cj<{)>6ͦ,F^kgQ}& )aR9+ ؼ3BuZڞQ7 HJeCxuTS;Ð{ E["^~jhQn<9IVwAQ\N옷.sտP\d~d!藚 ESd羟kYϭDx(Az^͕5T G$Gy3~$?.~BJ'Ȱ2R#3/8Wsg(\C7+"zJZHި\?t;MaryhyZ$ YP?fXWby$Mm )5Bp"۱Bŵٍ=imˎ(HȞi+C"i_HnS)N;jV9lbxl`{^W a;Naoo^ 羫 ,!ח!Wb 98E*6JxZQY3:c8*6Y&LTџemgH5<k`Mj^☮ljx_$[hZĀ-KyKl#6Hd6K-8T%~eғ kltrXa^Ai&q[|/$p7C'*ap})OCre$uH羠t>`/eir%7ϕ7~g|W>ֽehj~>8Bdk5hCN>(,O+B# ǫ*)s4'f.ԏ9>.u'e+ YKfiF/E^_a!v=M)oXX'ׅ(YtaꘁQ!b?rBsG ^[n[/W'_B)@sʦz)8PW#bhyAN8<Ád/:ZN1DoަGVYe: KP܋L6H$E)YQy_gcxcv)<](XU~FCneՓw9 |PY-6'APٙzIuhԧ T#.R=TaڿEYj 6-jy!юQGa%,J)a UO82U tĶ]&] 3F03y!U,tl>(1G_̼@"AXqGc E6l+/4cCIgEX, O21 ߠh e tHz(BBr!`zcK%]z:27m jWz)R#0@6^:_1- ,\yU/1j?Hb}# mTߥ<>,.a@ޅmI6txY2fm)2[l*-KZ< vtI0 ZxE װJ P@Ⱦ.C`TUī4_ç"sQ-)DQU)SWcUDpf·(:.ux$>mAj Q=Dꏜg~3!e* Yf|H3f]h^}5yi|M2,2= *w[3qҒ%q&)ц`X]i{=&oHbst;I9`v~*u@U_;8,&5g食\ԍC: ',w/|)Ώeɝi/x!K冤 Œe3\e|6]O1qmG rNI+갋Yzz{XEOY4A]LHc#/bLx%Yꈀ/Exώ%˘#~j{dZg}W G ^$* ]P3f慰7K|f_Lxw\F <+=?-G)ζY]=W8]WR{`B 谗7vrmR뗕>G{ 8 D QQ5D  Iƃ $RSU eq: ƕ5l8t;Φ=/ח<pyŎR3hř nQa# .r[TsuM]{_1u|_&%7h4 C6{θ#% h hOwa,;JҪ`V<Ά|q›OOnA'sµPpc ᩿Px^>Q|43y9cս]˽"ݱF v,26=m-d{ xNG%ٸmY;kXi a"e}53 Nw>kZԗK7L.cj%n+bJXcQFncnl 1}.)pf}k_(:!;ܮ[7 `tSu-lTi>JPG6ٖQـ -y8.kVŽN gt_X,pKcKA%x [#(1]_h2c/it_U#BW$ XdjlSOevO[yVa =]R&/%c˃79W[^y=A~J5;lD+BXO 1AļŸm04umKzu=Dx(VlMFwܮ \e29"=F?PEQrJ*&٤Su'(e2 4?}O'33<3MA=2pWϿBW@.g A`*n!xH9jb)/)MuV1i]dz3SO4~ mOrP?7[ Cf {G+u{:E2=-B+hҮjCm<ю˳IMnb=fjI2x>/7?V s,)VHӸ u_YrJ'B>~DUMƽidC\:QN=CV)8G=Q„mߨ 9NtF-+.Ηkǜ-rX:~{qB&'7y d͸3v %oL>>_Hd1FH&_NjoO:z2?u=4O_rN80lj_b;ҤOB%?8|VO8%b*Ns\dNQHc{,ι |a&kv|$M7,$Ah\*X@N )|׀5DZxWWԅ7XA-R%K6Vl$M/#>EpFr٘Br5Z/꧅qͳusIMa^BK)* XiQs 7 +oͶ=2 86VDSdY" "NO[&R+-PX1~ 9ܗ"`e 7Y\&f2nfyd)7N?ay{a4v'3GAbu[rm(9՘ḧ́n ioA^-dB/3새07Ff`>iYhWP,~piNy{H/*@K_3R@-13I &Bv_@i|/+xHzV4+)W: msDf_VZîBb~ޘv#Ǹ^=prdSnE Wֲ/fk3:wBII5 (=Y'XfU Rc'=ČP?;O/G`L|t}򅅨bD9-'楐`J"I;<!K{O7ʯM_m8d|2#&v8L9E!`]r[=u3W$%/Lrq.v>R&Y>"~hF?&1I>X)"W˪٥ܵK3l ƅpxv$˰5&Cʲހ?UއL>݅>`ozYk?rt"fe_3`eյ^s؏,~$qLξ.H@ GE u lc{]>[$/@TF5fs,2a(N+ZkGr)yZ#`"&Ϡ,>I|(bh=EpjGdq'FݛY'XUּDN֌6yNFJSR3ԀMDnK4H{-0\ G?_w< ={YsO~%3U4݄ax< ~>s"GYl?žg(yd z ݂P9PZN)%@f"eeΫuR&YrT`st "ȫ^hЯǣ@9du&ˠC t/qMm"_o=v8S,њ^ UU9)q񃫜L6<-xY3 =\%l4(s"Ez|b*r6 dF颸m(aQ%1=$s9Sv EeU.˚⹈eB bMJt-<%ή:?-pcoŪ~vm݋ډu"F ++WY\PD-`$][lpM^H{Ȋ2W42^=9 sL 7I.]`Ye2ބ^s 0(9|%)Aoxs:g8DPBbS{=2Md\n6mbNz ST&f q2(vCIQetETOV؉ؓ0Z$&sELŨ0UѥhT2/`3^qT@2pB-/؃t-wJ߆zs3%*ÎGF㷏#Sxy7P'OIb2wB[g0Or(3M ԇ9!ͼ@LI>GΒbÁ){3_l7X+ ѱH`Ҿl6'ra RENwYnK X]mLjQ)9ys('-x؁4*tTaeڢlgWAGARwE%Yjn?F,)uu_$P_i̋(5Vp<㦯WFB2kǙ Ȁm)ź4Jd͒&´ygv:qK| iLqDѮaWKlu{@}{m/+B-RZ ;D~~yj&C'~,!hO[Ohu_MMBh1Ls >O8(wxu)?|G{b6-kkdgʹ ^ w8a5TcM\[ &êISmhďW}|RUR;*%g!؝!(^";hCk&CD&N >隕q+{FE6v9E/n}XuHl Wk! }_nąPj G$LrkUSnGjЧ^Mu. N~А{&cA"24dU{åsjo{%! p[djT&$A"iⸯzH D Rpk)YT.`eGEQSNyYNI`8$]8z 3PJpGKic#Z:1xhtV YC) Dn Aq0l~im.U*0|7<;-ł[UNǗ:F2Z^,nx]fZ9Y=i o{kU?fqܝd:0:A!hIKA!DW;&LjN.d"<,eYɦۄT ʂR(W_`ӄ$m09t|Ȇ-{3c}ȩ=\X蛣oŇ<~;{%/gǡ6XЃ:~2W.nO&H C3X endstream endobj 515 0 obj << /Length1 1398 /Length2 5888 /Length3 0 /Length 6843 /Filter /FlateDecode >> stream xڍwT6 RDJD`Ih"^U@IP )7*(U@t"EEEus]Y+yg3}DH 8!0HA 1aHm, tB]`1 XR|K@0@Ujp,[ q<P> [܁Jp  A 8G+!#4AAp?B:phiOOOa+Vqz"p@c8À-!? o    Gb .H$dh poo } BQht#\@u]aNA΁, \ v!@u%# P  c.=!\ru#qXy} Jwo?uF<>K$ ;Z pskT8Hꖘ{AEzῌs5?4 'C ?,a~>i0; G'e1/%@?0tɚ0 oik i_FeeGHL($*AR[?B_-= x^E]>?ԅyt+JG(+"uw_v߀qExA# ZpwoBX%B`qao= 8o֛/  7Da_6–A ,M,apy. K:ԐP|D%$  I}5~("D.@B~@{p>h )0\Gl;CH˿C(LSupA,fQ.axIg`Nmnٳ}j8j8W8b.&q4=HV.]"2dmT9tpU1DvH~k{eI.#m/qMv;L|r}mΩ#z띦dp;W(NMMU|:Ϝbtz;+s|[K[7xo9&G ʩHTvIC|>ּ# zvXhOw-wzrK__x؇7UL&ɷg52j!j)b*_4};9"H»{>xӼVeI(d }4~f7&XM-4*Z麰[`*+÷J|@(% ~$Y6{8FTh'm7H Q}? NеxgWė${򺨈'~7h*NǛz}Zo- ܗ%.(8 ]}D7h-qtNSNHK-%r·~s`eΔajqfw]ͼ`a?y'Wf5=uA_pb&Lt3ZEوwI[V9\&k۵6ej?ڶ:={y7hjrJ^}J#ICH?z} x"7_^EoϷ+jqI|z2CMa=~+x?.>;B"nL~~{)04I7rE]hzcgrŞ,2 v@ߝۋ}EGL.՚~E}3LY]π7mD(#W^11zm[y+` 8k1WH`8"p!gPdaO|Ln-&텇T}W:UV;Fx^c~VxZe$2Z_,SQ? 7JS"Œ-gSowe?iލA_Wg :NSAcg3Ւ>xa\pѳjJޢ2Ff*hշ2*Dk<ꖼQ!E L1ȯ-6;!tKrJA3q1"< ֍} ӽk~;ٖ 'FyQwuc[ęTe,\L5zçpә1A_k`u +)pF'%Qc X*,rXgH;u|"WQkGb^nހjO"5GSvI ?Vy;Kʯ6yJb]LJМmP!G/3$$ג?=`Z@^ҞYXQlrgmVBnD3_hab؍$2J8aڗ338(3&t<3F]Ck*+&z{c1It×/-tӢ#Ku]j5kkw+Fz\@d)ڤn(Y[9n/G&FWc+ږL$K|f>Rxf"H~DA=45pQB;܋\MXo_V)ۙ*3ǚ2܎Rk".0pLMS^a $Ia/8yM+2Z@*a+s^mF mwܹ=zj7g([f Z˻L1dUOǛ,HСdyAJzKh(ic $U̼{-ǶSr/Ȍ:}: w6D?~ر ynK69i@CqgUjP0|9mR֢(+Ei1 /Wf2BjC,! vf$*~MlEMp ,c-pP܊ZbEsyLMt/|)|up`fTbcχ'~kB?X[_lvIQ&"BLcy˷YG+ [ {R \[ĮT׎n.nr>?hju:#QH9WbiX.JZhVpi2/܀SO >Ɇ&%L8,̑ %2s?~MPJ.=fAH5$`UƳfPRIŐK#7d.=xU{ȞsRA{^\m5Kg5TEx NAu?&u2U:[C393֌ |(%hqX+ƧfOJ݂Hms1JTe fR=]X~4!Zឋs"H`{@8.!.1xU:A7K,Dg'դ[=ՠT 9rZk=$3ڜ_%t,IѬɼ3%jb.ڸX(v[gT]FY[(G옊`N8*6:[zk\J];t?sU֊$39;>|g;VY=Te7 2N %_ivM}ݫRtSU-(t)Fq=vʆ9r,ݤĤq8+R}ydvI9M9Le3.jL=xeAVsE8.U\+JNp{cWz%nP(/zu9˴I8d|9.ҨIE6+]rg ')CXQ-xߧ~܌'aNʓR ! UI_űY>VMh#w(o9KӲ)@@ nK!a,S4X"ϊ˯F'DXwooj90a{` L/L9I`5U-зݼe{/xQez_n7<4mtonzC A9*6's&lxE+T եSkz.޿8U%ha誹ȶuF ~@[ϥLnsIz-qeqCѫ\<^3e~F9_\4 t8Driج}5o$*'?x"T1UsH-~^+%U{p#Ywq&aP⤉%ŲvTh4avgja`6]\+3ݏGwsKt4ljnvEA=d-[StjZ~^fZP3#mq7%-N&FCAx,6fD_ZI>_׊(fF'Q ԋ=|O{xJ_uN+3s0j?oՠjO޳* 2]Z d+_?xD9\WT"ܱeuWKXaC>OSzx'H0%/ ~Ƞ7W gUxkWB=p:6hn?9G$9%jJ tn[(k:b\a1=RZ߭մ)y xe+,t;c"[d4im35DcF5AH%DQtD!|  =Nݔ#0z#qЦ-//hrC~6~;G5ֺFMzIBg#WOU˙i.&?pg6сJV-Lt8<\]p_Ĭos&,yxVF Gͼ/ 9Xh%k?R+3y5;)y0\A=)d-*D/RdL}T16SI"wV$Av3/QQ | 嚟\8ҊA+}hPnչ[|2}u^c(h>H\I-uff[`9£xUCαw6z5tz0#Kiֲx̯0H38MxmL}Gv endstream endobj 517 0 obj << /Length1 1398 /Length2 5888 /Length3 0 /Length 6843 /Filter /FlateDecode >> stream xڍuT6("LABa0$[mlAD@;%$DAB:D3~{}?};NV=C~E(FAB a0mp>aH4J!c``ަ hPĥABB@a!!h4P삄h ༏vt ߏ@.7$%%+ !`PC!`{!K9J h \!0,  ;&!C-{$CQP4T:PZ|? ODHԯ`0vpܑ(8ij p|@0 Ǣ`0lj TU qX,猂?YvppXvEy}E?ǀ:; N0u? ń$%D$Ł0' Y ivǀy#ma'00o Hh#Q0g1H7~ , QXPMOQȔq*)݀" $$,?x;bQh|~w.HG!'A rt !1! _!7dwloH{?x," -*;j\?3Hs4~egZk4v/DiўvI f&YwT<kGjDY icx G_ + Ʀm1gj 0DxQt_Tո8(/AZ(iF5,]= 'u%/ &5 d Uy6FOl2:T -_ܛ 7"BPpgt<xGBeRIGЕnlx%l_lq Շ_Yoz.Z\f@n"1b+;4Ij!#] .te& <2?ċB\ITj#$>嗚 7 4U[\ݦROi͌%ZzZT9u+^Br4)O=_?LfԢ]c#UF f}d?f|/s/sU{@Rcs+aU:h;\,iX RRl%ux1d"%qMꒆ|KYff$e7Qk.a+;z TL;߮QVz<D,2N|Ns=:l4`Pxo-Wb.;hi+> ?ɅŶSp.wnCe`aPJ^!M$S|{1K gwY2\ =̀|0Be= ~BFǤY 0GFBџŖLUT}N^4\aAT|~40l3ЗNe n]/a& ,^/+z`[,;_`Dy鲅]sp'JUfԂ)Ʊ'oP^&!`#qNOMUyI+PNqahN23Agc߭]'>)ҧ:Msͣc`D%Lu%K:Z$nD N=^$cUE ^q6Ǝ]9k-! >iV@ے U9](WR(o|@"Δ9K̼k7׾L8>׏ayi0Bڍ OEgKׁTS$< .~us%Ucݝ1Uѵ_t J,j ]⃒p7j]@bpTEFN_t$` gaI 7r׍0oܸeaA5YyPA})~iw6s|_+3<||/Z. !3td#d=?pKTXX-G5L7vp*rP٩NY ┪ůjvONF)_p!*&|Ua\[QV oτE\xAGrUvB=t+bŭHvDfhc_,!B=e>dj?nWɻ\ZKk"g%w f[0^ň|Su_? (51zkEWa|f m-8R JڴR3áDb[.ʖE?hkoAXc\fV^,Ztm^qMY{籨|# $ *߭SR3a20Oh{n7}ѨD$q$)Ԃ;G/9 Rڻ^ *}<9[fsL^`-iwmf,'<@{ +VvF,(*Cdg),VcW 8>S) Gp`VO*>&%Omot g_ra:#2"Ɨ 97cKTܣqa^={rÛ iPJ6F[Zիb&WU=B}k--_= .HF,`ZzWMWK'bV[IK_ica9 ,Jh~$3^Õh֧}RY(3q]Laբ0:wR]@g Dŭ37AZhx*l?T "Q\]|!hΖkAҍM$C$Q>A%~bvs#>bR_7T̿xEǾ6 tk@Ԉ1:cm$i9MU}-@3?nx{W8M H4, CY<V('^u}gw2MlT>8=z]0lFڒZR)-gB(V6ne-1NL{c#lc^ ogeծ~Й;d<ܩfp/#°y=܇Krɝe#cMZ_)GbNrZxYr@zNM_L*o\/iPa T+L,iNUuz6~ ,כX_*YU-\&,X9u{ՋYta)L|@!v3~4Y];-=TLڿ ȭ~)&{%m}܄4dTs*˶A[B=ǯ$ AONwew\rm_v?=yyU?3o$jHI6#d4d]+$?R}Oе`; ԓNp)},츅UG߃NiN3TW$]5Yjcij|ahZ蟅9 lH&n&H } MxHzRk^i>p?qu y*~=/Uѻ2_R˘aG쬶MF6/OnK?}" Q|NeiG4OپASUxtI^¶5fh"s7*=|fJ AȸJ(/BOrgh 55ɌjބI>e,<60)_aU.K/v=PX1,42z3>o$@*~K7}2SxP8ý5ɝmh1>mǫܖ_gy$Y_o(hJ/ȼ=ʢ S ^Y(N6oY~qZZ+"׊ ;"]Pn)lP֒I6djgǼ`̜Yߒ9e!17 xA?PU+ٍDv/G?߰?_j_율u++<3 ϕ-'2ᡟE/ʌTD3mc* &|T-Hyt(u1 6~LnY!O$q׹Z}ngydjDLK~dK$ߘݙP +sXIL|9*_ttV5> stream xڍtT. C "0twH0  13C HKJ*tt#t ){׺wZ|{gww?+g (a(^>@AKKM $P#䯛@B0P@@@(O0#@@ PB@TEP H'jkW ..w:@ A0eqœ9`(\v(?; GJs?CQv$ r``EmP q8B jgX]oBPd wr<0[ QCy@0_@# + w xH0B!FUsJ0kBO1g0;aYՙuq)`\$BP0x7t rc&r;l0C@|6E" Q+-F7揍Y>0b'C/k8?S4P3cp8WPD1/>, m\5 ]=e n?i1r3ysw⿪X )::sa/ZWFZp` }Z-5鿣j(F r0[ yP2b Ep0. qd 1!1jC^/?Pֿ'(B @$c,F(L 3 f13f7p_~"Ss @< ` 8Q}EPI;ڐ$^҉ P3"T҈r~zڌFt3my^J*O#^f [f#xcF :' L]Xw#nXvsPx߫蘊wSUnnn-KӤe7Yy5XAw/s):p5,,Q;UC$νRO_eݶu}(JG„Fs/2?mPyYܒݶ*\N8>Cnw̨$T{';[=l(@!0"QJ?`u2/X^HC բ#f".o ywU\ @4eڟvASe|[)\'F3wbqdNF}֠5,(#NUl`vk,mьH0Zݻ_0+>ʬN@Pف'ooRWHͲhE'B yߘk붲jrճ8Lo6e7:=)hrhԧ'0, 7͔aqݶQ.:2*H%A yoEVd+xEG Ive lyEis蒥ƍ8D'nLv>9QPFF}BI =`b[U|(?LJP=TtM )0y y7{KjnyzCPfEg NC )vFϕQ;݅[ =M ԛN9vy"V`̖#,Z&8E}冷QO -VE\ȮX{8ͪ7MSgtǡd (5&twmx X'+JɣC dY;ƹm@F!7 wy)Fy~ d!$gdNZXPW܏؞BLƷSy:Dvjqc/I/}D`wֱc$;=X7\]8%At| >;5m Q??-z+}R*^pzmx̳!xEVm2ӊR5hZ`]0C8BXKwSP=ͣ6BROLVYEnkD z>rLIsTKX i|OXIz&lCڷgXOʂg'[CCs& w?aIܧ  WEM:&49R#;~WI8aF J*סsncij?UKCJn;.ѭ wga˕Yw.${enj+ɣgnMȖ 76\*=*Aky_cKӟG|#p*GpiK/pIB6˾&g7q1 ̗~z\| ;$.ĵ2TXl+Tk6K ʉظI#P7m\~ycOLmAߢ=>*˝'![0@OS@yLgJ^uBt|P_=BM6ơ:FO{%sQ1݋1U3׃C]%yTR~S˩|بjEwߜxA"FNXJU,)1s9 K( cdBMo[U &6,?PqkhpnuWo62m0z0Et(8MfK75sY |{P+ڴƂNu &՗v Ui27qd{s/^W 侲O,jgaLX~)2e$`yL;oX/*ŦnZT,_"F[|8W&4DIa3Sz.4nr2cx'oٝ¿r<:q+.h$8*T7؜|+R<_ 00oĮ?*-zvSmȃ1^tStw"V?H_ϔs_ &?YSL 9ڇ;RP)39 JH&l7_y_=tK -Ȓ,u~kpShRWk5!)Fm_pʩmTHX]oQ(`ŝl?I~ H/LY 0͓OC}d D4M/jֲv씮bblsy`/hWT~W_~0o"K㳮qx3Ch5_k_+sjWЂ|~^FkdnB˝x\|m goWLHf(Q!X2rqjZAߧrM~91"XZ)"'즶(Ir.P9 .6M?%G"[!VɕҒHNow oR_@7|xj(AٔyZbE ._:tϯc/r+/m6ﬕ)[rShwXWKr*wraƛ(USYʟRg0Pe~꿀JGtb7 ˞X1y&pMO6txɄtͶ\ȥ$i48Nja7gURՇލ7qO<ˎ,f(rc`\6|i86`>r%XU0$r| ]Jeq;M6%ړe$ 5'R~%gxiT4b޴?aG\DGpVȉ@ݧxͥ^O"H$g@K3aO}DL=|OA/5*wv?JToD~2Y" N{Ps7>̹JPַ7Ӊt-B`3/NAv⁧9=?{KPe|sL3rwz(\ >'˖O+JÜ 6 .'v䰐*Ԫ͓Koݸ=revy>.$|N2r!"b~JGJtcD]0@z <7+SOX-۴өbuz[M]I&$O.NGQem㸻b>L7JV%kqT.p|׹J4tfI-i|Л J?'`U+5ܥ2(#Oqeͥ9i7ȑ&CN}Q;cj.g"Vj-eUNok@] o<țY㼏-xɾzBh0[XA7ND_Bv5> |{1H$)QKkZ2u60ҽ#?Sh-`KYTQ@݃z>/Te J6JuUR_])Үb;ùC׻[Gb܊3]nGo9 Tw4hUAF깞;džKYjYf5o"AVΟ%/FU%W$\7Fs/W{sܨ/i$p˖&N~ee/և5_(6t%Ӝ WUzMq:w4qFf_p"9ұRVh5/霃I9UMu1}JOT^#LOi KiPex Ċ'3:Ӟfj˭^L!ŏ'kwؽ6d-e&߭DjiUR$R}.C*V&#»'ϻj?NbZ2&(3炟z+G)QDf󺈓PM?=pYvGW~Dbloe(Qg"CVVɖK0]k+M|*_i)f4ljPF6Z Od9bB]b[fx23JtI3&ckIq.=ot3z\7~0-sޘiBfp.LMa+i}4> stream xڌPl-;wwwwwqw ng9yޢ zm]۾TEQ (WTce3!PRjظ-F89e 4u$LAvN9{+;?N| SO "@@)jceJ?4V^^nD6榎ESwk(=@_!hݝLܘ\h^65h]0@OeL kN^@H`octtyx8Z]uY3c  ?;㿜M͝M}l6@;ⷡ d/)QU)fjfcDa@]twrp:!'a 4݇9:y9X8ZX.ÙY(+o daae]@osk5|R*svrXXAL=wW`ߊF swOth =V|2͗YOOQNZs1r8Y!è_N؂?=4>ZRrm-@g X8YAXW_.;m7!){iMl}mZZw(:j9ZEʺA?mqZظ[-5_#P`@enz:@+/t9RqrL]]M}@C!N+-Zb3;*/`{\fߢY0A<f?,`XYb0Af?EqQ@\ ?E?EqQ@\ ?Eq@\  ^2e0u폍ݟfB7@ \M퀠˿#k fdڟP-qpCb1[A)"Wz1DEEj|,6r  (?%cl t$ du/j_O?9AcKA8Q9ckl9@A״~$@\<~oߎ>VP7rr:pzDNP7Jw7u+0៴6ur/_믭y{A}! t'=κk b?!@7auɜ?̶!^pJpP#-ߪk lm]m;Ѵ>}I[5Wm)__f" M2HOȨ!rb-GYR5 er}"bPKr1N3 |,w Ɲun#D.!4Oo-qwZͭ_cbO8]wSЊw@)I>2C#1[vZcKgω.փ4@5A,cW2e캯1D]bwZks_ Ⱥ?[{]6Gdž#2F[{˅ X$72+'!zXh ki{gqwWU%f}xY%6VK-8M9SZ4~ތLC̓ԡ%U[CiŋRVtUqPD pE>XmK0[C Rf7O8xV5T?a4~xuuPX(fL)-Mjy*X8<`b錔%Wq~8r{vkwkЩPk*,k=q\(p.ĊnW1ugm @$) OSڋ|}]'x#4/JOK~ 6Me=T#dDZ#jJj6(YV?B=d(LNaϵTd+#US`>9Ĭ-޾ϵA!o_сvI&㧶┌;Ks`} a&+HIsi>C}aR'ρWpUg{S<8e̹`RW$>樊3҃zoӱRA0Ud}rB@-m1€oZP#6 ![j88_!+;Ur;ftqo~!kz<" u NyjMJ 5{wT_J4b'b9닯9m\?5WJLWy0QH?lY9RʎsſR15Q̤cSDzn/h #B&$/Qh1K+$ޞު7wl&nr1}q`єC~"PŻUZ>Q Hv3;+rvDMꅃ)V·Do~Y]ZT$(K!`*EtŊ`ўAJZ@dr(ޘgDJ֜}շF)0P"y/|,fx9xw}<2>Lm{5H΢L+lf^s%;P#"p*6/ {_#6 Se^C2|̱I~:) M2XQi}Rt68WqFJ; bEВuJ/J upjK/#g.+H1+*O?5%No~^ˇ,R74 멊LʮSz)rEKn׬Eh)PG.`|& IO^i{.l{ ΙB]!ܺif!x۠KޅFQGO֏AoniX}C7׎zېt_+n/D|HIbpᘴO/Xpw̜íT>ZP0M-dS)8wCac"f7?17[N | %5n̏&v9_ܴ!}=kP ^WG0*<"Il:$=ד%Z*=y䶩~{o`l/KXhdb?9Wo^ve aXӧ29x+ظ徊41CG7[Ve@qүLvl #Q5¢zr𩥵i=0&fD&fjqn._by:E4,f&O̶%;[&?$ G*Tu(`d˿N˖t,2^8bW6ΫH}r6=6B YlirTAzy``OHiDsP^@{d's]Х>NSk T9!2#Tq3({5-g@yF|fq2~ p?ⵦ z4n(rhb4&-YS5+ԁ˅'vKۺ6}םsh'Dw| qkİjQwt X{%{Ӽ opx4+Lu(FSC c\C}di:l8+e{̛{(|%05wVM]|.anZ x<@>%^ڈ:n2Z"8g}61,(A֯F3뚐+z }jJLT{ds``;VmT80`0B61-##J^MLFP73gFYg y!I'>QJvCF/蒱^Uv?)Yӯwtm9ǭkwX}4=Oh*ylx{a3K$5Y|e;tjyvt_<-tJ;Tr)㘘FO"BMUqpaYd⊜YȽgz2tﻤ=3dtr(=kupDTsrHUGQm_00oӕ )<i _ǫUx*?& 6M}wz$k%@ ZWɎskKc?u jqoD=#+;XqEDȖV@@#Jmh-ps%!ޮ0[.=;1":rh 89U%:lCn|*IEۻ{Hw=e<T_g>R窲{ƓߐOUښS%2 *jm{ַt]6>Br:u+GcPDiSmYIWZfa IߙȊ77DXuMմ_w`B:9,ۤ$Z֙Vh@C2;z2 F)JbψGES6-]w 4i+h C4&-%h@mNoTbThN%gɀo]swj@*rb$VedbҜ'/K+ql [Ҷ (kXaҜ7'd6dyHi}ՙHʧC޵FuR`E>QKuDA%/-+)/r9_pkqO_QaݻlYgEƮ홭?! O>%[5QcK@Wں9g3bꜼ_*rXktlUh4Qb`icSÍH]ku}KJ#p]3E-d LBm\ר9&C7KUb&kE+Cp6pMH^Ȩph26HbH*&-f}˧3bPm; <6%?8*&_(s #yN2;nx#bIСZ_}TUd1[NrƱѻZo-K_[{[1 ?dYH%+G22:{~X8=jdP +5;}9VzjƄE$U&8Q e1-bTt+y16;/&M";O,b܆>@L}`@OtpU( Fc>CHY7,#&OhQ+@˭5D,Z@HN׳fg  YaXMt5axB\R-6#%X^p*2ˀ/\;7֖ݳ ϋ11Tvd%8҇zk-%݊w'W1Kd#6.7]7 9^&xޙr $B9L/`l#d^hM|@n!{Jo'Q.l-;&jc:;K;4'ߜ@t=/[8 ῆƆɷclNV"Be-c^~bQM</# E:?,I39ɑوZ f$(9/Eۥ>͚(Ԑza!)?PǎN4A^{)_XxGP#hs$^d)ѩŏk=U4`fC1Gzذ"`QHAVCaRFB# H&tQG_ `fbyh0Tw<45!h⺆|ܛZ4X+ vZZzWQ"6gvPSU#kf")[~˴KD$n w6..V~!IJt,q;EBpw-Gk݉# IlL"<@$1Bk~|05 t9[Edc&K,IxF3OV4r+}{p}]rqRgX_O5R[uOF5^wFXMǧ"nyHF) N/jө{J '!GVaY_,3S;,4N.^GVQ|l OFızXЀ9תSٚ~׬wp$iNL9nV+x#*2 x2U4\\=%2_Dn"#;]q1Rr.*Zecˋ;f1\ڎf|jxizA˴ZANlxtl}R.E"xTBu*#X6.X# ) m"*c-trMJɍ}Nw(HuhDpԙ(hy:OZ1F(vӢX[SFNk|K( ۄjf,$z-4ց(WUϗ"F_!H&Fq=EsɑEfz 1ɒo3D "Xr5̦m5?B%r{VۥPk&Vxq+ĊB \" a4*Su'+5QG^ ф/|Y,Ô 3$0qwCL3&ܿԂf2L5Op í=Ъm3X/݇NؚZ5FMkE)*!DQKΊ*NCPH)3n'$Rt+F3't/3)F\,Ubh {iL#4V#8LAVϋ?hG 主K͵ nBuGk /]o/ӏ$n3!?vT%[Mkd[)Zi[-=2ns~ACtR xj25.vK*Jyҏ.")'PED\9J !0+t' >nox4k`n%,7noZ Ɏ@o{8AϦ,U{s2ҳpa(^.2A#l{?ޞKޮNPC!`a$Uɻk% 滷#tx !9E#wȰ~ t(f65ń/.->β`M@G\`2k;%o N|[̏ipv,MRD@UO ?-Z;zvHAiC֣p",P|Aqoc|~@Q;WNuQ tR/j.J7-?O%eHr%⒔kC_վj!&d^\kL"Ÿ>w%ڥ>&/JC *Ra1Eej5J6Qm#."@ѭփPh!*w0@]7]y`dFsvL "v9wi!3hߎ=U{9h` 72\4|R=nœ{Fv MvG i(y'G\>eHs{tmtG%Wj3 ?o3CѺAyǠjg@cx@aUgE\y}u]/;h" GvvCYQԩ:6ʗv盶@ Auv1G 6bݐjӻiJ&Nӑq`CbGe9B[?~g +;HJLW쨳Y͒QћIu8גmcu}H%ѷsׯ/C7:<%<48fq^c Ť6(tHuENr4pqļ@ JP#VaY Ҏ gl_9'{l˥Lox['ΟiAFcgPߎRQp2L">M4f9߆-o-bwЪG gmpIHx(RCa k\*"9I_7- O1N̓hpf4'F`Kxpr*3~ߦ 8Wh䨢VS \X\#ҕ2ύEETsY͝Y [+1WXҞ 4 ?t&3gP@; I06t8M#S˲L wЊ=$yp?+ZUv!%lrvtmӷ"M(>bτdƳ0`V(7T>{_Oa7%tj}(7^lhՓp ٷ!Isfˠq~Iu+_ NΓmdDp.=# ObnH QJ?ڸ#W'D%(|n/{\o de$Er1ҚμXEa"24SɄ߅Z.A鮹:]IltlGa}" >;E`b{dJjOaJ$1T'I*nקiMh,yp~71#U]!V͹JOGBϗD!"'_L+r2xbȬTRiPmNAk$zg8~M̢H"hXxV@DcDD2Zx]9k"J+2,+~ᘸ?"Z/g8𑀤>Mzl{ӫe l$]0 Q(2}Gn틞=ݯt^]|hmM.&R}>jh Vw0Tv֭Ziwee qFF,\$EӶ jM?W>ich;IjOL%I/,=Q^gGpdǙ5BI_yV}fYcLg9^ZK<%$Aaaȋ d3,%ikUlه6=@Fy2Ln]t29n w-ǒ$q!I2~no|A6&*HkIJ_G$ڝHtcdܐ 2dLI[᣷J줬(j()O iH[[b޿u?4uKp=ZP_l 0T'eWc ^f \/.t5mybhI@#c(mCp+8[hZsTq j ɭ_oݻ9:$ƛ$7F3r js=S@pK5W(pw3Q]k¢~l2qxR YakV)tA%_'- |&+0Rp( -y-;I΀k+3f~$*!~rr(1|)Io! JkԦ@G^q,-\LvIjQTYQwgPWL-;u"@Ѣh-ӌ+(*.4ɴw~9ziKpx^zuΌ:=JHS9TA{|>ߐ9 %6^_AcoݤBbeP)ʍ6dlĻzqAյSI"S?nĉ!/$ /g Z`ܙS %f{.Ձ/)%5iƹ6Vwd]PxHٷ8PwrOy neZ#y ϰ.g89]СRzy#YS u_hF}CHx1/#[lmj챆#"űJj`ܻH &Y'/\ H;HX>ׇ XNgϬ"e6 ye)C ?CTogI.@LGnӸwb\FE*>fy6nPŏ.q&a-[~,l/ xzR+cӟY>/D #y~9J{9;D(Pdns'MhT\J\Ef+dt+8]nKKO&tj#Obw^\ЅDS}d %c/ѺumGk+ N9`Q;qոt/Tv1)/%I:lug6:BSέKnךMpseOAHͳ䉇G/D`P80MM`(0(<&d&F r>, Rsq_"DgM ӆꈉ̎Jykgj"MF1pۨط8Y{R;acMoV%$l=2zleZ)4aqq,N?%6m Zji5sM) [dNU §0s3ŠO&g8QhD![׼_%vlBUKF6ږ++N31o 5|WtB%}F́cvVr=`[b,'CdI5ϢϞh`j~yW6FuP+=)g2 Tqqصt *UkJdmNZpAQ1^Uq |K3njauu#t)Y h& P)r`~sKaĖ Qgl:m"i\e \Oi(5%6<(x>4 |l0;9N"8JcsQa,T[)eĒ%<ύ6mZ$ }|`z7 kn*C,sU5_,ܱe_8mibg6t̚1ҭ$LJOD+ͶB s%Sh+kﴨ^~>u Η9u0׈YwHqaHzu9N1]a,Qs_Y 츦;@lCڱ:z98~\Dec 4rЎSlGfd4f=٩yp*?,4 @;\\7@ BS0ineqe&915<< 69hxK!`G9A"ًX)c-Lm (uy \ȻsPp>ZY֯v6EYfv -I?:pgIȫZتr>W*Sp pUW;!"h+6 N&v䥾`)hVjmj3eB8T\._~rWQxV۵|#-301,7^Ka5\g2zəϨĥd4c_O ިlgSсt:9}CDy66~) [jضn׶űEk}KtMZlN/xU*A0l]][S$iܺms+!cs?@`\(8I s.R&u 7$e*VD uTTH\ulaLc:8u} 5K`cYx&uӱR6KUM;;),&id%=Zlgzkb&սҵ]>^ZQ/=c .`Yg\ժXtO| z 5OS9.f&siڌJ}+}{oj,#S,سg򟟣82v ii8U{`'ѐ Z"m#0u r?G"Xc,THPlE~ԓu㕆:X/^9lbճ&c5Qh`3_(OB*^watNIqupF<y:V!K5bjDe^e S]ͱ IH1xrNIT]wt#*ⶱUY^ azZڞxߥ! g!Bp"7flGT}3ȞIs43m˜o cbP˻u[&rσ #m~~3?Ar M]i Fˇd-lHa v_/x1P{C\K?+Z -קH3b9[ZT%$]Lvoͭ-~`^ _ȻYjѤ#*bdCVޏhlFO?S(8%FVo2]G"ů: s|f!ogtiF -P9o4l?Bj=AXrkL%:9*(ARG~'t(eMrd(ڶz~%uo8{3U>"لr0-񲾧Fn+ro20=5$!omVd^ф1ڊ^A!ΏUMQ_24EWN/@n*Z]ܯ*3}\Q4ؗ5ˮ:RpDA,w~عhM,ƖJE~y2q,,[UMwZ"X~2h6\TAo 0el l}c K[ƮPK^z³k2ڛ|g>^KIDoQj!xr#g<'HIDQ'#E';!N:IW B6 COa`øRZL1P%ce{ދK]Ҡp {zbi"*eXJ ]فTqFHӽg22+C7}:#LJssTߞMUKry?p0RZ6.SdhcEVZ`(g(B<8>Mv:'{GXSI$&҃Jg&+!j>N9@7#V9"Rt ҃eOJlᦕ)?~kp^9XXhh 禮Te]l8? MZUb+ّ褄ֈϿݛGu CK)'#@܁t"bJLrHqLufGw6wu n-5R{3 5U^ KD?gZy]`˟5 ;ǎHZ1>.բ_D!G?/'WGS@%_}nn@O'w0,kj'u!\p&Fh e<+뵋nb8IM[UzpL7F>$ÀǍZGC2SIoHǦQm96E/M <(v7҃⋘ k 䔑.1aI\NMWOUD=II.Lדj )|+$Yfw9JqDKަ"E <Qh=r_@RFw[QYr4vU'<rZRm^KЧlivlpo!LyJ?AFDqA4.@$?(%SssIϿ;B8ߧf<#!4AKiyMч)Äeb3FaDkFa#~!ge)MJ(8X(|C ,/dʹܒ.13T[Vj6)5@:B0{E)4wlV2F >n +?NaSue&v1t-.TIW2խD).j49M\ct' 9eQB`6W ֡ N'A#Nlħ]LX JB̮11甌 SbMf/.)pÊmd#Tm륪ȅą;D~$u^֌e~wI)^?d~Պ W_ӥ|2;qןG0D.G [tQ2ח¯Z`蕬j;o%QXદRpDyg̈2"$t8n~. Q"΀#p,^~p<6v ?|i6%:") fz|SEgs^痄au V-"vxI[{EQ42;?W,\v5Q 4CPcd1ċ0vF8 ռkfF$YO& R.OT|#LV/7n7AdZBV~tH%/W??XZ O;l7-bAŗM/,!_D\MO-˧p؉o"eFbiy9C}<}FP6nY@/8̏QvZd!bCT~;MvɁLT \<0h:Q5Vp9LQ5?~&ц^jVY5qDe T#cdsbiiΣ:t2\jc./{ l]^5w/Tɢ<~`u։w,.9'@>=|FfeLܒ˨a|$IA^iE_GH.T~JA Ofv[SM^)/_l+&`@Elk?42D.zܞꓧQ_4l٨u)|!Y!Š鍟<\凂.Լ *q8 qqO5k#o$/xsm@_䂍DIgƂG ^gV#㻫?xM?p a'i0t K\I|8Y"x ~p}5HJr/9Q] z%׀-nOTc@晳ܺ\J+mwK^;+pݚ"(6ulaĿU+W<F AE"GͭW>]%ΰ$4VBڂxxx%_W!ࢸ5F5DZ"<GqNjp:tDeOR [2e:&I8騧 &; gig)~_W\0S|tjqsYNПJ]lOR) --FޔQy7E/Bp+y2D0D/mH?3P,B#g`y?SA\n=S'@m9VCbCѼ2.5S'M^/h=(GС/Fr(ADCp=F4hnm0'pb`O P^;rzǃg$g@_qGsj̝"lAh&PCՒZ%^DQcs~$EPG+\9"ϒQPG\˼p(jY b&/VX{>]s-Z:\u@1xmzaNPs3~8 YUPYF?_3 ԁzCНX0lGŒ4k8rdo\K {΀7UL#85OE;}.\xkEu̾q&b[dȨ~Mm6bI1Rrf2qLL)y<\֟hЈJЀC4 Ნ>'IHi 8SX}/Q HirsR⚠giRX/I)wbw$3a@sK&R H)$Z<Cڮw-儾ҽ2#i&]D Z!PgԌ2$\/jƗD.}1A, `. (yf}e9'k+gf ]P4zюCl,hQfឭeJaH75,LzѯN"{wvZTz&pِpt[Vw GG F `l9v 7Kn2G- %7 R+BۺhFYmygSOUMZJQL?MMIj *MQnnyvoȥş;kJ:S*u M"&JןQWvvs) 7v/]{IȲw.`'5U*#SMM>d1ܸ dN8p$7{UUo #{p$%3@P7U)$p{.|fv `AH:SB1OO*pPSPuƔͻ;̈0ěn}2YK(Pmq_3c`9᧐ mR on>Zpl!hM*!" ﴞ% ~ُ"@}X݂~,\{0A@K WQfUS]\bk5W|1z Y /seX1df[hw۳7×-}iRLRQwHFy@ >d.nz zYd;!7R-Fwd7yP?Շff(2"7ڬEi `En8ۛwvZ=p yB(:Zp\בc Ȣ@𣇧ɩds.Ww:cܑ{vzW#O~*&k E:kAvґ"KCWI\36=*`p-tr*R5aR ݞ0!sxHZn 4nN4z0(?|^T>;OwfCPWҫNUr_*{81; Vh2U%@IeuyVMђN[ D/VbEhMO$wBMP_aCk_>H:L rx&15T=C> aT (W%S JFJb ^[Wwn@Ͽ0f'X}}d*F[kcXrT|R ͝1qOXA{1/O.er*|_v#'1RFѧU>GLS@Ozl̈Lx[?=a |ᬭ]u45Qô J!Sxe*'K[24Jon"J+2{1Gk,>FV9yswaO 1 '6o-3 ytٕ5W&c7w6kAq{ endstream endobj 523 0 obj << /Length1 1511 /Length2 7868 /Length3 0 /Length 8889 /Filter /FlateDecode >> stream xڍTk6L) %5t7Ht0  %ݥ4R -Rߨ==}kz׎{ǵozWls cbHh89y99@0{^uA`L 0S..00''S?0@d Pa(B@g,zi;dmC#т %$$ ,3 q=@bQspssc7spf@ŘXn @ -9ƎEв95!V073(A@3l w4j@c?Zb;_޿,, f`w`ap+ l7s5ٛ# ~'nT!:g ( U!ǯ0&˂-!@0W~2 (uwcCV կ,]9 '_qrr qN †Wp-wGo%/#`( "<\ߊKX\\K `Vd 8A<.'#,!`{C_U^4VIIAO6!7' 8x;+3_Yp$vk-߱T!ܐo?v!#bo[Kњ9#Cp_ Zb$7,-_`6` 0AqqrUvG* bi},bkfP;bɅXCK 7` @ @~$pX$F?oW/q73f"0(|8䟘 -\P$.@ h5b!`[tY.Iƶ1b~C,'z"SY2db_º,խ^}5zpCz׍IF#(ї=ɪn Lr6-M['/_;zVE,'AW.ݺUEA_77EjG~6O"yc`?NReޏ_ᎺX,vn##'@=cNR$,[2ͣfM^`cN-ik;+\g[e%}!_QXJFXhNRlXI-6iM&L PW`g -n{̓v4{NAvڊTV>"_EGy]dj7ohཝ=3cP}ɼq9+tbP$1)1+-5?= JG㨷[4k^ky7nm?GKlakĎ}ΣO\,LqYmꙒMiWqW]]Y$Uw"RiL]Tr4_K|gMtӘ8hbDz鱻Q_iX>xOϽm$|2_C8+hfr;-o+IԷ,>-o (bS g@x>;m熻$]%_~Ɔ] bη[^UԬ 9\kِj\򀱟8N8QDYnQNsNg⌛cwu1 AC?Q.b(K=nkq ~B$ 4dq!je)NjD}~z^~i2r&: !g"9WOOjk}l'ziJǜbۊTq}l$K8hSldT$h EuMk:?@8P{ՍU;f w=as* {~hVo NP]`^a12 >&yލfOQ//5R$Mb>ͺhRmUOI^V#-lV^TMCtKl$peg䟡Qy"mx<}ֳ^>m {=_Fj[HAɊ 䨈%;|r͡F]P r3&K-4%}c DE׷=R266[t:s?_ ?/Kit4q3$KxK &~@ :4E#oy5d| 9Ꙩ 㘥+e8DiwxkIh".٣6Є  Tʛо4/dn2jH__òU}| G(. 鑪0KXm) jPRyvt=as3oPlgxO̡ZzfD|oهQfq+j9uε3eQkp0?^ϩ zSeba<Ϧnö,fkS 9[uY$ykb]/?^)wo'b`Y盡QvLsVDg =o)*ddI lN$OϚJz-ڰ#yH3U!ׅxspsfq#ѦTat\Rٌ[=T:!aߢo V 㷆lNLehO5H~yFãpGvɻ?)O|Jr$P(p " FS7>E b]BfQ?|zQ6wjHͨy 8< VE2D2i!udݲ)8UiG-H;!'X\{!$tˍx>) zY=89TX3v5·פz>e7p_[ՠر /"W9uci2jƈʔ[IE݂gb\sR Gl`0{.Υ>yD:zbb246Ua1,\"XpL%!O}Gg)jQug>tĀ3 s6[HQ 8mm=ڡK$ )VVڴgIu%}_'* ~+$-zC J GJCSNZg!e\&$ٗXSg殍X0Φ.:1{lk^[a%2T /)k88:-n=sz&E,wF'^^ ӎߵ]0$; 47i>G\ =e0i0ԋK2e۸i.}3iWoosg| ^ۋkN}%Ak[='ģH= -giaVu >0 W*B&Vzr/ ڜqcQ1mt`M}౷c`nwL*%ZfIkUe2~j^#rMCS4乪\gplK q13)D)R=D44>q!KM^nopan6FY C #}j V-R~!TwG]b+xdžϥoUƻt6D/%WQq.\gNJ  q}zRv=TixcYhh0 B [x;WW3fHyQ,Eu@Վn6N8pbz%e fggbsAEsTfߙCpjvSΠ Q$r [o Fw(OÅx_I`OM^d&?x:¼V-FD`#WG6cWQωF鵯Ua ̀ ^hw7;,Gl6ț \b9 ="Yp#19I=/Cpr:c]wQ/ +s*wleѤ"cŤX8UpN ##,5)n0Fk,&ww\k˕,.i䷀u1 PU=Twfrl$!hhpAWq(TLiG>Of[۪[8&/$n痟Sx_4OӨx2%B}"Ie[ uʏ߇mDW[qMhN cHE$șM% _g~NVCTG2w@w jx1N8#A h\e[NgtE~yJ9ْ&~ӓE U:jF<,nrC-iLxzHW75h~edYѢ5Qdc.(UM ?bl7ã{mބ[MEN*iν%R^E~X`DHbpz7hqԦJs1'fzL|&DŤOQ({ߒ* SOհML` 7\&{a$t'Vr19<\ꕥhzx5ngԆ#E f J*Bޯ) 5xVJr[Ѭ"cʞfO諪ɐQwlQِFxQ+m񍇳1*$cAgmt( \z5*5uhGUהpYBfz$"14!d(:#WṆ ӒmE[)YfçFzvS߱amX$'>!?\6\ >3zW3!K/nsXaטQ[r6եY}/!ip;$ Ç?G߿ zc1|-F:yvYy%2笫+Uݵ?WdxӨjSPAߩ2u9>/]O؋O*͘}Fn0%J#n#2G7~ݛQ=iLdj'M?myѰ2;G|y7-fJZ޳ˆY^e.*|bsZoܫ})OytYhVD: I1}?v񖥇^p'Ci#{ջlCC][>_ n oά \xʶeIUٍ{Z^3Yy/Mi?fsF%QX g GEJ(thRDz +.I|8Vf&Ō7&Ǭvȓ1X ckb˽z(#O.1-CϞ w,N\Rx`VՇgz#}OaƢR>2^.FݤXphإ t9G@$Tj^%wB ~܋ ݑ&<[hhDhS3tAI27JN"v,i$;xo!/qzNvR3 ^rBrl4e q,~JC#ygr<•UV,?I΍=alqeI僈yTBr۷ɏiC@+}ƞ#BI궾 Yr%l={h ߿(h̀pwGt\~щ3 "ii dM˳!-N9I՟J ZѸ2Z Ͽ})!;vs od.pnp6gK?P|Co(C;e+oN9/I_L=u{" Qvndso秱.S_< SsWFuVO_QrBŏHFU_+n k&+~ђ`NjqOεxԛXk۹d*ˉc;_$@V{o}U;}2QrM]|Ϡ!/}vuz }Y'Ӆ)S{\6b`S$H%- &A! &2WLt˷~Oq!ҲWz̦Q ùh<~ҰeFdndķa:~aUϠ`a0Y{n|j'<ީm#OOD"TǾ/cspo; -^}icռ- Ƶ;ɬtF+)WQbnƉsTˢ=(U8vK|E-ɂgxY-7; JY&h4m9-# MbMb endstream endobj 525 0 obj << /Length1 1880 /Length2 12563 /Length3 0 /Length 13737 /Filter /FlateDecode >> stream xڍT #ݥHpwwN`VHqw/P܋KqXys沽s$Td*Lb`34 `e`feeGcG:DH8M]_m`;7;@3?@dPd;]$^ +ku50:M@M`sJ Z:xxx0ڻ0 Wk P2C a rۡt0u^ v sk:@]Nt;XF?`cfo9ljnw4u9X,Av@+#w 5dgjWi1U+;]]]@v9.R`{{ $A@}bpm>A  4,Y4@Nn@9b^Mڬ.VVV>^ 4f#/'o+?G#d |@q1u\݀~>:!,@3fA}WXd0 ׿1?{|L\66vQ1r`ZvG k)_ +tV.V7r+WH/??~S{?us}E,8Pmߣ_49X*o3E P[-횿T~_0&6V{1sKU#J9-~;7 _u(-iv}MRX+E/`Q/x,f">׫lJ?N{cXץ-?k96mh t#rXlTl_ _gʯS6o+W_+?ֿgצ_c^IXD\\44<쯭y_{ ݜ_vk_Ez!6u!?kz0Os ^ޓ"p?P (Zuy^ljkŏci;)pM[τ EmVtj>HFGM)32dL>//2THXfggٹ.9JkɳDb1vrFHvcGc^nBy),^c C}g|3._Hw1?|=ç`F8{٢ާkwV:Y$#;0x&m[~BG*#)ea쳚AW@6,<)#: QhRl? WYfǸ)ЗQ4KXZht`r0ThߧB`a ?T;} g'=NMJ&jpC\Q0BnW%/@on6q_H4?(7/쿻G #_4-I0r xqGpXm(x7!+|'e3lXTh5朎ge,C;N ډf뱮̫iC3^qjGv|z(IHٍ2TPVQq$ MQZT`;:{H~^{_Eo;;|RBfZ#?Ah$ @Q-wAO$x ,Tr_Kӂ:~s̄؊f#/7,Ή*`rxHݒ#E_)lprvC̨kI> 1Nvtؑ%]o|{Y=OHƑ@z:LŖ}aVmw}k$CBvQ 07;; ){w*KO'1/>mU'Q-?׋Ȩ>0^jR p cHt[ʑܼ M BqA-FpltSVrHjIIϼEv}շ[F>9+= WMM{0V{AڶQ_ D4#.EQI!>}~zӍ-(O!,[ηRQ=;>Uf["[,}NyNlz(Vw?F%@;^LJ#Zgrx6aWfm(I-'{ޞ`CްDN6v`ujr/7ͪwt8qiȲd1f&(il)d-mAW۰PzeQ-? n~~`o얊NJ1a0<9>/rp]"0pe^tU ߛ]&E}X},ӡ wj hV"r:r8AElG)>FFY‚};xes|}QыE A?bBqIoR "z{TZ,-X>mp&|eo&p~~ :ފE, d{}W ay:91 ҉sԕF8ޢԍj=m*i -RRS:(HF*I24[c+Me':CaeIi؎dPgQ 8F5.|>H\Us2Lui)g!,r. &:U^ Iq`g.5^ɵڲ 릃c BEV7ߒDB5C;]7 H_ Xx4vk-/@)8f9l{,Xl;mh/$"$.bnTk|}ܚ?v_ϗ2kx?߃@en*c$62IZ\?gѪ9 U%aBmΟo 3mUyyMx[ߥf ͚MfJ2.ыaQ̃e}`*dfjcrefG )yט4[2B뼈ÖN+N~4.^&:XX Bi3ӓ] V'''&fSҾx[eMLxw^wypFgֱ#~9}0,<9,C'aL0f'm=f$:TlEBNڏt(rfeS{nϋ6XE%2(%FO /'4{Ԣ u _< lpn}+7CW_ *3F3]gj7 &' e6(to9])('eYhwu<3Y>odAv`Ѯ+Z1s"dXDlum yG2h, xbL@pmߚD&ZlFV,g7 ggrxGB3kB15v u1=x8ezu|}/'lS%.8W rp_?eفaLja"R_>&q?}r yY6S\E:֗y%g Fln5}Ϩ#6iΎ!'Ȱ6lQp}Sx5{{9e&A:ElroaZ0qݭxLh?qgvt grO7̊d^ǧČ!Y`Os'?p<cP$YvKT+&'u>(,;Sni\=:E+ g7ӛBtڗO$P](\vz:4)hC.~gU{^HxYz %c^\Vli6A׼U|$9?Q0}<m_w+|FGW,1ɛ騮{y;4_R/Pj{_ ٦L8?[/hs9gd}8*4J %--C4K|*ln|ݰVF{joyńVZ j}ج9(ךSk%3,- "d-/.T_Mu}+d7>%)e_[3Jg%kv3(mkwd9(\ulܠɖp|]ZZnt4ٗ++p6-A>lHܹ>wڍ oJgZ>&,D6',%a؍ n<{@1O~IǴo +ez-vUI#(t!Uv˸:pYy >iƤJtC0b$52yeYAٱe~(S('1) %rh;lBM\M9CVFHwnPtEy&!/,D}u$mK@Jubba燣+uOQokc=u[./h=[l~ 2pO A7,(B8 ]~jӓ~N Ђ巰p6st 垏73;3d7M-^i=d0%?[}a3*RA[Ex)Q5{$*>#Kr8#93}54?bXk_ ~uS%Be.YiU[+/D<q>v3C5v(RG*JP4qQ#NGv3=J}ڞRA7i JiuW#R7FW:| )Dtڮ,6L|P+~'ٷὌoSh$z )›1wg">1aiBᔭL=SvPy.BZhqTS,!aQ`i\ԴCm;^z`?V .M5(01{ʹ=hJnێdϔA)Ȉ%%GjgCs@9iޜuJf.Y. 3,l ó&AT$!XuN6W6czQNlO"gZ,Q'؆`?_kPul3nTrFҐ4ܝ ܢo]=rE *+EOpq{yug 6\y3z;y;^-CkkHOi O)C Sv kO#ap{ !}3wuK !Y XioBp>aif[aj N'S"S3mogY?}8C1&+LHhGʇ m]1mX}˕4XTw2SQr_iWFzj a3ت {tXIEGr{$)eN0kCGl57Xh9,@`e $ԏo@#j⿔~U IYOgi^<9{߱~#kyWnxSG{z-7Z=Z.Zjӏ>R>[㗣z'+UA0O#U VɃ/'y"@nUà};_>>z5,H%eJeB5 ֓K7|.X 0pk=>>O&X#к{|CYOXFEvmnK' $p5BznDZv-QCL7Q9API*Va_ #{²XVe [x6IP,}?5bv!`[4!01?_AGꆆMX3dVs Kz ᪸No8\NIgjBPoXh =ñh-t…/L26oZ.mZ{R5Y2Jw؏ [ MYB@e Sk?:(ڋ" 8NEyd1jk= z-^EDa*?Os7gٳ)47ue'Bs Qb/,w2E&{>9CWv&y7歿:Cgl&DV$eCz9G0.*g)ӛeQ̙g4Hf{ο3EYGi Ў㹮 :?~2էf8NMqڂ!)O2wf 2b}3P8֬]K`դ8-3.-r/(F!dfe|۔:U;a}51kZ:wDJ%$Rs'sY3d{H*.q?} $Ú{p OmFhЃuu8_]`zV˼ %J}I>R[©IZѵr`@1aBr}n@ ~u!|5Ғc#57e&n]%ۚ77 8Qlb.l6Y+:bp5Gd +!6R]~V[UjZjj1 D>Oުi!S`mwdBepxӗa_ؙLfR{Y.6E~%2Î>7RG0U|Q>$좸`3&N0x@ez_"Z^LYN|Gnk5׶_n {u)e/*Y*&H=OU<>n'lmYyz㣔MgeJ9H+h]8sNDTb^3ҬH6\5_₣<߿}{s6Ш謞B&XƝ>"p#^EWPۜw4km$Jh{tK7>L-m2\k5$Ck~R=,`r < mIZĿ ,|x}+jIk,Va[J6 TH[V27ؾ\ S`鉸oI9z:)i墪:/ :rLxi8{zW"IJ=O A)1sݷ2 [y-լrUEvqN=2\>)3V{p0Gǣ3Ɨ$M6 mdz}갞S5o1'W:ВEt Cu2ANچ°b6jB{K4uIz])|.<+ Rm\<ůa0#R.&c4P yrs!{ģ^OKKqT rG|8mL*7MB8vwYWXOfXO< qb#hi0 lP4>GBC$R|蔤aؽ_mZ,\?"uw! מ|_ ov/]0e[wr:Q$')RS4)>tGR8fS.*Cڱ^ԧ"H< d+Dλdϝb:idcg9CKB0J]퓲zF̰D1WRUAʻ؛N5WY@5}p2&r;]9E(LJ@!^qu2"US+\G Bymq ۫+vL@=SR$wOdN~b@^|‘Kuѓe "°E[b(Nq4_p[/6~* p9G?n;9~Ry B+?9H~10QT1OI#9'Hً`f݊/URނK{{)>@ʪ*PI:OH! 8#$&Zv-P$Y)Ka`B%b `IuF#t=BUB.,kc{%7+O2/pGC>< 5 i5cñq‚!^ 6w+5mB:[PGETLL /^= rE-E`qvTRmX;"0ʀai}_0R@`4k{".8@ܬj; iT+$Uֻb2?נdN4oܫR?3B[P J^o,2?(=RK?=aҚv $ສZ8F6 ;#5qN$DV@٤R v1ՙ1Vp<잞ͲK~|lOCb _""fnKY CSh+X5Q("{~)*] {mk9M*"=$;¬Y,cpEޓÇ-/F+VΰZ_WR-?fM#z 4KaCEީ$݄X65Pt bTp({At)ܐͭuM/-V:o{lOa{^9\K]َk/=TM98PL2֡CJ vxCƆhx]Tj'rOBA`lvX zu`h5!  gImViJ? w!RD{tk4Ȩqm-|I-MC\e6;Ey2 ڏXpY4װzysб ^f`*A$|s jY kM'5;[/m`+hbZ~٪I 1,(zQ. l]J[ٖb]!y!FL~(q'An?m.3UUyߤR]OHY4pcndl#UURټV§uIG|y3xT,.xpC#jN=Jfχ_UEoԯ/FfD4J9fow b)CUx}l=l%W\ ;bUC E<) ͘">ӫԁoȩ|;o)PwMy$ۄC;T~C/FdyYv8Dϟd8"vw:ȥFKd/?Qe`#pq}on}Tr*4*Y$>3͓k6+ "Jarz"n߉<#Fߗe@@@[+4$fɯz<ϸecWң*'EOL1Z,#=\ݷs7z2g`nY|jXUKLGZ#fTy&mYfF} o--T*{MUbi:_Cߣp spwA㛬uzc {+[w6p\ɟaurtO# D;[˼IvQF W ۀ\P^6T!SX&ZK(#'rPβohwvl*x::@7mU8-8sFOeXG/נъǿA%=Yr9qS{% F <śD]plYHE%*;)[t9*s ),c3 {aqK~esB%8vZiz%n,(WI8S"4AmhA5tx'c]8}U,\L,_LxgIϷT1-~;PaIcK-IDɨI8vJlb ~(o2%n'~c$DFմ(mV%+tdqI$I 6eX ܼQںI^h!3r{Υ+ 5+JS԰pU_)s4p۽?VvxkȹKb`c57Y԰ B(_h9#@ly!Gg8j?ѺL6:pk]3m7DXE|Zv5&.mSw& y{/r{4$UIvoҜs :o ״tk5)= #2|-;L Pu%17W6)ONϛ+]cM][n(O9 Ɉ4G ӣrvD@F4\XȦJ۾嘢t L z@;l$OCEJ:QNy_Dl1}3aՆwqԽAyd:X.LM>IgqUU%{ <]&kVnJk|b[ٵ/O*@S`Z/x eTz & .7mPN}K8# m|SIZ.k^FxՉ[3x,oz}cʒb<4(@{$Kk)zs(V[`齲29&K*i&Yq/:I1g2->;??em %|ʊ@Bް:aOοUij E15+zĶO#o;!*o/U'!?4} 5 em.u*-v$:v#Ц[sP&7NdJf-&5?W߆u5>HH($A2lUJfipR;bƼarsDe&D[Lj8x4$m³eX"78JYp K?o3O!&H>;/I A̍/ W嚎$kLY*=^C0@ʹH˭,s.- dl۳`edENZTB]VgZs_[:[|{S.:]lh$@pf,I0[YAYrD3fkbOMNCsKQ-AӌòLʏv5ND!^^ y_LkFh6Jpo>Q7H<,>E3N[6zSWi5 P D?qW^ᮩaIô{}Ňޡr;+P/rV, b: ~ͥ^$J$@=s[3'o UxLuB3C#jdGt囃'z@y +$.}Ϩo֭ߪM]3|a݅kD]l8']}ЭCta*r}ǭJuZ::U&m~VsM|.I+H",c^eO8$쩵y9$ ەE,匉ܷg9+TE'%ϦRA\cڊU)op";sU`6FC^ޫMq7v$v@4tAM2bheW:$TS񇞹2˾ endstream endobj 527 0 obj << /Length1 1816 /Length2 10618 /Length3 0 /Length 11750 /Filter /FlateDecode >> stream xڍveT[-Ncq -4иӸw-C<;3foZݽ;T5XMҎV6 @RICQS؀@N::Mk [I0{Pnv.  Ctt[`W:IG'/kK+N `0cp nv69@+ˎf ;5_%^[A Nl {W6GKF5 v(7džBдvWJr^vf`חEn` 9E_dX~<6{B-9;,v`"9&\_փAv _Aiq5wjbqes%2/Z\qE {}Ķ>` ks߭9k9X;B'f x@ `O3+ߛhz9Jrxigm~Aq7ϟF(sk3liO0_.֞} 9ߟ_.'w%$=>@+'+ B  c#@_z_4 FRv|10 <@/oeU?b01@v^X 2J/CTmX lnfY9e,,_*'\bfM=vv`UGWW ˬپ\'/+~Uq@.. /8yx>/iv6GK~ GG `W A ~?Hn7`_Z@nn|a|Qa|a|q<Eߐr~|7za;9_EE!_q4|2f/37[a}_W0 6CY^p4 iY'N?ϫuFɍkIȶ?5ꘕH>,txT,D7"nl [keAH S~CIϲgT7t"8?9 RTU#|[` "k&07h*2}G/rr[ݍc20 0.iaJ['3yoխ $:dvY6ɟV؅O3)8gǵ\SZ Gq8\@YY<^/&4py^FH.iGOZʆ<%K&7#>̧ A0P5V`YP]`U͚(N}ƾ)l/KIkwqn p2 &~N7Z> +?gWRa`[l8>=Ckz'Rj^,n|ْ>c!NH:$P|8}yFCKx ]"] {V0IPFuHӗ sew+S U3=jo>Vƈ @8a,JB^eL{B+ajTT,gSsl\Aʬ;Qh<ơ֞)W٪w5rG©Xf gو4\i3zz1Og|Tcץ8[ޖn\%p* *\ǐ:0lI(0 5;5L5,y//Z6 5rCN,\fFgh[SyCe?CFiu7%OTo+o J7Y &W"b$m>sKP X- iTIa/C:bsZV|E-TǃTJ"^m`mHˆ&M`l i%*,P8}ƕN09F-bı5v[$;3Tb\j!IY 3 !fܷK=XeUqvCTL\݇C4?b6ArZ^}-pz)f2WFe74GX1` Ab͟3T:3<3iYVƦuoټřH` `>/|Sy7FᮩYE얜j&CQ%㇝u+yip~hj9yRLS-lx͓ɯOZr&\=w_;$"/4,on7Ocf6ҔLc wkHAߜZ8pLKǍߤIR\gy ެeЏQM"jFTV󒬒Hݤf',?42O4 f-3n1i&ᮗtz Q|ĬH>:f;-ͬXV`:O==:q]iX'( j5?h:Y#K Sym4y4|:%;mq W'BD uF8Lh/0Tk~sCo:+e)"I } oycuuFVDs*`p 1[m0}5;jdF#k?s~{MyW 7lix]* +N<,:}\һe0N7iaÅ^e7Iy27ގ F2"5S)948p._l]QͪƱgґ%Xu-OaTS3d}E/{t̠St^Dq|ͪp3I;gF >n}DT L8.#ѰWrk{r>'t̫f?Ps`! ң~r e;CcJ. <1/=^$+Ziu\TVi[sZt8a]nX\%ڹZ'z׿4irKΝ6~[ꂗZK956"m؇DV̈hпmIExW&փ4FhgSRTf?]@,ya[s!oVU&*|;G Gf7kx_T 0$dPe>0Zrg%YrcQUۖ=@1I5r9ekQVǎn+j[ovWF~oOtST&mY闌#smL(.Ű]Upoydl1r %>?{.^6w$^#p/x Ͳ&m*DZiuHӞ<&b y|x/^<מQsI.z0ΓIn`bڋ^۹eVl&UR7Ǻ83(@ sv 3LrqʺP2mMi֍/۟kC2X,MoΪ|Ԣ[<1hko"EnՍ9$nėvW54lR":Gu":ʓ;EE1{w7:ج^V]|rb[gP^͈orL3BJ`y *PGu, 7qs ڸtEr@BY"13B?A6[4cS~ "$1`cǜ0CxK hP ,ppy(ԬR6Tr7$<_>>(5 mK{=A6bjvm]HGS^mg#>i|2rAFLIl( o7FajiJRy;6yo rESD(V?P󹸁><@]eOwbҁGA?z%)VNi^b}Oc?=7ܾu ``}GIB*R\E7f`mn)[MQ!@:w$@q'߸ȍ{m^0XF1ju)F @+^IrDطqT\:I:A=}Q_W#|8yF?(8k}}y Q:.CC :p( bꄆ#МBڸKۤVjvQ2Lcϣž+ԟwB2 _m.lI, E2Zl2Cz)ZHOlAn:^N4Bq.4ո錈:}' 768o@%ݞHI녧q"y*g}3iҰ8C/=Z@wsh6'`/W9/sp{h1l7$ޑ=|=hcnW0%T+B[:uTiEVsNBs 1 }}#ͤmҖt1lo5LJ䝧{V 8WV;"t>ј,i&Y<EZc,;]:g(.` 8m@G b<d!q"{(IQ0g\jIĖ>0 ,("*ZU[}Up5t+FRtd[~\{p[mWcA)!87讽bǩb]2Zn'BeL*^yUw< {)fNlxҦ.^"pu  _;%_,2CFePVʥchDL#/5yw^#Q/fQbcXQ;'}Gz4z|7`+H@l!|vA.#|c90z oaW Nm`HpN>ľHHP%FcZoldgSί{n\HrWl `MI yGV JvU.~.F? Ti;^f O԰rᒠ{8%ƥ~ǦpM(J`duZᖋ]Š}7OM|"d\\zh@ͽF)f7__4 G#xur)1d\YbT.FZ@<-(4#۶8rt{s':{`<1-sƛrm.}E8;/ֿZo52%+Hťp:aկŷ܋1od3aԱʹy.N;5 vǑ7慟eeN8|Jr욄p8CH.aǝN֜_ 9KcxܚU  bO}\dR:w-?â#FB簛 \C$[qԞ#ķG[y|geS>HX)]"i}D"$3ǿaJpb!wVG&mo$=눌T=2/g'>5; KqMqϲl1ک:C/8K@o^RchN$RDHnW5#XIFM'c6 @itQgN# m>]zxNYH*Ah.t!"j :]x>0>~M;‘g8/aS+,48Fkzny+M}8vӝK;^(nx ޹PW(2BV_KcF[0v%ޚvcr!&M'"\H) q:v`TЃEaa_үOѣsXt tt݊;Ȧ[Pxt )4z_BwH#nh[ 󑆚Ol!x[m*ǃv k͢5gUp}֒ e(1: W%njxl,^:ǴMhjz3Q]"ߩ[kM[cNp*s(͎t/ ,3>ID,V~LI>pEw`(&V$oaSǦ`ceߧ *{iM]J!d;4Ӑ_ve8}P9VH՜Ct+^Fb#,6mThW"~]t--‚7`lĐ=df@p,2bf"*SKɕ 7zqoЈSbTr@t gc'(;z8x0TtK` @} 1lxmfXXnjflMN cŦO(2׎oiH^5]zewN$=b -~v_ro&8'oZbը`& O8gјn00&`t~eݢ/gXt_}{OQ G0tB2Dg) u7Djz"x!\͚vT3եYY!\\caAHBg_;Jj1 @iI&|uGv{);:'% dh-F:#Vz8>|JBڥ}LI gYk .Oイ3hq%7vŬd'F˳ |D9j7 oIS%u0 Cdh@*b8- uO=T*) ~q TN)':b{Om, \XKWnrPG9t4=Jv֙[V[4=O`VX22L.(Au?BYSNrAWi6. I9ƔI9$ ƪ Bg Dgt"RJr|ZUK{'zFmz4[0悇֐|ŇbLN4%3Fm"CKU[>m::=Ksy>LuM&5&]kJ'ڴe7;mbEF [C 'e.GqIC&?M2"tt/:-bƻN= -@sDd .hOLd􎬵<|o1Ia1Tٲ€8'TҡxDƎte`\zMHEa4 Q%4a YZ(GSŎ<^# &OӡZ=‰%!S2Ǿ˔_Bcئ7YD-⼓jq#ş/ww{S-gЅIvʟ꣒QNuk/r1ͣed/S${pF]jw0-Tug`$GO&ջŋ{+rQ,Z1-0[CH!aV#\wbH#DjJFR:% _ }^]xlFߢF||U qcQb%y K*@D [JFJọB܏'G$ѢoSI;3 |1swp9P`oܮǂLCJ:8g&ށS&9p !%RdV ٻ4)p\wwO2?*#u+,piҴ}J`$mBePJ2+r"H{a5 aW_}cʖ\;|`ik!'0.*2FόR;iߔE y𼂴Ix4hn#1k.Zg;Y=ֵ0Ei~pVNFcpm,~jHzhWT'L:򗦦&JbC} n@R~f B٠o6b_+M"Bb2$T7DPJ8% uoܙĴdekU 2qfǪrV#ʓꮉe Ulҧp;?ʲKd(t譪{o4a6,-:=mpYG *[6.d[n? |aˮ>F'NAcgɢRڇ]r8@a:R>j#kw$۴Ř d_ xMYiG:' z%ɦ6☏i/5xugosd@OC$QټYٯ޺Oн+W߯]æ+1BSq6ʱ*I6k(9;ܩ?\l2] ~SţV,= sn9yYa]GIlZx4ؘ}ƶR5Nn4ink3pH^ d򱑿ªⲭkGԠ ޙ74:#z]"s+O^?_lD~?" endstream endobj 529 0 obj << /Length1 1401 /Length2 6058 /Length3 0 /Length 7007 /Filter /FlateDecode >> stream xڍwT[6R"C7 tw03 ] ҩH(%] " %!)~csZ߷fg}]{_^aa㑵@0$?/H /$¢E@B<P8L?0eS#Q@ 8 Pt~ ~Q =$T0EupD rܿYW 4HG+-ЃB!H`rD"$y^47 E: bBƋ;Bzp{7 .P[ A<Tu@OEr~?ODPد`- { RRE 0'삀^` :P ̇!~Am"N !x?Sz@lQpapo_+{(vn|0'DEeA H $@#n_Nf np75$jA#^ OǿWx @0k{@}3~7 0࿎OIDX;>??# Qaq i?mG Mu;&E\A [ԃ_!?;Rtqg `WH4()j\ *H0J 07P@촡H[|m74( G@-?_>lQE_.J=.P\Qz1 #Q!j@L@@?]_Um==PN/fZkKojn+TrV)Kͳ{~5IO0s͌rveړ%#4;gC>Y!s)ʹH4Ş%=hjDZ"k3L3$NרּUSM(:e1wb5bscE|1Xx n 90cjkX/b9YXŚFi}xp2 ZHTE-͵8o1!G0g<-Nx}:lI Ec&sXsA$qV]66Ϊ3okb.YnCZSh9iMX{#+= O"pRMG4sAIz [&^-pz^&3c\сi'%m=oD+Ek{UZ\]K-b4'0Xz#ᬉS:Qqˋ Png "eS?)<%C2M@GH-]D)מjZF!&gNHݑkN4dRyd2M扅}Yk 1tmb#Mp Gգ9L Ӹ^䉁ØifԇGz%`l恼GL{?u~dٷZ* C}Ce0#O\鶲LGnKRMz~9ei#涡hϟ|sa>9ݡզFǖִ` r6el:&cВeS @%ӱiGHC b/VD~"J]VM$Q& XsWc ?J#OYj1ۯM:'u+Ew"&LBs 0ݰ>$+jDk֡))O*ɮZb19+CoDXF̽GsV߰  }Gjd"L^WW/.Zi!M9΅Md[֮@&sb}ApP9ۊM,IΕSsKJ;w!\#-)%tipFT'݃@f & %^n›W.rv>K]7$e%: :fSnTQ}i֎L˱kz]#7{A" l81`ڗޏ >&~ʄۡei*PZqՠ*Ey F(A>+ufj\i{[ ,ьk;GS'AG)] 'ҶW2Ԫ'(l- {wf4 ǁ$1_N a*`XwMa4!d8dGZ 'mu&G% 9Np6~jR\剏˜Jh^Sp&S*>_#%ӼタJM[@(L3Mhcă;?#&$O3yj!XPoᡘC[Fi7 ~bʩ>ogNwvqi'N/45)PpeXQ~Gbwؔ1g?ZGQ'K~.YNab>#|Xͤ᲎o79WbqנGVv$uW?sqY|uRȑOq!k܈x~?gd!U#y)QzU679/^(K88-sAYav¾^5`QnW-eAh?G%.]S _⁋9sn' ?=s(o@␡GeicK48H!eg3n.is5A2{ֱ]S_6S צ\E̫Xg#|_s-21g Qf^&O>O6B2׵ȺXp<Qj$]ښY$k'?tWtymшP4==v|8Zgq1~y.5m/pUxl: YEd 䪆1kr0F mUϢJٻ>ŕ80AC͝a,*}lU0SX&\Tss#-={,^cR22y;} 7toQ%ـ]ڶ0TŜ Ux1)vCF MǘN2H'ȻdșK2NNSMI-gq "8hwTge OZ 7!yBC&̸,lǗwW"mJ7uY*_2 V#H%#- u~1_rb*s roF@cU\? *07NҶC,f[ŕ !+E]Ŧ@mXFuvOG>b۫\[-a#ݶG.gx;Ǜ7SKU)q|\K:͏/c:Q$HI{w?dzjltoc~=pt>p)UD,~Qg4&H'xPnk1~D!t:j8tśΪJ;tAcP ƴ=}<6O ܌~w%d1w{oƮMf̤FyUX+Zyn|2ηı4δA%ޑ1!Q_DH^K$]ْ]> ZWW͎ ż^ ,!c(<` 5 GnEΌ:S7CS™R%<ܵK.{˲0 zx޻ "i"h{fޣ-hT I>oȝ9jSōdcX~Uk?of-v£1~90?Y.y$Q̟Btz~1ó?Ljڬ;Yݸ2 y@6g`6Bo `geblK շjvL[̤8rܼe OV3꺣bs5Jwdvc2B7*6ψ Hj{);zByt^_^NA9H~CȳQXe.KΕ!ogaAf+^*h(>; X2 i?9RϺc;`v0A|{{P ޣב}@,T_RZ Z[frr*RG {5; &_&;?.`O^j㠻Y3|0V]Md[S>]k$iQ4/.[Ե[rkbWe=%-YfP0`?ꏚ̜ީc~YDH]5 TYȑʪ3Bo#NQyH]^i[[\dٔ>q]P>>UtD0%FM4K' a`t|I3_w^x:|,=s^޵E]ӎɵ V3'hgG6LtvbigoUn *ޤ;ȾFzG=h"Ic2QؖȜ 56N[LŎ:Go karj.t"MޜcqTZ7u|b2KЗ;mC^I|>HUxҌ}Q%󈔗Ӿʨ-zc%\+KKa52&ɷN#̟E<UB}1T*/5 >6#pvw5Lso}Pp;W5T?ox|8 _#`#,C'GlGa]%зa^ͅ:L#&fRcR[ cGL\u+'aNzoEk#z-n;X HDm@Kc3(R"ҍγqKXW$E˯ˈq̂>vqrTX5zSFZ}ՙ endstream endobj 531 0 obj << /Length1 1406 /Length2 6162 /Length3 0 /Length 7128 /Filter /FlateDecode >> stream xڍx4\ڶFAA c3:kD{DoQDI$z'B|}9oZ{sݞ,F v[*Jt, PD&`g7`w$;B۔A(4PhzB"!1)!q)  J DKAP;@ ؕ>PG߷.07@HRRw8@₮F0G ()pwxAQC  r5;0Bأ@!p$:nq4z +_ѿAῃA`0P-F@p_@ @ǃ$B _3 JfG! ~ u#:^pWP1<\MP7_6 @o>f ~W=z H"C#VnHiO7thB\&#(;_YWwG0o?@a>!@U@kP3@.@jP;/t_xTzC( #_Ot_>M.ZC#~MXT rw UiMfB3VH h#4?& AEhf׿xC tz/ϣ+ }Q(~xYjSnϗEL]y? ^NSCa+~?v0!ӣ I[b[r&^lRx݉|( pѣ)vnc>`a[E Y<"#w00| ;Wln9./]@Z*W%w8i*1G (zTJ[X|tA[ GR'#uYܞ#lDwj٫0Ά2E`yLܺ7:ӈs mX'"_&^<~($l*RQL:lox @AN1|Oeœ9~]POmj*8#kVb{2S1Tˆ;>7~:0/[SMkI1ٜ&Fm piRb 2Wb#/dBeR%O>LR6؉']c:@PZ+]NMhvWE<ş&6O?wyҰgP5nraCƛMo3 !5ְ"XEchR?Ue?H߽gľ;`W ?$"U:A~؄QDDY}#LNk`ےis YݥY/Ek-/(DU⇧Ozb|]{O7CtZp,G4Xόh_ ܩj)CxORnqv{!..t TRw3[1O~pgUoja: bR͵=,)]X>p1x Byl2e8vaeKco~dʎOlef)o\_E s*, ~%ofHӉq~uuYOfg #oIt3Lbq|7,Eܝ˦ӏm!slM$`Mn5k,o@Dǘ{ uF_S<1 D2e>x?dWe׎OQX EMM>eȂߺ.\?閅`;#;`̭Rl|4]eY|#=EÒ3Io<{lJp I&wY \ow'ПwK=Lտ9$LCGݠ*M<8Hvʙ:0 \ʶUSce,y|M{6\dKSM{8{_8+{?w4D.t!t~xE@Xb3q8r2&[[}Ǔ\S<\޹` ԾѶ[6:#׏䦸'9ge(B;Zs*l Pκf ovU|U K\opkqfZxpuֆ;F ~Svs+UUXs EOf}' yLoSTq_/`%o V1Roñ!Y JG)- E=iMˈ)A0KhX ^K<,DĥY)˲R2ъ1_GhhH"Oak5qlLZBm''n.\(a1"+v me6 to☆I>X S0b i8WT8-VÁ4jWݢAef}æjn7/+Aivg|1T$WjU }wi18N!d(O5i@{6=3^$P4/U06ĢBCoVVFN߅# ܷ{gwfSz3>hkn}V^[H!<,rHly韍viضI̖~pՔMlL~/Wda S\dF^W n aQ2¤y@o-4ajk +БX?dchO3Q/_S|cs0(Rf@K ہJA+u S+9@~^86$"E{]u+f~Q( _p{=~0L¼fy~^ SdaĞ+}oW剝0p/,L\|3@s5&JmL5iU$7I`Qx]3\R8ƁD+<+A+c}Lt57[ )`⪠O|8]v2MKtb/npfdcq'j-(^갅1>se]spԹGstCraUDA@mO%jWj&#*יٙv5ؾ9M ,MhtWfAd/ضTǷ_0'uNJ`Q KoSǻ)pъ~0ӕrn yyC}fd| ~z@?|$/W&B˝;b4j?Dy{%R#[k.s?*7y^zjrڦ5[>e VpC鳴$ɹ,4ba_I?0.UŪ:PrZ_W耡d-1 6i GtrGx>-2m!=g gjZuOt-5l}oo~0{|}Ь&g۸$!xJt @Mq灤[G[]'ZrtE⟕Y}2$dN'1_ SdN]bN/!-b\ӄ:3x$3iuh LuzVkT{m>8֣A`|dqCWZ3&&nouҗRz<;Nui &e7q1Ox?jLiY+&eߖwCVs,#^WbzKOsPÁdkeudEMUocL!Yf}6?M3΋URswX3}K*:_$uI|c^"7}(W  $t}@t8^?Ͷ317HB,2ඡe'DBӽ/?9C6߶ UQ`&9<%5; XxyI+!kaO& |lqe `tޯ@+S#刜hc׳%mt`@.^9A(y䶆ꦔ\*e>Do O$bYBO\6ҹsؼ3c1u Us$vNs"&QvT*v~}VG.-#iQy>H;p8ɒV['}ɵ*ndŘc} {q'Ҋze"߻xԅz۰ؚV4nlp!?'``{8$_@mg:HP|TM-& ,bۃڶ*lL^bzk,sjh5$j,#B7{Fz~~^KE]艮oyLDcXE'Y?O~wp) Wve9dvVC( o~|5)ïyTCF)MZ KЫ %^!l ~0M*i'6S{gxYڼA5lC%Yv4¿Q16I jc],~3U-݄JnO{F 㡏 kc;򗶼zVjOb^Gb毕Hh#佬M3{,l ~dM Yy{`M/sQ'!ga[پ>I3l3v ;dp|d6d/7}ݴ^~Ы.=K;xh+^co=/|occF(֌sN!*"?hz_ZϼJ=פR7{)LjXSO6>sADZu[n6\9,W6CgNV{a<| XP4[v] oY 7xd@D/x. KqSֶf|ڴ2xMwrPc#s;$yb.=a}Ky~NǷ1"ѡAPpSkL?JMљ,O6 EͽKf%20k}w}:xGG Raqq~~"~gKf[QƊjL`HL*)P+xC/>ӽt_W՗`J[P{b oq똱 =NΤa4/ed=ɼFK{ys*~ب]"?~yPS'ߝCO_I{i0b}C;DI 7nAk^nm4x){V3/9rEN(3ڏE?|sAcg3+UӈGKB!MS`9~_@gKKVX$D8X0HG1%RG )Y灀3/)bL#m(]KltV凐xWӇJ9fZ"/!8 kDKeC.U ̅iv qЋm ”Ҧc\^Y+4Ĥ>tRYx9i" '6)Kvk3gVӥ&+iIFi+^Ûe'z[ ـW7't(mHXXؑ?J^4Un8j:/ݥUçJ)L%g7ȧyHb8$:J)rO=g. ?yՎ gfJ-h endstream endobj 533 0 obj << /Length1 2354 /Length2 15457 /Length3 0 /Length 16864 /Filter /FlateDecode >> stream xڌP $Kݝ={ .5xי;f*{949!PƉ ,`bbe`bb#'W6wWG tp4 1p9̬ffN&& mx".Y \ TTFfnnN@s#T dkdtrW *^3'';FFWWWkG[S>j:@tp~ 3=9@?%['W 278BmPu @hg8tGNdnW) aprsv4r[j &`ͭ~; fQca[kk#DF ^%scc;1ؘ;%ELNv&&&.Vt32c]@44h898=i 067rMmd&Aw0wh1 `O: XqkŌR’Š? @ `gppsE.)icb O ۰ xPK[ ͵ؙ@?#1g+TqX[⭳ ڂNuU͝UtmLX/nGYl,zf&c.#K_& C0pp0pc1 :@H `du@yLl~/hGbIFFFӳփ 2w㷳ӟX. ah`dhehG mRA?bY}g0Ob0!~kRF?8@ҿ*p;x'ԻɟPo&.l韌 7OPp`cIvf@xtAZC"?sF͙?vn bqv klk@6v Y -;+t zT'wuo3333?AA@ksس8.uef,Zct2s P\mǠFDG],nAU!gP&:ׅaZ_w:6 m>Y=T !SK\rhw~BMpLAYX&z׋%d3xy3Bk[m_hJi__Tfs 3pH` Ѡ]!͠eOIy~a-d~X؅KCy6:E)tU {0jB5hH'$6(wk-{Jv45v'H 8&byMhe]b`=n5NnOj&w[Φv7 +Yf +~UD$!Z#Qܙ&wRjR VS1ЃngcTRSښO|'PMjr;5} XxcZ#9_${va"Y4igc 7UL. UQhzC^t[kG’NOʨL`eTMhVX:Z^Gn`GS z/_rG$l? 6иY7akT$c"283d(;>sXa51P(>T%= iauJ6Iؘwb-a .oy.u5VLG+SKSpUY^)cZl0yzuG,}> [2ov+Bm[J_%9vۿ1Kα]:k"jҦ49=4u[T]Ԉ&ÌW%2?82B0Bpz8? I@U utEI 6cH}ʬqrOQΧc7mx 'oX胨ԸSa#ʌ`aTV'ŎcD'q|UJyShAAlzҕX)P]bq<ŌDȰzy)A2Xz&fƢe}f0֕˯CV?lIЌn]DܒȄbSNg^+"yB*Jϒ$ײW}%`:%v-x׾7X\̗3t]sl7ʤ$py)[j2gisT=ֆŧa*#e+Q|>s^*\ [MSl@`uX Jr2UO!~T97$iK 9H2wL$uIcDuJW*|:^Yz{/5CtSAG3BUEIC;{rNK ᭯Y{ gb% "i0zRӆmӉ`"]C I>n5 2ܯگ Hs@}k?`&'rSחKv&țfE.؍$|{h3AcD< Dq7ƌC M%E|/1(ax97<+eQܫRmZ*fk|sluV|-͞rc^Էŵc 9BraMKyPDPT[B2&LMс[yQM |% 't!]m;T95:[Fj$<:vP_ [P" CƉ.L5󺱁XAR1d+ߣHC(?PQOhqS!8fFWyTՌ0E.d?=3nP({b|Dڅ 8-#J7"qfb~M-{(XN?6ɛL":Zi1`ou)SS [X}V($OabpcP#2++C ;֧)Y:LBՁPDәPtL05̒H0~@׽}Q5 LogY;ݲnC6mEcH}mw'Uᗉ@ImG2 F0[D?O&] (b}44HhOONƎyXrF iE>c=MY@1K$q>xĎe ބ`]i*- D!')B0LpbF,& _mOﲜަ~&:bI&q- (l1`k{;ia$?jf٣=`"'ET9q#VnCޢ3C>mܤcjr$uCכMR+ իt.cR)f,~tٺA~ttâH&F3uV>_.5*'>+] I8n<߮b3^oDZ9&FΟxSY%M& 1/1T0|ǔ[poGr8Q9)Rl01P,t۟B46u{WS^MP fࢎq4>-x]-*“!BEtZF63C9pE 5Q}PX#Tqs`Hbk&/KlCպ):14'%d 쇎s?dbw[ZMBHC"; C~m-' ln ^;!qWpTކ s`iy1ʏXНa_J~~;GqC?i$]-1ԙk?ROB#NP]>uwPb u'Z)xsT8ʯ`兼5zPjaʘ֚[%7u?m*|ٿ [CVZ+/c^0BQaVҜ^M|/!?qD?i\>,^?j4NٓFI~|Phy/G.)1U.QqyQ$@f͡m!aNѸ4;%+bHhIͱlE=5mv:/mhyqNWRBOUuh#vah1u0x_|ā ?$f{'l S퍥l2]6a>k]:z^GȜB-8QpcPWV@y$YiAqϘJ {1b(µYi@'H W?kM~n]QJkB(J>IjD"tn-᠐L枷vPv#Hz-NUf*[WSp'>ݽ,2@ДHoI>k{v+rV9y-?3HpHI4yg-焊Kln8+ gЍM&<5Eh &{K0ClKN vQ _b8Ej( U;D]g]\1a 8i$8٭8]ۨqa0?Q*״7-ixb.h+!U[ 908 %1&MRkY,[QDD^0c4f{bM^kf/L|Eu$Gg JCBʍQs.hK\.Vd^Lvplw$>զx\^ÖbF%)-en=4[cXr[}"eW$2M89+ WC|vFx֚}%/d&bI\EE{ŚK<c5&@>H &LFo4Ѵ czO(j8*@6ZkڮagN@`oZ? Fcj9!ʅo&ǨoS|0}bY4QW`pΜ-bZDpd<]p })=MBY#t.C x42. ; eq < m%mTl\L Yx)v^Q> +=JΫj®+F~Ь;Ȟ_YL),FK+1L4SzQ⻕`PqB!Zz⢄qܞ0t((UAis!f٩c[v'lJm)#R8zVa؏(.$Xܟ:gC gp=1dGZ#(em3 }q VUF7i ɜbf~Uz򦻜ޯ6m`z }:8m {fޟ$0!u8ht>Wg~zd/BP| Pz|ֱ#9얀=j{zowXK4M1̃!)}qT?ؤqaqoR "ѡX$Ժˎ7?SͅHVL5kbR$(t5QHᤥǘBI9 ?CMHZT+\e5E1q ̨k:)gf\w)6KLKJ2t}N kHϳ;2 嵦w~! 7qcq $ a]mo&0m8*lN[)PnxZ25Tǖ!ldYܢ }S\SkB;Nj'j+Y{P}t&_܈ L/_S{\{NN~-v~߉S=|n[nƜxlq`0AX @5Y4qg'E8|5h0*DQ;T\K}^8yW>/T2Q9'⤺^AT󼤏;$钄BlՖF:e41蕥 owv䶰9?up;j~ ] lT˴7 jg=>!F׋+QHf_ٞNP65 I1Y٧FBK}}{k.pp3fݝks(]j3.ho(hEK-,y1ذ[괱XasV[|׫ݺobx:r8}kp{im J3ȗ J]e].t._`b}̠,5k'jjhzF.A=˛ƍfPV̺;"5eDC&kN 4бhp^Wats2("FS2[@QZ~3`BAZypՏR5H,PBLF_ڷXgUԂ -K؇M(dZg`,~.CO?5K,Z#l^mEy+V;l̦ȅQjt[/p,Ul 너; ϴ.~;āIIf <]_lB~xqӴٮDž 5T*x$Glq,#0V&R|GPV%h7iLwt<,kV[I!W„dV_E'Bp=LUT8Z~Ahi"(m%tHEj DDDs%xI 8lÿF UV;[!nO28seg!nK1vdo؉(nd Ӕ#g H{> >GOq )SWXU [mZ aceZ~<`l@H9d/W!6TT#M y8̎Mm1 3ZK7.j>୉"ЃvA'FkZP.W~(QRp? I*<8\A,aI2^Tyԑ.-֑Ћgܹ cH@ S_TP%pH45ZìrL yZ ƦB{ $z>Y}6ܡ+»;KdV:$l.[l~e3#i~N8jzJ],EzV2ܻ!TCxElmLuWlۓ&;dԠVZE}G}=d5&gME f= *asO6dhмoǂ.DFj^r*y9`39mCqbNBB\; cox|55`pdѴ(=OZjk|cfp˲{P(~hN7_6PӁbhOifx x(rR;3'C,s.)epQZ]|hS9RT辫luoR(`1\qKZ%'gr%t R=lT:]^Q* >pˈ&%bC^'9s;p2tFo xO563RM'ȱD%5;٢(A)D޷MV#Wr$5?似-D˶a}] cŖ^v`&_8_$mu1P`Ls39q;2I]_c5{8L]Ƒ ߣ^縟 > Gc`m|čh1ѭ+n)4p :Fh,w(.vyqHj[dлop9&{ͧsN(~&s |jrU屮 ܔ] ;Y3ϧC~awҳIp^"L*Qi+%اc zmS}/N^*{:|6V[ڢɺp{:J.ix-!F؍-cpc+a\ ֡'{ܲ@E'a60 &>a<9D5&L:Q%..o-%Ǜv@!C%獵EOSVܱrA!':nV6绍'AkO~鐃<_Ȥm5j7rg2V3F):s &\?DţHB!"v[;ѤZpdw9tzDŽ#[&q^'j?ɏ[h̽;M-ʪTi2?IL\C8&s-6t,qۃ(I[ ,9B^R-`m@Kņ fl:>dTJxg=E!'KGdmfuW $޷5*e) Q֩ i bVUڔtAZ,K67\w3I֧'ze)ݎ&͙A\?cfgwe# 9/nޫF&-Ҿ&9zId?#dܫ@?2wtjJ~q.|l_vퟷ| #GR2*8Q;dRjdg(/:JJ8,U*e͕) v*P!!A|w0mC [Se|)md<"dOPےm)[NL Fƞ %c I-Q0*?Zʜߦݮɴl8zʃ6D.:_˓&vkӶ0Q (]`\ )+ǪEW`5ʓqX]ݍ>G)+ʶ|epI}_n X}|HP2.=XƷ1 !Ptb9rΪ+aAO:JI+*-(n#܅ .S.)<8Zh6)n L etp 3âBFSL/?YK;ۍ ERhB;lj{8Yt6I*Kͩp8Z~dS ]0Sjzq +==|[ί1&/U5昖|\<ޙ*9|Snr!ce !~D)<|<{.D72`thJ^ ܠvܙIm#8Dg}SvY"JMmx^="sˌp/=[_3PؑШ& &욡]u l*avv; O(*HXp<:`Z#-NeI?-[R(D*[42j"H_J1x!q\ڿTx&Mf$ sH\t[ɫnEZ7_ տ ,Pi@筭qɍXٳ~W@4jmϺ_y U B2;-'3m>]@aDeʆ߈`8g%~ٞ~}Pri%LGTq"l~kϧNq wTRȣ @M%ߏoz_I.sgY3aWJF![gT+=i\;G4h|ZT9g],O=o04t\IU~w4_$emw<)cc'>?pDS6.[+_AoSӇIUzЫV; "c}}T2-ͩWHjkHu|.ᯨ>f^g)b;,7y}oR)';RpݳW&qd?L*AVHpVq2D\ɪ4Ji{ڎ|ֆdoq&nkd?}/J'ѸozBZpr٨"Iv"eV#t4G0t_UkgKe=F1E:XT˴%O!(p˨MmcZ k:T_-uf^;!97xBg_V:JIGon7$0R8Sn$5[k)XpDMv6  3JůךcBO4;}]ck# vnswd}~{]X1-#_Mpc 6ÿQ(z%&ο/JQr3e H(x|I੶ǹk?z22,%>:ħm_^Xw^^X}3hl,LI} G^DC/"$k J0ȍ1P ;˵ ÿ݆'ϰ#i;c $`?:PTrhls#!!kpuS4_n{Y(ZÌQ(Ab/}q^Ngmd\ 2ʡuV ^DfG;'p5(B0ǮoI/ {O="c/ŷ]G IP5Np%`+wV @' BگO}MlRb*a*VE΄; UOb"(r aRź5+7̱HP&⺭G莨i c:*hx/LTOJH'G8BJQl&cRTMW{']ᗌZAv(3bs b.-"SaO>{5"[+ASsd ?,[to8UֹRAUrG7Z&MGuh0ob䴓3!ϐk'#FiZepoClT7+Now mFeJy?2'v}.ݯe+U/;@^>I~f-"? }aE'1CR&d<Z+.Zq`6|7)D<8TV[z&3> &kH t0ތ/3_6!7s30OO,4?KFTx%9 |Ώb.+ HGo(CsQBUWUS%,zZ3CM@\g4׈")Xz"T٣gX+b[\`=pvz LQٽ^69hvnm 0~61fҀ5>exݓgUD̵(_'M;O㋈S02ڃֈKv!L26A4Wyp#JK]D Xx$oLG,F3"` aߊ?*b{^/1Op^f`JiC)0C^Hk)srǯHDue0 $}c]-IemM a(,/:!eA_r<:~E_uW@*#<0h>v* (w 0?yaT+e"Ԝ69&N"ݍB:*/>tJ>if 64ܽZk/RLۻvjlFvgR1G61T9Ń }ic|NMJ$p=U`^BPPޝ}ׁKC3{&?r%)KI$>Y~Lq512 !%{!'QxY OޗO)vE;Uvm6Y=wg4h>&v? M:Wg!|'?dw,_bah2 h(_y!N/_8v ҧ}U~t%_jO|t"_~cD%uek|sշ`ٛ]>3Ta`4;^p~<4TߏϭΒWɎke]XO)q }cja徣fOm}\(dR1ɻ3N ~FYiZY|}w[^s5XNcm=!I|)s[)7N3M=;:$dD>B! ͔jD̵n)7~ #%dgoW*|"LhF\&mhk"w8Dn$yK*l枵SQ`N%@wP6uExSJ+ gO(eoEAI[>+[rc9A9t.mvع .#i'm $-k98to "x"Ry.os~D y!|ʚ,O'j7%ԌrFKE =mt4d6a-}'QDvl2b,:DmZKg|_`TeXQ(He2C(v"5=őy)XɊ{ ۃDPYB.G_P|!8}fa Ђ3x~WU0d%+ij.Ii {,S0 (=Kt-) 8>]d@@!H3i[𝷢˲E Ẑ r7#[hslOL(6#FŅyg 7)^OXxo1Ӓ1GV}D =al<I+}WD 1T3c8 ǖ)_LYi{ݹ*.eM8iԼx~@.OxMOKX_ʷP}(8I79tMԻxLth.ಓe"+.7O2vB5멩d۴\I@u1!g2 ] 5&&PN*5;w4*1t7n~-5U!O]y9/AͿm|}Ϝsgto9~3J@ rԡ]W2dW38ze/;ptgsc;3c(+Owx'Y1[%$*惘gbql,ŏ(`ѰcK~sTV&&TEiTeC +q7Aecm "XBG4Ys /6'ԝj?^튥n͖) endstream endobj 535 0 obj << /Length1 1772 /Length2 10020 /Length3 0 /Length 11131 /Filter /FlateDecode >> stream xڍTj6Lw#RC7C7t 0C )tJKwҍtҍ~xyZ߷fvozjU vIs{S=) ~)Ơׄl1N{N`&=Ž]l\<.~a.aNN7'; d@s=A/m=?Lf.!!v`' xYN44 ``@7773Kf6fP;\ Av;hZAk[@N`b:?e@N J0`rd. 23sA= PK PS‹ @S>>T=g3'̙bE2OSKف0gd N`{Y`[n qt+df 899y`G /_|OM}  /g+srxo0`KOf }'q8I^P[_ '%ebsxB. CL=@oOC\?? ZO'J*7oBr. ;?Ou=@w6}6o PK,qB`fV o+f U!;'=학ӻǿ\৵efrry`p>Ɉ` r@aO)|N/TH6@hV@>OlOlO\O'V'V'V'VN'V'V ,Y=j:;1''nB''r3''ﯝ|W0lL$غ6Z܍}gLl~G;k5*3pJ2ioyKRb{K={8ɝ6 KS`ה~t AlTqtQ#q{^_4uGm5C{(\$4(0v 4wܙ˫i_Tq><ֹcng=W5HHH(/ F&缊 89y'RFWX} M'7 A?.S7NxG'Tk߲̄%~ $BVګbU6mQ`x-be^ "Р°g_Fq_ pjP0awq?`*Cas u\Hm'1M[Ǭ<^VR{<Af,ƈ0.P9O \-~M5NR  \QM jbLS$kFZ޹&OHS`c9J>9mJ<:i5^˔t߆c4ϧ-yT)Jx"K<"Ɵ҇\J^jۥ"< Pƺe5:2VZIDt-rgx"Aؕ)g#?c/ n˿́Ma,+eZ?Zg!98@@]r:\YTXHvΛI tϫum IFCD*ޝ.F{.dn&B|/k nVCN8.u R8\e#W )] L(/185rЩBrIF";>v. >~B_:$]+|V{NV=,eO0VҢ NQG:4aI:w"KRnBSj'rW!GTe c Ɗs-a.OћG_1//q@Tzh^DO3A ̀nזNr]sI/{e D:&ndӜ Vʆ[to_D $Rh">.ξR4.R7>S2p~zu{죥 y%\m6^F7˶~泫5v3":u$%x ãZ E?_)ijKGXi~qHzXP@8$~&lg7#`6(ߦRNSiqFweXu=^)/l5b{U Lp$Ȉڿ|->UjRd1"ˊ=S_&>#[ͦbN=-8z΀rTyp%4|3y4u3HԹ573PBW=nWqQLKM{':6P e< Qw78E6:XM!B=,`@O(Y]&;C=J`ɉ9~Jk_\nPš2Egd\ݿrcE(IQ }[l]:rC ]}[ r6P3'^p!1rRwٵj.[Z7"gK{1 },Su_zY^: ;-up_)5=[nVO=] þ_1:S]w5SZP[ Ix,İH5{#t2y׭ nCTЄ;6з0VUh--lN%ú+v-}6ljqV=(|qE j>|vC*+'=q)tո6_* MߛP4Avp*&VC\Nl~,~X s b}Ru2w(3|Y/qFcjmqvV(a(5sGB!V`h$l '1D晪uuA0bCZpw=$GL:3c>~|Y\UWMZo~y0ai\ob NJob|7-۲#,K_ԟe+[hM[`Uޑ^섐:b^3c%!Tq4>)zI<")@Uխ<9M"R!ľ@[u]ѾTP%W'g>z AWxHWMY?Ķ|8t(5KPbTiid! AGB{1LMDgoQgˁ[0`cۺf4CYIH#L|i(8Ÿ׌w=(I6_S?~u&l"scmUnҀq-1xZ$wj:mwlI9SvICTeEgjdUe3 ez*{Đ;iy]8ݯ\VT|] T3R$B;V63Zο"` k9x0/ǜ3--`@aޭ[/;^ -]'+u{)xM xXbZj4a iXHI3vFqQlJC9~ӱ:4 oPV\eEId% YrP %]m"} {^喏= %mz_.1vfGt%n"ŸyƱF)>Ofuޠ(##(<ָ޽@ViyMACqך5lwdO8C* " PlI1=->ʉ7 \au'GQ#uͶnOw$DQasDne@݀4"g41)Fh[t?@繮8F󤖺fY^4wM$7>Ҩ', 6C"6ˡS8AF:ܓJQ7!#ZvUMoܯU~0MxeZM}'xD+>ie:4!<-F$":+2K*;ȋS,UVLTjr>\$`Udf9U6[һtݖk~-ⷭgex65^w$3c%>uf 5&HEp4Ӈ wRbn> d*6#n>w m[YOd,3m'K=jo F6b5a˘23d,|<\I\iT^mJ(1)j{s)&e8oB]0w^c툖?PlGDg:3S~)bm]j*[GǙkϯ#_.T7Gc!h?yVϐMS:(6 5LёGsr\v6Td\mX8ǵ'ۼr~9öSkNhнo٨s-9TCNC?S9&o_[ta)K*"MXv9Pa0P\qcܭg(c$E4g*0DufC%lq>0 zw/XK(eשqdy^vu_z7b(`Q.C :M+*-|6]NDd6161d^d0|(=9 H*E8BJ5!J 5*YHa+0eFjhEӟt؞H}qK`1W(AO-2H &S몱]F 7ءDouݗk7mFb(J釰= KcL=tuC${uڋ]"%4"I*<}]b*e_838&k =I$|Vq}`ixR-W=-륹c-7&RΓ6HtsRˬ'sܔQ0׻J} h). KBȲ0dH(0y/%XyEYx^;pH¡k̵_Lv҂@Ҩm@eG~"ˇن^>Τ:<-AJel\,$|CX44[x$/$ [UJoTFNhW'#k%rJU?/hǴ7b3 EgxӆٞkVߝ}sA{K5B*޽%S2&Wp %oR@N; ԳУYpʹ~XmQRťsOj/4UkHRy%vFVZ j\rlMܙҫ_ '遬#4(3\72usPj"6T7 b-b暽9|W-6X~N?HMP(x~2_/y r-8ROuHD"` jX'{ ~'JWOaF/S9r^H8<{gC\-n?jU:_m1eY X[Rtl`d4%Ky%n2eȊz# `. YH*ZWZqF[2k w|UQ,x mߵB8i)qbf.'bgI+/Lߜꇕ$|RBz/l@Ӓ ȎcmVƔ h=ԋ'Ew8Q=x7Y=>WHeˈbeK-ա gҰXv9Z#>)5(EL."u 2Uzx4Jeoմ19z*3B&OP7p)|G!,&p9mrc4Rػ=kĄv9" .ӭ[oBٶnNpT#Nv\}h:58g؉q^1=#? r#ޓy>4ATo6ٷb:o l\ҢE6U@,^ru_\UJ@60K)eIH2k.tni2#٠ۣKedɽo7ԁ 2Vt+,ŝ,dK)p/rvJ%ma5@U蹱t}.,Ͽ\mx&-e:7)q\"0D.6Ui}?b h242߼"tm.!gp23 6–xgԗ:X;}-s9<%%Du'cŤc,;&|"oT?Ѻ)WxM7][(ƌӜrZQI= W#ODpчR< /.Gf59ï:)m؞ǤѸh sSmC7R+c>plZF!NZ#(KV'|UI"o=wQ_=H(mGB*?Z؜&ӌ1.3&B Χ9١@z ɀ 돫t |`8:DzL7MO3oiO}'z,V,mQɣS> Jqۍ|G9!Àp 9;I$+1Ǖ/%R\BW tVÆLP[6}H|C~<6pU 'Gu#y)ё,8;Ba*1}Cmw/^ n"e7nk$M[fvv?g۾?>NU~zjn55A` =sU$:_"'ᣅ2F]͞\34Dpb_4lS,b^%5ZLEc(mB)u=˷ج ShF/J^:$SIx+[,!$B L|niɶOLәDGci(R9lL"Ih%߮}u,u{HgAQnQcR'(X"]ʟ^4d%D{V]/ϟ%4) KƒKUthS?0'"F!ɾ]UVu-xg\l\Euȇ>Y* cMzI'2w2M6Z71 Tv[DLC:!AꕣCɜ)(u3 3/\[lgE9~ݾ|q endstream endobj 497 0 obj << /Type /ObjStm /N 100 /First 905 /Length 3166 /Filter /FlateDecode >> stream x[nH}Waߪo@0/sq2ILtl9<&%RqXT:uI{ vX>O  o#|s+$1Nhei@D܃hDmh$)Z`ɠaN.A¨=N〬YaH]X D6Cz}MBEn W:ZZWzWRm͡H^* /MV~Nݞ.TkCic;kPpEa[IȏBUp+FK}舚|e#gեLlZʄt\IRGr &ՒIT #LKM?2k:)?e:lmVkCu6fR_5n!3`@5"RL#q=E+Z#ܵDݮ]l!xGIZv<ݔHbu?!$m|B󍗀R"!TC][M~.Q˒ۡfkM\~а.g%Ǣ6$ҦgY$~}!ȘE` a)ҀVªQ5;$ӊ&Xd^4g&oEd !?؈tPc'6$;hc2K_ =p)THԯL ƨJ0;^7"`lA`3d* 7q`3* aS0ԁ-mH&_#P~E2M[OcЂUJ|07 CN"{E#M7nPKثحVUz*J6"Rhe;6"w;JS[^^,M.y={P7}DIDm#%nc&|:99,l! yT~,w3`EvͨtDȯ |lk19c5+0 Q3MlI~wG3s}3,e-[%9{jPEQ~,.nbz^&(J5Q3EjNџtQT&2e|[EgM>3M8,kՊ7d͠ek%7cKk3&Ն*P~u#Z(_sU 0Zb5j7(SkDke~˱Ռy>ykHQɯ.#A;:e #ſsa" Nv W!LQfZ7fuiȑg0Ιe_]zcSY%߷[]]~k+5*v}֔D\얳j>VȳC9c9gE{wYʑ y)'JNL,R-~oNl<ۧmnYC7FcKn P|hT>@ 0Ww5B<l,&SAȏ5vNpWt492RFl<, pSX˿t ]W>Ou.G wA~O`Z[ƼaU#FϷ4 Z#7wkiGGFvLZ(46c"ZKBo>}~s # -ܧNun'~=}6"O&%V\(?]Dz|2^t/WX1YhnU"}U,Ub ogM^]ºXX endstream endobj 537 0 obj << /Type /ObjStm /N 100 /First 881 /Length 2098 /Filter /FlateDecode >> stream xڭ_o7)`?PHI8N`c}6V@R~=l!ϽQs$UU(ZI^E{ D;>d^"?6qA^@t]EfBFQD+Jh8kf4ICI`2WxaGniŖ!hb Fhb08+) 1\\, QaSe x 1&|8o!P@q( (c&t'%3m^2GF9;eYcLh h^W AUA8;E,!( e.fB!( t`aWPѼ(%a!ET=2:2 <( *P(<#KP.ByMPFƺʓϛϑ)ӕkL(7([,bPIȀ@,"BN>L(',OX A" ( =/\ȅ\g^ @6 N!(2>!dQA(THPPQkGMCTI99r V \ۯŷmnH7|G^>~q/Vޭa,G\_o)ӛØoDZR4\ vu??g;S:>'/?_|3դyFzu|l/.|VN:zSNJLgf[N|x7Wˏ.o٣؃as޿x!0H߫w+&r~Qegw_ CmSwC L]lfO٦vv٥wfV]㮖nļheSOˆFKUwl%-WLWvJ3-Z5Q]5-Z"IW-]-%-SũrV%Ohŕ{r ,qϕ{r ,qϕ{rO ,qO{rO ,qO{rO $qO{rI^Wu{pOr{-q+={-qs]{-p)T-Sl⮖nc̮=Ǻx`efUE<5fzďm<.)y̺Ю~e\}Xg݌ZZ{UK|ls~{هkHUvvLT-ih9I󙓛k5gK:Vs"$_͵s.:mױ:]_ǒvo|Kcu,:Mױ:6]_ǒto|Kcr:|W_u,:}Xu\}Sױ:.cquL]_ǒ똺7%_ױr:|W_Ǻ}Xu\}:|W_G)v%_GQr]]IuT}%jFKZ[)-{jm媖jr?e9Bl)lZ"IW-~reV{-'iU}{-{_]}ýÑrĽܻ.Kܻʽ;}-*>/6gigDىk33`Vg˙TmYjvWJ4MiN3pᘂ!%+Ef77qj,ށlWSG3S݆~Jl,i?){SzGOQJStpFWN$2F&/);teOGQ~91n;{>>LCY:Gቊe&c@ 7i endstream endobj 548 0 obj << /Producer (pdfTeX-1.40.15) /Creator (TeX) /CreationDate (D:20150328082146+01'00') /ModDate (D:20150328082146+01'00') /Trapped /False /PTEX.Fullbanner (This is pdfTeX, Version 3.14159265-2.6-1.40.15 (TeX Live 2014/Fink) kpathsea version 6.2.0) >> endobj 544 0 obj << /Type /ObjStm /N 4 /First 29 /Length 182 /Filter /FlateDecode >> stream x}= 0:H&i-. ~":i`C &mQ#c8 !f0%JD NV7*9< {ٚʴ?R_ oL-)l`Pɟn @q4ϯdZU"GU">C][띸w:ĥcڱ͹UO endstream endobj 549 0 obj << /Type /XRef /Index [0 550] /Size 550 /W [1 3 1] /Root 547 0 R /Info 548 0 R /ID [<4EE2BA66F187DB30488C96DBF64AC4CE> <4EE2BA66F187DB30488C96DBF64AC4CE>] /Length 1217 /Filter /FlateDecode >> stream x%9O]WFϾf2c&ccHD3v"0}QY >FD[Ge SDvbtY",DT@dѹr'PKV,DWVz\5{ȪuMfwn̷j! l#kRnTʫŘR]Qޥ.Y.y_MTRU|U!wh[|'U w.)AUm+@ʷSU)FU|+U [)LuH[T7o *]"t?)ϥ|T?ZRJ=z 5LQ)|-L;brn PG@;}[A|F-f5 0fi+`'`b0giSq ,XՌeKujjg`G*n-K/;w K]Yn_I<c#+P/ E^ p-JE%j@f-e0`/C4k/*% ZLE# C<<: rc;|c<wL`1 8ރqZU(jӪղ/#} VZ* Ih[39-}yexRՎYv TMT}aUf?Ȳ/T[6hZJՙe}ܲ{d]N D[_R`ٟ_On;\ endstream endobj startxref 195837 %%EOF quaternion/doc/quaternion.tex0000644000076500000240000000660112505453300015721 0ustar lukasstaff\input texinfo @c -*-texinfo-*- @c %**start of header @setfilename quaternion.info @settitle @thischapter @c use chapter name instead of title in the header of even pages @c @settitle Octave Quaternion Package @afourpaper @set VERSION 2.4.0 @finalout @c @afourwide @c %**end of header @c The following macro is used for the on-line help system, but we don't @c want lots of `See also: foo, bar, and baz' strings cluttering the @c printed manual (that information should be in the supporting text for @c each group of functions and variables). @macro seealso {args} @iftex @vskip 2pt @end iftex @ifnottex @c Texinfo @sp should work but in practice produces ugly results for HTML. @c A simple blank line produces the correct behavior. @c @sp 1 @end ifnottex @noindent @strong{See also:} \args\. @end macro @c %*** Start of TITLEPAGE @titlepage @title quaternion @value{VERSION} @subtitle Quaternion Package for GNU Octave @author Lukas F. Reichlin @author Juan Pablo Carbajal @page @vskip 0pt plus 1filll Copyright @copyright{} 2010-2015, Lukas F. Reichlin @email{lukas.reichlin@@gmail.com} This manual is generated automatically from the texinfo help strings of the package's functions. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. Permission is granted to copy and distribute translations of this manual into another language, under the same conditions as for modified versions. @page @paragraphindent 0 @chapheading Preface The @acronym{GNU} Octave quaternion package from version 2 onwards was developed by Lukas F. Reichlin with important contributions by Juan Pablo Carbajal. This new package is intended as a replacement for quaternion-1.0.0 by A. Scottedward Hodel. It is loosely based on ideas from the Quaternion Toolbox for Matlab by Steve Sangwine and Nicolas Le Bihan with a special focus on code simplicity and vectorization. Its main features are: @itemize @item Matrices and n-dimensional arrays of quaternions. @item Overloaded operators due to the use of classes introduced with Octave 3.2. @item Operator semantics similar to Octave's built-in complex numbers. @item Fully vectorized code for crunching large quaternion arrays in a speedy manner. @end itemize @sp 5 @subheading Using the help function Some functions of the quaternion package are listed with the somewhat cryptic prefix @code{@@quaternion/}. This prefix is only needed to view the help text of the function, e.g. @w{@code{help norm}} shows the built-in function while @w{@code{help @@quaternion/norm}} shows the overloaded function for quaternions. Note that there are quaternion functions like @code{unit} that have no built-in equivalent. When just using the function, the leading @code{@@quaternion/} must @strong{not} be typed. Octave selects the right function automatically. So one can type @w{@code{norm (q)}} and @w{@code{norm (matrix)}} regardless of the class of the argument. @end titlepage @c %*** End of TITLEPAGE @headings double @contents @c @chapter Function Reference @include functions.texi @end @node Function Index @unnumbered Function Index @printindex fn @bye quaternion/INDEX0000644000076500000240000000274212505453300013041 0ustar lukasstaffquaternion >> Quaternion Quaternion Constructors quaternion qi qj qk Conversions q2rot rot2q rotm2q Quaternion Methods @quaternion/abs @quaternion/arg @quaternion/blkdiag @quaternion/cast @quaternion/cat @quaternion/ceil @quaternion/columns @quaternion/conj @quaternion/cumsum @quaternion/diag @quaternion/diff @quaternion/exp @quaternion/fix @quaternion/floor @quaternion/full @quaternion/get @quaternion/inv @quaternion/isempty @quaternion/isfinite @quaternion/isinf @quaternion/isnan @quaternion/ispure @quaternion/isreal @quaternion/length @quaternion/log @quaternion/mean @quaternion/ndims @quaternion/norm @quaternion/numel @quaternion/repmat @quaternion/reshape @quaternion/round @quaternion/rows @quaternion/set @quaternion/size @quaternion/size_equal @quaternion/sparse @quaternion/squeeze @quaternion/sum @quaternion/tril @quaternion/triu @quaternion/unit Overloaded Quaternion Operators @quaternion/ctranspose @quaternion/end @quaternion/eq @quaternion/ge @quaternion/gt @quaternion/horzcat @quaternion/ldivide @quaternion/le @quaternion/lt @quaternion/minus @quaternion/mldivide @quaternion/mpower @quaternion/mrdivide @quaternion/mtimes @quaternion/ne @quaternion/plus @quaternion/power @quaternion/rdivide @quaternion/subsasgn @quaternion/subsref @quaternion/times @quaternion/transpose @quaternion/uminus @quaternion/uplus @quaternion/vertcat quaternion/inst/0000755000076500000240000000000012505453300013217 5ustar lukasstaffquaternion/inst/@quaternion/0000755000076500000240000000000012505453300015504 5ustar lukasstaffquaternion/inst/@quaternion/abs.m0000644000076500000240000000214712505453300016433 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{qabs} =} abs (@var{q}) ## Modulus of a quaternion. ## ## @example ## q = w + x*i + y*j + z*k ## abs (q) = sqrt (w.^2 + x.^2 + y.^2 + z.^2) ## @end example ## @end deftypefn ## Author: Lukas Reichlin ## Created: August 2010 ## Version: 0.2 function b = abs (a) if (nargin != 1) print_usage (); endif b = sqrt (norm2 (a)); endfunction quaternion/inst/@quaternion/arg.m0000644000076500000240000000231112505453300016430 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{theta} =} arg (@var{q}) ## Compute the argument or phase of quaternion @var{q} in radians. ## @var{theta} is defined as @code{atan2 (sqrt (q.x.^2 + q.y.^2 + q.z.^2), q.w)}. ## The argument @var{theta} lies in the range (0, pi). ## @end deftypefn ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function theta = arg (q) if (nargin != 1) print_usage (); endif theta = arg (complex (q.w, normv (q))); endfunction quaternion/inst/@quaternion/blkdiag.m0000644000076500000240000000324412505453300017262 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{q} =} blkdiag (@var{q1}, @var{q2}, @dots{}) ## Block-diagonal concatenation of quaternions. ## @end deftypefn ## Author: Lukas Reichlin ## Created: December 2011 ## Version: 0.1 function q = blkdiag (varargin) tmp = cellfun (@quaternion, varargin); # uniformoutput = true ! w = blkdiag (tmp.w); x = blkdiag (tmp.x); y = blkdiag (tmp.y); z = blkdiag (tmp.z); q = quaternion (w, x, y, z); endfunction %!shared C, D %! Aw = [2, 6; 10, 14]; %! Ax = [3, 7; 11, 15]; %! Ay = [4, 8; 12, 16]; %! Az = [5, 9; 13, 17]; %! A = quaternion (Aw, Ax, Ay, Az); %! %! Bw = [2, 6, 10; 14, 18, 22]; %! Bx = [3, 7, 11; 15, 19, 23]; %! By = [4, 8, 12; 16, 20, 24]; %! Bz = [5, 9, 13; 17, 21, 25]; %! B = quaternion (Bw, Bx, By, Bz); %! %! C = blkdiag (A, B); %! %! Dw = blkdiag (Aw, Bw); %! Dx = blkdiag (Ax, Bx); %! Dy = blkdiag (Ay, By); %! Dz = blkdiag (Az, Bz); %! D = quaternion (Dw, Dx, Dy, Dz); %!assert (C == D); quaternion/inst/@quaternion/cast.m0000644000076500000240000000344012505453300016615 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{q} =} cast (@var{q}, @var{'type'}) ## Convert the components of quaternion @var{q} to data type @var{type}. ## Valid types are int8, uint8, int16, uint16, int32, uint32, int64, ## uint64, double, single and logical. ## @end deftypefn ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function qret = cast (q, typ) if (nargin != 2 || ! ischar (typ)) # q is always a quaternion, no need to test print_usage (); endif if (! any (strcmp (typ, {"int8"; "uint8"; "int16"; "uint16"; "int32"; "uint32"; "int64"; "uint64"; "double"; "single"; "logical"}))) error ("quaternion: cast: type name '%s' is not a built-in type", typ); endif ## NOTE: Without strcmp, cast could be used to apply any function to the ## components of a quaternion. Shall I create such a method with ## a different name? w = feval (typ, q.w); x = feval (typ, q.x); y = feval (typ, q.y); z = feval (typ, q.z); qret = quaternion (w, x, y, z); endfunction quaternion/inst/@quaternion/cat.m0000644000076500000240000000230412505453300016430 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{q} =} cat (@var{dim}, @var{q1}, @var{q2}, @dots{}) ## Concatenation of quaternions along dimension @var{dim}. ## @end deftypefn ## Author: Lukas Reichlin ## Created: November 2011 ## Version: 0.1 function q = cat (dim, varargin) tmp = cellfun (@quaternion, varargin); # uniformoutput = true ! w = cat (dim, tmp.w); x = cat (dim, tmp.x); y = cat (dim, tmp.y); z = cat (dim, tmp.z); q = quaternion (w, x, y, z); endfunction quaternion/inst/@quaternion/ceil.m0000644000076500000240000000212512505453300016576 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{q} =} ceil (@var{q}) ## Round quaternion @var{q} towards positive infinity. ## @end deftypefn ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function q = ceil (q) if (nargin != 1) print_usage (); endif q.w = ceil (q.w); q.x = ceil (q.x); q.y = ceil (q.y); q.z = ceil (q.z); endfunction quaternion/inst/@quaternion/columns.m0000644000076500000240000000204512505453300017343 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{nc} =} columns (@var{q}) ## Return number of columns @var{nc} of quaternion array @var{q}. ## @end deftypefn ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.1 function c = columns (a) if (nargin != 1) print_usage (); endif c = columns (a.w); endfunction quaternion/inst/@quaternion/conj.m0000644000076500000240000000216212505453300016614 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{q} =} conj (@var{q}) ## Return conjugate of a quaternion. ## ## @example ## q = w + x*i + y*j + z*k ## conj (q) = w - x*i - y*j - z*k ## @end example ## @end deftypefn ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.1 function a = conj (a) if (nargin != 1) print_usage (); endif a.x = -a.x; a.y = -a.y; a.z = -a.z; endfunction quaternion/inst/@quaternion/ctranspose.m0000644000076500000240000000174012505453300020045 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## Conjugate transpose of a quaternion. Used by Octave for "q'". ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.1 function a = ctranspose (a) if (nargin != 1) print_usage (); endif a = conj (transpose (a)); endfunction quaternion/inst/@quaternion/cumsum.m0000644000076500000240000000312412505453300017173 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{q} =} cumsum (@var{q}) ## @deftypefnx {Function File} {@var{q} =} cumsum (@var{q}, @var{dim}) ## @deftypefnx {Function File} {@var{q} =} cumsum (@dots{}, @var{'native'}) ## @deftypefnx {Function File} {@var{q} =} cumsum (@dots{}, @var{'double'}) ## @deftypefnx {Function File} {@var{q} =} cumsum (@dots{}, @var{'extra'}) ## Cumulative sum of elements along dimension @var{dim}. If @var{dim} is omitted, ## it defaults to the first non-singleton dimension. ## See @code{help cumsum} for more information. ## @end deftypefn ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function q = cumsum (q, varargin) if (! isa (q, "quaternion")) print_usage (); endif q.w = cumsum (q.w, varargin{:}); q.x = cumsum (q.x, varargin{:}); q.y = cumsum (q.y, varargin{:}); q.z = cumsum (q.z, varargin{:}); endfunction quaternion/inst/@quaternion/diag.m0000644000076500000240000000350512505453300016571 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{q} =} diag (@var{v}) ## @deftypefnx {Function File} {@var{q} =} diag (@var{v}, @var{k}) ## Return a diagonal quaternion matrix with quaternion vector V on diagonal K. ## The second argument is optional. If it is positive, ## the vector is placed on the K-th super-diagonal. ## If it is negative, it is placed on the -K-th sub-diagonal. ## The default value of K is 0, and the vector is placed ## on the main diagonal. ## Given a matrix argument, instead of a vector, @command{diag} ## extracts the @var{K}-th diagonal of the matrix. ## @end deftypefn ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.2 function a = diag (a, b = 0) if (nargin > 2) print_usage (); endif a.w = diag (a.w, b); a.x = diag (a.x, b); a.y = diag (a.y, b); a.z = diag (a.z, b); endfunction %!shared R, S, T, U %! Q = quaternion (2, 3, 4, 5); %! R = diag ([Q, Q, Q]); %! W = diag ([2, 2, 2]); %! X = diag ([3, 3, 3]); %! Y = diag ([4, 4, 4]); %! Z = diag ([5, 5, 5]); %! S = quaternion (W, X, Y, Z); %! T = diag (R); %! U = [Q; Q; Q]; %!assert (R == S); %!assert (T == U); quaternion/inst/@quaternion/diff.m0000644000076500000240000000371212505453300016575 0ustar lukasstaff## Copyright (c) 1998, 2000, 2005, 2007 Auburn University. ## Copyright (c) 2011 Juan Pablo Carbajal ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{qdot} =} diff (@var{q}, @var{omega}) ## Derivative of a quaternion. ## ## Let Q be a quaternion to transform a vector from a fixed frame to ## a rotating frame. If the rotating frame is rotating about the ## [x, y, z] axes at angular rates [wx, wy, wz], then the derivative ## of Q is given by ## ## @example ## Q' = diff(Q, omega) ## @end example ## ## If the passive convention is used (rotate the frame, not the vector), ## then ## ## @example ## Q' = diff(Q,-omega) ## @end example ## @end deftypefn ## Adapted from: qderiv by A. S. Hodel function qd = diff (q, Omega) if (nargin != 2) print_usage (); endif if (! isa (q, "quaternion") || ! isscalar (q.w)) error ("quaternion: first argument '%s' must be a scalar quaternion", inputname(1)); endif Omega = vec (Omega); if (length (Omega) != 3) error ("quaternion: second argument '%s' must be a length 3 vector", inputname(2)); endif qd = 0.5 * quaternion (Omega(1), Omega(2), Omega(3)) * q; endfunction %!shared q %! q = quaternion(3,1,0,0); %!assert(quaternion(0,0,0.5,1.5) == diff(q,[0 0 1])) %!assert(quaternion(0,0,2,1) == diff(q,[0 1 1])) quaternion/inst/@quaternion/display.m0000644000076500000240000000313312505453300017327 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## Display routine for quaternions. Used by Octave internally. ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.2 function display (q) name = inputname (1); s = size (q); if (length (s) == 2 && all (s == 1)) # scalar quaternion w = num2str (q.w, 4); x = __num2str__ (q.x); y = __num2str__ (q.y); z = __num2str__ (q.z); disp ([name, " = ", w, x, "i" y, "j", z, "k"]); else # non-scalar quaternion disp ([name, ".w ="]); disp (q.w); disp (""); disp ([name, ".x ="]); disp (q.x); disp (""); disp ([name, ".y ="]); disp (q.y); disp (""); disp ([name, ".z ="]); disp (q.z); disp (""); endif endfunction function str = __num2str__ (num) if (num < 0) str = " - "; else str = " + "; endif str = [str, num2str(abs (num), 4)]; endfunction quaternion/inst/@quaternion/end.m0000644000076500000240000000274712505453300016442 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## End indexing for quaternions. ## Used by Octave for "q(1:end)". ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function ret = end (q, k, n) ## error: end: no method for class double ## octave 3.6.4 raises an error for the following 4 variants: ## ret = end (q.w, k, n); ## ret = feval ("end", q.w, k, n); ## ret = feval (@end, q.w, k, n); ## ret = builtin ("end", q.w, k, n); if (n == 1) # q(idx), note that ndims (q.w) >= 2 ret = numel (q.w); else # q(idx1, idx2), q(idx1, idx2, idx3), ... ret = size (q.w, k); endif endfunction %!test %! w = eye (3); %! q = quaternion (w); %! assert (q(end).w, w(end)); %! assert (q(end,1).w, w(end,1)); %! assert (q(1,end).w, w(1,end)); quaternion/inst/@quaternion/eq.m0000644000076500000240000000233712505453300016274 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## Equal to operator for two quaternions. Used by Octave for "q1 == q2". ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.4 function bool = eq (a, b) if (nargin != 2) error ("quaternion: eq: this is a binary operator"); endif a = quaternion (a); b = quaternion (b); bool = (a.w == b.w) & (a.x == b.x) & (a.y == b.y) & (a.z == b.z); endfunction %!test %! a = quaternion (2, 3, 4, 5); %! b = quaternion (2, -3, 4, 5); %! assert (a == a, true); %! assert (a == b, false); quaternion/inst/@quaternion/exp.m0000644000076500000240000000230612505453300016457 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{qexp} =} exp (@var{q}) ## Exponential of a quaternion. ## @end deftypefn ## Author: Lukas Reichlin ## Created: November 2011 ## Version: 0.1 function q = exp (q) if (nargin != 1) print_usage (); endif normv = normv (q); exps = exp (q.w); sinv = sin (normv); q.w = exps .* cos (normv); q.x = exps .* (q.x ./ normv) .* sinv; q.y = exps .* (q.y ./ normv) .* sinv; q.z = exps .* (q.z ./ normv) .* sinv; endfunction quaternion/inst/@quaternion/fix.m0000644000076500000240000000210212505453300016443 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{q} =} fix (@var{q}) ## Round quaternion @var{q} towards zero. ## @end deftypefn ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function q = fix (q) if (nargin != 1) print_usage (); endif q.w = fix (q.w); q.x = fix (q.x); q.y = fix (q.y); q.z = fix (q.z); endfunction quaternion/inst/@quaternion/floor.m0000644000076500000240000000213312505453300017002 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{q} =} floor (@var{q}) ## Round quaternion @var{q} towards negative infinity. ## @end deftypefn ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function q = floor (q) if (nargin != 1) print_usage (); endif q.w = floor (q.w); q.x = floor (q.x); q.y = floor (q.y); q.z = floor (q.z); endfunction quaternion/inst/@quaternion/full.m0000644000076500000240000000221412505453300016623 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{fq} =} full (@var{sq}) ## Return a full storage quaternion representation @var{fq} ## from sparse or diagonal quaternion @var{sq}. ## @end deftypefn ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function q = full (q) if (nargin != 1) print_usage (); endif q.w = full (q.w); q.x = full (q.x); q.y = full (q.y); q.z = full (q.z); endfunction quaternion/inst/@quaternion/ge.m0000644000076500000240000000227512505453300016263 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## Greater-than-or-equal-to operator for two quaternions. ## Used by Octave for "q1 >= q2". ## The ordering is lexicographic. ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function bool = ge (a, b) if (nargin != 2) error ("quaternion: ge: this is a binary operator"); endif bool = ! lt (a, b); endfunction %!test %! a = quaternion (2, 3, 4, 5); %! b = quaternion (2, -3, 4, 5); %! assert (a >= b, true); %! assert (b >= a, false); quaternion/inst/@quaternion/get.m0000644000076500000240000000430712505453300016445 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {} get (@var{q}) ## @deftypefnx {Function File} {@var{value} =} get (@var{q}, @var{"key"}) ## @deftypefnx {Function File} {[@var{val1}, @var{val2}, @dots{}] =} get (@var{q}, @var{"key1"}, @var{"key2"}, @dots{}) ## Access key values of quaternion objects. ## ## @strong{Keys} ## @table @var ## @item w ## Return scalar part @var{w} of quaternion @var{q} as a built-in type. ## ## @item x, y, z ## Return component @var{x}, @var{y} or @var{z} of the vector part of ## quaternion @var{q} as a built-in type. ## ## @item s ## Return scalar part of quaternion @var{q}. The vector part of @var{q} ## is set to zero. ## ## @item v ## Return vector part of quaternion @var{q}. The scalar part of @var{q} ## is set to zero. ## @end table ## @end deftypefn ## Author: Lukas Reichlin ## Created: April 2014 ## Version: 0.1 function varargout = get (q, varargin) if (! isa (q, "quaternion")) error ("quaternion: get: first argument must be a quaternion"); endif if (! all (cellfun (@ischar, varargin))) error ("quaternion: get: key names must be strings"); endif if (nargin == 1) [keys, vals] = keys_vals (q); nrows = numel (keys); str = strjust (strvcat (keys), "right"); str = horzcat (repmat (" ", nrows, 1), str, repmat (": ", nrows, 1), strvcat (vals)); disp (str); else for k = 1 : (nargin-1) key = varargin{k}; idx = substruct (".", key); varargout{k} = subsref (q, idx); endfor endif endfunction quaternion/inst/@quaternion/gt.m0000644000076500000240000000260612505453300016300 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## Greater-than operator for two quaternions. ## Used by Octave for "q1 > q2". ## The ordering is lexicographic. ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function bool = gt (a, b) if (nargin != 2) error ("quaternion: gt: this is a binary operator"); endif a = quaternion (a); b = quaternion (b); bool = (a.w > b.w) ... | (a.w == b.w & a.x > b.x) ... | (a.w == b.w & a.x == b.x & a.y > b.y) ... | (a.w == b.w & a.x == b.x & a.y == b.y & a.z > b.z); endfunction %!test %! a = quaternion (2, 3, 4, 5); %! b = quaternion (2, -3, 4, 5); %! assert (a > b, true); %! assert (b > a, false); quaternion/inst/@quaternion/horzcat.m0000644000076500000240000000214212505453300017333 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## Horizontal concatenation of quaternions. Used by Octave for "[q1, q2]". ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.1 function q = horzcat (varargin) tmp = cellfun (@quaternion, varargin); # uniformoutput = true ! w = horzcat (tmp.w); x = horzcat (tmp.x); y = horzcat (tmp.y); z = horzcat (tmp.z); q = quaternion (w, x, y, z); endfunction quaternion/inst/@quaternion/inv.m0000644000076500000240000000341312505453300016457 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{qinv} =} inv (@var{q}) ## Return inverse of a quaternion. ## @end deftypefn ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.4 function a = inv (a) if (nargin != 1) print_usage (); endif if (isscalar (a.w)) norm2 = norm2 (a); a.w = a.w / norm2; a.x = -a.x / norm2; a.y = -a.y / norm2; a.z = -a.z / norm2; elseif (issquare (a.w)) ## blockwise inversion, use recursion ## the formula is well-known from linear algebra n = rows (a.w); # a is square m1 = fix (n/2); m2 = m1 + 1; A = subsref (a, substruct ("()", {1:m1, 1:m1})); B = subsref (a, substruct ("()", {1:m1, m2:n})); C = subsref (a, substruct ("()", {m2:n, 1:m1})); D = subsref (a, substruct ("()", {m2:n, m2:n})); iA = inv (A); iAB = iA * B; CiA = C * iA; X = inv (D - C * iAB); Y = X * CiA; a = [iA + iAB*Y, -iAB*X; -Y, X]; else error ("quaternion: inv: require square matrices of quaternions"); endif endfunction quaternion/inst/@quaternion/isempty.m0000644000076500000240000000206312505453300017355 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{bool} =} isempty (@var{q}) ## Return true if quaternion @var{q} is empty and false otherwise. ## @end deftypefn ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function bool = isempty (q) if (nargin != 1) print_usage (); endif bool = isempty (q.w); endfunction quaternion/inst/@quaternion/isfinite.m0000644000076500000240000000223712505453300017500 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{bool} =} isfinite (@var{q}) ## Return a logical array which is true where the elements of ## @var{q} are finite values and false where they are not. ## @end deftypefn ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function bool = isfinite (q) if (nargin != 1) print_usage (); endif bool = isfinite (q.w) & isfinite (q.x) & isfinite (q.y) & isfinite (q.z); endfunction quaternion/inst/@quaternion/isinf.m0000644000076500000240000000221012505453300016765 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{bool} =} isinf (@var{q}) ## Return a logical array which is true where the elements of ## @var{q} are infinite and false where they are not. ## @end deftypefn ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function bool = isinf (q) if (nargin != 1) print_usage (); endif bool = isinf (q.w) | isinf (q.x) | isinf (q.y) | isinf (q.z); endfunction quaternion/inst/@quaternion/isnan.m0000644000076500000240000000221212505453300016767 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{bool} =} isnan (@var{q}) ## Return a logical array which is true where the elements of ## @var{q} are NaN values and false where they are not. ## @end deftypefn ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function bool = isnan (q) if (nargin != 1) print_usage (); endif bool = isnan (q.w) | isnan (q.x) | isnan (q.y) | isnan (q.z); endfunction quaternion/inst/@quaternion/ispure.m0000644000076500000240000000210312505453300017165 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{bool} =} ispure (@var{q}) ## Return true if scalar part of quaternion is zero, otherwise return false. ## @end deftypefn ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.1 function bool = ispure (a) if (nargin != 1) print_usage (); endif bool = all ((abs (a.w) < eps)(:)); endfunction quaternion/inst/@quaternion/isreal.m0000644000076500000240000000226312505453300017144 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{bool} =} isreal (@var{q}) ## Return true if the vector part of quaternion @var{q} is zero ## and false otherwise. ## @end deftypefn ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function bool = isreal (q) if (nargin != 1) print_usage (); endif ## bool = all ((abs(q.x) < eps & abs(q.y) < eps & abs(q.z) < eps)(:)); bool = all ((q.x == 0 & q.y == 0 & q.z == 0)(:)); endfunction quaternion/inst/@quaternion/ldivide.m0000644000076500000240000000201612505453300017301 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## Element-wise left division for quaternions. Used by Octave for "q1 .\\ q2". ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.2 function q = ldivide (a, b) if (nargin != 2) error ("quaternion: ldivide: this is a binary operator"); endif q = a.^-1 .* b; endfunction quaternion/inst/@quaternion/le.m0000644000076500000240000000227212505453300016265 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## Less-than-or-equal-to operator for two quaternions. ## Used by Octave for "q1 <= q2". ## The ordering is lexicographic. ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function bool = le (a, b) if (nargin != 2) error ("quaternion: le: this is a binary operator"); endif bool = ! gt (a, b); endfunction %!test %! a = quaternion (2, 3, 4, 5); %! b = quaternion (2, -3, 4, 5); %! assert (a <= b, false); %! assert (b <= a, true); quaternion/inst/@quaternion/length.m0000644000076500000240000000231712505453300017146 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{l} =} length (@var{q}) ## Return the "length" @var{l} of the quaternion array @var{q}. ## For quaternion matrices, the length is the number of rows or columns, ## whichever is greater (this odd definition is used for compatibility ## with @acronym{MATLAB}). ## @end deftypefn ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function l = length (q) if (nargin != 1) print_usage (); endif l = length (q.w); endfunction quaternion/inst/@quaternion/log.m0000644000076500000240000000335212505453300016446 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{qlog} =} log (@var{q}) ## Logarithmus naturalis of a quaternion. ## @end deftypefn ## Author: Lukas Reichlin ## Created: November 2011 ## Version: 0.1 function q = log (q) if (nargin != 1) print_usage (); endif normq = abs (q); normv = normv (q); acossq = acos (q.w ./ normq); q.w = log (normq); q.x = (q.x ./ normv) .* acossq; q.y = (q.y ./ normv) .* acossq; q.z = (q.z ./ normv) .* acossq; ## FIXME: q = quaternion (2, 3, 4, 5) ## p = log (exp (q)) ## p.v is wrong, probably somehow related to acos ## NOTE: p = exp (log (q)) is calculated correctly ## NOTE: qtfm 1.9 returns the same "wrong" result endfunction %!shared A, B %! Aw = [2, 6, 10; 14, 18, 22]; %! Ax = [3, 7, 11; 15, 19, 23]; %! Ay = [4, 8, 12; 16, 20, 24]; %! Az = [5, 9, 13; 17, 21, 25]; %! A = quaternion (Aw, Ax, Ay, Az); %! %! B = exp (log (A)); %! %!assert (A.w, B.w, 1e-4); %!assert (A.x, B.x, 1e-4); %!assert (A.y, B.y, 1e-4); %!assert (A.z, B.z, 1e-4); quaternion/inst/@quaternion/lt.m0000644000076500000240000000260712505453300016306 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## Less-than operator for two quaternions. ## Used by Octave for "q1 < q2". ## The ordering is lexicographic. ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function bool = lt (a, b) if (nargin != 2) error ("quaternion: lt: this is a binary operator"); endif a = quaternion (a); b = quaternion (b); bool = (a.w < b.w) ... | (a.w == b.w & a.x < b.x) ... | (a.w == b.w & a.x == b.x & a.y < b.y) ... | (a.w == b.w & a.x == b.x & a.y == b.y & a.z < b.z); endfunction %!test %! a = quaternion (2, 3, 4, 5); %! b = quaternion (2, -3, 4, 5); %! assert (a < b, false); %! assert (b < a, true); quaternion/inst/@quaternion/mean.m0000644000076500000240000000315312505453300016604 0ustar lukasstaff## Copyright (C) 2013 Willem Atsma ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{q} =} mean (@var{q}) ## @deftypefnx {Function File} {@var{q} =} mean (@var{q}, @var{dim}) ## @deftypefnx {Function File} {@var{q} =} mean (@var{q}, @var{opt}) ## @deftypefnx {Function File} {@var{q} =} mean (@var{q}, @var{dim}, @var{opt}) ## Compute the mean of the elements of the quaternion array @var{q}. ## ## @example ## mean (q) = mean (q.w) + mean (q.x)*i + mean (q.y)*j + mean (q.z)*k ## @end example ## ## See @code{help mean} for more information and a description of the ## parameters @var{dim} and @var{opt}. ## @end deftypefn ## Author: Willem Atsma ## Created: June 2013 ## Version: 0.1 function q = mean (q, varargin) if (! isa (q, "quaternion")) print_usage (); endif w = mean (q.w, varargin{:}); x = mean (q.x, varargin{:}); y = mean (q.y, varargin{:}); z = mean (q.z, varargin{:}); q = quaternion (w, x, y, z); endfunction quaternion/inst/@quaternion/minus.m0000644000076500000240000000217312505453300017020 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## Subtraction of two quaternions. Used by Octave for "q1 - q2". ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.2 function q = minus (a, b) if (nargin != 2) error ("quaternion: minus: this is a binary operator"); endif a = quaternion (a); b = quaternion (b); w = a.w - b.w; x = a.x - b.x; y = a.y - b.y; z = a.z - b.z; q = quaternion (w, x, y, z); endfunction quaternion/inst/@quaternion/mldivide.m0000644000076500000240000000201212505453300017452 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## Matrix left division for quaternions. Used by Octave for "q1 \\ q2". ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.2 function q = mldivide (a, b) if (nargin != 2) error ("quaternion: mldivide: this is a binary operator"); endif q = inv (a) * b; endfunction quaternion/inst/@quaternion/mpower.m0000644000076500000240000000367412505453300017205 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## Matrix power operator of quaternions. Used by Octave for "q^x". ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.2 function q = mpower (a, b) if (nargin != 2) error ("quaternion: mpower: this is a binary operator"); endif [r, c] = size (a); if (r != c) error ("quaternion: mpower: quaternion matrix must be square"); endif if (r == 1 && c == 1) # a scalar, b? q = a .^ b; # b could be a quaternion elseif (is_real_array (b) && isscalar (b) && fix (b) == b) e = fix (abs (b)); switch (sign (b)) case -1 # q^-e a = inv (a); q = a; case 0 # q^0 q = eye (r); # alternative: q = quaternion (eye (r)) return; case 1; # q^e q = a; endswitch for k = 2 : e q *= a; # improvement?: q^8 = ((q^2)^2)^2, q^9 = (((q^2)^2)^2)*q endfor else error ("quaternion: mpower: case not implemented yet"); q = expm (logm (a) * b); # don't know whether this formula is correct endif ## TODO: - q1 ^ q2 ## - arrays endfunction quaternion/inst/@quaternion/mrdivide.m0000644000076500000240000000201212505453300017460 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## Matrix right division for quaternions. Used by Octave for "q1 / q2". ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.2 function q = mrdivide (a, b) if (nargin != 2) error ("quaternion: mrdivide: this is a binary operator"); endif q = a * inv (b); endfunction quaternion/inst/@quaternion/mtimes.m0000644000076500000240000000236612505453300017167 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## Matrix multiplication of two quaternions. Used by Octave for "q1 * q2". ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.2 function q = mtimes (a, b) if (nargin != 2) error ("quaternion: mtimes: this is a binary operator"); endif a = quaternion (a); b = quaternion (b); w = a.w*b.w - a.x*b.x - a.y*b.y - a.z*b.z; x = a.y*b.z - a.z*b.y + a.w*b.x + a.x*b.w; y = a.z*b.x - a.x*b.z + a.w*b.y + a.y*b.w; z = a.x*b.y - a.y*b.x + a.w*b.z + a.z*b.w; q = quaternion (w, x, y, z); endfunction quaternion/inst/@quaternion/ndims.m0000644000076500000240000000232412505453300016775 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{n} =} ndims (@var{q}) ## Return the number of dimensions of quaternion @var{q}. ## For any array, the result will always be larger than or equal to 2. ## Trailing singleton dimensions are not counted. ## @end deftypefn ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function n = ndims (q) if (nargin != 1) print_usage (); endif n = ndims (q.w); endfunction %!test %! assert (ndims (quaternion (ones (4, 1, 2, 1))), 3); quaternion/inst/@quaternion/ne.m0000644000076500000240000000221512505453300016264 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## Not-equal-to operator for two quaternions. Used by Octave for "q1 != q2". ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function bool = ne (a, b) if (nargin != 2) error ("quaternion: ne: this is a binary operator"); endif bool = ! eq (a, b); endfunction %!test %! a = quaternion (2, 3, 4, 5); %! b = quaternion (2, -3, 4, 5); %! assert (a != a, false); %! assert (a != b, true); quaternion/inst/@quaternion/norm.m0000644000076500000240000000227212505453300016640 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{n} =} norm (@var{q}) ## Norm of a quaternion. ## @end deftypefn ## Author: Lukas Reichlin ## Created: November 2011 ## Version: 0.1 function n = norm (a) if (nargin != 1) print_usage (); endif if (! isscalar (a.w)) warning ("norm: use 'abs' to calculate the lengths of quaternion arrays"); error ("norm: only the 2-norm of scalar quaternions is implemented until now"); endif n = abs (a); endfunction quaternion/inst/@quaternion/numel.m0000644000076500000240000000255512505453300017011 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{n} =} numel (@var{q}) ## @deftypefnx {Function File} {@var{n} =} numel (@var{q}, @var{idx1}, @var{idx2}, @dots{}) ## For internal use only, use @code{prod(size(q))} or @code{numel (q.w)} instead. ## For technical reasons, this method must return the number of elements which are ## returned from cs-list indexing, no matter whether it is called with one or more ## arguments. ## @end deftypefn ## Author: Lukas Reichlin ## Created: February 2015 ## Version: 0.1 function ret = numel (q, varargin) ret = builtin ("numel", q, varargin{:}); endfunction %!test %! assert (numel (quaternion (eye (3))), 1); quaternion/inst/@quaternion/plus.m0000644000076500000240000000210612505453300016644 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## Addition of two quaternions. Used by Octave for "q1 + q2". ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.2 function q = plus (varargin) tmp = cellfun (@quaternion, varargin); # uniformoutput = true ! w = plus (tmp.w); x = plus (tmp.x); y = plus (tmp.y); z = plus (tmp.z); q = quaternion (w, x, y, z); endfunction quaternion/inst/@quaternion/power.m0000644000076500000240000000373612505453300017027 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## Copyright (c) 2011 Juan Pablo Carbajal ## ## 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 . ## -*- texinfo -*- ## Power operator of quaternions. Used by Octave for "q.^x". ## Exponent x can be scalar or of appropriate size. ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.4 function a = power (a, b) if (nargin != 2) error ("quaternion: power: this is a binary operator"); endif if (isa (b, "quaternion")) # exponent is a quaternion a = exp (log (a) .* b); # a could be real, but log doesn't care elseif (! isreal (b)) error ("quaternion:invalidArgument", "quaternion: power: invalid exponent"); elseif (b == -1) # special case for ldivide and rdivide norm2 = norm2 (a); # a is quaternion because b is not, a.w = a.w ./ norm2; # otherwise octave wouldn't call a.x = -a.x ./ norm2; # quaternion's power operator. a.y = -a.y ./ norm2; a.z = -a.z ./ norm2; else # exponent is real na = abs (a); nv = normv (a); th = acos (a.w ./ na); nab = na.^b; snt = sin (b.*th); a.w = nab .* cos (b.*th); a.x = (a.x ./ nv) .* nab .* snt; a.y = (a.y ./ nv) .* nab .* snt; a.z = (a.z ./ nv) .* nab .* snt; endif endfunction quaternion/inst/@quaternion/private/0000755000076500000240000000000012505453300017156 5ustar lukasstaffquaternion/inst/@quaternion/private/keys_vals.m0000644000076500000240000000334112505453300021335 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{keys}, @var{vals}] =} keys_vals (@var{q}) ## Return the list of keys as well as the assignable values for a quaternion q. ## @end deftypefn ## Author: Lukas Reichlin ## Created: April 2014 ## Version: 0.1 function [keys, vals] = keys_vals (q) str = num2str (size (q), "%d "); str = regexprep (str, " ", "x"); ## cell vector of keys keys = {"w"; "x"; "y"; "z"; "s"; "v"}; ## cell vector of values vals = {sprintf("real-valued array of type '%s', dimensions (%s)", class (q.w), str); sprintf("real-valued array of type '%s', dimensions (%s)", class (q.x), str); sprintf("real-valued array of type '%s', dimensions (%s)", class (q.y), str); sprintf("real-valued array of type '%s', dimensions (%s)", class (q.z), str); sprintf("scalar part of type 'quaternion', dimensions (%s)", str); sprintf("vector part of type 'quaternion', dimensions (%s)", str)}; endfunction quaternion/inst/@quaternion/private/norm2.m0000644000076500000240000000176712505453300020404 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{norm2} =} norm2 (@var{q}) ## Return squared norm of a quaternion. ## @end deftypefn ## Author: Lukas Reichlin ## Created: November 2011 ## Version: 0.1 function ret = norm2 (a) ret = a.w.^2 + a.x.^2 + a.y.^2 + a.z.^2; endfunction quaternion/inst/@quaternion/private/normv.m0000644000076500000240000000176012505453300020501 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{normv} =} normv (@var{q}) ## Return norm of the vector part. ## @end deftypefn ## Author: Lukas Reichlin ## Created: November 2011 ## Version: 0.1 function ret = normv (a) ret = sqrt (a.x.^2 + a.y.^2 + a.z.^2); endfunction quaternion/inst/@quaternion/quaternion.m0000644000076500000240000000620312505453300020050 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{q} =} quaternion (@var{w}) ## @deftypefnx {Function File} {@var{q} =} quaternion (@var{x}, @var{y}, @var{z}) ## @deftypefnx {Function File} {@var{q} =} quaternion (@var{w}, @var{x}, @var{y}, @var{z}) ## Constructor for quaternions - create or convert to quaternion. ## ## @example ## q = w + x*i + y*j + z*k ## @end example ## ## Arguments @var{w}, @var{x}, @var{y} and @var{z} can be scalars, ## matrices or n-dimensional arrays, but they must be real-valued ## and of equal size. ## If scalar part @var{w} or components @var{x}, @var{y} and @var{z} ## of the vector part are not specified, zero matrices of appropriate ## size are assumed. ## ## @strong{Example} ## @example ## @group ## octave:1> q = quaternion (2) ## q = 2 + 0i + 0j + 0k ## ## octave:2> q = quaternion (3, 4, 5) ## q = 0 + 3i + 4j + 5k ## ## octave:3> q = quaternion (2, 3, 4, 5) ## q = 2 + 3i + 4j + 5k ## @end group ## @end example ## @example ## @group ## octave:4> w = [2, 6, 10; 14, 18, 22]; ## octave:5> x = [3, 7, 11; 15, 19, 23]; ## octave:6> y = [4, 8, 12; 16, 20, 24]; ## octave:7> z = [5, 9, 13; 17, 21, 25]; ## octave:8> q = quaternion (w, x, y, z) ## q.w = ## 2 6 10 ## 14 18 22 ## ## q.x = ## 3 7 11 ## 15 19 23 ## ## q.y = ## 4 8 12 ## 16 20 24 ## ## q.z = ## 5 9 13 ## 17 21 25 ## ## octave:9> ## @end group ## @end example ## ## @end deftypefn ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.3 function q = quaternion (a, b, c, d) switch (nargin) case 1 if (isa (a, "quaternion")) # quaternion (q) q = a; return; elseif (is_real_array (a)) # quaternion (w) b = c = d = zeros (size (a), class (a)); else print_usage (); endif case 3 # quaternion (x, y, z) d = c; c = b; b = a; a = zeros (size (a), class (a)); case 4 # quaternion (w, x, y, z) ## nothing to do here, just prevent case "otherwise" otherwise print_usage (); endswitch if (! is_real_array (a, b, c, d)) error ("quaternion: arguments must be real-valued scalars, matrices or n-dimensional arrays"); endif if (! size_equal (a, b, c, d)); error ("quaternion: arguments must have identical sizes"); endif q = class (struct ("w", a, "x", b, "y", c, "z", d), "quaternion"); endfunction quaternion/inst/@quaternion/rdivide.m0000644000076500000240000000201612505453300017307 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## Element-wise right division for quaternions. Used by Octave for "q1 ./ q2". ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.2 function q = rdivide (a, b) if (nargin != 2) error ("quaternion: rdivide: this is a binary operator"); endif q = a .* b.^-1; endfunction quaternion/inst/@quaternion/repmat.m0000644000076500000240000000315112505453300017152 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{qret} =} repmat (@var{q}, @var{m}) ## @deftypefnx {Function File} {@var{qret} =} repmat (@var{q}, @var{m}, @var{n}) ## @deftypefnx {Function File} {@var{qret} =} repmat (@var{q}, [@var{m} @var{n}]) ## @deftypefnx {Function File} {@var{qret} =} repmat (@var{q}, [@var{m} @var{n} @var{p} @dots{}]) ## Form a block quaternion matrix @var{qret} of size @var{m} by @var{n}, ## with a copy of quaternion matrix @var{q} as each element. ## If @var{n} is not specified, form an @var{m} by @var{m} block matrix. ## @end deftypefn ## Author: Lukas Reichlin ## Created: July 2014 ## Version: 0.1 function q = repmat (a, varargin) if (! isa (a, "quaternion")) print_usage (); endif w = repmat (a.w, varargin{:}); x = repmat (a.x, varargin{:}); y = repmat (a.y, varargin{:}); z = repmat (a.z, varargin{:}); q = quaternion (w, x, y, z); endfunction quaternion/inst/@quaternion/reshape.m0000644000076500000240000000320512505453300017311 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{q} =} reshape (@var{q}, @var{m}, @var{n}, @dots{}) ## @deftypefnx {Function File} {@var{q} =} reshape (@var{q}, [@var{m} @var{n} @dots{}]) ## @deftypefnx {Function File} {@var{q} =} reshape (@var{q}, @dots{}, [], @dots{}) ## @deftypefnx {Function File} {@var{q} =} reshape (@var{q}, @var{size}) ## Return a quaternion array with the specified dimensions (@var{m}, @var{n}, @dots{}) ## whose elements are taken from the quaternion array @var{q}. The elements of the ## quaternion are accessed in column-major order (like Fortran arrays are stored). ## @end deftypefn ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function q = reshape (q, varargin) if (! isa (q, "quaternion")) print_usage (); endif q.w = reshape (q.w, varargin{:}); q.x = reshape (q.x, varargin{:}); q.y = reshape (q.y, varargin{:}); q.z = reshape (q.z, varargin{:}); endfunction quaternion/inst/@quaternion/round.m0000644000076500000240000000216012505453300017010 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{q} =} round (@var{q}) ## Round the components of quaternion @var{q} towards the nearest integers. ## @end deftypefn ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function q = round (q) if (nargin != 1) print_usage (); endif q.w = round (q.w); q.x = round (q.x); q.y = round (q.y); q.z = round (q.z); endfunction quaternion/inst/@quaternion/rows.m0000644000076500000240000000203112505453300016650 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{nr} =} rows (@var{q}) ## Return number of rows @var{nr} of quaternion array @var{q}. ## @end deftypefn ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.1 function r = rows (a) if (nargin != 1) print_usage (); endif r = rows (a.w); endfunction quaternion/inst/@quaternion/set.m0000644000076500000240000000576712505453300016474 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {} set (@var{q}) ## @deftypefnx {Function File} {} set (@var{q}, @var{"key"}, @var{value}, @dots{}) ## @deftypefnx {Function File} {@var{qret} =} set (@var{q}, @var{"key"}, @var{value}, @dots{}) ## Set or modify properties of quaternion objects. ## If no return argument @var{qret} is specified, the modified quaternion object is stored ## in input argument @var{q}. @command{set} can handle multiple keys in one call: ## @code{set (q, 'key1', val1, 'key2', val2, 'key3', val3)}. ## @code{set (q)} prints a list of the object's key names. ## ## @strong{Keys} ## @table @var ## @item w ## Assign real-valued array @var{val} to scalar part @var{w} of quaternion @var{q}. ## ## @item x, y, z ## Assign real-valued array @var{val} to component @var{x}, @var{y} or @var{z} ## of the vector part of quaternion @var{q}. ## ## @item s ## Assign scalar part of quaternion @var{val} to scalar part of quaternion @var{q}. ## The vector part of @var{q} is left untouched. ## ## @item v ## Assign vector part of quaternion @var{val} to vector part of quaternion @var{q}. ## The scalar part of @var{q} is left untouched. ## @end table ## @end deftypefn ## Author: Lukas Reichlin ## Created: April 2014 ## Version: 0.1 function qret = set (q, varargin) if (! isa (q, "quaternion")) error ("quaternion: set: first argument must be a quaternion"); endif if (nargin == 1) # set (q) [keys, vals] = keys_vals (q); nrows = numel (keys); str = strjust (strvcat (keys), "right"); str = horzcat (repmat (" ", nrows, 1), str, repmat (": ", nrows, 1), strvcat (vals)); disp (str); if (nargout != 0) qret = q; endif else # set (q, "key", val, ...) if (rem (nargin-1, 2)) error ("quaternion: set: keys and values must come in pairs"); endif if (! all (cellfun (@ischar, varargin(1:2:end)))) error ("quaternion: set: key names must be strings"); endif for k = 1 : 2: (nargin-1) key = varargin{k}; val = varargin{k+1}; idx = substruct (".", key); q = subsasgn (q, idx, val); endfor if (nargout == 0) # set (q, "key1", val1, ...) assignin ("caller", inputname (1), q); else # q = set (q, "key1", val1, ...) qret = q; endif endif endfunction quaternion/inst/@quaternion/size.m0000644000076500000240000000442212505453300016636 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{nvec} =} size (@var{q}) ## @deftypefnx {Function File} {@var{n} =} size (@var{q}, @var{dim}) ## @deftypefnx {Function File} {[@var{nx}, @var{ny}, @dots{}] =} size (@var{q}) ## Return size of quaternion arrays. ## ## @strong{Inputs} ## @table @var ## @item q ## Quaternion object. ## @item dim ## If given a second argument, @command{size} will return the size of the ## corresponding dimension. ## @end table ## ## @strong{Outputs} ## @table @var ## @item nvec ## Row vector. The first element is the number of rows and the second ## element the number of columns. If @var{q} is an n-dimensional array ## of quaternions, the n-th element of @var{nvec} corresponds to the ## size of the n-th dimension of @var{q}. ## @item n ## Scalar value. The size of the dimension @var{dim}. ## @item nx ## Number of rows. ## @item ny ## Number of columns. ## @item @dots{} ## Sizes of the 3rd to n-th dimensions. ## @end table ## @end deftypefn ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.2 function varargout = size (a, b) switch (nargout) case {0, 1} switch (nargin) case 1 # nvec = size (q) varargout{1} = size (a.w); case 2 # n = size (q, dim) varargout{1} = size (a.w, b); otherwise print_usage (); endswitch otherwise if (nargin == 1) # [nx, ny, ...] = size (q) varargout = num2cell (size (a.w)); else print_usage (); endif endswitch endfunction quaternion/inst/@quaternion/size_equal.m0000644000076500000240000000236212505453300020026 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{bool} =} size_equal (@var{a}, @var{b}, @dots{}) ## Return true if quaternions (and matrices) @var{a}, @var{b}, @dots{} ## are of equal size and false otherwise. ## @end deftypefn ## Author: Lukas Reichlin ## Created: October 2012 ## Version: 0.1 function bool = size_equal (varargin) s = cellfun (@size, varargin, "uniformoutput", false); bool = (nargin == 1 || isequal (s{:})); # isequal errors out with only 1 argument, nargin==0 handled by built-in size_equal endfunction quaternion/inst/@quaternion/sparse.m0000644000076500000240000000220412505453300017155 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{sq} =} sparse (@var{fq}) ## Return a sparse quaternion representation @var{sq} from ## full quaternion @var{fq}. ## @end deftypefn ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function q = sparse (q) if (nargin != 1) print_usage (); endif q.w = sparse (q.w); q.x = sparse (q.x); q.y = sparse (q.y); q.z = sparse (q.z); endfunction quaternion/inst/@quaternion/squeeze.m0000644000076500000240000000244512505453300017350 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{qret} =} squeeze (@var{q}) ## Remove singleton dimensions from quaternion @var{q} and return the result. ## Note that for compatibility with @acronym{MATLAB}, all objects have a minimum ## of two dimensions and row vectors are left unchanged. ## @end deftypefn ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function ret = squeeze (q) if (nargin != 1) print_usage (); endif w = squeeze (q.w); x = squeeze (q.x); y = squeeze (q.y); z = squeeze (q.z); ret = quaternion (w, x, y, z); endfunction quaternion/inst/@quaternion/subsasgn.m0000644000076500000240000001017712505453300017515 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## Subscripted assignment for quaternions. ## Used by Octave for "q.key = value". ## ## @strong{Subscripts} ## @table @var ## @item q.w ## Assign real-valued array @var{val} to scalar part @var{w} of quaternion @var{q}. ## ## @item q.x, q.y, q.z ## Assign real-valued array @var{val} to component @var{x}, @var{y} or @var{z} ## of the vector part of quaternion @var{q}. ## ## @item q.s ## Assign scalar part of quaternion @var{val} to scalar part of quaternion @var{q}. ## The vector part of @var{q} is left untouched. ## ## @item q.v ## Assign vector part of quaternion @var{val} to vector part of quaternion @var{q}. ## The scalar part of @var{q} is left untouched. ## ## @item q(@dots{}) ## Assign @var{val} to certain elements of quaternion array @var{q}, e.g. @code{q(3, 2:end) = val}. ## @end table ## Author: Lukas Reichlin ## Created: November 2011 ## Version: 0.3 function q = subsasgn (q, idx, val) switch (idx(1).type) case "()" # q(...) = val if (length (idx(1).subs) == 1 && isa (val, "quaternion")) # required by horzcat, vertcat, cat, ... q(idx(1).subs{:}) = val; # q = cellfun (@quaternion, varargin) else # general case val = quaternion (val); w = subsasgn (q.w, idx, val.w); x = subsasgn (q.x, idx, val.x); y = subsasgn (q.y, idx, val.y); z = subsasgn (q.z, idx, val.z); q = quaternion (w, x, y, z); endif case "." # q.w = val if (is_real_array (val)) if (! size_equal (subsref (q.w, idx(2:end)), val)) error ("quaternion: subsasgn: invalid argument size (%s), require dimensions (%s)", ... regexprep (num2str (size (val), "%d "), " ", "x"), ... regexprep (num2str (size (subsref (q.w, idx(2:end))), "%d "), " ", "x")); endif switch (tolower (idx(1).subs)) case {"w", "e"} q.w = subsasgn (q.w, idx(2:end), val); case {"x", "i"} q.x = subsasgn (q.x, idx(2:end), val); case {"y", "j"} q.y = subsasgn (q.y, idx(2:end), val); case {"z", "k"} q.z = subsasgn (q.z, idx(2:end), val); otherwise error ("quaternion: subsasgn: invalid subscript name '%s'", idx(1).subs); endswitch elseif (isa (val, "quaternion")) if (! size_equal (subsref (q.w, idx(2:end)), val.w)) error ("quaternion: subsasgn: invalid argument size (%s), require dimensions (%s)", ... regexprep (num2str (size (val), "%d "), " ", "x"), ... regexprep (num2str (size (subsref (q.w, idx(2:end))), "%d "), " ", "x")); endif switch (tolower (idx(1).subs)) case "s" q.w = subsasgn (q.w, idx(2:end), val.w); case "v" q.x = subsasgn (q.x, idx(2:end), val.x); q.y = subsasgn (q.y, idx(2:end), val.y); q.z = subsasgn (q.z, idx(2:end), val.z); otherwise error ("quaternion: subsasgn: invalid subscript name '%s'", idx(1).subs); endswitch else error ("quaternion: subsasgn: invalid argument type, require real-valued array"); endif otherwise error ("quaternion: subsasgn: invalid subscript type '%s'", idx(1).type); endswitch endfunction quaternion/inst/@quaternion/subsref.m0000644000076500000240000000540112505453300017333 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## Subscripted reference for quaternions. Used by Octave for "q.w". ## ## @strong{Subscripts} ## @table @var ## @item q.w ## Return scalar part @var{w} of quaternion @var{q} as a built-in type. ## ## @item q.x, q.y, q.z ## Return component @var{x}, @var{y} or @var{z} of the vector part of ## quaternion @var{q} as a built-in type. ## ## @item q.s ## Return scalar part of quaternion @var{q}. The vector part of @var{q} ## is set to zero. ## ## @item q.v ## Return vector part of quaternion @var{q}. The scalar part of @var{q} ## is set to zero. ## ## @item q(@dots{}) ## Extract certain elements of quaternion array @var{q}, e.g. @code{q(3, 2:end)}. ## @end table ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.6 function ret = subsref (q, s) if (numel (s) == 0) ret = q; return; endif switch (s(1).type) case "." # q.w switch (tolower (s(1).subs)) case {"w", "e"} # scalar part, returned as built-in type ret = subsref (q.w, s(2:end)); case {"x", "i"} ret = subsref (q.x, s(2:end)); case {"y", "j"} ret = subsref (q.y, s(2:end)); case {"z", "k"} ret = subsref (q.z, s(2:end)); case "s" # scalar part, vector part set to zero q.x = q.y = q.z = zeros (size (q.w), class (q.w)); ret = subsref (q, s(2:end)); case "v" # vector part, scalar part set to zero q.w = zeros (size (q.w), class (q.w)); ret = subsref (q, s(2:end)); otherwise error ("quaternion: invalid subscript name '%s'", s(1).subs); endswitch case "()" # q(...) w = subsref (q.w, s(1)); x = subsref (q.x, s(1)); y = subsref (q.y, s(1)); z = subsref (q.z, s(1)); tmp = quaternion (w, x, y, z); ret = subsref (tmp, s(2:end)); otherwise error ("quaternion: invalid subscript type '%s'", s(1).type); endswitch endfunction quaternion/inst/@quaternion/sum.m0000644000076500000240000000305012505453300016464 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{q} =} sum (@var{q}) ## @deftypefnx {Function File} {@var{q} =} sum (@var{q}, @var{dim}) ## @deftypefnx {Function File} {@var{q} =} sum (@dots{}, @var{'native'}) ## @deftypefnx {Function File} {@var{q} =} sum (@dots{}, @var{'double'}) ## @deftypefnx {Function File} {@var{q} =} sum (@dots{}, @var{'extra'}) ## Sum of elements along dimension @var{dim}. If @var{dim} is omitted, ## it defaults to the first non-singleton dimension. ## See @code{help sum} for more information. ## @end deftypefn ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function q = sum (q, varargin) if (! isa (q, "quaternion")) print_usage (); endif q.w = sum (q.w, varargin{:}); q.x = sum (q.x, varargin{:}); q.y = sum (q.y, varargin{:}); q.z = sum (q.z, varargin{:}); endfunction quaternion/inst/@quaternion/times.m0000644000076500000240000000245412505453300017010 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## Element-wise multiplication of two quaternions. Used by Octave for "q1 .* q2". ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.2 function q = times (a, b) if (nargin != 2) error ("quaternion: times: this is a binary operator"); endif a = quaternion (a); b = quaternion (b); w = a.w .* b.w - a.x .* b.x - a.y .* b.y - a.z .* b.z; x = a.y .* b.z - a.z .* b.y + a.w .* b.x + a.x .* b.w; y = a.z .* b.x - a.x .* b.z + a.w .* b.y + a.y .* b.w; z = a.x .* b.y - a.y .* b.x + a.w .* b.z + a.z .* b.w; q = quaternion (w, x, y, z); endfunction quaternion/inst/@quaternion/transpose.m0000644000076500000240000000203612505453300017701 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## Transpose of a quaternion. Used by Octave for "q.'". ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.1 function a = transpose (a) if (nargin != 1) print_usage (); endif a.w = transpose (a.w); a.x = transpose (a.x); a.y = transpose (a.y); a.z = transpose (a.z); endfunction quaternion/inst/@quaternion/tril.m0000644000076500000240000000334412505453300016640 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{q} =} tril (@var{q}) ## @deftypefnx {Function File} {@var{q} =} tril (@var{q}, @var{k}) ## @deftypefnx {Function File} {@var{q} =} tril (@var{q}, @var{k}, @var{'pack'}) ## Return a new quaternion matrix formed by extracting the lower ## triangular part of the quaternion @var{q}, and setting all ## other elements to zero. The second argument @var{k} is optional, ## and specifies how many diagonals above or below the main diagonal ## should also be included. Default value for @var{k} is zero. ## If the option "pack" is given as third argument, the extracted ## elements are not inserted into a matrix, but rather stacked ## column-wise one above other. ## @end deftypefn ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function q = tril (q, varargin) if (! isa (q, "quaternion")) print_usage (); endif q.w = tril (q.w, varargin{:}); q.x = tril (q.x, varargin{:}); q.y = tril (q.y, varargin{:}); q.z = tril (q.z, varargin{:}); endfunction quaternion/inst/@quaternion/triu.m0000644000076500000240000000334412505453300016651 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{q} =} triu (@var{q}) ## @deftypefnx {Function File} {@var{q} =} triu (@var{q}, @var{k}) ## @deftypefnx {Function File} {@var{q} =} triu (@var{q}, @var{k}, @var{'pack'}) ## Return a new quaternion matrix formed by extracting the upper ## triangular part of the quaternion @var{q}, and setting all ## other elements to zero. The second argument @var{k} is optional, ## and specifies how many diagonals above or below the main diagonal ## should also be included. Default value for @var{k} is zero. ## If the option "pack" is given as third argument, the extracted ## elements are not inserted into a matrix, but rather stacked ## column-wise one above other. ## @end deftypefn ## Author: Lukas Reichlin ## Created: December 2013 ## Version: 0.1 function q = triu (q, varargin) if (! isa (q, "quaternion")) print_usage (); endif q.w = triu (q.w, varargin{:}); q.x = triu (q.x, varargin{:}); q.y = triu (q.y, varargin{:}); q.z = triu (q.z, varargin{:}); endfunction quaternion/inst/@quaternion/uminus.m0000644000076500000240000000203112505453300017176 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## Unary minus of a quaternion. Used by Octave for "-q". ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.2 function a = uminus (a) if (nargin != 1) error ("quaternion: uminus: this is an unary operator"); endif a.w = -a.w; a.x = -a.x; a.y = -a.y; a.z = -a.z; endfunction quaternion/inst/@quaternion/unit.m0000644000076500000240000000220612505453300016641 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{qn} =} unit (@var{q}) ## Normalize quaternion to length 1 (unit quaternion). ## ## @example ## q = w + x*i + y*j + z*k ## unit (q) = q ./ sqrt (w.^2 + x.^2 + y.^2 + z.^2) ## @end example ## @end deftypefn ## Author: Lukas Reichlin ## Created: November 2011 ## Version: 0.1 function q = unit (a) if (nargin != 1) print_usage (); endif q = a ./ abs (a); endfunction quaternion/inst/@quaternion/uplus.m0000644000076500000240000000177312505453300017042 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## Unary plus of a quaternion. Used by Octave for "+q". ## Author: Lukas Reichlin ## Created: November 2011 ## Version: 0.2 function a = uplus (a) if (nargin != 1) error ("quaternion: uplus: this is an unary operator"); endif ## nothing to do here endfunction quaternion/inst/@quaternion/vertcat.m0000644000076500000240000000214012505453300017327 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## Vertical concatenation of quaternions. Used by Octave for "[q1; q2]". ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.1 function q = vertcat (varargin) tmp = cellfun (@quaternion, varargin); # uniformoutput = true ! w = vertcat (tmp.w); x = vertcat (tmp.x); y = vertcat (tmp.y); z = vertcat (tmp.z); q = quaternion (w, x, y, z); endfunction quaternion/inst/q2rot.m0000644000076500000240000001000212505453300014435 0ustar lukasstaff## Copyright (C) 1998, 1999, 2000, 2002, 2005, 2006, 2007 Auburn University ## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {[@var{axis}, @var{angle}] =} q2rot (@var{q}) ## @deftypefnx {Function File} {[@var{axis}, @var{angle}, @var{qn}] =} q2rot (@var{q}) ## Extract vector/angle form of a unit quaternion @var{q}. ## ## @strong{Inputs} ## @table @var ## @item q ## Unit quaternion describing the rotation. ## Quaternion @var{q} can be a scalar or an array. ## In the latter case, @var{q} is reshaped to a row vector ## and the return values @var{axis} and @var{angle} are ## concatenated horizontally, accordingly. ## @end table ## ## @strong{Outputs} ## @table @var ## @item axis ## Eigenaxis as a 3-d unit vector @code{[x; y; z]}. ## If input argument @var{q} is a quaternion array, ## @var{axis} becomes a matrix where ## @var{axis(:,i)} corresponds to @var{q(i)}. ## @item angle ## Rotation angle in radians. The positive direction is ## determined by the right-hand rule applied to @var{axis}. ## The angle lies in the interval [0, 2*pi]. ## If input argument @var{q} is a quaternion array, ## @var{angle} becomes a row vector where ## @var{angle(i)} corresponds to @var{q(i)}. ## @item qn ## Optional output of diagnostic nature. ## @code{qn = reshape (q, 1, [])} or, if needed, ## @code{qn = reshape (unit (q), 1, [])}. ## @end table ## ## @strong{Example} ## @example ## @group ## octave:1> axis = [0; 0; 1] ## axis = ## ## 0 ## 0 ## 1 ## ## octave:2> angle = pi/4 ## angle = 0.78540 ## octave:3> q = rot2q (axis, angle) ## q = 0.9239 + 0i + 0j + 0.3827k ## octave:4> [vv, th] = q2rot (q) ## vv = ## ## 0 ## 0 ## 1 ## ## th = 0.78540 ## octave:5> theta = th*180/pi ## theta = 45.000 ## octave:6> ## @end group ## @end example ## ## @end deftypefn ## Adapted from: quaternion by A. S. Hodel ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.4 function [vv, theta, q] = q2rot (q) if (nargin != 1 || nargout > 3) print_usage (); endif if (! isa (q, "quaternion")) error ("q2rot: require quaternion as input"); endif if (any (abs (abs (q) - 1) > 1e-12)) warning ("q2rot:normalizing", "q2rot: abs(q) != 1, normalizing"); q = unit (q); # do we still need this with the atan2 formula? endif q = reshape (q, 1, []); # row vector ## According to Wikipedia, ## ## the formula using atan2 ## theta = 2 * atan2 (||x||, s) ## should be numerically more stable than ## theta = 2 * acos (s) ## Possibly it helps if the quaternion has not exactly unit length. vv = [q.x; q.y; q.z]; norm_vv = norm (vv, 2, "cols"); theta = 2 * atan2 (norm_vv, q.w); ## NOTE: sin (theta/2) = norm (vv) idx = (norm_vv != 0); if (any (idx)) vv(:, idx) ./= ones (3, 1) * norm_vv(idx); # normalize vectors, prevent division by zero endif idx = ! idx; if (any (idx)) vv(:, idx) = [1; 0; 0] * ones (1, nnz (idx)); # set real-valued quaternions to default value endif endfunction %!test %! q = quaternion (2, 0, 0, 0); %! w = warning ("query", "q2rot:normalizing"); %! warning ("off", w.identifier); %! [vv, th, qn] = q2rot (q); %! warning (w.identifier, w.state); %! assert (vv, [1; 0; 0], 1e-4); %! assert (th, 0, 1e-4); %! assert (qn == quaternion (1), true); quaternion/inst/qi.m0000644000076500000240000000243612505453300014013 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {} qi ## Create x-component of a quaternion's vector part. ## ## @example ## q = w + x*qi + y*qj + z*qk ## @end example ## ## @strong{Example} ## @example ## @group ## octave:1> q1 = quaternion (1, 2, 3, 4) ## q1 = 1 + 2i + 3j + 4k ## octave:2> q2 = 1 + 2*qi + 3*qj + 4*qk ## q2 = 1 + 2i + 3j + 4k ## octave:3> ## @end group ## @end example ## ## @end deftypefn ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.1 function q = qi if (nargin != 0) print_usage (); endif q = quaternion (0, 1, 0, 0); endfunction quaternion/inst/qj.m0000644000076500000240000000243612505453300014014 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {} qj ## Create y-component of a quaternion's vector part. ## ## @example ## q = w + x*qi + y*qj + z*qk ## @end example ## ## @strong{Example} ## @example ## @group ## octave:1> q1 = quaternion (1, 2, 3, 4) ## q1 = 1 + 2i + 3j + 4k ## octave:2> q2 = 1 + 2*qi + 3*qj + 4*qk ## q2 = 1 + 2i + 3j + 4k ## octave:3> ## @end group ## @end example ## ## @end deftypefn ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.1 function q = qj if (nargin != 0) print_usage (); endif q = quaternion (0, 0, 1, 0); endfunction quaternion/inst/qk.m0000644000076500000240000000243612505453300014015 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {} qk ## Create z-component of a quaternion's vector part. ## ## @example ## q = w + x*qi + y*qj + z*qk ## @end example ## ## @strong{Example} ## @example ## @group ## octave:1> q1 = quaternion (1, 2, 3, 4) ## q1 = 1 + 2i + 3j + 4k ## octave:2> q2 = 1 + 2*qi + 3*qj + 4*qk ## q2 = 1 + 2i + 3j + 4k ## octave:3> ## @end group ## @end example ## ## @end deftypefn ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.1 function q = qk if (nargin != 0) print_usage (); endif q = quaternion (0, 0, 0, 1); endfunction quaternion/inst/rot2q.m0000644000076500000240000000650112505453300014446 0ustar lukasstaff## Copyright (C) 1998, 1999, 2000, 2002, 2005, 2006, 2007 Auburn University ## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{q} =} rot2q (@var{axis}, @var{angle}) ## Create unit quaternion @var{q} which describes a rotation of ## @var{angle} radians about the vector @var{axis}. This function uses ## the active convention where the vector @var{axis} is rotated by @var{angle} ## radians. If the coordinate frame should be rotated by @var{angle} ## radians, also called the passive convention, this is equivalent ## to rotating the @var{axis} by @var{-angle} radians. ## ## @strong{Inputs} ## @table @var ## @item axis ## Vector @code{[x, y, z]} or @code{[x; y; z]} describing the axis of rotation. ## @item angle ## Rotation angle in radians. The positive direction is ## determined by the right-hand rule applied to @var{axis}. ## If @var{angle} is a real-valued array, a quaternion array ## @var{q} of the same size is returned. ## @end table ## ## @strong{Outputs} ## @table @var ## @item q ## Unit quaternion describing the rotation. ## If @var{angle} is an array, @var{q(i,j)} corresponds to ## the rotation angle @var{angle(i,j)}. ## @end table ## ## @strong{Example} ## @example ## @group ## octave:1> axis = [0, 0, 1]; ## octave:2> angle = pi/4; ## octave:3> q = rot2q (axis, angle) ## q = 0.9239 + 0i + 0j + 0.3827k ## octave:4> v = quaternion (1, 1, 0) ## v = 0 + 1i + 1j + 0k ## octave:5> vr = q * v * conj (q) ## vr = 0 + 0i + 1.414j + 0k ## octave:6> ## @end group ## @end example ## ## @end deftypefn ## Adapted from: quaternion by A. S. Hodel ## Author: Lukas Reichlin ## Created: May 2010 ## Version: 0.2 function q = rot2q (vv, theta) if (nargin != 2 || nargout > 1) print_usage (); endif if (! is_real_array (vv) || ! isvector (vv) || length (vv) != 3) error ("rot2q: first argument 'axis' must be a length three vector"); endif if (! is_real_array (theta)) error ("rot2q: second argument 'angle' must be a scalar"); endif if (norm (vv) == 0) error ("rot2q: first argument 'axis' is zero"); endif if (abs (norm (vv) - 1) > 1e-12) warning ("rot2q:axis", "rot2q: ||axis|| != 1, normalizing") vv = vv / norm (vv); endif if (any ((abs (theta) > 2*pi)(:))) warning ("rot2q:angle", "rot2q: |angle| > 2 pi, normalizing") theta = rem (theta, 2*pi); endif w = cos (theta ./ 2); st2 = sin (theta ./ 2); x = vv(1) .* st2; y = vv(2) .* st2; z = vv(3) .* st2; q = quaternion (w, x, y, z); endfunction %!shared ax, an %! q = rot2q ([1;0;0], -1.2*pi); %! [ax, an] = q2rot (q); %!assert (abs (ax(1)), 1, 1e-4); %!assert (an*ax(1), -1.2*pi, 1e-4); quaternion/inst/rotm2q.m0000644000076500000240000000443512505453300014627 0ustar lukasstaff## Copyright (C) 2013 Willem Atsma ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Function File} {@var{q} =} rotm2q (@var{R}) ## Convert 3x3 rotation matrix @var{R} to unit quaternion @var{q}. ## @end deftypefn ## Author: Willem Atsma ## Based on C code from ## Created: May 2013 ## Version: 0.1 function q = rotm2q (R) if (nargin != 1) print_usage (); endif if (! is_real_array (R) || ! isequal (size (R), [3, 3])) error ("rotm2q: require a (3x3) rotation matrix"); endif T = trace (R); if (T > 0) s = 0.5 / sqrt (T+1); w = 0.25 / s; x = (R(3,2) - R(2,3)) * s; y = (R(1,3) - R(3,1)) * s; z = (R(2,1) - R(1,2)) * s; else if (R(1,1) > R(2,2) && R(1,1) > R(3,3)) s = 2 * sqrt (1 + R(1,1) - R(2,2) - R(3,3)); w = (R(3,2) - R(2,3)) / s; x = 0.25 * s; y = (R(1,2) + R(2,1)) / s; z = (R(1,3) + R(3,1)) / s; elseif (R(2,2) > R(3,3)) s = 2 * sqrt (1 + R(2,2) - R(1,1) - R(3,3)); w = (R(1,3) - R(3,1)) / s; x = (R(1,2) + R(2,1)) / s; y = 0.25 * s; z = (R(2,3) + R(3,2) ) / s; else s = 2 * sqrt (1 + R(3,3) - R(1,1) - R(2,2)); w = (R(2,1) - R(1,2)) / s; x = (R(1,3) + R(3,1)) / s; y = (R(2,3) + R(3,2)) / s; z = 0.25 * s; endif endif q = quaternion (w, x, y, z); endfunction %!test %! R = eye (3); %! q = rotm2q (R); %! assert (q.w, 1, 1e-4); %! assert (q.x, 0, 1e-4); %! assert (q.y, 0, 1e-4); %! assert (q.z, 0, 1e-4); %!test %! R = [[1;0;0], [0;0;1], [0;-1;0]]; %! q = rotm2q (R); %! [ax, an] = q2rot (q); %! assert (ax(:), [1;0;0], 1e-4); %! assert (an, pi/2, 1e-4); quaternion/inst/test_quaternion.m0000644000076500000240000000231612505453300016623 0ustar lukasstaff## Copyright (C) 2010-2015 Lukas F. Reichlin ## ## 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 . ## -*- texinfo -*- ## @deftypefn {Script File} {} test_quaternion ## Execute all available tests at once. ## @end deftypefn ## Author: Lukas Reichlin ## Created: December 2011 ## Version: 0.1 test @quaternion/blkdiag test @quaternion/diag test @quaternion/diff test @quaternion/end test @quaternion/eq test @quaternion/ge test @quaternion/gt test @quaternion/le test @quaternion/log test @quaternion/lt test @quaternion/ndims test @quaternion/ne test @quaternion/numel test q2rot test rot2q test rotm2q quaternion/NEWS0000644000076500000240000001465512505454256012767 0ustar lukasstaffSummary of important user-visible changes for releases of the quaternion package =============================================================================== quaternion-2.4.0 Release Date: 2015-03-21 Release Manager: Lukas Reichlin =============================================================================== ** q2rot -- Vectorized code to support the input of multiple quaternions. -- Return axis as a column vector. -- Add test. ** rot2q -- Support for multiple rotation angles (vectorized code). -- Improved error messages. -- Add test. ** The following functions are new: rotm2q ** The following functions are now overloaded for quaternions: mean numel (Thanks to Willem Atsma for all the changes above) ** The quaternion package now depends on Octave version 3.8.0 or beyond. ** In order to comply with modified Octave Forge rules, the package no longer auto-loads. See "help pkg" for details on auto-loading. =============================================================================== quaternion-2.2.2 Release Date: 2014-07-20 Release Manager: Lukas Reichlin =============================================================================== ** q2rot Fixed bug #42666. The function no longer errors out. The bug has been introduced with the changes in quaternion-2.2.1. (Thanks to Kjell Andersen) ** The following functions are now overloaded for quaternions: repmat =============================================================================== quaternion-2.2.1 Release Date: 2014-05-05 Release Manager: Lukas Reichlin =============================================================================== ** The following functions are now overloaded for quaternions: get set While they offer no new editing features compared to subscripted assignment and reference, they can display the types and dimensions of the quaternion's components if called with one argument: get (q) set (q) ** subsasgn, subsref -- Improved documentation. -- Support assignment of scalar and vector part from other quaternions: q1.v = q2 # assign components x, y and z, leave w untouched =============================================================================== quaternion-2.2.0 Release Date: 2014-01-04 Release Manager: Lukas Reichlin =============================================================================== ** eq Changed operator semantics of "==" to match those of complex numbers and other built-in types. Quaternion arrays are now compared element-wise. The old behavior can be restored by the expression bool = size_equal (a, b) && all (eq (a, b)(:)) ** end "end" indexing for quaternions works now as expected. ** The following functions are now overloaded for quaternions: arg isempty reshape cast isfinite round ceil isinf sparse cumsum isnan squeeze fix isreal sum floor length tril full ndims triu ** The following operators are now overloaded for quaternions: ge (>=) le (<=) ne (!=, ~=) gt (>) lt (<) Since there is no ordering that makes quaternions an ordered field, several definitions are possible. The ordering chosen here is the lexicographic one. ** quaternion -- Allow logicals as quaternion components. -- When called with one or three arguments, fill missing vector or scalar part with zeros of the same class as the given arguments. Before, always doubles were used. =============================================================================== quaternion-2.0.3 Release Date: 2013-10-28 Release Manager: Lukas Reichlin =============================================================================== ** Compatibility to GNU Octave 3.8 Replaced line continuation marker "\" by "..." to avoid deprecated syntax warning. ** q2rot -- The rotation angle now lies in the interval [0, 2*pi]. -- Fixed bug #39521. (Thanks to Juan Pablo Carbajal and Max Katsev) http://savannah.gnu.org/bugs/?39521 =============================================================================== quaternion-2.0.2 Release Date: 2012-10-25 Release Manager: Lukas Reichlin =============================================================================== ** eq -- Fix typo bug which gave false positives for the k-component. -- Avoid error if arguments are non-conformant. ** size_equal Add overloaded method because the built-in function gives false positives for quaternions. ** ldivide, mldivide, mpower Show error message if the number of input arguments is not 2. =============================================================================== quaternion-2.0.1 Release Date: 2012-10-14 Release Manager: Lukas Reichlin =============================================================================== ** inv Support for the inversion of quaternion matrices. Right and left division operators (/ and \) profit from this change and support quaternion matrices as well. ** Check number of arguments when operators are called by their function names, e.g. plus (q1, q2, q3). Function plus supports now more than two arguments. ** doc/quaternion.pdf Revised PDF manual. There is now a function index at the end of the manual. ** The TeX-files quaternion.tex and functions.texi for generating quaternion.pdf are included in the doc folder, next to quaternion.pdf. Note that functions.texi is generated automatically by the scripts in the quaternion/devel folder and the package generate_html. They are not included in the quaternion package and can be found on the OctaveForge SVN server. =============================================================================== quaternion-2.0.0 Release Date: 2012-03-28 Release Manager: Lukas Reichlin =============================================================================== ** First official release. Its main features are: -- Matrices and n-dimensional arrays of quaternions. -- Overloaded operators due to the use of classes. -- Operator semantics similar to Octave’s built-in complex numbers. -- Vectorized code for crunching large quaternion arrays in a speedy manner. =============================================================================== quaternion/src/0000755000076500000240000000000012505453300013031 5ustar lukasstaffquaternion/src/is_real_array.cc0000644000076500000240000000327112505453300016157 0ustar lukasstaff/* Copyright (C) 2010-2015 Lukas F. Reichlin 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 . Return true if all arguments are real-valued arrays and false otherwise. Author: Lukas Reichlin Created: November 2011 Version: 0.3 */ #include DEFUN_DLD (is_real_array, args, nargout, "-*- texinfo -*-\n\ @deftypefn {Loadable Function} {} is_real_array (@var{a}, @dots{})\n\ Return true if all arguments are real-valued arrays and false otherwise.\n\ @var{[]} is a valid array.\n\ Avoid nasty stuff like @code{true = isreal (\"a\")}.\n\ @end deftypefn") { octave_value retval = true; octave_idx_type nargin = args.length (); if (nargin == 0) { print_usage (); } else { for (octave_idx_type i = 0; i < nargin; i++) { // args(i).ndims () should be always >= 2 if (args(i).ndims () < 2 || ! ((args(i).is_numeric_type () && args(i).is_real_type ()) || args(i).is_bool_type ())) { retval = false; break; } } } return retval; } quaternion/src/Makefile0000644000076500000240000000025412505453300014472 0ustar lukasstaffall: is_real_array.oct # helper is_real_array.oct: is_real_array.cc mkoctfile is_real_array.cc clean: rm -rf *.o core octave-core *.oct *~ realclean: clean rm -rf *.a