symbolic-3.1.1/0000755000000000000000000000000014405647405010234 5ustar symbolic-3.1.1/CONTRIBUTORS0000644000000000000000000000144414405647405012117 0ustar Authors and Contributors ======================== Colin B. Macdonald Willem J. Atsma Andrés Prieto Carnë Draug Vadim Gribanov Alexander Misel Mike Miller Lagu Abhinav Tripathi Utkarsh Gautam Eric Chassande-Mottin Nicol N. Schraudolph Sylvain Pelissier Alex Vong Marco Falke NVS Abhilash Orion Poplawski Osella Giancarlo Olaf Till Tasos Papastylianou Tianyu Chen (billchenchina) Johannes Maria Frank Chris Gorman Fernando Alvarruiz Tasos Papastylianou Jing-Chen Peng Rafael Laboissière (Please contact the developers if your name should be here but isn't!) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Thanks also to the authors of the original GiNaC-based symbolic package: Ben Sapp pkienzle Michael Goffioul Willem J. Atsma Rafael Laboissiere Thomas Weber adb014 hauberg symbolic-3.1.1/COPYING0000644000000000000000000010446114405647405011275 0ustar 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. {one line to give the program's name and a brief idea of what it does.} Copyright (C) {year} {name of author} This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . 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: {project} Copyright (C) {year} {fullname} 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 . symbolic-3.1.1/DESCRIPTION0000644000000000000000000000124114405647405011740 0ustar Name: symbolic Version: 3.1.1 Date: 2023-03-19 Author: Colin B. Macdonald Maintainer: Colin B. Macdonald Title: Octave Symbolic Package using SymPy Description: Adds symbolic calculation features to GNU Octave. These include common Computer Algebra System tools such as algebraic operations, calculus, equation solving, Fourier and Laplace transforms, variable precision arithmetic and other features. Compatibility with other symbolic toolboxes is intended. Categories: symbolic Url: https://octave.sourceforge.io/symbolic Depends: octave (>= 5.1) SystemRequirements: python, sympy (>= 1.4), mpmath (>= 1.0) License: GPL-3.0-or-later symbolic-3.1.1/INDEX0000644000000000000000000001153514405647405011033 0ustar symbolic >> Symbolic computing Main functions syms @sym/sym vpa sympref vpasolve Assumptions assume assumptions @sym/assume @sym/assumeAlso Symbolic Constants catalan eulergamma Functions cell2sym digits dirac fibonacci findsymbols finiteset heaviside laguerreL lambertw poly2sym Double-precision numerical functions @double/adjoint @double/bernoulli @double/chebyshevT @double/chebyshevU @double/coshint @double/cosint @double/dilog @double/euler @double/fresnelc @double/fresnels @double/harmonic @double/logint @double/pochhammer @double/polylog @double/sinhint @double/sinint @double/zeta Mathematical methods for symbolic objects @sym/abs @sym/acosd @sym/acosh @sym/acos @sym/acoth @sym/acot @sym/acsch @sym/acsc @sym/adjoint @sym/airy @sym/angle @sym/arg @sym/asech @sym/asec @sym/asind @sym/asinh @sym/asin @sym/atan2 @sym/atand @sym/atanh @sym/atan @sym/bernoulli @sym/besselh @sym/besseli @sym/besselj @sym/besseljn @sym/besselk @sym/bessely @sym/besselyn @sym/beta @sym/cart2pol @sym/cbrt @sym/ceil @sym/charpoly @sym/chebyshevT @sym/chebyshevU @sym/chol @sym/cond @sym/conj @sym/cosd @sym/coshint @sym/cosh @sym/cosint @sym/cos @sym/coth @sym/cot @sym/cross @sym/csch @sym/csc @sym/ctranspose @sym/cumprod @sym/cumsum @sym/curl @sym/dawson @sym/degree @sym/det @sym/diag @sym/diff @sym/dilog @sym/dirac @sym/divergence @sym/divisors @sym/dot @sym/dsolve @sym/eig @sym/ei @sym/ellipke @sym/ellipticCE @sym/ellipticCK @sym/ellipticCPi @sym/ellipticE @sym/ellipticF @sym/ellipticK @sym/ellipticPi @sym/erfcinv @sym/erfc @sym/erfi @sym/erfinv @sym/erf @sym/euler @sym/expint @sym/exp @sym/expm @sym/eye @sym/factorial @sym/fix @sym/floor @sym/fourier @sym/frac @sym/fresnelc @sym/fresnels @sym/gammainc @sym/gammaln @sym/gamma @sym/gradient @sym/harmonic @sym/heaviside @sym/hessian @sym/hilb @sym/horner @sym/hypergeom @sym/hypot @sym/ifourier @sym/igamma @sym/ilaplace @sym/imag @sym/int @sym/intersect @sym/interval @sym/invhilb @sym/inv @sym/ismember @sym/isprime @sym/jacobian @sym/jordan @sym/kroneckerDelta @sym/kron @sym/laguerreL @sym/lambertw @sym/laplace @sym/laplacian @sym/lu @sym/lgamma @sym/limit @sym/log10 @sym/log2 @sym/logint @sym/log @sym/max @sym/min @sym/mod @sym/nchoosek @sym/nextprime @sym/nnz @sym/norm @sym/null @sym/numden @sym/orth @sym/partfrac @sym/piecewise @sym/pinv @sym/pochhammer @sym/polylog @sym/potential @sym/prevprime @sym/prod @sym/psi @sym/qr @sym/rank @sym/real @sym/round @sym/rref @sym/sech @sym/sec @sym/setdiff @sym/setxor @sym/signIm @sym/sign @sym/sinc @sym/sind @sym/sinhint @sym/sinh @sym/sinint @sym/sin @sym/solve @sym/sqrt @sym/ssinint @sym/sum @sym/svd @sym/symprod @sym/symsum @sym/tand @sym/tanh @sym/tan @sym/taylor @sym/toeplitz @sym/trace @sym/transpose @sym/tril @sym/triu @sym/union @sym/unique @sym/zeta @sym/ztrans Methods for manipulating symbolic objects: @sym/argnames @sym/char @sym/children @sym/coeffs @sym/equationsToMatrix @sym/expand @sym/factor @sym/findsym @sym/find @sym/fliplr @sym/flipud @sym/formula @sym/has @sym/ipermute @sym/lhs @sym/permute @sym/rhs @sym/rewrite @sym/subs @sym/symreplace @sym/symvar Methods for converting symbolic objects to other formats @sym/ccode @sym/double @sym/eval @sym/fortran @sym/function_handle @sym/latex @sym/matlabFunction @sym/pretty @sym/sym2poly @sym/sympy Arithmetic and logical methods for symbolic objects @sym/all @sym/any @sym/and @sym/eq @sym/ge @sym/gt @sym/isallconstant @sym/isAlways @sym/iscolumn @sym/isconstant @sym/isempty @sym/isequal @sym/isequaln @sym/isfinite @sym/isinf @sym/ismatrix @sym/isna @sym/isnan @sym/isNone @sym/isrow @sym/isscalar @sym/isvector @sym/ldivide @sym/le @sym/lt @sym/minus @sym/mldivide @sym/mpower @sym/mrdivide @sym/mtimes @sym/ne @sym/not @sym/or @sym/plus @sym/power @sym/rdivide @sym/times @sym/uminus @sym/uplus @sym/xor Other methods for symbolic objects @sym/cat @sym/colon @sym/columns @sym/display @sym/disp @sym/end @sym/ezcontour @sym/ezmesh @sym/ezplot3 @sym/ezplot @sym/ezsurf @sym/horzcat @sym/length @sym/linspace @sym/logical @sym/logspace @sym/numel @sym/ones @sym/repmat @sym/reshape @sym/resize @sym/rows @sym/simplify @sym/size @sym/sort @sym/subsasgn @sym/subsindex @sym/subsref @sym/vertcat @sym/zeros Class for symbolic functions @symfun/argnames @symfun/diff @symfun/formula @symfun/int @symfun/isequal @symfun/isequaln @symfun/ldivide @symfun/minus @symfun/mldivide @symfun/mpower @symfun/mrdivide @symfun/mtimes @symfun/numel @symfun/plus @symfun/power @symfun/rdivide @symfun/size @symfun/subsref @symfun/symfun @symfun/symvar @symfun/times @symfun/uminus Miscellaneous @logical/isAlways Deprecated octsympy_tests symbolic-3.1.1/Makefile0000644000000000000000000001452214405647405011700 0ustar SHELL := /bin/bash ## Copyright 2016-2019, 2022 Colin B. Macdonald ## ## Copying and distribution of this file, with or without modification, ## are permitted in any medium without royalty provided the copyright ## notice and this notice are preserved. This file is offered as-is, ## without any warranty. PACKAGE := $(shell grep "^Name: " DESCRIPTION | cut -f2 -d" ") VERSION := $(shell grep "^Version: " DESCRIPTION | cut -f2 -d" ") MATLAB_PACKAGE_NAME := octsympy BUILD_DIR := tmp MATLAB_PKG := ${BUILD_DIR}/${MATLAB_PACKAGE_NAME}-matlab-${VERSION} MATLAB_PKG_ZIP := ${BUILD_DIR}/${MATLAB_PACKAGE_NAME}-matlab-${VERSION}.zip OCTAVE_RELEASE := ${BUILD_DIR}/${PACKAGE}-${VERSION} OCTAVE_RELEASE_TARBALL := ${BUILD_DIR}/${PACKAGE}-${VERSION}.tar.gz INSTALLED_PACKAGE := ~/octave/${PACKAGE}-${VERSION}/packinfo/DESCRIPTION HTML_DIR := ${BUILD_DIR}/${PACKAGE}-html HTML_TARBALL := ${HTML_DIR}.tar.gz OCTAVE ?= octave MATLAB ?= matlab .PHONY: help clean install test doctest dist dist_zip html matlab_test matlab_pkg help: @echo Available rules: @echo " clean clean all temporary files" @echo " install install package in Octave" @echo " test run tests with Octave" @echo " doctest run doctests with Octave" @echo " dist create Octave package (${OCTAVE_RELEASE_TARBALL})" @echo " html create Octave Forge website (${HTML_TARBALL})" @echo " release create both tarballs and md5 sums" @echo @echo " matlab_test run tests with Matlab" @echo " matlab_pkg create Matlab package (${MATLAB_PKG_ZIP})" GIT_DATE := $(shell git show -s --format=\%ci) # Follows the recommendations of https://reproducible-builds.org/docs/archives define create_tarball $(shell cd $(dir $(1)) \ && find $(notdir $(1)) -print0 \ | LC_ALL=C sort -z \ | tar c --mtime="$(GIT_DATE)" \ --owner=root --group=root --numeric-owner \ --no-recursion --null -T - -f - \ | gzip -9n > "$(2)") endef %.tar.gz: % $(call create_tarball,$<,$(notdir $@)) %.zip: % cd "$(BUILD_DIR)" ; zip -9qr - "$(notdir $<)" > "$(notdir $@)" $(OCTAVE_RELEASE): .git/index | $(BUILD_DIR) @echo "Creating package version $(VERSION) release ..." -$(RM) -r "$@" git archive --format=tar --prefix="$@/" HEAD | tar -x $(RM) "$@/README.matlab.md" \ "$@/HOWTO-release.md" \ "$@/TODO.md" \ "$@/.gitignore" \ "$@/.mailmap" \ "$@/screenshot.png" \ "$@/screenshot-install.png" $(RM) -r "$@/.github" $(RM) -r "$@/testing" "$@/util" chmod -R a+rX,u+w,go-w "$@" $(HTML_DIR): install | $(BUILD_DIR) @echo "Generating HTML documentation. This may take a while ..." -$(RM) -r "$@" $(OCTAVE) --no-window-system --silent \ --eval "pkg load generate_html; " \ --eval "pkg load $(PACKAGE);" \ --eval "options = get_html_options ('octave-forge');" \ --eval "generate_package_html ('${PACKAGE}', '${HTML_DIR}', options)" chmod -R a+rX,u+w,go-w $@ dist: $(OCTAVE_RELEASE_TARBALL) html: $(HTML_TARBALL) md5: $(OCTAVE_RELEASE_TARBALL) $(HTML_TARBALL) @md5sum $^ release: md5 @echo "Upload @ https://sourceforge.net/p/octave/package-releases/new/" @echo "*After review*, an Octave-Forge admin will tag this with:" @echo " git tag -a v$(VERSION) -m \"Version $(VERSION)\"" ${BUILD_DIR} ${MATLAB_PKG}/private ${MATLAB_PKG}/tests_matlab ${MATLAB_PKG}/@sym ${MATLAB_PKG}/@symfun ${MATLAB_PKG}/@logical ${MATLAB_PKG}/@double: mkdir -p "$@" clean: rm -rf "${BUILD_DIR}" rm -f fntests.log test: @echo "Testing package in GNU Octave ..." @$(OCTAVE) --no-gui --silent --path "${CURDIR}/inst" \ --eval "set (0, 'defaultfigurevisible', 'off'); \ anyfail = octsympy_tests; \ sympref reset; \ exit (anyfail)" @echo doctest: @# Workaround for OctSymPy issue 273, we must pre-initialize the package @# Otherwise, it will make the doctests fail @echo "Testing documentation strings ..." @$(OCTAVE) --no-gui --silent --path "${CURDIR}/inst" \ --eval "pkg load doctest; \ sym ('x'); \ set (0, 'defaultfigurevisible', 'off'); \ success = doctest('inst/'); \ sympref reset; \ exit (!success)" @echo ## Install in Octave (locally) install: ${INSTALLED_PACKAGE} ${INSTALLED_PACKAGE}: ${OCTAVE_RELEASE_TARBALL} $(OCTAVE) --silent --eval "pkg install $<" ## Matlab packaging ## TODO: should be written to properly use artfacts matlab_pkg: $(MATLAB_PKG_ZIP) ${MATLAB_PKG}: $(BUILD_DIR) ${MATLAB_PKG}/private ml_extract_tests ## Matlab: extract unit tests from Octave files, place in separate files ml_extract_tests: ${MATLAB_PKG}/tests_matlab ml_copy cp -pR misc/octassert.m ${MATLAB_PKG}/tests_matlab/ cp -pR misc/extract_tests_for_matlab.m ${MATLAB_PKG}/ cp -pR misc/octsympy_tests_matlab.m ${MATLAB_PKG}/ cd ${MATLAB_PKG}/; ${OCTAVE} -q --eval "extract_tests_for_matlab" rm -f ${MATLAB_PKG}/extract_tests_for_matlab.m rm -f ${MATLAB_PKG}/tests_matlab/tests__sympref.m # temp ## Matlab: copy files ml_copy: ml_convert_comments cp -pR inst/private ${MATLAB_PKG}/ cp -pR inst/@sym/private ${MATLAB_PKG}/@sym/ cp -pR inst/@symfun/private ${MATLAB_PKG}/@symfun/ cp -pR misc/my_print_usage.m ${MATLAB_PKG}/private/print_usage.m cp -pR misc/my_print_usage.m ${MATLAB_PKG}/@sym/private/print_usage.m cp -pR misc/my_print_usage.m ${MATLAB_PKG}/@symfun/private/print_usage.m cp -fp CONTRIBUTORS ${MATLAB_PKG}/ cp -fp NEWS ${MATLAB_PKG}/ cp -fp COPYING ${MATLAB_PKG}/ cp -fp matlab_smt_differences.md ${MATLAB_PKG}/ cp -fp README.md ${MATLAB_PKG}/ cp -fp README.matlab.md ${MATLAB_PKG}/ rm -f ${MATLAB_PKG}/octsympy_tests.m ## Matlab: extract and convert comments to Matlab style ml_convert_comments: ${MATLAB_PKG}/@sym ${MATLAB_PKG}/@symfun ${MATLAB_PKG}/@double ${MATLAB_PKG}/@logical $(OCTAVE) --path ${CURDIR}/util --silent --eval "pwd, convert_comments('inst/', '', '../${MATLAB_PKG}/')" $(OCTAVE) --path ${CURDIR}/util --silent --eval "pwd, convert_comments('inst/', '@symfun', '../${MATLAB_PKG}/')" $(OCTAVE) --path ${CURDIR}/util --silent --eval "pwd, convert_comments('inst/', '@sym', '../${MATLAB_PKG}/')" $(OCTAVE) --path ${CURDIR}/util --silent --eval "pwd, convert_comments('inst/', '@double', '../${MATLAB_PKG}/')" $(OCTAVE) --path ${CURDIR}/util --silent --eval "pwd, convert_comments('inst/', '@logical', '../${MATLAB_PKG}/')" matlab_test: cd "${MATLAB_PKG}"; ${MATLAB} -nodesktop -nosplash -r "${MATLAB_STARTUP_CMD}; octsympy_tests_matlab" symbolic-3.1.1/NEWS0000644000000000000000000005270214405647405010741 0ustar octsympy 3.1.1 (2023-03-19) =========================== * New symbolic commands: cart2pol piecewise * `kron` works for three or more inputs (issue #1245). * Indexing bounds checking to support Octave 8. * Fix assumptions on SymPy 1.12. * Other misc fixes and changes for SymPy 1.12. octsympy 3.0.1 (2022-08-09) =========================== * New `@double` numerical functions; these are wrappers around SymPy, so they are slower than native floating-point implementations. adjoint * Misc bug fixes and improvements in error handling. * `.oct-config` files indicate source is UTF-8 encoded and should improve any locale or encoding problems on Octave 7 and above. * Fixes some errors when Python is running in Cygwin-like environment. But there could still be errors in other places (issue #1182). octsympy 3.0.0 (2022-07-05) =========================== * New symbolic commands: cumprod cumsum ztrans * `dsolve` output prefers expressions (right-hand sides) rather than equations. Also uses structs for systems. This brings it closer to `solve` and more compatible with other symbolic toolboxes. * `dsolve` supports arrays of initial conditions. * Fixes for SymPy 1.6 and later. * Fixes for Octave 6.x and Octave 7.1. * Drop Python 2 support. * The `symbolic-win-py-bundle-x.y.z.zip` is no longer provided as we have not been able to port it to Python 3. * Update minimum versions of SymPy to 1.4 and Octave to 5.1. * Remove deprecated `evalpy` and `python_cmd` utilities. octsympy 2.9.0 (2020-03-04) =========================== * Default python interpreter is now `python3`. * Fixes for SymPy 1.5. - `@sym/round` changed to round-to-even. - fix broken EmptySet `finiteset()`. * Documentation updates for upcoming Octave 6. * If the Pythonic package is loaded, automatically use it for Python communication (see `help sympref` for details). * Deprecation notice: `python_cmd` will be removed in a future release. octsympy 2.8.0 (2019-04-30) =========================== * New symbolic commands: eval ezmesh find sinc * Update minimum versions of SymPy to 1.2 and Octave to 4.2. * Fixes for SymPy 1.4. * Newer SymPy versions improve QR and LU on non-square matrices. * Support for expressions with min and max such as `min(x, y)`. * `subs(f)` now works: it finds values from the workspace. * `gammainc` now regularized correctly. * `lambertw` has more consistent printing. * Other bug fixes and documentation updates. octsympy 2.7.1 (2018-10-02) =========================== * Fixes for SymPy 1.3. * Various bug fixes and documentation updates. octsympy 2.7.0 (2018-07-12) =========================== * New symbolic commands: arg euler ezcontour * New `@double` numerical functions; these are wrappers around SymPy, so they are slower than native floating-point implementations. bernoulli euler chebyshevT pochhammer chebyshevU * The initial startup is much quieter! * `vpa` now warns of low-precision on non-numbers strings with decimals such as `vpa('cos(0.1)')`. See "help vpa" for details. * `subs` allows multiple scalar variables to be replaced with symbolic matrix expressions. * symfun can be evaluated at symbolic matrices: `f(sym([1 2; 3 4]))` now works where `f(x)` is a symfun. * Fixes for symfuns such as `syms N(t)` where the function name conflicts with a SymPy command. * Fixes for how assumptions interact with symfuns. * New command `sympref diagnose` to help debug Python/SymPy issues. * Improve `function_handle` support by supporting more functions. * Fixes for several bugs mentioning "immutable matrices". * `bernoulli` now works with array inputs. * Added a `private/defaultpython.m` to make it easier for distributors to control which python interpreter is used by default. * Fixes for GNU Octave 4.4. * Fixes for SymPy 1.2. * Various bug fixes and documentation updates. octsympy 2.6.0 (2017-07-27) =========================== * New symbolic commands: ellipke ellipticE harmonic ellipticCE ellipticF kroneckerDelta ellipticCK ellipticK pochhammer ellipticCPi ellipticPi * New `@double` numerical functions; these are wrappers around SymPy, so they are slower than native floating-point implementations. harmonic * Support for the new SymPy 1.1.1. * `solve` now supports vectors of equations and vectors of variables. * Better warning for `sym(0.1)`, updated docs about floating point. * Double values can now be converted to their exact rational value using `sym(0.1, 'f')`. Passing `'r'` gives the current heuristic behaviour. Neither raises a warning. * The default floating-point heuristics now check for square roots of integers, so `sym(sqrt(2))` should work. * `sym('i')` and `sym('I')` no longer create the imaginary unit: use `sym(i)` or `sym(1i)`. * `sym(e)` now gives the same as `exp(sym(1))`. However, `sym('e')` and `syms e` continue to create a variable named `e`. * `sym` now accepts function handles such as anonymous functions as inputs. * `subs` is not approriate for numerical evaluation; add an example in `help subs` which shows how to do this with `function_handle`. * Calling `sym(cell)` now creates a sym array instead of a cell array. Old behaviour of creating a cell array was deprecated in 2.5.0. * Bug fix: isequal(n) for symfun's correctly tests the argnames. octsympy 2.5.0 (2017-02-01) =========================== * New symbolic commands: acosd chol ones adjoint cosd prevprime angle dawson sind asind divisors sympy atand equationsToMatrix tand beta eye zeros cell2sym hilb charpoly invhilb * Add more `@double` numerical functions. For now these are simply wrappers around SymPy, so they are slower than native floating point implementations. coshint logint cosint polylog dilog sinhint fresnelc sinint fresnels zeta * The full set of assumptions implemented by Sympy can now be used. For example, `syms p prime` assumes `p` is prime. * `assume(x, 'clear')` can be used to clear assumptions on variables. Previously undocumented commands such as `sym(x, 'clear')` and `syms x clear` are now deprecated. * `assume` supports vector inputs. Also supported are alternative "command forms" such as `assume x y real` and `assume x y clear`. * `solve` now works with inequalities. * `sym('1.3')` now creates the rational number 13/10. * A new keyword option `coeffs(f, x, 'all')` returns both zero and non-zero coefficients. * Change (and document!) default matrix norm to the 2-norm (it was Frobenius). * `heaviside` accepts a second argument for its value at zero. * `isfinite` behaves correctly for variables (and is documented). * New experimental Python communication using the native Python/C interface, due to Abhinav Tripathi during Google Summer of Code 2016. * Bug fix: assign `[]` to row/column removes that that row/column. * `char(x)` now gives a more human-readable output, useful for example in labelling a figure. * ezplot supports implicit plotting of f(x, y) == 0. * Deprecation notice: `sym(cell)` will soon create a sym array (currently it creates a cell array of sym objects, and issues a warning). * Deprecation notice: `evalpy` will be removed in a future release. * Remove deprecated method for changing the Python executable using `sympref`: instead use the environment variable `PYTHON`. * Update minimum versions of SymPy to 1.0 and Octave to 4.0.0, so we can remove some crufty workarounds. octsympy 2.4.0 (2016-05-24) =========================== * New symbolic commands: acsc csch gammaln polylog asec dilog hypergeom psi asech ei hypot resize besseljn expint igamma sech besselyn ezsurf jordan signIm cat fresnelc laguerreL sinint cosint fresnels lgamma sinhint coshint gammainc logint ssinint * Move some functions from the "specfun" package. So now the Symbolic package includes some numerical (@double/@single) implementations: dirac heaviside laguerreL lambertw * Re-implement @double/laguerreL for numerical stability. * Add spherical Bessel functions: these are called `besseljn` and `besselyn` (for now, subject to change). Thanks to Utkarsh Gautam. * Fix: `@sym/dot` consistent with `@double/dot` thanks to Alex Vong. * The environment variable `PYTHON` controls which Python executable is used. The command `sympref python C:\bin\python` has been deprecated; instead please use: `setenv PYTHON C:\bin\python` * Improve support for Windows. Thanks to Abhinav Tripathi, Tatsuro Matsuoka, finalsnd, and Mike Miller. * Installation scripts merely warn if Python and SymPy aren't found. octsympy 2.3.0 (2016-04-08) =========================== * New commands: airy chebyshevU finiteset rewrite besselj chebyshevT has round bessely fix kron sort besseli frac linspace union besselk intersect logspace unique besselh interval max cbrt ismember min * Bug fix for working with certain unevaluated integrals. * Bug fixes for function_handle, fortran and ccode. * Bug fixes or improvements to repmat, reshape, python_cmd, factor, dot star, children. * Support for SymPy 1.0. * Errors raised in Python code are now caught and passed back to Octave in most cases. This simplifies implementation. - Note some error messages have changed slightly. - Windows users now see previously hidden error messages. Thanks to @latot. * Windows "bundle" package should work even if the system has another Python installed. Thanks to Abhinav Tripathi. * Installation bug fixes. Thanks to Abhinav Tripathi and Mike Miller. * New functions for converting sym to integers. Thanks to @latot. * Making a sym of a large integer like `sym(10^16)` gives a warning. Please use `sym(10)^16` or `sym('1000000000000123456789'). * New functions for dealing with sets and intervals and operations on them, thanks to @latot. * 2D Taylor expansions are implemented, thanks to Utkarsh Gautam. * Sort is implemented, thanks to Utkarsh Gautam. * Fourier and Laplace transforms (and their inverses) use a different implementation which improves handling of delta functions. Ideally, a later version will consolidate this with SymPy's original implementations. * Python `None` can be returned and manipulated. * Saving/Loading sym objects is now fully-supported (thanks to Abhinav Tripathi). * Documentation improvements. octsympy 2.2.4 (2015-12-14) =========================== * Fix display on Octave 3.8. * Support for SymPy 0.7.6.1. octsympy 2.2.3 (2015-11-25) =========================== * New commands: cross dot * sym('var') is more robust in case var happens to be a special value in SymPy. Now sym('E') is just a symbol rather than exp(sym(1)). Also sym('E1') and sym('Eq') no longer give errors. * Fix bug in assigning to column vectors, thanks to Grzegorz Dudziuk. * During install, test for PATH problems on Windows (issue #236). * Fix for Octave 4.1+ development versions, thanks to Mike Miller. octsympy 2.2.2 (2015-07-03) =========================== * Fix for configure script using Python 3 (thanks Vadim Gribanov). * Fourier transform fixes (thanks Alexander Misel, Andrés Prieto). They now follow the non-unitary angular frequency convention. * Support for SymPy 0.7.7.dev version. * Add some warnings to the documentation about unreliable results for "dsolve" on systems and from Fourier transforms. * Start using "print_usage" for invalid inputs as is common practice in Octave. * Bug fixes and update doctests. octsympy 2.2.1 (2015-04-22) =========================== * Fix an ascii pretty printing regression (issue #234). * Other minor fixes for doctests, sympref and symreplace. octsympy 2.2.0 (2015-04-20) =========================== * New commands: catalan eulergamma lambertw * Installing symbolic package now check for Python and minimum version of SymPy (thanks Carnë Draug for autoconf). * Installations from Octave-Forge ("pkg install -forge symbolic") should now work on Windows (thanks vassbu). You will need the Python and SymPy dependencies. Or you can use the [bundled package](https://github.com/cbm755/octsympy/releases) * Added support for Python 3 (still works with Python 2 as well). * Documentation improvements especially to assumptions. Examples within documentation can now be tested with doctests, see the `octsympy_doctests.m` function. * Fix a warning on Octave 4.0.0-rc1 and make tests work properly. * Other bug fixes: assumptions; symvar and symbolic matrix powers; various display issues. octsympy 2.1.0 (2015-03-06) =========================== * New commands: columns degree formula ismatrix numden rows * Additional ways of calling symsum, symprod, and subs for better compatibility with other symbolic toolboxes. * Bug fixes in poly2sym, sym2poly, symfun (thanks @rocketsound), prod, horner, coeffs. * Documentation improvements. * Improvements to "argnames" and "formula" for the dependent variables and dependent expression of a symfun. These are now implemented for basic sym objects as well. * Improvements to assumptions. E.g., `x = assume(x, 'positive')` no longer mucks around in the workspace for other instances of x (it still does this with no output argument, for compatibility with other symbolic toolboxes). You can use multiple assumptions with sym and syms, e.g., `syms n m positive even`. * Improve symbolic sized matrices such as `A = sym('a', [n m])`. These are still experimental; they correspond to MatixSymbols in SymPy and may need a recent SymPy development version. For now, the `size(A)` returns "1x1" although internally `NaN` is used for symbolic-sized dimensions. Enabling `size(A)` to return "NaNx3" may occur later. * Drop python_cmd_string, which has been deprecated since v0.1.1. octsympy 2.0.0 (2015-02-04) =========================== * Octsympy is now the "symbolic" package for Octave Forge. There was a previous "symbolic" package (based on GiNaC) which reached version 1.1.0. To prevent confusion, we are now at version 2.0.0. Additionally, the history of the two projects has been merged (thanks Carnë Draug). * New commands: coeffs ipermute isallconstant isconstant nchoosek permute * Fixes for development version of SymPy. * Fixes for vpa and vpasolve: high precision should be more reliable. * Improve handling `sym(pi/3)` and other small fractions of pi. It works but you'll still get a warning and 2*sym(pi)/3 is really the preferred approach! `sym(-pi)` now works. * On Windows, default to ascii rendering for now (until unicode is fixed in Octave on that platform). * No longer needs to autogenerate a bunch of functions at install time: hopefully making it easier than ever to get involved! octsympy 0.1.3 (2015-01-06) =========================== * New commands: argnames partfrac digits orth ilaplace rank laplace rref ldivide sum mldivide vpa null vpasolve * Symbolic backslash support. * variable-precision arithmetic support: see vpa, digits, vpasolve. * Much-improved dsolve thanks to Andrés Prieto. * Laplace and inverse Laplace transforms (Andrés Prieto). * Partial fractions (Andrés Prieto). * Improvements to solve (Andrés Prieto). * Preliminary support for matrix expressions, e.g., matrix to a symbolic power. * Should work properly with Stand-alone Python (thanks to David Manthey). octsympy 0.1.2 (2014-12-01) =========================== * New commands: children rhs expm setdiff lhs setxor pinv trace potential * Support new SymPy 0.7.6. This adds Octave code generation which means that OctSymPy's `matlabFunction` is supported. * For now, SymPy 0.7.5 should still work, but upgrading to SymPy 0.7.6 is recommended. octsympy 0.1.1 (2014-10-20) Rose Garden ======================================== Major Changes ------------- * Fix sym(double) approx by rationals (issue #121, thanks HuiZhong LU). * Improvements to sym() command: you can now pass the underlying "srepr" SymPy presentation to create an object. * Bug fixes: improvements to indexing, findsymbols and assumptions, isscalar/isvector failures on recent Octave, output formatting fixes, * New commands: and isscalar char isvector diag nnz eig or iscolumn uplus isrow xor Minor Changes ------------- * Improvements to logical and isAlways commands. * IPC system() should work on windows. * Better test system, easier to see "real" failures rather than expected (known) failures. * Improved handling of symfuns. * Improvements to internal string handling/escaping especially newlines. - Enter a multiline command using a cell array of lines e.g., `python_cmd({'a = 10' 'return (a, 2*a)'}) or `python_cmd({'a = 10'; 'return (a, 2*a)'}) - The same applies to `evalpy`. If you need the old deprecated behaviour, it is still available as `python_cmd_string`. octsympy 0.1.0 (2014-08-27) Pacific Coffee =========================================== Major Changes ------------- * `sympref` replaces `octsympy_config`. You can change the Python interpreter with `sympref python /path/to/python`. * Unicode pretty-printed output by default. - If you see `?` or other broken characters, try `sympref display ascii`. Then help me get this working on your system! - Or `sympref display flat` to disable pretty-printing. (You can still use the `pretty` command selectively). * Experimental Windows package with Python and SymPy included (look Ma, no deps!) Uses [David Manthey's single file py.exe Python] [1]. [1]: http://www.orbitals.com/programs/pyexe.html * Lots of new commands: atan2 fliplr isfinite norm ccode flipud isna not cond fortran jacobian qr conj ge laplacian real curl gradient le repmat det gt lt svd divergence hessian lu toeplitz ezplot3 imag matlabFunction tril ezplot inv ne triu * Preliminary code generation (`ccode`, `fortran` and `matlabFunction` functions). However, `matlabFunction` mostly depends on patches not yet in upstream SymPy. * Inequality support. * Assumptions now behave more like the Matlab Symbolic Math Toolbox. Minor or internal changes ------------------------- * Arithmetic operations on symfuns return symfuns instead of syms. * More robust XML-like IPC transport. * Move to proper Octave-style `%!` tests. * Debugging IPC modes: `systmpfile` (same as `system` but outputs a temp file for inspection) and `sysoneline` (work-in-progress). octsympy 0.0.4 (2014-05-26) Lovever Coffee =========================================== * Basic assumptions support. * Matlab packages, only slow system() ipc for now. * Improvements on passing variables between Octave and Python. octsympy 0.0.3 (2014-04-29) Wu Ke Song ======================================= * Many new commands. * `system()` communication no longer makes temporary files. To change the communication mechanism, use "octsympy_config ipc system". See also "help octsympy_config". * Added new tool "evalpy", this is fun and good for debugging... * Bugs fixed, docs updated * Start documenting differences with the Matlab Symbolic Math Toolbox. octsympy 0.0.2 (2014-04-20) =========================== * A preview release, test it out report issues. Documentation is a mess, various things are work-in-progress. But it works and I think has potential. symbolic-3.1.1/README.md0000644000000000000000000000704214405647405011516 0ustar Symbolic Package for GNU Octave =============================== An implementation of a symbolic toolbox using SymPy. [https://octave.sourceforge.io/symbolic] Note: Development for most Octave packages tends to take place in sourceforge. However, unlike most other Octave packages, the main development repository for this package is on **github** (https://github.com/cbm755/octsympy), and only _mirrored_ on sourceforge (https://sourceforge.net/p/octave/symbolic/). If you are thinking of contributing and you're looking at this README file from the sourceforge website, please consider visiting our github page and contributing there instead, as we do not tend to monitor sourceforge for activity. Goals ----- Feature parity with the other symbolic toolboxes. ![Screenshot 1](/screenshot.png) ![Screenshot 2](/screenshot-install.png) How to Install -------------- 1. The dependencies are Octave, Python, and SymPy. Consult the SymPy website for details on how to install SymPy. 2. Start Octave. 3. At Octave prompt type `pkg install -forge symbolic`. 4. At Octave prompt, type `pkg load symbolic`. 5. At Octave prompt, type `syms x`, then `f = (sin(x/2))^3`, `diff(f, x)`, etc. How to install on Ubuntu ------------------------- 1. Install the dependencies with `sudo apt-get install octave liboctave-dev python-sympy`. 2. Follow steps 2--5 above. How to Install on Windows ------------------------- 1. Get [Octave](http://www.octave.org) for Windows. 2. At the Octave prompt, type `pkg install -forge symbolic`. 3. At the Octave prompt, type `pkg load symbolic`. 4. At the Octave prompt, type `syms x`, then `f = (sin(x/2))^3`, `diff(f, x)`, etc. If you encounter any difficulties (even minor ones) please read and if possible help us improve the [wiki page on Windows Installation](https://github.com/cbm755/octsympy/wiki/Notes-on-Windows-installation). How to Install on Matlab ------------------------ Although this package is designed for GNU Octave, it will work with Matlab. Currently only the slower system()-based communication is available. 1. Download the latest release, e.g., `octsympy-matlab-2.7.0.tar.gz`. 2. Unzip it somewhere and add it to your Matlab Path. The .m files for Matlab have been reformatted for Matlab comment conventions, but are otherwise the same as the Octave source. How to Help ----------- We have a list of things to work on tagged [help wanted](https://github.com/cbm755/octsympy/issues?q=is:open+is:issue+label:"help+wanted"). Some of these should be quite easy to fix and would be a great way to get involved. Come join us! How to hack on the code: 1. Clone the repo with git (preferred, but you can use the "Download ZIP" instead if you want). 2. Run Octave in the `octsympy/inst/` directory. It should be safe to do this even if you have the released version of the package installed (but not loaded). Implementation -------------- Python code is generated to do the actual work. Each sym object keeps a text field for display purposes and a string (a SymPy `srepr`). The objects are communicated between Python and Octave by passing the srepr string back-and-forth. Currently pure m-file (and Python) implementation, no code to be compiled. Related Projects ---------------- * There was a previous "symbolic" package in Octave Forge based on GiNaC. Its history has now been merged into this project. * ["SymPy CAS" by Jonathan Lister](http://www.mathworks.com/matlabcentral/fileexchange/42787-sympy-cas-in-matlab). Calls SymPy commands using system(). symbolic-3.1.1/inst/0000755000000000000000000000000014405647405011211 5ustar symbolic-3.1.1/inst/.oct-config0000644000000000000000000000001714405647405013240 0ustar encoding=utf-8 symbolic-3.1.1/inst/@double/0000755000000000000000000000000014405647405012563 5ustar symbolic-3.1.1/inst/@double/adjoint.m0000644000000000000000000000414614405647405014376 0ustar %% Copyright (C) 2022 Alex Vong %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defun adjoint (@var{M}) %% Numerical Classical Adjoint / Adjugate of a square matrix. %% %% @strong{Note on Terminology}: This function computes the %% ``Classical Adjoint'' / Adjugate of @var{M}. For the Conjugate Transpose / %% Hermitian adjoint (which is commonly referred to as the ``Adjoint'' in %% modern usage), @pxref{@@double/ctranspose}. %% %% Example: %% @example %% @group %% M = [-3 2 -5; -1 0 -2; 3 -4 1]; %% A = adjoint (M) %% @result{} A = %% -8 18 -4 %% -5 12 -1 %% 4 -6 2 %% @end group %% @end example %% %% And note the following equalities involving the Classical Adjoint @code{A}: %% @example %% @group %% M * A %% @result{} ans = %% -6 0 0 %% 0 -6 0 %% 0 0 -6 %% @end group %% %% @group %% A * M %% @result{} ans = %% -6 0 0 %% 0 -6 0 %% 0 0 -6 %% @end group %% %% @group %% det (M) * eye (3) %% @result{} ans = %% Diagonal Matrix %% %% -6 0 0 %% 0 -6 0 %% 0 0 -6 %% @end group %% @end example %% @seealso{@@sym/adjoint} %% @end defun %% Reference: https://en.wikipedia.org/wiki/Adjugate_matrix function A = adjoint (M) A = double (adjoint (vpa (M, 16))); end %!test %! M = [1 2; 3 4]; %! A = [4 -2; -3 1]; %! assert (isequal (adjoint (M), A)); %!test %! assert (isequal (adjoint (42), 1)); symbolic-3.1.1/inst/@double/bernoulli.m0000644000000000000000000001025114405647405014733 0ustar %% Copyright (C) 2018-2019, 2022-2023 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypefun bernoulli (@var{n}) %% @deftypefunx bernoulli (@var{n}, @var{x}) %% Numerically evaluate Bernoulli numbers and polynomials. %% %% Examples: %% @example %% @group %% bernoulli (6) %% @result{} 0.023810 %% bernoulli (7) %% @result{} 0 %% @end group %% @end example %% %% Note there are two conventions in the literature about the sign of B_1, %% but for certain the absolute value is one half: %% @example %% @group %% @c Would render with an extra zero on earlier Octave %% @c doctest: +SKIP_IF(compare_versions (OCTAVE_VERSION(), '6.0.0', '<')) %% abs (bernoulli (1)) %% @result{} 0.5000 %% @end group %% @end example %% As of 2023, this numerical evaluation function is in a state of flux %% about which one it takes, @pxref{@@sym/bernoulli}. %% %% Polynomial example: %% @example %% @group %% bernoulli (2, pi) %% @result{} 6.8947 %% @end group %% @end example %% %% @strong{Note} this function may be slow for large numbers of inputs. %% This is because it is not a native double-precision implementation. %% %% @seealso{@@sym/bernoulli} %% @end deftypefun function y = bernoulli (m, x) if (nargin ~= 1 && nargin ~= 2) print_usage (); end if (nargin == 1) x = 0; end if (isequal (size (m), size (x)) || isscalar (m)) y = zeros (size (x)); elseif (isscalar (x)) y = zeros (size (m)); else error ('bernoulli: inputs N and X must have compatible sizes') end cmd = { 'Lm = _ins[0]' 'Lx = _ins[1]' 'if len(Lm) == 1 and len(Lx) != 1:' ' Lm = Lm*len(Lx)' 'if len(Lm) != 1 and len(Lx) == 1:' ' Lx = Lx*len(Lm)' 'c = [complex(mpmath.bernpoly(int(m), x)) for m,x in zip(Lm, Lx)]' 'return c,' }; c = pycall_sympy__ (cmd, num2cell (m(:)), num2cell (x(:))); for i = 1:numel (c) y(i) = c{i}; end end %!error bernoulli (1, 2, 3) %!error bernoulli ([1 2], [1 2 3]) %!error bernoulli ([1 2], [1; 2]) %!assert (bernoulli (0), 1) %!assert (bernoulli (3), 0) %!test %! % two different definitions in literature %! assert (abs (bernoulli (1)), 0.5, -eps) %!xtest %! % we want to use B_1 = 1/2, possible with a version-specific filter %! assert (bernoulli (1), 0.5, -eps) %!test %! n = sym(88); %! m = 88; %! A = bernoulli (m); %! B = double (bernoulli (n)); %! assert (A, B, -eps); %!test %! m = [0 2; 3 4]; %! n = sym(m); %! A = bernoulli (m); %! B = double (bernoulli (n)); %! assert (isequal (A, B)); %!test %! y = sym(19)/10; %! n = sym(2); %! x = 1.9; %! m = 2; %! A = bernoulli (m, x); %! B = double (bernoulli (n, y)); %! assert (A, B, -eps); %!test %! assert (isequal (bernoulli (4, inf), inf)) %! assert (isequal (bernoulli (4, -inf), inf)) %!xtest %! % still broken? %! assert (isequal (bernoulli (3, inf), inf)) %! assert (isequal (bernoulli (3, -inf), -inf)) %!test %! assert (isnan (bernoulli(3, nan))) %! assert (isnumeric (bernoulli(3, nan))) %!test %! % maple, complex input %! A = 34.21957245745810513 - 130.0046256649829101i; %! B = bernoulli(7, 2.123 + 1.234i); %! assert (A, B, -5*eps); %!test %! % x matrix, m scalar %! y = [1 2 sym(pi); exp(sym(1)) 5 6]; %! n = sym(2); %! x = double (y); %! m = 2; %! A = bernoulli (m, x); %! B = double (bernoulli (n, y)); %! assert (A, B, -eps); %!test %! % m matrix, x scalar %! m = [1 2 3; 4 5 6]; %! n = sym(m); %! y = sym(21)/10; %! x = 2.1; %! A = bernoulli (m, x); %! B = double (bernoulli (n, y)); %! assert (A, B, -3*eps); symbolic-3.1.1/inst/@double/chebyshevT.m0000644000000000000000000000752414405647405015055 0ustar %% Copyright (C) 2018-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defun chebyshevT (@var{n}, @var{x}) %% Numerically evaluate Chebyshev polynomials of the first kind. %% %% Evaluates the Chebyshev polynomial of the first kind of degree %% @var{n} at the point @var{x}, in double precision. Both inputs %% can be arrays but their sizes must be either the same or scalar. %% %% Example: %% @example %% @group %% @c doctest: +SKIP_IF(compare_versions (OCTAVE_VERSION(), '6.0.0', '<')) %% chebyshevT (18, 0.9) %% @result{} ans = -0.2614 %% @end group %% @end example %% %% Using this function may be preferable to evaluating the Chebyshev %% polynomial in monomial form because the latter can give poor %% accuracy due to numerical instability. %% See the example in @pxref{@@double/chebyshevU}. %% %% This function may be slow for large numbers of inputs. %% This is because it is not a native double-precision implementation %% but rather the numerical evaluation of the Python @code{mpmath} function %% @code{chebyshevt}. %% %% @seealso{@@sym/chebychevT, @@double/chebyshevU} %% @end defun function y = chebyshevT (n, x) if (nargin ~= 2) print_usage (); end if (isequal (size (n), size (x)) || isscalar(n)) y = zeros (size (x)); elseif (isscalar (x)) y = zeros (size (n)); else error ('chebyshevT: inputs N and X must have compatible sizes') end cmd = { 'Ln = _ins[0]' 'Lx = _ins[1]' 'if len(Ln) == 1 and len(Lx) != 1:' ' Ln = Ln*len(Lx)' 'if len(Ln) != 1 and len(Lx) == 1:' ' Lx = Lx*len(Ln)' 'c = [complex(mpmath.chebyt(n, x)) for n,x in zip(Ln, Lx)]' 'return c,' }; c = pycall_sympy__ (cmd, num2cell (n(:)), num2cell (x(:))); for i = 1:numel (c) y(i) = c{i}; end end %!error chebyshevT (1) %!error chebyshevT (1, 2, 3) %!error chebyshevT ([1 2], [1 2 3]) %!error chebyshevT ([1 2], [1; 2]) %!test %! y = sym(11)/10; %! t = sym(2); %! x = 1.1; %! s = 2; %! A = chebyshevT (s, x); %! B = double (chebyshevT (t, y)); %! assert (A, B, -2*eps); %!test %! % maple %! A = -0.304681164165948269030369; %! B = chebyshevT (18.1, 0.9); %! assert (A, B, -10*eps) %!test %! % maple, complex inputs %! % ChebyshevT(12.1+3.1*I, 0.5+0.2*I); %! A = 0.637229289490379273451 - 0.475324703778957991318*1i; %! B = chebyshevT (12.1+3.1*i, 0.5+0.2i); %! assert (A, B, -5*eps); %!test %! % maple, matrix inputs %! A = [0.59523064198266880000 0.57727442996887552000]; %! B = chebyshevT ([16 17], [0.9 0.7]); %! assert (A, B, -10*eps); %!test %! % x matrix, s scalar %! y = [1 2 sym(pi); exp(sym(1)) 5 6]; %! t = sym(2); %! x = double (y); %! s = 2; %! A = chebyshevT (s, x); %! B = double (chebyshevT (t, y)); %! assert (A, B, -eps); %!test %! % s matrix, x scalar %! t = [1 2 sym(pi); exp(sym(1)) 5 6]; %! y = sym(2); %! s = double (t); %! x = 2; %! A = chebyshevT (s, x); %! B = double (chebyshevT (t, y)); %! assert (A, B, -eps); %!xtest %! % https://github.com/fredrik-johansson/mpmath/issues/469 %! assert (chebyshevT (4, inf), inf) %! assert (chebyshevT (4, -inf), inf) %! assert (chebyshevT (3, inf), inf) %! assert (chebyshevT (3, -inf), -inf) symbolic-3.1.1/inst/@double/chebyshevU.m0000644000000000000000000001142114405647405015045 0ustar %% Copyright (C) 2018-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defun chebyshevU (@var{n}, @var{x}) %% Numerically evaluate Chebyshev polynomials of the second kind. %% %% Evaluates the Chebyshev polynomial of the second kind of degree %% @var{n} at the point @var{x}, in double precision. Both inputs %% can be arrays but their sizes must be either the same or scalar. %% %% Example: %% @example %% @group %% chebyshevU (18, 0.9) %% @result{} ans = 1.7315 %% @end group %% @end example %% %% Using this function may be preferable to evaluating the polynomial %% in monomial form because the latter can give poor accuracy due to %% numerical instability. For example, consider evaluating the %% Chebyshev polynomial of degree 10 at a point by evaluating %% in the monomial basis: %% @example %% @group %% syms n x %% C = chebyshevU (10, x) %% @result{} C = (sym) %% 10 8 6 4 2 %% 1024⋅x - 2304⋅x + 1792⋅x - 560⋅x + 60⋅x - 1 %% @c doctest: +XFAIL_IF(compare_versions (OCTAVE_VERSION(), '6.0.0', '<')) %% value1 = polyval (sym2poly (C), 0.96105) %% @result{} value1 = 0.2219 %% @end group %% @end example %% Instead, we could use the present function: %% @example %% @group %% @c doctest: +XFAIL_IF(compare_versions (OCTAVE_VERSION(), '6.0.0', '<')) %% value2 = chebyshevU (10, 0.96105) %% @result{} value2 = 0.2219 %% @end group %% @end example %% Both results look similar but @code{value2} is more accurate---they %% differ by significantly more than machine precision: %% @example %% @group %% value1 - value2 %% @result{} 1.0586e-13 %% @end group %% @end example %% %% @strong{Note} this function may be slow for large numbers of inputs. %% This is because it is not a native double-precision implementation %% but rather the numerical evaluation of the Python @code{mpmath} function %% @code{chebyshevu}. %% %% Developer note: would likely be faster if implemented directly %% using the three-term recurrence. %% %% @seealso{@@double/chebyshevT, @@sym/chebychevU} %% @end defun function y = chebyshevU (n, x) if (nargin ~= 2) print_usage (); end if (isequal (size (n), size (x)) || isscalar(n)) y = zeros (size (x)); elseif (isscalar (x)) y = zeros (size (n)); else error ('chebyshevU: inputs N and X must have compatible sizes') end cmd = { 'Ln = _ins[0]' 'Lx = _ins[1]' 'if len(Ln) == 1 and len(Lx) != 1:' ' Ln = Ln*len(Lx)' 'if len(Ln) != 1 and len(Lx) == 1:' ' Lx = Lx*len(Ln)' 'c = [complex(mpmath.chebyu(n, x)) for n,x in zip(Ln, Lx)]' 'return c,' }; c = pycall_sympy__ (cmd, num2cell (n(:)), num2cell (x(:))); for i = 1:numel (c) y(i) = c{i}; end end %!error chebyshevU (1) %!error chebyshevU (1, 2, 3) %!error chebyshevU ([1 2], [1 2 3]) %!error chebyshevU ([1 2], [1; 2]) %!test %! y = sym(11)/10; %! t = sym(2); %! x = 1.1; %! s = 2; %! A = chebyshevU (s, x); %! B = double (chebyshevU (t, y)); %! assert (A, B, -2*eps); %!test %! % maple %! A = 1.661891066691338157; %! B = chebyshevU (18.1, 0.9); %! assert (A, B, -3*eps) %!test %! % maple, complex inputs> %! % ChebyshevU(12.1+3.1*I, 0.5+0.2*I); %! A = 1.046959313670290818 - 0.03386773634958834846*1i; %! B = chebyshevU (12.1+3.1*i, 0.5+0.2i); %! assert (A, B, -3*eps); %!test %! % maple, matrix inputs %! A = [2.2543638828875776000 -1.3872651600553574400]; %! B = chebyshevU ([16 17], [0.9 0.8]); %! assert (A, B, -10*eps); %!test %! % x matrix, s scalar %! y = [1 2 sym(pi); exp(sym(1)) 5 6]; %! t = sym(2); %! x = double (y); %! s = 2; %! A = chebyshevU (s, x); %! B = double (chebyshevU (t, y)); %! assert (A, B, -eps); %!test %! % s matrix, x scalar %! t = [1 2 sym(pi); exp(sym(1)) 5 6]; %! y = sym(2); %! s = double (t); %! x = 2; %! A = chebyshevU (s, x); %! B = double (chebyshevU (t, y)); %! assert (A, B, -2*eps); %!xtest %! % https://github.com/fredrik-johansson/mpmath/issues/469 %! assert (chebyshevU (4, inf), inf) %! assert (chebyshevU (4, -inf), inf) %! assert (chebyshevU (3, inf), inf) %! assert (chebyshevU (3, -inf), -inf) symbolic-3.1.1/inst/@double/coshint.m0000644000000000000000000000516714405647405014421 0ustar %% Copyright (C) 2016-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defun coshint (@var{x}) %% Numerical coshint function. %% %% Example: %% @example %% @group %% @c doctest: +SKIP_IF(compare_versions (OCTAVE_VERSION(), '6.0.0', '<')) %% coshint (1.1) %% @result{} ans = 0.9907 %% @end group %% @end example %% %% @strong{Note} this function may be slow for large numbers of inputs. %% This is because it is not a native double-precision implementation %% but rather the numerical evaluation of the Python @code{mpmath} function %% @code{chi}. %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @seealso{@@sym/coshint} %% @end defun function y = coshint (x) if (nargin ~= 1) print_usage (); end cmd = { 'L = _ins[0]' 'A = [complex(mpmath.chi(x)) for x in L]' 'return A,' }; c = pycall_sympy__ (cmd, num2cell (x(:))); y = reshape (cell2mat (c), size (x)); end %!error coshint (1, 2) %!test %! x = 1.1; %! y = sym(11)/10; %! A = coshint (x); %! B = double (coshint (y)); %! assert (A, B, -4*eps); %!test %! y = [2 3 sym(pi); exp(sym(1)) 5 6]; %! x = double (y); %! A = coshint (x); %! B = double (coshint (y)); %! assert (A, B, -4*eps); %!test %! % maple: %! % > A := [1+2*I, -2 + 5*I, 100, 10*I, -1e-4 + 1e-6*I, -20 + I]; %! % > for a in A do evalf(Chi(a)) end do; %! x = [1+2i; -2+5i; 100; 10i; -1e-4 + 1e-6*1i; -20-1i]; %! A = [ 0.58447599687824767874 + 1.8682915044330306402*1i %! -0.63131069034703116988 + 1.8986171211850702957*1i %! 0.13577763724269399110e42 %! -0.045456433004455372635 + 1.5707963267948966192*1i %! -8.6330747070747332203 + 3.1315929868531280002*1i %! 0.74701205140887966531e7 + 0.10381444259644068585e8*1i ]; %! B = coshint (x); %! assert (A, B, -eps) %!assert (coshint (inf), inf) %!assert (isinf (coshint (-inf))) %!assert (imag (coshint (-inf)), pi) symbolic-3.1.1/inst/@double/cosint.m0000644000000000000000000000661214405647405014245 0ustar %% Copyright (C) 2016-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defun cosint (@var{x}) %% Numerical cosint function. %% %% Example: %% @example %% @group %% @c doctest: +SKIP_IF(compare_versions (OCTAVE_VERSION(), '6.0.0', '<')) %% cosint (1.1) %% @result{} ans = 0.3849 %% @end group %% @end example %% %% @strong{Note} this function may be slow for large numbers of inputs. %% This is because it is not a native double-precision implementation %% but rather the numerical evaluation of the Python @code{mpmath} function %% @code{ci}. %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @seealso{@@sym/cosint} %% @end defun function y = cosint (x) if (nargin ~= 1) print_usage (); end cmd = { 'L = _ins[0]' 'A = [complex(mpmath.ci(x)) for x in L]' 'return A,' }; c = pycall_sympy__ (cmd, num2cell (x(:))); y = reshape (cell2mat (c), size (x)); end %!error cosint (1, 2) %!test %! x = 1.1; %! y = sym(11)/10; %! A = cosint (x); %! B = double (cosint (y)); %! assert (A, B, -4*eps); %!test %! y = [2 3 sym(pi); exp(sym(1)) 5 6]; %! x = double (y); %! A = cosint (x); %! B = double (cosint (y)); %! assert (A, B, -4*eps); %!test %! % maple: %! % > A := [1+2*I, -2 + 5*I, 100, 10*I, -1e-4 + 1e-6*I, -20 + I]; %! % > for a in A do evalf(Ci(a)) end do; %! x = [1+2i; -2+5i; 100; 10i; -1e-4 + 1e-6*1i; -20-1i]; %! A = [ 2.0302963932917216378 - 0.15190715517585688438*1i %! 1.6153896382910774851 + 19.725754055338264980*1i %! -0.0051488251426104921444 %! 1246.1144860424544147 + 1.5707963267948966192*1i %! -8.6330747120742332203 + 3.1315929869531280002*1i %! 0.069822228467306149311 - 3.1184744625477294643*1i ]; %! B = cosint (x); %! assert (A, B, -eps) %!xtest %! % is it nan or -inf? SymPy says zoo. %! assert (isnan (cosint (0))) % could relax to within eps %!assert (cosint (inf), 0) %!assert (cosint (-inf), pi*1i, -eps) %!assert (cosint (1), 0.33740392290096813466, -eps) %!assert (cosint (-1), 0.33740392290096813466 + pi*1i, -eps) %!assert (cosint (pi), 0.073667912046425485978, -5*eps) %!assert (cosint (-pi), 0.07366791204642548597821 + pi*1i, -5*eps) %!assert (cosint (300), -3.3321999185921117800e-3, -2*eps) %!assert (cosint (1e4), -3.0551916724485212665e-5, -2*eps) %!assert (cosint (1 + 1i), 0.8821721805559363250506+0.2872491335199559395273*1i, eps) %!assert (cosint (1i), 0.8378669409802082408947 + pi/2*1i, -2*eps) %!test %! % compare both sinint and cosint to expint %! x = pi; %! C1 = cosint (x); %! S1 = sinint (x); %! R = expint (1i*x); %! C2 = -real (R); %! S2 = imag (R) + pi/2; %! assert (C1, C2, -100*eps); %! assert (S1, S2, -100*eps); symbolic-3.1.1/inst/@double/dilog.m0000644000000000000000000000472614405647405014050 0ustar %% Copyright (C) 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defun dilog (@var{x}) %% Numerical dilogarithm function %% %% Example: %% @example %% @group %% dilog (1.1) %% @result{} ans = -0.097605 %% @end group %% @end example %% %% @strong{Note} this function may be slow for large numbers of inputs. %% This is because it is not a native double-precision implementation %% but rather the numerical evaluation of the Python @code{mpmath} function %% @code{polylog}. %% %% @seealso{@@sym/dilog} %% @end defun function y = dilog (x) if (nargin ~= 1) print_usage (); end cmd = { 'L = _ins[0]' 'A = [complex(mpmath.polylog(2, 1-x)) for x in L]' 'return A,' }; c = pycall_sympy__ (cmd, num2cell(x(:))); assert (numel (c) == numel (x)) y = x; for i = 1:numel (c) y(i) = c{i}; end end %!test %! x = 1.1; %! y = sym(11)/10; %! A = dilog (x); %! B = double (dilog (y)); %! assert (A, B, -4*eps); %!test %! y = [2 2 sym(pi); exp(sym(1)) 5 6]; %! x = double (y); %! A = dilog (x); %! B = double (dilog (y)); %! assert (A, B, -eps); %!test %! % maple: %! % > A := [1+2*I, -2 + 5*I, 100, 10*I, -1e-4 + 1e-6*I, -20 + I]; %! % > for a in A do evalf(dilog(a)) end do; %! x = [1+2i; -2+5i; 100; 10i; -1e-4 + 1e-6*1i; -20-1i]; %! A = [ -0.59248494924959145800 - 1.5760154034463234224*1i %! -1.0549087538833908441 - 3.8759788000863368495*1i %! -12.192421669033171348 %! -2.9195729380904939394 - 3.9540920181102973073*1i %! 1.6459519160623984119 - 0.00032335296277550987686*1i %! -1.5445800511775466879 + 9.4256034277816069684*1i ]; %! B = dilog (x); %! assert (A, B, -eps) %!xtest %! % https://github.com/fredrik-johansson/mpmath/issues/473 %! assert (isinf (dilog (inf))) %!assert (isnan (dilog (-inf))) symbolic-3.1.1/inst/@double/euler.m0000644000000000000000000000746614405647405014072 0ustar %% Copyright (C) 2017-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypefun euler (@var{m}) %% @deftypefunx euler (@var{m}, @var{x}) %% Numerical Euler numbers or Euler polynomials. %% %% Examples: %% @example %% @group %% euler (0) %% @result{} 1 %% euler (32) %% @result{} 1.7752e+29 %% @end group %% @end example %% %% Polynomial example: %% @example %% @group %% euler (2, pi) %% @result{} 6.7280 %% @end group %% @end example %% %% @strong{Note} this function may be slow for large numbers of inputs. %% This is because it is not a native double-precision implementation. %% %% @seealso{@@sym/euler} %% @end deftypefun function y = euler (m, x) if (nargin ~= 1 && nargin ~= 2) print_usage (); end if (nargin == 1) y = zeros (size (m)); cmd = { 'return [float(euler(sp.Integer(m))) for m in _ins[0]],' }; c = pycall_sympy__ (cmd, num2cell (m(:))); for i = 1:numel (c) y(i) = c{i}; end return end if (isequal (size (m), size (x)) || isscalar (m)) y = zeros (size (x)); elseif (isscalar (x)) y = zeros (size (m)); else error ('euler: inputs M and X must have compatible sizes') end cmd = { 'Lm = _ins[0]' 'Lx = _ins[1]' 'if len(Lm) == 1 and len(Lx) != 1:' ' Lm = Lm*len(Lx)' 'if len(Lm) != 1 and len(Lx) == 1:' ' Lx = Lx*len(Lm)' 'c = [complex(mpmath.eulerpoly(int(m), x)) for m,x in zip(Lm, Lx)]' 'return c,' }; c = pycall_sympy__ (cmd, num2cell (m(:)), num2cell (x(:))); for i = 1:numel (c) y(i) = c{i}; end end %!error euler (1, 2, 3) %!error euler ([1 2], [1 2 3]) %!error euler ([1 2], [1; 2]) %!assert (isequal (euler (0), 1)) %!assert (isequal (euler (1), 0)) %!assert (isequal (euler (10), -50521)) %!test %! n = sym(88); %! m = 88; %! A = euler (m); %! B = double (euler (n)); %! assert (A, B, -eps); %!test %! m = [0 1; 2 4]; %! n = sym(m); %! A = euler (m); %! B = double (euler (n)); %! assert (isequal (A, B)); %!test %! y = sym(19)/10; %! n = sym(2); %! x = 1.9; %! m = 2; %! A = euler (m, x); %! B = double (euler (n, y)); %! assert (A, B, -eps); %!test %! % correct behaviour at floating point infinity %! assert (isequal (euler (4, inf), inf)) %! assert (isequal (euler (4, -inf), inf)) %! assert (isequal (euler (3, inf), inf)) %! assert (isequal (euler (3, -inf), -inf)) %!test %! assert (isnan (euler(3, nan))) %! assert (isnumeric (euler(3, nan))) %!test %! % maple, complex input %! A = 113.33970046079423204 - 46.991080726974811540i; %! B = euler(7, 2.12345 + 1.23i); %! assert (A, B, -eps); %!test %! % maple, complex input, large m, small x %! A = 0.18034673393294025238e276 + 0.27756266681280689172e276*i; %! B = euler (200, 0.123+0.234i); %! assert (A, B, -eps); %!test %! % x matrix, m scalar %! y = [1 2 sym(pi); exp(sym(1)) 5 6]; %! n = sym(2); %! x = double (y); %! m = 2; %! A = euler (m, x); %! B = double (euler (n, y)); %! assert (A, B, -eps); %!test %! % m matrix, x scalar %! m = [1 2 3; 4 5 6]; %! n = sym(m); %! y = sym(21)/10; %! x = 2.1; %! A = euler (m, x); %! B = double (euler (n, y)); %! assert (A, B, -3*eps); symbolic-3.1.1/inst/@double/fresnelc.m0000644000000000000000000000514314405647405014545 0ustar %% Copyright (C) 2016-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defun fresnelc (@var{x}) %% Numerical fresnelc function. %% %% Example: %% @example %% @group %% @c doctest: +SKIP_IF(compare_versions (OCTAVE_VERSION(), '6.0.0', '<')) %% fresnelc (1.1) %% @result{} ans = 0.7638 %% @end group %% @end example %% %% @strong{Note} this function may be slow for large numbers of inputs. %% This is because it is not a native double-precision implementation %% but rather the numerical evaluation of the Python @code{mpmath} function %% @code{fresnelc}. %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @seealso{@@sym/fresnelc} %% @end defun function y = fresnelc (x) if (nargin ~= 1) print_usage (); end cmd = { 'L = _ins[0]' 'A = [complex(mpmath.fresnelc(x)) for x in L]' 'return A,' }; c = pycall_sympy__ (cmd, num2cell (x(:))); y = reshape (cell2mat (c), size (x)); end %!error fresnelc (1, 2) %!test %! x = 1.1; %! y = sym(11)/10; %! A = fresnelc (x); %! B = double (fresnelc (y)); %! assert (A, B, -4*eps); %!test %! y = [2 3 sym(pi); exp(sym(1)) 5 6]; %! x = double (y); %! A = fresnelc (x); %! B = double (fresnelc (y)); %! assert (A, B, -4*eps); %!test %! % maple: %! % > A := [1+2*I, -2 + 5*I, 100, 10*I, -1e-4 + 1e-6*I, -20 + I]; %! % > for a in A do evalf(FresnelC(a)) end do; %! x = [1+2i; -2+5i; 100; 10i; -1e-4 + 1e-6*1i; -20-1i]; %! A = [ 16.087871374125480424 - 36.225687992881650217*1i %! 0.47688568479874574722e12 + 0.12213736710985573216e13*1i %! 0.49999989867881789756 %! 0.49989869420551572361*1i %! -0.000099999999999999997535 + 0.99999999999999987665e-6*1i %! 0.15391592966931193100e26 - 0.75738824160998910388e24*1i ]; %! B = fresnelc (x); %! assert (A, B, -eps) %!assert (fresnelc (inf), 0.5) %!assert (fresnelc (-inf), -0.5) symbolic-3.1.1/inst/@double/fresnels.m0000644000000000000000000000514214405647405014564 0ustar %% Copyright (C) 2016-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defun fresnels (@var{x}) %% Numerical fresnels function. %% %% Example: %% @example %% @group %% @c doctest: +SKIP_IF(compare_versions (OCTAVE_VERSION(), '6.0.0', '<')) %% fresnels (1.1) %% @result{} ans = 0.5365 %% @end group %% @end example %% %% @strong{Note} this function may be slow for large numbers of inputs. %% This is because it is not a native double-precision implementation %% but rather the numerical evaluation of the Python @code{mpmath} function %% @code{fresnels}. %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @seealso{@@sym/fresnels} %% @end defun function y = fresnels (x) if (nargin ~= 1) print_usage (); end cmd = { 'L = _ins[0]' 'A = [complex(mpmath.fresnels(x)) for x in L]' 'return A,' }; c = pycall_sympy__ (cmd, num2cell (x(:))); y = reshape (cell2mat (c), size (x)); end %!error fresnels (1, 2) %!test %! x = 1.1; %! y = sym(11)/10; %! A = fresnels (x); %! B = double (fresnels (y)); %! assert (A, B, -4*eps); %!test %! y = [2 3 sym(pi); exp(sym(1)) 5 6]; %! x = double (y); %! A = fresnels (x); %! B = double (fresnels (y)); %! assert (A, B, -4*eps); %!test %! % maple: %! % > A := [1+2*I, -2 + 5*I, 100, 10*I, -1e-4 + 1e-6*I, -20 + I]; %! % > for a in A do evalf(FresnelS(a)) end do; %! x = [1+2i; -2+5i; 100; 10i; -1e-4 + 1e-6*1i; -20-1i]; %! A = [ 36.725464883991438430 + 15.587751104404587334*1i %! 0.12213736710980573217e13 - 0.47688568479924574726e12*1i %! 0.49681690114783755327 %! -0.46816997858488224040*1i %! -0.52344169596561937423e-12 + 0.15707439669173367248e-13*1i %! 0.75738824160998910399e24 + 0.15391592966931193100e26*1i ]; %! B = fresnels (x); %! assert (A, B, -eps) %!assert (fresnels (inf), 0.5) %!assert (fresnels (-inf), -0.5) symbolic-3.1.1/inst/@double/harmonic.m0000644000000000000000000000363414405647405014547 0ustar %% Copyright (C) 2017-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defun harmonic (@var{x}) %% Numerical harmonic function. %% %% Example: %% @example %% @group %% harmonic (1.1) %% @result{} ans = 1.0626 %% @end group %% @end example %% %% @strong{Note} this function may be slow for large numbers of inputs. %% This is because it is not a native double-precision implementation %% but rather the numerical evaluation of the Python @code{mpmath} function %% @code{harmonic}. %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @seealso{@@sym/harmonic} %% @end defun function y = harmonic (x) if (nargin ~= 1) print_usage (); end cmd = { 'L = _ins[0]' 'A = [complex(mpmath.harmonic(x)) for x in L]' 'return A,' }; c = pycall_sympy__ (cmd, num2cell (x(:))); y = reshape (cell2mat (c), size (x)); end %!error harmonic (1, 2) %!test %! x = 1.1; %! y = sym(11)/10; %! A = harmonic (x); %! B = double (harmonic (y)); %! assert (A, B, -4*eps); %!test %! y = [2 3 sym(pi); exp(sym(1)) 5 6]; %! x = double (y); %! A = harmonic (x); %! B = double (harmonic (y)); %! assert (A, B, -4*eps); symbolic-3.1.1/inst/@double/logint.m0000644000000000000000000000475614405647405014251 0ustar %% Copyright (C) 2016-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defun logint (@var{x}) %% Numerical logint function. %% %% Example: %% @example %% @group %% logint (1.1) %% @result{} ans = -1.6758 %% @end group %% @end example %% %% @strong{Note} this function may be slow for large numbers of inputs. %% This is because it is not a native double-precision implementation %% but rather the numerical evaluation of the Python @code{mpmath} function %% @code{li}. %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @seealso{@@sym/logint} %% @end defun function y = logint (x) if (nargin ~= 1) print_usage (); end cmd = { 'L = _ins[0]' 'A = [complex(mpmath.li(x)) for x in L]' 'return A,' }; c = pycall_sympy__ (cmd, num2cell (x(:))); y = reshape (cell2mat (c), size (x)); end %!error logint (1, 2) %!test %! x = 1.1; %! y = sym(11)/10; %! A = logint (x); %! B = double (logint (y)); %! assert (A, B, -4*eps); %!test %! y = [2 3 sym(pi); exp(sym(1)) 5 6]; %! x = double (y); %! A = logint (x); %! B = double (logint (y)); %! assert (A, B, -4*eps); %!test %! % maple: %! % > A := [1+2*I, -2 + 5*I, 100, 10*I, -1e-4 + 1e-6*I, -20 + I]; %! % > for a in A do evalf(Li(a)) end do; %! x = [1+2i; -2+5i; 100; 10i; -1e-4 + 1e-6*1i; -20-1i]; %! A = [ 1.3876787420229375511 + 2.5087546988592328752*1i %! 1.6987684473874802274 + 4.5936366057115204667*1i %! 30.126141584079629926 %! 3.4936715673748995398 + 5.5260023797127391973*1i %! 0.90264689772681592152e-5 + 3.1415953634267361942*1i %! -2.3996350854560916779 - 7.6971739096353664559*1i ]; %! B = logint (x); %! assert (A, B, -eps) %!assert (logint (inf), inf) %!assert (isnan (logint (-inf))) symbolic-3.1.1/inst/@double/pochhammer.m0000644000000000000000000000552514405647405015073 0ustar %% Copyright (C) 2018-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defun pochhammer (@var{x}, @var{n}) %% Numerically evaluate the Rising Factorial or Pochhammer symbol. %% %% Example: %% @example %% @group %% pochhammer (18, 0.9) %% @result{} ans = 13.448 %% @end group %% @end example %% %% @seealso{@@sym/pochhammer} %% @end defun function y = pochhammer (n, x) if (nargin ~= 2) print_usage (); end if (isequal (size (n), size (x)) || isscalar(n)) y = zeros (size (x)); elseif (isscalar (x)) y = zeros (size (n)); else error ('pochhammer: inputs N and X must have compatible sizes') end cmd = { 'Ln = _ins[0]' 'Lx = _ins[1]' 'if len(Ln) == 1 and len(Lx) != 1:' ' Ln = Ln*len(Lx)' 'if len(Ln) != 1 and len(Lx) == 1:' ' Lx = Lx*len(Ln)' 'c = [complex(mpmath.rf(n, x)) for n,x in zip(Ln, Lx)]' 'return c,' }; c = pycall_sympy__ (cmd, num2cell (n(:)), num2cell (x(:))); for i = 1:numel (c) y(i) = c{i}; end end %!error pochhammer (1) %!error pochhammer (1, 2, 3) %!error pochhammer ([1 2], [1 2 3]) %!error pochhammer ([1 2], [1; 2]) %!test %! y = sym(11)/10; %! t = sym(3); %! x = 1.1; %! s = 3; %! A = pochhammer (x, s); %! B = double (pochhammer (y, t)); %! assert (A, B, -2*eps); %!test %! % maple %! A = 256.798558090310131720; %! B = pochhammer (18.1, 1.9); %! assert (A, B, -20*eps) %!test %! % maple, complex inputs> %! A = 2.67921619474318221972 + 1.96716724764630702653*1i; %! B = pochhammer (12.1+3.1*i, 0.5+0.2i); %! assert (A, B, -4*eps); %!test %! % maple, matrix inputs %! A = [5.61467232547723663908 20.6144884613920190965]; %! B = pochhammer ([0.9 0.8], [3.1 4.2]); %! assert (A, B, -3*eps); %!test %! % x matrix, s scalar %! y = [1 2 sym(pi); exp(sym(1)) 5 6]; %! t = sym(2); %! x = double (y); %! s = 2; %! A = pochhammer (s, x); %! B = double (pochhammer (t, y)); %! assert (A, B, -3*eps); %!test %! % s matrix, x scalar %! t = [1 2 sym(pi); exp(sym(1)) 5 6]; %! y = sym(2); %! s = double (t); %! x = 2; %! A = pochhammer (s, x); %! B = double (pochhammer (t, y)); %! assert (A, B, -5*eps); symbolic-3.1.1/inst/@double/polylog.m0000644000000000000000000000635214405647405014434 0ustar %% Copyright (C) 2016, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defun polylog (@var{s}, @var{z}) %% Numerical polylogarithm function %% %% Evaluates the polylogarithm of order @var{s} and argument @var{z}, %% in double precision. Both inputs can be arrays but their sizes %% must be either the same or scalar. %% %% Example: %% @example %% @group %% polylog (2, -4) %% @result{} ans = -2.3699 %% @end group %% @end example %% %% @strong{Note} this function may be slow for large numbers of inputs. %% This is because it is not a native double-precision implementation %% but rather the numerical evaluation of the Python @code{mpmath} function %% @code{polylog}. %% %% @seealso{@@sym/polylog} %% @end defun function y = polylog (s, x) if (nargin ~= 2) print_usage (); end if (isequal (size (s), size (x)) || isscalar(s)) y = zeros (size (x)); elseif (isscalar (x)) y = zeros (size( s)); else error ('polylog: inputs S and X must have compatible sizes') end cmd = { 'Ls = _ins[0]' 'Lx = _ins[1]' 'if len(Ls) == 1 and len(Lx) != 1:' ' Ls = Ls*len(Lx)' 'if len(Ls) != 1 and len(Lx) == 1:' ' Lx = Lx*len(Ls)' 'c = [complex(polylog(s, x)) for s,x in zip(Ls, Lx)]' 'return c,' }; c = pycall_sympy__ (cmd, num2cell (s(:)), num2cell (x(:))); for i = 1:numel (c) y(i) = c{i}; end end %!error polylog (1) %!error polylog (1, 2, 3) %!error polylog ([1 2], [1 2 3]) %!error polylog ([1 2], [1; 2]) %!test %! y = sym(11)/10; %! t = sym(2); %! x = 1.1; %! s = 2; %! A = polylog (s, x); %! B = double (polylog (t, y)); %! assert (A, B, -eps); %!test %! % maple %! A = 2.3201804233130983964 - 3.4513922952232026614*1i; %! B = polylog (2, 3); %! assert (A, B, -eps) %!test %! % maple, complex inputs %! A = -11.381456201167411758 + 6.2696695219721651947*1i; %! B = polylog (1+2i, 3+4i); %! assert (A, B, -eps); %!test %! % maple, matrix inputs %! A1 = 0.47961557317612748431 - 0.52788287823025778869*1i; %! A2 = -0.0049750526563452645369 - 0.024579343612396884851*1i; %! B = polylog ([-1-2i -3], [30+40i 40i]); %! assert ([A1 A2], B, -eps); %!test %! % x matrix, s scalar %! y = [1 2 sym(pi); exp(sym(1)) 5 6]; %! t = sym(2); %! x = double (y); %! s = 2; %! A = polylog (s, x); %! B = double (polylog (t, y)); %! assert (A, B, -eps); %!test %! % s matrix, x scalar %! t = [1 2 sym(pi); exp(sym(1)) 5 6]; %! y = sym(2); %! s = double (t); %! x = 2; %! A = polylog (s, x); %! B = double (polylog (t, y)); %! assert (A, B, -eps); symbolic-3.1.1/inst/@double/sinhint.m0000644000000000000000000000476314405647405014427 0ustar %% Copyright (C) 2016-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defun sinhint (@var{x}) %% Numerical sinhint function. %% %% Example: %% @example %% @group %% sinhint (1.1) %% @result{} ans = 1.1767 %% @end group %% @end example %% %% @strong{Note} this function may be slow for large numbers of inputs. %% This is because it is not a native double-precision implementation %% but rather the numerical evaluation of the Python @code{mpmath} function %% @code{shi}. %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @seealso{@@sym/sinhint} %% @end defun function y = sinhint (x) if (nargin ~= 1) print_usage (); end cmd = { 'L = _ins[0]' 'A = [complex(mpmath.shi(x)) for x in L]' 'return A,' }; c = pycall_sympy__ (cmd, num2cell (x(:))); y = reshape (cell2mat (c), size (x)); end %!error sinhint (1, 2) %!test %! x = 1.1; %! y = sym(11)/10; %! A = sinhint (x); %! B = double (sinhint (y)); %! assert (A, B, -4*eps); %!test %! y = [2 3 sym(pi); exp(sym(1)) 5 6]; %! x = double (y); %! A = sinhint (x); %! B = double (sinhint (y)); %! assert (A, B, -4*eps); %!test %! % maple: %! % > A := [1+2*I, -2 + 5*I, 100, 10*I, -1e-4 + 1e-6*I, -20 + I]; %! % > for a in A do evalf(Shi(a)) end do; %! x = [1+2i; -2+5i; 100; 10i; -1e-4 + 1e-6*1i; -20-1i]; %! A = [ 0.45769171128668800567 + 1.8332099215048436239*1i %! 0.60888490416819746440 + 1.2482232175376056201*1i %! 0.13577763724269399110e42 %! 1.6583475942188740493*1i %! -0.00010000000005553888891 + 0.10000000016666111119e-5*1i %! -0.74701205140887967022e7 - 0.10381447401236722090e8*1i ]; %! B = sinhint (x); %! assert (A, B, -eps) %!assert (sinhint (inf), inf) %!assert (sinhint (-inf), -inf) symbolic-3.1.1/inst/@double/sinint.m0000644000000000000000000000562414405647405014254 0ustar %% Copyright (C) 2016-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defun sinint (@var{x}) %% Numerical sinint function. %% %% Example: %% @example %% @group %% sinint (1.1) %% @result{} ans = 1.0287 %% @end group %% @end example %% %% @strong{Note} this function may be slow for large numbers of inputs. %% This is because it is not a native double-precision implementation %% but rather the numerical evaluation of the Python @code{mpmath} function %% @code{si}. %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @seealso{@@sym/sinint} %% @end defun function y = sinint (x) if (nargin ~= 1) print_usage (); end cmd = { 'L = _ins[0]' 'A = [complex(mpmath.si(x)) for x in L]' 'return A,' }; c = pycall_sympy__ (cmd, num2cell (x(:))); y = reshape (cell2mat (c), size (x)); end %!error sinint (1, 2) %!test %! x = 1.1; %! y = sym(11)/10; %! A = sinint (x); %! B = double (sinint (y)); %! assert (A, B, -4*eps); %!test %! y = [2 3 sym(pi); exp(sym(1)) 5 6]; %! x = double (y); %! A = sinint (x); %! B = double (sinint (y)); %! assert (A, B, -4*eps); %!assert (sinint (0), 0) %!assert (sinint (inf), pi/2) %!assert (sinint (-inf), -pi/2) %%tests against maple %!assert (sinint (1), 0.9460830703671830149414, -2*eps) %!assert (sinint (-1), -0.9460830703671830149414, -2*eps) %!assert (sinint (pi), 1.851937051982466170361, -2*eps) %!assert (sinint (-pi), -1.851937051982466170361, -2*eps) %!assert (sinint (300), 1.5708810882137495193, -2*eps) %!assert (sinint (1e4), 1.5708915453859619157, -2*eps) %!assert (sinint (20i), 1.2807826332028294459e7*1i, -2*eps) %!test %! % maple: %! % > A := [1+2*I, -2 + 5*I, 100, 10*I, -1e-4 + 1e-6*I, -20 + I]; %! % > for a in A do evalf(Si(a)) end do; %! x = [1+2i; -2+5i; 100; 10i; -1e-4 + 1e-6*1i; -20-1i]; %! A = [ 1.6782404878293681180 + 2.0396845546022061045*1i %! -18.154174221650281533 + 1.6146414539230479060*1i %! 1.5622254668890562934 %! 1246.1144901994233444*1i %! -0.000099999999944461111128 + 0.99999999833338888972e-6*1i %! -1.5386156269726011209 - 0.053969388020443786229*1i ]; %! B = sinint (x); %! assert (A, B, -eps) symbolic-3.1.1/inst/@double/zeta.m0000644000000000000000000000506114405647405013706 0ustar %% Copyright (C) 2016-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defun zeta (@var{x}) %% @defunx zeta (@var{n}, @var{x}) %% Numerical zeta function. %% %% Example: %% @example %% @group %% zeta (1.1) %% @result{} ans = 10.584 %% @end group %% @end example %% %% @strong{Note} this function may be slow for large numbers of inputs. %% This is because it is not a native double-precision implementation %% but rather the numerical evaluation of the Python @code{mpmath} function %% @code{zeta}. %% %% TODO: The two-argument form is not yet implemented. %% %% @seealso{@@sym/zeta} %% @end defun function y = zeta (n, x) if (nargin ~= 1 && nargin ~= 2) print_usage (); end if (nargin == 1) x = n; cmd = { 'L = _ins[0]' 'A = [complex(mpmath.zeta(x)) for x in L]' 'return A,' }; c = pycall_sympy__ (cmd, num2cell (x(:))); y = reshape (cell2mat (c), size (x)); return end error ('zeta: two input arguments not implemented'); end %!error zeta (1, 2, 3) %!assert (isnan (zeta (nan))) %!test %! x = 1.1; %! y = sym(11)/10; %! A = zeta (x); %! B = double (zeta (y)); %! assert (A, B, -4*eps); %!test %! y = [2 3 sym(pi); exp(sym(1)) 5 6]; %! x = double (y); %! A = zeta (x); %! B = double (zeta (y)); %! assert (A, B, -4*eps); %!test %! % maple: %! % > A := [1+2*I, -2 + 5*I, 100, 10*I, -1e-4 + 1e-6*I, -20 + I]; %! % > for a in A do evalf(Zeta(a)) end do; %! x = [1+2i; -2+5i; 100; 10i; -1e-4 + 1e-6*1i; -20-1i]; %! A = [ 0.59816556976238173670 - 0.35185474521784529050*1i %! 0.21425967567391921717 + 0.52503846985036050707*1i %! 1.0 %! 1.7564685929749629608 - 0.10151198543617116894*1i %! -0.49990811617645824900 - 0.91873792757763831501e-6*1i %! 175.09070083717643866 - 71.512541417467273425*1i ]; %! B = zeta (x); %! assert (A, B, -eps) %!assert (zeta (inf), 1.0) symbolic-3.1.1/inst/@logical/0000755000000000000000000000000014405647405012723 5ustar symbolic-3.1.1/inst/@logical/isAlways.m0000644000000000000000000000264114405647405014700 0ustar %% Copyright (C) 2014, 2016, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@logical isAlways (@var{t}) %% Test if expression is mathematically true. %% %% For inputs of type logical (true/false) this is just the %% logical itself. The reason for having this function is %% explained elsewhere (@pxref{@@sym/isAlways}). %% %% Examples: %% @example %% @group %% isAlways(true) %% @result{} ans = 1 %% isAlways(false) %% @result{} ans = 0 %% @end group %% @end example %% %% @seealso{@@sym/isAlways} %% @end defmethod function r = isAlways(p) if (nargin ~= 1) print_usage (); end r = p; end %!error isAlways (true, false) %!assert(isAlways(true)) %!assert(~isAlways(false)) symbolic-3.1.1/inst/@sym/0000755000000000000000000000000014405647405012121 5ustar symbolic-3.1.1/inst/@sym/abs.m0000644000000000000000000000326114405647405013046 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym abs (@var{x}) %% Symbolic abs function. %% %% Example: %% @example %% @group %% syms x %% y = abs (x) %% @result{} y = (sym) │x│ %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = abs(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('Abs', x); end %!error abs (sym(1), 2) %!assert (isequaln (abs (sym(nan)), sym(nan))) %!shared x, d %! d = -1; %! x = sym('-1'); %!test %! f1 = abs(x); %! f2 = abs(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = abs(A); %! f2 = abs(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = abs (d); %! f = abs (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/acos.m0000644000000000000000000000327414405647405013232 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym acos (@var{x}) %% Symbolic acos function. %% %% Example: %% @example %% @group %% syms x %% y = acos (x) %% @result{} y = (sym) acos(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = acos(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('acos', x); end %!error acos (sym(1), 2) %!assert (isequaln (acos (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = acos(x); %! f2 = acos(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = acos(A); %! f2 = acos(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = acos (d); %! f = acos (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/acosd.m0000644000000000000000000000314014405647405013366 0ustar %% Copyright (C) 2014-2016, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym acosd (@var{x}) %% Symbolic inverse cos function with output in degrees. %% %% Example: %% @example %% @group %% acosd (sqrt (sym (2))/2) %% @result{} (sym) 45 %% %% syms x %% y = acosd (x) %% @result{} y = (sym) %% 180⋅acos(x) %% ─────────── %% π %% @end group %% @end example %% %% @seealso{@@sym/cosd, @@sym/acos} %% @end defmethod function y = acosd(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('lambda a: deg(acos(a))', x); end %!error acosd (sym(1), 2) %!assert (isequaln (acosd (sym(nan)), sym(nan))) %!test %! f1 = acosd (sym(1)/2); %! f2 = acosd (1/2); %! assert (double (f1), f2, -eps) %!test %! D = [1 2; 3 4]/4; %! A = sym([1 2; 3 4])/4; %! f1 = acosd (A); %! f2 = acosd (D); %! assert (double (f1), f2, -eps) symbolic-3.1.1/inst/@sym/acosh.m0000644000000000000000000000331214405647405013373 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym acosh (@var{x}) %% Symbolic acosh function. %% %% Example: %% @example %% @group %% syms x %% y = acosh (x) %% @result{} y = (sym) acosh(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = acosh(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('acosh', x); end %!error acosh (sym(1), 2) %!assert (isequaln (acosh (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = acosh(x); %! f2 = acosh(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = acosh(A); %! f2 = acosh(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = acosh (d); %! f = acosh (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/acot.m0000644000000000000000000000327414405647405013233 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym acot (@var{x}) %% Symbolic acot function. %% %% Example: %% @example %% @group %% syms x %% y = acot (x) %% @result{} y = (sym) acot(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = acot(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('acot', x); end %!error acot (sym(1), 2) %!assert (isequaln (acot (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = acot(x); %! f2 = acot(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = acot(A); %! f2 = acot(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = acot (d); %! f = acot (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/acoth.m0000644000000000000000000000331214405647405013374 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym acoth (@var{x}) %% Symbolic acoth function. %% %% Example: %% @example %% @group %% syms x %% y = acoth (x) %% @result{} y = (sym) acoth(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = acoth(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('acoth', x); end %!error acoth (sym(1), 2) %!assert (isequaln (acoth (sym(nan)), sym(nan))) %!shared x, d %! d = 2; %! x = sym('2'); %!test %! f1 = acoth(x); %! f2 = acoth(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = acoth(A); %! f2 = acoth(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = acoth (d); %! f = acoth (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/acsc.m0000644000000000000000000000327414405647405013216 0ustar %% Copyright (C) 2016-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym acsc (@var{x}) %% Symbolic acsc function. %% %% Example: %% @example %% @group %% syms x %% y = acsc (x) %% @result{} y = (sym) acsc(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = acsc(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('acsc', x); end %!error acsc (sym(1), 2) %!assert (isequaln (acsc (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = acsc(x); %! f2 = acsc(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = acsc(A); %! f2 = acsc(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = acsc (d); %! f = acsc (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/acsch.m0000644000000000000000000000331214405647405013357 0ustar %% Copyright (C) 2016-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym acsch (@var{x}) %% Symbolic acsch function. %% %% Example: %% @example %% @group %% syms x %% y = acsch (x) %% @result{} y = (sym) acsch(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = acsch(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('acsch', x); end %!error acsch (sym(1), 2) %!assert (isequaln (acsch (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = acsch(x); %! f2 = acsch(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = acsch(A); %! f2 = acsch(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = acsch (d); %! f = acsch (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/adjoint.m0000644000000000000000000000403314405647405013727 0ustar %% Copyright (C) 2016 Lagu %% Copyright (C) 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym adjoint (@var{A}) %% Adjoint/Adjugate of a symbolic square matrix. %% %% @strong{Caution}: This computes the Adjugate or ``Classical Adjoint'' %% of the matrix. For the Conjugate Transpose (which is commonly %% referred to the ``Adjoint''), @pxref{@@sym/ctranspose}. %% %% Example: %% @example %% @group %% syms x %% A = [x x^3; 2*x i]; %% X = adjoint(A) %% @result{} X = (sym 2×2 matrix) %% ⎡ 3⎤ %% ⎢ ⅈ -x ⎥ %% ⎢ ⎥ %% ⎣-2⋅x x ⎦ %% @end group %% @end example %% And note the matrix adjugate @code{X} satisfies: %% @example %% @group %% A*X - det(A)*eye(2) %% @result{} ans = (sym 2×2 matrix) %% ⎡0 0⎤ %% ⎢ ⎥ %% ⎣0 0⎦ %% @end group %% @end example %% @seealso{@@sym/ctranspose} %% @end defmethod %% Reference: http://docs.sympy.org/dev/modules/matrices/matrices.html function y = adjoint(x) if (nargin ~= 1) print_usage(); end y = pycall_sympy__ ('_ins[0] = _ins[0] if _ins[0].is_Matrix else Matrix([_ins[0]]); return _ins[0].adjugate(),', x); end %!test %! syms x %! A = [x x^2; x^3 x^4]; %! B = [x^4 -x^2; -x^3 x]; %! assert( isequal( adjoint(A), B )) %!test syms x %! assert( isequal( adjoint(x), 1)) symbolic-3.1.1/inst/@sym/airy.m0000644000000000000000000000662014405647405013247 0ustar %% Copyright (C) 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym airy (@var{k}, @var{x}) %% @defmethodx @@sym airy (@var{x}) %% Symbolic Airy functions of first/second kind and their derivatives. %% %% @var{k} can be 0, 1, 2, or 3; as in the documentation for the %% non-symbolic Airy function, @pxref{airy}. %% %% Examples: %% @example %% @group %% syms z %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.4")')) %% Ai = airy(0, z) %% @result{} Ai = (sym) Ai(z) %% %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.4")')) %% Bi = airy(2, z) %% @result{} Bi = (sym) Bi(z) %% %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.4")')) %% Bi_prime = airy(3, z) %% @result{} Bi_prime = (sym) Bi'(z) %% %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.4")')) %% diff(Bi, z) %% @result{} (sym) Bi'(z) %% %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.4")')) %% diff(Bi, z, z) %% @result{} (sym) z⋅Bi(z) %% @end group %% @end example %% %% @seealso{@@sym/besselj, @@sym/bessely, @@sym/besseli, @@sym/besselk, @@sym/besselh} %% @end defmethod function A = airy(k, x) if (nargin == 2) % no-op elseif (nargin == 1) x = k; k = 0; else print_usage (); end assert(isscalar(k)) if (logical(k == 0)) A = elementwise_op ('airyai', sym(x)); elseif (logical(k == 1)) A = elementwise_op ('airyaiprime', sym(x)); elseif (logical(k == 2)) A = elementwise_op ('airybi', sym(x)); elseif (logical(k == 3)) A = elementwise_op ('airybiprime', sym(x)); else error('airy: expecting K = 0, 1, 2, or 3') end end %!test %! syms z %! a = airy(0, z); %! ap = airy(1, z); %! assert (isequal (diff (a), ap)) %! assert (isequal (diff (ap), z*a)) %!test %! syms z %! b = airy(2, z); %! bp = airy(3, z); %! assert (isequal (diff (b), bp)) %! assert (isequal (diff (bp), z*b)) %!test %! % default to k=0 %! syms z %! a = airy(0, z); %! a2 = airy(z); %! assert (isequal (a, a2)) %!error airy(0, sym('x'), 2) %!error airy(4, sym('z')) %!error airy(-1, sym('z')) %!test %! % symbolic k %! syms z %! b1 = airy(2, z); %! b2 = airy(sym(2), z); %! assert (isequal (b1, b2)) %!test %! % doubles, relative error %! X = [1 2 pi; 4i 5 6+6i]; %! Xs = sym(X); %! for k = 0:3 %! A = double(airy(k, Xs)); %! B = airy(k, X); %! assert (all (all (abs(A - B) < 500*eps*abs(A)))) %! end %!test %! % round-trip %! syms x %! for k = 0:3 %! A = airy(k, 10); %! q = airy(k, x); %! h = function_handle(q); %! B = h(10); %! assert (abs(A-B) < 500*eps*abs(A)) %! end symbolic-3.1.1/inst/@sym/all.m0000644000000000000000000000374314405647405013056 0ustar %% Copyright (C) 2014-2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym all (@var{x}) %% @defmethodx @@sym all (@var{x}, @var{dim}) %% Return true if all entries of a symbolic vector are nonzero. %% %% Similar behaviour to the built-in @code{all} with regard to %% matrices and the second argument. %% %% Throws an error if any entries are non-numeric. %% %% Example: %% @example %% @group %% all([sym(1) pi 3]) %% @result{} ans = 1 %% @end group %% @end example %% %% @seealso{@@sym/any} %% @end defmethod function z = all(x, varargin) if (nargin > 2) print_usage (); end z = all (logical (x), varargin{:}); %z = double (x, false); %if (isempty (z)) % error ('indeterminable') %else % z = all (z, varargin{:}); %end end %!test %! % matrix %! a = [0 3; 1 2]; %! s = sym (a); %! assert (isequal (all (s), all (a))) %! assert (isequal (all (s,1), all (a,1))) %! assert (isequal (all (s,2), all (a,2))) %!test %! % vector %! a = [1 2 3]; %! s = sym (a); %! assert (isequal (all (s), all (a))) %! assert (isequal (all (s,1), all (a,1))) %! assert (isequal (all (s,2), all (a,2))) %!test %! % should fail on symbols %! syms x %! s = [1 2 x]; %! try %! all (s) %! waserr = false; %! catch %! waserr = true; %! end %! assert (waserr) symbolic-3.1.1/inst/@sym/and.m0000644000000000000000000000417214405647405013045 0ustar %% Copyright (C) 2014-2016, 2018 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym and {(@var{x}, @var{y})} %% @defopx Operator @@sym {@var{x} & @var{y}} {} %% Logical "and" of symbolic arrays. %% %% Examples: %% @example %% @group %% sym(false) & sym(true) %% @result{} (sym) False %% %% syms x y z %% x & (y | z) %% @result{} (sym) x ∧ (y ∨ z) %% @end group %% @end example %% %% @seealso{@@sym/or, @@sym/not, @@sym/xor, @@sym/eq, @@sym/ne, %% @@sym/logical, @@sym/isAlways, @@sym/isequal} %% @end defop function r = and(x, y) if (nargin ~= 2) print_usage (); end r = elementwise_op ('And', sym(x), sym(y)); end %!shared t, f %! t = sym(true); %! f = sym(false); %!test %! % simple %! assert (isequal (t & f, f)) %! assert (isequal (t & t, t)) %!test %! % mix wih nonsym %! assert (isequal (t & false, f)) %! assert (isequal (t & true, t)) %! assert (isequal (t & 0, f)) %! assert (isequal (t & 1, t)) %! assert (isa (t & false, 'sym')) %! assert (isa (t & 1, 'sym')) %!test %! % array %! w = [t t f f]; %! z = [t f t f]; %! assert (isequal (w & z, [t f f f])) %!test %! % number %! assert (isequal( sym(1) & t, t)) %! assert (isequal( sym(0) & t, f)) %!test %! % output is sym even for scalar t/f %! assert (isa (t & f, 'sym')) %!test %! % eqns, exclusive %! syms x %! e = (x == 3) & (x^2 == 9); %! assert (isequal (subs(e, x, [-3 0 3]), [f f t])) %!error and (sym('x'), 2, 3) symbolic-3.1.1/inst/@sym/angle.m0000644000000000000000000000277314405647405013376 0ustar %% Copyright (C) 2016 Lagu %% Copyright (C) 2018-2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym angle (@var{x}) %% @defmethodx @@sym arg (@var{x}) %% Symbolic polar angle. %% %% Example: %% @example %% @group %% x = sym(2+3*i); %% y = angle(x) %% @result{} y = (sym) atan(3/2) %% @end group %% @end example %% @seealso{angle, @@sym/abs} %% @end defmethod function y = angle (x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('arg', x); end %!test %! Z = [sqrt(sym(3)) + 3*sym(i), 3 + sqrt(sym(3))*sym(i); 1 + sym(i), sym(i)]; %! Q = [sym(pi)/3 sym(pi)/6; sym(pi)/4 sym(pi)/2]; %! assert( isequal( angle(Z), Q)); %!test %! % roundtrip %! syms x %! A = angle (2+2i); %! f = angle (x); %! h = function_handle (f); %! B = h (2+2i); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/any.m0000644000000000000000000000374414405647405013076 0ustar %% Copyright (C) 2014-2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym any (@var{x}) %% @defmethodx @@sym any (@var{x}, @var{dim}) %% Return true if any entries of a symbolic vector are nonzero. %% %% Similar behaviour to the built-in @code{any} with regard to %% matrices and the second argument. %% %% Throws an error if any entries are non-numeric. %% %% Example: %% @example %% @group %% any([0; sym(pi); 0]) %% @result{} ans = 1 %% @end group %% @end example %% %% @seealso{@@sym/all} %% @end defmethod function z = any(x, varargin) if (nargin > 2) print_usage (); end z = any (logical (x), varargin{:}); % z = double (x, false); %if (isempty (z)) % error('indeterminable') %else % z = any (z, varargin{:}); %end end %!test %! % matrix %! a = [0 0; 1 0]; %! s = sym(a); %! assert (isequal (any (s), any (a))) %! assert (isequal (any (s,1), any (a,1))) %! assert (isequal (any (s,2), any (a,2))) %!test %! % vector %! a = [0 1 0]; %! s = sym(a); %! assert (isequal (any (s), any (a))) %! assert (isequal (any (s,1), any (a,1))) %! assert (isequal (any (s,2), any (a,2))) %!test %! % should fail on symbols %! syms x %! s = [0 1 x]; %! try %! any (s) %! waserr = false; %! catch %! waserr = true; %! end %! assert (waserr) symbolic-3.1.1/inst/@sym/arg.m0000644000000000000000000000233014405647405013046 0ustar %% Copyright (C) 2018 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym arg (@var{x}) %% @defmethodx @@sym angle (@var{x}) %% Symbolic polar angle. %% %% Example: %% @example %% @group %% x = sym(2+3*i); %% y = arg(x) %% @result{} y = (sym) atan(3/2) %% @end group %% @end example %% @seealso{arg, @@sym/abs} %% @end defmethod function y = arg (x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('arg', x); end %!test %! syms x %! assert (isequal (angle (x), arg (x))); symbolic-3.1.1/inst/@sym/argnames.m0000644000000000000000000000260414405647405014076 0ustar %% Copyright (C) 2015, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym argnames (@var{f}) %% Return the independent variables in a symfun. %% %% For a @@sym, this always returns the empty sym, but %% subclasses like @@symfun do something more interesting. %% %% Example: %% @example %% @group %% syms x y %% f = 2*x*y; %% argnames(f) %% @result{} (sym) [] (empty 0×0 matrix) %% @end group %% @end example %% %% @seealso{@@symfun/argnames, symvar, findsym, findsymbols} %% @end defmethod function vars = argnames(F) vars = sym([]); end %!test %! % basic tests %! syms x %! f = 2*x; %! assert (isempty (argnames(x))) %! assert (isempty (argnames(f))) symbolic-3.1.1/inst/@sym/asec.m0000644000000000000000000000327414405647405013220 0ustar %% Copyright (C) 2016-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym asec (@var{x}) %% Symbolic asec function. %% %% Example: %% @example %% @group %% syms x %% y = asec (x) %% @result{} y = (sym) asec(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = asec(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('asec', x); end %!error asec (sym(1), 2) %!assert (isequaln (asec (sym(nan)), sym(nan))) %!shared x, d %! d = 2; %! x = sym('2'); %!test %! f1 = asec(x); %! f2 = asec(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = asec(A); %! f2 = asec(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = asec (d); %! f = asec (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/asech.m0000644000000000000000000000331614405647405013365 0ustar %% Copyright (C) 2016-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym asech (@var{x}) %% Symbolic asech function. %% %% Example: %% @example %% @group %% syms x %% y = asech (x) %% @result{} y = (sym) asech(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = asech(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('asech', x); end %!error asech (sym(1), 2) %!assert (isequaln (asech (sym(nan)), sym(nan))) %!shared x, d %! d = 1/2; %! x = sym('1/2'); %!test %! f1 = asech(x); %! f2 = asech(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = asech(A); %! f2 = asech(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = asech (d); %! f = asech (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/asin.m0000644000000000000000000000327414405647405013237 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym asin (@var{x}) %% Symbolic asin function. %% %% Example: %% @example %% @group %% syms x %% y = asin (x) %% @result{} y = (sym) asin(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = asin(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('asin', x); end %!error asin (sym(1), 2) %!assert (isequaln (asin (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = asin(x); %! f2 = asin(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = asin(A); %! f2 = asin(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = asin (d); %! f = asin (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/asind.m0000644000000000000000000000314014405647405013373 0ustar %% Copyright (C) 2014-2016, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym asind (@var{x}) %% Symbolic inverse sin function with output in degrees. %% %% Example: %% @example %% @group %% asind (sqrt (sym (2))/2) %% @result{} (sym) 45 %% %% syms x %% y = asind (x) %% @result{} y = (sym) %% 180⋅asin(x) %% ─────────── %% π %% @end group %% @end example %% %% @seealso{@@sym/sind, @@sym/asin} %% @end defmethod function y = asind(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('lambda a: deg(asin(a))', x); end %!error asind (sym(1), 2) %!assert (isequaln (asind (sym(nan)), sym(nan))) %!test %! f1 = asind (sym(1)/2); %! f2 = asind (1/2); %! assert (double (f1), f2, -eps) %!test %! D = [1 2; 3 4]/4; %! A = sym([1 2; 3 4])/4; %! f1 = asind (A); %! f2 = asind (D); %! assert (double (f1), f2, -eps) symbolic-3.1.1/inst/@sym/asinh.m0000644000000000000000000000331214405647405013400 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym asinh (@var{x}) %% Symbolic asinh function. %% %% Example: %% @example %% @group %% syms x %% y = asinh (x) %% @result{} y = (sym) asinh(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = asinh(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('asinh', x); end %!error asinh (sym(1), 2) %!assert (isequaln (asinh (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = asinh(x); %! f2 = asinh(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = asinh(A); %! f2 = asinh(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = asinh (d); %! f = asinh (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/assume.m0000644000000000000000000001707014405647405013601 0ustar %% Copyright (C) 2014-2017 Colin B. Macdonald %% Copyright (C) 2017 Lagu %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {@var{x} =} assume (@var{x}, @var{cond}, @var{cond2}, @dots{}) %% @deftypemethodx @@sym {@var{x} =} assume (@var{x}, 'clear') %% @deftypemethodx @@sym {[@var{x}, @var{y}] =} assume ([@var{x} @var{y}], @dots{}) %% @deftypemethodx @@sym {} assume (@var{x}, @var{cond}, @var{cond2}, @dots{}) %% @deftypemethodx @@sym {} assume (@var{x}, 'clear') %% @deftypemethodx @@sym {} assume ([@var{x} @var{y}], @dots{}) %% New assumptions on a symbolic variable (replace old if any). %% %% This function has two different behaviours depending on whether %% it has an output argument or not. The first form is simpler; %% it returns a new sym with assumptions given by @var{cond}, for %% example: %% @example %% @group %% syms x %% x1 = x; %% x = assume(x, 'positive'); %% assumptions(x) %% @result{} ans = %% @{ %% [1,1] = x: positive %% @} %% assumptions(x1) % empty, x1 still has the original x %% @result{} ans = @{@}(0x0) %% @end group %% @end example %% %% Another example to help clarify: %% @example %% @group %% x1 = sym('x', 'positive') %% @result{} x1 = (sym) x %% x2 = assume(x1, 'negative') %% @result{} x2 = (sym) x %% assumptions(x1) %% @result{} ans = %% @{ %% [1,1] = x: positive %% @} %% assumptions(x2) %% @result{} ans = %% @{ %% [1,1] = x: negative %% @} %% @end group %% @end example %% %% %% The second form---with no output argument---is different; it %% attempts to find @strong{all} instances of symbols with the same name %% as @var{x} and replace them with the new version (with @var{cond} %% assumptions). For example: %% @example %% @group %% syms x %% x1 = x; %% f = sin(x); %% assume(x, 'positive'); %% assumptions(x) %% @result{} ans = %% @{ %% [1,1] = x: positive %% @} %% assumptions(x1) %% @result{} ans = %% @{ %% [1,1] = x: positive %% @} %% assumptions(f) %% @result{} ans = %% @{ %% [1,1] = x: positive %% @} %% @end group %% @end example %% %% To clear assumptions on a variable use @code{assume(x, 'clear')}, for example: %% @example %% @group %% syms x positive %% f = sin (x); %% assume (x, 'clear') %% isempty (assumptions (f)) %% @result{} ans = 1 %% @end group %% @end example %% %% @strong{Warning}: the second form operates on the caller's %% workspace via evalin/assignin. So if you call this from other %% functions, it will operate in your function's workspace (and not %% the @code{base} workspace). This behaviour is for compatibility %% with other symbolic toolboxes. %% %% FIXME: idea of rewriting all sym vars is a bit of a hack, not %% well tested (for example, with global vars.) %% %% @seealso{@@sym/assumeAlso, assume, assumptions, sym, syms} %% @end deftypemethod function varargout = assume(xx, varargin) assert (nargin > 1, 'assume: general algebraic assumptions are not supported'); for n = 2:nargin assert (ischar (varargin{n-1}), 'assume: conditions should be specified as strings') end for i = 1:numel (xx) x = subsref (xx, substruct('()', {i})); xstr = x.flat; if (nargin > 1 && strcmp(varargin{1}, 'clear')) assert (nargin == 2, 'assume: clear cannot be combined with other assumptions') newx = sym(xstr); else for n = 2:nargin cond = varargin{n-1}; ca.(cond) = true; end newx = sym(xstr, ca); end if (nargout > 0) varargout{i} = newx; else % --------------------------------------------- % Muck around in the caller's namespace, replacing syms % that match 'xstr' (a string) with the 'newx' sym. %xstr = %newx = context = 'caller'; % --------------------------------------------- S = evalin(context, 'whos'); evalin(context, '[];'); % clear 'ans' for i = 1:numel(S) obj = evalin(context, S(i).name); [newobj, flag] = symreplace(obj, xstr, newx); if flag, assignin(context, S(i).name, newobj); end end % --------------------------------------------- end end end %!test %! syms x %! x = assume(x, 'positive'); %! a = assumptions(x); %! assert(strcmp(a, 'x: positive')) %! x = assume(x, 'even'); %! a = assumptions(x); %! assert(strcmp(a, 'x: even')) %! x = assume(x, 'odd'); %! a = assumptions(x); %! assert(strcmp(a, 'x: odd')) %!error %! syms x %! x = assume (x, x); %!error %! syms x %! x = assume (x/pi, 'integer') %!test %! % multiple assumptions %! syms x %! x = assume(x, 'positive', 'integer'); %! [tilde, a] = assumptions(x, 'dict'); %! assert(a{1}.integer) %! assert(a{1}.positive) %!test %! % multiple assumptions %! syms x %! x = assume(x, 'even', 'positive'); %! [tilde, a] = assumptions(x, 'dict'); %! assert(a{1}.even) %! assert(a{1}.positive) %!test %! % has output so avoids workspace %! syms x positive %! x2 = x; %! f = sin(x); %! x = assume(x, 'negative'); %! a = assumptions(x); %! assert(strcmp(a, 'x: negative')) %! a = assumptions(x2); %! assert(strcmp(a, 'x: positive')) %! a = assumptions(f); %! assert(strcmp(a, 'x: positive')) %!test %! % clear: has output so avoids workspace %! syms x positive %! f = 2*x; %! x2 = assume(x, 'clear'); %! assert (~ isempty (assumptions (f))); %!test %! % has no output so does workspace %! syms x positive %! x2 = x; %! f = sin(x); %! assume(x, 'negative'); %! a = assumptions(x); %! assert(strcmp(a, 'x: negative')) %! a = assumptions(x2); %! assert(strcmp(a, 'x: negative')) %! a = assumptions(f); %! assert(strcmp(a, 'x: negative')) %!test %! % clear: has not output so does workspace %! syms x positive %! f = 2*x; %! assume(x, 'clear'); %! assert (isempty (assumptions (f))); %! assert (isempty (assumptions ())); %!test %! syms x positive %! assume (x, 'clear') %! assert (isempty (assumptions ())) %!error %! syms x %! x2 = assume (x, 'clear', 'real'); %!error %! syms a %! assume (a > 0) %!test %! syms x y %! assume ([x y], 'real') %! assert (strcmp (assumptions (x), 'x: real')) %! assert (strcmp (assumptions (y), 'y: real')) %!test %! syms x y %! assume ([x y], 'positive', 'even') %! assert (strcmp (assumptions (x), 'x: positive, even') || strcmp (assumptions (x), 'x: even, positive')) %! assert (strcmp (assumptions (y), 'y: positive, even') || strcmp (assumptions (y), 'y: even, positive')) %!test %! % with output, original x and y are unchanged %! syms x y %! [p, q] = assume ([x y], 'real'); %! assert (isempty (assumptions (x))) %! assert (isempty (assumptions (y))) %! assert (strcmp (assumptions (p), 'x: real')) %! assert (strcmp (assumptions (q), 'y: real')) %!test %! % matrix input %! syms a b c d %! assume ([a b; c d], 'real') %! assert (strcmp (assumptions (a), 'a: real')) %! assert (strcmp (assumptions (b), 'b: real')) %! assert (strcmp (assumptions (c), 'c: real')) %! assert (strcmp (assumptions (d), 'd: real')) symbolic-3.1.1/inst/@sym/assumeAlso.m0000644000000000000000000001403014405647405014411 0ustar %% Copyright (C) 2014-2017 Colin B. Macdonald %% Copyright (C) 2017 Lagu %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {@var{x} =} assumeAlso (@var{x}, @var{cond}, @var{cond2}, @dots{}) %% @deftypemethodx @@sym {[@var{x}, @var{y}] =} assumeAlso ([@var{x} @var{y}], @var{cond}, @dots{}) %% @deftypemethodx @@sym {} assumeAlso (@var{x}, @var{cond}) %% @deftypemethodx @@sym {} assumeAlso ([@var{x} @var{y}], @var{cond}, @dots{}) %% Add additional assumptions on a symbolic variable. %% %% Behaviour is similar to @code{assume}; however @var{cond} is combined %% with any existing assumptions of @var{x} instead of replacing them. %% %% Example: %% @example %% @group %% syms x integer %% x1 = x; %% assumptions(x1) %% @result{} ans = %% @{ %% [1,1] = x: integer %% @} %% %% x = assumeAlso(x, 'positive'); %% assumptions(x) %% @result{} ans = %% @{ %% [1,1] = x: integer, positive %% @} %% @end group %% @end example %% %% As with @code{assume}, note @code{x1} is unchanged: %% @example %% @group %% assumptions(x1) %% @result{} ans = %% @{ %% [1,1] = x: integer %% @} %% @end group %% @end example %% %% @strong{Warning}: with no output argument, this tries to find %% and replace any @var{x} within expressions in the caller's %% workspace. See @ref{assume}. %% %% @seealso{@@sym/assume, assumptions, sym, syms} %% @end deftypemethod function varargout = assumeAlso(xx, varargin) assert (nargin > 1, 'assumeAlso: general algebraic assumptions are not supported'); for n = 2:nargin assert (ischar (varargin{n-1}), 'assumeAlso: conditions should be specified as strings') end for i = 1:numel (xx) x = subsref (xx, substruct('()', {i})); [tilde,ca] = assumptions(x, 'dict'); if isempty(ca) ca = []; elseif (length(ca)==1) ca = ca{1}; else ca error('expected at most one dict') end for n=2:nargin cond = varargin{n-1}; ca.(cond) = true; end xstr = x.flat; newx = sym(xstr, ca); if (nargout > 0) varargout{i} = newx; else % --------------------------------------------- % Muck around in the caller's namespace, replacing syms % that match 'xstr' (a string) with the 'newx' sym. %xstr = %newx = context = 'caller'; % --------------------------------------------- S = evalin(context, 'whos'); evalin(context, '[];'); % clear 'ans' for i = 1:numel(S) obj = evalin(context, S(i).name); [newobj, flag] = symreplace(obj, xstr, newx); if flag, assignin(context, S(i).name, newobj); end end % --------------------------------------------- end end end %!test %! syms x %! x = assumeAlso(x, 'positive'); %! a = assumptions(x); %! assert(strcmp(a, 'x: positive')) %!error %! syms x %! x = assumeAlso (x, x); %!test %! syms x positive %! x = assumeAlso(x, 'integer'); %! [tilde, a] = assumptions(x, 'dict'); %! assert(a{1}.integer) %! assert(a{1}.positive) %!test %! % multiple assumptions %! syms x positive %! x = assumeAlso(x, 'integer', 'even'); %! [tilde, a] = assumptions(x, 'dict'); %! assert(a{1}.integer) %! assert(a{1}.positive) %! assert(a{1}.even) %!test %! % multiple assumptions %! syms x integer %! x = assumeAlso (x, 'even', 'positive'); %! [tilde, a] = assumptions (x, 'dict'); %! assert (a{1}.integer) %! assert (a{1}.even) %! assert (a{1}.positive) %!test %! % has output so avoids workspace %! syms x positive %! x2 = x; %! f = sin(x); %! assumeAlso(x, 'integer'); %! a = assumptions(x); %! assert(strcmp(a, 'x: positive, integer') || strcmp(a, 'x: integer, positive')) %! a = assumptions(x2); %! assert(strcmp(a, 'x: positive, integer') || strcmp(a, 'x: integer, positive')) %! a = assumptions(f); %! assert(strcmp(a, 'x: positive, integer') || strcmp(a, 'x: integer, positive')) %!test %! % has no output so does workspace %! syms x positive %! x2 = x; %! f = sin(x); %! assumeAlso(x, 'integer'); %! a = assumptions(x); %! assert(strcmp(a, 'x: positive, integer') || strcmp(a, 'x: integer, positive')) %! a = assumptions(x2); %! assert(strcmp(a, 'x: positive, integer') || strcmp(a, 'x: integer, positive')) %! a = assumptions(f); %! assert(strcmp(a, 'x: positive, integer') || strcmp(a, 'x: integer, positive')) %!error %! syms a %! assumeAlso (a > 0) %!test %! syms x y %! assumeAlso ([x y], 'even') %! assert (strcmp (assumptions (x), 'x: even')) %! assert (strcmp (assumptions (y), 'y: even')) %!test %! syms x y positive %! f = sin (2*x); %! assumeAlso ([x y], 'even') %! assert (strcmp (assumptions (x), 'x: even, positive') || strcmp (assumptions (x), 'x: positive, even')) %! assert (strcmp (assumptions (y), 'y: even, positive') || strcmp (assumptions (y), 'y: positive, even')) %! assert (strcmp (assumptions (f), 'x: even, positive') || strcmp (assumptions (f), 'x: positive, even')) %!test %! % with output, original x and y are unchanged %! syms x y positive %! f = sin (2*x); %! [p, q] = assumeAlso ([x y], 'even'); %! assert (strcmp (assumptions (x), 'x: positive')) %! assert (strcmp (assumptions (y), 'y: positive')) %! assert (strcmp (assumptions (f), 'x: positive')) %! assert (strcmp (assumptions (p), 'x: even, positive') || strcmp (assumptions (p), 'x: positive, even')) %! assert (strcmp (assumptions (q), 'y: even, positive') || strcmp (assumptions (q), 'y: positive, even')) symbolic-3.1.1/inst/@sym/atan.m0000644000000000000000000000327414405647405013230 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym atan (@var{x}) %% Symbolic atan function. %% %% Example: %% @example %% @group %% syms x %% y = atan (x) %% @result{} y = (sym) atan(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = atan(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('atan', x); end %!error atan (sym(1), 2) %!assert (isequaln (atan (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = atan(x); %! f2 = atan(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = atan(A); %! f2 = atan(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = atan (d); %! f = atan (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/atan2.m0000644000000000000000000000400714405647405013305 0ustar %% Copyright (C) 2014, 2016, 2018, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym atan2 (@var{x}, @var{y}) %% Return an angle from a point given by symbolic expressions. %% %% Examples: %% @example %% @group %% atan2(sym(1),1) %% @result{} (sym) %% π %% ─ %% 4 %% atan2(0, sym(-1)) %% @result{} (sym) π %% @end group %% @end example %% %% @seealso{@@sym/atan, @@sym/hypot} %% @end defmethod function a = atan2(y, x) if (nargin ~= 2) print_usage (); end a = elementwise_op ('atan2', sym(y), sym(x)); end %!error atan2 (1) %!error atan2 (1, 2, 3) %!test %! % some angles %! e = sym(1); %! a = atan2(0, e); %! assert (isequal (a, sym(0))) %! a = atan2(e, 0); %! assert (isequal (a, sym(pi)/2)) %!test %! % symbols can give numerical answer %! syms x positive %! a = atan2(0, x); %! assert (isequal (a, sym(0))) %! a = atan2(x, 0); %! assert (isequal (a, sym(pi)/2)) %! a = atan2(-x, 0); %! assert (isequal (a, -sym(pi)/2)) %!test %! % matrices %! x = sym([1 -2; 0 0]); %! y = sym([0 0; 8 -3]); %! a = atan2(y, x); %! sp = sym(pi); %! aex = [0 sp; sp/2 -sp/2]; %! assert (isequal (a, aex)) %!test %! % round trip %! syms x y %! xd = -2; yd = -3; %! f = atan2 (x, y); %! A = atan2 (xd, yd); %! h = function_handle (f); %! B = h (xd, yd); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/atand.m0000644000000000000000000000313614405647405013371 0ustar %% Copyright (C) 2014-2016, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym atand (@var{x}) %% Symbolic inverse tan function with output in degrees. %% %% Example: %% @example %% @group %% atand (sqrt (sym (3))) %% @result{} (sym) 60 %% %% syms x %% y = atand (x) %% @result{} y = (sym) %% 180⋅atan(x) %% ─────────── %% π %% @end group %% @end example %% %% @seealso{@@sym/tand, @@sym/atan} %% @end defmethod function y = atand(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('lambda a: deg(atan(a))', x); end %!error atand (sym(1), 2) %!assert (isequaln (atand (sym(nan)), sym(nan))) %!test %! f1 = atand (sym(1)/2); %! f2 = atand (1/2); %! assert (double (f1), f2, -eps) %!test %! D = [1 2; 3 4]/4; %! A = sym([1 2; 3 4])/4; %! f1 = atand (A); %! f2 = atand (D); %! assert (double (f1), f2, -eps) symbolic-3.1.1/inst/@sym/atanh.m0000644000000000000000000000331614405647405013375 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym atanh (@var{x}) %% Symbolic atanh function. %% %% Example: %% @example %% @group %% syms x %% y = atanh (x) %% @result{} y = (sym) atanh(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = atanh(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('atanh', x); end %!error atanh (sym(1), 2) %!assert (isequaln (atanh (sym(nan)), sym(nan))) %!shared x, d %! d = 1/2; %! x = sym('1/2'); %!test %! f1 = atanh(x); %! f2 = atanh(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = atanh(A); %! f2 = atanh(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = atanh (d); %! f = atanh (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/bernoulli.m0000644000000000000000000000624714405647405014303 0ustar %% Copyright (C) 2014-2016, 2018-2019, 2022-2023 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {@var{B} =} bernoulli (@var{n}) %% @deftypemethodx @@sym {@var{p} =} bernoulli (@var{n}, @var{x}) %% Return symbolic Bernoulli numbers or Bernoulli polynomials. %% %% With a sufficiently recent SymPy version, the first seven %% Bernoulli numbers are: %% @example %% @group %% @c doctest: +XFAIL_IF(pycall_sympy__ ('return Version(spver) < Version("1.12.dev")')) %% bernoulli (sym(0:6)) %% @result{} (sym) [1 1/2 1/6 0 -1/30 0 1/42] (1×7 matrix) %% @end group %% @end example %% %% Note there are two different definitions in use which differ %% in the sign of the value of B_1. As of 2023 and a sufficiently %% recent SymPy library, we use the definition with positive one half: %% @example %% @group %% @c doctest: +XFAIL_IF(pycall_sympy__ ('return Version(spver) < Version("1.12.dev")')) %% bernoulli (sym(1)) %% @result{} (sym) 1/2 %% @end group %% @end example %% %% Other examples: %% @example %% @group %% bernoulli (sym(6)) %% @result{} (sym) 1/42 %% bernoulli (sym(7)) %% @result{} (sym) 0 %% @end group %% @end example %% %% Polynomial example: %% @example %% @group %% syms x %% bernoulli (2, x) %% @result{} (sym) %% 2 1 %% x - x + ─ %% 6 %% @end group %% @end example %% @seealso{@@double/bernoulli, @@sym/euler} %% @end deftypemethod function r = bernoulli (varargin) if (nargin ~= 1 && nargin ~= 2) print_usage (); end for i = 1:nargin varargin{i} = sym (varargin{i}); end r = elementwise_op ('bernoulli', varargin{:}); end %!error bernoulli (sym(1), 2, 3) %!assert (isequal (bernoulli (sym(8)), -sym(1)/30)) %!assert (isequal (bernoulli (sym(9)), sym(0))) %!test syms x %! assert (isequal (bernoulli(3,x), x^3 - 3*x^2/2 + x/2)) %!test %! % two different definitions in literature %! assert (isequal (abs (bernoulli (sym(1))), sym(1)/2)) %!test %! % we use B_1 = 1/2 %! if (pycall_sympy__ ('return Version(spver) >= Version("1.12.dev")')) %! assert (isequal (bernoulli (sym(1)), sym(1)/2)) %! end %!test %! m = sym([0 2; 8 888889]); %! A = bernoulli (m); %! B = [1 sym(1)/6; -sym(1)/30 0]; %! assert (isequal (A, B)) %!test %! syms x %! A = bernoulli ([0; 1], x); %! B = [sym(1); x - sym(1)/2]; %! assert (isequal (A, B)) %!test %! % round trip %! syms n x %! f = bernoulli (n, x); %! h = function_handle (f, 'vars', [n x]); %! A = h (2, 2.2); %! B = bernoulli (2, 2.2); %! assert (A, B) symbolic-3.1.1/inst/@sym/besselh.m0000644000000000000000000000466214405647405013734 0ustar %% Copyright (C) 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym besselh (@var{alpha}, @var{k}, @var{x}) %% @defmethodx @@sym besselh (@var{alpha}, @var{x}) %% Symbolic Hankel functions of first/second kind. %% %% The kind @var{k} can be 1 or 2 and defaults to 1. %% %% Example: %% @example %% @group %% syms x alpha %% H1 = besselh(alpha, 1, x) %% @result{} H1 = (sym) hankel₁(α, x) %% %% H2 = besselh(alpha, 2, x) %% @result{} H2 = (sym) hankel₂(α, x) %% @end group %% @end example %% %% @seealso{@@sym/airy, @@sym/besselj, @@sym/bessely, @@sym/besseli, %% @@sym/besselk} %% @end defmethod function A = besselh(alpha, k, x) if (nargin == 3) % no-op elseif (nargin == 2) x = k; k = 1; else print_usage (); end assert(isscalar(k)) if (logical(k == 1)) A = elementwise_op ('hankel1', sym(alpha), sym(x)); elseif (logical(k == 2)) A = elementwise_op ('hankel2', sym(alpha), sym(x)); else error('besselh: expecting k = 1 or 2') end end %!test %! % default to k=1 %! syms z a %! A = besselh(a, z); %! B = besselh(a, 1, z); %! assert (isequal (A, B)) %!error besselh(sym('z')) %!error besselh(2, 0, sym('z')) %!error besselh(2, 3, sym('z')) %!test %! % doubles, relative error %! X = [1 2 pi; 4i 5 6+6i]; %! Xs = sym(X); %! Alpha = [pi 3 1; 3 2 0]; %! Alphas = sym(Alpha); %! for k = 1:2 %! A = double(besselh(Alphas, k, Xs)); %! B = besselh(Alpha, k, X); %! assert (all (all (abs(A - B) < 10*eps*abs(A)))) %! end %!test %! % round-trip %! syms x %! for k = 1:2 %! A = besselh(4, k, 10); %! q = besselh(4, k, x); %! h = function_handle(q); %! B = h(10); %! assert (abs(A - B) <= eps*abs(A)) %! end symbolic-3.1.1/inst/@sym/besseli.m0000644000000000000000000000326014405647405013726 0ustar %% Copyright (C) 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym besseli (@var{alpha}, @var{x}) %% Symbolic modified Bessel function of the first kind. %% %% Example: %% @example %% @group %% syms n x %% A = 2*besseli(n,x) %% @result{} A = (sym) 2⋅besseli(n, x) %% diff(A) %% @result{} (sym) besseli(n - 1, x) + besseli(n + 1, x) %% @end group %% @end example %% %% @seealso{@@sym/besselk, @@sym/besselj, @@sym/bessely} %% @end defmethod function I = besseli(n, x) if (nargin ~= 2) print_usage (); end I = elementwise_op ('besseli', sym(n), sym(x)); end %!test %! X = [1 2 3; 4 5 6]; %! ns = [sym(0) 1 -2; sym(1)/2 -sym(3)/2 pi]; %! n = double(ns); %! A = double(besseli(ns, X)); %! B = besseli(n, X); %! assert (all (all (abs (A - B) < 100*eps*abs(A)))) %!test %! % roundtrip %! syms x %! A = besseli(2, 10); %! q = besseli(2, x); %! h = function_handle(q); %! B = h(10); %! assert (abs (A - B) <= eps*abs(A)) %!error besseli(sym('x')) symbolic-3.1.1/inst/@sym/besselj.m0000644000000000000000000000324614405647405013733 0ustar %% Copyright (C) 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym besselj (@var{alpha}, @var{x}) %% Symbolic Bessel function of the first kind. %% %% Example: %% @example %% @group %% syms n x %% A = 2*besselj(n,x) %% @result{} A = (sym) 2⋅besselj(n, x) %% diff(A) %% @result{} (sym) besselj(n - 1, x) - besselj(n + 1, x) %% @end group %% @end example %% %% @seealso{@@sym/bessely, @@sym/besseli, @@sym/besselk} %% @end defmethod function J = besselj(n, x) if (nargin ~= 2) print_usage (); end J = elementwise_op ('besselj', sym(n), sym(x)); end %!test %! X = [1 2 3; 4 5 6]; %! ns = [sym(0) 1 -2; sym(1)/2 -sym(3)/2 pi]; %! n = double(ns); %! A = double(besselj(ns, X)); %! B = besselj(n, X); %! assert (all (all (abs (A - B) < 50*eps*abs(A)))) %!test %! % roundtrip %! syms x %! A = besselj(2, 10); %! q = besselj(2, x); %! h = function_handle(q); %! B = h(10); %! assert (abs (A - B) <= eps*abs(A)) %!error besselj(sym('x')) symbolic-3.1.1/inst/@sym/besseljn.m0000644000000000000000000000310714405647405014105 0ustar %% Copyright (C) 2016 Utkarsh Gautam %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym besseljn (@var{alpha}, @var{x}) %% Symbolic Spherical Bessel function of the first kind. %% %% Example: %% @example %% @group %% syms n x %% A = besseljn(n, x) %% @result{} A = (sym) jn(n, x) %% diff(A) %% @result{} ans = (sym) %% %% (n + 1)⋅jn(n, x) %% jn(n - 1, x) - ──────────────── %% x %% @end group %% @end example %% %% @seealso{@@sym/besselyn, @@sym/besselj} %% @end defmethod function Y = besseljn(n, x) if (nargin ~= 2) print_usage (); end Y = elementwise_op ('jn', sym(n), sym(x)); end %!test %! % roundtrip %! syms x %! A = double(besseljn(sym(2), sym(9))); %! q = besseljn(sym(2), x); %! h = function_handle(q); %! B = h(9); %! assert (abs (A - B) <= eps) %!error jn(sym('x')) symbolic-3.1.1/inst/@sym/besselk.m0000644000000000000000000000326014405647405013730 0ustar %% Copyright (C) 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym besselk (@var{alpha}, @var{x}) %% Symbolic modified Bessel function of the second kind. %% %% Example: %% @example %% @group %% syms n x %% A = 2*besselk(n,x) %% @result{} A = (sym) 2⋅besselk(n, x) %% diff(A) %% @result{} (sym) -besselk(n - 1, x) - besselk(n + 1, x) %% @end group %% @end example %% %% @seealso{@@sym/besseli, @@sym/besselj, @@sym/bessely} %% @end defmethod function K = besselk(n, x) if (nargin ~= 2) print_usage (); end K = elementwise_op ('besselk', sym(n), sym(x)); end %!test %! X = [1 2 3; 4 5 6]; %! ns = [sym(0) 1 -2; sym(1)/2 -sym(3)/2 pi]; %! n = double(ns); %! A = double(besselk(ns, X)); %! B = besselk(n, X); %! assert (all (all (abs (A - B) < 2*eps*abs(A)))) %!test %! % roundtrip %! syms x %! A = besselk(2, 10); %! q = besselk(2, x); %! h = function_handle(q); %! B = h(10); %! assert (abs (A - B) <= eps*abs(A)) %!error besselk(sym('x')) symbolic-3.1.1/inst/@sym/bessely.m0000644000000000000000000000325014405647405013745 0ustar %% Copyright (C) 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym bessely (@var{alpha}, @var{x}) %% Symbolic Bessel function of the second kind. %% %% Example: %% @example %% @group %% syms n x %% A = 2*bessely(n, x) %% @result{} A = (sym) 2⋅bessely(n, x) %% diff(A) %% @result{} (sym) bessely(n - 1, x) - bessely(n + 1, x) %% @end group %% @end example %% %% @seealso{@@sym/besselj, @@sym/besseli, @@sym/besselk} %% @end defmethod function Y = bessely(n, x) if (nargin ~= 2) print_usage (); end Y = elementwise_op ('bessely', sym(n), sym(x)); end %!test %! X = [1 2 3; 4 5 6]; %! ns = [sym(0) 1 -2; sym(1)/2 -sym(3)/2 pi]; %! n = double(ns); %! A = double(bessely(ns, X)); %! B = bessely(n, X); %! assert (all (all (abs (A - B) < 50*eps*abs(A)))) %!test %! % roundtrip %! syms x %! A = bessely(2, 10); %! q = bessely(2, x); %! h = function_handle(q); %! B = h(10); %! assert (abs (A - B) <= eps*abs(A)) %!error bessely(sym('x')) symbolic-3.1.1/inst/@sym/besselyn.m0000644000000000000000000000311514405647405014123 0ustar %% Copyright (C) 2016 Utkarsh Gautam %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym besselyn (@var{alpha}, @var{x}) %% Symbolic Spherical Bessel function of the second kind. %% %% Example: %% @example %% @group %% syms n x %% A = besselyn(n, x) %% @result{} A = (sym) yn(n, x) %% diff(A) %% @result{} ans = (sym) %% %% (n + 1)⋅yn(n, x) %% yn(n - 1, x) - ──────────────── %% x %% @end group %% @end example %% %% @seealso{@@sym/besseljn, @@sym/bessely} %% @end defmethod function Y = besselyn(n, x) if (nargin ~= 2) print_usage (); end Y = elementwise_op ('yn', sym(n), sym(x)); end %!test %! % roundtrip %! syms x %! A = double(besselyn(sym(2), sym(10))); %! q = besselyn(sym(2), x); %! h = function_handle(q); %! B = h(10); %! assert (abs (A - B) <= eps) %!error yn(sym('x')) symbolic-3.1.1/inst/@sym/beta.m0000644000000000000000000000342514405647405013216 0ustar %% Copyright (C) 2016 Lagu %% Copyright (C) 2018-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym beta (@var{x}, @var{y}) %% Beta function. %% %% Example: %% @example %% @group %% syms x y %% beta(x, y) %% @result{} ans = (sym) Β(x, y) %% @end group %% @end example %% %% The beta function is related to the gamma function: %% @example %% @group %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.4")')) %% rewrite (beta (x,y), "gamma") %% @result{} %% ans = (sym) %% Γ(x)⋅Γ(y) %% ───────── %% Γ(x + y) %% @end group %% @end example %% %% @seealso{@@sym/gamma} %% @end defmethod function r = beta(x, y) if (nargin ~= 2) print_usage (); end r = elementwise_op ('beta', sym(x), sym(y)); end %!error beta (sym(1), 2, 3) %!assert (isequal (double (beta (sym(1), 2)), 1/2)) %!assert (isinf (double (beta (sym(1), 0)))) %!test %! % round trip %! syms x y %! f = beta (x, y); %! h = function_handle (f); %! A = h (1.1, 2.2); %! B = beta (1.1, 2.2); %! assert (A, B) symbolic-3.1.1/inst/@sym/cart2pol.m0000644000000000000000000001275714405647405014041 0ustar %% Copyright (C) 2022 Alex Vong %% Copyright (C) 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {[@var{theta}, @var{r}] =} cart2pol (@var{x}, @var{y}) %% @deftypemethodx @@sym {[@var{theta}, @var{r}, @var{z}] =} cart2pol (@var{x}, @var{y}, @var{z}) %% @deftypemethodx @@sym {[@var{theta}, @var{r}] =} cart2pol (@var{C}) %% @deftypemethodx @@sym {[@var{theta}, @var{r}, @var{z}] =} cart2pol (@var{C}) %% Transform symbolic Cartesian coordinates into polar or cylindrical. %% %% If called with inputs @var{x}, @var{y} (and @var{z}), they must be of the %% same shape or a scalar. The shape of the outputs @var{theta}, @var{r} (and %% @var{z}) matches those of the inputs (except when the input is a scalar). %% %% If called with a single input @var{C}, it must be a column vector with 2 or %% 3 entries, or a matrix with 2 or 3 columns. The column vector or each row %% of the matrix represents a point in Cartesian coordinates (@var{x}, @var{y}) %% or (@var{x}, @var{y}, @var{z}). If input @var{C} is a column vector, %% outputs @var{theta}, @var{r} (and @var{z}) is a scalar. Otherwise, the %% shape of the outputs @var{theta}, @var{r} (and @var{z}) is a column vector %% with each row corresponding to that of the input matrix @var{C}. %% %% Given a point (@var{x}, @var{y}) in Cartesian coordinates, its corresponding %% polar coordinates can be obtained by: %% @example %% @group %% syms x y real %% [theta, r] = cart2pol (x, y) %% @result{} theta = (sym) atan2(y, x) %% r = (sym) %% _________ %% ╱ 2 2 %% ╲╱ x + y %% @end group %% @end example %% %% Similarly, given a point (@var{x}, @var{y}, @var{z}) in Cartesian %% coordinates, its corresponding cylindrical coordinates can be obtained by: %% @example %% @group %% syms x y z real %% [theta, r, z] = cart2pol (x, y, z) %% @result{} theta = (sym) atan2(y, x) %% r = (sym) %% _________ %% ╱ 2 2 %% ╲╱ x + y %% z = (sym) z %% @end group %% @end example %% %% @seealso{cart2pol} %% @end deftypemethod function [theta, r, z_out] = cart2pol (x_in, y_in, z_in) %% obtain the kth column of matrix A column_ref = @(A, k) subsref (A, substruct ('()', {':', k})); if nargin == 1 C = sym (x_in); sz = size (C); nrows = sz(1); ncols = sz(2); if isequal (sz, [2 1]) args = num2cell (C); [theta, r] = cart2pol (args{:}); elseif isequal (sz, [3 1]) args = num2cell (C); [theta, r, z_out] = cart2pol (args{:}); elseif ncols == 2 args = arrayfun (@(k) column_ref (C, k), 1:ncols, 'UniformOutput', false); [theta, r] = cart2pol (args{:}); elseif ncols == 3 args = arrayfun (@(k) column_ref (C, k), 1:ncols, 'UniformOutput', false); [theta, r, z_out] = cart2pol (args{:}); else warning ('cart2pol: C must be a column vector with 2 or 3 entries, or a matrix with 2 or 3 columns'); print_usage (); end return end x = sym (x_in); y = sym (y_in); if isscalar (size (x)) sz = size (y); elseif isscalar (size (y)) || isequal (size (x), size (y)) sz = size (x); else error ('cart2pol: all inputs must have compatible sizes'); end r = hypot (sym (x), sym (y)); theta = atan2 (sym (y), sym (x)); if nargin == 3 z = sym (z_in); if isscalar (z) z_out = z * ones (sz); elseif isequal(size (z), sz) z_out = z; else error ('cart2pol: all inputs must have compatible sizes'); end end end %!test %! % multiple non-scalar inputs %! x = sym ('x', [2 2]); %! assume (x, 'real'); %! y = sym ('y', [2 2]); %! assume (y, 'real'); %! [theta, r] = cart2pol (x, y); %! assert (isequal (r, sqrt (x.^2 + y.^2))); %! assert (isequal (tan (theta), y ./ x)); %! % mixing scalar inputs with non-scalar inputs %! syms z real %! [theta_2, r_2, z_2] = cart2pol (x, y, z); %! assert (isequal (r_2, sqrt (x.^2 + y.^2))); %! assert (isequal (tan (theta_2), y ./ x)); %! assert (isequal (z_2, z * ones (2, 2))); %!test %! % column vector with 2 entries %! syms x y real %! [theta, r] = cart2pol ([x; y]); %! assert (isequal (r, sqrt (x.^2 + y.^2))); %! assert (isequal (tan (theta), y ./ x)); %! % column vector with 3 entries %! syms z real %! [theta_2, r_2, z_2] = cart2pol ([x; y; z]); %! assert (isequal (r_2, sqrt (x.^2 + y.^2))); %! assert (isequal (tan (theta_2), y ./ x)); %! assert (isequal (z_2, z)); %!test %! % matrix with 2 columns %! syms x y u v real %! C = [x y; u v]; %! [theta, r] = cart2pol (C); %! assert (isequal (r, [sqrt(x.^2+y.^2); sqrt(u.^2+v.^2)])); %! assert (isequal (tan (theta), [y/x; v/u])); %! % matrix with 3 columns %! syms z w real %! C_2 = [x y z; u v w]; %! [theta_2, r_2, z_2] = cart2pol (C_2); %! assert (isequal (r, [sqrt(x.^2+y.^2); sqrt(u.^2+v.^2)])); %! assert (isequal (tan (theta), [y/x; v/u])); %! assert (isequal (z_2, [z; w])); symbolic-3.1.1/inst/@sym/cat.m0000644000000000000000000000334114405647405013047 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym cat (@var{dim}, @var{A}, @var{B}, @dots{}) %% Concatenate symbolic arrays along particular dimension. %% %% @var{dim} is currently restricted to 1 or 2 as symbolic arrays %% are currently only two-dimensional. %% %% Example: %% @example %% @group %% syms x %% cat(1, x, 2*x, 3*x) %% @result{} (sym) [x 2⋅x 3⋅x] (1×3 matrix) %% cat(2, x, x) %% @result{} (sym 2×1 matrix) %% ⎡x⎤ %% ⎢ ⎥ %% ⎣x⎦ %% @end group %% @end example %% @seealso{@@sym/vertcat, @@sym/horzcat} %% @end defmethod function z = cat(dim, varargin) if (logical(dim == 1)) z = horzcat(varargin{:}); elseif (logical(dim == 2)) z = vertcat(varargin{:}); else print_usage (); end end %!test %! % mostly tested in horzcat, vertcat: one for good measure %! syms x %! assert (isequal (cat(1, x, x), [x x])) %! assert (isequal (cat(2, x, x), [x; x])) %!error cat(3, sym(2), sym(3)) %!error cat(0, sym(2), sym(3)) symbolic-3.1.1/inst/@sym/cbrt.m0000644000000000000000000000355214405647405013236 0ustar %% Copyright (C) 2015-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym cbrt (@var{x}) %% Symbolic cbrt function. %% %% Example: %% @example %% @group %% syms x %% y = cbrt (x) %% @result{} y = (sym) %% 3 ___ %% ╲╱ x %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = cbrt(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('cbrt', x); end %!error cbrt (sym(1), 2) %!assert (isequaln (cbrt (sym(nan)), sym(nan))) %!shared x, d %! d = 2; %! x = sym('2'); %!test %! f1 = cbrt(x); %! f2 = 1.2599210498948731647; %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = cbrt(A); %! f2 = 1.2599210498948731647; %! f2 = [f2 f2; f2 f2]; %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! if (exist ('OCTAVE_VERSION', 'builtin')) %! A = cbrt (d); %! else %! % Issue #742 %! A = d^(1/3); %! end %! f = cbrt (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/ccode.m0000644000000000000000000000767514405647405013373 0ustar %% Copyright (C) 2014-2016, 2018-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {@var{s} =} ccode (@var{f}) %% @deftypemethodx @@sym {@var{s} =} ccode (@var{f1}, @dots{}, @var{fn}) %% @deftypemethodx @@sym {} ccode (@dots{}, 'file', @var{filename}) %% @deftypemethodx @@sym {[@var{c_stuff}, @var{h_stuff}] =} ccode (@dots{}, 'file', '') %% Convert symbolic expression into C code. %% %% Example: %% @example %% @group %% syms x %% g = taylor(log(1 + x), x, 0, 'order', 5); %% g = horner(g) %% @result{} g = (sym) %% ⎛ ⎛ ⎛1 x⎞ 1⎞ ⎞ %% x⋅⎜x⋅⎜x⋅⎜─ - ─⎟ - ─⎟ + 1⎟ %% ⎝ ⎝ ⎝3 4⎠ 2⎠ ⎠ %% ccode(g) %% @result{} x*(x*(x*(1.0/3.0 - 1.0/4.0*x) - 1.0/2.0) + 1) %% @end group %% @end example %% %% We can write to a file or obtain the contents directly: %% @example %% @group %% [C, H] = ccode(g, 'file', '', 'show_header', false); %% C.name %% @result{} file.c %% H.name %% @result{} file.h %% @end group %% %% @group %% disp(H.code) %% @print{} #ifndef PROJECT__FILE__H %% @print{} #define PROJECT__FILE__H %% @print{} %% @print{} double myfun(double x); %% @print{} %% @print{} #endif %% @end group %% %% @group %% disp(C.code) %% @print{} #include "file.h" %% @print{} #include %% @print{} %% @print{} double myfun(double x) @{ %% @print{} %% @print{} double myfun_result; %% @print{} myfun_result = x*(x*(x*(1.0/3.0 - 1.0/4.0*x) - 1.0/2.0) + 1); %% @print{} return myfun_result; %% @print{} %% @print{} @} %% @end group %% @end example %% %% FIXME: This doesn't write ``optimized'' code like Matlab's %% Symbolic Math Toolbox; it doesn't do ``Common Subexpression %% Elimination''. Presumably the compiler would do that for us %% anyway. Sympy has a ``cse'' module that will do it. See: %% http://stackoverflow.com/questions/22665990/optimize-code-generated-by-sympy %% %% @seealso{@@sym/fortran, @@sym/latex, @@ssym/function_handle} %% @end deftypemethod function varargout = ccode(varargin) [flg, meh] = codegen(varargin{:}, 'lang', 'C'); if flg == 0 varargout = {}; elseif flg == 1 varargout = meh(1); elseif flg == 2 varargout = {meh{1}, meh{2}}; else error('whut?'); end end %!shared x,y,z %! syms x y z %!test %! % basic test %! f = x*sin(y) + abs(z); %! source = ccode(f); %! expected = 'x*sin(y) + fabs(z)'; %! assert(strcmp(source, expected)) %!test %! % output test %! f = x*sin(y) + abs(z); %! [C, H] = ccode(f, 'file', '', 'show_header', false); %! expected_c_code = sprintf('#include \"file.h\"\n#include \n\ndouble myfun(double x, double y, double z) {\n\n double myfun_result;\n myfun_result = x*sin(y) + fabs(z);\n return myfun_result;\n\n}\n'); %! expected_h_code = sprintf('\n#ifndef PROJECT__FILE__H\n#define PROJECT__FILE__H\n\ndouble myfun(double x, double y, double z);\n\n#endif\n\n'); %! assert(strcmp(C.name, 'file.c')) %! assert(strcmp(H.name, 'file.h')) %! hwin = strrep(expected_h_code, sprintf('\n'), sprintf('\r\n')); %! assert (strcmp (H.code, expected_h_code) || strcmp (H.code, hwin)) %! s1 = expected_c_code; %! s2 = strrep(expected_c_code, sprintf('\n'), sprintf('\r\n')); %! assert (strcmp (C.code, s1) || strcmp (C.code, s2)) symbolic-3.1.1/inst/@sym/ceil.m0000644000000000000000000000330314405647405013212 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym ceil (@var{x}) %% Symbolic ceil function. %% %% Example: %% @example %% @group %% syms x %% y = ceil (x) %% @result{} y = (sym) ⌈x⌉ %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = ceil(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('ceiling', x); end %!error ceil (sym(1), 2) %!assert (isequaln (ceil (sym(nan)), sym(nan))) %!shared x, d %! d = 3/2; %! x = sym('3/2'); %!test %! f1 = ceil(x); %! f2 = ceil(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = ceil(A); %! f2 = ceil(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = ceil (d); %! f = ceil (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/char.m0000644000000000000000000000474514405647405013226 0ustar %% Copyright (C) 2014-2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym char (@var{x}) %% Return string representation of a symbolic expression. %% %% Example: %% @example %% @group %% f = [sym(pi)/2 ceil(sym('x')/3); sym('alpha') sym(3)/2] %% @result{} f = (sym 2×2 matrix) %% %% ⎡π ⎡x⎤⎤ %% ⎢─ ⎢─⎥⎥ %% ⎢2 ⎢3⎥⎥ %% ⎢ ⎥ %% ⎣α 3/2⎦ %% %% char(f) %% @result{} Matrix([[pi/2, ceiling(x/3)], [alpha, 3/2]]) %% @end group %% @end example %% %% This command generally gives a human-readable string but it may not be %% sufficient for perfect reconstruction of the symbolic expression. %% For example @code{char(x)} does not display assumptions: %% @example %% @group %% syms x positive %% char (x) %% @result{} x %% @end group %% @end example %% And because of this, passing the output of @code{char} to @code{sym} %% loses information: %% @example %% @group %% x2 = sym (char (x)); %% %% assumptions (x2) %% @result{} ans = %% @{@}(0x0) %% @end group %% @end example %% %% %% If you need a more precise string representation of a symbolic object, %% the underlying SymPy string representation (“srepr”) can be found %% using @code{sympy}: %% @example %% @group %% sympy (x) %% @result{} ans = Symbol('x', positive=True) %% @end group %% @end example %% %% @seealso{@@sym/disp, @@sym/pretty, @@sym/sympy, sym} %% @end defmethod function s = char(x) s = x.flat; end %!test %! % issue #91: expose as string %! a = sym(pi); %! assert (strcmp (char (a), 'pi')) %!shared x %! x = sym('x'); %!assert (strcmp (char (x), 'x')) %!assert (strcmp (char (2*x), '2*x')) %!assert (strcmp (char ([2*x x]), 'Matrix([[2*x, x]])')) %!assert (strcmp (char ([2*x 2; 1 x]), 'Matrix([[2*x, 2], [1, x]])')) symbolic-3.1.1/inst/@sym/charpoly.m0000644000000000000000000000550514405647405014125 0ustar %% Copyright (C) 2016 Lagu %% Copyright (C) 2017-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym charpoly (@var{A}) %% @defmethodx @@sym charpoly (@var{A}, @var{x}) %% Characteristic polynomial of symbolic matrix. %% %% Numerical example: %% @example %% @group %% A = sym([1 2; 3 4]); %% mu = sym('mu'); %% charpoly (A, mu) %% @result{} (sym) %% 2 %% μ - 5⋅μ - 2 %% @end group %% @end example %% %% We can then manipulate the characteristic polynomial, for example: %% @example %% @group %% b(mu) = charpoly (A, mu) %% @result{} b(mu) = (symfun) %% 2 %% μ - 5⋅μ - 2 %% b(1) %% @result{} (sym) -6 %% @end group %% @end example %% We can also confirm that the characteristic polynomial is zero %% at an eigenvalue: %% @example %% @group %% ev = eig(A); %% simplify(b(ev(1))) %% @result{} (sym) 0 %% @end group %% @end example %% %% The matrix can contain symbols: %% @example %% @group %% syms x %% charpoly ([x x;1 x], sym('lambda')) %% @result{} (sym) %% 2 2 %% λ - 2⋅λ⋅x + x - x %% @end group %% @end example %% %% If @var{x} is omitted, the polynomial coefficients are returned: %% @example %% @group %% charpoly (sym([4 1;3 9])) %% @result{} ans = (sym) [1 -13 33] (1×3 matrix) %% @end group %% @end example %% %% @seealso{@@sym/eig, @@sym/jordan} %% @end defmethod function y = charpoly(varargin) if (nargin >= 3) print_usage (); end cmd = {'if len(_ins) == 1:' ' coeff_list = _ins[0].charpoly().all_coeffs()' ' return Matrix([coeff_list])' 'else:' ' return _ins[0].charpoly(_ins[1]).as_expr(),'}; for i = 1:nargin varargin{i} = sym(varargin{i}); end y = pycall_sympy__ (cmd, varargin{:}); end %!error charpoly (sym (1), 1, 2) %!error charpoly (sym ([1 2])) %!test %! syms x %! A = sym([1 2; 3 4]); %! assert (isequal (charpoly(A, x), x^2 - 5*x -2)) %!test %! syms x %! A = sym([1 2; 3 4]); %! B = sym([1 -5 -2]); %! assert (isequal (charpoly(A), B)) %!test %! syms x %! A = sym([x x; x x]); %! B = sym([1 -2*x 0]); %! assert (isequal (charpoly(A), B)) symbolic-3.1.1/inst/@sym/chebyshevT.m0000644000000000000000000000440514405647405014406 0ustar %% Copyright (C) 2016 Abhinav Tripathi %% Copyright (C) 2016, 2018-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym chebyshevT (@var{n}, @var{x}) %% Find the nth symbolic Chebyshev polynomial of the first kind. %% %% If @var{n} is a vector then it returns a vector with Chebyshev polynomials %% of the first kind for each element of @var{n}. %% %% Examples: %% @example %% @group %% syms x %% chebyshevT(1, x) %% @result{} (sym) x %% chebyshevT(2, x) %% @result{} (sym) %% 2 %% 2⋅x - 1 %% syms n %% chebyshevT(n, x) %% @result{} (sym) chebyshevt(n, x) %% @end group %% @end example %% %% The inputs can be vectors, for example: %% @example %% @group %% syms x %% chebyshevT([0 1 2], x) %% @result{} (sym 1×3 matrix) %% ⎡ 2 ⎤ %% ⎣1 x 2⋅x - 1⎦ %% @end group %% @end example %% %% @seealso{@@sym/chebyshevU, @@double/chebyshevT} %% @end defmethod function y = chebyshevT(n, x) if (nargin ~= 2) print_usage (); end y = elementwise_op ('chebyshevt', sym(n), sym(x)); end %!error chebyshevT (sym(1)) %!error chebyshevT (sym(1), 2, 3) %!assert (isequaln (chebyshevT (2, sym(nan)), sym(nan))) %!shared x %! syms x %!assert(isequal(chebyshevT(0, x), sym(1))) %!assert(isequal(chebyshevT(1, x), x)) %!assert(isequal(chebyshevT(2, x), 2*x*x - 1)) %!assert(isequal(chebyshevT([0 1 2], x), [sym(1) x (2*x*x-1)])) %!test %! % round trip %! syms n z %! f = chebyshevT (n, z); %! h = function_handle (f, 'vars', [n z]); %! A = h (1.1, 2.2); %! B = chebyshevT (1.1, 2.2); %! assert (A, B) symbolic-3.1.1/inst/@sym/chebyshevU.m0000644000000000000000000000442514405647405014411 0ustar %% Copyright (C) 2016 Abhinav Tripathi %% Copyright (C) 2016, 2018-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym chebyshevU (@var{n}, @var{x}) %% Find the nth symbolic Chebyshev polynomial of the second kind. %% %% If @var{n} is a vector then it returns a vector with Chebyshev polynomials %% of the second kind for each element of @var{n}. %% %% Examples: %% @example %% @group %% syms x %% chebyshevU(1, x) %% @result{} (sym) 2⋅x %% chebyshevU(2, x) %% @result{} (sym) %% 2 %% 4⋅x - 1 %% syms n %% chebyshevU(n, x) %% @result{} (sym) chebyshevu(n, x) %% @end group %% @end example %% %% The inputs can be vectors, for example: %% @example %% @group %% syms x %% chebyshevU([0 1 2], x) %% @result{} (sym 1×3 matrix) %% ⎡ 2 ⎤ %% ⎣1 2⋅x 4⋅x - 1⎦ %% @end group %% @end example %% %% @seealso{@@sym/chebyshevT, @@double/chebyshevU} %% @end defmethod function y = chebyshevU(n, x) if (nargin ~= 2) print_usage (); end y = elementwise_op ('chebyshevu', sym(n), sym(x)); end %!error chebyshevU (sym(1)) %!error chebyshevU (sym(1), 2, 3) %!assert (isequaln (chebyshevU (2, sym(nan)), sym(nan))) %!shared x %! syms x %!assert(isequal(chebyshevU(0, x), sym(1))) %!assert(isequal(chebyshevU(1, x), 2*x)) %!assert(isequal(chebyshevU(2, x), 4*x*x - 1)) %!assert(isequal(chebyshevU([0 1 2], x), [sym(1) 2*x (4*x*x-1)])) %!test %! % round trip %! syms n z %! f = chebyshevU (n, z); %! h = function_handle (f, 'vars', [n z]); %! A = h (1.1, 2.2); %! B = chebyshevU (1.1, 2.2); %! assert (A, B) symbolic-3.1.1/inst/@sym/children.m0000644000000000000000000001053514405647405014073 0ustar %% Copyright (C) 2014, 2016, 2018-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym children (@var{f}) %% Return "children" (terms, lhs/rhs, etc) of symbolic expression. %% %% For a scalar expression, return a row vector of sym expressions: %% @example %% @group %% syms x y %% f = 2*x*y + sin(x); %% C = children(f) %% @result{} C = (sym) [2⋅x⋅y sin(x)] (1×2 matrix) %% %% children(C(1)) %% @result{} ans = (sym) [2 x y] (1×3 matrix) %% children(C(2)) %% @result{} ans = (sym) x %% @end group %% @end example %% %% A symbol/number/boolean has itself as children: %% @example %% @group %% children(x) %% @result{} ans = (sym) x %% @end group %% @end example %% %% For matrices/vectors, return a cell array where each entry is %% a row vector. The cell array is the same shape as the input. %% @example %% @group %% A = [x*y 2; 3 x] %% @result{} A = (sym 2×2 matrix) %% ⎡x⋅y 2⎤ %% ⎢ ⎥ %% ⎣ 3 x⎦ %% %% C = children (A) %% @result{} C = @{ ... @} %% @end group %% %% @group %% class (C), size (C) %% @result{} ans = cell %% @result{} ans = %% 2 2 %% %% C@{:@} %% @result{} ans = (sym) [x y] (1×2 matrix) %% @result{} ans = (sym) 3 %% @result{} ans = (sym) 2 %% @result{} ans = (sym) x %% @end group %% @end example %% %% %% For sets, @code{children} can be used to extract %% an matrix (array) containing the set elements, @pxref{finiteset}. %% This is useful for accessing the elements of a set. %% %% @seealso{@@sym/lhs, @@sym/rhs, @@sym/eq, @@sym/lt, finiteset} %% @end defmethod function r = children(f) cmd = { 'f, = _ins' 'f = sympify(f)' % mutable -> immutable 'def scalarfcn(a):' ' if not hasattr(a, "args") or len(a.args) == 0:' ' return sympy.Matrix([a])' % children(x) is [x] ' return sympy.Matrix([a.args])' '# note, not for MatrixExpr' 'if isinstance(f, sp.MatrixBase):' ' r = [scalarfcn(a) for a in f.T]' % note transpose 'else:' ' r = scalarfcn(f)' 'return r,' }; r = pycall_sympy__ (cmd, f); if (~isscalar(f)) r = reshape(r, size(f)); end end %!test %! % basics, sum %! syms x y %! f = 2*x + x*x + sin(y); %! assert (isempty (setxor (children(f), [2*x x*x sin(y)]))) %!test %! % basics, product %! syms x y %! f = 2*x*sin(y); %! assert (isempty (setxor (children(f), [2 x sin(y)]))) %!test %! % basics, product and powers %! syms x y %! f = 2*x^2*y^3; %! assert (isempty (setxor (children(f), [2 x^2 y^3]))) %!test %! % eqn, ineq %! syms x y %! lhs = 2*x^2; rhs = y^3 + 7; %! assert (isequal (children(lhs == rhs), [lhs rhs])) %! assert (isequal (children(lhs < rhs), [lhs rhs])) %! assert (isequal (children(lhs >= rhs), [lhs rhs])) %!test %! % matrix %! syms x y %! f = [4 + y 1 + x; 2 + x 3 + x]; %! c = children(f); %! ec = {[4 y], [1 x]; [2 x], [3 x]}; %! assert (isequal (size(c), size(ec))) %! for i=1:length(c) %! assert (isempty (setxor (c{i}, ec{i}))) %! end %!test %! % matrix, sum/prod %! syms x y %! f = [x + y; x*sin(y); sin(x)]; %! ec = {[x y]; [x sin(y)]; [x]}; %! c = children(f); %! assert (isequal (size(c), size(ec))) %! for i=1:length(c) %! assert (isempty (setxor (c{i}, ec{i}))) %! end %!test %! % scalar symbol %! syms x %! assert (isequal (children(x), x)) %!test %! % scalar number %! x = sym(6); %! assert (isequal (children(x), x)) %!test %! % symbolic size matrix %! syms n m integer %! A = sym('a', [n m]); %! C = children (A); %! assert (isequal (C(2), n)) %! assert (isequal (C(3), m)) %!xtest %! % symbolic size matrix, fails on newer SymPy Issue #1089 %! syms n m integer %! A = sym('a', [n m]); %! assert (isequal (children (A), [sym('a') n m])) symbolic-3.1.1/inst/@sym/chol.m0000644000000000000000000000416514405647405013232 0ustar %% Copyright (C) 2016 Lagu %% Copyright (C) 2017-2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {@var{L} =} chol (@var{A}) %% Cholesky factorization of symbolic symmetric matrix. %% %% Returns a lower-triangular matrix @var{L}, such that @code{L*L'} %% is matrix @var{A}. The matrix @var{A} must be symmetric %% positive-definite. Example: %% @example %% @group %% A = sym([1 2 4; 2 13 23; 4 23 43]) %% @result{} A = (sym 3×3 matrix) %% %% ⎡1 2 4 ⎤ %% ⎢ ⎥ %% ⎢2 13 23⎥ %% ⎢ ⎥ %% ⎣4 23 43⎦ %% %% L = chol(A) %% @result{} L = (sym 3×3 matrix) %% %% ⎡1 0 0 ⎤ %% ⎢ ⎥ %% ⎢2 3 0 ⎥ %% ⎢ ⎥ %% ⎣4 5 √2⎦ %% %% L*L' %% @result{} (sym 3×3 matrix) %% %% ⎡1 2 4 ⎤ %% ⎢ ⎥ %% ⎢2 13 23⎥ %% ⎢ ⎥ %% ⎣4 23 43⎦ %% @end group %% @end example %% %% @seealso{chol, @@sym/qr, @@sym/lu} %% @end deftypemethod function y = chol(x) if (nargin == 2) error('Operation not supported yet.'); elseif (nargin > 2) print_usage (); end y = pycall_sympy__ ('return _ins[0].cholesky(),', x); end %!error chol (sym ([1 2; 3 4])); %!error chol (sym ([1 2; 3 4; 5 6])); %!test %! A = chol(hilb(sym(2))); %! B = [[1 0]; sym(1)/2 sqrt(sym(3))/6]; %! assert( isequal( A, B )) symbolic-3.1.1/inst/@sym/coeffs.m0000644000000000000000000001713014405647405013546 0ustar %% Copyright (C) 2014-2017, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {@var{c} =} coeffs (@var{p}, @var{x}) %% @deftypemethodx @@sym {@var{c} =} coeffs (@var{p}) %% @deftypemethodx @@sym {@var{c} =} coeffs (@dots{}, 'all') %% @deftypemethodx @@sym {[@var{c}, @var{t}] =} coeffs (@var{p}, @var{x}) %% @deftypemethodx @@sym {[@var{c}, @var{t}] =} coeffs (@var{p}) %% @deftypemethodx @@sym {[@var{c}, @var{t}] =} coeffs (@dots{}, 'all') %% Return non-zero (or all) coefficients of symbolic polynomial. %% %% @var{c} contains the coefficients and @var{t} the corresponding %% terms. %% %% Example: %% @example %% @group %% syms x %% [c, t] = coeffs (x^6 + 3*x - 4) %% @result{} c = (sym) [1 3 -4] (1×3 matrix) %% @result{} t = (sym 1×3 matrix) %% ⎡ 6 ⎤ %% ⎣x x 1⎦ %% @end group %% @end example %% %% The polynomial can be multivariate: %% @example %% @group %% syms x y %% [c, t] = coeffs (x^2 + y*x) %% @result{} c = (sym) [1 1] (1×2 matrix) %% @result{} t = (sym 1×2 matrix) %% ⎡ 2 ⎤ %% ⎣x x⋅y⎦ %% @end group %% %% @group %% [c, t] = coeffs (x^2 + y*x, [x y]) % same %% @result{} c = (sym) [1 1] (1×2 matrix) %% @result{} t = (sym 1×2 matrix) %% ⎡ 2 ⎤ %% ⎣x x⋅y⎦ %% %% [c, t] = coeffs (x^2 + y*x, @{x y@}) % same %% @result{} c = (sym) [1 1] (1×2 matrix) %% @result{} t = (sym 1×2 matrix) %% ⎡ 2 ⎤ %% ⎣x x⋅y⎦ %% @end group %% @end example %% %% You can use the second argument to specify a vector or list of %% variables: %% @example %% @group %% [c, t] = coeffs (x^2 + y*x, x) %% @result{} c = (sym) [1 y] (1×2 matrix) %% @result{} t = (sym 1×2 matrix) %% ⎡ 2 ⎤ %% ⎣x x⎦ %% @end group %% @end example %% %% Omitting the second output is not recommended, especially for non-interactive %% code, because it gives only the non-zero coefficients, and additionally %% the output is in the ``wrong order'' compared to other polynomial-related %% commands: %% @example %% @group %% c = coeffs (x^6 + 3*x - 4) %% @result{} c = (sym) [-4 3 1] (1×3 matrix) %% @end group %% @end example %% @strong{Warning:} Again, note the order is reversed from the two-output %% case; this is for compatibility with Matlab's Symbolic Math Toolbox. %% %% If the optional input keyword @qcode{'all'} is passed, the zero %% coefficients are returned as well, and in the familiar order. %% @example %% @group %% c = coeffs (x^6 + 3*x - 4, 'all') %% @result{} c = (sym) [1 0 0 0 0 3 -4] (1×7 matrix) %% @end group %% @end example %% @strong{Note:} The @qcode{'all'} feature does not yet work with %% multivariate polynomials (https://github.com/cbm755/octsympy/issues/720). %% %% @seealso{@@sym/sym2poly} %% @end deftypemethod function [c, t] = coeffs(p, x, all) if (nargin == 1) x = []; all = false; elseif (nargin == 2) if (ischar (x)) assert (strcmpi (x, 'all'), ... 'coeffs: invalid 2nd input: if string, should be "all"') x = []; all = true; else all = false; end elseif (nargin == 3) assert (strcmpi (all, 'all'), ... 'coeffs: invalid 3rd input: should be string "all"') all = true; elseif (nargin > 3) print_usage (); end assert (isscalar (p), 'coeffs: works for scalar input only') p = sym(p); if (isempty (x)) x = symvar (p); if (isempty (x)) x = sym('x'); % any symbol end end x = sym(x); cmd = { '(f, xx, all) = _ins' 'if not xx.is_Matrix:' ' xx = sp.Matrix([xx])' 'xx = list(xx)' 'p = Poly.from_expr(f, *xx)' 'if all:' ' terms = p.all_terms()' 'else:' ' terms = p.terms()' 'cc = [q[1] for q in terms]' 'tt = [1]*len(terms)' 'for i, x in enumerate(p.gens):' ' tt = [t*x**q[0][i] for (t, q) in zip(tt, terms)]' 'return (Matrix([cc]), Matrix([tt]))' }; [c, t] = pycall_sympy__ (cmd, p, x, all); %% SMT compat: % reverse the order if t is not output. if (nargout <= 1) && (all == false) c = fliplr(c); end % if nargout == 1, its simplier to use 'p.coeffs()' end %!error coeffs (sym(1), 2, 3, 4) %!error coeffs (sym(1), 2, 'al') %!error coeffs (sym(1), 'al') %!test %! % simple %! syms x %! [c, t] = coeffs(6*x*x + 27); %! assert (isequal (c, [6 27])) %! assert (isequal (t, [x*x 1])) %!test %! % specify a variable %! syms x %! [c, t] = coeffs(6*x*x + 27, x); %! assert (isequal (c, [6 27])) %! assert (isequal (t, [x*x 1])) %!test %! % specify another variable %! syms x y %! [c, t] = coeffs(6*x + 27, y); %! assert (isequal (c, 6*x + 27)) %! assert (isequal (t, 1)) %!test %! % weird SMT order %! syms x %! a1 = [27 6]; %! a2 = [6 27]; %! c = coeffs(6*x*x + 27); %! assert (isequal (c, a1)) %! coeffs(6*x*x + 27); %! assert (isequal (ans, a1)) %! [c, t] = coeffs(6*x*x + 27); %! assert (isequal (c, a2)) %!test %! % no weird order with "all" %! syms x %! c = coeffs(6*x*x + 27, 'all'); %! assert (isequal (c, [6 0 27])) %!test %! % "all" %! syms x %! [c, t] = coeffs(6*x*x + 27, 'all'); %! assert (isequal (c, [6 0 27])) %! assert (isequal (t, [x^2 x 1])) %!test %! % "All" %! syms x %! [c, t] = coeffs(6*x, 'All'); %! assert (isequal (c, [6 0])) %! assert (isequal (t, [x 1])) %!test %! % multivariable array %! syms x y %! [c, t] = coeffs(6*x*x + 27*y*x + 36, [x y]); %! a = [6 27 36]; %! s = [x^2 x*y 1]; %! assert (isequal (c, a)) %! assert (isequal (t, s)) %! % with list %! [c, t] = coeffs(6*x*x + 27*y*x + 36, {x y}); %! assert (isequal (c, a)) %! assert (isequal (t, s)) %!test %! % other symbols treated as part of coeffs %! syms x y %! [c, t] = coeffs(6*x*x + 27*y*x + 36, x); %! a = [6 27*y 36]; %! s = [x^2 x 1]; %! assert (isequal (c, a)) %! assert (isequal (t, s)) %!error %! % TODO: multivariate all not working (https://github.com/cbm755/octsympy/issues/720) %! syms x y %! [c, t] = coeffs(6*x^2 + 7*y + 19, [x y], 'all'); %!test %! % empty same as not specifying; maybe not SMT compatible: %! % https://github.com/cbm755/octsympy/pull/708#discussion_r94292831 %! syms x y %! [c, t] = coeffs(6*x*x + 27*y*x + 36, {}); %! a = [6 27 36]; %! assert (isequal (c, a)) %! [c, t] = coeffs(6*x*x + 27*y*x + 36); %! assert (isequal (c, a)) %!test %! % no input defaults to all symbols (not symvar to get x) %! syms x y %! [c, t] = coeffs(6*x*x + 27*y*x + 36); %! assert (isequal (c, [6 27 36])) %!test %! % non sym input %! syms x %! assert (isequal (coeffs(6, x), sym(6))) %!test %! % constant input without x %! assert (isequal (coeffs(sym(6)), sym(6))) %!test %! % constant input without x %! assert (isequal (coeffs (sym(6), {}), sym(6))) %! % irrational coefficients %! syms x %! f = x^2 + sqrt(sym(2))*x; %! [c1, t1] = coeffs (f); %! [c2, t2] = coeffs (f, x); %! assert (isequal (c1, c2)) %! assert (isequal (t1, t2)) symbolic-3.1.1/inst/@sym/colon.m0000644000000000000000000000543314405647405013416 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym colon {(@var{a}, @var{b})} %% @defopx Method @@sym colon {(@var{a}, @var{step}, @var{b})} %% @defopx Operator @@sym {@var{a}:@var{b}} {} %% @defopx Operator @@sym {@var{a}:@var{step}:@var{b}} {} %% Generate a range of symbolic expressions. %% %% Examples: %% @example %% @group %% sym(5):10 %% @result{} ans = (sym) [5 6 7 8 9 10] (1×6 matrix) %% 0:sym(pi):5*sym(pi) %% @result{} ans = (sym) [0 π 2⋅π 3⋅π 4⋅π 5⋅π] (1×6 matrix) %% syms x %% x:2:(x+6) %% @result{} ans = (sym) [x x + 2 x + 4 x + 6] (1×4 matrix) %% @end group %% @end example %% %% The end point @var{b} might not be included: %% @example %% @group %% 0:sym(pi):10 %% @result{} ans = (sym) [0 π 2⋅π 3⋅π] (1×4 matrix) %% @end group %% @end example %% %% The @var{step} can be negative: %% @example %% @group %% sym(6):-3:-3 %% @result{} ans = (sym) [6 3 0 -3] (1×4 matrix) %% @end group %% @end example %% %% @seealso{@@sym/linspace} %% @end defop function y = colon(a, step, b) if (nargin == 2) b = step; step = sym(1); end cmd = { '(a, b, step) = _ins' 'B = floor((b-a)/step)' 'y = Matrix([range(0, B+1)])' 'y = y*step + Matrix([[a]*y.cols])' 'return y,' }; y = pycall_sympy__ (cmd, sym(a), sym(b), sym(step)); end %!test %! a = sym(1):5; %! b = sym(1:5); %! assert(isequal(a,b)); %! a = 1:sym(5); %! b = sym(1:5); %! assert(isequal(a,b)); %!test %! a = 2:sym(2):8; %! b = sym(2:2:8); %! assert(isequal(a,b)); %!test %! a = sym(10):-2:-4; %! b = sym(10:-2:-4); %! assert(isequal(a,b)); %!test %! % symbolic intervals %! p = sym(pi); %! L = 0:p/4:p; %! assert(isa(L,'sym')); %! assert(isequal(L, [0 p/4 p/2 3*p/4 p])); %!test %! % mixed symbolic and double intervals %! p = sym(pi); %! s = warning ('off', 'OctSymPy:sym:rationalapprox'); %! L = 0.1:(sym(pi)/3):2.3; %! warning(s) %! assert(isa(L,'sym')); %! t = sym(1)/10; %! assert(isequal(L, [t p/3+t 2*p/3+t])); %!error syms x; a = 0:x; %!error syms x; a = 1:x; symbolic-3.1.1/inst/@sym/columns.m0000644000000000000000000000240614405647405013761 0ustar %% Copyright (C) 2015, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym columns (@var{x}) %% Return the number of columns in a symbolic array. %% %% Example: %% @example %% @group %% A = [1 2 sym(pi); 4 5 2*sym(pi)]; %% m = columns (A) %% @result{} m = 3 %% @end group %% @end example %% %% @seealso{@@sym/rows, @@sym/size, @@sym/length, @@sym/numel} %% @end defmethod function n = columns(x) n = size(x, 2); end %!test %! a = sym([1 2 3]); %! assert (columns(a) == 3) %!test %! a = sym([1; 2]); %! assert (columns(a) == 1) symbolic-3.1.1/inst/@sym/cond.m0000644000000000000000000000311414405647405013221 0ustar %% Copyright (C) 2014, 2016, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym cond (@var{A}) %% Symbolic condition number of a symbolic matrix. %% %% Examples: %% @example %% @group %% A = sym([1 2; 3 0]); %% cond(A)^2 %% @result{} (sym) %% %% √13 + 7 %% ─────── %% 7 - √13 %% @end group %% @end example %% %% @seealso{@@sym/svd} %% @end defmethod function k = cond(A) cmd = { '(A,) = _ins' ... 'if not A.is_Matrix:' ... ' A = sp.Matrix([A])' ... 'return A.condition_number(),' }; k = pycall_sympy__ (cmd, sym(A)); end %!test %! A = [1 2; 3 4]; %! B = sym(A); %! k1 = cond(A); %! k2 = cond(B); %! k3 = double(k2); %! assert (k1 - k3 <= 100*eps) %!test %! % matrix with symbols %! syms x positive %! A = [x 0; sym(0) 2*x]; %! k1 = cond(A); %! assert (isequal (k1, sym(2))) symbolic-3.1.1/inst/@sym/conj.m0000644000000000000000000000514114405647405013231 0ustar %% Copyright (C) 2014, 2016, 2018 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym conj (@var{z}) %% Symbolic conjugate function. %% %% Examples: %% @example %% @group %% syms z %% conj(z) %% @result{} ans = (sym) %% _ %% z %% %% @end group %% @group %% syms x real %% conj(x) %% @result{} ans = (sym) x %% %% conj(sym(pi) + 6i) %% @result{} ans = (sym) π - 6⋅ⅈ %% @end group %% @end example %% %% Unlike @ref{@@sym/ctranspose}, this command does not transpose %% a matrix: %% @example %% @group %% A = [1 z x; sym(4) 5 6+7i] %% @result{} A = (sym 2×3 matrix) %% ⎡1 z x ⎤ %% ⎢ ⎥ %% ⎣4 5 6 + 7⋅ⅈ⎦ %% conj(A) %% @result{} ans = (sym 2×3 matrix) %% ⎡ _ ⎤ %% ⎢1 z x ⎥ %% ⎢ ⎥ %% ⎣4 5 6 - 7⋅ⅈ⎦ %% @end group %% @end example %% %% @seealso{@@sym/ctranspose, @@sym/real, @@sym/imag} %% @end defmethod function z = conj(x) if (nargin ~= 1) print_usage (); end % can just use .conjugate on matrix but avoids S.true err sf = { 'def _op(x):' ' if x in (S.true, S.false):' ' return x' ' return x.conjugate()' }; z = elementwise_op (sf, x); end %!test %! a = sym(6); %! b = sym(5i); %! assert (isequal (conj(a), a)) %! assert (isequal (conj(b), -b)) %! assert (isequal (conj(a+b), a-b)) %!test %! syms x %! assert (isequal (conj(conj(x)), x)) %!test %! syms x real %! assert (isequal (conj(x), x)) %!test %! % array %! syms x %! A = [x 6+1i; sym(1) x+2i]; %! B = [conj(x) 6-1i; sym(1) conj(x)-2i]; %! assert (isequal (conj(A), B)) %!test %! % true/false %! t = sym(true); %! f = sym(false); %! assert (isequal ( conj(t), t)) %! assert (isequal ( conj(f), f)) %!test %! % round trip %! syms x %! d = 3 - 5i; %! f = conj (x); %! A = conj (d); %! h = function_handle (f); %! B = h (d); %! assert (A, B) symbolic-3.1.1/inst/@sym/cos.m0000644000000000000000000000325614405647405013071 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym cos (@var{x}) %% Symbolic cos function. %% %% Example: %% @example %% @group %% syms x %% y = cos (x) %% @result{} y = (sym) cos(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = cos(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('cos', x); end %!error cos (sym(1), 2) %!assert (isequaln (cos (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = cos(x); %! f2 = cos(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = cos(A); %! f2 = cos(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = cos (d); %! f = cos (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/cosd.m0000644000000000000000000000306414405647405013232 0ustar %% Copyright (C) 2014-2016, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym cosd (@var{x}) %% Symbolic cos function with input in degrees. %% %% Example: %% @example %% @group %% cosd (sym (60)) %% @result{} (sym) 1/2 %% %% syms x %% y = cosd (x) %% @result{} y = (sym) %% ⎛π⋅x⎞ %% cos⎜───⎟ %% ⎝180⎠ %% @end group %% @end example %% %% @seealso{@@sym/acosd, @@sym/cos} %% @end defmethod function y = cosd(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('lambda a: cos(rad(a))', x); end %!error cosd (sym(1), 2) %!assert (isequaln (cosd (sym(nan)), sym(nan))) %!test %! f1 = cosd (sym(1)); %! f2 = cosd (1); %! assert (double (f1), f2, -eps) %!test %! D = [10 30; 110 -45]; %! A = sym(D); %! f1 = cosd (A); %! f2 = cosd (D); %! assert (double (f1), f2, -4*eps) symbolic-3.1.1/inst/@sym/cosh.m0000644000000000000000000000327414405647405013241 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym cosh (@var{x}) %% Symbolic cosh function. %% %% Example: %% @example %% @group %% syms x %% y = cosh (x) %% @result{} y = (sym) cosh(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = cosh(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('cosh', x); end %!error cosh (sym(1), 2) %!assert (isequaln (cosh (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = cosh(x); %! f2 = cosh(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = cosh(A); %! f2 = cosh(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = cosh (d); %! f = cosh (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/coshint.m0000644000000000000000000000343314405647405013751 0ustar %% Copyright (C) 2016-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym coshint (@var{x}) %% Symbolic coshint function. %% %% Example: %% @example %% @group %% syms x %% y = coshint (x) %% @result{} y = (sym) Chi(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = coshint(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('Chi', x); end %!error coshint (sym(1), 2) %!xtest %! assert (isequaln (coshint (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = coshint(x); %! f2 = 0.8378669409802082408947; %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = coshint(A); %! f2 = 0.8378669409802082408947; %! f2 = [f2 f2; f2 f2]; %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = coshint (d); %! f = coshint (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/cosint.m0000644000000000000000000000341714405647405013603 0ustar %% Copyright (C) 2016-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym cosint (@var{x}) %% Symbolic cosint function. %% %% Example: %% @example %% @group %% syms x %% y = cosint (x) %% @result{} y = (sym) Ci(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = cosint(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('Ci', x); end %!error cosint (sym(1), 2) %!xtest %! assert (isequaln (cosint (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = cosint(x); %! f2 = 0.3374039229009681346626; %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = cosint(A); %! f2 = 0.3374039229009681346626; %! f2 = [f2 f2; f2 f2]; %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = cosint (d); %! f = cosint (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/cot.m0000644000000000000000000000325614405647405013072 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym cot (@var{x}) %% Symbolic cot function. %% %% Example: %% @example %% @group %% syms x %% y = cot (x) %% @result{} y = (sym) cot(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = cot(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('cot', x); end %!error cot (sym(1), 2) %!assert (isequaln (cot (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = cot(x); %! f2 = cot(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = cot(A); %! f2 = cot(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = cot (d); %! f = cot (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/coth.m0000644000000000000000000000327414405647405013242 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym coth (@var{x}) %% Symbolic coth function. %% %% Example: %% @example %% @group %% syms x %% y = coth (x) %% @result{} y = (sym) coth(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = coth(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('coth', x); end %!error coth (sym(1), 2) %!assert (isequaln (coth (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = coth(x); %! f2 = coth(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = coth(A); %! f2 = coth(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = coth (d); %! f = coth (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/cross.m0000644000000000000000000000356714405647405013443 0ustar %% Copyright (C) 2015, 2016, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym cross (@var{a}, @var{b}) %% Symbolic cross product. %% %% Examples: %% @example %% @group %% a = [sym('a1'); sym('a2'); sym('a3')]; %% b = [sym('b1'); sym('b2'); sym('b3')]; %% cross(a, b) %% @result{} (sym 3×1 matrix) %% ⎡a₂⋅b₃ - a₃⋅b₂ ⎤ %% ⎢ ⎥ %% ⎢-a₁⋅b₃ + a₃⋅b₁⎥ %% ⎢ ⎥ %% ⎣a₁⋅b₂ - a₂⋅b₁ ⎦ %% %% cross(a, a) %% @result{} (sym 3×1 matrix) %% ⎡0⎤ %% ⎢ ⎥ %% ⎢0⎥ %% ⎢ ⎥ %% ⎣0⎦ %% @end group %% @end example %% %% @seealso{@@sym/dot} %% @end defmethod function c = cross(a, b) if (nargin ~= 2) print_usage (); end cmd = { 'a, b = _ins' 'return a.cross(b),' }; c = pycall_sympy__ (cmd, sym(a), sym(b)); end %!error cross (sym(1), 2, 3) %!test %! a = sym([1; 0; 0]); %! b = sym([0; 1; 0]); %! c = cross(a, b); %! assert (isequal (c, sym([0; 0; 1]))) %!test %! syms x %! a = sym([x; 0; 0]); %! b = sym([0; 1; 0]); %! c = cross(a, b); %! assert (isequal (c, sym([0; 0; x]))) symbolic-3.1.1/inst/@sym/csc.m0000644000000000000000000000325614405647405013055 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym csc (@var{x}) %% Symbolic csc function. %% %% Example: %% @example %% @group %% syms x %% y = csc (x) %% @result{} y = (sym) csc(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = csc(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('csc', x); end %!error csc (sym(1), 2) %!assert (isequaln (csc (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = csc(x); %! f2 = csc(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = csc(A); %! f2 = csc(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = csc (d); %! f = csc (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/csch.m0000644000000000000000000000327414405647405013225 0ustar %% Copyright (C) 2016-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym csch (@var{x}) %% Symbolic csch function. %% %% Example: %% @example %% @group %% syms x %% y = csch (x) %% @result{} y = (sym) csch(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = csch(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('csch', x); end %!error csch (sym(1), 2) %!assert (isequaln (csch (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = csch(x); %! f2 = csch(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = csch(A); %! f2 = csch(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = csch (d); %! f = csch (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/ctranspose.m0000644000000000000000000000610014405647405014455 0ustar %% Copyright (C) 2014-2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym ctranspose {(@var{A})} %% @defopx Operator @@sym {@var{A}'} {} %% Conjugate (Hermitian) transpose of a symbolic array. %% %% Example: %% @example %% @group %% syms z %% syms x real %% A = [1 x z; sym(4) 5 6+7i] %% @result{} A = (sym 2×3 matrix) %% ⎡1 x z ⎤ %% ⎢ ⎥ %% ⎣4 5 6 + 7⋅ⅈ⎦ %% ctranspose(A) %% @result{} (sym 3×2 matrix) %% ⎡1 4 ⎤ %% ⎢ ⎥ %% ⎢x 5 ⎥ %% ⎢ ⎥ %% ⎢_ ⎥ %% ⎣z 6 - 7⋅ⅈ⎦ %% @end group %% @end example %% %% This can be abbreviated to: %% @example %% @group %% A' %% @result{} (sym 3×2 matrix) %% ⎡1 4 ⎤ %% ⎢ ⎥ %% ⎢x 5 ⎥ %% ⎢ ⎥ %% ⎢_ ⎥ %% ⎣z 6 - 7⋅ⅈ⎦ %% @end group %% @end example %% %% @seealso{@@sym/transpose, @@sym/conj} %% @end defop function z = ctranspose(x) if (nargin ~= 1) print_usage (); end cmd = { 'x = _ins[0]' '# special case for Boolean terms' 'if x.has(S.true) or x.has(S.false):' ' def sf(x):' ' if x in (S.true, S.false):' ' return x' ' return x.conjugate()' ' if x.is_Matrix:' ' z = x.T' ' return z.applyfunc(lambda a: sf(a))' ' else:' ' return sf(x)' 'if x.is_Matrix:' ' return x.H' 'else:' ' return x.conjugate()' }; z = pycall_sympy__ (cmd, x); end %!test %! x = sym(1); %! assert (isequal (x', x)) %!assert (isempty (sym([])')) %!test %! % conjugate does nothing to real x %! syms x real %! assert (isequal (x', x)) %!test %! % complex %! syms x %! assert (isequal (x', conj(x))) %!test %! % complex array %! syms x %! A = [x 2*x]; %! B = [conj(x); 2*conj(x)]; %! assert(isequal(A', B)) %!test %! A = [1 2; 3 4]; %! assert(isequal( sym(A)' , sym(A') )) %!test %! A = [1 2] + 1i; %! assert(isequal( sym(A)' , sym(A') )) %!test %! % true/false %! t = sym(true); %! f = sym(false); %! assert (isequal ( t', t)) %! assert (isequal ( f', f)) %!test %! % more true/false %! syms x %! A = [x true 1i]; %! B = [conj(x); true; -sym(1i)]; %! assert (isequal ( A', B)) symbolic-3.1.1/inst/@sym/cumprod.m0000644000000000000000000001065514405647405013757 0ustar %% Copyright (C) 2020 Tasos Papastylianou %% Copyright (C) 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym cumprod (@var{x}) %% @defmethodx @@sym cumprod (@var{x}, @var{dim}) %% Cumulative product over the rows or columns of a symbolic array. %% %% If @var{dim} is omitted, it defaults to the first non-singleton dimension. %% For example: %% %% Examples: %% @example %% @group %% t = sym ('t'); %% Pi = sym ('pi'); %% T = [t; t + Pi / 2; t + Pi; t + 3 * Pi / 2; t + 2 * Pi]; %% C = cos (T); %% cumprod (C) %% @result{} (sym 5×1 matrix) %% ⎡ cos(t) ⎤ %% ⎢ ⎥ %% ⎢-sin(t)⋅cos(t) ⎥ %% ⎢ ⎥ %% ⎢ 2 ⎥ %% ⎢sin(t)⋅cos (t) ⎥ %% ⎢ ⎥ %% ⎢ 2 2 ⎥ %% ⎢sin (t)⋅cos (t)⎥ %% ⎢ ⎥ %% ⎢ 2 3 ⎥ %% ⎣sin (t)⋅cos (t)⎦ %% @end group %% @end example %% %% Specify dimension along which to compute the product: %% @example %% @group %% X = repmat (sym ('x'), 2, 3 ); %% %% cumprod (X, 1) %% @result{} (sym 2×3 matrix) %% ⎡x x x ⎤ %% ⎢ ⎥ %% ⎢ 2 2 2⎥ %% ⎣x x x ⎦ %% %% cumprod (X, 2) %% @result{} (sym 2×3 matrix) %% ⎡ 2 3⎤ %% ⎢x x x ⎥ %% ⎢ ⎥ %% ⎢ 2 3⎥ %% ⎣x x x ⎦ %% @end group %% @end example %% %% @seealso{@@sym/prod, @@sym/cumsum} %% @end defmethod function y = cumprod (x, dim) %% Check correctness of input arguments if (nargin > 2) print_usage (); endif if (nargin == 2) assert ( ~ isempty (dim), sprintf ('@sym/cumprod: dimension argument is an empty object') ); assert ( isnumeric (dim), sprintf ('@sym/cumprod: invalid dimension argument type: %s', class (dim)) ); dim = floor (dim(1)); % behaviour compatible with builtin cumprod assert ( dim > 0, sprintf ('@sym/cumprod: invalid dimension argument: %d', dim) ); else % (nargin == 1) %% Find first non-singleton dimension. if (all (size (x) == [1, 1])) y = x; % For efficiency, but also if we didn't do this explicitly, the return % 'find' operation below would return the invalid result '[]' else %% Note: This is a general formulation supporting multidimensional inputs, %% even though at the time of writing symbolic arrays are restricted to %% having no more than two dimensions (e.g. see @sym/cat) dim = find (size (x) > 1, 1); endif endif ydims = size (x); dimsize = ydims(dim); y = sym (zeros (ydims)); xidx = substruct ('()', repmat ({':'}, 1, ndims (x))); yidx = substruct ('()', repmat ({':'}, 1, ndims (y))); for i = 1 : dimsize xidx.subs{dim} = 1 : i; yidx.subs{dim} = i; y = subsasgn (y, yidx, prod (subsref (x, xidx), dim)); endfor endfunction %!shared x, y %! x = sym ('x'); %! y = sym ('y'); %!error cumprod (x, 1, 2) %!assert (isequal (cumprod ([-x; -2*x; -3*x]), [-x; 2*x^2; -6*x^3])) %!assert (isequal (expand (cumprod ([x + i, x - i])), [x + i, x^2 + 1])) %!assert (isequal (cumprod ([1, x; y, 2], 1), [1, x; y, 2*x] )) %!assert (isequal (cumprod ([1, x; y, 2], 2), [1, x; y, 2*y] )) %!test cumprod ([x, x], [2, 1]); # ensure behaves like builtin cumprod %!test cumprod ([x, x], [1, -2]); # ensure behaves like builtin cumprod %!error cumprod (x, []) %!error cumprod (x, {1}) %!error cumprod (x, struct('a', 1)) %!error cumprod (x, x) %!error cumprod (x, 0) %!error cumprod (x, -1) symbolic-3.1.1/inst/@sym/cumsum.m0000644000000000000000000001042114405647405013606 0ustar %% Copyright (C) 2020 Tasos Papastylianou %% Copyright (C) 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym cumsum (@var{x}) %% @defmethodx @@sym cumsum (@var{x}, @var{dim}) %% Cumulative sum over the rows or columns of a symbolic array. %% %% If @var{dim} is omitted, it defaults to the first non-singleton dimension. %% For example: %% %% Examples: %% @example %% @group %% t = sym ('t'); %% Pi = sym ('pi'); %% T = [t; t + Pi / 2; t + Pi; t + 3 * Pi / 2; t + 2 * Pi]; %% C = cos (T); %% cumsum (C) %% @result{} (sym 5×1 matrix) %% ⎡ cos(t) ⎤ %% ⎢ ⎥ %% ⎢-sin(t) + cos(t)⎥ %% ⎢ ⎥ %% ⎢ -sin(t) ⎥ %% ⎢ ⎥ %% ⎢ 0 ⎥ %% ⎢ ⎥ %% ⎣ cos(t) ⎦ %% @end group %% @end example %% %% Specify dimension along which to sum: %% @example %% @group %% X = repmat (sym ('x'), 2, 3); %% %% cumsum (X, 1) %% @result{} (sym 2×3 matrix) %% ⎡ x x x ⎤ %% ⎢ ⎥ %% ⎣2⋅x 2⋅x 2⋅x⎦ %% %% cumsum (X, 2) %% @result{} (sym 2×3 matrix) %% ⎡x 2⋅x 3⋅x⎤ %% ⎢ ⎥ %% ⎣x 2⋅x 3⋅x⎦ %% @end group %% @end example %% %% @seealso{@@sym/sum, @@sym/cumprod} %% @end defmethod function y = cumsum (x, dim) %% Check correctness of input arguments if (nargin > 2) print_usage (); endif if (nargin == 2) assert ( ~ isempty (dim), sprintf ('@sym/cumsum: dimension argument is an empty object') ); assert ( isnumeric (dim), sprintf ('@sym/cumsum: invalid dimension argument type: %s', class (dim)) ); dim = floor (dim(1)); % behaviour compatible with builtin cumsum assert ( dim > 0, sprintf ('@sym/cumsum: invalid dimension argument: %d', dim) ); else % (nargin == 1) %% Find first non-singleton dimension. if (all (size (x) == [1, 1])) y = x; % For efficiency, but also if we didn't do this explicitly, the return % 'find' operation below would return the invalid result '[]' else %% Note: This is a general formulation supporting multidimensional inputs, %% even though at the time of writing symbolic arrays are restricted to %% having no more than two dimensions (e.g. see @sym/cat) dim = find (size (x) > 1, 1); endif endif ydims = size (x); dimsize = ydims(dim); y = sym (zeros (ydims)); xidx = substruct ('()', repmat ({':'}, 1, ndims (x))); yidx = substruct ('()', repmat ({':'}, 1, ndims (y))); for i = 1 : dimsize xidx.subs{dim} = 1 : i; yidx.subs{dim} = i; y = subsasgn (y, yidx, sum (subsref (x, xidx), dim)); endfor endfunction %!shared x, y %! x = sym ('x'); %! y = sym ('y'); %!error cumsum (x, 1, 2) %!assert (isequal (cumsum ([-x; -2*x; -3*x]), [-x; -3*x; -6*x])) %!assert (isequal (cumsum ([x + 2i*y, 2*x + i*y]), [x + 2i*y, 3*x + 3i*y])) %!assert (isequal (cumsum ([x, 2*x; 3*x, 4*x], 1), [1*x, 2*x; 4*x, 6*x] )) %!assert (isequal (cumsum ([x, 2*x; 3*x, 4*x], 2), [1*x, 3*x; 3*x, 7*x] )) %!test cumsum ([x, x], [2, 1]); # ensure behaves like builtin cumsum %!test cumsum ([x, x], [1, -2]); # ensure behaves like builtin cumsum %!error cumsum (x, []) %!error cumsum (x, {1}) %!error cumsum (x, struct('a', 1)) %!error cumsum (x, x) %!error cumsum (x, 0) %!error cumsum (x, -1) symbolic-3.1.1/inst/@sym/curl.m0000644000000000000000000001137614405647405013254 0ustar %% Copyright (C) 2014, 2016, 2019, 2021-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym curl (@var{F}) %% @defmethodx @@sym curl (@var{F}, @var{x}) %% Symbolic curl of symbolic expression. %% %% Consider a vector expression @var{F}: %% @example %% @group %% syms f(x,y,z) g(x,y,z) h(x,y,z) %% F = [f; g; h] %% @result{} F = (sym 3×1 matrix) %% ⎡f(x, y, z)⎤ %% ⎢ ⎥ %% ⎢g(x, y, z)⎥ %% ⎢ ⎥ %% ⎣h(x, y, z)⎦ %% @end group %% @end example %% The curl of @var{F} is the vector expression: %% @example %% @group %% curl(F) %% @result{} (sym 3×1 matrix) %% ⎡ ∂ ∂ ⎤ %% ⎢- ──(g(x, y, z)) + ──(h(x, y, z))⎥ %% ⎢ ∂z ∂y ⎥ %% ⎢ ⎥ %% ⎢ ∂ ∂ ⎥ %% ⎢ ──(f(x, y, z)) - ──(h(x, y, z)) ⎥ %% ⎢ ∂z ∂x ⎥ %% ⎢ ⎥ %% ⎢ ∂ ∂ ⎥ %% ⎢- ──(f(x, y, z)) + ──(g(x, y, z))⎥ %% ⎣ ∂y ∂x ⎦ %% @end group %% @end example %% %% @var{F} and @var{x} should be vectors of length three. %% If omitted, @var{x} is determined using @code{symvar}. %% %% Example: %% @example %% @group %% syms x y z %% F = [y -x 0]; %% curl(F, @{x y z@}) %% @result{} (sym 3×1 matrix) %% ⎡0 ⎤ %% ⎢ ⎥ %% ⎢0 ⎥ %% ⎢ ⎥ %% ⎣-2⎦ %% @end group %% @end example %% %% Example verifying an identity: %% @example %% @group %% syms f(x, y, z) %% curl(gradient(f)) %% @result{} (sym 3×1 matrix) %% ⎡0⎤ %% ⎢ ⎥ %% ⎢0⎥ %% ⎢ ⎥ %% ⎣0⎦ %% @end group %% @end example %% %% Note: assumes @var{x} is a Cartesian coordinate system. %% %% @seealso{@@sym/divergence, @@sym/gradient, @@sym/laplacian, @@sym/jacobian, %% @@sym/hessian} %% @end defmethod function g = curl(v,x) assert(isvector(v) && length(v)==3, 'curl is for 3D vector fields') if (nargin == 1) x = symvar(v, 3); elseif (nargin == 2) % no-op else print_usage (); end assert(length(x)==3, 'coordinate system should have three components') % ugh issue 17 so do in python to avoid cmd = { '(v, x) = _ins' 'def d(u, y):' ' if u.is_constant():' % FIXME ? ' try:' ' return sp.core.numbers.Zero()' ' except AttributeError:' % fix for SymPy 1.5.x ' return sp.numbers.Zero()' ' return u.diff(y)' 'g = Matrix([ \' ' d(v[2], x[1]) - d(v[1], x[2]), \' ' d(v[0], x[2]) - d(v[2], x[0]), \' ' d(v[1], x[0]) - d(v[0], x[1]) ])' 'return g,' }; g = pycall_sympy__ (cmd, sym(v), x); end %!error curl([sym(1) 2 3], 42, 42) %!shared x,y,z %! syms x y z %!test %! % double const %! f = [1 2 3]; %! g = [sym(0); 0; 0]; %! assert (isequal (curl(f, [x y z]), g)) %! % should fail, calls @double: curl(f, {x y z}), g)) %!test %! % div curl always 0 %! v = [exp(x); x*y; sin(z)]; %! g = curl(v); %! a = divergence(g, [x y z]); %! assert (isAlways (a == sym(0))) %! assert (isa (a, 'sym')) %! g = curl(v, [x y z]); %! a = divergence(g, [x y z]); %! assert (isAlways (a == sym(0))) %! assert (isa (a, 'sym')) %!test %! % div curl always 0 %! v = [exp(x); erfc(x*y); sin(exp(x)*y+sinh(z))]; %! g = curl(v, [x y z]); %! a = divergence(g, [x y z]); %! assert (isAlways (a == sym(0))) %! assert (isa (a, 'sym')) %!test %! % curl grad is vec zero %! f = sin(exp(x)*y+sinh(z)); %! g = curl(gradient(f, [x,y,z])); %! assert (isequal (g, sym([0;0;0]))) %!test %! % 2d fcn in 2d/3d %! u = sin(exp(x)*y); %! v = x^2*y^3; %! vorticity2d = diff(v,x) - diff(u,y); %! omega = curl([u; v; 0], [x y z]); %! assert (isequal (omega, [0; 0; vorticity2d])) %!error <3D vector> curl([sym(1) 2 3 4]) %!error curl([sym(1) 2 3], {sym('x') sym('y') sym('z') sym('t')}) symbolic-3.1.1/inst/@sym/dawson.m0000644000000000000000000000304714405647405013576 0ustar %% Copyright (C) 2016 Lagu %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym dawson (@var{x}) %% Symbolic Dawson (scaled imaginary error) function. %% %% Example: %% @example %% @group %% syms x %% dawson (x) %% @result{} ans = (sym) %% 2 %% -x %% √π⋅ℯ ⋅erfi(x) %% ─────────────── %% 2 %% @end group %% @end example %% @seealso{dawson, @@sym/erfc, @@sym/erf, @@sym/erfcx, @@sym/erfi, @@sym/erfinv, @@sym/erfcinv} %% @end defmethod function y = dawson(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('lambda a: exp(-a**2)*erfi(a)*(sqrt(S(pi))/2)', x); end %!test %! if (exist ('OCTAVE_VERSION', 'builtin')) %! % dawson missing on Matlab, Issue #742 %! A = dawson([1 2]); %! B = double(dawson(sym([1 2]))); %! assert(A, B, -eps) %! end symbolic-3.1.1/inst/@sym/degree.m0000644000000000000000000000447314405647405013542 0ustar %% Copyright (C) 2015, 2016, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym degree (@var{p}) %% @defmethodx @@sym degree (@var{p}, @var{x}) %% Return the degree of a polynomial expression. %% %% Examples: %% @example %% @group %% syms x %% degree(x^2 + 6) %% @result{} (sym) 2 %% @end group %% @end example %% %% You can specify the variable or rely on the @code{symvar} default: %% @example %% @group %% syms x y %% degree(x^2 + y*x + 1) %% @result{} (sym) 2 %% degree(x^2 + y*x + 1, x) %% @result{} (sym) 2 %% degree(x^2 + y*x + 1, y) %% @result{} (sym) 1 %% @end group %% @end example %% %% FIXME: @code{degree(x^n, x)} does not work here (nor in SMT). %% %% @seealso{@@sym/sym2poly, poly2sym} %% @end defmethod function n = degree(p, x) if (nargin > 2) print_usage (); end if (nargin == 1) x = symvar(p, 1); end if (isempty(x)) % degree will fail if p is constant and no generator given x = sym('x'); end n = pycall_sympy__ ('return sympy.degree(*_ins),', sym(p), sym(x)); end %!error degree (sym(1), 2, 3) %!test %! syms x %! assert (isequal (degree(x^3), 3)) %! assert (isequal (degree(x^3 + 6), 3)) %!test %! % specify variable %! syms x y %! p = x^2 + y*x + 1; %! assert (isequal (degree(p), 2)) %! assert (isequal (degree(p, x), 2)) %! assert (isequal (degree(p, y), 1)) %!test %! syms x a oo %! assert (isequal (degree(x^3, a), 0)) %! assert (isequal (degree(sym(1), a), 0)) %! assert (isequal (degree(sym(0), a), -oo)) %!xtest %! % constant inputs %! syms oo %! assert (isequal (degree(sym(1)), 0)) %! assert (isequal (degree(sym(0)), -oo)) symbolic-3.1.1/inst/@sym/det.m0000644000000000000000000000275414405647405013063 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym det (@var{x}) %% Symbolic determinant of a matrix. %% %% Example: %% @example %% @group %% A = sym([2 4; 6 8]); %% det(A) %% @result{} ans = (sym) -8 %% @end group %% @end example %% %% @seealso{@@sym/eig, @@sym/charpoly, @@sym/trace} %% @end defmethod function z = det(x) if (nargin ~= 1) print_usage (); end cmd = { '(A,) = _ins' 'if not A.is_Matrix:' ' A = sp.Matrix([A])' 'return A.det(),' }; z = pycall_sympy__ (cmd, x); end %!assert (isequal (det(sym([])), 1)) %!test %! syms x y real %! assert (isequal (det([x 5; 7 y]), x*y-35)) %!test %! syms x %! assert (isequal (det(x), x)) %! assert (isequal (det(sym(-6)), sym(-6))) symbolic-3.1.1/inst/@sym/diag.m0000644000000000000000000000766514405647405013221 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypeop Method @@sym {@var{M} =} diag (@var{v}) %% @deftypeopx Method @@sym {@var{M} =} diag (@var{v}, @var{k}) %% @deftypeopx Method @@sym {@var{M} =} diag (@var{v}, @var{n}, @var{m}) %% @deftypeopx Method @@sym {@var{v} =} diag (@var{A}) %% @deftypeopx Method @@sym {@var{v} =} diag (@var{A}, @var{k}) %% Make diagonal matrix or extract diagonal of symbolic matrix. %% %% Example: %% @example %% @group %% A = sym([1 2 3; 4 5 6; 7 8 9]) %% @result{} A = (sym 3×3 matrix) %% ⎡1 2 3⎤ %% ⎢ ⎥ %% ⎢4 5 6⎥ %% ⎢ ⎥ %% ⎣7 8 9⎦ %% %% v = diag(A) %% @result{} v = (sym 3×1 matrix) %% ⎡1⎤ %% ⎢ ⎥ %% ⎢5⎥ %% ⎢ ⎥ %% ⎣9⎦ %% @end group %% @end example %% %% Make it back into a matrix: %% @example %% @group %% diag(v) %% @result{} (sym 3×3 matrix) %% ⎡1 0 0⎤ %% ⎢ ⎥ %% ⎢0 5 0⎥ %% ⎢ ⎥ %% ⎣0 0 9⎦ %% @end group %% @end example %% @seealso{@@sym/repmat} %% @end deftypeop function D = diag(A, k, c) if (nargin == 3) assert(isvector(A)) elseif (nargin == 1) k = 0; end if isvector(A) if (nargin == 3) r = double(k); c = double(c); k = 0; else k = double(k); r = length(A) + abs(k); c = r; end cmd = { '(A, k, r, c) = _ins' 'if not A.is_Matrix:' ' A = sp.Matrix([A])' 'D = sp.zeros(r, c)' 'if k >= 0:' ' for i in range(0, min(r, c, c-k, r+k)):' ' D[i,i+k] = A[i]' 'else:' ' for i in range(0, min(r, c, c-k, r+k)):' ' D[i-k,i] = A[i]' 'return D,' }; D = pycall_sympy__ (cmd, sym(A), int32(k), int32(r), int32(c)); else cmd = { '(A, k) = _ins' 'if not A.is_Matrix:' ' A = sp.Matrix([A])' 'r, c = A.shape' 'if k >= 0:' ' B = sp.Matrix([A[i,i+k] for i in range(0, min(r, c, c-k, r+k))])' 'else:' ' B = sp.Matrix([A[i-k,i] for i in range(0, min(r, c, c-k, r+k))])' 'return B,' }; D = pycall_sympy__ (cmd, sym(A), int32(double(k))); end end %!test %! % scalar %! syms x %! assert (isequal (diag(x), x)) %!test %! % row,col vec input %! syms x %! r = [1 x 2]; %! c = [sym(1); x]; %! assert (isequal (diag(diag(c)), c)) %! assert (isequal (diag(c), [sym(1) 0; 0 x])) %! assert (isequal (diag(diag(r)), r.')) %! assert (isequal (diag(r), [sym(1) 0 0; 0 x 0; sym(0) 0 2])) %!test %! % create matrix, kth diag %! syms x %! r = [1 x]; %! z = sym(0); %! assert (isequal (diag (x, 0), x)) %! assert (isequal (diag (x, 1), [z x; z z])) %! assert (isequal (diag (x, -1), [z z; x z])) %! assert (isequal (diag (x, 2), [z z x; z z z; z z z])) %! assert (isequal (diag (r, 1), [z 1 z; z z x; z z z])) %!test %! % extract kth diag %! A = sym([1 2 3; 4 5 6]); %! assert (isequal (diag(A), sym([1; 5]))) %! assert (isequal (diag(A, 0), sym([1; 5]))) %! assert (isequal (diag(A, 1), sym([2; 6]))) %! assert (isequal (diag(A, 2), sym(3))) %! assert (isequal (diag(A, -1), sym(4))) %! assert (isempty (diag(A, -2))) %! assert (isempty (diag(A, 3))) symbolic-3.1.1/inst/@sym/diff.m0000644000000000000000000001234714405647405013216 0ustar %% Copyright (C) 2014-2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym diff (@var{f}) %% @defmethodx @@sym diff (@var{f}, @var{x}) %% @defmethodx @@sym diff (@var{f}, @var{x}, @var{x}, @dots{}) %% @defmethodx @@sym diff (@var{f}, @var{x}, @var{n}) %% @defmethodx @@sym diff (@var{f}, @var{x}, @var{y}) %% @defmethodx @@sym diff (@var{f}, @var{x}, @var{x}, @var{y}, @var{y}, @dots{}) %% @defmethodx @@sym diff (@var{f}, @var{x}, @var{n}, @var{y}, @var{m}, @dots{}) %% Symbolic differentiation. %% %% Examples: %% @example %% @group %% syms x %% f = sin (cos (x)); %% diff (f) %% @result{} (sym) -sin(x)⋅cos(cos(x)) %% diff (f, x) %% @result{} (sym) -sin(x)⋅cos(cos(x)) %% simplify (diff (f, x, x)) %% @result{} (sym) %% 2 %% - sin (x)⋅sin(cos(x)) - cos(x)⋅cos(cos(x)) %% @end group %% @end example %% %% Partial differentiation: %% @example %% @group %% syms x y %% f = cos(2*x + 3*y); %% diff(f, x, y, x) %% @result{} (sym) 12⋅sin(2⋅x + 3⋅y) %% diff(f, x, 2, y, 3) %% @result{} (sym) -108⋅sin(2⋅x + 3⋅y) %% @end group %% @end example %% %% Other examples: %% @example %% @group %% diff(sym(1)) %% @result{} (sym) 0 %% @end group %% @end example %% %% Partial derivatives are assumed to commute: %% @example %% @group %% syms f(x, y) %% diff(f, x, y) %% @result{} ans(x, y) = (symfun) %% %% 2 %% ∂ %% ─────(f(x, y)) %% ∂y ∂x %% @end group %% %% @group %% diff(f, y, x) %% @result{} ans(x, y) = (symfun) %% %% 2 %% ∂ %% ─────(f(x, y)) %% ∂y ∂x %% @end group %% @end example %% %% @seealso{@@sym/int} %% @end defmethod function z = diff(f, varargin) % simpler version, but gives error on differentiating a constant %cmd = 'return sp.diff(*_ins),'; %% some special cases for SMT compat. % FIXME: with a sympy symvar, could move this to python? if (nargin == 1) % diff(f) -> symvar x = symvar(f, 1); if (isempty(x)) x = sym('x'); % e.g., diff(sym(6)) end z = diff(f, x); return else q = varargin{1}; % Note: access sympy srepr to avoid double() overhead for common diff(f,x) isnum2 = isnumeric (q) || (isa (q, 'sym') && strncmpi (sympy (q), 'Integer', 7)); if ((nargin == 2) && isnum2) % diff(f,2) -> symvar x = symvar(f, 1); if (isempty(x)) x = sym('x'); % e.g., diff(sym(6), 2) end z = diff(f, x, varargin{1}); return end if ((nargin == 3) && isnum2) % diff(f,2,x) -> diff(f,x,2) z = diff(f, varargin{2}, varargin{1}); return end end cmd = { 'f = _ins[0]' 'args = _ins[1:]' 'return f.diff(*args),' }; for i = 1:length(varargin) varargin{i} = sym(varargin{i}); end z = pycall_sympy__ (cmd, sym(f), varargin{:}); end %!shared x,y,z %! syms x y z %!test %! % basic %! assert(logical( diff(sin(x)) - cos(x) == 0 )) %! assert(logical( diff(sin(x),x) - cos(x) == 0 )) %! assert(logical( diff(sin(x),x,x) + sin(x) == 0 )) %!test %! % these fail when doubles are not converted to sym %! assert(logical( diff(sin(x),x,2) + sin(x) == 0 )) %! assert(logical( diff(sym(1),x) == 0 )) %! assert(logical( diff(1,x) == 0 )) %! assert(logical( diff(pi,x) == 0 )) %!test %! % symbolic diff of const (w/o variable) fails in sympy, but we work around %! assert (isequal (diff(sym(1)), sym(0))) %!test %! % nth symbolic diff of const %! assert (isequal (diff(sym(1), 2), sym(0))) %! assert (isequal (diff(sym(1), sym(1)), sym(0))) %!test %! % octave's vector difference still works %! assert(isempty(diff(1))) %! assert((diff([2 6]) == 4)) %!test %! % other forms %! f = sin(x); %! g = diff(f,x,2); %! assert (isequal (diff(f,2), g)) %! assert (isequal (diff(f,sym(2)), g)) %! g = diff(f,x); %! assert (isequal (diff(f), g)) %! assert (isequal (diff(f,1), g)) %!test %! % old SMT supported (still does?) the 'n' before the 'x' %! % we might remove this someday, no longer seems documented in SMT %! f = sin(x); %! g = diff(f,x,2); %! assert (isequal (diff(f,2,x), g)) %! assert (isequal (diff(f,sym(2),x), g)) %! g = diff(f,x); %! assert (isequal (diff(f,1,x), g)) %!test %! % matrix %! A = [x sin(x); x*y 10]; %! B = [1 cos(x); y 0]; %! assert(isequal(diff(A,x),B)) %!test %! % bug: use symvar %! a = x*y; %! b = diff(a); %! assert (isequal (b, y)) %!test %! % bug: symvar should be used on the matrix, not comp-by-comp %! a = [x y x*x]; %! b = diff(a); %! assert (~isequal (b(2), 1)) %! assert (isequal (b, [1 0 2*x])) %! b = diff(a,1); %! assert (~isequal (b(2), 1)) %! assert (isequal (b, [1 0 2*x])) symbolic-3.1.1/inst/@sym/dilog.m0000644000000000000000000000275214405647405013403 0ustar %% Copyright (C) 2016, 2018-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym dilog (@var{z}) %% Symbolic dilogarithm function. %% %% Example: %% @example %% @group %% syms z %% dilog (z) %% @result{} ans = (sym) polylog(2, 1 - z) %% @end group %% @end example %% %% @seealso{@@sym/polylog} %% @end defmethod function L = dilog(z) if (nargin ~= 1) print_usage (); end L = polylog(2, 1 - z); end %!assert (isequal (dilog (sym(1)), sym(0))) %!assert (isequal (dilog (sym(0)), sym(pi)^2/6)) %!assert (isequal (dilog (sym(2)), -sym(pi)^2/12)) %!assert (double(dilog(sym(-1))), pi^2/4 - pi*1i*log(2), eps) %!test %! % round-trip %! syms x %! f = dilog (x); %! h = function_handle (f); %! A = h (1.1); %! B = dilog (1.1); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/dirac.m0000644000000000000000000000331414405647405013362 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym dirac (@var{x}) %% Symbolic dirac function. %% %% Example: %% @example %% @group %% syms x %% y = dirac (x) %% @result{} y = (sym) δ(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = dirac(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('DiracDelta', x); end %!error dirac (sym(1), 2) %!assert (isequaln (dirac (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = dirac(x); %! f2 = dirac(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = dirac(A); %! f2 = dirac(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = dirac (d); %! f = dirac (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/disp.m0000644000000000000000000000670114405647405013242 0ustar %% Copyright (C) 2014-2016, 2018-2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {} disp (@var{x}) %% @deftypemethodx @@sym {} disp (@var{x}, 'unicode') %% @deftypemethodx @@sym {} disp (@var{x}, 'ascii') %% @deftypemethodx @@sym {} disp (@var{x}, 'flat') %% @deftypemethodx @@sym {@var{s} =} disp (@var{x}) %% Display the value of a symbolic expression. %% %% Examples: %% @example %% @group %% syms x a c %% str = disp(sin(2*sym(pi)*x)) %% @result{} str = sin(2⋅π⋅x) %% %% A = [sin(x/2) floor(a^(x*c)); acosh(2*x/pi) ceil(sin(x/gamma(x)))]; %% disp(A, 'unicode') %% @print{} ⎡ ⎛x⎞ ⎢ c⋅x⎥ ⎤ %% @print{} ⎢ sin⎜─⎟ ⎣a ⎦ ⎥ %% @print{} ⎢ ⎝2⎠ ⎥ %% @print{} ⎢ ⎥ %% @print{} ⎢ ⎛2⋅x⎞ ⎡ ⎛ x ⎞⎤⎥ %% @print{} ⎢acosh⎜───⎟ ⎢sin⎜────⎟⎥⎥ %% @print{} ⎣ ⎝ π ⎠ ⎢ ⎝Γ(x)⎠⎥⎦ %% @end group %% %% @group %% disp(A, 'ascii') %% @print{} [ /x\ / c*x\ ] %% @print{} [ sin|-| floor\a / ] %% @print{} [ \2/ ] %% @print{} [ ] %% @print{} [ /2*x\ / / x \\] %% @print{} [acosh|---| ceiling|sin|--------||] %% @print{} [ \ pi/ \ \Gamma(x)//] %% %% disp(A, 'flat') %% @print{} Matrix([[sin(x/2), floor(a**(c*x))], [acosh(2*x/pi), ceiling(sin(x/gamma(x)))]]) %% @end group %% @end example %% %% @seealso{@@sym/pretty} %% @end deftypemethod function varargout = disp(x, wh) if (nargin == 1) %% read config to see how to display x wh = sympref('display'); end switch lower(wh) case 'flat' s = x.flat; case 'ascii' s = x.ascii; case 'unicode' s = x.unicode; otherwise print_usage (); end s = make_indented(s); if (nargout == 0) disp(s) else varargout = {[s sprintf('\n')]}; % add a newline end end function s = make_indented(s, n) if (nargin == 1) n = 2; end pad = char (double (' ')*ones (1,n)); newl = sprintf('\n'); s = strrep (s, newl, [newl pad]); s = [pad s]; % first line end %!test %! syms x %! s = disp(sin(x)); %! assert(strcmp(s, sprintf(' sin(x)\n'))) %!test %! syms x %! s = disp(sin(x/2), 'flat'); %! assert(strcmp(s, sprintf(' sin(x/2)\n'))) %!test %! % Examples of 2x0 and 0x2 empty matrices: %! a = sym([1 2; 3 4]); %! b2x0 = a([true true], [false false]); %! b0x2 = a([false false], [true true]); %! assert (isequal (size (b2x0), [2 0])) %! assert (isequal (size (b0x2), [0 2])) %! s = disp(b2x0); %! assert(strcmp(s, sprintf(' []\n'))) %! s = disp(b0x2); %! assert(strcmp(s, sprintf(' []\n'))) symbolic-3.1.1/inst/@sym/display.m0000644000000000000000000001130414405647405013743 0ustar %% Copyright (C) 2014-2016, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym display (@var{x}) %% Display, on command line, the contents of a symbolic expression. %% %% Examples: %% @example %% @group %% x = sym('x') %% @result{} x = (sym) x %% %% display(x) %% @result{} x = (sym) x %% %% display([x 2 pi]) %% @result{} (sym) [x 2 π] (1×3 matrix) %% @end group %% @end example %% %% Other examples: %% @example %% @group %% A = sym([1 2; 3 4]) %% @result{} A = (sym 2×2 matrix) %% ⎡1 2⎤ %% ⎢ ⎥ %% ⎣3 4⎦ %% @end group %% %% @group %% syms n %% A = sym('A', [n n]) %% @result{} A = (sym) A (n×n matrix expression) %% B = 3*A %% @result{} B = (sym) 3⋅A (n×n matrix expression) %% %% A = sym(ones(0, 3)) %% @result{} A = (sym) [] (empty 0×3 matrix) %% %% A = sym('A', [0, n]) %% @result{} A = (sym) A (empty 0×n matrix expression) %% B = 3*A %% @result{} B = (sym) 3⋅A (empty 0×n matrix expression) %% @end group %% @end example %% %% @seealso{@@sym/disp} %% @end defmethod function display(x) %% Settings wh = sympref('display'); if (strcmp(wh, 'unicode')) unicode_dec = true; else unicode_dec = false; end if (exist('OCTAVE_VERSION', 'builtin')) [fmt, spacing] = format(); loose = strcmp (spacing, 'loose'); else % Matlab and Octave < 4 loose = strcmp(get(0, 'FormatSpacing'), 'loose'); end % weird hack to support "ans(x) = " output for @symfun name = private_disp_name(x, inputname (1)); dispstr = disp (x); dispstrtrim = strtrim (dispstr); hasnewlines = ~isempty (strfind (dispstrtrim, sprintf('\n'))); [desc_start, desc_end] = sym_describe (x, unicode_dec); toobig = hasnewlines; %toobig = hasnewlines || ~(isempty(x) || isscalar(x)); s1 = ''; if (~isempty(name)) s1 = sprintf ('%s = ', name); end if (toobig) if (isempty(desc_end)) s2 = sprintf('(%s)', desc_start); else s2 = sprintf('(%s %s)', desc_start, desc_end); end else if (isempty(desc_end)) s2 = sprintf('(%s) %s', desc_start, dispstrtrim); else s2 = sprintf('(%s) %s (%s)', desc_start, dispstrtrim, desc_end); end end s = [s1 s2]; disp (s) if (toobig) if (loose), fprintf ('\n'); end % don't use printf b/c ascii-art might have slashes disp (dispstr(1:end-1)); % remove existing newline, disp adds one if (loose), fprintf ('\n'); end end end function [s1 s2] = sym_describe(x, unicode_dec) if (unicode_dec) %timesstr = '×'; % https://savannah.gnu.org/bugs/index.php?56072 timesstr = do_highbyte_escapes('\xc3\x97'); else timesstr = 'x'; end s1 = class (x); srepr = sympy (x); d = size (x); % sort of isinstance(x, MatrixExpr) but cheaper is_matrix_symbol = false; matexprlist = {'MatrixSymbol' 'MatMul' 'MatAdd' 'MatPow'}; for i=1:length(matexprlist) if (strncmp(srepr, matexprlist{i}, length(matexprlist{i}))) is_matrix_symbol = true; end end if (isscalar (x)) && (~is_matrix_symbol) s2 = ''; elseif (is_matrix_symbol) %if (any(isnan(d))) % may not tell the truth if (any(isnan(x.size))) [nn, mm] = pycall_sympy__ ('return (_ins[0].rows, _ins[0].cols)', x); numrstr = strtrim(disp(nn, 'flat')); numcstr = strtrim(disp(mm, 'flat')); else nn = d(1); mm = d(2); numrstr = num2str(d(1), '%g'); numcstr = num2str(d(2), '%g'); end if (logical(nn == 0) || logical(mm == 0)) estr = 'empty '; else estr = ''; end s2 = sprintf ('%s%s%s%s matrix expression', estr, numrstr, timesstr, numcstr); elseif (length (d) == 2) if (isempty (x)) estr = 'empty '; else estr = ''; end s2 = sprintf ('%s%g%s%g matrix', estr, d(1), timesstr, d(2)); else s2 = sprintf ('%d-dim array', length (d)) end end % FIXME: Could quietly test with "evalc", but [missing in % Octave](https://savannah.gnu.org/patch/?8033). For now, a dummy % test. Doctests will cover this anyway. %!test %! assert(true) symbolic-3.1.1/inst/@sym/divergence.m0000644000000000000000000000723214405647405014416 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym divergence (@var{F}) %% @defmethodx @@sym divergence (@var{F}, @var{x}) %% Symbolic divergence of symbolic expression. %% %% Consider a vector expression @var{F}: %% @example %% @group %% syms f_1(x,y,z) f_2(x,y,z) f_3(x,y,z) %% F = [f_1; f_2; f_3] %% @result{} F = (sym 3×1 matrix) %% ⎡f₁(x, y, z)⎤ %% ⎢ ⎥ %% ⎢f₂(x, y, z)⎥ %% ⎢ ⎥ %% ⎣f₃(x, y, z)⎦ %% @end group %% @end example %% The divergence of @var{F} is the scalar expression: %% @example %% @group %% divergence(F) %% @result{} (sym) %% ∂ ∂ ∂ %% ──(f₁(x, y, z)) + ──(f₂(x, y, z)) + ──(f₃(x, y, z)) %% ∂x ∂y ∂z %% @end group %% @end example %% %% Examples: %% @example %% @group %% syms x y %% F = [x^2/2 y^2/2]; %% divergence(F) %% @result{} (sym) x + y %% @end group %% %% @group %% syms z %% F = [y x x*y]; %% divergence(F, [x; y; z]) %% @result{} (sym) 0 %% @end group %% @end example %% %% Note: assumes @var{x} is a Cartesian coordinate system. %% %% @seealso{@@sym/gradient, @@sym/curl, @@sym/laplacian, @@sym/jacobian, %% @@sym/hessian} %% @end defmethod function g = divergence(f, x) assert (isvector(f), 'divergence: defined for vectors') if (nargin == 1) x = symvar(f); elseif (nargin == 2) % np-op else print_usage (); end assert (length(f) == length(x), 'divergence: num vars must match vec length') idx1.type='()'; if (iscell(x)) idx2.type='{}'; else idx2.type='()'; end g = sym(0); for i = 1:length(f) idx1.subs={i}; idx2.subs={i}; g = g + diff (subsref(f,idx1), subsref(x,idx2)); end end %!shared x,y,z %! syms x y z %!test %! % 1D %! f = x^2; %! assert (isequal (divergence(f), diff(f,x))) %! assert (isequal (divergence(f,{x}), diff(f,x))) %! assert (isequal (divergence(f,[x]), diff(f,x))) %! assert (isequal (divergence(f,x), diff(f,x))) %!test %! % const %! f = [sym(1); 2; exp(sym(3))]; %! assert (isequal (divergence(f,{x,y,z}), 0)) %! f = [sym(1); 2; exp(sym('c'))]; %! assert (isequal (divergence(f,{x,y,z}), 0)) %!test %! % double const %! f = [1 2]; %! g = sym(0); %! assert (isequal (divergence(f, [x y]), g)) %! % should fail, calls @double: divergence(f, {x y}), g)) %!test %! % 1D fcn in 2d/3d %! f = [x y z]; %! assert (isequal (divergence(f), 3)) %! assert (isequal (divergence(f, {x,y,z}), 3)) %! assert (isequal (divergence(f, [x,y,z]), 3)) %!test %! % 2d fcn in 2d/3d %! f = sin(exp(x)*y+sinh(z)); %! g2 = [diff(f,x); diff(f,y)]; %! l2 = diff(g2(1),x) + diff(g2(2),y); %! g3 = [diff(f,x); diff(f,y); diff(f,z)]; %! l3 = diff(g3(1),x) + diff(g3(2),y) + diff(g3(3),z); %! assert (isequal (divergence(g2, {x,y}), l2)) %! assert (isequal (divergence(g3, {x,y,z}), l3)) %!error divergence ([1 2], [sym('x')]) %!error divergence ([1 2], sym('x'), 42) symbolic-3.1.1/inst/@sym/divisors.m0000644000000000000000000000255014405647405014143 0ustar %% Copyright (C) 2016 Lagu %% Copyright (C) 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym divisors (@var{x}) %% Get divisors of integer. %% %% Example: %% @example %% @group %% x = sym(150); %% y = divisors(x) %% @result{} y = (sym) [1 2 3 5 6 10 15 25 30 50 75 150] (1×12 matrix) %% @end group %% @end example %% @end defmethod %% Reference: http://docs.sympy.org/dev/modules/ntheory.html function y = divisors(x) if (nargin ~= 1) print_usage (); end y = pycall_sympy__ ('return S(divisors(_ins[0])),', x); y = cell2sym(y); end %!test %! assert( isequal( divisors(sym(150)), divisors(sym(-150)) )) symbolic-3.1.1/inst/@sym/dot.m0000644000000000000000000000414714405647405013073 0ustar %% Copyright (C) 2015-2016, 2018-2019, 2022 Colin B. Macdonald %% Copyright (C) 2016 Alex Vong %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym dot (@var{a}, @var{b}) %% Symbolic dot (scalar) product. %% %% This function computes 'sum (conj (A) .* B)'. %% %% Examples: %% @example %% @group %% a = [sym('a1'); sym('a2'); sym('a3')]; %% b = [sym('b1'); sym('b2'); sym('b3')]; %% dot(a, b) %% @result{} (sym) %% __ __ __ %% b₁⋅a₁ + b₂⋅a₂ + b₃⋅a₃ %% dot(a, a) %% @result{} (sym) %% __ __ __ %% a₁⋅a₁ + a₂⋅a₂ + a₃⋅a₃ %% @end group %% @end example %% %% @example %% @group %% syms x %% a = [x; 0; 0]; %% b = [0; 0; sym(1)]; %% dot(a, b) %% @result{} ans = (sym) 0 %% @end group %% @end example %% %% @seealso{@@sym/cross} %% @end defmethod function c = dot(a, b) if (nargin ~= 2) print_usage (); end % conjugate a to match the behavior of @double/dot cmd = { 'a, b = _ins' 'return a.dot(b, hermitian=True, conjugate_convention="left")' }; c = pycall_sympy__ (cmd, sym(a), sym(b)); end %!error dot (sym(1), 2, 3) %!test %! a = sym([1; 1; 0]); %! b = sym([1; 2; 4]); %! c = dot(a, b); %! assert (isequal (c, sym(3))) %!test %! syms x %! a = sym([x; 0; 0]); %! b = sym([0; 1; 0]); %! c = dot(a, b); %! assert (isequal (c, sym(0))) %!test %! assert (isequal (dot (sym([1 i]), sym([i 2])), sym(-i))) symbolic-3.1.1/inst/@sym/double.m0000644000000000000000000000727314405647405013562 0ustar %% Copyright (C) 2014-2017, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym double (@var{x}) %% Convert symbolic to doubles. %% %% Example: %% @example %% @group %% x = sym(1) / 3 %% @result{} x = (sym) 1/3 %% @c doctest: +SKIP_IF(compare_versions (OCTAVE_VERSION(), '6.0.0', '<')) %% double (x) %% @result{} ans = 0.3333 %% @end group %% @end example %% %% Despite the name, this is one way to convert a complex sym to %% floating point: %% @example %% @group %% z = sym(4i) - 3; %% double (z) %% @result{} ans = -3 + 4i %% @end group %% @end example %% %% If conversion fails, you get an error: %% @example %% @group %% syms x %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.9")')) %% double (x) %% @print{} ??? ... Cannot convert expression ... %% @end group %% @end example %% %% @seealso{sym, vpa} %% @end defmethod function y = double(x) % FIXME: port to uniop? if ~(isscalar(x)) % sympy N() works fine on matrices but it gives objects like "Matrix([[1.0,2.0]])" y = zeros(size(x)); for j = 1:numel(x) % temp = x(j) (Issue #17) idx.type = '()'; idx.subs = {j}; temp = double(subsref(x,idx)); if (isempty(temp)) y = []; return end y(j) = temp; end return end cmd = { '(x,) = _ins' 'if x == zoo:' % zoo -> Inf + Infi ' return (float(sp.oo), float(sp.oo))' 'if x == nan:' ' return (float(nan), 0.0)' 'x = complex(x)' 'return (x.real, x.imag)' }; [A, B] = pycall_sympy__ (cmd, x); %y = A + B*i; % not quite the same for Inf + InFi if (B == 0.0) y = A; else y = complex(A, B); end end %!test %! % numeric scalar %! a = double(sym(10)); %! assert (a == 10) %! assert (isa (a, 'double')) %!test %! % numeric vectors %! a = double(sym([10 12])); %! assert (isequal (a, [10 12])) %! assert (isa (a, 'double')) %!test %! % complex %! a = 3 + 4i; %! b = sym(a); %! assert (isequal (double (b), a)) %!xtest %! % unexpected, precisely same floating point %! a = 3 + 4i; %! b = sym(a); %! assert (isequal (double (b/pi), a/pi)) %!test %! % floating point %! x = sqrt(sym(2)); %! assert( abs(double(x) - sqrt(2)) < 2*eps) %! x = sym(pi); %! assert( abs(double(x) - pi) < 2*eps) %!test %! oo = sym(inf); %! assert( double(oo) == inf ) %! assert( double(-oo) == -inf ) %! assert( isnan(double(0*oo)) ) %!test %! zoo = sym('zoo'); %! assert (double(zoo) == complex(inf, inf)) %!test %! zoo = sym('zoo'); %! assert (double(-zoo) == double(zoo) ) %! assert( isnan(double(0*zoo)) ) %!test %! % nan %! snan = sym(nan); %! assert( isnan(double(snan))) %!test %! % don't want NaN+NaNi %! snan = sym(nan); %! assert (isreal (double (snan))) %!test %! % arrays %! a = [1 2; 3 4]; %! assert( isequal( double(sym(a)), a )) %! assert( isequal( double(sym(a)), a )) %! % should fail with error for non-double %!error syms x; double(x) %!error syms x; double([1 2 x]) symbolic-3.1.1/inst/@sym/dsolve.m0000644000000000000000000003046714405647405013605 0ustar %% Copyright (C) 2014-2016, 2018-2019, 2022 Colin B. Macdonald %% Copyright (C) 2014-2015 Andrés Prieto %% Copyright (C) 2020 Rafael Laboissière %% Copyright (C) 2020 Jing-Chen Peng %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {@var{sol} =} dsolve (@var{ode}) %% @deftypemethodx @@sym {@var{sol} =} dsolve (@var{ode}, @var{IC}) %% @deftypemethodx @@sym {@var{sol} =} dsolve (@var{ODEs}, @var{IC1}, @var{IC2}, @dots{}) %% @deftypemethodx @@sym {@var{sol} =} dsolve (@var{ODEs}, @var{ICs}) %% @deftypemethodx @@sym {[@var{sol}, @var{classify}] =} dsolve (@dots{}) %% Solve ordinary differential equations (ODEs) symbolically. %% %% Basic example: %% @example %% @group %% syms y(x) %% DE = diff(y, x) - 4*y == 0 %% @result{} DE = (sym) %% d %% -4⋅y(x) + ──(y(x)) = 0 %% dx %% @end group %% %% @group %% sol = dsolve (DE) %% @result{} sol = (sym) %% 4⋅x %% C₁⋅ℯ %% @end group %% @end example %% %% You can specify initial conditions: %% @example %% @group %% sol = dsolve (DE, y(0) == 1) %% @result{} sol = (sym) %% 4⋅x %% ℯ %% @end group %% @end example %% %% In some cases, SymPy can return a classification of the %% differential equation: %% @example %% @group %% DE = diff(y) == y^2 %% @result{} DE = (sym) %% d 2 %% ──(y(x)) = y (x) %% dx %% %% [sol, classify] = dsolve (DE, y(0) == 1) %% @result{} sol = (sym) %% -1 %% ───── %% x - 1 %% @result{} classify = ... separable ... %% @end group %% @end example %% %% Many types of ODEs can be solved, including initial-value %% problems and boundary-value problem: %% @example %% @group %% DE = diff(y, 2) == -9*y %% @result{} DE = (sym) %% 2 %% d %% ───(y(x)) = -9⋅y(x) %% 2 %% dx %% %% dsolve (DE, y(0) == 1, diff(y)(0) == 12) %% @result{} (sym) 4⋅sin(3⋅x) + cos(3⋅x) %% %% dsolve (DE, y(0) == 1, y(sym(pi)/2) == 2) %% @result{} (sym) -2⋅sin(3⋅x) + cos(3⋅x) %% @end group %% @end example %% %% Some systems can be solved, including initial-value problems %% involving linear systems of first order ODEs with constant %% coefficients: %% @example %% @group %% syms x(t) y(t) %% ode_sys = [diff(x(t),t) == 2*y(t); diff(y(t),t) == 2*x(t)] %% @result{} ode_sys = (sym 2×1 matrix) %% ⎡d ⎤ %% ⎢──(x(t)) = 2⋅y(t)⎥ %% ⎢dt ⎥ %% ⎢ ⎥ %% ⎢d ⎥ %% ⎢──(y(t)) = 2⋅x(t)⎥ %% ⎣dt ⎦ %% @end group %% %% @group %% soln = dsolve (ode_sys) %% @result{} soln = scalar structure containing ... %% x = ... %% y = ... %% %% @c doctest: +SKIP_IF(pycall_sympy__ ('return Version(spver) <= Version("1.5.1")')) %% soln.x %% @result{} ans = %% (sym) %% -2⋅t 2⋅t %% - C₁⋅ℯ + C₂⋅ℯ %% %% @c doctest: +SKIP_IF(pycall_sympy__ ('return Version(spver) <= Version("1.5.1")')) %% soln.y %% @result{} ans = %% (sym) %% -2⋅t 2⋅t %% C₁⋅ℯ + C₂⋅ℯ %% @end group %% @end example %% %% Note: The Symbolic Math Toolbox used to support strings like 'Dy + y = 0'; we %% are unlikely to support this so you will need to assemble a symbolic %% equation instead. %% %% @seealso{@@sym/diff, @@sym/int, @@sym/solve} %% @end deftypemethod function [soln,classify] = dsolve(ode,varargin) % Usually we cast to sym in the _cmd call, but want to be % careful here b/c of symfuns if (~ iscell (ode) && ~ all (isa (ode, 'sym'))) error('Inputs must be sym or symfun') end % FIXME: might be nice to expose SymPy's "sp.ode.classify_sysode" and % "sp.ode.classify_ode" with their own commands if (isscalar(ode) && nargout==2) cmd = { 'from sympy.solvers import classify_ode' 'return classify_ode(_ins[0]),' }; classify = pycall_sympy__ (cmd, ode); elseif(~isscalar(ode) && nargout==2) warning('Classification of systems of ODEs is currently not supported') classify=''; end cmd = { 'ode=_ins[0]; ics=_ins[1:]' 'if len(ics) == 1:' ' ics = ics[0]' 'try:' ' ics = {ic.lhs: ic.rhs for ic in ics}' 'except TypeError:' % not iterable ' ics = {ics.lhs: ics.rhs}' 'sol = sp.dsolve(ode, ics=ics)' 'def convert_helper(sympy_obj):' ' if isinstance(sympy_obj, Eq) and sympy_obj.lhs.is_Function:' % y(t) = rhs to str "y", rhs expression ' return str(sympy_obj.lhs.func), sympy_obj.rhs' ' return None, None' % if just single equality with simple lhs, we return the rhs 'if isinstance(sol, Eq):' ' if sol.lhs.is_Function:' ' return sol.rhs' % If the solution set is iterable (system or multiple solutions), % we will try to convert to structure of {"x": expr, "y": expr2, ...} 'try:' ' return_data = dict()' ' for solution_part in sol:' ' key, rhs = convert_helper(solution_part)' ' if key is None:' ' raise ValueError("not of right form for extraction")' ' if key in return_data.keys():' ' raise KeyError(f"repeated key {key}")' ' return_data[key] = rhs' ' return return_data' 'except (TypeError, ValueError, KeyError):' ' pass' % if nothing else worked, give back whatever form we have 'return sol' }; soln = pycall_sympy__ (cmd, ode, varargin{:}); end %!error dsolve (1, sym('x')) %!test %! syms y(x) %! de = diff(y, 2) - 4*y == 0; %! f = dsolve(de); %! syms C1 C2 %! g1 = C1*exp(-2*x) + C2*exp(2*x); %! g2 = C2*exp(-2*x) + C1*exp(2*x); %! assert (isequal (f, g1) || isequal (f, g2)) %!test %! % Not enough initial conditions %! syms y(x) C1 %! de = diff(y, 2) + 4*y == 0; %! g = 3*cos(2*x) + C1*sin(2*x); %! try %! f = dsolve(de, y(0) == 3); %! waserr = false; %! catch %! waserr = true; %! expectederr = regexp (lasterr (), 'Perhaps.*under-specified'); %! f = 42; %! end %! assert ((waserr && expectederr) || isequal (f, g)) %!test %! % Solution in implicit form %! syms y(x) C1 %! de = (2*x*y(x) - exp(-2*y(x)))*diff(y(x), x) + y(x) == 0; %! sol = dsolve (de); %! eqn = x*exp(2*y(x)) - log(y(x)) == C1; %! % could differ by signs %! sol = lhs (sol) - rhs (sol); %! eqn = lhs (eqn) - rhs (eqn); %! sol2 = subs (sol, C1, -C1); %! assert (isequal (sol, eqn) || isequal (sol2, eqn)) %%!xtest %%! % system with solution in implicit form %%! % TODO: not implemented upstream? %%! syms y(x) z(x) C1 %%! de1 = (2*x*y(x) - exp(-2*y(x)))*diff(y(x), x) + y(x) == 0; %%! de2 = diff(z, x) == 0; %%! sol = dsolve ([de1; de2]); %!test %! % Compute solution and classification %! syms y(x) C1 %! de = (2*x*y(x) - exp(-2*y(x)))*diff(y(x), x) + y(x) == 0; %! [sol, classy] = dsolve (de); %! assert (any (strcmp (classy, '1st_exact'))) %!test %! % initial conditions (first order ode) %! syms y(x) %! de = diff(y, x) + 4*y == 0; %! f = dsolve(de, y(0) == 3); %! g = 3*exp(-4*x); %! assert (isequal (f, g)) %!test %! % initial conditions (second order ode) %! syms y(x) %! de = diff(y, 2) + 4*y == 0; %! f = dsolve(de, y(0) == 3, subs(diff(y,x),x,0)==0); %! g = 3*cos(2*x); %! assert (isequal (f, g)) %!test %! % Dirichlet boundary conditions (second order ode) %! syms y(x) %! de = diff(y, 2) + 4*y == 0; %! f = dsolve(de, y(0) == 2, y(1) == 0); %! g = -2*sin(2*x)/tan(sym('2'))+2*cos(2*x); %! assert (isequal (simplify (f - g), 0)) %!test %! % Neumann boundary conditions (second order ode) %! syms y(x) %! de = diff(y, 2) + 4*y == 0; %! f = dsolve(de, subs(diff(y,x),x,0)==1, subs(diff(y,x),x,1)==0); %! g = sin(2*x)/2+cos(2*x)/(2*tan(sym('2'))); %! assert (isequal (simplify (f - g), 0)) %!test %! % Dirichlet-Neumann boundary conditions (second order ode) %! syms y(x) %! de = diff(y, 2) + 4*y == 0; %! f = dsolve(de, y(0) == 3, subs(diff(y,x),x,1)==0); %! g = 3*sin(2*x)*tan(sym('2'))+3*cos(2*x); %! assert (isequal (simplify (f - g), 0)) %!test %! % System of ODEs gives struct, Issue #1003. %! syms x(t) y(t) %! ode1 = diff(x(t),t) == 2*y(t); %! ode2 = diff(y(t),t) == 2*x(t); %! soln = dsolve([ode1, ode2]); %! assert (isstruct (soln)) %! assert (numfields (soln) == 2) %! assert (isequal (sort (fieldnames (soln)), {'x'; 'y'})) %!test %! % System of ODEs %! syms x(t) y(t) C1 C2 %! ode1 = diff(x(t),t) == 2*y(t); %! ode2 = diff(y(t),t) == 2*x(t); %! soln = dsolve([ode1, ode2]); %! soln = [soln.x, soln.y]; %! g1 = [C1*exp(-2*t) + C2*exp(2*t), -C1*exp(-2*t) + C2*exp(2*t)]; %! g2 = [C1*exp(2*t) + C2*exp(-2*t), C1*exp(2*t) - C2*exp(-2*t)]; %! g3 = [-C1*exp(-2*t) + C2*exp(2*t), C1*exp(-2*t) + C2*exp(2*t)]; %! g4 = [C1*exp(2*t) - C2*exp(-2*t), C1*exp(2*t) + C2*exp(-2*t)]; %! % old SymPy <= 1.5.1 had some extra twos %! g5 = [2*C1*exp(-2*t) + 2*C2*exp(2*t), -2*C1*exp(-2*t) + 2*C2*exp(2*t)]; %! g6 = [2*C1*exp(2*t) + 2*C2*exp(-2*t), 2*C1*exp(2*t) - 2*C2*exp(-2*t)]; %! assert (isequal (soln, g1) || isequal (soln, g2) || ... %! isequal (soln, g3) || isequal (soln, g4) || ... %! isequal (soln, g5) || isequal (soln, g6)) %!test %! % System of ODEs (initial-value problem) %! syms x(t) y(t) %! ode_1=diff(x(t),t) == 2*y(t); %! ode_2=diff(y(t),t) == 2*x(t); %! sol_ivp=dsolve([ode_1,ode_2],x(0)==1,y(0)==0); %! g_ivp=[exp(-2*t)/2+exp(2*t)/2,-exp(-2*t)/2+exp(2*t)/2]; %! assert (isequal ([sol_ivp.x, sol_ivp.y], g_ivp)) %!test %! syms y(x) %! de = diff(y, 2) + 4*y == 0; %! f = dsolve(de, y(0) == 0, y(sym(pi)/4) == 1); %! g = sin(2*x); %! assert (isequal (f, g)) %!test %! % Nonlinear example %! syms y(x) C1 %! e = diff(y, x) == y^2; %! g = -1 / (C1 + x); %! soln = dsolve(e); %! assert (isequal (soln, g)) %!test %! % Nonlinear example with initial condition %! syms y(x) %! e = diff(y, x) == y^2; %! g = -1 / (x - 1); %! soln = dsolve(e, y(0) == 1); %! assert (isequal (soln, g)) %!test %! % forcing, Issue #183, broken in older sympy %! if (pycall_sympy__ ('return Version(spver) >= Version("1.7.1")')) %! syms x(t) y(t) %! ode1 = diff(x) == x + sin(t) + 2; %! ode2 = diff(y) == y - t - 3; %! soln = dsolve([ode1 ode2], x(0) == 1, y(0) == 2); %! X = soln.x; %! Y = soln.y; %! assert (isequal (diff(X) - (X + sin(t) + 2), 0)) %! assert (isequal (diff(Y) - (Y - t - 3), 0)) %! end %!test %! syms f(x) a b %! de = diff(f, x) == 4*f; %! s = dsolve(de, f(a) == b); %! assert (isequal (subs(s, x, a), b)) %!test %! % array of ICs %! syms x(t) y(t) %! ode_1 = diff (x(t), t) == 2*y(t); %! ode_2 = diff (y(t), t) == 2*x(t); %! sol = dsolve([ode_1, ode_2], [x(0)==1 y(0)==0]); %! g = [exp(-2*t)/2+exp(2*t)/2, -exp(-2*t)/2+exp(2*t)/2]; %! assert (isequal ([sol.x, sol.y], g)) %!test %! % cell-array of ICs or ODEs, but not both %! % Note: to support both we'd need a wrapper outside of @sym %! syms x(t) y(t) %! ode_1 = diff (x(t), t) == 2*y(t); %! ode_2 = diff (y(t), t) == 2*x(t); %! sol = dsolve([ode_1, ode_2], {x(0)==1 y(0)==0}); %! g = [exp(-2*t)/2+exp(2*t)/2, -exp(-2*t)/2+exp(2*t)/2]; %! assert (isequal ([sol.x, sol.y], g)) %! sol = dsolve({ode_1, ode_2}, [x(0)==1 y(0)==0]); %! g = [exp(-2*t)/2+exp(2*t)/2, -exp(-2*t)/2+exp(2*t)/2]; %! assert (isequal ([sol.x, sol.y], g)) %!test %! % array of ICs, Issue #1040. %! if (pycall_sympy__ ('return Version(spver) >= Version("1.7.1")')) %! syms x(t) y(t) z(t) %! syms x_0 y_0 z_0 %! diffEqns = [diff(x, t) == -x + 1, diff(y, t) == -y, diff(z, t) == -z]; %! initCond = [x(0) == x_0, y(0) == y_0, z(0) == z_0]; %! soln = dsolve (diffEqns, initCond); %! soln = [soln.x, soln.y, soln.z]; %! exact_soln = [(x_0 - 1)*exp(-t) + 1 y_0*exp(-t) z_0*exp(-t)]; %! assert (isequal (soln, exact_soln)) %! end symbolic-3.1.1/inst/@sym/ei.m0000644000000000000000000000336514405647405012703 0ustar %% Copyright (C) 2015, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym ei (@var{x}) %% Symbolic exponential integral (Ei) function. %% %% Definition and example: %% @example %% @group %% syms x %% f = ei(x) %% @result{} f = (sym) Ei(x) %% rewrite(f, 'Integral') % doctest: +SKIP %% @result{} (sym) %% x %% ⌠ %% ⎮ t %% ⎮ ℯ %% ⎮ ── dt %% ⎮ t %% ⌡ %% -∞ %% @end group %% @end example %% (@strong{Note} rewriting as an integral is not yet supported.) %% %% Other examples: %% @example %% @group %% diff(f) %% @result{} (sym) %% x %% ℯ %% ── %% x %% @end group %% @end example %% %% @seealso{@@sym/expint} %% @end defmethod function y = ei(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('Ei', x); end %!test %! syms x %! f = ei(sym(0)); %! assert (double(f) == -inf) %!test %! D = [1.895117816355937 4.954234356001890]; %! A = ei(sym([1 2])); %! assert (all (abs(double(A) - D) < 1e-15)) symbolic-3.1.1/inst/@sym/eig.m0000644000000000000000000001154214405647405013046 0ustar %% Copyright (C) 2014, 2016, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {@var{Lambda} =} eig (@var{A}) %% @deftypemethodx @@sym {[@var{V}, @var{D}] =} eig (@var{A}) %% Symbolic eigenvalues/eigenvectors of a matrix. %% %% Example: %% @example %% @group %% A = sym([2 4; 6 8]); %% sort(eig(A)) %% @result{} ans = (sym 2×1 matrix) %% ⎡5 - √33⎤ %% ⎢ ⎥ %% ⎣5 + √33⎦ %% @end group %% @end example %% %% We can also compute the eigenvectors: %% @example %% @group %% @c doctest: +XFAIL_UNLESS(pycall_sympy__ ('return Version(spver) >= Version("1.8")')) %% [V, D] = eig(A) %% @result{} V = (sym 2×2 matrix) %% ⎡ √33 1 1 √33⎤ %% ⎢- ─── - ─ - ─ + ───⎥ %% ⎢ 6 2 2 6 ⎥ %% ⎢ ⎥ %% ⎣ 1 1 ⎦ %% @result{} D = (sym 2×2 matrix) %% ⎡5 - √33 0 ⎤ %% ⎢ ⎥ %% ⎣ 0 5 + √33⎦ %% @end group %% @end example %% The eigenvectors are the columns of @var{V}; we can extract one %% and check: %% @example %% @group %% @c doctest: +XFAIL_UNLESS(pycall_sympy__ ('return Version(spver) >= Version("1.8")')) %% v = V(:, 1) %% @result{} v = (sym 2×1 matrix) %% ⎡ √33 1⎤ %% ⎢- ─── - ─⎥ %% ⎢ 6 2⎥ %% ⎢ ⎥ %% ⎣ 1 ⎦ %% lambda = D(1,1) %% @result{} lambda = (sym) 5 - √33 %% @end group %% @group %% simplify(A*v - lambda*v) %% @result{} ans = (sym 2×1 matrix) %% ⎡0⎤ %% ⎢ ⎥ %% ⎣0⎦ %% @end group %% @end example %% %% @strong{Note}: the generalized eigenvalue problem is not yet supported. %% %% @seealso{@@sym/svd} %% @end deftypemethod function [V, D] = eig(A, B) if (nargin == 1) % no-op elseif (nargin == 2) error('eig: generalized eigenvalue problem not implemented') else print_usage (); end if (nargout <= 1) cmd = { '(A,) = _ins' 'if not A.is_Matrix:' ' A = sp.Matrix([A])' 'd = A.eigenvals()' 'if len(d) == 0:' ' raise(ValueError("failed to find eigenvalues"))' 'L = []' 'for (e, m) in d.items():' ' L.extend([e]*m)' 'L = sympy.Matrix(L)' 'return L,' }; V = pycall_sympy__ (cmd, sym(A)); else % careful, geometric vs algebraic mult, use m cmd = { '(A,) = _ins' 'if not A.is_Matrix:' ' A = sp.Matrix([A])' 'd = A.eigenvects()' 'if len(d) == 0:' ' raise(ValueError("failed to find eigenvalues"))' 'V = sp.zeros(A.shape[0], 0)' % empty 'L = []' 'for (e, m, bas) in d:' ' L.extend([e]*m)' ' if len(bas) < m:' ' bas.extend([bas[0]]*(m-len(bas)))' ' for v in bas:' ' V = V.row_join(v)' 'D = diag(*L)' 'return V, D' }; [V, D] = pycall_sympy__ (cmd, sym(A)); end end %!test %! % basic %! A = [1 2; 3 4]; %! B = sym(A); %! sd = eig(A); %! s = eig(B); %! s2 = double(s); %! assert (norm(sort(s2) - sort(sd)) <= 10*eps) %!test %! % scalars %! syms x %! a = sym(-10); %! assert (isequal (eig(a), a)) %! assert (isequal (eig(x), x)) %!test %! % diag, multiplicity %! A = diag([6 6 7]); %! B = sym(A); %! e = eig(B); %! assert (isequal (size (e), [3 1])) %! assert (sum(logical(e == 6)) == 2) %! assert (sum(logical(e == 7)) == 1) %!test %! % matrix with symbols %! syms x y positive %! A = [x+9 y; sym(0) 6]; %! s = eig(A); %! s = simplify(s); %! assert (isequal (s, [x+9; 6]) || isequal (s, [6; x+9])) %!test %! % eigenvects %! e = sym([5 5 5 6 7]); %! A = diag(e); %! [V, D] = eig(A); %! assert (isequal (diag(D), e.')) %! assert (isequal (V, diag(sym([1 1 1 1 1])))) %!test %! % alg/geom mult, eigenvects %! e = sym([5 5 5 6]); %! A = diag(e); %! A(1,2) = 1; %! [V, D] = eig(A); %! assert (isequal (diag(D), e.')) %! assert (sum(logical(V(1,:) ~= 0)) == 2) %! assert (sum(logical(V(2,:) ~= 0)) == 0) %! assert (sum(logical(V(3,:) ~= 0)) == 1) %! assert (sum(logical(V(4,:) ~= 0)) == 1) symbolic-3.1.1/inst/@sym/ellipke.m0000644000000000000000000000306114405647405013724 0ustar %% Copyright (C) 2016-2017 Lagu %% Copyright (C) 2017, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym [@var{K}, @var{E}] = ellipke (@var{m}) %% Complete elliptic integrals of the first and second kinds. %% %% Example: %% @example %% @group %% syms m %% [K, E] = ellipke (m) %% @result{} K = (sym) K(m) %% @result{} E = (sym) E(m) %% @end group %% @end example %% %% @seealso{ellipke, @@sym/ellipticK, @@sym/ellipticE} %% @end defmethod function varargout = ellipke(m) if (nargin ~= 1 || nargout > 2) print_usage (); end if (nargout == 0 || nargout == 1) varargout = {ellipticK(m)}; else varargout = {ellipticK(m) ellipticE(m)}; end end %!error ellipke (sym(1), 2) %!test %! for i = 2:10 %! [K E] = ellipke (sym (1)/i); %! [k e] = ellipke (1/i); %! assert (double ([K E]), [k e], 2*eps) %! end symbolic-3.1.1/inst/@sym/ellipticCE.m0000644000000000000000000000357614405647405014327 0ustar %% Copyright (C) 2016-2017 Lagu %% Copyright (C) 2017, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym ellipticCE (@var{m}) %% Complementary complete elliptic integral of the second kind. %% %% The complete elliptic integral (of the second kind) with the %% complementary parameter @code{1 - @var{m}} is given by: %% @example %% @group %% syms m %% ellipticCE (m) %% @result{} ans = (sym) E(1 - m) %% @end group %% @end example %% %% Examples: %% @example %% @group %% ellipticCE (sym(1)/3) %% @result{} ans = (sym) E(2/3) %% vpa (ans) %% @result{} (sym) 1.2611859497426054059627955614384 %% @end group %% @end example %% %% There are other conventions for the inputs of elliptic integrals, %% @pxref{@@sym/ellipticF}. %% %% @seealso{@@sym/ellipticE} %% @end defmethod function y = ellipticCE(m) if (nargin > 1) print_usage (); end y = ellipticE (sym (pi)/2, 1 - m); end %!error ellipticCE (sym (1), 2) %!assert (isequal (ellipticCE (sym (0)), sym (1))) %!assert (isequal (ellipticCE (sym (1)), sym (pi)/2)) %!assert (double (ellipticCE (sym (pi)/4)), 1.482786927, 10e-10) %!assert (double (ellipticCE (sym (pi)/2)), 1.775344699, 10e-10) symbolic-3.1.1/inst/@sym/ellipticCK.m0000644000000000000000000000347614405647405014334 0ustar %% Copyright (C) 2016-2017 Lagu %% Copyright (C) 2017, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym ellipticCK (@var{m}) %% Complementary complete elliptic integral of the first kind. %% %% The complete elliptic integral (of the first kind) with the %% complementary parameter @code{1 - @var{m}} is given by: %% @example %% @group %% syms m %% ellipticCK (m) %% @result{} ans = (sym) K(1 - m) %% @end group %% @end example %% %% Example: %% @example %% @group %% ellipticCK (sym (1)/4) %% @result{} ans = (sym) K(3/4) %% vpa (ans) %% @result{} (sym) 2.1565156474996432354386749988003 %% @end group %% @end example %% %% There are other conventions for the inputs of elliptic integrals, %% @pxref{@@sym/ellipticF}. %% %% @seealso{@@sym/ellipticK} %% @end defmethod function y = ellipticCK (m) if (nargin > 1) print_usage (); end y = ellipticK (1 - m); end %!error ellipticCK (sym (1), 2) %!assert (double (ellipticCK (sym (1)/2)), 1.8541, 10e-5) %!assert (double (ellipticCK (sym (101)/10)), 0.812691836806976, -3*eps) %!assert (isequal (ellipticCK (sym (1)), sym(pi)/2)) symbolic-3.1.1/inst/@sym/ellipticCPi.m0000644000000000000000000000373514405647405014510 0ustar %% Copyright (C) 2016-2017 Lagu %% Copyright (C) 2017, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym ellipticCPi (@var{nu}, @var{m}) %% Complementary complete elliptic integral of the third kind. %% %% This is the complete elliptic integral (of the third kind) with the %% complementary parameter @code{1 - @var{m}}: %% @example %% @group %% syms nu m %% ellipticCPi (nu, m) %% @result{} ans = (sym) Π(ν│1 - m) %% @end group %% @end example %% %% Examples: %% @example %% @group %% ellipticCPi (nu, sym(1)/4) %% @result{} ans = (sym) Π(ν│3/4) %% @end group %% %% @group %% ellipticCPi (sym(1)/2, sym(1)/4) %% @result{} ans = (sym) Π(1/2│3/4) %% vpa (ans) %% @result{} (sym) 3.2347734712494648531580124982005 %% @end group %% @end example %% %% There are other conventions for the inputs of elliptic integrals, %% @pxref{@@sym/ellipticF}. %% %% @seealso{@@sym/ellipticPi} %% @end defmethod function y = ellipticCPi(n, m) if (nargin ~= 2) print_usage (); end y = ellipticPi (n, sym (pi)/2, 1 - m); end %!error ellipticCPi (sym (1)) %!error ellipticCPi (sym (1), 2, 3) %!assert (double (ellipticCPi (0, sym (1)/2)), 1.854074677, 10e-10) %!assert (double (ellipticCPi (sym (6)/10, sym(71)/10)), 1.29469534336658, -20*eps) symbolic-3.1.1/inst/@sym/ellipticE.m0000644000000000000000000000675514405647405014226 0ustar %% Copyright (C) 2016-2017 Lagu %% Copyright (C) 2017, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym ellipticE (@var{m}) %% @defmethodx @@sym ellipticE (@var{phi}, @var{m}) %% Complete and incomplete elliptic integrals of the second kind. %% %% The incomplete elliptic integral of the second kind with %% amplitude @var{phi} and parameter @var{m} is given by: %% @example %% @group %% syms phi m %% ellipticE (phi, m) %% @result{} ans = (sym) E(φ│m) %% @end group %% %% @group %% rewrite (ans, 'Integral') % doctest: +SKIP %% @result{} ans = (sym) %% φ %% ⌠ %% ⎮ _________________ %% ⎮ ╱ 2 %% ⎮ ╲╱ - m⋅sin (α) + 1 dα %% ⌡ %% 0 %% @end group %% @end example %% %% The complete elliptic integral of the second kind with %% parameter @var{m} is given by: %% @example %% @group %% ellipticE (m) %% @result{} ans = (sym) E(m) %% @end group %% %% @group %% rewrite (ans, 'Integral') % doctest: +SKIP %% @result{} ans = (sym) %% π %% ─ %% 2 %% ⌠ %% ⎮ _________________ %% ⎮ ╱ 2 %% ⎮ ╲╱ - m⋅sin (α) + 1 dα %% ⌡ %% 0 %% @end group %% @end example %% %% Examples: %% @example %% @group %% vpa (ellipticE (sym (1), sym (1)/10)) %% @result{} (sym) 0.98620694978157550636951680164874 %% @end group %% %% @group %% vpa (ellipticE (sym (-pi)/4)) %% @result{} (sym) 1.8443492468732292114663773247580 %% @end group %% @end example %% %% There are other conventions for the inputs of elliptic integrals, %% @pxref{@@sym/ellipticF}. %% %% @seealso{@@sym/ellipke, @@sym/ellipticK, @@sym/ellipticPi} %% @end defmethod function y = ellipticE (phi, m) if (nargin == 1) m = phi; phi = sym (pi)/2; elseif (nargin == 2) % no-op else print_usage (); end y = elementwise_op ('elliptic_e', sym (phi), sym (m)); end %!error ellipticE (sym(1), 2, 3) %!assert (double (ellipticE (sym (-105)/10)), 3.70961391, 10e-9) %!assert (double (ellipticE (sym (-pi)/4)), 1.844349247, 10e-10) %!assert (double (ellipticE (sym (0))), 1.570796327, 10e-10) %!assert (double (ellipticE (sym (1))), 1, 10e-1) %!test %! % compare to Maple %! us = vpa (ellipticE (sym(7)/6, sym(13)/7), 40); %! % > evalf(EllipticE(sin(7/6), sqrt(13/7)), 40); %! maple = vpa ('0.6263078268598504591831743625971763209496', 40) + ... %! vpa ('0.1775496232203171126975790989055865596501j', 40); %! assert (abs (double (maple - us)), 0, 2e-39) %!test %! % compare to Maple %! us = vpa (ellipticE (sym(8)/7), 40); %! % > evalf(EllipticE(sqrt(8/7)), 40); %! maple = vpa ('0.8717182992576322508542205614105802333270', 40) + ... %! vpa ('0.1066754320328976949531350910798010526685j', 40); %! assert (abs (double (maple - us)), 0, 2e-39) symbolic-3.1.1/inst/@sym/ellipticF.m0000644000000000000000000000701014405647405014210 0ustar %% Copyright (C) 2016-2017 Lagu %% Copyright (C) 2017, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym ellipticF (@var{phi}, @var{m}) %% Incomplete elliptic integral of the first kind. %% %% The incomplete elliptic integral of the first kind with %% amplitude @var{phi} and parameter @var{m} is given by: %% @example %% @group %% syms phi m %% ellipticF (phi, m) %% @result{} ans = (sym) F(φ│m) %% @end group %% %% @group %% rewrite (ans, 'Integral') % doctest: +SKIP %% @result{} ans = (sym) %% φ %% ⌠ %% ⎮ 1 %% ⎮ ──────────────────── dα %% ⎮ _________________ %% ⎮ ╱ 2 %% ⎮ ╲╱ - m⋅sin (α) + 1 %% ⌡ %% 0 %% @end group %% @end example %% %% Example: %% @example %% @group %% vpa (ellipticF (sym (1), sym (-1))) %% @result{} (sym) 0.89639378946289458637047451642060 %% @end group %% @end example %% %% For the complete elliptic integral (of the first kind), @pxref{@@sym/ellipticK}. %% %% @strong{Note:} %% this function (and other elliptic integrals in the Symbolic package) %% follow the Abramowitz and Stegun convention for the ``parameter'' %% @iftex %% @math{m}. %% @end iftex %% @ifnottex %% @var{m}. %% @end ifnottex %% Other sources and software may use different conventions, such as %% @iftex %% the ``elliptic modulus'' @math{k} %% or the ``modular angle'' @math{\alpha}, %% related by @math{m = k^2 = \sin^2(\alpha)}. %% @end iftex %% @ifnottex %% the ``elliptic modulus'' k %% or the ``modular angle'' α, %% related by @code{@var{m} = k^2 = sin^2(α)}. %% @end ifnottex %% They may define these functions in terms of the sine of the amplitude %% @iftex %% @math{\sin(\phi)}. %% @end iftex %% @ifnottex %% @code{sin(@var{phi})}. %% @end ifnottex %% For example, Maple uses the elliptic modulus and the sine of the amplitude. %% %% @seealso{@@sym/ellipticK, @@sym/ellipticE, @@sym/ellipticPi} %% @end defmethod function y = ellipticF (phi, m) if (nargin ~= 2) print_usage (); end % y = ellipticPi (0, phi, m); y = elementwise_op ('elliptic_f', sym (phi), sym (m)); end %!error ellipticF (sym(1)) %!error ellipticF (sym(1), 2, 3) %!assert (double (ellipticF (sym (pi)/3, sym (-105)/10)), 0.6184459461, 10e-11) %!assert (double (ellipticF (sym (pi)/4, sym (-pi))), 0.6485970495, 10e-11) %!assert (double (ellipticF (sym (1), sym (-1))), 0.8963937895, 10e-11) %!assert (double (ellipticF (sym (pi)/6, sym (0))), 0.5235987756, 10e-11) %!test %! % compare to Maple %! us = vpa (ellipticF (sym(11)/10, sym(9)/4), 40); %! % > evalf(EllipticF(sin(11/10), sqrt(9/4)), 40); %! maple = vpa ('1.206444996991058996424988192917728014427', 40) - ... %! vpa ('0.8157358125823472313001683083685348517476j', 40); %! assert (abs (double (maple - us)), 0, 1e-39) symbolic-3.1.1/inst/@sym/ellipticK.m0000644000000000000000000000633114405647405014222 0ustar %% Copyright (C) 2016-2017 Lagu %% Copyright (C) 2017, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym ellipticK (@var{m}) %% Complete elliptic integral of the first kind. %% %% The complete elliptic integral of the first kind %% with parameter @var{m} is defined by: %% @example %% @group %% syms m %% ellipticK (m) %% @result{} ans = (sym) K(m) %% @end group %% %% @group %% rewrite (ans, 'Integral') % doctest: +SKIP %% @result{} ans = (sym) %% π %% ─ %% 2 %% ⌠ %% ⎮ 1 %% ⎮ ────────────────── dα %% ⎮ _______________ %% ⎮ ╱ 2 %% ⎮ ╲╱ 1 - m⋅sin (α) %% ⌡ %% 0 %% @end group %% @end example %% %% Examples: %% @example %% @group %% diff (ellipticK (m), m) %% @result{} (sym) %% -(1 - m)⋅K(m) + E(m) %% ──────────────────── %% 2⋅m⋅(1 - m) %% @end group %% %% @group %% vpa (ellipticK (sym (pi)/4)) %% @result{} (sym) 2.2252536839853959577044373301346 %% @end group %% @end example %% %% There are other conventions for the inputs of elliptic integrals, %% @pxref{@@sym/ellipticF}. %% %% @seealso{@@sym/ellipke, @@sym/ellipticF, @@sym/ellipticE, @@sym/ellipticPi} %% @end defmethod function y = ellipticK (m) if (nargin > 1) print_usage (); end % y = ellipticF (sym (pi)/2, m); y = elementwise_op ('elliptic_k', m); end %!error ellipticK (sym(1), 2) %!assert (isequal (ellipticK (sym (0)), sym (pi)/2)) %!assert (isequal (ellipticK (sym (-inf)), sym (0))) %!assert (double (ellipticK (sym (1)/2)), 1.854074677, 10e-10) %!assert (double (ellipticK (sym (pi)/4)), 2.225253684, 10e-10) %!assert (double (ellipticK (sym (-55)/10)), 0.9324665884, 10e-11) %!test %! % compare to double ellipke %! m = 1/5; %! ms = sym(1)/5; %! [K, E] = ellipke (m); %! assert (double (ellipticK (ms)), K, -1e-15) %! assert (double (ellipticE (ms)), E, -1e-15) %!test %! % compare to double ellipke %! if (exist ('OCTAVE_VERSION', 'builtin')) %! m = -10.3; %! ms = -sym(103)/10; %! [K, E] = ellipke (m); %! assert (double (ellipticK (ms)), K, -1e-15) %! assert (double (ellipticE (ms)), E, -1e-15) %! end %!test %! % compare to Maple %! us = vpa (ellipticK (sym (7)), 40); %! % > evalf(EllipticK(sqrt(7)), 40); %! maple = vpa ('0.6168027921799632674669917683443602673441', 40) - ... %! vpa ('0.9114898734184488922164103102629560336918j', 40); %! assert (abs (double (maple - us)), 0, 1e-39) symbolic-3.1.1/inst/@sym/ellipticPi.m0000644000000000000000000001116214405647405014376 0ustar %% Copyright (C) 2016-2017 Lagu %% Copyright (C) 2017, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym y = ellipticPi (@var{nu}, @var{m}) %% @defmethodx @@sym y = ellipticPi (@var{nu}, @var{phi}, @var{m}) %% Complete and incomplete elliptic integrals of the third kind. %% %% Incomplete elliptic integral of the third kind with characteristic %% @var{nu}, amplitude @var{phi} and parameter @var{m}: %% @example %% @group %% syms nu phi m %% ellipticPi (nu, phi, m) %% @result{} (sym) Π(ν; φ│m) %% @end group %% %% @group %% rewrite (ans, 'Integral') % doctest: +SKIP %% @result{} ans = (sym) %% φ %% ⌠ %% ⎮ 1 %% ⎮ ────────────────────────────────────── dα %% ⎮ _________________ %% ⎮ ╱ 2 ⎛ 2 ⎞ %% ⎮ ╲╱ - m⋅sin (α) + 1 ⋅⎝- ν⋅sin (α) + 1⎠ %% ⌡ %% 0 %% @end group %% @end example %% %% Complete elliptic integral of the third kind with characteristic %% @var{nu} and parameter @var{m}: %% @example %% @group %% ellipticPi (nu, m) %% @result{} ans = (sym) Π(ν│m) %% @end group %% %% @group %% rewrite (ans, 'Integral') % doctest: +SKIP %% @result{} ans = (sym) %% π %% ─ %% 2 %% ⌠ %% ⎮ 1 %% ⎮ ────────────────────────────────────── dα %% ⎮ _________________ %% ⎮ ╱ 2 ⎛ 2 ⎞ %% ⎮ ╲╱ - m⋅sin (α) + 1 ⋅⎝- ν⋅sin (α) + 1⎠ %% ⌡ %% 0 %% @end group %% @end example %% %% Examples: %% @example %% @group %% vpa (ellipticPi (sym (1), sym (1)/10, sym (1)/2)) %% @result{} (sym) 0.10041852861527457424263837477419 %% @end group %% %% @group %% vpa (ellipticPi (sym (pi)/4, sym (pi)/8)) %% @result{} (sym) 4.0068172051461721205075153294257 %% @end group %% @end example %% %% There are other conventions for the inputs of elliptic integrals, %% @pxref{@@sym/ellipticF}. %% %% @seealso{@@sym/ellipticF, @@sym/ellipticK, @@sym/ellipticE} %% @end defmethod function y = ellipticPi (nu, phi, m) switch nargin case 2 y = ellipticPi (nu, sym (pi)/2, phi); case 3 y = elementwise_op ('elliptic_pi', sym (nu), sym (phi), sym (m)); otherwise print_usage(); end end %!error ellipticPi (sym (1)) %!error ellipticPi (sym (1), 2, 3, 4) %!assert (double (ellipticPi (sym (-23)/10, sym (pi)/4, 0)), 0.5876852228, 10e-11) %!assert (double (ellipticPi (sym (1)/3, sym (pi)/3, sym (1)/2)), 1.285032276, 10e-11) %!assert (double (ellipticPi (sym (2), sym (pi)/6, sym (2))), 0.7507322117, 10e-11) %!xtest %! % FIXME: search/report upstream %! assert (double (ellipticPi (sym (-1), 0, sym (1))), 0) %!xtest %! % FIXME: this is a regression somewhere: loss of precision: Issue #1064 %! % compare to Maple, complete %! us = vpa (ellipticPi (sym(1)/6, sym(4)/3), 40); %! % > evalf(EllipticPi(sin(1/6), sqrt(4/3)), 40); %! maple = vpa ('2.019271696236161760696477679310987869058', 40) - ... %! vpa ('1.708165765120289929280805062355360570830j', 40); %! assert (abs (double (maple - us)), 0, 2e-39) %!test %! % compare to Maple, complete %! us = vpa (ellipticPi (sym(1)/6, sym(4)/3), 40); %! % > evalf(EllipticPi(sin(1/6), sqrt(4/3)), 40); %! maple = vpa ('2.019271696236161760696477679310987869058', 40) - ... %! vpa ('1.708165765120289929280805062355360570830j', 40); %! assert (abs (double (maple - us)), 0, 2e-30) %!test %! % compare to Maple, incomplete %! us = vpa (ellipticPi (sym(8)/7, sym(4)/3, sym(2)/7), 40); %! % > evalf(EllipticPi(sin(4/3), 8/7, sqrt(2/7)), 40); %! maple = vpa ('2.089415796799294830305265090302275542033', 40) - ... %! vpa ('4.798862045930802761256228043192491271947j', 40); %! assert (abs (double (maple - us)), 0, 6e-39) symbolic-3.1.1/inst/@sym/end.m0000644000000000000000000000371314405647405013051 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym end {(@var{A})} %% @defopx Operator @@sym {@var{A}(@var{n}:end)} {} %% @defopx Operator @@sym {@var{A}(end:@var{m})} {} %% Overloaded end for symbolic arrays. %% %% Examples: %% @example %% @group %% A = sym([10 11 12]) %% @result{} A = (sym) [10 11 12] (1×3 matrix) %% %% A(2:end) %% @result{} (sym) [11 12] (1×2 matrix) %% %% A(end-1:end) %% @result{} (sym) [11 12] (1×2 matrix) %% @end group %% @end example %% @end defop function r = end (obj, index_pos, num_indices) if ~(isscalar(index_pos)) error('can this happen?') end if (num_indices == 1) r = numel(obj); elseif (num_indices == 2) d = size(obj); r = d(index_pos); else obj index_pos num_indices error('now whut?'); end end %!test %! % scalar %! syms x %! y = x(1:end); %! assert (isequal (x, y)) %!test %! % vector %! syms x %! A = [1 2 x 4]; %! y = A(end-1:end); %! assert (isequal (y, [x 4])) %!test %! % subset of matrix %! syms x %! A = [1 2 x; x 3 9; 4 x*x 6]; %! y = A(end,1:end-1); %! assert (isequal (y, [4 x*x])) %!test %! % linear index of matrix %! syms x %! A = [1 2 x; x 3 9]; %! y = A(end); %! assert (isequal (y, sym(9))) symbolic-3.1.1/inst/@sym/eq.m0000644000000000000000000001125714405647405012712 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym eq {(@var{a}, @var{b})} %% @defopx Operator @@sym {@var{a} == @var{b}} {} %% Test for symbolic equality, and/or define equation. %% %% The code @code{@var{a} == @var{b}} can do one of two things: %% @itemize %% @item Return a symbolic boolean value if it can quickly determine %% that @code{a} and @code{b} are the same or not: %% @example %% @group %% sym(1) == sym(pi) %% @result{} (sym) False %% @end group %% @end example %% @item Otherwise, return a symbolic equation: %% @example %% @group %% syms x y %% 3*y == 24*x %% @result{} ans = (sym) 3⋅y = 24⋅x %% solve(ans, y) %% @result{} (sym) 8⋅x %% @end group %% @end example %% @end itemize %% %% Exactly which behaviour happens is a potential source of bugs! %% When @var{a} and/or @var{b} contain variables, we @emph{usually} %% (but not always) expect a symbolic equation. Compare: %% @example %% @group %% x == 3*x %% @result{} (sym) x = 3⋅x %% x == x %% @result{} (sym) True %% @end group %% @end example %% %% If you wish to force a boolean result, @pxref{@@sym/logical} and @pxref{@@sym/isAlways}: %% @example %% @group %% logical(x == 3*x) %% @result{} 0 %% islogical(ans) %% @result{} 1 %% @end group %% %% @group %% syms x y z %% eqn = x*(y + z) == x*y + x*z %% @result{} eqn = (sym) x⋅(y + z) = x⋅y + x⋅z %% logical(eqn) %% @result{} 0 %% isAlways(eqn) %% @result{} 1 %% @end group %% @end example %% %% Currently, these is no robust way to force an an equality equation %% @code{x == x}. %% %% @seealso{@@sym/logical, @@sym/isAlways, @@sym/isequal, @@sym/ne, @@sym/le} %% @end defop function t = eq(x, y) if (nargin ~= 2) print_usage (); end t = ineq_helper('[donotuse]', 'Eq', sym(x), sym(y)); end %!test %! % simple tests with scalar numbers %! assert (logical (sym(1) == sym(1))) %! assert (logical (sym(1) == 1)) %! assert (~logical (sym(1) == 0)) %! assert (isequal (sym(1) == sym(1), sym(true))) %! assert (isequal (sym(1) == 1, sym(true))) %! assert (isequal (sym(1) == 0, sym(false))) %!test %! % Type of the output is sym or logical? %! % FIXME: in current version, they are sym %! e = sym(1) == sym(1); %! %assert (islogical (e)) %! assert (isa (e, 'sym')) %!test %! % things involving a variable are usually not bool but sym. %! % (SMT behaviour says always, FIXME: currently we differ.) %! syms x %! e = x == 0; %! assert (~islogical (e)) %! assert (isa (e, 'sym')) %!test %! % ... except of course via cancelation %! syms x %! e = x - x == 0; %! assert (logical (e)) %! assert (isequal (e, sym(true))) %!test %! % array == array %! a = sym([1 2; 3 4]); %! y = a == a; %! assert (isequal( size(y), [2 2])) %! assert (isequal (y, sym([true true; true true]))) %! assert (all(all(y))) %! y = a == 1; %! assert (isequal( size(y), [2 2])) %! assert (isequal (y, sym([true false; false false]))) %! assert (any(any(y))) %! y = a == 42; %! assert (isequal( size(y), [2 2])) %! assert (isequal (y, sym([false false; false false]))) %!test %! % more array == array %! D = [0 1; 2 3]; %! A = [sym(0) 1; sym(2) 3]; %! DZ = D - D; %! assert (isequal (logical(A == A), [true true; true true])) %! assert (isequal (logical(A == D), [true true; true true])) %! assert (isequal (logical(A - D == DZ), [true true; true true])) %! assert (all (all ( A == A ))) %! assert (all (all ( A == D ))) %! assert (all (all ( A - D == DZ ))) %!test %! % logical output, right shape, etc %! t = true; f = false; %! a = sym([0 1 2; 3 4 5]); %! b = sym([0 1 1; 3 5 5]); %! e = a == b; %! eexp = sym(logical([1 1 0; 1 0 1])); %! assert (isequal (e, eexp)) %! a = sym([0 1 2]); %! b = sym([0 1 1]); %! e = a == b; %! eexp = sym(logical([1 1 0])); %! assert (isequal (e, eexp)) %! e = a' == b'; %! eexp = eexp.'; % is/was bug here with ' %! assert (isequal (e, eexp)) %!test %! % empty matrices compare to correct empty size %! a = zeros (sym(3), 0); %! assert (size (a == a), [3, 0]) %! a = zeros (sym(0), 2); %! assert (size (a == a), [0, 2]) symbolic-3.1.1/inst/@sym/equationsToMatrix.m0000644000000000000000000001434214405647405016003 0ustar %% Copyright (C) 2016 Lagu %% Copyright (C) 2016, 2018-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {[@var{A}, @var{b}] =} equationsToMatrix (@var{eqns}, @var{vars}) %% @deftypemethodx @@sym {[@var{A}, @var{b}] =} equationsToMatrix (@var{eqns}) %% @deftypemethodx @@sym {[@var{A}, @var{b}] =} equationsToMatrix (@var{eq1}, @var{eq2}, @dots{}) %% @deftypemethodx @@sym {[@var{A}, @var{b}] =} equationsToMatrix (@var{eq1}, @dots{}, @var{v1}, @var{v2}, @dots{}) %% Convert set of linear equations to matrix form. %% %% In its simplest form, equations @var{eq1}, @var{eq2}, etc can be %% passed as inputs: %% @example %% @group %% syms x y z %% [A, b] = equationsToMatrix (x + y == 1, x - y + 1 == 0) %% @result{} A = (sym 2×2 matrix) %% %% ⎡1 1 ⎤ %% ⎢ ⎥ %% ⎣1 -1⎦ %% %% @result{} b = (sym 2×1 matrix) %% %% ⎡1 ⎤ %% ⎢ ⎥ %% ⎣-1⎦ %% @end group %% @end example %% In this case, appropriate variables @emph{and their ordering} will be %% determined automatically using @code{symvar} (@pxref{@@sym/symvar}). %% %% In some cases it is important to specify the variables as additional %% inputs @var{v1}, @var{v2}, etc: %% @example %% @group %% syms a %% [A, b] = equationsToMatrix (a*x + y == 1, y - x == a) %% @print{} ??? ... nonlinear... %% %% [A, b] = equationsToMatrix (a*x + y == 1, y - x == a, x, y) %% @result{} A = (sym 2×2 matrix) %% %% ⎡a 1⎤ %% ⎢ ⎥ %% ⎣-1 1⎦ %% %% @result{} b = (sym 2×1 matrix) %% %% ⎡1⎤ %% ⎢ ⎥ %% ⎣a⎦ %% @end group %% @end example %% %% The equations and variables can also be passed as vectors @var{eqns} %% and @var{vars}: %% @example %% @group %% eqns = [x + y - 2*z == 0, x + y + z == 1, 2*y - z + 5 == 0]; %% [A, B] = equationsToMatrix (eqns, [x y]) %% @result{} A = (sym 3×2 matrix) %% %% ⎡1 1⎤ %% ⎢ ⎥ %% ⎢1 1⎥ %% ⎢ ⎥ %% ⎣0 2⎦ %% %% B = (sym 3×1 matrix) %% %% ⎡ 2⋅z ⎤ %% ⎢ ⎥ %% ⎢1 - z⎥ %% ⎢ ⎥ %% ⎣z - 5⎦ %% @end group %% @end example %% @seealso{@@sym/solve} %% @end deftypemethod function [A, b] = equationsToMatrix(varargin) % when Symbols are specified, this won't be used s = findsymbols (varargin); cmd = {'L, symvars = _ins' 'if not isinstance(L[-1], MatrixBase):' ' if isinstance(L[-1], Symbol):' % Symbol given, fill vars... ' vars = list()' ' for i in reversed(range(len(L))):' ' if isinstance(L[i], Symbol):' ' vars = [L.pop(i)] + vars' ' else:' % ... until we find a non-Symbol ' break' ' else:' ' vars = symvars' 'else:' ' if len(L) == 1:' % we have only a list of equations ' vars = symvars' ' else:' ' vars = L.pop(-1)' 'if len(L) == 1:' % might be matrix of eqns, don't want [Matrix] ' L = L[0]' 'vars = list(vars)' 'A, B = linear_eq_to_matrix(L, vars)' 'return True, A, B' }; for i = 1:length(varargin) varargin{i} = sym (varargin{i}); end [s, A, b] = pycall_sympy__ (cmd, varargin, s); if ~s error('Cannot convert to matrix; system may be nonlinear.'); end end %!test %! syms x y z %! [A, B] = equationsToMatrix ([x + y - z == 1, 3*x - 2*y + z == 3, 4*x - 2*y + z + 9 == 0], [x, y, z]); %! a = sym ([1 1 -1; 3 -2 1; 4 -2 1]); %! b = sym ([1; 3; -9]); %! assert (isequal (A, a)) %! assert (isequal (B, b)) %!test %! syms x y z %! A = equationsToMatrix ([3*x + -3*y - 5*z == 9, 4*x - 7*y + -3*z == -1, 4*x - 9*y - 3*z + 2 == 0], [x, y, z]); %! a = sym ([3 -3 -5; 4 -7 -3; 4 -9 -3]); %! assert (isequal (A, a)) %!test %! syms x y %! [A, B] = equationsToMatrix ([3*x + 9*y - 5 == 0, -8*x - 3*y == -2]); %! a = sym ([3 9; -8 -3]); %! b = sym ([5; -2]); %! assert (isequal (A, a)) %! assert (isequal (B, b)) %!test %! % override symvar order %! syms x y %! [A, B] = equationsToMatrix ([3*x + 9*y - 5 == 0, -8*x - 3*y == -2], [y x]); %! a = sym ([9 3; -3 -8]); %! b = sym ([5; -2]); %! assert (isequal (A, a)) %! assert (isequal (B, b)) %!test %! syms x y z %! [A, B] = equationsToMatrix ([x - 9*y + z == -5, -9*y*z == -5], [y, x]); %! a = sym ([[-9 1]; -9*z 0]); %! b = sym ([-5 - z; -5]); %! assert (isequal (A, a)) %! assert (isequal (B, b)) %!test %! syms x y %! [A, B] = equationsToMatrix (-6*x + 4*y == 5, 4*x - 4*y - 5, x, y); %! a = sym ([-6 4; 4 -4]); %! b = sym ([5; 5]); %! assert (isequal (A, a)) %! assert (isequal (B, b)) %!test %! % vertical list of equations %! syms x y %! [A, B] = equationsToMatrix ([-6*x + 4*y == 5; 4*x - 4*y - 5], [x y]); %! a = sym ([-6 4; 4 -4]); %! b = sym ([5; 5]); %! assert (isequal (A, a)) %! assert (isequal (B, b)) %!test %! syms x y %! [A, B] = equationsToMatrix (5*x == 1, y, x - 6*y - 7, y); %! a = sym ([0; 1; -6]); %! b = sym ([1 - 5*x; 0; -x + 7]); %! assert (isequal (A, a)) %! assert (isequal (B, b)) %!error %! syms x y %! [A, B] = equationsToMatrix (x^2 + y^2 == 1, x - y + 1, x, y); %!test %! % single equation %! syms x %! [A, B] = equationsToMatrix (3*x == 2, x); %! a = sym (3); %! b = sym (2); %! assert (isequal (A, a)) %! assert (isequal (B, b)) %!test %! % single equation w/ symvar %! syms x %! [A, B] = equationsToMatrix (3*x == 2); %! a = sym (3); %! b = sym (2); %! assert (isequal (A, a)) %! assert (isequal (B, b)) %!error %! syms x %! equationsToMatrix (3*x == 2, [x x]) symbolic-3.1.1/inst/@sym/erf.m0000644000000000000000000000325614405647405013061 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym erf (@var{x}) %% Symbolic erf function. %% %% Example: %% @example %% @group %% syms x %% y = erf (x) %% @result{} y = (sym) erf(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = erf(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('erf', x); end %!error erf (sym(1), 2) %!assert (isequaln (erf (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = erf(x); %! f2 = erf(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = erf(A); %! f2 = erf(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = erf (d); %! f = erf (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/erfc.m0000644000000000000000000000327414405647405013224 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym erfc (@var{x}) %% Symbolic erfc function. %% %% Example: %% @example %% @group %% syms x %% y = erfc (x) %% @result{} y = (sym) erfc(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = erfc(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('erfc', x); end %!error erfc (sym(1), 2) %!assert (isequaln (erfc (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = erfc(x); %! f2 = erfc(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = erfc(A); %! f2 = erfc(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = erfc (d); %! f = erfc (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/erfcinv.m0000644000000000000000000000334614405647405013741 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym erfcinv (@var{x}) %% Symbolic erfcinv function. %% %% Example: %% @example %% @group %% syms x %% y = erfcinv (x) %% @result{} y = (sym) erfcinv(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = erfcinv(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('erfcinv', x); end %!error erfcinv (sym(1), 2) %!assert (isequaln (erfcinv (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = erfcinv(x); %! f2 = erfcinv(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = erfcinv(A); %! f2 = erfcinv(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = erfcinv (d); %! f = erfcinv (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/erfi.m0000644000000000000000000000331014405647405013221 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym erfi (@var{x}) %% Symbolic erfi function. %% %% Example: %% @example %% @group %% syms x %% y = erfi (x) %% @result{} y = (sym) erfi(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = erfi(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('erfi', x); end %!error erfi (sym(1), 2) %!assert (isequaln (erfi (sym(nan)), sym(nan))) %!shared x, d %! d = 0; %! x = sym('0'); %!test %! f1 = erfi(x); %! f2 = 0; %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = erfi(A); %! f2 = 0; %! f2 = [f2 f2; f2 f2]; %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = erfi (d); %! f = erfi (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/erfinv.m0000644000000000000000000000333414405647405013573 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym erfinv (@var{x}) %% Symbolic erfinv function. %% %% Example: %% @example %% @group %% syms x %% y = erfinv (x) %% @result{} y = (sym) erfinv(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = erfinv(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('erfinv', x); end %!error erfinv (sym(1), 2) %!assert (isequaln (erfinv (sym(nan)), sym(nan))) %!shared x, d %! d = 1/2; %! x = sym('1/2'); %!test %! f1 = erfinv(x); %! f2 = erfinv(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = erfinv(A); %! f2 = erfinv(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = erfinv (d); %! f = erfinv (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/euler.m0000644000000000000000000000613614405647405013421 0ustar %% Copyright (C) 2017-2019, 2022-2023 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {@var{Em} =} euler (@var{m}) %% @deftypemethodx @@sym {@var{p} =} euler (@var{m}, @var{x}) %% Return symbolic Euler numbers or Euler polynomials. %% %% Examples: %% @example %% @group %% euler (sym(0)) %% @result{} (sym) 1 %% euler (sym(32)) %% @result{} (sym) 177519391579539289436664789665 %% @end group %% @end example %% %% Polynomial example: %% @example %% @group %% syms x %% euler (2, x) %% @result{} (sym) %% 2 %% x - x %% @end group %% %% @group %% euler (10, x) %% @result{} (sym) %% 10 9 7 5 3 %% x - 5⋅x + 30⋅x - 126⋅x + 255⋅x - 155⋅x %% @end group %% @end example %% %% @seealso{@@double/euler, @@sym/bernoulli} %% @end deftypemethod function r = euler (varargin) if (nargin ~= 1 && nargin ~= 2) print_usage (); end for i = 1:nargin varargin{i} = sym (varargin{i}); end r = elementwise_op ('euler', varargin{:}); end %!error euler (sym(1), 2, 3) %!assert (isequal (euler (sym(0)), sym(1))) %!test %! m = sym([0 1 2; 8 10 888889]); %! A = euler (m); %! B = sym([1 0 -1; 1385 -50521 0]); %! assert (isequal (A, B)) %!test %! syms x %! assert (isequal (euler(6, x), x^6 - 3*x^5 + 5*x^3 - 3*x)) %!assert (isnan (euler (3, sym(nan)))) %!test %! syms m x %! em = euler (m, x); %! A = subs(em, [m x], [2 sym(pi)]); %! assert (isequal (A, sym(pi)^2 - sym(pi))) %!test %! % vectorized %! syms x y %! A = euler([1; 2], [x; y]); %! B = [x - sym(1)/2; y^2 - y]; %! assert (isequal (A, B)) %!test %! % round trip %! syms m z %! f = euler (m, z); %! h = function_handle (f, 'vars', [m z]); %! A = h (2, 2.2); %! B = euler (2, 2.2); %! assert (A, B) %!test %! % compare vpa to maple: Digits:=34; evalf(euler(13, exp(1)+Pi*I/13)); %! A = vpa('1623.14184180556920918624604530515') + ... %! vpa('4270.98066989140286451493108809574')*1i; %! z = vpa (exp(1), 32) + vpa(pi, 32)/13*1i; %! B = euler (13, z); %! relerr = abs(double(abs((B - A)/A))); %! assert (relerr < 20*eps); %!xtest %! % as above, high-prec result broken in 1.12: https://github.com/sympy/sympy/issues/24156 %! A = vpa('1623.14184180556920918624604530515') + ... %! vpa('4270.98066989140286451493108809574')*1i; %! z = vpa (exp(1), 32) + vpa(pi, 32)/13*1i; %! B = euler (13, z); %! relerr = abs(double(abs((B - A)/A))); %! assert (relerr < 2e-31); symbolic-3.1.1/inst/@sym/eval.m0000644000000000000000000000637314405647405013237 0ustar %% Copyright (C) 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym eval (@var{f}) %% Symbolic expression to double, taking values from workspace. %% %% For expressions without symbols, @code{eval} does the same thing %% as @code{double}: %% @example %% @group %% f = 2*sin(sym(3)) %% @result{} f = (sym) 2⋅sin(3) %% @c doctest: +SKIP_IF(compare_versions (OCTAVE_VERSION(), '6.0.0', '<')) %% eval(f) %% @result{} ans = 0.2822 %% @c doctest: +SKIP_IF(compare_versions (OCTAVE_VERSION(), '6.0.0', '<')) %% double(f) %% @result{} ans = 0.2822 %% @end group %% @end example %% %% For an expression containing symbols, @code{eval} looks in the %% workspace for variables whose names match the symbols. It then %% evaluates the expression using the values from those variables. %% For example: %% @example %% @group %% syms x y %% f = x*sin(y) %% @result{} f = (sym) x⋅sin(y) %% @end group %% %% @group %% x = 2.1 %% @result{} x = 2.1000 %% y = 2.9 %% @result{} y = 2.9000 %% @end group %% %% @group %% f %% @result{} f = (sym) x⋅sin(y) %% %% @c doctest: +SKIP_IF(compare_versions (OCTAVE_VERSION(), '6.0.0', '<')) %% eval(f) %% @result{} ans = 0.5024 %% @end group %% @end example %% %% @seealso{@@sym/subs} %% @end defmethod function g = eval(f) if (nargin ~= 1) print_usage (); end %% take values of x from the workspace in = findsymbols (f); out = {}; i = 1; while (i <= length (in)) xstr = char (in{i}); try xval = evalin ('caller', xstr); foundit = true; catch foundit = false; end if (foundit) out{i} = xval; i = i + 1; else in(i) = []; % erase that input end end try %% Fails if the workspace doesn't have values for all symbols. % Could also fail for fcns with broken "roundtrip" fh = function_handle(f, 'vars', in); g = fh(out{:}); return catch % no-op end %% Instead, try substituting and converting to double. g = subs (f, in, out); try g = double (g); catch % just g then end end %!error eval (sym(1), 2) %!assert (isnumeric (eval (sym(3)))) %!assert (isnumeric (eval (sin (sym(3))))) %!test %! syms x y %! f = 2*x*y; %! x = 3; %! y = 4; %! g = eval (f); %! assert (isequal (g, 24)) %!test %! syms x y %! f = 2*x*y; %! clear y %! x = 3; %! g = eval (f); %! assert (isequal (g, 6*sym('y'))) %!test %! % do not convert inputs to sym, for SMT compat %! nearpi = pi + 1e-14; % sym could make this pi %! x = sym('x'); %! f = 2*x; %! x = nearpi; %! d = eval (f); %! assert (abs (d - 2*pi) > 1e-15) symbolic-3.1.1/inst/@sym/exp.m0000644000000000000000000000330014405647405013067 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym exp (@var{x}) %% Symbolic exp function. %% %% Example: %% @example %% @group %% syms x %% y = exp (x) %% @result{} y = (sym) %% x %% ℯ %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = exp(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('exp', x); end %!error exp (sym(1), 2) %!assert (isequaln (exp (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = exp(x); %! f2 = exp(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = exp(A); %! f2 = exp(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = exp (d); %! f = exp (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/expand.m0000644000000000000000000000257414405647405013566 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym expand (@var{f}) %% Combine parts of a symbolic product. %% %% Example: %% @example %% @group %% syms x %% expand ((x+1)*(x+5)) %% @result{} (sym) %% 2 %% x + 6⋅x + 5 %% @end group %% @end example %% %% @seealso{@@sym/factor} %% @end defmethod function y = expand(x) y = pycall_sympy__ ( 'return sympy.expand(*_ins),', sym(x)); end %!test %! syms x %! assert (logical (x^2 + 6*x + 5 == expand ((x+5)*(x+1)))) %! assert (isequal (x^2 + 6*x + 5, expand ((x+5)*(x+1)))) %!test %! % array %! syms x %! assert (isequal (expand ([x (x+1)*x]), [x x^2+x])) symbolic-3.1.1/inst/@sym/expint.m0000644000000000000000000000616314405647405013614 0ustar %% Copyright (C) 2015, 2016, 2018-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym expint (@var{x}) %% @defmethodx @@sym expint (@var{n}, @var{x}) %% Symbolic generalized exponential integral (expint) function. %% %% Integral definition: %% @example %% @group %% syms x %% E1 = expint(x) %% @result{} E1 = (sym) E₁(x) %% rewrite(E1, 'Integral') % doctest: +SKIP %% @result{} (sym) %% ∞ %% ⌠ %% ⎮ -t⋅x %% ⎮ ℯ %% ⎮ ───── dt %% ⎮ t %% ⌡ %% 1 %% @end group %% @end example %% %% This can also be written (using the substitution @code{u = t⋅x}) as: %% @example %% @group %% @c doctest: +SKIP %% ∞ %% ⌠ %% ⎮ -u %% ⎮ ℯ %% ⎮ ─── du %% ⎮ u %% ⌡ %% x %% @end group %% @end example %% %% With two arguments, we have: %% @example %% @group %% E2 = expint(2, x) %% @result{} E2 = (sym) E₂(x) %% @end group %% @end example %% %% In general: %% @example %% @group %% syms n x %% En = expint(n, x) %% @result{} En = (sym) expint(n, x) %% rewrite(En, 'Integral') % doctest: +SKIP %% @result{} (sym) %% ∞ %% ⌠ %% ⎮ -n -t⋅x %% ⎮ t ⋅ℯ dt %% ⌡ %% 1 %% @end group %% @end example %% %% Other example: %% @example %% @group %% diff(En, x) %% @result{} (sym) -expint(n - 1, x) %% @end group %% @end example %% %% @seealso{expint, @@sym/ei} %% @end defmethod function y = expint(n, x) if (nargin == 1) x = n; n = 1; elseif (nargin == 2) % no-op else print_usage (); end y = elementwise_op ('expint', sym(n), sym(x)); end %!error expint (sym(1), 2, 3) %!test %! f1 = expint(sym(1)); %! f2 = expint(1); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! f1 = expint(sym(1i)); %! f2 = expint(1i); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [1 2; 3 4]; %! A = sym(D); %! f1 = expint(A); %! f2 = expint(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! syms x %! A = expint(x); %! B = expint(1, x); %! assert (isequal (A, B)) %!test %! syms x %! A = exp(-x)/x; %! B = expint(0, x); %! assert (isequal (A, B)) %!test %! % round trip %! syms x %! A = expint (3); %! f = expint (x); %! h = function_handle (f); %! B = h (3); %! assert (A, B, -eps) %!error %! % round trip %! syms n x %! f = expint (n, x); %! h = function_handle (f); symbolic-3.1.1/inst/@sym/expm.m0000644000000000000000000000376014405647405013256 0ustar %% Copyright (C) 2014-2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym expm (@var{A}) %% Symbolic matrix exponential. %% %% Example: %% @example %% @group %% A = [sym(4) 1; sym(0) 4] %% @result{} A = (sym 2×2 matrix) %% ⎡4 1⎤ %% ⎢ ⎥ %% ⎣0 4⎦ %% %% expm(A) %% @result{} (sym 2×2 matrix) %% ⎡ 4 4⎤ %% ⎢ℯ ℯ ⎥ %% ⎢ ⎥ %% ⎢ 4⎥ %% ⎣0 ℯ ⎦ %% @end group %% @end example %% %% @seealso{@@sym/eig} %% @end defmethod function z = expm(x) if (nargin ~= 1) print_usage (); end cmd = { 'x, = _ins' 'if not x.is_Matrix:' ' x = sp.Matrix([[x]])' 'return x.exp(),' }; z = pycall_sympy__ (cmd, x); end %!test %! % scalar %! syms x %! assert (isequal (expm(x), exp(x))) %!test %! % diagonal %! A = [sym(1) 0; 0 sym(3)]; %! B = [exp(sym(1)) 0; 0 exp(sym(3))]; %! assert (isequal (expm(A), B)) %!test %! % diagonal w/ x %! syms x positive %! A = [sym(1) 0; 0 x+2]; %! B = [exp(sym(1)) 0; 0 exp(x+2)]; %! assert (isequal (expm(A), B)) %!test %! % non-diagonal %! syms x positive %! A = [sym(1) 2; 0 x+2]; %! B = expm(A); %! C = double(subs(B, x, 4)); %! D = expm(double(subs(A, x, 4))); %! assert (max (max (abs (C - D))) <= 1e-11) symbolic-3.1.1/inst/@sym/eye.m0000644000000000000000000000506414405647405013066 0ustar %% Copyright (C) 2016 Lagu %% Copyright (C) 2017, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym eye (@var{n}) %% @defmethodx @@sym eye (@var{n}, @var{m}) %% Return an identity matrix. %% %% Example: %% @example %% @group %% y = eye (sym(3)) %% @result{} y = (sym 3×3 matrix) %% ⎡1 0 0⎤ %% ⎢ ⎥ %% ⎢0 1 0⎥ %% ⎢ ⎥ %% ⎣0 0 1⎦ %% @end group %% @end example %% %% @seealso{eye, @@sym/zeros, @@sym/ones} %% @end defmethod function y = eye(varargin) % partial workaround for issue #13: delete when/if fixed properly if ((isa (varargin{nargin}, 'char')) && (strcmp (varargin{nargin}, 'sym'))) varargin = varargin(1:(nargin-1)); end if (isa (varargin{end}, 'char')) varargin = cell2nosyms (varargin); y = eye (varargin{:}); return end for i = 1:length(varargin) varargin{i} = sym(varargin{i}); end cmd = { 'if len(_ins) == 1:' ' n, = _ins' ' try:' ' n, m = iter(n)' ' except TypeError:' ' n, m = n, n' 'else:' ' n, m = _ins' 'if n == m:' ' return eye(n)' 'return eye(max(n,m))[0:n,0:m]' }; y = pycall_sympy__ (cmd, varargin{:}); end %!test %! y = eye(sym(2)); %! x = [1 0; 0 1]; %! assert( isequal( y, sym(x))) %!test %! y = eye(sym(2), 1); %! x = [1; 0]; %! assert( isequal( y, sym(x))) %!test %! y = eye(sym(1), 2); %! x = [1 0]; %! assert( isequal( y, sym(x))) %!test %! y = eye (sym([2 3])); %! x = sym (eye ([2 3])); %! assert (isequal (y, x)) %% Check types: %!assert( isa( eye(sym(2), 'double'), 'double')) %!assert( isa( eye(3, sym(3), 'single') , 'single')) %!assert( isa( eye(3, sym(3)), 'sym')) %!assert( isa( eye(3, sym(3), 'sym'), 'sym')) %!xtest %! % Issue #13 %! assert( isa( eye(3, 3, 'sym'), 'sym')) symbolic-3.1.1/inst/@sym/ezcontour.m0000644000000000000000000000440614405647405014333 0ustar %% Copyright (C) 2017 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym ezcontour (@var{f}) %% @defmethodx @@sym ezcontour (@dots{}, @var{dom}) %% @defmethodx @@sym ezcontour (@dots{}, @var{N}) %% Simple contour plots of symbolic expressions. %% %% Example: %% @example %% @group %% syms x y %% z = sin(2*x)*sin(y) %% @result{} z = (sym) sin(2⋅x)⋅sin(y) %% @c doctest: +SKIP %% ezcontour(z) %% @end group %% @end example %% %% See help for the (non-symbolic) @code{ezcontour}, which this %% routine calls after trying to convert sym inputs to %% anonymous functions. %% %% @seealso{ezcontour, @@sym/ezsurf, @@sym/function_handle} %% @end defmethod function varargout = ezcontour(varargin) % first input is handle, shift if (ishandle (varargin{1})) i = 2; else i = 1; end assert (isa (varargin{i}, 'sym')) vars = symvar (varargin{i}); assert (length (vars) <= 2, ... 'ezcontour: function must have at most two inputs'); if (isempty (vars) || ... (length (vars) == 1 && isequal (vars, sym('x'))) || ... (length (vars) == 1 && isequal (vars, sym('y')))) %% special treatment and ordering for x, y vars = [sym('x') sym('y')]; end varargin{i} = function_handle (varargin{i}, 'vars', vars); for i = (i+1):nargin if (isa (varargin{i}, 'sym')) %% plot ranges, etc: convert syms to doubles varargin{i} = double (varargin{i}); end end h = ezcontour (varargin{:}); if (nargout) varargout{1} = h; end end %!error %! syms x y z %! ezcontour (x*y*z) symbolic-3.1.1/inst/@sym/ezmesh.m0000644000000000000000000000701614405647405013576 0ustar %% Copyright (C) 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym ezmesh (@var{z}) %% @defmethodx @@sym ezmesh (@var{f1}, @var{f2}, @var{f3}) %% @defmethodx @@sym ezmesh (@dots{}, @var{dom}) %% @defmethodx @@sym ezmesh (@dots{}, @var{N}) %% Simple 3D wireframe mesh plots of symbolic expressions. %% %% Example 3D surface mesh plot: %% @example %% @group %% syms x y %% z = sin(2*x)*sin(y) %% @result{} z = (sym) sin(2⋅x)⋅sin(y) %% ezmesh(z) % doctest: +SKIP %% @end group %% @end example %% %% Example parametric mesh of a Möbius strip: %% @example %% @group %% syms u v %% x = (1+v*cos(u/2))*cos(u) %% @result{} x = (sym) %% ⎛ ⎛u⎞ ⎞ %% ⎜v⋅cos⎜─⎟ + 1⎟⋅cos(u) %% ⎝ ⎝2⎠ ⎠ %% y = (1+v*cos(u/2))*sin(u); %% z = v*sin(u/2); %% %% ezmesh(x, y, z, [0 2*pi -0.5 0.5], 32) % doctest: +SKIP %% axis equal %% @end group %% @end example %% %% See help for the (non-symbolic) @code{ezmesh}, which this %% routine calls after trying to convert sym inputs to %% anonymous functions. %% %% @seealso{ezmesh, @@sym/ezsurf, @@sym/ezplot, @@sym/function_handle} %% @end defmethod function varargout = ezmesh(varargin) % first input is handle, shift if (ishandle(varargin{1})) firstpotsym = 2; else firstpotsym = 1; end maxnumsym = 3; firstsym = []; for i = firstpotsym:nargin if (isa(varargin{i}, 'sym')) if (i < firstpotsym + maxnumsym) % one of the fcns to plot, covert to handle fcn % Each is function of one var, and its the same var for all thissym = symvar(varargin{i}); assert(length(thissym) <= 2, ... 'ezmesh: parameterized: functions should have at most two inputs'); if (isempty(thissym)) % a number, create a constant function in a dummy variable % (0*t works around some Octave oddity on 3.8 and hg Dec 2014) thisf = inline(sprintf('%g + 0*t', double(varargin{i})), 't'); %thisf = @(t) 0*t + double(varargin{i}); % no else % check variables match (sanity check) if (isempty(firstsym)) firstsym = thissym; else assert(all(logical(thissym == firstsym)), ... 'ezmesh: all functions must be in terms of the same variables'); end thisf = function_handle(varargin{i}); end varargin{i} = thisf; else % plot ranges, etc, convert syms to doubles varargin{i} = double(varargin{i}); end end end h = ezmesh(varargin{:}); if (nargout) varargout{1} = h; end end %!error %! syms u v t %! ezmesh(u*v, 2*u*v, 3*v*t) %!error %! syms u v t %! ezmesh(u*v, 2*u*v, u*v*t) symbolic-3.1.1/inst/@sym/ezplot.m0000644000000000000000000001356314405647405013624 0ustar %% Copyright (C) 2014-2017 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym ezplot (@var{f}) %% @defmethodx @@sym ezplot (@var{f1}, @var{f2}) %% @defmethodx @@sym ezplot (@var{f}, @var{dom}) %% @defmethodx @@sym ezplot (@var{f1}, @var{f2}, @var{dom}) %% @defmethodx @@sym ezplot (@dots{}, @var{N}) %% Simple plotting of symbolic expressions. %% %% Example parametric plot of a Lissajous Curve: %% @example %% @group %% syms t %% x = cos(3*t), y = sin(2*t) %% @result{} x = (sym) cos(3⋅t) %% @result{} y = (sym) sin(2⋅t) %% %% ezplot(x, y) % doctest: +SKIP %% @end group %% @end example %% %% Example plotting the zero level curve of a function of two %% variables: %% @example %% @group %% syms x y %% f = x^2 + y^2 - 1; %% ezplot (f) % doctest: +SKIP %% @end group %% @end example %% Here the curve is defined implicitly by @code{f(x, y) == 0}, %% but we do not enter the @code{== 0} part. %% %% See help for the (non-symbolic) @code{ezplot}, which this %% routine calls after trying to convert sym inputs to %% anonymous functions. %% %% Using sym arguments for @var{dom} and @var{n} can lead to %% ambiguity where OctSymPy cannot tell if you are specifying @var{n} %% or @var{f2}. For example: %% @example %% @group %% syms t %% f = sin(t); %% N = sym(50); %% %% % parametric plot of f(t), N(t) %% ezplot(f, N) % doctest: +SKIP %% %% % plot f vs t using 50 pts %% ezplot(f, double(N)) % doctest: +SKIP %% @end group %% @end example %% %% The solution, as shown in the example, is to convert the sym to %% a double. %% %% @seealso{ezplot, @@sym/ezplot3, @@sym/ezsurf, @@sym/function_handle} %% @end defmethod function varargout = ezplot(varargin) % first input is handle, shift if (ishandle(varargin{1})) fshift = 1; else fshift = 0; end firstsym = []; for i = (1+fshift):nargin if (isa(varargin{i}, 'sym')) if ( (i == 1 + fshift) || ... (i == 2 + fshift && isscalar(varargin{i})) ... ) % This is one of the fcns to plot, so convert to handle fcn % The "i == 2" issscalar cond is to supports ezplot(f, sym([0 1])) % Each is function of one var, and its the same var for all % (or could be a single function of two variables) thissym = symvar(varargin{i}); assert(length(thissym) <= 2, ... 'ezplot: plotting curves: functions should have at most two inputs'); if (isempty(thissym)) % a number, create a constant function in a dummy variable % (0*t works around some Octave oddity on 3.8 and hg Dec 2014) thisf = inline(sprintf('%g + 0*t', double(varargin{i})), 't'); %thisf = @(t) 0*t + double(varargin{i}); % no else % check variables match (sanity check) if (isempty(firstsym)) firstsym = thissym; else assert (all (logical (thissym == firstsym)), ... 'ezplot: all functions must be in terms of the same variables'); end thisf = function_handle(varargin{i}); end varargin{i} = thisf; else % plot ranges, etc, convert syms to doubles varargin{i} = double(varargin{i}); end end end h = ezplot(varargin{:}); if (nargout) varargout{1} = h; end end %%!shared hf %%! % offscreen rendering currently (2016-06) causing crashes: %%! % e.g., https://savannah.gnu.org/bugs/?44478 %%! hf = figure ('visible', 'off'); %!test %! % simple %! syms x %! f = cos(x); %! h = ezplot(f); %! xx = get(h, 'xdata'); %! yy = get(h, 'ydata'); %! assert (abs(yy(end) - cos(xx(end))) <= 2*eps) %! if (exist ('OCTAVE_VERSION', 'builtin')) %! % matlab misses endpoint with nodisplay %! assert (abs(xx(end) - 2*pi) <= 4*eps) %! assert (abs(yy(end) - cos(2*pi)) <= 4*eps) %! end %!test %! % parametric %! syms t %! x = cos(t); %! y = sin(t); %! h = ezplot(x, y); %! xx = get(h, 'xdata'); %! assert (abs(xx(end) - cos(2*pi)) <= 4*eps) %!error %! syms x t %! ezplot(t, x) %!error %! syms x t %! ezplot(t, t*x) %!test %! % implicit plot of f(x,y) == 0 %! syms x y %! f = sqrt(x*x + y*y) - 1; %! h = ezplot(f); %! if (exist ('OCTAVE_VERSION', 'builtin')) %! xx = get (h, 'xdata'); %! yy = get (h, 'ydata'); %! else %! if (isempty (get (h, 'zdata'))) %! xx = get (h, 'xdata'); %! yy = get (h, 'ydata'); %! else %! cm = get (h, 'ContourMatrix'); %! xx = cm(1, 2:end); %! yy = cm(2, 2:end); %! assert (cm(1, 1) == 0) %! assert (cm(2, 1) == length (xx)) %! end %! end %! assert (abs (max (xx) - 1) <= 0.02) %! assert (abs (max (yy) - 1) <= 0.02) %!error %! % implicit plot supports single function %! syms x y %! f = sqrt(x*x + y*y) - 1; %! g = sqrt(x*x + y*y) - 4; %! h = ezplot(f, g); %!test %! % bounds etc as syms %! if (exist ('OCTAVE_VERSION', 'builtin')) %! % this number-of-points option not supported on matlab %! syms x %! f = cos(x); %! h = ezplot(f, [0 2*sym(pi)], sym(42)); %! y = get(h, 'ydata'); %! assert (length(y) == 42) %! assert (abs(y(end) - cos(4*pi)) <= 4*eps) %! end %!test %! close all %%!test %%! close (hf); symbolic-3.1.1/inst/@sym/ezplot3.m0000644000000000000000000000754114405647405013706 0ustar %% Copyright (C) 2014-2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym ezplot3 (@var{f1}, @var{f2}, @var{f3}) %% @defmethodx @@sym ezplot3 (@dots{}, @var{dom}) %% @defmethodx @@sym ezplot3 (@dots{}, @var{N}) %% Simple 3D parametric plotting of symbolic expressions. %% %% Example parametric plot of a spiral: %% @example %% @group %% syms t %% x = t*cos(10*t), y = t*sin(10*t), z = t %% @result{} x = (sym) t⋅cos(10⋅t) %% @result{} y = (sym) t⋅sin(10⋅t) %% @result{} z = (sym) t %% %% ezplot3(x, y, z) % doctest: +SKIP %% @end group %% @end example %% %% See help for the (non-symbolic) @code{ezplot3}, which this %% routine calls after trying to convert sym inputs to %% anonymous functions. %% %% @seealso{ezplot3, @@sym/ezplot, @@sym/ezsurf, @@sym/function_handle} %% @end defmethod function varargout = ezplot3(varargin) % first input is handle, shift if (ishandle(varargin{1})) firstpotsym = 2; else firstpotsym = 1; end maxnumsym = 3; firstsym = []; for i = firstpotsym:nargin if (isa(varargin{i}, 'sym')) if (i < firstpotsym + maxnumsym) % one of the fcns to plot, covert to handle fcn % Each is function of one var, and its the same var for all thissym = symvar(varargin{i}); assert(length(thissym) <= 1, ... 'ezplot3: plotting curves: functions should have at most one input'); if (isempty(thissym)) % a number, create a constant function in a dummy variable % (0*t works around some Octave oddity on 3.8 and hg Dec 2014) thisf = inline(sprintf('%g + 0*t', double(varargin{i})), 't'); %thisf = @(t) 0*t + double(varargin{i}); % no else % check variables match (sanity check) if (isempty(firstsym)) firstsym = thissym; else assert(logical(thissym == firstsym), ... 'ezplot3: all functions must be in terms of the same variables'); end thisf = function_handle(varargin{i}); end varargin{i} = thisf; else % plot ranges, etc, convert syms to doubles varargin{i} = double(varargin{i}); end end end h = ezplot3(varargin{:}); if (nargout) varargout{1} = h; end end %%!shared hf %%! % offscreen rendering currently (2016-06) causing crashes: %%! % e.g., https://savannah.gnu.org/bugs/?44478 %%! hf = figure ('visible', 'off'); %!test %! % parametric %! syms t %! f1 = cos(t); %! f2 = sin(t); %! f3 = t; %! h = ezplot3(f1, f2, f3); %! zz = get(h, 'zdata'); %! assert (abs(zz(end) - 2*pi) <= 4*eps) %!error %! syms x t %! ezplot3(t, x, t) %!error %! syms x t %! ezplot3(t, t*x, t) %!test %! % bounds etc as syms %! if (exist ('OCTAVE_VERSION', 'builtin')) %! % disabled for matlab, see ezplot.m too %! syms t %! f1 = cos(t); %! f2 = sin(t); %! f3 = t; %! h = ezplot3(f1, f2, f3, [sym(0) sym(pi)], sym(42)); %! zz = get(h, 'zdata'); %! assert (length(zz) == 42) %! assert (abs(zz(end) - pi) <= 4*eps) %! end %!test %! close all %%!test %%! close (hf) symbolic-3.1.1/inst/@sym/ezsurf.m0000644000000000000000000000702514405647405013621 0ustar %% Copyright (C) 2016-2017, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym ezsurf (@var{z}) %% @defmethodx @@sym ezsurf (@var{f1}, @var{f2}, @var{f3}) %% @defmethodx @@sym ezsurf (@dots{}, @var{dom}) %% @defmethodx @@sym ezsurf (@dots{}, @var{N}) %% Simple 3D surface plots of symbolic expressions. %% %% Example 3D surface plot: %% @example %% @group %% syms x y %% z = sin(2*x)*sin(y) %% @result{} z = (sym) sin(2⋅x)⋅sin(y) %% ezsurf(z) % doctest: +SKIP %% @end group %% @end example %% %% Example parametric surface plot of a Möbius strip: %% @example %% @group %% syms u v %% x = (1+v*cos(u/2))*cos(u) %% @result{} x = (sym) %% ⎛ ⎛u⎞ ⎞ %% ⎜v⋅cos⎜─⎟ + 1⎟⋅cos(u) %% ⎝ ⎝2⎠ ⎠ %% y = (1+v*cos(u/2))*sin(u); %% z = v*sin(u/2); %% %% ezsurf(x, y, z, [0 2*pi -0.5 0.5], 32) % doctest: +SKIP %% axis equal %% @end group %% @end example %% %% See help for the (non-symbolic) @code{ezsurf}, which this %% routine calls after trying to convert sym inputs to %% anonymous functions. %% %% @seealso{ezsurf, @@sym/ezmesh, @@sym/ezplot, @@sym/function_handle} %% @end defmethod function varargout = ezsurf(varargin) % first input is handle, shift if (ishandle(varargin{1})) firstpotsym = 2; else firstpotsym = 1; end maxnumsym = 3; firstsym = []; for i = firstpotsym:nargin if (isa(varargin{i}, 'sym')) if (i < firstpotsym + maxnumsym) % one of the fcns to plot, covert to handle fcn % Each is function of one var, and its the same var for all thissym = symvar(varargin{i}); assert(length(thissym) <= 2, ... 'ezsurf: parameterized: functions should have at most two inputs'); if (isempty(thissym)) % a number, create a constant function in a dummy variable % (0*t works around some Octave oddity on 3.8 and hg Dec 2014) thisf = inline(sprintf('%g + 0*t', double(varargin{i})), 't'); %thisf = @(t) 0*t + double(varargin{i}); % no else % check variables match (sanity check) if (isempty(firstsym)) firstsym = thissym; else assert(all(logical(thissym == firstsym)), ... 'ezsurf: all functions must be in terms of the same variables'); end thisf = function_handle(varargin{i}); end varargin{i} = thisf; else % plot ranges, etc, convert syms to doubles varargin{i} = double(varargin{i}); end end end h = ezsurf(varargin{:}); if (nargout) varargout{1} = h; end end %!error %! syms u v t %! ezsurf(u*v, 2*u*v, 3*v*t) %!error %! syms u v t %! ezsurf(u*v, 2*u*v, u*v*t) symbolic-3.1.1/inst/@sym/factor.m0000644000000000000000000001161514405647405013561 0ustar %% Copyright (C) 2014, 2016-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {@var{e} =} factor (@var{n}) %% @deftypemethodx @@sym {[@var{p}, @var{m}] =} factor (@var{n}) %% @deftypemethodx @@sym {@var{g} =} factor (@var{f}) %% @deftypemethodx @@sym {@var{g} =} factor (@var{f}, @var{x}) %% @deftypemethodx @@sym {@var{g} =} factor (@var{f}, @var{x}, @var{y}, @dots{}) %% Factor a symbolic polynomial or integer. %% %% A symbolic integer @var{n} can be factored: %% @example %% @group %% e = factor(sym(28152)) %% @result{} e = (sym) %% 1 3 1 2 %% 17 ⋅2 ⋅23 ⋅3 %% @end group %% @end example %% %% However, if you want to do anything other than just look at the result, %% you probably want: %% @example %% @group %% [p, m] = factor(sym(28152)) %% @result{} p = (sym) [2 3 17 23] (1×4 matrix) %% @result{} m = (sym) [3 2 1 1] (1×4 matrix) %% prod(p.^m) %% @result{} (sym) 28152 %% @end group %% @end example %% %% An example of factoring a polynomial: %% @example %% @group %% syms x %% factor(x^2 + 7*x + 12) %% @result{} (sym) (x + 3)⋅(x + 4) %% @end group %% @end example %% %% When the expression @var{f} depends on multiple variables, %% the second argument @var{x} effects what is factored: %% @example %% @group %% syms x y %% f = expand((x+3)*(x+4)*(y+5)*(y+6)); %% factor(f) %% @result{} (sym) (x + 3)⋅(x + 4)⋅(y + 5)⋅(y + 6) %% factor(f, x, y) %% @result{} (sym) (x + 3)⋅(x + 4)⋅(y + 5)⋅(y + 6) %% factor(f, x) %% @result{} (sym) %% ⎛ 2 ⎞ %% (x + 3)⋅(x + 4)⋅⎝y + 11⋅y + 30⎠ %% factor(f, y) %% @result{} (sym) %% ⎛ 2 ⎞ %% (y + 5)⋅(y + 6)⋅⎝x + 7⋅x + 12⎠ %% @end group %% @end example %% %% Passing input @var{x} can be useful if your expression @var{f} might %% be a constant and you wish to avoid factoring it as an integer: %% @example %% @group %% f = sym(42); % i.e., a degree-zero polynomial %% factor(f) % no, don't want this %% @result{} (sym) %% 1 1 1 %% 2 ⋅3 ⋅7 %% factor(f, x) %% @result{} (sym) 42 %% @end group %% @end example %% %% @seealso{@@sym/expand} %% @end deftypemethod function [p, m] = factor(f, varargin) f = sym(f); for i = 1:length(varargin) varargin{i} = sym(varargin{i}); end if ((nargin > 1) || (~isempty (findsymbols (f)))) %% have symbols, do polynomial factorization if (nargout > 1) print_usage (); end p = pycall_sympy__ ('return factor(*_ins, deep=True)', f, varargin{:}); else %% no symbols: we are doing integer factorization if (~isscalar(f)) error ('factor: integer prime factoring is only supported for scalar input') end if (nargout <= 1) % this is rather fragile, as noted in docs p = pycall_sympy__ ('return factorint(_ins[0], visual=True),', f); else cmd = { 'd = factorint(_ins[0], visual=False)' 'num = len(d.keys())' 'sk = sorted(d.keys())' 'p = sp.Matrix(1, num, sk)' 'm = sp.Matrix(1, num, lambda i,j: d[sk[j]])' 'return (p, m)' }; [p, m] = pycall_sympy__ (cmd, f); end end end %!test %! % n = 152862; %! % [p,m] = factor(n); % only works on Octave, no Matlab as of 2014a %! n = 330; % so we use an output without repeated factors %! p = factor(n); m = ones(size(p)); %! [ps,ms] = factor(sym(n)); %! assert (isequal (p, ps)) %! assert (isequal (m, ms)) %!test %! n = sym(2)^4*13; %! [p,m] = factor(n); %! assert (isequal (p, [2 13])) %! assert (isequal (m, [4 1])) %!test syms x %! assert( logical (factor(x^2 + 6*x + 5) == (x+5)*(x+1))) %!test %! syms x %! f = [ x^4/2 + 5*x^3/12 - x^2/3 x^2 - 1 10]; %! g = [ x^2*(2*x - 1)*(3*x + 4)/12 (x+1)*(x-1) 10]; %! assert (isequal (factor(f), g)) %!test %! % "fragile form" works %! A = factor(sym(124)); %! B = strtrim(disp(A, 'flat')); %! assert (strcmp (B, '2**2*31**1')) %!error [p, m] = factor(sym('x')); %!error [p, m] = factor(sym(42), sym('x')); %!test %! % if polynomial happens to be a constant, don't attempt integer %! % factorization if a variable is specified %! f = sym(42); %! q = factor(f, sym('x')); %! assert (isequal (f, q)); symbolic-3.1.1/inst/@sym/factorial.m0000644000000000000000000000340114405647405014241 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym factorial (@var{x}) %% Symbolic factorial function. %% %% Example: %% @example %% @group %% syms x %% y = factorial (x) %% @result{} y = (sym) x! %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = factorial(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('factorial', x); end %!error factorial (sym(1), 2) %!xtest %! assert (isequaln (factorial (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = factorial(x); %! f2 = factorial(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = factorial(A); %! f2 = factorial(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = factorial (d); %! f = factorial (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/find.m0000644000000000000000000001216014405647405013217 0ustar %% Copyright (C) 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {} find (@var{x}) %% @deftypemethodx @@sym {} find (@var{x}, @var{n}) %% @deftypemethodx @@sym {} find (@var{x}, @var{n}, @var{dir}) %% @deftypemethodx @@sym {[@var{i}, @var{j}] =} find (@dots{}) %% @deftypemethodx @@sym {[@var{i}, @var{j}, @var{v}] =} find (@dots{}) %% Find non-zero or true entries of a symbolic matrix. %% %% Example: %% @example %% @group %% syms x y positive %% find ([0 x 0 y]) %% @result{} %% 2 4 %% @end group %% @end example %% %% Note its enough that an expression @emph{could} be non-zero: %% @example %% @group %% syms x y %% find ([x 0 0 1 x+y]) %% @result{} %% 1 4 5 %% @end group %% @end example %% %% For matrices containing equalities, inequalities and boolean %% expressions, @code{find} looks for @code{True} (but does not %% simplify): %% @example %% @group %% syms x y %% A = [x == x; or(x == y, x*(y+1) >= x*y+x); x^2-y^2 == (x-y)*(x+y)] %% @result{} A = (sym 3×1 matrix) %% ⎡ True ⎤ %% ⎢ ⎥ %% ⎢x = y ∨ x⋅(y + 1) ≥ x⋅y + x⎥ %% ⎢ ⎥ %% ⎢ 2 2 ⎥ %% ⎣ x - y = (x - y)⋅(x + y) ⎦ %% %% find (A) %% @result{} %% 1 %% @end group %% %% @group %% find (simplify (A)) %% @result{} %% 1 %% 2 %% 3 %% @end group %% @end example %% %% @seealso{find, @@sym/logical, @@sym/isAlways} %% @end deftypemethod function [i, j, v] = find(x, varargin) if (nargin > 3) print_usage (); end if (nargout <= 1) i = find (mylogical (x), varargin{1:end}); elseif (nargout == 2) [i, j] = find (mylogical (x), varargin{1:end}); elseif (nargout == 3) [i, j] = find (mylogical (x), varargin{1:end}); sz = size (i); v = zeros (sym (sz(1)), sz(2)); for n=1:numel(i) % issue #17: v(n) = x(i(n), j(n)); idx.type = '()'; idx.subs = {i(n), j(n)}; tmp = subsref(x, idx); idx.type = '()'; idx.subs = {n}; v = subsasgn(v, idx, tmp); end else print_usage (); end end function r = mylogical(p) % helper function, similar to "logical" % The difference is that expressions like "x+y" don't raise % errors and instead return "true" (that is, generally nonzero). % FIXME: could check if every entry is boolean, equality, inequality, etc % return all([s is None or isinstance(s, bool) or s.is_Boolean or s.is_Relational for s in x]) % And if so, call "logical". cmd = { 'def scalar2tf(x):' ' if x is None or isinstance(x, bool):' ' return bool(x)' ' if x.is_Boolean or x.is_Relational:' ' if x.doit() in (S.true, True):' ' return True' ' return False' ' try:' ' r = bool(x)' ' except TypeError:' ' r = False' ' return r' '#' 'x, = _ins' 'if x is not None and x.is_Matrix:' ' x = [a for a in x.T]' % note transpose 'else:' ' x = [x,]' 'return [scalar2tf(a) for a in x],' }; r = pycall_sympy__ (cmd, p); r = cell2mat(r); r = reshape(r, size(p)); end %!error find (sym (1), 2, 3, 4) %!error [x, y, z, w] = find (sym (1)) %!test %! syms x y positive %! assert (isequal (find ([0 x 0 y]), [2 4])) %! assert (isequal (find ([0 x 0 y], 1), 2)) %! assert (isequal (find ([0 x 0 y], 1, 'first'), 2)) %! assert (isequal (find ([0 x 0 y], 1, 'last'), 4)) %! assert (isequal (find ([0 x 0 y], 2, 'last'), [2 4])) %!test %! % its enough that it could be non-zero, does not have to be %! syms x y %! assert (isequal (find ([0 x+y]), 2)) %!test %! % false should not be found %! syms x y %! assert (isequal (find ([x==x x==y]), 1)) %! assert (isequal (find ([x==y]), [])) %!test %! % and/or should be treated as boolean %! syms x y %! assert (isequal (find ([or(x==y, x==2*y) x==y x==x]), 3)) %!test %! % None %! none = pycall_sympy__ ('return None'); %! assert (isequal (find ([sym(0) none sym(1)]), 3)) %! syms x y %! assert (isequal (find ([x==y none x==x]), 3)) %!test %! % two output %! syms x y %! A = [x 0 0; x+y 5 0]; %! [i, j] = find (A); %! assert (isequal (i, [1; 2; 2])) %! assert (isequal (j, [1; 1; 2])) %!test %! % three output %! syms x y %! A = [x 0 0; x+y 5 0]; %! [i, j, v] = find (A); %! assert (isequal (i, [1; 2; 2])) %! assert (isequal (j, [1; 1; 2])) %! assert (isequal (v, [x; x+y; sym(5)])) symbolic-3.1.1/inst/@sym/findsym.m0000644000000000000000000000407414405647405013755 0ustar %% Copyright (C) 2014-2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym findsym (@var{expr}) %% @defmethodx @@sym findsym (@var{expr}, @var{n}) %% Find symbols in expression, return them as comma-separated string. %% %% For details, @pxref{@@sym/symvar}; this just concatenates its output %% into a string. %% %% Example: %% @example %% @group %% syms y a b %% f = a*y + b; %% v = findsym (f) %% @result{} v = a,b,y %% v = findsym (f, 1) %% @result{} v = y %% @end group %% @end example %% %% @seealso{@@sym/symvar, symvar, findsymbols} %% @end defmethod function s = findsym(varargin) A = symvar(varargin{:}); s = strjoin(syms2charcells(A), ','); end function C = syms2charcells(S) C = {}; for i=1:length(S) if iscell(S) C{i} = S{i}.flat; else % MoFo Issue #17 %C{i} = S(i).flat idx.type = '()'; idx.subs = {i}; temp = subsref(S, idx); C{i} = temp.flat; end end end %!assert (strcmp (findsym (sym(2)), '')); %!shared x,y,f %! x=sym('x'); y=sym('y'); f=x^2+3*x*y-y^2; %!assert (strcmp (findsym (f), 'x,y')); %!assert (strcmp (findsym (f,1), 'x')); %!test %! % test order of returned vars %! syms x y a b c xx %! % https://www.mathworks.com/matlabcentral/newsreader/view_thread/237730 %! alpha = sym('alpha'); %! assert (strcmp (findsym(b*xx*exp(alpha) + c*sin(a*y), 2), 'xx,y')) symbolic-3.1.1/inst/@sym/fix.m0000644000000000000000000000301414405647405013063 0ustar %% Copyright (C) 2016 Lagu %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym fix (@var{x}) %% Symbolic fix function. %% %% Example: %% @example %% @group %% y = fix(sym(3)/2) %% @result{} y = (sym) 1 %% @end group %% @end example %% %% @seealso{@@sym/ceil, @@sym/floor, @@sym/frac, @@sym/round} %% @end defmethod function y = fix(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('Integer', x); end %!test %! d = 3/2; %! x = sym('3/2'); %! f1 = fix(x); %! f2 = fix(d); %! assert (isequal (f1, f2)) %!test %! D = [1.1 4.6; -3.4 -8.9]; %! A = [sym(11)/10 sym(46)/10; sym(-34)/10 sym(-89)/10]; %! f1 = fix(A); %! f2 = fix(D); %! assert( isequal (f1, f2)) %!test %! d = sym(-11)/10; %! c = -1; %! assert (isequal (fix (d), c)) %!test %! d = sym(-19)/10; %! c = -1; %! assert (isequal (fix (d), c)) symbolic-3.1.1/inst/@sym/fliplr.m0000644000000000000000000000322014405647405013564 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym fliplr (@var{A}) %% Flip a symbolic matrix horizontally. %% %% Example: %% @example %% @group %% A = sym([1 2 pi; 4 5 6]); %% fliplr (A) %% @result{} (sym 2×3 matrix) %% ⎡π 2 1⎤ %% ⎢ ⎥ %% ⎣6 5 4⎦ %% @end group %% @end example %% %% @seealso{@@sym/flipud, @@sym/reshape} %% @end defmethod function B = fliplr (A) cmd = { 'A, = _ins' 'if A is None or not A.is_Matrix:' ' A = sp.Matrix([A])' 'return A[:, ::-1]' }; B = pycall_sympy__ (cmd, sym(A)); end %!test %! % simple %! syms x %! A = [x 2; sym(pi) x]; %! B = [2 x; x sym(pi)]; %! assert (isequal (fliplr(A), B)) %!test %! % simple, odd # cols %! syms x %! A = [x 2 sym(pi); x 1 2]; %! B = [sym(pi) 2 x; 2 1 x]; %! assert (isequal (fliplr(A), B)) %!test %! % scalar %! syms x %! assert (isequal (fliplr(x), x)) symbolic-3.1.1/inst/@sym/flipud.m0000644000000000000000000000322414405647405013563 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym flipud (@var{A}) %% Flip a symbolic matrix vertically. %% %% Example: %% @example %% @group %% A = sym([1 2 pi; 4 5 6]); %% flipud (A) %% @result{} (sym 2×3 matrix) %% ⎡4 5 6⎤ %% ⎢ ⎥ %% ⎣1 2 π⎦ %% @end group %% @end example %% %% @seealso{@@sym/fliplr, @@sym/reshape} %% @end defmethod function B = flipud (A) cmd = { 'A, = _ins' 'if A is None or not A.is_Matrix:' ' A = sp.Matrix([A])' 'return A[::-1, :]' }; B = pycall_sympy__ (cmd, sym(A)); end %!test %! % simple %! syms x %! A = [x 2; sym(pi) x]; %! B = [sym(pi) x; x 2]; %! assert (isequal (flipud(A), B)) %!test %! % simple, odd # rows %! syms x %! A = [x 2; sym(pi) x; [1 2]]; %! B = [[1 2]; sym(pi) x; x 2]; %! assert (isequal (flipud(A), B)) %!test %! % scalar %! syms x %! assert (isequal (flipud(x), x)) symbolic-3.1.1/inst/@sym/floor.m0000644000000000000000000000331114405647405013416 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym floor (@var{x}) %% Symbolic floor function. %% %% Example: %% @example %% @group %% syms x %% y = floor (x) %% @result{} y = (sym) ⌊x⌋ %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = floor(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('floor', x); end %!error floor (sym(1), 2) %!assert (isequaln (floor (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = floor(x); %! f2 = floor(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = floor(A); %! f2 = floor(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = floor (d); %! f = floor (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/formula.m0000644000000000000000000000251314405647405013745 0ustar %% Copyright (C) 2015, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym formula (@var{f}) %% Return a symbolic expression for this object. %% %% For a @@sym, this simply returns the sym itself. Subclasses %% such as @@symfun may do more interesting things. %% %% Example: %% @example %% @group %% syms x %% f = 2*x; %% formula(f) %% @result{} ans = (sym) 2⋅x %% @end group %% @end example %% %% @seealso{@@symfun/formula, argnames, @@sym/argnames} %% @end defmethod function g = formula(f) g = f; end %!test %! syms x %! assert (isequal (formula(x), x)) %! assert (isequal (formula(2*x), 2*x)) symbolic-3.1.1/inst/@sym/fortran.m0000644000000000000000000001041514405647405013753 0ustar %% Copyright (C) 2014-2016, 2019, 2022 Colin B. Macdonald %% Copyright (C) 2017 Mike Miller %% Copyright (C) 2017 Alex Vong %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {@var{s} =} fortran (@var{g}) %% @deftypemethodx @@sym {@var{s} =} fortran (@var{g1}, @dots{}, @var{gn}) %% @deftypemethodx @@sym {} fortran (@dots{}, 'file', @var{filename}) %% @deftypemethodx @@sym {[@var{F}, @var{H}] =} fortran (@dots{}, 'file', '') %% Convert symbolic expression into Fortran code. %% %% Example returning a string of Fortran code: %% @example %% @group %% syms x %% g = taylor(log(1 + x), x, 0, 'order', 5); %% g = horner(g) %% @result{} g = (sym) %% ⎛ ⎛ ⎛1 x⎞ 1⎞ ⎞ %% x⋅⎜x⋅⎜x⋅⎜─ - ─⎟ - ─⎟ + 1⎟ %% ⎝ ⎝ ⎝3 4⎠ 2⎠ ⎠ %% fortran(g) %% @result{} x*(x*(x*(1.0d0/3.0d0 - 1.0d0/4.0d0*x) - 1.0d0/2.0d0) + 1) %% @end group %% @end example %% %% We can write to a file or obtain the contents directly: %% @example %% @group %% [f90, h] = fortran(g, 'file', '', 'show_header', false); %% f90.name %% @result{} file.f90 %% h.name %% @result{} file.h %% @end group %% %% @group %% disp(f90.code) %% @print{} REAL*8 function myfun(x) %% @print{} implicit none %% @print{} REAL*8, intent(in) :: x %% @print{} %% @print{} myfun = x*(x*(x*(1.0d0/3.0d0 - 1.0d0/4.0d0*x) - 1.0d0/2.0d0) + 1) %% @print{} %% @print{} end function %% @end group %% %% @group %% disp(h.code) %% @print{} interface %% @print{} REAL*8 function myfun(x) %% @print{} implicit none %% @print{} REAL*8, intent(in) :: x %% @print{} end function %% @print{} end interface %% @end group %% @end example %% %% FIXME: This doesn't write ``optimized'' code like Matlab's %% Symbolic Math Toolbox; it doesn't do ``Common Subexpression %% Elimination''. Presumably the compiler would do that for us %% anyway. Sympy has a ``cse'' module that will do it. See: %% http://stackoverflow.com/questions/22665990/optimize-code-generated-by-sympy %% %% @seealso{@@sym/ccode, @@sym/latex, @@sym/function_handle} %% @end deftypemethod function varargout = fortran(varargin) [flg, meh] = codegen(varargin{:}, 'lang', 'F95'); if flg == 0 varargout = {}; elseif flg == 1 varargout = meh(1); elseif flg == 2 varargout = {meh{1}, meh{2}}; else error('whut?'); end end %!shared x,y,z %! syms x y z %!test %! % basic test %! f = x*sin(y) + abs(z); %! source = fortran(f); %! expected = ' x*sin(y) + abs(z)'; %! s1 = strrep (expected, 'abs', 'Abs'); %! assert (strcmp (source, expected) || strcmp (source, s1)) %!test %! % output test %! f = x*sin(y) + abs(z); %! [F,H] = fortran(f, 'file', '', 'show_header', false); %! expected_h_code = sprintf('\ninterface\nREAL*8 function myfun(x, y, z)\nimplicit none\nREAL*8, intent(in) :: x\nREAL*8, intent(in) :: y\nREAL*8, intent(in) :: z\nend function\nend interface\n\n'); %! expected_f_code = sprintf('\nREAL*8 function myfun(x, y, z)\nimplicit none\nREAL*8, intent(in) :: x\nREAL*8, intent(in) :: y\nREAL*8, intent(in) :: z\n\nmyfun = x*sin(y) + abs(z)\n\nend function\n'); %! assert(strcmp(F.name, 'file.f90')) %! assert(strcmp(H.name, 'file.h')) %! %disp(expected_f_code); disp(F.code) %! s1 = strrep (expected_f_code, 'abs', 'Abs'); %! s2 = strrep (expected_f_code, sprintf ('\n'), sprintf ('\r\n')); %! s3 = strrep (s2, 'abs', 'Abs'); %! s4 = strrep (expected_h_code, sprintf ('\n'), sprintf ('\r\n')); %! assert (strcmp (F.code, expected_f_code) || strcmp (F.code, s1) || strcmp (F.code, s2) || strcmp (F.code, s3)) %! assert (strcmp (H.code, expected_h_code) || strcmp (H.code, s4)) symbolic-3.1.1/inst/@sym/fourier.m0000644000000000000000000001574214405647405013763 0ustar %% Copyright (C) 2014-2016, 2019 Colin B. Macdonald %% Copyright (C) 2015-2016 Andrés Prieto %% Copyright (C) 2015 Alexander Misel %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym fourier (@var{f}, @var{x}, @var{w}) %% @defmethodx @@sym fourier (@var{f}) %% @defmethodx @@sym fourier (@var{f}, @var{w}) %% Symbolic Fourier transform. %% %% The Fourier transform of a function @var{f} of @var{x} %% is a function @var{FF} of @var{w} defined by the integral below. %% @example %% @group %% syms f(x) w %% FF(w) = rewrite(fourier(f), 'Integral') %% @result{} FF(w) = (symfun) %% ∞ %% ⌠ %% ⎮ -ⅈ⋅w⋅x %% ⎮ f(x)⋅ℯ dx %% ⌡ %% -∞ %% @end group %% @end example %% %% Example: %% @example %% @group %% syms x %% f = exp(-abs(x)); %% fourier(f) %% @result{} (sym) %% 2 %% ────── %% 2 %% w + 1 %% @end group %% @end example %% %% Note @code{fourier} and @code{ifourier} implement the non-unitary, %% angular frequency convention for L^2 functions and distributions. %% %% *WARNING*: As of SymPy 0.7.6 (June 2015), there are many problems %% with (inverse) Fourier transforms of non-smooth functions, even very %% simple ones. Use at your own risk, or even better: help us fix SymPy. %% %% @seealso{@@sym/ifourier} %% @end defmethod function F = fourier(varargin) % FIXME: it only works for scalar functions % FIXME: it doesn't handle diff call (see SMT transform of diff calls) % If the physical variable of f is equal to "w", % "v" is the frequency domain variable (analogously to SMT) if (nargin == 1) f = sym(varargin{1}); x = symvar(f, 1); if (isempty(x)) x = sym('x'); end cmd = { 'f=_ins[0]; x=_ins[1]; k=sp.Symbol("w")' 'if x==k:' ' k=sp.Symbol("v")' 'F=0; a_ = sp.Wild("a_"); b_ = sp.Wild("b_")' 'fr=f.rewrite(sp.exp)' 'if type(fr)==sp.Add:' ' terms=fr.expand().args' 'else:' ' terms=(fr,)' 'for term in terms:' ' #compute the Fourier transform ' ' r=sp.simplify(term*sp.exp(-sp.I*x*k)).match(a_*sp.exp(b_))' ' # if a is constant and b/(I*x) is constant' ' modulus=r[a_]' ' phase=r[b_]/(sp.I*x)' ' if sp.diff(modulus,x)==0 and sp.diff(phase,x)==0:' ' F = F + modulus*2*sp.pi*sp.DiracDelta(-phase)' ' else:' ' Fterm=sp.integrate(sp.simplify(term*sp.exp(-sp.I*x*k)), (x, -sp.oo, sp.oo))' ' if Fterm.is_Piecewise:' ' F=F+sp.simplify(Fterm.args[0][0])' ' else:' ' F=F+sp.simplify(Fterm)' 'return F,'}; F = pycall_sympy__ (cmd, f, x); elseif (nargin == 2) f = sym(varargin{1}); k = sym(varargin{2}); x = symvar(f, 1); if (isempty(x)) x = sym('x'); % FIXME: should be dummy variable in case k was x end cmd = { 'f=_ins[0]; x=_ins[1]; k=_ins[2]' 'F=0; a_ = sp.Wild("a_"); b_ = sp.Wild("b_")' 'fr=f.rewrite(sp.exp)' 'if type(fr)==sp.Add:' ' terms=fr.expand().args' 'else:' ' terms=(fr,)' 'for term in terms:' ' #compute the Fourier transform ' ' r=sp.simplify(term*sp.exp(-sp.I*x*k)).match(a_*sp.exp(b_))' ' # if a is constant and b/(I*x) is constant' ' modulus=r[a_]' ' phase=r[b_]/(sp.I*x)' ' if sp.diff(modulus,x)==0 and sp.diff(phase,x)==0:' ' F = F + modulus*2*sp.pi*sp.DiracDelta(-phase)' ' else:' ' Fterm=sp.integrate(sp.simplify(term*sp.exp(-sp.I*x*k)), (x, -sp.oo, sp.oo))' ' if Fterm.is_Piecewise:' ' F=F+sp.simplify(Fterm.args[0][0])' ' else:' ' F=F+sp.simplify(Fterm)' 'return F,'}; F = pycall_sympy__ (cmd, f, x, k); elseif (nargin == 3) f = sym(varargin{1}); x = sym(varargin{2}); k = sym(varargin{3}); cmd = { 'f=_ins[0]; x=_ins[1]; k=_ins[2]' 'F=0; a_ = sp.Wild("a_"); b_ = sp.Wild("b_")' 'fr=f.rewrite(sp.exp)' 'if type(fr)==sp.Add:' ' terms=fr.expand().args' 'else:' ' terms=(fr,)' 'for term in terms:' ' #compute the Fourier transform ' ' r=sp.simplify(term*sp.exp(-sp.I*x*k)).match(a_*sp.exp(b_))' ' # if a is constant and b/(I*x) is constant' ' modulus=r[a_]' ' phase=r[b_]/(sp.I*x)' ' if sp.diff(modulus,x)==0 and sp.diff(phase,x)==0:' ' F = F + modulus*2*sp.pi*sp.DiracDelta(-phase)' ' else:' ' Fterm=sp.integrate(sp.simplify(term*sp.exp(-sp.I*x*k)), (x, -sp.oo, sp.oo))' ' if Fterm.is_Piecewise:' ' F=F+sp.simplify(Fterm.args[0][0])' ' else:' ' F=F+sp.simplify(Fterm)' 'return F,'}; F = pycall_sympy__ (cmd, f, x, k); else print_usage (); end end %!test %! % matlab SMT compatibiliy for arguments %! syms r x u w v %! Pi=sym('pi'); %! assert(logical( fourier(exp(-x^2)) == sqrt(Pi)/exp(w^2/4) )) %! assert(logical( fourier(exp(-w^2)) == sqrt(Pi)/exp(v^2/4) )) %! assert(logical( fourier(exp(-r^2),u) == sqrt(Pi)/exp(u^2/4) )) %! assert(logical( fourier(exp(-r^2),r,u) == sqrt(Pi)/exp(u^2/4) )) %!test %! % basic tests %! syms x w %! assert(logical( fourier(exp(-abs(x))) == 2/(w^2 + 1) )) %! assert(logical( fourier(x*exp(-abs(x))) == -(w*4*1i)/(w^4 + 2*w^2 + 1) )) %!test %! % Dirac delta tests %! syms x w %! Pi=sym('pi'); %! assert(logical( fourier(dirac(x-2)) == exp(-2*1i*w) )) %! assert (logical( fourier(sym(2), x, w) == 4*Pi*dirac(w) )) %!test %! % advanced test %! syms x w c d %! Pi=sym('pi'); %! F=Pi*(dirac(w-c)+dirac(w+c))+2*Pi*1i*(dirac(w+3*d)-dirac(w-3*d))+2/(w^2+1); %! assert(logical( fourier(cos(c*x)+2*sin(3*d*x)+exp(-abs(x))) == expand(F) )) %!xtest %! % Differential operator to algebraic %! % SymPy cannot evaluate? (Issue #170) %! syms x w f(x) %! assert(logical( fourier(diff(f(x),x),x,w) == -1i*w*fourier(f(x),x,w) )) symbolic-3.1.1/inst/@sym/frac.m0000644000000000000000000000301114405647405013205 0ustar %% Copyright (C) 2016 Lagu %% Copyright (C) 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym frac (@var{x}) %% Return the fractional part of a symbolic expression. %% %% Examples: %% @example %% @group %% y = frac(sym(3)/2) %% @result{} y = (sym) 1/2 %% %% syms x %% rewrite(frac(x), 'floor') %% @result{} ans = (sym) x - ⌊x⌋ %% @end group %% @end example %% %% @seealso{@@sym/ceil, @@sym/floor, @@sym/fix, @@sym/round} %% @end defmethod function y = frac(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('frac', x); end %!test %! f1 = frac(sym(11)/10); %! f2 = sym(1)/10; %! assert (isequal (f1, f2)) %!test %! d = sym(-11)/10; %! c = sym(9)/10; %! assert (isequal (frac (d), c)) %!test %! d = sym(-19)/10; %! c = sym(1)/10; %! assert (isequal (frac (d), c)) symbolic-3.1.1/inst/@sym/fresnelc.m0000644000000000000000000000352314405647405014103 0ustar %% Copyright (C) 2016, 2018-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym fresnelc (@var{x}) %% Symbolic Fresnel Cosine function. %% %% Example: %% @example %% @group %% @c doctest: +XFAIL_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.4")')) %% z = fresnelc(sym('x')) %% @result{} z = (sym) C(x) %% diff(z) %% @result{} (sym) %% ⎛ 2⎞ %% ⎜π⋅x ⎟ %% cos⎜────⎟ %% ⎝ 2 ⎠ %% @end group %% @end example %% %% @seealso{@@sym/fresnels} %% @end defmethod function J = fresnelc (x) if (nargin ~= 1) print_usage (); end J = elementwise_op ('fresnelc', x); end %!error fresnelc (sym(1), 2) %!test %! a = fresnelc(sym(0)); %! assert (isequal (a, sym(0))) %!test %! b = fresnelc(sym('oo')); %! assert (isequal (b, sym(1)/2)) %!test %! % values in a matrix %! syms x %! a = fresnelc([sym(0) sym('oo') x 1]); %! b = [sym(0) sym(1)/2 fresnelc(x) fresnelc(sym(1))]; %! assert (isequal (a, b)) %!test %! % round trip %! syms x %! f = fresnelc (x); %! h = function_handle (f); %! A = h (1.1); %! B = fresnelc (1.1); %! assert (A, B) symbolic-3.1.1/inst/@sym/fresnels.m0000644000000000000000000000352114405647405014121 0ustar %% Copyright (C) 2016, 2018-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym fresnels (@var{x}) %% Symbolic Fresnel Sine function. %% %% Example: %% @example %% @group %% @c doctest: +XFAIL_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.4")')) %% z = fresnels(sym('x')) %% @result{} z = (sym) S(x) %% diff(z) %% @result{} (sym) %% ⎛ 2⎞ %% ⎜π⋅x ⎟ %% sin⎜────⎟ %% ⎝ 2 ⎠ %% @end group %% @end example %% %% @seealso{@@sym/fresnelc} %% @end defmethod function J = fresnels (x) if (nargin ~= 1) print_usage (); end J = elementwise_op ('fresnels', x); end %!error fresnels (sym(1), 2) %!test %! a = fresnels(sym(0)); %! assert (isequal (a, sym(0))) %!test %! b = fresnels(sym('oo')); %! assert (isequal (b, sym(1)/2)) %!test %! % values in a matrix %! syms x %! a = fresnels([sym(0) sym('oo') x 1]); %! b = [sym(0) sym(1)/2 fresnels(x) fresnels(sym(1))]; %! assert (isequal (a, b)) %!test %! % round trip %! syms x %! f = fresnels (x); %! h = function_handle (f); %! A = h (1.1); %! B = fresnels (1.1); %! assert (A, B) symbolic-3.1.1/inst/@sym/function_handle.m0000644000000000000000000002507114405647405015444 0ustar %% Copyright (C) 2014-2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym function_handle (@var{f}) %% @defmethodx @@sym function_handle (@var{f1}, @dots{}, @var{fn}) %% @defmethodx @@sym function_handle (@dots{}, @var{param}, @var{value}) %% @defmethodx @@sym function_handle (@dots{}, 'vars', [@var{x} @dots{} @var{z}]) %% @defmethodx @@sym function_handle (@dots{}, 'file', @var{filename}) %% @defmethodx @@sym function_handle (@dots{}, 'outputs', [@var{o1} @dots{} @var{on}]) %% Convert symbolic expression into a standard function. %% %% This can make anonymous functions from symbolic expressions: %% @example %% @group %% syms x y %% f = x^2 + sin(y) %% @result{} f = (sym) %% 2 %% x + sin(y) %% h = function_handle(f) %% @result{} h = @@(x, y) x .^ 2 + sin (y) %% h(2, pi/2) %% @result{} ans = 5 %% @end group %% @end example %% %% Multiple arguments correspond to multiple outputs of the %% function. For example, the final @code{x} in this example %% specifies the third output (rather than the input): %% @example %% @group %% h = function_handle(x^2, 5*x, x); %% [a, b, c] = h(2) %% @result{} a = 4 %% @result{} b = 10 %% @result{} c = 2 %% @end group %% @end example %% %% The order and number of inputs can be specified: %% @example %% @group %% syms x y z %% h = function_handle(f, 'vars', [z y x]) %% @result{} h = @@(z, y, x) x .^ 2 + sin (y) %% @end group %% @end example %% %% For compatibility with the Symbolic Math Toolbox in Matlab, we %% provide a synonym: @pxref{@@sym/matlabFunction} %% %% OctSymPy can also generate an @code{.m} file from a symbolic %% expression by passing the keyword @code{file} with a string %% argument for @var{filename}. A handle to the function in the %% file will be returned. %% Passing an empty @var{filename} creates an anonymous function: %% @example %% @group %% h = function_handle(f, 'file', '') %% @result{} h = @@(x, y) x .^ 2 + sin (y) %% @end group %% @end example %% %% FIXME: naming outputs with @var{PARAM} as @code{outputs} %% not implemented. %% %% FIXME: does not ``optimize'' code, for example, using common %% subexpression elimination. %% %% @seealso{@@sym/ccode, @@sym/fortran, @@sym/latex, @@sym/matlabFunction} %% @end defmethod function f = function_handle(varargin) % We use the private/codegen function only for its input parsing [flg, meh] = codegen(varargin{:}, 'lang', 'octave'); assert(flg == -1); [Nin, inputs, inputstr, Nout, param] = deal(meh{:}); %% Outputs if (param.codegen) && (~isempty(param.fname)) cmd = { '(expr,fcnname,filename,showhdr,in_vars) = _ins' ... 'from sympy.utilities.codegen import codegen' ... 'try:' ... [' out = codegen((fcnname,expr), "' param.lang ... '", filename, header=showhdr' ... ', argument_sequence=in_vars)'] ... 'except ValueError as e:' ... ' return (False, str(e))' ... 'return (True, out)' }; [fcnpath, fcnname, fcnext] = fileparts(param.fname); [worked, out] = pycall_sympy__ (cmd, varargin(1:Nout), fcnname, fcnname, param.show_header, inputs); if (~worked) if (strcmp(out, 'Language ''octave'' is not supported.')) error('function_handle: your SymPy has no octave codegen'); else out error('function_handle: Some other error from SymPy code gen? file a bug!'); end end M.name = out{1}{1}; M.code = out{1}{2}; assert (strcmp (M.name, [fcnname '.m']), 'sanity check failed: names should match'); file_to_write = fullfile(fcnpath, [fcnname '.m']); [fid,msg] = fopen(file_to_write, 'w'); assert(fid > -1, msg) fprintf(fid, '%s', M.code); fclose(fid); fprintf('Wrote file %s.\n', file_to_write); % FIXME: Check upstream to rehash the files correctly once created % Due to an upstream bug in octave on windows, we have to wait for the file to be loaded. % See https://savannah.gnu.org/bugs/?31080 for more information...\n if (exist('OCTAVE_VERSION', 'builtin') && ispc()) fprintf('Workaround savannah.gnu.org/bugs/?31080: waiting for %s... ', fcnname); fflush(stdout); while (exist(fcnname) == 0) rehash() pause(1) end fprintf('Found!\n'); end f = str2func(fcnname); else % output function handle exprstrs = {}; for i=1:Nout expr = varargin{i}; cmd = { '(f,) = _ins' ... 'try:' ... ' a, b, s = octave_code(f, human=False)' ... 'except NameError as e:' ... ' return (False, str(e))' ... 'if len(b) != 0:' ... ' return (False, s)' ... 'if len(a) != 0:' ... ' return (False, "expected symbols-to-declare to be empty")' ... 'return (True, s)' }; [worked, codestr] = pycall_sympy__ (cmd, expr); if (~worked) error('function_handle: python codegen failed: %s', codestr) end exprstr{i} = codestr; end if (Nout == 1) f = eval(sprintf('@(%s) %s', inputstr, exprstr{1})); else str = [ sprintf('@(%s) deal(', inputstr) ... sprintf('%s,', exprstr{:})]; str = [str(1:end-1) ')']; f = eval(str); end end % Note: this fails in Matlab SMT too: %h = function_handle({x,y,z},'vars',{x y z}) % (could fix by moving it outside @sym) end %!shared x,y,z %! syms x y z %!test %! % basic test %! h = function_handle(2*x); %! assert(isa(h, 'function_handle')) %! assert(h(3)==6) %!test %! % autodetect inputs %! h = function_handle(2*x*y, x+y); %! [t1, t2] = h(3,5); %! assert(t1 == 30 && t2 == 8) %!test %! % specified inputs %! h = function_handle(2*x*y, 'vars', [x y]); %! assert(h(3,5)==30) %! h = function_handle(2*x*y, x+y, 'vars', [x y]); %! [t1, t2] = h(3,5); %! assert(t1 == 30 && t2 == 8) %!test %! % cell arrays for vars list %! h = function_handle(2*x*y, x+y, 'vars', {x y}); %! [t1, t2] = h(3,5); %! assert(t1 == 30 && t2 == 8) %! h = function_handle(2*x*y, x+y, 'vars', {'x' 'y'}); %! [t1, t2] = h(3,5); %! assert(t1 == 30 && t2 == 8) %!test %! % cell arrays specfies order, overriding symvar order %! h = function_handle(x*y, 12/y, 'vars', {y x}); %! [t1, t2] = h(3, 6); %! assert(t1 == 18 && t2 == 4) %! h = function_handle(x*y, 12/y, 'vars', [y x]); %! [t1, t2] = h(3, 6); %! assert(t1 == 18 && t2 == 4) %!test %! % cell arrays specfies order, overriding symvar order %! h = function_handle(x*y, 12/y, 'vars', {y x}); %! [t1, t2] = h(3, 6); %! assert(t1 == 18 && t2 == 4) %! h = function_handle(x*y, 12/y, 'vars', [y x]); %! [t1, t2] = h(3, 6); %! assert(t1 == 18 && t2 == 4) %!test %! % Functions with different names in Sympy. %! f = abs(x); % becomes Abs(x) %! h = function_handle(f); %! assert(h(-10) == 10) %! f = ceil(x); %! h = function_handle(f); %! assert(h(10.1) == 11) %!test %! % 'file' with empty filename returns handle %! h = function_handle(2*x*y, 'file', ''); %! assert(isa(h, 'function_handle')) %! assert(h(3,5)==30) %! h = function_handle(2*x*y, 'vars', {x y}, 'file', ''); %! assert(isa(h, 'function_handle')) %! assert(h(3,5)==30) %!test %! % output to disk %! fprintf('\n') %! if (exist ('OCTAVE_VERSION', 'builtin')) %! temp_file = tempname('', 'oct_'); %! else %! temp_file = tempname(); %! end %! % allow loading function from temp_file %! [temp_path, ans, ans] = fileparts(temp_file); %! addpath(temp_path); %! f = function_handle(2*x*y, 2^x, 'vars', {x y z}, 'file', temp_file); %! assert( isa(f, 'function_handle')) %! addpath(temp_path); % Matlab 2014a needs this? %! [a,b] = f(10,20,30); %! assert (isnumeric (a) && isnumeric (b)) %! assert (a == 400) %! assert (b == 1024) %! if (exist ('OCTAVE_VERSION', 'builtin')) %! assert (unlink([temp_file '.m']) == 0) %! else %! delete ([temp_file '.m']) %! end %! % remove temp_path from load path %! rmpath(temp_path); %!test %! % output to disk: also works with .m specified %! if (exist ('OCTAVE_VERSION', 'builtin')) %! temp_file = [tempname('', 'oct_') '.m']; %! else %! temp_file = [tempname() '.m']; %! end %! % allow loading function from temp_file %! [temp_path, ans, ans] = fileparts(temp_file); %! addpath(temp_path); %! f = function_handle(2*x*y, 2^x, 'vars', {x y z}, 'file', temp_file); %! assert( isa(f, 'function_handle')) %! addpath(temp_path); % Matlab 2014a needs this? %! [a,b] = f(10,20,30); %! assert (isnumeric (a) && isnumeric (b)) %! assert (a == 400) %! assert (b == 1024) %! if (exist ('OCTAVE_VERSION', 'builtin')) %! assert (unlink(temp_file) == 0) %! else %! delete (temp_file) %! end %! % remove temp_path from load path %! rmpath(temp_path); %!test %! % non-scalar outputs %! H = [x y z]; %! M = [x y; z 16]; %! V = [x;y;z]; %! h = function_handle(H, M, V); %! [t1,t2,t3] = h(1,2,3); %! assert(isequal(t1, [1 2 3])) %! assert(isequal(t2, [1 2; 3 16])) %! assert(isequal(t3, [1;2;3])) %!test %! % non-scalar outputs in .m files %! H = [x y z]; %! M = [x y; z 16]; %! V = [x;y;z]; %! if (exist ('OCTAVE_VERSION', 'builtin')) %! temp_file = tempname('', 'oct_'); %! else %! temp_file = tempname(); %! end %! % allow loading function from temp_file %! [temp_path, ans, ans] = fileparts(temp_file); %! addpath(temp_path); %! h = function_handle(H, M, V, 'vars', {x y z}, 'file', temp_file); %! assert( isa(h, 'function_handle')) %! addpath(temp_path); % Matlab 2014a needs this? %! [t1,t2,t3] = h(1,2,3); %! assert(isequal(t1, [1 2 3])) %! assert(isequal(t2, [1 2; 3 16])) %! assert(isequal(t3, [1;2;3])) %! if (exist ('OCTAVE_VERSION', 'builtin')) %! assert (unlink([temp_file '.m']) == 0) %! else %! delete ([temp_file '.m']) %! end %! % remove temp_path from load path %! rmpath(temp_path); %!test %! % order of outputs is lexiographic %! syms a A x y %! f = y + 10*a + 100*x + 1000*A; %! h = function_handle(f); %! assert (h(1, 2, 3, 4) == 1000 + 20 + 300 + 4) %!test %! % https://github.com/cbm755/octsympy/issues/854 %! f = function_handle (x + 1i*sqrt (sym(3))); %! assert (f (1), complex (1, sqrt (3)), -eps) symbolic-3.1.1/inst/@sym/gamma.m0000644000000000000000000000330714405647405013364 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym gamma (@var{x}) %% Symbolic gamma function. %% %% Example: %% @example %% @group %% syms x %% y = gamma (x) %% @result{} y = (sym) Γ(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = gamma(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('gamma', x); end %!error gamma (sym(1), 2) %!assert (isequaln (gamma (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = gamma(x); %! f2 = gamma(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = gamma(A); %! f2 = gamma(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = gamma (d); %! f = gamma (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/gammainc.m0000644000000000000000000001217014405647405014054 0ustar %% Copyright (C) 2016, 2018-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym gammainc (@var{x}, @var{a}) %% @defmethodx @@sym gammainc (@var{x}, @var{a}, 'lower') %% @defmethodx @@sym gammainc (@var{x}, @var{a}, 'upper') %% Symbolic regularized incomplete gamma function. %% %% Example: %% @example %% @group %% syms x a %% gammainc(x, a) %% @result{} (sym) %% γ(a, x) %% ─────── %% Γ(a) %% @end group %% %% @group %% gammainc(x, a, 'upper') %% @result{} (sym) %% Γ(a, x) %% ─────── %% Γ(a) %% @end group %% @end example %% %% @strong{Note} the order of inputs is swapped in the displayed %% symbolic expression, @ref{@@sym/igamma}. This is purely cosmetic %% and does not effect operations on the results: %% @example %% @group %% @c doctest: +SKIP_IF(compare_versions (OCTAVE_VERSION(), '6.0.0', '<')) %% gammainc(3, 1) %% @result{} ans = 0.9502 %% gammainc(x, a) %% @result{} (sym) %% γ(a, x) %% ─────── %% Γ(a) %% @c doctest: +SKIP_IF(compare_versions (OCTAVE_VERSION(), '6.0.0', '<')) %% double(subs(ans, [x a], [3 1])) %% @result{} ans = 0.9502 %% @end group %% @end example %% %% @seealso{gammainc, @@sym/igamma, @@sym/gamma} %% @end defmethod function y = gammainc(z, a, which) if (nargin == 2) which = 'lower'; elseif (nargin == 3) % no-op else print_usage (); end if (strcmp(which, 'lower')) y = elementwise_op ('lowergamma', sym(a), sym(z)); elseif (strcmp(which, 'upper')) y = elementwise_op ('uppergamma', sym(a), sym(z)); else print_usage (); end y = y ./ gamma (a); end %!assert (isequal (gammainc (sym(0), 1), sym(0))) %!assert (isequal (gammainc (sym(0), 2), sym(0))) %!assert (isequal (gammainc (sym('oo'), 1), sym(1))) %!assert (isequal (gammainc (sym(0), 1, 'upper'), sym(1))) %!assert (isequal (gammainc (sym(0), 2, 'upper'), sym(1))) %!assert (isequal (gammainc (sym('oo'), 1, 'upper'), sym(0))) %!test %! % default is lower %! syms x a %! assert (isequal (gammainc (x, a), gammainc(x, a, 'lower'))) %!test %! % compare to double %! x = 5; a = 1; %! A = gammainc (x, a); %! B = double (gammainc (sym(x), a)); %! assert(A, B, -eps) %!test %! % compare to double where gamma(a) != 1 %! x = 5; a = 3; %! A = gammainc (x, a); %! B = double (gammainc (sym(x), a)); %! assert(A, B, -eps) %!test %! % compare to double %! x = 100; a = 1; %! A = gammainc (x, a); %! B = double (gammainc (sym(x), a)); %! assert(A, B, -eps) %!test %! % compare to double %! xs = sym(1)/1000; x = 1/1000; a = 1; %! A = gammainc (x, a); %! B = double (gammainc (xs, a)); %! assert(A, B, -eps) %!test %! % compare to double %! x = 5; a = 1; %! A = gammainc (x, a, 'upper'); %! B = double (gammainc (sym(x), a, 'upper')); %! assert(A, B, -10*eps) %!test %! % compare to double %! x = 10; a = 1; %! A = gammainc (x, a, 'upper'); %! B = double (gammainc (sym(x), a, 'upper')); %! assert(A, B, -10*eps) %!test %! % compare to double %! x = 40; a = 1; %! A = gammainc (x, a, 'upper'); %! B = double (gammainc (sym(x), a, 'upper')); %! assert(A, B, -10*eps) %!test %! % compare to double %! xs = sym(1)/1000; x = 1/1000; a = 1; %! A = gammainc (x, a, 'upper'); %! B = double (gammainc (xs, a, 'upper')); %! assert(A, B, -eps) %!test %! % vectorized %! P = gammainc([sym(pi) 2], [1 3]); %! expected = [gammainc(pi, sym(1)) gammainc(2, sym(3))]; %! assert (isequal (P, expected)) %!test %! % vectorized %! P = gammainc(sym(pi), [1 3]); %! expected = [gammainc(sym(pi), 1) gammainc(sym(pi), 3)]; %! assert (isequal (P, expected)) %!test %! % vectorized %! P = gammainc([sym(pi) 2], 1); %! expected = [gammainc(pi, sym(1)) gammainc(2, sym(1))]; %! assert (isequal (P, expected)) %!test %! % round trip %! syms x a %! f = gammainc (x, a, 'upper'); %! h = function_handle (f, 'vars', [x a]); %! A = h (1.1, 2); %! B = gammainc (1.1, 2, 'upper'); %! assert (A, B) %!test %! % round trip %! syms x a %! f = gammainc (x, a, 'lower'); %! h = function_handle (f, 'vars', [x a]); %! A = h (1.1, 2); %! B = gammainc (1.1, 2, 'lower'); %! assert (A, B) %!test %! % round trip %! syms x a %! f = gammainc (x, a, 'upper'); %! h = function_handle (f, 'vars', [x a]); %! A = h (1.1, 2.2); %! B = gammainc (1.1, 2.2, 'upper'); %! assert (A, B) %!test %! % round trip %! syms x a %! f = gammainc (x, a, 'lower'); %! h = function_handle (f, 'vars', [x a]); %! A = h (1.1, 2.2); %! B = gammainc (1.1, 2.2, 'lower'); %! assert (A, B) symbolic-3.1.1/inst/@sym/gammaln.m0000644000000000000000000000513014405647405013712 0ustar %% Copyright (C) 2016, 2018 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym gammaln (@var{x}) %% @defmethodx @@sym lgamma (@var{x}) %% Symbolic logarithm of the gamma function. %% %% Example: %% @example %% @group %% syms x %% y = gammaln(x) %% @result{} y = (sym) loggamma(x) %% y = lgamma(x) %% @result{} y = (sym) loggamma(x) %% @end group %% @end example %% %% @seealso{gammaln, @@sym/gamma, @@sym/psi} %% @end defmethod function y = gammaln(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('loggamma', x); end %!assert (isequal (gammaln (sym (3)), log (sym (2)))) %!assert (isequal (gammaln (sym (10)), log (gamma (sym (10))))) %!test %! % compare to Maple: evalf(lnGAMMA(Pi)); %! maple = vpa ('0.827694592323437101529578558452359951153502', 40); %! us = vpa (gammaln (sym(pi)), 40); %! assert (abs(double(maple-us)) < 1e-39) %!test %! % compare to Maple: evalf(lnGAMMA(3+2*I)); %! maple = vpa ('-0.0316390593739611898037677296008797172022603', 40) + ... %! vpa ('2.02219319750132712401643376238334982100512j', 40); %! us = vpa (gammaln (sym(3) + 2i), 40); %! assert (abs(double(maple-us)) < 1e-39) %!test %! % compare to Maple: evalf(lnGAMMA(-1.5)); %! % notably, @double/gammaln has zero imag part %! maple = vpa ('0.8600470153764810145109326816703567873271571', 40) - ... %! vpa ('6.2831853071795864769252867665590057683943388j', 40); %! us = vpa (gammaln (-sym(3)/2), 40); %! assert (abs(double(maple-us)) < 1e-39) % should match @double/gammaln %!assert (gammaln (pi), double (gammaln (sym (pi))), -3*eps) %!assert (gammaln (100), double (gammaln (sym (100))), -3*eps) % failed at -3*eps on one system: Windows 10, Atom 64bit. %!assert (gammaln (1e-3), double (gammaln (1/sym (1e3))), -100*eps) %!test %! % round trip %! syms x %! f = gammaln (x); %! h = function_handle (f); %! A = h (1.1); %! B = gammaln (1.1); %! assert (A, B) symbolic-3.1.1/inst/@sym/ge.m0000644000000000000000000000346214405647405012677 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym ge {(@var{a}, @var{b})} %% @defopx Operator @@sym {@var{a} >= @var{b}} {} %% Test/define symbolic inequality, greater than or equal to. %% %% Examples: %% @example %% @group %% sym(1) >= sym(pi) %% @result{} (sym) False %% %% syms x %% x >= 10 %% @result{} (sym) x ≥ 10 %% @end group %% @end example %% %% @seealso{@@sym/gt, @@sym/lt, @@sym/le, @@sym/eq, @@sym/ne, %% @@sym/logical, @@sym/isAlways} %% @end defop function t = ge(x, y) if (nargin ~= 2) print_usage (); end t = ineq_helper('>=', 'Ge', sym(x), sym(y)); end %!test %! % simple %! x = sym(1); y = sym(1); e = x >= y; %! assert (logical (e)) %! x = sym(1); y = sym(2); e = x >= y; %! assert (~logical(e)) %!test %! % array -- array %! syms x %! a = sym([1 3 3 2*x]); %! b = sym([2 x 3 10]); %! e = a >= b; %! assert (isa (e, 'sym')) %! assert (~logical (e(1))) %! assert (isa (e(2), 'sym')) %! assert (isequal (e(2), 3 >= x)) %! assert (logical (e(3))) %! assert (isa (e(4), 'sym')) %! assert (isequal (e(4), 2*x >= 10)) symbolic-3.1.1/inst/@sym/gradient.m0000644000000000000000000001065214405647405014100 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym gradient (@var{f}) %% @defmethodx @@sym gradient (@var{f}, @var{x}) %% Symbolic gradient of symbolic expression. %% %% The gradient of scalar expression is the vector %% @example %% @group %% syms f(x, y, z) %% gradient(f) %% @result{} (sym 3×1 matrix) %% ⎡∂ ⎤ %% ⎢──(f(x, y, z))⎥ %% ⎢∂x ⎥ %% ⎢ ⎥ %% ⎢∂ ⎥ %% ⎢──(f(x, y, z))⎥ %% ⎢∂y ⎥ %% ⎢ ⎥ %% ⎢∂ ⎥ %% ⎢──(f(x, y, z))⎥ %% ⎣∂z ⎦ %% @end group %% @end example %% %% Example: %% @example %% @group %% f = x^3 + 5*y^2; %% gradient(f) %% @result{} (sym 2×1 matrix) %% ⎡ 2⎤ %% ⎢3⋅x ⎥ %% ⎢ ⎥ %% ⎣10⋅y⎦ %% @end group %% @end example %% %% @var{x} can be a scalar, vector or cell list. If omitted, %% it is determined using @code{symvar}. Example: %% @example %% @group %% gradient(f, @{x y z@}) %% @result{} (sym 3×1 matrix) %% ⎡ 2⎤ %% ⎢3⋅x ⎥ %% ⎢ ⎥ %% ⎢10⋅y⎥ %% ⎢ ⎥ %% ⎣ 0 ⎦ %% @end group %% @end example %% %% Note: assumes @var{x} is a Cartesian coordinate system. %% %% @seealso{@@sym/divergence, @@sym/curl, @@sym/laplacian, @@sym/jacobian, %% @@sym/hessian} %% @end defmethod function g = gradient(f,x) assert (isscalar(f), 'gradient: defined only for scalar functions') if (nargin == 1) x = symvar(f); if (isempty(x)) x = sym('x'); end elseif (nargin == 2) % no-op else print_usage (); end if (~iscell(x) && isscalar(x)) x = {x}; end cmd = { '(f, x) = _ins' 'if not f.is_Matrix:' ' f = Matrix([f])' 'G = f.jacobian(x).T' 'return G,' }; g = pycall_sympy__ (cmd, sym(f), x); end %!shared x,y,z %! syms x y z %!test %! % 1D %! f = x^2; %! assert (isequal (gradient(f), diff(f,x))) %! assert (isequal (gradient(f,{x}), diff(f,x))) %! assert (isequal (gradient(f,[x]), diff(f,x))) %! assert (isequal (gradient(f,x), diff(f,x))) %!test %! % const %! f = sym(1); %! g = sym(0); %! assert (isequal (gradient(f), g)) %! assert (isequal (gradient(f,x), g)) %!test %! % double const %! f = 1; %! g = sym(0); %! assert (isequal (gradient(f,x), g)) %!test %! % 1D fcn in 2d/3d %! f = sin(y); %! assert (isequal (gradient(f), diff(f,y))) %! assert (isequal (gradient(f, {x,y}), [sym(0); diff(f,y)])) %! assert (isequal (gradient(f, [x y]), [sym(0); diff(f,y)])) %! assert (isequal (size (gradient(f, {x,y})), [2 1])) %! assert (isequal (gradient(f, {x,y,z}), [0; diff(f,y); 0])) %! assert (isequal (gradient(f, [x y z]), [0; diff(f,y); 0])) %! assert (isequal (size (gradient(f, {x,y,z})), [3 1])) %!test %! % grad is column vector %! f = sin(y); %! assert (isequal (size (gradient(f, {x,y})), [2 1])) %! assert (isequal (size (gradient(f, {x,y,z})), [3 1])) %! assert (isequal (size (gradient(f, [x y])), [2 1])) %! assert (isequal (size (gradient(f, [x;y])), [2 1])) %!test %! % 2d fcn in 2d/3d %! f = sin(exp(x)*y); %! g2 = [diff(f,x); diff(f,y)]; %! g3 = [diff(f,x); diff(f,y); diff(f,z)]; %! assert (isequal (gradient(f), g2)) %! assert (isequal (gradient(f, {x,y}), g2)) %! assert (isequal (gradient(f, {x,y,z}), g3)) %!test %! % 2d fcn in 2d/3d %! f = sin(exp(x)*y+sinh(z)); %! g2 = [diff(f,x); diff(f,y)]; %! g3 = [diff(f,x); diff(f,y); diff(f,z)]; %! assert (isequal (gradient(f), g3)) %! assert (isequal (gradient(f, {x,y}), g2)) %! assert (isequal (gradient(f, {x,y,z}), g3)) %!error gradient(sym('x'), 42, 42) %!error gradient([sym('x') sym('x')]) symbolic-3.1.1/inst/@sym/gt.m0000644000000000000000000000343614405647405012717 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym gt {(@var{a}, @var{b})} %% @defopx Operator @@sym {@var{a} > @var{b}} {} %% Test/define symbolic inequality, greater than. %% %% Examples: %% @example %% @group %% sym(1) > sym(pi) %% @result{} (sym) False %% %% syms x %% x > 10 %% @result{} (sym) x > 10 %% @end group %% @end example %% %% @seealso{@@sym/ge, @@sym/lt, @@sym/le, @@sym/eq, @@sym/ne, %% @@sym/logical, @@sym/isAlways} %% @end defop function t = gt(x, y) if (nargin ~= 2) print_usage (); end t = ineq_helper('>', 'Gt', sym(x), sym(y)); end %!test %! % simple %! x = sym(1); y = sym(1); e = x > y; %! assert (~logical (e)) %! x = sym(1); y = sym(2); e = x > y; %! assert (~logical (e)) %!test %! % array -- array %! syms x %! a = sym([1 3 3 2*x]); %! b = sym([2 x 3 10]); %! e = a > b; %! assert (isa (e, 'sym')) %! assert (~logical (e(1))) %! assert (isa (e(2), 'sym')) %! assert (isequal (e(2), 3 > x)) %! assert (~logical (e(3))) %! assert (isa (e(4), 'sym')) %! assert (isequal (e(4), 2*x > 10)) symbolic-3.1.1/inst/@sym/harmonic.m0000644000000000000000000000637714405647405014114 0ustar %% Copyright (C) 2017-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym harmonic (@var{x}) %% Symbolic harmonic function. %% %% For integers, the harmonic function can be defined as: %% @example %% @group %% syms n integer %% y = harmonic (n) %% @result{} y = (sym) harmonic(n) %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.4")')) %% rewrite (y, 'Sum') %% @result{} (sym) %% %% n %% ____ %% ╲ %% ╲ %% ╲ 1 %% ╱ ─ %% ╱ k %% ╱ %% ‾‾‾‾ %% k = 1 %% @end group %% @end example %% %% Examples: %% @example %% @group %% harmonic (sym(1:7)) %% @result{} (sym 1×7 matrix) %% %% ⎡ 25 137 49 363⎤ %% ⎢1 3/2 11/6 ── ─── ── ───⎥ %% ⎣ 12 60 20 140⎦ %% @end group %% %% @group %% harmonic (sym(120)) %% @result{} ans = (sym) %% %% 18661952910524692834612799443020757786224277983797 %% ────────────────────────────────────────────────── %% 3475956553913558034594585593659201286533187398464 %% %% double (ans) %% @result{} ans = 5.3689 %% @end group %% @end example %% %% %% It is also defined for non-integers, for example: %% @example %% @group %% y = harmonic (sym(1)/3) %% @result{} y = (sym) harmonic(1/3) %% vpa (y) %% @result{} (sym) 0.44518188488072653761009301579513 %% @end group %% %% @group %% y = harmonic (sym(i)) %% @result{} y = (sym) harmonic(ⅈ) %% vpa (y) %% @result{} (sym) 0.67186598552400983787839057280431 + %% 1.07667404746858117413405079475⋅ⅈ %% @end group %% @end example %% %% An example establishing an identity: %% @example %% @group %% syms x %% A = psi (x) + eulergamma () %% @result{} A = (sym) polygamma(0, x) + γ %% rewrite (A, 'harmonic') %% @result{} ans = (sym) harmonic(x - 1) %% @end group %% @end example %% %% @seealso{bernoulli} %% @end defmethod function y = harmonic(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('harmonic', x); end %!error harmonic (sym(1), 2) %!xtest %! assert (isequaln (harmonic (sym(nan)), sym(nan))) %!assert (isequal (harmonic (sym(0)), sym(0))) %!assert (isinf (harmonic (sym(inf)))) %!assert (isequal (harmonic (sym([9 10])), [sym(7129)/2520 sym(7381)/2520])) %!test %! % round trip %! y = sym('y'); %! A = harmonic (7); %! f = harmonic (y); %! h = function_handle (f); %! B = h (7); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/has.m0000644000000000000000000000461114405647405013054 0ustar %% Copyright (C) 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym has (@var{expr}, @var{subexpr}) %% @defmethodx @@sym has (@var{M}, @var{subexpr}) %% Naively test if an expression contains a subexpression. %% %% Example: %% @example %% @group %% syms x %% has(x^2 + 3*x + 2, x^2) %% @result{} ans = 1 %% has((x+1)*(x+2), x^2) %% @result{} ans = 0 %% @end group %% @end example %% (Note @code{has} does not try to do any mathematics: it %% just checks whether @var{expr} @emph{as written} contains %% @var{subexpr}.) %% %% If the first argument is a matrix @var{M}, check if each element %% of the matrix contains @var{subexpr}: %% @example %% @group %% M = [sym(1) sym(pi)/2; 2*sym(pi) 4]; %% has(M, sym(pi)) %% @result{} ans = %% 0 1 %% 1 0 %% @end group %% @end example %% %% @strong{Caution:} @code{has} does not do mathematics; it is just %% searching for @var{subexpr}. This can lead to confusing results, %% for example, @code{has} should not be used to check for for membership %% in a set: %% @example %% @group %% A = finiteset(1, 2, -sym(pi)); %% has(A, -1) %% @result{} ans = 1 %% @end group %% @end example %% Instead, @pxref{@@sym/ismember}. %% %% @seealso{@@sym/ismember} %% @end defmethod function r = has(f, x) if (nargin ~= 2) print_usage (); end r = uniop_bool_helper(sym(f), 'lambda f,x: f.has(x)', [], sym(x)); end %!shared A, x, y %! syms x y %! A = [sym(pi) 2*sym(pi); x*y x+y]; %!assert (isequal (has(A, x), [false false; true true])); %!assert (isequal (has(A, x+y), [false false; false true])); %!assert (isequal (has(A, 2), [false true; false false])); %!assert (isequal (has(A, sym(pi)), [true true; false false])); symbolic-3.1.1/inst/@sym/heaviside.m0000644000000000000000000000710314405647405014241 0ustar %% Copyright (C) 2014-2016, 2018-2019, 2022 Colin B. Macdonald %% Copyright (C) 2022 Chris Gorman %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym heaviside (@var{x}) %% @defmethodx @@sym heaviside (@var{x}, @var{zero_value}) %% Symbolic Heaviside step function. %% %% Example: %% @example %% @group %% syms x %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.4")')) %% y = heaviside (x) %% @result{} y = (sym) θ(x) %% @end group %% @end example %% %% There are various conventions for 'heaviside(sym(0))'; this function %% returns the midpoint by default. %% @example %% @group %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.8")')) %% heaviside(sym(0)) %% @result{} (sym) 1/2 %% @end group %% @end example %% %% The optional second argument overrides the default. For example %% to make the function right-continuous, %% @example %% @group %% heaviside(0, sym(1)) %% @result{} (sym) 1 %% @end group %% @end example %% or left-continuous. %% @example %% @group %% heaviside(0, sym(0)) %% @result{} (sym) 0 %% @end group %% @end example %% %% If passed a matrix, the heaviside function is computed for each %% element. %% @example %% @group %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.8")')) %% heaviside([sym(-1) sym(0) sym(1) sym(x)]) %% @result{} (sym) [0 1/2 1 θ(x)] (1×4 matrix) %% @end group %% @end example %% @seealso{heaviside, @@sym/dirac} %% @end defmethod function y = heaviside(x, h0) if (nargin == 1) y = elementwise_op ('Heaviside', x); elseif (nargin == 2) y = elementwise_op ('Heaviside', sym(x), sym(h0)); else print_usage (); end end %!error heaviside (sym(1), 2, 3) %!assert (isequal (heaviside (sym(1)), sym(1))) %!assert (isequal (heaviside (-sym(1)), sym(0))) %!assert (double (heaviside (1)), heaviside (1)) %!test %! D = [1 -1; -10 20]; %! A = sym(D); %! assert (double (heaviside (A)), heaviside (D)) %!test %! H0 = sym([1 -2 0; 3 0 pi]); %! A = heaviside (sym(0), H0); %! assert (isequal (A, H0)) %!test %! A = heaviside ([-1 0 1], sym(1)/2); %! assert (isequal (A, [0 sym(1)/2 1])) %!test %! A = heaviside ([-1 0 1], sym(1)/2); %! assert (isequal (A, [0 sym(1)/2 1])) %!assert (isequaln (heaviside (sym(nan)), sym(nan))) %!test %! assert (isequaln (heaviside (sym(nan), sym(nan)), sym(nan))) %! assert (isequaln (heaviside (0, sym(nan)), sym(nan))) %! assert (isequaln (heaviside (2, sym(nan)), sym(1))) %! assert (isequaln (heaviside (-2, sym(nan)), sym(0))) %!test %! % round trip %! syms x %! A = heaviside (1); %! f = heaviside (x); %! h = function_handle (f); %! B = h (1); %! assert (A, B, -eps) %!test %! % round trip %! syms x h0 %! f = heaviside (x, h0); %! h = function_handle (f, 'vars', {x h0}); %! A = heaviside (1, 1/2); %! B = h (1, 1/2); %! assert (A, B, -eps) %! A = heaviside (0, 1/2); %! B = h (0, 1/2); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/hessian.m0000644000000000000000000001052514405647405013734 0ustar %% Copyright (C) 2014, 2016, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym hessian (@var{f}) %% @defmethodx @@sym hessian (@var{f}, @var{x}) %% Symbolic Hessian matrix of symbolic scalar expression. %% %% The Hessian of a scalar expression @var{f} is the matrix consisting %% of second derivatives: %% @example %% @group %% syms f(x, y, z) %% hessian(f) %% @result{} (sym 3×3 matrix) %% ⎡ 2 2 2 ⎤ %% ⎢ ∂ ∂ ∂ ⎥ %% ⎢ ───(f(x, y, z)) ─────(f(x, y, z)) ─────(f(x, y, z))⎥ %% ⎢ 2 ∂y ∂x ∂z ∂x ⎥ %% ⎢ ∂x ⎥ %% ⎢ ⎥ %% ⎢ 2 2 2 ⎥ %% ⎢ ∂ ∂ ∂ ⎥ %% ⎢─────(f(x, y, z)) ───(f(x, y, z)) ─────(f(x, y, z))⎥ %% ⎢∂y ∂x 2 ∂z ∂y ⎥ %% ⎢ ∂y ⎥ %% ⎢ ⎥ %% ⎢ 2 2 2 ⎥ %% ⎢ ∂ ∂ ∂ ⎥ %% ⎢─────(f(x, y, z)) ─────(f(x, y, z)) ───(f(x, y, z)) ⎥ %% ⎢∂z ∂x ∂z ∂y 2 ⎥ %% ⎣ ∂z ⎦ %% @end group %% @end example %% %% @var{x} can be a scalar, vector or cell list. If omitted, %% it is determined using @code{symvar}. %% %% Example: %% @example %% @group %% f = x*y; %% hessian(f) %% @result{} (sym 2×2 matrix) %% ⎡0 1⎤ %% ⎢ ⎥ %% ⎣1 0⎦ %% @end group %% @end example %% @seealso{@@sym/jacobian, @@sym/divergence, @@sym/gradient, @@sym/curl, %% @@sym/laplacian} %% @end defmethod function H = hessian(f, x) assert (isscalar(f), 'hessian: defined only for scalar functions') if (nargin == 1) x = symvar(f); if (isempty(x)) x = sym('x'); end elseif (nargin == 2) % no-op else print_usage (); end if (~iscell(x) && isscalar(x)) x = {x}; end cmd = { '(f,x,) = _ins' '#if not f.is_Matrix:' 'f = Matrix([f])' 'grad = f.jacobian(x).T' 'H = grad.jacobian(x)' 'return H,' }; H = pycall_sympy__ (cmd, sym(f), x); end %!error hessian (sym(1), 2, 3) %!error hessian ([sym(1) sym(2)]) %!shared x,y,z %! syms x y z %!test %! % 1D %! f = x^2; %! assert (isequal (hessian(f), diff(f,x,x))) %! assert (isequal (hessian(f,{x}), diff(f,x,x))) %! assert (isequal (hessian(f,x), diff(f,x,x))) %!test %! % const %! f = sym(1); %! g = sym(0); %! assert (isequal (hessian(f), g)) %! assert (isequal (hessian(f,x), g)) %!test %! % double const %! f = 1; %! g = sym(0); %! assert (isequal (hessian(f,x), g)) %!test %! % linear %! f = 42*x; %! g = sym(0); %! assert (isequal (hessian(f), g)) %! assert (isequal (hessian(f,x), g)) %!test %! % linear %! f = 42*x - sym('a')*y; %! g = [0 0; 0 0]; %! assert (isequal (hessian(f, {x y}), g)) %!test %! % 2d %! f = x*cos(y); %! g = [0 -sin(y); -sin(y) -f]; %! assert (isequal (hessian(f), g)) %! assert (isequal (hessian(f, {x y}), g)) %!test %! % 3d %! f = x*cos(z); %! Hexp = [0 0 -sin(z); sym(0) 0 0; -sin(z) 0 -f]; %! H = hessian(f, {x y z}); %! assert (isequal (H, Hexp)) symbolic-3.1.1/inst/@sym/hilb.m0000644000000000000000000000265614405647405013226 0ustar %% Copyright (C) 2016 Lagu %% Copyright (C) 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym hilb (@var{n}) %% Return the symbolic Hilbert matrix. %% %% Example: %% @example %% @group %% hilb (sym(2)) %% @result{} ans = (sym 2×2 matrix) %% ⎡ 1 1/2⎤ %% ⎢ ⎥ %% ⎣1/2 1/3⎦ %% @end group %% @end example %% %% @seealso{@@sym/invhilb} %% @end defmethod function y = hilb(x) if (nargin ~= 1) print_usage (); end y = pycall_sympy__ ('return Matrix(_ins[0], _ins[0], lambda i,j: 1 / (i + j + 1)),', x); end %!test %! A = hilb (sym(3)); %! B = [sym(1) sym(1)/2 sym(1)/3; sym(1)/2 sym(1)/3 sym(1)/4; sym(1)/3 sym(1)/4 sym(1)/5]; %! assert (isequal (A, B)) symbolic-3.1.1/inst/@sym/horner.m0000644000000000000000000000464514405647405013605 0ustar %% Copyright (C) 2014-2016, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym horner (@var{p}) %% @defmethodx @@sym horner (@var{p}, @var{x}) %% Convert a symbolic polynomial to Horner form. %% %% The Horner form minimizes the number of arthimetic operators to %% evaluate the polynomial. %% %% Example: %% @example %% @group %% syms x %% p = poly2sym ([2 4 6 8], x) %% @result{} p = (sym) %% 3 2 %% 2⋅x + 4⋅x + 6⋅x + 8 %% horner (p) %% @result{} ans = (sym) x⋅(x⋅(2⋅x + 4) + 6) + 8 %% @end group %% @end example %% %% You can specify the variable as a second input: %% @example %% @group %% syms x a %% p = expand((a+2)*(2*a+x)*(3*a+7)); %% horner(p, a) %% @result{} ans = (sym) a⋅(a⋅(6⋅a + 3⋅x + 26) + 13⋅x + 28) + 14⋅x %% @end group %% @end example %% %% @seealso{poly2sym} %% @end defmethod function y = horner(p, x) if (nargin > 2) print_usage (); end if (nargin == 1) x = symvar(p, 1); end if (isempty(x)) y = pycall_sympy__ ('return sp.horner(*_ins),', sym(p)); else y = pycall_sympy__ ('return sp.horner(*_ins),', sym(p), sym(x)); end end %!error horner (sym(1), 2, 3) %!assert (isAlways (horner(sym(1)) == 1)) %!test %! syms x %! assert (isAlways (horner(x) == x)) %!test %! syms x a %! p = a^2 + a*x + 2*a + 2*x; %! assert (isequal (horner (p, a), a*(a+x+2) + 2*x)) %! q = a^2 + 2*a + x*(a + 2); %! assert (isequal (horner (p, x), q)) %! assert (isequal (horner (p), q)) %!test %! syms x %! p = poly2sym ([2 4 6 8], x); %! q = horner (p); %! assert (isAlways (p == q)) %! assert (isAlways (horner(2*x^3 + 4*x^2 + 6*x + 8) == q)) %!test %! % non-sym input %! syms x %! assert (isequal (horner(6, x), sym(6))) symbolic-3.1.1/inst/@sym/horzcat.m0000644000000000000000000000674714405647405013767 0ustar %% Copyright (C) 2014-2017, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym {horzcat} {(@var{x}, @var{y}, @dots{})} %% @defopx Operator @@sym {[@var{x}, @var{y}, @dots{}]} {} %% @defopx Operator @@sym {[@var{x} @var{y} @dots{}]} {} %% Horizontally concatentate symbolic arrays. %% %% Example: %% @example %% @group %% A = sym([1 2; 3 4]) %% @result{} A = (sym 2×2 matrix) %% ⎡1 2⎤ %% ⎢ ⎥ %% ⎣3 4⎦ %% %% [A A A] %% @result{} (sym 2×6 matrix) %% ⎡1 2 1 2 1 2⎤ %% ⎢ ⎥ %% ⎣3 4 3 4 3 4⎦ %% @end group %% @end example %% @seealso{@@sym/vertcat, @@sym/cat} %% @end defop function h = horzcat(varargin) % special case for 0x0 but other empties should be checked for % compatibilty cmd = { '_proc = []' 'for i in _ins:' ' if i is None or not i.is_Matrix:' ' _proc.append(sp.Matrix([[i]]))' ' else:' ' if i.shape == (0, 0):' ' pass' ' else:' ' _proc.append(i)' 'return sp.MatrixBase.hstack(*_proc),' }; for i = 1:nargin varargin{i} = sym(varargin{i}); end h = pycall_sympy__ (cmd, varargin{:}); end %!test %! % basic %! syms x %! A = [x x]; %! B = horzcat(x, x); %! C = horzcat(x, x, x); %! assert (isa (A, 'sym')) %! assert (isa (B, 'sym')) %! assert (isa (C, 'sym')) %! assert (isequal (size(A), [1 2])) %! assert (isequal (size(B), [1 2])) %! assert (isequal (size(C), [1 3])) %!test %! % basic, part 2 %! syms x %! A = [x 1]; %! B = [1 x]; %! C = [1 2 x]; %! assert (isa (A, 'sym')) %! assert (isa (B, 'sym')) %! assert (isa (C, 'sym')) %! assert (isequal (size(A), [1 2])) %! assert (isequal (size(B), [1 2])) %! assert (isequal (size(C), [1 3])) %!test %! % row vectors %! a = [sym(1) 2]; %! b = [sym(3) 4]; %! assert (isequal ( [a b] , [1 2 3 4] )) %! assert (isequal ( [a 3 4] , [1 2 3 4] )) %! assert (isequal ( [3 4 a] , [3 4 1 2] )) %! assert (isequal ( [a [3 4]] , [1 2 3 4] )) %! assert (isequal ( [a sym(3) 4] , [1 2 3 4] )) %! assert (isequal ( [a [sym(3) 4]] , [1 2 3 4] )) %!test %! % col vectors %! a = [sym(1); 2]; %! b = [sym(3); 4]; %! assert (isequal ( [a b] , [1 3; 2 4] )) %! assert (isequal ( [a b a] , [1 3 1; 2 4 2] )) %!test %! % empty vectors %! v = sym(1); %! a = [v []]; %! assert (isequal (a, v)) %! a = [[] v []]; %! assert (isequal (a, v)) %! a = [v [] []]; %! assert (isequal (a, v)) %!test %! % more empty vectors %! v = [sym(1) sym(2)]; %! q = sym(ones(1, 0)); %! assert (isequal ([v q], v)) %!error %! v = [sym(1) sym(2)]; %! q = sym(ones(3, 0)); %! w = horzcat(v, q); %!test %! % issue #700 %! A = sym ([1 2]); %! B = simplify (A); %! assert (isequal ([B A], [A B])) symbolic-3.1.1/inst/@sym/hypergeom.m0000644000000000000000000000675414405647405014312 0ustar %% Copyright (C) 2016-2017, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym hypergeom (@var{a}, @var{b}, @var{z}) %% Symbolic generalized hypergeometric function. %% %% Example: %% @example %% @group %% syms z %% hypergeom ([1, 2, 3], [4, 5], z) %% @result{} (sym) %% ┌─ ⎛1, 2, 3 │ ⎞ %% ├─ ⎜ │ z⎟ %% 3╵ 2 ⎝ 4, 5 │ ⎠ %% @end group %% @end example %% %% Simplifying can be useful to express a hypergeometric %% function in terms of more elementary functions: %% @example %% @group %% simplify (hypergeom ([1 1], 2, -z)) %% @result{} (sym) %% log(z + 1) %% ────────── %% z %% @end group %% @end example %% %% The function can be `vectorized' over @var{z}: %% @example %% @group %% syms a b c %% hypergeom([a b], c, [z 1/z 8]) %% @result{} (sym 1×3 matrix) %% ⎡ ┌─ ⎛a, b │ ⎞ ┌─ ⎛a, b │ 1⎞ ┌─ ⎛a, b │ ⎞⎤ %% ⎢ ├─ ⎜ │ z⎟ ├─ ⎜ │ ─⎟ ├─ ⎜ │ 8⎟⎥ %% ⎣2╵ 1 ⎝ c │ ⎠ 2╵ 1 ⎝ c │ z⎠ 2╵ 1 ⎝ c │ ⎠⎦ %% @end group %% @end example %% %% The hypergeometric function can be differentiated, for example: %% @example %% @group %% w = hypergeom([a b], c, z) %% @result{} w = (sym) %% ┌─ ⎛a, b │ ⎞ %% ├─ ⎜ │ z⎟ %% 2╵ 1 ⎝ c │ ⎠ %% %% diff(w, z) %% @result{} (sym) %% ┌─ ⎛a + 1, b + 1 │ ⎞ %% a⋅b⋅ ├─ ⎜ │ z⎟ %% 2╵ 1 ⎝ c + 1 │ ⎠ %% ─────────────────────────── %% c %% @end group %% @end example %% @end defmethod function F = hypergeom(a, b, z) if (nargin ~= 3) print_usage (); end cmd = { '(a, b, z) = _ins' 'try:' ' iter(a)' 'except TypeError:' ' a = [a]' 'try:' ' iter(b)' 'except TypeError:' ' b = [b]' 'if z.is_Matrix:' ' return z.applyfunc(lambda x: hyper(a, b, x))' 'return hyper(a, b, z)' }; F = pycall_sympy__ (cmd, sym(a), sym(b), sym(z)); end %!assert (isequal (double (hypergeom ([1, 2], [2, 3], sym(0))), 1)) %!test %! % matrix input %! syms z %! a = sym([1 2]); %! b = sym([3 4]); %! A = hypergeom (a, b, [0 sym(1); 2 z]); %! B = [hypergeom(a,b,0) hypergeom(a,b,1); hypergeom(a,b,2) hypergeom(a,b,z)]; %! assert (isequal (A, B)) %!test %! % scalars for a and/or b %! syms z %! assert (isequal (hypergeom(1, 2, z), hypergeom({sym(1)}, {sym(2)}, z))) %! assert (isequal (hypergeom([1 2], 3, z), hypergeom([1 2], {sym(3)}, z))) %! assert (isequal (hypergeom(1, [2 3], z), hypergeom({sym(1)}, [2 3], z))) symbolic-3.1.1/inst/@sym/hypot.m0000644000000000000000000000432514405647405013446 0ustar %% Copyright (C) 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym hypot (@var{x}, @var{y}) %% @defmethodx @@sym hypot (@var{x}, @var{y}, @var{z}, @dots{}) %% Return hypoteneuse (distance) from symbolic expressions. %% %% Example of computing distance: %% @example %% @group %% syms x y real %% syms z %% hypot (x, y, z) %% @result{} (sym) %% ________________ %% ╱ 2 2 2 %% ╲╱ x + y + │z│ %% @end group %% @end example %% %% Another example involving complex numbers: %% @example %% @group %% hypot (sym([12 2]), [3+4i 1+2i]) %% @result{} (sym) [13 3] (1×2 matrix) %% @end group %% @end example %% %% @seealso{@@sym/atan2} %% @end defmethod function h = hypot(varargin) % two inputs: %h = sqrt(abs(sym(x)).^2 + abs(sym(y)).^2); two = sym(2); L = cellfun(@(x) power(abs(sym(x)), two), varargin, 'UniformOutput', false); s = L{1}; for i=2:length(L); s = s + L{i}; end h = sqrt(s); end %!assert (isequal (hypot (sym(3), 4), sym(5))) %!test %! % compare to @double (note Matlab hypot only takes 2 inputs) %! A = hypot (hypot ([1 2 3], [4 5 6]), [7 8 9]); %! B = double (hypot (sym([1 2 3]), [4 5 6], [7 8 9])); %! assert (A, B, -eps) %!test %! % compare to @double, with complex %! A = hypot ([1+2i 3+4i], [1 3+1i]); %! B = double (hypot (sym([1+2i 3+4i]), [1 3+1i])); %! assert (A, B, -eps) %!test %! % matrices %! x = sym([1 -2; 0 3]); %! y = sym([0 0; 8 4]); %! A = hypot (x, y); %! B = sym([1 2; 8 5]); %! assert (isequal (A, B)) symbolic-3.1.1/inst/@sym/ifourier.m0000644000000000000000000001414314405647405014126 0ustar %% Copyright (C) 2014-2016, 2018-2019, 2022 Colin B. Macdonald %% Copyright (C) 2015-2016 Andrés Prieto %% Copyright (C) 2015 Alexander Misel %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym ifourier (@var{G}, @var{w}, @var{x}) %% @defmethodx @@sym ifourier (@var{G}) %% @defmethodx @@sym ifourier (@var{G}, @var{x}) %% Symbolic inverse Fourier transform. %% %% The inverse Fourier transform of a function @var{G} of @var{w} %% is a function @var{f} of @var{x} defined by the integral below. %% @example %% @group %% syms G(w) x %% f(x) = rewrite(ifourier(G), 'Integral') %% @result{} f(x) = (symfun) %% ∞ %% ⌠ %% ⎮ ⅈ⋅w⋅x %% ⎮ G(w)⋅ℯ dw %% ⌡ %% -∞ %% ───────────────── %% 2⋅π %% @end group %% @end example %% %% Example: %% @example %% @group %% syms k %% F = sqrt(sym(pi))*exp(-k^2/4); %% ifourier(F) %% @result{} (sym) %% 2 %% -x %% ℯ %% @end group %% @group %% F = 2*sym(pi)*dirac(k); %% ifourier(F) %% @result{} ans = (sym) 1 %% @end group %% @end example %% %% Note @code{fourier} and @code{ifourier} implement the non-unitary, %% angular frequency convention for L^2 functions and distributions. %% %% *WARNING*: As of SymPy 0.7.6 (June 2015), there are many problems %% with (inverse) Fourier transforms of non-smooth functions, even very %% simple ones. Use at your own risk, or even better: help us fix SymPy. %% %% @seealso{@@sym/fourier} %% @end defmethod function f = ifourier(varargin) if (nargin > 3) print_usage (); end % FIXME: it only works for scalar functions % FIXME: it doesn't handle diff call (see SMT transform of diff calls) F = sym(varargin{1}); if (nargin == 3) k = sym(varargin{2}); else %% frequency domain variable not specifed % if exactly one symbol has char(k) == 'k'... symbols = findsymbols (F); charsyms = cell (size (symbols)); for i=1:numel(symbols) charsyms{i} = char (symbols{i}); end I = find (strcmp (charsyms, 'k')); assert (numel (I) <= 1, 'ifourier: there is more than one "k" symbol: check symvar(F) and sympy(F)') if (~ isempty (I)) k = symbols{I}; % ... we want that one else k = symvar(F, 1); % else we use symvar choice if (isempty(k)) k = sym('k'); end end end if (nargin == 1) x = sym('x'); %% If the frequency variable k turned out to be "x", then % use "t" as the spatial domain variable (analogously to SMT) if (strcmp (char (k), char (x))) x = sym('t'); end elseif (nargin == 2) x = sym(varargin{2}); elseif (nargin == 3) x = sym(varargin{3}); end cmd = { 'F, k, x = _ins' '#f = inverse_fourier_transform(F, k, x)' '#return f.subs(x, x/(2*S.Pi)) / (2*S.Pi)' 'f=0; a_ = sp.Wild("a_"); b_ = sp.Wild("b_")' 'Fr=F.rewrite(sp.exp)' 'if type(Fr)==sp.Add:' ' terms=Fr.expand().args' 'else:' ' terms=(Fr,)' 'for term in terms:' ' #compute the Fourier transform ' ' r=sp.simplify(term*sp.exp(sp.I*x*k)).match(a_*sp.exp(b_))' ' # if a is constant and b/(I*k) is constant' ' modulus=r[a_]' ' phase=r[b_]/(sp.I*k)' ' if sp.diff(modulus,k)==0 and sp.diff(phase,k)==0:' ' f = f + modulus*2*sp.pi*sp.DiracDelta(phase)' ' else:' ' fterm=sp.integrate(sp.simplify(term*sp.exp(sp.I*x*k)), (k, -sp.oo, sp.oo))' ' if fterm.is_Piecewise:' ' f=f+sp.simplify(fterm.args[0][0])' ' else:' ' f=f+sp.simplify(fterm)' 'return f/(2*sp.pi),'}; f = pycall_sympy__ (cmd, F, k, x); end %!error ifourier (sym(1), 2, 3, 4) %!test %! % matlab SMT compat %! syms t r u x w %! Pi=sym('pi'); %! assert(logical( ifourier(exp(-abs(w))) == 1/(Pi*(x^2 + 1)) )) %! assert(logical( ifourier(exp(-abs(x))) == 1/(Pi*(t^2 + 1)) )) %! assert(logical( ifourier(exp(-abs(r)),u) == 1/(Pi*(u^2 + 1)) )) %! assert(logical( ifourier(exp(-abs(r)),r,u) == 1/(Pi*(u^2 + 1)) )) %!test %! % basic %! syms x w %! Pi=sym('pi'); %! assert(logical( ifourier(exp(-w^2/4)) == 1/(sqrt(Pi)*exp(x^2)) )) %! assert(logical( ifourier(sqrt(Pi)/exp(w^2/4)) == exp(-x^2) )) %!test %! % Dirac delta tests %! syms x w %! Pi=sym('pi'); %! assert(logical( ifourier(dirac(w-2)) == exp(2*1i*x)/(2*Pi) )) %! assert (logical( ifourier(sym(2), w, x) == 2*dirac(x) )) %!test %! % advanced test %! syms x w c d %! Pi=sym('pi'); %! f=(Pi*(dirac(x-c)+dirac(x+c))+2*Pi*1i*(-dirac(x+3*d)+dirac(x-3*d))+2/(x^2+1))/(2*Pi); %! assert(logical( simplify(ifourier(cos(c*w)+2*sin(3*d*w)+exp(-abs(w)))-f) == 0 )) %!xtest %! % Inverse Fourier transform cannot recover non-smooth functions %! % SymPy cannot evaluate correctly?? %! syms x w %! assert(logical( ifourier(2/(w^2 + 1)) == exp(-abs(x)) )) %! assert(logical( ifourier(2/(w^2 + 1)) == heaviside(x)/exp(x) + heaviside(-x)*exp(x) )) %! assert(logical( ifourier(-(w*4)/(w^4 + 2*w^2 + 1) )== -x*exp(-abs(x))*1i )) %! assert(logical( ifourier(-(w*4)/(w^4 + 2*w^2 + 1) )== -x*(heaviside(x)/exp(x) + heaviside(-x)*exp(x))*1i )) %!error ifourier (sym('k', 'positive')*sym('k')) %!test %! % SMT compact, prefers k over symvar %! syms k x y %! assert (isequal (ifourier(y*exp(-k^2/4)), y/sqrt(sym(pi))*exp(-x^2))) symbolic-3.1.1/inst/@sym/igamma.m0000644000000000000000000000407214405647405013535 0ustar %% Copyright (C) 2016, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym igamma (@var{nu}, @var{x}) %% Symbolic upper incomplete gamma function. %% %% Example: %% @example %% @group %% syms x nu %% igamma (nu, x) %% @result{} (sym) Γ(ν, x) %% @end group %% @end example %% %% @strong{Note} the order of inputs and scaling is different from %% @ref{@@sym/gammainc}, specifically: %% @example %% @group %% igamma (nu, x) %% @result{} (sym) Γ(ν, x) %% gammainc (x, nu, 'upper') %% @result{} (sym) %% Γ(ν, x) %% ─────── %% Γ(ν) %% @end group %% @end example %% %% @seealso{@@sym/gammainc, @@sym/gamma} %% @end defmethod function y = igamma(a, z) if (nargin ~= 2) print_usage (); end y = elementwise_op ('uppergamma', sym(a), sym(z)); end %!test %! % mostly tested in @sym/gammainc %! syms x %! assert (isequal (igamma (2, x), gammainc(x, 2, 'upper'))) %!test %! % unregularized %! B = double (igamma (sym(3), 1)); %! A = gammainc (1, 3, 'upper')*gamma (3); %! assert (A, B, -2*eps) %!test %! % something like a round trip: no igamma() %! syms x a %! f = igamma (a, x); %! h = function_handle (f, 'vars', [a x]); %! A = h (1.1, 2.2); %! B = double (igamma (sym(11)/10, sym(22)/10)); %! C = gammainc (2.2, 1.1, 'upper')*gamma(1.1); %! assert (A, B, -10*eps) %! assert (A, C, -10*eps) symbolic-3.1.1/inst/@sym/ilaplace.m0000644000000000000000000001312314405647405014051 0ustar %% Copyright (C) 2014-2016 Andrés Prieto %% Copyright (C) 2015-2016, 2018-2019, 2022-2023 Colin Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym ilaplace (@var{G}, @var{s}, @var{t}) %% @defmethodx @@sym ilaplace (@var{G}) %% @defmethodx @@sym ilaplace (@var{G}, @var{t}) %% Inverse Laplace transform. %% %% The inverse Laplace transform of a function @var{G} of @var{s} %% is a function @var{f} of @var{t} defined by the integral below. %% @example %% @group %% syms g(s) t %% f(t) = rewrite(ilaplace(g), 'Integral') %% @result{} f(t) = (symfun) %% c + ∞⋅ⅈ %% ⌠ %% ⎮ s⋅t %% -ⅈ⋅ ⎮ g(s)⋅ℯ ds %% ⌡ %% c - ∞⋅ⅈ %% ──────────────────────── %% 2⋅π %% @end group %% @end example %% (This expression is usually written simply as the integral divided by %% @code{2⋅π⋅ⅈ}.) %% %% Example: %% @example %% @group %% syms s t %% F = 1/s^2; %% @c doctest: +XFAIL_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.4")')) %% ilaplace(F, s, t) %% @result{} (sym) t⋅θ(t) %% @end group %% @end example %% %% To avoid @code{Heaviside}, try: %% @example %% @group %% syms t positive %% ilaplace(1/s^2, s, t) %% @result{} (sym) t %% @end group %% @end example %% %% By default the ouput is a function of @code{t} (or @code{x} if the %% inverse transform happens to be with respect to @code{t}). This can %% be overriden by specifying @var{t}. For example: %% @example %% @group %% syms s %% syms t x positive %% ilaplace(1/s^2) %% @result{} (sym) t %% ilaplace(1/t^2) %% @result{} (sym) x %% ilaplace(1/s^2, x) %% @result{} (sym) x %% @end group %% @end example %% %% The independent variable of the input can be specified by @var{s}; %% if omitted it defaults a symbol named @code{s}, or @pxref{@@sym/symvar} %% if no such symbol is found. %% %% @seealso{@@sym/laplace} %% @end defmethod function f = ilaplace(varargin) if (nargin > 3) print_usage (); end % FIXME: it only works for scalar functions F = sym(varargin{1}); if (nargin == 3) s = sym(varargin{2}); else %% frequency domain variable not specified % if exactly one symbol has char(s) == 's'... symbols = findsymbols (F); charsyms = cell (size (symbols)); for i=1:numel(symbols) charsyms{i} = char (symbols{i}); end I = find (strcmp (charsyms, 's')); assert (numel (I) <= 1, 'ilaplace: there is more than one "s" symbol: check symvar(F) and sympy(F)') if (~ isempty (I)) s = symbols{I}; % ... we want that one else s = symvar (F, 1); if (isempty (s)) s = sym('s'); end end end if (nargin == 1) t = sym('t', 'positive'); % TODO: potentially confusing? % If the Laplace variable in the frequency domain is equal to "t", % "x" will be the physical variable (analogously to SMT) if (strcmp (char (s), char (t))) t = sym('x', 'positive'); end elseif (nargin == 2) t = sym(varargin{2}); elseif (nargin == 3) t = sym(varargin{3}); end cmd = { 'F, s, t = _ins' 'f = inverse_laplace_transform(F, s, t)' 'return f,' }; f = pycall_sympy__ (cmd, F, s, t); end %!error ilaplace (sym(1), 2, 3, 4) %!test %! % basic SMT compact: no heaviside %! syms s %! syms t positive %! assert (isequal (ilaplace(1/s^2), t)) %! assert (isequal (ilaplace(s/(s^2+9)), cos(3*t))) %! assert (isequal (ilaplace(6/s^4), t^3)) %!test %! % more SMT compact %! syms r %! syms u positive %! assert (isequal (ilaplace(1/r^2, u), u)) %! assert (isequal (ilaplace(1/r^2, r, u), u)) %!test %! % if t specified and not positive, we expect heaviside %! clear s t %! syms s t %! assert (isequal (ilaplace(1/s^2, s, t), t*heaviside(t))) %! assert (isequal (ilaplace(s/(s^2+9), t), cos(3*t)*heaviside(t))) %! assert (isequal (ilaplace(6/s^4, t), t^3*heaviside(t))) %!test %! % Heaviside test %! syms s %! t=sym('t', 'positive'); %! assert(logical( ilaplace(exp(-5*s)/s^2,t) == (t-5)*heaviside(t-5) )) %!test %! % Delta dirac test %! syms s %! t = sym('t'); %! assert (isequal (ilaplace (sym('2'), t), 2*dirac(t))) %!test %! % Delta dirac test 2 %! syms s t %! calc = ilaplace (5*exp (-3*s) - 2*exp (-2*s)/s, s, t); %! want = 5*dirac (t-3) - 2*heaviside (t-2); %! assert (isequal (calc, want)) %!test %! % Delta dirac test 3, coefficient %! syms s t %! syms c positive %! calc = ilaplace (2*exp (-c*s), s, t); %! want = 2*dirac (t - c); %! assert (isAlways (calc == want)) %!error ilaplace (sym('s', 'positive')*sym('s')) %!test %! % SMT compact, prefers s over symvar %! syms s x %! syms t positive %! assert (isequal (ilaplace(x/s^4), x*t^3/6)) %! t = sym('t'); %! assert (isequal (ilaplace(x/s^4, t), x*t^3/6*heaviside(t))) %!test %! % pick s even it has assumptions %! syms s real %! syms x t %! assert (isequal (ilaplace (x/s^2, t), x*t*heaviside(t))) symbolic-3.1.1/inst/@sym/imag.m0000644000000000000000000000356414405647405013224 0ustar %% Copyright (C) 2014, 2016, 2018-2019 Colin B. Macdonald %% Copyright (C) 2016 Lagu %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym imag (@var{z}) %% Imaginary part of a symbolic expression. %% %% Examples: %% @example %% @group %% syms z %% imag(z) %% @result{} ans = (sym) im(z) %% @end group %% %% @group %% syms x real %% imag(x) %% @result{} ans = (sym) 0 %% imag(1i*x) %% @result{} ans = (sym) x %% @end group %% %% @group %% imag([x sym(pi) + 6i 7 3i]) %% @result{} ans = (sym) [0 6 0 3] (1×4 matrix) %% @end group %% @end example %% %% @seealso{@@sym/real, @@sym/conj, @@sym/ctranspose} %% @end defmethod function y = imag(z) if (nargin ~= 1) print_usage (); end y = elementwise_op ('im', z); end %!assert (isequal (imag (sym (4) + 3i),3)) %!test %! syms x y real %! z = x + 1i*y; %! assert (isequal (imag (z),y)) %!test %! syms x y real %! Z = [4 x + 1i*y; 1i*y 4 + 3i]; %! assert (isequal (imag (Z),[0 y; y 3])) %!test %! syms x real %! d = exp (x*i); %! assert (isequal (imag (d), sin (x))) %!test %! % round trip %! syms x %! d = 3 - 5i; %! f = imag (x); %! A = imag (d); %! h = function_handle (f); %! B = h (d); %! assert (A, B) symbolic-3.1.1/inst/@sym/int.m0000644000000000000000000001055514405647405013077 0ustar %% Copyright (C) 2014-2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym int (@var{f}) %% @defmethodx @@sym int (@var{f}, @var{x}) %% @defmethodx @@sym int (@var{f}, @var{x}, @var{a}, @var{b}) %% @defmethodx @@sym int (@var{f}, @var{x}, [@var{a}, @var{b}]) %% @defmethodx @@sym int (@var{f}, @var{a}, @var{b}) %% @defmethodx @@sym int (@var{f}, [@var{a}, @var{b}]) %% Symbolic integration. %% %% Definite integral: %% @example %% @group %% syms x %% f = x^2; %% F = int(f, x, 1, 2) %% @result{} F = (sym) 7/3 %% @end group %% @end example %% or alternatively %% @example %% @group %% F = int(f, x, [1 2]) %% @result{} F = (sym) 7/3 %% @end group %% @end example %% %% Indefinite integral: %% @example %% @group %% F = int(f, x) %% @result{} F = (sym) %% 3 %% x %% ── %% 3 %% F = int(f) %% @result{} F = (sym) %% 3 %% x %% ── %% 3 %% @end group %% @end example %% %% @seealso{@@sym/diff} %% @end defmethod function F = int(f, x, a, b) if (nargin == 4) % int(f, x, a, b) assert(numel(a)==1) assert(numel(b)==1) definite = true; elseif (nargin == 2) && (numel(x) == 1) % int(f, x) definite = false; elseif (nargin == 1) % int(f) definite = false; x = symvar(f,1); if isempty(x) x = sym('x'); end elseif (nargin == 2) && (numel(x) == 2) % int(f, [a b]) idx.type = '()'; idx.subs = {2}; definite = true; b = subsref(x, idx); idx.subs = {1}; a = subsref(x, idx); x = symvar(f,1); if isempty(x) x = sym('x'); end elseif (nargin == 3) && (numel(a) == 2) % int(f, x, [a b]) definite = true; idx.type = '()'; idx.subs = {2}; b = subsref(a, idx); idx.subs = {1}; a = subsref(a, idx); elseif (nargin == 3) && (numel(a) == 1) % int(f, a, b) definite = true; b = a; a = x; x = symvar(f,1); if isempty(x) x = sym('x'); end else print_usage (); end %% now do the definite or indefinite integral if (definite) cmd = { '(f, x, a, b) = _ins' 'F = sp.integrate(f, (x, a, b))' 'return F,' }; F = pycall_sympy__ (cmd, sym(f), sym(x), sym(a), sym(b)); else cmd = { '(f,x) = _ins' 'd = sp.integrate(f, x)' 'return d,' }; F = pycall_sympy__ (cmd, sym(f), sym(x)); end end %!shared x,y,a %! syms x y a %!assert(logical(int(cos(x)) - sin(x) == 0)) %!assert(logical(int(cos(x),x) - sin(x) == 0)) %!assert(logical(int(cos(x),x,0,1) - sin(sym(1)) == 0)) %!test %! %% limits might be syms %! assert( isequal (int(cos(x),x,sym(0),sym(1)), sin(sym(1)))) %! assert( isequal (int(cos(x),x,0,a), sin(a))) %!test %! %% other variables present %! assert( isequal (int(y*cos(x),x), y*sin(x))) %!test %! %% limits as array %! assert( isequal (int(cos(x),x,[0 1]), sin(sym(1)))) %! assert( isequal (int(cos(x),x,sym([0 1])), sin(sym(1)))) %! assert( isequal (int(cos(x),x,[0 a]), sin(a))) %!test %! %% no x given %! assert( isequal (int(cos(x),[0 1]), sin(sym(1)))) %! assert( isequal (int(cos(x),sym([0 1])), sin(sym(1)))) %! assert( isequal (int(cos(x),[0 a]), sin(a))) %! assert( isequal (int(cos(x),0,a), sin(a))) %!test %! %% integration of const %! assert( isequal (int(sym(2),y), 2*y)) %! assert( isequal (int(sym(2)), 2*x)) %! assert( isequal (int(sym(2),[0 a]), 2*a)) %! assert( isequal (int(sym(2),0,a), 2*a)) %!test %! % componentwise int of array %! A = [x x*x]; %! assert (isequal (int(A, x), [x^2/2 x^3/3])) %!test %! % NonElementaryIntegral bug %! % https://savannah.gnu.org/bugs/index.php?46831 %! f = int(exp(exp(x))); %! f = f + 2; %! g = diff(f); %! assert (isequal (g, exp(exp(x)))) symbolic-3.1.1/inst/@sym/intersect.m0000644000000000000000000000527714405647405014312 0ustar %% Copyright (C) 2016, 2019 Colin B. Macdonald %% Copyright (C) 2016 Lagu %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym intersect (@var{A}, @var{B}) %% Return the common elements of two sets. %% %% Example: %% @example %% @group %% A = finiteset(sym(1), 2, 3); %% B = finiteset(sym(pi), 2); %% intersect(A, B) %% @result{} ans = (sym) @{2@} %% @end group %% @end example %% %% The sets can also be intervals or a mixture of finite sets %% and intervals: %% @example %% @group %% C = interval(sym(2), 10); %% intersect(A, C) %% @result{} ans = (sym) @{2, 3@} %% %% D = interval(0, sym(pi)); %% intersect(C, D) %% @result{} ans = (sym) [2, π] %% @end group %% @end example %% %% @seealso{@@sym/union, @@sym/setdiff, @@sym/setxor, @@sym/unique, %% @@sym/ismember, @@sym/finiteset, @@sym/interval} %% @end defmethod function r = intersect(a, b) if (nargin ~= 2) print_usage (); end cmd = { 'a, b = _ins' 'if isinstance(a, sp.Set) or isinstance(b, sp.Set):' ' return a & b,' '' 'A = sp.FiniteSet(*(list(a) if isinstance(a, sp.MatrixBase) else [a]))' 'B = sp.FiniteSet(*(list(b) if isinstance(b, sp.MatrixBase) else [b]))' 'C = A & B' 'return sp.Matrix([list(C)]),' }; r = pycall_sympy__ (cmd, sym(a), sym(b)); end %!test %! A = sym([1 2 3]); %! B = sym([1 2 4]); %! C = intersect(A, B); %! D = sym([1 2]); %! assert (isequal (C, D)) %!test %! % one nonsym %! A = sym([1 2 3]); %! B = [1 2 4]; %! C = intersect(A, B); %! D = sym([1 2]); %! assert (isequal (C, D)) %!test %! % empty %! A = sym([1 2 3]); %! C = intersect(A, A); %! assert (isequal (C, A)) %!test %! % empty input %! A = sym([1 2]); %! C = intersect(A, []); %! assert (isequal (C, sym([]))) %!test %! % scalar %! syms x %! assert (isequal (intersect([x 1], x), x)) %! assert (isequal (intersect(x, x), x)) %!test %! A = interval(sym(1), 3); %! B = interval(sym(2), 5); %! C = intersect(A, B); %! assert( isequal( C, interval(sym(2), 3))) symbolic-3.1.1/inst/@sym/interval.m0000644000000000000000000000400214405647405014117 0ustar %% Copyright (C) 2016-2017, 2019 Colin B. Macdonald %% Copyright (C) 2016 Lagu %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym interval (@var{A}, @var{B}) %% @defmethodx @@sym interval (@var{A}, @var{B}, @var{lopen}) %% @defmethodx @@sym interval (@var{A}, @var{B}, @var{lopen}, @var{ropen}) %% Return an interval. %% %% Examples: %% @example %% @group %% interval(sym(0), sym(1)) %% @result{} (sym) [0, 1] %% interval(sym(0), 1, true, true) %% @result{} (sym) (0, 1) %% interval(sym(0), 1, false, true) %% @result{} (sym) [0, 1) %% @end group %% @end example %% %% Intervals can be degenerate: %% @example %% @group %% interval(sym(1), 1) %% @result{} (sym) @{1@} %% interval(sym(2), 1) %% @result{} (sym) ∅ %% @end group %% @end example %% %% @seealso{finiteset, @@sym/union, @@sym/intersect, @@sym/setdiff, @@sym/unique, @@sym/ismember} %% @end defmethod function I = interval(varargin) if (nargin < 2 || nargin > 4) print_usage(); end for i = 1:nargin varargin{i} = sym(varargin{i}); end I = pycall_sympy__ ('return Interval(*_ins),', varargin{:}); end %!test %! a = interval(sym(1), 2); %! assert (isa (a, 'sym')) %!test %! % some set subtraction %! a = interval(sym(0), 4); %! b = interval(sym(0), 1); %! c = interval(sym(1), 4, true); %! q = a - b; %! assert (isequal( q, c)) symbolic-3.1.1/inst/@sym/inv.m0000644000000000000000000000367414405647405013105 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym inv (@var{A}) %% Symbolic inverse of a matrix. %% %% Examples: %% @example %% @group %% A = sym([1 2; 3 4]); %% inv(A) %% @result{} ans = (sym 2×2 matrix) %% ⎡-2 1 ⎤ %% ⎢ ⎥ %% ⎣3/2 -1/2⎦ %% @end group %% @end example %% %% If the matrix is singular, an error is raised: %% @example %% @group %% A = sym([1 2; 1 2]); %% inv(A) %% @print{} ??? ... Matrix det == 0; not invertible... %% @end group %% @end example %% %% @seealso{@@sym/ldivide, @@sym/rdivide} %% @end defmethod function z = inv(x) cmd = { 'x, = _ins' 'if x.is_Matrix:' ' return x.inv(),' 'else:' ' return S.One/x,' }; z = pycall_sympy__ (cmd, x); end %!test %! % scalar %! syms x %! assert (isequal (inv(x), 1/x)) %!test %! % diagonal %! syms x %! A = [sym(1) 0; 0 x]; %! B = [sym(1) 0; 0 1/x]; %! assert (isequal (inv(A), B)) %!test %! % 2x2 inverse %! A = [1 2; 3 4]; %! assert (max (max (abs (double (inv (sym (A))) - inv(A)))) <= 3*eps) %!error %! syms a; %! A = [a a; a a]; %! inv(A) %!error %! syms a; %! A = [a a]; %! inv(A) symbolic-3.1.1/inst/@sym/invhilb.m0000644000000000000000000000244514405647405013737 0ustar %% Copyright (C) 2016 Lagu %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym invhilb (@var{n}) %% Return the symbolic inverse of the Hilbert matrix. %% %% Example: %% @example %% @group %% invhilb (sym(2)) %% @result{} ans = (sym 2×2 matrix) %% ⎡4 -6⎤ %% ⎢ ⎥ %% ⎣-6 12⎦ %% @end group %% @end example %% %% @seealso{@@sym/hilb} %% @end defmethod function y = invhilb(x) if (nargin ~= 1) print_usage (); end y = inv(hilb(x)); end %!test %! A = invhilb(sym(3)); %! B = sym([9 -36 30;-36 192 -180;30 -180 180]); %! assert( isequal( A, B)) symbolic-3.1.1/inst/@sym/ipermute.m0000644000000000000000000000275614405647405014143 0ustar %% Copyright (C) 2015, 2016, 2018, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym ipermute (@var{B}, @var{iperm}) %% Invert a permutation the indices of a symbolic array. %% %% Example: %% @example %% @group %% A = sym([1 2 pi; 4 5 6]); %% B = permute(A, [2 1]); %% ipermute(B, [2 1]) %% @result{} ans = (sym 2×3 matrix) %% ⎡1 2 π⎤ %% ⎢ ⎥ %% ⎣4 5 6⎦ %% @end group %% @end example %% %% @seealso{@@sym/permute} %% @end defmethod function A = ipermute(B, iperm) if (nargin < 2) print_usage (); end A = permute(B, iperm); end %!error permute (sym(1)) %!error permute (sym(1), 2, 3) %!test %! syms x %! A = [1 x]; %! perm = [2 1]; %! B = permute(A, perm); %! C = ipermute(B, perm); %! assert (isequal(C, A)) symbolic-3.1.1/inst/@sym/isAlways.m0000644000000000000000000002122214405647405014072 0ustar %% Copyright (C) 2014-2016, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym isAlways (@var{eq}) %% @defmethodx @@sym isAlways (@var{eq}, 'Unknown', 'false') %% @defmethodx @@sym isAlways (@var{eq}, 'Unknown', 'true') %% @defmethodx @@sym isAlways (@var{eq}, 'Unknown', 'error') %% Test if expression is mathematically true. %% %% Example: %% @example %% @group %% syms x y %% isAlways(x*(1+y) == x+x*y) %% @result{} 1 %% @end group %% @end example %% Contrast this with a test for “structural equality“: %% @example %% @group %% logical(x*(1+y) == x+x*y) %% @result{} 0 %% @end group %% @end example %% %% The optional keyword argument @qcode{'Unknown'} specifies that happens %% for expressions that cannot simplify. By default these return %% false (that is, cannot verify it is always true). Pass the %% strings @qcode{'true'}, @qcode{'false'} or @qcode{'error'} to change the behaviour. You %% can also pass logical true/false. %% %% If @code{isAlways} is called on expressions without relationals, %% it will return true for non-zero numbers: %% @example %% @group %% isAlways (sym (10)) %% @result{} 1 %% @end group %% @end example %% %% It is safe to use @code{isAlways} even when the expression does not %% require simplifying: %% @example %% syms x %% isAlways (sin(x) - sin(x) == 0) %% @result{} 1 %% @end example %% In practice, @code{isAlways} might get called on a simple %% boolean variable, so this package implements @code{@@logical/isAlways} %% (which is essentially a no-op). %% %% @seealso{@@sym/logical, @@sym/isequal, @@sym/eq, @@logical/isAlways} %% @end defmethod function r = isAlways(p, varargin) if (~ ((nargin == 1) || (nargin == 3))) print_usage (); end if (nargin == 3) assert(strcmpi(varargin{1}, 'unknown')) cant = varargin{2}; if islogical(cant) % SMT doesn't allow nonstring but it seems reasonable elseif strcmpi(cant, 'true') cant = true; elseif strcmpi(cant, 'false') cant = false; elseif strcmpi(cant, 'error') % no-op else error('isAlways: invalid argument for "unknown" keyword') end else cant = false; end cmd = { 'def simplify_tfn(p):' ' if p in (S.true, S.false):' ' return bool(p)' ' r = simplify(p)' ' #FIXME; Boolean, simplify more than once?' ' if r in (S.true, S.false):' ' return bool(r)' ' # FIXME: hopefully we get sympy patched for some of this' ' #ver = sympy.__version__' ' #if ver == "0.7.5" or ver.startswith("0.7.6") or ver.startswith("0.7.7"):' ' if True:' ' if isinstance(p, Equality):' ' r = Eq(sp.simplify(p.lhs - p.rhs), 0)' ' r = simplify(r)' ' if r in (S.true, S.false):' ' return bool(r)' ' if isinstance(p, Unequality):' ' r = Eq(sp.simplify(p.lhs - p.rhs), 0)' ' r = simplify(r)' ' if r in (S.true, S.false):' ' return not bool(r)' ' if isinstance(p, (Lt, Gt, Le, Ge)):' ' r = p._eval_relation(sp.simplify(p.lhs - p.rhs), sp.S(0))' ' r = simplify(r)' ' if r in (S.true, S.false):' ' return bool(r)' ' # for SMT compat' ' if p.is_number:' ' r = p.is_zero' % FIXME: return bool(r)? ' if r in (S.true, S.false):' ' return not bool(r)' ' return None' }; % could distinguish b/w None and return a string for this last case cmd = vertcat(cmd, { '(x, unknown) = _ins' 'if x is not None and x.is_Matrix:' ' r = [a for a in x.T]' % note transpose 'else:' ' r = [x,]' 'r = [simplify_tfn(a) for a in r]' 'r = [unknown if a is None else a for a in r]' 'flag = True' 'if r.count("error") > 0:' ' flag = False' ' r = "cannot reliably convert sym to bool"' 'return (flag, r)' }); [flag, r] = pycall_sympy__ (cmd, p, cant); if (~flag) assert (ischar (r), 'isAlways: programming error?') error(['isAlways: ' r]) end r = cell2mat(r); r = reshape(r, size(p)); end %!test %! % basics %! assert(isAlways(true)) %! assert(isAlways(1==1)) %! assert(isAlways(sym(1)==sym(1))) %! assert(isAlways(sym(1)==1)) %!test %! % numbers to logic? %! assert (isAlways(sym(1))) %! assert (isAlways(sym(-1))) %! assert (~isAlways(sym(0))) %!shared x %! syms x %!test %! % in this case it is boolean %! expr = x - x == 0; %! assert (logical(expr)) %! assert (isAlways(expr)) %! % and both are logical type %! assert (islogical(logical(expr))) %! assert (islogical(isAlways(expr))) %!test %! % structurally same and mathematically true %! % (here expr should be sym, non-boolean) %! expr = x == x; %! assert (logical(expr)) %! assert (isAlways(expr)) %! %assert (~islogical(expr)) % FIXME: Issue #56 %! %assert (isa(expr, 'sym)) %!test %! % structurally same and mathematically true %! % (here expr should be sym, non-boolean) %! expr = 1 + x == x + 1; %! assert (logical(expr)) %! assert (isAlways(expr)) %!test %! % non-zero numbers are true %! assert (isAlways(sym(1))) %! assert (isAlways(sym(-10))) %! assert (~isAlways(sym(0))) % FIXME: should we support implicit == 0 like sympy? SMT does oppositve, plus it ignores assumptions? SMT behaviour is probably meant to mimic matlab doubles, %expr = x - x; %c=c+1; r(c) = logical(expr); %c=c+1; r(c) = isAlways(expr); %!shared x, y %! syms x y %!test %! % structurally same and mathematically true %! % (here expr should be sym, non-boolean) %! expr = x*(1+y) == x*(y+1); %! assert (logical(expr)) %! assert (isAlways(expr)) %! assert (islogical(isAlways(expr))) %!test %! % Now for some differences %! % simplest example from SymPy FAQ %! expr = x*(1+y) == x+x*y; %! assert (~logical(expr)) %! assert (isAlways(expr)) %!test %! % more differences 1, these don't simplify in sympy (as of 2016-01) %! expr = (x+1)^2 == x*x + 2*x + 1; %! assert (~logical(expr)) %! assert (isAlways(expr)) %!test %! % more differences 2 %! expr = sin(2*x) == 2*sin(x)*cos(x); %! assert (~logical(expr)) %! assert (isAlways(expr)) %!test %! % more differences 3, false %! expr = x*(x+y) == x^2 + x*y + 1; %! assert (~logical(expr)) %! assert (~isAlways(expr)) %! assert (~isAlways(expr, 'unknown', 'error')) %!test %! % logically not equal, math equal %! exprn = x*(x+y) ~= x^2 + x*y; %! assert (logical(exprn)) %! assert (~isAlways(exprn)) %!test %! % logically not equal, math not equal %! exprn = x*(x+y) ~= x^2 + x*y + 1; %! assert (logical(exprn)) %! assert (isAlways(exprn)) %!test %! % equal and not equal %! e1 = sin(x)^2 + cos(x)^2 == 1; %! e2 = sin(x)^2 + cos(x)^2 == 2; %! assert (~logical(e1)) %! assert (isAlways(e1)) %! assert (~logical(e2)) %! assert (~isAlways(e2)) %! assert (~isAlways(e2, 'unknown', 'error')) %!error isAlways(x, 'unknown', 'kevin') %!error isAlways(x, 'unknown') %!error isAlways(x, 'kevin', 'true') %!error %! a = [x*(x+y)==x^2+x*y x==y]; %! b = isAlways(a, 'unknown', 'error'); %!error %! a = x==y; %! b = isAlways(a, 'unknown', 'error'); %!test %! % array, unknown keyword %! a = [x==x x==x+1 x==y x*(x+y)==x^2+x*y cos(x)^2+sin(x)^2==2]; %! b = isAlways(a, 'unknown', false); %! c = isAlways(a, 'unknown', 'false'); %! expect = [true false false true false]; %! assert (islogical(b)) %! assert (isequal (b, expect)) %! assert (isequal (c, expect)) %! b = isAlways(a, 'unknown', true); %! c = isAlways(a, 'unknown', 'true'); %! expect = [true false true true false]; %! assert (islogical(b)) %! assert (isequal (b, expect)) %! assert (isequal (c, expect)) %!test %! % ineq %! e = x*(x+y) <= x^2 + x*y + 1; %! assert (~logical(e)) %! assert (isAlways(e)) %! e = x*(x+y) <= x^2 + x*y; %! assert (~logical(e)) %! assert (isAlways(e)) %test % % FIXME; booleans % e1 = x*(x+1) == x*x+x % e2 = x*(x+1)+2 == x*x+x+2 % b = e1 & e2 % assert isAlways(b) symbolic-3.1.1/inst/@sym/isNone.m0000644000000000000000000000472214405647405013537 0ustar %% Copyright (C) 2016, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym isNone (@var{x}) %% Return true if symbolic expression is Python object None. %% %% Python has a @code{None} object. %% %% Example: %% @example %% @group %% @c FIXME: pycall_sympy__ is implementation detail, maybe better %% @c to avoid it in our docs. %% a = pycall_sympy__ ('return None') %% @result{} a = (sym) None %% isNone(a) %% @result{} ans = 1 %% @end group %% @end example %% %% @seealso{@@sym/isnan, @@sym/isinf} %% @end defmethod function tf = isNone(x) if (nargin ~= 1) print_usage (); end tf = uniop_bool_helper(x, 'lambda a: a is None'); end %!test %! None = pycall_sympy__ ('return None'); %!shared None %! None = pycall_sympy__ ('return None'); %!assert (isNone(None)) %!assert (~isNone(sym('x'))) %!assert (islogical(isNone(None))) %!test %! a = [1 None]; %! a = [None None]; %! a = [None; 1]; %! a = [None; None]; %! a = [None 2; 3 None]; %!test %! a = sym([1 2]); %! a(1,2) = None; %! assert (isequal (a, [sym(1) None])); %!assert (isequal (None(1), None)); %!error None(None); %!error x=sym('x'); x(None); %!error x=1; x(None); %!error None(None); %!error 1 + None; %!error None - 1; %!error 6*None; %!error 2^None; %!error [1 2].*None; %!error isconstant(None); %!error nnz(None); % FIXME: possibly later we will want e.g., None -> false %!error logical(None); %!error isAlways(None); %!error logical([sym(true) None]); %!error isAlways([sym(true) None]); %!assert (isequal (children(None), None)) %!assert (isequal (repmat(None, 1, 2), [None None])) %!assert (isequal (fliplr(None), None)) %!assert (isequal (flipud(None), None)) symbolic-3.1.1/inst/@sym/isallconstant.m0000644000000000000000000000321014405647405015151 0ustar %% Copyright (C) 2014-2016 Colin B. Macdonald %% %% This file is part of OctSymPy %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym isallconstant (@var{x}) %% Whether all elements of a symbolic array are constant. %% %% Example: %% @example %% @group %% A = [1 2 sym(pi); sym(4) 5 6] %% @result{} A = (sym 2×3 matrix) %% ⎡1 2 π⎤ %% ⎢ ⎥ %% ⎣4 5 6⎦ %% %% isallconstant (A) %% @result{} ans = 1 %% @end group %% %% @group %% A(1) = sym('x') %% @result{} A = (sym 2×3 matrix) %% ⎡x 2 π⎤ %% ⎢ ⎥ %% ⎣4 5 6⎦ %% %% isallconstant (A) %% @result{} ans = 0 %% @end group %% @end example %% %% @seealso{@@sym/isconstant, @@sym/symvar, findsymbols} %% @end defmethod function z = isallconstant(x) z = isempty (findsymbols (x)); end %!assert (isallconstant([sym(1) 2 3])) %!test %! syms x %! assert (~isallconstant([sym(1) x 3])) %!test %! syms x %! assert (~isallconstant([sym(1) x; sym(2) 3])) symbolic-3.1.1/inst/@sym/iscolumn.m0000644000000000000000000000276514405647405014142 0ustar %% Copyright (C) 2014-2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym iscolumn (@var{x}) %% Return true if symbolic expression is a column vector. %% %% Example: %% @example %% @group %% v = sym([1; 2; 3]); %% iscolumn(v) %% @result{} 1 %% iscolumn(sym(1)) %% @result{} 1 %% iscolumn(v') %% @result{} 0 %% @end group %% @end example %% %% @seealso{@@sym/isrow, @@sym/isvector, @@sym/isscalar} %% @end defmethod function r = iscolumn(x) if (nargin ~= 1) print_usage (); end % from Rik Wehbring's Octave function: sz = size (x); r = (ndims (x) == 2 && (sz(2) == 1)); end %!assert (iscolumn (sym ([1]))) %!assert (iscolumn (sym ([1 2 3]'))) %!assert (~iscolumn (sym ([]))) %!assert (~iscolumn (sym ([1 2 3]))) %!assert (~iscolumn (sym ([1 2; 3 4]))) symbolic-3.1.1/inst/@sym/isconstant.m0000644000000000000000000000363214405647405014470 0ustar %% Copyright (C) 2014-2016, 2019, 2022 Colin B. Macdonald %% Copyright (C) 2022 Chris Gorman %% %% This file is part of OctSymPy %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym isconstant (@var{x}) %% Indicate which elements of symbolic array are constant. %% %% Example: %% @example %% @group %% syms x y %% A = [x 1 pi; 2 2*y catalan()] %% @c doctest: +XFAIL_UNLESS(pycall_sympy__ ('return Version(spver) >= Version("1.10")')) %% @result{} A = (sym 2×3 matrix) %% ⎡x 1 π⎤ %% ⎢ ⎥ %% ⎣2 2⋅y G⎦ %% %% isconstant (A) %% @result{} ans = %% 0 1 1 %% 1 0 1 %% @end group %% @end example %% %% @seealso{@@sym/isallconstant, @@sym/symvar, findsymbols} %% @end defmethod function z = isconstant(x) cmd = { '(x,) = _ins' 'if x is not None and x.is_Matrix:' ' return x.applyfunc(lambda a: a.is_constant()),' 'return x.is_constant(),' }; z = pycall_sympy__ (cmd, sym(x)); % Issue #27: Matrix of bools not converted to logical z = logical(z); end %!test %! syms x %! A = [x 2 3]; %! B = [false true true]; %! assert (isequal (isconstant (A), B)) %!test %! syms x %! A = [x 2; 3 x]; %! B = [false true; true false]; %! assert (isequal (isconstant (A), B)) symbolic-3.1.1/inst/@sym/isempty.m0000644000000000000000000000427614405647405014002 0ustar %% Copyright (C) 2014-2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym isempty (@var{x}) %% Return true a symbolic array is empty (one dimension is zero). %% %% Examples: %% @example %% @group %% isempty(sym([])) %% @result{} 1 %% isempty(sym(pi)) %% @result{} 0 %% isempty(sym(zeros(4, 0))) %% @result{} 1 %% @end group %% @end example %% %% @seealso{@@sym/size, @@sym/numel} %% @end defmethod function r = isempty(x) if (nargin ~= 1) print_usage (); end d = size(x); % Octave can have n x 0 and 0 x m empty arrays % logical in case one has symbolic size % r = logical(prod(d) == 0); % safer, in case we use NaN later r = any(logical(d == 0)); end %% Tests %!shared se, a %! se = sym ([]); %! a = sym ([1 2]); %!assert (~isempty (sym (1))) %!assert (isempty (sym (se))) %!assert (isempty (se == [])) %!test % assert (isempty (a([]))) % assert (isempty (a([se]))) %% Growing an empty symfun into a scalar %!test se(1) = 10; %!test assert ( isa (se, 'sym')) %!test assert ( isequal (se, 10)) %!shared %!test %! % empty matrices %! A = sym('A', [3 0]); %! assert (isempty (A)) %! A = sym(ones(3,0)); %! assert (isempty (A)) %!test %! % non-empty symbolic-size matrices %! syms n integer %! A = sym('A', [3 n]); %! assert (~isempty (A)) %!xtest %! % empty symbolic-size matrices %! % FIXME: will fail until size stop lying by saying 1x1 %! syms n integer %! A = sym('A', [0 n]); %! assert (isempty (A)) %! A = sym('A', [n 0]); %! assert (isempty (A)) symbolic-3.1.1/inst/@sym/isequal.m0000644000000000000000000000455014405647405013746 0ustar %% Copyright (C) 2014-2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym isequal (@var{f}, @var{g}) %% @defmethodx @@sym isequal (@var{f}, @var{g}, @dots{}) %% Test if contents of two or more arrays are equal. %% %% Example: %% @example %% @group %% syms x %% isequal([1 x], [1 x]) %% @result{} 1 %% @end group %% @end example %% %% Note NaN's compare as false: %% @example %% @group %% snan = sym(nan); %% isequal([1 snan], [1 snan]) %% @result{} 0 %% @end group %% @end example %% To avoid this behaviour, @pxref{isequaln}. %% %% Note the type of the arrays is not considered, just their shape %% and values. %% %% @seealso{@@sym/isequaln, @@sym/logical, @@sym/isAlways, @@sym/eq} %% @end defmethod function t = isequal(x, y, varargin) if (nargin < 2) print_usage (); end % isequal does not care about type, but if you wanted it to... %if ( ~ ( isa (x, 'sym') && isa (y, 'sym'))) % t = false; % return %end if (any (any (isnan (x)))) % at least on sympy 0.7.4, 0.7.5, nan == nan is true so we % detect is ourselves t = false; else t = isequaln(x, y, varargin{:}); end end %!test %! a = sym([1 2]); %! b = a; %! assert (isequal (a, b)) %! b(1) = 42; %! assert (~isequal (a, b)) %!test %! a = sym([1 2; 3 4]); %! b = a; %! assert (isequal (a, b)) %! b(1) = 42; %! assert (~isequal (a, b)) %!test %! a = sym([nan; 2]); %! b = a; %! assert (~isequal (a, b)) %!test %! % proper nan treatment %! a = sym([nan 2; 3 4]); %! b = a; %! assert (~isequal (a, b)) %!test %! % more than two arrays %! a = sym([1 2 3]); %! b = a; %! c = a; %! assert (isequal (a, b, c)) %! c(1) = 42; %! assert (~isequal (a, b, c)) symbolic-3.1.1/inst/@sym/isequaln.m0000644000000000000000000000474514405647405014132 0ustar %% Copyright (C) 2014-2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym isequaln (@var{f}, @var{g}) %% @defmethodx @@sym isequaln (@var{f}, @var{g}, @dots{}) %% Test if contents of arrays are equal, even with nan. %% %% Here NaN's are considered equal: %% @example %% @group %% syms x %% snan = sym(nan); %% isequaln([1 snan x], [1 snan x]) %% @result{} 1 %% @end group %% @end example %% To get the usual NaN convention, @pxref{isequal}. %% %% @seealso{@@sym/isequal, @@sym/logical, @@sym/isAlways, @@sym/eq} %% @end defmethod function t = isequaln(x, y, varargin) if (nargin < 2) print_usage (); end % isequal does not care about type, but if you wanted it to... %if ( ~ ( isa (x, 'sym') && isa (y, 'sym'))) % t = false; % return %end %% some special cases if ~(is_same_shape(x, y)) t = false; return end % In symy, nan == nan is true by structural (not mathematical) % equivalence, so we don't need to detect it ourselves. % Sympy's == returns a scalar for arrays, no special case. cmd = 'return (_ins[0] == _ins[1],)'; t = pycall_sympy__ (cmd, sym(x), sym(y)); if (~ islogical(t)) error('nonboolean return from python'); end if (nargin >= 3) t = t && isequaln(x, varargin{:}); end end %!test %! a = sym([1 2]); %! b = a; %! assert (isequaln (a, b)) %! b(1) = 42; %! assert (~isequaln (a, b)) %!test %! a = sym([1 2; 3 4]); %! b = a; %! assert (isequaln (a, b)) %! b(1) = 42; %! assert (~isequaln (a, b)) %!test %! a = sym([nan; 2]); %! b = a; %! assert (isequaln (a, b)) %!test %! a = sym([nan 2; 3 4]); %! b = a; %! assert (isequaln (a, b)) %!test %! % more than two arrays %! a = sym([nan 2 3]); %! b = a; %! c = a; %! assert (isequaln (a, b, c)) %! c(1) = 42; %! assert (~isequaln (a, b, c)) symbolic-3.1.1/inst/@sym/isfinite.m0000644000000000000000000000453214405647405014115 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym isfinite (@var{x}) %% Is symbolic expression finite. %% %% A number is finite if it is neither infinite (@pxref{@@sym/isinf}) %% nor NaN (@pxref{@@sym/isnan}), for example: %% @example %% @group %% isfinite (sym(42)) %% @result{} ans = 1 %% isfinite (sym(inf)) %% @result{} ans = 0 %% isfinite (sym(nan)) %% @result{} ans = 0 %% @end group %% @end example %% %% However for symbolic @emph{expressions}, the situation is more %% complicated, for example we cannot be sure @code{x} is finite: %% @example %% @group %% syms x %% isfinite (x) %% @result{} ans = 0 %% @end group %% @end example %% Of course, we also cannot be sure @code{x} is infinite: %% @example %% @group %% isinf (x) %% @result{} ans = 0 %% @end group %% @end example %% %% Assumptions play a role: %% @example %% @group %% syms x finite %% isfinite (x) %% @result{} ans = 1 %% @end group %% %% @group %% isfinite (1/x) % x could be zero %% @result{} ans = 0 %% %% syms y positive finite %% isfinite (1/y) %% @result{} ans = 1 %% @end group %% @end example %% %% @seealso{@@sym/isinf, @@sym/isnan} %% @end defmethod function r = isfinite(x) if (nargin ~= 1) print_usage (); end r = uniop_bool_helper(x, 'lambda a: a.is_finite'); end %!assert (isfinite(sym(1))) %!assert (isfinite(sym(-10))) %!assert (~isfinite(sym('oo'))) %!assert (~isfinite(sym('-oo'))) %!assert (~isfinite(sym(1)/0)) %!assert (~isfinite(sym(nan))) %!assert (isequal (isfinite (sym ([1 inf])), [true false])) %!test %! % finite-by-assumption %! syms x finite %! assert (isfinite (x)) symbolic-3.1.1/inst/@sym/isinf.m0000644000000000000000000000740514405647405013415 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym isinf (@var{x}) %% Return true if a symbolic expression is infinite. %% %% Example: %% @example %% @group %% syms x finite %% A = [sym(inf) sym(1)/0 1; x 1 sym(inf)] %% @result{} A = (sym 2×3 matrix) %% ⎡∞ zoo 1⎤ %% ⎢ ⎥ %% ⎣x 1 ∞⎦ %% isinf(A) %% @result{} ans = %% 1 1 0 %% 0 0 1 %% @end group %% @end example %% %% Note that the return is of type logical and thus either true or false. %% However, the underlying SymPy software supports @code{True/False/None} %% answers, where @code{None} indicates an unknown or indeterminate result. %% Consider the example: %% @example %% @group %% syms x %% isinf(x) %% @result{} ans = 0 %% @end group %% @end example %% Here SymPy would have said @code{None} as it does not know whether %% x is finite or not. However, currently @code{isinf} returns %% false, which perhaps should be interpreted as ``x cannot be shown to %% be infinite'' (as opposed to ``x is not infinite''). %% %% FIXME: this is behaviour might change in a future version; come %% discuss at @url{https://github.com/cbm755/octsympy/issues/308}. %% %% @seealso{@@sym/isnan, @@sym/double} %% @end defmethod function r = isinf(x) if (nargin ~= 1) print_usage (); end r = uniop_bool_helper(x, 'lambda a: a.is_infinite'); end %!shared x,zoo,oo,snan %! oo = sym(inf); %! zoo = sym('zoo'); %! x = sym('x'); %! snan = sym(nan); %!test %! % various ops that give inf and nan %! assert (isinf(oo)) %! assert (isinf(zoo)) %! assert (isinf(oo+oo)) %! assert (~isinf(oo+zoo)) %! assert (~isinf(0*oo)) %! assert (~isinf(0*zoo)) %! assert (~isinf(snan)) %! assert (~isinf(oo-oo)) %! assert (~isinf(oo-zoo)) %!test %! % arrays %! assert (isequal( isinf([oo zoo]), [1 1] )) %! assert (isequal( isinf([oo 1]), [1 0] )) %! assert (isequal( isinf([10 zoo]), [0 1] )) %! assert (isequal( isinf([x oo x]), [0 1 0] )) %!test %! % Must not contain string 'symbol'; these all should make an %! % actual infinity. Actually a ctor test, not isinf. %! % IIRC, SMT in Matlab 2013b fails. %! oo = sym(inf); %! assert (isempty (strfind (sympy (oo), 'Symbol'))) %! oo = sym(-inf); %! assert (isempty (strfind (sympy (oo), 'Symbol'))) %! oo = sym('inf'); %! assert (isempty (strfind (sympy (oo), 'Symbol'))) %! oo = sym('-inf'); %! assert (isempty (strfind (sympy (oo), 'Symbol'))) %! oo = sym('Inf'); %! assert (isempty (strfind (sympy (oo), 'Symbol'))) %!test %! % ops with infinity shouldn't collapse %! syms x oo zoo %! y = x + oo; %! assert (~isempty (strfind (lower (sympy (y)), 'add') )) %! y = x - oo; %! assert (~isempty (strfind (lower (sympy (y)), 'add') )) %! y = x - zoo; %! assert (~isempty (strfind (lower (sympy (y)), 'add') )) %! y = x*oo; %! assert (~isempty (strfind (lower (sympy (y)), 'mul') )) %!test %! % ops with infinity are not necessarily infinite %! syms x oo zoo %! y = x + oo; %! assert(~isinf(y)) % SMT 2014a says "true", I disagree %! y = x - zoo; %! assert(~isinf(y)) %! y = x*oo; %! assert(~isinf(y)) symbolic-3.1.1/inst/@sym/ismatrix.m0000644000000000000000000000325214405647405014141 0ustar %% Copyright (C) 2015, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym ismatrix (@var{x}) %% Return true if this symbolic expression is a matrix. %% %% This returns true for all 2D arrays including matrices, scalars, %% vectors and empty matrices. This function is provided mostly for %% compatibility with double arrays: it would return false for 3D %% arrays; however 3D symbolic arrays are not currently supported. %% %% Example: %% @example %% @group %% A = sym([1 2; 3 4]); %% ismatrix(A) %% @result{} 1 %% ismatrix(sym([1 2 3])) %% @result{} 1 %% @end group %% @end example %% %% @seealso{@@sym/isscalar, @@sym/isvector, @@sym/size} %% @end defmethod function b = ismatrix(x) b = (length(size(x)) == 2); end %!assert(ismatrix(sym('x'))) %!assert(ismatrix(sym([1 2 3]))) %!assert(ismatrix(sym([1; 2]))) %!assert(ismatrix(sym([1 2; 3 4]))) %!assert(ismatrix(sym([]))) %!assert(ismatrix(sym(ones(1,0)))) %!assert(ismatrix(sym(ones(0,3)))) symbolic-3.1.1/inst/@sym/ismember.m0000644000000000000000000000453414405647405014110 0ustar %% Copyright (C) 2016 Lagu %% Copyright (C) 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym ismember (@var{x}, @var{S}) %% @defmethodx @@sym ismember (@var{x}, @var{M}) %% Test if an object is contained within a set or a matrix. %% %% This function can be used in two ways, the first is to check %% if @var{x} is contained in a set @var{S}: %% @example %% @group %% I = interval(sym(0), sym(pi)); %% ismember(2, I) %% @result{} ans = 1 %% @end group %% @end example %% %% It can also be used to check if @var{x} is contained in a %% matrix @var{M}: %% @example %% @group %% B = [sym(1) 2; 2*sym(pi) 4]; %% ismember(sym(pi), B) %% @result{} ans = 0 %% @end group %% @end example %% %% In either case, the first argument @var{x} can also be a matrix: %% @example %% @group %% A = [sym(3), 4 2; sym(1) 0 1]; %% ismember(A, B) %% @result{} ans = %% 0 1 1 %% 1 0 1 %% @end group %% @end example %% %% @seealso{@@sym/unique, @@sym/union, @@sym/intersect, @@sym/setdiff, %% @@sym/setxor} %% @end defmethod function r = ismember(x, y) if (nargin ~= 2) print_usage (); end r = uniop_bool_helper(sym(x), 'lambda x,y: x in y', [], sym(y)); end %!assert (ismember (2, interval(sym(0),2))) %!assert (~ismember (3, interval(sym(0),2))) %!test %! % something in a matrix %! syms x %! A = [1 x; sym(pi) 4]; %! assert (ismember (sym(pi), A)) %! assert (ismember (x, A)) %! assert (~ismember (2, A)) %!test %! % set %! syms x %! S = finiteset(2, sym(pi), x); %! assert (ismember (x, S)) %!test %! % set with positive symbol %! syms p positive %! S = finiteset(2, sym(pi), p); %! assert (~ismember (-1, S)) symbolic-3.1.1/inst/@sym/isna.m0000644000000000000000000000261714405647405013237 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym isna (@var{x}) %% Symbolic expressions cannot be the Octave/R missing data NA. %% %% Always returns false: %% @example %% @group %% isna([sym(1) sym('x') sym(nan)]) %% @result{} ans = %% 0 0 0 %% @end group %% @end example %% (We have this mainly so @code{assert} works properly.) %% %% @seealso{@@sym/isnan} %% @end defmethod function r = isna(x) r = logical(zeros(size(x))); end %!test %! % no sym should be NA %! syms x oo %! assert (~isna(sym(1))) %! assert (~isna(x)) %! assert (~isna(oo)) %! assert (~isna(sym(nan))) %! assert (isequal (isna (sym ([1 nan])), [false false])) symbolic-3.1.1/inst/@sym/isnan.m0000644000000000000000000000522714405647405013415 0ustar %% Copyright (C) 2014-2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym isnan (@var{x}) %% Return true if a symbolic expression is Not-a-Number. %% %% Example: %% @example %% @group %% A = [sym(1) sym(0)/0 sym(1)/0; sym(nan) 1 2] %% @result{} A = (sym 2×3 matrix) %% ⎡ 1 nan zoo⎤ %% ⎢ ⎥ %% ⎣nan 1 2 ⎦ %% isnan(A) %% @result{} ans = %% 0 1 0 %% 1 0 0 %% @end group %% @end example %% %% Note that the return is of type logical. %% %% @seealso{@@sym/isinf, @@sym/double} %% @end defmethod function r = isnan(x) if (nargin ~= 1) print_usage (); end r = uniop_bool_helper(x, 'lambda a: a is sp.nan'); end %!shared x,zoo,oo,snan %! oo = sym(inf); %! zoo = sym('zoo'); %! x = sym('x'); %! snan = sym(nan); %!test %! % various ops that give nan %! assert (isnan(0*oo)) %! assert (isnan(0*zoo)) %! assert (isnan(snan)) %! assert (isnan(snan-snan)) %! assert (isnan(oo+snan)) %! assert (isnan(oo-oo)) %! assert (isnan(oo-zoo)) %! assert (isnan(oo+zoo)) %! assert (~isnan(oo)) %! assert (~isnan(zoo)) %! assert (~isnan(oo+oo)) %!test %! % more ops give nan %! assert(isnan(x+snan)) %! assert(isnan(x*snan)) %! assert(isnan(0*snan)) %! assert(isnan(x+nan)) %! assert(isnan(x*nan)) %! assert(isnan(sym(0)*nan)) %!test %! % array %! assert (isequal( isnan([oo zoo]), [0 0] )) %! assert (isequal( isnan([10 snan]), [0 1] )) %! assert (isequal( isnan([snan snan]), [1 1] )) %! assert (isequal( isnan([snan x]), [1 0] )) %!test %! % sub in to algebraic expression gives nan %! y = x - oo; %! y = subs(y, x, oo); %! assert(isnan(y)) %!test %! % Must not contain string 'symbol'; these all should make an %! % actual nan. Actually a ctor test, not isnan. %! y = sym(nan); %! assert (isempty (strfind (sympy (y), 'Symbol'))) %! y = sym('nan'); %! assert (isempty (strfind (sympy (y), 'Symbol'))) %! y = sym('NaN'); %! assert (isempty( strfind (sympy (y), 'Symbol'))) symbolic-3.1.1/inst/@sym/isprime.m0000644000000000000000000000377514405647405013763 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym isprime (@var{n}) %% Return true if a symbolic number is prime. %% %% Example: %% @example %% @group %% n = sym(127); %% m = 2^n - 1 %% @result{} m = (sym) 170141183460469231731687303715884105727 %% isprime(m) %% @result{} ans = 1 %% @end group %% @end example %% %% Example: %% @example %% @group %% syms q negative %% isprime(q) %% @result{} ans = 0 %% @end group %% @end example %% %% @seealso{@@sym/nextprime, @@sym/prevprime} %% @end defmethod function z = isprime(x) % this will give True/False/None %z = elementwise_op ('lambda x: x.is_prime', x); %z = uniop_bool_helper(x, 'lambda x: x.is_prime', 'sym'); sf = { 'def sf(x):' ' r = x.is_prime' ' if r is None:' ' raise AttributeError("isprime: cannot determine if input is prime")' ' return r' }; z = uniop_bool_helper(x, sf); end %!assert (isprime (sym(5))) %!assert (~isprime (sym(4))) %!assert (~isprime (sym(0))) %!assert (~isprime (sym(1))) %!test %! a = [5 7 6; 1 2 337]; %! assert (isequal (isprime (a), [true true false; false true true])) %!assert (~isprime(sym(-4))) %!assert (~isprime(sym(4i))) %!assert (~isprime(sym(3)/5)) %!error %! isprime(sym('x')); symbolic-3.1.1/inst/@sym/isrow.m0000644000000000000000000000272414405647405013447 0ustar %% Copyright (C) 2014-2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym isrow (@var{x}) %% Return true if symbolic expression is a row vector. %% %% Example: %% @example %% @group %% h = sym([1 2 3]); %% isrow(h) %% @result{} 1 %% isrow(sym(1)) %% @result{} 1 %% isrow(h') %% @result{} 0 %% @end group %% @end example %% %% @seealso{@@sym/iscolumn, @@sym/isvector, @@sym/isscalar} %% @end defmethod function r = isrow(x) if (nargin ~= 1) print_usage (); end % from Rik Wehbring's Octave function sz = size (x); r = (ndims (x) == 2 && (sz(1) == 1)); end %!assert (isrow (sym ([1]))) %!assert (isrow (sym ([1 2 3]))) %!assert (~isrow (sym ([]))) %!assert (~isrow (sym ([1 2 3]'))) %!assert (~isrow (sym ([1 2; 3 4]))) symbolic-3.1.1/inst/@sym/isscalar.m0000644000000000000000000000254114405647405014102 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym isscalar (@var{x}) %% Return true if this symbolic expression is a scalar. %% %% Example: %% @example %% @group %% s = sym(1); %% v = sym([1 2 3]); %% isscalar(s) %% @result{} 1 %% isscalar(v) %% @result{} 0 %% @end group %% @end example %% %% @seealso{@@sym/size, @@sym/numel, @@sym/isvector} %% @end defmethod function b = isscalar(x) if (nargin ~= 1) print_usage (); end d = size(x); n = prod(d); b = (n == 1); end %!assert(isscalar(sym('x'))) %!test %! a = sym([1 2 3]); %! assert(~isscalar(a)) %!assert(~isscalar(sym([]))) symbolic-3.1.1/inst/@sym/isvector.m0000644000000000000000000000277714405647405014152 0ustar %% Copyright (C) 2014-2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym isvector (@var{x}) %% Return true if this symbolic expression is a vector. %% %% Example: %% @example %% @group %% A = sym([1 2; 3 4]); %% v = sym([1 2 3]); %% h = v'; %% isvector(A) %% @result{} 0 %% isvector(v) %% @result{} 1 %% isvector(h) %% @result{} 1 %% @end group %% @end example %% %% @seealso{@@sym/size, @@sym/numel, @@sym/isscalar} %% @end defmethod function b = isvector(x) if (nargin ~= 1) print_usage (); end d = size(x); b = any(d == 1); end %!assert(isvector(sym('x'))) %!assert(isvector(sym([1 2 3]))) %!assert(isvector(sym([1; 2]))) %!assert(~isvector(sym([1 2; 3 4]))) %!assert(~isvector(sym([]))) %!assert(isvector(sym(ones(1,0)))) %!assert(~isvector(sym(ones(0,3)))) symbolic-3.1.1/inst/@sym/jacobian.m0000644000000000000000000001105614405647405014050 0ustar %% Copyright (C) 2014, 2016, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym jacobian (@var{f}) %% @defmethodx @@sym jacobian (@var{f}, @var{x}) %% Symbolic Jacobian of symbolic expression. %% %% The Jacobian of a scalar expression is: %% @example %% @group %% syms f(x, y, z) %% jacobian(f) %% @result{} (sym 1×3 matrix) %% ⎡∂ ∂ ∂ ⎤ %% ⎢──(f(x, y, z)) ──(f(x, y, z)) ──(f(x, y, z))⎥ %% ⎣∂x ∂y ∂z ⎦ %% @end group %% @end example %% %% @var{x} can be a scalar, vector or cell list. If omitted, %% it is determined using @code{symvar}. %% %% Example: %% @example %% @group %% f = sin(x*y); %% jacobian(f) %% @result{} (sym) [y⋅cos(x⋅y) x⋅cos(x⋅y)] (1×2 matrix) %% %% jacobian(f, [x y z]) %% @result{} (sym) [y⋅cos(x⋅y) x⋅cos(x⋅y) 0] (1×3 matrix) %% @end group %% @end example %% %% For vector input, the output is a matrix: %% @example %% @group %% syms f(x,y,z) g(x,y,z) %% jacobian([f; g]) %% @result{} (sym 2×3 matrix) %% ⎡∂ ∂ ∂ ⎤ %% ⎢──(f(x, y, z)) ──(f(x, y, z)) ──(f(x, y, z))⎥ %% ⎢∂x ∂y ∂z ⎥ %% ⎢ ⎥ %% ⎢∂ ∂ ∂ ⎥ %% ⎢──(g(x, y, z)) ──(g(x, y, z)) ──(g(x, y, z))⎥ %% ⎣∂x ∂y ∂z ⎦ %% @end group %% @end example %% %% Example: %% @example %% @group %% jacobian([2*x + 3*z; 3*y^2 - cos(x)]) %% @result{} (sym 2×3 matrix) %% ⎡ 2 0 3⎤ %% ⎢ ⎥ %% ⎣sin(x) 6⋅y 0⎦ %% @end group %% @end example %% @seealso{@@sym/divergence, @@sym/gradient, @@sym/curl, @@sym/laplacian, %% @@sym/hessian} %% @end defmethod function g = jacobian(f, x) assert (isvector(f), 'jacobian: defined only for vectors expressions') if (nargin == 1) x = symvar(f); if (isempty(x)) x = sym('x'); end elseif (nargin == 2) % no-op else print_usage (); end if (~iscell(x) && isscalar(x)) x = {x}; end cmd = { '(f, x) = _ins' 'if not f.is_Matrix:' ' f = Matrix([f])' 'G = f.jacobian(x)' 'return G,' }; g = pycall_sympy__ (cmd, sym(f), x); end %!error jacobian (sym(1), 2, 3) %!error jacobian ([sym(1) 2; sym(3) 4]) %!shared x,y,z %! syms x y z %!test %! % 1D %! f = x^2; %! assert (isequal (jacobian(f), diff(f,x))) %! assert (isequal (jacobian(f,{x}), diff(f,x))) %! assert (isequal (jacobian(f,x), diff(f,x))) %!test %! % const %! f = sym(1); %! g = sym(0); %! assert (isequal (jacobian(f), g)) %! assert (isequal (jacobian(f,x), g)) %!test %! % double const %! f = 1; %! g = sym(0); %! assert (isequal (jacobian(f,x), g)) %!test %! % diag %! f = [x y^2]; %! g = [sym(1) 0; 0 2*y]; %! assert (isequal (jacobian(f), g)) %! assert (isequal (jacobian(f, [x y]), g)) %! assert (isequal (jacobian(f, {x y}), g)) %!test %! % anti-diag %! f = [y^2 x]; %! g = [0 2*y; sym(1) 0]; %! assert (isequal (jacobian(f), g)) %! assert (isequal (jacobian(f, {x y}), g)) %!test %! % shape %! f = [x y^2]; %! assert (isequal (size(jacobian(f, {x y z})), [2 3])) %! assert (isequal (size(jacobian(f, [x y z])), [2 3])) %! assert (isequal (size(jacobian(f, [x; y; z])), [2 3])) %! assert (isequal (size(jacobian(f.', {x y z})), [2 3])) %!test %! % scalar f %! f = x*y; %! assert (isequal (size(jacobian(f, {x y})), [1 2])) %! g = gradient(f, {x y}); %! assert (isequal (jacobian(f, {x y}), g.')) %!test %! % vect f wrt 1 var %! f = [x x^2]; %! assert (isequal (size(jacobian(f, x)), [2 1])) %! f = f.'; % same shape output %! assert (isequal (size(jacobian(f, x)), [2 1])) symbolic-3.1.1/inst/@sym/jordan.m0000644000000000000000000001106314405647405013555 0ustar %% Copyright (C) 2016 Alex Vong %% Copyright (C) 2017-2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {@var{J} =} jordan (@var{A}) %% @deftypemethodx @@sym {[@var{V}, @var{J}] =} jordan (@var{A}) %% Symbolic Jordan canonical form of a matrix. %% %% Example: %% @example %% @group %% A = sym ([6 5 -2 -3; -3 -1 3 3; 2 1 -2 -3; -1 1 5 5]); %% jordan (A) %% @result{} ans = (sym 4×4 matrix) %% ⎡2 1 0 0⎤ %% ⎢ ⎥ %% ⎢0 2 0 0⎥ %% ⎢ ⎥ %% ⎢0 0 2 1⎥ %% ⎢ ⎥ %% ⎣0 0 0 2⎦ %% @end group %% @end example %% %% We can also compute the generalized eigenvectors: %% @example %% @group %% [V, J] = jordan (A) %% @result{} V = (sym 4×4 matrix) %% ⎡4 1 5 0⎤ %% ⎢ ⎥ %% ⎢-3 0 -3 1⎥ %% ⎢ ⎥ %% ⎢2 0 1 0⎥ %% ⎢ ⎥ %% ⎣-1 0 1 0⎦ %% @result{} J = (sym 4×4 matrix) %% ⎡2 1 0 0⎤ %% ⎢ ⎥ %% ⎢0 2 0 0⎥ %% ⎢ ⎥ %% ⎢0 0 2 1⎥ %% ⎢ ⎥ %% ⎣0 0 0 2⎦ %% @end group %% %% @group %% A*V - V*J %% @result{} ans = (sym 4×4 matrix) %% ⎡0 0 0 0⎤ %% ⎢ ⎥ %% ⎢0 0 0 0⎥ %% ⎢ ⎥ %% ⎢0 0 0 0⎥ %% ⎢ ⎥ %% ⎣0 0 0 0⎦ %% @end group %% @end example %% %% The generalized eigenvectors are the columns of @var{V}. %% Those corresponding to a Jordan block form a cycle. %% We can check those columns corresponding to the leftmost Jordan block: %% @example %% @group %% lambda = J(2, 2) %% @result{} lambda = (sym) 2 %% B = A - lambda*eye (4); %% v2 = V(:, 2) %% @result{} v2 = (sym 4×1 matrix) %% ⎡1⎤ %% ⎢ ⎥ %% ⎢0⎥ %% ⎢ ⎥ %% ⎢0⎥ %% ⎢ ⎥ %% ⎣0⎦ %% v1 = B * v2 %% @result{} v1 = (sym 4×1 matrix) %% ⎡4 ⎤ %% ⎢ ⎥ %% ⎢-3⎥ %% ⎢ ⎥ %% ⎢2 ⎥ %% ⎢ ⎥ %% ⎣-1⎦ %% v0 = B * v1 %% @result{} v0 = (sym 4×1 matrix) %% ⎡0⎤ %% ⎢ ⎥ %% ⎢0⎥ %% ⎢ ⎥ %% ⎢0⎥ %% ⎢ ⎥ %% ⎣0⎦ %% @end group %% @end example %% %% @seealso{@@sym/charpoly, @@sym/eig} %% @end deftypemethod function [V, J] = jordan (A) cmd = {'(A, calctrans) = _ins' 'if not A.is_Matrix:' ' A = sp.Matrix([A])' 'return A.jordan_form(calctrans)'}; if (nargout <= 1) V = pycall_sympy__ (cmd, sym (A), false); else [V, J] = pycall_sympy__ (cmd, sym (A), true); end end %!test %! % basic %! A = sym ([2 1 0 0; 0 2 1 0; 0 0 3 0; 0 1 -1 3]); %! [V, J] = jordan (A); %! assert (isequal (inv (V) * A * V, J)); %! assert (isequal (J, sym ([2 1 0 0; 0 2 0 0; 0 0 3 0; 0 0 0 3]))) %! % the first 2 generalized eigenvectors form a cycle %! assert (isequal ((A - J(1, 1) * eye (4)) * V(:, 1), zeros (4, 1))); %! assert (isequal ((A - J(2, 2) * eye (4)) * V(:, 2), V(:, 1))); %! % the last 2 generalized eigenvectors are eigenvectors %! assert (isequal ((A - J(3, 3) * eye (4)) * V(:, 3), zeros (4, 1))); %! assert (isequal ((A - J(4, 4) * eye (4)) * V(:, 4), zeros (4, 1))); %!test %! % scalars %! assert (isequal (jordan (sym (-10)), sym (-10))); %! assert (isequal (jordan (sym ('x')), sym ('x'))); %!test %! % diagonal matrices %! A = diag (sym ([6 6 7])); %! [V1, D] = eig (A); %! [V2, J] = jordan (A); %! assert (isequal (V1, V2)); %! assert (isequal (D, J)); %!test %! % matrices of unknown entries %! A = [sym('a') sym('b'); sym('c') sym('d')]; %! [V, D] = eig (A); %! J = jordan (A); %! assert (isequal (simplify (D), simplify (J))); %!test %! % matrices of mixed entries %! A = [sym('x')+9 sym('y'); sym(0) 6]; %! [V, D] = eig (A); %! J = jordan (A); %! assert (isequal (simplify (D), simplify (J))); symbolic-3.1.1/inst/@sym/kron.m0000644000000000000000000000733114405647405013254 0ustar %% Copyright (C) 2016 Utkarsh Gautam %% Copyright (C) 2016, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym kron (@var{a}, @var{b}) %% @defmethodx @@sym kron (@var{a}, @var{b}, @dots{}, @var{c}) %% Kronecker tensor product of two or more symbolic matrices. %% %% Examples: %% @example %% @group %% syms x %% kron(eye(2)*x, [1, -1; -1, 1]) %% @result{} ans = (sym 4×4 matrix) %% %% ⎡x -x 0 0 ⎤ %% ⎢ ⎥ %% ⎢-x x 0 0 ⎥ %% ⎢ ⎥ %% ⎢0 0 x -x⎥ %% ⎢ ⎥ %% ⎣0 0 -x x ⎦ %% %% @end group %% @end example %% %% @example %% @group %% syms x y %% kron([1, 2], [x, y; y, x]) %% @result{} ans = (sym 2×4 matrix) %% %% ⎡x y 2⋅x 2⋅y⎤ %% ⎢ ⎥ %% ⎣y x 2⋅y 2⋅x⎦ %% %% @end group %% @end example %% %% @example %% @group %% kron([1, 2], [x, y; y, x], [1; 7]) %% @result{} ans = (sym 4×4 matrix) %% %% ⎡ x y 2⋅x 2⋅y ⎤ %% ⎢ ⎥ %% ⎢7⋅x 7⋅y 14⋅x 14⋅y⎥ %% ⎢ ⎥ %% ⎢ y x 2⋅y 2⋅x ⎥ %% ⎢ ⎥ %% ⎣7⋅y 7⋅x 14⋅y 14⋅x⎦ %% %% @end group %% @end example %% @end defmethod function c = kron (varargin) if (nargin < 2) print_usage (); end for i = 1:nargin varargin{i} = sym (varargin{i}); end cmd = { '_ins = (a if isinstance(a, (MatrixBase, NDimArray)) else Matrix([a]) for a in _ins)' 'from sympy.physics.quantum import TensorProduct' 'return TensorProduct(*_ins)' }; c = pycall_sympy__ (cmd, varargin{:}); end %!error kron (sym (2)) %!test %! syms x y %! A = [sin(x), sin(y); x, y]; %! B = ones(2); %! expected = sym([sin(x), sin(x), sin(y), sin(y); sin(x), sin(x), sin(y), sin(y); x, x, y, y; x, x, y, y]); %! assert (isequal (kron(A, B), expected)) %!test %! syms x y %! A = [sin(x), sin(y); x, y]; %! B = 2; %! assert (isequal (kron(A, B), 2*A)) %!test %! syms x y %! A = [sin(x), sin(y)]; %! B = 2; %! assert (isequal( kron(B, A), 2*A)) %!test %! syms x y; %! X = [tan(x), tan(x)]; %! Y = [cot(x); cot(x)]; %! expected = sym(ones(2)); %! assert (isequal (simplify(kron(X, Y)), expected)) %!test %! syms x y z %! X = [x, y, z]; %! Y = [y, y; x, x]; %! expected = [x*y, x*y, y^2, y^2, y*z, y*z; x^2, x^2, x*y, x*y, x*z, x*z]; %! assert (isequal (kron(X, Y), expected)) %!test %! syms x y %! X = [x, x^2; y, y^2]; %! Y = [1, 0; 0, 1]; %! expected = [x, x^2, 0, 0; y, y^2, 0, 0; 0, 0, x, x^2; 0, 0, y, y^2]; %! assert (isequal (kron(Y, X), expected)) %!test %! syms x y z %! assert (isequal (kron (x, y, z), x*y*z)) %! assert (isequal (kron (x, y, z, 4), 4*x*y*z)) %! assert (isequal (kron ([2 3], y, z), [2 3]*y*z)) %! assert (isequal (kron ([2 3], [4; 5], y), [8 12; 10 15]*y)) %!test %! syms x y %! A = kron ([x y], [1, -1; -1, 1], [2 3; 4 5]); %! D = kron ([7 9], [1, -1; -1, 1], [2 3; 4 5]); %! A = double (subs (A, [x y], [7 9])); %! assert (isequal (A, D)) symbolic-3.1.1/inst/@sym/kroneckerDelta.m0000644000000000000000000000374114405647405015241 0ustar %% Copyright (C) 2017-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym kroneckerDelta (@var{n}, @var{m}) %% @defmethodx @@sym kroneckerDelta (@var{n}) %% Kronecker Delta function. %% %% Examples: %% @example %% @group %% kroneckerDelta (sym(4), sym(5)) %% @result{} ans = (sym) 0 %% kroneckerDelta (sym(4), sym(4)) %% @result{} ans = (sym) 1 %% @end group %% @end example %% %% @example %% @group %% syms n m integer %% kroneckerDelta (m, n) %% @result{} ans = (sym) %% %% δ %% m,n %% @end group %% @end example %% %% The second input defaults to zero: %% @example %% @group %% kroneckerDelta (n) %% @result{} ans = (sym) %% %% δ %% 0,n %% @end group %% @end example %% %% @seealso{@@sym/dirac} %% @end defmethod function a = kroneckerDelta (n, m) if (nargin == 1) m = sym(0); elseif (nargin > 2) print_usage (); end a = elementwise_op ('KroneckerDelta', sym(n), sym(m)); end %!error kroneckerDelta (sym(1), 2, 3) %!test %! syms x %! assert (isequal (kroneckerDelta (x, x), sym(1))) %!assert (isequal (kroneckerDelta ([sym(1) 2 3], [1 2 0]), sym([1 1 0]))) %!test %! % round trip %! syms x y %! f = kroneckerDelta (x, y); %! h = function_handle (f); %! assert (h (1, 2), 0) %! assert (h (2, 2), 1) symbolic-3.1.1/inst/@sym/laguerreL.m0000644000000000000000000001174214405647405014226 0ustar %% Copyright (C) 2016, 2018-2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym laguerreL (@var{n}, @var{x}) %% @defmethodx @@sym laguerreL (@var{n}, @var{alpha}, @var{x}) %% Symbolic Laguerre polynomials and associated Laguerre polynomials. %% %% Example: %% @example %% @group %% syms x n %% laguerreL(5, x) %% @result{} ans = (sym) %% 5 4 3 %% x 5⋅x 5⋅x 2 %% - ─── + ──── - ──── + 5⋅x - 5⋅x + 1 %% 120 24 3 %% laguerreL(n, x) %% @result{} ans = (sym) laguerre(n, x) %% @end group %% @end example %% %% When @var{alpha} is nonzero, we get generalized (associated) Laguerre %% polynomials: %% @example %% @group %% laguerreL(n, 1, x) %% @result{} ans = (sym) assoc_laguerre(n, 1, x) %% @end group %% @end example %% %% The polynomials can be manipulated symbolically, for example: %% @example %% @group %% L = laguerreL(n, x); %% diff(L, x) %% @result{} ans = (sym) -assoc_laguerre(n - 1, 1, x) %% @end group %% @end example %% %% Laguerre @emph{Functions} have non-positive integer @var{N}, %% such as %% @example %% @group %% syms x %% N = -3; %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.4")')) %% y = laguerreL(N, x) %% @result{} y = (sym) %% ⎛ 2 ⎞ %% ⎜x ⎟ x %% ⎜── + 2⋅x + 1⎟⋅ℯ %% ⎝2 ⎠ %% @end group %% @end example %% These satisfy Laguerre's differential equation: %% @example %% @group %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.4")')) %% x*diff(y, x, x) + (1 - x)*diff(y, x) + N*y == 0 %% @result{} (sym) ... %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.4")')) %% simplify(ans) %% @result{} (sym) True %% @end group %% @end example %% %% Note: the Generalized Laguerre @emph{Function} is not implemented. %% %% @seealso{laguerreL, @@sym/chebychevT, @@sym/chebychevU} %% @end defmethod function L = laguerreL(n, alpha, x) if (nargin == 2) x = alpha; L = elementwise_op ('laguerre', sym(n), sym(x)); elseif (nargin == 3) L = elementwise_op ('assoc_laguerre', sym(n), sym(alpha), sym(x)); else print_usage (); end end %!shared x %! syms x %!assert (isequal (laguerreL(0, x), sym(1))) %!assert (isequal (laguerreL(1, x), 1-x)) %!assert (isequal (laguerreL(2, x), x^2/2 - 2*x + 1)) %!error laguerreL(x) %!error laguerreL(1, 2, x, 3) %!shared %!test %! if (pycall_sympy__ ('return Version(spver) > Version("1.4")')) %! syms x %! assert (isequal (laguerreL (-3, x), exp(x)*(x^2/2 + 2*x + 1))) %! end %!test %! syms x n %! L = laguerreL([2 n], x); %! expected = [laguerreL(2, x) laguerreL(n, x)]; %! assert (isequal (L, expected)) %!test %! syms x y %! L = laguerreL([1; 2], [x; y]); %! expected = [laguerreL(1, x); laguerreL(2, y)]; %! assert (isequal (L, expected)) %!test %! syms x n %! assert (isequal (laguerreL(n, 0, x), laguerreL(n, x))) %!shared x, y, n %! syms x y n %!assert (isequal (laguerreL([1 n], 0, x), laguerreL([1 n], x))) %!test %! L = laguerreL([1; n], [pi; 0], [x; y]); %! expected = [laguerreL(1, pi, x); laguerreL(n, 0, y)]; %! assert (isequal (L, expected)) %!test %! L = laguerreL([1 n], [pi 0], x); %! expected = [laguerreL(1, pi, x) laguerreL(n, 0, x)]; %! assert (isequal (L, expected)) %!test %! L = laguerreL([1 n], pi, [x y]); %! expected = [laguerreL(1, pi, x) laguerreL(n, pi, y)]; %! assert (isequal (L, expected)) %!test %! L = laguerreL(1, [pi 0], [x y]); %! expected = [laguerreL(1, pi, x) laguerreL(1, 0, y)]; %! assert (isequal (L, expected)) %!test %! L = laguerreL([1 n], pi, x); %! expected = [laguerreL(1, pi, x) laguerreL(n, pi, x)]; %! assert (isequal (L, expected)) %!test %! L = laguerreL(1, [pi 0], x); %! expected = [laguerreL(1, pi, x) laguerreL(1, 0, x)]; %! assert (isequal (L, expected)) %!test %! L = laguerreL(1, pi, [x y]); %! expected = [laguerreL(1, pi, x) laguerreL(1, pi, y)]; %! assert (isequal (L, expected)) %!test %! % round trip %! f = laguerreL (n, x); %! h = function_handle (f); %! A = h (1, 3.2); %! B = laguerreL (1, 3.2); %! assert (A, B) %! A = h ([1 2], [3.3 4.4]); %! B = laguerreL ([1 2], [3.3 4.4]); %! assert (A, B) %!error %! % round trip %! f = laguerreL (n, y, x); %! h = function_handle (f); symbolic-3.1.1/inst/@sym/lambertw.m0000644000000000000000000000553214405647405014121 0ustar %% Copyright (C) 2015, 2016, 2018-2019 Colin B. Macdonald %% Copyright (C) 2019 Mike Miller %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym lambertw (@var{x}) %% @defmethodx @@sym lambertw (@var{k}, @var{x}) %% Symbolic Lambert W function. %% %% The Lambert W function is the inverse of @code{W*exp(W)}. The %% branch @var{k} defaults to zero if omitted. %% %% Examples: %% @example %% @group %% syms x %% lambertw(x) %% @result{} (sym) lambertw(x) %% lambertw(2, x) %% @result{} (sym) lambertw(2, x) %% @end group %% @end example %% %% Also supports vector/matrix input: %% @example %% @group %% syms x y %% lambertw([0 1], [x y]) %% @result{} (sym) [lambertw(x) lambertw(1, y)] (1×2 matrix) %% @end group %% @end example %% @seealso{lambertw} %% @end defmethod function W = lambertw(k, x) if (nargin == 1) x = sym(k); W = elementwise_op ('LambertW', x); elseif (nargin == 2) x = sym(x); k = sym(k); W = elementwise_op ('LambertW', x, k); else print_usage (); end end %!test %! % W(x)*exp(W(x)) == x %! syms x %! T = lambertw(x)*exp(lambertw(x)); %! T = double (subs (T, x, 10)); %! assert (isequal (T, 10)); %!test %! % k, x not x, k to match SMT %! syms x %! T = lambertw(2, x)*exp(lambertw(2, x)); %! T = double (subs (T, x, 10)); %! assert (abs(T - 10) < 1e-15) %!assert (isequal (lambertw(sym(0)), sym(0))) %!assert ( isequal (lambertw (-1/exp(sym(1))), -sym(1))) %!assert ( isequal (lambertw (0, -1/exp(sym(1))), -sym(1))) %!assert ( isequal (lambertw (-1, -1/exp(sym(1))), -sym(1))) %!xtest %! % W(x)*exp(W(x)) == x; FIXME: a failure in SymPy? %! syms x %! T = simplify(lambertw(x)*exp(lambertw(x))); %! assert (isequal (T, x)) % should match @double/lambertw %!assert (abs (lambertw(pi) - double(lambertw(sym(pi)))) < 5*eps) %!assert (abs (lambertw(-1, 5) - double(lambertw(-1, sym(5)))) < 5*eps) %!assert (abs (lambertw(2, 2) - double(lambertw(2, sym(2)))) < 5*eps) %!test %! % round trip %! syms x k %! A = lambertw (5); %! f = lambertw (x); %! h = function_handle (f); %! B = h (5); %! assert (A, B) %! %! A = lambertw (3, 5); %! f = lambertw (k, x); %! h = function_handle (f); %! B = h (3, 5); %! assert (A, B) symbolic-3.1.1/inst/@sym/laplace.m0000644000000000000000000001323714405647405013706 0ustar %% Copyright (C) 2014-2016 Andrés Prieto %% Copyright (C) 2015-2016, 2019 Colin Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym laplace (@var{f}, @var{t}, @var{s}) %% @defmethodx @@sym laplace (@var{f}) %% @defmethodx @@sym laplace (@var{f}, @var{s}) %% Laplace transform. %% %% The Laplace transform of a function @var{f} of @var{t} %% is a function @var{G} of @var{s} defined by the integral below. %% @example %% @group %% syms f(t) s %% G(s) = rewrite(laplace(f), 'Integral') %% @result{} G(s) = (symfun) %% ∞ %% ⌠ %% ⎮ -s⋅t %% ⎮ f(t)⋅ℯ dt %% ⌡ %% 0 %% @end group %% @end example %% %% %% Example: %% @example %% @group %% syms t %% f = t^2; %% laplace(f) %% @result{} (sym) %% 2 %% ── %% 3 %% s %% @end group %% @end example %% %% By default the ouput is a function of @code{s} (or @code{z} if the Laplace %% transform happens to be with respect to @code{s}). This can be overriden %% by specifying @var{s}. For example: %% @example %% @group %% syms t s z %% laplace(exp(t)) %% @result{} (sym) %% 1 %% ───── %% s - 1 %% laplace(exp(s)) %% @result{} (sym) %% 1 %% ───── %% z - 1 %% laplace(exp(t), z) %% @result{} (sym) %% 1 %% ───── %% z - 1 %% @end group %% @end example %% %% If not specified by @var{t}, the independent variable is chosen by %% looking for a symbol named @code{t}. If no such symbol is found, %% @pxref{@@sym/symvar} is used, which choses a variable close to @code{x}: %% @example %% @group %% syms a y %% laplace (a*exp (y)) %% @result{} (sym) %% a %% ───── %% s - 1 %% @end group %% @end example %% %% @seealso{@@sym/ilaplace} %% @end defmethod function F = laplace(varargin) % FIXME: it only works for scalar functions % FIXME: it doesn't handle diff call (see SMT transform of diff calls) f = sym(varargin{1}); if (nargin == 1 || nargin == 2) %% time domain variable not specified % if exactly one symbol has char(t) == 't'... symbols = findsymbols (f); charsyms = cell (size (symbols)); for c=1:numel(charsyms) charsyms{c} = char (symbols{c}); end match = find (strcmp (charsyms, 't')); assert (numel (match) <= 1, 'laplace: there is more than one "t" symbol: check symvar(F) and sympy(F)') if (~ isempty (match)) t = symbols{match}; % ... we want that one else t = symvar (f, 1); if (isempty (t)) t = sym ('t', 'positive'); end end end % If the physical variable of f is equal to "s", % "z" is the frequency domain variable (analogously to SMT) if (nargin == 1) cmd = { 'f=_ins[0]; t=_ins[1]; s=sp.Symbol("s")' 'if t==s:' ' s=sp.Symbol("z")' 'F=sp.laplace_transform(f, t, s)' 'if isinstance(F, sp.LaplaceTransform):' ' return F,' 'else:' ' return F[0],'}; F = pycall_sympy__ (cmd, f, t); elseif (nargin == 2) s = sym(varargin{2}); cmd = { 'f=_ins[0]; t=_ins[1]; s=_ins[2]' 'F=sp.laplace_transform(f, t, s)' 'if isinstance(F, sp.LaplaceTransform):' ' return F,' 'else:' ' return F[0],'}; F = pycall_sympy__ (cmd, f, t, s); elseif (nargin == 3) t = sym(varargin{2}); s = sym(varargin{3}); cmd = { 'f=_ins[0]; t=_ins[1]; s=_ins[2]' 'F=sp.laplace_transform(f, t, s)' 'if isinstance(F, sp.LaplaceTransform):' ' return F,' 'else:' ' return F[0],'}; F = pycall_sympy__ (cmd, f, t, s); else print_usage (); end end %!test %! % basic %! syms t s u w %! assert(logical( laplace(cos(3*t)) == s/(s^2+9) )) %! assert(logical( laplace(t^3) == 6/s^4 )) %!test %! % matlab SMT compat %! syms t s u w z %! assert(logical( laplace(exp(2*t)) == 1/(s-2) )) %! assert(logical( laplace(exp(2*s)) == 1/(z-2) )) %! assert(logical( laplace(exp(2*u),w) == 1/(w-2) )) %! assert(logical( laplace(exp(2*u),u,w) == 1/(w-2) )) %!test %! syms x s t z %! % matlab SMT prefers t over x %! assert (isequal (laplace (x*exp (t), z), x/(z - 1))) %! % as usual, you can just specify: %! assert (isequal (laplace(x*exp(t), t, z), x/(z - 1))) % SMT result %! assert (isequal (laplace(x*exp(t), x, z), exp(t)/z^2)) %!test %! syms x a s %! % if no t, use symvar: take x before a %! assert (isequal (laplace (a*exp (x)), a/(s - 1))) %!error laplace (sym('t')*sym('t', 'real')) %!test %! % constant, issue #250 %! syms s %! f = laplace(2, s); %! assert (isequal (f, 2/s)) %!test %! % Dirac delta and Heaviside tests %! syms t s %! assert (isequal (laplace(dirac(t-3)), exp(-3*s))) %! assert (isequal (laplace((t-3)*heaviside(t-3)), exp(-3*s)/s^2)) %!xtest %! % Differential operator to algebraic %! % SymPy cannot evaluate? (Issue #170) %! syms s f(t) %! assert(logical( laplace(diff(f(t),t),t,s) == s*laplace(f(t),t,s)-f(0) )) symbolic-3.1.1/inst/@sym/laplacian.m0000644000000000000000000000704614405647405014232 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym laplacian (@var{f}) %% @defmethodx @@sym laplacian (@var{f}, @var{x}) %% Symbolic Laplacian of symbolic expression. %% %% The Laplacian of a scalar expression @var{f} is %% the scalar expression: %% @example %% @group %% syms f(x, y, z) %% laplacian(f) %% @result{} (sym) %% 2 2 2 %% ∂ ∂ ∂ %% ───(f(x, y, z)) + ───(f(x, y, z)) + ───(f(x, y, z)) %% 2 2 2 %% ∂x ∂y ∂z %% @end group %% @end example %% %% @var{x} can be a scalar, vector or cell list. If omitted, %% it is determined using @code{symvar}. %% %% Example: %% @example %% @group %% syms x y %% laplacian(x^3 + 5*y^2) %% @result{} (sym) 6⋅x + 10 %% @end group %% @end example %% %% Note: assumes @var{x} is a Cartesian coordinate system. %% %% @seealso{@@sym/divergence, @@sym/gradient, @@sym/curl, @@sym/jacobian, %% @@sym/hessian} %% @end defmethod function g = laplacian(f,x) assert (isscalar(f), 'laplacian: only scalar functions supported') if (nargin == 1) x = symvar(f); if (isempty(x)) x = sym('x'); end elseif (nargin == 2) % no-op else print_usage (); end if (~iscell(x) && isscalar(x)) x = {x}; end cmd = { '(f, x) = _ins' 'g = 0' 'for y in x:' ' g = g + f.diff(y, 2)' 'return g,' }; g = pycall_sympy__ (cmd, sym(f), x); end %!shared x,y,z %! syms x y z %!test %! % 1D %! f = x^2; %! g = diff(f,x,x); %! assert (isequal (laplacian(f), g)) %! assert (isequal (laplacian(f,{x}), g)) %! assert (isequal (laplacian(f,[x]), g)) %! assert (isequal (laplacian(f,x), g)) %!test %! % const %! f = sym(1); %! g = sym(0); %! assert (isequal (laplacian(f), g)) %! assert (isequal (laplacian(f,x), g)) %! f = sym('c'); %! assert (isequal (laplacian(f,x), g)) %!test %! % double const %! f = 1; %! g = sym(0); %! assert (isequal (laplacian(f,x), g)) %!test %! % 1D fcn in 2d/3d %! f = sin(2*y); %! g = -4*f; %! assert (isequal (laplacian(f), g)) %! assert (isequal (laplacian(f, {x,y}), g)) %! assert (isequal (laplacian(f, {x,y,z}), g)) %!test %! % 2d fcn in 2d/3d %! f = sin(exp(x)*y); %! g = diff(f,x,x) + diff(f,y,y); %! assert (isequal (laplacian(f), g)) %! assert (isequal (laplacian(f, {x,y}), g)) %!test %! % 2d fcn in 2d/3d %! f = sin(exp(x)*y+sinh(z)); %! gr2 = gradient(f, {x,y}); %! divgr2 = divergence(gr2, {x,y}); %! l2 = laplacian(f,{x,y}); %! gr3 = gradient(f, {x,y,z}); %! divgr3 = divergence(gr3, {x,y,z}); %! l3 = laplacian(f,{x,y,z}); %! assert (isAlways (l2 == divgr2)) %! assert (isAlways (l3 == divgr3)) %!error laplacian(sym('x'), sym('x'), 42) %!error laplacian([sym('x'), sym('x')]) symbolic-3.1.1/inst/@sym/latex.m0000644000000000000000000000324614405647405013421 0ustar %% Copyright (C) 2014-2016, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {} latex (@var{x}) %% @deftypemethodx @@sym {@var{s} =} latex (@var{x}) %% Display or return LaTeX typesetting code for symbolic expression. %% %% Example: %% @example %% @group %% syms x %% latex(sin(x/2)) %% @print{} \sin@{\left(\frac@{x@}@{2@} \right)@} %% @end group %% %% @group %% A = [sym(1) 2; sym(3) 4]; %% s = latex(A) %% @result{} s = \left[\begin@{matrix@}1 & 2\\3 & 4\end@{matrix@}\right] %% @end group %% @end example %% %% @seealso{@@sym/disp, @@sym/pretty} %% @end deftypemethod function varargout = latex(x) if (nargin ~= 1) print_usage (); end cmd = { 'return sp.latex(*_ins),' }; s = pycall_sympy__ (cmd, x); if (nargout == 0) disp(s) else varargout = {s}; end end %!test %! syms x %! y = sin(x); %! assert (strcmp (latex (y), '\sin{\left(x \right)}')) %!assert (strcmp (latex (exp (sym('x'))), 'e^{x}')) symbolic-3.1.1/inst/@sym/ldivide.m0000644000000000000000000000467114405647405013727 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym ldivide {(@var{x}, @var{y})} %% @defopx Operator @@sym {@var{x} .\ @var{y}} {} %% Element-wise backslash division of symbolic expressions. %% %% Example: %% @example %% @group %% syms x %% A = sym([1 137; 3 4]) %% @result{} A = (sym 2×2 matrix) %% ⎡1 137⎤ %% ⎢ ⎥ %% ⎣3 4 ⎦ %% B = [x pi; 2*x 8] %% @result{} B = (sym 2×2 matrix) %% ⎡ x π⎤ %% ⎢ ⎥ %% ⎣2⋅x 8⎦ %% A .\ B %% @result{} ans = (sym 2×2 matrix) %% ⎡ π ⎤ %% ⎢ x ───⎥ %% ⎢ 137⎥ %% ⎢ ⎥ %% ⎢2⋅x ⎥ %% ⎢─── 2 ⎥ %% ⎣ 3 ⎦ %% @end group %% @end example %% @seealso{@@sym/rdivide, @@sym/mldivide} %% @end defop function z = ldivide(x, y) z = rdivide(y, x); end %!test %! % scalar %! syms x %! assert (isa (x .\ 1, 'sym')) %! assert (isa (x .\ x, 'sym')) %! assert (isequal (x .\ 1, 1/x)) %! assert (isequal (x .\ x, sym(1))) %!test %! % matrix-scalar %! D = [1 1; 2 3]; %! A = sym(D); %! assert (isequal ( A .\ 6 , D .\ 6 )) %! assert (isequal ( A .\ sym(6) , D .\ 6 )) %! assert (isequal ( D .\ sym(6) , D .\ 6 )) %!test %! % matrix-matrix %! D = [1 2; 3 4]; %! A = sym(D); %! assert (isequal ( A .\ A , D .\ D )) %! assert (isequal ( A .\ D , D .\ D )) %! assert (isequal ( D .\ A , D .\ D )) %!test %! % matrix .\ matrix with symbols %! syms x y %! A = [x y; x^2 2*y]; %! B = [y x; x y]; %! assert (isequal ( A .\ A , sym(ones(2, 2)) )) %! assert (isequal ( B .\ A , [x/y y/x; x 2] )) %!test %! % scalar .\ matrix %! D = 3*[1 2; 3 4]; %! A = sym(D); %! assert (isequal ( 3 .\ A , 3 .\ D )) symbolic-3.1.1/inst/@sym/le.m0000644000000000000000000000345514405647405012706 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym le {(@var{a}, @var{b})} %% @defopx Operator @@sym {@var{a} <= @var{b}} {} %% Test/define symbolic inequality, less than or equal to. %% %% Examples: %% @example %% @group %% sym(1) <= sym(pi) %% @result{} (sym) True %% %% syms x %% x <= 10 %% @result{} (sym) x ≤ 10 %% @end group %% @end example %% %% @seealso{@@sym/lt, @@sym/gt, @@sym/ge, @@sym/eq, @@sym/ne, %% @@sym/logical, @@sym/isAlways} %% @end defop function t = le(x, y) if (nargin ~= 2) print_usage (); end t = ineq_helper('<=', 'Le', sym(x), sym(y)); end %!test %! % simple %! x = sym(1); y = sym(1); e = x <= y; %! assert (logical (e)) %! x = sym(1); y = sym(2); e = x <= y; %! assert (logical (e)) %!test %! % array -- array %! syms x %! a = sym([1 3 3 2*x]); %! b = sym([2 x 3 10]); %! e = a <= b; %! assert (isa (e, 'sym')) %! assert (logical (e(1))) %! assert (isa (e(2), 'sym')) %! assert (isequal (e(2), 3 <= x)) %! assert (logical (e(3))) %! assert (isa (e(4), 'sym')) %! assert (isequal (e(4), 2*x <= 10)) symbolic-3.1.1/inst/@sym/length.m0000644000000000000000000000257314405647405013567 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym length (@var{x}) %% Length of a symbolic vector. %% %% Example: %% @example %% @group %% syms x %% A = [1 2 x; x 3 4]; %% length(A) %% @result{} 3 %% @end group %% @end example %% %% As usual, be careful with this and matrices: you may want %% @code{numel} instead. %% %% @seealso{@@sym/numel, @@sym/size} %% @end defmethod function n = length(x) d = size(x); n = max(d); end %!test %! a = sym([1 2 3]); %! assert(length(a) == 3); %!test %! % 2D array %! a = sym([1 2 3; 4 5 6]); %! assert(length(a) == 3); %!test %! % empty %! a = sym([]); %! assert(length(a) == 0); symbolic-3.1.1/inst/@sym/lgamma.m0000644000000000000000000000243614405647405013542 0ustar %% Copyright (C) 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym gammaln (@var{x}) %% @defmethodx @@sym lgamma (@var{x}) %% Symbolic logarithm of the gamma function. %% %% Example: %% @example %% @group %% syms x %% y = gammaln(x) %% @result{} y = (sym) loggamma(x) %% y = lgamma(x) %% @result{} y = (sym) loggamma(x) %% @end group %% @end example %% %% @seealso{gammaln, @@sym/gamma, @@sym/psi} %% @end defmethod function y = lgamma(x) y = gammaln(x); end %!test %! % tested by gammaln %! assert (isequal (lgamma (sym ('x')), gammaln (sym ('x')))) symbolic-3.1.1/inst/@sym/lhs.m0000644000000000000000000000435614405647405013075 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym lhs (@var{f}) %% Left-hand side of symbolic expression. %% %% Example: %% @example %% @group %% syms x %% eqn = 5*x <= 3*x + 6 %% @result{} eqn = (sym) 5⋅x ≤ 3⋅x + 6 %% lhs(eqn) %% @result{} ans = (sym) 5⋅x %% @end group %% @end example %% %% Input @var{f} can also be a matrix: %% @example %% @group %% A = [eqn 8*x==6] %% @result{} A = (sym) [5⋅x ≤ 3⋅x + 6 8⋅x = 6] (1×2 matrix) %% lhs(A) %% @result{} ans = (sym) [5⋅x 8⋅x] (1×2 matrix) %% @end group %% @end example %% %% Gives an error if any of the symbolic objects have no left-hand side. %% %% @seealso{@@sym/rhs, @@sym/children, @@sym/formula, @@sym/argnames} %% @end defmethod function L = lhs(f) L = elementwise_op ('lambda a: a.lhs', f); end %!test %! syms x y %! f = x + 1 == 2*y; %! assert (isequal (lhs(f), x + 1)) %! assert (isequal (rhs(f), 2*y)) %!test %! syms x y %! f = x + 1 < 2*y; %! assert (isequal (lhs(f), x + 1)) %! assert (isequal (rhs(f), 2*y)) %!test %! syms x y %! f = x + 1 >= 2*y; %! assert (isequal (lhs(f), x + 1)) %! assert (isequal (rhs(f), 2*y)) %!test %! syms x y %! A = [x == y 2*x < 2*y; 3*x > 3*y 4*x <= 4*y; 5*x >= 5*y x < 0]; %! L = [x 2*x; 3*x 4*x; 5*x x]; %! R = [y 2*y; 3*y 4*y; 5*y 0]; %! assert (isequal( lhs(A), L)) %! assert (isequal( rhs(A), R)) %!error %! syms x %! lhs(x) %!error %! lhs(sym(true)) %!error %! syms x %! A = [1 + x == 2*x sym(6)]; %! lhs(A) symbolic-3.1.1/inst/@sym/limit.m0000644000000000000000000000735714405647405013431 0ustar %% Copyright (C) 2014-2016, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym limit (@var{expr}, @var{x}, @var{a}, @var{dir}) %% @defmethodx @@sym limit (@var{expr}, @var{x}, @var{a}) %% @defmethodx @@sym limit (@var{expr}, @var{a}) %% @defmethodx @@sym limit (@var{expr}) %% Evaluate symbolic limits. %% %% The limit of @var{expr} as @var{x} tends to @var{a} from %% @var{dir}. @var{dir} can be @code{left} or @code{right}. %% %% Examples: %% @example %% @group %% syms x %% L = limit(sin(x)/x, x, 0) %% @result{} L = (sym) 1 %% L = limit(1/x, x, sym(inf)) %% @result{} L = (sym) 0 %% L = limit(1/x, x, 0, 'left') %% @result{} L = (sym) -∞ %% L = limit(1/x, x, 0, 'right') %% @result{} L = (sym) ∞ %% @end group %% @end example %% %% If @var{x} is omitted, @code{symvar} is used to determine the %% variable. If @var{a} is omitted, it defaults to 0. %% %% @var{dir} defaults to @code{right}. Note this is different from %% Matlab's Symbolic Math Toolbox which returns @code{NaN} for %% @code{limit(1/x, x, 0)} %% (and @code{+/-inf} if you specify @code{left/right}). I'm not %% sure how to get this nicer behaviour from SymPy. %% FIXME: this is https://github.com/cbm755/octsympy/issues/74 %% %% @seealso{@@sym/diff} %% @end defmethod function L = limit(f, x, a, dir) if (nargin > 4 || nargin < 1) print_usage (); end f = sym(f); if (nargin < 4) dir= 'right'; end if (nargin == 2) a = x; x = symvar(f, 1); end if (nargin == 1) x = symvar(f, 1); a = 0; end switch (lower (dir)) case {'left' '-'} pdir = '-'; case {'right' '+'} pdir = '+'; otherwise print_usage (); end if (isempty (x)) L = f; return end L = elementwise_op ('lambda f, x, a, dir: f.limit(x, a, dir=dir)', ... sym(f), sym(x), sym(a), pdir); end %!error limit (sym(1), 2, 3, 4, 5) %!shared x, oo %! syms x %! oo = sym(inf); %!assert (isa (limit(x, x, pi), 'sym')) %!assert (isequal (limit(x, x, pi), sym(pi))) %!assert (isequal (limit(sin(x)/x, x, 0), 1)) %!test %! % left/right-hand limit %! assert (isequal (limit(1/x, x, 0, 'right'), oo)) %! assert (isequal (limit(1/x, x, 0), oo)) %! assert (isequal (limit(1/x, x, 0, 'left'), -oo)) %! assert (isequal (limit(1/x, x, oo), 0)) %! assert (isequal (limit(sign(x), x, 0, 'left'), -1)) %! assert (isequal (limit(sign(x), x, 0, 'right'), 1)) %! assert (isequal (limit(sign(x), x, 0, '-'), -1)) %! assert (isequal (limit(sign(x), x, 0, '+'), 1)) %!test %! % matrix %! syms y %! A = [x 1/x x*y]; %! B = sym([3 sym(1)/3 3*y]); %! assert (isequal (limit(A, x, 3), B)) %!test %! % omitting arguments %! syms a %! assert (isequal (limit(a), 0)) %! assert (isequal (limit(a*x+a+2), a+2)) %! assert (isequal (limit(a*x+a+2, 6), 7*a+2)) %!test %! % constants %! assert (isequal (limit(sym(6)), 6)) %! assert (isequal (limit(sym(6), 7), 6)) %! assert (isequal (limit([sym(6) sym(2)], 7), [6 2])) %!test %! % double constant, with sym limit %! a = limit (6, sym(0)); %! assert (isa (a, 'sym')) %! assert (isequal (a, sym(6))) symbolic-3.1.1/inst/@sym/linspace.m0000644000000000000000000000471014405647405014077 0ustar %% Copyright (C) 2015-2016, 2018 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym linspace (@var{a}, @var{b}) %% @defmethodx @@sym linspace (@var{a}, @var{b}, @var{n}) %% Return a symbolic vector of equispaced points. %% %% Examples: %% @example %% @group %% h = linspace(sym(1), sym(2), 3) %% @result{} h = (sym) [1 3/2 2] (1×3 matrix) %% h = linspace(sym(1), sym(10), 12) %% @result{} h = (sym 1×12 matrix) %% ⎡ 20 29 38 47 56 65 74 83 92 101 ⎤ %% ⎢1 ── ── ── ── ── ── ── ── ── ─── 10⎥ %% ⎣ 11 11 11 11 11 11 11 11 11 11 ⎦ %% @end group %% @end example %% %% If @var{n} is omitted, a default value is used: %% @example %% @group %% length(linspace(sym(pi)/2, sym(pi))) %% @result{} 100 %% @end group %% @end example %% %% @seealso{@@sym/logspace, @@sym/colon} %% @end defmethod function r = linspace(a, b, N) if (nargin == 2) N = 100; elseif (nargin == 3) % nop else print_usage (); end % special case, see Octave "help linspace". if (logical(N < 2)) r = b; return end a = sym(a); b = sym(b); d = (b - a) / (N-1); r = a + (sym(0):(N-1))*d; end %!test %! a = linspace(sym(3), 5, 5); %! b = [sym(6) 7 8 9 10]/2; %! assert (isequal (a, b)) %!test %! % non-integers %! A = linspace(0, sym(pi), 10); %! assert (length (A) == 10); %! assert (isequal (A(6), 5*sym(pi)/9)); %!test %! % default argument for N %! A = linspace(1, 100); %! assert (length (A) == 100); %!test %! % special case for just N = 1 %! A = linspace(sym(2), 3, 1); %! assert (isequal (A, 3)) %! A = linspace(sym(2), 3, 0); %! assert (isequal (A, 3)) %! A = linspace(sym(2), 3, sym(3)/2); %! assert (isequal (A, 3)) symbolic-3.1.1/inst/@sym/log.m0000644000000000000000000000325614405647405013066 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym log (@var{x}) %% Symbolic log function. %% %% Example: %% @example %% @group %% syms x %% y = log (x) %% @result{} y = (sym) log(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = log(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('log', x); end %!error log (sym(1), 2) %!assert (isequaln (log (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = log(x); %! f2 = log(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = log(A); %! f2 = log(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = log (d); %! f = log (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/log10.m0000644000000000000000000000272214405647405013224 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym log10 (@var{x}) %% Symbolic log base 10 function. %% %% Examples: %% @example %% @group %% log10(sym(1000)) %% @result{} ans = (sym) 3 %% %% syms x %% log10(x) %% @result{} ans = (sym) %% log(x) %% ─────── %% log(10) %% @end group %% @end example %% @seealso{@@sym/log, @@sym/log2} %% @end defmethod function z = log10(x) z = elementwise_op ('lambda x: sp.log(x, 10)', x); end %!assert (isequal (log10 (sym (1000)), sym (3))) %!assert (isequal (log10 (sym ([10 100])), sym ([1 2]))) %!test %! % round-trip %! syms x %! f = log10 (x); %! h = function_handle (f); %! A = h (1.1); %! B = log10 (1.1); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/log2.m0000644000000000000000000000272214405647405013145 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym log2 (@var{x}) %% Symbolic log base 2 function. %% %% Examples: %% @example %% @group %% log2(sym(256)) %% @result{} ans = (sym) 8 %% %% syms x %% log2(x) %% @result{} ans = (sym) %% log(x) %% ────── %% log(2) %% @end group %% @end example %% %% @seealso{@@sym/log, @@sym/log10} %% @end defmethod function z = log2(x) z = elementwise_op ('lambda x: sp.log(x, 2)', x); end %!assert (isequal (log2 (sym (1024)), sym (10))) %!assert (isequal (log2 (sym ([2 16; 32 1])), sym ([1 4; 5 0]))) %!test %! % round-trip %! syms x %! f = log2 (x); %! h = function_handle (f); %! A = h (1.1); %! B = log2 (1.1); %! assert (A, B, -5*eps) symbolic-3.1.1/inst/@sym/logical.m0000644000000000000000000001341714405647405013717 0ustar %% Copyright (C) 2014-2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym logical (@var{eq}) %% Test if expression is "structurally" true. %% %% This should probably be used with if/else flow control. %% %% Example: %% @example %% @group %% syms x y %% logical(x*(1+y) == x*(y+1)) %% @result{} 1 %% logical(x == y) %% @result{} 0 %% @end group %% @end example %% %% Note this is different from @code{isAlways} which tries to %% determine mathematical truth: %% @example %% @group %% isAlways(x*(1+y) == x+x*y) %% @result{} 1 %% logical(x*(1+y) == x+x*y) %% @result{} 0 %% @end group %% @end example %% %% Sometimes we end up with a symbolic logical values; @code{logical} %% can convert these to native logical values: %% @example %% @group %% sym(true) %% @result{} ans = (sym) True %% logical(ans) %% @result{} ans = 1 %% @end group %% @end example %% %% @code{logical} treats objects according to: %% @itemize %% @item @code{@@logical} true/false: as is. %% @item symbolic logical true/false: convert to true/false. %% @item equalities (==), unequalities (~=): check for structural %% equivalence (whether lhs and rhs match without simplifying.) %% @item numbers: true if nonzero, false if zero. %% @item nan, oo, zoo: FIXME %% @item boolean expr: And, Or: FIXME %% @item other objects raise error. %% @end itemize %% %% @seealso{@@sym/isAlways, @@sym/isequal, @@sym/eq} %% @end defmethod function r = logical(p) % do not simplify here cmd = { 'def scalar2tfn(p):' ' if p in (S.true, S.false):' ' return bool(p)' ' # ineq nothing to do, but Eq, Ne check structural eq' ' if isinstance(p, Eq):' ' r = p.lhs == p.rhs' % could not be true from Eq ctor ' return bool(r)' % none -> false ' if isinstance(p, Ne):' ' r = p.lhs != p.rhs' ' return bool(r)' ' if isinstance(p, (Lt, Gt, Le, Ge)):' ' return False' % didn't reduce in ctor, needs isAlways ' # for SMT compat' ' if p.is_number:' ' r = p.is_zero' % FIXME: return bool(r)? ' if r in (S.true, S.false):' ' return not bool(r)' ' return None' ' #return "cannot reliably convert sym \"%s\" to bool" % str(p))' }; cmd = vertcat(cmd, { '(x, unknown) = _ins' 'if x is not None and x.is_Matrix:' ' r = [a for a in x.T]' % note transpose 'else:' ' r = [x,]' 'r = [scalar2tfn(a) for a in r]' 'r = [unknown if a is None else a for a in r]' 'flag = True' 'if r.count("error") > 0:' ' flag = False' ' r = "cannot reliably convert sym to bool"' 'return (flag, r)' }); [flag, r] = pycall_sympy__ (cmd, p, 'error'); % FIXME: oo, zoo error too in SMT % ' elif p is nan:' % ' raise TE # FIXME: check SMT' if (~flag) assert (ischar (r), 'logical: programming error?') error(['logical: ' r]) end r = cell2mat(r); r = reshape(r, size(p)); end %!test %! % basics, many others in isAlways.m %! assert (logical(true)) %! assert (~(logical(false))) %!test %! % numbers to logic? %! assert (logical(sym(1))) %! assert (logical(sym(-1))) %! assert (~logical(sym(0))) %!test %! % eqns, "structurally equivalent" %! syms x %! e = logical(x == x); %! assert ( islogical (e)) %! assert (e) %! e = logical(x == 1); %! assert ( islogical (e)) %! assert (~e) %!test %! % eqn could have solutions but are false in general %! syms x %! e = logical(x^2 == x); %! assert ( islogical (e)) %! assert (~e) %! e = logical(2*x == x); %! assert ( islogical (e)) %! assert (~e) %!test %! % FIXME: (not sure yet) T/F matrices should stay sym until logical() %! a = sym(1); %! e = a == a; %! assert (isa (e, 'sym')) %! assert (islogical (logical (e))) %! e = [a == a a == 0 a == a]; %! assert (isa (e, 'sym')) %! assert (islogical (logical (e))) %!test %! % sym vectors of T/F to logical %! a = sym(1); %! e = [a == a a == 0 a == a]; %! w = logical(e); %! assert (islogical (w)) %! assert (isequal (w, [true false true])) %! e = e'; %! w = logical(e); %! assert (islogical (w)) %! assert (isequal (w, [true; false; true])) %!test %! % sym matrix of T/F to logical %! a = sym([1 2 3; 4 5 6]); %! b = sym([1 2 0; 4 0 6]); %! e = a == b; %! w = logical(e); %! assert (islogical (w)) %! assert (isequal (w, [true true false; true false true])) %!error %! syms x %! logical(x); %!error %! logical(sym(nan)) %!test %! % but oo and zoo are non-zero so we call those true %! % (SMT errors on these) FIXME %! syms oo zoo %! assert (logical (oo)) %! % assert (logical (zoo)) %%!xtest %%! % FIXME: what about positive x? %%! syms x positive %%! w = logical(x); %%! assert (w) %!test %! % older Octave (< 4.2) didn't automatically do "if (logical(obj))" %! e = sym(true); %! if (e) %! assert(true); %! else %! assert(false); %! end %!test %! % more of above %! e2 = sym(1) == sym(1); %! if (e2) %! assert(true); %! else %! assert(false); %! end %! e3 = sym([1 2]) == sym([1 1]); %! if (e3(1)) %! assert(true); %! else %! assert(false); %! end symbolic-3.1.1/inst/@sym/logint.m0000644000000000000000000000341514405647405013576 0ustar %% Copyright (C) 2016-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym logint (@var{x}) %% Symbolic logint function. %% %% Example: %% @example %% @group %% syms x %% y = logint (x) %% @result{} y = (sym) li(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = logint(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('li', x); end %!error logint (sym(1), 2) %!xtest %! assert (isequaln (logint (sym(nan)), sym(nan))) %!shared x, d %! d = 2; %! x = sym('2'); %!test %! f1 = logint(x); %! f2 = 1.045163780117492784845; %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = logint(A); %! f2 = 1.045163780117492784845; %! f2 = [f2 f2; f2 f2]; %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = logint (d); %! f = logint (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/logspace.m0000644000000000000000000000625414405647405014103 0ustar %% Copyright (C) 2015, 2016, 2018 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym logspace (@var{a}, @var{b}) %% @defmethodx @@sym logspace (@var{a}, @var{b}, @var{n}) %% Return a symbolic vector of logarithmically-spaced points. %% %% The result will be @var{n} points between @code{10^@var{a}} %% and @code{10^@var{b}}, which are equispaced on a logscale. %% %% Examples: %% @example %% @group %% logspace(sym(-2), 1, 4) %% @result{} (sym) [1/100 1/10 1 10] (1×4 matrix) %% logspace(sym(0), 3, 4) %% @result{} (sym) [1 10 100 1000] (1×4 matrix) %% @end group %% @end example %% %% If omitted, @var{n} will default to 50. A special case occurs %% if @var{b} is @code{pi}; this gives logarithmically-spaced points %% between @code{10^@var{a}} and @code{pi} instead: %% @example %% @group %% logspace(0, sym(pi), 4) %% @result{} (sym 1×4 matrix) %% ⎡ 3 ___ 2/3 ⎤ %% ⎣1 ╲╱ π π π⎦ %% @end group %% @end example %% %% @code{logspace} can be combined with @code{vpa}: %% @example %% @group %% logspace(vpa(-1), vpa(2), 5)' %% @result{} ans = (sym 5×1 matrix) %% ⎡ 0.1 ⎤ %% ⎢ ⎥ %% ⎢0.56234132519034908039495103977648⎥ %% ⎢ ⎥ %% ⎢3.1622776601683793319988935444327 ⎥ %% ⎢ ⎥ %% ⎢17.782794100389228012254211951927 ⎥ %% ⎢ ⎥ %% ⎣ 100.0 ⎦ %% @end group %% @end example %% %% @seealso{@@sym/linspace} %% @end defmethod function r = logspace(a, b, N) if (nargin == 2) N = 50; elseif (nargin == 3) % nop else print_usage (); end a = sym(a); b = sym(b); spi = sym('pi'); if (logical(b == spi)) b = log10(spi); end e = linspace(a, b, N); r = 10.^e; end %!test %! % default argument for N %! A = logspace(0, 2); %! assert (length (A) == 50); %!test %! % special case: pi as end pt %! A = logspace(-sym(3), sym(pi), 3); %! assert (isequal (A(end), sym(pi))) %!test %! A = logspace(-sym(4), 0, 3); %! B = [sym(1)/10000 sym(1)/100 sym(1)]; %! assert (isequal (A, B)) %!test %! % vpa support, might need recent sympy for sympy issue #10063 %! n = 32; %! A = logspace(-vpa(1,n), 0, 3); %! B = [10^(-vpa(1,n)) 10^(-vpa(sym(1)/2,n)) vpa(1,n)]; %! assert (isequal (A, B)) %! assert (max(abs(double(A) - logspace(-1, 0, 3))) < 1e-15) symbolic-3.1.1/inst/@sym/lt.m0000644000000000000000000001072114405647405012717 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym lt {(@var{a}, @var{b})} %% @defopx Operator @@sym {@var{a} < @var{b}} {} %% Test/define symbolic inequality, less than. %% %% Examples: %% @example %% @group %% sym(1) < sym(pi) %% @result{} (sym) True %% %% syms x real %% x < 10 %% @result{} (sym) x < 10 %% @end group %% @end example %% %% %% Note that having symbols in the expressions for @var{a} %% or @var{b} does not necessarily give an inequation: %% @example %% @group %% x < x + 2 %% @result{} (sym) True %% @end group %% @end example %% %% Assumptions can also play a role: %% @example %% @group %% syms x real %% x^2 < 0 %% @result{} (sym) False %% %% syms n negative %% syms p positive %% n < p %% @result{} (sym) True %% @end group %% @end example %% %% @seealso{@@sym/le, @@sym/gt, @@sym/ge, @@sym/eq, @@sym/ne, %% @@sym/logical, @@sym/isAlways} %% @end defop function t = lt(x, y) if (nargin ~= 2) print_usage (); end t = ineq_helper('<', 'Lt', sym(x), sym(y)); end %% Note: % in general, put tests in lt unless they are specific to % another inequality. %!test %! % simple %! x = sym(1); y = sym(1); e = x < y; %! assert (~logical (e)) %! x = sym(1); y = sym(2); e = x < y; %! assert (logical (e)) %!test %! % mix sym and double %! x = sym(1); y = 1; e = x < y; %! assert (~logical (e)) %! x = sym(1); y = 2; e = x < y; %! assert (logical (e)) %! x = 1; y = sym(1); e = x < y; %! assert (~logical (e)) %! x = 1; y = sym(2); e = x < y; %! assert (logical (e)) %!test %! % Type of the output is sym or logical? %! % FIXME: in current version, they are sym %! x = sym(1); y = sym(1); e1 = x < y; %! x = sym(1); y = sym(2); e2 = x < y; %! %assert (islogical (e1)) %! %assert (islogical (e2)) %! assert (isa (e1, 'sym')) %! assert (isa (e2, 'sym')) %!test %! % ineq w/ symbols %! syms x y %! e = x < y; %! assert (~islogical (e)) %! assert (isa (e, 'sym')) %!test %! % array -- array %! syms x %! a = sym([1 3 3 2*x]); %! b = sym([2 x 3 10]); %! e = a < b; %! assert (isa (e, 'sym')) %! assert (logical (e(1))) %! assert (isa (e(2), 'sym')) %! assert (isequal (e(2), 3 < x)) %! assert (~logical (e(3))) %! assert (isa (e(4), 'sym')) %! assert (isequal (e(4), 2*x < 10)) %!test %! % array -- scalar %! syms x oo %! a = sym([1 x oo]); %! b = sym(3); %! e = a < b; %! assert (isa (e, 'sym')) %! assert (logical (e(1))) %! assert (isa (e(2), 'sym')) %! assert (isequal (e(2), x < 3)) %! assert (~logical (e(3))) %!test %! % scalar -- array %! syms x oo %! a = sym(1); %! b = sym([2 x -oo]); %! e = a < b; %! assert (isa (e, 'sym')) %! assert (logical (e(1))) %! assert (isa (e(2), 'sym')) %! assert (isequal (e(2), 1 < x)) %! assert (~logical (e(3))) %!test %! % ineq w/ nan %! syms x %! snan = sym(nan); %! e = x < snan; %! assert (~logical (e)) %! e = snan < x; %! assert (~logical (e)) %! b = [sym(0) x]; %! e = b < snan; %! assert (isequal (e, [false false])) %!test %! % oo %! syms oo x %! e = oo < x; %! assert (isa (e, 'sym')) %! assert (strcmp (strtrim (disp (e, 'flat')), 'oo < x')) %!test %! % sympy true matrix %! a = sym([1 3 3]); %! b = sym([2 4 1]); %! e = a < b; %! %assert (~isa (e, 'sym')) %! %assert (islogical (e)) %! assert (isequal (e, [true true false])) %!test %! % oo, finite real variables %! syms oo %! syms z real %! assumeAlso(z, 'finite') %! e = -oo < z; %! assert (isequal (e, sym(true))) %! e = z < oo; %! assert (isequal (e, sym(true))) %!test %! % -oo, positive var (known failure w/ sympy 0.7.6.x) %! syms oo %! syms z positive %! e = -oo < z; %! assert (logical (e)) %! assert (isequal (e, sym(true))) %!test %! % positive %! syms z positive %! e = -1 < z; %! assert (isequal (e, sym(true))) %!test %! syms oo %! z = sym('z', 'negative'); %! e = z < oo; %! assert (isequal (e, sym(true))) symbolic-3.1.1/inst/@sym/lu.m0000644000000000000000000000730314405647405012722 0ustar %% Copyright (C) 2014-2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {[@var{L}, @var{U}] =} lu (@var{A}) %% @deftypemethodx @@sym {[@var{L}, @var{U}, @var{P}] =} lu (@var{A}) %% @deftypemethodx @@sym {[@dots{}] =} lu (@var{A}, 'vector') %% Symbolic LU factorization of a matrix. %% %% Example: %% @example %% @group %% A = sym([1 2; 3 4]); %% %% [L, U] = lu (A) %% @result{} L = (sym 2×2 matrix) %% %% ⎡1 0⎤ %% ⎢ ⎥ %% ⎣3 1⎦ %% %% @result{} U = (sym 2×2 matrix) %% %% ⎡1 2 ⎤ %% ⎢ ⎥ %% ⎣0 -2⎦ %% %% @end group %% @end example %% %% @seealso{lu, @@sym/qr} %% @end deftypemethod function [L, U, P] = lu(A, opt) if (nargin < 2) opt = 'matrix'; end assert (strcmp(opt, 'matrix') || strcmp(opt, 'vector')) cmd = { '(A, opt) = _ins' ... 'if not A.is_Matrix:' ... ' A = sp.Matrix([A])' ... '(L, U, p) = A.LUdecomposition()' ... '# convert list to P' ... 'n = L.shape[0]' ... 'if opt == "matrix":' ... ' P = sp.eye(n)' ... 'else:' ... ' P = sp.Matrix(range(1, n+1))' ... 'for w in p:' ... ' P.row_swap(*w)' ... 'return (L, U, P)' }; [L, U, P] = pycall_sympy__ (cmd, sym(A), opt); if (nargout == 2) L = P.' * L; end end %!test %! % scalar %! [l, u, p] = lu(sym(6)); %! assert (isequal (l, sym(1))) %! assert (isequal (u, sym(6))) %! assert (isequal (p, sym(1))) %! syms x %! [l, u, p] = lu(x); %! assert (isequal (l*u, p*x)) %! [l, u] = lu(x); %! assert (isequal (l*u, x)) %!test %! % perm %! A = sym(fliplr(2*eye(3))); %! [L, U, P] = lu(A); %! assert (isequal (L*U, P*A)) %! [L, U, P] = lu(A, 'matrix'); %! assert (isequal (L*U, P*A)) %! [L, U, p] = lu(A, 'vector'); %! assert (isequal (L*U, A(p,:))) %! [L, U] = lu(A); %! assert (isequal (L*U, A)) %!test %! % p is col vectpr %! A = sym([0 2; 3 4]); %! [L, U, p] = lu(A, 'vector'); %! assert(iscolumn(p)) %!test %! % simple matrix %! A = [1 2; 3 4]; %! B = sym(A); %! [L, U, P] = lu(B); %! assert (isequal (L*U, P*B)) %! assert (isequal (U(2,1), sym(0))) %! % needs pivot %! A = [0 2; 3 4]; %! B = sym(A); %! [L, U, P] = lu(B); %! [Ld, Ud, Pd] = lu(A); %! assert (isequal (L*U, P*A)) %! assert (isequal (U(2,1), sym(0))) %! % matches regular LU %! assert ( max(max(double(L)-Ld)) <= 10*eps) %! assert ( max(max(double(U)-Ud)) <= 10*eps) %! assert ( isequal (P, Pd)) %!test %! % rectangular %! A = sym([1 2; 3 4; 5 6]); %! [L, U] = lu (A); %! assert (isequal (L*U, A)) %!test %! % rectangular %! A = sym([1 2 3; 4 5 6]); %! [L, U] = lu (A); %! assert (isequal (L*U, A)) %!test %! % rectangular, repeated row %! A = sym([1 2 3; 2 4 6]); %! [L, U] = lu (A); %! assert (isequal (L*U, A)) %!test %! % rectangular, needs permutation %! A = sym([0 0 0; 1 2 3]); %! [L, U] = lu (A); %! assert (isequal (L*U, A)) %! assert (~isequal (tril (L), L)) %! [L, U, P] = lu (A); %! assert (isequal (L*U, P*A)) %! assert (isequal (tril (L), L)) symbolic-3.1.1/inst/@sym/matlabFunction.m0000644000000000000000000000252414405647405015250 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym matlabFunction (@var{f}) %% Convert symbolic expression into a standard function. %% %% This is a synonym of @code{function_handle}. For further %% documentation, @pxref{@@sym/function_handle} %% %% @seealso{@@sym/function_handle} %% %% @end defmethod function f = matlabFunction(varargin) f = function_handle(varargin{:}); end %!test %! % autodetect inputs %! syms x y %! s = warning('off', 'OctSymPy:function_handle:nocodegen'); %! h = matlabFunction(2*x*y, x+y); %! warning(s) %! [t1, t2] = h(3,5); %! assert(t1 == 30 && t2 == 8) symbolic-3.1.1/inst/@sym/max.m0000644000000000000000000000526214405647405013071 0ustar %% Copyright (C) 2015, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {} max (@var{a}) %% @deftypemethodx @@sym {} max (@var{a}, @var{b}) %% @deftypemethodx @@sym {} max (@var{a}, [], @var{dim}) %% @deftypemethodx @@sym {[@var{r}, @var{I}] =} max (@dots{}) %% Return maximum value of a symbolic vector or vectors. %% %% Example: %% @example %% @group %% max(sym(1), sym(2)) %% @result{} (sym) 2 %% max([1 2*sym(pi) 6]) %% @result{} (sym) 2⋅π %% [M, I] = max([1 2*sym(pi) 6]) %% @result{} M = (sym) 2⋅π %% @result{} I = 2 %% @end group %% @end example %% %% @seealso{@@sym/min} %% @end deftypemethod function [z, I] = max(A, B, dim) if (nargout <= 1) if (nargin == 1) if (isvector(A)) z = pycall_sympy__ ('return Max(*_ins[0])', A); else z = max(A, [], 1); end elseif (nargin == 2) z = elementwise_op ('Max', sym(A), sym(B)); elseif (nargin == 3) assert (isempty (B)) assert (logical(dim == 1) || logical(dim == 2)) cmd = { '(A, dim) = _ins' 'if not A.is_Matrix:' ' A = sp.Matrix([A])' 'if dim == 0:' ' if A.rows == 0:' ' return A' ' return Matrix([[Max(*A.col(i)) for i in range(0, A.cols)]])' 'elif dim == 1:' ' if A.cols == 0:' ' return A' ' return Matrix([Max(*A.row(i)) for i in range(0, A.rows)])' }; z = pycall_sympy__ (cmd, A, dim - 1); else print_usage (); end return end % dealing with the index (2nd output) is complicated, defer to min if (nargin == 1) [z, I] = min(-A); z = -z; elseif (nargin == 3) [z, I] = min(-A, -B, dim); z = -z; else print_usage (); end end %% many other tests are in @sym/min %!test %! % simple %! assert (isequal (max([sym(10) sym(11)]), sym(11))) %!test %! syms x y %! assert (isequal (children (max (x, y)), [x y])) symbolic-3.1.1/inst/@sym/min.m0000644000000000000000000002206614405647405013070 0ustar %% Copyright (C) 2015, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {} min (@var{a}) %% @deftypemethodx @@sym {} min (@var{a}, @var{b}) %% @deftypemethodx @@sym {} min (@var{a}, [], @var{dim}) %% @deftypemethodx @@sym {[@var{r}, @var{I}] =} min (@dots{}) %% Return minimum value of a symbolic vector or vectors. %% %% Example: %% @example %% @group %% min(sym(1), sym(2)) %% @result{} (sym) 1 %% m = min([1 sym(pi)/4 6]) %% @result{} m = (sym) %% π %% ─ %% 4 %% [m, I] = min([sym(1) 0 6]) %% @result{} m = (sym) 0 %% @result{} I = 2 %% @end group %% @end example %% %% @seealso{@@sym/max} %% @end deftypemethod function [z, I] = min(A, B, dim) if (nargout <= 1) if (nargin == 1) if (isvector(A)) z = pycall_sympy__ ('return Min(*_ins[0])', A); else z = min(A, [], 1); end elseif (nargin == 2) z = elementwise_op('Min', sym(A), sym(B)); elseif (nargin == 3) assert (isempty (B)) assert (logical(dim == 1) || logical(dim == 2)) cmd = { '(A, dim) = _ins' 'if not A.is_Matrix:' ' A = sp.Matrix([A])' 'if dim == 0:' ' if A.rows == 0:' ' return A' ' return Matrix([[Min(*A.col(i)) for i in range(0, A.cols)]])' 'elif dim == 1:' ' if A.cols == 0:' ' return A' ' return Matrix([Min(*A.row(i)) for i in range(0, A.rows)])' }; z = pycall_sympy__ (cmd, A, dim - 1); else print_usage (); end return end % We have second output: need the index of the minimum, can't use "Min" if (nargin == 1) if (isvector(A)) cmd = { 'A = _ins[0]' 'val, idx = min((val, idx) for (idx, val) in enumerate(A))' 'return val, idx+1' }; [z, I] = pycall_sympy__ (cmd, A); else [z, I] = min(A, [], 1); end elseif (nargin == 3) assert (isempty (B)) assert (logical(dim == 1) || logical(dim == 2)) cmd = { '(A, dim) = _ins' 'def myargmin(z):' ' return min((val, idx) for (idx, val) in enumerate(z))' 'if not A.is_Matrix:' ' A = sp.Matrix([A])' 'if dim == 0:' ' if (A.cols == 0):' ' return (Matrix(0, 0, []), Matrix(0, 0, []))' ' if (A.rows == 0):' ' return (A, A)' ' val_idx_pairs = [myargmin(A.col(i)) for i in range(0, A.cols)]' ' m, I = zip(*val_idx_pairs)' ' return (Matrix([m]), Matrix([I]))' 'elif dim == 1:' ' if (A.rows == 0):' ' return (Matrix(0,0,[]), Matrix(0,0,[]))' ' if (A.cols == 0):' ' return (A, A)' ' val_idx_pairs = [myargmin(A.row(i)) for i in range(0, A.rows)]' ' m, I = zip(*val_idx_pairs)' ' return (Matrix(m), Matrix(I))' }; [z, I] = pycall_sympy__ (cmd, A, dim - 1); I = double(I); if (~isempty(I)) I = I + 1; end else print_usage (); end end %!test %! % scalars with dim %! a = min(sym(pi), [], 1); %! b = sym(pi); %! assert (isequal (a, b)); %! a = min(sym(pi), [], 2); %! assert (isequal (a, b)); %! a = max(sym(pi), [], 1); %! assert (isequal (a, b)); %! a = max(sym(pi), [], 2); %! assert (isequal (a, b)); %!shared A, D %! D = [0 1 2 3]; %! A = sym(D); %!test %! % row vectors %! assert (isequal (min(A), sym(min(D)))) %! assert (isequal (min(A), sym(0))) %! assert (isequal (max(A), sym(max(D)))) %! assert (isequal (max(A), sym(3))) %!test %! % row vectors with dim %! assert (isequal (min(A, [], 1), sym(min(D, [], 1)))) %! assert (isequal (min(A, [], 2), sym(min(D, [], 2)))) %! assert (isequal (max(A, [], 1), sym(max(D, [], 1)))) %! assert (isequal (max(A, [], 2), sym(max(D, [], 2)))) %!test %! % column vectors %! A = A.'; %! D = D.'; %! assert (isequal (min(A), sym(min(D)))) %! assert (isequal (min(A), sym(0))) %! assert (isequal (max(A), sym(max(D)))) %! assert (isequal (max(A), sym(3))) %!test %! % row vectors with dim %! assert (isequal (min(A, [], 1), sym(min(D, [], 1)))) %! assert (isequal (min(A, [], 2), sym(min(D, [], 2)))) %! assert (isequal (max(A, [], 1), sym(max(D, [], 1)))) %! assert (isequal (max(A, [], 2), sym(max(D, [], 2)))) %!shared %!test %! % empty %! a = min(sym([])); %! assert(isempty(a)) %! a = max(sym([])); %! assert(isempty(a)) %!test %! % matrix %! A = [1 4 6; 2 2 5]; %! A = sym(A); %! assert (isequal (min(A), sym([1 2 5]))) %! assert (isequal (min(A, [], 1), sym([1 2 5]))) %! assert (isequal (min(A, [], 2), sym([1; 2]))) %! assert (isequal (max(A), sym([2 4 6]))) %! assert (isequal (max(A, [], 1), sym([2 4 6]))) %! assert (isequal (max(A, [], 2), sym([6; 5]))) %!test %! % index output is double not sym %! [m, I] = min(sym(2), [], 1); %! assert (strcmp(class(I), 'double')) %! [m, I] = max(sym(2), [], 1); %! assert (strcmp(class(I), 'double')) %!test %! % empty rows/columns, I is double %! A = sym(zeros(0, 4)); %! [m, I] = min(A, [], 1); %! assert (strcmp(class(I), 'double')) %! [m, I] = max(A, [], 1); %! assert (strcmp(class(I), 'double')) %! A = sym(zeros(3, 0)); %! [m, I] = min(A, [], 2); %! assert (strcmp(class(I), 'double')) %! [m, I] = max(A, [], 2); %! assert (strcmp(class(I), 'double')) %!test %! % index output %! A = [0 1 9; 10 7 4]; %! B = sym(A); %! [m1, I1] = min(A); %! [m2, I2] = min(B); %! assert (isequal (I1, I2)) %! assert (isequal (m1, double(m2))) %! [m1, I1] = max(A); %! [m2, I2] = max(B); %! assert (isequal (I1, I2)) %! assert (isequal (m1, double(m2))) %!test %! % index output, with dim %! A = [0 1 9; 10 7 4]; %! B = sym(A); %! [m1, I1] = min(A, [], 1); %! [m2, I2] = min(B, [], 1); %! assert (isequal (I1, I2)) %! assert (isequal (m1, double(m2))) %! [m1, I1] = min(A, [], 2); %! [m2, I2] = min(B, [], 2); %! assert (isequal (I1, I2)) %! assert (isequal (m1, double(m2))) %! [m1, I1] = max(A, [], 1); %! [m2, I2] = max(B, [], 1); %! assert (isequal (I1, I2)) %! assert (isequal (m1, double(m2))) %! [m1, I1] = max(A, [], 2); %! [m2, I2] = max(B, [], 2); %! assert (isequal (I1, I2)) %! assert (isequal (m1, double(m2))) %!test %! % empty columns %! A = sym(zeros(0, 4)); %! [m, I] = min(A, [], 1); %! assert (isequal (size(m), [0 4])) %! assert (isequal (size(I), [0 4])) %! [m, I] = max(A, [], 1); %! assert (isequal (size(m), [0 4])) %! assert (isequal (size(I), [0 4])) %!test %! % empty rows %! A = sym(zeros(3, 0)); %! [m, I] = min(A, [], 2); %! assert (isequal (size(m), [3 0])) %! assert (isequal (size(I), [3 0])) %! [m, I] = max(A, [], 2); %! assert (isequal (size(m), [3 0])) %! assert (isequal (size(I), [3 0])) %!test %! % another empty case %! % we differ slightly from double which gives 1x0/0x1 %! A = sym(zeros(3, 0)); %! [m, I] = min(A, [], 1); %! assert (isempty (m)) %! assert (isempty (I)) %! A = sym(zeros(0, 3)); %! [m, I] = min(A, [], 2); %! assert (isempty (m)) %! assert (isempty (I)) %!test %! % empty without index output %! A = sym(zeros(3, 0)); %! assert (isempty (min (A, [], 1))) %! assert (isempty (max (A, [], 1))) %! assert (isempty (min (A, [], 2))) %! assert (isempty (max (A, [], 2))) %! A = sym(zeros(0, 3)); %! assert (isempty (min (A, [], 1))) %! assert (isempty (max (A, [], 1))) %! assert (isempty (min (A, [], 2))) %! assert (isempty (max (A, [], 2))) %!test %! % binary op form, one a scalar %! A = sym([3 1 9]); %! m = min(A, sym(2)); %! M = max(A, sym(2)); %! assert (isequal (m, sym([2 1 2]))) %! assert (isequal (M, sym([3 2 9]))) %! m = min(sym(2), A); %! M = max(sym(2), A); %! assert (isequal (m, sym([2 1 2]))) %! assert (isequal (M, sym([3 2 9]))) %!test %! % binary op form, both scalar %! m = min(sym(1), sym(2)); %! M = max(sym(2), sym(2)); %! assert (isequal (m, sym(1))) %! assert (isequal (M, sym(2))) %!test %! syms x y %! assert (isequal (children (min (x, y)), [x y])) %!test %! syms x y z %! A = [x 1; y z]; %! assert (isequal (min (A, [], 1), [min(x, y) min(1, z)])) %! assert (isequal (max (A, [], 1), [max(x, y) max(1, z)])) %! assert (isequal (min (A, [], 2), [min(x, 1); min(y, z)])) %! assert (isequal (max (A, [], 2), [max(x, 1); max(y, z)])) %!test %! syms x y positive %! a = min([x 2 y -6]); %! assert (isequal (a, -6)) %! a = max([x y -6]); %! assert (isequal (a, max(x, y))) %!test %! syms x negative %! a = min([x 6 10]); %! assert (isequal (a, x)) %! a = max([x -2 6]); %! assert (isequal (a, 6)) symbolic-3.1.1/inst/@sym/minus.m0000644000000000000000000000351614405647405013437 0ustar %% Copyright (C) 2014, 2016, 2018-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym minus {(@var{x}, @var{y})} %% @defopx Operator @@sym {@var{x} - @var{y}} {} %% Subtract one symbolic expression from another. %% %% Example: %% @example %% @group %% syms x y %% x - y %% @result{} (sym) x - y %% @end group %% @end example %% @end defop function z = minus(x, y) cmd = { 'x, y = _ins' 'if x is None or y is None:' ' return x - y' 'if x.is_Matrix and not y.is_Matrix:' ' return x - y*sp.ones(*x.shape),' 'if not x.is_Matrix and y.is_Matrix:' ' return x*sp.ones(*y.shape) - y,' 'return x - y' }; z = pycall_sympy__ (cmd, sym(x), sym(y)); end %!test %! % scalar %! syms x %! assert (isa (x-1, 'sym')) %! assert (isa (x-x, 'sym')) %! assert (isequal (x-x, sym(0))) %!test %! % matrices %! D = [0 1; 2 3]; %! A = sym(D); %! DZ = D - D; %! assert (isequal ( A - D , DZ )) %! assert (isequal ( A - A , DZ )) %! assert (isequal ( D - A , DZ )) %! assert (isequal ( A - 2 , D - 2 )) %! assert (isequal ( 4 - A , 4 - D )) symbolic-3.1.1/inst/@sym/mldivide.m0000644000000000000000000001040714405647405014076 0ustar %% Copyright (C) 2014, 2016, 2018-2019, 2022 Colin B. Macdonald %% Copyright (C) 2022 Alex Vong %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym mldivide {(@var{A}, @var{b})} %% @defopx Operator @@sym {@var{A} \ @var{b}} {} %% Symbolic backslash: solve symbolic linear systems. %% %% This operator tries to broadly match the behaviour of the %% backslash operator for double matrices. %% For scalars, this is just division: %% @example %% @group %% sym(2) \ 1 %% @result{} ans = (sym) 1/2 %% @end group %% @end example %% %% But for matrices, it solves linear systems %% @example %% @group %% A = sym([1 2; 3 4]); %% b = sym([5; 11]); %% x = A \ b %% @result{} x = (sym 2×1 matrix) %% ⎡1⎤ %% ⎢ ⎥ %% ⎣2⎦ %% A*x == b %% @result{} ans = (sym 2×1 matrix) %% ⎡True⎤ %% ⎢ ⎥ %% ⎣True⎦ %% @end group %% @end example %% %% Over- and under-determined systems are supported: %% @example %% @group %% A = sym([5 2]); %% x = A \ 10 %% @result{} x = (sym 2×1 matrix) %% ⎡ 2⋅c₁⎤ %% ⎢2 - ────⎥ %% ⎢ 5 ⎥ %% ⎢ ⎥ %% ⎣ c₁ ⎦ %% A*x == 10 %% @result{} ans = (sym) True %% @end group %% @group %% A = sym([1 2; 3 4; 9 12]); %% b = sym([5; 11; 33]); %% x = A \ b %% @result{} x = (sym 2×1 matrix) %% ⎡1⎤ %% ⎢ ⎥ %% ⎣2⎦ %% A*x - b %% @result{} ans = (sym 3×1 matrix) %% ⎡0⎤ %% ⎢ ⎥ %% ⎢0⎥ %% ⎢ ⎥ %% ⎣0⎦ %% @end group %% @end example %% @seealso{@@sym/ldivide, @@sym/mrdivide} %% @end defop function x = mldivide(A, b) % not for singular %'ans = A.LUsolve(b)' if (isscalar(A)) x = A .\ b; return end cmd = { '(A, B) = _ins' 'flag = 0' 'if not A.is_Matrix:' ' A = sympy.Matrix([A])' 'if not B.is_Matrix:' ' B = sympy.Matrix([B])' 'if any([y.is_Float for y in A]) or any([y.is_Float for y in B]):' ' flag = 1' 'M = A.cols' 'Z = sympy.zeros(M, B.cols)' 'for k in range(0, B.cols):' ' b = B.col(k)' ' x = [Symbol("c%d" % (j + k*M)) for j in range(0, M)]' ' AA = A.hstack(A, b)' ' d = solve_linear_system(AA, *x)' ' if d is None:' ' Z[:, k] = sympy.Matrix([S.NaN]*M)' ' else:' ' # apply dict' ' Z[:, k] = sympy.Matrix([d.get(c, c) for c in x])' 'return (flag, Z)' }; [flag, x] = pycall_sympy__ (cmd, sym(A), sym(b)); if (flag ~= 0) warning('octsympy:backslash:vpa', ... 'vpa backslash may not match double backslash') end end %!test %! % scalar %! syms x %! assert (isa( x\x, 'sym')) %! assert (isequal( x\x, sym(1))) %! assert (isa( 2\x, 'sym')) %! assert (isa( x\2, 'sym')) %!test %! % scalar \ matrix: easy, no system %! D = 2*[0 1; 2 3]; %! A = sym(D); %! assert (isequal ( 2 \ A , D/2 )) %! assert (isequal ( sym(2) \ A , D/2 )) %!test %! % singular matrix %! A = sym([1 2; 2 4]); %! b = sym([5; 10]); %! x = A \ b; %! syms c1 %! y = [-2*c1 + 5; c1]; %! assert (isequal (x, y)) %!test %! % singular matrix, mult RHS %! A = sym([1 2; 2 4]); %! B = sym([[5; 10] [0; 2] [0; 0]]); %! x = A \ B; %! syms c1 c5 %! y = [-2*c1 + 5 nan -2*c5; c1 nan c5]; %! assert (isequaln (x, y)) %!warning %! % vpa, nearly singular matrix %! A = sym([1 2; 2 4]); %! A(1,1) = vpa('1.001'); %! b = sym([1; 2]); %! x = A \ b; %! y = [sym(0); vpa('0.5')]; %! assert (isequal (x, y)) %!warning %! % vpa, singular rhs %! A = sym([1 2; 2 4]); %! b = [vpa('1.01'); vpa('2')]; %! x = A \ b; %! assert (all(isnan(x))) symbolic-3.1.1/inst/@sym/mod.m0000644000000000000000000000707314405647405013065 0ustar %% Copyright (C) 2014-2016, 2018, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym mod (@var{x}, @var{n}) %% @defmethodx @@sym mod (@var{x}, @var{n}, false) %% Element-wise modular arithmetic on symbolic arrays and polynomials. %% %% Example: %% @example %% @group %% mod([10 3 1], sym(3)) %% @result{} ans = (sym) [1 0 1] (1×3 matrix) %% @end group %% @end example %% %% If any of the entries contain variables, we assume they are %% univariate polynomials and convert their coefficients to mod %% @var{n}: %% @example %% @group %% syms x %% mod(5*x + 7, 3) %% @result{} (sym) 2⋅x + 1 %% mod(x, 3) % (coefficient is 1 mod 3) %% @result{} (sym) x %% @end group %% @end example %% You can disable this behaviour by passing @code{false} as the %% third argument: %% @example %% @group %% q = mod(x, 3, false) %% @result{} q = (sym) x mod 3 %% subs(q, x, 10) %% @result{} ans = (sym) 1 %% %% syms n integer %% mod(3*n + 2, 3, false) %% @result{} (sym) 2 %% @end group %% @end example %% %% @seealso{@@sym/coeffs} %% @end defmethod function z = mod(x, n, canpoly) if (nargin > 3) print_usage (); end if (nargin < 3) canpoly = true; end isconst = isempty (findsymbols (x)); if (~canpoly || isconst) z = elementwise_op ('lambda a,b: a % b', sym(x), sym(n)); else %% its not constant, assume everything is poly and mod the coefficients z = x; for i = 1:numel(x) % t = x(i) idx.type = '()'; idx.subs = {i}; t = subsref (x, idx); if (isscalar(n)) m = n; else m = subsref (n, idx); % m = n(i) end sv = symvar(t, 1); % Note: sympy Polys have a .termwise: would that be easier? [c, t] = coeffs(t, sv); c = mod(c, m, false); % force no poly here rhs = t * c.'; % recombine the new poly z = subsasgn(z, idx, rhs); %z(i) = rhs; end end end %!error mod (sym(1), 2, 3 ,4) %!assert (isequal (mod (sym(5), 4), sym(1))) %!assert (isequal (mod ([sym(5) 8], 4), [1 0] )) %!assert (isequal (mod (sym(5), [2 3]), [1 2] )) %!assert (isequal (mod ([sym(5) sym(6)], [2 3]), [1 0] )) %!test %! syms x %! assert (isequal ( mod (5*x, 3), 2*x )) %!test %! syms x %! a = [7*x^2 + 3*x + 3 3*x; 13*x^4 6*x]; %! assert (isequal ( mod (a,3), [x^2 0; x^4 0] )) %!test %! % vector of polys with mix of vars: symvar on each %! syms x y %! a = [6*x 7*y]; %! b = mod(a, 4); %! c = [2*x 3*y]; %! assert (isequal (b, c)) %!test %! % coeff has variable %! syms x %! n = sym('n', 'integer'); %! p = (3*n + 2)*x; %! q = mod(p, 3); %! assert (isequal (q, 2*x)) %!test %! % coeff has variable %! syms x a %! p = a*x; %! q = mod(p, 3); %! q = children(q); %! q = q(2); % order might be fragile! %! w = subs(q, a, 5); %! assert (isequal (w, 2)) %!test %! % different modulo %! syms x y %! q = mod([5*x + 10 5*y + 10], [2 3]); %! assert (isequal (q, [x 2*y + 1])) symbolic-3.1.1/inst/@sym/mpower.m0000644000000000000000000000654014405647405013615 0ustar %% Copyright (C) 2014, 2016, 2018-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym mpower {(@var{x}, @var{y})} %% @defopx Operator @@sym {@var{x} ^ @var{y}} {} %% Symbolic expression matrix exponentiation. %% %% Scalar example: %% @example %% @group %% syms x %% sym('x')^3 %% @result{} ans = (sym) %% 3 %% x %% @end group %% @end example %% %% The @code{^} notation is use to raise a matrix to a scalar power: %% @example %% @group %% A = [sym(pi) 2; 0 x] %% @result{} A = (sym 2×2 matrix) %% ⎡π 2⎤ %% ⎢ ⎥ %% ⎣0 x⎦ %% A^2 %% @result{} (sym 2×2 matrix) %% ⎡ 2 ⎤ %% ⎢π 2⋅x + 2⋅π⎥ %% ⎢ ⎥ %% ⎢ 2 ⎥ %% ⎣0 x ⎦ %% A^2 == A*A %% @result{} (sym 2×2 matrix) %% ⎡True True⎤ %% ⎢ ⎥ %% ⎣True True⎦ %% @end group %% @end example %% %% Using this for scalar raised to a matrix power is not yet supported. %% %% @seealso{@@sym/power} %% @end defop function z = mpower(x, y) cmd = { 'x, y = _ins' 'return x**y' }; z = pycall_sympy__ (cmd, sym(x), sym(y)); end %!test %! syms x %! assert(isequal(x^(sym(4)/5), x.^(sym(4)/5))) %!test %! % integer powers of scalars %! syms x %! assert (isequal (x^2, x*x)) %! assert (isequal (x^sym(3), x*x*x)) %!test %! % array ^ integer %! syms x y %! A = [x 2; y 4]; %! assert (isequal (A^2, A*A)) %! assert (isequal (simplify(A^3 - A*A*A), [0 0; 0 0])) %!test %! % array ^ rational %! Ad = [1 2; 0 3]; %! A = sym(Ad); %! B = A^(sym(1)/3); %! Bd = Ad^(1/3); %! assert (max(max(abs(double(B) - Bd))) < 1e-14) %!test %! % non-integer power %! A = sym([1 2; 0 3]); %! B = A^pi; %! C = [1 -1+3^sym(pi); 0 sym(3)^pi]; %! assert (isequal (B, C)) %!test %! % matpow %! syms n %! A = sym([1 2; 3 4]); %! B = A^n; %! C = 10 + B + B^2; %! D = subs(C, n, 1); %! E = 10 + A + A^2; %! assert (isequal (simplify(D), simplify(E))) %!test %! % matpow, sub in zero gives identity %! A = sym([1 2; 0 3]); %! syms n; %! B = A^n; %! C = subs(B, n, 1); %! assert (isequal (C, A)) %! C = subs(B, n, 0); %! assert (isequal (C, sym(eye(2)))) %!xtest %! % scalar^array (e.g., defined by matrix exponential) not implemented in SymPy? %! % on 1.0 < SymPy <= 1.5.1, you can form the expression but still cannot eval %! syms x %! A = [1 2; 3 4]; %! B = x^A; %! assert (strcmp (regexprep (disp (B, 'flat'), '\s+', ''), 'x**Matrix([[1,2],[3,4]])')) %! % sub in and compare to double %! Bs = subs(B, x, sym(3)/2); %! D1 = double(Bs); %! D2 = (3/2)^[1 2; 3 4]; %! assert (max(max(abs(D1 - D2))) < 1e-14) %!error %! A = sym([1 2; 3 4]); %! B = A^A; symbolic-3.1.1/inst/@sym/mrdivide.m0000644000000000000000000000613714405647405014111 0ustar %% Copyright (C) 2014, 2016, 2018-2019, 2022 Colin B. Macdonald %% Copyright (C) 2022 Chris Gorman %% Copyright (C) 2022 Alex Vong %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym mrdivide {(@var{x}, @var{y})} %% @defopx Operator @@sym {@var{x} / @var{y}} {} %% Forward slash division of symbolic expressions. %% %% Example: %% @example %% @group %% A = sym([1 pi; 3 4]) %% @result{} A = (sym 2×2 matrix) %% ⎡1 π⎤ %% ⎢ ⎥ %% ⎣3 4⎦ %% A / 2 %% @result{} ans = (sym 2×2 matrix) %% ⎡ π⎤ %% ⎢1/2 ─⎥ %% ⎢ 2⎥ %% ⎢ ⎥ %% ⎣3/2 2⎦ %% @end group %% @end example %% %% The forward slash notation can be used to solve systems %% of the form A⋅B = C using @code{A = C / B}: %% @example %% @group %% B = sym([1 0; 1 2]); %% C = A*B %% @result{} C = (sym 2×2 matrix) %% ⎡1 + π 2⋅π⎤ %% ⎢ ⎥ %% ⎣ 7 8 ⎦ %% C / B %% @result{} ans = (sym 2×2 matrix) %% ⎡1 π⎤ %% ⎢ ⎥ %% ⎣3 4⎦ %% C * inv(B) %% @result{} ans = (sym 2×2 matrix) %% ⎡1 π⎤ %% ⎢ ⎥ %% ⎣3 4⎦ %% @end group %% @end example %% @seealso{@@sym/rdivide, @@sym/mldivide} %% @end defop function z = mrdivide(x, y) z = (y.' \ x.').'; end %!test %! % scalar %! syms x %! assert (isa( x/x, 'sym')) %! assert (isequal( x/x, sym(1))) %! assert (isa( 2/x, 'sym')) %! assert (isa( x/2, 'sym')) %!test %! % matrix / scalar %! D = 2*[0 1; 2 3]; %! A = sym(D); %! assert (isequal ( A/2 , D/2 )) %! assert (isequal ( A/sym(2) , D/2 )) %!test %! % I/A: either invert A or leave unevaluated: not bothered which %! A = sym([1 2; 3 4]); %! B = sym(eye(2)) / A; %! assert (isequal (B, inv(A)) || strncmpi (sympy (B), 'MatPow', 6)) %!xtest %! % immutable test, upstream: TODO %! A = sym([1 2; 3 4]); %! B = sym('ImmutableDenseMatrix([[Integer(1), Integer(2)], [Integer(3), Integer(4)]])'); %! assert (isequal (A/A, B/B)) %!test %! % A = C/B is C = A*B %! A = sym([1 2; 3 4]); %! B = sym([1 3; 4 8]); %! C = A*B; %! A2 = C / B; %! assert (isequal (A, A2)) %!test %! A = [1 2; 3 4]; %! B = A / A; %! % assert (isequal (B, sym(eye(2)) %! assert (isequal (B(1,1), 1)) %! assert (isequal (B(2,2), 1)) %! assert (isequal (B(2,1), 0)) %! assert (isequal (B(1,2), 0)) %!test %! A = sym([5 6]); %! B = sym([1 2; 3 4]); %! C = A*B; %! A2 = C / B; %! assert (isequal (A, A2)) symbolic-3.1.1/inst/@sym/mtimes.m0000644000000000000000000000363114405647405013600 0ustar %% Copyright (C) 2014, 2016, 2018-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym mtimes {(@var{x}, @var{y})} %% @defopx Operator @@sym {@var{x} * @var{y}} {} %% Multiply symbolic matrices. %% %% Example: %% @example %% @group %% syms x y %% A = sym([1 2; 3 4]) %% @result{} A = (sym 2×2 matrix) %% ⎡1 2⎤ %% ⎢ ⎥ %% ⎣3 4⎦ %% B = [x; y] %% @result{} B = (sym 2×1 matrix) %% ⎡x⎤ %% ⎢ ⎥ %% ⎣y⎦ %% A * B %% @result{} (sym 2×1 matrix) %% ⎡ x + 2⋅y ⎤ %% ⎢ ⎥ %% ⎣3⋅x + 4⋅y⎦ %% @end group %% @end example %% @end defop function z = mtimes(x, y) cmd = { '(x,y) = _ins' 'return x*y,' }; z = pycall_sympy__ (cmd, sym(x), sym(y)); end %!test %! % scalar %! syms x %! assert (isa (x*2, 'sym')) %! assert (isequal (2*sym(3), sym(6))) %! assert (isequal (sym(2)*3, sym(6))) %!test %! % matrix-scalar %! D = [0 1; 2 3]; %! A = sym(D); %! assert (isa (2*A, 'sym')) %! assert (isequal ( 2*A , 2*D )) %! assert (isequal ( A*2 , 2*D )) %!test %! % matrix-matrix %! D = [0 1; 2 3]; %! A = sym(D); %! assert (isa (A*A, 'sym')) %! assert (isequal ( A*A , D*D )) symbolic-3.1.1/inst/@sym/nchoosek.m0000644000000000000000000000674514405647405014124 0ustar %% Copyright (C) 2015-2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym nchoosek (@var{n}, @var{k}) %% Symbolic binomial coefficient. %% %% Examples: %% @example %% @group %% syms n k %% nchoosek(n, k) %% @result{} ans = (sym) %% ⎛n⎞ %% ⎜ ⎟ %% ⎝k⎠ %% %% nchoosek(101, k) %% @result{} ans = (sym) %% ⎛101⎞ %% ⎜ ⎟ %% ⎝ k ⎠ %% %% nchoosek(sym(1001), sym(25)) %% @result{} (sym) 48862197129890117991367706991027565961778719519790 %% @end group %% @end example %% %% The binomial coefficient can be written in terms of factorials: %% @example %% @group %% rewrite (nchoosek (n, k), 'factorial') %% @result{} ans = (sym) %% n! %% ──────────── %% k!⋅(-k + n)! %% @end group %% @end example %% %% For inputs which are not positive integers (including complex numbers), %% the result is defined in terms of the @code{gamma} function: %% @example %% @group %% rewrite (nchoosek (n, k), 'gamma') %% @result{} (sym) %% Γ(n + 1) %% ────────────────────── %% Γ(k + 1)⋅Γ(-k + n + 1) %% @end group %% @end example %%% %% For example: %% @example %% @group %% nchoosek (-sym(3), sym(2)) %% @result{} (sym) 6 %% nchoosek (sym(5)/2, sym(3)) %% @result{} (sym) 5/16 %% nchoosek (3+4i, sym(2)) %% @result{} (sym) -5 + 10⋅ⅈ %% @end group %% @end example %% @seealso{@@sym/factorial, @@sym/gamma} %% @end defmethod function C = nchoosek(n, k) if (~isscalar(n)) error('nchoosek: set input for n not implemented'); end assert (isscalar(k), 'nchoosek: k must be scalar'); C = pycall_sympy__ ('return sp.binomial(*_ins),', sym(n), sym(k)); end %!assert (isequal (nchoosek(sym(5), sym(2)), sym(10))) %!assert (isequal (nchoosek(sym(5), 2), sym(10))) %!assert (isequal (nchoosek(5, sym(2)), sym(10))) %!assert (isequal (nchoosek(sym(10), 0), 1)) %!assert (isequal (nchoosek(sym(10), -1), 0)) %!test %! n = sym('n', 'nonnegative', 'integer'); %! assert (isequal (nchoosek (n, n), sym(1))) %!test %! n = sym('n', 'integer'); %! q = nchoosek(n, 2); %! w = subs(q, n, 5); %! assert (isequal (w, 10)) %!test %! n = sym('n', 'integer'); %! k = sym('k', 'integer'); %! q = nchoosek(n, k); %! w = subs(q, {n k}, {5 2}); %! assert (isequal (w, 10)) %!test %! % negative input %! assert (isequal (nchoosek (sym(-2), sym(5)), sym(-6))) %!test %! % complex input %! n = sym(1 + 3i); %! k = sym(5); %! A = nchoosek (n, k); %! B = gamma (n + 1) / (gamma (k + 1) * gamma (n - k + 1)); %! assert (double (A), double (B), -2*eps) %!test %! % complex input %! n = sym(-2 + 3i); %! k = sym(1 + i); %! A = nchoosek (n, k); %! B = gamma (n + 1) / (gamma (k + 1) * gamma (n - k + 1)); %! assert (double (A), double (B), -2*eps) symbolic-3.1.1/inst/@sym/ne.m0000644000000000000000000000450014405647405012700 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym ne {(@var{a}, @var{b})} %% @defopx Operator @@sym {@var{a} ~= @var{b}} {} %% @defopx Operator @@sym {@var{a} != @var{b}} {} %% Test/define symbolic inequality, not equal to. %% %% Examples: %% @example %% @group %% syms x y %% x ~= y %% @result{} ans = (sym) x ≠ y %% @end group %% %% @group %% sym(1) ~= sym(pi) %% @result{} ans = (sym) True %% @end group %% @end example %% %% @seealso{@@sym/eq, @@sym/lt, @@sym/le, @@sym/gt, @@sym/ge, %% @@sym/logical, @@sym/isAlways, @@sym/isequal} %% @end defop function t = ne(x, y) % nanspecial is (python) 'True' here b/c nan is not equal % to everything, even itself. t = ineq_helper('[donotuse]', 'Ne', sym(x), sym(y), 'S.true'); end %!test %! % simple %! x = sym(1); y = sym(1); e = x ~= y; %! assert (~logical (e)) %! x = sym(1); y = sym(2); e = x ~= y; %! assert (logical(e)) %!test %! % array -- array %! syms x %! a = sym([1 3 3 2*x]); %! b = sym([2 x 3 10]); %! e = a ~= b; %! assert (isa (e, 'sym')) %! assert (logical (e(1))) %! assert (isa (e(2), 'sym')) %! assert (isequal (e(2), 3 ~= x)) %! assert (~logical (e(3))) %! assert (isa (e(4), 'sym')) %! assert (isequal (e(4), 2*x ~= 10)) %!test %! % oo %! syms oo x %! e = oo ~= x; %! assert (isa (e, 'sym')) %! s = strtrim (disp (e, 'flat')); %! % SymPy <= 0.7.6.x will be '!=', newer gives 'Ne', test both %! assert (strcmp (s, 'oo != x') || strcmp (s, 'Ne(oo, x)')) %!test %! % nan %! syms oo x %! snan = sym(nan); %! e = snan ~= sym(0); %! assert (logical (e)) %! e = snan ~= snan; %! assert (logical (e)) symbolic-3.1.1/inst/@sym/nextprime.m0000644000000000000000000000312114405647405014307 0ustar %% Copyright (C) 2015, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym nextprime (@var{x}) %% Return the next prime number. %% %% Example: %% @example %% @group %% nextprime(sym(2)) %% @result{} ans = (sym) 3 % %% nextprime([sym(2) 10 0 -1 65530]) %% @result{} (sym) [3 11 2 2 65537] (1×5 matrix) %% @end group %% @end example %% %% @seealso{@@sym/isprime, @@sym/prevprime} %% @end defmethod function y = nextprime(x) %y = elementwise_op ('nextprime', x); % workaround as upstream SymPy returns int, not sym y = elementwise_op ('lambda a: S(nextprime(a))', x); end %!assert (isequal (nextprime(sym(2)), 3)); %!assert (isequal (nextprime(sym(18)), 19)); %!assert (isequal (nextprime(sym([1 2 3])), [2 3 5])); %!assert (isequal (nextprime(sym([-1 0])), [2 2])); %!test %! % result is a sym %! p = nextprime(sym(2)); %! assert (isa (p, 'sym')) symbolic-3.1.1/inst/@sym/nnz.m0000644000000000000000000000362714405647405013114 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym nnz (@var{A}) %% Number of non-zero elements in the symbolic array. %% %% Example: %% @example %% @group %% A = sym([1 0 0; 0 1 0]); %% nnz(A) %% @result{} ans = 2 %% @end group %% @end example %% %% @seealso{@@sym/numel} %% @end defmethod function n = nnz(A) % some future-proofing here for supporting symbolic sparse matrices % but what is SparseMatrix has bools in it? cmd = { 'def scalar2tf(a):' ' if a in (S.true, S.false):' ' return bool(a)' %' if a is S.NaN:' %' return True' ' return a != 0' 'A = _ins[0]' 'if not A.is_Matrix:' ' A = sp.Matrix([A])' 'try:' ' n = A.nnz()' 'except AttributeError:' ' n = sum([scalar2tf(a) for a in A])' 'return n,' }; n = pycall_sympy__ (cmd, A); end %!assert (nnz (sym ([1])) == 1) %!assert (nnz (sym ([0])) == 0) %!assert (nnz (sym ([])) == 0) %!assert (nnz (sym ([1 0; 0 3])) == 2) %!test %! syms x %! assert (nnz ([x 0]) == 1) %!assert (nnz (sym (true)) == 1) %!assert (nnz (sym (false)) == 0) %!assert (nnz (sym (inf)) == 1) %!assert (nnz (sym (nan)) == 1) symbolic-3.1.1/inst/@sym/norm.m0000644000000000000000000000533214405647405013255 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym norm (@var{A}) %% @defmethodx @@sym norm (@var{v}) %% @defmethodx @@sym norm (@var{A}, @var{ord}) %% Symbolic vector/matrix norm. %% %% The first argument can either be a matrix @var{A} or a %% matrix @var{v}. %% The second argument @var{ord} defaults to 2. %% %% Matrix example: %% @example %% @group %% A = sym([8 1 6; 3 5 7; 4 9 2]); %% norm (A) %% @result{} (sym) 15 %% norm (A, 2) %% @result{} (sym) 15 %% norm (A, 'fro') %% @result{} (sym) √285 %% @end group %% @end example %% %% Vector example: %% @example %% @group %% syms a positive %% v = sym([1; a; 2]); %% norm (v) %% @result{} (sym) %% ________ %% ╱ 2 %% ╲╱ a + 5 %% %% norm (v, 1) %% @result{} (sym) a + 3 %% norm (v, inf) %% @result{} (sym) Max(2, a) %% @end group %% @end example %% %% @seealso{@@sym/svd} %% @end defmethod function z = norm(x, ord) if (nargin < 2) ord = 'meh'; line1 = 'x = _ins[0]; ord = 2'; else line1 = '(x,ord) = _ins'; end if (ischar(ord)) if (~strcmp(ord, 'fro') && ~strcmp(ord, 'meh')) error('invalid norm') end else ord = sym(ord); end cmd = { line1 ... 'if not x.is_Matrix:' ... ' x = sympy.Matrix([x])' ... 'return x.norm(ord),' }; z = pycall_sympy__ (cmd, sym(x), ord); end %!assert (isequal (norm(sym(-6)), 6)) %!test %! % 2-norm default %! A = [1 2; 3 4]; %! n1 = norm (sym (A)); %! assert (isequal (n1, sqrt (sqrt (sym(221)) + 15))) %! assert (norm (A), double (n1), -eps) %!test %! syms x y real %! assert (isequal (norm([x 1; 3 y], 'fro'), sqrt(x^2 + y^2 + 10))) %!test %! syms x real %! assert (isequal (norm([x 1], 2), sqrt(x^2 + 1))) %!test %! % test sym vs double ord %! syms x %! assert (isequal (norm([x 2 1], 1), abs(x) + 3)) %! assert (isequal (norm([x 2 1], sym(1)), abs(x) + 3)) %! assert (isequal (norm([sym(-3) 2 1], inf), sym(3))) %! assert (isequal (norm([sym(-3) 2 1], sym(inf)), sym(3))) symbolic-3.1.1/inst/@sym/not.m0000644000000000000000000000513214405647405013100 0ustar %% Copyright (C) 2014-2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym not {(@var{x})} %% @defopx Operator @@sym {~@var{x}} {} %% @defopx Operator @@sym {!@var{x}} {} %% Logical "not" of a symbolic array. %% %% Example: %% @example %% @group %% syms x y %% eqn = 2*x == y %% @result{} eqn = (sym) 2⋅x = y %% not(eqn) %% @result{} ans = (sym) 2⋅x ≠ y %% @end group %% @end example %% %% More briefly: %% @example %% @group %% ~(x==y) %% @result{} ans = (sym) x ≠ y %% !(x==y) %% @result{} ans = (sym) x ≠ y %% @end group %% @end example %% %% Applies to each entry of a matrix: %% @example %% @group %% A = [x < y, 2*x + y >= 0, true] %% @result{} A = (sym) [x < y 2⋅x + y ≥ 0 True] (1×3 matrix) %% ~A %% @result{} ans = (sym) [x ≥ y 2⋅x + y < 0 False] (1×3 matrix) %% @end group %% @end example %% %% @seealso{@@sym/eq, @@sym/ne, @@sym/logical, @@sym/isAlways} %% @end defop function r = not(x) if (nargin ~= 1) print_usage (); end r = elementwise_op ('Not', x); end %!shared t, f %! t = sym(true); %! f = sym(false); %!test %! % simple %! assert (isequal( ~t, f)) %! assert (isequal( ~t, f)) %!test %! % array %! w = [t t f t]; %! z = [f f t f]; %! assert (isequal( ~w, z)) %!test %! % number %! assert (isequal( ~sym(5), f)) %! assert (isequal( ~sym(0), t)) %!test %! % output is sym %! syms x %! e = ~(x == 4); %! assert (isa (e, 'sym')) %! assert (strncmp (sympy(e), 'Unequality', 10)) %!test %! % output is sym even for scalar t/f (should match other bool fcns) %! assert (isa (~t, 'sym')) %!test %! % symbol ineq %! syms x %! a = [t f x == 1 x ~= 2 x < 3 x <= 4 x > 5 x >= 6]; %! b = [f t x ~= 1 x == 2 x >= 3 x > 4 x <= 5 x < 6]; %! assert (isequal( ~a, b)) %!test %! syms x %! y = ~x; %! s = disp(y, 'flat'); %! assert (strcmp (strtrim (s), '~x') || strcmpi (strtrim (s), 'Not(x)')) %!error not (sym(1), 2) symbolic-3.1.1/inst/@sym/null.m0000644000000000000000000000367614405647405013265 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym null (@var{A}) %% Basis for the nullspace of a symbolic matrix. %% %% Return a matrix whose columns are a basis for the nullspace of %% the matrix. %% Examples: %% @example %% @group %% A = sym([1 1; 2 0]); %% null (A) %% @result{} (sym) [] (empty 2×0 matrix) %% @end group %% %% @group %% A = sym([1 2; 1 2]); %% null (A) %% @result{} (sym 2×1 matrix) %% %% ⎡-2⎤ %% ⎢ ⎥ %% ⎣1 ⎦ %% @end group %% %% @group %% A = sym(zeros(2,2)); %% null (A) %% @result{} (sym 2×2 matrix) %% %% ⎡1 0⎤ %% ⎢ ⎥ %% ⎣0 1⎦ %% @end group %% @end example %% %% @seealso{@@sym/rank, @@sym/orth} %% @end defmethod function r = null(A) cmd = { 'A = _ins[0]' 'if not A.is_Matrix:' ' A = sympy.Matrix([A])' 'ns = A.nullspace()' 'if len(ns) == 0:' ' return sympy.zeros(A.cols, 0),' 'return sympy.Matrix.hstack(*ns),' }; r = pycall_sympy__ (cmd, A); end %!test %! A = sym([1 2; 3 4]); %! assert (isempty (null (A))) %!assert (isempty (null (sym(4)))) %!test %! A = sym([1 2 3; 3 4 5]); %! assert (isequal (null(A), sym([1;-2;1]))) symbolic-3.1.1/inst/@sym/numden.m0000644000000000000000000000606614405647405013575 0ustar %% Copyright (C) 2015, 2016, 2018-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {[@var{N}, @var{D}] =} numden (@var{f}) %% Extract numerator and denominator of a symbolic expression. %% %% Examples: %% @example %% @group %% f = sym(5)/6; %% [N, D] = numden (f) %% @result{} N = (sym) 5 %% @result{} D = (sym) 6 %% @end group %% %% @group %% syms x %% f = (x^2+2*x-1)/(2*x^3+9*x^2+6*x+3) %% @result{} f = (sym) %% 2 %% x + 2⋅x - 1 %% ───────────────────── %% 3 2 %% 2⋅x + 9⋅x + 6⋅x + 3 %% %% [N, D] = numden (f) %% @result{} N = (sym) %% 2 %% x + 2⋅x - 1 %% %% @result{} D = (sym) %% 3 2 %% 2⋅x + 9⋅x + 6⋅x + 3 %% @end group %% @end example %% %% @var{f} can be a matrix, for example: %% @example %% @group %% f = [1/x exp(x) exp(-x)]; %% @c @result{} f = (sym 1×3 matrix) %% @c ⎡1 x -x⎤ %% @c ⎢─ ℯ ℯ ⎥ %% @c ⎣x ⎦ %% [N, D] = numden (f) %% @result{} N = (sym 1×3 matrix) %% ⎡ x ⎤ %% ⎣1 ℯ 1⎦ %% %% @result{} D = (sym 1×3 matrix) %% ⎡ x⎤ %% ⎣x 1 ℯ ⎦ %% @end group %% @end example %% %% @seealso{@@sym/partfrac, @@sym/children, @@sym/coeffs, @@sym/children, @@sym/lhs, @@sym/rhs} %% @end deftypemethod function [N, D] = numden (f) if (nargin ~= 1) print_usage (); end cmd = { 'f, = _ins' 'if not isinstance(f, MatrixBase):' ' return fraction(f)' 'n = f.as_mutable()' 'd = n.copy()' 'for i in range(0, len(n)):' ' n[i], d[i] = fraction(f[i])' 'return n, d' }; [N, D] = pycall_sympy__ (cmd, f); end %!error numden (sym(1), 2) %!test %! syms x %! [n, d] = numden (1/x); %! assert (isequal (n, sym(1)) && isequal (d, x)) %!test %! syms x y %! n1 = [sym(1); x]; %! d1 = [x; y]; %! [n, d] = numden (n1 ./ d1); %! assert (isequal (n, n1) && isequal (d, d1)) %!test %! [n, d] = numden (sym(2)); %! assert (isequal (n, 2)); %! assert (isequal (d, 1)); %!test %! syms x y %! [n, d] = numden ((x + pi)/(y + 6)); %! assert (isequal (n, x + pi)); %! assert (isequal (d, y + 6)); %!test %! syms x y %! [n, d] = numden ((x^2 + y^2)/(x*y)); %! assert (isequal (n, x^2 + y^2)); %! assert (isequal (d, x*y)); symbolic-3.1.1/inst/@sym/numel.m0000644000000000000000000000250414405647405013420 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym numel (@var{x}) %% Return number of elements in symbolic array. %% %% Example: %% @example %% @group %% syms x %% A = [1 2 x; x 3 4]; %% numel(A) %% @result{} 6 %% @end group %% @end example %% %% @seealso{@@sym/length, @@sym/size} %% @end defmethod function n = numel(x) %disp('numel call') d = size(x); n = prod(d); end %!test %! a = sym([1 2 3]); %! assert(numel(a) == 3); %!test %! % 2D array %! a = sym([1 2 3; 4 5 6]); %! assert(numel(a) == 6); %!test %! % empty %! a = sym([]); %! assert(numel(a) == 0); symbolic-3.1.1/inst/@sym/ones.m0000644000000000000000000000464714405647405013256 0ustar %% Copyright (C) 2016 Lagu %% Copyright (C) 2017, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym ones (@var{n}) %% @defmethodx @@sym ones (@var{n}, @var{m}) %% Return a matrix whose elements are all 1. %% %% Example: %% @example %% @group %% y = ones (sym(3)) %% @result{} y = (sym 3×3 matrix) %% ⎡1 1 1⎤ %% ⎢ ⎥ %% ⎢1 1 1⎥ %% ⎢ ⎥ %% ⎣1 1 1⎦ %% @end group %% @end example %% %% @seealso{ones, @@sym/zeros, @@sym/eye} %% @end defmethod function y = ones(varargin) % partial workaround for issue #13: delete when/if fixed properly if ((isa (varargin{nargin}, 'char')) && (strcmp (varargin{nargin}, 'sym'))) varargin = varargin(1:(nargin-1)); end if (isa (varargin{end}, 'char')) varargin = cell2nosyms (varargin); y = ones (varargin{:}); return end for i = 1:length(varargin) varargin{i} = sym(varargin{i}); end if (length (varargin) == 1 && ~isscalar (varargin{1})) y = pycall_sympy__ ('return ones(*_ins[0])', varargin{1}); else y = pycall_sympy__ ('return ones(*_ins)', varargin{:}); end end %!test %! y = ones(sym(2)); %! x = [1 1; 1 1]; %! assert( isequal( y, sym(x))) %!test %! y = ones(sym(2), 1); %! x = [1; 1]; %! assert( isequal( y, sym(x))) %!test %! y = ones(sym(1), 2); %! x = [1 1]; %! assert( isequal( y, sym(x))) %!test %! y = ones (sym([2 3])); %! x = sym (ones ([2 3])); %! assert (isequal (y, x)) %% Check types: %!assert( isa( ones(sym(2), 'double'), 'double')) %!assert( isa( ones(3, sym(3), 'single') , 'single')) %!assert( isa( ones(3, sym(3)), 'sym')) %!assert( isa( ones(3, sym(3), 'sym'), 'sym')) %!xtest %! % Issue #13 %! assert( isa( ones(3, 3, 'sym'), 'sym')) symbolic-3.1.1/inst/@sym/or.m0000644000000000000000000000354214405647405012723 0ustar %% Copyright (C) 2014-2016, 2018 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym or {(@var{x}, @var{y})} %% @defopx Operator @@sym {@var{x} | @var{y}} {} %% Logical "or" of symbolic arrays. %% %% Examples: %% @example %% @group %% sym(false) | sym(true) %% @result{} (sym) True %% @end group %% %% @group %% syms x y z %% x & (y | z) %% @result{} (sym) x ∧ (y ∨ z) %% @end group %% @end example %% %% @seealso{@@sym/and, @@sym/not, @@sym/xor, @@sym/eq, @@sym/ne, %% @@sym/logical, @@sym/isAlways, @@sym/isequal} %% @end defop function r = or(x, y) if (nargin ~= 2) print_usage (); end r = elementwise_op ('Or', sym(x), sym(y)); end %!shared t, f %! t = sym(true); %! f = sym(false); %!test %! % simple %! assert (isequal (t | f, t)) %! assert (isequal (t | t, t)) %! assert (isequal (f | f, f)) %!test %! % array %! w = [t t f f]; %! z = [t f t f]; %! assert (isequal (w | z, [t t t f])) %!test %! % output is sym even for scalar t/f %! assert (isa (t | f, 'sym')) %!test %! % eqns %! syms x %! e = or(x == 4, x == 5); %! assert (isequal (subs(e, x, [3 4 5 6]), [f t t f])) %!error or (sym(1), 2, 3) symbolic-3.1.1/inst/@sym/orth.m0000644000000000000000000000577514405647405013271 0ustar %% Copyright (C) 2015, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym orth (@var{A}) %% Orthonormal basis for column space (range) of symbolic matrix. %% %% Examples: %% @example %% @group %% A = sym([1 1; 2 0]); %% orth (A) %% @result{} (sym 2×2 matrix) %% %% ⎡ √5 2⋅√5⎤ %% ⎢ ── ────⎥ %% ⎢ 5 5 ⎥ %% ⎢ ⎥ %% ⎢2⋅√5 -√5 ⎥ %% ⎢──── ────⎥ %% ⎣ 5 5 ⎦ %% @end group %% %% @group %% A = sym([1 2; 1 2]); %% orth (A) %% @result{} ans = (sym 2×1 matrix) %% %% ⎡√2⎤ %% ⎢──⎥ %% ⎢2 ⎥ %% ⎢ ⎥ %% ⎢√2⎥ %% ⎢──⎥ %% ⎣2 ⎦ %% @end group %% @end example %% %% The basis is often not unique and in general @code{double(orth(A))} may %% not match the output of @code{orth(double(A))}. %% %% @seealso{@@sym/rank, @@sym/null, @@sym/rref} %% @end defmethod function B = orth(A) cmd = { 'A = _ins[0]' 'if not A.is_Matrix:' ' A = sp.Matrix([A])' 'L = A.rref()' 'B = [A[:, i] for i in L[1]]' % get pivot columns in original 'B = sp.GramSchmidt(B, True)' 'B = sp.Matrix.hstack(*B)' 'return B,' }; B = pycall_sympy__ (cmd, A); end %!test %! A = [1 2; 3 6]; %! K = orth(A); %! L = orth(sym(A)); %! assert (isequal (size(L), [2 1])) %! dif1 = abs (double(L) - K); %! dif2 = abs (double(L) + K); %! assert (all (dif1 < 1e-15) || all (dif2 < 1e-15)) %!test %! A = [1; 3]; %! K = orth(A); %! L = orth(sym(A)); %! assert (isequal (size(L), [2 1])) %! dif1 = abs (double(L) - K); %! dif2 = abs (double(L) + K); %! assert (all (dif1 < 1e-16) || all (dif2 < 1e-16)) %!test %! A = sym([1 2; 3 4]); %! L = orth(sym(A)); %! assert (isequal (size(L), [2 2])) %! v = L(:, 1); %! w = L(:, 2); %! assert (isAlways (v' * v == 1)) %! assert (isAlways (w' * w == 1)) %! assert (isAlways (v' * w == 0)) %!test %! A = sym([1 1; 1 0; 1 0]); %! L = orth(sym(A)); %! assert (isequal (size(L), [3 2])) %! v = L(:, 1); %! w = L(:, 2); %! assert (isAlways (v' * v == 1)) %! assert (isAlways (w' * w == 1)) %! assert (isAlways (v' * w == 0)) %! % y and z components must be equal %! assert (isAlways (v(2) == v(3))) %! assert (isAlways (w(2) == w(3))) symbolic-3.1.1/inst/@sym/partfrac.m0000644000000000000000000000512614405647405014105 0ustar %% Copyright (C) 2014-2016, 2019 Colin B. Macdonald %% Copyright (C) 2014-2015 Andrés Prieto %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym partfrac (@var{f}) %% @defmethodx @@sym partfrac (@var{f}, @var{x}) %% Compute partial fraction decomposition of a rational function. %% %% Examples: %% @example %% @group %% syms x %% f = 2/(x + 4)/(x + 1) %% @result{} f = (sym) %% 2 %% ─────────────── %% (x + 1)⋅(x + 4) %% @end group %% %% @group %% partfrac(f) %% @result{} ans = (sym) %% 2 2 %% - ───────── + ───────── %% 3⋅(x + 4) 3⋅(x + 1) %% @end group %% @end example %% %% Other examples: %% @example %% @group %% syms x y %% partfrac(y/(x + y)/(x + 1), x) %% @result{} ans = (sym) %% y y %% - ─────────────── + ─────────────── %% (x + y)⋅(y - 1) (x + 1)⋅(y - 1) %% @end group %% %% @group %% partfrac(y/(x + y)/(x + 1), y) %% @result{} ans = (sym) %% x 1 %% - ─────────────── + ───── %% (x + 1)⋅(x + y) x + 1 %% @end group %% @end example %% %% @seealso{@@sym/factor} %% @end defmethod function z = partfrac(f, x) % some special cases for SMT compat. if (nargin == 1) x = symvar(f, 1); if (isempty(x)) x = sym('x'); end end cmd = 'return sp.polys.partfrac.apart(_ins[0],_ins[1]),'; z = pycall_sympy__ (cmd, sym(f), sym(x)); end %!test %! % basic %! syms x y z %! assert(logical( partfrac(y/(x + 2)/(x + 1),x) == -y/(x + 2) + y/(x + 1) )) %! assert(logical( factor(partfrac(x^2/(x^2 - y^2),y)) == factor(x/(2*(x + y)) + x/(2*(x - y)) ))) %! assert(logical( factor(partfrac(x^2/(x^2 - y^2),x)) == factor(-y/(2*(x + y)) + y/(2*(x - y)) + 1 ))) symbolic-3.1.1/inst/@sym/permute.m0000644000000000000000000000343614405647405013766 0ustar %% Copyright (C) 2015, 2016, 2018, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym permute (@var{A}, @var{perm}) %% Permute the indices of a symbolic array. %% %% Generalizes transpose, but currently doesn't do much as we only %% support 2D symbolic arrays. %% %% Example: %% @example %% @group %% A = sym([1 2 pi; 4 5 6]); %% B = permute(A, [2 1]) %% @result{} B = (sym 3×2 matrix) %% ⎡1 4⎤ %% ⎢ ⎥ %% ⎢2 5⎥ %% ⎢ ⎥ %% ⎣π 6⎦ %% @end group %% @end example %% %% @seealso{@@sym/ipermute} %% @end defmethod function B = permute(A, perm) if (nargin < 2) print_usage (); end if (isequal(perm, [1 2])) B = A; elseif (isequal(perm, [2 1])) B = A.'; else print_usage (); end end %!error permute (sym(1)) %!error permute (sym(1), 2, 3) %!test %! D = round(10*rand(5,3)); %! A = sym(D); %! B = permute(A, [1 2]); %! assert (isequal(B, A)) %! B = permute(A, [2 1]); %! assert (isequal(B, A.')) %!test %! syms x %! A = [1 x]; %! B = permute(A, [2 1]); %! assert (isequal(B, [1; x])) symbolic-3.1.1/inst/@sym/piecewise.m0000644000000000000000000000605314405647405014260 0ustar %% Copyright (C) 2022 Alex Vong %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym piecewise (@var{cond1}, @var{val1}, @var{cond2}, @var{val2}, @dots{}) %% @defmethodx @@sym piecewise (@var{cond1}, @var{val1}, @var{cond2}, @var{val2}, @dots{}, @var{else_val}) %% Construct piecewise function. %% %% The returned piecewise function evaluates to @var{val1} if @var{cond1} %% holds, @var{val2} if @var{cond2} holds, @dots{} etc. In the case where none %% of the conditions hold, it evaluates to @var{else_val} if provided. If %% @var{else_val} is not provided, it evaluates to @code{nan}. %% %% Examples: %% @example %% @group %% syms x real %% f = piecewise (abs (x) < 1, exp (- 1 / (1 - x^2)), abs (x) >= 1, 0) %% @result{} f = (sym) %% ⎧ -1 %% ⎪ ────── %% ⎪ 2 %% ⎨ 1 - x %% ⎪ℯ for │x│ < 1 %% ⎪ %% ⎩ 0 otherwise %% @end group %% @end example %% %% For this piecewise function, we can omit the redundant condition at the end: %% @example %% @group %% syms x real %% f = piecewise (abs (x) < 1, exp (- 1 / (1 - x^2)), 0) %% @result{} f = (sym) %% ⎧ -1 %% ⎪ ────── %% ⎪ 2 %% ⎨ 1 - x %% ⎪ℯ for │x│ < 1 %% ⎪ %% ⎩ 0 otherwise %% @end group %% @end example %% %% @seealso{if} %% @end defmethod function f = piecewise (varargin) if nargin < 1 print_usage (); end cmd = {'def pack_args_without_else(args):' ' return [(val, cond) for cond, val in unflatten(args, 2)]' 'def pack_args(args):' ' if len(args) % 2 == 0:' ' return pack_args_without_else(args)' ' else:' ' return pack_args_without_else(args[:-1]) + [(args[-1], True)]' 'return Piecewise(*pack_args(_ins))' }; args = cellfun (@sym, varargin, 'UniformOutput', false); f = pycall_sympy__ (cmd, args{:}); end %!test %! % basic %! syms x real %! f = piecewise (abs (x) < 1, 1); %! assert (isnan (subs (f, -1))); %! assert (isequal (subs (f, 0), 1)); %! assert (isnan (subs (f, 1))); %!test %! % heaviside %! syms x real %! f = rewrite (heaviside (x, 1 / sym (2)), 'Piecewise'); %! g = piecewise (x < 0, 0, x == 0, 1 / sym (2), x > 0, 1); %! assert (logical (simplify (f == g))); %% FIXME: expand test suite, add SMT compat tests, ... symbolic-3.1.1/inst/@sym/pinv.m0000644000000000000000000000327714405647405013264 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym pinv (@var{A}) %% Symbolic Moore-Penrose pseudoinverse of a matrix. %% %% Example: %% @example %% @group %% A = sym([1 2; 3 4; 5 6]) %% @result{} A = (sym 3×2 matrix) %% ⎡1 2⎤ %% ⎢ ⎥ %% ⎢3 4⎥ %% ⎢ ⎥ %% ⎣5 6⎦ %% %% pinv(A) %% @result{} (sym 2×3 matrix) %% ⎡-4/3 -1/3 2/3 ⎤ %% ⎢ ⎥ %% ⎢ 13 ⎥ %% ⎢ ── 1/3 -5/12⎥ %% ⎣ 12 ⎦ %% @end group %% @end example %% @end defmethod function z = pinv(x) cmd = { 'x, = _ins' 'if not x.is_Matrix:' ' x = sp.Matrix([[x]])' 'return x.pinv(),' }; z = pycall_sympy__ (cmd, x); end %!test %! % scalar %! syms x %! assert (isequal (pinv(x), 1/x)) %!test %! % 2x3 %! A = [1 2 3; 4 5 6]; %! assert (max (max (abs (double (pinv (sym (A))) - pinv(A)))) <= 10*eps) symbolic-3.1.1/inst/@sym/plus.m0000644000000000000000000000472414405647405013271 0ustar %% Copyright (C) 2014, 2016, 2018-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym plus {(@var{x}, @var{y})} %% @defopx Operator @@sym {@var{x} + @var{y}} {} %% Add two symbolic expressions together. %% %% Example: %% @example %% @group %% syms x y %% x + y %% @result{} (sym) x + y %% @end group %% @end example %% @end defop function z = plus(x, y) % Note elementwise_op *prefers* element-wise operations, which may not % be what we always want here (e.g., see MatrixExpr test below). %z = elementwise_op ('lambda x, y: x + y', x, y); % Instead, we do broadcasting only in special cases (to match % Octave behaviour) and otherwise leave it up to SymPy. cmd = { 'x, y = _ins' 'if x is None or y is None:' ' return x + y' 'if x.is_Matrix and not y.is_Matrix:' ' return x + y*sp.ones(*x.shape),' 'if not x.is_Matrix and y.is_Matrix:' ' return x*sp.ones(*y.shape) + y,' 'return x + y' }; z = pycall_sympy__ (cmd, sym(x), sym(y)); end %!test %! % basic addition %! syms x %! assert (isa (x+5, 'sym')) %! assert (isa (5+x, 'sym')) %! assert (isa (5+sym(4), 'sym')) %! assert (isequal (5+sym(4), sym(9))) %!test %! % array addition %! syms x %! D = [0 1; 2 3]; %! A = [sym(0) 1; sym(2) 3]; %! DZ = D - D; %! assert( isequal ( A + D , 2*D )) %! assert( isequal ( D + A , 2*D )) %! assert( isequal ( A + A , 2*D )) %! assert( isequal ( A + 2 , D + 2 )) %! assert( isequal ( 4 + A , 4 + D )) %!test %! % ensure MatrixExpr can be manipulated somewhat %! syms n m integer %! A = sym('A', [n m]); %! B = subs(A, [n m], [5 6]); %! B = B + 1; %! assert (isa (B, 'sym')) %! C = B(1, 1); % currently makes a MatrixElement %! C = C + 1; %! assert (isa (C, 'sym')) symbolic-3.1.1/inst/@sym/pochhammer.m0000644000000000000000000000404214405647405014422 0ustar %% Copyright (C) 2017-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym pochhammer (@var{x}, @var{n}) %% Rising Factorial or Pochhammer symbol. %% %% Example: %% @example %% @group %% syms x n %% pochhammer (x, n) %% @result{} (sym) RisingFactorial(x, n) %% @end group %% @end example %% %% The Pochhammer symbol can be defined in terms of the Gamma %% function: %% @example %% @group %% syms x positive %% rewrite (pochhammer (x, n), 'gamma') %% @result{} (sym) %% %% Γ(n + x) %% ──────── %% Γ(x) %% @end group %% @end example %% %% %% For positive integer @var{n}, the result has a simple form: %% @example %% @group %% pochhammer (x, 4) %% @result{} (sym) x⋅(x + 1)⋅(x + 2)⋅(x + 3) %% @end group %% @end example %% %% @seealso{@@sym/gamma, @@double/pochhammer} %% @end defmethod function I = pochhammer(x, n) if (nargin ~= 2) print_usage (); end I = elementwise_op ('RisingFactorial', sym(x), sym(n)); end %!error pochhammer (sym(1)) %!error pochhammer (sym(1), 2, 3) %!assert (isequal (pochhammer (sym(3), 4), sym(360))) %!assert (isequal (pochhammer (sym([2 3]), 3), sym([24 60]))) %!test %! % round trip %! syms n z %! f = pochhammer (z, n); %! h = function_handle (f, 'vars', [z n]); %! A = h (1.1, 2.2); %! B = pochhammer (1.1, 2.2); %! assert (A, B) symbolic-3.1.1/inst/@sym/polylog.m0000644000000000000000000000434214405647405013767 0ustar %% Copyright (C) 2016, 2018 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym polylog (@var{s}, @var{z}) %% Symbolic polylogarithm function. %% %% Returns the polylogarithm of order @var{s} and argument @var{z}. %% %% Example: %% @example %% @group %% syms z s %% polylog(s, z) %% @result{} ans = (sym) polylog(s, z) %% diff(ans, z) %% @result{} (sym) %% polylog(s - 1, z) %% ───────────────── %% z %% @end group %% @end example %% %% The polylogarithm satisfies many identities, for example: %% @example %% @group %% syms s positive %% polylog (s+1, 1) %% @result{} (sym) ζ(s + 1) %% zeta (s+1) %% @result{} (sym) ζ(s + 1) %% @end group %% @end example %% %% @seealso{@@sym/dilog, @@sym/zeta} %% @end defmethod function L = polylog(s, z) if (nargin ~= 2) print_usage (); end L = elementwise_op ('polylog', sym(s), sym(z)); end %!assert (isequal (polylog (sym('s'), 0), sym(0))) %!assert (isequal (double (polylog (1, sym(-1))), -log(2))) %!assert (isequal (double (polylog (0, sym(2))), -2)) %!assert (isequal (double (polylog (-1, sym(2))), 2)) %!assert (isequal (double (polylog (-2, sym(3))), -1.5)) %!assert (isequal (double (polylog (-3, sym(2))), 26)) %!assert (isequal (double (polylog (-4, sym(3))), -15)) %!assert (isequal (double (polylog (1, sym(1)/2)), log(2))) %!test %! % round trip %! syms s z %! f = polylog (s, z); %! h = function_handle (f, 'vars', [s z]); %! A = h (1.1, 2.2); %! B = polylog (1.1, 2.2); %! assert (A, B) symbolic-3.1.1/inst/@sym/potential.m0000644000000000000000000000710214405647405014276 0ustar %% Copyright (C) 2014-2016, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym potential (@var{v}) %% @defmethodx @@sym potential (@var{v}, @var{x}) %% @defmethodx @@sym potential (@var{v}, @var{x}, @var{y}) %% Symbolic potential of a vector field. %% %% Finds the potential of the vector field @var{v} with respect to %% the variables @var{x}$. The potential is defined up to an %% additive constant, unless the third argument is given; in which %% case the potential is such that @var{p} is zero at the point %% @var{y}. %% %% Example: %% @example %% @group %% syms x y z %% f = x*y*z; %% g = gradient (f) %% @result{} g = (sym 3×1 matrix) %% ⎡y⋅z⎤ %% ⎢ ⎥ %% ⎢x⋅z⎥ %% ⎢ ⎥ %% ⎣x⋅y⎦ %% potential (g) %% @result{} (sym) x⋅y⋅z %% @end group %% @end example %% %% Return symbolic @code{nan} if the field has no potential (based %% on checking if the Jacobian matrix of the field is %% nonsymmetric). For example: %% @example %% @group %% syms x y %% a = [x; x*y^2]; %% potential (a) %% @result{} (sym) nan %% @end group %% @end example %% %% @seealso{@@sym/gradient, @@sym/jacobian} %% @end defmethod function p = potential(v, x, y) if (nargin > 3) print_usage (); end assert (isvector(v), 'potential: defined for vector fields') if (nargin == 1) x = symvar(v); end % orient same as vec field x = reshape(x, size(v)); if (nargin < 3) y = 0*x; end assert ((length(v) == length(x)) && (length(x) == length(y)), ... 'potential: num vars must match vec length') cmd = { '(v, x, y) = _ins' 'if not v.is_Matrix:' ' v = Matrix([v])' ' x = Matrix([x])' ' y = Matrix([y])' 'G = v.jacobian(x)' 'if not G.is_symmetric():' ' return S.NaN,' '_lambda = sympy.Dummy("lambda", real=True)' 'q = y + _lambda*(x - y)' 'vlx = v.subs(list(zip(list(x), list(q))), simultaneous=True)' 'p = integrate((x-y).dot(vlx), (_lambda, 0, 1))' 'return p.simplify(),' }; p = pycall_sympy__ (cmd, sym(v), x, sym(y)); end %!error potential (sym(1), 2, 3, 4) %!shared x,y,z %! syms x y z %!test %! % 1D %! f = 3*x^2; %! F = x^3; %! assert (isequal (potential(f), F)) %! assert (isequal (potential(f, x), F)) %! assert (isequal (potential(f, x, 0), F)) %! assert (isequal (potential(f, x, 2), F - 8)) %!test %! F = x*exp(y) + (z-1)^2; %! f = gradient(F); %! G = potential(f, [x;y;z], [0;1;1]); %! assert (isAlways (G == F)) %!test %! F = x*exp(y); %! f = gradient(F); %! G = potential(f); %! assert (isAlways (G == F)) %!test %! % no potential exists %! syms x y %! a = [x; x*y^2]; %! assert (isnan (potential (a))) %!shared %!xtest %! % fails b/c of sympy #8458 (piecewise expr that should simplify) %! syms x %! f = cos(x); %! assert (isequal (potential(f, x), sin(x))) symbolic-3.1.1/inst/@sym/power.m0000644000000000000000000000651614405647405013443 0ustar %% Copyright (C) 2014, 2016, 2018-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym power {(@var{x}, @var{y})} %% @defopx Operator @@sym {@var{x} .^ @var{y}} {} %% Symbolic expression componentwise exponentiation. %% %% The @code{.^} notation can be used to raise each @emph{element} %% of a matrix to a power: %% @example %% @group %% syms x %% A = [sym(pi) 2; 3 x] %% @result{} A = (sym 2×2 matrix) %% ⎡π 2⎤ %% ⎢ ⎥ %% ⎣3 x⎦ %% A.^2 %% @result{} ans = (sym 2×2 matrix) %% ⎡ 2 ⎤ %% ⎢π 4 ⎥ %% ⎢ ⎥ %% ⎢ 2⎥ %% ⎣9 x ⎦ %% @end group %% @end example %% %% It can also be used on two matrices: %% @example %% @group %% A.^[1 2; 3 4] %% @result{} ans = (sym 2×2 matrix) %% ⎡π 4 ⎤ %% ⎢ ⎥ %% ⎢ 4⎥ %% ⎣27 x ⎦ %% @end group %% @end example %% %% @seealso{@@sym/mpower} %% @end defop function z = power(x, y) cmd = { '(x,y) = _ins' 'if x.is_Matrix and y.is_Matrix:' ' x = x.as_mutable()' ' for i in range(0, len(x)):' ' x[i] = x[i]**y[i]' ' return x,' 'if x.is_Matrix and not y.is_Matrix:' ' return x.applyfunc(lambda a: a**y),' 'if not x.is_Matrix and y.is_Matrix:' ' return y.applyfunc(lambda a: x**a),' 'return x**y' }; z = pycall_sympy__ (cmd, sym(x), sym(y)); end %!test %! % scalar .^ scalar %! syms x %! assert (isa (x.^2, 'sym')) %! assert (isa (2.^x, 'sym')) %! assert (isa (x.^x, 'sym')) %! assert (isequal (x.^2, x^2)) %! assert (isequal (2.^x, 2^x)) %! assert (isequal (x.^x, x^x)) %!test %! % scalar .^ matrix %! D = [0 1; 2 3]; %! A = sym(D); %! assert (isequal ( sym(2).^D , 2.^D )) %! assert (isequal ( sym(2).^A , 2.^A )) %! assert (isequal ( 2.^D , 2.^A )) %! assert (isequal ( 2.^A , 2.^A )) %!test %! % matrix .^ matrix %! syms x %! A = [x 2*x; 3*x 4*x]; %! D = [0 1; 2 3]; %! B = sym(D); %! assert (isequal ( A.^D, [1 2*x; 9*x^2 64*x^3] )) %! assert (isequal ( A.^B, [1 2*x; 9*x^2 64*x^3] )) %!test %! % matrix .^ scalar %! syms x %! A = [x 2*x]; %! assert (isequal ( A.^2, [x^2 4*x^2] )) %! assert (isequal ( A.^sym(2), [x^2 4*x^2] )) %!test %! % 1^oo %! % (sympy >= 0.7.5 gives NaN, SMT R2013b: gives 1) %! oo = sym(inf); %! assert (isnan (1^oo)) %!test %! % 1^zoo %! % (1 on sympy 0.7.4--0.7.6, but nan in git (2014-12-12, a210908d4)) %! zoo = sym('zoo'); %! assert (isnan (1^zoo)) %!test %! % immutable test %! A = sym([1 2]); %! B = sym('ImmutableDenseMatrix([[Integer(1), Integer(2)]])'); %! assert (isequal (A.^A, B.^B)) symbolic-3.1.1/inst/@sym/pretty.m0000644000000000000000000000547214405647405013636 0ustar %% Copyright (C) 2014-2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {} pretty (@var{x}) %% @deftypemethodx @@sym {@var{s} =} pretty (@var{x}) %% @deftypemethodx @@sym {@var{s} =} pretty (@var{x}, 'unicode') %% @deftypemethodx @@sym {@var{s} =} pretty (@var{x}, 'ascii') %% Return/display unicode/ascii-art representation of expression. %% %% By default, this is similar to @code{disp(x)}: %% @example %% @group %% syms n %% pretty (ceil (pi/n)); %% @print{} ⎡π⎤ %% @print{} ⎢─⎥ %% @print{} ⎢n⎥ %% @end group %% @end example %% %% However, if you set @code{sympref display ascii}, @code{pretty(x)} %% displays ascii-art instead. The optional second argument forces %% the output: %% @example %% @group %% pretty (ceil (pi/n), 'ascii'); %% @print{} /pi\ %% @print{} ceiling|--| %% @print{} \n / %% @end group %% @end example %% %% This method might be useful if you usually prefer %% @code{sympref display flat} but occasionally want to pretty %% print an expression. %% %% @seealso{@@sym/disp, @@sym/latex} %% @end deftypemethod function varargout = pretty(x, wh) if (nargin == 1) % read config to see how to display x wh = sympref('display'); end % if config says flat, pretty does unicode if (strcmp('flat', lower(wh))) if (ispc () && (~isunix ())) % Unicode not working on Windows, Issue #83. wh = 'ascii'; else wh = 'unicode'; end end if (nargout == 0) disp(x, wh) else varargout{1} = disp(x, wh); end end %!test %! % simple %! syms x %! s1 = pretty(sin(x)); %! s2 = sprintf(' sin(x)\n'); %! assert (strcmp (s1, s2)) %!test %! % force ascii %! syms x %! s1 = pretty(sin(x/2), 'ascii'); %! s2 = sprintf(' /x\\\n sin|-|\n \\2/\n'); %! swin = strrep(s1, sprintf('\r\n'), sprintf('\n')); %! assert (strcmp (s1, s2) || strcmp (swin, s2)) %!test %! % force unicode %! syms x %! s1 = pretty(sin(x/2), 'unicode'); %! s2 = sprintf(' ⎛x⎞\n sin⎜─⎟\n ⎝2⎠\n'); %! swin = strrep(s1, sprintf('\r\n'), sprintf('\n')); %! assert (strcmp (s1, s2) || strcmp (swin, s2)) symbolic-3.1.1/inst/@sym/prevprime.m0000644000000000000000000000317614405647405014317 0ustar %% Copyright (C) 2017 NVS Abhilash %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym prevprime (@var{x}) %% Return the previous prime number. %% %% Example: %% @example %% @group %% prevprime(sym(3)) %% @result{} ans = (sym) 2 % %% prevprime([sym(3) 10 100 1000 65530]) %% @result{} (sym) [2 7 97 997 65521] (1×5 matrix) %% @end group %% @end example %% %% @seealso{@@sym/isprime, @@sym/nextprime} %% @end defmethod function y = prevprime(x) if (nargin ~= 1) print_usage () end %y = elementwise_op ('prevprime', x); % workaround as upstream SymPy returns int, not sym y = elementwise_op ('lambda a: S(prevprime(a))', x); end %!assert (isequal (prevprime(sym(3)), 2)); %!assert (isequal (prevprime(sym(20)), 19)); %!assert (isequal (prevprime(sym([3 5 10])), [2 3 7])); %!error prevprime(sym(2)) %!error prevprime(sym(-2)) %!test %! % result is a sym %! p = prevprime(sym(3)); %! assert (isa (p, 'sym')) symbolic-3.1.1/inst/@sym/private/0000755000000000000000000000000014405647405013573 5ustar symbolic-3.1.1/inst/@sym/private/assert_same_shape.m0000644000000000000000000000155514405647405017445 0ustar %% Copyright (C) 2014 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . function t = assert_same_shape(x,y) if ~(is_same_shape(x,y)) error('array inputs must have same size and shape'); end symbolic-3.1.1/inst/@sym/private/cell2nosyms.m0000644000000000000000000000154114405647405016224 0ustar %% Copyright (C) 2016 Lagu %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . function z = cell2nosyms(x) for i=1:length(x) if isa(x{i}, 'sym') x{i} = double(x{i}); end end z = x; end symbolic-3.1.1/inst/@sym/private/check_assumptions.m0000644000000000000000000000314514405647405017476 0ustar %% Copyright (C) 2016 Lagu %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @deftypefun check_assumptions (@var{x}) %% Check if the input have valid assumptions. %% %% Private helper function. %% %% @seealso{sym} %% @end deftypefun function check_assumptions (x) ca_helper (x) end %% Is safer use a helper when private functions call it self for classdef. function ca_helper (x) persistent valid_asm if (isempty (valid_asm)) valid_asm = assumptions ('possible'); end if (~islogical (x)) if (isa (x, 'char')) assert (ismember (x, valid_asm), ['sym: the assumption "' x '" is not supported in your Sympy version.']) elseif (isstruct (x)) fields = fieldnames (x); for j = 1:numel (fields) ca_helper (fields{j}) end elseif (iscell (x)) for j = 1:length (x) ca_helper (x{j}) end else error ('sym: assumption must be a string or struct or cell') end end end symbolic-3.1.1/inst/@sym/private/codegen.m0000644000000000000000000001342214405647405015357 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . function [outflag,output] = codegen(varargin) [Nin, inputs, inputstr, Nout, param] = codegen_input_parser(varargin{:}); %fprintf('debug: %d inputs, %d outputs\n', Nin, Nout); %% fortran.m/ccode.m % these call us with lang if (isfield(param, 'lang')) assert(strcmpi(param.lang, 'F95') || ... strcmpi(param.lang, 'C') || ... strcmpi(param.lang, 'Octave')) else param.lang = 'Octave'; end if (strcmpi(param.lang, 'Octave')) outflag = -1; output = {Nin, inputs, inputstr, Nout, param}; return end %% Outputs if (param.codegen) %cmd = { '(expr,fcnname,fname,showhdr) = _ins' ... % 'from sympy.utilities.codegen import codegen' ... % ['out = codegen((fcnname,expr), "' param.lang ... % '", filename, header=showhdr)'] ... % 'return out,' }; %if (user_provided_vars) cmd = { '(expr,fcnname,filename,showhdr,in_vars) = _ins' ... 'from sympy.utilities.codegen import codegen' ... ['out = codegen((fcnname,expr), "' param.lang ... '", filename, header=showhdr' ... ', argument_sequence=in_vars)'] ... 'return out,' }; %end assert(Nout == 1, 'FIXME: multiple inputs? need names?'); if isempty(param.fname) fname2 = 'file'; fcnname = 'myfun'; else fname2 = param.fname; fcnname = param.fname; end % was note here about findsymbols vs symvar ordering: not relevant out = pycall_sympy__ (cmd, varargin{1}, fcnname, fname2, param.show_header, inputs); C.name = out{1}{1}; C.code = out{1}{2}; H.name = out{2}{1}; H.code = out{2}{2}; if (isempty(param.fname)) output = {C, H}; outflag = 2; else [fid,msg] = fopen(C.name, 'w'); assert(fid > -1, msg) fprintf(fid, '%s', C.code) fclose(fid); [fid,msg] = fopen(H.name, 'w'); assert(fid > -1, msg) fprintf(fid, '%s', H.code) fclose(fid); fprintf('Wrote files %s and %s.\n', C.name, H.name); output = {}; outflag = 0; end else if (strcmp(param.lang, 'C')) cmd = { '(f,) = _ins' ... 's = ccode(f)' ... 'return s,' }; elseif (strcmp(param.lang, 'F95')) cmd = { '(f,) = _ins' ... 's = fcode(f)' ... 'return s,' }; else error('only C and F95 supported'); end exprstrs = {}; for i=1:Nout expr = varargin{i}; exprstr{i} = pycall_sympy__ (cmd, expr); end if (Nout == 1) output = {exprstr{1}}; else output = exprstr; end outflag = 1; end end function [Nin, inputs, inputstr, Nout, param] = codegen_input_parser(varargin) param.codegen = false; param.user_provided_vars = false; param.show_header = true; Nout = -42; %% input processing % loop over inputs to find: (f1,f2,...,f_{Nout}, param, value) i = 0; while (i < nargin) i = i + 1; if (ischar(varargin{i})) if (Nout < 0) Nout = i-1; end if strcmpi(varargin{i}, 'vars') temp = varargin{i+1}; i = i + 1; param.user_provided_vars = true; if (isa(temp, 'sym')) inputs = temp; elseif (iscell(temp)) inputs = temp; for j=1:length(inputs) assert(isa(inputs{j},'sym') || ischar(inputs{j}), ... 'only sym/char supported in vars list'); end else error('invalid "vars" param'); end elseif strcmpi(varargin{i}, 'file') param.codegen = true; param.fname = varargin{i+1}; i = i + 1; elseif strcmpi(varargin{i}, 'show_header') param.show_header = logical(varargin{i+1}); i = i + 1; elseif strcmpi(varargin{i}, 'lang') param.lang = varargin{i+1}; i = i + 1; elseif strcmp(varargin{i}, 'outputs') warning('fixme: named "outputs" to be implemented?') outs = varargin{i+1} i = i + 1; else error('invalid option') end end end if (Nout < 0) Nout = nargin; end for i=1:Nout if ~(isa(varargin{i}, 'sym')) warning('expected output expressions to be syms'); end if (isa(varargin{i}, 'symfun')) warning('FIXME: symfun! does that need special treatment?'); end end %% get input string if (~param.user_provided_vars) inputs = findsymbols(varargin(1:Nout)); end Nin = length(inputs); inputstr = strjoin(syms2charcells(inputs), ','); %fprintf('debug: %d inputs, %d outputs\n', Nin, Nout); end function A = cell2symarray(C) A = sym([]); for i=1:length(C) %A(i) = C{i}; % Issue #17 idx.type = '()'; idx.subs = {i}; A = subsasgn(A, idx, C{i}); end end function C = syms2charcells(S) C = {}; for i=1:length(S) if iscell(S) if isa(S{i}, 'sym') C{i} = S{i}.flat; else C{i} = S{i}; end else % MoFo Issue #17 %C{i} = S(i).flat idx.type = '()'; idx.subs = {i}; temp = subsref(S,idx); C{i} = temp.flat; end end end symbolic-3.1.1/inst/@sym/private/detect_special_str.m0000644000000000000000000000362714405647405017621 0ustar %% Copyright (C) 2015-2017 Colin B. Macdonald %% Copyright (C) 2016 Lagu %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @deftypefun {@var{s} =} detect_special_str (@var{x}) %% Recognize special constants, return their sympy string equivalent. %% %% Private helper function. %% %% This function should return a string @var{s} which can be instantiated %% directly in Python such as @code{['return' @var{s}]}. If no special %% value is found, it returns the empty string. %% %% @seealso{sym, vpa} %% @end deftypefun function s = detect_special_str (x) % Table of special strings. Format for each row is: % {list of strings to recognize}, resulting python expr % Note: case sensitive % Note: python expr should be in list for identity "sym(sympy(x)) == x" table = {{'pi'} 'S.Pi'; ... {'inf' 'Inf' 'oo'} 'S.Infinity'; ... {'NaN' 'nan'} 'S.NaN'; ... {'zoo'} 'S.ComplexInfinity'}; s = ''; assert (ischar (x)) for j = 1:length (table) for n = 1:length (table{j, 1}) if (strcmp (x, table{j, 1}{n}) || strcmp (x, ['+' table{j, 1}{n}])) s = table{j, 2}; return elseif (strcmp (x, ['-' table{j, 1}{n}])) s = ['-' table{j, 2}]; return end end end end symbolic-3.1.1/inst/@sym/private/do_highbyte_escapes.m0000644000000000000000000000422514405647405017744 0ustar function r = do_highbyte_escapes(s) %DO_HIGHBYTE_ESCAPES Convert "\x"-escaped strings to bytes % Convert sequences strings of the form '\xNM' into characters. % Here NM is a two-char hex string. Typically sequences of these % represent utf-8 characters. % % Example: % >> s = 'aaa\xe2\x8c\x88bbb\xe2\x8c\x89ccc'; % >> do_highbyte_escapes(s) % ans = aaa⌈bbb⌉ccc % % % But be careful for escaped backslashes that happen to be followed % by an 'x'; substrings with an even number of backspaces such as % '\\x' or '\\\\x' should not be converted. Examples: % >> s = 'aaa \xe2\x8c\x88 bbb \\xe2\\x8c\\\\x89 ccc'; % >> do_highbyte_escapes(s) % ans = aaa ⌈ bbb \\xe2\\x8c\\\\x89 ccc % % >> s = 'aaa \\\xe2\x8c\x88 bbb'; % >> do_highbyte_escapes(s) % ans = aaa \\⌈ bbb % % % Copyright 2016-2017, 2022 Colin B. Macdonald % % Copying and distribution of this file, with or without modification, % are permitted in any medium without royalty provided the copyright % notice and this notice are preserved. This file is offered as-is, % without any warranty. % pad the string with one char in case string starts with \x s = ['_' s]; i = 2; % start at 2 b/c of this padding [TE, NM] = regexp(s, '(?<=[^\\])(?:\\\\)*\\x(?..)', 'tokenExtents', 'names'); % 1. 2. 3. 4. % explanation: % 1. look behind ... % 2. ... for anything that isn't '\' % 3. zero or more pairs '\\' % 4. two chars as a named token if (isempty(TE)) r = s(i:end); return end % get the two-char hex numbers make them into bytes dec = char (hex2dec (struct2cell (NM))); % faster: %d = uint8('ee'); %d = (d >= 48 & d <= 57).*(d-48) + (d >= 97 & d <= 102).*(d-87); %d = 16*d(1) + d(2); % Yep, its a loop :( Takes about 0.02s for a string of length 1179 % containing 291 escaped unicode chars. Roughly 6 times slower than % the hex2dec bit above. r = ''; for j=1:length(TE) r = [r s(i:TE{j}(1)-3) dec(j)]; i = TE{j}(2)+1; end r = [r s(i:end)]; if (~ exist ('OCTAVE_VERSION', 'builtin')) % matlab is not UTF-8 internally r = native2unicode(uint8(r)); end end symbolic-3.1.1/inst/@sym/private/double_to_sym_exact.m0000644000000000000000000000243114405647405020001 0ustar %% Copyright (C) 2017, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @deftypefun {@var{y} =} double_to_sym_exact (@var{x}) %% Convert a double value to the equivalent rational sym %% %% Private helper function. %% %% @end deftypefun function y = double_to_sym_exact (x) if (isnan (x)) y = pycall_sympy__ ('return S.NaN'); elseif (isinf (x) && x < 0) y = pycall_sympy__ ('return -S.Infinity'); elseif (isinf (x)) y = pycall_sympy__ ('return S.Infinity'); else %% Rational will exactly convert from a float y = pycall_sympy__ ('return Rational(_ins[0])', x); end end symbolic-3.1.1/inst/@sym/private/double_to_sym_heuristic.m0000644000000000000000000000462514405647405020703 0ustar %% Copyright (C) 2017, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @deftypefun {@var{y} =} double_to_sym_heuristic (@var{x}, @var{ratwarn}, @var{argnstr}) %% Convert a double value to a nearby "nice" sym %% %% Private helper function. %% %% @end deftypefun function y = double_to_sym_heuristic (x, ratwarn, argnstr) assert (isempty (argnstr)) if (isnan (x)) y = pycall_sympy__ ('return S.NaN'); elseif (isinf (x) && x < 0) y = pycall_sympy__ ('return -S.Infinity'); elseif (isinf (x)) y = pycall_sympy__ ('return S.Infinity'); elseif (isequal (x, pi)) %% Special case for pi y = pycall_sympy__ ('return S.Pi'); elseif (isequal (x, -pi)) y = pycall_sympy__ ('return -S.Pi'); elseif (isequal (x, exp (1))) %% Special case for e y = pycall_sympy__ ('return sympy.exp(1)'); elseif (isequal (x, -exp (1))) y = pycall_sympy__ ('return -sympy.exp(1)'); elseif ((abs (x) < flintmax) && (mod (x, 1) == 0)) y = pycall_sympy__ ('return Integer(_ins[0])', int64 (x)); else %% Find the nearest rational, rational*pi or sqrt(integer) if (ratwarn) warning('OctSymPy:sym:rationalapprox', ... 'passing floating-point values to sym is dangerous, see "help sym"'); end [N1, D1] = rat (x); [N2, D2] = rat (x / pi); N3 = round (x^2); err1 = abs (N1 / D1 - x); err2 = abs ((N2*pi) / D2 - x); err3 = abs (sqrt (N3) - x); if (err1 <= err3) if (err1 <= err2) y = pycall_sympy__ ('return Rational(*_ins)', int64 (N1), int64 (D1)); else y = pycall_sympy__ ('return Rational(*_ins)*S.Pi', int64 (N2), int64 (D2)); end else y = pycall_sympy__ ('return sqrt(Integer(*_ins))', int64 (N3)); end end end symbolic-3.1.1/inst/@sym/private/elementwise_op.m0000644000000000000000000000653214405647405016776 0ustar %% Copyright (C) 2014, 2016, 2018-2019, 2022 Colin B. Macdonald %% Copyright (C) 2016 Lagu %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defun elementwise_op (@var{scalar_fcn}, @var{A}) %% @defunx elementwise_op (@var{scalar_fcn}, @var{A}, @var{B}) %% @defunx elementwise_op (@var{scalar_fcn}, @var{A}, @var{B}, @dots{}) %% Apply a scalar function element-by-element to the inputs. %% %% Examples: %% @example %% A = sym(3) %% B = sym([4 5 6; 7 4 2]) %% elementwise_op('lambda a, b: a % b', A, B) %% %% elementwise_op('round', B) %% @end example %% %% If you need use a complicated function you can declare an @code{_op} %% python function in a cell array and use it: %% %% @example: %% scalar_fcn = @{ 'def _op(a,b,c,d):'; ' return a % c + d / b' @}; %% A = 3; %% B = [1 2;3 4]; %% C = inv(B); %% D = 1; %% elementwise_op(scalar_fcn, sym(A), sym(B), sym(C), sym(D)) %% @end example %% %% As you can see you need declare when you need a sym object, %% or the function will use it in a literal way. %% %% @example %% syms x %% A = [x -x sin(x)/x]; %% B = x; %% C = [-inf, 0, inf]; %% D = '+'; %% elementwise_op('lambda a, b, c, d: a.limit(b, c, d)', sym(A), sym(B), sym(C), D) %% @end example %% %% This example will send @code{D} (@qcode{'+'}) to the function without %% converting the string to a symbol. %% %% Notes: %% This function doesn't work with MatrixSymbol. %% Matrix arguments must all have equal sizes. %% %% @end defun function z = elementwise_op(scalar_fcn, varargin) if (iscell(scalar_fcn)) %assert strncmp(scalar_fcn_str, 'def ', 4) cmd = scalar_fcn; else cmd = {['_op = ' scalar_fcn]}; end % Dear hacker from the distant future: to enable Tensor support, try % using `isinstance(A, (MatrixBase, NDimArray))` in a few places below. % note: cmd is already cell array, hence [ concatenates with it cmd = [ cmd % Make sure all matrices in the input are the same size, and set q to one of them 'q = None' 'for A in _ins:' ' if isinstance(A, MatrixBase):' ' if q is None:' ' q = A' ' else:' ' assert q.shape == A.shape, "Matrices in input must all have the same shape"' % all inputs were scalars: 'if q is None:' ' return _op(*_ins)' % at least one input was a matrix: '# dbout(f"at least one matrix param, shape={q.shape}")' 'elements = []' 'for i in range(0, len(q)):' ' elements.append(_op(*[k[i] if isinstance(k, MatrixBase) else k for k in _ins]))' 'return Matrix(*q.shape, elements)' ]; z = pycall_sympy__ (cmd, varargin{:}); end symbolic-3.1.1/inst/@sym/private/ineq_helper.m0000644000000000000000000000222314405647405016243 0ustar %% Copyright (C) 2014 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . function t = ineq_helper(op, fop, lhs, rhs, nanspecial) if (nargin == 4) nanspecial = 'S.false'; end % FIXME: this will need to catch exceptions soon op = { 'def _op(lhs, rhs):' ' # workaround sympy nan behaviour, Issue #9' ' if lhs is nan or rhs is nan:' [' return ' nanspecial] [' return ' fop '(lhs, rhs)'] }; t = elementwise_op (op, lhs, rhs); end symbolic-3.1.1/inst/@sym/private/is_same_shape.m0000644000000000000000000000171614405647405016556 0ustar %% Copyright (C) 2014 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . function t = is_same_shape(x,y) %IS_SAME_SHAPE Inputs have same shape % Note does not say same type d1 = size(x); d2 = size(y); t = ( ... (length(d1) == length(d2)) && ... (all(d1 == d2)) ... ); symbolic-3.1.1/inst/@sym/private/is_valid_index.m0000644000000000000000000000302414405647405016731 0ustar %% Copyright (C) 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defun is_valid_index (@var{x}) %% Could the input in principle be used as an index. %% %% Note it doesn't check that its valid for any particular %% indexing operation, just that its not too crazy (e.g., %% a non-integer). %% %% Specific things that are valid: %% @itemize %% @item strings @qcode{':'} and @qcode{'@w{}'} %% @item empties such as @qcode{[]} %% @item boolean %% @item finite real integers %% @end itemize %% @end defun function r = is_valid_index(x) if (ischar (x)) r = strcmp (x, ':') || strcmp (x, ''); return end if (isempty (x)) r = true; return end if (islogical (x)) r = true; return end % check that all are integers x = x(:); r = all (isreal (x) & isfinite (x) & (x == floor(x))); end symbolic-3.1.1/inst/@sym/private/make_sym_matrix.m0000644000000000000000000000452714405647405017152 0ustar %% Copyright (C) 2014, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . function A = make_sym_matrix(As, sz) % private helper function for making symbolic matrix assert (ischar (As), 'Cannot create symbolic matrix with non-string') assert (isequal (size(sz), [1 2]), 'Cannot create symbolic matrix with that size') % regexp: non-digit followed by any word assert (~ isempty (regexp (As, '^\D\w*$')), 'Cannot create symbolic matrix with expression "%s"', As) if (isa(sz, 'sym')) cmd = { 'As, (n, m), = _ins' 'if n.is_Integer and m.is_Integer:' ' return (0, int(n), int(m)) ' 'else:' ' return (1, sympy.MatrixSymbol(As, n, m), 0)' }; [flag, n, m] = pycall_sympy__ (cmd, As, sz); if (flag) A = n; return end else n = int32(sz(1)); m = int32(sz(2)); end % FIXME: returning an appropriate MatrixSymbol is nice idea, % but would need more work on IPC, size(). The ideal thing % might be a string representation that looks like this % when displayed in Octave, but is represented with a % MatrixSymbol internally. cmd = { 'As, n, m = _ins' '#A = sympy.MatrixSymbol(As, n, m)' 'if n == 0 or m == 0:' ' return sympy.Matrix(n, m, []),' ' #sympy.MatrixSymbol(As, n, m),' % broken? 'if n < 10 and m < 10:' ' extra = ""' 'else:' ' extra = "_"' 'L = [[Symbol("%s%d%s%d" % (As, i+1, extra, j+1)) \' ' for j in range(0, m)] \' ' for i in range(0, n)]' 'A = sympy.Matrix(L)' 'return A,' }; A = pycall_sympy__ (cmd, As, n, m); end symbolic-3.1.1/inst/@sym/private/mat_access.m0000644000000000000000000000540214405647405016054 0ustar %% Copyright (C) 2014, 2023 Colin B. Macdonald %% Copyright (C) 2016 Abhinav Tripathi %% Copyright (C) 2017 Mike Miller %% Copyright (C) 2017 NVS Abhilash %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @defun mat_access (@var{A}, @var{subs}) %% Private helper routine for symbolic array access. %% %% Big piece of spaghetti code :( %% %% @end defun function z = mat_access(A, subs) if ((length(subs) == 1) && (islogical(subs{1}))) %% A(logical) subs{1} = find (subs{1}); idx = subs{1}; if (isempty (idx)) % fix the dimensions when both A and idx are vectors if (max (size (idx)) > 0) if (iscolumn (A)) idx = idx(:); elseif (isrow (A)) idx = idx(:)'; end end z = sym (zeros (size (idx))); return; end elseif ( (length(subs) == 1) && strcmp(subs{1}, ':') ) %% A(:) z = reshape(A, numel(A), 1); return end if (length (subs) == 1) %% linear index into a matrix/vector/scalar A i = subs{1}; if strcmp(i, '') i = []; % yes empty str ok here end if (ischar(i)) error(['invalid indexing, i="' i '"']) end % Octave 8 does not raise error from ind2sub so we do it ourselves sz = size (A); if (i > prod (sz)) error ('%d is out of bound %d (dimensions are %dx%d)\n', i, prod (sz), sz) end [r, c] = ind2sub (sz, i); z = mat_rclist_access(A, r(:), c(:)); % output shape, see also logic in comments in mat_mask_access.m if (~isscalar(A) && isrow(A) && isvector(i)) z = reshape(z, 1, length(i)); % i might be row or col elseif (~isscalar(A) && iscolumn(A) && isvector(i)) assert(iscolumn(z)) else % all other cases we take shape of i z = reshape(z, size(i)); end return elseif (length(subs) == 2) r = subs{1}; c = subs{2}; assert( isvector(r) || isempty(r) || strcmp(r, ':') ) assert( isvector(c) || isempty(c) || strcmp(c, ':') ) if strcmp(r, ''), r = []; end if strcmp(c, ''), c = []; end z = mat_rccross_access(A, r, c); return else error('Unknown indexing') end end symbolic-3.1.1/inst/@sym/private/mat_rccross_access.m0000644000000000000000000000601514405647405017613 0ustar %% Copyright (C) 2014, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @defun mat_rccross_access (@var{A}, @var{r}, @var{c}) %% Private helper routine for symbolic array access. %% %% Access entries of @var{A} that are the cross product of vectors %% @var{r} and @var{c}. @var{r} and @var{c} could be strings. %% Namely @code{':'}. %% %% @var{r} and @var{c} could contain duplicates. This is one %% reason why this code doesn't easily replace %% @code{mat_rclist_access}. %% %% @var{z} return is small matrix with @code{len(@var{c})} columns %% and @code{len(@var{r})} rows. %% %% @end defun function z = mat_rccross_access(A, r, c) if (ischar(r) && ischar(c) && strcmp(r, ':') && strcmp(c, ':')) z = A; return end %if both expressible as py slices... % FIXME: Could optimize these cases [n, m] = size(A); if (isnumeric(r) && isempty(r)) % no-op elseif (isnumeric(r) && isvector(r)) assert(all(r >= 1) && all(r <= n), 'index out of range') elseif (strcmp(r, ':')) r = 1:n; elseif (islogical(r) && isvector(r) && (length(r) == n)) I = r; r = 1:n; r = r(I); else error('unknown 2d-indexing in rows') end if (isnumeric(c) && isempty(c)) % no-op elseif (isnumeric(c) && isvector(c)) assert(all(c >= 1) && all(c <= m), 'index out of range') elseif (strcmp(c,':')) c = 1:m; elseif (islogical(c) && isvector(c) && (length(c) == m)) J = c; c = 1:m; c = c(J); else error('unknown 2d-indexing in columns') end cmd = { '(A, rr, cc) = _ins' 'if not A.is_Matrix:' ' A = sp.Matrix([A])' 'M = [[0]*len(cc) for i in range(len(rr))]' 'for i in range(0, len(rr)):' ' for j in range(0, len(cc)):' ' M[i][j] = A[rr[i], cc[j]]' '# M = sp.Matrix(M)' '# not quite b/c of preserving 3x0 and 0x3 for example' 'M = sp.Matrix(len(rr), len(cc), [c for r in M for c in r])' 'return M,' }; rr = num2cell(int32(r-1)); cc = num2cell(int32(c-1)); z = pycall_sympy__ (cmd, A, rr, cc); % FIXME: here's some code could be used for slices if (1==0) cmd = { 'A = _ins[0]' ... 'r = slice(_ins[1],_ins[2])' ... 'c = slice(_ins[3],_ins[4])' ... 'M = A[r,c]' ... 'return M,' }; z = pycall_sympy__ (cmd, A, r1-1, r2, c1-1, c2); end end symbolic-3.1.1/inst/@sym/private/mat_rclist_access.m0000644000000000000000000000314014405647405017431 0ustar %% Copyright (C) 2014, 2016, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @defun mat_rclist_access (@var{A}, @var{r}, @var{c}) %% Private helper routine for sym array access via lists of row/col. %% %% @code{(r(i),c(i))} specify entries of the matrix @var{A}. %% Returns a column vector of these extracted from @var{A}. %% %% @end defun function z = mat_rclist_access(A, r, c) if ~( isvector(r) && isvector(c) && (length(r) == length(c)) ) error('this routine is for a list of rows and cols'); end cmd = { '(A, rr, cc) = _ins' 'if A is None or not A.is_Matrix:' ' A = sp.Matrix([A])' 'n = len(rr)' 'M = [[0] for i in range(n)]' 'for i in range(0, n):' ' M[i][0] = A[rr[i],cc[i]]' 'M = sp.Matrix(M)' 'return M,' }; rr = num2cell(int32(r-1)); cc = num2cell(int32(c-1)); z = pycall_sympy__ (cmd, A, rr, cc); end symbolic-3.1.1/inst/@sym/private/mat_rclist_asgn.m0000644000000000000000000000704614405647405017131 0ustar %% Copyright (C) 2014, 2016-2017, 2019, 2022 Colin B. Macdonald %% Copyright (C) 2020 Mike Miller %% Copyright (C) 2020 Fernando Alvarruiz %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @defun mat_rclist_asgn (@var{A}, @var{r}, @var{c}, @var{B}) %% Private helper routine for sym array assigment using lists. %% %% @code{(R(i),C(i))} specify entries of the matrix @var{A}. %% We execute @code{A(R(i),C(i)) = B(i)}. %% %% Notes: %% @itemize %% @item @var{B} is accessed with linear indexing. %% @item @var{B} might be a scalar, used many times. %% @item @var{A} might need to get bigger, if so it will be padded %% with zeros. %% @end itemize %% %% @end defun function z = mat_rclist_asgn(A, r, c, B) if (isempty (r) && isempty (c) && (isempty (B) || isscalar (B))) z = A; return end if ~( isvector(r) && isvector(c) && (length(r) == length(c)) ) error('this routine is for a list of rows and cols'); end if ((numel(B) == 1) && (numel(r) > 1)) B = repmat(B, size(r)); end if (length(r) ~= numel(B)) error('not enough/too much in B') end % Easy trick to copy A into larger matrix AA: % AA = sp.Matrix.zeros(n, m) % AA[0, 0] = A % Also usefil: .copyin_matrix cmd = { '(A, r, c, B) = _ins' '# B linear access fix, transpose for sympy row-based' 'if B is None or not B.is_Matrix:' ' B = sp.Matrix([[B]])' 'BT = B.T' '# make a resized copy of A, and copy existing stuff in' 'if isinstance(A, list):' ' assert len(A) == 0, "unexpectedly non-empty list: report bug!"' ' n = max(max(r) + 1, 1)' ' m = max(max(c) + 1, 1)' ' AA = [[0]*m for i in range(n)]' 'elif A is None or not isinstance(A, MatrixBase):' ' # we have non-matrix, put in top-left' ' n = max(max(r) + 1, 1)' ' m = max(max(c) + 1, 1)' ' AA = [[0]*m for i in range(n)]' ' AA[0][0] = A' 'else:' ' # build bigger matrix' ' n = max(max(r) + 1, A.rows)' ' m = max(max(c) + 1, A.cols)' ' AA = [[0]*m for i in range(n)]' ' # copy current matrix in' ' for i in range(A.rows):' ' for j in range(A.cols):' ' AA[i][j] = A[i, j]' '# now insert the new bits from B' 'for i, (r, c) in enumerate(zip(r, c)):' ' AA[r][c] = BT[i]' 'return sp.Matrix(AA),' }; rr = num2cell(int32(r-1)); cc = num2cell(int32(c-1)); z = pycall_sympy__ (cmd, A, rr, cc, B); % a simpler earlier version, but only for scalar r,c %cmd = { '(A, r, c, b) = _ins' % 'if not A.is_Matrix:' % ' A = sp.Matrix([[A]])' % 'AA = sp.Matrix.zeros(max(r+1, A.rows), max(c+1, A.cols))' % 'AA[0, 0] = A' % 'AA[r, c] = b' % 'return AA,' }; end symbolic-3.1.1/inst/@sym/private/mat_replace.m0000644000000000000000000001237014405647405016230 0ustar %% Copyright (C) 2014-2016, 2019, 2022-2023 Colin B. Macdonald %% Copyright (C) 2016 Lagu %% Copyright (C) 2016 Abhinav Tripathi %% Copyright (C) 2017 NVS Abhilash %% Copyright (C) 2020 Fernando Alvarruiz %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @defun mat_replace (@var{A}, @var{subs}, @var{rhs}) %% Private helper routine for setting symbolic array entries. %% %% @end defun function z = mat_replace(A, subs, b) if (length (subs) == 1 && islogical (subs{1})) %% A(logical) = B subs{1} = find (subs{1}); if isempty (subs{1}) z = A; return; end end %% Check when b is [] if (isempty(b)) switch length(subs) case 1 if strcmp(subs{1}, ':') z = sym([]); return end if (isempty (subs{1})) z = A; return end if rows(A) == 1 z = delete_col(A, subs{1}); return elseif columns(A) == 1 z = delete_row(A, subs{1}); return else z = sym([]); for i=1:A.size(2) z = [z subsref(A, substruct ('()', {':', i})).']; end z = subsasgn (z, substruct ('()', {subs{1}}), []); return end case 2 if (isempty (subs{1}) || isempty (subs{2})) z = A; return end if strcmp(subs{1}, ':') if strcmp(subs{2}, ':') z = sym(zeros(0,columns(A))); return else z = delete_col(A, subs{2}); return end elseif strcmp(subs{2}, ':') z = delete_row(A, subs{1}); return else error('A null assignment can only have one non-colon index.'); % Standard octave error end otherwise error('Unexpected subs input') end end if (length(subs) == 1 && strcmp(subs{1}, ':') && length(b) == 1) z = pycall_sympy__ ('return ones(_ins[0], _ins[1])*_ins[2],', uint64(A.size(1)), uint64(A.size(2)), sym(b)); return elseif (length(subs) == 1) % can use a single index to grow a vector, so we carefully deal with % vector vs linear index to matrix (not required for access) [n,m] = size(A); if (n == 0 || n == 1) c = subs{1}; r = ones(size(c)); elseif (m == 1) r = subs{1}; c = ones(size(r)); else % linear indices into 2D array % Octave 8 does not raise error from ind2sub so we do it ourselves sz = size (A); i = subs{1}; if (i > prod (sz)) error ('%d is out of bound %d (dimensions are %dx%d)\n', i, prod (sz), sz) end [r, c] = ind2sub (size (A), i); % keep all the indices in a row vector r = reshape (r, 1, []); c = reshape (c, 1, []); end elseif (length(subs) == 2) r = subs{1}; c = subs{2}; [n,m] = size(A); if (isnumeric(r) && ((isvector(r) || isempty(r)))) % no-op elseif (strcmp(r,':')) r = 1:n; elseif (islogical(r) && isvector(r) && (length(r) == n)) I = r; r = 1:n; r = r(I); else error('unknown 2d-indexing in rows') end if (isnumeric(c) && ((isvector(c) || isempty(c)))) % no-op elseif (strcmp(c,':')) c = 1:m; elseif (islogical(c) && isvector(c) && (length(c) == m)) J = c; c = 1:m; c = c(J); else error('unknown 2d-indexing in columns') end [r,c] = ndgrid(r,c); if ~(isscalar (b) || (isvector (r) && isvector (b)) || is_same_shape (r, b)) % vectors may have diff orientations but if we have matrices then % they must have the same shape (Octave/Matlab do this for double) error('A(I,J,...) = X: dimensions mismatch') end r = r(:); c = c(:); else error('unknown indexing') end z = mat_rclist_asgn(A, r, c, b); end function z = delete_col(A, subs) if isscalar (A) z = sym(zeros (1, 0)); else cmd = { 'A, subs = _ins' 'if isinstance(subs, Integer):' ' A.col_del(subs - 1)' ' return A,' 'for i in sorted(subs, reverse=True):' ' A.col_del(i - 1)' 'return A,' }; z = pycall_sympy__ (cmd, A, sym(subs)); end end function z = delete_row(A, subs) if isscalar (A) % no test coverage: not sure how to hit this z = sym(zeros (0, 1)); else cmd = { 'A, subs = _ins' 'if isinstance(subs, Integer):' ' A.row_del(subs - 1)' ' return A,' 'for i in sorted(subs, reverse=True):' ' A.row_del(i - 1)' 'return A,' }; z = pycall_sympy__ (cmd, A, sym(subs)); end end symbolic-3.1.1/inst/@sym/private/numeric_array_to_sym.m0000644000000000000000000000265014405647405020206 0ustar %% Copyright (C) 2014, 2015, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . function z = numeric_array_to_sym(A) %private helper for sym ctor % convert an array to syms, currently on 1D, 2D. [n, m] = size(A); if (n == 0 || m == 0) cmd = { sprintf('return sp.Matrix(%d, %d, []),', n, m) }; z = pycall_sympy__ (cmd); return end Ac = cell(n,1); for i=1:n % we want all sym creation to go through the ctor. Ac{i} = cell(m,1); for j=1:m Ac{i}{j} = sym(A(i,j)); end end %Ac = {{x 2}; {3 4}; {8 9}}; d = size(A); if (length(d) > 2) error('conversion not supported for arrays of dim > 2'); end cmd = { 'L = _ins[0]' 'M = sp.Matrix(L)' 'return M,' }; z = pycall_sympy__ (cmd, Ac); symbolic-3.1.1/inst/@sym/private/uniop_bool_helper.m0000644000000000000000000000523514405647405017462 0ustar %% Copyright (C) 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . function r = uniop_bool_helper(x, scalar_fcn, opt, varargin) % SCALAR_FCN can either be the name of a function or a lambda % definition of a new function. It can be multiline cell array % defining a a new function called "sf". % % Many SymPy commands return True/False/None (or S.true/S.false/None), % where None is used for "don't know" or "can't tell". % The string OPT describes what to do about this. % 'bool': the default, always return Octave bool (logical) array, % maps None to false. % 'sym': always return symbolic array, which might contain True, % False, None. % 'symIfAnyNone': if the result has any None, return a symbolic % array, otherwise return a bool array. % % If you'd like to raise an error on None, do so in SCALAR_FCN. % See isprime.m for example. % % Any additional arguments after OPT are passed to SCALAR_FCN as-is. if (iscell(scalar_fcn)) cmd = scalar_fcn; else cmd = {['sf = ' scalar_fcn]}; end if ((nargin < 3) || isempty(opt)) opt = 'bool'; end switch opt case 'bool' cmd = [ cmd 'x = _ins[0]' 'pp = _ins[1:]' 'if x is not None and x.is_Matrix:' ' # bool will map None to False' ' return [bool(sf(a, *pp)) for a in x.T],' 'return bool(sf(x, *pp))' ]; r = pycall_sympy__ (cmd, x, varargin{:}); if (~isscalar(x)) r = reshape(cell2mat(r), size(x)); end case 'sym' warning('FIXME: not working for scalars') cmd = [ cmd 'x = _ins[0]' 'pp = _ins[1:]' 'if x if not None and x.is_Matrix:' ' return x.applyfunc(sf, *pp)' 'return sf(x, *pp)' ]; r = pycall_sympy__ (cmd, x, varargin{:}); case 'symIfAnyNone' error('FIXME: not implemented') otherwise error('uniop_bool_helper: option "%s" not implemented', opt) end end symbolic-3.1.1/inst/@sym/private_disp_name.m0000644000000000000000000000235714405647405015777 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @defmethod @@sym private_disp_name (@var{x}, @var{name}) %% A string appropriate for representing the name of this sym. %% %% Private method: this is not the method you are looking for. %% %% @end defmethod function s = private_disp_name(x, input_name) s = input_name; % subclasses might do something more interesting, but they should % be careful to ensure empty input_name gives empty s. end %!test %! syms x %! s = private_disp_name(x, 'x'); %! assert (strcmp (s, 'x')) symbolic-3.1.1/inst/@sym/prod.m0000644000000000000000000000517314405647405013251 0ustar %% Copyright (C) 2014-2016, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym prod (@var{x}) %% @defmethodx @@sym prod (@var{x}, @var{n}) %% Product of symbolic expressions. %% %% Example: %% @example %% @group %% syms x y z %% prod([x y z]) %% @result{} (sym) x⋅y⋅z %% @end group %% @end example %% %% Can specify row or column sums using @var{n}: %% @example %% @group %% f = prod([x y; x z], 1) %% @result{} f = (sym 1×2 matrix) %% %% ⎡ 2 ⎤ %% ⎣x y⋅z⎦ %% %% f = prod([x y; x z], 2) %% @result{} f = (sym 2×1 matrix) %% %% ⎡x⋅y⎤ %% ⎢ ⎥ %% ⎣x⋅z⎦ %% %% @end group %% @end example %% %% @seealso{@@sym/sum, @@sym/symprod} %% @end defmethod function y = prod(x, n) x = sym(x); if (nargin == 1) if (isrow(x)) n = 2; elseif (iscolumn(x)) n = 1; else n = 1; end elseif (nargin == 2) n = double(n); else print_usage (); end cmd = { 'A = _ins[0]' 'if not isinstance(A, sympy.MatrixBase):' ' A = Matrix([A])' 'B = sp.Matrix.zeros(A.rows, 1)' 'for i in range(0, A.rows):' ' B[i] = prod(A.row(i))' 'return B' }; if (n == 1) y = pycall_sympy__ (cmd, transpose(x)); y = transpose(y); elseif (n == 2) y = pycall_sympy__ (cmd, x); else print_usage (); end end %!error prod (sym(1), 2, 3) %!error prod (sym(1), 42) %!shared x,y,z %! syms x y z %!assert (isequal (prod (x), x)) %!assert (isequal (prod ([x y z]), x*y*z)) %!assert (isequal (prod ([x; y; z]), x*y*z)) %!assert (isequal (prod ([x y z], 1), [x y z])) %!assert (isequal (prod ([x y z], 2), x*y*z)) %!shared a,b %! b = [1 2; 3 4]; a = sym(b); %!assert (isequal (prod(a), prod(b))) %!assert (isequal (prod(a,1), prod(b,1))) %!assert (isequal (prod(a,2), prod(b,2))) %!test %! % weird inputs %! a = prod('xx', sym(1)); %! assert (isequal (a, sym('xx'))) symbolic-3.1.1/inst/@sym/psi.m0000644000000000000000000000756514405647405013107 0ustar %% Copyright (C) 2015, 2016, 2018 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym psi (@var{x}) %% @defmethodx @@sym psi (@var{k}, @var{x}) %% Symbolic polygamma function. %% %% The first polygamma (or ``psi'') function is the logarithmic %% derivative of the gamma function: %% @example %% @group %% syms x %% psi(x) %% @result{} (sym) polygamma(0, x) %% diff(log(gamma(x))) %% @result{} (sym) polygamma(0, x) %% @end group %% @end example %% %% More generally, we have the @var{k}+1 derivative: %% @example %% @group %% psi(1, x) %% @result{} (sym) polygamma(1, x) %% diff(psi(x)) %% @result{} (sym) polygamma(1, x) %% diff(log(gamma(x)), 2) %% @result{} (sym) polygamma(1, x) %% @end group %% @end example %% %% @seealso{psi, @@sym/gamma, @@sym/gammainc} %% @end defmethod function W = psi(k, x) if (nargin == 1) x = k; k = 0; elseif (nargin == 2) % no-op else print_usage (); end W = elementwise_op ('polygamma', sym(k), sym(x)); end %!assert (isequal (psi (sym (1)), -eulergamma)) %!assert (isequal (psi (1, sym (1)), sym (pi)^2/6)) %!assert (isinf (psi (sym ('inf')))) %!test %! % compare to Maple: evalf(Psi(-101/100)); %! maple = vpa ('100.3963127058453949545769053445198842332424', 40); %! us = vpa (psi (sym (-101)/100), 40); %! assert (abs(double(maple-us)) < 1e-39) %!test %! % compare to Maple: evalf(Psi(1, 3*I-2)); %! maple = vpa ('-0.1651414829219882371561038184133243839778799', 40) - ... %! vpa ('0.1960040752985823275302034466611711263617296j', 40); %! us = vpa (psi (1, sym (-2) + sym(3i)), 40); %! assert (abs(double(maple-us)) < 1e-39) %!test %! % should match @double/psi %! if (exist ('psi','builtin')) %! assert (psi (pi), double (psi (sym (pi))), -3*eps) %! assert (psi (100), double (psi (sym (100))), -3*eps) %! assert (psi (1e-3), double (psi (1/sym (1e3))), -3*eps) %! if (exist ('OCTAVE_VERSION', 'builtin')) %! % 2014a doesn't support negative or complex arguments %! assert (psi (-1.5), double (psi (sym (-3)/2)), -3*eps) %! assert (psi (-8.3), double (psi (sym (-83)/10)),-4*eps) %! assert (psi (2i), double (psi (sym (2i))), -3*eps) %! assert (psi (10i+3), double (psi (sym (10i)+3)), -3*eps) %! end %! end %!test %! % @double/psi loses accuracy near the poles: note higher rel tol %! if (exist ('psi','builtin')) %! if (exist ('OCTAVE_VERSION', 'builtin')) %! assert (psi (-1.1), double (psi (sym (-11)/10)), -6*eps) %! assert (psi (-1.01), double (psi (sym (-101)/100)), -50*eps) %! end %! end % 2016-05: for k>0, @double/psi only does real positive %!test %! if (exist ('psi','builtin')) %! assert (psi (1, pi), double (psi (1, sym (pi))), -3*eps) %! assert (psi (1, 100), double (psi (1, sym (100))), -3*eps) %! assert (psi (1, 1e-4), double (psi (1, 1/sym (1e4))), -3*eps) %! end %!test %! if (exist ('psi','builtin')) %! assert (psi (2, pi), double (psi (2, sym (pi))), -3*eps) %! assert (psi (2, 1000), double (psi (2, sym (1000))), -3*eps) %! assert (psi (2, 1e-4), double (psi (2, 1/sym (1e4))), -3*eps) %! end %!test %! % round trip %! if (exist ('psi','builtin')) %! syms x %! f = psi (x); %! h = function_handle (f); %! A = h (1.1); %! B = psi (1.1); %! assert (A, B) %! end symbolic-3.1.1/inst/@sym/qr.m0000644000000000000000000001321014405647405012716 0ustar %% Copyright (C) 2014, 2016, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {[@var{Q}, @var{R}] =} qr (@var{A}) %% @deftypemethodx @@sym {[@var{Q}, @var{R}] =} qr (@var{A}, 0) %% @deftypemethodx @@sym {@var{R} =} qr (@var{A}) %% Symbolic QR factorization of a matrix. %% %% Example: %% @example %% @group %% A = sym([1 1; 1 0]); %% %% [Q, R] = qr (A) %% @result{} Q = (sym 2×2 matrix) %% %% ⎡√2 √2 ⎤ %% ⎢── ── ⎥ %% ⎢2 2 ⎥ %% ⎢ ⎥ %% ⎢√2 -√2 ⎥ %% ⎢── ────⎥ %% ⎣2 2 ⎦ %% %% @result{} R = (sym 2×2 matrix) %% %% ⎡ √2⎤ %% ⎢√2 ──⎥ %% ⎢ 2 ⎥ %% ⎢ ⎥ %% ⎢ √2⎥ %% ⎢0 ──⎥ %% ⎣ 2 ⎦ %% @end group %% @end example %% %% Passing an extra argument of @code{0} gives an ``economy-sized'' %% factorization. This is currently the default behaviour even without %% the extra argument. In fact the result may even more minimal than %% the double precision @ref{qr}; when the input has low rank, a %% rectangular rank-revealing result is returned: %% @example %% @group %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.7.1")')) %% [Q, R] = qr (sym ([6 2; 6 2])) %% @result{} Q = (sym 2×1 matrix) %% ⎡√2⎤ %% ⎢──⎥ %% ⎢2 ⎥ %% ⎢ ⎥ %% ⎢√2⎥ %% ⎢──⎥ %% ⎣2 ⎦ %% @result{} R = (sym) [6⋅√2 2⋅√2] (1×2 matrix) %% @end group %% @end example %% We have one column in @code{Q} because the original matrix had %% rank one: %% @example %% @group %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.7.1")')) %% Q*R %% @result{} ans = (sym 2×2 matrix) %% ⎡6 2⎤ %% ⎢ ⎥ %% ⎣6 2⎦ %% @end group %% @end example %% %% But what of the extreme case of a zero matrix? %% @example %% @group %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.7.1")')) %% [Q, R] = qr (sym (zeros (2, 2))) %% @result{} Q = (sym) [] (empty 2×0 matrix) %% @result{} R = (sym) [] (empty 0×2 matrix) %% @end group %% @group %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.7.1")')) %% Q*R %% @result{} ans = (sym 2×2 matrix) %% ⎡0 0⎤ %% ⎢ ⎥ %% ⎣0 0⎦ %% @end group %% @end example %% Magic? Not really but don't let anyone tell you the dimensions %% of empty matrices are unimportant! %% %% @seealso{qr, @@sym/lu} %% @end deftypemethod function [varargout] = qr(A, ord) if (nargin == 2) assert (ord == 0, 'OctSymPy:NotImplemented', 'Matrix "B" form not implemented') elseif (nargin ~= 1) print_usage (); end if (nargout == 3) error ('OctSymPy:NotImplemented', 'permutation output form not implemented') end %% TODO: sympy QR routine could be improved, as of 2019: % * does not give permutation matrix % * probably numerically unstable for Float matrices cmd = { 'A = _ins[0]' ... 'if not A.is_Matrix:' ... ' A = sp.Matrix([A])' ... '(Q, R) = A.QRdecomposition()' ... 'return (Q, R)' }; [Q, R] = pycall_sympy__ (cmd, sym(A)); if (nargout <= 1) varargout{1} = R; else varargout{1} = Q; varargout{2} = R; end end %!error qr (sym(1), 2, 3) %!error [Q, R, P] = qr (sym(1)) %!error qr (sym(1), 1) %!test %! % scalar %! [q, r] = qr(sym(6)); %! assert (isequal (q, sym(1))) %! assert (isequal (r, sym(6))) %!test %! syms x positive %! [q, r] = qr(x); %! assert (isequal (q*r, x)) %! assert (isequal (q, sym(1))) %! assert (isequal (r, x)) %!test %! % trickier if x could be zero, fails on 1.8 <= SymPy <= 1.10.1 %! syms x %! [q, r] = qr(x); %! if (pycall_sympy__ ('return Version(spver) > Version("1.10.1")')) %! assert (isequal (q*r, x)) %! end %!test %! A = [1 2; 3 4]; %! B = sym(A); %! [Q, R] = qr(B); %! assert (isequal (Q*R, B)) %! assert (isequal (R(2,1), sym(0))) %! assert (isequal (Q(:,1)'*Q(:,2), sym(0))) %! %[QA, RA] = qr(A) %! %assert ( max(max(double(Q)-QA)) <= 10*eps) %! %assert ( max(max(double(Q)-QA)) <= 10*eps) %!test %! % non square: tall skinny %! A = sym([1 2; 3 4; 5 6]); %! [Q, R] = qr (A, 0); %! assert (size (Q), [3 2]) %! assert (size (R), [2 2]) %! assert (isequal (Q*R, A)) %!test %! % non square: short fat %! A = sym([1 2 3; 4 5 6]); %! [Q, R] = qr (A); %! assert (isequal (Q*R, A)) %!test %! % non square: short fat, rank deficient %! A = sym([1 2 3; 2 4 6]); %! [Q, R] = qr (A); %! assert (isequal (Q*R, A)) %! A = sym([1 2 3; 2 4 6; 0 0 0]); %! [Q, R] = qr (A); %! assert (isequal (Q*R, A)) %!test %! % rank deficient %! A = sym([1 2 3; 2 4 6; 0 0 0]); %! [Q, R] = qr (A); %! assert (isequal (Q*R, A)) %! A = sym([1 2 3; 2 5 6; 0 0 0]); %! [Q, R] = qr (A); %! assert (isequal (Q*R, A)) %!test %! % single return value R not Q %! assert (isequal (qr (sym(4)), sym(4))) symbolic-3.1.1/inst/@sym/rank.m0000644000000000000000000000322314405647405013232 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym rank (@var{A}) %% Rank of a symbolic matrix. %% %% Examples: %% @example %% @group %% A = sym([1 1; 2 0]); %% rank (A) %% @result{} ans = 2 %% @end group %% %% @group %% A = sym([1 2; 1 2]); %% rank (A) %% @result{} ans = 1 %% @end group %% @end example %% %% @seealso{@@sym/cond, @@sym/null, @@sym/orth} %% @end defmethod function r = rank(A) cmd = { 'A = _ins[0]' 'if not A.is_Matrix:' ' A = sp.Matrix([A])' 'return A.rank(),' }; r = pycall_sympy__ (cmd, A); end %!test %! A = sym([1 2; 3 4]); %! assert (rank(A) == 2); %!test %! A = sym([1 2 3; 3 4 5]); %! assert (rank(A) == 2); %!test %! A = sym([1 2; 1 2]); %! assert (rank(A) == 1); %!test %! A = sym([1 2; 3 4]); %! assert (rank(A) == 2); %!assert (rank(sym(1)) == 1); %!assert (rank(sym(0)) == 0); %!assert (rank(sym('x', 'positive')) == 1); symbolic-3.1.1/inst/@sym/rdivide.m0000644000000000000000000000734314405647405013734 0ustar %% Copyright (C) 2014, 2016, 2018-2019, 2022 Colin B. Macdonald %% Copyright (C) 2022 Alex Vong %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym rdivide {(@var{x}, @var{y})} %% @defopx Operator @@sym {@var{x} ./ @var{y}} {} %% Element-wise forward slash division of symbolic expressions. %% %% Example: %% @example %% @group %% syms x %% A = sym([1 137; 3 4]) %% @result{} A = (sym 2×2 matrix) %% ⎡1 137⎤ %% ⎢ ⎥ %% ⎣3 4 ⎦ %% B = [x pi; 2*x 8] %% @result{} B = (sym 2×2 matrix) %% ⎡ x π⎤ %% ⎢ ⎥ %% ⎣2⋅x 8⎦ %% A ./ B %% @result{} ans = (sym 2×2 matrix) %% ⎡ 1 137⎤ %% ⎢ ─ ───⎥ %% ⎢ x π ⎥ %% ⎢ ⎥ %% ⎢ 3 ⎥ %% ⎢─── 1/2⎥ %% ⎣2⋅x ⎦ %% @end group %% @end example %% %% Either @var{x} or @var{y} can be scalar: %% @example %% @group %% A ./ 2 %% @result{} ans = (sym 2×2 matrix) %% ⎡1/2 137/2⎤ %% ⎢ ⎥ %% ⎣3/2 2 ⎦ %% 2 ./ B %% @result{} ans = (sym 2×2 matrix) %% ⎡2 2 ⎤ %% ⎢─ ─ ⎥ %% ⎢x π ⎥ %% ⎢ ⎥ %% ⎢1 ⎥ %% ⎢─ 1/4⎥ %% ⎣x ⎦ %% @end group %% @end example %% %% Finally, the can both be scalar: %% @example %% @group %% 2 ./ x %% @result{} ans = (sym) %% 2 %% ─ %% x %% @end group %% @end example %% @seealso{@@sym/ldivide, @@sym/mrdivide} %% @end defop function z = rdivide(x, y) %% 2022-06: TODO cannot simply call hadamard_product for sympy <1.9, %% see upstream: https://github.com/sympy/sympy/issues/8557 cmd = { '(x,y) = _ins' 'if x.is_Matrix and y.is_Matrix:' ' y_eltwise_recip = y.applyfunc(lambda a: 1/a)' ' if Version(spver) < Version("1.9"):' ' try:' ' return x.multiply_elementwise(y_eltwise_recip)' ' except:' ' pass' ' return hadamard_product(x, y_eltwise_recip)' 'if not x.is_Matrix and y.is_Matrix:' ' return y.applyfunc(lambda a: x/a),' 'else:' ' return x/y,' }; z = pycall_sympy__ (cmd, sym(x), sym(y)); end %!test %! % scalar %! syms x %! assert (isa (x ./ 1, 'sym')) %! assert (isa (x ./ x, 'sym')) %! assert (isequal (x ./ 1, x)) %! assert (isequal (x ./ x, sym(1))) %!test %! % matrix-scalar %! D = 2*[0 1; 2 3]; %! A = sym(D); %! assert (isequal ( A./2 , D/2 )) %! assert (isequal ( A./sym(2) , D/2 )) %! assert (isequal ( D./sym(2) , D/2 )) %!test %! % matrix ./ matrix %! D = [1 2; 3 4]; %! A = sym(D); %! assert (isequal ( A./A , D./D )) %! assert (isequal ( A./D , D./D )) %! assert (isequal ( D./A , D./D )) %!test %! % matrix ./ matrix with symbols %! syms x y %! A = [x y; x^2 2*y]; %! B = [y x; x y]; %! assert (isequal ( A./A , sym(ones(2,2)) )) %! assert (isequal ( A./B , [x/y y/x; x 2] )) %!test %! % scalar ./ matrix %! D = [1 2; 3 4]; %! A = sym(D); %! assert (isequal ( 12./A , 12./D )) symbolic-3.1.1/inst/@sym/real.m0000644000000000000000000000345214405647405013226 0ustar %% Copyright (C) 2014, 2016, 2018-2019 Colin B. Macdonald %% Copyright (C) 2016 Lagu %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym real (@var{z}) %% Real part of a symbolic expression. %% %% Examples: %% @example %% @group %% syms z %% real(z) %% @result{} ans = (sym) re(z) %% @end group %% %% @group %% syms x real %% real(x) %% @result{} ans = (sym) x %% %% real([x sym(pi) + 6i 7 3i]) %% @result{} ans = (sym) [x π 7 0] (1×4 matrix) %% @end group %% @end example %% %% @seealso{@@sym/imag, @@sym/conj, @@sym/ctranspose} %% @end defmethod function y = real(z) if (nargin ~= 1) print_usage (); end y = elementwise_op ('re', z); end %!assert (isequal (real (sym (4) + 3i),4)) %!test %! syms x y real %! z = x + 1i*y; %! assert (isequal (real (z),x)) %!test %! syms x y real %! Z = [4 x + 1i*y; x 4 + 3i]; %! assert (isequal (real (Z),[4 x; x 4])) %!test %! syms x real %! d = exp (x*i); %! assert (isequal (real (d), cos (x))) %!test %! % round trip %! syms x %! d = 3 - 5i; %! f = real (x); %! A = real (d); %! h = function_handle (f); %! B = h (d); %! assert (A, B) symbolic-3.1.1/inst/@sym/repmat.m0000644000000000000000000000464714405647405013602 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym repmat (@var{A}, @var{n}, @var{m}) %% @defmethodx @@sym repmat (@var{A}, [@var{n} @var{m}]) %% Build symbolic block matrices. %% %% Examples: %% @example %% @group %% repmat([1 2 sym(pi)], 2, 3) %% @result{} (sym 2×9 matrix) %% ⎡1 2 π 1 2 π 1 2 π⎤ %% ⎢ ⎥ %% ⎣1 2 π 1 2 π 1 2 π⎦ %% %% repmat(sym(pi), [1 3]) %% @result{} (sym) [π π π] (1×3 matrix) %% @end group %% @end example %% %% @seealso{@@sym/vertcat, @@sym/horzcat} %% @end defmethod function B = repmat(A, n, m) if (nargin == 2) m = n(2); n = n(1); elseif (nargin == 3) % no-op else print_usage (); end cmd = { '(A, n, m) = _ins' 'if n == 0 or m == 0:' ' return sp.Matrix(n, m, [])' 'if A is None or not A.is_Matrix:' ' A = sp.Matrix([A])' 'L = [A]*m' 'B = sp.Matrix.hstack(*L)' 'L = [B]*n' 'B = sp.Matrix.vstack(*L)' 'return B' }; B = pycall_sympy__ (cmd, sym(A), int32(n), int32(m)); end %!test %! % simple %! syms x %! A = [x x x; x x x]; %! assert (isequal (repmat(x, 2, 3), A)) %!test %! % block cf double %! A = [1 2 3; 4 5 6]; %! B = sym(A); %! C = repmat(A, 2, 3); %! D = repmat(B, 2, 3); %! assert (isequal (C, D)) %!test %! % empty %! A = repmat(sym([]), 2, 3); %! assert (isempty(A)); %! assert (isequal (size(A), [0 0])) %!test %! % more empties %! A = repmat(sym(pi), [0 0]); %! assert (isequal (size(A), [0 0])) %! A = repmat(sym(pi), [0 3]); %! assert (isequal (size(A), [0 3])) %! A = repmat(sym(pi), [2 0]); %! assert (isequal (size(A), [2 0])) symbolic-3.1.1/inst/@sym/reshape.m0000644000000000000000000000640114405647405013727 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym reshape (@var{x}, @var{n}, @var{m}) %% @defmethodx @@sym reshape (@var{x}, [@var{n}, @var{m}]) %% Change the shape of a symbolic array. %% %% Examples: %% @example %% @group %% A = sym([1 2 3; 4 5 6]) %% @result{} A = (sym 2×3 matrix) %% ⎡1 2 3⎤ %% ⎢ ⎥ %% ⎣4 5 6⎦ %% @end group %% %% @group %% reshape(A, [3 2]) %% @result{} ans = (sym 3×2 matrix) %% ⎡1 5⎤ %% ⎢ ⎥ %% ⎢4 3⎥ %% ⎢ ⎥ %% ⎣2 6⎦ %% @end group %% %% @group %% reshape(A, 1, 6) %% @result{} ans = (sym) [1 4 2 5 3 6] (1×6 matrix) %% @end group %% @end example %% %% @seealso{@@sym/size, @@sym/resize} %% @end defmethod function z = reshape(a, n, m) % reshaping a double array with sym sizes if ~(isa(a, 'sym')) if (nargin == 2) z = reshape(a, double(n)); else z = reshape(a, double(n), double(m)); end return end if (nargin == 2) && (length(n) == 2) m = n(2); n = n(1); elseif (nargin == 3) % nop else print_usage (); end cmd = { '(A, n, m) = _ins' 'if A is not None and A.is_Matrix:' ' #sympy is row-based' ' return A.T.reshape(m,n).T' 'else:' ' if n != 1 or m != 1:' ' raise ValueError("cannot reshape scalar to non-1x1 size")' ' return A' }; z = pycall_sympy__ (cmd, sym(a), int32(n), int32(m)); end %!test %! d = [2 4 6; 8 10 12]; %! a = sym(d); %! assert (isequal (reshape(a, [1 6]), reshape(d, [1 6]))) %! assert (isequal (reshape(a, 1, 6), reshape(d, 1, 6))) %! assert (isequal (reshape(a, 2, 3), reshape(d, 2, 3))) %! assert (isequal (reshape(a, 3, 2), reshape(d, 3, 2))) %! assert (isequal (reshape(a, 6, 1), reshape(d, 6, 1))) %!shared x, a, d %! syms x %! a = [1 x^2 x^4; x x^3 x^5]; %! d = [0 2 4; 1 3 5]; %! %!test %! b = reshape(a, [1 6]); %! assert (isequal (size(b), [1 6])) %! assert (isequal (b, x.^reshape(d,1,6))) %! %!test %! b = reshape(a, [6 1]); %! assert (isequal (size(b), [6 1])) %! assert (isequal (b, x.^reshape(d,6,1))) %! b = reshape(b, size(a)); %! assert (isequal (size(b), [2 3])) %! assert (isequal (b, a)) %! %!test %! b = a(:); %! assert( isequal (size(b), [6 1])) %! assert( isequal (b, x.^(d(:)))) %! %!test %! % reshape scalar %! assert (logical( reshape(x, 1, 1) == x )) %! assert (logical( reshape(x, [1 1]) == x )) %!shared a %! syms a %!error reshape(a, 2, 1) %!error reshape(a, 1, 2) %!error reshape(a, 1, 1, 1) %!error reshape(a, [1, 1, 1]) symbolic-3.1.1/inst/@sym/resize.m0000644000000000000000000000516414405647405013606 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym resize {(@var{a}, @var{m})} %% @defmethodx @@sym resize {(@var{a}, @var{n}, @var{m})} %% @defmethodx @@sym resize {(@var{a}, [@var{n} @var{m}])} %% Resize a symbolic array, cropping or padding with zeros. %% %% Example %% @example %% @group %% A = sym([1 2; pi 4]) %% @result{} A = (sym 2×2 matrix) %% ⎡1 2⎤ %% ⎢ ⎥ %% ⎣π 4⎦ %% @end group %% %% @group %% resize(A, 1, 4) %% @result{} (sym) [1 2 0 0] (1×4 matrix) %% %% resize(A, [1 4]) %% @result{} (sym) [1 2 0 0] (1×4 matrix) %% @end group %% %% @group %% resize(A, 3) %% @result{} (sym 3×3 matrix) %% ⎡1 2 0⎤ %% ⎢ ⎥ %% ⎢π 4 0⎥ %% ⎢ ⎥ %% ⎣0 0 0⎦ %% @end group %% @end example %% %% @seealso{@@sym/reshape} %% @end defmethod function B = resize(A, n, m) if ((nargin == 2) && isscalar(n)) m = n; elseif ((nargin == 2) && (length(n) == 2)) m = n(2); n = n(1); elseif ((nargin == 3) && isscalar(n) && isscalar(m)) % no-op else print_usage (); end cmd = { 'A, n, m = _ins' 'if A is None or not A.is_Matrix:' ' A = Matrix([A])' 'return Matrix(n, m, lambda i,j: 0 if i >= A.rows or j >= A.cols else A[i,j])' }; B = pycall_sympy__ (cmd, sym(A), int32(n), int32(m)); end %!test %! B = sym([1 0 0; 0 0 0]); %! assert (isequal (resize (sym(1), 2, 3), B)) %! assert (isequal (resize (sym(1), [2 3]), B)) %!test %! B = sym([1 0; 0 0]); %! assert (isequal (resize (sym(1), 2), B)) %!test %! A = sym([pi 2; 3 4]); %! assert (isequal (resize (A, 1), sym(pi))) %!assert (isequal (size (resize (sym(1), 0, 0)), [0 0])) %!assert (isequal (size (resize (sym(1), 6, 0)), [6 0])) %!assert (isequal (size (resize (sym(1), 0, 3)), [0 3])) %!error resize (sym(1)) %!error resize (sym(1), 2, 3, 4) %!error resize (sym(1), [2 3 4]) symbolic-3.1.1/inst/@sym/rewrite.m0000644000000000000000000000675114405647405013771 0ustar %% Copyright (C) 2016, 2019, 2022 Colin Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym rewrite (@var{f}, @var{how}) %% Rewrite a symbolic expression. %% %% Attempts to rewrite an expression @var{f} in terms of functions %% indicated by the @emph{case-sensitive} string @var{how}. %% %% Examples using trigonometry: %% @example %% @group %% syms x %% rewrite(exp(x), 'sin') %% @result{} ans = (sym) sinh(x) + cosh(x) %% rewrite(sin(x), 'exp') %% @result{} ans = (sym) %% ⎛ ⅈ⋅x -ⅈ⋅x⎞ %% -ⅈ⋅⎝ℯ - ℯ ⎠ %% ────────────────── %% 2 %% @end group %% @end example %% %% Often @code{sincos} is more useful than @code{sin} or @code{cos}: %% @example %% @group %% rewrite(tan(x), 'sin') %% @result{} (sym) %% 2 %% 2⋅sin (x) %% ───────── %% sin(2⋅x) %% rewrite(tan(x), 'sincos') %% @result{} (sym) %% sin(x) %% ────── %% cos(x) %% @end group %% @end example %% %% The argument @var{f} can be a matrix: %% @example %% @group %% rewrite([exp(x) cos(x) asin(x)], 'log') %% @result{} ans = (sym 1×3 matrix) %% ⎡ ⎛ ________⎞⎤ %% ⎢ x ⎜ ╱ 2 ⎟⎥ %% ⎣ℯ cos(x) -ⅈ⋅log⎝ⅈ⋅x + ╲╱ 1 - x ⎠⎦ %% @end group %% @end example %% (and note that some elements of @var{f} might be unchanged.) %% %% Example using integrals: %% @example %% @group %% syms f(t) s %% G = laplace(f) %% @result{} G = (sym) LaplaceTransform(f(t), t, s) %% rewrite(G, 'Integral') %% @result{} ans = (sym) %% ∞ %% ⌠ %% ⎮ -s⋅t %% ⎮ f(t)⋅ℯ dt %% ⌡ %% 0 %% @end group %% @end example %% @strong{Note} the case-sensitivity of @var{how}: %% use @code{Integral} not @code{integral}. %% %% Further examples: %% @example %% @group %% syms n r %% rewrite(factorial(n), 'gamma') %% @result{} ans = (sym) Γ(n + 1) %% @end group %% @group %% nCr = nchoosek(n, r) %% @result{} nCr = (sym) %% ⎛n⎞ %% ⎜ ⎟ %% ⎝r⎠ %% rewrite(nCr, 'factorial') %% @result{} ans = (sym) %% n! %% ─────────── %% r!⋅(n - r)! %% @end group %% @end example %% %% @seealso{@@sym/simplify, @@sym/expand, @@sym/factor} %% @end defmethod function F = rewrite(f, how) if (nargin ~= 2) print_usage (); end F = elementwise_op ('lambda f, how: f.rewrite(how)', sym(f), how); end %!test %! syms x %! assert (isequal (rewrite(x, 'exp'), x)) %!test %! % empty %! e = sym([]); %! assert (isequal (rewrite(e, 'sin'), e)) %!test %! syms x %! A = [exp(x) exp(2*x)]; %! B = [sinh(x) + cosh(x) sinh(2*x) + cosh(2*x)]; %! assert (isequal (rewrite(A, 'sin'), B)) symbolic-3.1.1/inst/@sym/rhs.m0000644000000000000000000000266614405647405013105 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym rhs (@var{f}) %% Right-hand side of symbolic expression. %% %% Example: %% @example %% @group %% syms x %% eqn = 5*x <= 3*x + 6 %% @result{} eqn = (sym) 5⋅x ≤ 3⋅x + 6 %% rhs(eqn) %% @result{} ans = (sym) 3⋅x + 6 %% @end group %% @end example %% %% Gives an error if any of the symbolic objects have no right-hand side. %% %% @seealso{@@sym/lhs, @@sym/children, @@sym/formula, @@sym/argnames} %% @end defmethod function R = rhs(f) R = elementwise_op ('lambda a: a.rhs', f); end %% most tests are in lhs %!test %! syms x %! f = x + 1 == 2*x; %! assert (isequal (rhs(f), 2*x)) %!error %! syms x %! rhs(x) symbolic-3.1.1/inst/@sym/round.m0000644000000000000000000000512614405647405013432 0ustar %% Copyright (C) 2016 Lagu %% Copyright (C) 2016 Mike Miller %% Copyright (C) 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym round (@var{x}) %% Symbolic round function. %% %% Example: %% @example %% @group %% y = round (sym(-27)/10) %% @result{} y = (sym) -3 %% @end group %% @end example %% %% Note as of SymPy 1.5, this function rounds toward even: %% @example %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.4")')) %% @group %% round ([sym(5)/2 sym(7)/2]) %% @result{} (sym) [2 4] (1×2 matrix) %% @end group %% @end example %% This differs from the builtin numeric function @pxref{round}; %% it corresponds to the builtin Octave function @pxref{roundb}. %% @example %% @group %% round ([5/2 7/2]) %% @result{} 3 4 %% roundb ([5/2 7/2]) %% @result{} 2 4 %% @end group %% @end example %% %% @seealso{roundb, @@sym/ceil, @@sym/floor, @@sym/fix, @@sym/frac} %% @end defmethod function y = round(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('lambda a: Integer(a.round()) if isinstance(a, Number) else a.round()', x); end %!test %! d = 3/2; %! x = sym('3/2'); %! f1 = round(x); %! f2 = round(d); %! assert (isequal (f1, f2)) %!xtest %! % ideally rounding direction would match Octave %! d = 5/2; %! x = sym('5/2'); %! f1 = round(x); %! f2 = round(d); %! assert (isequal (f1, f2)) %!test %! D = [1.1 4.6; -3.4 -8.9]; %! A = [sym(11)/10 sym(46)/10; sym(-34)/10 sym(-89)/10]; %! f1 = round(A); %! f2 = round(D); %! assert( isequal (f1, f2)) %!test %! d = sym(-11)/10; %! c = -1; %! assert (isequal (round (d), c)) %!test %! d = sym(-19)/10; %! c = -2; %! assert (isequal (round (d), c)) %!test %! d = 7j/2; %! x = sym(7j)/2; %! f1 = round (x); %! f2 = round (d); %! assert (isequal (f1, f2)) %!test %! d = 5/3 - 4j/7; %! x = sym(5)/3 - sym(4j)/7; %! f1 = round (x); %! f2 = round (d); %! assert (isequal (f1, f2)) symbolic-3.1.1/inst/@sym/rows.m0000644000000000000000000000237714405647405013302 0ustar %% Copyright (C) 2015, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym rows (@var{x}) %% Return the number of rows in a symbolic array. %% %% Example: %% @example %% @group %% A = [1 2 sym(pi); 4 5 2*sym(pi)]; %% n = rows (A) %% @result{} n = 2 %% @end group %% @end example %% %% @seealso{@@sym/columns, @@sym/size, @@sym/length, @@sym/numel} %% @end defmethod function n = rows(x) n = size(x, 1); end %!test %! a = sym([1 2 3]); %! assert (rows(a) == 1) %!test %! a = sym([1 2 3; 4 5 6]); %! assert (rows(a) == 2) symbolic-3.1.1/inst/@sym/rref.m0000644000000000000000000000373114405647405013241 0ustar %% Copyright (C) 2015, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {@var{r} =} rref (@var{A}) %% @deftypemethodx @@sym {[@var{r}, @var{k}] =} rref (@var{A}) %% Reduced Row Echelon Form of a symbolic matrix. %% %% Example: %% @example %% @group %% A = sym([1 2 3; 2 3 4]); %% rref (A) %% @result{} (sym 2×3 matrix) %% %% ⎡1 0 -1⎤ %% ⎢ ⎥ %% ⎣0 1 2 ⎦ %% %% @end group %% @end example %% %% Optional second output gives the indices of pivots. %% %% @seealso{@@sym/rank, @@sym/null, @@sym/orth} %% @end deftypemethod function [r, k] = rref(A) cmd = { 'A = _ins[0]' 'if not A.is_Matrix:' ' A = sp.Matrix([A])' 'L = A.rref()' 'K = sp.Matrix([L[1]])' 'return (L[0], K)' }; [r, k] = pycall_sympy__ (cmd, A); k = k + 1; end %!test %! A = sym([1 2; 3 4]); %! [r, k] = rref(A); %! assert (isequal (r, eye(2))) %! assert (isequal (k, [1 2])) %!assert (isequal (rref(sym([2 1])), [1 sym(1)/2])) %!assert (isequal (rref(sym([1 2; 2 4])), [1 2; 0 0])) %!assert (isequal (rref(sym([0 0; 2 4])), [1 2; 0 0])) %!test %! A = sym([1 2 3; 2 3 4]); %! [r, k] = rref(A); %! assert (isequal (r, [1 0 -1; 0 1 2])) %! assert (isequal (k, [1 2])); symbolic-3.1.1/inst/@sym/sec.m0000644000000000000000000000325614405647405013057 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym sec (@var{x}) %% Symbolic sec function. %% %% Example: %% @example %% @group %% syms x %% y = sec (x) %% @result{} y = (sym) sec(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = sec(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('sec', x); end %!error sec (sym(1), 2) %!assert (isequaln (sec (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = sec(x); %! f2 = sec(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = sec(A); %! f2 = sec(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = sec (d); %! f = sec (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/sech.m0000644000000000000000000000327414405647405013227 0ustar %% Copyright (C) 2016-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym sech (@var{x}) %% Symbolic sech function. %% %% Example: %% @example %% @group %% syms x %% y = sech (x) %% @result{} y = (sym) sech(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = sech(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('sech', x); end %!error sech (sym(1), 2) %!assert (isequaln (sech (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = sech(x); %! f2 = sech(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = sech(A); %! f2 = sech(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = sech (d); %! f = sech (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/setdiff.m0000644000000000000000000000532314405647405013726 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% Copyright (C) 2016 Lagu %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym setdiff (@var{A}, @var{B}) %% Set subtraction. %% %% Example: %% @example %% @group %% A = interval(1, sym(pi)); %% B = interval(sym(2), 3); %% setdiff(A, B) %% @result{} ans = (sym) [1, 2) ∪ (3, π] %% @end group %% @end example %% %% You can mix finite sets and intervals: %% @example %% @group %% setdiff(A, finiteset(3)) %% @result{} ans = (sym) [1, 3) ∪ (3, π] %% %% setdiff(A, finiteset(sym(pi))) %% @result{} ans = (sym) [1, π) %% %% setdiff(finiteset(1, 2, sym(pi)), B) %% @result{} ans = (sym) @{1, π@} %% @end group %% @end example %% %% @seealso{@@sym/union, @@sym/intersect, @@sym/setxor, @@sym/unique, %% @@sym/ismember, @@sym/finiteset, @@sym/interval} %% @end defmethod function r = setdiff(a, b) if (nargin ~= 2) print_usage (); end cmd = { 'a, b = _ins' 'if isinstance(a, sp.Set) or isinstance(b, sp.Set):' ' return a - b,' '' 'A = sp.FiniteSet(*(list(a) if isinstance(a, sp.MatrixBase) else [a]))' 'B = sp.FiniteSet(*(list(b) if isinstance(b, sp.MatrixBase) else [b]))' 'C = A - B' 'return sp.Matrix([list(C)]),' }; r = pycall_sympy__ (cmd, sym(a), sym(b)); end %!test %! A = sym([1 2 3]); %! B = sym([1 2 4]); %! C = setdiff(A, B); %! D = sym([3]); %! assert (isequal (C, D)) %!test %! % one nonsym %! A = sym([1 2 3]); %! B = [1 2 4]; %! C = setdiff(A, B); %! D = sym([3]); %! assert (isequal (C, D)) %!test %! % empty %! A = sym([1 2 3]); %! C = setdiff(A, A); %! assert (isempty (C)) %!test %! % empty input %! A = sym([1 2]); %! C = setdiff(A, []); %! assert (isequal (C, A) || isequal (C, sym([2 1]))) %!test %! % scalar %! syms x %! assert (isequal (setdiff([x 1], x), sym(1))) %! assert (isempty (setdiff(x, x))) %!test %! A = interval(sym(1), 3); %! B = interval(sym(2), 5); %! C = setdiff(A, B); %! assert( isequal( C, interval(sym(1), 2, false, true))) symbolic-3.1.1/inst/@sym/setxor.m0000644000000000000000000000537614405647405013636 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% Copyright (C) 2016 Lagu %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym setxor (@var{A}, @var{B}) %% Return the symmetric difference of two sets. %% %% Example: %% @example %% @group %% A = interval(2, sym(10)); %% B = interval(0, sym(pi)); %% setxor(A, B) %% @result{} ans = (sym) [0, 2) ∪ (π, 10] %% @end group %% @end example %% %% And we note this is the same as the union of: %% @example %% @group %% setdiff(A, B) %% @result{} ans = (sym) (π, 10] %% setdiff(B, A) %% @result{} ans = (sym) [0, 2) %% @end group %% @end example %% %% @seealso{@@sym/union, @@sym/intersect, @@sym/setdiff, @@sym/unique, %% @@sym/ismember, @@sym/finiteset, @@sym/interval} %% @end defmethod function r = setxor(a, b) if (nargin ~= 2) print_usage (); end cmd = { 'a, b = _ins' 'if isinstance(a, sp.Set) or isinstance(b, sp.Set):' ' return a ^ b' '' 'A = sp.FiniteSet(*(list(a) if isinstance(a, sp.MatrixBase) else [a]))' 'B = sp.FiniteSet(*(list(b) if isinstance(b, sp.MatrixBase) else [b]))' 'C = A ^ B' 'return sp.Matrix([list(C)]),' }; r = pycall_sympy__ (cmd, sym(a), sym(b)); end %!test %! A = sym([1 2 3]); %! B = sym([1 2 4]); %! C = setxor(A, B); %! D1 = sym([3 4]); %! D2 = sym([4 3]); %! assert (isequal (C, D1) || isequal (C, D2)) %!test %! % one nonsym %! A = sym([1 2 3]); %! B = [1 2 4]; %! C = setxor(A, B); %! D1 = sym([3 4]); %! D2 = sym([4 3]); %! assert (isequal (C, D1) || isequal (C, D2)) %!test %! % empty %! A = sym([1 2 3]); %! C = setxor(A, A); %! assert (isempty (C)) %!test %! % empty input %! A = sym([1 2]); %! C = setxor(A, []); %! assert (isequal (C, A) || isequal (C, sym([2 1]))) %!test %! % scalar %! syms x %! assert (isequal (setxor([x 1], x), sym(1))) %! assert (isempty (setxor(x, x))) %!test %! A = interval(sym(1), 3); %! B = interval(sym(2), 5); %! C = setxor(A, B); %! D = union (interval (sym(1), 2, false, true), interval (sym(3), 5, true, false)); %! assert( isequal( C, D)) symbolic-3.1.1/inst/@sym/sign.m0000644000000000000000000000327414405647405013245 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym sign (@var{x}) %% Symbolic sign function. %% %% Example: %% @example %% @group %% syms x %% y = sign (x) %% @result{} y = (sym) sign(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = sign(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('sign', x); end %!error sign (sym(1), 2) %!assert (isequaln (sign (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = sign(x); %! f2 = sign(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = sign(A); %! f2 = sign(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = sign (d); %! f = sign (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/signIm.m0000644000000000000000000000354114405647405013530 0ustar %% Copyright (C) 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym signIm (@var{z}) %% Return the sign of the imaginary part of a complex expression. %% %% Examples: %% @example %% @group %% signIm (sym(3) + 2i) %% @result{} (sym) 1 %% signIm (3 - 1i*sym(pi)) %% @result{} (sym) -1 %% signIm (sym(3)) %% @result{} (sym) 0 %% @end group %% %% @group %% syms x y real %% signIm (x) %% @result{} (sym) 0 %% signIm (x + 1i*y) %% @result{} (sym) sign(y) %% @end group %% @end example %% %% @seealso{@@sym/imag, @@sym/sign} %% @end defmethod function y = signIm(z) if (nargin ~= 1) print_usage (); end y = sign (imag (z)); end %!assert (isequal (signIm (sym(1)), sym(0))) %!assert (isequal (signIm (sym(1) + 2i), sym(1))) %!assert (isequal (signIm (sym(1) - 2i), sym(-1))) %!test %! % intermediate A looks bit weird, but it works %! syms z %! A = signIm (z); %! assert (isequal (subs(A, z, 3+sym(4i)), sym(1))) %! assert (isequal (subs(A, z, 3-sym(4i)), sym(-1))) %!test %! % really a @sym/sign test, but that one is autogen %! z = 3 + sym(4i); %! A = sign (z); %! B = z / abs(z); %! assert (double (A), double (B), eps) symbolic-3.1.1/inst/@sym/simplify.m0000644000000000000000000000342314405647405014135 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym simplify (@var{x}) %% Simplify an expression. %% %% Example: %% @example %% @group %% syms x %% p = x^2 + x + 1 %% @result{} p = (sym) %% 2 %% x + x + 1 %% q = horner (p) %% @result{} q = (sym) x⋅(x + 1) + 1 %% @end group %% %% @group %% d = p - q %% @result{} d = (sym) %% 2 %% x - x⋅(x + 1) + x %% %% isAlways(p == q) %% @result{} 1 %% %% simplify(p - q) %% @result{} (sym) 0 %% @end group %% @end example %% %% Please note that @code{simplify} is not a well-defined mathematical %% operation: its precise behaviour can change between software versions %% (and certainly between different software packages!) %% %% @seealso{@@sym/isAlways, @@sym/factor, @@sym/expand, @@sym/rewrite} %% @end defmethod function y = simplify(x) cmd = 'return sp.simplify(*_ins),'; y = pycall_sympy__ (cmd, x); end %!shared x,p,q %! syms x %! p = x^2 + x + 1; %! q = horner (p); %!assert(~isequal( p - q, 0)) %!assert(isequal( simplify(p - q), 0)) symbolic-3.1.1/inst/@sym/sin.m0000644000000000000000000000325614405647405013076 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym sin (@var{x}) %% Symbolic sin function. %% %% Example: %% @example %% @group %% syms x %% y = sin (x) %% @result{} y = (sym) sin(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = sin(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('sin', x); end %!error sin (sym(1), 2) %!assert (isequaln (sin (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = sin(x); %! f2 = sin(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = sin(A); %! f2 = sin(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = sin (d); %! f = sin (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/sinc.m0000644000000000000000000000601714405647405013237 0ustar %% Copyright (C) 2016, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym sinc (@var{x}) %% Symbolic normalized sinc function. %% %% The normalized sinc function is defined by %% @example %% @group %% syms x %% rewrite (sinc (x), 'sin') %% @result{} (sym) %% ⎧sin(π⋅x) %% ⎪──────── for π⋅x ≠ 0 %% ⎨ π⋅x %% ⎪ %% ⎩ 1 otherwise %% @end group %% @end example %% %% Caution, the notation @code{sinc} is also commonly used to represent %% the unnormalized sinc function %% @iftex %% @math{\frac{\sin(x)}{x}}. %% @end iftex %% @ifnottex %% @code{sin(x)/x}. %% @end ifnottex %% %% Further examples: %% @example %% @group %% rewrite (sin (x)/x, 'sinc') %% @result{} ans = (sym) %% ⎛x⎞ %% sinc⎜─⎟ %% ⎝π⎠ %% @end group %% %% @group %% rewrite (sin (pi*x)/(pi*x), 'sinc') %% @result{} ans = (sym) sinc(x) %% @end group %% %% @group %% syms x nonzero %% simplify (diff (sinc (x))) %% @result{} ans = (sym) %% cos(π⋅x) sin(π⋅x) %% ──────── - ──────── %% x 2 %% π⋅x %% @end group %% @end example %% %% @seealso{sinc} %% @end defmethod function y = sinc(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('sinc', pi*x); end %!error sinc (sym(1), 2) %!assert (isequaln (sinc (sym(nan)), sym(nan))) %!assert (isequal (sinc (sym(0)), sym(1))) %!assert (isequal (sinc (sym(1)), sym(0))) %!assert (isequal (sinc (-sym(1)), sym(0))) %!assert (double (sinc (sym(pi))), sinc (pi), -10*eps) %!test %! A = [-sym(1)/2 sym(1)/2 pi; -sym(7)/2 sym(71)/2 sym(101)/3]; %! D = double (A); %! assert (sinc (D), double (sinc (A)), -200*eps) %!test %! A = [sym(51)/2 sym(1001)/3 sym(10001)/3 sym(100001)/3]; %! D = double (A); %! assert (sinc (D), double (sinc (A)), 1e-10) %!test %! % round trip %! syms x %! A = sinc (1); %! f = sinc (x); %! h = function_handle (f); %! B = h (1); %! assert (A, B, -eps) %!test %! % round trip %! syms x %! f = sinc (x); %! h = function_handle (f); %! A = sinc (1.5); %! B = h (1.5); %! assert (A, B, -eps) %!test %! syms x %! h = function_handle (sinc (x)); %! A = double (sinc (sym (12)/10)); %! B = h (1.2); %! C = sinc (1.2); %! assert (A, B, -eps) %! assert (A, C, -eps) symbolic-3.1.1/inst/@sym/sind.m0000644000000000000000000000306514405647405013240 0ustar %% Copyright (C) 2014-2016, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym sind (@var{x}) %% Symbolic sin function with input in degrees. %% %% Example: %% @example %% @group %% 2*sind (sym (60)) %% @result{} (sym) √3 %% %% syms x %% y = sind (x) %% @result{} y = (sym) %% ⎛π⋅x⎞ %% sin⎜───⎟ %% ⎝180⎠ %% @end group %% @end example %% %% @seealso{@@sym/asind, @@sym/sin} %% @end defmethod function y = sind(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('lambda a: sin(rad(a))', x); end %!error sind (sym(1), 2) %!assert (isequaln (sind (sym(nan)), sym(nan))) %!test %! f1 = sind (sym(1)); %! f2 = sind (1); %! assert (double (f1), f2, -eps) %!test %! D = [10 30; 110 -45]; %! A = sym(D); %! f1 = sind (A); %! f2 = sind (D); %! assert (double (f1), f2, -eps) symbolic-3.1.1/inst/@sym/sinh.m0000644000000000000000000000327414405647405013246 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym sinh (@var{x}) %% Symbolic sinh function. %% %% Example: %% @example %% @group %% syms x %% y = sinh (x) %% @result{} y = (sym) sinh(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = sinh(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('sinh', x); end %!error sinh (sym(1), 2) %!assert (isequaln (sinh (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = sinh(x); %! f2 = sinh(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = sinh(A); %! f2 = sinh(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = sinh (d); %! f = sinh (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/sinhint.m0000644000000000000000000000343114405647405013754 0ustar %% Copyright (C) 2016-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym sinhint (@var{x}) %% Symbolic sinhint function. %% %% Example: %% @example %% @group %% syms x %% y = sinhint (x) %% @result{} y = (sym) Shi(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = sinhint(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('Shi', x); end %!error sinhint (sym(1), 2) %!xtest %! assert (isequaln (sinhint (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = sinhint(x); %! f2 = 1.057250875375728514572; %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = sinhint(A); %! f2 = 1.057250875375728514572; %! f2 = [f2 f2; f2 f2]; %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = sinhint (d); %! f = sinhint (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/sinint.m0000644000000000000000000000341714405647405013610 0ustar %% Copyright (C) 2016-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym sinint (@var{x}) %% Symbolic sinint function. %% %% Example: %% @example %% @group %% syms x %% y = sinint (x) %% @result{} y = (sym) Si(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = sinint(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('Si', x); end %!error sinint (sym(1), 2) %!xtest %! assert (isequaln (sinint (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = sinint(x); %! f2 = 0.9460830703671830149414; %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = sinint(A); %! f2 = 0.9460830703671830149414; %! f2 = [f2 f2; f2 f2]; %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = sinint (d); %! f = sinint (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/size.m0000644000000000000000000000712614405647405013257 0ustar %% Copyright (C) 2014-2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {@var{d} =} size (@var{x}) %% @deftypemethodx @@sym {[@var{n}, @var{m}] =} size (@var{x}) %% @deftypemethodx @@sym {@var{d} =} size (@var{x}, @var{dim}) %% Return the size of a symbolic array. %% %% Examples: %% @example %% @group %% syms x %% A = [1 2 x; x 3 4]; %% [n, m] = size(A) %% @result{} n = 2 %% @result{} m = 3 %% @end group %% %% @group %% A = sym('a', [3 4]); %% [n, m] = size(A) %% @result{} n = 3 %% @result{} m = 4 %% size(A, 1) %% @result{} 3 %% size(A, 2) %% @result{} 4 %% @end group %% @end example %% %% Symbolic-sized matrices currently return @code{1 × 1} but we might %% prefer @code{NaN × NaN}: %% @example %% @group %% syms n m integer %% A = sym('a', [n m]) %% @result{} A = (sym) a (n×m matrix expression) %% %% size(A) % doctest: +XFAIL %% @result{} NaN NaN %% @end group %% @end example %% %% @seealso{@@sym/length, @@sym/numel} %% @end deftypemethod function [n, m] = size(x, dim) % Note: symbolic sized matrices should return double, not sym/string. n = x.size; % FIXME: for now, we artificially force symbolic sized objects % (where one or more dimension is recorded as NaN) to be 1x1. % This effects MatrixSymbol and MatrixExpr. See Issue #159. if (any(isnan(n))) n = [1 1]; end % Alternatively: %n(isnan(n)) = 1; if (nargin == 2) && (nargout == 2) print_usage (); elseif (nargout == 2) m = n(2); n = n(1); elseif (nargin == 2) n = n(dim); end end %!test %! a = sym([1 2 3]); %! [n,m] = size(a); %! assert (n == 1 && m == 3) %!test %! a = sym([1 2 3]); %! n = size(a); %! assert (isequal (n, [1 3])) %!test %! %% size, numel, length %! a = sym([1 2 3; 4 5 6]); %! assert (isa (size(a), 'double')) %! assert (isa (numel(a), 'double')) %! assert (isa (length(a), 'double')) %! assert (isequal (size(a), [2 3])) %! assert (length(a) == 3) %! assert (numel(a) == 6) %! a = sym([1; 2; 3]); %! assert (isequal (size(a), [3 1])) %! assert (length(a) == 3) %! assert (numel(a) == 3) %!test %! %% size by dim %! a = sym([1 2 3; 4 5 6]); %! n = size(a, 1); %! assert (n == 2) %! m = size(a, 2); %! assert (m == 3) %! a = sym([1 2 3]'); %! n = size(a, 1); %! assert (n == 3) %! m = size(a, 2); %! assert (m == 1) %!xtest %! % symbolic-size matrices %! syms n m integer %! A = sym('A', [n m]); %! d = size(A); %! assert (~isa(d, 'sym')) %! assert (isnumeric(d)) %! assert (isequaln (d, [NaN NaN])) %!xtest %! % half-symbolic-size matrices %! % FIXME: will fail until size stop lying by saying 1x1 %! syms n integer %! A = sym('A', [n 3]); %! assert (isequaln (size(A), [NaN 3])) %! A = sym('A', [4 n]); %! assert (isequaln (size(A), [4 NaN])) %!xtest %! % half-symbolic-size empty matrices %! % FIXME: will fail until size stop lying by saying 1x1 %! syms n integer %! A = sym('A', [n 0]); %! assert (isequaln (size(A), [NaN 0])) symbolic-3.1.1/inst/@sym/solve.m0000644000000000000000000002275514405647405013442 0ustar %% Copyright (C) 2014-2019, 2022 Colin B. Macdonald %% Copyright (C) 2014-2015 Andrés Prieto %% Copyright (C) 2016 Lagu %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {@var{sol} =} solve (@var{eqn}) %% @deftypemethodx @@sym {@var{sol} =} solve (@var{eqn}, @var{var}) %% @deftypemethodx @@sym {@var{sol} =} solve (@var{eqn1}, @dots{}, @var{eqnN}) %% @deftypemethodx @@sym {@var{sol} =} solve (@var{eqn1}, @dots{}, @var{eqnN}, @var{var1}, @dots{}, @var{varM}) %% @deftypemethodx @@sym {@var{sol} =} solve (@var{eqns}, @var{vars}) %% @deftypemethodx @@sym {[@var{s1, @dots{}, sn}] =} solve (@var{eqns}, @var{vars}) %% Symbolic solutions of equations, inequalities and systems. %% %% Examples %% @example %% @group %% syms x %% solve(x == 2*x + 6, x) %% @result{} ans = (sym) -6 %% solve(x^2 + 6 == 5*x, x); %% sort(ans) %% @result{} ans = (sym 2×1 matrix) %% ⎡2⎤ %% ⎢ ⎥ %% ⎣3⎦ %% @end group %% @end example %% %% Sometimes its helpful to assume an unknown is real: %% @example %% @group %% syms x real %% solve(abs(x) == 1, x); %% sort(ans) %% @result{} ans = (sym 2×1 matrix) %% ⎡-1⎤ %% ⎢ ⎥ %% ⎣1 ⎦ %% @end group %% @end example %% %% In general, the output will be a list of dictionaries. Each %% entry of the list is one a solution, and the variables that make %% up that solutions are keys of the dictionary (fieldnames of the %% struct). %% @example %% @group %% syms x y %% d = solve(x^2 == 4, x + y == 1); %% %% % the first solution %% @c doctest: +SKIP % nondeterministic ordering %% d@{1@}.x %% @result{} (sym) -2 %% @c doctest: +SKIP % nondeterministic ordering %% d@{1@}.y %% @result{} (sym) 3 %% %% % the second solution %% @c doctest: +SKIP % nondeterministic ordering %% d@{2@}.x %% @result{} (sym) 2 %% @c doctest: +SKIP % nondeterministic ordering %% d@{2@}.y %% @result{} (sym) -1 %% @end group %% @end example %% %% But there are various special cases for the output (single %% versus multiple variables, single versus multiple solutions, %% etc). %% FIXME: provide a 'raw_output' argument or something to %% always give the general output. %% %% Alternatively: %% @example %% @group %% @c doctest: +SKIP % nondeterministic ordering %% [X, Y] = solve(x^2 == 4, x + y == 1, x, y) %% @result{} X = (sym 2×1 matrix) %% ⎡-2⎤ %% ⎢ ⎥ %% ⎣2 ⎦ %% @result{} Y = (sym 2×1 matrix) %% ⎡3 ⎤ %% ⎢ ⎥ %% ⎣-1⎦ %% @end group %% @end example %% %% You can solve inequalities and systems involving mixed %% inequalities and equations. For example: %% @example %% @group %% solve(x^2 == 4, x > 0) %% @result{} ans = (sym) x = 2 %% @end group %% %% @group %% syms x %% solve(x^2 - 1 > 0, x < 10) %% @result{} ans = (sym) (-∞ < x ∧ x < -1) ∨ (1 < x ∧ x < 10) %% @end group %% @end example %% %% @seealso{@@sym/eq, @@sym/dsolve} %% @end deftypemethod function varargout = solve(varargin) for i = 1:nargin varargin{i} = sym(varargin{i}); end %% input parsing explanation % stage 0: no equations found yet % stage 1: equations found, could be more % stage 2: started finding symbols % stage 3: done, no more input expected cmd = { 'eqs = list(); symbols = list()' 'stage = 0' 'for arg in _ins:' ' if arg.is_Matrix:' ' if any([a.is_Relational for a in arg]):' ' assert stage == 0 or stage == 1' ' eqs.extend(arg)' ' stage = 1' ' elif stage == 0:' ' eqs.extend(arg)' ' stage = 1' ' else:' ' assert stage != 0 or stage == 1 or stage == 2' ' symbols.extend(arg)' ' stage = 3' ' elif arg.is_Symbol and stage == 0:' ' eqs.append(arg)' ' stage = 1' ' elif arg.is_Symbol:' ' assert stage != 0 or stage == 1 or stage == 2' ' symbols.append(arg)' ' stage = 2' ' else:' ' # e.g., Relational, or Expr implicitly assumed == 0' ' assert stage == 0 or stage == 1' ' eqs.append(arg)' ' stage = 1' 'eqs = [e for e in eqs if e not in (True, S.true)]' % https://github.com/sympy/sympy/issues/14632 }; if (nargout == 0 || nargout == 1) cmd = [ cmd 'd = sp.solve(eqs, *symbols, dict=True)' 'if not isinstance(d, (list, tuple)):' % https://github.com/sympy/sympy/issues/11661 ' return d,' 'if len(d) >= 1 and len(d[0].keys()) == 1:' % one variable... ' if len(d) == 1:' % one variable, single solution ' return d[0].popitem()[1],' ' else:' % one variable, multiple solutions ' return sp.Matrix([r.popitem()[1] for r in d]),' 'if len(d) == 1:' ' d = d[0]' 'return d,' ]; out = pycall_sympy__ (cmd, varargin{:}); varargout = {out}; else % multiple outputs cmd = [ cmd 'd = sp.solve(eqs, *symbols, set=True)' 'if not isinstance(d, (list, tuple)):' % https://github.com/sympy/sympy/issues/11661 ' return d,' '(vars, solns) = d' 'q = []' 'for (i, var) in enumerate(vars):' ' q.append(sp.Matrix([t[i] for t in solns]))' 'return q,' ]; out = pycall_sympy__ (cmd, varargin{:}); varargout = out; if (length(out) ~= nargout) warning('solve: number of outputs did not match solution vars'); end end end %!test %! % Simple, single variable, single solution %! syms x %! d = solve(10*x == 50); %! assert (isequal (d, 5)) %!test %! % Single variable, multiple solutions %! syms x %! d = solve(x^2 == 4); %! assert (length(d) == 2); %! assert (isequal (d, [2; -2]) || isequal (d, [-2; 2])) %!shared x,y,eq %! syms x y %! eq = 10*x == 20*y; %!test %! d = solve(eq, x); %! assert (isequal (d, 2*y)) %!test %! d = solve(eq, y); %! assert (isequal (d, x/2)) %!test %! d = solve(eq); %! assert (isequal (d, 2*y)) %!shared x,y %! syms x y %!test %! d = solve(2*x - 3*y == 0, x + y == 1); %! assert (isequal (d.x, sym(3)/5) && isequal(d.y, sym(2)/5)) %!test %! d = solve(2*x - 3*y == 0, x + y == 1, x, y); %! assert (isequal (d.x, sym(3)/5) && isequal(d.y, sym(2)/5)) %!test %! % Multiple solutions, multiple variables %! d = solve(x^2 == 4, x + y == 1); %! assert (length(d) == 2); %! % FIXME: SMT has d.x gives vector and d.y giving vector, what is %! % more intuitive? %! for i = 1:2 %! assert (isequal (d{i}.x + d{i}.y, 1)) %! assert (isequal ((d{i}.x)^2, 4)) %! end %!test %! % No solutions %! syms x y z %! d = solve(x == y, z); %! assert (isempty (d)); %!test %! % Multiple outputs with single solution %! [X, Y] = solve(2*x + y == 5, x + y == 3); %! assert (isequal (X, 2)) %! assert (isequal (Y, 1)) %!test %! % system: vector of equations, vector of vars %! [X, Y] = solve([2*x + y == 5, x + y == 3], [x y]); %! assert (isequal (X, 2)) %! assert (isequal (Y, 1)) %!test %! % system: vector of equations, individual vars %! [X, Y] = solve([2*x + y == 5, x + y == 3], x, y); %! assert (isequal (X, 2)) %! assert (isequal (Y, 1)) %!test %! % system: individual equations, vector of vars %! [X, Y] = solve(2*x + y == 5, x + y == 3, [x y]); %! assert (isequal (X, 2)) %! assert (isequal (Y, 1)) %!test %! % Multiple outputs with multiple solns %! [X, Y] = solve(x*x == 4, x == 2*y); %! assert ((isequal (X, [2; -2]) && isequal (Y, [1; -1])) || ... %! (isequal (X, [-2; 2]) && isequal (Y, [-1; 1]))) %!test %! % Multiple outputs with multiple solns, specify vars %! [X, Y] = solve(x*x == 4, x == 2*y, x, y); %! assert ((isequal (X, [2; -2]) && isequal (Y, [1; -1])) || ... %! (isequal (X, [-2; 2]) && isequal (Y, [-1; 1]))) %!error %! % mult outputs not allowed for scalar equation, even with mult soln (?) %! [s1, s2] = solve(x^2 == 4, x); %!test %! % overdetermined %! X = solve(2*x - 10 == 0, 3*x - 15 == 0, x); %! assert (isequal (X, sym(5))) %!test %! a = solve(2*x >= 10, 10*x <= 50); %! assert (isequal( a, x==sym(5))) %!test %! A = solve([2*x == 4*y, 2 == 3], x); %! assert (isempty (A)) %!test %! % Issue #850 %! A = solve (sym(pi)^2*x + y == 0); %! assert (isequal (A, -y/sym(pi)^2)) %!test %! % https://github.com/sympy/sympy/issues/14632 %! A = solve([2*x == 4*y, sym(2) == 2], x); %! assert (isequal (A, 2*y)) %!test %! % https://github.com/sympy/sympy/issues/14632 %! A = solve([2*x^2 == 32*y^2, sym(2) == 2], x); %! B = solve([2*x^2 == 32*y^2], x); %! assert (isequal (A, B) || isequal (A, flip (B))) %!test %! A = solve ([x+1 0], x); %! assert (isequal (A, sym (-1))) %!test %! A = solve (x + 1, x); %! assert (isequal (A, sym (-1))) %! A = solve (x, x); %! assert (isequal (A, sym (0))) symbolic-3.1.1/inst/@sym/sort.m0000644000000000000000000000535114405647405013272 0ustar %% Copyright (C) 2016 Utkarsh Gautam %% Copyright (C) 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym sort (@var{f}) %% Order the elements in increasing order. %% %% Example: %% @example %% @group %% sort([sym(2), sym(1)]) %% @result{} ans = (sym) [1 2] (1×2 matrix) %% @end group %% @end example %% %% For matrices, sort orders the elements within columns %% @example %% @group %% s = sort([sym(2), sym(1); sym(3), sym(0)]) %% @result{} s = (sym 2×2 matrix) %% %% ⎡2 0⎤ %% ⎢ ⎥ %% ⎣3 1⎦ %% %% @end group %% @end example %% %% @seealso{@@sym/unique} %% @end defmethod function s = sort(f) if (nargin ~= 1) print_usage (); end if (rows(f) <= 1 && columns(f) <= 1) s = f; else cmd = { '(f) = _ins' 'f = Matrix(f).tolist()' 's = []' 'for c in f:' ' s.append(sorted(c))' 'return Matrix(s)' }; if (rows(f)>1) f = f'; s = pycall_sympy__ (cmd, f); s = s'; else s = pycall_sympy__ (cmd, f); end end end %!error sort (sym(1), 2) %!test %! f = [sym(1), sym(0)]; %! expected = sym([0, 1]); %! assert (isequal (sort(f), expected)) %!test %! f = [sym(1)]; %! expected = sym(1); %! assert (isequal (sort(f), expected)) %!test %! f = [sym(3), sym(2), sym(6)]; %! s = sort(f); %! expected_s = sym([2, 3, 6]); %! assert (isequal (s, expected_s)) %!test %! f = [sym(pi), sin(sym(2)), sqrt(sym(6))]; %! s = sort(f); %! expected_s = sym([sin(sym(2)), sqrt(sym(6)), sym(pi)]); %! assert (isequal (s, expected_s)) %!test %! f = [sym(1), sym(2); sym(2), sym(pi); sym(pi), sym(1)]; %! s = sort(f); %! expected_s = ([sym(1), sym(1); sym(2), sym(2); sym(pi), sym(pi)]); %! assert (isequal (s, expected_s)) %!assert (isequal (sort(sym([])), sym([]))) %!error sort([sym('x') 1]) %!test %! % but with assumptions, symbols can be sorted %! p = sym('p', 'positive'); %! n = sym('n', 'negative'); %! expected_s = [n p]; %! s = sort ([p n]); %! assert (isequal (s, expected_s)) symbolic-3.1.1/inst/@sym/sqrt.m0000644000000000000000000000336114405647405013273 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym sqrt (@var{x}) %% Symbolic sqrt function. %% %% Example: %% @example %% @group %% syms x %% y = sqrt (exp(x)) %% @result{} y = (sym) %% ____ %% ╱ x %% ╲╱ ℯ %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = sqrt(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('sqrt', x); end %!error sqrt (sym(1), 2) %!assert (isequaln (sqrt (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = sqrt(x); %! f2 = sqrt(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = sqrt(A); %! f2 = sqrt(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = sqrt (d); %! f = sqrt (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/ssinint.m0000644000000000000000000000251214405647405013766 0ustar %% Copyright (C) 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym ssinint (@var{x}) %% Symbolic shifted sine integral function. %% %% Example: %% @example %% @group %% syms x %% y = ssinint(x) %% @result{} y = (sym) %% π %% Si(x) - ─ %% 2 %% @end group %% @end example %% @seealso{@@sym/sinint} %% @end defmethod function y = ssinint(x) y = elementwise_op ('Si', x) - sym(pi)/2; end %!assert (isequal (ssinint(sym(0)), -sym(pi)/2)) %!test %! A = ssinint (sym ([0 1])); %! B = [-pi/2 -0.62471325642771360426]; %! assert( all(all( abs(double(A)-B) < 1e-15 ))) symbolic-3.1.1/inst/@sym/subs.m0000644000000000000000000002634114405647405013261 0ustar %% Copyright (C) 2014-2017, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym subs (@var{f}, @var{x}, @var{y}) %% @defmethodx @@sym subs (@var{f}, @var{y}) %% @defmethodx @@sym subs (@var{f}) %% Replace symbols in an expression with other expressions. %% %% Example substituting a value for a variable: %% @example %% @group %% syms x y %% f = x*y; %% subs(f, x, 2) %% @result{} ans = (sym) 2⋅y %% @end group %% @end example %% If @var{x} is omitted, @code{symvar} is called on @var{f} to %% determine an appropriate variable. %% %% @var{x} and @var{y} can also be vectors or lists of syms to %% replace: %% @example %% @group %% subs(f, @{x y@}, @{sin(x) 16@}) %% @result{} ans = (sym) 16⋅sin(x) %% %% F = [x x*y; 2*x*y y]; %% subs(F, @{x y@}, [2 sym(pi)]) %% @result{} ans = (sym 2×2 matrix) %% %% ⎡ 2 2⋅π⎤ %% ⎢ ⎥ %% ⎣4⋅π π ⎦ %% @end group %% @end example %% %% With only one argument, @code{subs(@var{F})} will attempt to find values for %% each symbol in @var{F} by searching the workspace: %% @example %% @group %% f = x*y %% @result{} f = (sym) x⋅y %% @end group %% %% @group %% x = 42; %% f %% @result{} f = (sym) x⋅y %% @end group %% @end example %% Here assigning a numerical value to the variable @code{x} did not %% change the expression (because symbols are not the same as variables!) %% However, we can automatically update @code{f} by calling: %% @example %% @group %% subs(f) %% @result{} ans = (sym) 42⋅y %% @end group %% @end example %% %% @strong{Warning}: @code{subs} cannot be easily used to substitute a %% @code{double} matrix; it will cast @var{y} to a @code{sym}. Instead, %% create a ``function handle'' from the symbolic expression, which can %% be efficiently evaluated numerically. For example: %% @example %% @group %% syms x %% f = exp(sin(x)) %% @result{} f = (sym) %% %% sin(x) %% ℯ %% %% fh = function_handle(f) %% @result{} fh = %% %% @@(x) exp (sin (x)) %% @end group %% %% @c doctest: +SKIP_IF(compare_versions (OCTAVE_VERSION(), '6.0.0', '<')) %% @group %% fh(linspace(0, 2*pi, 700)') %% @result{} ans = %% 1.0000 %% 1.0090 %% 1.0181 %% 1.0273 %% 1.0366 %% ... %% @end group %% @end example %% %% @strong{Note}: Mixing scalars and matrices may lead to trouble. %% We support the case of substituting one or more symbolic matrices %% in for symbolic scalars, within a scalar expression: %% @example %% @group %% f = sin(x); %% g = subs(f, x, [1 sym('a'); pi sym('b')]) %% @result{} g = (sym 2×2 matrix) %% %% ⎡sin(1) sin(a)⎤ %% ⎢ ⎥ %% ⎣ 0 sin(b)⎦ %% @end group %% @end example %% %% When using multiple variables and matrix substitions, it may be %% helpful to use cell arrays: %% @example %% @group %% subs(y*sin(x), @{x, y@}, @{3, [2 sym('a')]@}) %% @result{} ans = (sym) [2⋅sin(3) a⋅sin(3)] (1×2 matrix) %% @end group %% %% @group %% subs(y*sin(x), @{x, y@}, @{[2 3], [2 sym('a')]@}) %% @result{} ans = (sym) [2⋅sin(2) a⋅sin(3)] (1×2 matrix) %% @end group %% @end example %% %% @strong{Caution}, multiple interdependent substitutions can be %% ambiguous and results may depend on the order in which you %% specify them. %% A cautionary example: %% @example %% @group %% syms y(x) A B %% u = y + diff(y, x) %% @result{} u(x) = (symfun) %% d %% y(x) + ──(y(x)) %% dx %% %% subs(u, @{y, diff(y, x)@}, @{A, B@}) %% @result{} ans = (sym) A %% %% subs(u, @{diff(y, x), y@}, @{B, A@}) %% @result{} ans = (sym) A + B %% @end group %% @end example %% %% Here it would be clearer to explicitly avoid the ambiguity %% by calling @code{subs} twice: %% @example %% @group %% subs(subs(u, diff(y, x), B), y, A) %% @result{} ans = (sym) A + B %% @end group %% @end example %% %% @seealso{@@sym/symfun} %% @end defmethod function g = subs(f, in, out) if (nargin > 3) print_usage (); end if (nargin == 1) %% take values of x from the workspace in = findsymbols (f); out = {}; i = 1; while (i <= length (in)) xstr = char (in{i}); try xval = evalin ('caller', xstr); foundit = true; catch foundit = false; end if (foundit) out{i} = xval; i = i + 1; else in(i) = []; % erase that input end end g = subs (f, in, out); return end if (nargin == 2) out = in; in = symvar(f, 1); if (isempty(in)) in = sym('x'); end end % ensure everything is sym f = sym(f); if (iscell (in)) for i = 1:numel(in) in{i} = sym(in{i}); end else in = sym(in); end if (iscell (out)) for i = 1:numel(out) out{i} = sym(out{i}); end else out = sym(out); end %% Simpler code for scalar x %if (isscalar(in) && isscalar(in) && isscalar(out)) % cmd = { '(f, x, y) = _ins' % 'return f.subs(x, y).doit(),' }; % g = pycall_sympy__ (cmd, sym(f), sym(in), sym(out)); % return %end if (~ iscell (in) && isscalar (in)) in = {in}; end if (iscell (in) && isscalar (in) && ~ iscell (out)) out = {out}; end % "zip" will silently truncate assert (numel (in) == 1 || numel (in) == numel (out), ... 'subs: number of outputs must match inputs') cmd = { '(f, xx, yy) = _ins' 'has_vec_sub = any(y.is_Matrix for y in yy)' 'if not has_vec_sub:' ' sublist = list(zip(xx, yy))' ' g = f.subs(sublist, simultaneous=True).doit()' ' return g' '# more complicated when dealing with matrix/vector' 'sizes = {(a.shape if a.is_Matrix else (1, 1)) for a in yy}' 'sizes.discard((1, 1))' 'assert len(sizes) == 1, "all substitions must be same size or scalar"' 'size = sizes.pop()' 'numel = prod(size)' 'g = [0]*numel' 'for i in range(len(g)):' ' yyy = [y[i] if y.is_Matrix else y for y in yy]' ' sublist = list(zip(xx, yyy))' ' g[i] = f.subs(sublist, simultaneous=True).doit()' 'return Matrix(*size, g)' }; g = pycall_sympy__ (cmd, f, in, out); end %!error subs (sym(1), 2, 3, 4) %!shared x,y,t,f %! syms x y t %! f = x*y; %!test %! assert( isequal( subs(f, x, y), y^2 )) %! assert( isequal( subs(f, y, sin(x)), x*sin(x) )) %! assert( isequal( subs(f, x, 16), 16*y )) %!test %! % multiple subs w/ cells %! assert( isequal( subs(f, {x}, {t}), y*t )) %! assert( isequal( subs(f, {x y}, {t t}), t*t )) %! assert( isequal( subs(f, {x y}, {t 16}), 16*t )) %! assert( isequal( subs(f, {x y}, {16 t}), 16*t )) %! assert( isequal( subs(f, {x y}, {2 16}), 32 )) %!test %! % multiple subs w/ vectors %! assert( isequal( subs(f, [x y], [t t]), t*t )) %! assert( isequal( subs(f, [x y], [t 16]), 16*t )) %! assert( isequal( subs(f, [x y], [2 16]), 32 )) %!test %! % anything you can think of %! assert( isequal( subs(f, [x y], {t t}), t*t )) %! assert( isequal( subs(f, {x y}, [t t]), t*t )) %! assert( isequal( subs(f, {x; y}, [t; t]), t*t )) %!test %! % sub in doubles gives sym (matches SMT 2013b) %! % FIXME: but see %! % http://www.mathworks.co.uk/help/symbolic/gradient.html %! assert( isequal( subs(f, {x y}, {2 pi}), 2*sym(pi) )) %! assert( ~isa(subs(f, {x y}, {2 pi}), 'double')) %! assert( isa(subs(f, {x y}, {2 pi}), 'sym')) %! assert( isa(subs(f, {x y}, {2 sym(pi)}), 'sym')) %! assert( isa(subs(f, {x y}, {sym(2) sym(pi)}), 'sym')) %!shared x,y,t,f,F %! syms x y t %! f = sin(x)*y; %! F = [f; 2*f]; %!test %! % need the simultaneous=True flag in SymPy (matches SMT 2013b) %! assert( isequal( subs(f, [x t], [t 6]), y*sin(t) )) %! assert( isequal( subs(F, [x t], [t 6]), [y*sin(t); 2*y*sin(t)] )) %!test %! % swap x and y (also needs simultaneous=True %! assert( isequal( subs(f, [x y], [y x]), x*sin(y) )) %!test %! % but of course both x and y to t still works %! assert( isequal( subs(f, [x y], [t t]), t*sin(t) )) %% reset the shared variables %!shared %!test %! % Issue #10, subbing matrices in for scalars %! syms y %! a = sym([1 2; 3 4]); %! f = sin(y); %! g = subs(f, y, a); %! assert (isequal (g, sin(a))) %!test %! % Issue #10, subbing matrices in for scalars %! syms y %! a = sym([1 2]); %! g = subs(sin(y), {y}, {a}); %! assert (isequal (g, sin(a))) %!test %! % Issue #10, subbing matrices in for scalars %! syms y %! a = sym([1; 2]); %! g = subs(sin(y), {y}, a); %! assert (isequal (g, sin(a))) %!test %! % Issue #10, subbing matrices in for scalars %! syms y %! a = [10 20 30]; %! f = 2*y; %! g = subs(f, y, a); %! assert (isequal (g, 2*a)) %! assert (isa (g, 'sym')) %!test %! % Issue #10, sub matrices in for two scalars %! syms x y %! a = [10 20 30]; %! f = x^2*y; %! g = subs(f, {x y}, {a a+1}); %! h = a.^2.*(a+1); %! assert (isequal (g, h)) %!test %! % Issue #10, sub matrices in for two scalars %! syms x y z %! a = [10 20 30]; %! f = x^2*y; %! g = subs(f, {x y}, {a z}); %! h = a.^2*z; %! assert (isequal (g, h)) %! g = subs(f, {x y}, {a 6}); %! h = a.^2*6; %! assert (isequal (g, h)) %!error %! syms x y %! a = [10 20 30]; %! f = x^2*y; %! g = subs(f, {x y}, {[10 20 30] [10 20]}); %!test %! % two inputs %! syms x y %! assert (isequal (subs (2*x, 6), sym(12))) %! assert (isequal (subs (2*x*y^2, 6), 12*y^2)) %! assert (isequal (subs (2*y, 6), sym(12))) %! assert (isequal (subs (sym(2), 6), sym(2))) %!test %! % only two inputs, vector %! syms x %! assert (isequal (subs (2*x, [3 5]), sym([6 10]))) %!test %! % SMT compat, subbing in vec/mat for nonexist x %! syms x y z %! % you might think this would be y: %! assert (~ isequal (subs (y, x, [1 2]), y)) %! % but it gives two y's: %! assert (isequal (subs (y, x, [1 2]), [y y])) %! assert (isequal (subs (sym(42), [3 5]), sym([42 42]))) %! assert (isequal (subs (sym(42), x, []), sym([]))) %! assert (isequal (subs (y, {x y}, {[1 2; 3 4], 6}), sym([6 6; 6 6]))) %! assert (isequal (subs (y, {x z}, {[1 2; 3 4], 6}), [y y; y y])) %!test %! syms x y %! assert (isequal (subs (sym(42), x, y), sym(42))) %! assert (isequal (subs (sym(42), y), sym(42))) %! assert (isequal (subs (sym(42)), sym(42))) %!test %! % empty lists %! assert (isequal (subs (sym(42), {}, {}), sym(42))) %! assert (isequal (subs (42, sym([]), sym([])), sym(42))) %!test %! syms x y %! f = x*y; %! x = 6; y = 7; %! g = subs (f); %! assert (isequal (g, sym (42))) %! assert (isa (g, 'sym')) %!test %! syms x y %! f = x*y; %! x = 6; %! g = subs (f); %! assert (isequal (g, 6*y)) %!test %! syms x y %! f = x*y; %! xsave = x; %! x = 6; %! g = subs (f); %! assert (isequal (g, 6*y)) %! assert (isequal (f, xsave*y)) %!test %! syms a x y %! f = a*x*y; %! a = 6; %! clear x %! g = subs (f); %! syms x %! assert (isequal (g, 6*x*y)) symbolic-3.1.1/inst/@sym/subsasgn.m0000644000000000000000000003744214405647405014136 0ustar %% Copyright (C) 2014-2017, 2019, 2022-2023 Colin B. Macdonald %% Copyright (C) 2016 Lagu %% Copyright (C) 2016 Abhinav Tripathi %% Copyright (C) 2017 NVS Abhilash %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypeop Method @@sym {@var{f} =} subsasgn (@var{f}, @var{idx}, @var{rhs}) %% @deftypeopx Operator @@sym {} {@var{f}(@var{i}) = @var{rhs}} {} %% @deftypeopx Operator @@sym {} {@var{f}(@var{i}, @var{j}) = @var{rhs}} {} %% @deftypeopx Operator @@sym {} {@var{f}(@var{i}:@var{j}) = @var{rhs}} {} %% @deftypeopx Operator @@sym {} {@var{f}(@var{x}) = @var{symexpr}} {} %% Assign to entries of a symbolic array. %% %% Examples: %% @example %% @group %% A = sym([10 11 12]); %% A(3) = 44 %% @result{} A = (sym) [10 11 44] (1×3 matrix) %% %% A(1:2) = [42 43] %% @result{} A = (sym) [42 43 44] (1×3 matrix) %% %% A(1, 1) = 41 %% @result{} A = (sym) [41 43 44] (1×3 matrix) %% @end group %% @end example %% %% This method also gets called when creating @@symfuns: %% @example %% @group %% syms x %% f(x) = 3*x^2 %% @result{} f(x) = (symfun) %% 2 %% 3⋅x %% @end group %% @end example %% %% @seealso{@@sym/subsref, @@sym/subindex, @@sym/end, symfun} %% @end deftypeop function out = subsasgn (val, idx, rhs) switch idx.type case '()' %% symfun constructor % f(x) = rhs % f is val % x is idx.subs{1} % This also gets called for "syms f(x)" all_syms = true; for i = 1:length(idx.subs) all_syms = all_syms && isa(idx.subs{i}, 'sym'); end if (all_syms) cmd = { 'L, = _ins' 'return all([x is not None and x.is_Symbol for x in L])' }; all_Symbols = pycall_sympy__ (cmd, idx.subs); end if (all_syms && all_Symbols) %% Make a symfun if (~isa(rhs, 'sym')) % rhs is, e.g., a double, then we call the constructor rhs = sym(rhs); end out = symfun(rhs, idx.subs); else %% Not symfun: e.g., f(double) = ..., f(sym(2)) = ..., % convert any sym subs to double and do array assign for i = 1:length(idx.subs) if (isa(idx.subs{i}, 'sym')) idx.subs{i} = double(idx.subs{i}); end end for i = 1:length(idx.subs) if (~ is_valid_index(idx.subs{i})) error('OctSymPy:subsref:invalidIndices', ... 'invalid indices: should be integers or boolean'); end end out = mat_replace(val, idx.subs, sym(rhs)); end case '.' assert( isa(rhs, 'sym')) assert( ~isa(idx.subs, 'sym')) assert( ~isa(val, 'sym')) val.(idx.subs) = rhs; out = val; otherwise disp('FIXME: do we need to support any other forms of subscripted assignment?') idx rhs val error('broken'); end end %!shared a,b %! b = [1:4]; %! a = sym(b); %!test a(1) = 10; b(1) = 10; %! assert(isequal( a, b )) %!test I = logical([1 0 1 0]); %! a(I) = 2; b(I) = 2; %! assert(isequal( a, b )) %!test I = logical([1 0 1 0]); %! a(I) = [2 4]; b(I) = [2 4]; %! assert(isequal( a, b )) %!test I = logical([1 0 1 0]); %! a(I) = [2; 4]; b(I) = [2; 4]; %! assert(isequal( a, b )) %!shared %!test %! b = 1:4; b = [b; 2*b; 3*b]; %! a = sym(b); %! rhs = [10 11; 12 13]; %! a([1:2],[1:2]) = rhs; %! b([1:2],[1:2]) = rhs; %! assert(isequal( a, b )) %! a(1:2,1:2) = rhs; %! assert(isequal( a, b )) %!test %! % slice : %! b = 1:4; b = [b; 2*b]; %! a = sym(b); %! rhs = [10 11; 12 13]; %! a(:,2:3) = rhs; %! b(:,2:3) = rhs; %! assert(isequal( a, b )) %!test %! % grow 2D %! b = 1:4; b = [b; 2*b]; %! a = sym(b); %! rhs = [10 11; 12 13]; %! a([1 end+1],end:end+1) = rhs; %! b([1 end+1],end:end+1) = rhs; %! assert(isequal( a, b )) %!test %! % grow from nothing %! clear a %! a(3) = sym (1); %! b = sym ([0 0 1]); %! assert (isequal (a, b)) %!test %! % grow from nothing, 2D %! clear a %! a(2, 3) = sym (1); %! b = sym ([0 0 0; 0 0 1;]); %! assert (isequal (a, b)) %!test %! % linear indices of 2D %! b = 1:4; b = [b; 2*b; 3*b]; %! a = sym(b); %! b(1:4) = [10 11 12 13]; %! a(1:4) = [10 11 12 13]; %! assert(isequal( a, b )) %! b(1:4) = [10 11; 12 13]; %! a(1:4) = [10 11; 12 13]; %! assert(isequal( a, b )) %!error %! % Wrong shape matrix RHS: Matlab/Octave don't allow this on doubles. %! % Matlab SMT 2013b gets it wrong. We throw an error. %! rhs = [10 11; 12 13]; %! a = sym (magic (3)); %! a(1:2,1:2) = rhs(:); %!test %! % Issue #963: vector RHS with diff orientation from 2D indexing %! b = 1:4; b = [b; 2*b; 3*b]; %! a = sym(b); %! b(1:2:3, 1) = 11:2:13; %! a(1:2:3, 1) = sym(11:2:13); %! assert (isequal (a, b)) %! b(1:2:3, 1) = 1:2:3; %! a(1:2:3, 1) = 1:2:3; %! assert (isequal (a, b)) %!test %! % Issue #963: vector RHS with diff orientation from 2D indexing %! a = sym (magic (3)); %! b = a; %! a(1:2:3, 2) = [14 15]; %! b(1:2:3, 2) = [14; 15]; %! assert (isequal (a, b)) %! a(2, 1:2:3) = [24 25]; %! b(2, 1:2:3) = [24; 25]; %! assert (isequal (a, b)) %!test %! % 1D growth and 'end' %! g = sym([1 2 3]); %! g(3:4) = [67 68]; %! g(end:end+1) = [12 14]; %! assert(isequal( g, [1 2 67 12 14] )) %!test %! % expanding empty and scalar %! syms x %! c = sym([]); %! c(1) = x; %! assert(isequal( c, x )) %! c(2) = 2*x; %! assert(isequal( c, [x 2*x] )) %% 2d logical indexing, ref and asgn %!shared a,b,I,J %! b = 1:4; b = [b; 3*b; 5*b]; a = sym(b); %! I = logical([1 0 1]); %! J = logical([1 0 1 0]); %!assert(isequal( a(I,J), b(I,J) )) %!test %! rhs = [90 91; 92 93]; %! b(I, J) = rhs; %! a(I, J) = rhs; %! assert(isequal( a, b )) %!test %! b(I, J) = 100; %! a(I, J) = 100; %! assert(isequal( a, b )) %!shared %!test %! % logical with all false %! syms x %! y = x; %! y(false) = 6; %! assert(isequal( y, x )); %! a = [x x]; %! a([false false]) = [6 6]; %! assert(isequal( a, [x x] )); %!test %! % issue #18, scalar access %! syms x %! x(1) = sym(6); %! assert(isequal( x, sym(6) )); %! x(1) = 6; %! assert(isequal( x, sym(6) )); %! x(true) = 88; %! assert(isequal( x, sym(88) )); %!test %! % bug: assignment to column vector used to fail %! A = sym(zeros(3,1)); %! A(1) = 5; %!test %! % symfun creation (generic function) %! syms x %! g(x) = x*x; %! assert(isa(g,'symfun')) %!test %! % symfun creation (generic function) %! syms x g(x) %! assert(isa(g,'symfun')) %!test %! % symfun creation when g already exists and is a sym/symfun %! syms x %! g = x; %! syms g(x) %! assert(isa(g,'symfun')) %! clear g %! g(x) = x; %! g(x) = x*x; %! assert(isa(g,'symfun')) %!test %! % Issue #443: assignment with sym indices %! A = sym([10 11]); %! A(sym(1)) = 12; %! assert (isequal (A, sym([12 11]))) %!test %! % Issue #443: assignment with sym indices %! A = sym([10 11]); %! A(sym(1), 1) = 12; %! assert (isequal (A, sym([12 11]))) %! A(sym(1), sym(1)) = 13; %! assert (isequal (A, sym([13 11]))) %!test %! % Issue #443: assignment with sym indices, increase size %! A = sym([10 11]); %! A(sym(2), 1) = 12; %! assert (isequal (A, sym([10 11; 12 0]))) %!error %! % Issue #443 %! A = sym([10 11]); %! A(2, sym('x')) = sym(12); %!error %! % Issue #443 %! A = sym([10 11]); %! A(sym(2), sym('x')) = sym(12); %!error %! % issue #445 %! A = sym([10 11]); %! A(1.1) = 13 %!error %! % issue #445 %! A = sym([10 11]); %! A(sym(pi)) = 13 %!error %! % issue #445 %! A = sym([1 2; 3 4]); %! A(1.3, 1.2) = 13 %!test %! % older expansion tests %! syms x %! f = [2*x 3*x]; %! f(2) = 4*x; %! assert (isequal (f, [2*x 4*x])) %! f(2) = 2; %! assert (isequal(f, [2*x 2])) %! g = f; %! g(1,3) = x*x; %! assert (isequal(g, [2*x 2 x^2])) %! g = f; %! g(3) = x*x; %! assert (isequal(g, [2*x 2 x^2])) %! g = f; %! g(3) = 4; %! assert (isequal(g, [2*x 2 4])) %!test %! % older slicing tests %! syms x %! f = [1 x^2 x^4]; %! f(1:2) = [x x]; %! assert (isequal( f, [x x x^4] )) %! f(1:2) = [1 2]; %! assert (isequal( f, [1 2 x^4] )) %! f(end-1:end) = [3 4]; %! assert (isequal( f, [1 3 4] )) %! f(3:4) = [10 11]; %! assert (isequal( f, [1 3 10 11] )) %! f(end:end+1) = [12 14]; %! assert (isequal( f, [1 3 10 12 14] )) %!test %! % struct.str = sym, sometimes calls subsasgn %! d = struct(); %! syms x %! d.a = x; %! assert (isa (d, 'struct')) %! assert (isequal (d.a, x)) %! d.('a') = x; %! assert (isa (d, 'struct')) %! assert (isequal (d.a, x)) %! d = setfield(d, 'a', x); %! assert (isa (d, 'struct')) %! assert (isequal (d.a, x)) %! % at least on Oct 3.8, this calls sym's subsasgn %! d = struct(); %! d = setfield(d, 'a', x); %! assert (isa (d, 'struct')) %! assert (isequal (d.a, x)) %!test %! % bool scalar assignments of true/false into sym %! syms x %! a = sym([1 2 x 3]); %! b = [1 2 10 4]; %! e = a == b; %! assert (logical (e(2))) %! e(2) = false; %! assert (~logical (e(2))) %!test %! % bool vector assignments of true/false into sym %! syms x %! a = sym([1 2 x 3]); %! b = [1 2 10 4]; %! e = a == b; %! e(1:2) = [true true]; %! assert (isequal (e, [sym(1)==1 sym(2)==2 x==10 sym(3)==4])) %!test %! % bool scalar promoted to vector assignments into sym %! syms x %! a = sym([1 2 x 3]); %! b = [1 2 10 4]; %! e = a == b; %! e(1:2) = true; %! assert (isequal (e, [sym(1)==1 sym(2)==2 x==10 sym(3)==4])) %!test %! % grow scalar equality expression into a matrix of equalities %! syms a b c d %! e = a == b; %! e(2) = c == d; %! assert (isequal (e, [a==b c==d])) %% 2D arrays from mat_mask_asgn %!shared a, b, I %! b = [1:4]; b = [b; 3*b; 5*b]; %! a = sym(b); %! I = mod (b, 5) > 1; %!test %! A = a; A(I) = 2*b(I); %! B = b; B(I) = 2*b(I); %! assert (isequal (A, B)) %!test %! % scalar RHS %! A = a; A(I) = 17; %! B = b; B(I) = 17; %! assert (isequal (A, B)) %!test %! % nonetheless, above strange case should give right answer %! I = logical([1 0 1 0; 0 1 0 1; 1 0 1 0]); %! rhs = 2*b(I); %! rhs2 = reshape(rhs, 2, 3); %! A0 = a; A1 = a; %! A0(I) = rhs; %! A1(I) = rhs2; %! assert (isequal (A0, A1)) %% Tests from mat_rclist_asgn %!shared AA, BB %! BB = [1 2 3; 4 5 6]; %! AA = sym(BB); %!test %! A = AA; B = BB; %! B([1 6]) = [8 9]; %! A([1 6]) = [8 9]; %! assert (isequal (A, B)) %!test %! % rhs scalar %! A = AA; B = BB; %! B([1 6]) = 88; %! A([1 6]) = 88; %! assert (isequal (A, B)) %!test %! % If rhs is not a vector, make sure col-based access works %! rhs = [18 20; 19 21]; %! A = AA; B = BB; %! B([1 6]) = 88; %! A([1 6]) = 88; %! B([1 2 3 4]) = rhs; %! A([1 2 3 4]) = rhs; %! assert (isequal (A, B)) %!test %! % Growth %! A = AA; B = BB; %! A(1,5) = 10; %! B(1,5) = 10; %! assert (isequal (A, B)) %!shared %!test %! % Check row deletion 1D %! a = sym([1; 3; 5]); %! b = sym([3; 5]); %! a(1) = []; %! assert( isequal( a, b)) %!test %! % Check column deletion 1D %! a = sym([1, 4, 8]); %! b = sym([4, 8]); %! a(1) = []; %! assert( isequal( a, b)) %!test %! % Check row deletion 2D %! a = sym([1, 2; 3, 4]); %! b = sym([3, 4]); %! a(1, :) = []; %! assert( isequal( a, b)) %!test %! % Check column deletion 2D %! a = sym([1, 2; 3, 4]); %! b = sym([2; 4]); %! a(:, 1) = []; %! assert( isequal( a, b)) %!test %! % General assign %! a = sym([1, 2; 3, 4]); %! b = sym([5, 5; 5, 5]); %! a(:) = 5; %! assert( isequal( a, b)) %!test %! % Empty matrix %! a = sym([1, 2; 3, 4]); %! a(:) = []; %! assert( isequal( a, sym([]))) %!test %! % Disassemble matrix %! a = sym([1 2; 3 4; 5 6]); %! b = sym([3 5 2 4 6]); %! a(1) = []; %! assert (isequal (a, b)); %!error %! a = sym([1, 2; 3, 4]); %! a(1, 2) = []; %!test %! % Issue #964 %! a = sym(10); %! a(1) = []; %! assert (isempty (a)) %! assert (isequal (a, zeros(1, 0))) %!test %! % Issue #963: scalar asgn to empty part of matrix %! A = sym (magic (3)); %! B = A; %! A(1, []) = 42; %! assert (isequal (A, B)) %! A([], 2) = 42; %! assert (isequal (A, B)) %! A([]) = 42; %! assert (isequal (A, B)) %! A([], []) = 42; %! assert (isequal (A, B)) %! A(2:3, []) = 42; %! assert (isequal (A, B)) %! A([], 2:3) = 42; %! assert (isequal (A, B)) %! A(:, []) = 42; %! assert (isequal (A, B)) %! A([], :) = 42; %! assert (isequal (A, B)) %!test %! % Issue #1026 %! a = sym(1:5); %! a(1:3) = []; %! assert (isequal (a, sym([4 5]))) %!test %! % Issue #1026 %! B = eye(4); %! A = sym(B); %! A(1:2, :) = []; %! B(1:2, :) = []; %! assert (isequal (A, B)) %!error %! % TODO: do we care what error? %! A = sym (magic (3)); %! A(2:3, []) = [66; 66]; %!error %! A = sym (magic (3)); %! A([]) = [66; 66]; %!error %! A = sym (magic (3)); %! A([], 1) = [66; 66]; %!test %! % Issue #966: empty indexing, empty RHS, A unchanged %! B = magic(3); %! A = sym(B); %! A(1, []) = []; %! assert (isequal (A, B)) %! A([], 2) = []; %! assert (isequal (A, B)) %! A([], []) = []; %! assert (isequal (A, B)) %! A(2:3, []) = []; %! assert (isequal (A, B)) %! A([], 2:3) = []; %! assert (isequal (A, B)) %! A(:, []) = []; %! assert (isequal (A, B)) %! A([], :) = []; %! assert (isequal (A, B)) %!test %! % Issue 967 %! B = [1 2; 3 4]; %! A = sym(B); %! A([]) = []; %! assert (isequal (A, B)) %!test %! % Issue #965 %! a = sym(7); %! a([]) = []; %! assert (isequal (a, sym(7))) %!test %! % Issue #965 %! a = sym(7); %! a([]) = 42; %! assert (isequal (a, sym(7))) %!error %! % Issue #965 %! a = sym(7); %! a([]) = [42 42] %!test %! b = eye (3); %! a = sym (b); %! I = [2 3; 4 5]; %! a(I) = -2*I; %! b(I) = -2*I; %! assert (isequal (a, sym (b))); %! assert (size (a), [3 3]); %% Tests from mat_replace %!error %! syms x %! A = [1 x; x 2]; %! A(5) = x; %!test %! % 2D indexing with length in one dimension more than 2 %! a = sym ([1 2; 3 4; 5 6]); %! indices = [1 4; 2 5; 3 6]; %! b = [10 11; 12 13; 14 15]; %! a(indices) = b; %! assert (isequal (a, sym (b))); %!test %! A = sym ([0 0 0]); %! indices = [false true false]; %! A(indices) = 1; %! assert (isequal (A, sym ([0 1 0]))); %! A(indices) = []; %! assert (isequal (A, sym ([0 0]))); %! indices = [false false]; %! A(indices) = []; %! assert (isequal (A, sym ([0 0]))); %!shared a, b %! a = [1 2 3 5; 4 5 6 9; 7 5 3 2]; %! b = sym (a); %!test %! A = a; B = b; %! A(true) = 0; %! B(true) = 0; %! assert (isequal (A, B)) %!test %! A = a; B = b; %! A(false) = 0; %! B(false) = 0; %! assert (isequal (A, B)) %!test %! c = [false true]; %! A = a; B = b; %! A(c) = 0; B(c) = 0; %! assert (isequal (A, B)) %! d = c | true; %! A(d) = 1; B(d) = 1; %! assert (isequal (A, B)) %! d = c & false; %! A(d) = 2; B(d) = 2; %! assert (isequal (A, B)) %!test %! c = [false true false true; true false true false; false true false true]; %! A = a; B = b; %! A(c) = 0; B(c) = 0; %! assert (isequal (A, B)) %! d = c | true; %! A(d) = 1; B(d) = 1; %! assert (isequal (A, B)) %! d = c & false; %! A(d) = 2; B(d) = 2; %! assert (isequal (A, B)) %!test %! c = [false true false true false]; %! A = a; B = b; %! A(c) = 0; B(c) = 0; %! assert (isequal (A, B)) %! d = c | true; %! A(d) = 1; B(d) = 1; %! assert (isequal (A, B)) %! d = c & false; %! A(d) = 2; B(d) = 2; %! assert (isequal (A, B)) %!test %! c = [false; true; false; true; false]; %! A = a; B = b; %! A(c) = 0; B(c) = 0; %! assert (isequal (A, B)) %! d = c | true; %! A(d) = 1; B(d) = 1; %! assert (isequal (A, B)) %! d = c & false; %! A(d) = 2; B(d) = 2; %! assert (isequal (A, B)) %!test %! c = [false true; false true; true false]; %! A = a; B = b; %! A(c) = 0; B(c) = 0; %! assert (isequal (A, B)) %! d = c | true; %! A(d) = 1; B(d) = 1; %! assert (isequal (A, B)) %! d = c & false; %! A(d) = 2; B(d) = 2; %! assert (isequal (A, B)) %% End of mat_* tests symbolic-3.1.1/inst/@sym/subsindex.m0000644000000000000000000000615614405647405014313 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym subsindex {(@var{x})} %% @defopx Operator @@sym {@var{A}(sym(@var{x}))} {} %% Used to implement indexing by sym. %% %% Note returns zero-based index. %% %% This function should not need to be called directly, but it %% is used internally, for example in: %% @example %% @group %% A = sym([10 11]); %% A(sym(1)) %% @result{} (sym) 10 %% %% A(sym(2)) = sym('x') %% @result{} A = (sym) [10 x] (1×2 matrix) %% @end group %% @end example %% %% @seealso{@@sym/subsref, @@sym/subsasgn, @@sym/end} %% @end defop function b = subsindex(x) % check if all bool or all integer cmd = { '(A,) = _ins' 'if A is None:' ' return 0' 'if not A.is_Matrix:' ' A = sp.Matrix([A])' 'if all([x.is_Integer for x in A]):' ' return 1,' 'elif all([x in (S.true, S.false) for x in A]):' ' return 2,' 'else:' ' return 0,' }; flag = pycall_sympy__ (cmd, x); assert(isnumeric(flag)) if (flag == 0) error('OctSymPy:subsindex:values', 'subscript indices must be integers or boolean'); elseif (flag == 1) % integer b = double(x) - 1; % zero-based elseif (flag == 2) % boolean b = find(logical(x)) - 1; % zero-based else error('subsindex: programming error'); end end %!test %! i = sym(1); %! a = 7; %! assert(a(i)==a); %! i = sym(2); %! a = 2:2:10; %! assert(a(i)==4); %!test %! i = sym([1 3 5]); %! a = 1:10; %! assert( isequal (a(i), [1 3 5])) %!test %! i = sym([1 3 5]); %! a = sym(1:10); %! assert( isequal (a(i), sym([1 3 5]))); %!test %! % should be an error if it doesn't convert to double %! syms x %! a = 1:10; %! try %! a(x) %! waserr = false; %! catch %! waserr = true; %! end %! assert(waserr) %!test %! syms x %! assert (isequal (x(sym (true)), x)) %! assert (isequal (x(sym (false)), sym ([]))) %!test %! x = 6; %! assert (isequal (x(sym (true)), 6)) %! assert (isequal (x(sym (false)), [])) %!test %! a = sym([10 12 14]); %! assert (isequal (a(sym ([true false true])), a([1 3]))) %! assert (isequal (a(sym ([false false false])), sym (ones(1,0)))) %!test %! a = [10 11; 12 13]; %! p = [true false; true true]; %! assert (isequal (a(sym (p)), a(p))) %! p = [false false false]; %! assert (isequal (a(sym (p)), a(p))) %!error %! a = [10 12]; %! I = [sym(true) 2]; %! b = a(I); symbolic-3.1.1/inst/@sym/subsref.m0000644000000000000000000002141214405647405013750 0ustar %% Copyright (C) 2014, 2016-2017, 2022-2023 Colin B. Macdonald %% Copyright (C) 2016 Lagu %% Copyright (C) 2016 Abhinav Tripathi %% Copyright (C) 2017 NVS Abhilash %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym subsref {(@var{f}, @var{idx})} %% @defopx Operator @@sym {@var{f}(@var{i})} {} %% @defopx Operator @@sym {@var{f}(@var{i}, @var{j})} {} %% @defopx Operator @@sym {@var{f}(@var{i}:@var{j})} {} %% @defopx Operator @@sym {@var{f}.property} {} %% Access entries of a symbolic array. %% %% Examples: %% @example %% @group %% A = sym([10 11 12]); %% A(2) %% @result{} (sym) 11 %% %% A(2:3) %% @result{} (sym) [11 12] (1×2 matrix) %% %% A(1, 1) %% @result{} (sym) 10 %% @end group %% %% @group %% A.flat %% @result{} Matrix([[10, 11, 12]]) %% @end group %% @end example %% %% @seealso{@@sym/subsasgn, @@sym/subsindex, @@sym/end} %% @end defop function varargout = subsref (f, idx) switch idx.type case '()' % sym(sym) indexing gets here for i = 1:length(idx.subs) if (isa(idx.subs{i}, 'sym')) idx.subs{i} = subsindex(idx.subs{i})+1; end end for i = 1:length(idx.subs) if (~ is_valid_index(idx.subs{i})) error('OctSymPy:subsref:invalidIndices', ... 'invalid indices: should be integers or boolean'); end end out = mat_access(f, idx.subs); case '.' fld = idx.subs; if (strcmp (fld, 'pickle')) out = f.pickle; elseif (strcmp (fld, 'flat')) out = f.flat; elseif (strcmp (fld, 'ascii')) out = f.ascii; elseif (strcmp (fld, 'unicode')) out = f.unicode; %elseif (strcmp (fld, 'extra')) % out = f.extra; % not part of the interface %elseif (strcmp (fld, 'size')) % out = f.size; else error ('@sym/subsref: invalid or nonpublic property ''%s''', fld); end otherwise error ('@sym/subsref: invalid subscript type ''%s''', idx.type); end % Octave 7.1, Issue #1112 and https://savannah.gnu.org/bugs/?61898 varargout = {out}; end %!shared a,b %! b = [1:4]; %! a = sym(b); %!assert(isequal( a(1), b(1) )) %!assert(isequal( a(2), b(2) )) %!assert(isequal( a(4), b(4) )) %!assert(isempty( a([]) )) %!shared a,b %! b = [1:4]; b = [b; 3*b; 5*b]; %! a = sym(b); %!assert(isequal( a(1), b(1) )) %!assert(isequal( a(2), b(2) )) %!assert(isequal( a(4), b(4) )) %!assert(isequal( a(:,:), a )) %!assert(isequal( a(1:2,1:3), a(1:2,1:3) )) %!assert(isequal( a(1:2:3,[1 2 4]), b(1:2:3,[1 2 4]) )) %!assert(isequal( a(1:2:3,[4 2 3 1]), b(1:2:3,[4 2 3 1]) )) % repeats %!assert(isequal( a(1:2:3,[4 1 1 1]), b(1:2:3,[4 1 1 1]) )) %!assert(isequal( a([],:), b([],:) )) %!assert(isequal( size(a([],:)), [0 4] )) %!assert(isequal( a(1:2,[]), b(1:2,[]) )) %!assert(isequal( size(a(1:2,[])), [2 0] )) %!assert(isempty( a(1:2,[]) )) %!assert(isempty( a([],[]) )) %!assert(isequal( a([],[]), sym([]) )) %!assert(~isequal( a(1:2,[]), sym([]) )) %!shared e %! e = sym([1 3 5; 2 4 6]); %!assert(isequal( e(:), sym((1:6)') )) %!assert(isequal( e([1 2 3]), sym([1 2 3]) )) %!assert(isequal( e([1; 3; 4]), sym([1; 3; 4]) )) %!assert(isempty( e([]) )) %!assert(isempty( e('') )) %!assert(isequal( e([]), sym([]) )) %!shared a,b %! b = 1:5; a = sym(b); %!assert(isequal( a([1 2 5]), b([1 2 5]) )) %!assert(isequal( a([1; 2; 5]), b([1; 2; 5]) )) %!shared x %! syms x %!test %! % logical with empty result %! assert(isempty( x(false) )) %! a = [x x]; %! assert(isempty( a([false false]) )) %!test %! % issue 18, scalar access %! assert(isequal( x(1), x )) %! assert(isequal( x(true), x )) %!shared %!test %! % older access tests %! syms x %! f = [x 2; 3 4*x]; %! % element access %! assert (logical( f(1,1) == x )) %! assert (logical( f(1,2) == 2 )) %! % linear access of 2d array %! assert (logical( f(1) == x )) %! assert (logical( f(2) == 3 )) % column based %! assert (logical( f(3) == 2 )) %!shared a,b %! % effectively a random matrix %! a = reshape( round(50*(sin(1:20)+1)), 5,4); %! b = sym(a); %!test %! % older array refs test %! assert (logical(b(1,1) == a(1,1))) %! assert (logical(b(3,1) == a(3,1))) %! assert (logical(b(1,3) == a(1,3))) %! assert (logical(b(4,4) == a(4,4))) %!test %! % older array refs test: linear indices %! assert (logical(b(1) == a(1))) %! assert (logical(b(3) == a(3))) %! assert (logical(b(13) == a(13))) %!test %! % older array refs test: end %! assert (all(all(logical( b(end,1) == a(end,1) )))) %! assert (all(all(logical( b(2,end) == a(2,end) )))) %! assert (all(all(logical( b(end,end) == a(end,end) )))) %! assert (all(all(logical( b(end-1,1) == a(end-1,1) )))) %! assert (all(all(logical( b(2,end-1) == a(2,end-1) )))) %! assert (all(all(logical( b(end-1,end-1) == a(end-1,end-1) )))) %!shared %!test %! % older slicing tests %! syms x %! a = [1 2 3 4 5 6]; a = [a; 3*a; 5*a; 2*a; 4*a]; %! b = sym(a); %! assert (isequal( b(:,1), a(:,1) )) %! assert (isequal( b(:,2), a(:,2) )) %! assert (isequal( b(1,:), a(1,:) )) %! assert (isequal( b(2,:), a(2,:) )) %! assert (isequal( b(:,:), a(:,:) )) %! assert (isequal( b(1:3,2), a(1:3,2) )) %! assert (isequal( b(1:4,:), a(1:4,:) )) %! assert (isequal( b(1:2:5,:), a(1:2:5,:) )) %! assert (isequal( b(1:2:4,:), a(1:2:4,:) )) %! assert (isequal( b(2:2:4,3), a(2:2:4,3) )) %! assert (isequal( b(2:2:4,3), a(2:2:4,3) )) %!test %! % 2D arrays %! b = [1:4]; b = [b; 3*b; 5*b]; %! a = sym(b); %! I = rand(size(b)) > 0.5; %! assert (isequal (a(I), b(I))) %! I = I(:); %! assert (isequal (a(I), b(I))) %! I = I'; %! assert (isequal (a(I), b(I))) %! I = logical(zeros(size(b))); %! assert (isequal (a(I), b(I))) %!test %! % 1D arrays, does right with despite warning %! r = [1:6]; %! ar = sym(r); %! c = r'; %! ac = sym(c); %! Ir = rand(size(r)) > 0.5; %! Ic = rand(size(c)) > 0.5; %! assert (isequal (ar(Ir), r(Ir))) %! assert (isequal (ac(Ic), c(Ic))) %! assert (isequal (ar(Ic), r(Ic))) %! assert (isequal (ac(Ir), c(Ir))) %!test %! % rccross tests %! B = [1 2 3 4; 5 6 7 9; 10 11 12 13]; %! A = sym(B); %! assert (isequal (A([1 3],[2 3]), B([1 3], [2 3]) )) %! assert (isequal (A(1,[2 3]), B(1,[2 3]) )) %! assert (isequal (A([1 2],4), B([1 2],4) )) %! assert (isequal (A([2 1],[4 2]), B([2 1],[4 2]) )) %! assert (isequal (A([],[]), B([],[]) )) %!error %! % issue #445 %! A = sym([10 11]); %! A(1.1) %!error %! % issue #445 %! A = sym([10 11]); %! A(sym(4)/3) %!error %! % issue #445 %! A = sym([1 2; 3 4]); %! A(1.1, 1) %!error %! % issue #445 %! A = sym([1 2; 3 4]); %! A(1, sym(4)/3) %!error %! A = sym([1 2; 3 4]); %! A(5) %!shared a, b %! a = [1 2 3 5; 4 5 6 9; 7 5 3 2]; %! b = sym (a); %!test %! c = true; %! assert (isequal (a(c), b(c))) %! c = false; %! assert (isequal (a(c), b(c))) %!test %! c = [false true]; %! assert (isequal (a(c), b(c))) %! d = c | true; %! assert (isequal (a(d), b(d))) %! d = c & false; %! assert (isequal (a(d), b(d))) %!test %! c = [false true false true; true false true false; false true false true]; %! assert (isequal (a(c), b(c))) %! d = c | true; %! assert (isequal (a(d), b(d))) %! d = c & false; %! assert (isequal (a(d), b(d))) %!test %! c = [false true false true false]; %! assert (isequal (a(c), b(c))) %! d = c | true; %! assert (isequal (a(d), b(d))) %! d = c & false; %! assert (isequal (a(d), b(d))) %!test %! c = [false; true; false; true; false]; %! assert (isequal (a(c), b(c))) %! d = c | true; %! assert (isequal (a(d), b(d))) %! d = c & false; %! assert (isequal (a(d), b(d))) %!test %! c = [false true; false true; true false]; %! assert (isequal (a(c), b(c))) %! d = c | true; %! assert (isequal (a(d), b(d))) %! d = c & false; %! assert (isequal (a(d), b(d))) %!shared %!test %! % Orientation of empty results of logical indexing on row or column vectors %! r = [1:6]; %! c = r'; %! ar = sym(r); %! ac = sym(c); %! assert (isequal (ar(false), r(false))) %! assert (isequal (ac(false), c(false))) %! assert (isequal (ar(false (1, 6)), r(false (1, 6)))) %! assert (isequal (ac(false (1, 6)), c(false (1, 6)))) %! assert (isequal (ar(false (6, 1)), r(false (6, 1)))) %! assert (isequal (ac(false (6, 1)), c(false (6, 1)))) symbolic-3.1.1/inst/@sym/sum.m0000644000000000000000000000521114405647405013102 0ustar %% Copyright (C) 2014-2016, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym sum (@var{x}) %% @defmethodx @@sym sum (@var{x}, @var{n}) %% Sum of symbolic expressions. %% %% Sum over the rows or columns of an expression. By default, sum %% over the rows. Can specify row or column sums using @var{n}. %% To perform symbolic summations, @pxref{@@sym/symsum}. %% %% Examples: %% @example %% @group %% syms x y z %% sum([x y z]) %% @result{} (sym) x + y + z %% %% sum([x y; x z], 1) %% @result{} (sym) [2⋅x y + z] (1×2 matrix) %% %% sum([x y; x z], 2) %% @result{} (sym 2×1 matrix) %% ⎡x + y⎤ %% ⎢ ⎥ %% ⎣x + z⎦ %% @end group %% @end example %% %% @seealso{@@sym/prod, @@sym/symsum} %% @end defmethod function y = sum(x, n) x = sym(x); if (nargin == 1) if (isrow(x)) n = 2; elseif (iscolumn(x)) n = 1; else n = 1; end elseif (nargin == 2) n = double(n); else print_usage (); end cmd = { 'A = _ins[0]' 'if not isinstance(A, sympy.MatrixBase):' ' A = Matrix([A])' 'B = sp.Matrix.zeros(A.rows, 1)' 'for i in range(0, A.rows):' ' B[i] = sum(A.row(i))' 'return B' }; if (n == 1) y = pycall_sympy__ (cmd, transpose(x)); y = transpose(y); elseif (n == 2) y = pycall_sympy__ (cmd, x); else print_usage (); end end %!error sum (sym(1), 2, 3) %!error sum (sym(1), 42) %!shared x,y,z %! syms x y z %!assert (isequal (sum (x), x)) %!assert (isequal (sum ([x y z]), x+y+z)) %!assert (isequal (sum ([x; y; z]), x+y+z)) %!assert (isequal (sum ([x y z], 1), [x y z])) %!assert (isequal (sum ([x y z], 2), x+y+z)) %!shared a,b %! b = [1 2; 3 4]; a = sym(b); %!assert (isequal (sum(a), sum(b))) %!assert (isequal (sum(a,1), sum(b,1))) %!assert (isequal (sum(a,2), sum(b,2))) %!test %! % weird inputs %! a = sum('xx', sym(1)); %! assert (isequal (a, sym('xx'))) symbolic-3.1.1/inst/@sym/svd.m0000644000000000000000000000513614405647405013100 0ustar %% Copyright (C) 2014, 2016, 2018-2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {@var{S} =} svd (@var{A}) %% @deftypemethodx @@sym {[@var{U}, @var{S}, @var{V}] =} svd (@var{A}) %% Symbolic singular value decomposition. %% %% The SVD: U*S*V' = A %% %% Singular values example: %% @example %% @group %% A = sym([1 0; 3 0]); %% svd(A) %% @result{} (sym 2×1 matrix) %% %% ⎡√10⎤ %% ⎢ ⎥ %% ⎣ 0 ⎦ %% %% @end group %% @end example %% %% FIXME: currently only singular values, not singular vectors. %% Should add full SVD to sympy. %% %% @seealso{svd, @@sym/eig} %% @end deftypemethod function [S, varargout] = svd(A) if (nargin >= 2) error('svd: economy-size not supported yet') end if (nargout >= 2) error('svd: singular vectors not yet computed by sympy') end cmd = { '(A,) = _ins' 'if not A.is_Matrix:' ' A = sp.Matrix([A])' 'L = sp.Matrix(A.singular_values())' 'return L,' }; S = pycall_sympy__ (cmd, sym(A)); end %!test %! % basic %! A = [1 2; 3 4]; %! B = sym(A); %! sd = svd(A); %! s = svd(B); %! s2 = double(s); %! assert (norm(s2 - sd) <= 10*eps) %!test %! % scalars %! syms x %! syms y positive %! a = sym(-10); %! assert (isequal (svd(a), sym(10))) %! assert (isequal (svd(x), sqrt(x*conj(x)))) %! assert (isequal (svd(y), y)) %!test %! % matrix with symbols %! syms x positive %! A = [x+1 0; sym(0) 2*x+1]; %! s = svd(A); %! s2 = subs(s, x, 2); %! assert (isequal (s2, [sym(5); 3])) %!test %! % matrix with symbols %! syms x positive %! A = [x+1 0; sym(0) 2*x+1]; %! s = svd(A); %! s2 = subs(s, x, 2); %! assert (isequal (s2, [sym(5); 3])) %!test %! % matrix with symbols, nonneg sing values %! syms x real %! A = [x 0; 0 sym(-5)]; %! s = svd(A); %! assert (isequal (s, [abs(x); 5])) %%!test %%! % no sing vecs %%! A = [x 0; sym(0) 2*x] %%! [u,s,v] = cond(A) %%! assert (false) symbolic-3.1.1/inst/@sym/sym.m0000644000000000000000000007527314405647405013125 0ustar %% Copyright (C) 2014-2019, 2022 Colin B. Macdonald %% Copyright (C) 2016 Lagu %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypeop Constructor @@sym {@var{x} =} sym (@var{y}) %% @deftypeopx Constructor @@sym {@var{x} =} sym (@var{y}, @var{assumestr}) %% @deftypeopx Constructor @@sym {@var{x} =} sym (@var{y}, @var{assumestr1}, @var{assumestr2}, @dots{}) %% @deftypeopx Constructor @@sym {@var{x} =} sym (@var{A}, [@var{n}, @var{m}]) %% @deftypeopx Constructor @@sym {@var{x} =} sym (@var{y}, @var{ratflag}) %% @deftypeopx Constructor @@sym {@var{x} =} sym (@var{handle}) %% Define symbols and numbers as symbolic expressions. %% %% @var{y} can be an integer, a string or one of several special %% double values. It can also be a double matrix or a cell %% array. %% %% Examples: %% @example %% @group %% x = sym ('x') %% @result{} x = (sym) x %% y = sym ('2') %% @result{} y = (sym) 2 %% y = sym (3) %% @result{} y = (sym) 3 %% y = sym (inf) %% @result{} y = (sym) ∞ %% y = sym (pi) %% @result{} y = (sym) π %% y = sym (1i) %% @result{} y = (sym) ⅈ %% @end group %% @end example %% %% A sym of a sym is a sym (idempotence): %% @example %% @group %% sym (sym (pi)) %% @result{} (sym) π %% @end group %% @end example %% %% A matrix of integers can be input: %% @example %% @group %% sym ([1 2; 3 4]) %% @result{} (sym 2×2 matrix) %% ⎡1 2⎤ %% ⎢ ⎥ %% ⎣3 4⎦ %% @end group %% @end example %% %% However, if the entries are not simply integers, its better to call %% @code{sym} inside the matrix: %% @example %% @group %% [sym(pi) sym(3)/2; sym(1) 0] %% @result{} (sym 2×2 matrix) %% ⎡π 3/2⎤ %% ⎢ ⎥ %% ⎣1 0 ⎦ %% @end group %% @end example %% (Careful: at least one entry per row must be @code{sym} to workaround %% a GNU Octave bug @url{https://savannah.gnu.org/bugs/?42152}.) %% @c @example %% @c [sym(pi) 2; 1 0] %% @c @print{} ??? octave_base_value::map_value(): wrong type argument 'scalar' %% @c @end example %% %% Passing double values to sym is not recommended and will give a warning: %% @example %% @group %% sym(0.1) %% @print{} warning: passing floating-point values to sym is %% @print{} dangerous, see "help sym"... %% @result{} ans = (sym) 1/10 %% @end group %% @end example %% %% In this particular case, the warning is easy to avoid: %% @example %% @group %% sym(1)/10 %% @result{} (sym) 1/10 %% @end group %% @end example %% %% The ``danger'' here is that typing @code{0.1} gives a double-precision %% floating-point value which differs slightly from the fraction %% @code{sym(1)/10} (and this is true for most decimal expressions). %% It is generally impossible to determine which exact symbolic value the %% user intended. %% The warning indicates that some heuristics have been applied %% (namely a preference for ``small'' fractions, small fractions %% of π and square roots of integers). %% Further examples include: %% @example %% @group %% y = sym(pi/100) %% @print{} warning: passing floating-point values to sym is %% @print{} dangerous, see "help sym"... %% @result{} y = (sym) %% π %% ─── %% 100 %% @end group %% %% @group %% y = sym(pi)/100 %% @result{} y = (sym) %% π %% ─── %% 100 %% @end group %% @end example %% (@code{sym(pi)} is a special case; it does not raise the warning). %% %% %% There is an additional reason for the float-point warning, %% relevant if you are doing something like @code{sym(1.23456789012345678)}. %% In many cases, floating-point numbers should be thought of as %% approximations (with about 15 decimal digits of relative accuracy). %% This means that mixing floating-point values and symbolic computations %% with the goal of obtaining exact results is often a fool's errand. %% Compounding this, symbolic computations may not always use numerically %% stable algorithms (as their inputs are assumed exact) whereas a %% floating-point input is effectively perturbed in the 15th digit. %% %% If what you really want is higher-precision floating-point %% computations, @pxref{vpa}. %% %% %% If having read the above, you @emph{still} want to do something %% symbolic with floating-point inputs, you can use the @var{ratflag} %% argument; by setting it to @qcode{'f'}, you will obtain the precise %% rational number which is equal to the floating-point value: %% @example %% @group %% sym(0.1, 'f') %% @result{} (sym) %% 3602879701896397 %% ───────────────── %% 36028797018963968 %% @end group %% @end example %% %% The default heuristic rational behaviour can be obtained by passing %% @var{ratflag} as @qcode{'r'}; this avoids the floating-point warning: %% @example %% @group %% sym(0.1, 'r') %% @result{} (sym) 1/10 %% @end group %% @end example %% %% %% For symbols, a second (and further) arguments can provide assumptions %% or restrictions on the type of the symbol: %% @example %% @group %% x = sym ('x', 'positive') %% @result{} x = (sym) x %% x = sym ('x', 'positive', 'integer') %% @result{} x = (sym) x %% @end group %% @end example %% @xref{assumptions}, for the list of supported assumptions. %% %% Caution: it is possible to create multiple variants of the %% same symbol with different assumptions. %% @example %% @group %% x1 = sym('x') %% @result{} x1 = (sym) x %% x2 = sym('x', 'positive') %% @result{} x2 = (sym) x %% x1 == x2 %% @result{} (sym) x = x %% isAlways(x1 == x2) %% @result{} 0 %% logical(x1 == x2) %% @result{} 0 %% @end group %% @end example %% %% The second argument can also specify the size of a matrix: %% @example %% @group %% A = sym('a', [2 3]) %% @result{} A = (sym 2×3 matrix) %% ⎡a₁₁ a₁₂ a₁₃⎤ %% ⎢ ⎥ %% ⎣a₂₁ a₂₂ a₂₃⎦ %% @end group %% @end example %% or even with symbolic size: %% @example %% @group %% syms m n positive integer %% B = sym('B', [m n]) %% @result{} B = (sym) B (m×n matrix expression) %% @end group %% @end example %% %% Anonymous functions can be converted to symbolic expressions by %% passing their function handle: %% @example %% @group %% f = @@(n, x) sin (pi*besselj (n, x)/2) %% @result{} f = @@(n, x) sin (pi * besselj (n, x) / 2) %% class (f) %% @result{} function_handle %% sym(f) %% @result{} (sym) %% ⎛π⋅besselj(n, x)⎞ %% sin⎜───────────────⎟ %% ⎝ 2 ⎠ %% @end group %% @end example %% %% It is also possible to save sym objects to file and then load them when %% needed in the usual way with the @code{save} and @code{load} commands. %% %% The underlying SymPy string representation (``srepr'') can usually be passed %% directly to @code{sym}: @pxref{@@sym/char} for discussion of the details. %% %% @seealso{syms, assumptions, @@sym/assume, @@sym/assumeAlso} %% @end deftypeop function s = sym(x, varargin) if (nargin == 0) x = 0; end %% The actual class constructor % Tempting to make a 'private constructor' but we need to access % this from the python ipc stuff: outside the class. We identify % this non-user-facing usage by empty x and 6 inputs total. Note % that "sym([])" is valid but "sym([], ...)" is otherwise not. if (isempty (x) && nargin == 6) s.pickle = varargin{1}; s.size = varargin{2}; s.flat = varargin{3}; s.ascii = varargin{4}; s.unicode = varargin{5}; s.extra = []; s = class (s, 'sym'); return end %% User interface for defining sym % sym(1), sym('x'), etc. %if (strcmp (class (x), 'symfun') && nargin==1) % % FIXME: pass a symfun to sym() ctor; convert to pure sym % % (SMT does not do this in 2014a). bad idea? % s = x.sym; % return if (isa (x, 'sym')) if (nargin == 1) s = x; return else x = x.flat; end end if (iscell (x)) %% Cell arrays are converted to sym arrays assert (isempty (varargin)); s = cell2sym (x); return end if (isa (x, 'function_handle')) assert (nargin == 1) %% Need argnames of the handle. TODO: can do better than regex? vars = regexp (func2str (x), '^\@\(([\w,\s]*)\)', 'tokens', 'once'); assert (length (vars) == 1) vars = vars{1}; if (isempty (vars)) vars = {}; % empty char to empty cell else vars = strsplit (vars, {',' ' '}); end for i = 1:length (vars) vars{i} = sym (sprintf ('Symbol("%s")', vars{i})); end %% call the function with those arguments as symbolic inputs s = x (vars{:}); if (~ isa (s, 'sym')) % e.g., for "@(x) 7" s = sym (s); end return end asm = {}; isnumber = isnumeric (x) || islogical (x); ratwarn = true; ratflag = 'r'; if (nargin >= 2) if (ismatrix (varargin{1}) && ~ischar (varargin{1}) && ~isstruct (varargin{1}) && ~iscell (varargin{1})) %% Handle MatrixSymbols assert (nargin < 3, 'MatrixSymbol do not support assumptions') s = make_sym_matrix (x, varargin{1}); return elseif (nargin == 2 && isnumber && ischar (varargin{1}) && isscalar (varargin{1})) %% explicit ratflag given sclear = false; ratflag = varargin{1}; switch ratflag case 'f' ratwarn = false; case 'r' ratwarn = false; case {'d' 'e'} error ('sym: RATFLAG ''%s'' is not implemented', ratflag) otherwise error ('sym: invalid RATFLAG ''%s''', ratflag) end elseif (nargin == 2 && ischar (varargin{1}) && strcmp (varargin{1}, 'clear')) sclear = true; varargin(1) = []; warning ('OctSymPy:deprecated', ... ['"sym(x, ''clear'')" is deprecated and will be removed in a future version;\n' ... ' use "assume(x, ''clear'')" instead.']) else sclear = false; assert (~isnumber, 'Only symbols can have assumptions.') check_assumptions (varargin); % Check if assumptions exist - Sympy don't check this asm = varargin; end end if (~isscalar (x) && isnumber) % Handle octave numeric matrix s = numeric_array_to_sym (x); return elseif (isa (x, 'double')) % Handle double/complex iscmplx = ~isreal (x); if (iscmplx && isequal (x, 1i)) s = pycall_sympy__ ('return S.ImaginaryUnit'); return elseif (iscmplx) xx = {real(x); imag(x)}; else xx = {x}; end yy = cell(2, 1); for n = 1:numel (xx) x = xx{n}; switch ratflag case 'f' y = double_to_sym_exact (x); case 'r' y = double_to_sym_heuristic (x, ratwarn, []); otherwise error ('sym: this case should not be possible') end yy{n} = y; end if (iscmplx) s = yy{1} + yy{2}*1i; else s = yy{1}; end return elseif (isinteger (x)) % Handle integer vealues s = pycall_sympy__ ('return Integer(*_ins)', x); return elseif (islogical (x)) % Handle logical values if (x) s = pycall_sympy__ ('return S.true'); else s = pycall_sympy__ ('return S.false'); end return end if (isa (x, 'char')) %% Need to decide whether to use S() or Symbol() % TODO: tests pass without this? Is there a example where this is needed? %% sym('---1') -> '-' '1' Split first symbols to can search operators correctly. %r = 1; %xc = ''; % Used to check operators skipping first symbols %for i = 1:length (x) % if (strcmp (x (i), '-')) % r = r*-1; % elseif (~strcmp (x (i), '+')) % if (r == -1) % xc = x (i:end); % x = ['-' x(i:end)]; % else % x = xc = x (i:end); % end % break % end %end y = detect_special_str (x); if (~ isempty (y)) assert (isempty (asm), 'Only symbols can have assumptions.') s = pycall_sympy__ (['return ' y]); return end isnum = ~isempty (regexp (strtrim (x), ... '^[-+]*?[\d_]*\.?[\d_]*(e[+-]?[\d_]+)?$')); %% Use Symbol() for words, not numbers, not "f(x)". if ((~ isnum) && (~ isempty (regexp (strtrim (x), '^\w+$')))) cmd = { 'd = dict()' 'x = _ins[0]' '_ins = _ins[1:]' 'for i in range(len(_ins)):' ' if isinstance(_ins[i], dict):' ' d.update(_ins[i])' ' #elif isinstance(_ins[i], list):' % TODO: allow a list? ' # for j in range(len(_ins[i])):' ' # d.update({_ins[i][j]:True})' ' elif isinstance(_ins[i], (str, bytes)):' ' d.update({_ins[i]:True})' ' else:' ' raise ValueError("something unexpected in assumptions")' 'return Symbol(x, **d)' }; s = pycall_sympy__ (cmd, x, asm{:}); if (nargin == 2 && sclear) % --------------------------------------------- % Muck around in the caller's namespace, replacing syms % that match 'xstr' (a string) with the 'newx' sym. context = 'caller'; S = evalin(context, 'whos'); evalin(context, '[];'); % clear 'ans' for i = 1:numel(S) obj = evalin(context, S(i).name); [newobj, flag] = symreplace(obj, x, s); if flag, assignin(context, S(i).name, newobj); end end % --------------------------------------------- end return else % S() in other case assert (isempty (asm), 'Only symbols can have assumptions.') % TODO: future version might warn on expression strings % Check if the user try to execute operations from sym %if (~isempty (regexp (xc, '\!|\&|\^|\:|\*|\/|\\|\+|\-|\>|\<|\=|\~'))) % warning ('Please avoid execute operations from sym function.'); %end % Usually want rational output here (i.e., if input was "1.2"). % But if input has words and parentheses it might be raw Sympy code. if (isempty (regexp (x, '\w\(.*\)'))) s = pycall_sympy__ (['return S("' x '", rational=True)']); return end hint_symfun = false; %% distinguish b/w sym('ff(w)') and sym('ff(6, Symbol("w"))') % regexp detects F() T = regexp (x, '^(\w+)\(([\w,\s]*)\)$', 'tokens'); if (length (T) == 1 && length (T{1}) == 2) hint_symfun = true; name = T{1}{1}; varnamestr = T{1}{2}; varnames = strtrim (strsplit (varnamestr, ',')); %% Blocklist some strings for which srepr(x) == str(x) % Python code for this: % >>> ns = {}; exec('from sympy import *', ns) % ... for (k, v) in ns.items(): % ... if not callable(v) and k not in ['__builtins__', 'C']: % ... if k == srepr(v): % ... print(k) var_blocklist = {'E' 'I' 'nan' 'oo' 'pi' 'zoo' 'Catalan' ... 'EulerGamma' 'GoldenRatio' 'true' 'false'}; %% special case: if all (x,y,z) are in the blocklist, we should *not* % force symfun, thus preserving the identity sympy(sym(x)) == x if (all (cellfun (@(v) (any (strcmp (v, var_blocklist))), varnames))) hint_symfun = false; end %% special case some function names to always make a Function % Currently this is unused, but could be used if we want % different behaviour for the "I" in "I(t)" vs "F(I, t)". % SMT 2014 compat: does *not* have I, E here %function_allowlist = {'I', 'E', 'ff', 'FF'}; %if (hint_symfun) % if (any (strcmp (name, function_allowlist))) % x = ['Function("' name '")(' varnamestr ')']; % end %end end cmd = {'x, hint_symfun = _ins' 'if hint_symfun:' ' from sympy.abc import _clash1' ' myclash = {v: Function(v) for v in ["ff", "FF"]}' ' myclash.update(_clash1)' ' #myclash.pop("I", None)' % remove for SMT compat ' #myclash.pop("E", None)' 'else:' ' myclash = dict()' 'try:' ' return (0, 0, sympify(x, locals=myclash))' 'except Exception as e:' ' lis = set()' ' if "(" in x or ")" in x:' ' x2 = split("\(|\)| |,", x)' ' x2 = [p for p in x2 if p]' ' for i in x2:' ' try:' ' if eval("callable(" + i + ")"):' ' lis.add(i)' ' except:' ' pass' ' if len(lis) > 0:' ' return (str(e), 1, "\", \"".join(str(e) for e in lis))' ' return (str(e), 2, 0)' }; [err flag s] = pycall_sympy__ (cmd, x, hint_symfun); switch (flag) case 1 % Bad call to python function error (['Python: %s\n' ... 'Error occurred using "%s" Python function, perhaps use another variable name?'], ... err, s); case 2 % Something else error (['Python: %s\n' ... 'Seems you cannot use "%s" for a variable name; perhaps this is a bug?'], ... err, x); end return end end error ('Conversion to symbolic with those arguments not (yet) supported') end %!test %! % integers %! x = sym ('2'); %! y = sym (2); %! assert (isa (x, 'sym')) %! assert (isa (y, 'sym')) %! assert (isequal (x, y)) %!test %! % infinity %! for x = {'inf', '-inf', inf, -inf, 'Inf'} %! y = sym (x{1}); %! assert (isa (y, 'sym')) %! assert (isinf (double (y))) %! assert (isinf (y)) %! end %!test %! % pi %! x = sym ('pi'); %! assert (isa (x, 'sym')) %! assert (isequal (sin (x), sym (0))) %! assert (abs (double (x) - pi) < 2*eps ) %! x = sym (pi); %! assert (isa (x, 'sym')) %! assert (isequal (sin (x), sym (0))) %! assert (abs (double (x) - pi) < 2*eps ) %!test %! % rationals %! x = sym(1) / 3; %! assert (isa (x, 'sym')) %! assert (isequal (3*x - 1, sym (0))) %! x = 1 / sym (3); %! assert (isa (x, 'sym')) %! assert (isequal (3*x - 1, sym (0))) %! x = sym ('1/3'); %! assert (isa (x, 'sym')) %! assert (isequal (3*x - 1, sym (0))) %!test %! % passing small rationals %! x = sym ('1/2'); %! assert (double (x) == 1/2 ) %! assert (isequal (2*x, sym (1))) %!warning x = sym (1/2); %!test %! % passing small rationals w/o quotes: despite the warning, %! % it should work %! s = warning ('off', 'OctSymPy:sym:rationalapprox'); %! x = sym (1/2); %! warning (s) %! assert (double (x) == 1/2 ) %! assert (isequal (2*x, sym (1))) %!test %! assert (isa (sym (pi), 'sym')) %! assert (isa (sym ('beta'), 'sym')) %!test %! % sym from array %! D = [0 1; 2 3]; %! A = [sym(0) 1; sym(2) 3]; %! assert (isa (sym (D), 'sym')) %! assert (isequal (size (sym (D)), size (D))) %! assert (isequal (sym (D), A)) %!test %! % more sym from array %! syms x %! A = [x x]; %! assert (isequal (sym (A), A)) %! A = [1 x]; %! assert (isequal (sym (A), A)) %!test %! %% assumptions and clearing them %! clear variables % for matlab test script %! x = sym('x', 'real'); %! f = {x {2*x}}; %! asm = assumptions(); %! assert ( ~isempty(asm)) %! s = warning ('off', 'OctSymPy:deprecated'); %! x = sym('x', 'clear'); %! warning (s) %! asm = assumptions(); %! assert ( isempty(asm)) %!test %! %% matlab compat, syms x clear should add x to workspace %! x = sym('x', 'real'); %! f = 2*x; %! clear x %! assert (~logical(exist('x', 'var'))) %! s = warning ('off', 'OctSymPy:deprecated'); %! x = sym('x', 'clear'); %! warning (s) %! assert (logical(exist('x', 'var'))) %!test %! %% assumptions should work if x is already a sym %! x = sym('x'); %! x = sym(x, 'real'); %! assert (~isempty(assumptions(x))) %!test %! %% likewise for clear %! x = sym('x', 'real'); %! f = 2*x; %! s = warning ('off', 'OctSymPy:deprecated'); %! x = sym(x, 'clear'); %! warning (s) %! assert (isempty(assumptions(x))) %! assert (isempty(assumptions(f))) %!test %! % bool %! t = sym (false); %! t = sym (true); %! assert (logical (t)) %!test %! % bool vec/mat %! a = sym (1); %! t = sym ([true false]); %! assert (isequal (t, [a == 1 a == 0])) %! t = sym ([true false; false true]); %! assert (isequal (t, [a == 1 a == 0; a == 0 a == 1])) %!test %! % symbolic matrix %! A = sym ('A', [2 3]); %! assert (isa (A, 'sym')) %! assert (isequal (size (A), [2 3])) %! A(1, 1) = 7; %! assert (isa (A, 'sym')) %! A = A + 1; %! assert (isa (A, 'sym')) %!test %! % symbolic matrix, symbolic but Integer size %! A = sym ('A', sym([2 3])); %! assert (isa (A, 'sym')) %! assert (isequal (size (A), [2 3])) %!test %! % symbolic matrix, subs in for size %! syms n m integer %! A = sym ('A', [n m]); %! B = subs (A, [n m], [5 6]); %! assert (isa (B, 'sym')) %! assert (isequal (size (B), [5 6])) %!error sym('2*a', [2 3]) %!error sym(2*sym('a'), [2 3]) %!error sym('1', [2 3]) %!error sym(1, [2 3]) %!error %! % TODO: symbolic tensor, maybe supported someday %! sym('a', [2 3 4]) %!test %! % 50 shapes of empty %! a = sym (ones (0, 3)); %! assert (isa (a, 'sym')) %! assert (isequal (size (a), [0 3])) %! a = sym (ones (2, 0)); %! assert (isequal (size (a), [2 0])) %! a = sym ([]); %! assert (isequal (size (a), [0 0])) %!test %! % moar empty %! a = sym ('a', [0 3]); %! assert (isa (a, 'sym')) %! assert (isequal (size (a), [0 3])) %! a = sym ('a', [2 0]); %! assert (isa (a, 'sym')) %! assert (isequal (size (a), [2 0])) %!test %! % embedded sympy commands, various quotes, issue #143 %! a = sym ('a'); %! a1 = sym ('Symbol("a")'); %! a2 = sym ('Symbol(''a'')'); %! assert (isequal (a, a1)) %! assert (isequal (a, a2)) %! % Octave only, and eval to hide from Matlab parser %! if exist ('OCTAVE_VERSION', 'builtin') %! eval( 'a3 = sym("Symbol(''a'')");' ); %! eval( 'a4 = sym("Symbol(\"a\")");' ); %! assert (isequal (a, a3)) %! assert (isequal (a, a4)) %! end %!test %! % complex %! x = sym(1 + 2i); %! assert (isequal (x, sym(1)+sym(2)*1i)) %!test %! % doubles bigger than int32 INTMAX should not fail %! d = 4294967295; %! a = sym (d); %! assert (isequal (double (a), d)) %! d = d + 123456; %! a = sym (d); %! assert (isequal (double (a), d)) %!test %! % int32 integer types %! a = sym (100); %! b = sym (int32 (100)); %! assert (isequal (a, b)) %!test %! % int32 MAXINT integers %! a = sym ('2147483647'); %! b = sym (int32 (2147483647)); %! assert (isequal (a, b)) %! a = sym ('-2147483647'); %! b = sym (int32 (-2147483647)); %! assert (isequal (a, b)) %! a = sym ('4294967295'); %! b = sym (uint32 (4294967295)); %! assert (isequal (a, b)) %!test %! % int64 integer types %! a = sym ('123456789012345'); %! b = sym (int64(123456789012345)); %! c = sym (uint64(123456789012345)); %! assert (isequal (a, b)) %! assert (isequal (a, c)) %!test %! % integer arrays %! a = int64 ([1 2 100]); %! s = sym (a); %! assert (isequal (double (a), [1 2 100])) %!test %! % bigger int64 integer types %! q = int64 (123456789012345); %! w = 10000*q + 123; %! a = sym ('1234567890123450123'); %! b = sym (w); %! assert (isequal (a, b)) %!test %! % sym(double) heuristic %! s = warning ('off', 'OctSymPy:sym:rationalapprox'); %! x = sym(2*pi/3); %! assert (isequal (x/sym(pi), sym(2)/3)) %! x = sym(22*pi); %! assert (isequal (x/sym(pi), sym(22))) %! x = sym(pi/123); %! assert (isequal (x/sym(pi), sym(1)/123)) %! warning (s) %!test %! % sym(double) with 'r': no warning %! a = 0.1; %! x = sym(a, 'r'); %! assert (isequal (x, sym(1)/10)) %!test %! % sym(double, 'f') %! a = 0.1; %! x = sym(a, 'f'); %! assert (~isequal (x, sym(1)/10)) %! assert (isequal (x, sym('3602879701896397')/sym('36028797018963968'))) %!test %! x = sym(pi, 'f'); %! assert (~isequal (x, sym('pi'))) %! assert (isequal (x, sym('884279719003555')/sym('281474976710656'))) %!test %! q = sym('3602879701896397')/sym('36028797018963968'); %! x = sym(1 + 0.1i, 'f'); %! assert (isequal (x, 1 + 1i*q)) %! x = sym(0.1 + 0.1i, 'f'); %! assert (isequal (x, q + 1i*q)) %!test %! assert (isequal (sym(inf, 'f'), sym(inf))) %! assert (isequal (sym(-inf, 'f'), sym(-inf))) %! assert (isequaln (sym(nan, 'f'), sym(nan))) %! assert (isequal (sym(complex(inf, -inf), 'f'), sym(complex(inf, -inf)))) %! assert (isequaln (sym(complex(nan, inf), 'f'), sym(complex(nan, inf)))) %! assert (isequaln (sym(complex(-inf, nan), 'f'), sym(complex(-inf, nan)))) %!test %! assert (isequal (sym (sqrt(2), 'r'), sqrt (sym (2)))) %! assert (isequal (sym (sqrt(12345), 'r'), sqrt (sym (12345)))) %!test %! % symbols with special sympy names %! syms Ei Eq %! assert (~isempty (regexp (sympy (Eq), '^Symbol'))) %! assert (~isempty (regexp (sympy (Ei), '^Symbol'))) %!test %! % more symbols with special sympy names %! x = sym('FF'); %! assert (~isempty (regexp (x.pickle, '^Symbol'))) %! x = sym('ff'); %! assert (~isempty (regexp (x.pickle, '^Symbol'))) %!test %! % E can be a sym not just exp(sym(1)) %! syms E %! assert (~logical (E == exp(sym(1)))) %!test %! % e can be a symbol, not exp(sym(1)) %! syms e %! assert (~ logical (e == exp(sym(1)))) %!test %! % double e %! x = sym (exp (1)); %! y = exp (sym (1)); %! assert (isequal (x, y)) %! if (exist ('OCTAVE_VERSION', 'builtin')) %! x = sym (e); %! assert (isequal (x, y)) %! end %!test %! x = sym (-exp (1)); %! y = -exp (sym (1)); %! assert (isequal (x, y)) %!assert (~ isequal (sym (exp(1)), sym (exp(1), 'f'))) %!warning sym (1e16); %!warning sym (-1e16); %!warning sym (10.33); %!warning sym (-5.23); %!warning sym (sqrt (1.4142135623731)); %!error %! x = sym ('x', 'positive2'); %!error %! x = sym ('x', 'integer', 'positive2'); %!error %! x = sym ('x', 'integer2', 'positive'); %!error %! x = sym ('-pi', 'positive') %!error %! x = sym ('pi', 'integer') %!test %! % multiple assumptions %! n = sym ('n', 'negative', 'even'); %! a = assumptions (n); %! assert (strcmp (a, 'n: negative, even') || strcmp (a, 'n: even, negative')) %!error %! % multiple assumptions as a list %! % TODO: should this be allowed? %! n = sym ('n', {'negative', 'even'}); %! a = assumptions (n); %! assert (strcmp (a, 'n: negative, even') || strcmp (a, 'n: even, negative')) %!error %! n = sym ('n', {{'negative', 'even'}}); %!test %! % save/load sym objects %! syms x %! y = 2*x; %! a = 42; %! myfile = tempname (); %! save (myfile, 'x', 'y', 'a') %! clear x y a %! load (myfile) %! assert (isequal (y, 2*x)) %! assert (a == 42) %! if (exist ('OCTAVE_VERSION', 'builtin')) %! assert (unlink (myfile) == 0) %! else %! delete ([myfile '.mat']) %! end %!test %! a = sym ('2.1'); %! b = sym (21) / 10; %! %% https://github.com/sympy/sympy/issues/11703 %! assert (pycall_sympy__ ('return _ins[0] == _ins[1] and hash(_ins[0]) == hash(_ins[1])', a, b)) %!test %! % issue #706 %! a = sym('Float("1.23")'); %! assert (~ isempty (strfind (char (a), '.'))) % TODO: test that might be used in the future %%!warning sym ('1*2'); %!assert (isequal (sym({1 2 'a'}), [sym(1) sym(2) sym('a')])); %!error sym({1 2 'a'}, 'positive'); %!error sym({'a' 'b'}, 'positive'); %!test %! a = sym ('--1'); %! b = sym ('---1'); %! assert (isequal (a, sym (1))) %! assert (isequal (b, sym (-1))) %!test %! % num2cell works on sym arrays %! syms x %! C1 = num2cell ([x 2 3; 4 5 6*x]); %! assert (iscell (C1)) %! assert (isequal (size (C1), [2 3])) %! assert (isequal (C1{1,1}, x)) %! assert (isequal (C1{2,3}, 6*x)) %! assert (isequal (C1{1,3}, sym(3))) %! assert (isa (C1{1,3}, 'sym')) %!test %! % function_handle %! f = @(x, y) y*sin(x); %! syms x y %! assert (isequal (sym (f), y*sin(x))); %! f = @(x) 42; %! assert (isequal (sym (f), sym (42))); %! f = @() 42; %! assert (isequal (sym (f), sym (42))); %!error %! % function_handle %! f = @(x) A*sin(x); %! sym (f) %!test %! % Issue #885 %! clear f x % if test not isolated (e.g., on matlab) %! syms x %! f(x) = sym('S(x)'); %! f(x) = sym('I(x)'); %! f(x) = sym('O(x)'); %!test %! % sym(sympy(x) == x identity, Issue #890 %! syms x %! f = exp (1i*x); %! s = sympy (f); %! g = sym (s); %! assert (isequal (f, g)) %!test %! % sym(sympy(x) == x identity %! % Don't mistake "pi" (which is "srepr(S.Pi)") for a symfun variable %! f = sym ('ff(pi, pi)'); %! s1 = sympy (f); %! s2 = 'FallingFactorial(pi, pi)'; %! assert (strcmp (s1, s2)) %!test %! % sym(sympy(x) == x identity %! % Don't mistake "I" (which is "srepr(S.ImaginaryUnit)") for a symfun variable %! f = sym ('sin(I)'); %! g = 1i*sinh (sym (1)); %! assert (isequal (f, g)) %! s = sympy (f); %! assert (isempty (strfind (s, 'Function'))) %!error %! % sym(sympy(x) == x identity %! % Don't mistake "true/false" (which is "srepr(S.true)") for a symfun variable %! % (Used to print as `S.true` but just `true` in sympy 1.2) %! sym ('E(true,false)') %!test %! % some variable names that are special to sympy but should not be for us %! f = sym ('f(S, Q, C, O, N)'); %! s1 = sympy (f); %! s2 = 'Function(''f'')(Symbol(''S''), Symbol(''Q''), Symbol(''C''), Symbol(''O''), Symbol(''N''))'; %! assert (strcmp (s1, s2)) %!test %! % For SMT 2014 compatibilty, I and E would become ImaginaryUnit and Exp(1) %! % but I'm not sure this is by design. This test would need to change if %! % we want stricter SMT compatibilty. %! f = sym ('f(x, I, E)'); %! s1 = sympy (f); %! s2 = 'Function(''f'')(Symbol(''x''), Symbol(''I''), Symbol(''E''))'; %! assert (strcmp (s1, s2)) %!test %! % not the identity, force symfun %! f = sym ('FF(w)'); %! s1 = sympy (f); %! s2 = 'Function(''FF'')(Symbol(''w''))'; %! assert (strcmp (s1, s2)) %!test %! % not the identity, force symfun %! f = sym ('FF(w, pi)'); %! s1 = sympy (f); %! s2 = 'Function(''FF'')(Symbol(''w''), pi)'; %! assert (strcmp (s1, s2)) %!test %! % not the identity, force symfun %! f = sym ('ff(x, y)'); %! s1 = sympy (f); %! s2 = 'Function(''ff'')(Symbol(''x''), Symbol(''y''))'; %! assert (strcmp (s1, s2)) %!test %! % But this one should satisfy "sym(sympy(x) == x" identity %! % (OOTB, SymPy has ff -> FallingFactorial) %! f = sym ('FallingFactorial(x, y)'); %! s1 = sympy (f); %! s2 = 'FallingFactorial(Symbol(''x''), Symbol(''y''))'; %! assert (strcmp (s1, s2)) symbolic-3.1.1/inst/@sym/sym2poly.m0000644000000000000000000001150314405647405014075 0ustar %% Copyright (C) 2003 Willem J. Atsma %% Copyright (C) 2014-2016, 2019 Colin B. Macdonald %% %% 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, or (at your option) any later version. %% %% This software 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 software; see the file COPYING. If not, %% see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {@var{doublec} =} sym2poly (@var{p}) %% @deftypemethodx @@sym {@var{c} =} sym2poly (@var{p}, @var{x}) %% Return vector of coefficients of a symbolic polynomial. %% %% In the two-input form, the second argument @var{x} specifies the free %% variable; in this case this function returns a row vector @var{c} of %% symbolic expressions. The coefficients correspond to decreasing exponent %% of the free variable. Example: %% @example %% @group %% syms x y %% sym2poly(2*x^2 + 3*x - pi, x) %% @result{} (sym) [2 3 -π] (1×3 matrix) %% sym2poly(x^2 + y*x, x) %% @result{} (sym) [1 y 0] (1×3 matrix) %% @end group %% @end example %% %% @strong{Warning}: Using the single-argument form, the coefficient vector %% @var{c} is a plain numeric vector (double). This is for compatibility %% with the Matlab Symbolic Math Toolbox. %% We suggest making this clear in your code by explicitly casting to @code{double}, %% as in: %% @example %% @group %% syms x %% @c doctest: +SKIP_IF(compare_versions (OCTAVE_VERSION(), '6.0.0', '<')) %% double(sym2poly(pi*x^3 + 3*x/2 + exp(sym(1)))) %% @result{} 3.1416 0 1.5000 2.7183 %% @end group %% @end example %% You may prefer specifying @var{X} or using @code{coeffs}: %% @example %% @group %% coeffs(pi*x^3 + 3*x/2 + exp(sym(1)), 'all') %% @result{} (sym) [π 0 3/2 ℯ] (1×4 matrix) %% @end group %% @end example %% %% If @var{p} is not a polynomial the result has no warranty. SymPy can %% certainly deal with more general concepts of polynomial but we do not %% yet expose all of that here. %% %% @seealso{poly2sym, @@sym/coeffs, polyval, roots} %% @end deftypemethod %% Created: 18 April 2003 %% Changed: 25 April 2003 %% Removed the use of differentiate to get to coefficients - round-off %% errors cause problems. Now using newly created sumterms(). %% Changed: 6 May 2003 %% Removed the attempt to use ldegree(), degree() and coeff() - results %% with these are inconsistent. %% Changed: 16 April 2014 %% Used the comment header and tests in OctSymPy, but rewrote %% the body (by Colin Macdonald). function c = sym2poly(p, x) if ~(isscalar(p)) error ('sym2poly: works for scalar input only'); end if (nargin == 1) ss = findsymbols(p); if (length (ss) >= 2) error ('sym2poly: input has more than one symbol: not clear what you want me to do') elseif (length (ss) == 1) x = ss{1}; else x = sym('x'); end convert_to_double = true; elseif (nargin == 2) convert_to_double = false; else print_usage (); end cmd = { 'f = _ins[0]' 'x = _ins[1]' 'p = Poly.from_expr(f,x)' 'return p.all_coeffs(),' }; c2 = pycall_sympy__ (cmd, sym(p), sym(x)); if (isempty(c2)) error ('sym2poly: empty python output, can this happen? A bug.') end % FIXME: should be able to convert c2 to array faster than array % expansion! Particularly in the case where we just convert to % double anyway! c = sym([]); for j = 1:numel(c2) % Bug #17 %c(j) = c2{j}; idx.type = '()'; idx.subs = {j}; c = subsasgn(c, idx, c2{j}); end if (convert_to_double) c = double(c); end end %!shared x,y,a,b,c %! syms x y a b c %!assert (isequal (sym2poly (x^2 + 3*x - 4), [1 3 -4])) %!assert (isequal (sym2poly (x^6 - x^3), [1 0 0 -1 0 0 0])) %!assert (isequal (sym2poly (x^2 + 3*x - 4, x), [1 3 -4])) %!assert (norm (sym2poly (pi*x^2 + exp(sym(1))) - [pi 0 exp(1)]) < 10*eps) %% types %!assert (isa (sym2poly (x^2 + 3*x - 4), 'double')) %!assert (isa (sym2poly (x^2 + 3*x - 4, x), 'sym')) %% tests with other vars %!assert (isequal (sym2poly (x^2+y*x, x), [sym(1) y sym(0)])) %!assert (isequal (sym2poly (x^2+y*x, y), [x x^2])) %% inverse relationship %!assert (isequal (sym2poly (poly2sym ([a b c], x), x), [a b c])) %!assert (isequal (poly2sym (sym2poly(a*x^2 + c, x), x), a*x^2 + c)) %!assert (isequal (sym2poly (poly2sym ([1 2 3])), [1 2 3])) %!error %! % too many symbols for single-input %! p = a*x^2 + 2; %! c = sym2poly (p); %!assert (isequal (sym2poly (sym(5)), sym(5))) symbolic-3.1.1/inst/@sym/symprod.m0000644000000000000000000001126714405647405014003 0ustar %% Copyright (C) 2014-2016, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym symprod (@var{f}, @var{n}, @var{a}, @var{b}) %% @defmethodx @@sym symprod (@var{f}, @var{n}, [@var{a} @var{b}]) %% @defmethodx @@sym symprod (@var{f}, @var{a}, @var{b}) %% @defmethodx @@sym symprod (@var{f}, [@var{a} @var{b}]) %% @defmethodx @@sym symprod (@var{f}, @var{n}) %% @defmethodx @@sym symprod (@var{f}) %% Symbolic product. %% %% The product of the expression @var{f} as variable @var{n} changes %% from @var{a} to @var{b}. When @var{n} is omitted it is determined %% using @code{symvar} and defaults to @code{x} if @var{f} is %% constant. The limits @var{a} and @var{b} default to @code{1} and %% @var{n} respectively. %% %% Examples: %% @example %% @group %% syms n m x %% symprod(sin(n*x), n, [1 3]) %% @result{} (sym) sin(x)⋅sin(2⋅x)⋅sin(3⋅x) %% symprod(n, n, 1, m) %% @result{} (sym) m! %% @end group %% @end example %% %% Unevaluated product: %% @example %% @group %% syms x m %% symprod(sin(x), x, [1 m]) %% @result{} (sym) %% m %% ─┬─┬─ %% │ │ sin(x) %% │ │ %% x = 1 %% @end group %% @end example %% %% @seealso{@@sym/symsum, @@sym/prod} %% @end defmethod function S = symprod(f, n, a, b) if (nargin > 4) print_usage (); end idx1.type = '()'; idx1.subs = {1}; idx2.type = '()'; idx2.subs = {2}; if (nargin == 1) n = symvar(f, 1); if (isempty(n)) n = sym('x'); end a = sym(1); b = n; elseif (nargin == 2) && (length(n) == 2) f = sym(f); %a = n(1); % issue #17 %b = n(2); a = subsref(n, idx1); b = subsref(n, idx2); n = symvar(f, 1); if (isempty(n)) n = sym('x'); end elseif (nargin == 2) f = sym(f); n = sym(n); a = sym(1); b = n; elseif (nargin == 3) && (length(a) == 2) f = sym(f); n = sym(n); %b = a(2); % issue #17 %a = a(1); b = subsref(a, idx2); a = subsref(a, idx1); elseif (nargin == 3) f = sym(f); b = a; a = n; n = symvar(f, 1); if (isempty(n)) n = sym('x'); end else f = sym(f); n = sym(n); a = sym(a); b = sym(b); end cmd = { '(f, n, a, b) = _ins' 'S = sp.product(f, (n, a, b))' 'return S,' }; S = pycall_sympy__ (cmd, sym(f), sym(n), sym(a), sym(b)); end %!error symprod (sym(1), 2, 3, 4, 5) %!test %! % simple %! syms n %! assert (isequal (symprod(n, n, 1, 10), factorial(sym(10)))) %! assert (isequal (symprod(n, n, sym(1), sym(10)), factorial(10))) %!test %! % one input %! syms n %! f = symprod (n); %! g = factorial (n); %! assert (isequal (f, g)) %! f = symprod (2*n); %! g = 2^n * factorial (n); %! assert (isequal (f, g)) %!test %! % constant input %! f = symprod (sym(2)); %! syms x %! g = 2^x; %! assert (isequal (f, g)) %!test %! % two inputs %! syms n %! f = symprod (2*n, n); %! g = 2^n * factorial (n); %! assert (isequal (f, g)) %!test %! % two inputs, second is range %! syms n %! f = symprod (n, [1 6]); %! g = 720; %! assert (isequal (f, g)) %! f = symprod (n, [sym(1) 6]); %! g = 720; %! assert (isequal (f, g)) %! f = symprod (2*n, [1 6]); %! g = sym(2)^6*720; %! assert (isequal (f, g)) %!test %! % three inputs, last is range %! syms n %! f = symprod (2*n, n, [1 4]); %! g = sym(384); %! assert (isequal (f, g)) %! f = symprod (2*n, n, [sym(1) 4]); %! g = sym(384); %! assert (isequal (f, g)) %! f = symprod (2, n, [sym(1) 4]); %! g = sym(16); %! assert (isequal (f, g)) %!test %! % three inputs, no range %! syms n %! f = symprod (2*n, 1, 4); %! g = sym(384); %! assert (isequal (f, g)) %! f = symprod (5, sym(1), 3); %! g = sym(125); %! assert (isequal (f, g)) %!test %! % infinite product %! syms a n oo %! zoo = sym('zoo'); %! assert (isequal (symprod(a, n, 1, oo), a^oo)) %! assert (isequal (symprod(a, n, 1, inf), a^oo)) %%!test %%! % FIXME: commented out test... %%! % SymPy 0.7.6: nan %%! % SymPy git: interesting that 1**oo is nan but this is still 1 %%! assert (isequal (symprod(1, n, 1, oo), sym(1))) symbolic-3.1.1/inst/@sym/sympy.m0000644000000000000000000000375114405647405013466 0ustar %% Copyright (C) 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym sympy (@var{x}) %% The underlying SymPy representation as a string. %% %% Each symbolic @code{sym} expression has an underlying Python %% object, which is stored as a character array consisting of the %% the object's @code{srepr} (``String Representation''). %% This method returns that string and can be helpful for debugging %% or for copy-pasting a @code{sym} object into a Python environment %% such as Jupyter. %% %% Example: %% @example %% @group %% syms x positive %% srepr = sympy (x) %% @result{} srepr = Symbol('x', positive=True) %% @end group %% @end example %% %% Unlike @code{@@sym/char}, the result can be passed directly back %% to @code{sym} with perfect fidelity: %% @example %% @group %% x2 = sym (srepr) %% @result{} x2 = (sym) x %% x2 == x %% @result{} (sym) True %% @end group %% @end example %% %% @seealso{@@sym/char, @@sym/disp, @@sym/pretty, sym} %% @end defmethod function s = sympy(x) s = x.pickle; end %!assert (strcmp (sympy (sym(pi)), 'pi')) %!assert (strcmp (sympy (sym(1)), 'Integer(1)')) %!assert (strcmp (sympy (sym(2)/3), 'Rational(2, 3)')) %!assert (strcmp (sympy (sym('x')), 'Symbol(''x'')')) %!test %! x = sym('x'); %! assert (isequal (sym(sympy(x)), x)) symbolic-3.1.1/inst/@sym/symreplace.m0000644000000000000000000001766014405647405014455 0ustar %% Copyright (C) 2014-2016, 2018 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@sym {} symreplace (@var{newx}) %% @deftypemethodx @@sym {} symreplace (@var{x}, @var{newx}) %% @deftypemethodx @@sym {} symreplace (@var{x}, @var{newx}, @var{context}) %% @deftypemethodx @@sym {} symreplace (@var{xstr}, @var{newx}) %% @deftypemethodx @@sym {} symreplace (@var{xstr}, @var{newx}, @var{context}) %% @deftypemethodx @@sym {[@var{f}, @var{flag}] =} symreplace (@var{f}, @var{xstr}, @var{newx}) %% Replace symbols in caller's workspace or in syms/struct/cells. %% %% @strong{WARNING}: you probably do not need this for normal %% usage; @pxref{@@sym/subs} instead. %% %% One mode of operation is similar to @code{subs()}: %% @example %% @group %% syms x y %% f = @{x; 2*x; sin(x)@}; %% g = symreplace(f, x, y); %% g@{:@} %% @result{} ans = (sym) y %% @result{} ans = (sym) 2⋅y %% @result{} ans = (sym) sin(y) %% g = symreplace(f, 'x', y); % alternative %% @end group %% @end example %% However, unlike @code{subs()}, here @code{f} can be a cell array %% or struct, which we recursively traverse down into. %% %% @var{flag} is true if the output @var{f} was changed from %% the input @var{f}: %% @example %% @group %% syms x y %% f = sin(y); %% [g, flag] = symreplace(f, x, y) %% @result{} g = (sym) sin(y) %% @result{} flag = 0 %% @end group %% @end example %% %% The alternative form using @var{xstr} is used internally by %% OctSymPy for assumptions (@pxref{@@sym/assume}, @pxref{@@sym/assumeAlso}), %% to replace one @code{x} with another @code{x} with possibly %% different assumptions. For example: %% @example %% @group %% syms x positive %% f = x^2; %% assumptions(f)@{:@} %% @result{} x: positive %% x = sym('x', 'real'); %% f = symreplace(f, 'x', x); %% assumptions(f)@{:@} %% @result{} x: real %% @end group %% @end example %% %% The other mode of operation is also used by OctSymPy for %% supporting assumptions. It has no output but plenty of %% side-effects! Not scared off yet? Here's what it does: %% @example %% @group %% syms x real %% f = abs(x); %% syms x positive %% f %% @result{} f = (sym) │x│ %% symreplace ('x', x) %% f %% @result{} f = (sym) x %% @end group %% @end example %% %% Here is the scary part: this works by searching expressions in %% the @strong{callers workspace} for variables with same name as %% @var{x}/@var{xstr}. We then substitute @var{newx}. If @var{x} %% is omitted, the string of @var{newx} is used instead. This is %% precisely what happens when using @code{assume}: %% @example %% @group %% syms x %% f = abs(x); %% assume(x, 'positive') %% f %% @result{} f = (sym) x %% @end group %% @end example %% %% Note: operates on the caller's workspace via evalin/assignin. %% So if you call this from other functions, it will operate in %% your function's workspace (not the @code{base} workspace). %% You can pass @code{'base'} to @var{context} to operate in %% the base context instead. %% %% Note for developers: if you want to call this from your function %% but have it work on the 'caller' context %% @strong{of your function}, that unfortunately does not seem to %% be possible. Copy-paste the highlighted bits of this code into %% your function instead (see @code{assume} for example). %% %% @seealso{@@sym/assume, @@sym/assumeAlso, assumptions, sym, syms} %% @end deftypemethod function varargout = symreplace(varargin) %% This is the first ("benign") form if ((nargout >= 1) || (nargin == 3 && ~ischar(varargin{3}))) [varargout{1:2}] = symreplace_helper(varargin{:}); return end %% otherwise, no output: this is the scary one if (nargin == 1) newx = varargin{1}; xstr = newx.flat; context = 'caller'; elseif (nargin == 2) xstr = varargin{1}; newx = varargin{2}; context = 'caller'; elseif (nargin == 3) xstr = varargin{1}; newx = varargin{2}; context = varargin{3}; else print_usage (); end assert(ischar(context) && ... (strcmp(context, 'caller') || strcmp(context, 'base'))) % we just want the string if (isa(xstr, 'sym')) xstr = xstr.flat; end %% Here's the piece with side-effects % This is the part that you might want to copy into your function % --------------------------------------------- % Muck around in the caller's namespace, replacing syms % that match 'xstr' (a string) with the 'newx' sym. %xstr = %newx = %context = 'caller'; S = evalin(context, 'whos'); evalin(context, '[];'); % clear 'ans' for i = 1:numel(S) obj = evalin(context, S(i).name); [newobj, flag] = symreplace(obj, xstr, newx); if flag, assignin(context, S(i).name, newobj); end end % --------------------------------------------- %% end of side-effects bit end function [newobj, flag] = symreplace_helper(obj, xstr, newx) % If you need to add other things other than struct/cell/sym, this is % place to do it. if (isa (xstr, 'sym')) xstr = xstr.flat; end assert (ischar (xstr)) flag = false; if isa (obj, 'symfun') sf_args = argnames (obj); sf_formula = formula (obj); [sf_args, flag1] = symreplace_helper(sf_args, xstr, newx); [sf_formula, flag2] = symreplace_helper(sf_formula, xstr, newx); if (flag1 || flag2) flag = true; newobj = symfun (sf_formula, sf_args); end elseif isa(obj, 'sym') % check if contains any symbols with the same string as x. symlist = findsymbols(obj); for c = 1:length(symlist) if strcmp(xstr, symlist{c}.flat) flag = true; break end end % If so, subs in the new x and replace that variable. if (flag) newobj = subs(obj, symlist{c}, newx); end elseif iscell(obj) %fprintf('Recursing into a cell array of numel=%d\n', numel(obj)) newobj = obj; flag = false; for i=1:numel(obj) [temp, flg] = symreplace_helper(obj{i}, xstr, newx); if (flg) newobj{i} = temp; flag = true; end end elseif isstruct(obj) %fprintf('Recursing into a struct array of numel=%d\n', numel(obj)) newobj = obj; fields = fieldnames(obj); for i=1:numel(obj) for j=1:length(fields) thisobj = getfield(obj, {i}, fields{j}); [temp, flg] = symreplace_helper(thisobj, xstr, newx); if (flg) % This requires work on octave but not on matlab! Instead, gratuitous % use of eval()... %newobj = setfield(newobj, {i}, fields{j}, temp); eval(sprintf('newobj(%d).%s = temp;', i, fields{j})); flag = true; end end end end if ~(flag) newobj = obj; end end %!test %! % start with assumptions on x then remove them %! syms x positive %! f = x*10; %! symreplace(x, sym('x')) %! assert(isempty(assumptions(x))) %!test %! % replace x with y %! syms x %! f = x*10; %! symreplace(x, sym('y')) %! assert( isequal (f, 10*sym('y'))) %!test %! % gets inside cells %! syms x %! f = {x 1 2 {3 4*x}}; %! symreplace(x, sym('y')) %! syms y %! assert( isequal (f{1}, y)) %! assert( isequal (f{4}{2}, 4*y)) %!test %! % gets inside structs/cells %! syms x %! my.foo = {x 1 2 {3 4*x}}; %! my.bar = x; %! g = {'ride' my 'motor' 'sicle'}; %! symreplace(x, sym('y')) %! syms y %! f = g{2}; %! assert( isequal (f.foo{1}, y)) %! assert( isequal (f.foo{4}{2}, 4*y)) %! assert( isequal (f.bar, y)) symbolic-3.1.1/inst/@sym/symsum.m0000644000000000000000000001172114405647405013636 0ustar %% Copyright (C) 2014-2016, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym symsum (@var{f}, @var{n}, @var{a}, @var{b}) %% @defmethodx @@sym symsum (@var{f}, @var{n}, [@var{a} @var{b}]) %% @defmethodx @@sym symsum (@var{f}, @var{a}, @var{b}) %% @defmethodx @@sym symsum (@var{f}, [@var{a} @var{b}]) %% @defmethodx @@sym symsum (@var{f}, @var{n}) %% @defmethodx @@sym symsum (@var{f}) %% Symbolic summation. %% %% The sum of the expression @var{f} for @var{n} from @var{a} to %% @var{b}. When @var{n} is omitted it is determined using %% @code{symvar} and defaults to @code{x} if @var{f} is constant. The %% limits @var{a} and @var{b} default to 0 and @var{n} - 1 %% respectively. %% %% @example %% @group %% syms n m %% symsum(1/n^2, n, 1, m) %% @result{} (sym) harmonic(m, 2) %% %% symsum(exp(2*n)/sin(n), n, 2*m, 6*m) %% @result{} (sym) %% 6⋅m %% ____ %% ╲ %% ╲ 2⋅n %% ╲ ℯ %% ╱ ────── %% ╱ sin(n) %% ╱ %% ‾‾‾‾ %% n = 2⋅m %% @end group %% @end example %% %% @seealso{@@sym/symprod, @@sym/sum} %% @end defmethod function S = symsum(f, n, a, b) if (nargin > 4) print_usage (); end idx1.type = '()'; idx1.subs = {1}; idx2.type = '()'; idx2.subs = {2}; if (nargin == 1) n = symvar(f, 1); if (isempty(n)) n = sym('x'); end a = sym(0); b = n - 1; elseif (nargin == 2) && (length(n) == 2) f = sym(f); %a = n(1); % issue #17 %b = n(2); a = subsref(n, idx1); b = subsref(n, idx2); n = symvar(f, 1); if (isempty(n)) n = sym('x'); end elseif (nargin == 2) f = sym(f); n = sym(n); a = sym(0); b = n - 1; elseif (nargin == 3) && (length(a) == 2) f = sym(f); n = sym(n); %b = a(2); % issue #17 %a = a(1); b = subsref(a, idx2); a = subsref(a, idx1); elseif (nargin == 3) f = sym(f); b = a; a = n; n = symvar(f, 1); if (isempty(n)) n = sym('x'); end else f = sym(f); n = sym(n); a = sym(a); b = sym(b); end cmd = { '(f, n, a, b) = _ins' 'S = sp.summation(f, (n, a, b))' 'return S,' }; S = pycall_sympy__ (cmd, sym(f), sym(n), sym(a), sym(b)); end %!error symsum (sym(1), 2, 3, 4, 5) %!test %! % finite sums %! syms n %! assert (isequal (symsum(n,n,1,10), 55)) %! assert(isa(symsum(n,n,1,10), 'sym')) %! assert (isequal (symsum(n,n,sym(1),sym(10)), 55)) %! assert (isequal (symsum(n,n,sym(1),sym(10)), 55)) %! assert (isequal (symsum(1/n,n,1,10), sym(7381)/2520)) %!test %! % negative limits %! syms n %! assert (isequal (symsum(n,n,-3,3), sym(0))) %! assert (isequal (symsum(n,n,-3,0), sym(-6))) %! assert (isequal (symsum(n,n,-3,-1), sym(-6))) %!test %! % one input %! syms n %! f = symsum (n); %! g = n^2/2 - n/2; %! assert (isequal (f, g)) %! f = symsum (2*n); %! g = n^2 - n; %! assert (isequal (f, g)) %!test %! % constant input %! f = symsum (sym(2)); %! syms x %! g = 2*x; %! assert (isequal (f, g)) %!test %! % two inputs %! syms n %! f = symsum (2*n, n); %! g = n^2 - n; %! assert (isequal (f, g)) %!test %! % two inputs, second is range %! syms n %! f = symsum (n, [1 6]); %! g = 21; %! assert (isequal (f, g)) %! f = symsum (n, [sym(1) 6]); %! g = 21; %! assert (isequal (f, g)) %! f = symsum (2*n, [1 6]); %! g = 2*21; %! assert (isequal (f, g)) %!test %! % three inputs, last is range %! syms n %! f = symsum (2*n, n, [1 4]); %! g = sym(20); %! assert (isequal (f, g)) %! f = symsum (2*n, n, [sym(1) 4]); %! g = sym(20); %! assert (isequal (f, g)) %! f = symsum (2, n, [sym(1) 4]); %! g = sym(8); %! assert (isequal (f, g)) %!test %! % three inputs, no range %! syms n %! f = symsum (2*n, 1, 4); %! g = sym(20); %! assert (isequal (f, g)) %! f = symsum (5, sym(1), 3); %! g = sym(15); %! assert (isequal (f, g)) %!test %! % ok to use double's for arguments in infinite series %! syms n oo %! assert(isequal(symsum(1/n^2,n,1,oo), sym(pi)^2/6)) %! assert(isequal(symsum(1/n^2,n,1,inf), sym(pi)^2/6)) %!test %! % should be oo because 1 is real but seems to be %! % zoo/oo depending on sympy version %! syms n oo %! zoo = sym('zoo'); %! assert (isequal (symsum(1/n,n,1,oo), oo) || ... %! isequal (symsum(1/n,n,1,oo), zoo)) symbolic-3.1.1/inst/@sym/symvar.m0000644000000000000000000001212714405647405013623 0ustar %% Copyright (C) 2014-2016, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym symvar (@var{f}) %% @defmethodx @@sym symvar (@var{f}, @var{n}) %% Find symbols in expression and return them as a symbolic vector. %% %% The symbols are sorted in alphabetic order with capital letters %% first. If @var{n} is specified, the @var{n} symbols closest to %% @code{x} are returned. %% %% Example: %% @example %% @group %% syms x y %% f = x^2 + 3*x*y - y^2; %% symvar (f) %% @result{} (sym) [x y] (1×2 matrix) %% symvar (f, 1) %% @result{} (sym) x %% @end group %% @end example %% %% Further examples: %% @example %% @group %% syms a x t %% f = a*x + t; %% symvar (f, 1) %% @result{} (sym) x %% symvar (f, 2) %% @result{} (sym) [x t] (1×2 matrix) %% symvar (f, 3) %% @result{} (sym) [x t a] (1×3 matrix) %% @end group %% @end example %% And note its ok to ask for more: %% @example %% @group %% symvar (f, 1000) %% @result{} (sym) [x t a] (1×3 matrix) %% @end group %% @end example %% %% %% Compatibility with other implementations: the output should %% match the order of the equivalent command in the Matlab Symbolic %% Toolbox version 2014a, as documented here: %% http://www.mathworks.co.uk/help/symbolic/symvar.html %% %% If two variables have the same symbol but different assumptions, %% they will both appear in the output. It is not well-defined %% in what order they appear. %% %% @seealso{findsymbols, @@sym/findsym} %% @end defmethod function vars = symvar(F, Nout) if (nargin > 2) print_usage (); end symlist = findsymbols (F); Nlist = length (symlist); if (nargin == 1) vars = sym([]); for i=1:Nlist %vars(i) = symlist{i}; idx.type = '()'; idx.subs = {i}; vars = subsasgn(vars, idx, symlist{i}); end return end % behaviour is rather different specific number of outputs requests assert(Nout >= 0, 'number of requested symbols should be positive') if (Nlist < Nout) %if (Nout == 1) % warning('Asked for one variable, but none found.'); %else % warning('Asked for %d variables, but only %d found.',Nout,Nlist); %end Nout = Nlist; end vars = sym([]); if (Nout == 0) return end symstrings = {}; for i=1:Nlist symstrings{i} = symlist{i}.flat; end %% define a map for resorting sortorder = 'xywzvutsrqponmlkjihgfedcbaXYWZVUTSRQPONMLKJIHGFEDCBA'; AZaz = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; assert(length(AZaz) == length(sortorder)) for i=1:length(sortorder) map.(sortorder(i)) = AZaz(i); end symstr_forsort = {}; for i=1:Nlist str = symstrings{i}; first = str(1); str(1) = map.(first); symstr_forsort{i} = str; end symstr_forsort; [xs,I] = sort(symstr_forsort); for i=1:Nout %vars(i) = symlist{i}; idx.type = '()'; idx.subs = {i}; vars = subsasgn(vars, idx, symlist{I(i)}); end end %!error symvar (sym(1), 2, 3) %!test %! %% some empty cases %! assert (isempty (symvar (sym(1)))); %! assert (isempty (symvar (sym(1),1))); %! assert (isempty (symvar (sym(1),0))); %! assert (isempty (symvar (sym('x'),0))); %!shared x,y,f %! x=sym('x'); y=sym('y'); f=x^2+3*x*y-y^2; %!assert (isequal (symvar (f), [x y])); %!assert (isequal (symvar (f, 1), x)); %!test %! %% closest to x %! syms x y a b c xx %! alpha = sym('alpha'); %! % https://www.mathworks.com/matlabcentral/newsreader/view_thread/237730 %! assert( isequal (symvar (b*xx*exp(alpha) + c*sin(a*y), 2), [xx y])) %! %% tests to match Matlab R2013b %!shared x,y,z,a,b,c,X,Y,Z %! syms x y z a b c X Y Z %!test %! %% X,Y,Z first if no 2nd argument %! s = prod([x y z a b c X Y Z]); %! assert (isequal( symvar (s), [X Y Z a b c x y z] )) %!test %! %% uppercase have *low* priority with argument? %! s = prod([x y z a b c X Y Z]); %! assert (isequal (symvar (s,4), [x, y, z, c] )) %!test %! %% closest to x %! s = prod([y z a b c Y Z]); %! assert (isequal( symvar (s,6), [ y, z, c, b, a, Y] )) %! s = prod([a b c Y Z]); %! assert (isequal( symvar (s,4), [ c, b, a, Y] )) %!test %! %% upper case letters in correct order %! s = X*Y*Z; %! assert (isequal( symvar (s,3), [X Y Z] )) %!test %! % diff. assumptions make diff. symbols %! x1 = sym('x'); %! x2 = sym('x', 'positive'); %! f = x1*x2; %! assert (length (symvar (f)) == 2) %! z = symvar (f, 1); %! assert (xor (isequal (z, x1), isequal (z, x2))) symbolic-3.1.1/inst/@sym/tan.m0000644000000000000000000000325614405647405013067 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym tan (@var{x}) %% Symbolic tan function. %% %% Example: %% @example %% @group %% syms x %% y = tan (x) %% @result{} y = (sym) tan(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = tan(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('tan', x); end %!error tan (sym(1), 2) %!assert (isequaln (tan (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = tan(x); %! f2 = tan(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = tan(A); %! f2 = tan(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = tan (d); %! f = tan (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/tand.m0000644000000000000000000000306314405647405013227 0ustar %% Copyright (C) 2014-2016, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym tand (@var{x}) %% Symbolic tan function with input in degrees. %% %% Example: %% @example %% @group %% tand (sym (60)) %% @result{} (sym) √3 %% %% syms x %% y = tand (x) %% @result{} y = (sym) %% ⎛π⋅x⎞ %% tan⎜───⎟ %% ⎝180⎠ %% @end group %% @end example %% %% @seealso{@@sym/atand, @@sym/tan} %% @end defmethod function y = tand(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('lambda a: tan(rad(a))', x); end %!error tand (sym(1), 2) %!assert (isequaln (tand (sym(nan)), sym(nan))) %!test %! f1 = tand (sym(1)); %! f2 = tand (1); %! assert (double (f1), f2, -eps) %!test %! D = [10 30; 110 -45]; %! A = sym(D); %! f1 = tand (A); %! f2 = tand (D); %! assert (double (f1), f2, -eps) symbolic-3.1.1/inst/@sym/tanh.m0000644000000000000000000000327414405647405013237 0ustar %% Copyright (C) 2014-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym tanh (@var{x}) %% Symbolic tanh function. %% %% Example: %% @example %% @group %% syms x %% y = tanh (x) %% @result{} y = (sym) tanh(x) %% @end group %% @end example %% %% Note: this file is autogenerated: if you want to edit it, you might %% want to make changes to 'generate_functions.py' instead. %% %% @end defmethod function y = tanh(x) if (nargin ~= 1) print_usage (); end y = elementwise_op ('tanh', x); end %!error tanh (sym(1), 2) %!assert (isequaln (tanh (sym(nan)), sym(nan))) %!shared x, d %! d = 1; %! x = sym('1'); %!test %! f1 = tanh(x); %! f2 = tanh(d); %! assert( abs(double(f1) - f2) < 1e-15 ) %!test %! D = [d d; d d]; %! A = [x x; x x]; %! f1 = tanh(A); %! f2 = tanh(D); %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! A = tanh (d); %! f = tanh (y); %! h = function_handle (f); %! B = h (d); %! assert (A, B, -eps) symbolic-3.1.1/inst/@sym/taylor.m0000644000000000000000000002117414405647405013616 0ustar %% Copyright (C) 2014-2018, 2019 Colin B. Macdonald %% Copyright (C) 2016 Utkarsh Gautam %% Copyright (C) 2016 Lagu %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym taylor (@var{f}) %% @defmethodx @@sym taylor (@var{f}, @var{x}) %% @defmethodx @@sym taylor (@var{f}, @var{x}, @var{a}) %% @defmethodx @@sym taylor (@var{f}, [@var{x}, @var{y}]) %% @defmethodx @@sym taylor (@var{f}, [@var{x}, @var{y}], [@var{a}, @var{b}]) %% @defmethodx @@sym taylor (@dots{}, @var{key}, @var{value}) %% Symbolic Taylor series. %% %% If omitted, @var{x} is chosen with @code{symvar} and @var{a} %% defaults to zero. %% %% Key/value pairs can be used to set the order: %% @example %% @group %% syms x %% f = exp(x); %% taylor(f, x, 0, 'order', 6) %% @result{} (sym) %% 5 4 3 2 %% x x x x %% ─── + ── + ── + ── + x + 1 %% 120 24 6 2 %% @end group %% @end example %% %% Two-dimensional expansion: %% @example %% @group %% syms x y %% f = exp(x*y); %% taylor(f, [x,y] , [0,0], 'order', 7) %% @result{} (sym) %% 3 3 2 2 %% x ⋅y x ⋅y %% ───── + ───── + x⋅y + 1 %% 6 2 %% @end group %% @end example %% %% As an alternative to passing @var{a}, you can also set the %% expansion point using a key/value notation: %% @example %% @group %% syms x %% f = exp(x); %% taylor(f, 'expansionPoint', 1, 'order', 4) %% @result{} (sym) %% 3 2 %% ℯ⋅(x - 1) ℯ⋅(x - 1) %% ────────── + ────────── + ℯ⋅(x - 1) + ℯ %% 6 2 %% @end group %% @end example %% %% @seealso{@@sym/diff} %% @end defmethod function s = taylor(f, varargin) if (nargin == 1) % taylor(f) x = symvar(f,1); a = sym(0); i = nargin; elseif (nargin == 2) % taylor(f,[x,y]) x = varargin{1}; a = zeros(1, length(x)); i = nargin; elseif (~ischar(varargin{1}) && ~ischar(varargin{2})) % taylor(f, x, a) % taylor(f, [x,y], [a,b]) % taylor(f, [x,y], [a,b], 'param', ...) x = varargin{1}; a = varargin{2}; if length(a) ~= length(x) && length(a) == 1 a = a*ones(1, length(x)); end i = 3; elseif (~ischar(varargin{1}) && ischar(varargin{2})) % taylor(f, x, 'param', ...) % taylor(f, [x,y], 'param', ...) x = varargin{1}; a = zeros(1, length(x)); i = 2; else % taylor(f,'param') assert (ischar(varargin{1})) x = symvar(f,1); a = zeros(1, length(x)); i = 1; end n = 6; %default order while (i <= (nargin-1)) if (strcmpi(varargin{i}, 'order')) n = varargin{i+1}; i = i + 2; elseif (strcmpi(varargin{i}, 'expansionPoint')) a = varargin{i+1}; i = i + 2; else error('invalid key/value pair') end end if (isfloat(n)) n = int32(n); end assert( isequal( length(x), length(a)), 'The length of the expansion point must be the same as the input variables.') if (numel(x) == 1) cmd = { '(f, x, a, n) = _ins' 's = f.series(x, a, n).removeO()' 'return s,' }; else % Multivariate case. % TODO: keep on eye on upstream sympy; someday it will do this, e.g., % https://github.com/sympy/sympy/issues/6234 % https://stackoverflow.com/questions/22857162/multivariate-taylor-approximation-in-sympy cmd = {'(f, x, a, n) = _ins' 'dic = dict(zip(x, a))' 'xa = list(x)' 'for i in range(len(x)):' ' xa[i] = x[i]-a[i]' 'expn = f.subs(dic) # first constant term' 'for i in range(1,n):' ' tmp = S(0)' ' d = list(itertools.product(x, repeat=i))' ' for j in d:' ' tmp2 = S(1)' ' for p in range(len(x)):' ' tmp2 = tmp2*xa[p]**j.count(x[p])' ' tmp = tmp + f.diff(*j).subs(dic)*tmp2' %%FIXME: In this case we should use a cache system to avoid ' expn = expn + tmp / factorial(i)' %% diff in all vars every time (more ram, less time). 'return simplify(expn)' }; end s = pycall_sympy__ (cmd, sym(f), sym(x), sym(a), n); end %!test %! syms x %! f = exp(x); %! expected = 1 + x + x^2/2 + x^3/6 + x^4/24 + x^5/120; %! assert (isequal (taylor(f), expected)) %! assert (isequal (taylor(f,x), expected)) %! assert (isequal (taylor(f,x,0), expected)) %!test %! syms x %! f = exp(x); %! expected = 1 + x + x^2/2 + x^3/6 + x^4/24; %! assert (isequal (taylor(f,'order',5), expected)) %! assert (isequal (taylor(f,x,'order',5), expected)) %! assert (isequal (taylor(f,x,0,'order',5), expected)) %!test %! % key/value ordering doesn't matter %! syms x %! f = exp(x); %! g1 = taylor(f, 'expansionPoint', 1, 'order', 3); %! g2 = taylor(f, 'order', 3, 'expansionPoint', 1); %! assert (isequal (g1, g2)) %!test %! syms x %! f = x^2; %! assert (isequal (taylor(f,x,0,'order',0), 0)) %! assert (isequal (taylor(f,x,0,'order',1), 0)) %! assert (isequal (taylor(f,x,0,'order',2), 0)) %! assert (isequal (taylor(f,x,0,'order',3), x^2)) %! assert (isequal (taylor(f,x,0,'order',4), x^2)) %!test %! syms x y %! f = exp(x)+exp(y); %! expected = 2 + x + x^2/2 + x^3/6 + x^4/24 + y + y^2/2 + y^3/6 + y^4/24; %! assert (isAlways(taylor(f,[x,y],'order',5)== expected)) %! assert (isAlways(taylor(f,[x,y],[0,0],'order',5) == expected)) %!test %! % key/value ordering doesn't matter %! syms x %! f = exp(x); %! g1 = taylor(f, 'expansionPoint', 1, 'order', 3); %! g2 = taylor(f, 'order', 3, 'expansionPoint', 1); %! assert (isequal (g1, g2)) %!test %! syms x %! f = x^2; %! assert (isequal (taylor(f,x,0,'order',0), 0)) %! assert (isequal (taylor(f,x,0,'order',1), 0)) %! assert (isequal (taylor(f,x,0,'order',2), 0)) %! assert (isequal (taylor(f,x,0,'order',3), x^2)) %! assert (isequal (taylor(f,x,0,'order',4), x^2)) %!test %! % syms for a and order %! syms x %! f = x^2; %! assert (isequal (taylor(f,x,sym(0),'order',sym(2)), 0)) %! assert (isequal (taylor(f,x,sym(0),'order',sym(4)), x^2)) %!test %! syms x y %! f = exp (x^2 + y^2); %! expected = 1+ x^2 +y^2 + x^4/2 + x^2*y^2 + y^4/2; %! assert (isAlways(taylor(f,[x,y],'order',5)== expected)) %! assert (isAlways(taylor(f,[x,y],'expansionPoint', [0,0],'order',5) == expected)) %!test %! syms x y %! f = sqrt(1+x^2+y^2); %! expected = 1+ x^2/2 +y^2/2 - x^4/8 - x^2*y^2/4 - y^4/8; %! assert (isAlways(taylor(f,[x,y],'order',6)== expected)) %! assert (isAlways(taylor(f,[x,y],'expansionPoint', [0,0],'order',5) == expected)) %!test %! syms x y %! f = sin (x^2 + y^2); %! expected = sin(sym(1))+2*cos(sym(1))*(x-1)+(cos(sym(1))-2*sin(sym(1)))*(x-1)^2 + cos(sym(1))*y^2; %! assert (isAlways(taylor(f,[x,y],'expansionPoint', [1,0],'order',3) == expected)) %!test %! % key/value ordering doesn't matter %! syms x y %! f = exp(x+y); %! g1 = taylor(f, 'expansionPoint',1, 'order', 3); %! g2 = taylor(f, 'order', 3, 'expansionPoint',1); %! assert (isAlways(g1== g2)) %!test %! syms x y %! f = x^2 + y^2; %! assert (isAlways(taylor(f,[x,y],[0,0],'order',0)== sym(0) )) %! assert (isAlways(taylor(f,[x,y],[0,0],'order',1)== sym(0) )) %! assert (isAlways(taylor(f,[x,y],[0,0],'order',2)== sym(0) )) %! assert (isAlways(taylor(f,[x,y],[0,0],'order',3)== sym(x^2 + y^2))) %! assert (isAlways(taylor(f,[x,y],[0,0],'order',4)== sym(x^2 + y^2))) %!test %! % expansion point %! syms x a %! f = x^2; %! g = taylor(f,x,2); %! assert (isequal (simplify(g), f)) %! assert (isequal (g, 4*x+(x-2)^2-4)) %! g = taylor(f,x,a); %! assert (isequal (simplify(g), f)) %!test %! % wrong order-1 series with nonzero expansion pt: %! % upstream bug https://github.com/sympy/sympy/issues/9351 %! syms x %! g = x^2 + 2*x + 3; %! h = taylor (g, x, 4, 'order', 1); %! assert (isequal (h, 27)) %!test %! syms x y z %! g = x^2 + 2*y + 3*z; %! h = taylor (g, [x,y,z], 'order', 4); %! assert (isAlways(h == g)) ; %!test %! syms x y z %! g = sin(x*y*z); %! h = taylor (g, [x,y,z], 'order', 4); %! assert (isAlways(h == x*y*z)) ; %!error %! syms x y %! taylor(0, [x, y], [1, 2, 3]); symbolic-3.1.1/inst/@sym/times.m0000644000000000000000000000631314405647405013423 0ustar %% Copyright (C) 2014, 2016, 2018-2019, 2022 Colin B. Macdonald %% Copyright (C) 2022 Alex Vong %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym times {(@var{x}, @var{y})} %% @defopx Operator @@sym {@var{x} .* @var{y}} {} %% Return Hadamard product (element-wise multiplication) of matrices. %% %% Example: %% @example %% @group %% syms x %% A = [2 x]; %% B = [3 4]; %% A.*B %% @result{} ans = (sym) [6 4⋅x] (1×2 matrix) %% @end group %% @end example %% %% For ``matrix expressions'' such as matrices with symbolic size, %% the product may not be evaluated: %% @example %% @group %% syms n m integer %% A = sym('A', [n m]); %% B = sym('B', [n m]); %% A.*B %% @result{} ans = (sym) A∘B %% @end group %% @end example %% @seealso{@@sym/power} %% @end defop function z = times(x, y) %% 2022-06: TODO cannot simply call hadamard_product for sympy <1.9, %% see upstream: https://github.com/sympy/sympy/issues/8557 cmd = { '(x,y) = _ins' 'if x is None or y is None:' ' return x*y' 'if x.is_Matrix and y.is_Matrix:' ' if Version(spver) < Version("1.9"):' ' try:' ' return x.multiply_elementwise(y)' ' except (AttributeError, TypeError):' ' pass' ' return hadamard_product(x, y)' 'return x*y' }; z = pycall_sympy__ (cmd, sym(x), sym(y)); end %!test %! % scalar %! syms x %! assert (isa (x.*2, 'sym')) %! assert (isequal (x.*2, x*2)) %! assert (isequal (2.*sym(3), sym(6))) %! assert (isequal (sym(2).*3, sym(6))) %!test %! % matrix-matrix and matrix-scalar %! D = [0 1; 2 3]; %! A = sym(D); %! assert (isequal ( 2.*A , 2*D )) %! assert (isequal ( A.*2 , 2*D )) %! assert (isequal ( A.*A , D.*D )) %! assert (isequal ( A.*D , D.*D )) %! assert (isequal ( D.*A , D.*D )) %!test %! syms x %! A = [1 x]; %! B = [2 3]; %! assert (isequal (A.*B, [2 3*x])) %!test %! % immutable test %! A = sym([1 2]); %! B = sym('ImmutableDenseMatrix([[Integer(1), Integer(2)]])'); %! assert (isequal (A.*A, B.*B)) %!test %! % MatrixSymbol test %! A = sym([1 2; 3 4]); %! B = sym('ImmutableDenseMatrix([[Integer(1), Integer(2)], [Integer(3), Integer(4)]])'); %! C = sym('MatrixSymbol("C", 2, 2)'); %! assert (~ isempty (strfind (sympy (C.*C), 'Hadamard'))) %! assert (~ isempty (strfind (sympy (A.*C), 'Hadamard'))) %! assert (~ isempty (strfind (sympy (C.*A), 'Hadamard'))) %! assert (~ isempty (strfind (sympy (B.*C), 'Hadamard'))) %! assert (~ isempty (strfind (sympy (C.*B), 'Hadamard'))) symbolic-3.1.1/inst/@sym/toeplitz.m0000644000000000000000000000710314405647405014152 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym toeplitz (@var{c}, @var{r}) %% @defmethodx @@sym toeplitz (@var{r}) %% Construct a symbolic Toeplitz matrix. %% %% Examples: %% @example %% @group %% A = toeplitz (sym([0 1 2 3])) %% @result{} A = (sym 4×4 matrix) %% %% ⎡0 1 2 3⎤ %% ⎢ ⎥ %% ⎢1 0 1 2⎥ %% ⎢ ⎥ %% ⎢2 1 0 1⎥ %% ⎢ ⎥ %% ⎣3 2 1 0⎦ %% %% A = toeplitz (sym([0 1 2 3]), sym([0 -1 -2 -3 -4])) %% @result{} A = (sym 4×5 matrix) %% %% ⎡0 -1 -2 -3 -4⎤ %% ⎢ ⎥ %% ⎢1 0 -1 -2 -3⎥ %% ⎢ ⎥ %% ⎢2 1 0 -1 -2⎥ %% ⎢ ⎥ %% ⎣3 2 1 0 -1⎦ %% @end group %% @end example %% %% @end defmethod function A = toeplitz (C, R) if (nargin == 1) [C, R] = deal(C', C); elseif (nargin ~= 2) print_usage (); end R = sym(R); C = sym(C); assert(isvector(R)); assert(isvector(C)); % Diagonal conflict idx.type = '()'; idx.subs = {1}; if (nargin == 2) && ~(isequal(subsref(R,idx), subsref(C,idx))); warning('OctSymPy:toeplitz:diagconflict', ... 'toeplitz: column wins diagonal conflict') R = subsasgn(R, idx, subsref(C, idx)); end % (if just one input (R) then we want it to get the diag) cmd = { '(C, R) = _ins' 'if not R.is_Matrix:' ' return R' '(n, m) = (len(C), len(R))' 'A = sp.zeros(n, m)' 'for i in range(0, n):' ' for j in range(0, m):' ' if i - j > 0:' ' A[i, j] = C[i-j]' ' else:' ' A[i, j] = R[j-i]' 'return A' }; A = pycall_sympy__ (cmd, C, R); end %!test %! % rect %! R = [10 20 40]; C = [10 30]; %! A = sym(toeplitz(R,C)); %! B = toeplitz(sym(R),sym(C)); %! assert (isequal (A, B)) %! R = [10 20]; C = [10 30 50]; %! A = sym(toeplitz(R,C)); %! B = toeplitz(sym(R),sym(C)); %! assert (isequal (A, B)) %!test %! % symbols %! syms x y %! R = [10 20 40]; C = [10 30]; %! Rs = [10 x 40]; Cs = [10 y]; %! A = toeplitz(R,C); %! B = toeplitz(Rs,Cs); %! assert (isequal (A, subs(B,[x,y],[20 30]))) %!test %! % hermitian %! syms a b c %! A = [a b c; conj(b) a b; conj(c) conj(b) a]; %! B = toeplitz([a,b,c]); %! assert (isequal( A, B)) %!warning %! % mismatch %! syms x %! B = toeplitz([10 x], [1 3 x]); %!warning %! % scalar %! B = toeplitz(sym(2), 3); %! assert (isequal (B, sym(2))) %!test %! % mismatch %! syms x y %! fprintf('\n one warning expected\n') % how to quiet this one? %! A = toeplitz([10 2], [1 3 5]); %! s = warning ('off', 'OctSymPy:toeplitz:diagconflict'); %! B = toeplitz([10 x], [1 3 y]); %! warning(s) %! assert (isequal (A, subs(B, [x,y], [2 5]))) symbolic-3.1.1/inst/@sym/trace.m0000644000000000000000000000464614405647405013407 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym trace (@var{A}) %% Trace of symbolic matrix. %% %% Example: %% @example %% @group %% syms x %% A = [1 2 x; 3 sym(pi) 4; 13 5 2*x] %% @result{} A = (sym 3×3 matrix) %% ⎡1 2 x ⎤ %% ⎢ ⎥ %% ⎢3 π 4 ⎥ %% ⎢ ⎥ %% ⎣13 5 2⋅x⎦ %% trace(A) %% @result{} ans = (sym) 2⋅x + 1 + π %% @end group %% @end example %% %% As an example, we can check that the trace of the product is @emph{not} %% the product of the traces: %% @example %% @group %% A = sym([1 2; 3 4]); %% B = sym([pi 3; 1 8]); %% trace(A*B) %% @result{} ans = (sym) π + 43 %% trace(A) * trace(B) %% @result{} ans = (sym) 5⋅π + 40 %% @end group %% @end example %% However, such a property does hold if we use the Kronecker tensor product %% (@pxref{@@sym/trace}): %% @example %% @group %% kron(A, B) %% @result{} ans = (sym 4×4 matrix) %% ⎡ π 3 2⋅π 6 ⎤ %% ⎢ ⎥ %% ⎢ 1 8 2 16⎥ %% ⎢ ⎥ %% ⎢3⋅π 9 4⋅π 12⎥ %% ⎢ ⎥ %% ⎣ 3 24 4 32⎦ %% trace(kron(A, B)) %% @result{} ans = (sym) 5⋅π + 40 %% trace(A) * trace(B) %% @result{} ans = (sym) 5⋅π + 40 %% @end group %% @end example %% %% @seealso{@@sym/det} %% @end defmethod function z = trace(x) cmd = { 'x, = _ins' 'if not x.is_Matrix:' ' x = sp.Matrix([[x]])' 'return sp.trace(x),' }; z = pycall_sympy__ (cmd, x); end %!test %! % scalar %! syms x %! assert (isequal (trace(x), x)) %!test %! syms x %! A = [x 3; 2*x 5]; %! assert (isequal (trace(A), x + 5)) symbolic-3.1.1/inst/@sym/transpose.m0000644000000000000000000000423414405647405014320 0ustar %% Copyright (C) 2014-2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym transpose {(@var{A})} %% @defopx Operator @@sym {@var{A}.'} {} %% Structural transpose (not conjugate) of a symbolic array. %% %% Example: %% @example %% @group %% syms z %% syms x real %% A = [1 x z; sym(4) 5 6+7i] %% @result{} A = (sym 2×3 matrix) %% ⎡1 x z ⎤ %% ⎢ ⎥ %% ⎣4 5 6 + 7⋅ⅈ⎦ %% transpose(A) %% @result{} (sym 3×2 matrix) %% ⎡1 4 ⎤ %% ⎢ ⎥ %% ⎢x 5 ⎥ %% ⎢ ⎥ %% ⎣z 6 + 7⋅ⅈ⎦ %% @end group %% @end example %% %% This can be abbreviated to: %% @example %% @group %% A.' %% @result{} (sym 3×2 matrix) %% ⎡1 4 ⎤ %% ⎢ ⎥ %% ⎢x 5 ⎥ %% ⎢ ⎥ %% ⎣z 6 + 7⋅ⅈ⎦ %% @end group %% @end example %% %% @seealso{@@sym/ctranspose} %% @end defop function z = transpose(x) if (nargin ~= 1) print_usage (); end cmd = { 'x = _ins[0]' 'if x.is_Matrix:' ' return x.T' 'else:' ' return x' }; z = pycall_sympy__ (cmd, x); end %!test %! x = sym(1); %! assert (isequal (x.', x)) %!assert (isempty (sym([]).')) %!test %! syms x; %! assert (isequal (x.', x)) %!test %! A = [1 2; 3 4]; %! assert(isequal( sym(A).' , sym(A.') )) %!test %! A = [1 2] + 1i; %! assert(isequal( sym(A).' , sym(A.') )) symbolic-3.1.1/inst/@sym/tril.m0000644000000000000000000000442314405647405013254 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym tril (@var{A}) %% @defmethodx @@sym tril (@var{A}, @var{k}) %% Lower-triangular part of a symbolic matrix. %% %% Example: %% @example %% @group %% A = sym([1 2 3; 4 5 6; 7 8 9]) %% @result{} A = (sym 3×3 matrix) %% ⎡1 2 3⎤ %% ⎢ ⎥ %% ⎢4 5 6⎥ %% ⎢ ⎥ %% ⎣7 8 9⎦ %% %% tril(A) %% @result{} (sym 3×3 matrix) %% ⎡1 0 0⎤ %% ⎢ ⎥ %% ⎢4 5 0⎥ %% ⎢ ⎥ %% ⎣7 8 9⎦ %% @end group %% %% @group %% tril(A, 1) %% @result{} (sym 3×3 matrix) %% ⎡1 2 0⎤ %% ⎢ ⎥ %% ⎢4 5 6⎥ %% ⎢ ⎥ %% ⎣7 8 9⎦ %% @end group %% @end example %% @seealso{@@sym/tril} %% @end defmethod function L = tril(A,k) if (nargin == 1) k = 0; end if ~(isa(A, 'sym')) % k was a sym L = tril(A, double(k)); return end L = triu(A.', -k); L = L.'; end %!test %! syms x %! assert (isequal (tril(x), x)) %!test %! % with symbols %! syms x %! A = [x 2*x; 3*x 4*x]; %! assert (isequal (tril(A), [x 0; 3*x 4*x])) %!test %! % diagonal shifts %! B = round(10*rand(3,4)); %! A = sym(B); %! assert (isequal (tril(A), tril(B))) %! assert (isequal (tril(A,0), tril(B,0))) %! assert (isequal (tril(A,1), tril(B,1))) %! assert (isequal (tril(A,-1), tril(B,-1))) %!test %! % double array pass through %! B = round(10*rand(3,4)); %! assert (isequal (tril(B,sym(1)), tril(B,1))) %! assert (isa (tril(B,sym(1)), 'double')) symbolic-3.1.1/inst/@sym/triu.m0000644000000000000000000000575614405647405013277 0ustar %% Copyright (C) 2014, 2016, 2018-2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym triu (@var{A}) %% @defmethodx @@sym triu (@var{A}, @var{k}) %% Upper-triangular part of a symbolic matrix. %% %% Example: %% @example %% @group %% A = sym([1 2 3; 4 5 6; 7 8 9]) %% @result{} A = (sym 3×3 matrix) %% ⎡1 2 3⎤ %% ⎢ ⎥ %% ⎢4 5 6⎥ %% ⎢ ⎥ %% ⎣7 8 9⎦ %% %% triu(A) %% @result{} (sym 3×3 matrix) %% ⎡1 2 3⎤ %% ⎢ ⎥ %% ⎢0 5 6⎥ %% ⎢ ⎥ %% ⎣0 0 9⎦ %% @end group %% %% @group %% triu(A, 1) %% @result{} (sym 3×3 matrix) %% ⎡0 2 3⎤ %% ⎢ ⎥ %% ⎢0 0 6⎥ %% ⎢ ⎥ %% ⎣0 0 0⎦ %% @end group %% @end example %% @seealso{@@sym/tril} %% @end defmethod function U = triu(A,k) if (nargin == 1) k = 0; end if ~(isa(A, 'sym')) % k was a sym U = triu(A, double(k)); return end cmd = { '(A,k) = _ins' 'if A.is_Matrix:' ' A = A.as_mutable()' ' (n,m) = A.shape' ' for c in range(0,m):' ' for r in range(max(0,1+c-k),n):' ' A[r,c] = 0' ' return A,' 'elif k == 0:' ' return A,' 'else:' ' return sp.S(0),' }; U = pycall_sympy__ (cmd, A, int32(double(k))); end %!test %! % scalar %! syms x %! assert (isequal (triu(x), x)) %! assert (isequal (triu(x,0), x)) %! assert (isequal (triu(x,1), 0)) %! assert (isequal (triu(x,-1), 0)) %!test %! % with symbols %! syms x %! A = [x 2*x; 3*x 4*x]; %! assert (isequal (triu(A), [x 2*x; 0 4*x])) %!test %! % diagonal shifts %! B = round(10*rand(3,4)); %! A = sym(B); %! assert (isequal (triu(A), triu(B))) %! assert (isequal (triu(A,0), triu(B,0))) %! assert (isequal (triu(A,1), triu(B,1))) %! assert (isequal (triu(A,-1), triu(B,-1))) %!test %! % double array pass through %! B = round(10*rand(3,4)); %! assert (isequal (triu(B,sym(1)), triu(B,1))) %! assert (isa (triu(B,sym(1)), 'double')) %!test %! % immutable test %! A = sym('ImmutableDenseMatrix([[Integer(1), Integer(2)], [Integer(3), Integer(4)]])'); %! assert (isequal (triu (A), sym ([1 2; 0 4]))) %! assert (isequal (tril (A), sym ([1 0; 3 4]))) symbolic-3.1.1/inst/@sym/uminus.m0000644000000000000000000000251614405647405013623 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym uminus (@var{x}) %% @defopx Operator @@sym {-@var{x}} {} %% Return the negation of a symbolic expression. %% %% Example: %% @example %% @group %% syms x %% -x %% @result{} (sym) -x %% -(3 - 2*x) %% @result{} (sym) 2⋅x - 3 %% @end group %% @end example %% @end defop function z = uminus(x) z = pycall_sympy__ ('return -_ins[0],', x); end %!test %! % scalar %! syms x %! assert (isa (-x, 'sym')) %! assert (isequal (-(-x), x)) %!test %! % matrix %! D = [0 1; 2 3]; %! A = sym(D); %! assert( isequal( -A, -D )) symbolic-3.1.1/inst/@sym/union.m0000644000000000000000000000474314405647405013437 0ustar %% Copyright (C) 2016, 2019 Colin B. Macdonald %% Copyright (C) 2016 Lagu %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym union (@var{A}, @var{B}) %% Return the union of elements of two sets. %% %% Examples: %% @example %% @group %% A = finiteset(sym(1), sym(2)); %% B = finiteset(sym(pi), 2); %% C = union(A, B) %% @result{} C = (sym) @{1, 2, π@} %% %% D = interval(sym(3), 4); %% union(C, D) %% @result{} ans = (sym) @{1, 2@} ∪ [3, 4] %% @end group %% @end example %% %% @seealso{@@sym/intersect, @@sym/setdiff, @@sym/setxor, @@sym/unique, %% @@sym/ismember, @@sym/finiteset, @@sym/interval} %% @end defmethod function r = union(a, b) if (nargin ~= 2) print_usage (); end cmd = { 'a, b = _ins' 'if isinstance(a, sp.Set) or isinstance(b, sp.Set):' ' return a | b,' '' 'A = sp.FiniteSet(*(list(a) if isinstance(a, sp.MatrixBase) else [a]))' 'B = sp.FiniteSet(*(list(b) if isinstance(b, sp.MatrixBase) else [b]))' 'C = A | B' 'return sp.Matrix([list(C)]),' }; r = pycall_sympy__ (cmd, sym(a), sym(b)); end %!test %! A = sym([1 2 3]); %! B = sym([1 2 4]); %! C = union(A, B); %! D = sym([1 2 3 4]); %! assert (isequal (C, D)) %!test %! % one nonsym %! A = sym([1 2 3]); %! B = [1 2 4]; %! C = union(A, B); %! D = sym([1 2 3 4]); %! assert (isequal (C, D)) %!test %! % empty %! A = sym([1 2 3]); %! C = union(A, A); %! assert (isequal(C, A)) %!test %! % empty input %! A = sym([1 2]); %! C = union(A, []); %! assert (isequal (C, sym([1 2]))) %!test %! % scalar %! syms x %! assert (isequal (union([x 1], x), [1 x])) %! assert (isequal (union(x, x), x)) %!test %! A = interval(sym(1), 3); %! B = interval(sym(2), 5); %! C = union(A, B); %! assert( isequal( C, interval(sym(1), 5))) symbolic-3.1.1/inst/@sym/unique.m0000644000000000000000000000377214405647405013616 0ustar %% Copyright (C) 2016, 2019 Colin B. Macdonald %% Copyright (C) 2016 Lagu %% Copyright (C) 2022 Alex Vong %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym unique (@var{A}) %% Return the unique elements of a symbolic matrix. %% %% Example: %% @example %% @group %% syms x %% A = [sym(1) 2 pi x x pi 2*sym(pi)]; %% unique(A) %% @result{} ans = (sym) [1 2 π x 2⋅π] (1×5 matrix) %% @end group %% @end example %% %% Note the @emph{output will be a matrix}. If instead you want a %% @emph{set}, try: %% @example %% @group %% finiteset(num2cell(A)) %% @result{} ans = (sym) @{1, 2, π, 2⋅π, x@} %% @end group %% @end example %% %% @seealso{@@sym/union, @@sym/intersect, @@sym/setdiff, @@sym/setxor, %% @@sym/ismember, @@sym/finiteset} %% @end defmethod function r = unique(A) if (nargin ~= 1) print_usage (); end cmd = {'(A,) = _ins' 'if A.is_Matrix:' ' return sp.Matrix([list(uniq(*_ins))]),' 'else:' ' return _ins'}; r = pycall_sympy__ (cmd, A); end %!test %! A = sym([1 2 3 3 5 3 2 6 5]); %! B = sym([1 2 3 5 6]); %! assert (isequal (unique(A), B)) %!test %! syms x y %! A = [1 2 3 3 4 5 5 6 7 7 x x y y]; %! B = [1 2 3 4 5 6 7 x y]; %! assert (isequal (unique(A), B)) %!test %! syms x %! assert (isequal (unique(x), x)) symbolic-3.1.1/inst/@sym/uplus.m0000644000000000000000000000233314405647405013450 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym uplus (@var{x}) %% @defopx Operator @@sym {+@var{x}} {} %% Symbolic unitary minus. %% %% A no-op. Example: %% @example %% @group %% syms x %% +x %% @result{} (sym) x %% @end group %% @end example %% @seealso{@@sym/uminus} %% @end defop function x = uplus(x) % no-op end %!test %! syms x %! assert (isa (+x, 'sym')) %! assert (isequal (+x, x)) %!test %! A = sym([0 -1 inf]); %! assert( isequal ( +A, A)) symbolic-3.1.1/inst/@sym/vertcat.m0000644000000000000000000000735014405647405013754 0ustar %% Copyright (C) 2014-2017, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@sym {vertcat} {(@var{x}, @var{y}, @dots{})} %% @defopx Operator @@sym {[@var{x}; @var{y}; @dots{}]} {} %% Vertically concatentate symbolic arrays. %% %% Example: %% @example %% @group %% A = sym([1 2]) %% @result{} A = (sym) [1 2] (1×2 matrix) %% [A; A; 2*A] %% @result{} (sym 3×2 matrix) %% ⎡1 2⎤ %% ⎢ ⎥ %% ⎢1 2⎥ %% ⎢ ⎥ %% ⎣2 4⎦ %% @end group %% @end example %% @seealso{@@sym/horzcat, @@sym/cat} %% @end defop function h = vertcat(varargin) % special case for 0x0 but other empties should be checked for % compatibilty cmd = { '_proc = []' 'for i in _ins:' ' if i is None or not i.is_Matrix:' ' _proc.append(sp.Matrix([[i]]))' ' else:' ' if i.shape == (0, 0):' ' pass' ' else:' ' _proc.append(i)' 'return sp.MatrixBase.vstack(*_proc),' }; for i = 1:nargin varargin{i} = sym(varargin{i}); end h = pycall_sympy__ (cmd, varargin{:}); end %!test %! % basic %! syms x %! A = [x; x]; %! B = vertcat(x, x); %! C = vertcat(x, x, x); %! assert (isa (A, 'sym')) %! assert (isa (B, 'sym')) %! assert (isa (C, 'sym')) %! assert (isequal (size(A), [2 1])) %! assert (isequal (size(B), [2 1])) %! assert (isequal (size(C), [3 1])) %!test %! % basic, part 2 %! syms x %! A = [x; 1]; %! B = [1; x]; %! C = [1; 2; x]; %! assert (isa (A, 'sym')) %! assert (isa (B, 'sym')) %! assert (isa (C, 'sym')) %! assert (isequal (size(A), [2 1])) %! assert (isequal (size(B), [2 1])) %! assert (isequal (size(C), [3 1])) %!test %! % column vectors %! a = [sym(1); 2]; %! b = [sym(3); 4]; %! assert (isequal ( [a;b] , [1; 2; 3; 4] )) %! assert (isequal ( [a;b;a] , [1; 2; 3; 4; 1; 2] )) %!test %! % row vectors %! a = [sym(1) 2]; %! b = [sym(3) 4]; %! assert (isequal ( [a;b] , [1 2; 3 4] )) %! assert (isequal ( [a;b;a] , [1 2; 3 4; 1 2] )) %!test %! % row vector, other row %! a = [sym(1) 2]; %! assert (isequal ( [a; [sym(3) 4]] , [1 2; 3 4] )) %!test %! % empty vectors %! v = [sym(1) sym(2)]; %! a = [v; []]; %! assert (isequal (a, v)) %! a = [[]; v; []]; %! assert (isequal (a, v)) %! a = [v; []; []]; %! assert (isequal (a, v)) %!xtest %! % FIXME: is this Octave bug? worth worrying about %! syms x %! a = [x; [] []]; %! assert (isequal (a, x)) %!test %! % more empty vectors %! v = [sym(1) sym(2)]; %! q = sym(ones(0, 2)); %! assert (isequal ([v; q], v)) %!error %! v = [sym(1) sym(2)]; %! q = sym(ones(0, 3)); %! w = vertcat(v, q); %!test %! % Octave 3.6 bug: should pass on 3.8.1 and matlab %! a = [sym(1) 2]; %! assert (isequal ( [a; [3 4]] , [1 2; 3 4] )) %! assert (isequal ( [a; sym(3) 4] , [1 2; 3 4] )) %! % more examples %! syms x %! [x [x x]; x x x]; %! [[x x] x; x x x]; %! [[x x] x; [x x] x]; %! [x x x; [x x] x]; %!test %! % issue #700 %! A = sym ([1 2]); %! B = simplify (A); %! assert (isequal ([B; A], [A; B])) symbolic-3.1.1/inst/@sym/xor.m0000644000000000000000000000366314405647405013117 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym xor (@var{x}, @var{y}) %% Logical xor of symbolic arrays. %% %% Examples: %% @example %% @group %% xor(sym(true), sym(true)) %% @result{} ans = (sym) False %% @end group %% %% @group %% syms x y %% xor (x, y) %% @result{} (sym) x ⊻ y %% @end group %% @end example %% %% @seealso{@@sym/and, @@sym/or, @@sym/not, @@sym/eq, @@sym/ne, %% @@sym/logical, @@sym/isAlways} %% @end defmethod function r = xor(x, y) if (nargin ~= 2) print_usage (); end r = elementwise_op ('Xor', sym(x), sym(y)); end %!shared t, f %! t = sym(true); %! f = sym(false); %!test %! % simple %! assert (isequal (xor(t, f), t)) %! assert (isequal (xor(t, t), f)) %!test %! % array %! w = [t t f f]; %! z = [t f t f]; %! assert (isequal (xor(w, z), [f t t f])) %!xtest %! % output is sym even for scalar t/f %! % ₣IXME: should match other bool fcns %! assert (isa (xor(t, f), 'sym')) %!test %! % eqns %! syms x %! e = xor(x == 4, x == 5); %! assert (isequal (subs(e, x, [3 4 5 6]), [f t t f])) %!test %! % eqns, exclusive %! syms x %! e = xor(x == 3, x^2 == 9); %! assert (isequal (subs(e, x, [-3 0 3]), [t f f])) %!error xor (sym('x'), 1, 2) symbolic-3.1.1/inst/@sym/zeros.m0000644000000000000000000000466614405647405013455 0ustar %% Copyright (C) 2016 Lagu %% Copyright (C) 2017, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym zeros (@var{n}) %% @defmethodx @@sym zeros (@var{n}, @var{m}) %% Return a matrix whose elements are all 0. %% %% Example: %% @example %% @group %% y = zeros (sym(3)) %% @result{} y = (sym 3×3 matrix) %% ⎡0 0 0⎤ %% ⎢ ⎥ %% ⎢0 0 0⎥ %% ⎢ ⎥ %% ⎣0 0 0⎦ %% @end group %% @end example %% %% @seealso{zeros, @@sym/ones, @@sym/eye} %% @end defmethod function y = zeros(varargin) % partial workaround for issue #13: delete when/if fixed properly if ((isa (varargin{nargin}, 'char')) && (strcmp (varargin{nargin}, 'sym'))) varargin = varargin(1:(nargin-1)); end if (isa (varargin{end}, 'char')) varargin = cell2nosyms (varargin); y = zeros (varargin{:}); return end for i = 1:length(varargin) varargin{i} = sym(varargin{i}); end if (length (varargin) == 1 && ~isscalar (varargin{1})) y = pycall_sympy__ ('return zeros(*_ins[0])', varargin{1}); else y = pycall_sympy__ ('return zeros(*_ins)', varargin{:}); end end %!test %! y = zeros(sym(2)); %! x = [0 0; 0 0]; %! assert( isequal( y, sym(x))) %!test %! y = zeros(sym(2), 1); %! x = [0; 0]; %! assert( isequal( y, sym(x))) %!test %! y = zeros(sym(1), 2); %! x = [0 0]; %! assert( isequal( y, sym(x))) %!test %! y = zeros (sym([2 3])); %! x = sym (zeros ([2 3])); %! assert (isequal (y, x)) %% Check types: %!assert( isa( zeros(sym(2), 'double'), 'double')) %!assert( isa( zeros(3, sym(3), 'single') , 'single')) %!assert( isa( zeros(3, sym(3)), 'sym')) %!assert( isa( zeros(3, sym(3), 'sym'), 'sym')) %!xtest %! % Issue #13 %! assert( isa( zeros(3, 3, 'sym'), 'sym')) symbolic-3.1.1/inst/@sym/zeta.m0000644000000000000000000000525714405647405013253 0ustar %% Copyright (C) 2016, 2018-2019, 2022 Colin B. Macdonald %% Copyright (C) 2016 Lagu %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym zeta (@var{x}) %% @defmethodx @@sym zeta (@var{n}, @var{z}) %% Symbolic zeta function. %% %% Example: %% @example %% @group %% syms x %% y = zeta (x) %% @result{} y = (sym) ζ(x) %% @end group %% @end example %% %% With 2 arguments you get the @var{n}th derivative %% of the zeta function evaluated in @var{x}: %% @example %% @group %% syms x %% y = zeta (4, x) %% @result{} y = (sym) %% 4 %% d %% ───(ζ(x)) %% 4 %% dx %% @end group %% @end example %% %% @seealso{@@double/zeta} %% @end defmethod function y = zeta(n, z) if (nargin > 2) print_usage (); end if (nargin == 1) z = n; y = elementwise_op ('zeta', sym (z)); return end %% I don't think upstream sympy has a form for the derivatives % (mpmath does, we'll use that directly in @double/zeta) cmd = {'def _op(a, n):' ' z = Dummy("z")' ' return Derivative(zeta(z), (z, n)).subs(z, a)'}; y = elementwise_op (cmd, sym (z), sym (n)); end %!error zeta (sym(1), 2, 3) %!assert (isequaln (zeta (sym(nan)), sym(nan))) %!test %! f1 = zeta (sym(2)); %! f2 = pi^2/6; %! assert (double (f1), f2, -1e-15) %!test %! A = sym([0 2; 4 6]); %! f1 = zeta (A); %! f2 = [-1/2 pi^2/6; pi^4/90 pi^6/945]; %! assert( all(all( abs(double(f1) - f2) < 1e-15 ))) %!test %! % round trip %! y = sym('y'); %! f = zeta (y); %! h = function_handle (f); %! A = zeta (2); %! B = h (2); %! assert (A, B, -eps) %%!xtest %%! % Disabled: causes stack overflows and crashes Python in Fedora 30 %%! % https://github.com/sympy/sympy/issues/11802 %%! assert (double (zeta (sym (3), 4)), -0.07264084989132137196, -1e-14) %!test %! syms x %! assert (isequal (zeta (0, x), zeta(x))) %!test %! % ensure its the nth deriv wrt x, not the n deriv %! syms x n %! F = zeta (n, x); %! F = subs(F, n, 3); %! assert (isequal (F, diff (zeta (x), x, x, x))) symbolic-3.1.1/inst/@sym/ztrans.m0000644000000000000000000003704514405647405013631 0ustar %% Copyright (C) 2022 Alex Vong %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@sym ztrans (@var{f}, @var{n}, @var{z}) %% @defmethodx @@sym ztrans (@var{f}) %% @defmethodx @@sym ztrans (@var{f}, @var{z}) %% Symbolic one-sided Z-transform. %% %% The one-sided Z-transform of a function @var{f} of @var{n} %% is a function @var{X} of @var{z} defined by the Laurent series below. %% @example %% @group %% syms n nonnegative integer %% syms f(n) %% syms z nonzero complex %% X(z) = ztrans (f) %% @result{} X(z) = (symfun) %% ∞ %% ___ %% ╲ %% ╲ -n %% ╱ z ⋅f(n) %% ╱ %% ‾‾‾ %% n = 0 %% @end group %% @end example %% %% %% Example: %% @example %% @group %% syms n %% f = n^2; %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.4")')) %% ztrans (f) %% @result{} (sym) %% ⎧ 1 %% ⎪ -1 - ─ %% ⎪ z 1 %% ⎪─────────── for ─── < 1 %% ⎪ 3 │z│ %% ⎪ ⎛ 1⎞ %% ⎪z⋅⎜-1 + ─⎟ %% ⎪ ⎝ z⎠ %% ⎨ %% ⎪ ∞ %% ⎪ ___ %% ⎪ ╲ %% ⎪ ╲ 2 -n %% ⎪ ╱ n ⋅z otherwise %% ⎪ ╱ %% ⎪ ‾‾‾ %% ⎩n = 0 %% @end group %% @end example %% %% By default the output is a function of @code{z} (or @code{w} if @code{z} is %% an independent variable of @code{f}). This can be overridden by specifying %% @var{z}. For example: %% @example %% @group %% syms n z w %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.4")')) %% ztrans (exp (n)) %% @result{} (sym) %% ⎧ 1 ℯ %% ⎪ ───── for ─── < 1 %% ⎪ ℯ │z│ %% ⎪ 1 - ─ %% ⎪ z %% ⎪ %% ⎪ ∞ %% ⎨ ___ %% ⎪ ╲ %% ⎪ ╲ -n n %% ⎪ ╱ z ⋅ℯ otherwise %% ⎪ ╱ %% ⎪ ‾‾‾ %% ⎪n = 0 %% ⎩ %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.4")')) %% ztrans (exp (z)) %% @result{} (sym) %% ⎧ 1 ℯ %% ⎪ ───── for ─── < 1 %% ⎪ ℯ │w│ %% ⎪ 1 - ─ %% ⎪ w %% ⎪ %% ⎪ ∞ %% ⎨ ___ %% ⎪ ╲ %% ⎪ ╲ -z z %% ⎪ ╱ w ⋅ℯ otherwise %% ⎪ ╱ %% ⎪ ‾‾‾ %% ⎪z = 0 %% ⎩ %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.4")')) %% ztrans (exp (n), w) %% @result{} (sym) %% ⎧ 1 ℯ %% ⎪ ───── for ─── < 1 %% ⎪ ℯ │w│ %% ⎪ 1 - ─ %% ⎪ w %% ⎪ %% ⎪ ∞ %% ⎨ ___ %% ⎪ ╲ %% ⎪ ╲ -n n %% ⎪ ╱ w ⋅ℯ otherwise %% ⎪ ╱ %% ⎪ ‾‾‾ %% ⎪n = 0 %% ⎩ %% @end group %% @end example %% %% If not specified by @var{n}, the independent variable is chosen by %% looking for a symbol named @code{n}. If no such symbol is found, %% @pxref{@@sym/symvar} is used, which choses a variable close to @code{x}: %% @example %% @group %% syms a n y %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.4")')) %% ztrans (n * exp (y)) %% @result{} (sym) %% ⎛⎧ 1 1 ⎞ %% ⎜⎪────────── for ─── < 1⎟ %% ⎜⎪ 2 │z│ ⎟ %% ⎜⎪ ⎛ 1⎞ ⎟ %% ⎜⎪z⋅⎜1 - ─⎟ ⎟ %% ⎜⎪ ⎝ z⎠ ⎟ %% ⎜⎪ ⎟ y %% ⎜⎨ ∞ ⎟⋅ℯ %% ⎜⎪ ___ ⎟ %% ⎜⎪ ╲ ⎟ %% ⎜⎪ ╲ -n ⎟ %% ⎜⎪ ╱ n⋅z otherwise ⎟ %% ⎜⎪ ╱ ⎟ %% ⎜⎪ ‾‾‾ ⎟ %% ⎝⎩n = 0 ⎠ %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.4")')) %% ztrans (a * exp (y)) %% @result{} (sym) %% ⎛⎧ 1 ℯ ⎞ %% ⎜⎪ ───── for ─── < 1⎟ %% ⎜⎪ ℯ │z│ ⎟ %% ⎜⎪ 1 - ─ ⎟ %% ⎜⎪ z ⎟ %% ⎜⎪ ⎟ %% ⎜⎪ ∞ ⎟ %% a⋅⎜⎨ ___ ⎟ %% ⎜⎪ ╲ ⎟ %% ⎜⎪ ╲ -y y ⎟ %% ⎜⎪ ╱ z ⋅ℯ otherwise ⎟ %% ⎜⎪ ╱ ⎟ %% ⎜⎪ ‾‾‾ ⎟ %% ⎜⎪y = 0 ⎟ %% ⎝⎩ ⎠ %% @end group %% @end example %% %% @var{f}, @var{n} and @var{z} can be scalars or matrices of the same size. %% Scalar inputs are first expanded to matrices to match the size of the %% non-scalar inputs. Then @code{ztrans} will be applied elementwise. %% @example %% @group %% syms n m k c z w u v %% f = [n^2 exp(n); 1/factorial(k) kroneckerDelta(c)]; %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.4")')) %% ztrans (f, [n m; k c], [z w; u v]) %% @result{} (sym 2×2 matrix) %% ⎡⎧ 1 ⎤ %% ⎢⎪ -1 - ─ ⎛⎧ 1 1 ⎞ ⎥ %% ⎢⎪ z 1 ⎜⎪ ───── for ─── < 1⎟ ⎥ %% ⎢⎪─────────── for ─── < 1 ⎜⎪ 1 │w│ ⎟ ⎥ %% ⎢⎪ 3 │z│ ⎜⎪ 1 - ─ ⎟ ⎥ %% ⎢⎪ ⎛ 1⎞ ⎜⎪ w ⎟ ⎥ %% ⎢⎪z⋅⎜-1 + ─⎟ ⎜⎪ ⎟ ⎥ %% ⎢⎪ ⎝ z⎠ ⎜⎪ ∞ ⎟ n⎥ %% ⎢⎨ ⎜⎨ ___ ⎟⋅ℯ ⎥ %% ⎢⎪ ∞ ⎜⎪ ╲ ⎟ ⎥ %% ⎢⎪ ___ ⎜⎪ ╲ -m ⎟ ⎥ %% ⎢⎪ ╲ ⎜⎪ ╱ w otherwise ⎟ ⎥ %% ⎢⎪ ╲ 2 -n ⎜⎪ ╱ ⎟ ⎥ %% ⎢⎪ ╱ n ⋅z otherwise ⎜⎪ ‾‾‾ ⎟ ⎥ %% ⎢⎪ ╱ ⎜⎪m = 0 ⎟ ⎥ %% ⎢⎪ ‾‾‾ ⎝⎩ ⎠ ⎥ %% ⎢⎩n = 0 ⎥ %% ⎢ ⎥ %% ⎢ 1 ⎥ %% ⎢ ─ ⎥ %% ⎢ u ⎥ %% ⎣ ℯ 1 ⎦ %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.4")')) %% ztrans (f, [n m; k c], z) %% @result{} (sym 2×2 matrix) %% ⎡⎧ 1 ⎤ %% ⎢⎪ -1 - ─ ⎛⎧ 1 1 ⎞ ⎥ %% ⎢⎪ z 1 ⎜⎪ ───── for ─── < 1⎟ ⎥ %% ⎢⎪─────────── for ─── < 1 ⎜⎪ 1 │z│ ⎟ ⎥ %% ⎢⎪ 3 │z│ ⎜⎪ 1 - ─ ⎟ ⎥ %% ⎢⎪ ⎛ 1⎞ ⎜⎪ z ⎟ ⎥ %% ⎢⎪z⋅⎜-1 + ─⎟ ⎜⎪ ⎟ ⎥ %% ⎢⎪ ⎝ z⎠ ⎜⎪ ∞ ⎟ n⎥ %% ⎢⎨ ⎜⎨ ___ ⎟⋅ℯ ⎥ %% ⎢⎪ ∞ ⎜⎪ ╲ ⎟ ⎥ %% ⎢⎪ ___ ⎜⎪ ╲ -m ⎟ ⎥ %% ⎢⎪ ╲ ⎜⎪ ╱ z otherwise ⎟ ⎥ %% ⎢⎪ ╲ 2 -n ⎜⎪ ╱ ⎟ ⎥ %% ⎢⎪ ╱ n ⋅z otherwise ⎜⎪ ‾‾‾ ⎟ ⎥ %% ⎢⎪ ╱ ⎜⎪m = 0 ⎟ ⎥ %% ⎢⎪ ‾‾‾ ⎝⎩ ⎠ ⎥ %% ⎢⎩n = 0 ⎥ %% ⎢ ⎥ %% ⎢ 1 ⎥ %% ⎢ ─ ⎥ %% ⎢ z ⎥ %% ⎣ ℯ 1 ⎦ %% @end group %% @end example %% %% As of sympy 1.10.1, sympy cannot find the closed form of one-sided %% Z-transform involving trigonometric functions and Heaviside step function. %% @example %% @group %% syms n %% ztrans (cos (n)) %% @result{} (sym) %% ∞ %% ___ %% ╲ %% ╲ -n %% ╱ z ⋅cos(n) %% ╱ %% ‾‾‾ %% n = 0 %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) > Version("1.4")')) %% ztrans (heaviside (n - 3)) %% @result{} (sym) %% ∞ %% ___ %% ╲ %% ╲ -n %% ╱ z ⋅θ(n - 3) %% ╱ %% ‾‾‾ %% n = 0 %% @end group %% @end example %% %% @end defmethod function X = ztrans (varargin) if (nargin > 3 || nargin == 0) print_usage (); end %% ensure all inputs are sym if ~all (cellfun (@(x) isa (x, 'sym'), varargin)) inputs = cellfun (@sym, varargin, 'UniformOutput', false); X = ztrans (inputs{:}); return end %% recursively call ztrans for non-scalar inputs if ~all (cellfun (@isscalar, varargin)) inputs = cellfun (@(x) num2cell (x), varargin, 'UniformOutput', false); X = sym (cellfun (@ztrans, inputs{:}, 'UniformOutput', false)); return end f = sym (varargin{1}); f_vars = findsymbols (f); find_var_from_f = @(v) f_vars (cellfun (@(x) strcmp (char (x), v), f_vars)); %% select var n if (nargin == 3) n = sym (varargin{2}); else ns = find_var_from_f ('n'); assert (numel (ns) <= 1, 'ztrans: there is more than one "n" symbol: check symvar (f) and sympy (f)'); if (~isempty (ns)) n = ns{:}; % use var n from f elseif (~isempty (f_vars)) n = symvar (f, 1); % select var from f using symfun else n = sym ('n', 'nonnegative', 'integer'); % use freshly generated var n end end %% select var z if (nargin == 3) z = sym (varargin{3}); elseif (nargin == 2) z = sym (varargin{2}); else zs = find_var_from_f ('z'); if (isempty (zs)) % use var z if f is a not function of z z = sym ('z'); else % use var w if f is a function of z z = sym ('w'); end end X = symsum (f / z^n, n, 0, inf); end %% Z-transform table: %% https://en.wikipedia.org/wiki/Z-transform#Table_of_common_Z-transform_pairs %!test %! % basic Z-transform table checks %! % X1, ..., X4 must have inner radius of convergence 1 %! syms n z %! % trick to extract the closed form formula using the fact that inner roc = 1 %! closed_form = @(X) subs (X, abs (1 / z), 1 / sym (2)); %! % check if ztrans(f) == X %! check_ztrans = @(f, X) logical (simplify (closed_form (ztrans (f)) == X)); %! f1 = sym (1); %! X1 = 1 / (1 - 1 / z); %! assert (check_ztrans (f1, X1)); %! f2 = n; %! X2 = (1 / z) / (1 - 1 / z)^2; %! assert (check_ztrans (f2, X2)); %! f3 = n^2; %! X3 = (1 / z) * (1 + 1 / z) / (1 - 1 / z)^3; %! assert (check_ztrans (f3, X3)); %! f4 = n^3; %! X4 = (1 / z) * (1 + 4 / z + 1 / z^2) / (1 - 1 / z)^4; %! assert (check_ztrans (f4, X4)); %! % basic matrix checks %! A1 = ztrans ([f1 f2; f3 f4]); %! B1 = [ztrans(f1) ztrans(f2); ztrans(f3) ztrans(f4)]; %! assert (isequal (A1, B1)); %! A2 = ztrans ([f1 f2; f3 f4], z); %! B2 = [ztrans(f1, z) ztrans(f2, z); ztrans(f3, z) ztrans(f4, z)]; %! assert (isequal (A2, B2)); %! A3 = ztrans ([f1 f2; f3 f4], n, z); %! B3 = [ztrans(f1, n, z) ztrans(f2, n, z); ztrans(f3, n, z) ztrans(f4, n, z)]; %! assert (isequal (A3, B3)); %!test %! % additional Z-transform table checks %! % X1, ..., X4 must have inner radius of convergence a %! syms n nonnegative integer %! syms m positive integer %! syms a %! syms z %! % trick to extract the closed form formula using the fact that inner roc = a %! closed_form = @(X) subs (X, abs (a / z), 1 / sym (2)); %! % check if ztrans(f) == X %! check_ztrans = @(f, X) logical (simplify (closed_form (ztrans (f)) == X)); %! f1 = a^n; %! X1 = 1 / (1 - a / z); %! assert (check_ztrans (f1, X1)); %! f2 = n * a^n; %! X2 = (a / z) / (1 - a / z)^2; %! assert (check_ztrans (f2, X2)); %! f3 = n^2 * a^n; %! X3 = (a / z) * (1 + a / z) / (1 - a / z)^3; %! assert (check_ztrans (f3, X3)); %! f4 = nchoosek(n + m - 1, m - 1) * a^n; %! X4 = 1 / (1 - a / z)^m; %! assert (check_ztrans (f4, X4)); %! % additional matrix checks %! A1 = ztrans (f1, [n m; m n], [z a; a z]); %! B1 = [ztrans(f1, n, z) ztrans(f1, m, a); ztrans(f1, m, a) ztrans(f1, n, z)]; %! assert (isequal (A1, B1)); %! A2 = ztrans (f1, m, [z a; a z]); %! B2 = [ztrans(f1, m, z) ztrans(f1, m, a); ztrans(f1, m, a) ztrans(f1, m, z)]; %! assert (isequal (A2, B2)); %! A3 = ztrans (f1, [n m; m n], a); %! B3 = [ztrans(f1, n, a) ztrans(f1, m, a); ztrans(f1, m, a) ztrans(f1, n, a)]; %! assert (isequal (A3, B3)); %!test %! % Kronecker delta checks %! syms n n0 nonnegative integer %! syms z %! assert (isequal (ztrans (kroneckerDelta (n)), 1)); %! assert (isequal (ztrans (kroneckerDelta (n - n0)), 1 / z^n0)); %!test %! % basic var selection checks %! syms n m z w %! assert (isequal (ztrans (1 / factorial (n)), exp (1 / z))); %! assert (isequal (ztrans (1 / factorial (z)), exp (1 / w))); %! assert (isequal (ztrans (1 / factorial (m), w), exp (1 / w))); %! assert (isequal (ztrans (1 / factorial (m), m, w), exp (1 / w))); %!test %! % additional var selection checks %! syms n m z %! f = kroneckerDelta(m) / factorial (n); %! assert (isequal (ztrans (f, z), exp (1 / z) * kroneckerDelta (m))); %! assert (isequal (ztrans (f, n, z), exp (1 / z) * kroneckerDelta (m))); %! assert (isequal (ztrans (f, m, z), 1 / factorial (n))); %!test %! % if no t, use symvar: take x before a %! syms a x z %! assert (isequal (ztrans (a / factorial (x)), a * exp (1 / z))); %!error ztrans (sym ('n')^sym ('n', 'nonnegative', 'integer')) symbolic-3.1.1/inst/@symfun/0000755000000000000000000000000014405647405012632 5ustar symbolic-3.1.1/inst/@symfun/argnames.m0000644000000000000000000000316214405647405014607 0ustar %% Copyright (C) 2014-2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@symfun argnames (@var{f}) %% Return the independent variables in a symfun. %% %% The counterpart of @code{argname} is @code{formula}: %% @code{argname} for the independent %% variables and @code{formula} for the dependent expression. %% %% Examples: %% @example %% @group %% syms x y %% f(x, y) = x^2; %% argnames(f) %% @result{} (sym) [x y] (1×2 matrix) %% @end group %% @end example %% %% @seealso{@@symfun/formula, @@symfun/symvar, findsymbols} %% @end defmethod function vars = argnames(F) vars = [F.vars{:}]; end %!test %! % basic test %! syms f(x) %! assert (isequal (argnames (f), x)) %!test %! % Multiple variables, abstract symfun %! syms f(t, x, y) %! assert (isequal (argnames (f), [t x y])) %!test %! % Concrete symfun %! syms x y z t %! f(t, x, y) = x + y + z; %! assert (isequal (argnames (f), [t x y])) symbolic-3.1.1/inst/@symfun/diff.m0000644000000000000000000000547414405647405013732 0ustar %% Copyright (C) 2014-2016, 2018-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@symfun diff (@var{f}) %% @defmethodx @@symfun diff (@var{f}, @var{x}) %% @defmethodx @@symfun diff (@var{f}, @var{x}, @var{x}, @dots{}) %% @defmethodx @@symfun diff (@var{f}, @var{x}, @var{n}) %% @defmethodx @@symfun diff (@var{f}, @var{x}, @var{y}) %% @defmethodx @@symfun diff (@var{f}, @var{x}, @var{x}, @var{y}, @var{y}, @dots{}) %% @defmethodx @@symfun diff (@var{f}, @var{x}, @var{n}, @var{y}, @var{m}, @dots{}) %% Symbolic differentiation of symbolic functions. %% %% Mostly the same as @code{@@sym/diff} (and indeed it %% calls that code) but returns a @code{symfun}. %% %% The derivative is itself a symfun so you can evaluate at a point like: %% @example %% @group %% syms u(x) %% up = diff(u) % u'(x) %% @result{} up(x) = (symfun) %% d %% ──(u(x)) %% dx %% up(2) % u'(2) %% @result{} ans = (sym) %% ⎛d ⎞│ %% ⎜──(u(x))⎟│ %% ⎝dx ⎠│x=2 %% @end group %% @end example %% %% On GNU Octave, a further shortcut is possible: %% @example %% @group %% syms u(x) %% diff(u)(2) %% @result{} ans = (sym) %% ⎛d ⎞│ %% ⎜──(u(x))⎟│ %% ⎝dx ⎠│x=2 %% @end group %% %% @group %% syms f(x, y) %% diff(f, x, y, y)(3, 2) % a third partial eval at (3, 2) %% @result{} ans = (sym) %% ⎛ 3 ⎞│ %% ⎜ ∂ ⎟│ %% ⎜──────(f(x, y))⎟│ %% ⎜ 2 ⎟│ %% ⎝∂y ∂x ⎠│x=3, y=2 %% @end group %% @end example %% %% @seealso{@@sym/diff, @@symfun/int} %% @end defmethod %% Author: Colin B. Macdonald %% Keywords: symbolic, differentiation function z = diff(f, varargin) z = diff(formula (f), varargin{:}); z = symfun(z, f.vars); end %!test %! % concrete fcn %! syms x %! f(x) = x*x; %! g(x) = 2*x; %! assert (logical (diff(f) == g)) %! assert (isa (diff(f), 'symfun')) %!test %! % abstract fcn %! syms y(x) %! assert (logical (diff(y) == diff(y(x)))) %! assert (isa (diff(y), 'symfun')) symbolic-3.1.1/inst/@symfun/formula.m0000644000000000000000000000373014405647405014460 0ustar %% Copyright (C) 2015, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@symfun formula (@var{f}) %% Return a symbolic expression for this symfun. %% %% This returns the expression that defines the function given by %% the symfun @var{f}. Typically this is the RHS of the symfun: %% @example %% @group %% syms x %% f(x) = sin(x); %% formula(f) %% @result{} ans = (sym) sin(x) %% @end group %% @end example %% %% The command @ref{@@symfun/argname} gives the independent variables %% of the @@symfun. Basically, @code{argname} for the independent %% variables and @code{formula} for the dependent expression. %% %% If the symfun @var{f} is abstract, this returns @var{f} as a %% sym: %% @example %% @group %% syms f(x) %% formula(f) % but note it's a sym %% @result{} ans = (sym) f(x) %% @end group %% @end example %% %% @seealso{@@symfun/argnames} %% @end defmethod function g = formula(f) g = f.sym; end %!test %! % simple %! syms x %! f(x) = sin(x); %! g = formula(f); %! assert (isequal (g, sin(x))); %!test %! % concrete: return is a sym, not a symfun %! syms x %! f(x) = sin(x); %! g = formula(f); %! assert (~isa(g, 'symfun')); %!test %! % abstract: return is a sym, not a symfun %! syms f(x) %! g = formula(f); %! assert (~isa(g, 'symfun')); symbolic-3.1.1/inst/@symfun/int.m0000644000000000000000000000626314405647405013611 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@symfun int (@var{f}) %% @defmethodx @@symfun int (@var{f}, @var{x}) %% @defmethodx @@symfun int (@var{f}, @var{x}, @var{a}, @var{b}) %% @defmethodx @@symfun int (@var{f}, @var{x}, [@var{a}, @var{b}]) %% @defmethodx @@symfun int (@var{f}, @var{a}, @var{b}) %% @defmethodx @@symfun int (@var{f}, [@var{a}, @var{b}]) %% Symbolic integration of a symfun. %% %% The indefinite integral of a symfun returns another symfun: %% @example %% @group %% syms x %% f(x) = sin(x) %% @result {} f(x) = (symfun) sin(x) %% h = int(f, x) %% @result {} h(x) = (symfun) -cos(x) %% @end group %% @end example %% %% Definite integrals return a sym: %% @example %% @group %% f(x) = sin(x) %% @result {} f(x) = (symfun) sin(x) %% int(f, x, [0 pi]) %% @result {} (sym) 2 %% @end group %% @end example %% %% @seealso{@@sym/int, @@symfun/diff} %% @end defmethod %% Author: Colin B. Macdonald %% Keywords: symbolic, integration function F = int(f, varargin) if (nargin == 1) indefinite = true; elseif (nargin == 2) && (numel(varargin{1}) == 1) % "int(f, x)" but not "int(f, [a b])" indefinite = true; else indefinite = false; end F = int(formula (f), varargin{:}); if (indefinite) F = symfun(F, f.vars); end end %!test %! % indefinite integral of symfun gives symfun %! syms x %! f(x) = x^2; %! g = int(f); %! assert (isa(g, 'symfun')) %! g = int(f, x); %! assert (isa(g, 'symfun')) %!test %! % indefinite integral of abstract symfun gives symfun %! syms f(x) %! g = int(f); %! assert (isa(g, 'symfun')) %! g = int(f, x); %! assert (isa(g, 'symfun')) %!test %! % definite integral does not give symfun %! syms x %! f(x) = x^2; %! g = int(f, x, 0, 2); %! assert (isa(g, 'sym')) %! assert (~isa(g, 'symfun')) %!test %! % ... even if it has a variable in it %! syms x t %! f(x) = x; %! g = int(f, x, 0, t); %! assert (isa(g, 'sym')) %! assert (~isa(g, 'symfun')) %!test %! % ... even if the input is abstract funcion %! syms f(x) %! g = int(f, x, 0, 2); %! assert (isa(g, 'sym')) %! assert (~isa(g, 'symfun')) %!test %! % symfun in x, integrated in y gives symfun still in x %! % (SMT does this too). %! syms f(x) y %! g = int(f, y); %! assert (isa (g, 'symfun')) %! assert (isequal (argnames (g), x)) %!test %! % same as above, but concrete symfun %! syms x y %! f(x) = x^2; %! g = int(f, y); %! assert (isa (g, 'symfun')) %! assert (isequal (argnames (g), x)) %! assert (isequal (formula(g), x^2*y)) symbolic-3.1.1/inst/@symfun/isequal.m0000644000000000000000000000415014405647405014453 0ustar %% Copyright (C) 2017 NVS Abhilash %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@symfun isequal (@var{f}, @var{g}) %% @defmethodx @@symfun isequal (@var{f}, @var{g}, @dots{}) %% Test if contents of two or more arrays are equal. %% %% Example: %% @example %% @group %% syms x %% f(x) = x + 1; %% g(x) = x + 1; %% isequal(f, g) %% @result{} 1 %% @end group %% @end example %% %% Note: two symfuns are equal if they have the same formula @emph{and} %% same arguments: %% @example %% @group %% syms x y %% f(x) = x + 1; %% g(x, y) = x + 1; %% isequal(f, g) %% @result{} 0 %% @end group %% @end example %% %% @seealso{@@sym/isequal, @@symfun/formula, @@symfun/argnames} %% @end defmethod function t = isequal(x, y, varargin) if (nargin <= 1) print_usage (); end t = isequal(formula(x), formula(y)) && isequal(argnames(x), argnames(y)); if nargin >= 3 && t t = t && isequal(x, varargin{:}); end end %!error isequal (symfun('x + 1', x)) %!test %! syms x y %! f(x) = 2*x; %! g(x) = 2*x; %! assert (isequal (f, g)) %!test %! syms x %! f(x) = 2*x + 1; %! g(x) = 2*x + 1; %! h(x) = 2*x + 1; %! assert (isequal (f, g, h)) %!test %! syms x %! f(x) = 2*x + 1; %! g(x) = 2*x + 1; %! h(x) = 2*x; %! assert (~ isequal (f, g, h)) %!test %! syms x y %! f(x) = 2*x; %! g(x, y) = 2*x; %! assert (~ isequal (f, g)) %!test %! syms x y %! f(x) = symfun(nan, x); %! g(x) = symfun(nan, x); %! assert (~ isequal (f, g)) symbolic-3.1.1/inst/@symfun/isequaln.m0000644000000000000000000000466014405647405014637 0ustar %% Copyright (C) 2017 NVS Abhilash %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@symfun isequaln (@var{f}, @var{g}) %% @defmethodx @@symfun isequaln (@var{f}, @var{g}, @dots{}) %% Test if contents of two or more arrays are equal, even with nan. %% %% Example: %% @example %% @group %% syms x %% f(x) = x + 1; %% g(x) = x + 1; %% isequaln(f, g) %% @result{} 1 %% @end group %% @end example %% %% Note: two symfuns are equal if they have the same formula @emph{and} %% same arguments: %% @example %% @group %% syms x y %% f(x) = x + 1; %% g(x, y) = x + 1; %% isequaln(f, g) %% @result{} 0 %% @end group %% @end example %% %% Note: isequaln considers NaN's to be equal: %% @example %% @group %% syms x y %% f(x) = nan; %% g(x) = nan; %% isequaln(f, g) %% @result{} 1 %% @end group %% @end example %% %% @seealso{@@symfun/isequal, @@sym/isequal, @@symfun/formula, @@symfun/argnames} %% @end defmethod function t = isequaln(x, y, varargin) if (nargin <= 1) print_usage (); end t = isequaln(formula(x), formula(y)) && isequal(argnames(x), argnames(y)); if nargin >= 3 && t t = t && isequaln(x, varargin{:}); end end %!error isequaln (symfun('x + 1', x)) %!test %! syms x y %! f(x) = 2*x; %! g(x) = 2*x; %! assert (isequaln (f, g)) %!test %! syms x %! f(x) = 2*x + 1; %! g(x) = 2*x + 1; %! h(x) = 2*x + 1; %! assert (isequaln (f, g, h)) %!test %! syms x %! f(x) = 2*x + 1; %! g(x) = 2*x + 1; %! h(x) = 2*x; %! assert (~ isequaln (f, g, h)) %!test %! syms x y %! f(x) = 2*x; %! g(x, y) = 2*x; %! assert (~ isequaln (f, g)) %!test %! syms x y %! f(x) = symfun(nan, x); %! g(x) = symfun(nan, x); %! assert (isequaln (f, g)) %!test %! syms x y %! f(x) = symfun(nan, x); %! g(x, y) = symfun(nan, x); %! assert (~ isequaln (f, g)) symbolic-3.1.1/inst/@symfun/ldivide.m0000644000000000000000000000277014405647405014436 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@symfun ldivide {(@var{f}, @var{g})} %% @defopx Operator @@symfun {@var{f} .\ @var{g}} {} %% Component-wise backslash division of symbolic functions. %% %% Simple example: %% @example %% @group %% syms x %% f(x) = [1 x sin(x)]; %% g(x) = [x x pi]; %% @end group %% %% @group %% h = f .\ g %% @result{} h(x) = (symfun) %% ⎡ π ⎤ %% ⎢x 1 ──────⎥ %% ⎣ sin(x)⎦ %% @end group %% @end example %% %% @seealso{@@symfun/rdivide} %% @end defop function h = ldivide(f, g) [vars, s1, s2] = helper_symfun_binops(f, g); h = symfun(s1 .\ s2, vars); end %!test %! syms x %! f(x) = x^2; %! assert( isa(f .\ f, 'symfun')) %! assert( isa(f .\ x, 'symfun')) symbolic-3.1.1/inst/@symfun/minus.m0000644000000000000000000000601414405647405014144 0ustar %% Copyright (C) 2014, 2016, 2018-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@symfun minus {(@var{f}, @var{g})} %% @defopx Operator @@symfun {@var{f} - @var{g}} {} %% Subtract one symbolic function from another. %% %% Example: %% @example %% @group %% syms x %% f(x) = 2*x; %% g(x) = sin(x); %% @end group %% %% @group %% h = f - g %% @result{} h(x) = (symfun) 2⋅x - sin(x) %% @end group %% @end example %% %% Matrix example: %% @example %% @group %% syms x y %% f(x, y) = sym([1 12; 13 4]); %% g(x, y) = [x 0; 0 y]; %% @end group %% %% @group %% h = g - f %% @result{} h(x, y) = (symfun) %% ⎡x - 1 -12 ⎤ %% ⎢ ⎥ %% ⎣ -13 y - 4⎦ %% @end group %% @end example %% %% @seealso{@@symfun/plus, @@symfun/uminus} %% @end defop function h = minus(f, g) [vars, s1, s2] = helper_symfun_binops(f, g); h = symfun(s1 - s2, vars); end %!test %! syms x %! f(x) = x^2; %! assert( isa(f - f, 'symfun')) %! assert( isa(f - x, 'symfun')) %!test %! % Octave bug #42735 fixed in 4.4.2 %! syms x %! f(x) = x^2; %! g = x^2; %! h = x - f; assert (isa (h, 'symfun') && isequal (formula (h), x - g)) %! h = x + f; assert (isa (h, 'symfun') && isequal (formula (h), x + g)) %! h = x * f; assert (isa (h, 'symfun') && isequal (formula (h), x * g)) %! h = x / f; assert (isa (h, 'symfun') && isequal (formula (h), x / g)) %! h = x ^ f; assert (isa (h, 'symfun') && isequal (formula (h), x ^ g)) %! h = x .* f; assert (isa (h, 'symfun') && isequal (formula (h), x .* g)) %! h = x ./ f; assert (isa (h, 'symfun') && isequal (formula (h), x ./ g)) %! h = x .^ f; assert (isa (h, 'symfun') && isequal (formula (h), x .^ g)) %!test %! % different variables %! syms x y %! f(x) = 2*x; %! g(y) = sin(y); %! h = f - g(x); %! assert( isa(h, 'symfun')) %! assert( isequal (argnames (h), argnames (f))) %! assert (isequal (formula (h), 2*x - sin(x))) %! % and even if rh-sym has a dummy variable: %! h = f - g(y); %! assert( isa(h, 'symfun')) %! assert( isequal (argnames (h), argnames(f))) %! assert (isequal (formula (h), 2*x - sin(y))) %!test %! % different variables, f has more %! syms x y %! f(x,y) = 2*x*y; %! g(y) = sin(y); %! h = f - g(y) + g(x); %! assert( isa(h, 'symfun')) %! assert( isequal (argnames (h), argnames (f))) %! assert (isequal (formula (h), 2*x*y - sin(y) + sin(x))) symbolic-3.1.1/inst/@symfun/mldivide.m0000644000000000000000000000264314405647405014612 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@symfun mldivide {(@var{f}, @var{g})} %% @defopx Operator @@symfun {@var{f} \ @var{g}} {} %% Backslash division of symbolic functions. %% %% Simple example: %% @example %% @group %% syms f(x) %% g(x) = sin(x); %% @end group %% %% @group %% h = f \ g %% @result{} h(x) = (symfun) %% sin(x) %% ────── %% f(x) %% @end group %% @end example %% %% @seealso{@@sym/mldivide} %% @end defop function h = mldivide(f, g) [vars, s1, s2] = helper_symfun_binops(f, g); h = symfun(s1 \ s2, vars); end %!test %! syms x %! f(x) = x^2; %! assert( isa(f\f, 'symfun')) %! assert( isa(f\x, 'symfun')) symbolic-3.1.1/inst/@symfun/mpower.m0000644000000000000000000000366614405647405014334 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@symfun mpower {(@var{f}, @var{n})} %% @defopx Operator @@symfun {@var{f} ^ @var{n}} {} %% Symbolic function exponentiation. %% %% Example: %% @example %% @group %% syms x y %% f(x, y) = [x 0; 2 y]; %% @end group %% %% @group %% h = f ^ 2 %% @result{} h(x, y) = (symfun) %% ⎡ 2 ⎤ %% ⎢ x 0 ⎥ %% ⎢ ⎥ %% ⎢ 2⎥ %% ⎣2⋅x + 2⋅y y ⎦ %% @end group %% @end example %% %% The exponent can also be a @@symfun: %% @example %% @group %% syms g(x) %% f(x) = sym([2 0; 3 1]); %% %% h = f^g %% @result{} h(x) = (symfun) %% ⎡ g(x) ⎤ %% ⎢ 2 0⎥ %% ⎢ ⎥ %% ⎢ g(x) ⎥ %% ⎣3⋅2 - 3 1⎦ %% @end group %% @end example %% %% @seealso{@@symfun/power} %% @end defop function h = mpower(f, g) [vars, s1, s2] = helper_symfun_binops(f, g); h = symfun(s1 ^ s2, vars); end %!test %! syms x %! f(x) = 2*x; %! h = f^f; %! assert( isa(h, 'symfun')) %! assert (isequal (formula (h), (2*x)^(2*x))) %! h = f^sym(2); %! assert( isa(h, 'symfun')) %! assert (isequal (formula (h), 4*x^2)) symbolic-3.1.1/inst/@symfun/mrdivide.m0000644000000000000000000000264714405647405014624 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@symfun mrdivide {(@var{f}, @var{g})} %% @defopx Operator @@symfun {@var{f} / @var{g}} {} %% Forward slash division of symbolic functions. %% %% Simple example: %% @example %% @group %% syms f(x) %% g(x) = sin(x); %% @end group %% %% @group %% h = f / g %% @result{} h(x) = (symfun) %% f(x) %% ────── %% sin(x) %% @end group %% @end example %% %% @seealso{@@sym/mrdivide} %% @end defop function h = mrdivide(f, g) [vars, s1, s2] = helper_symfun_binops(f, g); h = symfun(s1 / s2, vars); end %!test %! syms x %! f(x) = x^2; %! assert( isa(f/f, 'symfun')) %! assert( isa(f/x, 'symfun')) symbolic-3.1.1/inst/@symfun/mtimes.m0000644000000000000000000000322014405647405014303 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@symfun mtimes {(@var{f}, @var{g})} %% @defopx Operator @@symfun {@var{f} * @var{g}} {} %% Multiply symbolic functions. %% %% Example: %% @example %% @group %% syms x %% f(x) = 2*x; %% g(x) = sin(x); %% @end group %% %% @group %% h = f*g %% @result{} h(x) = (symfun) 2⋅x⋅sin(x) %% @end group %% @end example %% %% Matrix example: %% @example %% @group %% syms x y %% f(x, y) = sym([1 2; 3 4]); %% g(x, y) = [x 0; 0 y]; %% @end group %% %% @group %% h = f*g %% @result{} h(x, y) = (symfun) %% ⎡ x 2⋅y⎤ %% ⎢ ⎥ %% ⎣3⋅x 4⋅y⎦ %% @end group %% @end example %% %% @seealso{@@symfun/times} %% @end defop function h = mtimes(f, g) [vars, s1, s2] = helper_symfun_binops(f, g); h = symfun(s1 * s2, vars); end %!test %! syms x %! f(x) = x^2; %! assert( isa(f * f, 'symfun')) %! assert( isa(f * x, 'symfun')) symbolic-3.1.1/inst/@symfun/numel.m0000644000000000000000000000236414405647405014135 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@symfun numel (@var{f}) %% Number of elements in a symfun. %% %% This behaves differently than for @@sym: %% @example %% @group %% syms x y %% f(x, y) = [1 x; y 2]; %% %% numel(f) %% @result{} 1 %% @end group %% @end example %% %% @seealso{@@sym/numel} %% @end defmethod function n = numel(f) % see issue #107, #109 n = 1; end %!test %! syms x %! f(x) = x^2; %! assert(numel(f)==1) %!test %! syms x %! f(x) = [1 x]; %! assert(numel(f)==1) symbolic-3.1.1/inst/@symfun/plus.m0000644000000000000000000000324114405647405013773 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@symfun plus {(@var{f}, @var{g})} %% @defopx Operator @@symfun {@var{f} + @var{g}} {} %% Add two symbolic functions together. %% %% Example: %% @example %% @group %% syms x %% f(x) = 2*x; %% g(x) = sin(x); %% @end group %% %% @group %% h = f + g %% @result{} h(x) = (symfun) 2⋅x + sin(x) %% @end group %% @end example %% %% Matrix example: %% @example %% @group %% syms x y %% f(x, y) = sym([1 2; 3 4]); %% g(x, y) = [x 0; 0 y]; %% @end group %% %% @group %% h = f + g %% @result{} h(x, y) = (symfun) %% ⎡x + 1 2 ⎤ %% ⎢ ⎥ %% ⎣ 3 y + 4⎦ %% @end group %% @end example %% %% @seealso{@@symfun/minus} %% @end defop function h = plus(f, g) [vars, s1, s2] = helper_symfun_binops(f, g); h = symfun(s1 + s2, vars); end %!test %! syms x %! f(x) = x^2; %! assert( isa(f + f, 'symfun')) %! assert( isa(f + x, 'symfun')) symbolic-3.1.1/inst/@symfun/power.m0000644000000000000000000000320414405647405014143 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@symfun power {(@var{f}, @var{g})} %% @defopx Operator @@symfun {@var{f} .^ @var{g}} {} %% Symbolic function component-wise exponentiation. %% %% Example: %% @example %% @group %% syms x y %% f(x, y) = [x 0; 2 y]; %% g(x, y) = sym([1 2; 3 4]); %% @end group %% %% @group %% h = f .^ g %% @result{} h(x, y) = (symfun) %% ⎡x 0 ⎤ %% ⎢ ⎥ %% ⎢ 4⎥ %% ⎣8 y ⎦ %% @end group %% @end example %% %% @seealso{@@symfun/mpower} %% @end defop function h = power(f, g) [vars, s1, s2] = helper_symfun_binops(f, g); h = symfun(s1 .^ s2, vars); end %!test %! syms x %! f(x) = 2*x; %! h = f.^f; %! assert( isa(h, 'symfun')) %! assert (isequal (formula (h), (2*x)^(2*x))) %!test %! syms x %! f(x) = [x 2*x]; %! h = f.^[x 3]; %! assert( isa(h, 'symfun')) %! assert (isequal (formula (h), [x^x 8*x^3])) symbolic-3.1.1/inst/@symfun/private/0000755000000000000000000000000014405647405014304 5ustar symbolic-3.1.1/inst/@symfun/private/helper_symfun_binops.m0000644000000000000000000000247514405647405020724 0ustar %% Copyright (C) 2014, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . function [vars,s1,s2] = helper_symfun_binops(f, g) if (isa(f,'symfun')) && (isa(g, 'symfun')) %disp('debug: symfun symfun') if ~isequal(f.vars, g.vars) error('arithmetric operators on symfuns must have same vars') end vars = f.vars; s1 = formula (f); s2 = formula (g); elseif (isa(f,'symfun')) %disp('debug: symfun sym') vars = f.vars; s1 = formula (f); s2 = g; elseif (isa(g, 'symfun')) %disp('debug: sym symfun') vars = g.vars; s1 = f; s2 = formula (g); else error('Tertium Non Datur') end symbolic-3.1.1/inst/@symfun/private_disp_name.m0000644000000000000000000000310314405647405016476 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @defmethod @@symfun private_disp_name (@var{f}, @var{name}) %% A string appropriate for representing the name of this symfun. %% %% Private method: this is not the method you are looking for. %% %% @end defmethod function s = private_disp_name(f, input_name) if (isempty(input_name)) s = input_name; return end vars = f.vars; if length(vars) == 0 varstr = ''; else v = vars{1}; varstr = v.flat; end for i = 2:length(vars); v = vars{i}; varstr = [varstr ', ' v.flat]; end s = [input_name, '(', varstr, ')']; end %!test %! syms f(x) %! s = private_disp_name(f, 'f'); %! assert (strcmp (s, 'f(x)')) %!test %! syms x y %! g(y, x) = x + y; %! s = private_disp_name(g, 'g'); %! assert (strcmp (s, 'g(y, x)')) %!test %! syms f(x) %! assert (isempty (private_disp_name(f, ''))) symbolic-3.1.1/inst/@symfun/rdivide.m0000644000000000000000000000317514405647405014444 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@symfun rdivide {(@var{f}, @var{g})} %% @defopx Operator @@symfun {@var{f} ./ @var{g}} {} %% Forward slash component division of symbolic functions. %% %% Simple example: %% @example %% @group %% syms x %% f(x) = [1 x sin(x)]; %% g(x) = [x x pi]; %% @end group %% %% @group %% h = f ./ g %% @result{} h(x) = (symfun) %% ⎡1 sin(x)⎤ %% ⎢─ 1 ──────⎥ %% ⎣x π ⎦ %% @end group %% @end example %% %% @seealso{@@symfun/ldivide} %% @end defop function h = rdivide(f, g) [vars, s1, s2] = helper_symfun_binops(f, g); h = symfun(s1 ./ s2, vars); end %!test %! syms x %! f(x) = x^2; %! assert( isa(f./f, 'symfun')) %! assert( isa(f./[x x^2], 'symfun')) %!test %! syms x %! f(x) = [x 2*x]; %! h = f./[x 2]; %! assert( isa(h, 'symfun')) %! assert (isequal (formula (h), [1 x])) symbolic-3.1.1/inst/@symfun/size.m0000644000000000000000000000353714405647405013772 0ustar %% Copyright (C) 2014, 2016 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@symfun {@var{d} =} size (@var{x}) %% @deftypemethodx @@symfun {[@var{n}, @var{m}] =} size (@var{x}) %% @deftypemethodx @@symfun {@var{d} =} size (@var{x}, @var{dim}) %% Return the size of a symbolic function. %% %% This behaves differently than for @@sym: %% @example %% @group %% syms x y %% f(x, y) = [1 x; y 2]; %% %% size(f) %% @result{} 1 1 %% @end group %% %% @group %% length(f) %% @result{} 1 %% @end group %% @end example %% %% @seealso{@@sym/size} %% @end deftypemethod function [n, m] = size(x, dim) n = [1 1]; if (nargin == 2) && (nargout == 2) print_usage (); elseif (nargout == 2) m = 1; n = 1; elseif (nargin == 2) n = 1; end end %!test %! syms x %! f(x) = x; %! d = size(f); %! assert (isequal (d, [1 1])) %! [n, m] = size(f); %! assert (isequal ([n m], [1 1])) %! assert (size(f, 1) == 1) %! assert (size(f, 2) == 1) %!test %! syms x %! f(x) = [1 x]; %! d = size(f); %! assert (isequal (d, [1 1])) %! [n, m] = size(f); %! assert (isequal ([n m], [1 1])) %! assert (size(f, 1) == 1) %! assert (size(f, 2) == 1) symbolic-3.1.1/inst/@symfun/subsref.m0000644000000000000000000000417214405647405014465 0ustar %% Copyright (C) 2014, 2016-2017, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@symfun subsref {(@var{f}, @var{idx})} %% @defopx Operator @@symfun {@var{f}(@var{x})} {} %% Evaluate a symfun at a particular value. %% %% Example: %% @example %% @group %% syms x %% f(x) = sin(x); %% f(2) %% @result{} (sym) sin(2) %% %% syms h(x, y) %% h(2, 3) %% @result{} (sym) h(2, 3) %% @end group %% @end example %% %% @seealso{@@sym/subsref} %% @end defop function out = subsref (f, idx) switch idx.type case '()' out = subs (formula (f), argnames (f), idx.subs); case '.' fld = idx.subs; if (strcmp (fld, 'vars')) out = f.vars; elseif (strcmp (fld, 'sym')) % TODO: we previously supported a symfun.sym property/method/whatever % which developers used to mean "cast to sym". But that might not be % correct and should probably be deprecated/removed. In most cases, % you probably want "formula(f)". out = formula (f); else out = subsref (formula (f), idx); end otherwise error ('@symfun/subsref: invalid subscript type ''%s''', idx.type); end end %!test %! syms x %! f(x) = x^2; %! v = f.vars; %! assert(iscell(v)) %! assert(length(v)==1) %! assert(isequal(v{1},x)) %!test %! %% pass through to sym properties %! syms x %! f(x) = x^2; %! y = x^2; % not a symfun %! assert(strcmp(f.flat, y.flat)) symbolic-3.1.1/inst/@symfun/symfun.m0000644000000000000000000002107314405647405014334 0ustar %% Copyright (C) 2014-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypemethod @@symfun {@var{f} =} symfun (@var{expr}, @var{vars}) %% Define a symbolic function (not usually invoked directly). %% %% A symfun can be abstract or concrete. An abstract symfun %% represents an unknown function (for example, in a differential %% equation). A concrete symfun represents a known function such as %% @iftex %% @math{f(x) = \sin(x)}. %% @end iftex %% @ifnottex %% f(x) = sin(x). %% @end ifnottex %% %% A concrete symfun: %% @example %% @group %% syms x %% f(x) = sin(x) %% @result{} f(x) = (symfun) sin(x) %% f %% @result{} f(x) = (symfun) sin(x) %% f(1) %% @result{} ans = (sym) sin(1) %% f(x) %% @result{} ans = (sym) sin(x) %% @end group %% @end example %% %% An abstract symfun: %% @example %% @group %% syms g(x) %% g %% @result{} g(x) = (symfun) g(x) %% @end group %% @end example %% (Note this creates the sym @code{x} automatically if it does %% not already exist.) %% %% Example: multivariable symfuns: %% @example %% @group %% syms x y %% g(x, y) = 2*x + sin(y) %% @result{} g(x, y) = (symfun) 2⋅x + sin(y) %% syms g(x, y) %% g %% @result{} g(x, y) = (symfun) g(x, y) %% @end group %% @end example %% %% Example: creating an abstract function formally of two variables %% but depending only on @code{x}: %% @example %% @group %% syms x y h(x) %% h(x, y) = h(x) %% @result{} h(x, y) = (symfun) h(x) %% @end group %% @end example %% %% A symfun can be composed inside another. For example, to %% demonstrate the chain rule in calculus, we might do: %% @example %% @group %% syms f(t) g(t) %% F(t) = f(g(t)) %% @result{} F(t) = (symfun) f(g(t)) %% diff(F, t) %% @result{} ans(t) = (symfun) %% d d %% ─────(f(g(t)))⋅──(g(t)) %% dg(t) dt %% @end group %% @end example %% %% It is possible to create an abstract symfun without using the %% @code{syms} command: %% @example %% @group %% x = sym('x'); %% g(x) = sym('g(x)') %% @result{} g(x) = (symfun) g(x) %% @end group %% @end example %% (note the @code{x} must be included on the left-hand side.) %% However, @code{syms} is safer because this can fail or give %% unpredictable results for certain function names: %% @example %% @group %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) < Version("1.8")')) %% beta(x) = sym('beta(x)') %% @print{} ??? ... Error ... %% @end group %% @end example %% whereas on more recent SymPy we get %% @example %% @group %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) >= Version("1.8")')) %% beta(x) = sym('beta(x)') %% @result{} beta(x) = (symfun) Β(x, x) %% @end group %% @end example %% in either case, we're not getting an abstract symfun but rather the %% beta function (see @ref{@@sym/beta}). %% %% It is usually not necessary to call @code{symfun} directly %% but it can be done: %% @example %% @group %% f = symfun(x*sin(y), [x y]) %% @result{} f(x, y) = (symfun) x⋅sin(y) %% g = symfun(sym('g(x)'), x) %% @result{} g(x) = (symfun) g(x) %% @end group %% @end example %% %% @seealso{sym, syms} %% @end deftypemethod function f = symfun(expr, vars) if (nargin == 0) % octave docs say need a no-argument default for loading from files expr = sym(0); vars = sym('x'); elseif (nargin == 1) print_usage (); elseif (nargin > 2) print_usage (); end % if the vars are in a sym array, put them in a cell array if (isa( vars, 'sym')) varsarray = vars; vars = cell(1, numel(varsarray)); for i = 1:numel(varsarray) vars{i} = varsarray(i); end end % check that vars are unique Symbols cmd = { 'L, = _ins' 'if not all([x is not None and x.is_Symbol for x in L]):' ' return False' 'return len(set(L)) == len(L)' }; if (~ pycall_sympy__ (cmd, vars)) error('OctSymPy:symfun:argNotUniqSymbols', ... 'symfun arguments must be unique symbols') end if (ischar (expr)) error ('symfun(, x) is not supported, see "help symfun" for options') end if (isa(expr, 'symfun')) % allow symfun(, x) expr = formula (expr); else % e.g., allow symfun(, x) expr = sym(expr); end assert (isa (vars, 'cell')) for i=1:length(vars) assert (isa (vars{i}, 'sym')) end f.vars = vars; f = class(f, 'symfun', expr); superiorto ('sym'); end %!error symfun (1, sym('x'), 3) %!error symfun ('f', sym('x')) %!test %! syms x y %! syms f(x) %! assert(isa(f,'symfun')) %! clear f %! f(x,y) = sym('f(x,y)'); %! assert(isa(f,'symfun')) %!test %! % symfuns are syms as well %! syms x %! f(x) = 2*x; %! assert (isa (f, 'symfun')) %! assert (isa (f, 'sym')) %! assert (isequal (f(3), 6)) %! assert (isequal (f(sin(x)), 2*sin(x))) %!test %! syms x y %! f = symfun(sym('f(x)'), {x}); %! assert(isa(f, 'symfun')) %! f = symfun(sym('f(x,y)'), [x y]); %! assert(isa(f, 'symfun')) %! f = symfun(sym('f(x,y)'), {x y}); %! assert(isa(f, 'symfun')) %!test %! % rhs is not sym %! syms x %! f = symfun(8, x); %! assert (isa (f,'symfun')) %! assert (isequal (f(10), sym(8))) %!test %! % vector symfun %! syms x y %! F(x,y) = [1; 2*x; y; y*sin(x)]; %! assert (isa (F, 'symfun')) %! assert (isa (F, 'sym')) %! assert (isequal (F(sym(pi)/2,4) , [sym(1); sym(pi); 4; 4] )) %!test %! x = sym('x'); %! y = sym('y'); %! f(x) = sym('f(x)'); %! g(x,y) = sym('g(x,y)'); %! % make sure these don't fail %! f(1); %! g(1,2); %! g(x,y); %! diff(g, x); %! diff(g, y); %!test %! % defining 1D symfun in terms of a 2D symfun %! syms x y t %! syms 'g(x,y)' %! f(t) = g(t,t); %! f(5); %! assert (length (argnames (f)) == 1) %! assert (isequal (argnames (f), t)) %! assert (isequal( formula(diff(f,x)), sym(0))) %!test %! % replace g with shorter and specific fcn %! syms x g(x) %! g; %! g(x) = 2*x; %! assert( isequal (g(5), 10)) %!test %! % octave <= 3.8 needs quotes on 2D symfuns, so make sure it works %! syms x y %! syms 'f(x)' %! syms 'g(x,y)' %! assert (isa (f, 'symfun')) %! assert (isa (g, 'symfun')) %!test %! % Bug #41: Octave <= 3.8 parser fails without quotes around 2D fcn %! syms x y %! eval('syms g(x,y)') %! assert (isa (g, 'symfun')) %!test %! % and these days it works without eval trick %! syms g(x,y) %! assert (isa (g, 'symfun')) %!test %! % syms f(x) without defining x %! clear x %! syms f(x) %! assert(isa(f, 'symfun')) %! assert(isa(x, 'sym')) %!test %! % SMT compat: symfun indep var overwrites existing var %! t = 6; %! syms f(t) %! assert (logical (t ~= 6)) %!test %! % SMT compat: symfun indep var overwrites existing var, even if sym %! syms x %! t = x; %! syms f(t) %! assert (~ logical (t == x)) %!test %! syms x y %! f(x) = x^2; %! g(x,y) = sym('g(x,y)'); %! f2 = 2*f; %! assert( isequal (f2(4), 32)) %! assert( isa(f2, 'symfun')) %! assert( isa(2*g, 'symfun')) %! assert( isa(0*g, 'symfun')) % in SMT, this is the zero symfun %!test %! % syms has its own parsing code, check it works %! syms f(x,y) %! g = f; %! syms f(x, y) %! assert (isequal (f, g)) %! syms 'f( x, y )' %! assert (isequal (f, g)) %!test %! % syms own parsing code should not reorder the vars %! syms f(y, x) %! v = argnames (f); %! assert (isequal (v(1), y) && isequal (v(2), x)) %!test %! % assignment of symfun to symfun, issue #189 %! syms t %! x(t) = 2*t; %! y(t) = x; %! assert (isa (y, 'symfun')) %! y = symfun(x, t); %! assert (isa (y, 'symfun')) %! % others %! y = x; %! assert (isa (y, 'symfun')) %! y(t) = x(t); %! assert (isa (y, 'symfun')) %!test %! % assignment of generic symfun to symfun %! syms t x(t) %! y(t) = x; %! assert (isa (y, 'symfun')) %! y = symfun(x, t); %! assert (isa (y, 'symfun')) %!error %! % Issue #444: invalid args %! syms x %! f(x, x) = 2*x; %!error %! % Issue #444: invalid args %! syms x y %! f(x, y, x) = x + y; %!error %! % Issue #444: invalid args %! syms x y %! f(x, y, x) = x + y; %!error %! % Issue #444: expression as arg %! syms x %! f(2*x) = 4*x; symbolic-3.1.1/inst/@symfun/symvar.m0000644000000000000000000001240514405647405014333 0ustar %% Copyright (C) 2014-2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defmethod @@symfun symvar (@var{f}) %% @defmethodx @@symfun symvar (@var{f}, @var{n}) %% Find symbols in symfun and return them as a symbolic vector. %% %% If @var{n} specified, we take from the explicit function variables %% first followed by the output of @code{symvar} on any other symbols %% in the sym (expression) of the symfun. %% %% Example: %% @example %% @group %% syms a x f(t, s) %% symvar (f, 1) %% @result{} (sym) t %% symvar (f, 2) %% @result{} (sym) [t s] (1×2 matrix) %% @end group %% @end example %% Note preference for the arguments of the symfun: %% @example %% @group %% h = f*a + x %% @result{} h(t, s) = (symfun) a⋅f(t, s) + x %% symvar (h, 1) %% @result{} (sym) t %% symvar (h, 2) %% @result{} (sym) [t s] (1×2 matrix) %% symvar (h, 3) %% @result{} (sym) [t s x] (1×3 matrix) %% symvar (h, 4) %% @result{} (sym) [t s x a] (1×4 matrix) %% @end group %% @end example %% %% On the other hand, if @var{n} is omitted, the results are %% sorted as explained elsewhere (@pxref{@@sym/symvar}). %% For example: %% @example %% @group %% symvar (f, 2) %% @result{} (sym) [t s] (1×2 matrix) %% symvar (f) %% @result{} (sym) [s t] (1×2 matrix) %% symvar (h) %% @result{} (sym) [a s t x] (1×4 matrix) %% @end group %% @end example %% %% @strong{Compatibility with other implementations}: the output generally %% matches the equivalent command in the Matlab Symbolic Toolbox %% (tested with version 2014a). For example: %% @example %% @group %% syms x y s t %% f(t, s) = 1 %% @result{} f(t, s) = (symfun) 1 %% symvar (f, 1) %% @result{} (sym) t %% symvar (f, 2) %% @result{} (sym) [t s] (1×2 matrix) %% @end group %% @end example %% However, when the symfun formula does not depend on the %% arguments, the results are not the same: %% @example %% @group %% symvar (f) % SMT would give [] %% @result{} (sym) [s t] (1×2 matrix) %% @end group %% @end example %% %% If two variables have the same symbol but different assumptions, %% they will both appear in the output. It is not well-defined %% in what order they appear. %% %% @seealso{findsymbols, @@symfun/argnames, @@symfun/formula} %% @end defmethod function vars = symvar(F, Nout) if (nargin == 1) % Note: symvar(symfun) differs from SMT, see test below tmp = formula (F); vars = symvar([argnames(F) tmp(:)]); else assert(Nout >= 0, 'number of requested symbols should be positive') % take first few from the arguments of the symfun vars = argnames (F); M = length(vars); if (Nout <= M) vars = vars(1:Nout); return end symvars = symvar (formula (F), inf); symvars = remove_dupes(symvars, vars); vars = [vars symvars(1:min(end, Nout-M))]; end end function a = remove_dupes(symvars, vars) M = length(vars); % ones(1, 3, 'logical') doesn't work in Matlab keep = logical(ones(1, length(symvars))); for j = 1:length(symvars) for i = 1:M if (strcmp (sympy (symvars(j)), sympy (vars(i)))) keep(j) = false; break end end end a = symvars(keep); end %!test %! % basic %! syms f(t, s) %! assert (isempty (symvar (f, 0))) %! assert (isequal (symvar (f, 1), t)) %! assert (isequal (symvar (f, 2), [t s])) %! assert (isequal (symvar (f, 3), [t s])) %!test %! % note preference for vars of symfun, if n requested %! syms x f(y) %! assert (isequal (symvar(f*x, 1), y)) %! assert (isequal (symvar(f(y)*x, 1), x)) %!test %! % symfun, checked smt %! syms x f(y) %! a = f*x; %! b = f(y)*x; %! assert (isequal (symvar(a), [x y])) %! assert (isequal (symvar(b), [x y])) %!test %! % preference for the explicit variables %! syms a x f(t, s) %! h = f*a + x; %! assert (isequal (symvar (h, 1), t)) %! assert (isequal (symvar (h, 2), [t s])) %! assert (isequal (symvar (h, 3), [t s x])) %! assert (isequal (symvar (h, 4), [t s x a])) %! assert (isequal (symvar (h, 5), [t s x a])) %! assert (isequal (symvar (h), [a s t x])) %!test %! % symfun dep on some vars only, matches smt w/ n %! syms x s t %! f(s) = x; %! g(s, t) = x*s; %! assert (isequal (symvar(f, 1), s)) %! assert (isequal (symvar(f, 2), [s x])) %! assert (isequal (symvar(g, 1), s)) %! assert (isequal (symvar(g, 2), [s t])) %! assert (isequal (symvar(g, 3), [s t x])) %!test %! % A documented difference from SMT on symvar(symfun) w/o n %! syms x s t %! f(s) = x; %! g(s, t) = x*s; %! % SMT would have %! %assert (isequal (symvar(f), x)) % no s %! %assert (isequal (symvar(g), [s x])) % no t %! assert (isequal (symvar(f), [s x])) %! assert (isequal (symvar(g), [s t x])) symbolic-3.1.1/inst/@symfun/times.m0000644000000000000000000000314014405647405014127 0ustar %% Copyright (C) 2014, 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@symfun times {(@var{f}, @var{g})} %% @defopx Operator @@symfun {@var{f} .* @var{g}} {} %% Symbolic function component-wise multiplication. %% %% Example: %% @example %% @group %% syms x y %% f(x, y) = sym([1 2; 3 4]); %% g(x, y) = [x 0; 2 y]; %% @end group %% %% @group %% h = f .* g %% @result{} h(x, y) = (symfun) %% ⎡x 0 ⎤ %% ⎢ ⎥ %% ⎣6 4⋅y⎦ %% @end group %% @end example %% %% @seealso{@@symfun/mtimes} %% @end defop function h = times(f, g) [vars, s1, s2] = helper_symfun_binops(f, g); h = symfun(s1 .* s2, vars); end %!test %! syms x %! f(x) = x^2; %! assert( isa(f .* f, 'symfun')) %! assert( isa(f .* x, 'symfun')) %!test %! syms x %! f(x) = [x 2*x]; %! h = f.*[x 3]; %! assert( isa(h, 'symfun')) %! assert (isequal (formula (h), [x^2 6*x])) symbolic-3.1.1/inst/@symfun/uminus.m0000644000000000000000000000246514405647405014337 0ustar %% Copyright (C) 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defop Method @@symfun uminus {(@var{f})} %% @defopx Operator @@symfun {-@var{f}} {} %% Return the negation of a symbolic function. %% %% Example: %% @example %% @group %% syms x %% f(x) = 2*x; %% h = -f %% @result{} h(x) = (symfun) -2⋅x %% @end group %% @end example %% %% @seealso{@@symfun/minus} %% @end defop function h = uminus(f) h = symfun(-formula(f), f.vars); end %!test %! % Issue #447 %! syms x %! f(x) = x^2; %! assert (isa (-f, 'symfun')) %!test %! syms f(x) %! h = -f; %! assert (isa (h, 'symfun')) symbolic-3.1.1/inst/assume.m0000644000000000000000000001442714405647405012674 0ustar %% Copyright (C) 2017, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deffn Command assume {@var{x} @var{cond}} %% @deffnx Command assume {@var{x} @var{cond} @var{cond2} @dots{}} %% @deffnx Command assume {@var{x} @var{y} @dots{} @var{cond} @var{cond2} @dots{}} %% Specify assumptions for a symbolic variable (replace existing). %% %% Example: %% @example %% @group %% syms n x y %% assume n integer %% assume x y real %% assumptions %% @result{} ans = %% @{ %% [1,1] = n: integer %% [1,2] = x: real %% [1,3] = y: real %% @} %% @end group %% @end example %% %% To clear assumptions on a variable, use @code{assume x clear}, for example: %% @example %% @group %% assume x y clear %% assumptions %% @result{} ans = %% @{ %% [1,1] = n: integer %% @} %% @end group %% @end example %% %% For more precise control over assumptions, @pxref{@@sym/assume} %% and @pxref{@@sym/assumeAlso}. %% %% @seealso{@@sym/assume, @@sym/assumeAlso, assumptions, sym, syms} %% @end deffn function varargout = assume(varargin) assert (nargout == 0, 'assume: use functional form if you want output'); assert (nargin > 1, 'assume: general algebraic assumptions are not supported'); %% Find symbol/assumptions boundary and verify input valid_asm = assumptions ('possible'); lastvar = -1; for n = 1:nargin assert (ischar (varargin{n}), 'assume: command form expects string inputs only') if (ismember (varargin{n}, valid_asm)) if (lastvar < 0) lastvar = n - 1; end elseif (strcmp (varargin{n}, 'clear')) assert (n == nargin, 'assume: "clear" should be the final argument') assert (lastvar < 0, 'assume: should not combine "clear" with other assumptions') lastvar = n - 1; elseif (lastvar > 0) error('assume: cannot have symbols after assumptions') else assert (isvarname (varargin{n}), 'assume: only symbols can have assumptions') end end if (lastvar < 0) error ('assume: no assumptions were given') end if (lastvar == 0) error ('assume: cannot have only assumptions w/o symbols') end asm = varargin((lastvar+1):end); vars = varargin(1:lastvar); %% loop over each variable for n = 1:length (vars) vals = evalin ('caller', vars{n}); newvals = cell(1, numel (vals)); [newvals{:}] = assume (vals, asm{:}); for i = 1:length (newvals) newx = newvals{i}; xstr = newx.flat; % --------------------------------------------- % Muck around in the caller's namespace, replacing syms % that match 'xstr' (a string) with the 'newx' sym. context = 'caller'; % --------------------------------------------- S = evalin(context, 'whos'); evalin(context, '[];'); % clear 'ans' for i = 1:numel(S) obj = evalin(context, S(i).name); [newobj, flag] = symreplace(obj, xstr, newx); if flag, assignin(context, S(i).name, newobj); end end % --------------------------------------------- end end end %!error %! a = assume('a', 'real') %!error %! assume positive integer %!error %! assume x y %!error %! assume x clear real %!error %! assume a>0 %!error %! assume 'x/pi' integer %!test %! syms x %! assume x positive %! a = assumptions(x); %! assert(strcmp(a, 'x: positive')) %! assume x even %! a = assumptions(x); %! assert(strcmp(a, 'x: even')) %!test %! % multiple assumptions %! syms x %! assume x positive integer %! [tilde, a] = assumptions(x, 'dict'); %! assert(a{1}.integer) %! assert(a{1}.positive) %!test %! % does workspace %! syms x positive %! x2 = x; %! f = sin(x); %! assume x negative %! a = assumptions(x); %! assert(strcmp(a, 'x: negative')) %! a = assumptions(x2); %! assert(strcmp(a, 'x: negative')) %! a = assumptions(f); %! assert(strcmp(a, 'x: negative')) %!error %! % does not create new variable x %! clear x %! assume x real %!error %! % no explicit variable named x %! clear x %! f = 2*sym('x'); %! assume x real %!test %! % clear does workspace %! syms x positive %! f = 2*x; %! assume x clear %! assert (isempty (assumptions (f))); %! assert (isempty (assumptions ())); %!test %! syms x y %! f = sin (2*x); %! assume x y real %! assert (strcmp (assumptions (x), 'x: real')) %! assert (strcmp (assumptions (y), 'y: real')) %! assert (strcmp (assumptions (f), 'x: real')) %!test %! syms x y %! f = sin (2*x); %! assume x y positive even %! assert (strcmp (assumptions (x), 'x: positive, even') || strcmp (assumptions (x), 'x: even, positive')) %! assert (strcmp (assumptions (y), 'y: positive, even') || strcmp (assumptions (y), 'y: even, positive')) %! assert (strcmp (assumptions (f), 'x: positive, even') || strcmp (assumptions (f), 'x: even, positive')) %!test %! % works from variable names not symbols %! syms x y %! a = [x y]; %! assume a real %! assert (strcmp (assumptions (x), 'x: real')) %! assert (strcmp (assumptions (y), 'y: real')) %!test %! % works from variable names not symbols %! y = sym('x'); %! f = 2*y; %! assume y real %! assert (strcmp (assumptions (f), 'x: real')) %!test %! % matrix of symbols %! syms a b c d %! A = [a b; c d]; %! assume A real %! assert (strcmp (assumptions (a), 'a: real')) %! assert (strcmp (assumptions (b), 'b: real')) %! assert (strcmp (assumptions (c), 'c: real')) %! assert (strcmp (assumptions (d), 'd: real')) %!test %! % assume after symfun %! clear x %! syms f(x) %! assume x real %! assert (~ isempty (assumptions (formula (f)))) %! assert (~ isempty (assumptions (argnames (f)))) symbolic-3.1.1/inst/assumptions.m0000644000000000000000000001420714405647405013760 0ustar %% Copyright (C) 2014-2016, 2019, 2023 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypefun {@var{A} =} assumptions () %% @deftypefunx {@var{A} =} assumptions (@var{x}) %% @deftypefunx {[@var{v}, @var{d}] =} assumptions (@var{x}, 'dict') %% @deftypefunx {@var{L} =} assumptions ('possible') %% List assumptions on symbolic variables. %% %% The assumptions are returned as a cell-array of strings: %% @example %% @group %% syms x y positive %% syms n integer %% assumptions %% @result{} ans = %% @{ %% [1,1] = n: integer %% [1,2] = x: positive %% [1,3] = y: positive %% @} %% assumptions(n) %% @result{} ans = %% @{ %% [1,1] = n: integer %% @} %% @end group %% @end example %% %% You can get the list of assumptions relevant to an expression: %% @example %% @group %% f = sin(n*x); %% assumptions(f) %% @result{} ans = %% @{ %% [1,1] = n: integer %% [1,2] = x: positive %% @} %% @end group %% @end example %% %% With the optional second argument set to the string @code{'dict'}, %% return the assumption dictionaries in @var{d} corresponding %% to the variables in @var{v}. %% %% You can also get a list of possible assumptions: %% @example %% @group %% A = assumptions('possible'); %% strjoin(sort(A), ', ') %% @result{} ans = ..., finite, ..., positive, ..., zero %% @end group %% @end example %% %% @seealso{sym, syms, @@sym/assume, @@sym/assumeAlso} %% @end deftypefun %% Author: Colin B. Macdonald %% Keywords: symbolic function [A, B] = assumptions(F, outp) if ((nargin == 1) && ischar(F) && strcmp(F, 'possible')) A = valid_sym_assumptions(); return end if ((nargin == 0) || isempty(F)) find_all_free_symbols = true; else find_all_free_symbols = false; end if (nargin <= 1) outp = 'no'; end if (find_all_free_symbols) %% no input arguments % find all syms, check each for free symbols workspace = {}; context = 'caller'; S = evalin(context, 'whos'); evalin(context, '[];'); % clear 'ans' for i = 1:numel(S) workspace{i} = evalin(context, S(i).name); end F = findsymbols(workspace); end cmd = { 'x = _ins[0]' 'outputdict = _ins[1]' 'if Version(spver) > Version("1.11.1"):' ' d = x._assumptions_orig' 'else:' ' d = x._assumptions.generator' 'astr = ", ".join(sorted([("" if v else "~") + str(k) for (k,v) in d.items()]))' 'if outputdict:' ' return (astr, d)' 'return astr,' }; c = 0; A = {}; if strcmp(outp, 'dict') B = {}; end if (isempty(F)) return end s = findsymbols(F); for i=1:length(s) x = s{i}; if strcmp(outp, 'dict') [astr, adict] = pycall_sympy__ (cmd, x, true); if ~isempty(astr) c = c + 1; A{c} = x; B{c} = adict; end else astr = pycall_sympy__ (cmd, x, false); if ~isempty(astr) c = c + 1; str = [x.flat ': ' astr]; A{c} = str; %if c == 1 % A = str; %elseif c == 2 % A = {A str}; %else % A{c} = str; %end end end end end %!test %! syms x %! assert(isempty(assumptions(x))) %!test %! x = sym('x', 'positive'); %! a = assumptions(x); %! assert(~isempty(strfind(a{1}, 'positive'))) %!test %! syms x %! assert(isempty(assumptions(x))) %!test %! clear variables % for matlab test script %! syms x positive %! assert(~isempty(assumptions())) %! clear x %! assert(isempty(assumptions())) %!test %! % make sure we have at least these possible assumptions %! A = {'real' 'positive' 'negative' 'integer' 'even' 'odd' 'rational'}; %! B = assumptions('possible'); %! assert (isempty (setdiff(A, B))) %!test %! A = assumptions('possible'); %! for i = 1:length(A) %! x = sym('x', A{i}); %! a = assumptions(x); %! assert(strcmp(a{1}, ['x: ' A{i}] )) %! s1 = sympy (x); %! s2 = ['Symbol(''x'', ' A{i} '=True)']; %! assert (strcmp (s1, s2)) %! end %!test %! syms x positive %! syms y real %! syms z %! f = x*y*z; %! a = assumptions(f); %! assert(length(a) == 2) %! assert(~isempty(strfind(a{1}, 'positive'))) %! assert(~isempty(strfind(a{2}, 'real'))) %!test %! % dict output %! syms x positive %! syms y real %! syms z %! f = x*y*z; %! [v, d] = assumptions(f, 'dict'); %! assert(length(v) == 2) %! assert(iscell(v)) %! assert(isa(v{1}, 'sym')) %! assert(isa(v{2}, 'sym')) %! assert(length(d) == 2) %! assert(iscell(d)) %! assert(isstruct(d{1})) %! assert(isstruct(d{2})) %!test %! %% assumptions on just the vars in an expression %! clear variables % for matlab test script %! syms x y positive %! f = 2*x; %! assert(length(assumptions(f))==1) %! assert(length(assumptions())==2) %!test %! %% assumptions in cell/struct %! clear variables % for matlab test script %! syms x y z w positive %! f = {2*x [1 2 y] {1, {z}}}; %! assert(length(assumptions())==4) %! assert(length(assumptions(f))==3) %! clear x y z w %! assert(length(assumptions())==3) %! assert(length(assumptions(f))==3) %!test %! % multiple assumptions %! n = sym('n', 'negative', 'even'); %! assert (logical (n < 0)) %! assert (~(logical (n > 0))) %! assert (~(logical (n == -1))) %!test %! % multiple assumptions: eqn neither true nor false %! n = sym('n', 'negative', 'even'); %! assert (~isequal (n, sym(true)) && ~isequal (n, sym(false))) %!test %! %% TODO: rewrite later with https://github.com/cbm755/octsympy/issues/622 %! a = pycall_sympy__ ('return Symbol("a", real=False)'); %! assert (strcmp (assumptions (a), {'a: ~real'})) symbolic-3.1.1/inst/catalan.m0000644000000000000000000000301514405647405012771 0ustar %% Copyright (C) 2015 Carnë Draug %% Copyright (C) 2016, 2018-2019, 2022 Colin B. Macdonald %% Copyright (C) 2022 Chris Gorman %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deffn Constant catalan () %% Return Catalan constant. %% %% @example %% @group %% @c doctest: +SKIP_UNLESS(pycall_sympy__ ('return Version(spver) >= Version("1.10")')) %% catalan () %% @result{} (sym) G %% %% vpa (catalan ()) %% @result{} (sym) 0.91596559417721901505460351493238 %% @end group %% @end example %% %% @seealso{eulergamma} %% @end deffn %% Author: Carnë Draug %% Keywords: symbolic, constants function g = catalan () if (nargin ~= 0) print_usage (); end g = pycall_sympy__ ('return sympy.S.Catalan,'); end %!error catalan (sym(1)) %!assert (double (catalan ()) > 0.915965594177) %!assert (double (catalan ()) < 0.915965594178) symbolic-3.1.1/inst/cell2sym.m0000644000000000000000000000334614405647405013127 0ustar %% Copyright (C) 2016 Lagu %% Copyright (C) 2017 Colin B. Macdonald %% %% 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, or (at your option) any later version. %% %% This software 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 software; see the file COPYING. If not, %% see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defun @@sym cell2sym (@var{x}) %% Convert cell array to symbolic array. %% %% Examples: %% @example %% @group %% cell2sym(@{'x', 'y'@}) %% @result{} ans = (sym) [x y] (1×2 matrix) %% @end group %% @end example %% %% @example %% @group %% cell2sym(@{'x', 2; pi 'y'@}) %% @result{} ans = (sym 2×2 matrix) %% ⎡x 2⎤ %% ⎢ ⎥ %% ⎣π y⎦ %% @end group %% @end example %% @seealso{sym, syms} %% @end defun function c = cell2sym(p) if (nargin < 1 || nargin > 2) print_usage (); elseif (nargin == 2) error('Flag not supported yet'); end s = size(p); c = sym([]); %% FIXME: Don't support multi-dimensional yet. assert (length (s) == 2) for i=1:s(1) for j=1:s(2) c(i, j) = p{i, j}; end end end %!test %! A = {1 2 3; 4 5 6}; %! B = [1 2 3; 4 5 6]; %! assert (isequal (cell2sym(A), sym(B))) %!test %! A = {'a' 'b'; 'c' 10}; %! B = [sym('a') sym('b'); sym('c') sym(10)]; %! assert (isequal (cell2sym(A), B)) symbolic-3.1.1/inst/digits.m0000644000000000000000000000356114405647405012657 0ustar %% Copyright (C) 2014, 2015 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypefn {Command} {} digits @var{n} %% @deftypefnx {Function} {} digits (@var{n}) %% @deftypefnx {Function} {@var{n} =} digits () %% @deftypefnx {Function} {@var{oldn} =} digits (@var{n}) %% Set/get number of digits used in variable precision arith. %% %% Examples: %% @example %% @group %% n_orig = digits(7); %% vpa('pi') %% @result{} (sym) 3.141593 %% %% digits(42) %% vpa('pi') %% @result{} (sym) 3.14159265358979323846264338327950288419717 %% %% digits(n_orig) % reset digits to saved value %% @end group %% @end example %% @seealso{sym, vpa, vpasolve} %% @end deftypefn function m = digits(n) if (~ ((nargin == 0) || (nargin == 1))) print_usage (); end if (nargin == 0) || (nargout == 1) m = sympref('digits'); end if (nargin == 1) sympref('digits', n); end end %!test %! orig = digits(32); % to reset later %! m = digits(64); %! p = vpa(sym(pi)); %! assert (abs (double (sin(p))) < 1e-64) %! n = digits(m); %! assert (n == 64) %! p = vpa(sym(pi)); %! assert (abs (double (sin(p))) < 1e-32) %! assert (abs (double (sin(p))) > 1e-40) %! digits(orig) symbolic-3.1.1/inst/dirac.m0000644000000000000000000000340014405647405012446 0ustar %% Copyright (C) 2006 Sylvain Pelissier %% Copyright (C) 2015-2016 Colin B. Macdonald %% %% 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 -*- %% @documentencoding UTF-8 %% @defun dirac (@var{x}) %% Compute the Dirac delta (generalized) function. %% %% The Dirac delta ``function'' is a generalized function (or distribution) %% which is zero almost everywhere, except at the origin where it is %% infinite. %% %% Examples: %% @example %% @group %% dirac (0) %% @result{} Inf %% dirac (1) %% @result{} 0 %% dirac ([-10 -1 0 1 inf]) %% @result{} 0 0 Inf 0 0 %% @end group %% @end example %% @seealso{heaviside, @@sym/dirac} %% @end defun function y = dirac(x) if (nargin ~= 1) print_usage (); end if (~isreal (x)) error ('dirac: X must not contain complex values'); end y = zeros (size (x), class (x)); y(x == 0) = Inf; y(isnan (x)) = NaN; end %!assert (isinf (dirac (0))) %!assert (dirac (1) == 0) %!assert (isnan (dirac (nan))) %!assert (isequaln (dirac ([-1 1 0 eps inf -inf nan]), [0 0 inf 0 0 0 nan])) %!error dirac (1i) %!assert (isa (dirac (single (0)), 'single')) symbolic-3.1.1/inst/eulergamma.m0000644000000000000000000000265314405647405013514 0ustar %% Copyright (C) 2015 Carnë Draug %% Copyright (C) 2016, 2018-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deffn Constant eulergamma () %% Return Euler--Mascheroni constant. %% %% @example %% @group %% eulergamma %% @result{} (sym) γ %% %% vpa (eulergamma ()) %% @result{} (sym) 0.57721566490153286060651209008240 %% @end group %% @end example %% %% @seealso{catalan} %% @end deffn %% Author: Carnë Draug %% Keywords: symbolic, constants function g = eulergamma () if (nargin ~= 0) print_usage (); end g = pycall_sympy__ ('return sympy.S.EulerGamma,'); end %!error catalan (sym(1)) %!assert (double (eulergamma ()) > 0.577215664901) %!assert (double (eulergamma ()) < 0.577215664902) symbolic-3.1.1/inst/fibonacci.m0000644000000000000000000000356614405647405013316 0ustar %% Copyright (C) 2014, 2016, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @documentencoding UTF-8 %% @deftypefun {@var{F} =} fibonacci (@var{n}) %% @deftypefunx {@var{p} =} fibonacci (@var{n}, @var{x}) %% Return symbolic Fibonacci numbers or Fibonacci polynomials. %% %% Examples: %% @example %% @group %% fibonacci(15) %% @result{} (sym) 610 %% syms n %% fibonacci(n) %% @result{} (sym) %% F %% n %% @end group %% @end example %% %% Polynomial example: %% @example %% @group %% syms x %% fibonacci(10, x) %% @result{} (sym) %% 9 7 5 3 %% x + 8⋅x + 21⋅x + 20⋅x + 5⋅x %% @end group %% @end example %% %% @seealso{euler, bernoulli} %% @end deftypefun function r = fibonacci(n, x) if (nargin == 1) r = pycall_sympy__ ('return sp.fibonacci(*_ins),', sym(n)); elseif (nargin == 2) r = pycall_sympy__ ('return sp.fibonacci(*_ins),', sym(n), sym(x)); else print_usage (); end end %!assert (isequal ( fibonacci (sym(0)), 0)) %!assert (isequal ( fibonacci (sym(14)), sym(377))) %!assert (isequal ( fibonacci (14), 377)) %!test syms x %! assert (isequal (fibonacci (5,x), x^4 + 3*x^2 + 1)) symbolic-3.1.1/inst/findsymbols.m0000644000000000000000000001171214405647405013722 0ustar %% Copyright (C) 2014, 2016, 2018-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defun findsymbols (@var{x}) %% Return a list (cell array) of the symbols in an expression. %% %% The list is sorted alphabetically. For details, @pxref{@@sym/symvar}. %% %% If two variables have the same symbol but different assumptions, %% they will both appear in the output. It is not well-defined %% in what order they appear. %% %% @var{x} could be a sym, sym array, cell array, or struct. %% %% @example %% @group %% syms x y z %% C = @{x, 2*x*y, [1 x; sin(z) pi]@}; %% S = findsymbols (C) %% @result{} S = @{ ... @} %% S@{:@} %% @result{} ans = (sym) x %% @result{} ans = (sym) y %% @result{} ans = (sym) z %% @end group %% @end example %% %% Note ℯ, ⅈ, π, etc are not considered as symbols. %% %% Note only returns symbols actually appearing in the RHS of a %% @code{symfun}. %% %% @seealso{symvar, @@sym/symvar, @@sym/findsym} %% @end defun function L = findsymbols(obj, dosort) if (nargin == 1) dosort = true; elseif (nargin ~= 2) print_usage (); end if isa(obj, 'sym') cmd = { 'if isinstance(_ins[0], MatrixBase):' ' # having problems with Eq in matrices in SymPy >= 1.7.1' ' s = set().union(*(i.free_symbols for i in _ins[0] if i is not None))' 'else:' ' s = _ins[0].free_symbols' 'l = list(s)' 'l = sorted(l, key=str)' 'return l,' }; L = pycall_sympy__ (cmd, obj); elseif iscell(obj) %fprintf('Recursing into a cell array of numel=%d\n', numel(obj)) L = {}; for i=1:numel(obj) temp = findsymbols(obj{i}, false); if ~isempty(temp) L = {L{:} temp{:}}; end end elseif isstruct(obj) %fprintf('Recursing into a struct array of numel=%d\n', numel(obj)) L = {}; fields = fieldnames(obj); for i=1:numel(obj) for j=1:length(fields) thisobj = getfield(obj, {i}, fields{j}); temp = findsymbols(thisobj, false); if ~isempty(temp) L = {L{:} temp{:}}; end end end else L = {}; end % sort and make unique using internal representation if dosort Ls = {}; for i=1:length(L) Ls{i} = sympy (L{i}); end [tilde, I] = unique(Ls); L = L(I); end end %!test %! syms x b y n a arlo %! z = a*x + b*pi*sin (n) + exp (y) + exp (sym (1)) + arlo; %! s = findsymbols (z); %! assert (isequal ([s{:}], [a,arlo,b,n,x,y])) %!test %! syms x %! s = findsymbols (x); %! assert (isequal (s{1}, x)) %!test %! syms z x y a %! s = findsymbols ([x y; 1 a]); %! assert (isequal ([s{:}], [a x y])) %!assert (isempty (findsymbols (sym (1)))) %!assert (isempty (findsymbols (sym ([1 2])))) %!assert (isempty (findsymbols (sym (nan)))) %!assert (isempty (findsymbols (sym (inf)))) %!assert (isempty (findsymbols (exp (sym (2))))) %!test %! % empty sym for findsymbols, findsym, and symvar %! assert (isempty (findsymbols (sym([])))) %! assert (isempty (findsym (sym([])))) %! assert (isempty (symvar (sym([])))) %!test %! % diff. assumptions make diff. symbols %! x1 = sym('x'); %! x2 = sym('x', 'positive'); %! f = x1*x2; %! assert (length (findsymbols (f)) == 2) %!test %! % symfun or sym %! syms x f(y) %! a = f*x; %! b = f(y)*x; %! assert (isequal (findsymbols(a), {x y})) %! assert (isequal (findsymbols(b), {x y})) %!test %! % findsymbols on symfun does not find the argnames (unless they %! % are on the RHS of course, this matches SMT 2014a). %! syms a x y %! f(x, y) = a; % const symfun %! assert (isequal (findsymbols(f), {a})) %! syms a x y %! f(x, y) = a*y; %! assert (isequal (findsymbols(f), {a y})) %!test %! % sorts lexigraphically, same as symvar *with single input* %! % (note symvar does something different with 2 inputs). %! syms A B a b x y X Y %! f = A*a*B*b*y*X*Y*x; %! assert (isequal (findsymbols(f), {A B X Y a b x y})) %! assert (isequal (symvar(f), [A B X Y a b x y])) %!test %! % symbols in matpow %! syms x y %! syms n %! A = [sin(x) 2; y 1]; %! B = A^n; %! L = findsymbols(B); %! assert (isequal (L, {n x y})) %!test %! % array of eq %! syms x y %! assert (isequal (findsymbols (2 == [2 x y]), {x y})) %!test %! % array of ineq %! syms x y %! A = [x < 1 2*x < y x >= 2 3 <= x x != y]; %! assert (isequal (findsymbols (A), {x y})) symbolic-3.1.1/inst/finiteset.m0000644000000000000000000000773214405647405013372 0ustar %% Copyright (C) 2016-2017, 2019, 2023 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypefun {@var{S} =} finiteset (@var{a}, @var{b}, @dots{}) %% @deftypefunx {@var{S} =} finiteset (@var{cellarray}) %% @deftypefunx {@var{emptyset} =} finiteset () %% Return a symbolic set containing the inputs without duplicates. %% %% Example: %% @example %% @group %% syms x y %% S = finiteset(1, pi, x, 1, 1, x, x + y) %% @result{} S = (sym) @{1, π, x, x + y@} %% subs(S, x, pi) %% @result{} ans = (sym) @{1, π, y + π@} %% @end group %% @end example %% %% You can also use this to make the empty set: %% @example %% @group %% finiteset() %% @result{} ans = (sym) ∅ %% @end group %% @end example %% %% You cannot directly access elements of a set using indexing: %% @example %% @group %% S(2) %% @print{} ??? 2 is out of bound ... %% @end group %% @end example %% Instead you can first convert it to a cell (@pxref{@@sym/children}): %% @example %% @group %% elements = children(S) %% @result{} elements = (sym) [1 π x x + y] (1×4 matrix) %% elements(end) %% @result{} ans = (sym) x + y %% @end group %% @end example %% %% Careful, passing a matrix creates a set of matrices (rather than a %% set from the elements of the matrix): %% @example %% @group %% finiteset([1 x 1 1]) %% @result{} ans = (sym) @{[1 x 1 1]@} %% finiteset([1 pi], [1 x 1 1], [1 pi]) %% @result{} ans = (sym) @{[1 π], [1 x 1 1]@} %% @end group %% @end example %% %% On the other hand, if you @emph{want} to make a set from the %% elements of a matrix, first convert it to a cell array: %% @example %% @group %% A = [1 x 1; 2 1 x]; %% finiteset(num2cell(A)) %% @result{} ans = (sym) @{1, 2, x@} %% @end group %% @end example %% %% Sets can be nested: %% @example %% @group %% finiteset(finiteset(), finiteset(finiteset())) %% @result{} (sym) @{∅, @{∅@}@} %% @end group %% @end example %% %% @strong{Note} that cell arrays are @emph{not} the same thing as %% sets (despite the similar rendering using @code{@{} and @code{@}}). %% For example, this creates a set containing a set: %% @example %% @group %% finiteset(finiteset(1, 2, 3, 3)) %% @result{} ans = (sym) @{@{1, 2, 3@}@} %% @end group %% @end example %% whereas passing a single cell array @var{cellarray} creates a set %% containing each element of @var{cellarray}: %% @example %% @group %% finiteset(@{1, 2, 3, 3@}) %% @result{} ans = (sym) @{1, 2, 3@} %% @end group %% @end example %% (This is implemented mainly to enable the @code{num2cell} example %% above.) %% %% @seealso{@@sym/interval, @@sym/ismember, @@sym/children, @@sym/union, %% @@sym/intersect, @@sym/setdiff, @@sym/setxor} %% @end deftypefun function S = finiteset(varargin) % special case if (nargin == 1 && iscell(varargin{1})) varargin = varargin{1}; nargin == numel (varargin); end for i = 1:numel(varargin) varargin{i} = sym(varargin{i}); end S = pycall_sympy__ ('return FiniteSet(*_ins),', varargin{:}); end %!test %! s1 = finiteset(sym(1), 2, 2); %! s2 = finiteset(sym(1), 2, 2, 2); %! assert (isequal (s1, s2)) %!test %! s1 = finiteset(sym(0), 1); %! s2 = finiteset(sym(0), 2, 3); %! s = finiteset(sym(0), 1, 2, 3); %! assert (isequal (s1 + s2, s)) %!test %! e = finiteset(); %! s = finiteset(sym(1)); %! s2 = e + s; %! assert (isequal (s, s2)) symbolic-3.1.1/inst/heaviside.m0000644000000000000000000000450014405647405013327 0ustar %% Copyright (C) 2006 Sylvain Pelissier %% Copyright (C) 2015-2016, 2019, 2022 Colin B. Macdonald %% %% 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 -*- %% @documentencoding UTF-8 %% @defun heaviside (@var{x}) %% @defunx heaviside (@var{x}, @var{zero_value}) %% Compute the Heaviside unit-step function. %% %% The Heaviside function is 0 for negative @var{x} and 1 for %% positive @var{x}. %% %% Example: %% @example %% @group %% heaviside([-inf -3 -1 1 3 inf]) %% @result{} 0 0 0 1 1 1 %% @end group %% @end example %% %% There are various conventions for @code{heaviside(0)}; this %% function returns 0.5 by default: %% @example %% @group %% @c Would render with an extra zero on earlier Octave %% @c doctest: +SKIP_IF(compare_versions (OCTAVE_VERSION(), '6.0.0', '<')) %% heaviside(0) %% @result{} 0.5000 %% @end group %% @end example %% However, this can be changed via the optional second input %% argument: %% @example %% @group %% heaviside(0, 1) %% @result{} 1 %% @end group %% @end example %% @seealso{dirac, @@sym/heaviside} %% @end defun function y = heaviside (x, zero_value) if (nargin < 1 || nargin > 2) print_usage (); end if (nargin == 1) zero_value = 0.5; end if (~isreal (x)) error ('heaviside: X must not contain complex values'); end y = cast (x > 0, class (x)); y(x == 0) = zero_value; y(isnan (x)) = NaN; end %!assert (heaviside (0) == 0.5) %!assert (isnan (heaviside (nan))) %!assert (isequal (heaviside ([-inf -eps 0 eps inf]), [0 0 0.5 1 1])) %!assert (isequaln (heaviside ([-1 1 nan]), [0 1 nan])) %!assert (heaviside (0, 1) == 1) %!error heaviside (1i) %!assert (isa (heaviside (single (0)), 'single')) symbolic-3.1.1/inst/laguerreL.m0000644000000000000000000001123314405647405013311 0ustar %% Copyright (C) 2008 Eric Chassande-Mottin %% Copyright (C) 2011 Carnë Draug %% Copyright (C) 2016, 2018, 2022 Colin B. Macdonald %% %% 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 -*- %% @documentencoding UTF-8 %% @defun laguerreL (@var{n}, @var{x}) %% Evaluate Laguerre polynomials. %% %% Compute the value of the Laguerre polynomial of order @var{n} %% for each element of @var{x}. %% For example, the Laguerre polynomial of order 14 evaluated at %% the point 6 is %% @example %% @group %% @c doctest: +SKIP_IF(compare_versions (OCTAVE_VERSION(), '6.0.0', '<')) %% laguerreL (14, 6) %% @result{} 0.9765 %% @end group %% @end example %% %% This implementation uses a three-term recurrence directly on the values %% of @var{x}. The result is numerically stable, as opposed to evaluating %% the polynomial using the monomial coefficients. For example, we can %% compare the above result to a symbolic construction: %% @example %% @group %% syms x %% L = laguerreL (14, x); %% exact = subs (L, x, 6) %% @result{} exact = (sym) %% 34213 %% ───── %% 35035 %% @end group %% @end example %% If we extract the monomial coefficients and numerically evaluate the %% polynomial at a point, the result is rather poor: %% @example %% @group %% coeffs = sym2poly (L); %% @c doctest: +XFAIL_IF(compare_versions (OCTAVE_VERSION(), '6.0.0', '<')) %% polyval (coeffs, 6) %% @result{} 0.9765 %% err = ans - double (exact); %% num2str (err, '%.3g') %% @result{} -1.68e-11 %% @end group %% @end example %% So please don't do that! The numerical @code{laguerreL} function %% does much better: %% @example %% @group %% err = laguerreL (14, 6) - double (exact) %% @result{} err = 9.9920e-16 %% @end group %% @end example %% %% @seealso{@@sym/laguerreL} %% @end defun function L = laguerreL(n, x) if (nargin ~= 2) print_usage (); end if (any (n < 0) || any (mod (n, 1) ~= 0)) error('second argument "n" must consist of positive integers'); end if (~isscalar (n) && isscalar (x)) x = x*ones (size (n)); elseif (~isscalar (n) && ~isscalar (x) && ~isequal (size (n), size (x))) error ('inputs must be same size or scalar') end L0 = ones (size (x), class(x)); L1 = 1 - x; if (isscalar (n)) if (n == 0) L = L0; elseif (n == 1) L = L1; else for k = 2:n L = (2*k-1-x)/k .* L1 - (k-1)/k * L0; L0 = L1; L1 = L; end end else L = L0; L(n >= 1) = L1(n >= 1); maxn = max (n(:)); for k = 2:maxn I = (n >= k); % mask for entries still to be updated L(I) = (2*k - 1 - x(I))/k .* L1(I) - (k - 1)/k * L0(I); L0 = L1; L1 = L; end end end %!error laguerreL (1) %!error laguerreL (1, 2, 3) %!assert (isequal (laguerreL (0, rand), 1)) %!test %! x = rand; %! assert (isequal (laguerreL (1, x), 1 - x)) %!test %! x=rand; %! y1=laguerreL(2, x); %! p2=[.5 -2 1]; %! y2=polyval(p2,x); %! assert(y1 - y2, 0, 10*eps); %!test %! x=rand; %! y1=laguerreL(3, x); %! p3=[-1/6 9/6 -18/6 1]; %! y2=polyval(p3,x); %! assert(y1 - y2, 0, 20*eps); %!test %! x=rand; %! y1=laguerreL(4, x); %! p4=[1/24 -16/24 72/24 -96/24 1]; %! y2=polyval(p4,x); %! assert(y1 - y2, 0, 30*eps) %!error laguerreL(1.5, 10) %!error laguerreL([0 1], [1 2 3]) %!error laguerreL([0 1], [1; 2]) %!test %! % numerically stable implementation (in n) %! L = laguerreL (10, 10); %! Lex = 1763/63; %! assert (L, Lex, -eps) %! L = laguerreL (20, 10); %! Lex = -177616901779/14849255421; % e.g., laguerreL(sym(20),10) %! assert (L, Lex, -eps) %!test %! % vectorized x %! L = laguerreL (2, [5 6 7]); %! Lex = [3.5 7 11.5]; %! assert (L, Lex, eps) %!test %! L = laguerreL (0, [4 5]); %! assert (L, [1 1], eps) %!test %! % vector n %! L = laguerreL ([0 1 2 3], [4 5 6 9]); %! assert (L, [1 -4 7 -26], eps) %!test %! % vector n, scalar x %! L = laguerreL ([0 1 2 3], 6); %! assert (L, [1 -5 7 1], eps) %!assert (isa (laguerreL (0, single (1)), 'single')) %!assert (isa (laguerreL (1, single ([1 2])), 'single')) %!assert (isa (laguerreL ([1 2], single ([1 2])), 'single')) symbolic-3.1.1/inst/lambertw.m0000644000000000000000000001543314405647405013212 0ustar %% Copyright (C) 1998 Nicol N. Schraudolph %% Copyright (C) 2016 Colin B. Macdonald %% %% 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 -*- %% @documentencoding UTF-8 %% @defun lambertw (@var{z}) %% @defunx lambertw (@var{n}, @var{z}) %% Compute the Lambert W function of @var{z}. %% %% This function satisfies W(z).*exp(W(z)) = z, and can thus be used to express %% solutions of transcendental equations involving exponentials or logarithms. %% %% @var{n} must be integer, and specifies the branch of W to be computed; %% W(z) is a shorthand for W(0,z), the principal branch. Branches %% 0 and -1 are the only ones that can take on non-complex values. %% %% For example, the principal branch passes through the point (0, 0): %% @example %% @group %% lambertw (0) %% @result{} ans = 0 %% @end group %% @end example %% And the 0 and -1 branches coincide for the following real value: %% @example %% @group %% x = -1/exp (1); %% lambertw (x) %% @result{} ans = -1 %% lambertw (-1, x) %% @result{} ans = -1 %% @end group %% @end example %% %% If either @var{n} or @var{z} are non-scalar, the function is mapped to each %% element; both may be non-scalar provided their dimensions agree. %% For example, we can repeat the above calculation as: %% @example %% @group %% lambertw ([0 -1], x) %% @result{} ans = %% -1 -1 %% @end group %% @end example %% %% This implementation should return values within 2.5*eps of its %% counterpart in Maple V, release 3 or later. Please report any %% discrepancies to the author, Nici Schraudolph . %% %% For further algorithmic details, see: %% %% Corless, Gonnet, Hare, Jeffrey, and Knuth (1996), `On the Lambert %% W Function', Advances in Computational Mathematics 5(4):329-359. %% %% @seealso{@@sym/lambertw} %% @end defun function w = lambertw(b,z) if (nargin == 1) z = b; b = 0; else %% some error checking if (nargin ~= 2) print_usage (); else if (any(round(real(b)) ~= b)) error('branch number for lambertw must be integer') end end end %% series expansion about -1/e % % p = (1 - 2*abs(b)).*sqrt(2*e*z + 2); % w = (11/72)*p; % w = (w - 1/3).*p; % w = (w + 1).*p - 1 % % first-order version suffices: % w = (1 - 2*abs(b)).*sqrt(2*exp(1)*z + 2) - 1; %% asymptotic expansion at 0 and Inf % v = log(z + (z == 0 | b == 0)) + 2*pi*1i*b; v = v - log(v + (v == 0)); %% choose strategy for initial guess % c = abs(z + 1/exp(1)); c = (c > 1.45 - 1.1*abs(b)); c = c | (b.*imag(z) > 0) | (~imag(z) & (b == 1)); w = (1 - c).*w + c.*v; %% Halley iteration % for n = 1:10 p = exp(w); t = w.*p - z; f = (w ~= -1); t = f.*t./(p.*(w + f) - 0.5*(w + 2.0).*t./(w + f)); w = w - t; done = (abs (real (t)) < (2.48*eps)*(1.0 + abs (real (w))) & ... abs (imag (t)) < (2.48*eps)*(1.0 + abs (imag (w)))); if (all (done)) break end end % special treatment for infinity and nan isnaninf = (isinf (z) & isreal (z)) | isnan (z); % don't show the warning if we're going to overwrite that entry if (~ all (done | isnaninf)) warning ('iteration limit reached, result of lambertw may be inaccurate'); end if (any (isnaninf)) % broadcast z and b to same size if (isscalar (z) && ~isscalar (b)) z = repmat (z, size (b)); elseif (~isscalar (z) && isscalar (b)) b = repmat (b, size (z)); end w(isnan (z)) = nan; I = isinf (z) & isreal (z) & (z > 0); w(I) = inf + 2*b(I)*pi*1i; I = isinf (z) & isreal (z) & (z < 0); w(I) = inf + (2*b(I) + 1)*pi*1i; end end %!assert (isequal (lambertw (0), 0)) %!assert (isequal (lambertw (0, 0), 0)) %!assert (lambertw (-1/exp(1)), -1, 2*eps) %!assert (lambertw (0, -1/exp(1)), -1, 2*eps) %!assert (lambertw (-1, -1/exp(1)), -1, 2*eps) %!test %! x = [1 2 3 pi 10 100 1000 12345]; %! W = lambertw (x); %! assert (W.*exp (W), x, -3*eps) %!test %! x = [1 2 3 pi 10 100 1000 12345]; %! k = [-3 -2 -1 0 1 2 3 4]; %! W = lambertw (k, x); %! assert (W.*exp (W), x, -10*eps) %!test %! % input shape preserved %! x = [0 1; 2 3]; %! b = x; %! W = lambertw (b, x); %! assert (W.*exp (W), x, -10*eps) %!test %! % input shape preserved %! x = [0 1; 2 3]; %! b = 0; %! W = lambertw (b, x); %! assert (W.*exp (W), x, -10*eps) %!test %! % input shape preserved %! x = 10; %! b = [0 1; 2 3]; %! W = lambertw (b, x); %! assert (W.*exp (W), x*ones (size (b)), -10*eps) %!assert (isnan (lambertw (nan))) %!test %! % limiting behaviour as z large %! k = 3; %! A = lambertw (k, 1e100); %! assert (abs (imag (A) - 2*pi*k) < 0.1) %!test %! % limiting behaviour as z large, up imag axis %! k = 1; %! A = lambertw (k, 1e100*1i); %! assert (abs (imag (A) - (2*k+0.5)*pi) < 0.1) %!test %! % limiting behaviour as z large, down imag axis %! k = -2; %! A = lambertw (k, -1e100*1i); %! assert (abs (imag (A) - (2*k-0.5)*pi) < 0.1) %!test %! % limiting behaviour as z large, near branch %! k = 3; %! A = lambertw (k, -1e100); %! B = lambertw (k, -1e100 + 1i); %! C = lambertw (k, -1e100 - 1i); %! assert (abs (imag (A) - (2*k+1)*pi) < 0.1) %! assert (abs (imag (B) - (2*k+1)*pi) < 0.1) %! assert (abs (imag (C) - (2*k-1)*pi) < 0.1) %!test %! % infinities and nan %! A = lambertw ([inf exp(1) -inf nan]); %! B = [inf 1 inf + pi*1i nan]; %! assert (isequaln (A, B)) %!test %! % infinities and nan %! A = lambertw (3, [inf 1 -inf nan]); %! B = [inf + 2*3*pi*1i lambertw(3,1) inf + (2*3+1)*pi*1i nan]; %! assert (isequaln (A, B)) %!test %! % infinities and nan %! A = lambertw ([0 1 2 0], [inf -inf nan exp(1)]); %! B = [inf inf+3*pi*1i nan 1]; %! assert (isequaln (A, B)) %!test %! % scalar infinity z, vector b %! A = lambertw ([1 2 -3], inf); %! B = [lambertw(1, inf) lambertw(2, inf) lambertw(-3, inf)]; %! assert (isequal (A, B)) %!test %! % scalar -infinity z, vector b %! A = lambertw ([1 2 -3], -inf); %! B = [lambertw(1, -inf) lambertw(2, -inf) lambertw(-3, -inf)]; %! assert (isequal (A, B)) %!test %! % scalar z nan, vector b %! A = lambertw ([1 2 -3], nan); %! B = [nan nan nan]; %! assert (isequaln (A, B)) symbolic-3.1.1/inst/misc.tst0000644000000000000000000000746614405647405012715 0ustar %% Copyright (C) 2014, 2016-2017, 2019, 2022 Colin B. Macdonald %% Copyright (C) 2016 Lagu %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% some new tests, may want to put elsewhere... %!shared x %! syms x %!assert (isequal (x(1), x)); %!assert (isequal (x(end), x)); %!error x(0) %!error x(-1) %!error x(end+1) %!error x(42, 42) %!error x(1, 42) %!error x(42, 1) %!assert (isequal (x(1, 1), x)); %!assert (isequal (x(:, :), x)); %!assert (isequal (x(:), x)); %!error x('::') %!error x(1, '::') %!shared a %! syms x %! a = [1 2 x]; %!error a(42, 42) %!error a(0, 1) %!error a(1, 0) %!shared x %! syms x %!error x([1 2; 1 1]) %!error x([1 2]) %!test %! % matrix index into matrix %! m = [1 x; 3 6*x]; %! assert (isequal (m([4 1; 3 3]), [6*x 1; x x])) %!test %! % vector index into matrix, orientation, prompted by issue #114 %! m = [0 x; 2*x 3]; %! assert (isequal (m([2; 1; 3]), [2*x; 0; x])) %! assert (isequal (m([2 1 3]), [2*x 0 x])) %!test %! % matrix index into vector (scalar), issue #113 %! assert (isequal (x([1 1; 1 1]), [x x; x x])) %! assert (isequal (x([1 1]), [x x])) %! assert (isequal (x([1; 1]), [x; x])) %!test %! % matrix index into vector (scalar), issue #113 %! a = [1 x 3]; %! assert (isequal (a([1 2; 2 3]), [1 x; x 3])) %! % but vec into vec takes orientation from a %! assert (isequal (a([2 3]), [x 3])) %! assert (isequal (a([2; 2]), [x x])) %!test %! % matrix index into vector %! a = [10 20 x]; %! assert (isequal (a([3 1; 3 2]), [x 10; x 20])) %!test %! % empty indexing %! assert (isempty (x([]))) %! assert (isequal (size(x([])), [0 0])) %! m = [0 x 1; 2*x 3 0]; %! assert (isequal (size(m([])), [0 0])) %! assert (isequal (size(m([],[])), [0 0])) %! assert (isequal (size(m(:,[])), [2 0])) %! assert (isequal (size(m([],:)), [0 3])) %!shared %!test %! r = pycall_sympy__ ('return Version("0.7.6") > Version("0.7.6"),'); %! assert (isequal (r, false)) %!test %! r = pycall_sympy__ ('return Version("0.7.6") >= Version("0.7.6"),'); %! assert (isequal (r, true)) %!xtest %! % `.dev` is not treated quite right except by packaging.version.Version %! r = pycall_sympy__ ('return Version("0.7.6") > Version("0.7.6.dev"),'); %! assert (isequal (r, true)) %! r = pycall_sympy__ ('return Version("0.7.6") >= Version("0.7.6.dev"),'); %! assert (isequal (r, true)) %!test %! r = pycall_sympy__ ('return Version("0.7.6.1") > Version("0.7.6"),'); %! assert (isequal (r, true)) %!test %! r = pycall_sympy__ ('return Version("0.7.6.1") >= Version("0.7.6"),'); %! assert (isequal (r, true)) %!test %! r = pycall_sympy__ ('return Version("0.7.6.1.dev") >= Version("0.7.6"),'); %! assert (isequal (r, true)) %!test %! r = pycall_sympy__ ('return Version("0.7.6.dev") >= Version("0.7.5"),'); %! assert (isequal (r, true)) %!test %! r = pycall_sympy__ ('return Version("1.0.1") > Version("1.0"),'); %! assert (isequal (r, true)) %!test %! r = pycall_sympy__ ('return Version("1.0") > Version("0.7.6"),'); %! assert (isequal (r, true)) symbolic-3.1.1/inst/octsympy_tests.m0000644000000000000000000000363514405647405014507 0ustar %% Copyright (C) 2014, 2016-2017, 2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @defun octsympy_tests () %% Run the test suite, log results, and return true if any fail. %% %% On recent Octave, this is a thin layer around the built-in Octave %% command @code{__run_test_suite__ (@{'.'@}, @{@})}. %% %% Testing should work once the package is installed, which is otherwise %% harder to test (need to know the installation directory). %% %% TODO: eventually we should drop this file altogether, and use %% @code{pkg test symbolic} instead, see %% @url{https://github.com/cbm755/octsympy/issues/1142} %% and @url{https://savannah.gnu.org/bugs/?62681}. %% %% @seealso{test, runtests, doctest} %% @end defun function anyfail = octsympy_tests () if (compare_versions (OCTAVE_VERSION (), '4.4.0', '>=')) pkgdir = fileparts (mfilename ('fullpath')) % Maybe later: https://savannah.gnu.org/bugs/?55841 %if (strcmp (fullfile (pkgdir), fullfile (pwd))) % % be quieter if pkgdir is the current dir % pkgdir = '.'; %end [pass, fail] = __run_test_suite__ ({pkgdir}, {}); anyfail = fail > 0; return end error ('older Octave not supported') end % muhaha, no one is watching the watchers %!assert(true) symbolic-3.1.1/inst/poly2sym.m0000644000000000000000000000630414405647405013170 0ustar %% Copyright (C) 2003 Willem J. Atsma %% Copyright (C) 2014-2016 Colin B. Macdonald %% %% 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, or (at your option) any later version. %% %% This software 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 software; see the file COPYING. If not, %% see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defun poly2sym (@var{c}) %% @defunx poly2sym (@var{c}, @var{x}) %% Create a symbolic polynomial expression from coefficients. %% %% If @var{x} is not specified, the free variable is set to @code{sym('x')}. @var{c} %% may be a vector of doubles or syms. It can also be a cell array vector. %% @var{x} may be a symbolic expression or something that converts to one. %% The coefficients correspond to decreasing exponent of the free variable. %% %% Example: %% @example %% @group %% x = sym ('x'); %% y = sym ('y'); %% poly2sym ([2 5]) %% @result{} (sym) 2⋅x + 5 %% poly2sym (@{2*y 5 -3@}, x) %% @result{} (sym) %% 2 %% 2⋅x ⋅y + 5⋅x - 3 %% @end group %% @end example %% %% @seealso{@@sym/sym2poly, polyval, roots} %% @end defun function p = poly2sym(c,x) if (nargin == 1) x = sym('x'); elseif (nargin == 2) x = sym(x); else print_usage (); end N = length(c); if (~iscell(c)) tmp = c; c = {}; for i=1:N % Bug #17 %c{i} = tmp(i) idx.type = '()'; idx.subs = {i}; c{i} = subsref(tmp, idx); end end p = sym(0); for i=1:N % horner form %p = p*x+c{i}; % monomial form (this is what matlab SMT does) p = p + c{i} * x^(N-i); end end %!shared x,y,a,b,c,p %! syms x y a b c %! p = x^3 + 2*x^2 + 3*x + 4; %!assert(isAlways( poly2sym([1 2 3 4]) == p )) %!assert(isAlways( poly2sym([1 2 3 4],x) == p )) %!assert(isAlways( poly2sym([1 2 3 4],y) == subs(p,x,y) )) %!assert(isAlways( poly2sym([1 2 3 4],5) == subs(p,x,5) )) %!assert(isequal( poly2sym ([1]), 1 )) %!assert(isequal( poly2sym ([]), 0 )) %% symbolic coefficents %!assert(isAlways( poly2sym(sym([1 2 3 4]),x) == p )) %!assert(isAlways( poly2sym([a b c],x) == a*x^2 + b*x + c )) %!assert(isAlways( poly2sym([a b c]) == a*x^2 + b*x + c )) %!assert(isequal( poly2sym(sym([])), 0 )) %% cell arrays %!assert(isAlways( poly2sym({sym(1) sym(2)}, x) == x + 2 )) %!assert(isequal( poly2sym ({1}), 1 )) %!assert(isequal( poly2sym ({}), 0 )) %!assert(isequal( poly2sym ({1}, x), 1 )) %!assert(isequal( poly2sym ({}, x), 0 )) %% weird cases (matlab SMT does this too, I think it should be an error) %!assert(isAlways( poly2sym([x x], x) == x^2 + x )) %!test %! % mixed cell array with doubles and syms %! assert (isequal (poly2sym ({2.0 sym(3) int64(4)}), 2*x^2 + 3*x + 4)) %!test %! % string for x %! p = poly2sym ([1 2], 's'); %! syms s %! assert (isequal (p, s + 2)) symbolic-3.1.1/inst/private/0000755000000000000000000000000014405647405012663 5ustar symbolic-3.1.1/inst/private/assert_have_python_and_sympy.m0000644000000000000000000002055714405647405021042 0ustar %% Copyright (C) 2016-2019, 2022 Colin B. Macdonald %% Copyright (C) 2022 Alex Vong %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @defun assert_have_python_and_sympy (pyexec) %% @defunx assert_have_python_and_sympy (pyexec, verbose) %% Check that Python and SymPy are installed and working. %% %% @seealso{sympref} %% @end defun function assert_have_python_and_sympy (pyexec, verbose) minsympyver = '1.4'; if (nargin < 2) verbose = false; end if (verbose) disp ('') disp ('Symbolic package diagnostics') disp ('============================') disp ('') disp ('Python and SymPy are needed for most features of the Symbolic package.') disp ('') fprintf ('The Python interpreter is currently: "%s".\n', pyexec) disp ('') disp ('Computers may have more than one Python interpreter installed. If you') disp ('need to, you can select a different one using the PYTHON environment') disp ('variable (see "help sympref"). For example, to use Python 3, try') disp (' setenv PYTHON python3') disp (' sympref reset') disp ('') fprintf ('Attempting to run %s -c "print(\\"Python says hello\\")"\n\n', pyexec); end [status, output] = system ([pyexec ' -c "print(\"Python says hello\")"']); if (verbose) status output end if ( (status ~= 0) || (~ strcmp(strtrim(output), 'Python says hello')) ) if (~ verbose) error ('OctSymPy:nopython', ... ['Cannot run the Python executable "%s"\n' ... ' Try "sympref diagnose" for more information.'], ... pyexec) end disp ('') disp ('Unfortunately, that command failed!') disp ('We expected to see "status = 0" and "output = Python says hello".') disp ('') disp (' * Is there an error message above?') disp ('') disp (' * Do you have Python installed?') disp ('') disp (' * Please try using "setenv" as described above.') disp ('') disp (' * Most systems search the PATH environment when looking for commands.') disp (' Your path seems to be:') disp ('') disp (getenv ('PATH')) # if (ispc () && (~isunix ())) # disp ('') # disp (' * Did you install the Symbolic bundle for Windows that includes Python?') # disp (' Please refer to the installation notes for Windows users at') # disp (' ') # end return end if (verbose) disp ('Good, Python ran correctly.') disp ('') disp ('') disp ('Python version') disp ('--------------') disp ('') disp ('Let''s check what version of Python we are calling...') disp ('') fprintf ('Attempting to run %s -c "import sys; print(sys.version)"\n', pyexec); [status, output] = system ([pyexec ' -c "import sys; print(sys.version)"']); status output fprintf ('Running %s -c "import sys; print(sys.executable)"\n', pyexec); [status, output] = system ([pyexec ' -c "import sys; print(sys.executable)"']); output fprintf ('Checking if %s is running in a Cygwin-like POSIX environment...', pyexec); if python_env_is_cygwin_like (pyexec) fprintf (' yes\n\n'); else fprintf (' no\n\n'); end disp (''); show_system_info (); end if (verbose) disp ('') disp ('SymPy Python Library') disp ('--------------------') disp ('') disp ('SymPy is a Python library used by Symbolic for almost all features.') disp ('') fprintf ('Attempting to run %s -c "import sympy; print(sympy.__version__)"\n\n', pyexec); end [status, output] = system([pyexec ' -c "import sympy; print(sympy.__version__)"']); if (verbose) status output end if (status ~= 0) if (~ verbose) error ('OctSymPy:nosympy', ... ['Python cannot import SymPy: have you installed SymPy?\n' ... ' Try "sympref diagnose" for more information.']) end disp ('') disp ('Unfortunately status was non-zero: probably Python cannot import sympy.') disp ('') disp (' * Is there an error message above?') disp ('') disp (' * Do you have SymPy installed? If not, please try to install it and') disp (' try again.') disp ('') disp (' * If you do have SymPy installed, maybe it''s installed for a different') disp (' Python interpreter than the one we found? Please try "setenv" as') disp (' described above to change your python interpreter.') return end spver = strtrim(output); if (verbose) fprintf ('SymPy must be at least version %s; you have version %s.\n', ... minsympyver, spver); end if (~ exist ('OCTAVE_VERSION', 'builtin')) % no compare_versions on matlab, just assume its ok (!) if (verbose) disp ('We cannot easily compare versions on your system: please verify the above.') end else if (compare_versions (spver, minsympyver, '<')) if (~ verbose) error('OctSymPy:oldsympy', ... ['SymPy version %s found but is too old (%s required)\n' ... ' Try "sympref diagnose" for more information.'], ... spver, minsympyver) end disp ('**** Your SymPy is too old! ****') disp ('Installed newer version already? Perhaps it was for a different Python?') disp ('Try "setenv" as described above to change your python interpreter.') return end end if (verbose) disp ('') disp ('Good, a working version of SymPy is installed.') disp ('') disp ('') disp ('Python XML Parsing and DOM Support') disp ('----------------------------------') disp ('') disp ('The XML DOM library is used by Symbolic for passing values to and from Python.') disp ('Some older versions of Python formatted XML output differently. As long as you') disp ('have any reasonably recent version of Python, this should pass.') disp ('') end script = ['import xml.dom.minidom as minidom; ' ... 'doc = minidom.parseString(\"value\"); ' ... 'print(doc.toprettyxml(indent=\"\"))']; if (verbose) fprintf ('Attempting to run %s -c "%s"\n\n', pyexec, script); end if (ispc () && (~isunix ())) script = strrep (script, '<', '^<'); script = strrep (script, '>', '^>'); end [status, output] = system([pyexec ' -c "' script '"']); if (verbose) status output end if (status ~= 0) if (~ verbose) error ('OctSymPy:noxmldom', ... ['Something wrong, perhaps with XML DOM: is this an unusual Python setup?\n' ... ' Try "sympref diagnose" for more information.']) end disp ('') disp ('Unfortunately status was non-zero: perhaps Python cannot import xml.dom?') disp ('') disp (' * Is there an error message above?') disp ('') disp (' * Are you using an unusual Python installation? If not, please try to') disp (' reinstall it and try again.') return end xmlout = strtrim (output); if (isempty (strfind (xmlout, 'value'))) if (~ verbose) error ('OctSymPy:oldxmldom', ... ['Python XML output is not compatible, probably an old version of Python?\n' ... ' Try "sympref diagnose" for more information.']) end disp ('**** Your Python is too old! ****') disp ('') disp ('The XML output shown above must have "value" all on one line.') disp ('If your Python interpreter is an older release, please try upgrading to a more') disp ('recent version. Symbolic should work with Python 2 (version 2.7.3 or newer)') disp ('and Python 3 (version 3.2.3 or newer).') return end if (verbose) fprintf ('\nYour kit looks good for running the Symbolic package. Happy hacking!\n\n') end end symbolic-3.1.1/inst/private/assert_pythonic_and_sympy.m0000644000000000000000000001157414405647405020352 0ustar %% Copyright (C) 2019, 2022 Colin B. Macdonald %% Copyright (C) 2022 Alex Vong %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @defun assert_pythonic_and_sympy () %% @defunx assert_pythonic_and_sympy (verbose) %% Check that Python and SymPy are installed and working. %% %% @seealso{sympref} %% @end defun function assert_pythonic_and_sympy (verbose) minsympyver = '1.4'; if (nargin < 1) verbose = false; end if (verbose) disp ('') disp ('Symbolic package diagnostics') disp ('============================') disp ('') disp ('Python and SymPy are needed for most features of the Symbolic package.') disp ('') disp ('You seem to have loaded the Pythonic package; we will try to use it') disp ('instead of directly calling a Python interpreter. You can override') disp ('this using "sympref" or by unloading Pythonic:') disp (' pkg unload pythonic') disp ('or') disp (' sympref ipc popen2') disp (' sympref reset') disp ('') disp ('Attempting to run "py.str(''Python says hello'')":') disp ('') end try output = py.str('Python says hello'); if (verbose) output end assert (strcmp (strtrim (char (output)), 'Python says hello')) catch if (~ verbose) error ('OctSymPy:nopython', ... ['Cannot use the Pythonic "py" command\n' ... ' Try "sympref diagnose" for more information.']) ... end disp ('') disp ('Unfortunately, that command failed!') disp ('We expected to see "output = [Python object of type str] ... hello"') disp ('') disp (' * Are you using the most recent Pythonic?') disp (' check: https://gitlab.com/mtmiller/octave-pythonic') disp ('') disp (' * Please try unloading "pythonic" or using "sympref ipc" as above.') disp ('') return end if (verbose) disp ('') disp ('Good, Python ran correctly.') disp ('') disp ('Python version') disp ('--------------') disp ('') pyversion () disp ('') show_system_info () else pyver = pyversion (); end if (verbose) disp ('') disp ('SymPy Python Library') disp ('--------------------') disp ('') disp ('SymPy is a Python library used by Symbolic for almost all features.') disp ('') disp ('Attempting to run "py.sympy.__version__":') disp ('') end try output = py.sympy.__version__; if (verbose) output end catch if (~ verbose) error ('OctSymPy:nosympy', ... ['Python cannot import SymPy: have you installed SymPy?\n' ... ' Try "sympref diagnose" for more information.']) end disp ('') disp ('Unfortunately we cannot import sympy.') disp ('') disp (' * Do you have SymPy installed? If not, please try to install it and') disp (' try again.') disp ('') disp (' * If you do have SymPy installed, maybe it''s installed for a different') disp (' Python environment than the one Pythonic is linked to? Please try') disp (' without Pythonic as described above.') return end spver = strtrim (char (output)); if (verbose) disp ('') fprintf ('SymPy must be at least version %s; you have version %s.\n', ... minsympyver, spver); end if (~ exist ('OCTAVE_VERSION', 'builtin')) % no compare_versions on matlab, just assume its ok (!) if (verbose) disp ('We cannot easily compare versions on your system: please verify the above.') end else if (compare_versions (spver, minsympyver, '<')) if (~ verbose) error('OctSymPy:oldsympy', ... ['SymPy version %s found but is too old (%s required)\n' ... ' Try "sympref diagnose" for more information.'], ... spver, minsympyver) end disp ('**** Your SymPy is too old! ****') disp ('Installed newer version already? Perhaps it was for a different Python') disp ('environment? You could try without Pythonic (see above).') return end end if (verbose) disp ('') disp ('Good, a working version of SymPy is installed.') disp ('') end if (verbose) fprintf ('\nYour kit looks good for running the Symbolic package. Happy hacking!\n\n') end end symbolic-3.1.1/inst/private/check_and_convert.m0000644000000000000000000000463614405647405016511 0ustar %% Copyright (C) 2016 Abhinav Tripathi %% Copyright (C) 2016, 2017, 2022 Colin B. Macdonald %% Copyright (C) 2020 Tianyu Chen (billchenchina) %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . function obj = check_and_convert(var_pyobj) persistent builtins persistent sp persistent list_or_tuple persistent _sym if isempty(builtins) builtins = pyeval("__builtins__"); list_or_tuple = py.tuple({builtins.list, builtins.tuple}); sp = py.sympy; _sym = py.tuple({sp.Basic, sp.MatrixBase}); end if (~ py.isinstance(var_pyobj, list_or_tuple)) var_pyobj = {var_pyobj}; end obj = {}; for i = 1:length(var_pyobj) x = var_pyobj{i}; if (~ isa (x, 'pyobject')) obj{i} = x; elseif (py.isinstance(x, _sym) || isequal(x, py.None)) obj{i} = get_sym_from_python(x); elseif (py.isinstance(x, list_or_tuple)) obj{i} = check_and_convert(x); elseif (isa (x, 'py.str')) obj{i} = char (x); elseif (py.isinstance(x, builtins.dict)) make_str_keys = pyeval ('lambda x: {str(k): v for k, v in x.items()}'); x = pycall (make_str_keys, x); s = struct (x); % make sure values are converted to sym s = structfun (@(t) check_and_convert (t){:}, s, 'UniformOutput', false); obj{i} = s; elseif (isa (x, 'py.int')) if (py.isinstance(x, pyeval('bool'))) error ('unexpected python bool') end if (abs (double (x)) > intmax ('int64')) error ('precision would be lost converting integer larger than %ld', ... intmax ('int64')) end obj{i} = int64 (x); else warning ('OctSymPy:pythonic_no_convert', sprintf ('something was not converted from pyobject: %s', char (x))) obj{i} = x; end end end symbolic-3.1.1/inst/private/cygpath.m0000644000000000000000000000260614405647405014504 0ustar %% Copyright (C) 2022 Alex Vong %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @defun cygpath () %% Convert Windows native path to Cygwin POSIX-style path. %% %% @seealso{python_env_is_cygwin_like} %% @end defun function posix_path = cygpath (native_path) %% FIXME: only allow safe characters inside "..." if ~isempty (strfind (native_path, '"')) error ('cygpath: native path %s must not contain "', native_path); end [status, out] = system (['cygpath -u "' native_path '"']); if status ~= 0 error ('cygpath: cygpath exited with status %d', status); end posix_path = regexprep (out, '[\r]?[\n]$', ''); % strip trailing newline assert (logical (regexp (posix_path, '^[^\r\n]+$'))); % validate path end symbolic-3.1.1/inst/private/defaultpython.m0000644000000000000000000000272114405647405015731 0ustar %% Copyright (C) 2018-2019 Mike Miller %% Copyright (C) 2018, 2020-2021 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @defun defaultpython () %% A string to execute to call a Python interpreter. %% %% Distributors/vendors may find this a convenient place to change %% the default python executable, e.g., to specify "python3.8" or to %% hardcode a path to a particular executable. %% %% End-users can always override this by setting the environment %% variable @code{PYTHON} as documented in @pxref{sympref}. %% %% @end defun function python = defaultpython () % PEP394 says Python 3 installs should all provide this command python = 'python3'; if (ispc () && (~isunix ())) % 2020-03: Python.org installer/Anaconda do not provide python3 python = 'python'; end end symbolic-3.1.1/inst/private/do_highbyte_escapes.m0000644000000000000000000000520414405647405017032 0ustar function r = do_highbyte_escapes(s) %DO_HIGHBYTE_ESCAPES Convert "\x"-escaped strings to bytes % Convert sequences strings of the form '\xNM' into characters. % Here NM is a two-char hex string. Typically sequences of these % represent utf-8 characters. % % Example: % >> s = 'aaa\xe2\x8c\x88bbb\xe2\x8c\x89ccc'; % >> do_highbyte_escapes(s) % ans = aaa⌈bbb⌉ccc % % % But be careful for escaped backslashes that happen to be followed % by an 'x'; substrings with an even number of backspaces such as % '\\x' or '\\\\x' should not be converted. Examples: % >> s = 'aaa \xe2\x8c\x88 bbb \\xe2\\x8c\\\\x89 ccc'; % >> do_highbyte_escapes(s) % ans = aaa ⌈ bbb \\xe2\\x8c\\\\x89 ccc % % >> s = 'aaa \\\xe2\x8c\x88 bbb'; % >> do_highbyte_escapes(s) % ans = aaa \\⌈ bbb % % % Copyright 2016-2017, 2022 Colin B. Macdonald % % Copying and distribution of this file, with or without modification, % are permitted in any medium without royalty provided the copyright % notice and this notice are preserved. This file is offered as-is, % without any warranty. % pad the string with one char in case string starts with \x s = ['_' s]; i = 2; % start at 2 b/c of this padding [TE, NM] = regexp(s, '(?<=[^\\])(?:\\\\)*\\x(?..)', 'tokenExtents', 'names'); % 1. 2. 3. 4. % explanation: % 1. look behind ... % 2. ... for anything that isn't '\' % 3. zero or more pairs '\\' % 4. two chars as a named token if (isempty(TE)) r = s(i:end); return end % get the two-char hex numbers make them into bytes dec = char (hex2dec (struct2cell (NM))); % faster: %d = uint8('ee'); %d = (d >= 48 & d <= 57).*(d-48) + (d >= 97 & d <= 102).*(d-87); %d = 16*d(1) + d(2); % Yep, its a loop :( Takes about 0.02s for a string of length 1179 % containing 291 escaped unicode chars. Roughly 6 times slower than % the hex2dec bit above. r = ''; for j=1:length(TE) r = [r s(i:TE{j}(1)-3) dec(j)]; i = TE{j}(2)+1; end r = [r s(i:end)]; if (~ exist ('OCTAVE_VERSION', 'builtin')) % matlab is not UTF-8 internally r = native2unicode(uint8(r)); end end %% Note: tests in private/ execute but generally fail with __run_test_suite__ % So these are commented out as of 2017-08 %%!test %%! s = 'a\\\xe2\x8c\x88y\xe2\x8c\x89b'; %%! r = 'a\\⌈y⌉b'; %%! assert (do_highbyte_escapes(s), r) %%!test %%! s = '\\xe2'; %%! r = '\\xe2'; %%! assert (do_highbyte_escapes(s), r) %%!test %%! s = '\xe2\x8c\x88'; %%! r = '⌈'; %%! assert (do_highbyte_escapes(s), r) %%!test %%! s = '\\\xe2\x8c\x88'; %%! r = '\\⌈'; %%! assert (do_highbyte_escapes(s), r) symbolic-3.1.1/inst/private/extractblock.m0000644000000000000000000001315714405647405015535 0ustar %% Copyright (C) 2014-2017 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . function A = extractblock(out) %private function %note: only parses the first (I think). No %particular reason it could not do more than one. % Parse xml (no xmlread in octave and this is probably faster) % this regexp creates pairs like { "text after tag"} Z = regexp(out, '(<[^<>]*>)([^<>]*)' ,'tokens'); % Now we have some code that crawls over those pairs and creates % the octave objects. i = 1; [i, A] = helper(Z, i, false); % assert (i == length(Z)), no; might be other stuff or another block assert(length(A) == 1) A = A{1}; end function [i, A] = helper(data, i, inblock) initem = false; A = {}; while (1) switch data{i}{1} case '' inblock = true; case '' assert(inblock); return case '' assert (inblock) assert (initem) item{length(item)+1} = data{i}{2}; case '' assert (inblock) assert (initem) item{length(item)+1} = []; case '' assert (inblock) assert (initem) case '' % next fields are for the item assert (inblock) assert (~initem) item = {}; initem = true; case '' assert (inblock) assert (initem) %A = [A {item}]; temp = process_item(item); %A{length(A)+1} = item; A{length(A)+1} = temp; initem = false; case '' %disp('down into list') [i, List] = helper(data, i+1, inblock); if initem item{length(item)+1} = List; else A{length(A)+1} = List; end case '' List = {}; if initem item{length(item)+1} = List; else A{length(A)+1} = List; end case '' assert (inblock) return otherwise %if strcmpi(data{i}{1}(1:5), ' flintmax) error ('precision would be lost converting integer larger than %ld', ... flintmax) end r = int64 (r); case OCTCODE_DOUBLE assert(M == 1) r = hex2num(C{2}); case OCTCODE_COMPLEX assert(M == 2) r = hex2num(C{2}) + hex2num(C{3})*1i; case OCTCODE_STR assert(M == 1) % did we escape all strings? if (isempty(C{2})) r = ''; else r = str_do_escapes(str_post_xml_filter(C{2})); end case OCTCODE_BOOL assert(M == 1) r = strcmpi(C{2}, 'true'); case OCTCODE_SYM assert(M == 6) sz1 = str2double(C{3}); sz2 = str2double(C{4}); % fixme: should we use 's for these not raw ? str = str_post_xml_filter(C{2}); flat = str_post_xml_filter(C{5}); ascii = str_do_escapes(str_post_xml_filter(C{6})); unicode = str_do_escapes(str_post_xml_filter(C{7})); % empty [] here identifies this to the sym ctor r = sym([], str, [sz1 sz2], flat, ascii, unicode); case OCTCODE_DICT %warning('FIXME: wip'); keys = C{2}{1}; vals = C{3}{1}; % FIXME: why the {1} here? %r = cell2struct(C{2}{1}, C{3}{1}) % no assert(length(keys) == length(vals)) r = struct(); for i=1:length(keys) r = setfield (r, keys{i}, vals{i}); end case OCTCODE_ERROR assert(M == 2) str1 = str_post_xml_filter(C{2}); str2 = str_post_xml_filter(C{3}); disp('extractblock: read an error back from python') str1 str2 %disp('Continuing, but unsure if its safe to do so!') r = 'there was a python error'; error('error reading back from python') otherwise C error('extractblock: not implemented or something wrong'); end end function r = str_do_escapes(s) if (exist ('OCTAVE_VERSION', 'builtin')) r = do_string_escapes (do_highbyte_escapes (s)); else s = strrep (s, '%', '%%'); r = sprintf (do_highbyte_escapes (s)); end end function r = str_post_xml_filter(r) r = strrep(r, '<', '<'); r = strrep(r, '>', '>'); r = strrep(r, '"', '"'); % must be last: r = strrep(r, '&', '&'); end symbolic-3.1.1/inst/private/get_sym_from_python.m0000644000000000000000000000460214405647405017136 0ustar %% Copyright (C) 2016 Abhinav Tripathi %% Copyright (C) 2016, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . function retS = get_sym_from_python(var_pyobj) persistent shape_func persistent sp persistent sp_matrix persistent tuple_1_1 tuple_0_0 persistent use_unicode_false use_unicode_true if isempty(shape_func) shape_func = pyeval(strjoin({'lambda x : [float(r)', 'if (isinstance(r, sp.Basic) and r.is_Integer)', 'else float("nan") if isinstance(r, sp.Basic)', 'else r for r in x.shape]'}, ' ')); sp = py.sympy; sp_matrix = py.tuple({sp.Matrix, sp.ImmutableMatrix}); use_unicode_false = pyargs('use_unicode', false); use_unicode_true = pyargs('use_unicode', true); tuple_1_1 = py.tuple ({1, 1}); tuple_0_0 = py.tuple ({int8(0),int8(0)}); end % Don't return 1x1 matrices if (py.isinstance(var_pyobj, sp_matrix) && isequal(var_pyobj.shape, tuple_1_1)) % TODO: Probably better if supported via Pythonic % https://gitlab.com/mtmiller/octave-pythonic/issues/11 var_pyobj = var_pyobj.__getitem__(tuple_0_0); end ascii = char (sp.pretty (var_pyobj, use_unicode_false)); unicode = char (sp.pretty (var_pyobj, use_unicode_true)); srepr = char (sp.srepr (var_pyobj)); flat = char (py.str (var_pyobj)); if py.isinstance(var_pyobj, sp_matrix) _d = var_pyobj.shape; % TODO: could use int64, but is size supposed to be double? sz = [double(_d{1}) double(_d{2})]; elseif py.isinstance(var_pyobj, sp.MatrixExpr) _d = pycall(shape_func, var_pyobj); sz = [double(_d{1}) double(_d{2})]; else sz = [1 1]; end retS = sym([], srepr, sz, flat, ascii, unicode); end symbolic-3.1.1/inst/private/indent_lines.m0000644000000000000000000000203114405647405015510 0ustar %% Copyright (C) 2014 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . function B = indent_lines(A, n) % indent each line in the cell array A by n spaces pad = repmat(' ', 1, n); if (0 == 1) % 27s B = cellfun(@(x) [pad x], A, 'UniformOutput', false); else % 23s B = cell(size(A)); for i = 1:numel(A) B{i} = [pad A{i}]; end end end symbolic-3.1.1/inst/private/octave_array_to_python.m0000644000000000000000000000244614405647405017631 0ustar %% Copyright (C) 2016 Lagu %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . function r = octave_array_to_python(a) t = ''; [numrows, numcols] = size (a); if (numrows == 0) r = mat2str([]); return; elseif (numrows > 1) t = strcat('[', t); t = strcat(t, octave_array_to_python(a(1, :))); for i = 2:numrows t = strcat(t, ', '); t = strcat(t, octave_array_to_python(a(i, :))); end t = strcat(t, ']'); else t = strcat('[', t); t = strcat(t, mat2str(a(1, 1))); for i = 2:numcols t = strcat(t, ', '); t = strcat(t, mat2str(a(1, i))); end t = strcat(t, ']'); end r = t; symbolic-3.1.1/inst/private/python_copy_vars_from.m0000644000000000000000000000227314405647405017476 0ustar %% Copyright (C) 2014 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . function s = python_copy_vars_from(out, tryexcept) %private function if (nargin == 1) tryexcept = true; end if (~tryexcept) %% no error checking s = { sprintf('octoutput_drv(%s)', out) }; else %% with try-except block s = { 'try:' ... sprintf(' octoutput_drv(%s)', out) ... 'except:' ... ' echo_exception_stdout("while copying variables from Python")' ... ' raise' }; end symbolic-3.1.1/inst/private/python_copy_vars_to.m0000644000000000000000000001173014405647405017153 0ustar %% Copyright (C) 2014-2015 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . function L = python_copy_vars_to(in, te, varargin) %private function if (~te) %% no error checking L = do_list(0, in, varargin); L = { sprintf('%s = []', in) ... L{:} }; else %% put inside try-except L = do_list(4, in, varargin); L = { 'try:' ... sprintf(' %s = []', in) ... L{:} ... ' octoutput_drv("PYTHON: successful variable import")' ... 'except:' ... ' echo_exception_stdout("while copying variables to Python")' ... ' raise' }; end end function a = do_list(indent, in, varlist) sp = repmat(' ', 1, indent); a = {}; c = 0; for i = 1:numel(varlist) x = varlist{i}; if (isa(x,'sym')) c=c+1; a{c} = [sp '# sym']; % The extra printf around the srepr helps if it still has % escape codes (and seems harmless if it does not) c=c+1; a{c} = sprintf ('%s%s.append(%s)', sp, in, sprintf (sympy (x))); elseif (ischar(x)) assert (strcmp (x, '') || isrow (x), ... 'multirow char arrays cannot be converted to Python strings') if (exist ('OCTAVE_VERSION', 'builtin')) x = undo_string_escapes(x); else % roughly same as the above on Matlab? x = strrep(x, '\', '\\'); x = strrep(x, '"', '\"'); for cc = {'\n' '\r' '\t' '\b' '\f'} x = strrep(x, sprintf(cc{:}), cc{:}); end end c=c+1; a{c} = [sp in '.append("' x '")']; % or do we want a printf() around the string? %c=c+1; a{c} = sprintf('%s%s.append("%s")', sp, in, x); elseif (islogical(x) && isscalar(x)) if (x) c=c+1; a{c} = [sp in '.append(True)']; else c=c+1; a{c} = [sp in '.append(False)']; end elseif (isinteger(x) && isscalar(x)) c=c+1; a{c} = sprintf('%s%s.append(%s) # int type', ... sp, in, num2str(x, '%ld')); elseif (isfloat(x) && isscalar(x) && isreal(x)) % Floating point input. By default, all Octave numbers are % IEEE double: we pass these using the exact hex % representation. We could detect and treat % (double-precision) integers specially (which might % help with indexing in some places) but I think it might be % too magical. For now, all doubles become floats in Python. if (isa(x, 'single')) x = double(x); % don't hate, would happen in Python anyway end c=c+1; a{c} = sprintf('%s%s.append(hex2d("%s")) # double', ... sp, in, num2hex(x)); elseif (isfloat(x) && isscalar(x)) % iscomplex(x) if (isa(x, 'single')) x = double(x); % don't hate, would happen in Python anyway end c=c+1; a{c} = sprintf('%s%s.append(hex2d("%s")+hex2d("%s")*1j) # complex', ... sp, in, num2hex(real(x)), num2hex(imag(x))); elseif (iscell(x)) c=c+1; a{c} = [sp '# cell array: xfer to list']; inn = [in 'n']; c=c+1; a{c} = sprintf('%s%s = []', sp, inn); c=c+1; a{c} = sprintf('%s%s.append(%s)', sp, in, inn); b = do_list(indent, inn, x); a = {a{:} b{:}}; c = length(a); elseif (isstruct(x) && isscalar(x)) c=c+1; a{c} = [sp '# struct: xfer to dict']; inkeys = [in 'k']; invalues = [in 'v']; c=c+1; a{c} = sprintf('%s%s = []', sp, inkeys); b = do_list(indent, inkeys, fieldnames(x)); a = {a{:} b{:}}; c = length(a); c=c+1; a{c} = sprintf('%s%s = []', sp, invalues); b = do_list(indent, invalues, struct2cell(x)); a = {a{:} b{:}}; c = length(a); c=c+1; a{c} = sprintf('%s%s.append(dict(zip(%s,%s)))', sp, in, inkeys, invalues); elseif (ismatrix(x) && (isnumeric(x) || islogical(x))) % What should we do with double arrays? Perhaps map them to numpy % arrays is the most useful in general. For now, we map them to a % list-of-lists. This could change in the future. See also: % https://github.com/cbm755/octsympy/issues/134 % https://github.com/cbm755/octsympy/pull/336 c=c+1; a{c} = sprintf('%s%s.append(%s)', sp, in, sprintf(octave_array_to_python(x))); else i, x error('don''t know how to move that variable to python'); end end c=c+1; a{c} = [sp '# end of a list']; end symbolic-3.1.1/inst/private/python_env_is_cygwin_like.m0000644000000000000000000000325314405647405020314 0ustar %% Copyright (C) 2022 Alex Vong %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @defun python_env_is_cygwin_like (pyexec) %% Check if Python @var{pyexec} is running in a Cygwin-like POSIX environment, %% such as Cygwin or MSYS2. The result is memoized to speed up subsequent %% calls. %% %% @seealso{cygpath} %% @end defun function r = python_env_is_cygwin_like (pyexec) persistent python_env_is_cygwin_like_memo if ~isempty (python_env_is_cygwin_like_memo) r = python_env_is_cygwin_like_memo; return end if ispc () if system ('where /q cygpath') ~= 0 r = false; python_env_is_cygwin_like_memo = r; return end [status, out] = system ([pyexec ' -c "import os; print(os.name)"']); if status ~= 0 error ('python_env_is_cygwin_like: %s exited with status %d', ... pyexec, status); end r = ~isempty (regexp (out, 'posix', 'match')); python_env_is_cygwin_like_memo = r; else r = false; python_env_is_cygwin_like_memo = r; end end symbolic-3.1.1/inst/private/python_header.m0000644000000000000000000000177614405647405015705 0ustar %% Copyright (C) 2014, 2015, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . function s = python_header() %private persistent PyStrCache if (isempty(PyStrCache)) thisdir = fileparts (mfilename ('fullpath')); pyfile = fullfile (thisdir, 'python_header.py'); PyStrCache = fileread (pyfile); end s = PyStrCache; end symbolic-3.1.1/inst/private/python_header.py0000644000000000000000000002133414405647405016071 0ustar # Copyright (C) 2014-2017, 2019, 2021-2022 Colin B. Macdonald # Copyright (C) 2019 Mike Miller # Copyright (C) 2020 Tianyu Chen (billchenchina) # Copyright (C) 2021 Johannes Maria Frank # Copyright (C) 2022 Chris Gorman # Copyright (C) 2022 Alex Vong # SPDX-License-Identifier: GPL-3.0-or-later # In some cases this code is fed into stdin: two blank lines between # try-except blocks, no blank lines within each block. import sys sys.ps1 = ""; sys.ps2 = "" def echo_exception_stdout(mystr): exception_str = sys.exc_info()[0].__name__ + ": " + str(sys.exc_info()[1]) # hardcode xml, we may not have imports yet. 1003 is code for string. print("\n") print("\n1003\nINTERNAL_PYTHON_ERROR\n") print("\n1003") print("" + mystr.replace("&", "&").replace("<", "<").replace(">", ">") + "\n") print("\n1003") print("" + exception_str.replace("&", "&").replace("<", "<").replace(">", ">") + "\n") print("\n\n") try: import sympy import mpmath import sympy as sp from sympy import __version__ as spver # need this to reactivate from srepr from sympy import * from sympy.logic.boolalg import Boolean, BooleanFunction from sympy.core.relational import Relational # temporary? for piecewise support from sympy.functions.elementary.piecewise import ExprCondPair from sympy.integrals.risch import NonElementaryIntegral from sympy.matrices.expressions.matexpr import MatrixElement # for hypergeometric from sympy.functions.special.hyper import TupleArg # for sets from sympy.utilities.iterables import uniq try: # quick fix for https://github.com/cbm755/octsympy/issues/1053 # TODO: investigate the sym ctor in this case, likely a better fix in there from sympy.core.symbol import Str except ImportError: pass import copy import binascii import struct import codecs import xml.etree.ElementTree as ET try: from packaging.version import Version except ImportError: try: # available on SymPy >= 1.9 from sympy.external.importtools import version_tuple as Version except ImportError: # will fail on Python 3.12: drop this soon in favour of above from distutils.version import LooseVersion def Version(v): return LooseVersion(v.replace('.dev', '')) import itertools import collections from re import split # patch pretty printer, issue #952 try: from sympy.printing.pretty.pretty import PrettyPrinter _mypp = PrettyPrinter except: # is this needed for SymPy 1.4? TODO: Bump minimum SymPy and cleanup _mypp = pretty.__globals__["PrettyPrinter"] def _my_rev_print(cls, f, **kwargs): g = f.func(*reversed(f.args), evaluate=False) return cls._print_Function(g, **kwargs) _mypp._print_LambertW = lambda cls, f: _my_rev_print(cls, f, func_name='lambertw') _mypp._print_sinc = lambda cls, f: cls._print_Function(f.func(f.args[0]/sp.pi, evaluate=False)) del _mypp except: echo_exception_stdout("in python_header import block") raise try: def dbout(l): # should be kept in sync with the same function # defined in inst/private/python_ipc_native.m sys.stderr.write("pydebug: " + str(l) + "\n") def d2hex(x): # used to pass doubles back-and-forth return binascii.hexlify(struct.pack(">d", x)).decode() def hex2d(s): bins = bytes([int(s[x:x+2], 16) for x in range(0, len(s), 2)]) return struct.unpack(">d", bins)[0] def myesc(s): # workaround https://bugs.python.org/issue25270 if not s: return s b, _ = codecs.escape_encode(s.encode('utf-8')) return b.decode('ascii') except: echo_exception_stdout("in python_header defining fcns block 1") raise try: def objectfilter(x): """Perform final fixes before passing objects back to Octave""" if isinstance(x, sp.Matrix) and x.shape == (1, 1): return x[0, 0] #elif isinstance(x, sp.MatrixExpr): # return x.doit() return x # def octoutput_drv(x, tostdout=True): xroot = ET.Element("output_block") octoutput(x, xroot) # simple, but no newlines and escapes unicode #print(ET.tostring(xroot)) #print("\n") # Clashes with some expat lib in Matlab, Issue #63 import xml.dom.minidom as minidom DOM = minidom.parseString(ET.tostring(xroot)) # want real newlines here (so hard to do escaping *after* this) s = DOM.toprettyxml(indent="", newl="\n") if tostdout: print(s) else: return s except: echo_exception_stdout("in python_header defining fcns block 3") raise try: def octoutput(x, et): OCTCODE_INT = 1001 OCTCODE_DOUBLE = 1002 OCTCODE_STR = 1003 OCTCODE_BOOL = 1005 OCTCODE_COMPLEX = 1006 OCTCODE_DICT = 1010 OCTCODE_SYM = 1020 x = objectfilter(x) if isinstance(x, bool): a = ET.SubElement(et, "item") f = ET.SubElement(a, "f") f.text = str(OCTCODE_BOOL) f = ET.SubElement(a, "f") f.text = str(x) elif x is None or isinstance(x, (sp.Basic, sp.MatrixBase)): # FIXME: is it weird to pretend None is a SymPy object? if isinstance(x, (sp.Matrix, sp.ImmutableMatrix)): _d = x.shape elif isinstance(x, sp.MatrixExpr): # nan for symbolic size _d = [float(r) if (isinstance(r, sp.Basic) and r.is_Integer) else float('nan') if isinstance(r, sp.Basic) else r for r in x.shape] elif x is None: _d = (1,1) else: _d = (1, 1) try: pretty_ascii = sp.pretty(x, use_unicode=False) except: # e.g., SymPy issue #10414 pretty_ascii = str(x) pretty_unicode = sp.pretty(x, use_unicode=True) a = ET.SubElement(et, "item") f = ET.SubElement(a, "f") f.text = str(OCTCODE_SYM) f = ET.SubElement(a, "f") f.text = sympy.srepr(x) f = ET.SubElement(a, "f") f.text = str(_d[0]) f = ET.SubElement(a, "f") f.text = str(_d[1]) f = ET.SubElement(a, "f") f.text = str(x) # esc? f = ET.SubElement(a, "f") f.text = myesc(pretty_ascii) f = ET.SubElement(a, "f") f.text = myesc(pretty_unicode) elif isinstance(x, (list, tuple)): c = ET.SubElement(et, "list") for y in x: octoutput(y, c) elif isinstance(x, int): a = ET.SubElement(et, "item") f = ET.SubElement(a, "f") f.text = str(OCTCODE_INT) f = ET.SubElement(a, "f") f.text = str(x) elif isinstance(x, float): # We pass IEEE doubles using the exact hex representation a = ET.SubElement(et, "item") f = ET.SubElement(a, "f") f.text = str(OCTCODE_DOUBLE) f = ET.SubElement(a, "f") f.text = d2hex(x) elif isinstance(x, complex): a = ET.SubElement(et, "item") f = ET.SubElement(a, "f") f.text = str(OCTCODE_COMPLEX) f = ET.SubElement(a, "f") f.text = d2hex(x.real) f = ET.SubElement(a, "f") f.text = d2hex(x.imag) elif isinstance(x, str): a = ET.SubElement(et, "item") f = ET.SubElement(a, "f") f.text = str(OCTCODE_STR) f = ET.SubElement(a, "f") f.text = myesc(x) elif isinstance(x, dict): # Note: the dict cannot be too complex, keys must convert to # strings for example. Values can be dicts, lists. a = ET.SubElement(et, "item") f = ET.SubElement(a, "f") f.text = str(OCTCODE_DICT) # Convert keys to strings keystr = [str(y) for y in x.keys()] c = ET.SubElement(a, "list") octoutput(keystr, c) c = ET.SubElement(a, "list") # FIXME: bit of a kludge, use iterable instead of list, tuple above? octoutput(list(x.values()), c) else: raise ValueError("octoutput does not know how to export type " + str(type(x))) except: echo_exception_stdout("in python_header defining fcns block 4") raise # end of python header, now couple blank lines symbolic-3.1.1/inst/private/python_ipc_driver.m0000644000000000000000000000554714405647405016603 0ustar %% Copyright (C) 2014-2016, 2019-2020, 2022 Colin B. Macdonald %% Copyright (C) 2017 Mike Miller %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @deftypefun {[@var{A}, @var{db}] =} python_ipc_driver (@dots{}) %% Private function: run Python/SymPy command and return objects. %% %% @var{A} is the resulting object, which might be an error code. %% %% @var{db} usually contains diagnostics to help with debugging %% or error reporting. %% @end deftypefun function [A, db] = python_ipc_driver(what, cmd, varargin) which_ipc = sympref('ipc'); %% version check if exist('OCTAVE_VERSION', 'builtin') if (compare_versions (OCTAVE_VERSION (), '5.1', '<')) fprintf(['\n********************************************************************\n' ... 'Your Octave version is %s but Octsympy is currently untested on\n' ... 'anything before 5.1.\n\n'], OCTAVE_VERSION ()) warning('Old Octave version detected: probably trouble ahead!') fprintf('\n********************************************************************\n\n') fflush(stdout); end end if (strcmp(lower(which_ipc), 'default')) % TODO: may need to adjust, ideally just 'py' if (exist ('pyversion') && exist ('pyexec') && exist ('pyeval')) which_ipc = 'native'; elseif (exist ('popen2') > 1) which_ipc = 'popen2'; else which_ipc = 'system'; end end switch lower(which_ipc) case 'native' [A, db] = python_ipc_native(what, cmd, varargin{:}); case 'popen2' [A, db] = python_ipc_popen2(what, cmd, varargin{:}); case 'system' if (ispc () && (~isunix ())) [A, db] = python_ipc_sysoneline(what, cmd, varargin{:}); else [A, db] = python_ipc_system(what, cmd, false, varargin{:}); end case 'systmpfile' %% for debugging, not intended for long-term usage [A, db] = python_ipc_system(what, cmd, true, varargin{:}); case 'sysoneline' %% for debugging, not intended for long-term usage [A, db] = python_ipc_sysoneline(what, cmd, varargin{:}); otherwise if (strcmp (what, 'reset')) A = true; db = []; else error ('invalid ipc mechanism') end end symbolic-3.1.1/inst/private/python_ipc_native.m0000644000000000000000000001165114405647405016567 0ustar %% Copyright (C) 2016, 2018-2019 Colin B. Macdonald %% Copyright (C) 2016 Abhinav Tripathi %% Copyright (C) 2021 Johannes Maria Frank %% Copyright (C) 2022 Chris Gorman %% Copyright (C) 2022 Alex Vong %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @deftypefn {Function File} {[@var{A}, @var{info}] =} python_ipc_native (@dots{}) %% Private helper function for Python IPC. %% %% @var{A} is the resulting object, which might be an error code. %% %% @var{info} usually contains diagnostics to help with debugging %% or error reporting. %% %% @code{@var{info}.prelines}: the number of lines of header code %% before the command starts. %% %% @end deftypefn function [A, info] = python_ipc_native(what, cmd, varargin) persistent show_msg persistent have_headers info.prelines = 0; if (strcmp(what, 'reset')) A = true; have_headers = []; return end if ~(strcmp(what, 'run')) error('unsupported command') end verbose = ~sympref('quiet'); if (verbose && isempty(show_msg)) assert_pythonic_and_sympy () fprintf ('Symbolic pkg v%s: ', sympref ('version')) end newl = sprintf('\n'); if isempty(have_headers) pyexec(strjoin({'import sys' 'import sympy' 'import mpmath' 'import sympy as sp' 'from sympy import __version__ as spver' 'from sympy import *' 'from sympy.logic.boolalg import Boolean, BooleanFunction' 'from sympy.core.relational import Relational' '# temporary? for piecewise support' 'from sympy.functions.elementary.piecewise import ExprCondPair' 'from sympy.integrals.risch import NonElementaryIntegral' 'from sympy.matrices.expressions.matexpr import MatrixElement' '# for hypergeometric' 'from sympy.functions.special.hyper import TupleArg' '# for sets' 'from sympy.utilities.iterables import uniq' 'try:' ' # quick fix for https://github.com/cbm755/octsympy/issues/1053' ' # TODO: investigate the sym ctor in this case, likely a better fix in there' ' from sympy.core.symbol import Str' 'except ImportError:' ' pass' 'import copy' 'import struct' 'import codecs' 'try:' ' from packaging.version import Version' 'except ImportError:' ' try:' ' from sympy.external.importtools import version_tuple as Version' ' except ImportError:' ' from distutils.version import LooseVersion' ' def Version(v):' ' return LooseVersion(v.replace(".dev", ""))' 'import itertools' 'import collections' 'from re import split' '# patch pretty printer, issue #952' 'from sympy.printing.pretty.pretty import PrettyPrinter' '_mypp = PrettyPrinter' 'def _my_rev_print(cls, f, **kwargs):' ' g = f.func(*reversed(f.args), evaluate=False)' ' return cls._print_Function(g, **kwargs)' '_mypp._print_LambertW = lambda cls, f: _my_rev_print(cls, f, func_name="lambertw")' '_mypp._print_sinc = lambda cls, f: cls._print_Function(f.func(f.args[0]/sp.pi, evaluate=False))' 'del _mypp' 'def dbout(l):' ' # should be kept in sync with the same function' ' # defined in inst/private/python_header.py' ' sys.stderr.write("pydebug: " + str(l) + "\n")' }, newl)) have_headers = true; end if (verbose && isempty (show_msg)) fprintf ('using Pythonic interface, SymPy v%s.\n', ... char (py.sympy.__version__)) show_msg = true; end ins = store_vars_in_python(varargin); pyexec (strjoin (cmd, newl)); outs = pycall ('_fcn', ins); A = check_and_convert(outs); end symbolic-3.1.1/inst/private/python_ipc_popen2.m0000644000000000000000000001347514405647405016512 0ustar %% Copyright (C) 2014-2019, 2022 Colin B. Macdonald %% Copyright (C) 2018, 2020 Mike Miller %% Copyright (C) 2022 Alex Vong %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @deftypefun {[@var{A}, @var{info}] =} python_ipc_popen2 (@dots{}) %% Private helper function for Python IPC. %% %% @var{A} is the resulting object, which might be an error code. %% %% @var{info} usually contains diagnostics to help with debugging %% or error reporting. %% %% @code{@var{info}.prelines}: the number of lines of header code %% before the command starts. %% %% @code{@var{info}.raw}: the raw output, for debugging. %% @end deftypefun function [A, info] = python_ipc_popen2(what, cmd, varargin) persistent emergency_cleanup fin fout pid py_startup_timeout = 30; % seconds verbose = ~sympref('quiet'); info = []; if (strcmp(what, 'reset')) if (~ isempty (pid)) if (verbose) disp ('Closing the Python communications link.') end end A = true; if (is_valid_file_id (fin)) % produces a single newline char: not sure why t = fclose (fin); fin = []; waitpid (pid); pid = []; A = A && (t == 0); end if (is_valid_file_id (fout)) t = fclose (fout); fout = []; A = A && (t == 0); end emergency_cleanup = []; % trigger while we know it is a no-op fin = []; fout = []; pid = []; return end if ~(strcmp(what, 'run')) error('unsupported command') end newl = sprintf('\n'); if isempty(pid) if (verbose) fprintf ('Symbolic pkg v%s: ', sympref('version')) end pyexec = sympref('python'); assert_have_python_and_sympy (pyexec) % formatting matters args = {'-i', '-c', 'import sys; sys.ps1=''''; sys.ps2='''''}; [fin, fout, pid] = popen2 (pyexec, args); fflush (stdout); if (pid < 0) error('popen2() failed'); end then = @(f, g) g (f ()); % will be called when we `clear functions`: avoids dangling file handles emergency_cleanup = onCleanup (@() ... then (@(varagin) ... [is_valid_file_id(fin) && fclose(fin), ... is_valid_file_id(fout) && fclose(fout)], ... @(varargin) ~isempty(pid) && waitpid(pid))); headers = python_header(); fputs (fin, headers); fprintf (fin, '\n\n'); %fflush(fin); % print a block then read it to make sure we're live fprintf (fin, 'octoutput_drv(("Communication established.", sympy.__version__, sys.version))\n\n'); fflush(fin); % if any exceptions in start-up, we probably get those instead [out, err] = readblock(fout, py_startup_timeout); if (err) error('OctSymPy:python_ipc_popen2:timeout', ... 'ipc_popen2: something wrong? timed out starting python') end A = extractblock(out); if (iscell(A) && strcmp(A{1}, 'Communication established.')) if (verbose) fprintf ('Python communication link active, SymPy v%s.\n', A{2}); end elseif (iscell(A) && strcmp(A{1}, 'INTERNAL_PYTHON_ERROR')) info.raw = out; % We want to return so that pycall_sympy__ can report the error instead of us. % But if cannot load python_header correctly, we cannot assume the pipe is % ok (e.g., probably have other errors sitting on the stdout). So reset. python_ipc_popen2('reset'); return else A out python_ipc_popen2('reset'); error('ipc_popen2: something unexpected has gone wrong in starting python') end end %% load all the inputs into python as pickles % they will be in the list '_ins' % there is a try-except block here, sends a block if sucessful loc = python_copy_vars_to('_ins', true, varargin{:}); write_lines(fin, loc, true); fflush(fin); [out, err] = readblock(fout, inf); if (err) error('OctSymPy:python_ipc_popen2:xfer', ... 'ipc_popen2: xfer vars: something wrong? timed out?') end %% did we succeed in copying all the inputs? A = extractblock(out); if (ischar(A) && strcmp(A, 'PYTHON: successful variable import')) % pass elseif (iscell(A) && strcmp(A{1}, 'INTERNAL_PYTHON_ERROR')) info.raw = out; % the pipe should still be in working order, no need to reset return else disp ('Debugging output:') A out msg = ['ipc_popen2: something unexpected happened sending variables to python.\n' ... ' This can happen after interrupting with Ctrl-C.\n' ... ' Do "sympref reset" and try your command again.']; error (sprintf (msg)) end % The number of lines of code before the command itself: because % we send variables before, this is always zero. info.prelines = 0; % code for output, or perhaps a thrown error output_code = python_copy_vars_from('_outs'); % cmd is a snippet of python code defining a function '_fcn' cmd = [cmd {''} '_outs = _fcn(_ins)']; write_lines(fin, cmd, true) write_lines(fin, output_code, true) fflush(fin); [out, err] = readblock(fout, inf); if (err) error('OctSymPy:python_ipc_popen2:cmderr', ... 'ipc_popen2: cmd error? read block returned error'); end A = extractblock(out); info.raw = out; symbolic-3.1.1/inst/private/python_ipc_sysoneline.m0000644000000000000000000001115414405647405017467 0ustar %% Copyright (C) 2014-2018, 2022 Colin B. Macdonald %% Copyright (C) 2018-2019 Osella Giancarlo %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @deftypefun {[@var{A}, @var{info}] =} python_ipc_sysoneline (@dots{}) %% Private helper function for Python IPC. %% %% @var{A} is the resulting object, which might be an error code. %% %% @var{info} usually contains diagnostics to help with debugging %% or error reporting. %% %% @code{@var{info}.prelines}: the number of lines of header code %% before the command starts. %% %% @code{@var{info}.raw}: the raw output, for debugging. %% @end deftypefun function [A, info] = python_ipc_sysoneline(what, cmd, varargin) persistent first_time info = []; if (strcmp(what, 'reset')) show_msg = []; A = true; return end if ~(strcmp(what, 'run')) error('unsupported command') end verbose = ~sympref('quiet'); if (isempty(first_time)) first_time = true; end if (verbose && first_time) fprintf ('Symbolic pkg v%s: using one-line system() communication with SymPy.\n', ... sympref ('version')) disp('Warning: this will be *SLOW*. Every round-trip involves executing a') disp('new Python process and many operations involve several round-trips.') disp('Warning: "sysoneline" will fail when using very long expressions.') end newl = sprintf('\n'); %% Headers % embedding the headers in the -c command is too long for % Windows. We have a 8000 char budget, and the header uses all % of it. mydir = fileparts (mfilename ('fullpath')); mydir = strrep ([mydir filesep()], '\', '\\'); % execfile() only works on python 2 headers = ['exec(open(\"' mydir 'python_header.py\").read()); ']; %s = python_header_embed2(); %headers = ['exec(\"' s '\"); ']; %% load all the inputs into python as pickles s = python_copy_vars_to('_ins', true, varargin{:}); % extra escaping s = myesc(s); % join all the cell arrays with escaped newline s = strjoin(s, '\\n'); s1 = ['exec(\"' s '\"); ']; % The number of lines of code before the command itself (IIRC, all % newlines must be escaped so this should always be zero). assert(numel(strfind(s1, newl)) == 0); info.prelines = 0; %% The actual command % cmd is a snippet of python code defining a function '_fcn'. cmd = [cmd '_outs = _fcn(_ins)']; % now we have a snippet of python code that does something % with _ins and produces _outs. s = myesc(cmd); s = strjoin(s, '\\n'); s2 = ['exec(\"' s '\"); ']; %% output, or perhaps a thrown error s = python_copy_vars_from('_outs'); s = myesc(s); s = strjoin(s, '\\n'); s3 = ['exec(\"' s '\");']; pyexec = sympref('python'); if (first_time) assert_have_python_and_sympy (pyexec) end bigs = [headers s1 s2 s3]; %% paste all the commands into the system() command line % python -c [status,out] = system([pyexec ' -c "' bigs '"']); info.raw = out; % two blocks if everything worked, one on variable import fail ind = strfind(out, ''); if (status ~= 0) && isempty(ind) status out ind error('sysoneline ipc: system() call failed!'); end info.raw = out; A = extractblock(out(ind(1):end)); if (ischar(A) && strcmp(A, 'PYTHON: successful variable import')) % pass elseif (iscell(A) && strcmp(A{1}, 'INTERNAL_PYTHON_ERROR')) return else A out error('sysoneline ipc: something unexpected happened sending variables to python') end assert(length(ind) == 2) A = extractblock(out(ind(2):end)); if (first_time) first_time = false; end end function s = myesc(s) for i = 1:length(s) % order is important here % escape quotes twice s{i} = strrep(s{i}, '\', '\\\\'); % dbl-quote is rather special here % /" -> ///////" -> ///" -> /" -> " s{i} = strrep(s{i}, '"', '\\\"'); if (ispc () && (~isunix ())) %Escape sequence for WIN (Octave & Matlab) s{i} = strrep(s{i}, '>', '^>'); s{i} = strrep(s{i}, '<', '^<'); end end end symbolic-3.1.1/inst/private/python_ipc_system.m0000644000000000000000000001153714405647405016630 0ustar %% Copyright (C) 2014-2016, 2022 Colin B. Macdonald %% Copyright (C) 2022 Alex Vong %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @deftypefun {[@var{A}, @var{info}] =} python_ipc_system (@dots{}) %% Private helper function for Python IPC. %% %% @var{A} is the resulting object, which might be an error code. %% %% @var{info} usually contains diagnostics to help with debugging %% or error reporting. %% %% @code{@var{info}.prelines}: the number of lines of header code %% before the command starts. %% %% @code{@var{info}.raw}: the raw output, for debugging. %% @end deftypefun function [A, info] = python_ipc_system(what, cmd, mktmpfile, varargin) persistent first_time persistent tmpfilename info = []; if (strcmp(what, 'reset')) show_msg = []; A = true; return end if ~(strcmp(what, 'run')) error('unsupported command') end verbose = ~sympref('quiet'); if (isempty(first_time)) first_time = true; end if (verbose && first_time) fprintf ('Symbolic pkg v%s: using slower system() communications with SymPy.\n', ... sympref ('version')) disp('Warning: this will be *SLOW*. Every round-trip involves executing a') disp('new python process and many operations involve several round-trips.') end newl = sprintf('\n'); %% Headers headers = python_header(); %% load all the inputs into python as pickles s_in = python_copy_vars_to('_ins', true, varargin{:}); % the number of lines of code before the command itself info.prelines = numel(strfind(headers, newl)) + numel(strfind(s_in, newl)); %% output, or perhaps a thrown error s_out = python_copy_vars_from('_outs'); cmd = [cmd '_outs = _fcn(_ins)']; % join all the cell arrays with newlines s = strjoin([s_in cmd s_out], newl); pyexec = sympref('python'); if (first_time) assert_have_python_and_sympy (pyexec) end %% FIXME: Issue #63: with new regexp code on Matlab % workaround: % sympref python 'LD_LIBRARY_PATH="" python' % to prevent a conflict with the expat shipped with Matlab 2014a % See here with oracle % https://bugzilla.redhat.com/show_bug.cgi?id=821337 % FIXME: make this the default on Matlab install? bigs = [headers s]; if (~mktmpfile) %% paste all the commands into the system() command line % escaping: cmd or inputs might have \" % " -> \" % \" -> \\\" % \n -> \\n bigs = strrep(bigs, '\', '\\'); bigs = strrep(bigs, '"', '\"'); [status,out] = system([pyexec ' -c "' bigs '"']); else %% Generate a temp .py file then execute it with system() % can be useful for debugging, or if "python -c" fails for you if (isempty (tmpfilename)) tmpfilename = [tempname() '_octsympytmp.py']; if (verbose) disp (['This session will use the temp file "' tmpfilename '"']) end end [fd, msg] = fopen (tmpfilename, 'w'); if fd < 0 error ('system ipc: failed to create temporary file %s: %s', ... tmpfilename, msg); end fprintf(fd, '# temporary autogenerated code\n\n'); % we just added two more lines at the top info.prelines = info.prelines + 2; status = fputs(fd, bigs); if status < 0 error ('system ipc: failed to write the big string to %s (fd %d)', ... tmpfilename, fd); end status = fclose(fd); if status < 0 error ('system ipc: failed to close %s (fd %d) after writing', ... tmpfilename, fd); end if python_env_is_cygwin_like (pyexec) tmpfilename = cygpath (tmpfilename); end [status, out] = system ([pyexec ' ' tmpfilename]); end info.raw = out; % two blocks if everything worked, one on variable import fail ind = strfind(out, ''); if (status ~= 0) && isempty(ind) status out ind error('system ipc: system() call failed!'); end A = extractblock(out(ind(1):end)); if (ischar(A) && strcmp(A, 'PYTHON: successful variable import')) % pass elseif (iscell(A) && strcmp(A{1}, 'INTERNAL_PYTHON_ERROR')) return else A out error('system ipc: something unexpected happened sending variables to python') end assert(length(ind) == 2) A = extractblock(out(ind(2):end)); if (first_time) first_time = false; end end symbolic-3.1.1/inst/private/readblock.m0000644000000000000000000000670614405647405015000 0ustar %% Copyright (C) 2014-2015 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . function [A, err] = readblock(fout, timeout) %private function: read one block % how long to wait before displaying "Waiting..." wait_disp_thres = 8.0; tagblock = ''; tagendblock = ''; err = false; EAGAIN = errno ('EAGAIN'); % Windows emits this when pipe is waiting (see % octave/libinterp/corefcn/syscalls.cc test code) EINVAL = errno ('EINVAL'); done = false; started = false; nwaits = 0; dispw = false; start = time(); fclear (fout); % otherwise, fails on next call do if (ispc () && (~isunix ())) errno (0); % win32, see syscalls.cc test code end s = fgets (fout); if (ischar (s)) %fputs (stdout, s); if (started) A = [A s]; end % here is the tag, so start recording output if (strncmp(s, tagblock, length(tagblock))) started = true; A = s; end % if we see the end tag, we're done if (strncmp(s, tagendblock, length(tagendblock))) done = true; end elseif (errno() == EAGAIN || errno() == EINVAL) waitdelta = exp(nwaits/10)/1e4; if (time() - start <= wait_disp_thres) %fprintf(stdout, 'W'); % debugging, in general do nothing elseif (~dispw) fprintf(stdout, 'Waiting...') dispw = true; else fprintf(stdout, '.') end fclear (fout); %if (ispc () && (~isunix ())) %errno (0); % maybe can do this on win32? %end pause (waitdelta); nwaits = nwaits + 1; elseif (errno() == 0) waitdelta = exp(nwaits/10)/1e4; if (time() - start <= wait_disp_thres) %fprintf(stdout, 'W'); % debugging, in general do nothing elseif (~dispw) fprintf(stdout, '[usually something wrong if you see stars] Waiting***') dispw = true; else fprintf(stdout, '*') end fclear (fout); %if (ispc () && (~isunix ())) %errno (0); % maybe can do this on win32? %end pause (waitdelta); nwaits = nwaits + 1; else warning ('OctSymPy:readblock:invaliderrno', ... sprintf('readblock: s=%d, errno=%d, perhaps error in the command?', s, errno())) pause(0.1) % FIXME; replace with waitdelta etc end %disp('paused'); pause if (time() - start > timeout) warning('OctSymPy:readblock:timeout', ... sprintf('readblock: timeout of %g exceeded, breaking out', timeout)); if (started) disp('output so far:') A else disp('no output so far') A = ''; end A = [A '\nFAILED TIMEOUT\n']; err = true; break end until (done) if (dispw) fprintf(stdout, '\n') end %fclose (fout); %waitpid (pid); symbolic-3.1.1/inst/private/show_system_info.m0000644000000000000000000000234714405647405016446 0ustar %% Copyright (C) 2022 Alex Vong %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @defun show_system_info () %% Show information about the current system. %% %% @seealso{computer, ver} %% @end defun function show_system_info () [platform, array_maxsize, endian] = computer (); arch = computer ('arch'); disp ('System info'); disp ('-----------'); disp (''); fprintf ('Platform: %s\n', platform); fprintf ('Array Maximum Size: %d\n', array_maxsize); fprintf ('Endianness: %s\n', endian); fprintf ('Architecture: %s\n', arch); ver (); disp (''); end symbolic-3.1.1/inst/private/store_vars_in_python.m0000644000000000000000000000232314405647405017317 0ustar %% Copyright (C) 2016 Abhinav Tripathi %% Copyright (C) 2016 Colin B. Macdonald %% Copyright (C) 2022 Alex Vong %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . function var_pyobj = store_vars_in_python (L) var_pyobj = py.list (); for i = 1:numel(L) x = L{i}; if (isa(x, 'sym')) var_pyobj.append (pyeval (sympy (x))) elseif (iscell (x)) var_pyobj.append (store_vars_in_python (x)) elseif (isnumeric (x) && isequal (x, [])) % See #1151 for more details var_pyobj.append (py.list ()); else var_pyobj.append(x); end end end symbolic-3.1.1/inst/private/undo_highbyte_escapes.m0000644000000000000000000000173014405647405017375 0ustar function r = undo_highbyte_escapes(s) %UNDO_HIGHBYTE_ESCAPES Convert non-ascii characters into \x escapes % Suppose we have a unicode string such as % >> s = '⌈y⌉' % s = ⌈y⌉ % >> double(s) % ans = 226 140 136 121 226 140 137 % % % We can escape the highbytes as in: % >> r = undo_highbyte_escapes(s) % r = \xe2\x8c\x88y\xe2\x8c\x89 % % % FIXME: do a vectorized implementation, or at least skip % continuous chunks of ascii % % FIXME: probably only works on Octave, not Matlab. % % Copyright 2016-2017 Colin B. Macdonald % % Copying and distribution of this file, with or without modification, % are permitted in any medium without royalty provided the copyright % notice and this notice are preserved. This file is offered as-is, % without any warranty. d = double(s); %I = d > 127; r = ''; for j=1:length(d) if (d(j) <= 127) r = [r s(j)]; else r = [r '\x' tolower(dec2hex(d(j)))]; end end symbolic-3.1.1/inst/private/valid_sym_assumptions.m0000644000000000000000000000234414405647405017500 0ustar %% Copyright (C) 2015, 2019 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @defun valid_sym_assumptions () %% Return list of valid assumptions. %% %% @end defun %% Reference: http://docs.sympy.org/dev/modules/core.html %% FIXME: Maybe in the future remove this file and replace with something else. function L = valid_sym_assumptions() persistent List if (isempty(List)) cmd = {'from sympy.core.assumptions import _assume_defined' 'return list(_assume_defined),'}; List = pycall_sympy__ (cmd); end L = List; end symbolic-3.1.1/inst/private/write_lines.m0000644000000000000000000000163114405647405015366 0ustar %% Copyright (C) 2014-2015 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . function A = write_lines(f, L, xtra) %private function newl = sprintf('\n'); if (xtra) L(end+1:end+2) = {'' ''}; end fputs(f, strjoin(L, newl)); end symbolic-3.1.1/inst/pycall_sympy__.m0000644000000000000000000003444114405647405014420 0ustar %% Copyright (C) 2014-2019, 2022 Colin B. Macdonald %% Copyright (C) 2022 Alex Vong %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypefun {[@var{a}, @var{b}, @dots{}] =} pycall_sympy__ (@var{cmd}, @var{x}, @var{y}, @dots{}) %% Run some Python command on some objects and return other objects. %% %% This function is not really intended for end users. %% %% Here @var{cmd} is a string of Python code. %% Inputs @var{x}, @var{y}, @dots{} can be a variety of objects %% (possible types listed below). Outputs @var{a}, @var{b}, @dots{} are %% converted from Python objects: not all types are possible, see %% below. %% %% Example: %% @example %% @group %% x = 10; y = 2; %% cmd = '(x, y) = _ins; return (x+y, x-y)'; %% [a, b] = pycall_sympy__ (cmd, x, y) %% @result{} a = 12 %% @result{} b = 8 %% @end group %% @end example %% %% The inputs will be in a list called @code{_ins}. %% Instead of @code{return}, you can append to the Python list %% @code{_outs}: %% @example %% @group %% cmd = '(x, y) = _ins; _outs.append(x**y)'; %% a = pycall_sympy__ (cmd, x, y) %% @result{} a = 100 %% @end group %% @end example %% %% If you want to return a list, one way is to append a comma %% to the return command. Compare these two examples: %% @example %% @group %% L = pycall_sympy__ ('return [1, -3.4, "python"],') %% @result{} L = %% @{ %% [1,1] = 1 %% [1,2] = -3.4000 %% [1,3] = python %% @} %% [a, b, c] = pycall_sympy__ ('return [1, -3.4, "python"]') %% @result{} a = 1 %% @result{} b = -3.4000 %% @result{} c = python %% @end group %% @end example %% %% You can also pass a cell-array of lines of code. But be careful %% with whitespace: its Python! %% @example %% @group %% cmd = @{ '(x,) = _ins' %% 'if x.is_Matrix:' %% ' return x.T' %% 'else:' %% ' return x' @}; %% @end group %% @end example %% The cell array can be either a row or a column vector. %% Each of these strings probably should not have any newlines %% (other than escaped ones e.g., inside strings). An exception %% might be Python triple-quoted """ multiline strings """. %% FIXME: test this. %% It might be a good idea to avoid blank lines as they can cause %% problems with some of the IPC mechanisms. %% %% Possible input types: %% @itemize %% @item sym objects %% @item strings (char) %% @item scalar doubles %% @item structs %% @end itemize %% They can also be cell arrays of these items. Multi-D cell %% arrays may not work properly. %% %% Possible output types: %% @itemize %% @item SymPy objects %% @item int %% @item float %% @item string %% @item unicode strings %% @item bool %% @item dict (converted to structs) %% @item lists/tuples (converted to cell vectors) %% @end itemize %% FIXME: add a py_config to change the header? The python %% environment is defined in python_header.py. Changing it is %% currently harder than it should be. %% %% Note: if you don't pass in any syms, this shouldn't need SymPy. %% But it still imports it in that case. If you want to run this %% w/o having the SymPy package, you'd need to hack a bit. %% %% @end deftypefun function varargout = pycall_sympy__ (cmd, varargin) if (~iscell(cmd)) if (isempty(cmd)) cmd = {}; else cmd = {cmd}; end end % empty command will cause empty try: except: block if isempty(cmd) cmd = {'pass'}; end %% IPC interface % the ipc mechanism shall put the input variables in the tuple % '_ins' and it will return to us whatever we put in the tuple % '_outs'. There is no particular reason this needs to define % a function, I just thought it isolates local variables a bit. % Careful: fix this constant if you change the code below. % Test with "pycall_sympy__ ('raise')" which should say "line 1". LinesBeforeCmdBlock = 3; % replace blank lines w/ empty comments (unnec. b/c of try:?) %I = cellfun(@isempty, cmd); %cmd(I) = repmat({'#'}, 1, nnz(I)); cmd = indent_lines(cmd, 8); cmd = { 'def _fcn(_ins):' ... ' _outs = []' ... ' try:' ... cmd{:} ... ' except Exception as e:' ... ' ers = type(e).__name__ + ": " + str(e) if str(e) else type(e).__name__' ... ' _outs = ("COMMAND_ERROR_PYTHON", ers, sys.exc_info()[-1].tb_lineno)' ... ' return _outs' ... }; [A, db] = python_ipc_driver('run', cmd, varargin{:}); if (~iscell(A)) A={A}; end %% Error reporting % ipc drivers are supposed to give back these specially formatting error strings if (~isempty(A) && ischar(A{1}) && strcmp(A{1}, 'COMMAND_ERROR_PYTHON')) errcmdlineno = A{3} - db.prelines; errlineno = errcmdlineno - LinesBeforeCmdBlock; if (errcmdlineno <= 0 || errcmdlineno > length (cmd)) error ('Python exception: %s\n occurred at unexpected line number, maybe near line %d?', ... A{2}, errlineno); else error ('Python exception: %s\n occurred at line %d of the Python code block:\n %s', ... A{2}, errlineno, strtrim (cmd{errcmdlineno})); end elseif (~isempty(A) && ischar(A{1}) && strcmp(A{1}, 'INTERNAL_PYTHON_ERROR')) % Here A{3} is the error msg and A{2} is more info about where it happened if (strfind (A{3}, 'KeyboardInterrupt')) what_to_do = ['Probably something was interrupted by "Ctrl-C".\n' ... ' Do "sympref reset" and repeat your command.']; else what_to_do = ['Try "sympref reset" and repeat your command?\n' ... ' (consider filing an issue at ' ... 'https://github.com/cbm755/octsympy/issues)']; end error ('Python exception: %s\n occurred %s.\n %s', ... A{3}, A{2}, sprintf (what_to_do)) end M = length(A); varargout = cell(1,M); for i=1:M varargout{i} = A{i}; end if nargout ~= M warning('number of outputs don''t match, was this intentional?') end end %!test %! % general test %! x = 10; y = 6; %! cmd = '(x,y) = _ins; return (x+y,x-y)'; %! [a,b] = pycall_sympy__ (cmd, x, y); %! assert (a == x + y && b == x - y) %!test %! % bool %! assert (pycall_sympy__ ('return True,')) %! assert (~pycall_sympy__ ('return False,')) %!test %! % float %! assert (abs(pycall_sympy__ ('return 1.0/3,') - 1/3) < 1e-15) %!test %! % int %! r = pycall_sympy__ ('return 123456'); %! assert (r == 123456) %! assert (isinteger (r)) %!test %! % string %! x = 'octave'; %! cmd = 's = _ins[0]; return s.capitalize(),'; %! y = pycall_sympy__ (cmd, x); %! assert (strcmp(y, 'Octave')) %!test %! % string with escaped newlines, comes back as escaped newlines %! x = 'a string\nbroke off\nmy guitar\n'; %! y = pycall_sympy__ ('return _ins', x); %! assert (strcmp(y, x)) %!test %! % string with actual newlines, comes back as actual newlines %! x = sprintf('a string\nbroke off\nmy guitar\n'); %! y = pycall_sympy__ ('return _ins', x); %! y2 = strrep(y, sprintf('\n'), sprintf('\r\n')); % windows %! assert (strcmp(x, y) || strcmp(x, y2)) %!test %! % cmd string with newlines, works with cell %! y = pycall_sympy__ ('return "string\nbroke",'); %! y2 = sprintf('string\nbroke'); %! y3 = strrep(y2, sprintf('\n'), sprintf('\r\n')); % windows %! assert (strcmp(y, y2) || strcmp(y, y3)) %!test %! % string with XML escapes %! x = '<> >< <<>>'; %! y = pycall_sympy__ ('return _ins', x); %! assert (strcmp(y, x)) %! x = '&'; %! y = pycall_sympy__ ('return _ins', x); %! assert (strcmp(y, x)) %!test %! % strings with double quotes %! x = 'a\"b\"c'; %! y = pycall_sympy__ ('return _ins', x); %! assert (strcmp(y, x)) %! x = '\"'; %! y = pycall_sympy__ ('return _ins', x); %! assert (strcmp(y, x)) %!test %! % cmd has double quotes, these must be escaped by user %! % (of course: she is writing python code) %! expy = 'a"b"c'; %! y = pycall_sympy__ ('return "a\"b\"c",'); %! assert (strcmp(y, expy)) %!test %! % strings with quotes %! x = 'a''b'; % this is a single quote %! y = pycall_sympy__ ('return _ins', x); %! assert (strcmp(y, x)) %!test %! % strings with quotes %! x = '\"a''b\"c''\"d'; %! y = pycall_sympy__ ('return _ins[0]', x); %! assert (strcmp(y, x)) %!test %! % strings with quotes %! expy = '"a''b"c''"d'; %! y = pycall_sympy__ ('s = "\"a''b\"c''\"d"; return s'); %! assert (strcmp(y, expy)) %!test %! % strings with printf escapes %! x = '% %% %%% %%%% %s %g %%s'; %! y = pycall_sympy__ ('return _ins', x); %! assert (strcmp(y, x)) %!test %! % cmd with printf escapes %! x = '% %% %%% %%%% %s %g %%s'; %! y = pycall_sympy__ (['return "' x '",']); %! assert (strcmp(y, x)) %!test %! % cmd w/ backslash and \n must be escaped by user %! expy = 'a\b\\c\nd\'; %! y = pycall_sympy__ ('return "a\\b\\\\c\\nd\\",'); %! assert (strcmp(y, expy)) %!test %! % slashes %! x = '/\\ // \\\\ \\/\\/\\'; %! z = '/\ // \\ \/\/\'; %! y = pycall_sympy__ ('return _ins', x); %! assert (strcmp(y, x)) %!test %! % slashes %! z = '/\ // \\ \/\/\'; %! y = pycall_sympy__ ('return "/\\ // \\\\ \\/\\/\\"'); %! assert (strcmp(y, z)) %!test %! % strings with special chars %! x = '!@#$^&* you!'; %! y = pycall_sympy__ ('return _ins', x); %! assert (strcmp(y, x)) %! x = '~-_=+[{]}|;:,.?'; %! y = pycall_sympy__ ('return _ins', x); %! assert (strcmp(y, x)) %!xtest %! % string with backtick trouble for system -c (sysoneline) %! x = '`'; %! y = pycall_sympy__ ('return _ins', x); %! assert (strcmp(y, x)) %!test %! % unicode %! s1 = '我爱你'; %! cmd = 'return u"\u6211\u7231\u4f60",'; %! s2 = pycall_sympy__ (cmd); %! assert (strcmp (s1, s2)) %!test %! % unicode with \x %! s1 = '我'; %! cmd = 'return b"\xe6\x88\x91".decode("utf-8")'; %! s2 = pycall_sympy__ (cmd); %! assert (strcmp (s1, s2)) %!test %! % unicode with \x and some escaped backslashes %! s1 = '\我\'; %! cmd = 'return b"\\\xe6\x88\x91\\".decode("utf-8")'; %! s2 = pycall_sympy__ (cmd); %! assert (strcmp (s1, s2)) %!xtest %! % unicode passthru %! s = '我爱你'; %! s2 = pycall_sympy__ ('return _ins', s); %! assert (strcmp (s, s2)) %! s = '我爱你<>\&//\#%% %\我'; %! s2 = pycall_sympy__ ('return _ins', s); %! assert (strcmp (s, s2)) %!xtest %! % unicode w/ slashes, escapes %! s = '我<>\&//\#%% %\我'; %! s2 = pycall_sympy__ ('return "我<>\\&//\\#%% %\\我"'); %! assert (strcmp (s, s2)) %!test %! % list, tuple %! assert (isequal (pycall_sympy__ ('return [1,2,3],'), {1, 2, 3})) %! assert (isequal (pycall_sympy__ ('return (4,5),'), {4, 5})) %! assert (isequal (pycall_sympy__ ('return (6,),'), {6,})) %! assert (isequal (pycall_sympy__ ('return [],'), {})) %!test %! % dict %! cmd = 'd = dict(); d["a"] = 6; d["b"] = 10; return d,'; %! d = pycall_sympy__ (cmd); %! assert (d.a == 6 && d.b == 10) %!test %! r = pycall_sympy__ ('return 6'); %! assert (isequal (r, 6)) %!test %! r = pycall_sympy__ ('return "Hi"'); %! assert (strcmp (r, 'Hi')) %!test %! % blank lines, lines with spaces %! a = pycall_sympy__ ({ '', '', ' ', 'return 6', ' ', ''}); %! assert (isequal (a, 6)) %!test %! % blank lines, strange comment lines %! cmd = {'a = 1', '', '#', '', '# ', ' #', 'a = a + 2', ' #', 'return a'}; %! a = pycall_sympy__ (cmd); %! assert (isequal (a, 3)) %!test %! % return empty string (was https://bugs.python.org/issue25270) %! assert (isempty (pycall_sympy__ ('return ""'))) %!test %! % return nothing (via an empty list) %! % note distinct from 'return [],' %! pycall_sympy__ ('return []') %!test %! % return nothing (because no return command) %! pycall_sympy__ ('dummy = 1') %!test %! % return nothing (because no command) %! pycall_sympy__ ('') %!test %! % return nothing (because no command) %! pycall_sympy__ ({}) %!error %! % python exception while passing variables to python %! % This tests the "INTERNAL_PYTHON_ERROR" path. %! % FIXME: this is a very specialized test, relies on internal octsympy %! % implementation details, and may need to be adjusted for changes. %! disp('') %! disp('**********************************************************************') %! disp('') %! disp(' Some deliberate AttributeError and ValueError may appear next') %! disp('') %! disp('v v v v v v v v v v v v v v v v v v v v v v v v') %! b = sym([], 'S.This_is_supposed_to_make_an_exception', [1 1], 'Test', 'Test', 'Test'); %! c = b + 1; %!test %! % ...and after the above test, the pipe should still work %! a = pycall_sympy__ ('return _ins[0]*2', 3); %! assert (isequal (a, 6)) %!test %! % This command does not fail with native interface and '@pyobject' %! s = warning ('off', 'OctSymPy:pythonic_no_convert'); %! try %! q = pycall_sympy__ ({'return type(int)'}); %! catch %! msg = lasterror.message; %! assert (~ isempty (regexp (msg, '.*does not know how to.*'))) %! end %! warning (s) %! disp('^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^') %! disp(' End of deliberate errors!') %! disp(' You should see "46/46" or "Passes 46 out of 46 tests" below') %! disp('**********************************************************************') %! % ...and after the above test, the pipe should still work %! a = pycall_sympy__ ('return _ins[0]*2', 3); %! assert (isequal (a, 6)) %!test %! % complex input %! [A, B] = pycall_sympy__ ('z = 2*_ins[0]; return (z.real,z.imag)', 3+4i); %! assert (A, 6) %! assert (B, 8) %!test %! % complex output %! z = pycall_sympy__ ('return 3+2j'); %! assert (z, 3+2i) %!error %! s = char ('abc', 'defgh', '12345'); %! r = pycall_sympy__ ('return _ins[0]', s); %!test %! r = pycall_sympy__ ('return len(_ins[0])', ''); %! assert (r == 0) %!test %! % ensure the 0x0 matrix in octave gets mapped to the empty list in python %! % @sym/subsasgn currently replies on this behaviour %! assert (pycall_sympy__ ('return _ins[0] == []', [])); %!test %! % ensure the empty string gets mapped to the empty string in python %! assert (pycall_sympy__ ('return _ins[0] == ""', '')); symbolic-3.1.1/inst/sympref.m0000644000000000000000000003260714405647405013064 0ustar %% Copyright (C) 2014-2020, 2022-2023 Colin B. Macdonald %% Copyright (C) 2017 NVS Abhilash %% Copyright (C) 2017 Mike Miller %% Copyright (C) 2022 Alex Vong %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypefn Command {} sympref @var{cmd} %% @deftypefnx Command {} sympref @var{cmd} @var{args} %% @deftypefnx Function {@var{r} =} sympref () %% @deftypefnx Function {@var{r} =} sympref (@var{cmd}) %% @deftypefnx Function {@var{r} =} sympref (@var{cmd}, @var{args}) %% Preferences for the Symbolic package. %% %% @code{sympref} can set or get various preferences and %% configurations. The various choices for @var{cmd} and %% @var{args} are documented below. %% %% Run @strong{diagnostics} on your system: %% @example %% @comment doctest: +SKIP %% sympref diagnose %% @print{} ... %% @end example %% %% %% @strong{Display} of syms: %% %% @example %% @group %% sympref display %% @result{} ans = unicode %% %% @end group %% @group %% syms x %% sympref display flat %% sin(x/2) %% @result{} (sym) sin(x/2) %% %% sympref display ascii %% sin(x/2) %% @result{} (sym) %% /x\ %% sin|-| %% \2/ %% %% sympref display unicode %% sin(x/2) %% @result{} (sym) %% ⎛x⎞ %% sin⎜─⎟ %% ⎝2⎠ %% %% sympref display default %% @end group %% @end example %% %% By default, a unicode pretty printer is used to display %% symbolic expressions. If that doesn't work (e.g., if you %% see @code{?} characters) then try the @code{ascii} option. %% %% %% @strong{Communication mechanism}: %% %% @example %% @group %% sympref ipc %% @result{} ans = default %% @end group %% @end example %% %% This default depends on your system. If you have loaded the %% @uref{https://gitlab.com/mtmiller/octave-pythonic, Pythonic package}, %% the default will be the @code{native} mechanism. %% Otherwise, typically the @code{popen2} mechanism will be used, %% which uses a pipe to communicate with Python. %% If that doesn't work, try @code{sympref ipc system} which is %% much slower, as a new Python process is started for each operation. %% %% Other options for @code{sympref ipc} include: %% @itemize %% @item @code{sympref ipc popen2}: force popen2 choice. %% @item @code{sympref ipc native}: use the @code{py} interface to %% interact directly with an embedded Python interpreter, e.g., %% provided by the Octave Pythonic package. %% @item @code{sympref ipc system}: construct a long string of %% the command and pass it directly to the python interpreter with %% the @code{system()} command. This typically assembles a multiline %% string for the commands, except on Windows where a long one-line %% string is used. %% @item @code{sympref ipc systmpfile}: output the python commands %% to a file in @code{tempdir} and then call that. %% For debugging, will not be supported long-term. %% @item @code{sympref ipc sysoneline}: put the python commands all %% on one line and pass to @code{python -c} using a call to @code{system()}. %% For debugging, will not be supported long-term. %% @end itemize %% %% Except for @code{native}, all of these communication interfaces %% depend on the current @strong{Python executable}, which can be queried: %% @example %% @comment doctest: +SKIP %% sympref python %% @result{} ans = python %% @end example %% Changing this might help if you've installed %% a local Python interpreter somewhere else on your system. %% The value can be changed by setting the environment variable %% @code{PYTHON}, which can be configured in the OS, or it can be %% set within Octave using: %% @example %% @comment doctest: +SKIP %% setenv PYTHON python3 %% setenv PYTHON $@{HOME@}/.local/bin/python %% setenv PYTHON C:\Python\python.exe %% sympref reset %% @end example %% If the environment variable is empty or not set, the package %% uses a default setting (often @code{python}). %% %% %% @strong{Reset}: reset the SymPy communication mechanism. This can be %% useful after an error occurs and the connection with Python %% becomes confused. %% %% @example %% @group %% sympref reset % doctest: +SKIP %% @end group %% @end example %% %% %% @strong{Default precision}: control the number of digits used by %% variable-precision arithmetic (see also the @ref{digits} command). %% %% @example %% @group %% sympref digits % get %% @result{} ans = 32 %% sympref digits 64 % set %% sympref digits default %% @end group %% @end example %% %% Be @strong{quiet} by minimizing startup and diagnostics messages: %% @example %% @group %% sympref quiet %% @result{} ans = 0 %% sympref quiet on %% sympref quiet default %% @end group %% @end example %% %% Report the @strong{version} number: %% %% @example %% @group %% sympref version %% @result{} 3.1.1 %% @end group %% @end example %% %% @seealso{sym, syms} %% @end deftypefn function varargout = sympref(cmd, arg) persistent settings if (isempty(settings)) settings = 42; sympref('defaults') end if (nargin == 0) varargout{1} = settings; return end if (isstruct (cmd)) assert (isequal (sort (fieldnames (cmd)), ... sort ({'ipc'; 'display'; 'digits'; 'quiet'})), ... 'sympref: structure has incorrect field names') settings = []; sympref ('quiet', cmd.quiet) sympref ('display', cmd.display) sympref ('digits', cmd.digits) sympref ('ipc', cmd.ipc) return end switch lower(cmd) case 'defaults' settings = []; settings.ipc = 'default'; sympref ('display', 'default') sympref ('digits', 'default') sympref ('quiet', 'default') case 'version' assert (nargin == 1) varargout{1} = '3.1.1'; case 'display' if (nargin == 1) varargout{1} = settings.display; else arg = lower (arg); if (strcmp (arg, 'default')) arg = 'unicode'; if (ispc () && (~isunix ())) % Unicode not working on Windows, Issue #83. arg = 'ascii'; end end assert(strcmp(arg, 'flat') || strcmp(arg, 'ascii') || ... strcmp(arg, 'unicode')) settings.display = arg; end case 'digits' if (nargin == 1) varargout{1} = settings.digits; else if (ischar(arg)) if (strcmpi(arg, 'default')) arg = 32; else arg = str2double(arg); end end arg = int32(arg); assert(arg > 0, 'precision must be positive') settings.digits = arg; end case 'snippet' warning ('OctSymPy:deprecated', ... 'Debugging mode "snippet" has been removed'); case 'quiet' if (nargin == 1) varargout{1} = settings.quiet; else if (strcmpi(arg, 'default')) settings.quiet = false; else settings.quiet = tf_from_input(arg); end end case 'python' if (nargin ~= 1) error('old syntax ''sympref python'' removed; use ''setenv PYTHON'' instead') end pyexec = getenv('PYTHON'); if (isempty(pyexec)) pyexec = defaultpython (); end varargout{1} = pyexec; case 'ipc' if (nargin == 1) varargout{1} = settings.ipc; else verbose = ~sympref('quiet'); sympref('reset') settings.ipc = arg; switch arg case 'default' msg = 'Choosing the default [autodetect] communication mechanism'; case 'native' msg = 'Forcing the native Python/C API communication mechanism'; case 'system' msg = 'Forcing the system() communication mechanism'; case 'popen2' msg = 'Forcing the popen2() communication mechanism'; case 'systmpfile' msg = 'Forcing systmpfile ipc: warning: this is for debugging'; case 'sysoneline' msg = 'Forcing sysoneline ipc: warning: this is for debugging'; otherwise msg = ''; if (~ ischar (arg)) arg = num2str (arg); end warning('OctSymPy:sympref:invalidarg', ... 'Unsupported IPC mechanism ''%s'': hope you know what you''re doing', ... arg) end if (verbose) disp(msg) end end case 'reset' verbose = ~sympref('quiet'); python_ipc_driver('reset', []); %case 'path' %pkg_path = fileparts (mfilename ('fullpath')); % or %pkg_l = pkg ('list'); %idx = strcmp ('octsympy', cellfun (@(x) x.name, pkg_l, 'UniformOutput', false)); %if (~ any (idx)) % error ('the package %s is not installed', your_pkg); %end %pkg_path = pkg_l{idx}.dir case 'diagnose' if (strcmp (lower (sympref ('ipc')), 'default') && ... exist ('pyversion') && exist ('pyexec') && exist ('pyeval')) % TODO: see note in ipc_native assert_pythonic_and_sympy (true) else assert_have_python_and_sympy (sympref ('python'), true) end otherwise error ('sympref: invalid preference or command ''%s''', lower (cmd)); end end function r = tf_from_input(s) if (~ischar(s)) r = logical(s); elseif (strcmpi(s, 'true')) r = true; elseif (strcmpi(s, 'false')) r = false; elseif (strcmpi(s, 'on')) r = true; elseif (strcmpi(s, 'off')) r = false; elseif (strcmpi(s, '[]')) r = false; else r = str2double(s); assert(~isnan(r), 'invalid expression to convert to bool') r = logical(r); end end %!shared sympref_orig %! sympref_orig = sympref (); %!test %! % test quiet, side effect of making following tests a bit less noisy! %! sympref quiet on %! a = sympref('quiet'); %! assert(a == 1) %% Test for correct line numbers in Python exceptions. These first tests %% happen with the default ipc---usually popen2. We don't explicitly test %% popen2 because test suite should be portable. %!error pycall_sympy__ ('raise ValueError'); %!error pycall_sympy__ ('raise ValueError', sym('x')); %!error pycall_sympy__ ('raise ValueError', sym([1 2 3; 4 5 6])); %!error pycall_sympy__ ('raise ValueError', {1; 1; 1}); %!error pycall_sympy__ ('raise ValueError', struct('a', 1, 'b', 'word')); %!error pycall_sympy__ ( {'x = 1' 'raise ValueError'} ); %!error pycall_sympy__ ( {'x = 1' 'pass' '1/0'} ); %!error pycall_sympy__ ( {'a=1' 'b=1' 'raise ValueError' 'c=1' 'd=1'} ); %% Test for correct line error in Python exceptions. %!error pycall_sympy__ ('raise ValueError'); %!error pycall_sympy__ ('raise ValueError', sym('x')); %!error pycall_sympy__ ('raise ValueError', sym([1 2 3; 4 5 6])); %!error pycall_sympy__ ('raise ValueError', {1; 1; 1}); %!error pycall_sympy__ ('raise ValueError', struct('a', 1, 'b', 'word')); %!error pycall_sympy__ ( {'x = 1' 'raise ValueError'} ); %!error <1/0> pycall_sympy__ ( {'x = 1' 'pass' '1/0'} ); %!error pycall_sympy__ ( {'a=1' 'b=1' 'raise ValueError' 'c=1' 'd=1'} ); %!test %! % system should work on all system, but just runs sysoneline on windows %! sympref('ipc', 'system'); %! syms x %!error pycall_sympy__ ('raise ValueError') %!error pycall_sympy__ ('raise ValueError', sym('x')) %!error pycall_sympy__ ('raise ValueError', struct('a', 1, 'b', 'word')) %!error pycall_sympy__ ({'a=1' 'b=1' 'c=1; raise ValueError' 'd=1'}); %!test %! % sysoneline should work on all systems %! sympref('ipc', 'sysoneline'); %! syms x %!error pycall_sympy__ ('raise ValueError') %!error pycall_sympy__ ('raise ValueError', struct('a', 1, 'b', 'word')) %!test %! sympref('ipc', 'systmpfile'); %! syms x %!error pycall_sympy__ ('raise ValueError') %!error pycall_sympy__ ('raise ValueError', struct('a', 1, 'b', 'word')) %!test %! s = warning ('off', 'OctSymPy:sympref:invalidarg'); %! sympref ('ipc', 'bogus'); %! assert (strcmp (sympref ('ipc'), 'bogus')) %! warning (s) %!error syms ('x') %!test %! sympref('defaults') %! assert(strcmp(sympref('ipc'), 'default')) %! sympref('quiet', 'on') %!test %! % restore sympref from structure %! old = sympref (); %! sympref ('display', 'ascii'); %! sympref ('digits', 64); %! old = orderfields (old); % re-ordering the fields should be ok %! sympref (old); %! new = sympref (); %! assert (isequal (old, new)) %!error %! s.a = 'hello'; %! s.b = 'world'; %! sympref (s) %!test %! syms x %! sympref('reset'); %! % restore original sympref settings %! sympref ('ipc', sympref_orig.ipc); %! syms x %! sympref ('quiet', sympref_orig.quiet); %!error sympref ('nosuchsetting') %!error sympref ('nosuchsetting', true) symbolic-3.1.1/inst/syms.m0000644000000000000000000001702714405647405012371 0ustar %% Copyright (C) 2014-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deffn Command syms %% @deffnx Command syms @var{x} %% @deffnx Command syms {@var{x} @var{y} @dots{}} %% @deffnx Command syms @var{f(x)} %% @deffnx Command syms {@var{x} @var{asm}} %% @deffnx Command syms {@var{x} @var{asm} @var{asm2} @dots{}} %% Create symbolic variables and symbolic functions. %% %% This is a convenience function. For example: %% @example %% syms x y z %% @end example %% instead of: %% @example %% @group %% x = sym('x'); %% y = sym('y'); %% z = sym('z'); %% @end group %% @end example %% %% The last arguments can provide one or more assumptions (type or %% restriction) on the variable (@pxref{sym}). %% @example %% @group %% syms x y z positive %% syms n positive even %% @end group %% @end example %% %% Symfuns represent abstract or concrete functions. Abstract %% symfuns can be created with @code{syms}: %% @example %% syms f(x) %% @end example %% Here @code{x} is created in the callers workspace, %% as a @strong{side effect}. %% %% Called without arguments, @code{syms} displays a list of %% all symbolic functions defined in the current workspace. %% @example %% @group %% syms x y z %% syms %% @print{} Symbolic variables in current scope: %% @print{} x %% @print{} y %% @print{} z %% @end group %% @end example %% %% Using @code{syms} to create a new symbol with different assumptions %% does not automatically replace instances of the old symbol in the %% caller's workspace. For example suppose we make an absolute value %% expression: %% @example %% @group %% syms x %% f = abs (x) %% @result{} f = (sym) │x│ %% @end group %% @end example %% If we make a new positive @code{x}, @code{f} still contains the old %% symbol: %% @example %% @group %% syms x positive %% simplify (f) %% @result{} (sym) │x│ %% @end group %% @end example %% Note: this behaviour is slightly different from Matlab's Symbolic %% Math Toolbox, which does change existing symbols. %% If that behaviour is desired, @pxref{@@sym/assume} which modifies %% existing expressions in the caller's workspace: %% @example %% @group %% syms x %% assume x positive %% f %% @result{} f = (sym) x %% @end group %% @end example %% %% Caution: On Matlab, you may not want to use @code{syms} within %% functions. %% In particular, if you shadow a function name, you may get %% hard-to-track-down bugs. For example, instead of writing %% @code{syms alpha} use @code{alpha = sym('alpha')} within functions. %% [https://www.mathworks.com/matlabcentral/newsreader/view_thread/237730] %% %% @seealso{sym, assume} %% @end deffn %% Author: Colin B. Macdonald %% Keywords: symbolic, symbols, CAS function syms(varargin) %% No inputs %output names of symbolic vars if (nargin == 0) S = evalin('caller', 'whos'); disp('Symbolic variables in current scope:') for i=1:numel(S) %S(i) if strcmp(S(i).class, 'sym') disp([' ' S(i).name]) elseif strcmp(S(i).class, 'symfun') % FIXME improve display of symfun disp([' ' S(i).name ' (symfun)']) end end return end %% Find assumptions valid_asm = assumptions('possible'); last = -1; for n=1:nargin assert(ischar(varargin{n}), 'syms: expected string inputs') if (ismember(varargin{n}, valid_asm)) if (last < 0) last = n - 1; end elseif (strcmp(varargin{n}, 'clear')) error ('OctSymPy:oldsyntax', ... 'Old "syms x clear" not supported; use "assume x clear" or "assume(x, ''clear'')"') elseif (last > 0) error('syms: cannot have symbols after assumptions') end end if (last < 0) asm = {}; exprs = varargin; elseif (last == 0) error('syms: cannot have only assumptions w/o symbols') else asm = varargin((last+1):end); exprs = varargin(1:last); end % loop over each input for i = 1:length(exprs) expr = exprs{i}; % look for parenthesis: check if we're making a symfun if (isempty (strfind (expr, '(') )) % no assert(isvarname(expr)); % help prevent malicious strings assignin('caller', expr, sym(expr, asm{:})) else % yes, this is a symfun assert(isempty(asm), 'mixing symfuns and assumptions not supported') % regex matches: abc(x,y), f(var), f(x, y, z), f(r2d2), f( x, y ) % should not match: Rational(2, 3), f(2br02b) assert(~isempty(regexp(expr, '^\w+\(\s*[A-z]\w*(,\s*[A-z]\w*)*\s*\)$')), ... 'invalid symfun expression') T = regexp (expr, '^(\w+)\((.*)\)$', 'tokens'); assert (length (T) == 1 && length (T{1}) == 2) name = T{1}{1}; varnames = strtrim (strsplit (T{1}{2}, ',')); vars = {}; for j = 1:length (varnames) % is var in the workspace? try v = evalin ('caller', varnames{j}); create = false; catch create = true; end % if var was defined, is it a symbol with the right name? if (~ create) if (~ isa (v, 'sym')) create = true; elseif (~ strcmp (v.flat, varnames{j})) create = true; end end if (create) v = sym (varnames{j}); assignin ('caller', varnames{j}, v); end vars{j} = v; end cmd = { 'f, vars = _ins' 'return Function(f)(*vars)' }; s = pycall_sympy__ (cmd, name, vars); sf = symfun(s, vars); assignin('caller', name, sf); end end end %!test %! %% assumptions %! syms x real %! x2 = sym('x', 'real'); %! assert (isequal (x, x2)) %!test %! % assumptions and clearing them on a symbol %! syms x real %! assert (~isempty (assumptions (x))) %! syms x %! assert (isempty (assumptions (x))) %!test %! % Note SMT would clear syms in existing expressions %! syms x real %! f = {x {2*x} cos(x/2)}; %! assert (~isempty (assumptions (f))) %! syms x %! % but we do not: this would have to toggle for pure SMT compat %! assert (~isempty (assumptions (f))) %! % assert (isempty (assumptions (f))) %!error %! syms x clear %!error %! syms x positive y %!error %! % this sometimes catches typos or errors in assumption names %! % (if you need careful checking, use sym not syms) %! syms x positive evne %!error %! syms positive integer %!test %! % does not create a variable called positive %! syms x positive integer %! assert (logical(exist('x', 'var'))) %! assert (~logical(exist('positive', 'var'))) %!test %! % Issue #885 %! syms S(x) I(x) O(x) %!test %! % Issue #290 %! syms FF(x) %! syms ff(x) %! syms Eq(x) %!test %! % Issue #290 %! syms beta(x) %!test %! syms x real %! syms f(x) %! assert (~ isempty (assumptions (x))) %!test %! syms x real %! f(x) = symfun(sym('f(x)'), x); %! assert (~ isempty (assumptions (x))) %! assert (~ isempty (assumptions (argnames (f)))) symbolic-3.1.1/inst/test_bugs.tst0000644000000000000000000001462714405647405013756 0ustar %% Copyright (C) 2014-2017 Colin B. Macdonald %% Copyright (C) 2016 Lagu %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% Tests % tests listed here are for current or fixed bugs. Could move % these to appropriate functions later if desired. %!test %! % Issue #5, scalar expansion %! a = sym(1); %! a(2) = 2; %! assert (isequal(a, [1 2])) %! a = sym([]); %! a([1 2]) = [1 2]; %! assert (isa(a, 'sym')) %! assert (isequal(a, [1 2])) %! a = sym([]); %! a([1 2]) = sym([1 2]); %! assert (isa(a, 'sym')) %! assert (isequal(a, [1 2])) %!test %! % "any, all" not implemented %! D = [0 1; 2 3]; %! A = sym(D); %! assert (isequal( size(any(A-D)), [1 2] )) %! assert (isequal( size(all(A-D,2)), [2 1] )) %!test %! % double wasn't implemented correctly for arrays %! D = [0 1; 2 3]; %! A = sym(D); %! assert (isequal( size(double(A)), size(A) )) %! assert (isequal( double(A), D )) %!test %! % in the past, inf/nan in array ctor made wrong matrix %! a = sym([nan 1 2]); %! assert (isequaln (a, [nan 1 2])) %! a = sym([1 inf]); %! assert( isequaln (a, [1 inf])) %!test %! % Issue #103: rot90, fliplr, flipud, flip on scalars %! % (In Octave, we do not need to overload these) %! syms x %! assert (isequal (rot90(x), x)) %! assert (isequal (rot90(x, 1), x)) %! assert (isequal (rot90(x, 17), x)) %! assert (isequal (fliplr(x), x)) %! assert (isequal (flipud(x), x)) %!test %! % Issue #103: rot90, fliplr, flipud, flip on vectors %! syms x %! h = [1 2 x]; %! v = [1; 2; x]; %! assert (isequal (rot90(h), flipud(v))) %! assert (isequal (rot90(h, 1), flipud(v))) %! assert (isequal (rot90(h, 2), fliplr(h))) %! assert (isequal (rot90(h, 3), v)) %! assert (isequal (rot90(h, 4), h)) %! assert (isequal (rot90(h, 17), rot90(h, 1))) %! assert (isequal (rot90(v), h)) %! assert (isequal (flipud(h), h)) %! assert (isequal (fliplr(v), v)) %! assert (isequal (fliplr(h), [x 2 1])) %! assert (isequal (flipud(v), [x; 2; 1])) %!test %! % Issue #103: rot90, fliplr, flipud, flip on matrices %! syms x %! A = [1 x 3; x 5 6]; %! assert (isequal (rot90(A), [sym(3) 6; x 5; 1 x])) %! assert (isequal (rot90(A, 2), [6 5 x; 3 x 1])) %! assert (isequal (rot90(A, 3), [x 1; 5 x; sym(6) 3])) %! assert (isequal (rot90(A, 4), A)) %! assert (isequal (flipud(A), [x 5 6; 1 x 3])) %! assert (isequal (fliplr(A), [3 x 1; 6 5 x])) %!test %! syms x %! h = [1 2 x]; %! v = [1; 2; x]; %! A = [1 x 3; x 5 6]; %! assert (isequal (flip(x), x)) %! assert (isequal (flip(x, 1), x)) %! assert (isequal (flip(x, 2), x)) %! assert (isequal (flip(h, 1), h)) %! assert (isequal (flip(h, 2), fliplr(h))) %! assert (isequal (flip(A, 1), flipud(A))) %! assert (isequal (flip(A, 2), fliplr(A))) %% Bugs still active % Change these from xtest to test and move them up as fixed. %%!test %%! % FIXME: in SMT, x - true goes to x - 1 %%! syms x %%! y = x - (1==1) %%! assert( isequal (y, x - 1)) %!xtest %! % Issue #8: array construction when row is only doubles %! % fails on: Octave 3.6.4, 3.8.1, 4.0.0, hg tip Dec 2015. %! % works on: Matlab %! try %! A = [sym(0) 1; 2 3]; %! failed = false; %! catch %! failed = true; %! end %! assert (~failed) %! assert (isequal(A, [1 2; 3 4])) %!test %! % boolean not converted to sym (part of Issue #58) %! y = sym(1==1); %! assert( isa (y, 'sym')) %! y = sym(1==0); %! assert( isa (y, 'sym')) %!test %! % Issue #9, nan == 1 should be bool false not "nan == 1" sym %! snan = sym(0)/0; %! y = snan == 1; %! assert (~logical(y)) %!test %! % Issue #9, for arrays, passes currently, probably for wrong reason %! snan = sym(nan); %! A = [snan snan 1] == [10 12 1]; %! assert (isequal (A, sym([false false true]))) %!test %! % these seem to work %! e = sym(inf) == 1; %! assert (~logical(e)) %!test %! % known failure, issue #55; an upstream issue %! snan = sym(nan); %! assert (~logical(snan == snan)) %% x == x tests % Probably should move to eq.m when fixed %!test %! % in SMT x == x is a sym (not "true") and isAlways returns true %! syms x %! assert (isAlways( x == x )) %!xtest %! % fails to match SMT (although true here is certainly reasonable) %! syms x %! e = x == x; %! assert (strcmp (strtrim(disp(e, 'flat')), 'x == x')) %!xtest %! % "fails" (well goes to false, which is reasonable enough) %! syms x %! e = x - 5 == x - 3; %! assert (strcmp (strtrim(disp(e, 'flat')), 'x - 5 == x - 3')) %%!test %%! % using eq for == and "same obj" is strange, part 1 %%! % this case passes %%! syms x %%! e = (x == 4) == (x == 4); %%! assert (isAlways( e )) %%! assert (logical( e )) %%!test %%! % using eq for == and "same obj" is strange, part 2 %%! syms x %%! e = (x-5 == x-3) == (x == 4); %%! assert (~logical( e )) %%! % assert (~isAlways( e )) %%!xtest %%! % using eq for == and "same obj" is strange, part 3 %%! % this fails too, but should be true, although perhaps %%! % only with a call to simplify (i.e., isAlways should %%! % get it right). %%! syms x %%! e = (2*x-5 == x-1) == (x == 4); %%! assert (isAlways( e )) %%! assert (islogical( e )) %%! assert (isa(e, 'logical')) %%! assert (e) %!xtest %! % SMT behaviour for arrays: if any x's it should not be logical %! % output but instead syms for the equality objects %! syms x %! assert (isequal ( [x x] == sym([1 2]), [x==1 x==2] )) %! assert (isequal ( [x x] == [1 2], [x==1 x==2] )) %! % FIXME: new bool means these don't test the right thing %! %assert (~islogical( [x 1] == 1 )) %! %assert (~islogical( [x 1] == x )) %! %assert (~islogical( [x x] == x )) % not so clear %!xtest %! % FIXME: symbolic matrix size, Issue #159 %! syms n m integer %! A = sym('A', [n m]); %! assert (isequal (size (A), [n m])) %!xtest %! % symbolic matrix, subs in for size, Issue #160 %! syms n m integer %! A = sym('A', [n m]); %! B = subs(A, [n m], [5 6]); %! assert (isa (B, 'sym')) %! assert (isequal (size (B), [5 6])) %! % FIXME: not same as an freshly created 5 x 6. %! C = sym('B', [5 6]); %! assert (isequal(B, C)) symbolic-3.1.1/inst/vpa.m0000644000000000000000000002210214405647405012152 0ustar %% Copyright (C) 2014-2019, 2021-2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defun vpa (@var{x}) %% @defunx vpa (@var{x}, @var{n}) %% Create a variable-precision floating point number. %% %% @var{x} can be a string, a sym or a double. Example: %% @example %% @group %% x = vpa('1/3', 32) %% @result{} x = (sym) 0.33333333333333333333333333333333 %% a = sym(1)/3; %% x = vpa(a, 32) %% @result{} x = (sym) 0.33333333333333333333333333333333 %% @end group %% @end example %% %% If @var{n} is omitted it defaults to the current value of %% @code{digits()}. %% %% Be careful when creating a high-precision float from a %% double as you will generally only get 15 digits: %% @example %% @group %% vpa(1/3) %% @result{} (sym) 0.3333333333333333148296162... %% vpa(sqrt(2)); %% ans^2 %% @result{} (sym) 2.0000000000000002734323463... %% @end group %% @end example %% %% For the same reason, passing numbers with decimal points %% may produce undesirable results: %% @example %% @group %% vpa(0.1) %% @result{} (sym) 0.1000000000000000055511151... %% @end group %% @end example %% %% Instead, enclose the decimal number in a string: %% @example %% @group %% vpa('0.1') %% @result{} (sym) 0.10000000000000000000000000000000 %% @end group %% @end example %% %% Very simple expressions can also be enclosed in quotes: %% @example %% @group %% vpa('sqrt(2)') %% @result{} (sym) 1.4142135623730950488016887242097 %% @end group %% @end example %% %% But be careful as this can lead to unexpected behaviour, such as %% low-precision results if the string contains decimal points: %% @example %% @group %% vpa('cos(0.1)') %% @print{} warning: string expression involving decimals is %% @print{} dangerous, see "help vpa"... %% @result{} ans = (sym) 0.99500416527802... %% @end group %% @end example %% %% Instead, it is preferrable to use @code{sym} or @code{vpa} on the %% inner-most parts of your expression: %% @example %% @group %% cos(vpa('0.1')) %% @result{} (sym) 0.99500416527802576609556198780387 %% vpa(cos(sym(1)/10)) %% @result{} (sym) 0.99500416527802576609556198780387 %% @end group %% @end example %% %% @seealso{sym, vpasolve, digits} %% @end defun function r = vpa(x, n) if (nargin == 1) n = digits(); elseif (nargin ~= 2) print_usage (); end if (isa(x, 'sym')) cmd = { 'x, n = _ins' 'return sympy.N(x, n),' }; r = pycall_sympy__ (cmd, x, n); elseif (ischar (x)) x = strtrim (x); isfpnum = ... ~isempty (regexp (x, '^[-+]*?[\d_]*\.[\d_]*(e[+-]?[\d_]+)?[ij]?$')); if (~isfpnum && ~isempty (strfind (x, '.'))) warning ('OctSymPy:vpa:precisionloss', ... 'string expression involving decimals is dangerous, see "help vpa"') end if (isfpnum && any (strcmp (x(end), {'i', 'j'}))) r = sym (1i)*vpa (x(1:end-1), n); return end if (any (strcmp (x, {'inf', 'Inf', '+inf', '+Inf'}))) x = 'S.Infinity'; elseif (strcmp (x, '-inf') || strcmp (x, '-Inf')) x = '-S.Infinity'; elseif (strcmp (x, 'I')) x = 'Symbol("I")'; elseif (any (strcmp (x, {'1i', '1j'}))) x = 'S.ImaginaryUnit'; end % Want Float if its '2.3' but N if its 'sqrt(2)' cmd = { 'x, n = _ins' 'try:' ' return sympy.Float(x, n),' 'except ValueError:' ' return sympy.N(x, n),' }; r = pycall_sympy__ (cmd, x, n); elseif (isfloat (x) && ~isreal (x)) r = vpa (real (x), n) + sym (1i)*vpa (imag (x), n); elseif (isfloat(x) && isscalar(x) == 1) if (isnan (x)) x = 'S.NaN'; elseif (isinf (x) && x < 0) x = '-S.Infinity'; elseif (isinf (x)) x = 'S.Infinity'; elseif (isequal (x, pi)) x = 'S.Pi'; elseif (isequal (x, -pi)) x = '-S.Pi'; elseif (isequal (x, exp (1))) x = exp (sym (1)); elseif (isequal (x, -exp (1))) x = -exp (sym (1)); end cmd = { 'x, n = _ins' 'return sympy.N(x, n)' }; r = pycall_sympy__ (cmd, x, n); elseif (isinteger(x) && isscalar(x) == 1) cmd = { 'x, n = _ins' 'return sympy.N(x, n),' }; r = pycall_sympy__ (cmd, x, n); elseif (~isscalar(x)) cmd = { sprintf('return sympy.ZeroMatrix(%d, %d).as_mutable(),', size(x)) }; r = pycall_sympy__ (cmd); for i=1:numel(x) r(i) = vpa(x(i), n); end else x class(x) error('conversion to vpa with those arguments not (yet) supported'); end end %!test %! a = vpa(0, 4); %! b = double(a); %! assert(b == 0) %!test %! a = vpa(pi, 4); %! b = sin(a); %! assert(abs(double(b)) < 1e-4) %!test %! % vpa from double is ok, doesn't warn (c.f., sym(2.3)) %! a = vpa(2.3); %! assert(true) %!test %! % vpa from double not more than 16 digits %! a = vpa(sqrt(pi), 32); %! b = sin(a^2); %! assert(abs(double(b)) > 1e-20) %! assert(abs(double(b)) < 1e-15) %!test %! a = vpa(sym(pi), 32); %! b = sin(a); %! assert(abs(double(b)) < 1e-30) %!test %! a = vpa(sym(pi), 256); %! b = sin(a); %! assert(abs(double(b)) < 1e-256) %!test %! % pi str %! a = vpa('pi', 32); %! b = sin(a); %! assert(abs(double(b)) < 1e-32) %!test %! % pi str %! a = vpa('pi', 32); %! b = vpa(sym('pi'), 32); %! assert (double (a - b) == 0) %!test %! spi = sym(pi); %! a = vpa(spi, 10); %! b = double(a); %! assert(~isAlways(spi == a)) %!test %! % matrix of sym %! a = [sym(pi) 0; sym(1)/2 1]; %! b = [pi 0; 0.5 1]; %! c = vpa(a, 6); %! assert(max(max(abs(double(c)-b))) < 1e-6) %!test %! % matrix of double %! b = [pi 0; 0.5 1]; %! c = vpa(b, 6); %! assert(max(max(abs(double(c)-b))) < 1e-6) %!test %! % integer type %! a = vpa(int32(6), 64); %! b = vpa(6, 64); %! assert (isequal (a, b)) %!test %! % matrix of int %! b = int32([pi 0; 6.25 1]); %! c = vpa(b, 6); %! assert (isequal (double(c), [3 0; 6 1])) %!test %! % can pass pi directly to vpa %! a = vpa(sym(pi), 128); %! b = vpa(pi, 128); %! assert (isequal (a, b)) %!test %! % if sym does sth special for e so should vpa %! a = vpa(sym(exp(1)), 64); %! b = vpa(exp(1), 64); %! assert (isequal (a, b)) %!test %! % can pass pi directly to vpa, even in array %! a = vpa(sym([2 pi]), 128); %! b = vpa([2 pi], 128); %! assert (isequal (a, b)) %!test %! % can pass i directly to vpa %! a = vpa(sym(i)); %! b = vpa(i); %!test %! % 'i' and 'I' just make vars %! a = vpa(sym(1i)); %! b = vpa('i'); %! c = vpa('I'); %! assert (~isequal (a, b)) %! assert (~isequal (a, c)) %!test %! % '1i' and '1j' strings %! a = vpa(sym(1i)); %! b = vpa('1i'); %! c = vpa('1j'); %! assert (isequal (a, b)) %! assert (isequal (a, c)) %!test %! % Issue #868, precision loss on '0.33j' %! a = vpa('0.33j', 40); %! b = vpa('0.33i', 40); %! assert (double (abs (imag (a)*100/33) - 1) < 1e-39) %! assert (isequal (a, b)) %!test %! % inf/-inf do not become symbol('inf') %! S = {'oo', '-oo', 'inf', 'Inf', '-inf', '+inf'}; %! for j = 1:length(S) %! a = vpa(S{j}); %! b = vpa(sym(S{j})); %! assert (isequal (a, b)) %! end %!test %! a = vpa('2.3', 20); %! s = strtrim(disp(a, 'flat')); %! assert (strcmp (s, '2.3000000000000000000')) %!test %! % these should *not* be the same %! a = vpa(2.3, 40); %! b = vpa('2.3', 40); %! sa = sympy (a); %! sb = sympy (b); %! assert (~isequal (a, b)) %! assert (abs(double(a - b)) > 1e-20) %! assert (abs(double(a - b)) < 1e-15) %! assert (~strcmp(sa, sb)) %!test %! % these should *not* be the same %! x = vpa('1/3', 32); %! y = vpa(sym(1)/3, 32); %! z = vpa(1/3, 32); %! assert (isequal (x, y)) %! assert (~isequal (x, z)) %!test %! % big integers %! a = int64(12345678); %! a = a*a; %! b = vpa(a); %! c = vpa('152415765279684'); %! assert (isequal (b, c)) %!test %! % big integers (workaround poor num2str, works in 4.0?) %! a = int64(1234567891); a = a*a; %! b = vpa(a); %! c = vpa('1524157877488187881'); %! assert (isequal (b, c)) %!warning vpa ('sqrt(2.0)'); %!warning %! if (pycall_sympy__ ('return Version(spver) > Version("1.4")')) %! a = vpa('2**0.5'); %! b = vpa(sqrt(sym(2))); %! assert (isequal (a, b)) %! else %! warning('dangerous') % fake it until we drop 1.4 %! end %!test %! a = vpa('2.3e1'); %! b = vpa(' 2.3e+1 '); %! assert (isequal (a, b)) %! a = vpa('21e-1'); %! b = vpa('2.1'); %! assert (isequal (a, b)) %!test %! % Issue #859, operations on immutable matrices %! x = vpa (sym ([1 2])); %! % If vpa no longer makes an ImmutableDenseMatrix, %! % may need to adjust or remove this test. %! assert (~ isempty (strfind (sympy (x), 'Immutable'))) %! y = sin(x); %! y2 = [sin(vpa(sym(1))) sin(vpa(sym(2)))]; %! assert (isequal (y, y2)) symbolic-3.1.1/inst/vpasolve.m0000644000000000000000000001132614405647405013231 0ustar %% Copyright (C) 2014-2019, 2022 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defun vpasolve (@var{e}) %% @defunx vpasolve (@var{e}, @var{x}) %% @defunx vpasolve (@var{e}, @var{x}, @var{x0}) %% Numerical solution of a symbolic equation. %% %% Variable-precision numerical solution of the equation @var{e} %% for variable @var{x} using initial guess of @var{x0}. %% %% Example: %% @example %% @group %% syms x %% eqn = exp(x) == x + 2; %% vpasolve(eqn, x, 0.1) %% @result{} (sym) 1.1461932206205825852370610285214 %% @end group %% @end example %% %% Systems of equations are supported: %% @example %% @group %% syms x y %% eqns = [y*exp(x) == 16; x^5 == x + x*y^2] %% @result{} eqns = (sym 2×1 matrix) %% %% ⎡ x ⎤ %% ⎢ y⋅ℯ = 16 ⎥ %% ⎢ ⎥ %% ⎢ 5 2 ⎥ %% ⎣x = x⋅y + x⎦ %% @end group %% %% @group %% vpasolve(eqns, [x; y], [1; 1]) %% @result{} (sym 2×1 matrix) %% %% ⎡1.7324062670465659633407456995303⎤ %% ⎢ ⎥ %% ⎣2.8297332667835974266598942031498⎦ %% @end group %% @end example %% %% Complex roots can be found but you must provide a complex initial %% guess: %% @example %% @group %% vpasolve(x^2 + 2 == 0, x, 1i) %% @result{} (sym) 1.4142135623730950488016887242097⋅ⅈ %% @end group %% @end example %% %% @seealso{vpa} %% @end defun function r = vpasolve(e, x, x0) if (nargin < 1 || nargin > 3) print_usage (); end if (nargin < 3) x0 = sym(0); end if (nargin < 2) x = symvar(e, 1); end n = digits(); % everything to column vector e = e(:); x = x(:); x0 = x0(:); if (isscalar (x0)) && (numel (x) >= 2) x0 = x0 * ones (size (x)); end % IPC cannot pass double matrices yet if (isnumeric (x0) && (numel (x0) > 1)) x0 = num2cell (x0); end cmd = { '(e, x, x0, n) = _ins' 'import mpmath' 'mpmath.mp.dps = n' 'r = nsolve(e, x, x0)' 'return r' }; r = pycall_sympy__ (cmd, sym(e), x, x0, n); end %!test %! syms x %! vpi = vpa(sym(pi), 64); %! e = tan(x/4) == 1; %! q = vpasolve(e, x, 3.0); %! w = q - vpi ; %! assert (double(w) < 1e-30) %!test %! syms x %! vpi = vpa(sym(pi), 64); %! e = tan(x/4) == 1; %! q = vpasolve(e, x); %! w = q - vpi; %! assert (double(w) < 1e-30) %! q = vpasolve(e); %! w = q - vpi; %! assert (double(w) < 1e-30) %!test %! % very accurate pi %! syms x %! e = tan(x/4) == 1; %! m = digits(256); %! q = vpasolve(e, x, 3); %! assert (double(abs(sin(q))) < 1e-256) %! digits(m); %!test %! % very accurate sqrt 2 %! syms x %! e = x*x == 2; %! m = digits(256); %! q = vpasolve(e, x, 1.5); %! assert (double(abs(q*q - 2)) < 1e-256) %! digits(m); %!test %! % very accurate sqrt pi %! % (used to fail https://github.com/sympy/sympy/issues/8564) %! syms x %! e = x*x == sym(pi); %! m = digits(256); %! q = vpasolve(e, x, 3); %! assert (double(abs(sin(q*q))) < 1e-256) %! digits(m); %!test %! syms x %! r = vpasolve(x^2 + 2 == 0, x, 1i); %! assert (double (imag(r)^2 - 2), 0, 1e-32) %! assert (double (real(r)^2), 0, 1e-32) %! r = vpasolve(x^2 + 2 == 0, x, -3i + 5); %! assert (double (imag(r)^2 - 2), 0, 1e-32) %! assert (double (real(r)^2), 0, 1e-32) %!test %! % system %! syms x y %! f = 3*x^2 - 2*y^2 - 1; %! g = x^2 - 2*x + y^2 + 2*y - 8; %! r = vpasolve([f; g], [x; y], sym([-1; 1])); %! assert (isa (r, 'sym')) %! assert (numel (r) == 2) %!test %! % system, double guess %! syms x y %! f = 3*x^2 - 2*y^2 - 1; %! g = x^2 - 2*x + y^2 + 2*y - 8; %! r = vpasolve([f; g], [x; y], [-1.1 1.2]); %!test %! % system, double guess %! syms x y %! f = 3*x^2 - 2*y^2 - 1; %! g = x^2 - 2*x + y^2 + 2*y - 8; %! r1 = vpasolve([f; g], [x; y], [-1.1]); %! r2 = vpasolve([f; g], [x; y], [-1.1 -1.1]); %! assert (isequal (r1, r2)) %!test %! % system, more eqns than unknowns %! syms x y %! eqns = [x^3 - x - y == 0; y*exp(x) == 16; log(y) + x == 4*log(sym(2))]; %! r = vpasolve (eqns, [x; y], [1; 1]); %! A = subs (lhs (eqns), [x; y], r); %! err = A - [0; 16; 4*log(sym(2))]; %! assert (double (err), zeros (size (err)), 1e-31) symbolic-3.1.1/matlab_smt_differences.md0000644000000000000000000001023714405647405015241 0ustar Differences between OctSymPy and the Symbolic Math Toolbox ========================================================== The Symbolic Math Toolbox (SMT) is proprietary software sold by The Mathworks. We want some minimal compatibility. This document notes the differences. Functions SMT has that OctSymPy does not have --------------------------------------------- > "Uh, all of them, I think." > --John Conner, 1995 That is, your help is needed here. Functions that OctSymPy has which SMT does not have --------------------------------------------------- These should be updated to match SMT if/when they are added. * fibonacci * isprime * nextprime * lhs/rhs * isconstant/isallconstant Differences ----------- * bernoulli in octsympy gives explicit polynomials whereas SMT treats e.g., diff() using identities. * SMT's sym() constructor allows big string expressions: we don't really support that (and its not the way modern SMT is used either). Build your expressions like sym('x')/2 rather than sym('x/2'). (If you do want to pass long strings, they should be valid Python SymPy `srepr` syntax---i.e., you probably don't want to do this!) * OctSymPy has [p,m] = factor(a) which returns an array of the prime factors and their multiplicities. Pure Matlab 'factor' has this but strangely SMT 'factor' does not. * Assumptions are quite different, although we fake quite a bit for compatibility, see section below. * SMT has isinf(x + oo) and isinf(x*oo) true. SymPy says false. * SMT logical(sym('x')), logical(sym(pi)) are errors. OctSymPy has true (b/c nonzero). FIXME: double-check later * SMT char(expr) outputs MuPAD code string; OctSymPy outputs SymPy string. * Suppose we have a symfun `g(s,t) = x`. Both SMT and OctSymPy agree that `symvar(g, 1)` is `s` (i.e., preference for the independent variables). However, `symvar(g)` gives `[s t x]` in OctSymPy and `x` in SMT. I suspect this is an SMT bug. At any rate, its probably better to use `argnames` and `symvar(formula)` if these sorts of subtlies are important to you. * SMT and OctSymPy differ in how the return solutions to systems of equation has multiple solutions. For example: `d = solve(x*x == 4, x == 2*y)` In OctSymPy, the two solutions are `d{1}` and `d{2}`. Components are accessed as `d{1}.x` (the x component of the first solution). In SMT, its the opposite: `d.x` gives the x component of both solutions as a column vector. I prefer our way (but this could be changed fairly easily.) `[X, Y] = solve(x*x == 4, x == 2*y)` does the same on both, returning column vectors for X and Y. * SMT sym2poly converts to a double array. We *currently* copy this behaviour but might change in the future. We recommend `double(sym2poly(x^2 + 3))` for clarity and compatibility. Our sym2poly also takes an optional extra argument to specify `x` which returns a symbolic row vector. * SMT fourier/ifourier/laplace/ilaplace have strange rules for determining a transform with respect to what variable. We just use symvar (that is, a preference for `x` over other variables like `t`). Differences in assumptions -------------------------- In OctSymPy, if you create a symbol with assumptions, those stay with any expressions and are not "updated" if you introduce a new symbol with the same expression. For example: ```` syms x positive x2 = sym('x', 'real') isequal(x,x2) % false ```` or ```` x = sym('x', 'positive') eqn = x^2 == 4 solve(eqn) % 2 x = sym('x') solve(eqn) % still 2, eqn has the old symbol solve(eqn,x) % empty: the variable in x is not the same as that in eqn. ```` Other notes: * SMT assumptions seem to be stored centrally: FIXME: double check that SMT functions do have their own assumptions workspace. * assume(), assumeAlso(), sym('x', 'clear'), "syms x clear". All of these muck around in the caller's workspace, traversing sym, struct and cell arrays to replace x with the new x. * in both OctSymPy and SMT, you can add assumptions when creating a sym as in sym('x', 'real') and sym('x', 'positive'). OctSymPy also supports others including 'integer', 'even', 'odd'. symbolic-3.1.1/misc/0000755000000000000000000000000014405647405011167 5ustar symbolic-3.1.1/misc/.oct-config0000644000000000000000000000001714405647405013216 0ustar encoding=utf-8 symbolic-3.1.1/misc/extract_tests_for_matlab.m0000644000000000000000000001004214405647405016424 0ustar % Copyright (C) 2014-2017 Colin B. Macdonald % % This file is part of OctSymPy. % % OctSymPy 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 software 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 software; see the file COPYING. % If not, see . function extract_tests_for_matlab() dirs = {'.', '@sym', '@symfun', '@double', '@logical'}; dirstr = {'', 'sym', 'symfun', 'double', 'logical'}; outdir = 'tests_matlab'; for j=1:length(dirs) files = dir(dirs{j}); for i=1:length(files) mfile = files(i).name; if ( (~files(i).isdir) && strcmp(mfile(end-1:end), '.m') ) %str = mfile(1:end-2); fprintf('>>> Looking for tests in: %s', mfile); tf = proc_file(dirs{j}, dirstr{j}, mfile, outdir); if tf fprintf('\t[done]\n'); else fprintf('\t[no tests]\n'); end end end end endfunction function r = proc_file(base, basestr, nm, outdir) %nm = 'symfun.m'; %base = '@symfun'; name_no_m = nm(1:end-2); in_name = [base '/' nm]; body = __extract_test_code(in_name); r = true; if isempty(body) r = false; return end %% process it a bit % Chop it up into blocks for evaluation. %__lineidx = find (__body == "\n"); %__blockidx = __lineidx(find (! isspace (__body(__lineidx+1))))+1; nl = sprintf('\n'); % add an extra newline to ensure final line has one body = [body nl]; ddot = 'fprintf(''.'')'; dskip = 'fprintf(''s'')'; body = regexprep(body, '^test\n', [nl ddot nl '%test' nl], 'lineanchors'); body = regexprep(body, '^test ', [nl ddot nl '%test' nl], 'lineanchors'); body = regexprep(body, '^assert', [nl ddot nl 'assert'], 'lineanchors'); body = regexprep(body, 'assert', 'octassert'); body = regexprep(body, '^(shared.*)\n', ['%$1' nl], 'lineanchors', 'dotexceptnewline'); % FIXME: better to put these inside appropriate try catch end" body = regexprep(body, '^xtest\n( [^\n]*\n)*', [nl dskip nl '%xtest' ... ' (**TEST EXPECTED TO FAIL: REMOVE**)' nl], 'lineanchors'); body = regexprep(body, '^error [^\n]+\n( [^\n]*\n)*', [nl dskip nl '%error' ... ' (**ERROR TEST: NOT SUPPORTED, REMOVED**)' nl], 'lineanchors'); body = regexprep(body, '^error\n( [^\n]*\n)*', [nl dskip nl '%error' ... ' (**ERROR TEST: NOT SUPPORTED, REMOVED**)' nl], 'lineanchors'); body = regexprep(body, '^warning [^\n]+\n( [^\n]*\n)*', [nl dskip nl '%warning' ... ' (**WARNING TEST: NOT SUPPORTED, REMOVED**)' nl], 'lineanchors'); % output it out_name = ['tests_' basestr '_' name_no_m]; full_out_name = [outdir '/' out_name '.m']; fid = fopen (full_out_name, 'w'); fprintf(fid, 'function %s()\n', out_name); fprintf(fid, '%%%% Auto extracted tests from %s\n', in_name); fprintf(fid, '%% This file autogenerated from the inline Octave tests\n'); fprintf(fid, '%% in the above file. Don''t modify directly.\n'); % FIXME: fprintf better than this schar thing? its for utf8 fwrite(fid, body, "schar"); fprintf(fid, '\n\n\n%%%% End of tests\n'); fprintf(fid, 'disp('' Passed'')\n'); fclose(fid); endfunction % This code from Octave source: /scripts/testfun/test.m % Copyright (C) 2005-2013 Paul Kienzle % GPL function body = __extract_test_code (nm) fid = fopen (nm, "rt"); body = ''; if (fid >= 0) while (! feof (fid)) ln = fgetl (fid); if (length (ln) >= 2 && strcmp (ln(1:2), "%!")) body = [body, "\n"]; if (length (ln) > 2) body = [body, ln(3:end)]; endif endif endwhile fclose (fid); endif endfunction symbolic-3.1.1/misc/my_print_usage.m0000644000000000000000000000272014405647405014373 0ustar %% Copyright (C) 2015 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @deftypefn {Function File} {} print_usage () %% Wrapper for print_usage on Matlab. %% %% Matlab has no print_usage function. Preparing %% the Matlab package should rename this from %% "my_print_usage.m" to "print_usage.m". %% %% @seealso{error} %% @end deftypefn function print_usage () % if we are on Octave if (exist ('OCTAVE_VERSION', 'builtin')) %evalin ('caller', 'print_usage ();' ); %return end H = dbstack; name = H(2).name; msgid = sprintf('%s:invalidCall', name); errmsg = sprintf('Invalid call to "%s": see documentation', name); %error('Invalid call to "%s": see documentation', name) ME = MException(msgid, errmsg); ME.throwAsCaller(); end symbolic-3.1.1/misc/octassert.m0000644000000000000000000000317214405647405013357 0ustar %% Copyright (C) 2016-2017 Colin B. Macdonald %% %% This file is part of OctSymPy. %% %% OctSymPy 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 software 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 software; see the file COPYING. %% If not, see . %% -*- texinfo -*- %% @documentencoding UTF-8 %% @defun octassert (@var{a},@var{b},@var{tol}) %% Wrapper for assert on Matlab. %% %% Octave's @code{assert} has this three-input version %% for testing either abs or rel tol. This only supports %% scalar @var{tol}: Octave can have a vector there. %% @end defun function octassert (varargin) if (exist ('OCTAVE_VERSION', 'builtin')) warning('why are you calling this on Octave? No need...') end if (nargin == 1) assert(varargin{1}); return elseif (nargin == 2) tol = 0; elseif (nargin == 3) tol = varargin{3}; else error('no such assert call with 4 inputs?') end a = varargin{1}; b = varargin{2}; a = a(:); b = b(:); assert (isscalar (tol)) if (tol < 0) % rel error assert (all (abs (a - b) <= abs (tol)*abs (b))) else % abs error assert (all (abs (a - b) <= abs (tol))) end end symbolic-3.1.1/misc/octsympy_tests_matlab.m0000644000000000000000000000321714405647405016001 0ustar % Copyright (C) 2014-2017 Colin B. Macdonald % % This file is part of OctSymPy. % % OctSymPy 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 software 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 software; see the file COPYING. % If not, see . addpath(pwd) base = 'tests_matlab'; files = dir(base); cd(base); % usually I'd just use cputime(), but some of our IPC mechanisms are % light on CPU and heavy on IO. totaltime = clock(); totalcputime = cputime(); num_tests = 0; % do tests in random order: %rng('shuffle') %for i=randperm(length(files)) for i=1:length(files) mfile = files(i).name; % detect tests b/c directory contains other stuff (e.g., surdirs and % helper files) if ( (~files(i).isdir) && strncmp(mfile, 'test', 4) && mfile(end) ~= '~') testtime = clock(); str = mfile(1:end-2); num_tests = num_tests + 1; fprintf(['>>> Running test(s) in: ' mfile ' ']); % no newline eval(str) testtime = etime(clock(), testtime); end end totaltime = etime(clock(),totaltime); totalcputime = cputime() - totalcputime; fprintf('\n***** Ran tests from %d files, %g seconds (%gs CPU) *****\n', ... num_tests, totaltime, totalcputime); cd('..') symbolic-3.1.1/octave-symbolic.metainfo.xml0000644000000000000000000000340014405647405015654 0ustar octave-symbolic www.octave.org-octave.desktop Symbolic Symbolic manipulation, calculus, variable precision arithmetic, and other computer algebra features

Adds symbolic calculation features to GNU Octave. These include common Computer Algebra System tools such as algebraic operations, calculus, equation solving, Fourier and Laplace transforms, variable precision arithmetic and other features. Compatibility with other symbolic toolboxes is intended.

symbolic computing computer algebra system CAS algebraic manipulation algebraic equation calculus transform solve variable precision arithmetic vpa sym Symbolic Math Toolbox https://octave.sourceforge.io/symbolic https://github.com/cbm755/octsympy/issues/new FSFAP GPL-3.0-or-later Octave-Forge Community octave-maintainers@gnu.org