Imported Upstream version 4.6.0.125

Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2016-08-03 10:59:49 +00:00
parent a569aebcfd
commit e79aa3c0ed
17047 changed files with 3137615 additions and 392334 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,421 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
/*=========================================================================
**
** Class: Complex
**
**
** Purpose:
** This feature is intended to create Complex Number as a type
** that can be a part of the .NET framework (base class libraries).
** A complex number z is a number of the form z = x + yi, where x and y
** are real numbers, and i is the imaginary unit, with the property i2= -1.
**
**
===========================================================================*/
using System;
using System.Globalization;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
namespace System.Numerics {
#if !SILVERLIGHT
[Serializable]
#endif // !SILVERLIGHT
public struct Complex : IEquatable<Complex>, IFormattable {
// --------------SECTION: Private Data members ----------- //
private Double m_real;
private Double m_imaginary;
// ---------------SECTION: Necessary Constants ----------- //
private const Double LOG_10_INV = 0.43429448190325;
// --------------SECTION: Public Properties -------------- //
public Double Real {
get {
return m_real;
}
}
public Double Imaginary {
get {
return m_imaginary;
}
}
public Double Magnitude {
get {
return Complex.Abs(this);
}
}
public Double Phase {
get {
return Math.Atan2(m_imaginary, m_real);
}
}
// --------------SECTION: Attributes -------------- //
public static readonly Complex Zero = new Complex(0.0, 0.0);
public static readonly Complex One = new Complex(1.0, 0.0);
public static readonly Complex ImaginaryOne = new Complex(0.0, 1.0);
// --------------SECTION: Constructors and factory methods -------------- //
public Complex(Double real, Double imaginary) /* Constructor to create a complex number with rectangular co-ordinates */
{
this.m_real = real;
this.m_imaginary = imaginary;
}
public static Complex FromPolarCoordinates(Double magnitude, Double phase) /* Factory method to take polar inputs and create a Complex object */
{
return new Complex((magnitude * Math.Cos(phase)), (magnitude * Math.Sin(phase)));
}
public static Complex Negate(Complex value) {
return -value;
}
public static Complex Add(Complex left, Complex right) {
return left + right;
}
public static Complex Subtract(Complex left, Complex right) {
return left - right;
}
public static Complex Multiply(Complex left, Complex right) {
return left * right;
}
public static Complex Divide(Complex dividend, Complex divisor) {
return dividend / divisor;
}
// --------------SECTION: Arithmetic Operator(unary) Overloading -------------- //
public static Complex operator -(Complex value) /* Unary negation of a complex number */
{
return (new Complex((-value.m_real), (-value.m_imaginary)));
}
// --------------SECTION: Arithmetic Operator(binary) Overloading -------------- //
public static Complex operator +(Complex left, Complex right) {
return (new Complex((left.m_real + right.m_real), (left.m_imaginary + right.m_imaginary)));
}
public static Complex operator -(Complex left, Complex right) {
return (new Complex((left.m_real - right.m_real), (left.m_imaginary - right.m_imaginary)));
}
public static Complex operator *(Complex left, Complex right) {
// Multiplication: (a + bi)(c + di) = (ac -bd) + (bc + ad)i
Double result_Realpart = (left.m_real * right.m_real) - (left.m_imaginary * right.m_imaginary);
Double result_Imaginarypart = (left.m_imaginary * right.m_real) + (left.m_real * right.m_imaginary);
return (new Complex(result_Realpart, result_Imaginarypart));
}
public static Complex operator /(Complex left, Complex right) {
// Division : Smith's formula.
double a = left.m_real;
double b = left.m_imaginary;
double c = right.m_real;
double d = right.m_imaginary;
if (Math.Abs(d) < Math.Abs(c)) {
double doc = d / c;
return new Complex((a + b * doc) / (c + d * doc), (b - a * doc) / (c + d * doc));
} else {
double cod = c / d;
return new Complex((b + a * cod) / (d + c * cod), (-a + b * cod) / (d + c * cod));
}
}
// --------------SECTION: Other arithmetic operations -------------- //
public static Double Abs(Complex value) {
if(Double.IsInfinity(value.m_real) || Double.IsInfinity(value.m_imaginary)) {
return double.PositiveInfinity;
}
// |value| == sqrt(a^2 + b^2)
// sqrt(a^2 + b^2) == a/a * sqrt(a^2 + b^2) = a * sqrt(a^2/a^2 + b^2/a^2)
// Using the above we can factor out the square of the larger component to dodge overflow.
double c = Math.Abs(value.m_real);
double d = Math.Abs(value.m_imaginary);
if (c > d) {
double r = d / c;
return c * Math.Sqrt(1.0 + r * r);
} else if (d == 0.0) {
return c; // c is either 0.0 or NaN
} else {
double r = c / d;
return d * Math.Sqrt(1.0 + r * r);
}
}
public static Complex Conjugate(Complex value) {
// Conjugate of a Complex number: the conjugate of x+i*y is x-i*y
return (new Complex(value.m_real, (-value.m_imaginary)));
}
public static Complex Reciprocal(Complex value) {
// Reciprocal of a Complex number : the reciprocal of x+i*y is 1/(x+i*y)
if ((value.m_real == 0) && (value.m_imaginary == 0)) {
return Complex.Zero;
}
return Complex.One / value;
}
// --------------SECTION: Comparison Operator(binary) Overloading -------------- //
public static bool operator ==(Complex left, Complex right) {
return ((left.m_real == right.m_real) && (left.m_imaginary == right.m_imaginary));
}
public static bool operator !=(Complex left, Complex right) {
return ((left.m_real != right.m_real) || (left.m_imaginary != right.m_imaginary));
}
// --------------SECTION: Comparison operations (methods implementing IEquatable<ComplexNumber>,IComparable<ComplexNumber>) -------------- //
public override bool Equals(object obj) {
if (!(obj is Complex)) return false;
return this == ((Complex)obj);
}
public bool Equals(Complex value) {
return ((this.m_real.Equals(value.m_real)) && (this.m_imaginary.Equals(value.m_imaginary)));
}
// --------------SECTION: Type-casting basic numeric data-types to ComplexNumber -------------- //
public static implicit operator Complex(Int16 value) {
return (new Complex(value, 0.0));
}
public static implicit operator Complex(Int32 value) {
return (new Complex(value, 0.0));
}
public static implicit operator Complex(Int64 value) {
return (new Complex(value, 0.0));
}
[CLSCompliant(false)]
public static implicit operator Complex(UInt16 value) {
return (new Complex(value, 0.0));
}
[CLSCompliant(false)]
public static implicit operator Complex(UInt32 value) {
return (new Complex(value, 0.0));
}
[CLSCompliant(false)]
public static implicit operator Complex(UInt64 value) {
return (new Complex(value, 0.0));
}
[CLSCompliant(false)]
public static implicit operator Complex(SByte value) {
return (new Complex(value, 0.0));
}
public static implicit operator Complex(Byte value) {
return (new Complex(value, 0.0));
}
public static implicit operator Complex(Single value) {
return (new Complex(value, 0.0));
}
public static implicit operator Complex(Double value) {
return (new Complex(value, 0.0));
}
public static explicit operator Complex(BigInteger value) {
return (new Complex((Double)value, 0.0));
}
public static explicit operator Complex(Decimal value) {
return (new Complex((Double)value, 0.0));
}
// --------------SECTION: Formattig/Parsing options -------------- //
public override String ToString() {
return (String.Format(CultureInfo.CurrentCulture, "({0}, {1})", this.m_real, this.m_imaginary));
}
public String ToString(String format) {
return (String.Format(CultureInfo.CurrentCulture, "({0}, {1})", this.m_real.ToString(format, CultureInfo.CurrentCulture), this.m_imaginary.ToString(format, CultureInfo.CurrentCulture)));
}
public String ToString(IFormatProvider provider) {
return (String.Format(provider, "({0}, {1})", this.m_real, this.m_imaginary));
}
public String ToString(String format, IFormatProvider provider) {
return (String.Format(provider, "({0}, {1})", this.m_real.ToString(format, provider), this.m_imaginary.ToString(format, provider)));
}
public override Int32 GetHashCode() {
Int32 n1 = 99999997;
Int32 hash_real = this.m_real.GetHashCode() % n1;
Int32 hash_imaginary = this.m_imaginary.GetHashCode();
Int32 final_hashcode = hash_real ^ hash_imaginary;
return (final_hashcode);
}
// --------------SECTION: Trigonometric operations (methods implementing ITrigonometric) -------------- //
public static Complex Sin(Complex value) {
double a = value.m_real;
double b = value.m_imaginary;
return new Complex(Math.Sin(a) * Math.Cosh(b), Math.Cos(a) * Math.Sinh(b));
}
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sinh", Justification = "[....]: Existing Name")]
public static Complex Sinh(Complex value) /* Hyperbolic sin */
{
double a = value.m_real;
double b = value.m_imaginary;
return new Complex(Math.Sinh(a) * Math.Cos(b), Math.Cosh(a) * Math.Sin(b));
}
public static Complex Asin(Complex value) /* Arcsin */
{
if ((value.m_imaginary == 0 && value.m_real < 0) || value.m_imaginary > 0)
{
return -Asin(-value);
}
return (-ImaginaryOne) * Log(ImaginaryOne * value + Sqrt(One - value * value));
}
public static Complex Cos(Complex value) {
double a = value.m_real;
double b = value.m_imaginary;
return new Complex(Math.Cos(a) * Math.Cosh(b), - (Math.Sin(a) * Math.Sinh(b)));
}
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Cosh", Justification = "[....]: Existing Name")]
public static Complex Cosh(Complex value) /* Hyperbolic cos */
{
double a = value.m_real;
double b = value.m_imaginary;
return new Complex(Math.Cosh(a) * Math.Cos(b), Math.Sinh(a) * Math.Sin(b));
}
public static Complex Acos(Complex value) /* Arccos */
{
if ((value.m_imaginary == 0 && value.m_real > 0) || value.m_imaginary < 0)
{
return System.Math.PI - Acos(-value);
}
return (-ImaginaryOne) * Log(value + ImaginaryOne*Sqrt(One - (value * value)));
}
public static Complex Tan(Complex value) {
return (Sin(value) / Cos(value));
}
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Tanh", Justification = "[....]: Existing Name")]
public static Complex Tanh(Complex value) /* Hyperbolic tan */
{
return (Sinh(value) / Cosh(value));
}
public static Complex Atan(Complex value) /* Arctan */
{
Complex Two = new Complex(2.0, 0.0);
return (ImaginaryOne / Two) * (Log(One - ImaginaryOne * value) - Log(One + ImaginaryOne * value));
}
// --------------SECTION: Other numerical functions -------------- //
public static Complex Log(Complex value) /* Log of the complex number value to the base of 'e' */
{
return (new Complex((Math.Log(Abs(value))), (Math.Atan2(value.m_imaginary, value.m_real))));
}
public static Complex Log(Complex value, Double baseValue) /* Log of the complex number to a the base of a double */
{
return (Log(value) / Log(baseValue));
}
public static Complex Log10(Complex value) /* Log to the base of 10 of the complex number */
{
Complex temp_log = Log(value);
return (Scale(temp_log, (Double)LOG_10_INV));
}
public static Complex Exp(Complex value) /* The complex number raised to e */
{
Double temp_factor = Math.Exp(value.m_real);
Double result_re = temp_factor * Math.Cos(value.m_imaginary);
Double result_im = temp_factor * Math.Sin(value.m_imaginary);
return (new Complex(result_re, result_im));
}
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sqrt", Justification = "[....]: Existing Name")]
public static Complex Sqrt(Complex value) /* Square root ot the complex number */
{
return Complex.FromPolarCoordinates(Math.Sqrt(value.Magnitude), value.Phase / 2.0);
}
public static Complex Pow(Complex value, Complex power) /* A complex number raised to another complex number */
{
if (power == Complex.Zero) {
return Complex.One;
}
if (value == Complex.Zero) {
return Complex.Zero;
}
double a = value.m_real;
double b = value.m_imaginary;
double c = power.m_real;
double d = power.m_imaginary;
double rho = Complex.Abs(value);
double theta = Math.Atan2(b, a);
double newRho = c * theta + d * Math.Log(rho);
double t = Math.Pow(rho, c) * Math.Pow(Math.E, -d * theta);
return new Complex(t * Math.Cos(newRho), t * Math.Sin(newRho));
}
public static Complex Pow(Complex value, Double power) // A complex number raised to a real number
{
return Pow(value, new Complex(power, 0));
}
//--------------- SECTION: Private member functions for internal use -----------------------------------//
private static Complex Scale(Complex value, Double factor) {
Double result_re = factor * value.m_real;
Double result_im = factor * value.m_imaginary;
return (new Complex(result_re, result_im));
}
}
}

View File

@@ -0,0 +1,16 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace System.Numerics
{
internal static class HashCodeHelper
{
/// <summary>
/// Combines two hash codes, useful for combining hash codes of individual vector elements
/// </summary>
internal static int CombineHashCodes(int h1, int h2)
{
return (((h1 << 5) + h1) ^ h2);
}
}
}

View File

@@ -0,0 +1,13 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace System.Numerics
{
/// <summary>
/// An attribute that can be attached to JIT Intrinsic methods/properties
/// </summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property)]
internal class JitIntrinsicAttribute : Attribute
{
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,360 @@
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
using System;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
namespace System.Numerics {
[StructLayout(LayoutKind.Explicit)]
internal struct DoubleUlong {
[FieldOffset(0)]
public double dbl;
[FieldOffset(0)]
public ulong uu;
}
internal static class NumericsHelpers {
private const int kcbitUint = 32;
public static void GetDoubleParts(double dbl, out int sign, out int exp, out ulong man, out bool fFinite) {
Contract.Ensures(Contract.ValueAtReturn(out sign) == +1 || Contract.ValueAtReturn(out sign) == -1);
DoubleUlong du;
du.uu = 0;
du.dbl = dbl;
sign = 1 - ((int)(du.uu >> 62) & 2);
man = du.uu & 0x000FFFFFFFFFFFFF;
exp = (int)(du.uu >> 52) & 0x7FF;
if (exp == 0) {
// Denormalized number.
fFinite = true;
if (man != 0)
exp = -1074;
}
else if (exp == 0x7FF) {
// NaN or Inifite.
fFinite = false;
exp = int.MaxValue;
}
else {
fFinite = true;
man |= 0x0010000000000000;
exp -= 1075;
}
}
public static double GetDoubleFromParts(int sign, int exp, ulong man) {
DoubleUlong du;
du.dbl = 0;
if (man == 0)
du.uu = 0;
else {
// Normalize so that 0x0010 0000 0000 0000 is the highest bit set.
int cbitShift = CbitHighZero(man) - 11;
if (cbitShift < 0)
man >>= -cbitShift;
else
man <<= cbitShift;
exp -= cbitShift;
Contract.Assert((man & 0xFFF0000000000000) == 0x0010000000000000);
// Move the point to just behind the leading 1: 0x001.0 0000 0000 0000
// (52 bits) and skew the exponent (by 0x3FF == 1023).
exp += 1075;
if (exp >= 0x7FF) {
// Infinity.
du.uu = 0x7FF0000000000000;
}
else if (exp <= 0) {
// Denormalized.
exp--;
if (exp < -52) {
// Underflow to zero.
du.uu = 0;
}
else {
du.uu = man >> -exp;
Contract.Assert(du.uu != 0);
}
}
else {
// Mask off the implicit high bit.
du.uu = (man & 0x000FFFFFFFFFFFFF) | ((ulong)exp << 52);
}
}
if (sign < 0)
du.uu |= 0x8000000000000000;
return du.dbl;
}
// Do an in-place twos complement of d and also return the result.
// "Dangerous" because it causes a mutation and needs to be used
// with care for immutable types
public static uint[] DangerousMakeTwosComplement(uint[] d) {
// first do complement and +1 as long as carry is needed
int i = 0;
uint v = 0;
for (; i < d.Length; i++) {
v = ~d[i] + 1;
d[i] = v;
if (v != 0) { i++; break; }
}
if (v != 0) {
// now ones complement is sufficient
for (; i < d.Length; i++) {
d[i] = ~d[i];
}
} else {
//??? this is weird
d = resize(d, d.Length + 1);
d[d.Length - 1] = 1;
}
return d;
}
public static uint[] resize(uint[] v, int len) {
if (v.Length == len) return v;
uint[] ret = new uint[len];
int n = System.Math.Min(v.Length, len);
for (int i = 0; i < n; i++) {
ret[i] = v[i];
}
return ret;
}
public static void Swap<T>(ref T a, ref T b) {
T tmp = a;
a = b;
b = tmp;
}
public static uint GCD(uint u1, uint u2) {
const int cvMax = 32;
if (u1 < u2)
goto LOther;
LTop:
Contract.Assert(u2 <= u1);
if (u2 == 0)
return u1;
for (int cv = cvMax; ; ) {
u1 -= u2;
if (u1 < u2)
break;
if (--cv == 0) {
u1 %= u2;
break;
}
}
LOther:
Contract.Assert(u1 < u2);
if (u1 == 0)
return u2;
for (int cv = cvMax; ; ) {
u2 -= u1;
if (u2 < u1)
break;
if (--cv == 0) {
u2 %= u1;
break;
}
}
goto LTop;
}
public static ulong GCD(ulong uu1, ulong uu2) {
const int cvMax = 32;
if (uu1 < uu2)
goto LOther;
LTop:
Contract.Assert(uu2 <= uu1);
if (uu1 <= uint.MaxValue)
goto LSmall;
if (uu2 == 0)
return uu1;
for (int cv = cvMax; ; ) {
uu1 -= uu2;
if (uu1 < uu2)
break;
if (--cv == 0) {
uu1 %= uu2;
break;
}
}
LOther:
Contract.Assert(uu1 < uu2);
if (uu2 <= uint.MaxValue)
goto LSmall;
if (uu1 == 0)
return uu2;
for (int cv = cvMax; ; ) {
uu2 -= uu1;
if (uu2 < uu1)
break;
if (--cv == 0) {
uu2 %= uu1;
break;
}
}
goto LTop;
LSmall:
uint u1 = (uint)uu1;
uint u2 = (uint)uu2;
if (u1 < u2)
goto LOtherSmall;
LTopSmall:
Contract.Assert(u2 <= u1);
if (u2 == 0)
return u1;
for (int cv = cvMax; ; ) {
u1 -= u2;
if (u1 < u2)
break;
if (--cv == 0) {
u1 %= u2;
break;
}
}
LOtherSmall:
Contract.Assert(u1 < u2);
if (u1 == 0)
return u2;
for (int cv = cvMax; ; ) {
u2 -= u1;
if (u2 < u1)
break;
if (--cv == 0) {
u2 %= u1;
break;
}
}
goto LTopSmall;
}
public static ulong MakeUlong(uint uHi, uint uLo) {
return ((ulong)uHi << kcbitUint) | uLo;
}
public static uint GetLo(ulong uu) {
return (uint)uu;
}
public static uint GetHi(ulong uu) {
return (uint)(uu >> kcbitUint);
}
public static uint Abs(int a) {
uint mask = (uint)(a >> 31);
return ((uint)a ^ mask) - mask;
}
// public static ulong Abs(long a) {
// ulong mask = (ulong)(a >> 63);
// return ((ulong)a ^ mask) - mask;
// }
public static uint CombineHash(uint u1, uint u2) {
return ((u1 << 7) | (u1 >> 25)) ^ u2;
}
public static int CombineHash(int n1, int n2) {
return (int)CombineHash((uint)n1, (uint)n2);
}
public static int CbitHighZero(uint u) {
if (u == 0)
return 32;
int cbit = 0;
if ((u & 0xFFFF0000) == 0) {
cbit += 16;
u <<= 16;
}
if ((u & 0xFF000000) == 0) {
cbit += 8;
u <<= 8;
}
if ((u & 0xF0000000) == 0) {
cbit += 4;
u <<= 4;
}
if ((u & 0xC0000000) == 0) {
cbit += 2;
u <<= 2;
}
if ((u & 0x80000000) == 0)
cbit += 1;
return cbit;
}
public static int CbitLowZero(uint u) {
if (u == 0)
return 32;
int cbit = 0;
if ((u & 0x0000FFFF) == 0) {
cbit += 16;
u >>= 16;
}
if ((u & 0x000000FF) == 0) {
cbit += 8;
u >>= 8;
}
if ((u & 0x0000000F) == 0) {
cbit += 4;
u >>= 4;
}
if ((u & 0x00000003) == 0) {
cbit += 2;
u >>= 2;
}
if ((u & 0x00000001) == 0)
cbit += 1;
return cbit;
}
public static int CbitHighZero(ulong uu) {
if ((uu & 0xFFFFFFFF00000000) == 0)
return 32 + CbitHighZero((uint)uu);
return CbitHighZero((uint)(uu >> 32));
}
// public static int CbitLowZero(ulong uu) {
// if ((uint)uu == 0)
// return 32 + CbitLowZero((uint)(uu >> 32));
// return CbitLowZero((uint)uu);
// }
//
// public static int Cbit(uint u) {
// u = (u & 0x55555555) + ((u >> 1) & 0x55555555);
// u = (u & 0x33333333) + ((u >> 2) & 0x33333333);
// u = (u & 0x0F0F0F0F) + ((u >> 4) & 0x0F0F0F0F);
// u = (u & 0x00FF00FF) + ((u >> 8) & 0x00FF00FF);
// return (int)((ushort)u + (ushort)(u >> 16));
// }
//
// static int Cbit(ulong uu) {
// uu = (uu & 0x5555555555555555) + ((uu >> 1) & 0x5555555555555555);
// uu = (uu & 0x3333333333333333) + ((uu >> 2) & 0x3333333333333333);
// uu = (uu & 0x0F0F0F0F0F0F0F0F) + ((uu >> 4) & 0x0F0F0F0F0F0F0F0F);
// uu = (uu & 0x00FF00FF00FF00FF) + ((uu >> 8) & 0x00FF00FF00FF00FF);
// uu = (uu & 0x0000FFFF0000FFFF) + ((uu >> 16) & 0x0000FFFF0000FFFF);
// return (int)((uint)uu + (uint)(uu >> 32));
// }
}
}

View File

@@ -0,0 +1,366 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Globalization;
using System.Runtime.CompilerServices;
namespace System.Numerics
{
/// <summary>
/// A structure encapsulating a 3D Plane
/// </summary>
public struct Plane : IEquatable<Plane>
{
/// <summary>
/// The normal vector of the Plane.
/// </summary>
public Vector3 Normal;
/// <summary>
/// The distance of the Plane along its normal from the origin.
/// </summary>
public float D;
/// <summary>
/// Constructs a Plane from the X, Y, and Z components of its normal, and its distance from the origin on that normal.
/// </summary>
/// <param name="x">The X-component of the normal.</param>
/// <param name="y">The Y-component of the normal.</param>
/// <param name="z">The Z-component of the normal.</param>
/// <param name="d">The distance of the Plane along its normal from the origin.</param>
public Plane(float x, float y, float z, float d)
{
Normal = new Vector3(x, y, z);
this.D = d;
}
/// <summary>
/// Constructs a Plane from the given normal and distance along the normal from the origin.
/// </summary>
/// <param name="normal">The Plane's normal vector.</param>
/// <param name="d">The Plane's distance from the origin along its normal vector.</param>
public Plane(Vector3 normal, float d)
{
this.Normal = normal;
this.D = d;
}
/// <summary>
/// Constructs a Plane from the given Vector4.
/// </summary>
/// <param name="value">A vector whose first 3 elements describe the normal vector,
/// and whose W component defines the distance along that normal from the origin.</param>
public Plane(Vector4 value)
{
Normal = new Vector3(value.X, value.Y, value.Z);
D = value.W;
}
/// <summary>
/// Creates a Plane that contains the three given points.
/// </summary>
/// <param name="point1">The first point defining the Plane.</param>
/// <param name="point2">The second point defining the Plane.</param>
/// <param name="point3">The third point defining the Plane.</param>
/// <returns>The Plane containing the three points.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Plane CreateFromVertices(Vector3 point1, Vector3 point2, Vector3 point3)
{
if (Vector.IsHardwareAccelerated)
{
Vector3 a = point2 - point1;
Vector3 b = point3 - point1;
// N = Cross(a, b)
Vector3 n = Vector3.Cross(a, b);
Vector3 normal = Vector3.Normalize(n);
// D = - Dot(N, point1)
float d = -Vector3.Dot(normal, point1);
return new Plane(normal, d);
}
else
{
float ax = point2.X - point1.X;
float ay = point2.Y - point1.Y;
float az = point2.Z - point1.Z;
float bx = point3.X - point1.X;
float by = point3.Y - point1.Y;
float bz = point3.Z - point1.Z;
// N=Cross(a,b)
float nx = ay * bz - az * by;
float ny = az * bx - ax * bz;
float nz = ax * by - ay * bx;
// Normalize(N)
float ls = nx * nx + ny * ny + nz * nz;
float invNorm = 1.0f / (float)Math.Sqrt((double)ls);
Vector3 normal = new Vector3(
nx * invNorm,
ny * invNorm,
nz * invNorm);
return new Plane(
normal,
-(normal.X * point1.X + normal.Y * point1.Y + normal.Z * point1.Z));
}
}
/// <summary>
/// Creates a new Plane whose normal vector is the source Plane's normal vector normalized.
/// </summary>
/// <param name="value">The source Plane.</param>
/// <returns>The normalized Plane.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Plane Normalize(Plane value)
{
const float FLT_EPSILON = 1.192092896e-07f; // smallest such that 1.0+FLT_EPSILON != 1.0
if (Vector.IsHardwareAccelerated)
{
float normalLengthSquared = value.Normal.LengthSquared();
if (Math.Abs(normalLengthSquared - 1.0f) < FLT_EPSILON)
{
// It already normalized, so we don't need to farther process.
return value;
}
float normalLength = (float)Math.Sqrt(normalLengthSquared);
return new Plane(
value.Normal / normalLength,
value.D / normalLength);
}
else
{
float f = value.Normal.X * value.Normal.X + value.Normal.Y * value.Normal.Y + value.Normal.Z * value.Normal.Z;
if (Math.Abs(f - 1.0f) < FLT_EPSILON)
{
return value; // It already normalized, so we don't need to further process.
}
float fInv = 1.0f / (float)Math.Sqrt(f);
return new Plane(
value.Normal.X * fInv,
value.Normal.Y * fInv,
value.Normal.Z * fInv,
value.D * fInv);
}
}
/// <summary>
/// Transforms a normalized Plane by a Matrix.
/// </summary>
/// <param name="plane"> The normalized Plane to transform.
/// This Plane must already be normalized, so that its Normal vector is of unit length, before this method is called.</param>
/// <param name="matrix">The transformation matrix to apply to the Plane.</param>
/// <returns>The transformed Plane.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Plane Transform(Plane plane, Matrix4x4 matrix)
{
Matrix4x4 m;
Matrix4x4.Invert(matrix, out m);
float x = plane.Normal.X, y = plane.Normal.Y, z = plane.Normal.Z, w = plane.D;
return new Plane(
x * m.M11 + y * m.M12 + z * m.M13 + w * m.M14,
x * m.M21 + y * m.M22 + z * m.M23 + w * m.M24,
x * m.M31 + y * m.M32 + z * m.M33 + w * m.M34,
x * m.M41 + y * m.M42 + z * m.M43 + w * m.M44);
}
/// <summary>
/// Transforms a normalized Plane by a Quaternion rotation.
/// </summary>
/// <param name="plane"> The normalized Plane to transform.
/// This Plane must already be normalized, so that its Normal vector is of unit length, before this method is called.</param>
/// <param name="rotation">The Quaternion rotation to apply to the Plane.</param>
/// <returns>A new Plane that results from applying the rotation.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Plane Transform(Plane plane, Quaternion rotation)
{
// Compute rotation matrix.
float x2 = rotation.X + rotation.X;
float y2 = rotation.Y + rotation.Y;
float z2 = rotation.Z + rotation.Z;
float wx2 = rotation.W * x2;
float wy2 = rotation.W * y2;
float wz2 = rotation.W * z2;
float xx2 = rotation.X * x2;
float xy2 = rotation.X * y2;
float xz2 = rotation.X * z2;
float yy2 = rotation.Y * y2;
float yz2 = rotation.Y * z2;
float zz2 = rotation.Z * z2;
float m11 = 1.0f - yy2 - zz2;
float m21 = xy2 - wz2;
float m31 = xz2 + wy2;
float m12 = xy2 + wz2;
float m22 = 1.0f - xx2 - zz2;
float m32 = yz2 - wx2;
float m13 = xz2 - wy2;
float m23 = yz2 + wx2;
float m33 = 1.0f - xx2 - yy2;
float x = plane.Normal.X, y = plane.Normal.Y, z = plane.Normal.Z;
return new Plane(
x * m11 + y * m21 + z * m31,
x * m12 + y * m22 + z * m32,
x * m13 + y * m23 + z * m33,
plane.D);
}
/// <summary>
/// Calculates the dot product of a Plane and Vector4.
/// </summary>
/// <param name="plane">The Plane.</param>
/// <param name="value">The Vector4.</param>
/// <returns>The dot product.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Dot(Plane plane, Vector4 value)
{
return plane.Normal.X * value.X +
plane.Normal.Y * value.Y +
plane.Normal.Z * value.Z +
plane.D * value.W;
}
/// <summary>
/// Returns the dot product of a specified Vector3 and the normal vector of this Plane plus the distance (D) value of the Plane.
/// </summary>
/// <param name="plane">The plane.</param>
/// <param name="value">The Vector3.</param>
/// <returns>The resulting value.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float DotCoordinate(Plane plane, Vector3 value)
{
if (Vector.IsHardwareAccelerated)
{
return Vector3.Dot(plane.Normal, value) + plane.D;
}
else
{
return plane.Normal.X * value.X +
plane.Normal.Y * value.Y +
plane.Normal.Z * value.Z +
plane.D;
}
}
/// <summary>
/// Returns the dot product of a specified Vector3 and the Normal vector of this Plane.
/// </summary>
/// <param name="plane">The plane.</param>
/// <param name="value">The Vector3.</param>
/// <returns>The resulting dot product.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float DotNormal(Plane plane, Vector3 value)
{
if (Vector.IsHardwareAccelerated)
{
return Vector3.Dot(plane.Normal, value);
}
else
{
return plane.Normal.X * value.X +
plane.Normal.Y * value.Y +
plane.Normal.Z * value.Z;
}
}
/// <summary>
/// Returns a boolean indicating whether the two given Planes are equal.
/// </summary>
/// <param name="value1">The first Plane to compare.</param>
/// <param name="value2">The second Plane to compare.</param>
/// <returns>True if the Planes are equal; False otherwise.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Plane value1, Plane value2)
{
return (value1.Normal.X == value2.Normal.X &&
value1.Normal.Y == value2.Normal.Y &&
value1.Normal.Z == value2.Normal.Z &&
value1.D == value2.D);
}
/// <summary>
/// Returns a boolean indicating whether the two given Planes are not equal.
/// </summary>
/// <param name="value1">The first Plane to compare.</param>
/// <param name="value2">The second Plane to compare.</param>
/// <returns>True if the Planes are not equal; False if they are equal.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Plane value1, Plane value2)
{
return (value1.Normal.X != value2.Normal.X ||
value1.Normal.Y != value2.Normal.Y ||
value1.Normal.Z != value2.Normal.Z ||
value1.D != value2.D);
}
/// <summary>
/// Returns a boolean indicating whether the given Plane is equal to this Plane instance.
/// </summary>
/// <param name="other">The Plane to compare this instance to.</param>
/// <returns>True if the other Plane is equal to this instance; False otherwise.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Plane other)
{
if (Vector.IsHardwareAccelerated)
{
return this.Normal.Equals(other.Normal) && this.D == other.D;
}
else
{
return (Normal.X == other.Normal.X &&
Normal.Y == other.Normal.Y &&
Normal.Z == other.Normal.Z &&
D == other.D);
}
}
/// <summary>
/// Returns a boolean indicating whether the given Object is equal to this Plane instance.
/// </summary>
/// <param name="obj">The Object to compare against.</param>
/// <returns>True if the Object is equal to this Plane; False otherwise.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
if (obj is Plane)
{
return Equals((Plane)obj);
}
return false;
}
/// <summary>
/// Returns a String representing this Plane instance.
/// </summary>
/// <returns>The string representation.</returns>
public override string ToString()
{
CultureInfo ci = CultureInfo.CurrentCulture;
return String.Format(ci, "{{Normal:{0} D:{1}}}", Normal.ToString(), D.ToString(ci));
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>The hash code.</returns>
public override int GetHashCode()
{
return Normal.GetHashCode() + D.GetHashCode();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,451 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Text;
namespace System.Numerics
{
/// <summary>
/// A structure encapsulating two single precision floating point values and provides hardware accelerated methods.
/// </summary>
public partial struct Vector2 : IEquatable<Vector2>, IFormattable
{
#region Public Static Properties
/// <summary>
/// Returns the vector (0,0).
/// </summary>
public static Vector2 Zero { get { return new Vector2(); } }
/// <summary>
/// Returns the vector (1,1).
/// </summary>
public static Vector2 One { get { return new Vector2(1.0f, 1.0f); } }
/// <summary>
/// Returns the vector (1,0).
/// </summary>
public static Vector2 UnitX { get { return new Vector2(1.0f, 0.0f); } }
/// <summary>
/// Returns the vector (0,1).
/// </summary>
public static Vector2 UnitY { get { return new Vector2(0.0f, 1.0f); } }
#endregion Public Static Properties
#region Public instance methods
/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>The hash code.</returns>
public override int GetHashCode()
{
int hash = this.X.GetHashCode();
hash = HashCodeHelper.CombineHashCodes(hash, this.Y.GetHashCode());
return hash;
}
/// <summary>
/// Returns a boolean indicating whether the given Object is equal to this Vector2 instance.
/// </summary>
/// <param name="obj">The Object to compare against.</param>
/// <returns>True if the Object is equal to this Vector2; False otherwise.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
if (!(obj is Vector2))
return false;
return Equals((Vector2)obj);
}
/// <summary>
/// Returns a String representing this Vector2 instance.
/// </summary>
/// <returns>The string representation.</returns>
public override string ToString()
{
return ToString("G", CultureInfo.CurrentCulture);
}
/// <summary>
/// Returns a String representing this Vector2 instance, using the specified format to format individual elements.
/// </summary>
/// <param name="format">The format of individual elements.</param>
/// <returns>The string representation.</returns>
public string ToString(string format)
{
return ToString(format, CultureInfo.CurrentCulture);
}
/// <summary>
/// Returns a String representing this Vector2 instance, using the specified format to format individual elements
/// and the given IFormatProvider.
/// </summary>
/// <param name="format">The format of individual elements.</param>
/// <param name="formatProvider">The format provider to use when formatting elements.</param>
/// <returns>The string representation.</returns>
public string ToString(string format, IFormatProvider formatProvider)
{
StringBuilder sb = new StringBuilder();
string separator = NumberFormatInfo.GetInstance(formatProvider).NumberGroupSeparator;
sb.Append('<');
sb.Append(this.X.ToString(format, formatProvider));
sb.Append(separator);
sb.Append(' ');
sb.Append(this.Y.ToString(format, formatProvider));
sb.Append('>');
return sb.ToString();
}
/// <summary>
/// Returns the length of the vector.
/// </summary>
/// <returns>The vector's length.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Length()
{
if (Vector.IsHardwareAccelerated)
{
float ls = Vector2.Dot(this, this);
return (float)Math.Sqrt(ls);
}
else
{
float ls = X * X + Y * Y;
return (float)Math.Sqrt((double)ls);
}
}
/// <summary>
/// Returns the length of the vector squared. This operation is cheaper than Length().
/// </summary>
/// <returns>The vector's length squared.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float LengthSquared()
{
if (Vector.IsHardwareAccelerated)
{
return Vector2.Dot(this, this);
}
else
{
return X * X + Y * Y;
}
}
#endregion Public Instance Methods
#region Public Static Methods
/// <summary>
/// Returns the Euclidean distance between the two given points.
/// </summary>
/// <param name="value1">The first point.</param>
/// <param name="value2">The second point.</param>
/// <returns>The distance.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Distance(Vector2 value1, Vector2 value2)
{
if (Vector.IsHardwareAccelerated)
{
Vector2 difference = value1 - value2;
float ls = Vector2.Dot(difference, difference);
return (float)System.Math.Sqrt(ls);
}
else
{
float dx = value1.X - value2.X;
float dy = value1.Y - value2.Y;
float ls = dx * dx + dy * dy;
return (float)Math.Sqrt((double)ls);
}
}
/// <summary>
/// Returns the Euclidean distance squared between the two given points.
/// </summary>
/// <param name="value1">The first point.</param>
/// <param name="value2">The second point.</param>
/// <returns>The distance squared.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float DistanceSquared(Vector2 value1, Vector2 value2)
{
if (Vector.IsHardwareAccelerated)
{
Vector2 difference = value1 - value2;
return Vector2.Dot(difference, difference);
}
else
{
float dx = value1.X - value2.X;
float dy = value1.Y - value2.Y;
return dx * dx + dy * dy;
}
}
/// <summary>
/// Returns a vector with the same direction as the given vector, but with a length of 1.
/// </summary>
/// <param name="value">The vector to normalize.</param>
/// <returns>The normalized vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Normalize(Vector2 value)
{
if (Vector.IsHardwareAccelerated)
{
float length = value.Length();
return value / length;
}
else
{
float ls = value.X * value.X + value.Y * value.Y;
float invNorm = 1.0f / (float)Math.Sqrt((double)ls);
return new Vector2(
value.X * invNorm,
value.Y * invNorm);
}
}
/// <summary>
/// Returns the reflection of a vector off a surface that has the specified normal.
/// </summary>
/// <param name="vector">The source vector.</param>
/// <param name="normal">The normal of the surface being reflected off.</param>
/// <returns>The reflected vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Reflect(Vector2 vector, Vector2 normal)
{
if (Vector.IsHardwareAccelerated)
{
float dot = Vector2.Dot(vector, normal);
return vector - (2 * dot * normal);
}
else
{
float dot = vector.X * normal.X + vector.Y * normal.Y;
return new Vector2(
vector.X - 2.0f * dot * normal.X,
vector.Y - 2.0f * dot * normal.Y);
}
}
/// <summary>
/// Restricts a vector between a min and max value.
/// </summary>
/// <param name="value1">The source vector.</param>
/// <param name="min">The minimum value.</param>
/// <param name="max">The maximum value.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Clamp(Vector2 value1, Vector2 min, Vector2 max)
{
// This compare order is very important!!!
// We must follow HLSL behavior in the case user specified min value is bigger than max value.
float x = value1.X;
x = (x > max.X) ? max.X : x;
x = (x < min.X) ? min.X : x;
float y = value1.Y;
y = (y > max.Y) ? max.Y : y;
y = (y < min.Y) ? min.Y : y;
return new Vector2(x, y);
}
/// <summary>
/// Linearly interpolates between two vectors based on the given weighting.
/// </summary>
/// <param name="value1">The first source vector.</param>
/// <param name="value2">The second source vector.</param>
/// <param name="amount">Value between 0 and 1 indicating the weight of the second source vector.</param>
/// <returns>The interpolated vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Lerp(Vector2 value1, Vector2 value2, float amount)
{
return new Vector2(
value1.X + (value2.X - value1.X) * amount,
value1.Y + (value2.Y - value1.Y) * amount);
}
/// <summary>
/// Transforms a vector by the given matrix.
/// </summary>
/// <param name="position">The source vector.</param>
/// <param name="matrix">The transformation matrix.</param>
/// <returns>The transformed vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Transform(Vector2 position, Matrix3x2 matrix)
{
return new Vector2(
position.X * matrix.M11 + position.Y * matrix.M21 + matrix.M31,
position.X * matrix.M12 + position.Y * matrix.M22 + matrix.M32);
}
/// <summary>
/// Transforms a vector by the given matrix.
/// </summary>
/// <param name="position">The source vector.</param>
/// <param name="matrix">The transformation matrix.</param>
/// <returns>The transformed vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Transform(Vector2 position, Matrix4x4 matrix)
{
return new Vector2(
position.X * matrix.M11 + position.Y * matrix.M21 + matrix.M41,
position.X * matrix.M12 + position.Y * matrix.M22 + matrix.M42);
}
/// <summary>
/// Transforms a vector normal by the given matrix.
/// </summary>
/// <param name="normal">The source vector.</param>
/// <param name="matrix">The transformation matrix.</param>
/// <returns>The transformed vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 TransformNormal(Vector2 normal, Matrix3x2 matrix)
{
return new Vector2(
normal.X * matrix.M11 + normal.Y * matrix.M21,
normal.X * matrix.M12 + normal.Y * matrix.M22);
}
/// <summary>
/// Transforms a vector normal by the given matrix.
/// </summary>
/// <param name="normal">The source vector.</param>
/// <param name="matrix">The transformation matrix.</param>
/// <returns>The transformed vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 TransformNormal(Vector2 normal, Matrix4x4 matrix)
{
return new Vector2(
normal.X * matrix.M11 + normal.Y * matrix.M21,
normal.X * matrix.M12 + normal.Y * matrix.M22);
}
/// <summary>
/// Transforms a vector by the given Quaternion rotation value.
/// </summary>
/// <param name="value">The source vector to be rotated.</param>
/// <param name="rotation">The rotation to apply.</param>
/// <returns>The transformed vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Transform(Vector2 value, Quaternion rotation)
{
float x2 = rotation.X + rotation.X;
float y2 = rotation.Y + rotation.Y;
float z2 = rotation.Z + rotation.Z;
float wz2 = rotation.W * z2;
float xx2 = rotation.X * x2;
float xy2 = rotation.X * y2;
float yy2 = rotation.Y * y2;
float zz2 = rotation.Z * z2;
return new Vector2(
value.X * (1.0f - yy2 - zz2) + value.Y * (xy2 - wz2),
value.X * (xy2 + wz2) + value.Y * (1.0f - xx2 - zz2));
}
#endregion Public Static Methods
#region Public operator methods
// all the below methods should be inlined as they are
// implemented over JIT intrinsics
/// <summary>
/// Adds two vectors together.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <returns>The summed vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Add(Vector2 left, Vector2 right)
{
return left + right;
}
/// <summary>
/// Subtracts the second vector from the first.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <returns>The difference vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Subtract(Vector2 left, Vector2 right)
{
return left - right;
}
/// <summary>
/// Multiplies two vectors together.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <returns>The product vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Multiply(Vector2 left, Vector2 right)
{
return left * right;
}
/// <summary>
/// Multiplies a vector by the given scalar.
/// </summary>
/// <param name="left">The source vector.</param>
/// <param name="right">The scalar value.</param>
/// <returns>The scaled vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Multiply(Vector2 left, Single right)
{
return left * right;
}
/// <summary>
/// Multiplies a vector by the given scalar.
/// </summary>
/// <param name="left">The scalar value.</param>
/// <param name="right">The source vector.</param>
/// <returns>The scaled vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Multiply(Single left, Vector2 right)
{
return left * right;
}
/// <summary>
/// Divides the first vector by the second.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <returns>The vector resulting from the division.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Divide(Vector2 left, Vector2 right)
{
return left / right;
}
/// <summary>
/// Divides the vector by the given scalar.
/// </summary>
/// <param name="left">The source vector.</param>
/// <param name="divisor">The scalar value.</param>
/// <returns>The result of the division.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Divide(Vector2 left, Single divisor)
{
return left / divisor;
}
/// <summary>
/// Negates a given vector.
/// </summary>
/// <param name="value">The source vector.</param>
/// <returns>The negated vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Negate(Vector2 value)
{
return -value;
}
#endregion Public operator methods
}
}

View File

@@ -0,0 +1,296 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Runtime.CompilerServices;
namespace System.Numerics
{
// This file contains the definitions for all of the JIT intrinsic methods and properties that are recognized by the current x64 JIT compiler.
// The implementation defined here is used in any circumstance where the JIT fails to recognize these members as intrinsic.
// The JIT recognizes these methods and properties by name and signature: if either is changed, the JIT will no longer recognize the member.
// Some methods declared here are not strictly intrinsic, but delegate to an intrinsic method. For example, only one overload of CopyTo()
public partial struct Vector2
{
/// <summary>
/// The X component of the vector.
/// </summary>
public Single X;
/// <summary>
/// The Y component of the vector.
/// </summary>
public Single Y;
#region Constructors
/// <summary>
/// Constructs a vector whose elements are all the single specified value.
/// </summary>
/// <param name="value">The element to fill the vector with.</param>
[JitIntrinsic]
public Vector2(Single value) : this(value, value) { }
/// <summary>
/// Constructs a vector with the given individual elements.
/// </summary>
/// <param name="x">The X component.</param>
/// <param name="y">The Y component.</param>
[JitIntrinsic]
public Vector2(Single x, Single y)
{
X = x;
Y = y;
}
#endregion Constructors
#region Public Instance Methods
/// <summary>
/// Copies the contents of the vector into the given array.
/// </summary>
/// <param name="array">The destination array.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void CopyTo(Single[] array)
{
CopyTo(array, 0);
}
/// <summary>
/// Copies the contents of the vector into the given array, starting from the given index.
/// </summary>
/// <exception cref="ArgumentNullException">If array is null.</exception>
/// <exception cref="RankException">If array is multidimensional.</exception>
/// <exception cref="ArgumentOutOfRangeException">If index is greater than end of the array or index is less than zero.</exception>
/// <exception cref="ArgumentException">If number of elements in source vector is greater than those available in destination array
/// or if there are not enough elements to copy.</exception>
public void CopyTo(Single[] array, int index)
{
if (array == null)
{
// Match the JIT's exception type here. For perf, a NullReference is thrown instead of an ArgumentNull.
throw new NullReferenceException(SR.GetString("Arg_NullArgumentNullRef"));
}
if (index < 0 || index >= array.Length)
{
throw new ArgumentOutOfRangeException(SR.GetString("Arg_ArgumentOutOfRangeException", index));
}
if ((array.Length - index) < 2)
{
throw new ArgumentException(SR.GetString("Arg_ElementsInSourceIsGreaterThanDestination", index));
}
array[index] = X;
array[index + 1] = Y;
}
/// <summary>
/// Returns a boolean indicating whether the given Vector2 is equal to this Vector2 instance.
/// </summary>
/// <param name="other">The Vector2 to compare this instance to.</param>
/// <returns>True if the other Vector2 is equal to this instance; False otherwise.</returns>
[JitIntrinsic]
public bool Equals(Vector2 other)
{
return this.X == other.X && this.Y == other.Y;
}
#endregion Public Instance Methods
#region Public Static Methods
/// <summary>
/// Returns the dot product of two vectors.
/// </summary>
/// <param name="value1">The first vector.</param>
/// <param name="value2">The second vector.</param>
/// <returns>The dot product.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Dot(Vector2 value1, Vector2 value2)
{
return value1.X * value2.X +
value1.Y * value2.Y;
}
/// <summary>
/// Returns a vector whose elements are the minimum of each of the pairs of elements in the two source vectors.
/// </summary>
/// <param name="value1">The first source vector.</param>
/// <param name="value2">The second source vector.</param>
/// <returns>The minimized vector.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Min(Vector2 value1, Vector2 value2)
{
return new Vector2(
(value1.X < value2.X) ? value1.X : value2.X,
(value1.Y < value2.Y) ? value1.Y : value2.Y);
}
/// <summary>
/// Returns a vector whose elements are the maximum of each of the pairs of elements in the two source vectors
/// </summary>
/// <param name="value1">The first source vector</param>
/// <param name="value2">The second source vector</param>
/// <returns>The maximized vector</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Max(Vector2 value1, Vector2 value2)
{
return new Vector2(
(value1.X > value2.X) ? value1.X : value2.X,
(value1.Y > value2.Y) ? value1.Y : value2.Y);
}
/// <summary>
/// Returns a vector whose elements are the absolute values of each of the source vector's elements.
/// </summary>
/// <param name="value">The source vector.</param>
/// <returns>The absolute value vector.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 Abs(Vector2 value)
{
return new Vector2(Math.Abs(value.X), Math.Abs(value.Y));
}
/// <summary>
/// Returns a vector whose elements are the square root of each of the source vector's elements.
/// </summary>
/// <param name="value">The source vector.</param>
/// <returns>The square root vector.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 SquareRoot(Vector2 value)
{
return new Vector2((Single)Math.Sqrt(value.X), (Single)Math.Sqrt(value.Y));
}
#endregion Public Static Methods
#region Public Static Operators
/// <summary>
/// Adds two vectors together.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <returns>The summed vector.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 operator +(Vector2 left, Vector2 right)
{
return new Vector2(left.X + right.X, left.Y + right.Y);
}
/// <summary>
/// Subtracts the second vector from the first.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <returns>The difference vector.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 operator -(Vector2 left, Vector2 right)
{
return new Vector2(left.X - right.X, left.Y - right.Y);
}
/// <summary>
/// Multiplies two vectors together.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <returns>The product vector.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 operator *(Vector2 left, Vector2 right)
{
return new Vector2(left.X * right.X, left.Y * right.Y);
}
/// <summary>
/// Multiplies a vector by the given scalar.
/// </summary>
/// <param name="left">The scalar value.</param>
/// <param name="right">The source vector.</param>
/// <returns>The scaled vector.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 operator *(Single left, Vector2 right)
{
return new Vector2(left, left) * right;
}
/// <summary>
/// Multiplies a vector by the given scalar.
/// </summary>
/// <param name="left">The source vector.</param>
/// <param name="right">The scalar value.</param>
/// <returns>The scaled vector.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 operator *(Vector2 left, Single right)
{
return left * new Vector2(right, right);
}
/// <summary>
/// Divides the first vector by the second.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <returns>The vector resulting from the division.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 operator /(Vector2 left, Vector2 right)
{
return new Vector2(left.X / right.X, left.Y / right.Y);
}
/// <summary>
/// Divides the vector by the given scalar.
/// </summary>
/// <param name="value1">The source vector.</param>
/// <param name="value2">The scalar value.</param>
/// <returns>The result of the division.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 operator /(Vector2 value1, float value2)
{
float invDiv = 1.0f / value2;
return new Vector2(
value1.X * invDiv,
value1.Y * invDiv);
}
/// <summary>
/// Negates a given vector.
/// </summary>
/// <param name="value">The source vector.</param>
/// <returns>The negated vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2 operator -(Vector2 value)
{
return Zero - value;
}
/// <summary>
/// Returns a boolean indicating whether the two given vectors are equal.
/// </summary>
/// <param name="left">The first vector to compare.</param>
/// <param name="right">The second vector to compare.</param>
/// <returns>True if the vectors are equal; False otherwise.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Vector2 left, Vector2 right)
{
return left.Equals(right);
}
/// <summary>
/// Returns a boolean indicating whether the two given vectors are not equal.
/// </summary>
/// <param name="left">The first vector to compare.</param>
/// <param name="right">The second vector to compare.</param>
/// <returns>True if the vectors are not equal; False if they are equal.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Vector2 left, Vector2 right)
{
return !(left == right);
}
#endregion Public Static Operators
}
}

View File

@@ -0,0 +1,471 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Text;
namespace System.Numerics
{
/// <summary>
/// A structure encapsulating three single precision floating point values and provides hardware accelerated methods.
/// </summary>
public partial struct Vector3 : IEquatable<Vector3>, IFormattable
{
#region Public Static Properties
/// <summary>
/// Returns the vector (0,0,0).
/// </summary>
public static Vector3 Zero { get { return new Vector3(); } }
/// <summary>
/// Returns the vector (1,1,1).
/// </summary>
public static Vector3 One { get { return new Vector3(1.0f, 1.0f, 1.0f); } }
/// <summary>
/// Returns the vector (1,0,0).
/// </summary>
public static Vector3 UnitX { get { return new Vector3(1.0f, 0.0f, 0.0f); } }
/// <summary>
/// Returns the vector (0,1,0).
/// </summary>
public static Vector3 UnitY { get { return new Vector3(0.0f, 1.0f, 0.0f); } }
/// <summary>
/// Returns the vector (0,0,1).
/// </summary>
public static Vector3 UnitZ { get { return new Vector3(0.0f, 0.0f, 1.0f); } }
#endregion Public Static Properties
#region Public Instance Methods
/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>The hash code.</returns>
public override int GetHashCode()
{
int hash = this.X.GetHashCode();
hash = HashCodeHelper.CombineHashCodes(hash, this.Y.GetHashCode());
hash = HashCodeHelper.CombineHashCodes(hash, this.Z.GetHashCode());
return hash;
}
/// <summary>
/// Returns a boolean indicating whether the given Object is equal to this Vector3 instance.
/// </summary>
/// <param name="obj">The Object to compare against.</param>
/// <returns>True if the Object is equal to this Vector3; False otherwise.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
if (!(obj is Vector3))
return false;
return Equals((Vector3)obj);
}
/// <summary>
/// Returns a String representing this Vector3 instance.
/// </summary>
/// <returns>The string representation.</returns>
public override string ToString()
{
return ToString("G", CultureInfo.CurrentCulture);
}
/// <summary>
/// Returns a String representing this Vector3 instance, using the specified format to format individual elements.
/// </summary>
/// <param name="format">The format of individual elements.</param>
/// <returns>The string representation.</returns>
public string ToString(string format)
{
return ToString(format, CultureInfo.CurrentCulture);
}
/// <summary>
/// Returns a String representing this Vector3 instance, using the specified format to format individual elements
/// and the given IFormatProvider.
/// </summary>
/// <param name="format">The format of individual elements.</param>
/// <param name="formatProvider">The format provider to use when formatting elements.</param>
/// <returns>The string representation.</returns>
public string ToString(string format, IFormatProvider formatProvider)
{
StringBuilder sb = new StringBuilder();
string separator = NumberFormatInfo.GetInstance(formatProvider).NumberGroupSeparator;
sb.Append('<');
sb.Append(((IFormattable)this.X).ToString(format, formatProvider));
sb.Append(separator);
sb.Append(' ');
sb.Append(((IFormattable)this.Y).ToString(format, formatProvider));
sb.Append(separator);
sb.Append(' ');
sb.Append(((IFormattable)this.Z).ToString(format, formatProvider));
sb.Append('>');
return sb.ToString();
}
/// <summary>
/// Returns the length of the vector.
/// </summary>
/// <returns>The vector's length.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Length()
{
if (Vector.IsHardwareAccelerated)
{
float ls = Vector3.Dot(this, this);
return (float)System.Math.Sqrt(ls);
}
else
{
float ls = X * X + Y * Y + Z * Z;
return (float)System.Math.Sqrt(ls);
}
}
/// <summary>
/// Returns the length of the vector squared. This operation is cheaper than Length().
/// </summary>
/// <returns>The vector's length squared.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float LengthSquared()
{
if (Vector.IsHardwareAccelerated)
{
return Vector3.Dot(this, this);
}
else
{
return X * X + Y * Y + Z * Z;
}
}
#endregion Public Instance Methods
#region Public Static Methods
/// <summary>
/// Returns the Euclidean distance between the two given points.
/// </summary>
/// <param name="value1">The first point.</param>
/// <param name="value2">The second point.</param>
/// <returns>The distance.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Distance(Vector3 value1, Vector3 value2)
{
if (Vector.IsHardwareAccelerated)
{
Vector3 difference = value1 - value2;
float ls = Vector3.Dot(difference, difference);
return (float)System.Math.Sqrt(ls);
}
else
{
float dx = value1.X - value2.X;
float dy = value1.Y - value2.Y;
float dz = value1.Z - value2.Z;
float ls = dx * dx + dy * dy + dz * dz;
return (float)System.Math.Sqrt((double)ls);
}
}
/// <summary>
/// Returns the Euclidean distance squared between the two given points.
/// </summary>
/// <param name="value1">The first point.</param>
/// <param name="value2">The second point.</param>
/// <returns>The distance squared.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float DistanceSquared(Vector3 value1, Vector3 value2)
{
if (Vector.IsHardwareAccelerated)
{
Vector3 difference = value1 - value2;
return Vector3.Dot(difference, difference);
}
else
{
float dx = value1.X - value2.X;
float dy = value1.Y - value2.Y;
float dz = value1.Z - value2.Z;
return dx * dx + dy * dy + dz * dz;
}
}
/// <summary>
/// Returns a vector with the same direction as the given vector, but with a length of 1.
/// </summary>
/// <param name="value">The vector to normalize.</param>
/// <returns>The normalized vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 Normalize(Vector3 value)
{
if (Vector.IsHardwareAccelerated)
{
float length = value.Length();
return value / length;
}
else
{
float ls = value.X * value.X + value.Y * value.Y + value.Z * value.Z;
float length = (float)System.Math.Sqrt(ls);
return new Vector3(value.X / length, value.Y / length, value.Z / length);
}
}
/// <summary>
/// Computes the cross product of two vectors.
/// </summary>
/// <param name="vector1">The first vector.</param>
/// <param name="vector2">The second vector.</param>
/// <returns>The cross product.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 Cross(Vector3 vector1, Vector3 vector2)
{
return new Vector3(
vector1.Y * vector2.Z - vector1.Z * vector2.Y,
vector1.Z * vector2.X - vector1.X * vector2.Z,
vector1.X * vector2.Y - vector1.Y * vector2.X);
}
/// <summary>
/// Returns the reflection of a vector off a surface that has the specified normal.
/// </summary>
/// <param name="vector">The source vector.</param>
/// <param name="normal">The normal of the surface being reflected off.</param>
/// <returns>The reflected vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 Reflect(Vector3 vector, Vector3 normal)
{
if (Vector.IsHardwareAccelerated)
{
float dot = Vector3.Dot(vector, normal);
Vector3 temp = normal * dot * 2f;
return vector - temp;
}
else
{
float dot = vector.X * normal.X + vector.Y * normal.Y + vector.Z * normal.Z;
float tempX = normal.X * dot * 2f;
float tempY = normal.Y * dot * 2f;
float tempZ = normal.Z * dot * 2f;
return new Vector3(vector.X - tempX, vector.Y - tempY, vector.Z - tempZ);
}
}
/// <summary>
/// Restricts a vector between a min and max value.
/// </summary>
/// <param name="value1">The source vector.</param>
/// <param name="min">The minimum value.</param>
/// <param name="max">The maximum value.</param>
/// <returns>The restricted vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 Clamp(Vector3 value1, Vector3 min, Vector3 max)
{
// This compare order is very important!!!
// We must follow HLSL behavior in the case user specified min value is bigger than max value.
float x = value1.X;
x = (x > max.X) ? max.X : x;
x = (x < min.X) ? min.X : x;
float y = value1.Y;
y = (y > max.Y) ? max.Y : y;
y = (y < min.Y) ? min.Y : y;
float z = value1.Z;
z = (z > max.Z) ? max.Z : z;
z = (z < min.Z) ? min.Z : z;
return new Vector3(x, y, z);
}
/// <summary>
/// Linearly interpolates between two vectors based on the given weighting.
/// </summary>
/// <param name="value1">The first source vector.</param>
/// <param name="value2">The second source vector.</param>
/// <param name="amount">Value between 0 and 1 indicating the weight of the second source vector.</param>
/// <returns>The interpolated vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 Lerp(Vector3 value1, Vector3 value2, float amount)
{
if (Vector.IsHardwareAccelerated)
{
Vector3 firstInfluence = value1 * (1f - amount);
Vector3 secondInfluence = value2 * amount;
return firstInfluence + secondInfluence;
}
else
{
return new Vector3(
value1.X + (value2.X - value1.X) * amount,
value1.Y + (value2.Y - value1.Y) * amount,
value1.Z + (value2.Z - value1.Z) * amount);
}
}
/// <summary>
/// Transforms a vector by the given matrix.
/// </summary>
/// <param name="position">The source vector.</param>
/// <param name="matrix">The transformation matrix.</param>
/// <returns>The transformed vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 Transform(Vector3 position, Matrix4x4 matrix)
{
return new Vector3(
position.X * matrix.M11 + position.Y * matrix.M21 + position.Z * matrix.M31 + matrix.M41,
position.X * matrix.M12 + position.Y * matrix.M22 + position.Z * matrix.M32 + matrix.M42,
position.X * matrix.M13 + position.Y * matrix.M23 + position.Z * matrix.M33 + matrix.M43);
}
/// <summary>
/// Transforms a vector normal by the given matrix.
/// </summary>
/// <param name="normal">The source vector.</param>
/// <param name="matrix">The transformation matrix.</param>
/// <returns>The transformed vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 TransformNormal(Vector3 normal, Matrix4x4 matrix)
{
return new Vector3(
normal.X * matrix.M11 + normal.Y * matrix.M21 + normal.Z * matrix.M31,
normal.X * matrix.M12 + normal.Y * matrix.M22 + normal.Z * matrix.M32,
normal.X * matrix.M13 + normal.Y * matrix.M23 + normal.Z * matrix.M33);
}
/// <summary>
/// Transforms a vector by the given Quaternion rotation value.
/// </summary>
/// <param name="value">The source vector to be rotated.</param>
/// <param name="rotation">The rotation to apply.</param>
/// <returns>The transformed vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 Transform(Vector3 value, Quaternion rotation)
{
float x2 = rotation.X + rotation.X;
float y2 = rotation.Y + rotation.Y;
float z2 = rotation.Z + rotation.Z;
float wx2 = rotation.W * x2;
float wy2 = rotation.W * y2;
float wz2 = rotation.W * z2;
float xx2 = rotation.X * x2;
float xy2 = rotation.X * y2;
float xz2 = rotation.X * z2;
float yy2 = rotation.Y * y2;
float yz2 = rotation.Y * z2;
float zz2 = rotation.Z * z2;
return new Vector3(
value.X * (1.0f - yy2 - zz2) + value.Y * (xy2 - wz2) + value.Z * (xz2 + wy2),
value.X * (xy2 + wz2) + value.Y * (1.0f - xx2 - zz2) + value.Z * (yz2 - wx2),
value.X * (xz2 - wy2) + value.Y * (yz2 + wx2) + value.Z * (1.0f - xx2 - yy2));
}
#endregion Public Static Methods
#region Public operator methods
// All these methods should be inlined as they are implemented
// over JIT intrinsics
/// <summary>
/// Adds two vectors together.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <returns>The summed vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 Add(Vector3 left, Vector3 right)
{
return left + right;
}
/// <summary>
/// Subtracts the second vector from the first.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <returns>The difference vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 Subtract(Vector3 left, Vector3 right)
{
return left - right;
}
/// <summary>
/// Multiplies two vectors together.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <returns>The product vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 Multiply(Vector3 left, Vector3 right)
{
return left * right;
}
/// <summary>
/// Multiplies a vector by the given scalar.
/// </summary>
/// <param name="left">The source vector.</param>
/// <param name="right">The scalar value.</param>
/// <returns>The scaled vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 Multiply(Vector3 left, Single right)
{
return left * right;
}
/// <summary>
/// Multiplies a vector by the given scalar.
/// </summary>
/// <param name="left">The scalar value.</param>
/// <param name="right">The source vector.</param>
/// <returns>The scaled vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 Multiply(Single left, Vector3 right)
{
return left * right;
}
/// <summary>
/// Divides the first vector by the second.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <returns>The vector resulting from the division.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 Divide(Vector3 left, Vector3 right)
{
return left / right;
}
/// <summary>
/// Divides the vector by the given scalar.
/// </summary>
/// <param name="left">The source vector.</param>
/// <param name="divisor">The scalar value.</param>
/// <returns>The result of the division.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 Divide(Vector3 left, Single divisor)
{
return left / divisor;
}
/// <summary>
/// Negates a given vector.
/// </summary>
/// <param name="value">The source vector.</param>
/// <returns>The negated vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 Negate(Vector3 value)
{
return -value;
}
#endregion Public operator methods
}
}

View File

@@ -0,0 +1,322 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Runtime.CompilerServices;
namespace System.Numerics
{
// This file contains the definitions for all of the JIT intrinsic methods and properties that are recognized by the current x64 JIT compiler.
// The implementation defined here is used in any circumstance where the JIT fails to recognize these members as intrinsic.
// The JIT recognizes these methods and properties by name and signature: if either is changed, the JIT will no longer recognize the member.
// Some methods declared here are not strictly intrinsic, but delegate to an intrinsic method. For example, only one overload of CopyTo()
// is actually recognized by the JIT, but both are here for simplicity.
public partial struct Vector3
{
/// <summary>
/// The X component of the vector.
/// </summary>
public Single X;
/// <summary>
/// The Y component of the vector.
/// </summary>
public Single Y;
/// <summary>
/// The Z component of the vector.
/// </summary>
public Single Z;
#region Constructors
/// <summary>
/// Constructs a vector whose elements are all the single specified value.
/// </summary>
/// <param name="value">The element to fill the vector with.</param>
[JitIntrinsic]
public Vector3(Single value) : this(value, value, value) { }
/// <summary>
/// Constructs a Vector3 from the given Vector2 and a third value.
/// </summary>
/// <param name="value">The Vector to extract X and Y components from.</param>
/// <param name="z">The Z component.</param>
public Vector3(Vector2 value, float z) : this(value.X, value.Y, z) { }
/// <summary>
/// Constructs a vector with the given individual elements.
/// </summary>
/// <param name="x">The X component.</param>
/// <param name="y">The Y component.</param>
/// <param name="z">The Z component.</param>
[JitIntrinsic]
public Vector3(Single x, Single y, Single z)
{
X = x;
Y = y;
Z = z;
}
#endregion Constructors
#region Public Instance Methods
/// <summary>
/// Copies the contents of the vector into the given array.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void CopyTo(Single[] array)
{
CopyTo(array, 0);
}
/// <summary>
/// Copies the contents of the vector into the given array, starting from index.
/// </summary>
/// <exception cref="ArgumentNullException">If array is null.</exception>
/// <exception cref="RankException">If array is multidimensional.</exception>
/// <exception cref="ArgumentOutOfRangeException">If index is greater than end of the array or index is less than zero.</exception>
/// <exception cref="ArgumentException">If number of elements in source vector is greater than those available in destination array.</exception>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void CopyTo(Single[] array, int index)
{
if (array == null)
{
// Match the JIT's exception type here. For perf, a NullReference is thrown instead of an ArgumentNull.
throw new NullReferenceException(SR.GetString("Arg_NullArgumentNullRef"));
}
if (index < 0 || index >= array.Length)
{
throw new ArgumentOutOfRangeException(SR.GetString("Arg_ArgumentOutOfRangeException", index));
}
if ((array.Length - index) < 3)
{
throw new ArgumentException(SR.GetString("Arg_ElementsInSourceIsGreaterThanDestination", index));
}
array[index] = X;
array[index + 1] = Y;
array[index + 2] = Z;
}
/// <summary>
/// Returns a boolean indicating whether the given Vector3 is equal to this Vector3 instance.
/// </summary>
/// <param name="other">The Vector3 to compare this instance to.</param>
/// <returns>True if the other Vector3 is equal to this instance; False otherwise.</returns>
[JitIntrinsic]
public bool Equals(Vector3 other)
{
return X == other.X &&
Y == other.Y &&
Z == other.Z;
}
#endregion Public Instance Methods
#region Public Static Methods
/// <summary>
/// Returns the dot product of two vectors.
/// </summary>
/// <param name="vector1">The first vector.</param>
/// <param name="vector2">The second vector.</param>
/// <returns>The dot product.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Dot(Vector3 vector1, Vector3 vector2)
{
return vector1.X * vector2.X +
vector1.Y * vector2.Y +
vector1.Z * vector2.Z;
}
/// <summary>
/// Returns a vector whose elements are the minimum of each of the pairs of elements in the two source vectors.
/// </summary>
/// <param name="value1">The first source vector.</param>
/// <param name="value2">The second source vector.</param>
/// <returns>The minimized vector.</returns>
[JitIntrinsic]
public static Vector3 Min(Vector3 value1, Vector3 value2)
{
return new Vector3(
(value1.X < value2.X) ? value1.X : value2.X,
(value1.Y < value2.Y) ? value1.Y : value2.Y,
(value1.Z < value2.Z) ? value1.Z : value2.Z);
}
/// <summary>
/// Returns a vector whose elements are the maximum of each of the pairs of elements in the two source vectors.
/// </summary>
/// <param name="value1">The first source vector.</param>
/// <param name="value2">The second source vector.</param>
/// <returns>The maximized vector.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 Max(Vector3 value1, Vector3 value2)
{
return new Vector3(
(value1.X > value2.X) ? value1.X : value2.X,
(value1.Y > value2.Y) ? value1.Y : value2.Y,
(value1.Z > value2.Z) ? value1.Z : value2.Z);
}
/// <summary>
/// Returns a vector whose elements are the absolute values of each of the source vector's elements.
/// </summary>
/// <param name="value">The source vector.</param>
/// <returns>The absolute value vector.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 Abs(Vector3 value)
{
return new Vector3(Math.Abs(value.X), Math.Abs(value.Y), Math.Abs(value.Z));
}
/// <summary>
/// Returns a vector whose elements are the square root of each of the source vector's elements.
/// </summary>
/// <param name="value">The source vector.</param>
/// <returns>The square root vector.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 SquareRoot(Vector3 value)
{
return new Vector3((Single)Math.Sqrt(value.X), (Single)Math.Sqrt(value.Y), (Single)Math.Sqrt(value.Z));
}
#endregion Public Static Methods
#region Public Static Operators
/// <summary>
/// Adds two vectors together.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <returns>The summed vector.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 operator +(Vector3 left, Vector3 right)
{
return new Vector3(left.X + right.X, left.Y + right.Y, left.Z + right.Z);
}
/// <summary>
/// Subtracts the second vector from the first.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <returns>The difference vector.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 operator -(Vector3 left, Vector3 right)
{
return new Vector3(left.X - right.X, left.Y - right.Y, left.Z - right.Z);
}
/// <summary>
/// Multiplies two vectors together.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <returns>The product vector.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 operator *(Vector3 left, Vector3 right)
{
return new Vector3(left.X * right.X, left.Y * right.Y, left.Z * right.Z);
}
/// <summary>
/// Multiplies a vector by the given scalar.
/// </summary>
/// <param name="left">The source vector.</param>
/// <param name="right">The scalar value.</param>
/// <returns>The scaled vector.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 operator *(Vector3 left, Single right)
{
return left * new Vector3(right);
}
/// <summary>
/// Multiplies a vector by the given scalar.
/// </summary>
/// <param name="left">The scalar value.</param>
/// <param name="right">The source vector.</param>
/// <returns>The scaled vector.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 operator *(Single left, Vector3 right)
{
return new Vector3(left) * right;
}
/// <summary>
/// Divides the first vector by the second.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <returns>The vector resulting from the division.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 operator /(Vector3 left, Vector3 right)
{
return new Vector3(left.X / right.X, left.Y / right.Y, left.Z / right.Z);
}
/// <summary>
/// Divides the vector by the given scalar.
/// </summary>
/// <param name="value1">The source vector.</param>
/// <param name="value2">The scalar value.</param>
/// <returns>The result of the division.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 operator /(Vector3 value1, float value2)
{
float invDiv = 1.0f / value2;
return new Vector3(
value1.X * invDiv,
value1.Y * invDiv,
value1.Z * invDiv);
}
/// <summary>
/// Negates a given vector.
/// </summary>
/// <param name="value">The source vector.</param>
/// <returns>The negated vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3 operator -(Vector3 value)
{
return Zero - value;
}
/// <summary>
/// Returns a boolean indicating whether the two given vectors are equal.
/// </summary>
/// <param name="left">The first vector to compare.</param>
/// <param name="right">The second vector to compare.</param>
/// <returns>True if the vectors are equal; False otherwise.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Vector3 left, Vector3 right)
{
return (left.X == right.X &&
left.Y == right.Y &&
left.Z == right.Z);
}
/// <summary>
/// Returns a boolean indicating whether the two given vectors are not equal.
/// </summary>
/// <param name="left">The first vector to compare.</param>
/// <param name="right">The second vector to compare.</param>
/// <returns>True if the vectors are not equal; False if they are equal.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Vector3 left, Vector3 right)
{
return (left.X != right.X ||
left.Y != right.Y ||
left.Z != right.Z);
}
#endregion Public Static Operators
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,353 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Runtime.CompilerServices;
namespace System.Numerics
{
// This file contains the definitions for all of the JIT intrinsic methods and properties that are recognized by the current x64 JIT compiler.
// The implementation defined here is used in any circumstance where the JIT fails to recognize these members as intrinsic.
// The JIT recognizes these methods and properties by name and signature: if either is changed, the JIT will no longer recognize the member.
// Some methods declared here are not strictly intrinsic, but delegate to an intrinsic method. For example, only one overload of CopyTo()
public partial struct Vector4
{
/// <summary>
/// The X component of the vector.
/// </summary>
public Single X;
/// <summary>
/// The Y component of the vector.
/// </summary>
public Single Y;
/// <summary>
/// The Z component of the vector.
/// </summary>
public Single Z;
/// <summary>
/// The W component of the vector.
/// </summary>
public Single W;
#region Constructors
/// <summary>
/// Constructs a vector whose elements are all the single specified value.
/// </summary>
/// <param name="value">The element to fill the vector with.</param>
[JitIntrinsic]
public Vector4(Single value)
: this(value, value, value, value)
{
}
/// <summary>
/// Constructs a vector with the given individual elements.
/// </summary>
/// <param name="w">W component.</param>
/// <param name="x">X component.</param>
/// <param name="y">Y component.</param>
/// <param name="z">Z component.</param>
[JitIntrinsic]
public Vector4(Single x, Single y, Single z, Single w)
{
W = w;
X = x;
Y = y;
Z = z;
}
/// <summary>
/// Constructs a Vector4 from the given Vector2 and a Z and W component.
/// </summary>
/// <param name="value">The vector to use as the X and Y components.</param>
/// <param name="z">The Z component.</param>
/// <param name="w">The W component.</param>
public Vector4(Vector2 value, Single z, Single w)
{
X = value.X;
Y = value.Y;
Z = z;
W = w;
}
/// <summary>
/// Constructs a Vector4 from the given Vector3 and a W component.
/// </summary>
/// <param name="value">The vector to use as the X, Y, and Z components.</param>
/// <param name="w">The W component.</param>
public Vector4(Vector3 value, Single w)
{
X = value.X;
Y = value.Y;
Z = value.Z;
W = w;
}
#endregion Constructors
#region Public Instance Methods
/// <summary>
/// Copies the contents of the vector into the given array.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void CopyTo(Single[] array)
{
CopyTo(array, 0);
}
/// <summary>
/// Copies the contents of the vector into the given array, starting from index.
/// </summary>
/// <exception cref="ArgumentNullException">If array is null.</exception>
/// <exception cref="RankException">If array is multidimensional.</exception>
/// <exception cref="ArgumentOutOfRangeException">If index is greater than end of the array or index is less than zero.</exception>
/// <exception cref="ArgumentException">If number of elements in source vector is greater than those available in destination array.</exception>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void CopyTo(Single[] array, int index)
{
if (array == null)
{
// Match the JIT's exception type here. For perf, a NullReference is thrown instead of an ArgumentNull.
throw new NullReferenceException(SR.GetString("Arg_NullArgumentNullRef"));
}
if (index < 0 || index >= array.Length)
{
throw new ArgumentOutOfRangeException(SR.GetString("Arg_ArgumentOutOfRangeException", index));
}
if ((array.Length - index) < 4)
{
throw new ArgumentException(SR.GetString("Arg_ElementsInSourceIsGreaterThanDestination", index));
}
array[index] = X;
array[index + 1] = Y;
array[index + 2] = Z;
array[index + 3] = W;
}
/// <summary>
/// Returns a boolean indicating whether the given Vector4 is equal to this Vector4 instance.
/// </summary>
/// <param name="other">The Vector4 to compare this instance to.</param>
/// <returns>True if the other Vector4 is equal to this instance; False otherwise.</returns>
[JitIntrinsic]
public bool Equals(Vector4 other)
{
return this.X == other.X
&& this.Y == other.Y
&& this.Z == other.Z
&& this.W == other.W;
}
#endregion Public Instance Methods
#region Public Static Methods
/// <summary>
/// Returns the dot product of two vectors.
/// </summary>
/// <param name="vector1">The first vector.</param>
/// <param name="vector2">The second vector.</param>
/// <returns>The dot product.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Dot(Vector4 vector1, Vector4 vector2)
{
return vector1.X * vector2.X +
vector1.Y * vector2.Y +
vector1.Z * vector2.Z +
vector1.W * vector2.W;
}
/// <summary>
/// Returns a vector whose elements are the minimum of each of the pairs of elements in the two source vectors.
/// </summary>
/// <param name="value1">The first source vector.</param>
/// <param name="value2">The second source vector.</param>
/// <returns>The minimized vector.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 Min(Vector4 value1, Vector4 value2)
{
return new Vector4(
(value1.X < value2.X) ? value1.X : value2.X,
(value1.Y < value2.Y) ? value1.Y : value2.Y,
(value1.Z < value2.Z) ? value1.Z : value2.Z,
(value1.W < value2.W) ? value1.W : value2.W);
}
/// <summary>
/// Returns a vector whose elements are the maximum of each of the pairs of elements in the two source vectors.
/// </summary>
/// <param name="value1">The first source vector.</param>
/// <param name="value2">The second source vector.</param>
/// <returns>The maximized vector.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 Max(Vector4 value1, Vector4 value2)
{
return new Vector4(
(value1.X > value2.X) ? value1.X : value2.X,
(value1.Y > value2.Y) ? value1.Y : value2.Y,
(value1.Z > value2.Z) ? value1.Z : value2.Z,
(value1.W > value2.W) ? value1.W : value2.W);
}
/// <summary>
/// Returns a vector whose elements are the absolute values of each of the source vector's elements.
/// </summary>
/// <param name="value">The source vector.</param>
/// <returns>The absolute value vector.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 Abs(Vector4 value)
{
return new Vector4(Math.Abs(value.X), Math.Abs(value.Y), Math.Abs(value.Z), Math.Abs(value.W));
}
/// <summary>
/// Returns a vector whose elements are the square root of each of the source vector's elements.
/// </summary>
/// <param name="value">The source vector.</param>
/// <returns>The square root vector.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 SquareRoot(Vector4 value)
{
return new Vector4((Single)Math.Sqrt(value.X), (Single)Math.Sqrt(value.Y), (Single)Math.Sqrt(value.Z), (Single)Math.Sqrt(value.W));
}
#endregion Public Static Methods
#region Public static operators
/// <summary>
/// Adds two vectors together.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <returns>The summed vector.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 operator +(Vector4 left, Vector4 right)
{
return new Vector4(left.X + right.X, left.Y + right.Y, left.Z + right.Z, left.W + right.W);
}
/// <summary>
/// Subtracts the second vector from the first.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <returns>The difference vector.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 operator -(Vector4 left, Vector4 right)
{
return new Vector4(left.X - right.X, left.Y - right.Y, left.Z - right.Z, left.W - right.W);
}
/// <summary>
/// Multiplies two vectors together.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <returns>The product vector.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 operator *(Vector4 left, Vector4 right)
{
return new Vector4(left.X * right.X, left.Y * right.Y, left.Z * right.Z, left.W * right.W);
}
/// <summary>
/// Multiplies a vector by the given scalar.
/// </summary>
/// <param name="left">The source vector.</param>
/// <param name="right">The scalar value.</param>
/// <returns>The scaled vector.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 operator *(Vector4 left, Single right)
{
return left * new Vector4(right);
}
/// <summary>
/// Multiplies a vector by the given scalar.
/// </summary>
/// <param name="left">The scalar value.</param>
/// <param name="right">The source vector.</param>
/// <returns>The scaled vector.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 operator *(Single left, Vector4 right)
{
return new Vector4(left) * right;
}
/// <summary>
/// Divides the first vector by the second.
/// </summary>
/// <param name="left">The first source vector.</param>
/// <param name="right">The second source vector.</param>
/// <returns>The vector resulting from the division.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 operator /(Vector4 left, Vector4 right)
{
return new Vector4(left.X / right.X, left.Y / right.Y, left.Z / right.Z, left.W / right.W);
}
/// <summary>
/// Divides the vector by the given scalar.
/// </summary>
/// <param name="value1">The source vector.</param>
/// <param name="value2">The scalar value.</param>
/// <returns>The result of the division.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 operator /(Vector4 value1, float value2)
{
float invDiv = 1.0f / value2;
return new Vector4(
value1.X * invDiv,
value1.Y * invDiv,
value1.Z * invDiv,
value1.W * invDiv);
}
/// <summary>
/// Negates a given vector.
/// </summary>
/// <param name="value">The source vector.</param>
/// <returns>The negated vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 operator -(Vector4 value)
{
return Zero - value;
}
/// <summary>
/// Returns a boolean indicating whether the two given vectors are equal.
/// </summary>
/// <param name="left">The first vector to compare.</param>
/// <param name="right">The second vector to compare.</param>
/// <returns>True if the vectors are equal; False otherwise.</returns>
[JitIntrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Vector4 left, Vector4 right)
{
return left.Equals(right);
}
/// <summary>
/// Returns a boolean indicating whether the two given vectors are not equal.
/// </summary>
/// <param name="left">The first vector to compare.</param>
/// <param name="right">The second vector to compare.</param>
/// <returns>True if the vectors are not equal; False if they are equal.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Vector4 left, Vector4 right)
{
return !(left == right);
}
#endregion Public static operators
}
}

View File

@@ -0,0 +1,29 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Runtime.CompilerServices;
namespace System.Numerics
{
/// <summary>
/// Contains various methods useful for creating, manipulating, combining, and converting generic vectors with one another.
/// </summary>
internal static class Vector
{
// Every operation must either be a JIT intrinsic or implemented over a JIT intrinsic
// as a thin wrapper
// Operations implemented over a JIT intrinsic should be inlined
// Methods that do not have a <T> type parameter are recognized as intrinsics
/// <summary>
/// Returns whether or not vector operations are subject to hardware acceleration through JIT intrinsic support.
/// </summary>
[JitIntrinsic]
public static bool IsHardwareAccelerated
{
get
{
return false;
}
}
}
}