Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

According to List of compilable functions Erf and Erfc are compilable functions.

However, I want to make a compiled version of the PDF of a VoightDistribution to use in a NonlinearModelFit and it doesn't seem that the Erfc of a complex value will compile.

funcReal = 
 Compile[{{x, _Real}}, Erfc[x I], CompilationTarget -> "C", 
  RuntimeOptions -> "Speed"]
funcComplex = 
 Compile[{{x, _Complex}}, Erfc[x I], CompilationTarget -> "C", 
  RuntimeOptions -> "Speed"]

Needs["CompiledFunctionTools`"];
CompilePrint[funcReal] (*same as funcComplex*)

    1 argument
    2 Real registers
    4 Complex registers
    Underflow checking off
    Overflow checking off
    Integer overflow checking off
    RuntimeAttributes -> {}

    R0 = A1
    C0 = 0. + 1. I
    R1 = 0.
    Result = C3

1   C1 = R0 + R1 I
2   C1 = C1 * C0
3   C2 = R0 + R1 I
4   C2 = C2 * C0
5   C3 = MainEvaluate[ Hold[Erfc][ C2]]
6   Return

Note the call to MainEvalulate

Erfc[I] // N
funcReal[1]
funcComplex[1]

1. - 1.65043 I

1. - 1.65043 I

1. - 1.65043 I

All the functions work but because of the MainEvalulate they offer no performance benefit. How can I compile this function? Is this possible? Is there an alternative formula I could use?

Removing the CompilationTarget doesn't solve the problem either.

share|improve this question
3  
They compile for real values, but do not appear to compile for complex arguments. –  asim Feb 20 '13 at 17:56
1  
Look at e.g. Plot3D[Arg@Erf[x + I y], {x, -5, 5}, {y, -5, 5}]. This is not a function you would probably wish to try to find an alternative formula for, even approximately. –  Oleksandr R. Feb 20 '13 at 18:25
1  
On the other hand, regarding the PDF of the Voigt distribution: dx.doi.org/10.1016/0368-2048(94)02189-7 –  Oleksandr R. Feb 20 '13 at 18:46

1 Answer 1

up vote 2 down vote accepted

From Mathematica Documentation, we have a Pseudo Voigt Distribution that might be used as an approximation. This might be useful as a basis for making a compilable function.

In[1]:= PseudoVoigtDistribution[de_, si_] := 
 Block[{g = (de^5 + si^5 + 2.69296 si^4 de + 2.42843 si^3 de^2 + 
      4.47163 si^2 de^3 + 0.07842 si de^4)^(1/5), eta},
  eta = de/g;
  eta = eta*(1.36603 - 0.47719 eta + 0.11116 eta^2);
  MixtureDistribution[{1 - eta, eta}, {NormalDistribution[0, g], 
    CauchyDistribution[0, g]}]
  ]
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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