# Additional cuComplex functions: cuCnorm, cuCsqrt, cuCexp and some complex-double functions.

I have created some extra functions which I needed for my CUDA project.
Posting them here if anyone could use them. I wrote them in a C++ project. Some changes should be made to be compatible with C (predeclaration?).

1. cuCnorm calculates the norm of 3 complex numbers (protected against intermediate underflow and overflow)
2. cuCexp calculates the exp of a complex number
3. cuCsqrt calculates the sqrt of a complex number, combination of atan2, cos & sin is not used. That method generates bit errors.
4. various other functions for calculations with complex <-> double numbers.
``````__host__ __device__ static __inline__ cuDoubleComplex cuCexp(cuDoubleComplex x)
{
double factor = exp(x.x);
return make_cuDoubleComplex(factor * cos(x.y), factor * sin(x.y));
}

__host__ __device__ static __inline__ double cuCnorm(cuDoubleComplex a, cuDoubleComplex b, cuDoubleComplex c)
{
double absA = cuCabs(a);
double absB = cuCabs(b);
double absC = cuCabs(c);
double u, v, w, r, s;

if (absA > absB){
if (absA > absC){
// a is largest
u = absA;
v = absB;
w = absC;

}
else{
// c is largest
u = absC;
v = absA;
w = absB;
}
}
else{
if (absB > absC){
// b is largest
u = absB;
v = absC;
w = absA;
}
else{
// c is largest
u = absC;
v = absA;
w = absB;
}
}
r = v / u;
s = w / u;
r = 1.0 + r*r + s*s;
r = u * sqrt(r);

if ((u == 0.0) ||
(u > 1.79769313486231570e+308) || (v > 1.79769313486231570e+308) || (w > 1.79769313486231570e+308)) {
r = u + v + w;
}
return r;
}

__host__ __device__ static __inline__ cuDoubleComplex cuCsqrt(cuDoubleComplex x)
{
double cosA = x.x / radius;
cuDoubleComplex out;
out.x = sqrt(radius * (cosA + 1.0) / 2.0);
out.y = sqrt(radius * (1.0 - cosA) / 2.0);
// signbit should be false if x.y is negative
if (signbit(x.y))
out.y *= -1.0;

return out;
}

__host__ __device__ static __inline__ cuDoubleComplex cuCadd(cuDoubleComplex x, double y)
{
return make_cuDoubleComplex(cuCreal(x) + y, cuCimag(x));
}
__host__ __device__ static __inline__ cuDoubleComplex cuCdiv(cuDoubleComplex x, double y)
{
return make_cuDoubleComplex(cuCreal(x) / y, cuCimag(x) / y);
}
__host__ __device__ static __inline__ cuDoubleComplex cuCmul(cuDoubleComplex x, double y)
{
return make_cuDoubleComplex(cuCreal(x) * y, cuCimag(x) * y);
}
__host__ __device__ static __inline__ cuDoubleComplex cuCsub(cuDoubleComplex x, double y)
{
return make_cuDoubleComplex(cuCreal(x) - y, cuCimag(x));
}
``````