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.

New contributor
user68331 is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
$\endgroup$
  • $\begingroup$ ToString[CForm[0.05]]<>"q" ? $\endgroup$ – Alx Nov 8 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 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 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 at 16:41
2
$\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$
  • $\begingroup$ +1 - SymbolicC is very useful. $\endgroup$ – Jason B. Nov 8 at 15:41
1
$\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$
  • $\begingroup$ I was exactly looking for something like this but could not find it. Thank you. $\endgroup$ – user68331 Nov 8 at 17:20
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.

New contributor
user68331 is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
$\endgroup$

Your Answer

user68331 is a new contributor. Be nice, and check out our Code of Conduct.

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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