context: using System;
  using System.Globalization;
  using System.Runtime.InteropServices;
  
  namespace WCell.Util.Graphics
  {
      [StructLayout(LayoutKind.Sequential, Size = 16)]
      public struct Quaternion : IEquatable<Quaternion>
      {
          public float X;
          public float Y;
          public float Z;
          public float W;
          private static Quaternion _identity;
  
          public static Quaternion Identity
          {
              get
              {
                  return _identity;
              }
          }
  
          public Quaternion(float x, float y, float z, float w)
          {
              this.X = x;
              this.Y = y;
              this.Z = z;
              this.W = w;
          }
  
          public Quaternion(Vector3 vectorPart, float scalarPart)
          {
              this.X = vectorPart.X;
              this.Y = vectorPart.Y;
              this.Z = vectorPart.Z;
              this.W = scalarPart;
          }
  
          public override string ToString()
          {
              CultureInfo currentCulture = CultureInfo.CurrentCulture;
              return string.Format(currentCulture, "{{X:{0} Y:{1} Z:{2} W:{3}}}", new object[] { this.X.ToString(currentCulture), this.Y.ToString(currentCulture), this.Z.ToString(currentCulture), this.W.ToString(currentCulture) });
          }
  
          public bool Equals(Quaternion other)
          {
              return ((((this.X == other.X) && (this.Y == other.Y)) && (this.Z == other.Z)) && (this.W == other.W));
          }
  
          public override bool Equals(object obj)
          {
              bool flag = false;
              if (obj is Quaternion)
              {
                  flag = this.Equals((Quaternion)obj);
              }
              return flag;
          }
  
          public override int GetHashCode()
          {
              return (((this.X.GetHashCode() + this.Y.GetHashCode()) + this.Z.GetHashCode()) + this.W.GetHashCode());
          }
  
          public float LengthSquared()
          {
              return ((((this.X * this.X) + (this.Y * this.Y)) + (this.Z * this.Z)) + (this.W * this.W));
          }
  
          public float Length()
          {
              float num = (((this.X * this.X) + (this.Y * this.Y)) + (this.Z * this.Z)) + (this.W * this.W);
              return (float)Math.Sqrt((double)num);
          }
  
          public void Normalize()
          {
              float num2 = (((this.X * this.X) + (this.Y * this.Y)) + (this.Z * this.Z)) + (this.W * this.W);
              float num = 1f / ((float)Math.Sqrt((double)num2));
              this.X *= num;
              this.Y *= num;
              this.Z *= num;
              this.W *= num;
          }
  
          public static Quaternion Normalize(Quaternion quaternion)
          {
              Quaternion quaternion2;
              float num2 = (((quaternion.X * quaternion.X) + (quaternion.Y * quaternion.Y)) + (quaternion.Z * quaternion.Z)) + (quaternion.W * quaternion.W);
              float num = 1f / ((float)Math.Sqrt((double)num2));
              quaternion2.X = quaternion.X * num;
              quaternion2.Y = quaternion.Y * num;
              quaternion2.Z = quaternion.Z * num;
              quaternion2.W = quaternion.W * num;
              return quaternion2;
          }
  
          public static void Normalize(ref Quaternion quaternion, out Quaternion result)
          {
              float num2 = (((quaternion.X * quaternion.X) + (quaternion.Y * quaternion.Y)) + (quaternion.Z * quaternion.Z)) + (quaternion.W * quaternion.W);
              float num = 1f / ((float)Math.Sqrt((double)num2));
              result.X = quaternion.X * num;
              result.Y = quaternion.Y * num;
              result.Z = quaternion.Z * num;
              result.W = quaternion.W * num;
          }
  
          public void Conjugate()
          {
              this.X = -this.X;
              this.Y = -this.Y;
              this.Z = -this.Z;
          }
  
          public static Quaternion Conjugate(Quaternion value)
          {
              Quaternion quaternion;
              quaternion.X = -value.X;
              quaternion.Y = -value.Y;
              quaternion.Z = -value.Z;
              quaternion.W = value.W;
              return quaternion;
          }
  
          public static void Conjugate(ref Quaternion value, out Quaternion result)
          {
              result.X = -value.X;
              result.Y = -value.Y;
              result.Z = -value.Z;
              result.W = value.W;
          }
  
          public static Quaternion Inverse(Quaternion quaternion)
          {
              Quaternion quaternion2;
              float num2 = (((quaternion.X * quaternion.X) + (quaternion.Y * quaternion.Y)) + (quaternion.Z * quaternion.Z)) + (quaternion.W * quaternion.W);
              float num = 1f / num2;
              quaternion2.X = -quaternion.X * num;
              quaternion2.Y = -quaternion.Y * num;
              quaternion2.Z = -quaternion.Z * num;
              quaternion2.W = quaternion.W * num;
              return quaternion2;
          }
  
          public static void Inverse(ref Quaternion quaternion, out Quaternion result)
          {
              float num2 = (((quaternion.X * quaternion.X) + (quaternion.Y * quaternion.Y)) + (quaternion.Z * quaternion.Z)) + (quaternion.W * quaternion.W);
              float num = 1f / num2;
              result.X = -quaternion.X * num;
              result.Y = -quaternion.Y * num;
              result.Z = -quaternion.Z * num;
              result.W = quaternion.W * num;
          }
  
          public static Quaternion CreateFromAxisAngle(Vector3 axis, float angle)
          {
              Quaternion quaternion;
              float num2 = angle * 0.5f;
              float num = (float)Math.Sin((double)num2);
              float num3 = (float)Math.Cos((double)num2);
              quaternion.X = axis.X * num;
              quaternion.Y = axis.Y * num;
              quaternion.Z = axis.Z * num;
              quaternion.W = num3;
              return quaternion;
          }
  
          public static void CreateFromAxisAngle(ref Vector3 axis, float angle, out Quaternion result)
          {
              float num2 = angle * 0.5f;
              float num = (float)Math.Sin((double)num2);
              float num3 = (float)Math.Cos((double)num2);
              result.X = axis.X * num;
              result.Y = axis.Y * num;
              result.Z = axis.Z * num;
              result.W = num3;
          }
  
          public static Quaternion CreateFromYawPitchRoll(float yaw, float pitch, float roll)
          {
              Quaternion quaternion;
              float num9 = roll * 0.5f;
              float num6 = (float)Math.Sin((double)num9);
              float num5 = (float)Math.Cos((double)num9);
              float num8 = pitch * 0.5f;
              float num4 = (float)Math.Sin((double)num8);
              float num3 = (float)Math.Cos((double)num8);
              float num7 = yaw * 0.5f;
              float num2 = (float)Math.Sin((double)num7);
              float num = (float)Math.Cos((double)num7);
              quaternion.X = ((num * num4) * num5) + ((num2 * num3) * num6);
              quaternion.Y = ((num2 * num3) * num5) - ((num * num4) * num6);
              quaternion.Z = ((num * num3) * num6) - ((num2 * num4) * num5);
              quaternion.W = ((num * num3) * num5) + ((num2 * num4) * num6);
              return quaternion;
          }
  
          public static void CreateFromYawPitchRoll(float yaw, float pitch, float roll, out Quaternion result)
          {
              float num9 = roll * 0.5f;
              float num6 = (float)Math.Sin((double)num9);
              float num5 = (float)Math.Cos((double)num9);
              float num8 = pitch * 0.5f;
              float num4 = (float)Math.Sin((double)num8);
              float num3 = (float)Math.Cos((double)num8);
              float num7 = yaw * 0.5f;
              float num2 = (float)Math.Sin((double)num7);
              float num = (float)Math.Cos((double)num7);
              result.X = ((num * num4) * num5) + ((num2 * num3) * num6);
              result.Y = ((num2 * num3) * num5) - ((num * num4) * num6);
              result.Z = ((num * num3) * num6) - ((num2 * num4) * num5);
              result.W = ((num * num3) * num5) + ((num2 * num4) * num6);
          }
  
          public static Quaternion CreateFromRotationMatrix(Matrix matrix)
          {
              float num8 = (matrix.M11 + matrix.M22) + matrix.M33;
              Quaternion quaternion = new Quaternion();
              if (num8 > 0f)
              {
                  float num = (float)Math.Sqrt((double)(num8 + 1f));
                  quaternion.W = num * 0.5f;
                  num = 0.5f / num;
                  quaternion.X = (matrix.M23 - matrix.M32) * num;
                  quaternion.Y = (matrix.M31 - matrix.M13) * num;
                  quaternion.Z = (matrix.M12 - matrix.M21) * num;
                  return quaternion;
              }
              if ((matrix.M11 >= matrix.M22) && (matrix.M11 >= matrix.M33))
              {
                  float num7 = (float)Math.Sqrt((double)(((1f + matrix.M11) - matrix.M22) - matrix.M33));
                  float num4 = 0.5f / num7;
                  quaternion.X = 0.5f * num7;
                  quaternion.Y = (matrix.M12 + matrix.M21) * num4;
                  quaternion.Z = (matrix.M13 + matrix.M31) * num4;
                  quaternion.W = (matrix.M23 - matrix.M32) * num4;
                  return quaternion;
              }
              if (matrix.M22 > matrix.M33)
              {
                  float num6 = (float)Math.Sqrt((double)(((1f + matrix.M22) - matrix.M11) - matrix.M33));
                  float num3 = 0.5f / num6;
                  quaternion.X = (matrix.M21 + matrix.M12) * num3;
                  quaternion.Y = 0.5f * num6;
                  quaternion.Z = (matrix.M32 + matrix.M23) * num3;
                  quaternion.W = (matrix.M31 - matrix.M13) * num3;
                  return quaternion;
              }
              float num5 = (float)Math.Sqrt((double)(((1f + matrix.M33) - matrix.M11) - matrix.M22));
              float num2 = 0.5f / num5;
              quaternion.X = (matrix.M31 + matrix.M13) * num2;
              quaternion.Y = (matrix.M32 + matrix.M23) * num2;
              quaternion.Z = 0.5f * num5;
              quaternion.W = (matrix.M12 - matrix.M21) * num2;
              return quaternion;
          }
  
          public static void CreateFromRotationMatrix(ref Matrix matrix, out Quaternion result)
          {
              float num8 = (matrix.M11 + matrix.M22) + matrix.M33;
              if (num8 > 0f)
              {
                  float num = (float)Math.Sqrt((double)(num8 + 1f));
                  result.W = num * 0.5f;
                  num = 0.5f / num;
                  result.X = (matrix.M23 - matrix.M32) * num;
                  result.Y = (matrix.M31 - matrix.M13) * num;
                  result.Z = (matrix.M12 - matrix.M21) * num;
              }
              else if ((matrix.M11 >= matrix.M22) && (matrix.M11 >= matrix.M33))
              {
                  float num7 = (float)Math.Sqrt((double)(((1f + matrix.M11) - matrix.M22) - matrix.M33));
                  float num4 = 0.5f / num7;
                  result.X = 0.5f * num7;
                  result.Y = (matrix.M12 + matrix.M21) * num4;
                  result.Z = (matrix.M13 + matrix.M31) * num4;
                  result.W = (matrix.M23 - matrix.M32) * num4;
              }
              else if (matrix.M22 > matrix.M33)
              {
                  float num6 = (float)Math.Sqrt((double)(((1f + matrix.M22) - matrix.M11) - matrix.M33));
                  float num3 = 0.5f / num6;
                  result.X = (matrix.M21 + matrix.M12) * num3;
                  result.Y = 0.5f * num6;
                  result.Z = (matrix.M32 + matrix.M23) * num3;
                  result.W = (matrix.M31 - matrix.M13) * num3;
              }
              else
              {
                  float num5 = (float)Math.Sqrt((double)(((1f + matrix.M33) - matrix.M11) - matrix.M22));
                  float num2 = 0.5f / num5;
                  result.X = (matrix.M31 + matrix.M13) * num2;
                  result.Y = (matrix.M32 + matrix.M23) * num2;
                  result.Z = 0.5f * num5;
                  result.W = (matrix.M12 - matrix.M21) * num2;
              }
          }
  
          public static float Dot(Quaternion quaternion1, Quaternion quaternion2)
          {
              return ((((quaternion1.X * quaternion2.X) + (quaternion1.Y * quaternion2.Y)) + (quaternion1.Z * quaternion2.Z)) + (quaternion1.W * quaternion2.W));
          }
  
          public static void Dot(ref Quaternion quaternion1, ref Quaternion quaternion2, out float result)
          {
              result = (((quaternion1.X * quaternion2.X) + (quaternion1.Y * quaternion2.Y)) + (quaternion1.Z * quaternion2.Z)) + (quaternion1.W * quaternion2.W);
          }
  
          public static Quaternion Slerp(Quaternion quaternion1, Quaternion quaternion2, float amount)
          {
              float num2;
              float num3;
              Quaternion quaternion;
              float num = amount;
              float num4 = (((quaternion1.X * quaternion2.X) + (quaternion1.Y * quaternion2.Y)) + (quaternion1.Z * quaternion2.Z)) + (quaternion1.W * quaternion2.W);
              bool flag = false;
              if (num4 < 0f)
              {
                  flag = true;
                  num4 = -num4;
              }
              if (num4 > 0.999999f)
              {
                  num3 = 1f - num;
                  num2 = flag ? -num : num;
              }
              else
              {
                  float num5 = (float)Math.Acos((double)num4);
                  float num6 = (float)(1.0 / Math.Sin((double)num5));
                  num3 = ((float)Math.Sin((double)((1f - num) * num5))) * num6;
                  num2 = flag ? (((float)-Math.Sin((double)(num * num5))) * num6) : (((float)Math.Sin((double)(num * num5))) * num6);
              }
              quaternion.X = (num3 * quaternion1.X) + (num2 * quaternion2.X);
              quaternion.Y = (num3 * quaternion1.Y) + (num2 * quaternion2.Y);
              quaternion.Z = (num3 * quaternion1.Z) + (num2 * quaternion2.Z);
  
gt:             quaternion.W = (num3 * quaternion1.W) + (num2 * quaternion2.W);