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 radius = cuCabs(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));
}

Thanks for your contribution!