Partial work on quaternions and some other tweaks.

This commit is contained in:
That-One-Nerd 2025-05-13 08:59:02 -04:00
parent 664ba0fab7
commit 3a7a3c320e
7 changed files with 472 additions and 49 deletions

View File

@ -2,7 +2,7 @@
namespace Nerd_STF.Helpers namespace Nerd_STF.Helpers
{ {
public static class CordicHelper internal static class CordicHelper
{ {
// Starts at 4 radians. Each index downwards is half that. // Starts at 4 radians. Each index downwards is half that.
// Goes from 2^2 to 2^-19. // Goes from 2^2 to 2^-19.

View File

@ -1,5 +1,6 @@
using Nerd_STF.Mathematics; using Nerd_STF.Mathematics;
using Nerd_STF.Mathematics.Algebra; using Nerd_STF.Mathematics.Algebra;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
@ -110,5 +111,44 @@ namespace Nerd_STF.Helpers
} }
return total.ToString(); return total.ToString();
} }
private static readonly string dimNumSymbols = " ijk?";
#if CS8_OR_GREATER
public static string HighDimNumberToString(IEnumerable<double> terms, string? format, IFormatProvider? provider)
#else
public static string HighDimNumberToString(IEnumerable<double> terms, string format, IFormatProvider provider)
#endif
{
StringBuilder builder = new StringBuilder();
int index = 0;
bool first = true;
foreach (double term in terms)
{
if (term == 0)
{
index++;
continue;
}
if (first) builder.Append(term.ToString(format, provider));
else
{
if (term > 0)
{
builder.Append(" + ");
builder.Append(term.ToString(format, provider));
}
else
{
builder.Append(" - ");
builder.Append((-term).ToString(format, provider));
}
}
if (index > 0) builder.Append(dimNumSymbols[MathE.Min(index, dimNumSymbols.Length)]);
first = false;
index++;
}
if (first) builder.Append(0.0.ToString(format, provider));
return builder.ToString();
}
} }
} }

View File

@ -4,8 +4,9 @@ namespace Nerd_STF.Mathematics
public interface IPresets4d<TSelf> : IPresets3d<TSelf> public interface IPresets4d<TSelf> : IPresets3d<TSelf>
where TSelf : IPresets4d<TSelf> where TSelf : IPresets4d<TSelf>
{ {
static abstract TSelf LowW { get; } // TODO: The HighW and LowW vectors could also be called "ana" and "kata."
static abstract TSelf HighW { get; } static abstract TSelf LowW { get; } // Kata
static abstract TSelf HighW { get; } // Ana
} }
} }
#endif #endif

View File

@ -260,7 +260,7 @@ namespace Nerd_STF.Mathematics
public static bool operator ==(Int2 a, Int2 b) => a.Equals(b); public static bool operator ==(Int2 a, Int2 b) => a.Equals(b);
public static bool operator !=(Int2 a, Int2 b) => !a.Equals(b); public static bool operator !=(Int2 a, Int2 b) => !a.Equals(b);
public static explicit operator Int2(Complex complex) => new Int2((int)complex.Real, (int)complex.Imaginary); public static explicit operator Int2(Complex complex) => new Int2((int)complex.r, (int)complex.i);
public static explicit operator Int2(Float2 floats) => new Int2((int)floats.x, (int)floats.y); public static explicit operator Int2(Float2 floats) => new Int2((int)floats.x, (int)floats.y);
public static explicit operator Int2(Float3 floats) => new Int2((int)floats.x, (int)floats.y); public static explicit operator Int2(Float3 floats) => new Int2((int)floats.x, (int)floats.y);
public static explicit operator Int2(Float4 floats) => new Int2((int)floats.x, (int)floats.y); public static explicit operator Int2(Float4 floats) => new Int2((int)floats.x, (int)floats.y);

View File

@ -2,18 +2,21 @@
using Nerd_STF.Helpers; using Nerd_STF.Helpers;
using Nerd_STF.Mathematics.Algebra; using Nerd_STF.Mathematics.Algebra;
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Numerics; using System.Numerics;
using System.Text;
namespace Nerd_STF.Mathematics.Numbers namespace Nerd_STF.Mathematics.Numbers
{ {
public struct Complex : IEquatable<Complex>, public struct Complex : IComparable<Complex>,
IFormattable IEquatable<Complex>,
IFormattable,
INumberGroup<Complex, double>
#if CS11_OR_GREATER #if CS11_OR_GREATER
,INumber<Complex>, ,INumber<Complex>,
IFromTuple<Complex, (double, double)>,
IInterpolable<Complex>, IInterpolable<Complex>,
IPresets2d<Complex>, IPresets2d<Complex>,
IRoundable<Complex>, IRoundable<Complex>,
@ -55,6 +58,61 @@ namespace Nerd_STF.Mathematics.Numbers
i = imaginary; i = imaginary;
} }
public double this[int index]
{
get
{
switch (index)
{
case 0: return r;
case 1: return i;
default: throw new ArgumentOutOfRangeException(nameof(index));
}
}
set
{
switch (index)
{
case 0: r = value; break;
case 1: i = value; break;
default: throw new ArgumentOutOfRangeException(nameof(index));
}
}
}
public ListTuple<double> this[string key]
{
get
{
double[] items = new double[key.Length];
for (int i = 0; i < key.Length; i++)
{
char c = key[i];
switch (c)
{
case 'r': items[i] = r; break;
case 'i': items[i] = this.i; break;
default: throw new ArgumentException("Invalid key.", nameof(key));
}
}
return new ListTuple<double>(items);
}
set
{
IEnumerator<double> stepper = value.GetEnumerator();
for (int i = 0; i < key.Length; i++)
{
char c = key[i];
stepper.MoveNext();
switch (c)
{
case 'r': r = stepper.Current; break;
case 'i': this.i = stepper.Current; break;
default: throw new ArgumentException("Invalid key.", nameof(key));
}
}
}
}
#if CS8_OR_GREATER #if CS8_OR_GREATER
public static Complex Parse(string? str) => public static Complex Parse(string? str) =>
#else #else
@ -195,20 +253,19 @@ namespace Nerd_STF.Mathematics.Numbers
public static Complex Floor(Complex num) => public static Complex Floor(Complex num) =>
new Complex(MathE.Floor(num.r), new Complex(MathE.Floor(num.r),
MathE.Floor(num.i)); MathE.Floor(num.i));
public static Complex Lerp(Complex a, Complex b, double t, bool clamp = false) => public static Complex Lerp(Complex a, Complex b, double t, bool clamp = true) =>
new Complex(MathE.Lerp(a.r, b.r, t, clamp), new Complex(MathE.Lerp(a.r, b.r, t, clamp),
MathE.Lerp(a.i, b.i, t, clamp)); MathE.Lerp(a.i, b.i, t, clamp));
public static Complex Product(IEnumerable<Complex> vals) public static Complex Product(IEnumerable<Complex> vals)
{ {
bool any = false; bool any = false;
double resultR = 1, resultI = 1; Complex result = One;
foreach (Complex val in vals) foreach (Complex val in vals)
{ {
any = true; any = true;
resultR *= val.r; result *= val;
resultI *= val.i;
} }
return any ? new Complex(resultR, resultI) : Zero; return any ? result : Zero;
} }
public static Complex Round(Complex val) => public static Complex Round(Complex val) =>
new Complex(MathE.Round(val.r), new Complex(MathE.Round(val.r),
@ -338,12 +395,20 @@ namespace Nerd_STF.Mathematics.Numbers
{ {
reals[index] = val.r; reals[index] = val.r;
imaginaries[index] = val.i; imaginaries[index] = val.i;
index++;
} }
return (reals, imaginaries); return (reals, imaginaries);
} }
public int CompareTo(double other) => Magnitude.CompareTo(MathE.Abs(other)); public IEnumerator<double> GetEnumerator()
public int CompareTo(Complex other) => Magnitude.CompareTo(other.Magnitude); {
yield return r;
yield return i;
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public int CompareTo(double other) => MagnitudeSqr.CompareTo(MathE.Abs(other * other));
public int CompareTo(Complex other) => MagnitudeSqr.CompareTo(other.MagnitudeSqr);
#if CS8_OR_GREATER #if CS8_OR_GREATER
public int CompareTo(object? other) public int CompareTo(object? other)
#else #else
@ -352,8 +417,9 @@ namespace Nerd_STF.Mathematics.Numbers
{ {
if (other is null) return 1; if (other is null) return 1;
else if (other is Complex otherComplex) return CompareTo(otherComplex); else if (other is Complex otherComplex) return CompareTo(otherComplex);
else if (other is double otherDouble) return CompareTo(otherDouble);
else if (TryConvertFrom(other, out Complex otherConvert)) return CompareTo(otherConvert); else if (TryConvertFrom(other, out Complex otherConvert)) return CompareTo(otherConvert);
else return 0; else return 1;
} }
public bool Equals(double other) => r == other && i == 0; public bool Equals(double other) => r == other && i == 0;
public bool Equals(Complex other) => r == other.r && i == other.i; public bool Equals(Complex other) => r == other.r && i == other.i;
@ -369,41 +435,24 @@ namespace Nerd_STF.Mathematics.Numbers
else return false; else return false;
} }
public override int GetHashCode() => base.GetHashCode(); public override int GetHashCode() => base.GetHashCode();
public override string ToString() => ToString(null, null); public override string ToString() => ToStringHelper.HighDimNumberToString(this, null, null);
#if CS8_OR_GREATER #if CS8_OR_GREATER
public string ToString(string? format) => ToString(format, null); public string ToString(string? format) => ToStringHelper.HighDimNumberToString(this, format, null);
public string ToString(IFormatProvider? provider) => ToString(null, provider); public string ToString(IFormatProvider? provider) => ToStringHelper.HighDimNumberToString(this, null, provider);
public string ToString(string? format, IFormatProvider? provider) => ToStringHelper.HighDimNumberToString(this, format, provider);
#else #else
public string ToString(string format) => ToString(format, null); public string ToString(string format) => ToStringHelper.HighDimNumberToString(this, format, null);
public string ToString(IFormatProvider provider) => ToString(null, provider); public string ToString(IFormatProvider provider) => ToStringHelper.HighDimNumberToString(this, null, provider);
#endif public string ToString(string format, IFormatProvider provider) => ToStringHelper.HighDimNumberToString(this, format, provider);
#if CS8_OR_GREATER
public string ToString(string? format, IFormatProvider? provider)
#else
public string ToString(string format, IFormatProvider provider)
#endif #endif
public double[] ToArray() => new double[] { r, i };
public Fill<double> ToFill()
{ {
if (r == 0 && i == 0) return 0.0.ToString(format, provider); Complex @this = this;
else if (r == 0) return $"{i.ToString(format, provider)}i"; return i => @this[i];
else
{
StringBuilder builder = new StringBuilder();
builder.Append(r.ToString(format, provider));
if (i > 0)
{
builder.Append(" + ");
builder.Append(i.ToString(format, provider));
builder.Append('i');
}
else if (i < 0)
{
builder.Append(" - ");
builder.Append((-i).ToString(format, provider));
builder.Append('i');
}
return builder.ToString();
}
} }
public List<double> ToList() => new List<double>() { r, i };
#if CS11_OR_GREATER #if CS11_OR_GREATER
public bool TryFormat(Span<char> dest, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider? provider) public bool TryFormat(Span<char> dest, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider? provider)
@ -414,16 +463,17 @@ namespace Nerd_STF.Mathematics.Numbers
charsWritten = result.Length; charsWritten = result.Length;
return true; return true;
} }
static Complex IIncrementOperators<Complex>.operator ++(Complex a) => new Complex(a.r + 1, a.i);
static Complex IDecrementOperators<Complex>.operator --(Complex a) => new Complex(a.r - 1, a.i);
#endif #endif
public static Complex operator +(Complex a) => a; public static Complex operator +(Complex a) => a;
public static Complex operator +(Complex a, Complex b) => new Complex(a.r + b.r, a.i + b.i); public static Complex operator +(Complex a, Complex b) => new Complex(a.r + b.r, a.i + b.i);
public static Complex operator +(Complex a, double b) => new Complex(a.r + b, a.i); public static Complex operator +(Complex a, double b) => new Complex(a.r + b, a.i);
public static Complex operator ++(Complex a) => new Complex(a.r + 1, a.i);
public static Complex operator -(Complex a) => new Complex(-a.r, -a.i); public static Complex operator -(Complex a) => new Complex(-a.r, -a.i);
public static Complex operator -(Complex a, Complex b) => new Complex(a.r - b.r, a.i - b.i); public static Complex operator -(Complex a, Complex b) => new Complex(a.r - b.r, a.i - b.i);
public static Complex operator -(Complex a, double b) => new Complex(a.r - b, a.i); public static Complex operator -(Complex a, double b) => new Complex(a.r - b, a.i);
public static Complex operator --(Complex a) => new Complex(a.r - 1, a.i);
public static Complex operator *(Complex a, Complex b) => new Complex(a.r * b.r - a.i * b.i, a.r * b.i + a.i * b.r); public static Complex operator *(Complex a, Complex b) => new Complex(a.r * b.r - a.i * b.i, a.r * b.i + a.i * b.r);
public static Complex operator *(Complex a, double b) => new Complex(a.r * b, a.i * b); public static Complex operator *(Complex a, double b) => new Complex(a.r * b, a.i * b);
public static Complex operator /(Complex a, Complex b) public static Complex operator /(Complex a, Complex b)
@ -447,9 +497,14 @@ namespace Nerd_STF.Mathematics.Numbers
public static bool operator <=(Complex a, Complex b) => a.CompareTo(b) <= 0; public static bool operator <=(Complex a, Complex b) => a.CompareTo(b) <= 0;
public static implicit operator Complex(System.Numerics.Complex num) => new Complex(num.Real, num.Imaginary); public static implicit operator Complex(System.Numerics.Complex num) => new Complex(num.Real, num.Imaginary);
public static implicit operator System.Numerics.Complex(Complex num) => new Complex(num.r, num.i);
public static implicit operator Complex(Float2 group) => new Complex(group.x, group.y); public static implicit operator Complex(Float2 group) => new Complex(group.x, group.y);
public static explicit operator Complex(Int2 group) => new Complex(group.x, group.y); public static explicit operator Complex(Int2 group) => new Complex(group.x, group.y);
public static implicit operator Complex(ListTuple<double> tuple) => new Complex(tuple[0], tuple[1]);
public static implicit operator Complex(ValueTuple<double, double> tuple) => new Complex(tuple.Item1, tuple.Item2);
public static explicit operator Complex(Vector2 group) => new Complex(group.X, group.Y); public static explicit operator Complex(Vector2 group) => new Complex(group.X, group.Y);
public static implicit operator System.Numerics.Complex(Complex num) => new Complex(num.r, num.i);
public static implicit operator ListTuple<double>(Complex num) => new ListTuple<double>(num.r, num.i);
public static implicit operator ValueTuple<double, double>(Complex num) => (num.r, num.i);
} }
} }

View File

@ -325,7 +325,7 @@ namespace Nerd_STF.Mathematics.Numbers
return false; return false;
} }
else if (value is Fraction valueFrac) result = valueFrac; else if (value is Fraction valueFrac) result = valueFrac;
else if (value is Complex valueComp) result = Approximate(valueComp.Real); else if (value is Complex valueComp) result = Approximate(valueComp.r);
else if (value is double valueDouble) result = Approximate(valueDouble); else if (value is double valueDouble) result = Approximate(valueDouble);
else if (value is float valueSingle) result = Approximate(valueSingle); else if (value is float valueSingle) result = Approximate(valueSingle);
#if NET5_0_OR_GREATER #if NET5_0_OR_GREATER

View File

@ -0,0 +1,327 @@
using Nerd_STF.Exceptions;
using Nerd_STF.Helpers;
using Nerd_STF.Mathematics.Algebra;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
namespace Nerd_STF.Mathematics.Numbers
{
public struct Quaternion : IComparable<double>,
IEnumerable<double>,
IFormattable,
INumberGroup<Quaternion, double>
#if CS11_OR_GREATER
,//INumber<Quaternion>,
//IFromTuple<Quaternion, (double, double, double, double)>,
IInterpolable<Quaternion>,
IPresets4d<Quaternion>,
IRoundable<Quaternion>,
ISimpleMathOperations<Quaternion>,
ISplittable<Quaternion, (double[] Ws, double[] Xs, double[] Ys, double[] Zs)>,
IVectorOperations<Quaternion>
#endif
{
public static Quaternion Backward => new Quaternion(0, 0, 0, -1);
public static Quaternion Down => new Quaternion(0, 0, -1, 0);
public static Quaternion Forward => new Quaternion(0, 0, 0, 1);
public static Quaternion HighW => new Quaternion(1, 0, 0, 0);
public static Quaternion Left => new Quaternion(0, -1, 0, 0);
public static Quaternion LowW => new Quaternion(-1, 0, 0, 0);
public static Quaternion Right => new Quaternion(0, 1, 0, 0);
public static Quaternion Up => new Quaternion(0, 0, 1, 0);
public static Quaternion One => new Quaternion(1, 1, 1, 1);
public static Quaternion Zero => new Quaternion(0, 0, 0, 0);
public Quaternion Conjugate => new Quaternion(w, -x, -y, -z);
public double Magnitude => MathE.Sqrt(w * w + x * x + y * y + z * z);
public double MagnitudeSqr => w * w + x * x + y * y + z * z;
public double w, x, y, z;
public Quaternion(double w, double x, double y, double z)
{
this.w = w;
this.x = x;
this.y = y;
this.z = z;
}
public Quaternion(IEnumerable<double> nums)
{
w = 0;
x = 0;
y = 0;
z = 0;
int index = 0;
foreach (double item in nums)
{
this[index] = item;
index++;
if (index == 4) break;
}
}
public Quaternion(Fill<double> fill)
{
w = fill(0);
x = fill(1);
y = fill(2);
z = fill(3);
}
public double this[int index]
{
get
{
switch (index)
{
case 0: return w;
case 1: return x;
case 2: return y;
case 3: return z;
default: throw new ArgumentOutOfRangeException(nameof(index));
}
}
set
{
switch (index)
{
case 0: w = value; break;
case 1: x = value; break;
case 2: y = value; break;
case 3: z = value; break;
default: throw new ArgumentOutOfRangeException(nameof(index));
}
}
}
public ListTuple<double> this[string key]
{
get
{
double[] items = new double[key.Length];
for (int i = 0; i < key.Length; i++)
{
char c = key[i];
switch (c)
{
case 'w': items[i] = w; break;
case 'x': items[i] = x; break;
case 'y': items[i] = y; break;
case 'z': items[i] = z; break;
default: throw new ArgumentException("Invalid key.", nameof(key));
}
}
return new ListTuple<double>(items);
}
set
{
IEnumerator<double> stepper = value.GetEnumerator();
for (int i = 0; i < key.Length; i++)
{
char c = key[i];
stepper.MoveNext();
switch (c)
{
case 'w': w = stepper.Current; break;
case 'x': x = stepper.Current; break;
case 'y': y = stepper.Current; break;
case 'z': z = stepper.Current; break;
default: throw new ArgumentException("Invalid key.", nameof(key));
}
}
}
}
public static Quaternion Abs(Quaternion num) => new Quaternion(num.Magnitude, 0, 0, 0);
public static Quaternion Ceiling(Quaternion num) =>
new Quaternion(MathE.Ceiling(num.w),
MathE.Ceiling(num.x),
MathE.Ceiling(num.y),
MathE.Ceiling(num.z));
public static Quaternion Ceiling(Quaternion num, Quaternion min, Quaternion max) =>
new Quaternion(MathE.Clamp(num.w, min.w, max.w),
MathE.Clamp(num.x, min.x, max.x),
MathE.Clamp(num.y, min.y, max.y),
MathE.Clamp(num.z, min.z, max.z));
public static Quaternion ClampMagnitude(Quaternion num, double minMag, double maxMag)
{
Quaternion copy = num;
ClampMagnitude(ref copy, minMag, maxMag);
return copy;
}
public static void ClampMagnitude(ref Quaternion num, double minMag, double maxMag)
{
if (minMag > maxMag) throw new ClampOrderMismatchException(nameof(minMag), nameof(maxMag));
double mag = num.Magnitude;
double factor;
if (mag < minMag) factor = minMag / mag;
else if (mag > maxMag) factor = maxMag / mag;
else factor = 1;
num.w *= factor;
num.x *= factor;
num.y *= factor;
num.z *= factor;
}
public static double Dot(Quaternion a, Quaternion b) => a.w * b.w + a.x * b.x + a.y * b.y + a.z * b.z;
public static double Dot(IEnumerable<Quaternion> nums)
{
double w = 1, x = 1, y = 1, z = 1;
foreach (Quaternion q in nums)
{
w *= q.w;
x *= q.x;
y *= q.y;
z *= q.z;
}
return w + x + y + z;
}
public static Quaternion Floor(Quaternion num) =>
new Quaternion(MathE.Floor(num.w),
MathE.Floor(num.x),
MathE.Floor(num.y),
MathE.Floor(num.z));
public static Quaternion Lerp(Quaternion a, Quaternion b, double t, bool clamp = true) =>
new Quaternion(MathE.Lerp(a.w, b.w, t, clamp),
MathE.Lerp(a.x, b.x, t, clamp),
MathE.Lerp(a.y, b.y, t, clamp),
MathE.Lerp(a.z, b.z, t, clamp));
public static Quaternion Product(IEnumerable<Quaternion> nums)
{
bool any = false;
Quaternion result = One;
foreach (Quaternion q in nums)
{
any = true;
result *= q;
}
return any ? result : Zero;
}
public static Quaternion Round(Quaternion num) =>
new Quaternion(MathE.Round(num.w),
MathE.Round(num.x),
MathE.Round(num.y),
MathE.Round(num.z));
public static Quaternion Sum(IEnumerable<Quaternion> nums)
{
bool any = false;
Quaternion result = One;
foreach (Quaternion q in nums)
{
any = true;
result += q;
}
return any ? result : Zero;
}
public static (double[] Ws, double[] Xs, double[] Ys, double[] Zs) SplitArray(IEnumerable<Quaternion> nums)
{
int count = nums.Count();
double[] Ws = new double[count],
Xs = new double[count],
Ys = new double[count],
Zs = new double[count];
int index = 0;
foreach (Quaternion q in nums)
{
Ws[index] = q.w;
Xs[index] = q.x;
Ys[index] = q.y;
Zs[index] = q.z;
index++;
}
return (Ws, Xs, Ys, Zs);
}
public IEnumerator<double> GetEnumerator()
{
yield return w;
yield return x;
yield return y;
yield return z;
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public int CompareTo(double other) => MagnitudeSqr.CompareTo(other * other);
public int CompareTo(Quaternion other) => MagnitudeSqr.CompareTo(other.MagnitudeSqr);
#if CS8_OR_GREATER
public int CompareTo(object? other)
#else
public int CompareTo(object other)
#endif
{
if (other is null) return 1;
else if (other is Quaternion otherQuat) return CompareTo(otherQuat);
else if (other is double otherNum) return CompareTo(otherNum);
//else if (TryConvertFrom(other, out Quaternion otherConvert)) return CompareTo(otherConvert);
else return 1;
}
public bool Equals(double other) => w == other && x == 0 && y == 0 && z == 0;
public bool Equals(Complex other) => w == other.r && x == other.i && y == 0 && z == 0;
public bool Equals(Quaternion other) => w == other.w && x == other.x && y == other.y && z == other.z;
#if CS8_OR_GREATER
public override bool Equals(object? other)
#else
public override bool Equals(object other)
#endif
{
if (other is null) return false;
else if (other is Quaternion otherQuat) return Equals(otherQuat);
else if (other is Complex otherComp) return Equals(otherComp);
else if (other is double otherNum) return Equals(otherNum);
//else if (TryConvertFrom(other, out Quaternion otherConvert)) return Equals(otherConvert);
else return false;
}
public override int GetHashCode() => base.GetHashCode();
public override string ToString() => ToStringHelper.HighDimNumberToString(this, null, null);
#if CS8_OR_GREATER
public string ToString(string? format) => ToStringHelper.HighDimNumberToString(this, format, null);
public string ToString(IFormatProvider? provider) => ToStringHelper.HighDimNumberToString(this, null, provider);
public string ToString(string? format, IFormatProvider? provider) => ToStringHelper.HighDimNumberToString(this, format, provider);
#else
public string ToString(string format) => ToStringHelper.HighDimNumberToString(this, format, null);
public string ToString(IFormatProvider provider) => ToStringHelper.HighDimNumberToString(this, null, provider);
public string ToString(string format, IFormatProvider provider) => ToStringHelper.HighDimNumberToString(this, format, provider);
#endif
public double[] ToArray() => new double[] { w, x, y, z };
public Fill<double> ToFill()
{
Quaternion @this = this;
return i => @this[i];
}
public List<double> ToList() => new List<double>() { w, x, y, z };
public static Quaternion operator +(Quaternion a) => a;
public static Quaternion operator +(Quaternion a, Quaternion b) => new Quaternion(a.w + b.w, a.x + b.x, a.y + b.y, a.z + b.z);
public static Quaternion operator +(Quaternion a, Complex b) => new Quaternion(a.w + b.r, a.x + b.i, a.y, a.z);
public static Quaternion operator +(Quaternion a, double b) => new Quaternion(a.w + b, a.x, a.y, a.z);
public static Quaternion operator -(Quaternion a) => new Quaternion(-a.w, -a.x, -a.y, -a.z);
public static Quaternion operator -(Quaternion a, Quaternion b) => new Quaternion(a.w - b.w, a.x - b.x, a.y - b.y, a.z - b.z);
public static Quaternion operator -(Quaternion a, Complex b) => new Quaternion(a.w - b.r, a.x - b.i, a.y, a.z);
public static Quaternion operator -(Quaternion a, double b) => new Quaternion(a.w - b, a.x, a.y, a.z);
public static Quaternion operator *(Quaternion a, Quaternion b) =>
new Quaternion(a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z,
a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y,
a.w * b.y - a.x * b.z + a.y * b.w + a.z * b.x,
a.w * b.z + a.x * b.y - a.y * b.x + a.z * b.w);
public static Quaternion operator *(Quaternion a, Complex b) =>
new Quaternion(a.w * b.r - a.x * b.i,
a.x * b.r + a.w * b.i,
a.y * b.r + a.z * b.i,
a.z * b.r - a.y * b.i);
public static Quaternion operator *(Quaternion a, double b) => new Quaternion(a.w * b, a.x * b, a.y * b, a.z * b);
public static bool operator ==(Quaternion a, Quaternion b) => a.Equals(b);
public static bool operator !=(Quaternion a, Quaternion b) => !a.Equals(b);
public static bool operator >(Quaternion a, Quaternion b) => a.CompareTo(b) > 0;
public static bool operator <(Quaternion a, Quaternion b) => a.CompareTo(b) < 0;
public static bool operator >=(Quaternion a, Quaternion b) => a.CompareTo(b) >= 0;
public static bool operator <=(Quaternion a, Quaternion b) => a.CompareTo(b) <= 0;
public static implicit operator Quaternion(Complex complex) => new Quaternion(complex.r, complex.i, 0, 0);
}
}