1
$\begingroup$

I want to create C-Code from some expressions which have many explicit floating point numbers in them. I need real numbers to be in quadruple and not double precision.

Is there a way to add a 'q' suffix to all numbers when applying CForm, i. e. write 0.05q instead of 0.05?

I know, that I can use NumberForm to do this without CForm

NumberForm[#, 32, NumberFormat -> (Row[{#1, "q", #3}] &)] &

but it does not work anymore after applying CForm.

$\endgroup$
4
  • $\begingroup$ ToString[CForm[0.05]]<>"q" ? $\endgroup$
    – Alx
    Nov 8, 2019 at 11:20
  • $\begingroup$ This does not work for me, as I was searching for a way to add the "q" to every real number in the expression and not just to a single one. Doing it by hand is not feasible. $\endgroup$
    – user68331
    Nov 8, 2019 at 15:29
  • $\begingroup$ It is obvious you can use Map. Take example from Carl Woll answer: ToString[CForm[#]] <> "q" & /@ {N[Pi], N[Pi^100, 50], N[Pi^-30, 25]} gives the same answer. Or you can use replasement rule: {N[Pi], N[Pi^100, 50], N[Pi^-30, 25]} /. x_Real :> ToString[CForm[x]] <> "q". $\endgroup$
    – Alx
    Nov 8, 2019 at 16:40
  • $\begingroup$ For arbitrary expression: Sin[12.] + 5 Sqrt[1.3] /. x_Real :> ToString[CForm[x]] <> "q" gives 5.164304207495255q. $\endgroup$
    – Alx
    Nov 8, 2019 at 16:41

3 Answers 3

4
$\begingroup$

I would override the default formatting of real numbers in CForm. One possibility similar to yours is:

Unprotect[Real];
Format[r_Real, CForm] := Format[
    ToString @ NumberForm[
        r, 
        32, 
        NumberFormat->(Row[{#1, "e", #3,"q"}]&),
        NumberPadding->{"", ""}
    ],
    OutputForm
]
Protect[Real];

The OutputForm formatting strips quotes from strings. Then:

{N[Pi], N[Pi^100, 50], N[Pi^-30, 25]} //CForm

List(3.141592653589793q,5.1878483143196131920862615246303e49q, 1.217597700325186296592143e-15q)

With this approach there is no need to postprocess the output of CForm.

$\endgroup$
1
  • $\begingroup$ I was exactly looking for something like this but could not find it. Thank you. $\endgroup$
    – user68331
    Nov 8, 2019 at 17:20
3
$\begingroup$

If you are creating C code from the Wolfram language, you will find the SymbolicC package useful.

Needs["SymbolicC`"]
CConstant[0.05, "q"] // ToCCodeString

"0.05q"

To handle an expression using SymbolicC

expr = 2.4 a + 4.1 b;
ToCCodeString[CExpression[expr] /. r_Real :> aq[r]];
StringReplace[%, "aq(" ~~ Shortest[r__] ~~ ")" :> r <> "q"]

"a*2.4q + b*4.1q"

$\endgroup$
1
  • $\begingroup$ +1 - SymbolicC is very useful. $\endgroup$
    – Jason B.
    Nov 8, 2019 at 15:41
0
$\begingroup$

So after some searching and trying things, I found a solution. I modified the solution given in https://community.wolfram.com/groups/-/m/t/1085655 where a somewhat similar but different problem was dealt with:

 mapReplace[exp_] := 
   MapAt[acf[ToString[NumberForm[#, 32, NumberFormat -> (Row[{#1, "e", #3, "q"}] &), 
      NumberPadding -> {"", ""}]]] &, exp, Position[exp, _Real]]

CNumberReformat[expr_] := 
 StringReplace[StringReplace[
   ToString[mapReplace[expr],CForm]
   , {Shortest["acf(\"" ~~ x__ ~~ "\")"] :> "(" <> x <> ")"}], {"eq" :> "q"}]

The first function replaces the numbers with a dummy function acf with the number as argument. The number is correctly formatted using NumberForm, i. e. the 'q' is added. The second function then replaces this with the correct string.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.