samwise samwise - 28 days ago 16
C++ Question

sympy ccode number type

I am using Sympy to manipulate and differentiate a user-defined input function in order to generate a C++ library to be used with an external C++ program. It works great, except that for the fact that Sympy insists on expressing 1/2 as 1.0L/2.0L. Fine, except some of the variables in the main code are of type std::complex, so this is causing a compile-time error since it can't (implicitly) multiply/add/subtract a complex with long doubles (or ints, for that matter). I tried compiling with -std=c++14 since this has more support for implicit type casting, but the "problem" persists.

In the meantime, I've written a set of helper functions to deal with those operations, but I was wondering if there is any way to tell Sympy to output any numerical value it has as a double? For example, instead of outputting 1.0L/2.0L to the C code, can I force it to just write 1.0/2.0 (or even 0.5)? Likewise, instead of writing an int such as 2, I'd like it to write 2.0. I tried setting the precision flag (in the sympy.printing.ccode function call) but it did not change anything. I couldn't seem to find anything online

I'd be very grateful for any advice.

Many thanks,
Sam

Answer

Right now there isn't an option for this (I opened an issue for it).

A workaround is to subclass sympy.printing.ccode.CCodePrinter and override _print_Rational. This is the current definition:

def _print_Rational(self, expr):
    p, q = int(expr.p), int(expr.q)
    return '%d.0L/%d.0L' % (p, q)

So you can write something like

class MyCCodePrinter(CCodePrinter):
    def _print_Rational(self, expr):
        p, q = int(expr.p), int(expr.q)
        return '%d.0/%d.0' % (p, q)

You can then print expressions with MyCCodePrinter().doprint(expr).