GithubHelp home page GithubHelp logo

symengine / symengine Goto Github PK

View Code? Open in Web Editor NEW
1.1K 41.0 272.0 433.55 MB

SymEngine is a fast symbolic manipulation library, written in C++

Home Page: https://symengine.org

License: Other

Mathematica 0.53% C++ 92.09% CMake 4.68% C 1.31% Shell 0.41% Batchfile 0.01% Python 0.67% Yacc 0.17% Pawn 0.12%
math computer-algebra c-plus-plus

symengine's Introduction

SymEngine

Build and test symengine Build status codecov.io

SymEngine is a standalone fast C++ symbolic manipulation library. Optional thin wrappers allow usage of the library from other languages, e.g.:

Try SymEngine

Tutorials are at SymEngine.org.

Run an interactive C++ session with SymEngine using Binder.

License

All files are licensed under MIT license, see the LICENSE for more information. Third party code packaged are licensed under BSD 3-clause license (see the LICENSE file).

Mailinglist, Chat

SymEngine mailinglist: http://groups.google.com/group/symengine

Gitter

Installation

Conda package manager

conda install symengine -c conda-forge

Conan package manager

conan install --requires="symengine/[*]"

Building from source

Install prerequisites. For Debian based systems (Ubuntu etc.):

apt-get install cmake libgmp-dev

For RPM based systems (Fedora etc.):

yum install cmake gmp-devel

Install SymEngine:

mkdir build && cd build
cmake ..
make
make install

This will configure and build SymEngine in the default Release mode with all code and compiler optimizations on and then install it on your system.

Run tests:

ctest

Development

GitHub Actions checks the code in both Release and Debug mode with all possible checks, so just sending a GitHub pull request is enough and you can use any mode you want to develop it. However, the best way to develop SymEngine on Linux is to use the Debug mode with BFD support on:

cmake -DCMAKE_BUILD_TYPE=Debug -DWITH_BFD=yes ..

This BFD support turns on nice Python-like stack traces on exceptions, assert errors or segfaults, and the Debug mode automatically turns on WITH_SYMENGINE_RCP=no (which uses Teuchos::RCP with full Debug time checking) and WITH_SYMENGINE_ASSERT=yes, so the code cannot segfault in Debug mode, as long as our style conventions (e.g. no raw pointers) are followed, which is easy to check by visual inspection of a given Pull Request. In Release mode, which is the default, the code is as performing a manual reference counting and raw pointers (and if there is a bug, it could segfault, in which case all you have to do is to turn Debug mode on and get a nice exception with a stack trace).

To make WITH_BFD=yes work, you need to install binutils-dev first, otherwise, you will get a CMake error during configuring. For Debian-based systems (Ubuntu etc.)

apt-get install binutils-dev

For RPM-based systems (Fedora etc.)

yum install binutils-devel

On OpenSuSE, you will additionally need glibc-devel.

CMake Options

Here are all the CMake options that you can use to configure the build, with their default values are indicated below:

cmake -DCMAKE_INSTALL_PREFIX:PATH="/usr/local" \  # Installation prefix
    -DCMAKE_BUILD_TYPE:STRING="Release" \         # Type of build, one of: Debug or Release
    -DWITH_BFD:BOOL=OFF \                         # Install with BFD library (requires binutils-dev)s
    -DWITH_SYMENGINE_ASSERT:BOOL=OFF \            # Test all SYMENGINE_ASSERT statements in the code
    -DWITH_SYMENGINE_RCP:BOOL=ON \                # Use our faster special implementation of RCP
    -DWITH_SYMENGINE_THREAD_SAFE:BOOL=OFF \       # Build with thread safety
    -DWITH_ECM:BOOL=OFF \                         # Build with GMP-ECM library for integer factorization
    -DWITH_PRIMESIEVE:BOOL=OFF \                  # Install with Primesieve library
    -DWITH_FLINT:BOOL=OFF \                       # Install with Flint library
    -DWITH_ARB:BOOL=OFF \                         # Install with ARB library
    -DWITH_TCMALLOC:BOOL=OFF \                    # Install with TCMalloc linked
    -DWITH_OPENMP:BOOL=OFF \                      # Install with OpenMP enabled
    -DWITH_PIRANHA:BOOL=OFF \                     # Install with Piranha library
    -DWITH_MPFR:BOOL=OFF \                        # Install with MPFR library
    -DWITH_MPC:BOOL=OFF \                         # Install with MPC library
    -DWITH_LLVM:BOOL=OFF \                        # Build with LLVM libraries
    -DWITH_SYSTEM_CEREAL:BOOL=OFF \               # Build with cereal headers from the system instead of
                                                    the vendored copy
    -DBUILD_TESTS:BOOL=ON \                       # Build with tests
    -DBUILD_BENCHMARKS:BOOL=ON \                  # Build with benchmarks
    -DBUILD_BENCHMARKS_GOOGLE:BOOL=OFF \          # Build with Google Benchmark benchmarks
    -DINTEGER_CLASS:STRING=gmp \                  # Choose storage type for Integer. one of gmp, gmpxx,
                                                    flint, piranha, boostmp
    -DBUILD_SHARED_LIBS:BOOL=OFF \                # Build a shared library.
    -DCMAKE_INSTALL_RPATH_USE_LINK_PATH:BOOL=OFF\ # Add dependencies to rpath when a shared lib is built
    ..

If OpenMP is enabled, then SYMENGINE_THREAD_SAFE is also enabled automatically irrespective of the user input for WITH_SYMENGINE_THREAD_SAFE.

CMake prints the value of its options at the end of the run. If you want to use a different compiler, do:

CC=clang CXX=clang++ cmake ..

If you want to set additional compilation flags, do:

CXXFLAGS="$CXXFLAGS -march=native" cmake ..

These environment variables are checked only in the first run of cmake and you have to delete the build directory or CMakeCache.txt file for these environment variables to be picked up in subsequent runs.

Using INTEGER_CLASS=boostmp would remove the dependency on gmp and use boost's multiprecision integer and rational classes. This would make boost, the only dependency and all the code would be under permissive licenses, namely, MIT, BSD 3-clause and Boost License.

Piranha (WITH_PIRANHA) depends on Boost, so it is off by default. The benchmarked code seems to depend on the order in which you execute the benchmarks in a given executable, due to internal malloc implementation. We have found that this order dependence is reduced by enabling WITH_TCMALLOC=ON and since it also speeds the benchmarks up, we recommend to always use TCMalloc when benchmarking (and the Release mode of SymEngine, which is the default).

External Libraries

Use CMAKE_PREFIX_PATH to specify the prefixes of the external libraries.

cmake -DCMAKE_PREFIX_PATH=<prefix1>;<prefix2>

If the headers and libs are not in <prefix>/include and <prefix>/lib respectively, use CMAKE_LIBRARY_PATH and CMAKE_INCLUDE_PATH.

If CMake still cannot find the library, you can specify the path to the library by doing cmake -DPKG_LIBRARY=/path/libname.so ., where PKG should be replaced with the name of the external library (GMP, ARB, BFD, FLINT, MPFR, ...). Similarly, -DPKG_INCLUDE_DIR can be used for headers.

Recommended options to build

For package managers

For packaging symengine it is recommended to use GMP, MPFR, MPC, FLINT, LLVM as dependencies if they are available and built with thread safety on.

cmake -DWITH_GMP=on -DWITH_MPFR=on -DWITH_MPC=on -DINTEGER_CLASS=flint -DWITH_LLVM=on
-DWITH_SYMENGINE_THREAD_SAFE=on ..

Optimized build

To build with more optimizations, you can use the above dependencies and options, and also,

CXXFLAGS="-march=native -O3" cmake -DWITH_TCMALLOC=on -DWITH_SYMENGINE_THREAD_SAFE=no ..

Developer Documentation

Please follow the C++ Style Guide when developing.

The design decisions are documented in Design.

symengine's People

Contributors

0x6773 avatar abhinavagarwal07 avatar abinashmeher999 avatar ahumenberger avatar bjodah avatar cbehan avatar certik avatar char-chen avatar codemaxx avatar cqc-alec avatar haozeke avatar isuruf avatar ivme avatar jppelteret avatar lkeegan avatar marlin-na avatar myluszczak avatar nishnik avatar rajithv avatar ranjithkumar007 avatar rikardn avatar rwst avatar shikharj avatar shivamvats avatar srajangarg avatar sudowin avatar sumith1896 avatar sushant-hiray avatar thilinarmtb avatar upabjojr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

symengine's Issues

Do not overload the operators

Introduce functions for the arithmetic. Do not overload operators.

That can be an optional addition, but should not be on by default.

The problem is that if:

RCP<Basic> x = rcp(new Symbol("x"));
RCP<Basic> y = rcp(new Symbol("y"));

then the addition operator must access x+y (as opposed to (*x) + (*y)), because it needs to access the RCP pointers and be able to reference/dereference them.

But overloading RCP then clashes with the RCP implementation itself. So one should instead introduce functions
ADD(const RCP<Basic> &a, const RCP<Basic> &b). Possibly use some other naming convention.

warnings when compiling the Python code

Scanning dependencies of target csympy_wrapper
[100%] Building CXX object csympy/lib/CMakeFiles/csympy_wrapper.dir/csympy_wrapper.cpp.o
/Users/aaronmeurer/Documents/csympy/csympy/lib/csympy_wrapper.cpp:10825:28: warning: unused function '__Pyx_PyObject_AsString' [-Wunused-function]
static CYTHON_INLINE char* __Pyx_PyObject_AsString(PyObject* o) {
                           ^
/Users/aaronmeurer/Documents/csympy/csympy/lib/csympy_wrapper.cpp:10822:32: warning: unused function '__Pyx_PyUnicode_FromString' [-Wunused-function]
static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(char* c_str) {
                               ^
/Users/aaronmeurer/Documents/csympy/csympy/lib/csympy_wrapper.cpp:10944:33: warning: unused function '__Pyx_PyIndex_AsSsize_t' [-Wunused-function]
static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) {
                                ^
/Users/aaronmeurer/Documents/csympy/csympy/lib/csympy_wrapper.cpp:10973:33: warning: unused function '__Pyx_PyInt_FromSize_t' [-Wunused-function]
static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) {
                                ^
/Users/aaronmeurer/Documents/csympy/csympy/lib/csympy_wrapper.cpp:9806:32: warning: unused function '__Pyx_GetItemInt_List_Fast' [-Wunused-function]
static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i,
                               ^
/Users/aaronmeurer/Documents/csympy/csympy/lib/csympy_wrapper.cpp:10416:29: warning: function '__Pyx_PyInt_As_size_t' is not needed and will not be emitted [-Wunneeded-internal-declaration]
static CYTHON_INLINE size_t __Pyx_PyInt_As_size_t(PyObject *x) {
                            ^
/Users/aaronmeurer/Documents/csympy/csympy/lib/csympy_wrapper.cpp:10516:27: warning: function '__Pyx_PyInt_As_long' is not needed and will not be emitted [-Wunneeded-internal-declaration]
static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) {
                          ^
/Users/aaronmeurer/Documents/csympy/csympy/lib/csympy_wrapper.cpp:7430:18: warning: unused function '__pyx_convert_string_to_py_' [-Wunused-function]
static PyObject *__pyx_convert_string_to_py_(const std::string &__pyx_v_s) {
                 ^
8 warnings generated.
Linking CXX shared module csympy_wrapper.so
[100%] Built target csympy_wrapper

((x**3+x**2+x)**2).expand() is wrong

CSymPy gives:

In [6]: ((x**3+x**2+x)**2).expand()
Out[6]: 2x^5 + x^6 + x^2 + 2x^3 + 2x^4

while SymPy gives:

In [2]: ((x**3+x**2+x)**2).expand()
x**6 + 2*x**5 + 3*x**4 + 2*x**3 + x**2

This is caused by assigning into the dict directly if "x" is a symbol, but this approach fails if the x**3+x**2+x contains the same symbol with different powers.

Proper factorization using ECM

The factorization using ECM is only probabilistic (it uses a different elliptic curve each time). As such, the proper (minimal) algorithm to use it is as follows:

  • test that the number N is a prime
  • if not, choose the B1 parameter using a table from the README file in the ECM distribution
  • keep calling ecmfactor() with this B1 until it returns a non-trivial factor. Possibly if it doesn't return a factor in 10 calls or so, return an exception.

More complicated algorithm than this can of course be implemented.

Implement ways to handle general SymPy expressions

We need some kind of a general class, that could handle a pointer to a SymPy expression, so that one can pass in SymPy expressions and they would work. This should also work for general Julia expressions etc.

This will obviously be much slower than using native CSymPy expressions, but the advantage is that one can use advanced SymPy classes that are not yet implemented in CSymPy.

Port CSymPy to Python 3.2 and 3.3

And test this on Travis-CI. This requires modifying our CMake to work with the new print statement. Cython should probably work, and then we just need to make sure our testsuite works.

Try to use sparsehash

The sparsehash might be significantly faster than the std::map and std::unordered_map that we use. We should try it out on our benchmarks.

Use virtual functions instead of switches

Go over the code and change code of this type:

void Mul::as_base_exp(const RCP<Basic> &self, const Ptr<RCP<Basic>> &exp,
        const Ptr<RCP<Basic>> &base)
{
    if (is_a<Symbol>(*self)) {
        *exp = one;
        *base = self;
    } else if (is_a_Number(*self)) {
        *exp = one;
        *base = self;
    } else if (is_a<Pow>(*self)) {
        *exp = rcp_static_cast<Pow>(self)->exp_;
        *base = rcp_static_cast<Pow>(self)->base_;
    } else if (is_a<Add>(*self)) {
        *exp = one;
        *base = self;
    } else if (is_a_sub<Function>(*self)) {
        *exp = one;
        *base = self;
    } else {
        std::cout << "as_base_exp: " << *self << std::endl;
        throw std::runtime_error("Not implemented yet.");
    }
}

Into virtual functions calls. That should cleanup the code and speed things up considerably.

Two equal longer Mul compare unequal

e = Integer(3)/2 * cos(x**2)**(-2) * x * sin(x**2) * cos(3*x/4)
f = Integer(3)/2 * cos(x**2)**(-2) * x * sin(x**2) * cos(3*x/4)

Then

>>> e == f
False

They print differently too:

>>> e
3/2x*cos(3/4x)*cos(x^2)^-2*sin(x^2)
>>> f
3/2x*cos(x^2)^-2*cos(3/4x)*sin(x^2)

Out of tree build fails:

ondrej@kittiwake:~/repos/csympy(master)$ mkdir build
ondrej@kittiwake:~/repos/csympy(master)$ cd build/
ondrej@kittiwake:~/repos/csympy/build(master)$ cmake -DWITH_BFD=no ..
-- The C compiler identification is GNU 4.6.3
-- The CXX compiler identification is GNU 4.6.3
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Found GMP: /nh/nest/u/ondrej/repos/python-hpcmp2/local/lib/libgmpxx.so;/nh/nest/u/ondrej/repos/python-hpcmp2/local/lib/libgmp.so  


Configuration results
---------------------
C++ compiler: /usr/bin/c++
Build type: Debug
C++ compiler flags: -std=c++0x -Wall -Wextra -fPIC -g -Wno-unused-parameter -ggdb
Installation prefix: /usr/local
GMP_INCLUDE_DIRS: /nh/nest/u/ondrej/repos/python-hpcmp2/local/include
GMP_LIBRARIES: /nh/nest/u/ondrej/repos/python-hpcmp2/local/lib/libgmpxx.so;/nh/nest/u/ondrej/repos/python-hpcmp2/local/lib/libgmp.so
WITH_BFD: no
-- Configuring done
-- Generating done
-- Build files have been written to: /nh/nest/u/ondrej/repos/csympy/build
ondrej@kittiwake:~/repos/csympy/build(master)$ make
Scanning dependencies of target csympy
[  6%] Building CXX object src/CMakeFiles/csympy.dir/basic.cpp.o
In file included from /nh/nest/u/ondrej/repos/csympy/src/teuchos/Teuchos_RCPNode.hpp:52:0,
                 from /nh/nest/u/ondrej/repos/csympy/src/teuchos/Teuchos_RCPDecl.hpp:51,
                 from /nh/nest/u/ondrej/repos/csympy/src/teuchos/Teuchos_RCP.hpp:58,
                 from /nh/nest/u/ondrej/repos/csympy/src/basic.h:12,
                 from /nh/nest/u/ondrej/repos/csympy/src/basic.cpp:1:
/nh/nest/u/ondrej/repos/csympy/src/teuchos/Teuchos_ConfigDefs.hpp:52:28: fatal error: Teuchos_config.h: No such file or directory
compilation terminated.
make[2]: *** [src/CMakeFiles/csympy.dir/basic.cpp.o] Error 1
make[1]: *** [src/CMakeFiles/csympy.dir/all] Error 2
make: *** [all] Error 2

Jacobian calculation benchmark

Here is a real life problem (by @moorepants): https://gist.github.com/certik/10342153. Run b.py from that gist:

$ python b.py 
Reading
Done
Jacobian
Done
Time:  28.4419150352

It takes 28s on my laptop using SymPy. The benchmark reads the matrices from the file A.txt. You can generate the formulas in this file using a.py if you wish (you need to install https://github.com/pydy/pydy-code-gen/ for that), but for this benchmark, just the Jacobian calculation is important.

Mul gets a^0

In [13]: (2*a**(-2*x**2)) * (3*a**(2*x**2))
Out[13]: 6a^0

In [14]: type(_)
Out[14]: csympy.lib.csympy_wrapper.Mul

This is most probably caused by not checking for zero in Mul::dict_add_term:

        } else {
            // General case:
            it->second = add(it->second, exp);
        }

Fix printing of more complicated expressions

Parentheses:

For example:

In [5]: x+y -(x+y)
Out[5]: y + x + -1y + x

In [6]: _.expand()
Out[6]: 0

or

In [7]: x**y**z
Out[7]: x^y^z

+ or - signs:

In [13]: _.expand()
Out[13]: -2 + -2x + -2y

Pow

In [9]: a**(-2*x**2) * a**(3*x)
Out[9]: a^3x + -2x^2

In [10]: a**(-2*x**2) * a**(3*x**2)
Out[10]: a^x^2

In [11]: (x**2)*a
Out[11]: x^2*a

Add Travis tests for clang

Here is how to compile with clang 3.4 on Ubuntu:

CXX=clang cmake -DCMAKE_BUILD_TYPE=Debug -DWITH_CSYMPY_ASSERT=yes -DWITH_BFD=yes -DLIBS="stdc++ -lm" .

Notice the extra -DLIBS="stdc++ -lm" argument. Without it the linking fails. It'd be nice to figure out why this is needed. But more importantly, add a simple test to Travis, just to make sure it compiles with clang.

Speedup is_a<Integer>

By using static class variables and directly compare against them. That should be faster than using RTTI as we currently do.

What version Cython is required?

I have the latest version of Cython from the Ubuntu repo (0.17.4) and tried this:

$ cmake -DCMAKE_INSTALL_PREFIX="~/bin" -DWITH_PYTHON=yes .
-- The C compiler identification is GNU 4.7.3
-- The CXX compiler identification is GNU 4.7.3
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Found GMP: /usr/lib/x86_64-linux-gnu/libgmpxx.so;/usr/lib/x86_64-linux-gnu/libgmp.so  
-- Python version: 2.7
-- Python install path: /usr/lib/python2.7/dist-packages
-- Could NOT find PYTHON (missing:  PYTHON_LIBRARY) 
-- Found CYTHON: /usr/bin/cython
CMake Error at cmake/FindCython.cmake:39 (MESSAGE):
  Your Cython version is too old.  Please upgrade Cython.
Call Stack (most recent call first):
  CMakeLists.txt:94 (find_package)

Do I have to install a newer version of Cython? I usually keep the ubuntu repo version on my system and install Cython in virtualenvs if I need the latest and greatest, but I've always had trouble installing c/c++ apps with python wrappers in virtualenvs.

Cythonizing csympy_wrapper.pyx syntax error

Error compiling Cython file:
------------------------------------------------------------
...
        T& operator*() nogil except +
        # Not yet supported in Cython:
#        RCP[T]& operator=(RCP[T] &r_ptr) nogil except +
        void reset() nogil except +

    RCP[Symbol] rcp_static_cast_Symbol "Teuchos::rcp_static_cast<CSymPy::Symbol>"(const RCP[Basic] &b) nogil
                                                                                                  ^
------------------------------------------------------------

csympy.pxd:14:99: Expected ')', found '&'

Possible speedup of Symbol() comparsion

Currently we compare strings (!) for things like:

RCP<Basic> x1 = symbol("x");
RCP<Basic> x2 = symbol("x");
assert eq(x1, x2);

Possible improvements are for example only compare memory location, then x1 and x2 would compare unequal, and one would have to use the particular instance always. It's a design change, but it should make things faster.

Rename Dict_int to umap_basic_int

So that it is clear what exact map this is (umap = unordered_map). Because later on we need to create umap_basic_basic and also map_basic_basic.

Use SymPy to do the printing

CSymPy has (IMO) broken printing, e.g.,

In [6]: x = csympy.Symbol('x')

In [7]: 2*x
Out[7]: 2x

In [8]: 2x
  File "<ipython-input-8-2e585cac9259>", line 1
    2x
     ^
SyntaxError: invalid syntax

Instead of reinventing printing, it should just use SymPy's printing. At the very least it should use the SymPy printing architecture, which is very extensible to different kinds of printers.

Implement Julia wrappers

We need to fix #149 (C wrappers) first for this. Then the Julia wrapper would just call this using ccall and provide some nicer Julia interface.

Use DSW algorithm for balanced search trees

We currently use std::map for Muls. Since a typical Mul has just a few factors, it probably doesn't matter at all.

However, for Adds, the standard std::map seems slower than std::unordered_map, so we use the latter. std::map uses red-black trees, that balance the tree with every insertion. A better way might be to use the DSW algorithm, to only balance the tree once after it is constructed. Here is some implementation + benchmarking code. Here is another implementation. If it gets faster, maybe it can be used instead of std::unordered_map, because the advantage of using balanced search trees is that the items are sorted, which I think is essential for comparison and computing hashes.

Implement symbol() and integer()

These functions will do:

return rcp(new Symbol("x"));

That way the raw pointer handling is hidden from the user. These functions should be inlined.

Convert long from Python to C++

Currently:

In [1]: from csympy import *

In [2]: Integer(123434444444444444444)
---------------------------------------------------------------------------
OverflowError                             Traceback (most recent call last)
<ipython-input-2-387ab8ec74a4> in <module>()
----> 1 Integer(123434444444444444444)

/auto/nest/nest/u/ondrej/repos/csympy/csympy/lib/csympy_wrapper.so in csympy.lib.csympy_wrapper.Integer.__cinit__ (/nh/nest/u/ondrej/repos/csympy/csympy/lib/csympy_wrapper.cpp:4773)()

OverflowError: Python int too large to convert to C long

Enable x^y * z in Mul

Currently Mul can only handle integer exponents. Make it so that arbitrary exponents can be used.

Add seems to be fine with Integer coefficients, because if something is not an Integer, it is not a coefficient (except Rationals, which is #31).

Document how to do comparisons

You have to use

*x == *s

and not

x == s

Because the latter just compares the RCP objects directly. This is confusing and we should just use the __eq__ method directly and do not override the operators.

cmake/make errors on OS X w/ MacPorts python3.2

Using MacPorts python3.2, the print statements in FindPython.cmake need to be changed to use python3 style printing (using cmake -DWITH_PYTHON=yes .).

After modifying that, I got an error on running make, where

In file included from /Users/gilbertgede/Software/csympy/src/basic.cpp:1:
/Users/gilbertgede/Software/csympy/src/basic.h:12:10: fatal error: 
      'unordered_map' file not found
#include <unordered_map>

I think there needs to be a FindCXX11.cmake file? I'm not really familiar with cmake.

Also, ports I had to install were:
binutils
gmp
pyXX-cython (py32-cython in my case).

Go over the code and polish routines

After all arithmetic is in and works, we need to go over all the code and thing about it and polish things up. Some of the if statements in things like expand, mul etc. grew quite organically, and there might be a cleaner way to handle it.

Compilation failure (Teuchos related)

From master if I do mkdir build && cd build && cmake .. &> build.log && make VERBOSE=1 &>> build.log, I get the following in the build.log:

-- The C compiler identification is GNU 4.7.3
-- The CXX compiler identification is GNU 4.7.3
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done


Configuration results
---------------------
C++ compiler: /usr/bin/c++
Build type: Debug
C++ compiler flags: -std=c++0x -Wall -Wextra -fPIC -g -Wno-unused-parameter -ggdb
Installation prefix: /usr/local
-- Configuring done
-- Generating done
-- Build files have been written to: /home/luke/repos/csympy/build
/usr/bin/cmake -H/home/luke/repos/csympy -B/home/luke/repos/csympy/build --check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start /home/luke/repos/csympy/build/CMakeFiles /home/luke/repos/csympy/build/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
make[1]: Entering directory `/home/luke/repos/csympy/build'
make -f src/CMakeFiles/csympy.dir/build.make src/CMakeFiles/csympy.dir/depend
make[2]: Entering directory `/home/luke/repos/csympy/build'
cd /home/luke/repos/csympy/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/luke/repos/csympy /home/luke/repos/csympy/src /home/luke/repos/csympy/build /home/luke/repos/csympy/build/src /home/luke/repos/csympy/build/src/CMakeFiles/csympy.dir/DependInfo.cmake --color=
Dependee "/home/luke/repos/csympy/build/src/CMakeFiles/csympy.dir/DependInfo.cmake" is newer than depender "/home/luke/repos/csympy/build/src/CMakeFiles/csympy.dir/depend.internal".
Dependee "/home/luke/repos/csympy/build/src/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/home/luke/repos/csympy/build/src/CMakeFiles/csympy.dir/depend.internal".
Scanning dependencies of target csympy
make[2]: Leaving directory `/home/luke/repos/csympy/build'
make -f src/CMakeFiles/csympy.dir/build.make src/CMakeFiles/csympy.dir/build
make[2]: Entering directory `/home/luke/repos/csympy/build'
/usr/bin/cmake -E cmake_progress_report /home/luke/repos/csympy/build/CMakeFiles 1
[  6%] Building CXX object src/CMakeFiles/csympy.dir/basic.cpp.o
cd /home/luke/repos/csympy/build/src && /usr/bin/c++    -std=c++0x -Wall -Wextra -fPIC -g -Wno-unused-parameter -ggdb -I/home/luke/repos/csympy/src/teuchos    -o CMakeFiles/csympy.dir/basic.cpp.o -c /home/luke/repos/csympy/src/basic.cpp
/usr/bin/cmake -E cmake_progress_report /home/luke/repos/csympy/build/CMakeFiles 2
[ 12%] Building CXX object src/CMakeFiles/csympy.dir/dict.cpp.o
cd /home/luke/repos/csympy/build/src && /usr/bin/c++    -std=c++0x -Wall -Wextra -fPIC -g -Wno-unused-parameter -ggdb -I/home/luke/repos/csympy/src/teuchos    -o CMakeFiles/csympy.dir/dict.cpp.o -c /home/luke/repos/csympy/src/dict.cpp
/usr/bin/cmake -E cmake_progress_report /home/luke/repos/csympy/build/CMakeFiles 3
[ 18%] Building CXX object src/CMakeFiles/csympy.dir/symbol.cpp.o
cd /home/luke/repos/csympy/build/src && /usr/bin/c++    -std=c++0x -Wall -Wextra -fPIC -g -Wno-unused-parameter -ggdb -I/home/luke/repos/csympy/src/teuchos    -o CMakeFiles/csympy.dir/symbol.cpp.o -c /home/luke/repos/csympy/src/symbol.cpp
/usr/bin/cmake -E cmake_progress_report /home/luke/repos/csympy/build/CMakeFiles 4
[ 25%] Building CXX object src/CMakeFiles/csympy.dir/integer.cpp.o
cd /home/luke/repos/csympy/build/src && /usr/bin/c++    -std=c++0x -Wall -Wextra -fPIC -g -Wno-unused-parameter -ggdb -I/home/luke/repos/csympy/src/teuchos    -o CMakeFiles/csympy.dir/integer.cpp.o -c /home/luke/repos/csympy/src/integer.cpp
/usr/bin/cmake -E cmake_progress_report /home/luke/repos/csympy/build/CMakeFiles 5
[ 31%] Building CXX object src/CMakeFiles/csympy.dir/add.cpp.o
cd /home/luke/repos/csympy/build/src && /usr/bin/c++    -std=c++0x -Wall -Wextra -fPIC -g -Wno-unused-parameter -ggdb -I/home/luke/repos/csympy/src/teuchos    -o CMakeFiles/csympy.dir/add.cpp.o -c /home/luke/repos/csympy/src/add.cpp
/usr/bin/cmake -E cmake_progress_report /home/luke/repos/csympy/build/CMakeFiles 6
[ 37%] Building CXX object src/CMakeFiles/csympy.dir/mul.cpp.o
cd /home/luke/repos/csympy/build/src && /usr/bin/c++    -std=c++0x -Wall -Wextra -fPIC -g -Wno-unused-parameter -ggdb -I/home/luke/repos/csympy/src/teuchos    -o CMakeFiles/csympy.dir/mul.cpp.o -c /home/luke/repos/csympy/src/mul.cpp
/usr/bin/cmake -E cmake_progress_report /home/luke/repos/csympy/build/CMakeFiles 7
[ 43%] Building CXX object src/CMakeFiles/csympy.dir/pow.cpp.o
cd /home/luke/repos/csympy/build/src && /usr/bin/c++    -std=c++0x -Wall -Wextra -fPIC -g -Wno-unused-parameter -ggdb -I/home/luke/repos/csympy/src/teuchos    -o CMakeFiles/csympy.dir/pow.cpp.o -c /home/luke/repos/csympy/src/pow.cpp
Linking CXX static library libcsympy.a
cd /home/luke/repos/csympy/build/src && /usr/bin/cmake -P CMakeFiles/csympy.dir/cmake_clean_target.cmake
cd /home/luke/repos/csympy/build/src && /usr/bin/cmake -E cmake_link_script CMakeFiles/csympy.dir/link.txt --verbose=1
/usr/bin/ar cr libcsympy.a  CMakeFiles/csympy.dir/basic.cpp.o CMakeFiles/csympy.dir/dict.cpp.o CMakeFiles/csympy.dir/symbol.cpp.o CMakeFiles/csympy.dir/integer.cpp.o CMakeFiles/csympy.dir/add.cpp.o CMakeFiles/csympy.dir/mul.cpp.o CMakeFiles/csympy.dir/pow.cpp.o
/usr/bin/ranlib libcsympy.a
make[2]: Leaving directory `/home/luke/repos/csympy/build'
/usr/bin/cmake -E cmake_progress_report /home/luke/repos/csympy/build/CMakeFiles  1 2 3 4 5 6 7
[ 43%] Built target csympy
make -f src/teuchos/CMakeFiles/teuchos.dir/build.make src/teuchos/CMakeFiles/teuchos.dir/depend
make[2]: Entering directory `/home/luke/repos/csympy/build'
cd /home/luke/repos/csympy/build && /usr/bin/cmake -E cmake_depends "Unix Makefiles" /home/luke/repos/csympy /home/luke/repos/csympy/src/teuchos /home/luke/repos/csympy/build /home/luke/repos/csympy/build/src/teuchos /home/luke/repos/csympy/build/src/teuchos/CMakeFiles/teuchos.dir/DependInfo.cmake --color=
Dependee "/home/luke/repos/csympy/build/src/teuchos/CMakeFiles/teuchos.dir/DependInfo.cmake" is newer than depender "/home/luke/repos/csympy/build/src/teuchos/CMakeFiles/teuchos.dir/depend.internal".
Dependee "/home/luke/repos/csympy/build/src/teuchos/CMakeFiles/CMakeDirectoryInformation.cmake" is newer than depender "/home/luke/repos/csympy/build/src/teuchos/CMakeFiles/teuchos.dir/depend.internal".
Scanning dependencies of target teuchos
make[2]: Leaving directory `/home/luke/repos/csympy/build'
make -f src/teuchos/CMakeFiles/teuchos.dir/build.make src/teuchos/CMakeFiles/teuchos.dir/build
make[2]: Entering directory `/home/luke/repos/csympy/build'
/usr/bin/cmake -E cmake_progress_report /home/luke/repos/csympy/build/CMakeFiles 11
[ 50%] Building CXX object src/teuchos/CMakeFiles/teuchos.dir/Teuchos_dyn_cast.cpp.o
cd /home/luke/repos/csympy/build/src/teuchos && /usr/bin/c++    -std=c++0x -Wall -Wextra -fPIC -g -Wno-unused-parameter -ggdb   -o CMakeFiles/teuchos.dir/Teuchos_dyn_cast.cpp.o -c /home/luke/repos/csympy/src/teuchos/Teuchos_dyn_cast.cpp
/usr/bin/cmake -E cmake_progress_report /home/luke/repos/csympy/build/CMakeFiles 12
[ 56%] Building CXX object src/teuchos/CMakeFiles/teuchos.dir/Teuchos_Ptr.cpp.o
cd /home/luke/repos/csympy/build/src/teuchos && /usr/bin/c++    -std=c++0x -Wall -Wextra -fPIC -g -Wno-unused-parameter -ggdb   -o CMakeFiles/teuchos.dir/Teuchos_Ptr.cpp.o -c /home/luke/repos/csympy/src/teuchos/Teuchos_Ptr.cpp
/usr/bin/cmake -E cmake_progress_report /home/luke/repos/csympy/build/CMakeFiles 13
[ 62%] Building CXX object src/teuchos/CMakeFiles/teuchos.dir/Teuchos_RCPNode.cpp.o
cd /home/luke/repos/csympy/build/src/teuchos && /usr/bin/c++    -std=c++0x -Wall -Wextra -fPIC -g -Wno-unused-parameter -ggdb   -o CMakeFiles/teuchos.dir/Teuchos_RCPNode.cpp.o -c /home/luke/repos/csympy/src/teuchos/Teuchos_RCPNode.cpp
/usr/bin/cmake -E cmake_progress_report /home/luke/repos/csympy/build/CMakeFiles 14
[ 68%] Building CXX object src/teuchos/CMakeFiles/teuchos.dir/Teuchos_TestForException.cpp.o
cd /home/luke/repos/csympy/build/src/teuchos && /usr/bin/c++    -std=c++0x -Wall -Wextra -fPIC -g -Wno-unused-parameter -ggdb   -o CMakeFiles/teuchos.dir/Teuchos_TestForException.cpp.o -c /home/luke/repos/csympy/src/teuchos/Teuchos_TestForException.cpp
/usr/bin/cmake -E cmake_progress_report /home/luke/repos/csympy/build/CMakeFiles 15
[ 75%] Building CXX object src/teuchos/CMakeFiles/teuchos.dir/Teuchos_TypeNameTraits.cpp.o
cd /home/luke/repos/csympy/build/src/teuchos && /usr/bin/c++    -std=c++0x -Wall -Wextra -fPIC -g -Wno-unused-parameter -ggdb   -o CMakeFiles/teuchos.dir/Teuchos_TypeNameTraits.cpp.o -c /home/luke/repos/csympy/src/teuchos/Teuchos_TypeNameTraits.cpp
/usr/bin/cmake -E cmake_progress_report /home/luke/repos/csympy/build/CMakeFiles 16
[ 81%] Building CXX object src/teuchos/CMakeFiles/teuchos.dir/Teuchos_stacktrace.cpp.o
cd /home/luke/repos/csympy/build/src/teuchos && /usr/bin/c++    -std=c++0x -Wall -Wextra -fPIC -g -Wno-unused-parameter -ggdb   -fno-strict-aliasing -o CMakeFiles/teuchos.dir/Teuchos_stacktrace.cpp.o -c /home/luke/repos/csympy/src/teuchos/Teuchos_stacktrace.cpp
In file included from /home/luke/repos/csympy/src/teuchos/Teuchos_stacktrace.cpp:69:0:
/usr/include/bfd.h:37:2: error: #error config.h must be included before this header
make[2]: *** [src/teuchos/CMakeFiles/teuchos.dir/Teuchos_stacktrace.cpp.o] Error 1
make[2]: Leaving directory `/home/luke/repos/csympy/build'
make[1]: *** [src/teuchos/CMakeFiles/teuchos.dir/all] Error 2
make[1]: Leaving directory `/home/luke/repos/csympy/build'
make: *** [all] Error 2

Implement complex numbers

Probably the best way is to actually extend (i.e. subclass) our Number to allow complex Integers and complex Rationals. Because then the rest of the code can stay pretty much intact.

The other option is to implement a symbol I (like in SymPy), but then we need to implement the special arithmetic like I^2 = -1 and so on, which would probably complicate things.

Use valarray instead of vector in monomial_mul in monomials.cpp

Citing from [1]:

The vector described in §4.4.1 was designed to be a general
mechanism for holding values, to be flexible, and to fit into the
architecture of containers, iterators, and algorithms. However, it does
not support mathematical vector operations. Adding such operations
to vector would be easy, but its generality and flexibility precludes
optimizations that are often considered essential for serious numerical
work. Consequently, the standard library provides (in <valarray>) a
vector-like template, called valarray, that is less general and more
amenable to optimization for numerical computation

The usual arithmetic operations and the most common mathematical
functions are supported for valarrays.

[1] Stroustrup, B. (2013). The C++ Programming Language (4th ed., p. 1368). Addison-Wesley Professional.

Integer Factorization

I am wondering how the interfaces to the factorization should be provided.
It should be as simple as possible doing only the basic things. Would it be
heavy to do something like in sage, creating a Factorization class which
can later be reused in other domains like polynomial factorizations?

sage factorizations

Also, if we only use gmp-ecm it would be a prerequisite to install csympy
as gmp currently is. I think we will have to provide additional algorithms for
factorization if gmp-ecm is not installed.

Implement Rational

Currently, I think the easiest is to:

  • Rename Integer to Rational
  • Change mpz_class to mpq_class
  • Fix arithmetic in Rational, but that should be trivial.

We can add Integer later if needed. For now we need to make sure that arbitrary rational numbers work (in all exponents and coefficients).

Test installation properly

The CSymPy make install installation needs to work, both in C++ and with Python wrappers.

TODO:

  • Test that CSymPy C++ library can be properly installed and that it works
  • Run Travis Python tests after installing it
  • Decide if we want to support Python wrappers without installing it (currently this is the only way to use it)
  • Make sure the following works in virtualenv:
cmake -DCMAKE_INSTALL_PREFIX="$VIRTUAL_ENV"
make
make install

compiling fails on Mac (link.h missing)

When trying to compile csympy using clang, I run into the following issues:

I can't use libstdc++ (GNU STL), because it does not have unordered_map on OS X 10.9.
I can't use libc++ (clang STL), because it does not have link.h, which is needed by teuchos.

Implement trailing whitespace check

Just like in SymPy in sympy/utilities/tests/test_code_quality.py.

Not sure yet where we should put them, since it depends on Python. But the point is to run them once in Travis, so that we catch any trailing whitespace in PRs.

Implement Subs class

Implement Subs class, just like in SymPy to be able to do things like f(x^2).diff(x) -> 2*x*Subs(Derivative(f(_xi_1), _xi_1), _xi_1, x**2).

Fix ((x+1)**2).expand()

In [20]: ((x+1)**2).expand()
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-20-1e8e83ed507f> in <module>()
----> 1 ((x+1)**2).expand()

/home/ondrej/repos/csympy/csympy/lib/csympy_wrapper.so in csympy.lib.csympy_wrapper.Basic.expand (/home/ondrej/repos/csympy/csympy/lib/csympy_wrapper.cpp:2084)()

RuntimeError: multinomial_coefficients: m >= 2 must hold.

The problem is that it doesn't notice that the "1" is hidden in Add::coef_, it assumes that coef_==0.

.gitignore

There are a ton of untracked files after compiling. This project desperately needs a .gitignore.

diff of functions of one variable is needed for using csympy in mechanics

In [33]: a, b = dynamicsymbols('a b')

In [34]: a
Out[34]: a(t)

In [35]: type(a)
Out[35]: csympy.lib.csympy_wrapper.FunctionSymbol

In [36]: t = csympy.Symbol('t')

In [37]: type(t)
Out[37]: csympy.lib.csympy_wrapper.Symbol

In [38]: a.diff(t)
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-38-e96cdd2bca06> in <module>()
----> 1 a.diff(t)

/home/moorepants/src/csympy/csympy/lib/csympy_wrapper.so in csympy.lib.csympy_wrapper.Basic.diff (/home/moorepants/src/csympy/csympy/lib/csympy_wrapper.cpp:4098)()

RuntimeError: f(x).diff(x) not implemented yet.
> /home/moorepants/src/csympy/csympy_wrapper.pyx(154)csympy.lib.csympy_wrapper.Basic.diff (/home/moorepants/src/csympy/csympy/lib/csympy_wrapper.cpp:4098)()

This test (https://github.com/certik/csympy/blob/master/csympy/tests/test_functions.py) shows that it should work. I'm not sure what I'm doing wrong.

Implement Logic and basic Assumption classes

  • The basic logic classes, And, Or, Not, True, False. It may also be useful to have Implies and Equivalent. They should behave more or less exactly the way they do in SymPy.
  • A version of Q
  • The ability for things like Q.positive(expr) to be represented, where expr is a SymPy (not CSymPy) expression (see #153).

Fix printing of -x

Currently:

In [1]: from csympy import *

In [2]: var("x y z")
Out[2]: (x, y, z)

In [3]: -x
Out[3]: -1x

But it should print as -x.

Implement differentiating with respect to x^2

As reported by @thilinarmtb.

Probably this might not be important at this moment but I found that I can't do something like below.

In [34]: var("t")
Out[34]: t

In [35]: f = function_symbol("f", t**2)
In [37]: f.diff(t**2)
TypeError: Argument 'x' has incorrect type (expected csympy.lib.csympy_wrapper.Symbol, got csympy.lib.csympy_wrapper.Pow)

This is due to the fact that currently Derivative::diff only takes Symbols as arguments. Is this the intended behaviour? I checked with SymPy and If I am not mistaken SymPy doesn't do this kind of differentiation either.

>>>diff(sin(x), x**2)
Traceback (most recent call last): File "<string>", line 1, in <module> File "/base/data/home/apps/s~sympy-live-hrd/43.373169527249054993/sympy/sympy/core/function.py", line 1526, in diff return Derivative(f, *symbols, **kwargs) File "/base/data/home/apps/s~sympy-live-hrd/43.373169527249054993/sympy/sympy/core/function.py", line 925, in __new__ Can\'t differentiate wrt the variable: %s, %s''' % (v, count))) ValueError: Can't differentiate wrt the variable: x**2, 1

Wolfram-alpha doesn't execute this kind of derivatives but represent it in Leibniz notation. See here. Would it be okay at this moment to do something like below ?

In [1]: var("t")
Out[1]: t

In [2]: f = function_symbol("f", t**2)
In [3]: f.diff(t**2)
Out[3]: Derivative(f(t^2), t^2)

Here f doesn't necessarily need to be a function of t**2, it can be a function of t or a function of a function of t. Is there a reason to avoid this kind of derivatives?

Write and test good C wrappers for CSymPy

We need to figure out a good C API, which would probably just be lots of functions like basic_diff which would accept a pointer as a first argument, thus emulating our objects.

Then we need to test it, using C.

This will be very good for writing higher lever language wrappers, like Julia, Ruby, Matlab, ...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.