public static void std_coords_to_half_diff_coords(double _ThetaIn, double _PhiIn, double _ThetaOut, double _PhiOut,
out double _ThetaHalf, out double _PhiHalf, out double _ThetaDiff, out double _PhiDiff)
{
// compute in vector
double in_vec_z = Math.Cos(_ThetaIn);
double proj_in_vec = Math.Sin(_ThetaIn);
double in_vec_x = proj_in_vec * Math.Cos(_PhiIn);
double in_vec_y = proj_in_vec * Math.Sin(_PhiIn);
In.Set(in_vec_x, in_vec_y, in_vec_z);
// compute out vector
double out_vec_z = Math.Cos(_ThetaOut);
double proj_out_vec = Math.Sin(_ThetaOut);
double out_vec_x = proj_out_vec * Math.Cos(_PhiOut);
double out_vec_y = proj_out_vec * Math.Sin(_PhiOut);
Out.Set(out_vec_x, out_vec_y, out_vec_z);
// compute halfway vector
Half.Set(in_vec_x + out_vec_x, in_vec_y + out_vec_y, in_vec_z + out_vec_z);
Half.Normalize();
// compute _ThetaHalf, _PhiHalf
_ThetaHalf = Math.Acos(Half.z);
_PhiHalf = Math.Atan2(Half.y, Half.x);
// Compute diff vector
In.Rotate(ref Normal, -_PhiHalf, out Temp);
Temp.Rotate(ref BiTangent, -_ThetaHalf, out Diff);
// Compute _ThetaDiff, _PhiDiff
_ThetaDiff = Math.Acos(Math.Min(1.0, Diff.z));
_PhiDiff = Math.Atan2(Diff.y, Diff.x);
}