Sunday, August 23, 2015

GSoc 2015 Week 12 & 13

This week we announced the release of SymEngine on Sage list. For that, I made some changes into the build system for versioning and to use SymEngine from other C/C++ projects.
First, SymEngineConfig.cmake would output a set of flags, imported dependencies, etc. SymEngineConfigVersion.cmake would check that the version is compatible and if the 32/64-bitness is correct of the SymEngine project and the other CMake project. When SymEngine is only built, then these files would be at the root level and when installed they would be at /lib/cmake/symengine. An excerpt from the wiki page, I wrote at, https://github.com/sympy/symengine/wiki/Using-SymEngine-from-a-Cpp-project
Using SymEngine in another CMake project
To use SymEngine from another CMake project include the following in yourCMakeLists.txt file
find_package(SymEngine 0.1.0 CONFIG)
You can give the path to the SymEngine installation directory if it was installed to a non standard location by,
find_package(SymEngine 0.1.0 CONFIG PATHS /path/to/install/dir/lib/cmake/symengine)
Alternatively, you can give the path to the build directory.
find_package(SymEngine 0.1.0 CONFIG PATHS /path/to/build/dir)
An example project would be,
cmake_minimum_required(VERSION 2.8)
find_package(symengine 0.1.0 CONFIG)
set(CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE} "-std=c++0x")

include_directories(${SYMENGINE_INCLUDE_DIRS})
add_executable(example main.cpp)
target_link_libraries(example ${SYMENGINE_LIBRARIES})
More options are here
Using SymEngine in Non CMake projects
You can get the include flags and link flags needed for SymEngine using the command line CMake.
compile_flags=`cmake --find-package -DNAME=SymEngine -DCOMPILER_ID=GNU -DLANGUAGE=CXX -DMODE=COMPILE`
link_flags=`cmake --find-package -DNAME=SymEngine -DCOMPILER_ID=GNU -DLANGUAGE=CXX -DMODE=LINK`

g++ $compile_flags main.cpp $link_flags
Python wrappers
There was a suggestion to make the Python wrappers separate, so that in a distribution like Gentoo, the package sources can be distributed separately.
So, I worked on the Python wrappers to get them to be built independently or with the main repo. Now, the python wrappers directory along with the setup.py file from the root folder can be packaged and they would work without a problem.

Saturday, August 15, 2015

GSoC week 10 and 11

symengine-0.1.0 beta version was released this week and these two weeks were spent on making sure symengine works without a problem on Sage.

One issue was the linking of the python libraries in Sage. In binary releases of sage, the variable distutils.sysconfig.get_config_var('LIBDIR')  is wrong. It is set to the build machine's location. In Windows this is set to empty. Earlier, to link the python libraries into the python wrappers, python library was found using the above variable, but in some cases like Sage and Windows this method fails. To fix this, CMake now looks in `sys.prefix`/libs and `sys.prefix`/lib as well to find the python libraries.

Another issue that came up was cmake generating bad link flags. When installing in Sage, it is important to make sure the libraries in Sage are linked and not the system wide libraries. To do that libraries were searched for in the sage directories ignoring the system wide libraries. When given the full path of the libraries to link, we noticed a strange behaviour. `/path/to/sage/local/lib/libgmp.so` was changed to `-lgmp` causing the linker to pick up the system-wide gmp library. 

After reading through CMake documentation, I realized that this was due to `find_library` giving wrong locations of system libraries where there are multiple libraries of the same name for different architectures. For example if the output of `find_library(math NAMES m)` was given to find the standard math library, it may find a `libm.so` that was intended for a different architecture. Therefore when cmake realizes that the library being linked to is a system library then the full path is converted to `-lm` to delegate the task to the linker to find the correct library. 

This behaviour is useful for some scenarios, but in our case, this was not the behaviour I needed. Fortunately there was a workaround for this mentioned in the documentation. Using IMPORTED target feature in CMake, I was able to get CMake to use the full path of the library.

R7 and R8 benchmarks from symbench benchmarks of sage were added to benchmark SymEngine-C++ against GiNaC and also SymEngine-Python against SymPy and Sage.

Saturday, July 25, 2015

GSoC Week 8 and 9

These two weeks me and Ondrej started adding support for different compilers.

I added support for MinGW and MinGW-w64. There were some documented, but not yet fixed bugs in MinGW that I encountered. When including cmath, there were errors saying `_hypot` not defined, and `off64_t` not defied. I added flags `-D_hypot=hypot -Doff64_t=_off64_t` to fix this temporarily. With that symengine was successfully built.

For python wrappers in windows, after building there was a wrapper not found error which was the result of not having the extension name as pyd in windows. Another problem faced was that, python distribution's `libpython27.a` for x64 was compiled for 32 bit architecture and there were linking errors. I found some patched files at http://www.lfd.uci.edu/~gohlke/pythonlibs/#libpython and python wrappers were built successfully. Also added continuous integration for MinGW using appveyor.

With MinGW, to install gmp all you had to do was run the command `mingw-get install mingw32-gmp`. For MinGW-w64, I had to compile gmp. For this appveyor came in handy. I started a build in appveyor, stopped it and then logged into the appveyor machine remotely using `remmina` (Each VM was shutdown after 40 minutes. Within that 40 minutes you can login and debug the building). I compiled gmp using msys and mingw-w64 and then downloaded them to my machine. For appveyor runs, these pre-compiled binaries of gmp were used to test MinGW-w64

Ondrej and I worked together to make sure SymEngine could be built using MSVC in Debug mode. Since gmp couldn't be used out of the box in MSVC, we used MPIR project's sources which included visual studio project files. MPIR is a fork of GMP and provides MSVC support. We used it to build SymEngine in MSVC. Later I added support for Release mode and also added continuous integration for both build types and platform types.

Python extension can also be built with MSVC. We are testing the Python extensions in Release mode only right now, because appveyor has only python release mode libraries and therefore when building the extension in Debug mode it gives an error saying python27_d.lib is not found.

I also improved the wrappers for Matrix by adding `__getitem__` and `__setitem__` so that the matrices can be used easily in Python.

Another improvement to SymEngine was the automatic simplification of expressions like `0.0*x` and `x**0.0`. These expressions are not simplified more in master, so I 'm proposing a patch to simplify them to `0.0` and `1.0` respectively.

Monday, July 13, 2015

GSoC Week 7

This week I worked on the Sage wrappers and Python wrappers. To make it easier to try out symengine, I made changes to the sage wrappers such that if sage does not have symengine_conversions methods, (i.e. sage not updated to the symengine branch) then conversions would be done via python strings. For example, an integer is converted to a Python string and then to a Sage integer. This is slow, but makes it easier to install symengine. You can try it out by downloading cmake-3.2.3.spkg and symengine-0.1.spkg and installing them. (Link to download is .....) To install type

sage -i /path/to/cmake-3.2.3.spkg

sage -i /path/to/symengine-0.1.spkg

Python wrappers included only a small amount of functions from SymEngine. Wrappers were added to functions like log, trigonometric functions, hyperbolic functions and their inverses.

CMake package for Sage is now ready for review, http://trac.sagemath.org/ticket/18078.

SymEngine package for Sage can be found here, https://github.com/isuruf/sage/tree/symengine. A PR would be sent as soon as CMake ticket is positively reviewed.

Next week, testing with Sage, Python docstrings, SymEngine package for Sage are the main things that I have planned for now. Also a PyNumber class to handle python numbers would be started as well.

Friday, July 3, 2015

GSoC Week 6

This week, I worked on improving the testing and making Sage wrappers. First, building with Clang had several issues and they were not tested. One issue was a clang bug when `-ffast-math` optimization is used. This flag would make floating point arithmetic perform better, but it may do arithmetic not allowed by the IEEE floating point standard. Since it performs faster we have enabled it in Release mode and due to a bug in clang, a compiler error is given saying  error: unknown type name '__extern_always_inline' . This was fixed by first checking if the error is there in cmake and then adding a flag D__extern_always_inline=inline. Another issue was that type_traits header was not found. This was fixed by upgrading the standard C++ library, libstdc++

This week, I finished the wrappers for Sage. Now converters to and from sage can be found at sage.symbolic.symengine. For this module to convert using the C++ level members, symengine_wrapper.pyx 's definitions of the classes were taken out and declared in symengine_wrapper.pxd and implemented in pyx file. To install symengine in sage, https://github.com/sympy/symengine/issues/474 has to be resolved. A cmake check will be added to find whether this issue exists and if so, then the flag -Wa,-q will be added to the list of flags. We have to make a release of symengine if we were to make spkg's to install symengine in Sage, so some of my time next week will involve getting symengine ready for a release and then making spkgs for everyone to try out symengine.

Friday, June 26, 2015

GSoC Week 5

This week, I looked into installing SymEngine in Sage and wrappers. One issue was that we have a header named `complex.h` and some libraries look inside `$SAGE_LOCAL/include` for the C header `complex` and this leads to errors. It was decided to install symengine headers inside a folder called `symengine` so that a header could be accessed by `symengine/basic.h` form and it avoids clashes.

I looked at other libraries for how this is done. Some libraries have the installing headers in a separate folder like `include/project_name`, but `.cpp`s under `src`. Some libraries have headers and source files in the same folder and they are included in `project_name` folder. Since SymEngine has headers and sources in the same folder, we decided to rename `src` to `symengine`. This lead to another problem. Python wrappers folder was named `symengine`. So I moved them to `symengine/python/symengine` to enable using symengine python wrappers inside the build directory (although you have to change directory into `symengine/python` to use it).

Some other work involved, making sure `make install` installed all the python tests and installing dependencies in Travis-ci without using sudo.

That's all the updates for this week. Mid evaluations are coming this week, so I hope to get a SymEngine spkg done this week.

Saturday, June 20, 2015

GSoC 2015 - Week 4

This week I got access to OS X, so I decided to do all the work related to OS X this week while I had access. First of all, I worked on getting CMake to build on Sage in OS X 10.10. CMake is supported to be built using clang on OS X and is not supporting gcc. Since sage uses gcc for building packages, I tried building CMake on Sage. (Thanks to +Rajith for giving me the chance to work on his Mac).

Main problem with CMake in OSX 10.10 was that it uses an Apple header <CoreFoundation/CoreFoundation.h> which is a collection of headers including <CoreFoundation/CFStream.h> which in turn includes a faulty Apple header '/usr/local/include/dispatch/dispatch.h'. After going through CMake code, it seemed that although the header 'CoreFoundation.h' was included 'CFStream.h' was not needed. So I used the specific headers needed (<CoreFoundation/CFBundle.h> etc.) and CMake was successfully built on Sage. Testing the CMake installation resulted in 6 out of 387 tests failing.

Another good news was that we got access to test SymEngine on TravisCI with OSX. We are testing clang and gcc both to make sure, symengine builds on both. Building with clang was successful, but with gcc there were couple of problems and was hard to check on TravisCI as there were huge queuing times for builds on OSX.

One issue is that on OSX, gmp library we are linking to is installed by homebrew. g++ was using a different C++ standard library than what gmp was compiled with and hence linking errors occur. A CMake check was added to try to compile a simple program with gmpxx and if it fails, give an error message at configuration time.

Another issue was that `uint` was used in some places instead of `unsigned int`. On Linux and OSX clang `unsigned int` was typedef as `uint`, so there was no problem detected in automated tests in Travis-CI. Since `uint` is not a C++ standard type, it was changed to `unsigned int`.

Next week, I will try to figure out why 6 tests in CMake test suite fails and try to fix those and get CMake into optional packages. Also I will work on the wrappers for sage for SymEngine.

Sunday, June 14, 2015

GSoC 2015 : Week 3

This week, I continued my work from the previous two weeks to complete the floating point support for SymEngine.

RealDouble was the wrapper for double used in SymEngine and it used to return NaN for numerical evaluations that resulted in a complex number. Checks were added to ensure that if the result was complex, a ComplexDouble was returned. So now, `asin` for RealDouble looks like this

    virtual RCP<const Basic> asin(const Basic &x) const {
        SYMENGINE_ASSERT(is_a<RealDouble>(x))
        double d = static_cast<const RealDouble &>(x).i;
        if (d <= 1.0 && d >= -1.0) {
            return number(std::asin(d));
        } else {
            return number(std::asin(std::complex<double>(d)));
        }
    }

Here, when the result is a double, a RealMPFR is returned, while when it is complex, RealDouble is converted to std::complex<double>, evaluated and then a ComplexDouble is returned.

Implementing RealMPFR took more time than I thought, because of several design decisions that were needed to be taken.

Basic classes in SymEngine are immutable classes. So, when constructing a RealMPFR class, the mpfr_t value has to be passed into the RealMPFR's constructor. Which means when working with RealMPFR, we would first construct a mpfr_t, initialize it, set a value to the mpfr_t and then construct the RealMPFR. Therefore when exceptions are raised and caught, memory leaks happen, because the mpfr_t is not managed. This is also in EvalMPFR class where if we had an expression like 3 + x that we want to evaluate numerically, but when trying to evaluate x numerically, an exception is raised and a memory leak happens. Solution was to implement a managed mpfr_class that acts like mpz_class. 

To avoid adding a new dependency, I implemented a simple mpfr_class that would manage the mpfr_t inside it. 

class mpfr_class {
private:
    mpfr_t mp;
public:
    mpfr_ptr get_mpfr_t() { return mp; }
    mpfr_srcptr get_mpfr_t() const { return mp; }
    mpfr_class(mpfr_t m) {
        mpfr_init2(mp, mpfr_get_prec(m));
        mpfr_set(mp, m, MPFR_RNDN);
    }
    mpfr_class(mpfr_prec_t prec = 53) {
        mpfr_init2(mp, prec);
    }
mpfr_class(const mpfr_class& other) { mpfr_init2(mp, mpfr_get_prec(other.get_mpfr_t())); mpfr_set(mp, other.get_mpfr_t(), MPFR_RNDN); } mpfr_class(mpfr_class&& other) { mp->_mpfr_d = nullptr; mpfr_swap(mp, other.get_mpfr_t()); } mpfr_class& operator=(const mpfr_class& other) { mpfr_set_prec(mp, mpfr_get_prec(other.get_mpfr_t())); mpfr_set(mp, other.get_mpfr_t(), MPFR_RNDN); return *this; } mpfr_class& operator=(mpfr_class&& other) { mpfr_swap(mp, other.get_mpfr_t()); return *this; } ~mpfr_class() { if (mp->_mpfr_d != nullptr) { mpfr_clear(mp); } } };

To add the move constructors and destructors, it was needed to know if a mpfr_class has been initialized or not. This was achieved by setting _mpfr_d pointer to null when move constructor is called to avoid adding a data member to mpfr_class. Thanks to +Ondřej Čertík  and +Francesco Biscani  for the ideas and comments. 

Similarly an mpc_class was introduced to manage a mpc_t object. Another decision taken was to use a default rounding mode for rounding when operations on RealMPFR's and ComplexMPC's are done.

When adding two RealMPFR's of different precisions, it was decided to promote the RealMPFR with low precision to higher precision. An example of this is given below.

RCP<const Number> RealMPFR::addreal(const RealMPFR &other) const {
    mpfr_class t(std::max(get_prec(), other.get_prec()));
    mpfr_add(t.get_mpfr_t(), i.get_mpfr_t(), other.i.get_mpfr_t(), MPFR_RNDN);
    return rcp(new RealMPFR(std::move(t)));
}
To add SymEngine into Sage, I had to add CMake into Sage as well, since CMake is a dependency of SymEngine. Problem with including CMake was that it fails to build with OS X 10.10 due to a bug in a header installed in OS X 10.10 (/usr/include/dispatch/object.h). This header does not give a fault when compiling with clang but with gcc which is included in Sage this gives an error. This seemed to be a problem in building bundled curl in cmake, but realized that it was not so afterwards. After building curl and linking with it in cmake, I got the same error on OS X. I got access to OS X 10.10 only this week, but will try next week as time permits.

For next week, I am going to implement the wrappers for SymEngine for Sage. (i.e. conversions to and from Sage).

Sunday, June 7, 2015

GSoC 2015 : Weeks 1 & 2

These two weeks, I worked on finishing up the floating point support for SymEngine.

First ComplexDouble class was introduced to keep a std::complex<double>. With automatic simplification interface completed, implementing this class did not touch any of the other classes except for RealDouble which used the ComplexDouble classes when an operation on RealDouble resulted in a complex.

SymEngine had eval_arb and eval_double for numerical evaluations, but eval_double is double precision only and since arb is not a standard package with sage, SymEngine needed to use another library already in Sage for that. eval_mpfr method was introduced to use MPFR to get arbitrary precision numerical approximations for symbolic expressions. MPFR library is a C library for multiple-precision floating-point computations with correct rounding. MPFR is also a dependency of arb and therefore SymEngine already had support for linking against it in cmake. See PR.

Next step is to interface a library for arbitrary precision complex floating point computations and MPC which is a Sage standard package is used. MPC extends the functionality of MPFR to complex numbers. eval_mpc was written to evaluate the expressions using MPC.

This weekend, I hope to finish eval_mpc, add a RealMPFR and a ComplexMPC classes to store mpfr_t and mpc_t respectively and then write a eval function that would combine all 4 methods, eval_double, eval_complex_double, eval_mpfr, eval_mpc and finally wrap it into python so that a user can call it with expression.n(number_of_bits)

3rd and 4th week, I am going to concentrate on getting the wrappers for Sage done. CSymPy (Python wrappers of SymEngine) to Sage and Sage to CSymPy conversion support is going to be added to sage via Cython. This PR has some work on this for CSymPy to Sage conversions, but then it was decided to implement this in the sage symbolic directory to avoid a cyclic dependency.

Saturday, May 23, 2015

GSoC 2015 - Community Bonding Period

I've been accepted to Google Summer of Code 2015 to integrate CSymPy into SageMath by the mentoring organization, Python Software Foundation.

Here's the abstract about the GSoC project

CSymPy is a fast symbolic manipulation library written in C++. Sage uses Pynac as its main symbolic engine. csympy is much faster than what is already there at Sage. Several benchmarks from http://wiki.sagemath.org/symbench run on csympy suggests that csympy is 6 times or more faster. A big long term goal would be to have csympy become the default symbolic manipulation engine of sage and this GSoC project proposes to have it as an alternative symbolic manipulation engine for sage

Full GSoC application with the timeline can be found here

Updates on the GSoC project will be posted in this blog under GSoC

CSymPy was renamed to SymEngine.
CSymPy started out as a experimental core for SymPy written in C++, hence the name CSymPy. Another GSoC project is setting up wrappers to use csympy from Ruby which has nothing to do with Python. A new name SymEngine was proposed and the C++ library was changed to it while keeping the name CSymPy for the Python wrappers.


Getting CMake into Sage
SymEngine uses cmake as its build tool, but unlike autotools, cmake needs to be there at configure time, not at packaging. Therefore Sage needs to contain cmake to build symengine. I made a ticket at http://trac.sagemath.org/ticket/18078 to get cmake into sage. cmake builds fine on Linux with only 3 tests failing (all of them about curl, which is not needed for symengine), but fails to build on Mac OS X. Ondrej has some experience on building cmake on OS X due to his work in Hashdist and we will try to get it working next week as GSoC starts.


Floating point support in SymEngine
SymEngine had support only for integers, rationals and gaussian rationals. I'm going to add support for floating point values with RealDouble as default (for double precision values) and RealMPFR as an optional class if MPFR library is installed for arbitrary precision floating point values. RealDouble was implemented two weeks ago and RealMPFR will be implemented soon. (There's also a plan to have a RealArb class to use arb library for floating point calculations). Link to PR

Automatic evaluations for functions when the argument is not an exact value (like RealDouble) was added last week. Now sin(pi/2 - 0.0) will return 1.00000000 automatically without the need to call eval_double to evaluate numerically. Link to PR

SymEngine keeps expressions as it is without losing the precision. For example, sqrt(2) is kept as it is without approximating it as a double. Therefore to get a numerical value, we need to evaluate it as a double. SymEngine had a function eval_double to evaluate and get the value as a double, but lacked the functionality evaluate complex numbers. This feature was added last week as well. Link to PR

In the coming weeks, to complete the floating point support in SymEngine,

  • Add a ComplexDouble class to store std::complex<double>
  • Add evaluate_mpfr method to evaluate using mpfr library
  • Add a RealMPFR class to store a mpfr_t value
  • Interface MPC library to support arbitrary precision complex floating point values.