diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 13c606899e..29cd35a33d 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -87,7 +87,7 @@ jobs: - name: Restore run: dotnet restore --runtime ${{ matrix.rid }} - name: Test - run: dotnet test -c Release --no-restore --runtime ${{ matrix.rid }} --collect:"XPlat Code Coverage" --results-directory ./coverage --logger:"trx" + run: dotnet test --results-directory coverage --coverage --coverage-output-format cobertura --report-trx -c Release # TODO: https://github.com/dorny/test-reporter?tab=readme-ov-file#recommended-setup-for-public-repositories #- name: Test Report # uses: dorny/test-reporter@v1 diff --git a/Directory.Packages.props b/Directory.Packages.props index de0b8f8952..0c0cf4d13b 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -6,11 +6,11 @@ - + - + @@ -40,8 +40,11 @@ - + + + + - \ No newline at end of file + diff --git a/eng/build/Build.Publishing.cs b/eng/build/Build.Publishing.cs index ff6cd6fad4..e90d55f256 100644 --- a/eng/build/Build.Publishing.cs +++ b/eng/build/Build.Publishing.cs @@ -46,31 +46,21 @@ partial class Build AbsolutePath OutputPackageDir => RootDirectory / "artifacts" / "pkg"; - private void RemoveTemporaryFeeds() - { - try - { - if (DotNet("nuget list source").Any(x => x.Text.Contains(TemporaryNuGetFeed))) - { - DotNet($"nuget remove source \"{TemporaryNuGetFeed}\""); - } - } - catch - { - // probably hasn't existed yet, don't care. - } - } + AbsolutePath NuGetConfigFile => TemporaryDirectory / "push.nuget.config"; + + private void RemoveTemporaryFeeds() => NuGetConfigFile.DeleteFile(); private IEnumerable AddTemporaryFeed() { - if (NugetFeed.Contains("nuget.org")) - { - return []; - } + NuGetConfigFile.WriteAllText( + "" + + "" + ); var srcSettings = new DotNetNuGetAddSourceSettings() .SetName(TemporaryNuGetFeed) - .SetSource(NugetFeed); + .SetSource(NugetFeed) + .SetConfigFile(NuGetConfigFile); if (NugetUsername is null != NugetPassword is null) { @@ -130,7 +120,8 @@ DotNetNuGetPushSettings NuGetPushSettings var ret = new DotNetNuGetPushSettings() .SetNoServiceEndpoint(NugetNoServiceEndpoint) .EnableSkipDuplicate() - .SetSource(NugetFeed.Contains("nuget.org") ? "nuget.org" : TemporaryNuGetFeed); + .SetSource(NugetFeed.Contains("nuget.org") ? "nuget.org" : TemporaryNuGetFeed) + .AddProcessAdditionalArguments("--configfile", NuGetConfigFile); if (NugetApiKey is not null) { ret = ret.SetApiKey(NugetApiKey); diff --git a/generator.json b/generator.json index 914ed1551a..0d9b49e219 100644 --- a/generator.json +++ b/generator.json @@ -2,8 +2,8 @@ "Jobs": { "Microsoft": { "Solution": "Silk.NET.sln", - "SourceProject": "TODO.csproj", - "TestProject": "tests/TODO.csproj", + "SourceProject": "sources/Win32/Win32/Silk.NET.Win32.csproj", + "TestProject": "tests/Win32/Win32/Silk.NET.Win32.UnitTests.csproj", "DefaultLicenseHeader": "eng/silktouch/header.txt", "Mods": [ "AddIncludes", @@ -18,7 +18,8 @@ "sources/Windows/um/icm/Windows.gen.cs": "eng/submodules/terrafx.interop.windows/sources/Interop/Windows/Windows/um/icm/Windows.cs", "sources/Gdiplus/um/gdiplustypes/GpRect.gen.cs": "eng/submodules/terrafx.interop.windows/sources/Interop/Windows/Gdiplus/um/gdiplustypes/GpRect.cs", "sources/Gdiplus/um/gdiplustypes/GpRectF.gen.cs": "eng/submodules/terrafx.interop.windows/sources/Interop/Windows/Gdiplus/um/gdiplustypes/GpRectF.cs", - "sources/Gdiplus/um/gdiplustypes/GpPathData.gen.cs": "eng/submodules/terrafx.interop.windows/sources/Interop/Windows/Gdiplus/um/gdiplustypes/GpPathData.cs" + "sources/Gdiplus/um/gdiplustypes/GpPathData.gen.cs": "eng/submodules/terrafx.interop.windows/sources/Interop/Windows/Gdiplus/um/gdiplustypes/GpPathData.cs", + "sources/Windows/shared/strsafe/Windows.gen.cs": "eng/submodules/terrafx.interop.windows/sources/Interop/Windows/Windows/shared/strsafe/Windows.gen.cs" }, "InputSourceRoot": "eng/submodules/terrafx.interop.windows/sources/Interop/Windows", "InputTestRoot": "eng/submodules/terrafx.interop.windows/tests/Interop/Windows", diff --git a/global.json b/global.json index 899a4df6e1..0ad01216bd 100644 --- a/global.json +++ b/global.json @@ -2,5 +2,8 @@ "sdk": { "version": "10.0.100", "rollForward": "major" + }, + "test": { + "runner": "Microsoft.Testing.Platform" } } diff --git a/nuget.config b/nuget.config new file mode 100644 index 0000000000..d956be7da3 --- /dev/null +++ b/nuget.config @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/sources/Maths/Maths/Plane.cs b/sources/Maths/Maths/Plane.cs index 83b0fccaf1..1aaa6c388e 100644 --- a/sources/Maths/Maths/Plane.cs +++ b/sources/Maths/Maths/Plane.cs @@ -14,8 +14,8 @@ namespace Silk.NET.Maths /// The type used to store values. [Serializable] [DataContract] - public struct Plane - : IEquatable> where T : unmanaged, IFormattable, IEquatable, IComparable + public struct Plane : IEquatable> + where T : unmanaged, IFormattable, IEquatable, IComparable { /// The normal vector of the Plane. [DataMember] @@ -58,22 +58,21 @@ public Plane(Vector4D value) /// The first Plane to compare. /// The second Plane to compare. /// True if the Planes are equal; False otherwise. - [MethodImpl((MethodImplOptions) 768)] - public static bool operator ==(Plane value1, Plane value2) - => value1.Normal == value2.Normal && Scalar.Equal(value1.Distance, value2.Distance); + [MethodImpl((MethodImplOptions)768)] + public static bool operator ==(Plane value1, Plane value2) => + value1.Normal == value2.Normal && Scalar.Equal(value1.Distance, value2.Distance); /// Returns a boolean indicating whether the two given Planes are not equal. /// The first Plane to compare. /// The second Plane to compare. /// True if the Planes are not equal; False if they are equal. - [MethodImpl((MethodImplOptions) 768)] - public static bool operator !=(Plane value1, Plane value2) - => !(value1 == value2); + [MethodImpl((MethodImplOptions)768)] + public static bool operator !=(Plane value1, Plane value2) => !(value1 == value2); /// Returns a boolean indicating whether the given Object is equal to this Plane instance. /// The Object to compare against. /// True if the Object is equal to this Plane; False otherwise. - [MethodImpl((MethodImplOptions) 768)] + [MethodImpl((MethodImplOptions)768)] public override readonly bool Equals(object? obj) { return (obj is Plane other) && Equals(other); @@ -82,7 +81,7 @@ public override readonly bool Equals(object? obj) /// Returns a boolean indicating whether the given Plane is equal to this Plane instance. /// The Plane to compare this instance to. /// True if the other Plane is equal to this instance; False otherwise. - [MethodImpl((MethodImplOptions) 768)] + [MethodImpl((MethodImplOptions)768)] public readonly bool Equals(Plane other) { return Normal.Equals(other.Normal) && Scalar.Equal(Distance, other.Distance); @@ -92,7 +91,7 @@ public readonly bool Equals(Plane other) /// The hash code. public override readonly int GetHashCode() { - return Normal.GetHashCode() + Distance.GetHashCode(); + return HashCode.Combine(Normal.GetHashCode(), Distance.GetHashCode()); } /// Returns a String representing this Plane instance. @@ -100,7 +99,12 @@ public override readonly int GetHashCode() public override readonly string ToString() { CultureInfo ci = CultureInfo.CurrentCulture; - return string.Format(ci, "{{Normal:{0} D:{1}}}", Normal.ToString(), Distance.ToString("G", ci)); + return string.Format( + ci, + "{{Normal:{0} D:{1}}}", + Normal.ToString(), + Distance.ToString("G", ci) + ); } /// @@ -108,113 +112,114 @@ public override readonly string ToString() /// /// The source matrix /// The matrix - public static explicit operator Plane(Plane from) - => new((Vector3D) from.Normal, Scalar.As(from.Distance)); + public static explicit operator Plane(Plane from) => + new((Vector3D)from.Normal, Scalar.As(from.Distance)); /// /// Converts a into one with a of /// /// The source matrix /// The matrix - public static explicit operator Plane(Plane from) - => new((Vector3D) from.Normal, Scalar.As(from.Distance)); + public static explicit operator Plane(Plane from) => + new((Vector3D)from.Normal, Scalar.As(from.Distance)); /// /// Converts a into /// /// The source matrix /// The matrix - public static explicit operator System.Numerics.Plane(Plane from) - => new((System.Numerics.Vector3) from.Normal, Scalar.As(from.Distance)); - + public static explicit operator System.Numerics.Plane(Plane from) => + new((System.Numerics.Vector3)from.Normal, Scalar.As(from.Distance)); + /// /// Converts a into one with a of /// /// The source matrix /// The matrix - public static explicit operator Plane(Plane from) - => new((Vector3D) from.Normal, Scalar.As(from.Distance)); + public static explicit operator Plane(Plane from) => + new((Vector3D)from.Normal, Scalar.As(from.Distance)); /// /// Converts a into one with a of /// /// The source matrix /// The matrix - public static explicit operator Plane(Plane from) - => new((Vector3D) from.Normal, Scalar.As(from.Distance)); + public static explicit operator Plane(Plane from) => + new((Vector3D)from.Normal, Scalar.As(from.Distance)); /// /// Converts a into one with a of /// /// The source matrix /// The matrix - public static explicit operator Plane(Plane from) - => new((Vector3D) from.Normal, Scalar.As(from.Distance)); + public static explicit operator Plane(Plane from) => + new((Vector3D)from.Normal, Scalar.As(from.Distance)); /// /// Converts a into one with a of /// /// The source matrix /// The matrix - public static explicit operator Plane(Plane from) - => new((Vector3D) from.Normal, Scalar.As(from.Distance)); + public static explicit operator Plane(Plane from) => + new((Vector3D)from.Normal, Scalar.As(from.Distance)); /// /// Converts a into one with a of /// /// The source matrix /// The matrix - public static explicit operator Plane(Plane from) - => new((Vector3D) from.Normal, Scalar.As(from.Distance)); + public static explicit operator Plane(Plane from) => + new((Vector3D)from.Normal, Scalar.As(from.Distance)); /// /// Converts a into one with a of /// /// The source matrix /// The matrix - public static explicit operator Plane(Plane from) - => new((Vector3D) from.Normal, Scalar.As(from.Distance)); + public static explicit operator Plane(Plane from) => + new((Vector3D)from.Normal, Scalar.As(from.Distance)); /// /// Converts a into one with a of /// /// The source matrix /// The matrix - public static explicit operator Plane(Plane from) - => new((Vector3D) from.Normal, Scalar.As(from.Distance)); + public static explicit operator Plane(Plane from) => + new((Vector3D)from.Normal, Scalar.As(from.Distance)); /// /// Converts a into one with a of /// /// The source matrix /// The matrix - public static explicit operator Plane(Plane from) - => new((Vector3D) from.Normal, Scalar.As(from.Distance)); + public static explicit operator Plane(Plane from) => + new((Vector3D)from.Normal, Scalar.As(from.Distance)); /// /// Converts a into one with a of /// /// The source matrix /// The matrix - public static explicit operator Plane(Plane from) - => new((Vector3D) from.Normal, Scalar.As(from.Distance)); + public static explicit operator Plane(Plane from) => + new((Vector3D)from.Normal, Scalar.As(from.Distance)); /// /// Converts a into one with a of /// /// The source matrix /// The matrix - public static explicit operator Plane(Plane from) - => new((Vector3D) from.Normal, Scalar.As(from.Distance)); - + public static explicit operator Plane(Plane from) => + new((Vector3D)from.Normal, Scalar.As(from.Distance)); + /// /// Returns this plane casted to /// /// The type to cast to /// The casted plane - public Plane As() where TOther : unmanaged, IFormattable, IEquatable, IComparable + public Plane As() + where TOther : unmanaged, IFormattable, IEquatable, IComparable { return new(Normal.As(), Scalar.As(Distance)); } } -} \ No newline at end of file +} diff --git a/sources/Maths/Maths/PublicAPI/net10.0-android/PublicAPI.Shipped.txt b/sources/Maths/Maths/PublicAPI/net10.0-android/PublicAPI.Shipped.txt new file mode 100644 index 0000000000..7dc5c58110 --- /dev/null +++ b/sources/Maths/Maths/PublicAPI/net10.0-android/PublicAPI.Shipped.txt @@ -0,0 +1 @@ +#nullable enable diff --git a/sources/Maths/Maths/PublicAPI/net10.0-android/PublicAPI.Unshipped.txt b/sources/Maths/Maths/PublicAPI/net10.0-android/PublicAPI.Unshipped.txt new file mode 100644 index 0000000000..7dc5c58110 --- /dev/null +++ b/sources/Maths/Maths/PublicAPI/net10.0-android/PublicAPI.Unshipped.txt @@ -0,0 +1 @@ +#nullable enable diff --git a/sources/Maths/Maths/Scalar.Bitwise/Scalar.Not.cs b/sources/Maths/Maths/Scalar.Bitwise/Scalar.Not.cs index 4db3748511..2181bdb694 100644 --- a/sources/Maths/Maths/Scalar.Bitwise/Scalar.Not.cs +++ b/sources/Maths/Maths/Scalar.Bitwise/Scalar.Not.cs @@ -10,7 +10,8 @@ static partial class Scalar /// /// Performs Not on supported types /// - public static T Not(T value) where T : unmanaged + public static T Not(T value) + where T : unmanaged { return Byte(value); @@ -19,113 +20,113 @@ static T Byte(T value) { if (typeof(T) == typeof(byte)) { - return (T) (object) (byte) (~ (byte) (object) value); + return (T)(object)(byte)(~((byte)(object)value) & byte.MaxValue); } return SByte(value); } - + [MethodImpl(MaxOpt)] static T SByte(T value) { if (typeof(T) == typeof(sbyte)) { - return (T) (object) (sbyte) (~ (sbyte) (object) value); + return (T)(object)(sbyte)(~(sbyte)(object)value); } return UInt16(value); } - + [MethodImpl(MaxOpt)] static T UInt16(T value) { if (typeof(T) == typeof(ushort)) { - return (T) (object) (ushort) (~ (ushort) (object) value); + return (T)(object)(ushort)(~(ushort)(object)value); } return Int16(value); } - + [MethodImpl(MaxOpt)] static T Int16(T value) { if (typeof(T) == typeof(short)) { - return (T) (object) (short) (~ (short) (object) value); + return (T)(object)(short)(~(short)(object)value); } return UInt32(value); } - + [MethodImpl(MaxOpt)] static T UInt32(T value) { if (typeof(T) == typeof(uint)) { - return (T) (object) (uint) (~ (uint) (object) value); + return (T)(object)(uint)(~(uint)(object)value); } return Int32(value); } - + [MethodImpl(MaxOpt)] static T Int32(T value) { if (typeof(T) == typeof(int)) { - return (T) (object) (int) (~ (int) (object) value); + return (T)(object)(int)(~(int)(object)value); } return UInt64(value); } - + [MethodImpl(MaxOpt)] static T UInt64(T value) { if (typeof(T) == typeof(ulong)) { - return (T) (object) (ulong) (~ (ulong) (object) value); + return (T)(object)(ulong)(~(ulong)(object)value); } return Int64(value); } - + [MethodImpl(MaxOpt)] static T Int64(T value) { if (typeof(T) == typeof(long)) { - return (T) (object) (long) (~ (long) (object) value); + return (T)(object)(long)(~(long)(object)value); } return Single(value); } - + [MethodImpl(MaxOpt)] static T Single(T value) { if (typeof(T) == typeof(float)) { - var res = ~ Unsafe.As(ref value); + var res = ~Unsafe.As(ref value); return Unsafe.As(ref res); } return Double(value); } - + [MethodImpl(MaxOpt)] static T Double(T value) { if (typeof(T) == typeof(double)) { - var res = ~ Unsafe.As(ref value); + var res = ~Unsafe.As(ref value); return Unsafe.As(ref res); } return Other(value); } - + [MethodImpl(MaxOpt)] static T Other(T value) { @@ -134,4 +135,4 @@ static T Other(T value) } } } -} \ No newline at end of file +} diff --git a/sources/Maths/Maths/Scalar.Bitwise/Scalar.RotateLeft.cs b/sources/Maths/Maths/Scalar.Bitwise/Scalar.RotateLeft.cs index 979340447b..5918b586fe 100644 --- a/sources/Maths/Maths/Scalar.Bitwise/Scalar.RotateLeft.cs +++ b/sources/Maths/Maths/Scalar.Bitwise/Scalar.RotateLeft.cs @@ -11,106 +11,107 @@ static partial class Scalar /// Rotates a given value bitwise. /// Shifting float and double obeys unsigned integers' behaviour. /// - public static T RotateLeft(T value, int offset) where T : unmanaged + public static T RotateLeft(T value, int offset) + where T : unmanaged { return Byte(value, offset); - + [MethodImpl(MaxOpt)] static T Byte(T value, int offset) { if (typeof(T) == typeof(byte)) { - var v = (byte) (object) value; - return (T) (object) (byte) ((v << offset) | (v >> (8 - offset))); + var v = (byte)(object)value; + return (T)(object)(byte)(((v << offset) | (v >> (8 - offset))) & 0xFF); } - + return SByte(value, offset); } - + [MethodImpl(MaxOpt)] static T SByte(T value, int offset) { if (typeof(T) == typeof(sbyte)) { - var v = (sbyte) (object) value; - return (T) (object) (sbyte) ((v << offset) | (v >> (8 - offset))); + var v = (sbyte)(object)value; + return (T)(object)(sbyte)(((v << offset) | (v >> (8 - offset))) & 0xFF); } - + return UShort(value, offset); } - + [MethodImpl(MaxOpt)] static T UShort(T value, int offset) { if (typeof(T) == typeof(ushort)) { - var v = (ushort) (object) value; - return (T) (object) (ushort) ((v << offset) | (v >> (16 - offset))); + var v = (ushort)(object)value; + return (T)(object)(ushort)(((v << offset) | (v >> (16 - offset))) & 0xFFFF); } - + return Short(value, offset); } - + [MethodImpl(MaxOpt)] static T Short(T value, int offset) { if (typeof(T) == typeof(short)) { - var v = (short) (object) value; - return (T) (object) (short) ((v << offset) | (v >> (16 - offset))); + var v = (short)(object)value; + return (T)(object)(short)(((v << offset) | (v >> (16 - offset))) & 0xFFFF); } - + return UInt(value, offset); } - + [MethodImpl(MaxOpt)] static T UInt(T value, int offset) { if (typeof(T) == typeof(uint)) { - var v = (uint) (object) value; - return (T) (object) (uint) ((v << offset) | (v >> (32 - offset))); + var v = (uint)(object)value; + return (T)(object)(uint)((v << offset) | (v >> (32 - offset))); } - + return Int(value, offset); } - + [MethodImpl(MaxOpt)] static T Int(T value, int offset) { if (typeof(T) == typeof(int)) { - var v = (int) (object) value; - return (T) (object) (int) ((v << offset) | (v >> (32 - offset))); + var v = (int)(object)value; + return (T)(object)(int)((v << offset) | (v >> (32 - offset))); } - + return ULong(value, offset); } - + [MethodImpl(MaxOpt)] static T ULong(T value, int offset) { if (typeof(T) == typeof(ulong)) { - var v = (ulong) (object) value; - return (T) (object) (ulong) ((v << offset) | (v >> (64 - offset))); + var v = (ulong)(object)value; + return (T)(object)(ulong)((v << offset) | (v >> (64 - offset))); } - + return Long(value, offset); } - + [MethodImpl(MaxOpt)] static T Long(T value, int offset) { if (typeof(T) == typeof(long)) { - var v = (long) (object) value; - return (T) (object) (long) ((v << offset) | (v >> (64 - offset))); + var v = (long)(object)value; + return (T)(object)(long)((v << offset) | (v >> (64 - offset))); } - + return Float(value, offset); } - + [MethodImpl(MaxOpt)] static T Float(T value, int offset) { @@ -120,10 +121,10 @@ static T Float(T value, int offset) var res = (v << offset) | (v >> (32 - offset)); return Unsafe.As(ref res); } - + return Double(value, offset); } - + [MethodImpl(MaxOpt)] static T Double(T value, int offset) { @@ -133,10 +134,10 @@ static T Double(T value, int offset) var res = (v << offset) | (v >> (64 - offset)); return Unsafe.As(ref res); } - + return Other(value, offset); } - + [MethodImpl(MaxOpt)] static T Other(T _, int __) { @@ -145,4 +146,4 @@ static T Other(T _, int __) } } } -} \ No newline at end of file +} diff --git a/sources/Maths/Maths/Scalar.Bitwise/Scalar.RotateRight.cs b/sources/Maths/Maths/Scalar.Bitwise/Scalar.RotateRight.cs index 3324597f08..604ebf63eb 100644 --- a/sources/Maths/Maths/Scalar.Bitwise/Scalar.RotateRight.cs +++ b/sources/Maths/Maths/Scalar.Bitwise/Scalar.RotateRight.cs @@ -11,106 +11,107 @@ static partial class Scalar /// Rotates a given value bitwise. /// Shifting float and double obeys unsigned integers' behaviour. /// - public static T RotateRight(T value, int offset) where T : unmanaged + public static T RotateRight(T value, int offset) + where T : unmanaged { return Byte(value, offset); - + [MethodImpl(MaxOpt)] static T Byte(T value, int offset) { if (typeof(T) == typeof(byte)) { - var v = (byte) (object) value; - return (T) (object) (byte) ((v >> offset) | (v << (8 - offset))); + var v = (byte)(object)value; + return (T)(object)(byte)(((v >> offset) | (v << (8 - offset))) & 0xFF); } - + return SByte(value, offset); } - + [MethodImpl(MaxOpt)] static T SByte(T value, int offset) { if (typeof(T) == typeof(sbyte)) { - var v = (sbyte) (object) value; - return (T) (object) (sbyte) ((v >> offset) | (v << (8 - offset))); + var v = (sbyte)(object)value; + return (T)(object)(sbyte)(((v >> offset) | (v << (8 - offset))) & 0xFF); } - + return UShort(value, offset); } - + [MethodImpl(MaxOpt)] static T UShort(T value, int offset) { if (typeof(T) == typeof(ushort)) { - var v = (ushort) (object) value; - return (T) (object) (ushort) ((v >> offset) | (v << (16 - offset))); + var v = (ushort)(object)value; + return (T)(object)(ushort)(((v >> offset) | (v << (16 - offset))) & 0xFFFF); } - + return Short(value, offset); } - + [MethodImpl(MaxOpt)] static T Short(T value, int offset) { if (typeof(T) == typeof(short)) { - var v = (short) (object) value; - return (T) (object) (short) ((v >> offset) | (v << (16 - offset))); + var v = (short)(object)value; + return (T)(object)(short)(((v >> offset) | (v << (16 - offset))) & 0xFFFF); } - + return UInt(value, offset); } - + [MethodImpl(MaxOpt)] static T UInt(T value, int offset) { if (typeof(T) == typeof(uint)) { - var v = (uint) (object) value; - return (T) (object) (uint) ((v >> offset) | (v << (32 - offset))); + var v = (uint)(object)value; + return (T)(object)(uint)((v >> offset) | (v << (32 - offset))); } - + return Int(value, offset); } - + [MethodImpl(MaxOpt)] static T Int(T value, int offset) { if (typeof(T) == typeof(int)) { - var v = (int) (object) value; - return (T) (object) (int) ((v >> offset) | (v << (32 - offset))); + var v = (int)(object)value; + return (T)(object)(int)((v >> offset) | (v << (32 - offset))); } - + return ULong(value, offset); } - + [MethodImpl(MaxOpt)] static T ULong(T value, int offset) { if (typeof(T) == typeof(ulong)) { - var v = (ulong) (object) value; - return (T) (object) (ulong) ((v >> offset) | (v << (64 - offset))); + var v = (ulong)(object)value; + return (T)(object)(ulong)((v >> offset) | (v << (64 - offset))); } - + return Long(value, offset); } - + [MethodImpl(MaxOpt)] static T Long(T value, int offset) { if (typeof(T) == typeof(long)) { - var v = (long) (object) value; - return (T) (object) (long) ((v >> offset) | (v << (64 - offset))); + var v = (long)(object)value; + return (T)(object)(long)((v >> offset) | (v << (64 - offset))); } - + return Float(value, offset); } - + [MethodImpl(MaxOpt)] static T Float(T value, int offset) { @@ -120,10 +121,10 @@ static T Float(T value, int offset) var res = (v >> offset) | (v << (32 - offset)); return Unsafe.As(ref res); } - + return Double(value, offset); } - + [MethodImpl(MaxOpt)] static T Double(T value, int offset) { @@ -133,10 +134,10 @@ static T Double(T value, int offset) var res = (v >> offset) | (v << (64 - offset)); return Unsafe.As(ref res); } - + return Other(value, offset); } - + [MethodImpl(MaxOpt)] static T Other(T _, int __) { @@ -145,4 +146,4 @@ static T Other(T _, int __) } } } -} \ No newline at end of file +} diff --git a/sources/Maths/Maths/Scalar.Log.cs b/sources/Maths/Maths/Scalar.Log.cs deleted file mode 100644 index a286fda059..0000000000 --- a/sources/Maths/Maths/Scalar.Log.cs +++ /dev/null @@ -1,307 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -// ported / adopted from https://github.com/amd/aocl-libm-ose/tree/master/src/optmized - -/* - * Copyright (C) 2008-2020 Advanced Micro Devices, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -using System; -using System.Runtime.CompilerServices; -#if SSE -using System.Runtime.Intrinsics; -using System.Runtime.Intrinsics.X86; -#endif - -namespace Silk.NET.Maths -{ - public static partial class Scalar - { - private static uint[] InitLog() - { -#if POH - var logTblLookup = GC.AllocateUninitializedArray(771, true); -#else - var logTblLookup = new uint[771]; -#endif - int i = 0; - logTblLookup[i++] = 0x40000000; logTblLookup[i++] = 0x0; logTblLookup[i++] = 0x0; logTblLookup[i++] = 0x3fff00ff; logTblLookup[i++] = 0x3b7f8000; logTblLookup[i++] = 0x32aa2b11; logTblLookup[i++] = 0x3ffe03f8; logTblLookup[i++] = 0x3bff0000; logTblLookup[i++] = 0x3429ac42; logTblLookup[i++] = - 0x3ffd08e5; logTblLookup[i++] = 0x3c3ee000; logTblLookup[i++] = 0x350ebf02; logTblLookup[i++] = 0x3ffc0fc1; logTblLookup[i++] = 0x3c7e0000; logTblLookup[i++] = 0x35a8b0fc; logTblLookup[i++] = 0x3ffb1885; logTblLookup[i++] = 0x3c9e7000; logTblLookup[i++] = -0x36244347; logTblLookup[i++] = 0x3ffa232d; logTblLookup[i++] = 0x3cbdc000; logTblLookup[i++] = 0x368d83eb; logTblLookup[i++] = 0x3ff92fb2; logTblLookup[i++] = 0x3cdcf000; logTblLookup[i++] = 0x36e013d8; logTblLookup[i++] = 0x3ff83e10; logTblLookup[i++] = -0x3cfc1000; logTblLookup[i++] = 0x361b0e78; logTblLookup[i++] = 0x3ff74e40; logTblLookup[i++] = 0x3d0d8000; logTblLookup[i++] = 0x36d98924; logTblLookup[i++] = 0x3ff6603e; logTblLookup[i++] = 0x3d1cf000; logTblLookup[i++] = 0x3687b9ff; logTblLookup[i++] = -0x3ff57404; logTblLookup[i++] = 0x3d2c5000; logTblLookup[i++] = 0x36375f92; logTblLookup[i++] = 0x3ff4898d; logTblLookup[i++] = 0x3d3ba000; logTblLookup[i++] = 0x3631ec66; logTblLookup[i++] = 0x3ff3a0d5; logTblLookup[i++] = 0x3d4ae000; logTblLookup[i++] = -0x36830ec9; logTblLookup[i++] = 0x3ff2b9d6; logTblLookup[i++] = 0x3d5a1000; logTblLookup[i++] = 0x36dd7119; logTblLookup[i++] = 0x3ff1d48c; logTblLookup[i++] = 0x3d693000; logTblLookup[i++] = 0x3735c56e; logTblLookup[i++] = 0x3ff0f0f1; logTblLookup[i++] = -0x3d785000; logTblLookup[i++] = 0x35c30046; logTblLookup[i++] = 0x3ff00f01; logTblLookup[i++] = 0x3d83a000; logTblLookup[i++] = 0x37cc1acc; logTblLookup[i++] = 0x3fef2eb7; logTblLookup[i++] = 0x3d8b2000; logTblLookup[i++] = 0x379b7752; logTblLookup[i++] = -0x3fee500f; logTblLookup[i++] = 0x3d929000; logTblLookup[i++] = 0x37fb1785; logTblLookup[i++] = 0x3fed7304; logTblLookup[i++] = 0x3d9a0000; logTblLookup[i++] = 0x37ebcb0e; logTblLookup[i++] = 0x3fec9791; logTblLookup[i++] = 0x3da17000; logTblLookup[i++] = -0x375cbea6; logTblLookup[i++] = 0x3febbdb3; logTblLookup[i++] = 0x3da8d000; logTblLookup[i++] = 0x37839f83; logTblLookup[i++] = 0x3feae564; logTblLookup[i++] = 0x3db03000; logTblLookup[i++] = 0x36b1526f; logTblLookup[i++] = 0x3fea0ea1; logTblLookup[i++] = -0x3db78000; logTblLookup[i++] = 0x37528ae5; logTblLookup[i++] = 0x3fe93965; logTblLookup[i++] = 0x3dbed000; logTblLookup[i++] = 0x36ecdaf6; logTblLookup[i++] = 0x3fe865ac; logTblLookup[i++] = 0x3dc61000; logTblLookup[i++] = 0x37a2eb19; logTblLookup[i++] = -0x3fe79373; logTblLookup[i++] = 0x3dcd5000; logTblLookup[i++] = 0x37a12310; logTblLookup[i++] = 0x3fe6c2b4; logTblLookup[i++] = 0x3dd49000; logTblLookup[i++] = 0x36da7496; logTblLookup[i++] = 0x3fe5f36d; logTblLookup[i++] = 0x3ddbc000; logTblLookup[i++] = -0x37482bb1; logTblLookup[i++] = 0x3fe52598; logTblLookup[i++] = 0x3de2f000; logTblLookup[i++] = 0x36a91eb8; logTblLookup[i++] = 0x3fe45933; logTblLookup[i++] = 0x3dea1000; logTblLookup[i++] = 0x3789eb36; logTblLookup[i++] = 0x3fe38e39; logTblLookup[i++] = -0x3df13000; logTblLookup[i++] = 0x3783b715; logTblLookup[i++] = 0x3fe2c4a7; logTblLookup[i++] = 0x3df85000; logTblLookup[i++] = 0x36430046; logTblLookup[i++] = 0x3fe1fc78; logTblLookup[i++] = 0x3dff6000; logTblLookup[i++] = 0x371131dc; logTblLookup[i++] = -0x3fe135aa; logTblLookup[i++] = 0x3e033000; logTblLookup[i++] = 0x380a8965; logTblLookup[i++] = 0x3fe07038; logTblLookup[i++] = 0x3e06b000; logTblLookup[i++] = 0x383f3e68; logTblLookup[i++] = 0x3fdfac1f; logTblLookup[i++] = 0x3e0a3000; logTblLookup[i++] = -0x3842c234; logTblLookup[i++] = 0x3fdee95c; logTblLookup[i++] = 0x3e0db000; logTblLookup[i++] = 0x38156a98; logTblLookup[i++] = 0x3fde27eb; logTblLookup[i++] = 0x3e113000; logTblLookup[i++] = 0x375e3215; logTblLookup[i++] = 0x3fdd67c9; logTblLookup[i++] = -0x3e14a000; logTblLookup[i++] = 0x38297c10; logTblLookup[i++] = 0x3fdca8f1; logTblLookup[i++] = 0x3e181000; logTblLookup[i++] = 0x386b8c72; logTblLookup[i++] = 0x3fdbeb62; logTblLookup[i++] = 0x3e1b8000; logTblLookup[i++] = 0x387e100f; logTblLookup[i++] = -0x3fdb2f17; logTblLookup[i++] = 0x3e1ef000; logTblLookup[i++] = 0x38615876; logTblLookup[i++] = 0x3fda740e; logTblLookup[i++] = 0x3e226000; logTblLookup[i++] = 0x3815b666; logTblLookup[i++] = 0x3fd9ba42; logTblLookup[i++] = 0x3e25d000; logTblLookup[i++] = -0x36dbce69; logTblLookup[i++] = 0x3fd901b2; logTblLookup[i++] = 0x3e293000; logTblLookup[i++] = 0x37e5e3a2; logTblLookup[i++] = 0x3fd84a5a; logTblLookup[i++] = 0x3e2c9000; logTblLookup[i++] = 0x381c6ccc; logTblLookup[i++] = 0x3fd79436; logTblLookup[i++] = -0x3e2ff000; logTblLookup[i++] = 0x38183854; logTblLookup[i++] = 0x3fd6df44; logTblLookup[i++] = 0x3e335000; logTblLookup[i++] = 0x37cd4273; logTblLookup[i++] = 0x3fd62b81; logTblLookup[i++] = 0x3e36b000; logTblLookup[i++] = 0x35fe719d; logTblLookup[i++] = -0x3fd578e9; logTblLookup[i++] = 0x3e3a0000; logTblLookup[i++] = 0x37f8f540; logTblLookup[i++] = 0x3fd4c77b; logTblLookup[i++] = 0x3e3d5000; logTblLookup[i++] = 0x38448108; logTblLookup[i++] = 0x3fd41733; logTblLookup[i++] = 0x3e40a000; logTblLookup[i++] = -0x386050a2; logTblLookup[i++] = 0x3fd3680d; logTblLookup[i++] = 0x3e43f000; logTblLookup[i++] = 0x38503290; logTblLookup[i++] = 0x3fd2ba08; logTblLookup[i++] = 0x3e474000; logTblLookup[i++] = 0x38146f44; logTblLookup[i++] = 0x3fd20d21; logTblLookup[i++] = -0x3e4a9000; logTblLookup[i++] = 0x373539e9; logTblLookup[i++] = 0x3fd16154; logTblLookup[i++] = 0x3e4dd000; logTblLookup[i++] = 0x381b173f; logTblLookup[i++] = 0x3fd0b6a0; logTblLookup[i++] = 0x3e511000; logTblLookup[i++] = 0x385e0ff1; logTblLookup[i++] = -0x3fd00d01; logTblLookup[i++] = 0x3e545000; logTblLookup[i++] = 0x38767e44; logTblLookup[i++] = 0x3fcf6475; logTblLookup[i++] = 0x3e579000; logTblLookup[i++] = 0x3864a740; logTblLookup[i++] = 0x3fcebcf9; logTblLookup[i++] = 0x3e5ad000; logTblLookup[i++] = -0x3828cf48; logTblLookup[i++] = 0x3fce168a; logTblLookup[i++] = 0x3e5e1000; logTblLookup[i++] = 0x3786742e; logTblLookup[i++] = 0x3fcd7127; logTblLookup[i++] = 0x3e614000; logTblLookup[i++] = 0x38342ac6; logTblLookup[i++] = 0x3fcccccd; logTblLookup[i++] = -0x3e647000; logTblLookup[i++] = 0x387be3cd; logTblLookup[i++] = 0x3fcc2978; logTblLookup[i++] = 0x3e67b000; logTblLookup[i++] = 0x36d53827; logTblLookup[i++] = 0x3fcb8728; logTblLookup[i++] = 0x3e6ae000; logTblLookup[i++] = 0x3685ad3f; logTblLookup[i++] = -0x3fcae5d8; logTblLookup[i++] = 0x3e6e0000; logTblLookup[i++] = 0x385e5056; logTblLookup[i++] = 0x3fca4588; logTblLookup[i++] = 0x3e713000; logTblLookup[i++] = 0x3803b715; logTblLookup[i++] = 0x3fc9a634; logTblLookup[i++] = 0x3e746000; logTblLookup[i++] = -0x3494aa97; logTblLookup[i++] = 0x3fc907da; logTblLookup[i++] = 0x3e778000; logTblLookup[i++] = 0x37adcbdc; logTblLookup[i++] = 0x3fc86a79; logTblLookup[i++] = 0x3e7aa000; logTblLookup[i++] = 0x38052b26; logTblLookup[i++] = 0x3fc7ce0c; logTblLookup[i++] = -0x3e7dc000; logTblLookup[i++] = 0x380c36af; logTblLookup[i++] = 0x3fc73294; logTblLookup[i++] = 0x3e807000; logTblLookup[i++] = 0x37d88b5b; logTblLookup[i++] = 0x3fc6980c; logTblLookup[i++] = 0x3e820000; logTblLookup[i++] = 0x371652d3; logTblLookup[i++] = -0x3fc5fe74; logTblLookup[i++] = 0x3e838000; logTblLookup[i++] = 0x38dc2fe7; logTblLookup[i++] = 0x3fc565c8; logTblLookup[i++] = 0x3e851000; logTblLookup[i++] = 0x3892713a; logTblLookup[i++] = 0x3fc4ce08; logTblLookup[i++] = 0x3e86a000; logTblLookup[i++] = -0x37d6af35; logTblLookup[i++] = 0x3fc43730; logTblLookup[i++] = 0x3e882000; logTblLookup[i++] = 0x38c5fcd7; logTblLookup[i++] = 0x3fc3a13e; logTblLookup[i++] = 0x3e89b000; logTblLookup[i++] = 0x38070294; logTblLookup[i++] = 0x3fc30c31; logTblLookup[i++] = -0x3e8b3000; logTblLookup[i++] = 0x38ae55d6; logTblLookup[i++] = 0x3fc27806; logTblLookup[i++] = 0x3e8cc000; logTblLookup[i++] = 0x3652dd42; logTblLookup[i++] = 0x3fc1e4bc; logTblLookup[i++] = 0x3e8e4000; logTblLookup[i++] = 0x3818c16a; logTblLookup[i++] = -0x3fc15250; logTblLookup[i++] = 0x3e8fc000; logTblLookup[i++] = 0x387f9e49; logTblLookup[i++] = 0x3fc0c0c1; logTblLookup[i++] = 0x3e914000; logTblLookup[i++] = 0x38a0fde8; logTblLookup[i++] = 0x3fc0300c; logTblLookup[i++] = 0x3e92c000; logTblLookup[i++] = -0x38b00870; logTblLookup[i++] = 0x3fbfa030; logTblLookup[i++] = 0x3e944000; logTblLookup[i++] = 0x38ad09ef; logTblLookup[i++] = 0x3fbf112b; logTblLookup[i++] = 0x3e95c000; logTblLookup[i++] = 0x38981d5c; logTblLookup[i++] = 0x3fbe82fa; logTblLookup[i++] = -0x3e974000; logTblLookup[i++] = 0x3862bae1; logTblLookup[i++] = 0x3fbdf59d; logTblLookup[i++] = 0x3e98c000; logTblLookup[i++] = 0x37e392a9; logTblLookup[i++] = 0x3fbd6910; logTblLookup[i++] = 0x3e9a3000; logTblLookup[i++] = 0x38eecd4c; logTblLookup[i++] = -0x3fbcdd53; logTblLookup[i++] = 0x3e9bb000; logTblLookup[i++] = 0x38933160; logTblLookup[i++] = 0x3fbc5264; logTblLookup[i++] = 0x3e9d3000; logTblLookup[i++] = 0x3798aad3; logTblLookup[i++] = 0x3fbbc841; logTblLookup[i++] = 0x3e9ea000; logTblLookup[i++] = -0x38a7d2e1; logTblLookup[i++] = 0x3fbb3ee7; logTblLookup[i++] = 0x3ea02000; logTblLookup[i++] = 0x37421a1b; logTblLookup[i++] = 0x3fbab656; logTblLookup[i++] = 0x3ea19000; logTblLookup[i++] = 0x386f2a05; logTblLookup[i++] = 0x3fba2e8c; logTblLookup[i++] = -0x3ea30000; logTblLookup[i++] = 0x38c5e10e; logTblLookup[i++] = 0x3fb9a786; logTblLookup[i++] = 0x3ea48000; logTblLookup[i++] = 0x35d00801; logTblLookup[i++] = 0x3fb92144; logTblLookup[i++] = 0x3ea5f000; logTblLookup[i++] = 0x37bf2aef; logTblLookup[i++] = -0x3fb89bc3; logTblLookup[i++] = 0x3ea76000; logTblLookup[i++] = 0x38173260; logTblLookup[i++] = 0x3fb81703; logTblLookup[i++] = 0x3ea8d000; logTblLookup[i++] = 0x382d872e; logTblLookup[i++] = 0x3fb79301; logTblLookup[i++] = 0x3eaa4000; logTblLookup[i++] = -0x3822c3ae; logTblLookup[i++] = 0x3fb70fbb; logTblLookup[i++] = 0x3eabb000; logTblLookup[i++] = 0x37ee2e8b; logTblLookup[i++] = 0x3fb68d31; logTblLookup[i++] = 0x3ead2000; logTblLookup[i++] = 0x372ac3d3; logTblLookup[i++] = 0x3fb60b61; logTblLookup[i++] = -0x3eae8000; logTblLookup[i++] = 0x38dedfac; logTblLookup[i++] = 0x3fb58a48; logTblLookup[i++] = 0x3eaff000; logTblLookup[i++] = 0x38983854; logTblLookup[i++] = 0x3fb509e7; logTblLookup[i++] = 0x3eb16000; logTblLookup[i++] = 0x3802f2ba; logTblLookup[i++] = -0x3fb48a3a; logTblLookup[i++] = 0x3eb2c000; logTblLookup[i++] = 0x38dab982; logTblLookup[i++] = 0x3fb40b41; logTblLookup[i++] = 0x3eb43000; logTblLookup[i++] = 0x38481e9b; logTblLookup[i++] = 0x3fb38cfa; logTblLookup[i++] = 0x3eb59000; logTblLookup[i++] = -0x38dd911b; logTblLookup[i++] = 0x3fb30f63; logTblLookup[i++] = 0x3eb70000; logTblLookup[i++] = 0x380eaa2c; logTblLookup[i++] = 0x3fb2927c; logTblLookup[i++] = 0x3eb86000; logTblLookup[i++] = 0x38a1713c; logTblLookup[i++] = 0x3fb21643; logTblLookup[i++] = -0x3eb9c000; logTblLookup[i++] = 0x38ebfb5e; logTblLookup[i++] = 0x3fb19ab6; logTblLookup[i++] = 0x3ebb3000; logTblLookup[i++] = 0x379c2474; logTblLookup[i++] = 0x3fb11fd4; logTblLookup[i++] = 0x3ebc9000; logTblLookup[i++] = 0x38255fdd; logTblLookup[i++] = -0x3fb0a59b; logTblLookup[i++] = 0x3ebdf000; logTblLookup[i++] = 0x385e0a38; logTblLookup[i++] = 0x3fb02c0b; logTblLookup[i++] = 0x3ebf5000; logTblLookup[i++] = 0x38783b83; logTblLookup[i++] = 0x3fafb322; logTblLookup[i++] = 0x3ec0b000; logTblLookup[i++] = -0x38741da1; logTblLookup[i++] = 0x3faf3ade; logTblLookup[i++] = 0x3ec21000; logTblLookup[i++] = 0x3851da1f; logTblLookup[i++] = 0x3faec33e; logTblLookup[i++] = 0x3ec37000; logTblLookup[i++] = 0x38119a33; logTblLookup[i++] = 0x3fae4c41; logTblLookup[i++] = -0x3ec4d000; logTblLookup[i++] = 0x374e1b05; logTblLookup[i++] = 0x3fadd5e6; logTblLookup[i++] = 0x3ec62000; logTblLookup[i++] = 0x38dbe42c; logTblLookup[i++] = 0x3fad602b; logTblLookup[i++] = 0x3ec78000; logTblLookup[i++] = 0x388f439b; logTblLookup[i++] = -0x3faceb10; logTblLookup[i++] = 0x3ec8e000; logTblLookup[i++] = 0x37cfd68b; logTblLookup[i++] = 0x3fac7692; logTblLookup[i++] = 0x3eca3000; logTblLookup[i++] = 0x38ca0e11; logTblLookup[i++] = 0x3fac02b0; logTblLookup[i++] = 0x3ecb9000; logTblLookup[i++] = -0x38234113; logTblLookup[i++] = 0x3fab8f6a; logTblLookup[i++] = 0x3ecce000; logTblLookup[i++] = 0x38cac08c; logTblLookup[i++] = 0x3fab1cbe; logTblLookup[i++] = 0x3ece4000; logTblLookup[i++] = 0x37d605b8; logTblLookup[i++] = 0x3faaaaab; logTblLookup[i++] = -0x3ecf9000; logTblLookup[i++] = 0x3891f660; logTblLookup[i++] = 0x3faa392f; logTblLookup[i++] = 0x3ed0e000; logTblLookup[i++] = 0x38e0326b; logTblLookup[i++] = 0x3fa9c84a; logTblLookup[i++] = 0x3ed24000; logTblLookup[i++] = 0x378121cb; logTblLookup[i++] = -0x3fa957fb; logTblLookup[i++] = 0x3ed39000; logTblLookup[i++] = 0x3824966c; logTblLookup[i++] = 0x3fa8e83f; logTblLookup[i++] = 0x3ed4e000; logTblLookup[i++] = 0x386c9a9a; logTblLookup[i++] = 0x3fa87917; logTblLookup[i++] = 0x3ed63000; logTblLookup[i++] = -0x388c612c; logTblLookup[i++] = 0x3fa80a81; logTblLookup[i++] = 0x3ed78000; logTblLookup[i++] = 0x38949924; logTblLookup[i++] = 0x3fa79c7b; logTblLookup[i++] = 0x3ed8d000; logTblLookup[i++] = 0x388f075f; logTblLookup[i++] = 0x3fa72f05; logTblLookup[i++] = -0x3eda2000; logTblLookup[i++] = 0x38777bcd; logTblLookup[i++] = 0x3fa6c21e; logTblLookup[i++] = 0x3edb7000; logTblLookup[i++] = 0x38359d3d; logTblLookup[i++] = 0x3fa655c4; logTblLookup[i++] = 0x3edcc000; logTblLookup[i++] = 0x37b12d26; logTblLookup[i++] = -0x3fa5e9f7; logTblLookup[i++] = 0x3ede0000; logTblLookup[i++] = 0x38f04587; logTblLookup[i++] = 0x3fa57eb5; logTblLookup[i++] = 0x3edf5000; logTblLookup[i++] = 0x38a6ced4; logTblLookup[i++] = 0x3fa513fd; logTblLookup[i++] = 0x3ee0a000; logTblLookup[i++] = -0x381ff116; logTblLookup[i++] = 0x3fa4a9cf; logTblLookup[i++] = 0x3ee1e000; logTblLookup[i++] = 0x38ebd3e7; logTblLookup[i++] = 0x3fa44029; logTblLookup[i++] = 0x3ee33000; logTblLookup[i++] = 0x3874e3ff; logTblLookup[i++] = 0x3fa3d70a; logTblLookup[i++] = -0x3ee47000; logTblLookup[i++] = 0x38fbe3cd; logTblLookup[i++] = 0x3fa36e72; logTblLookup[i++] = 0x3ee5c000; logTblLookup[i++] = 0x3860744d; logTblLookup[i++] = 0x3fa3065e; logTblLookup[i++] = 0x3ee70000; logTblLookup[i++] = 0x38d785c3; logTblLookup[i++] = -0x3fa29ecf; logTblLookup[i++] = 0x3ee85000; logTblLookup[i++] = 0x37c75ce4; logTblLookup[i++] = 0x3fa237c3; logTblLookup[i++] = 0x3ee99000; logTblLookup[i++] = 0x387e7e01; logTblLookup[i++] = 0x3fa1d13a; logTblLookup[i++] = 0x3eead000; logTblLookup[i++] = -0x38bfcd71; logTblLookup[i++] = 0x3fa16b31; logTblLookup[i++] = 0x3eec1000; logTblLookup[i++] = 0x38f392c5; logTblLookup[i++] = 0x3fa105a9; logTblLookup[i++] = 0x3eed6000; logTblLookup[i++] = 0x3754f8b1; logTblLookup[i++] = 0x3fa0a0a1; logTblLookup[i++] = -0x3eeea000; logTblLookup[i++] = 0x37d40984; logTblLookup[i++] = 0x3fa03c17; logTblLookup[i++] = 0x3eefe000; logTblLookup[i++] = 0x38059907; logTblLookup[i++] = 0x3f9fd80a; logTblLookup[i++] = 0x3ef12000; logTblLookup[i++] = 0x38081a7c; logTblLookup[i++] = -0x3f9f747a; logTblLookup[i++] = 0x3ef26000; logTblLookup[i++] = 0x37e350d1; logTblLookup[i++] = 0x3f9f1166; logTblLookup[i++] = 0x3ef3a000; logTblLookup[i++] = 0x3784c3ad; logTblLookup[i++] = 0x3f9eaecd; logTblLookup[i++] = 0x3ef4d000; logTblLookup[i++] = -0x38fd32cc; logTblLookup[i++] = 0x3f9e4cad; logTblLookup[i++] = 0x3ef61000; logTblLookup[i++] = 0x38cce923; logTblLookup[i++] = 0x3f9deb07; logTblLookup[i++] = 0x3ef75000; logTblLookup[i++] = 0x38906320; logTblLookup[i++] = 0x3f9d89d9; logTblLookup[i++] = -0x3ef89000; logTblLookup[i++] = 0x380f5faf; logTblLookup[i++] = 0x3f9d2922; logTblLookup[i++] = 0x3ef9c000; logTblLookup[i++] = 0x38f2de41; logTblLookup[i++] = 0x3f9cc8e1; logTblLookup[i++] = 0x3efb0000; logTblLookup[i++] = 0x3891fd38; logTblLookup[i++] = -0x3f9c6917; logTblLookup[i++] = 0x3efc4000; logTblLookup[i++] = 0x37946dfd; logTblLookup[i++] = 0x3f9c09c1; logTblLookup[i++] = 0x3efd7000; logTblLookup[i++] = 0x38ac47bc; logTblLookup[i++] = 0x3f9baadf; logTblLookup[i++] = 0x3efeb000; logTblLookup[i++] = -0x379e41ec; logTblLookup[i++] = 0x3f9b4c70; logTblLookup[i++] = 0x3effe000; logTblLookup[i++] = 0x3897042c; logTblLookup[i++] = 0x3f9aee73; logTblLookup[i++] = 0x3f008000; logTblLookup[i++] = 0x397d5893; logTblLookup[i++] = 0x3f9a90e8; logTblLookup[i++] = -0x3f012000; logTblLookup[i++] = 0x392952d3; logTblLookup[i++] = 0x3f9a33cd; logTblLookup[i++] = 0x3f01c000; logTblLookup[i++] = 0x389eefce; logTblLookup[i++] = 0x3f99d723; logTblLookup[i++] = 0x3f025000; logTblLookup[i++] = 0x396fced5; logTblLookup[i++] = -0x3f997ae7; logTblLookup[i++] = 0x3f02f000; logTblLookup[i++] = 0x390a5e93; logTblLookup[i++] = 0x3f991f1a; logTblLookup[i++] = 0x3f039000; logTblLookup[i++] = 0x37f97073; logTblLookup[i++] = 0x3f98c3bb; logTblLookup[i++] = 0x3f042000; logTblLookup[i++] = -0x392e4426; logTblLookup[i++] = 0x3f9868c8; logTblLookup[i++] = 0x3f04c000; logTblLookup[i++] = 0x385e9eae; logTblLookup[i++] = 0x3f980e41; logTblLookup[i++] = 0x3f055000; logTblLookup[i++] = 0x393b5f67; logTblLookup[i++] = 0x3f97b426; logTblLookup[i++] = -0x3f05f000; logTblLookup[i++] = 0x3865c84a; logTblLookup[i++] = 0x3f975a75; logTblLookup[i++] = 0x3f068000; logTblLookup[i++] = 0x3931e65d; logTblLookup[i++] = 0x3f97012e; logTblLookup[i++] = 0x3f072000; logTblLookup[i++] = 0x38130ba4; logTblLookup[i++] = -0x3f96a850; logTblLookup[i++] = 0x3f07b000; logTblLookup[i++] = 0x39120e4e; logTblLookup[i++] = 0x3f964fda; logTblLookup[i++] = 0x3f084000; logTblLookup[i++] = 0x3979cf17; logTblLookup[i++] = 0x3f95f7cc; logTblLookup[i++] = 0x3f08e000; logTblLookup[i++] = -0x38b81788; logTblLookup[i++] = 0x3f95a025; logTblLookup[i++] = 0x3f097000; logTblLookup[i++] = 0x3938caca; logTblLookup[i++] = 0x3f9548e5; logTblLookup[i++] = 0x3f0a1000; logTblLookup[i++] = 0x37809491; logTblLookup[i++] = 0x3f94f209; logTblLookup[i++] = -0x3f0aa000; logTblLookup[i++] = 0x38c3d2f5; logTblLookup[i++] = 0x3f949b93; logTblLookup[i++] = 0x3f0b3000; logTblLookup[i++] = 0x392e55d6; logTblLookup[i++] = 0x3f944581; logTblLookup[i++] = 0x3f0bc000; logTblLookup[i++] = 0x39755dec; logTblLookup[i++] = -0x3f93efd2; logTblLookup[i++] = 0x3f0c6000; logTblLookup[i++] = 0x385c1fec; logTblLookup[i++] = 0x3f939a86; logTblLookup[i++] = 0x3f0cf000; logTblLookup[i++] = 0x38e6b468; logTblLookup[i++] = 0x3f93459c; logTblLookup[i++] = 0x3f0d8000; logTblLookup[i++] = -0x392a5abf; logTblLookup[i++] = 0x3f92f114; logTblLookup[i++] = 0x3f0e1000; logTblLookup[i++] = 0x395c0fb9; logTblLookup[i++] = 0x3f929cec; logTblLookup[i++] = 0x3f0eb000; logTblLookup[i++] = 0x3707f33c; logTblLookup[i++] = 0x3f924925; logTblLookup[i++] = -0x3f0f4000; logTblLookup[i++] = 0x383ebce1; logTblLookup[i++] = 0x3f91f5bd; logTblLookup[i++] = 0x3f0fd000; logTblLookup[i++] = 0x38a34b87; logTblLookup[i++] = 0x3f91a2b4; logTblLookup[i++] = 0x3f106000; logTblLookup[i++] = 0x38dcd193; logTblLookup[i++] = -0x3f915009; logTblLookup[i++] = 0x3f10f000; logTblLookup[i++] = 0x3905fe33; logTblLookup[i++] = 0x3f90fdbc; logTblLookup[i++] = 0x3f118000; logTblLookup[i++] = 0x39186bdf; logTblLookup[i++] = 0x3f90abcc; logTblLookup[i++] = 0x3f121000; logTblLookup[i++] = -0x3925b7a4; logTblLookup[i++] = 0x3f905a38; logTblLookup[i++] = 0x3f12a000; logTblLookup[i++] = 0x392de74c; logTblLookup[i++] = 0x3f900901; logTblLookup[i++] = 0x3f133000; logTblLookup[i++] = 0x3931009a; logTblLookup[i++] = 0x3f8fb824; logTblLookup[i++] = -0x3f13c000; logTblLookup[i++] = 0x392f0945; logTblLookup[i++] = 0x3f8f67a2; logTblLookup[i++] = 0x3f145000; logTblLookup[i++] = 0x392806fb; logTblLookup[i++] = 0x3f8f177a; logTblLookup[i++] = 0x3f14e000; logTblLookup[i++] = 0x391bff61; logTblLookup[i++] = -0x3f8ec7ab; logTblLookup[i++] = 0x3f157000; logTblLookup[i++] = 0x390af813; logTblLookup[i++] = 0x3f8e7835; logTblLookup[i++] = 0x3f160000; logTblLookup[i++] = 0x38e9ed45; logTblLookup[i++] = 0x3f8e2918; logTblLookup[i++] = 0x3f169000; logTblLookup[i++] = -0x38b4012f; logTblLookup[i++] = 0x3f8dda52; logTblLookup[i++] = 0x3f172000; logTblLookup[i++] = 0x38686dc8; logTblLookup[i++] = 0x3f8d8be3; logTblLookup[i++] = 0x3f17b000; logTblLookup[i++] = 0x37aa6542; logTblLookup[i++] = 0x3f8d3dcb; logTblLookup[i++] = -0x3f183000; logTblLookup[i++] = 0x396b99a8; logTblLookup[i++] = 0x3f8cf009; logTblLookup[i++] = 0x3f18c000; logTblLookup[i++] = 0x393d07d4; logTblLookup[i++] = 0x3f8ca29c; logTblLookup[i++] = 0x3f195000; logTblLookup[i++] = 0x39099c89; logTblLookup[i++] = -0x3f8c5584; logTblLookup[i++] = 0x3f19e000; logTblLookup[i++] = 0x38a2ba33; logTblLookup[i++] = 0x3f8c08c1; logTblLookup[i++] = 0x3f1a7000; logTblLookup[i++] = 0x37a27674; logTblLookup[i++] = 0x3f8bbc51; logTblLookup[i++] = 0x3f1af000; logTblLookup[i++] = -0x395276ea; logTblLookup[i++] = 0x3f8b7034; logTblLookup[i++] = 0x3f1b8000; logTblLookup[i++] = 0x390bdaa4; logTblLookup[i++] = 0x3f8b246b; logTblLookup[i++] = 0x3f1c1000; logTblLookup[i++] = 0x3880fe58; logTblLookup[i++] = 0x3f8ad8f3; logTblLookup[i++] = -0x3f1c9000; logTblLookup[i++] = 0x397069ab; logTblLookup[i++] = 0x3f8a8dcd; logTblLookup[i++] = 0x3f1d2000; logTblLookup[i++] = 0x391b9f3f; logTblLookup[i++] = 0x3f8a42f8; logTblLookup[i++] = 0x3f1db000; logTblLookup[i++] = 0x38844a00; logTblLookup[i++] = -0x3f89f874; logTblLookup[i++] = 0x3f1e3000; logTblLookup[i++] = 0x3963fffc; logTblLookup[i++] = 0x3f89ae41; logTblLookup[i++] = 0x3f1ec000; logTblLookup[i++] = 0x39013539; logTblLookup[i++] = 0x3f89645c; logTblLookup[i++] = 0x3f1f5000; logTblLookup[i++] = -0x37ce4dad; logTblLookup[i++] = 0x3f891ac7; logTblLookup[i++] = 0x3f1fd000; logTblLookup[i++] = 0x392dc269; logTblLookup[i++] = 0x3f88d181; logTblLookup[i++] = 0x3f206000; logTblLookup[i++] = 0x38749102; logTblLookup[i++] = 0x3f888889; logTblLookup[i++] = -0x3f20e000; logTblLookup[i++] = 0x3947f423; logTblLookup[i++] = 0x3f883fde; logTblLookup[i++] = 0x3f217000; logTblLookup[i++] = 0x389c6de0; logTblLookup[i++] = 0x3f87f781; logTblLookup[i++] = 0x3f21f000; logTblLookup[i++] = 0x394ff17d; logTblLookup[i++] = -0x3f87af70; logTblLookup[i++] = 0x3f228000; logTblLookup[i++] = 0x389a5134; logTblLookup[i++] = 0x3f8767ab; logTblLookup[i++] = 0x3f230000; logTblLookup[i++] = 0x3945e10e; logTblLookup[i++] = 0x3f872033; logTblLookup[i++] = 0x3f239000; logTblLookup[i++] = -0x38687e67; logTblLookup[i++] = 0x3f86d905; logTblLookup[i++] = 0x3f241000; logTblLookup[i++] = 0x3929e8f5; logTblLookup[i++] = 0x3f869223; logTblLookup[i++] = 0x3f24a000; logTblLookup[i++] = 0x37aa0e8c; logTblLookup[i++] = 0x3f864b8a; logTblLookup[i++] = -0x3f252000; logTblLookup[i++] = 0x38f85db0; logTblLookup[i++] = 0x3f86053c; logTblLookup[i++] = 0x3f25a000; logTblLookup[i++] = 0x395eb4ab; logTblLookup[i++] = 0x3f85bf37; logTblLookup[i++] = 0x3f263000; logTblLookup[i++] = 0x38735f9a; logTblLookup[i++] = -0x3f85797c; logTblLookup[i++] = 0x3f26b000; logTblLookup[i++] = 0x39169d1d; logTblLookup[i++] = 0x3f853408; logTblLookup[i++] = 0x3f273000; logTblLookup[i++] = 0x396c08dc; logTblLookup[i++] = 0x3f84eedd; logTblLookup[i++] = 0x3f27c000; logTblLookup[i++] = -0x38747ea0; logTblLookup[i++] = 0x3f84a9fa; logTblLookup[i++] = 0x3f284000; logTblLookup[i++] = 0x3909e601; logTblLookup[i++] = 0x3f84655e; logTblLookup[i++] = 0x3f28c000; logTblLookup[i++] = 0x3952605d; logTblLookup[i++] = 0x3f842108; logTblLookup[i++] = -0x3f295000; logTblLookup[i++] = 0x37b4996f; logTblLookup[i++] = 0x3f83dcf9; logTblLookup[i++] = 0x3f29d000; logTblLookup[i++] = 0x38ad05ba; logTblLookup[i++] = 0x3f839930; logTblLookup[i++] = 0x3f2a5000; logTblLookup[i++] = 0x391233cd; logTblLookup[i++] = -0x3f8355ad; logTblLookup[i++] = 0x3f2ad000; logTblLookup[i++] = 0x3949aa5a; logTblLookup[i++] = 0x3f83126f; logTblLookup[i++] = 0x3f2b5000; logTblLookup[i++] = 0x397ceada; logTblLookup[i++] = 0x3f82cf75; logTblLookup[i++] = 0x3f2be000; logTblLookup[i++] = -0x382fe66e; logTblLookup[i++] = 0x3f828cc0; logTblLookup[i++] = 0x3f2c6000; logTblLookup[i++] = 0x38adb5cd; logTblLookup[i++] = 0x3f824a4e; logTblLookup[i++] = 0x3f2ce000; logTblLookup[i++] = 0x38fb25fb; logTblLookup[i++] = 0x3f820821; logTblLookup[i++] = -0x3f2d6000; logTblLookup[i++] = 0x3920261b; logTblLookup[i++] = 0x3f81c636; logTblLookup[i++] = 0x3f2de000; logTblLookup[i++] = 0x393e9874; logTblLookup[i++] = 0x3f81848e; logTblLookup[i++] = 0x3f2e6000; logTblLookup[i++] = 0x3958ee36; logTblLookup[i++] = -0x3f814328; logTblLookup[i++] = 0x3f2ee000; logTblLookup[i++] = 0x396f2b8a; logTblLookup[i++] = 0x3f810204; logTblLookup[i++] = 0x3f2f7000; logTblLookup[i++] = 0x35aa4906; logTblLookup[i++] = 0x3f80c122; logTblLookup[i++] = 0x3f2ff000; logTblLookup[i++] = -0x3776d68c; logTblLookup[i++] = 0x3f808081; logTblLookup[i++] = 0x3f307000; logTblLookup[i++] = 0x37cbd11e; logTblLookup[i++] = 0x3f804020; logTblLookup[i++] = 0x3f30f000; logTblLookup[i++] = 0x37fbf692; logTblLookup[i++] = 0x3f800000; logTblLookup[i++] = -0x3f317000; logTblLookup[i++] = 0x3805fdf4; - - return logTblLookup; - } - - private static uint[] _logTblLookup = InitLog(); - - [MethodImpl(MaxOpt)] - private static unsafe float CoreFastLog(float x) - { - [MethodImpl(MaxOpt)] - static unsafe uint asuint(float x) - { -#if SSE - if (Sse.IsSupported) - return Vector128.CreateScalarUnsafe(x).AsUInt32().ToScalar(); // ToScalar "relies" on Sse (the fallback is garbage) - else -#endif - return *(uint*) &x; // this produces bad codegen on < net5 - } - - [MethodImpl(MaxOpt)] - static unsafe float asfloat(uint x) - { -#if SSE - if (Sse.IsSupported) - return Vector128.CreateScalarUnsafe(x).AsSingle().ToScalar(); // ToScalar "relies" on Sse (the fallback is garbage) - else -#endif - return *(float*) &x; // this produces bad codegen on < net5 - } - - uint ux = asuint(x); - - - if (ux - 0x00800000 < 0x7f800000 - 0x00800000) // inverted because likeliness - { - goto EndCheck; - } - else - { - /* x < 0x1p-126 or inf or nan. */ - if (ux * 2 == 0) /* log(0) = -inf */ - return float.NegativeInfinity; - if (ux == 0x7f800000) /* log(inf) = inf */ - return x; - if ((ux & 0x80000000) > 0 || ux * 2 >= 0xff000000) - return float.NaN; - - /* - * 'x' has to be denormal, Normalize it - * there is a possibility that only the last (23'rd) bit is set - * Hence multiply by 2^23 to bring to 1.xxxxx format. - */ - ux = asuint(x * 8388608); - ux -= 23 << 23; - } - - EndCheck: - const int EXPSHIFTBITS_SP32 = 23; // number of bits to shift left to get the exponent - // exponent bias, calculated as (2^(k-1)) - 1, were k = number of bits used to encode the exponent - const int EMAX_SP32 = 127; - const int MANTBITS_SP32 = 0x007fffff; // the bits the mantissa takes up - - int expo = (int) ((ux >> EXPSHIFTBITS_SP32) - EMAX_SP32); - float f_expo = (float) expo; - - const uint NEAR_ONE_LO = 0b111111011100000000000000000000; // BitConverter.SingleToInt32Bits(1 - 1 * 0.0625f); - const uint NEAR_ONE_HI = 0b111111110101010000000000000000; // BitConverter.SingleToInt32Bits(1 + 1.0625f * 0.0625f); - - // Values not very close to 1, !(e^(-1/16) <= x <= e^(1/16) - if (ux - NEAR_ONE_LO >= NEAR_ONE_HI - NEAR_ONE_LO) - { - /* - * Here onwards, 'x' is neither -ve, nor close to 1 - */ - uint mant, mant1, idx; - float y, f, finv, r, r2, q, w; - - const int MASK_MANT_ALL7 = 0b_1111111_10000000_00000000; - // const int MASK_MANT8 = 0x00008000; - mant = ux & MANTBITS_SP32; - mant1 = ux & MASK_MANT_ALL7; - /*This step is needed for more accuracy */ - /* mant1 += ((ux & MASK_MANT8) << 1); */ - - const int LOGF_N = 8; - idx = mant1 >> (EXPSHIFTBITS_SP32 - LOGF_N); - - const int HALFEXPBITS_SP32 = 0b_111111_00000000_00000000_00000000; - y = asfloat(mant | HALFEXPBITS_SP32); - f = asfloat(mant1 | HALFEXPBITS_SP32); - - float f_128_head; - float f_128_tail; -#if POH - var tbl = ((uint*)Unsafe.AsPointer(ref _logTblLookup[0])) + (idx * 3); - finv = asfloat(tbl[0]); - f_128_head = asfloat(tbl[1]); - f_128_tail = asfloat(tbl[2]); -#else - fixed (uint* tbl = _logTblLookup) - { - var p = tbl + (idx * 3); - finv = asfloat(p[0]); - f_128_head = asfloat(p[1]); - f_128_tail = asfloat(p[2]); - } -#endif - - r = (f - y) * finv; - const float C1 = .5f; - const float C2 = 3.333333432674407958984375E-1f; // 1/3 - - r2 = r * r; /* r^2 */ - q = r + (r2 * (C1 + r * C2)); - - const float LOG2_TAIL = 1.18725025653839111328f * 0.00000762939f; - q = (f_expo * LOG2_TAIL) - q; - - const float LOG2_HEAD = 1.3862762451171875f * 0.5f; - w = (LOG2_HEAD * f_expo) + f_128_head; - - q = f_128_tail + q + w; - - return q; - - } - else - { - [MethodImpl(MaxOpt)] - static float InlineLog1Pf(float x) - { - float r, r2, w; - - r = x - 1.0f; - - w = r / (2.0f + r); - - float correction = w * r; - - w += w; - - float w2 = w * w; - - const float A1 = 8.33333333333317923934e-02f; - const float A2 = 1.25000000037717509602e-02f; - - r2 = (w * w2 * (A1 + A2 * w2)) - correction; - - float f = r2 + r; - - return f; - } - - return InlineLog1Pf(x); - } - } - } -} \ No newline at end of file diff --git a/sources/Maths/Maths/Scalar.MathFPort.cs b/sources/Maths/Maths/Scalar.MathFPort.cs index f42d9d3897..81c9ceec68 100644 --- a/sources/Maths/Maths/Scalar.MathFPort.cs +++ b/sources/Maths/Maths/Scalar.MathFPort.cs @@ -43,31 +43,54 @@ public static partial class Scalar /// The type of /// The absolute of the given value [MethodImpl(MaxOpt)] - public static unsafe T Abs(T x) where T : unmanaged + public static unsafe T Abs(T x) + where T : unmanaged { if (typeof(T) == typeof(Half)) { #if NET5_0 && INTRINSICS if (Sse2.IsSupported) { - return (T)(object)(Half)Sse.And(Vector128.CreateScalarUnsafe((float) (Half) (object) x), Vector128.Create(-0.0f)).ToScalar(); - } + return (T) + (object) + (Half) + Sse.And( + Vector128.CreateScalarUnsafe((float)(Half)(object)x), + Vector128.Create(-0.0f) + ) + .ToScalar(); + } else if (AdvSimd.IsSupported) { - return (T)(object)(Half)AdvSimd.And(Vector128.CreateScalarUnsafe((float) (Half) (object) x), Vector128.Create(-0.0f)).ToScalar(); + return (T) + (object) + (Half) + AdvSimd + .And( + Vector128.CreateScalarUnsafe((float)(Half)(object)x), + Vector128.Create(-0.0f) + ) + .ToScalar(); } else #elif NETCOREAPP3_1 && INTRINSICS - if (Sse.IsSupported) - { - return (T)(object)(Half)Sse.And(Vector128.CreateScalarUnsafe((float) (Half) (object) x), Vector128.CreateScalarUnsafe(-0.0f)).ToScalar(); - } - else + if (Sse.IsSupported) + { + return (T) + (object) + (Half) + Sse.And( + Vector128.CreateScalarUnsafe((float)(Half)(object)x), + Vector128.CreateScalarUnsafe(-0.0f) + ) + .ToScalar(); + } + else #endif { - var v = *(ushort*) &x; + var v = *(ushort*)&x; v &= 0x7FFF; - return *(T*) &v; + return *(T*)&v; } } @@ -81,24 +104,45 @@ static T Float(T x) #if NET5_0 && INTRINSICS if (Sse.IsSupported) { - return (T)(object)(float)Sse.And(Vector128.CreateScalarUnsafe((float)(object)x), Vector128.Create((uint)0x7FFF_FFFF).AsSingle()).ToScalar(); + return (T) + (object) + (float) + Sse.And( + Vector128.CreateScalarUnsafe((float)(object)x), + Vector128.Create((uint)0x7FFF_FFFF).AsSingle() + ) + .ToScalar(); } else if (AdvSimd.IsSupported) { - return (T) (object) (float)AdvSimd.AbsScalar(Vector64.CreateScalarUnsafe((float) (object) x)).ToScalar(); + return (T) + (object) + (float) + AdvSimd + .AbsScalar(Vector64.CreateScalarUnsafe((float)(object)x)) + .ToScalar(); } else #elif NETCOREAPP3_1 && INTRINSICS if (Sse.IsSupported) { - return (T)(object)(float)Sse.And(Vector128.CreateScalarUnsafe((float)(object)x), Vector128.CreateScalarUnsafe((uint)0x7FFF_FFFF).AsSingle()).ToScalar(); + return (T) + (object) + (float) + Sse.And( + Vector128.CreateScalarUnsafe((float)(object)x), + Vector128 + .CreateScalarUnsafe((uint)0x7FFF_FFFF) + .AsSingle() + ) + .ToScalar(); } else #endif { - var v = *(uint*) &x; + var v = *(uint*)&x; v &= 0x7FFF_FFFF; - return *(T*) &v; + return *(T*)&v; } } @@ -113,24 +157,45 @@ static T Double(T x) #if NET5_0 && INTRINSICS if (Sse2.IsSupported) { - return (T)(object)(double)Sse2.And(Vector128.CreateScalarUnsafe((double)(object)x), Vector128.Create((ulong)0x7FFF_FFFF_FFFF_FFF).AsDouble()).ToScalar(); + return (T) + (object) + (double) + Sse2.And( + Vector128.CreateScalarUnsafe((double)(object)x), + Vector128.Create((ulong)0x7FFF_FFFF_FFFF_FFF).AsDouble() + ) + .ToScalar(); } else if (AdvSimd.IsSupported) { - return (T) (object) (double)AdvSimd.AbsScalar(Vector64.CreateScalar((double) (object) x)).ToScalar(); + return (T) + (object) + (double) + AdvSimd + .AbsScalar(Vector64.CreateScalar((double)(object)x)) + .ToScalar(); } else #elif NETCOREAPP3_1 && INTRINSICS if (Sse2.IsSupported) { - return (T)(object)(double)Sse2.And(Vector128.CreateScalarUnsafe((double)(object)x), Vector128.CreateScalarUnsafe((ulong)0x7FFF_FFFF_FFFF_FFF).AsDouble()).ToScalar(); + return (T) + (object) + (double) + Sse2.And( + Vector128.CreateScalarUnsafe((double)(object)x), + Vector128 + .CreateScalarUnsafe((ulong)0x7FFF_FFFF_FFFF_FFF) + .AsDouble() + ) + .ToScalar(); } else #endif { - var v = *(ulong*) &x; + var v = *(ulong*)&x; v &= 0x7FFF_FFFF_FFFF_FFFF; - return *(T*) &v; + return *(T*)&v; } } @@ -145,18 +210,24 @@ static T SByte(T x) #if SSE if (Ssse3.IsSupported) { - return (T)(object)(sbyte)Ssse3.Abs(Vector128.CreateScalar((sbyte) (object) x)).ToScalar(); + return (T) + (object) + (sbyte) + Ssse3.Abs(Vector128.CreateScalar((sbyte)(object)x)).ToScalar(); } #endif #if AdvSIMD if (AdvSimd.IsSupported) { - return (T) (object) (sbyte)AdvSimd.Abs(Vector64.CreateScalar((sbyte) (object) x)).ToScalar(); + return (T) + (object) + (sbyte) + AdvSimd.Abs(Vector64.CreateScalar((sbyte)(object)x)).ToScalar(); } #endif - var px = (sbyte) (object) x; - sbyte mask = (sbyte) (px >> (sizeof(sbyte) - 1)); - return (T) (object) (sbyte) ((px + mask) ^ mask); + var px = (sbyte)(object)x; + sbyte mask = (sbyte)(px >> (sizeof(sbyte) - 1)); + return (T)(object)(sbyte)((px + mask) ^ mask); } return Byte(x); @@ -181,18 +252,22 @@ static T Int(T x) #if SSE if (Ssse3.IsSupported) { - return (T)(object)(int)Ssse3.Abs(Vector128.CreateScalar((int) (object) x)).ToScalar(); + return (T) + (object) + (int)Ssse3.Abs(Vector128.CreateScalar((int)(object)x)).ToScalar(); } #endif #if AdvSIMD if (AdvSimd.IsSupported) { - return (T) (object)(int) AdvSimd.Abs(Vector64.CreateScalar((int) (object) x)).ToScalar(); + return (T) + (object) + (int)AdvSimd.Abs(Vector64.CreateScalar((int)(object)x)).ToScalar(); } #endif - var px = (int) (object) x; - int mask = (int) (px >> (sizeof(int) - 1)); - return (T) (object) (int) ((px + mask) ^ mask); + var px = (int)(object)x; + int mask = (int)(px >> (sizeof(int) - 1)); + return (T)(object)(int)((px + mask) ^ mask); } return UInt(x); @@ -214,9 +289,9 @@ static T Long(T x) { if (typeof(T) == typeof(long)) { - var px = (long) (object) x; - long mask = (long) (px >> (sizeof(long) - 1)); - return (T) (object) (long) ((px + mask) ^ mask); + var px = (long)(object)x; + long mask = (long)(px >> (sizeof(long) - 1)); + return (T)(object)(long)((px + mask) ^ mask); } return ULong(x); @@ -241,18 +316,24 @@ static T Short(T x) #if SSE if (Ssse3.IsSupported) { - return (T)(object)(short)Ssse3.Abs(Vector128.CreateScalar((short) (object) x)).ToScalar(); + return (T) + (object) + (short) + Ssse3.Abs(Vector128.CreateScalar((short)(object)x)).ToScalar(); } #endif #if AdvSIMD if (AdvSimd.IsSupported) { - return (T) (object)(short)AdvSimd.Abs(Vector64.CreateScalar((short) (object) x)).ToScalar(); + return (T) + (object) + (short) + AdvSimd.Abs(Vector64.CreateScalar((short)(object)x)).ToScalar(); } #endif - var px = (short) (object) x; - short mask = (short) (px >> (sizeof(short) - 1)); - return (T) (object) (short) ((px + mask) ^ mask); + var px = (short)(object)x; + short mask = (short)(px >> (sizeof(short) - 1)); + return (T)(object)(short)((px + mask) ^ mask); } return UShort(x); @@ -273,8 +354,9 @@ static T UShort(T x) static T Complex(T x) { if (typeof(T) == typeof(Complex)) - return (T)(object) new Complex(System.Numerics.Complex.Abs((Complex)(object)x), 0); - + return (T) + (object)new Complex(System.Numerics.Complex.Abs((Complex)(object)x), 0); + return Decimal(x); } @@ -283,7 +365,7 @@ static T Decimal(T x) { if (typeof(T) == typeof(decimal)) { - return (T) (object) Math.Abs((decimal) (object) x); + return (T)(object)Math.Abs((decimal)(object)x); } ThrowUnsupportedType(); @@ -304,14 +386,15 @@ static T Decimal(T x) /// NaN if x < -1 or x > 1 or x equals NaN. /// [MethodImpl(MaxOpt)] - public static T Acos(T x) where T : notnull + public static T Acos(T x) + where T : notnull { if (typeof(T) == typeof(Half)) { #if !MATHF - return (T) (object) (Half) (float) Math.Acos((float) (Half) (object) x); // KIPLING + return (T)(object)(Half)(float)Math.Acos((float)(Half)(object)x); // KIPLING #else - return (T) (object) (Half) MathF.Abs((float) (Half) (object) x); + return (T)(object)(Half)MathF.Abs((float)(Half)(object)x); #endif } @@ -323,9 +406,9 @@ static T Float(T x) if (typeof(T) == typeof(float)) { #if !MATHF - return (T) (object) (float) Math.Acos((float) (object) x); // KIPLING + return (T)(object)(float)Math.Acos((float)(object)x); // KIPLING #else - return (T) (object) MathF.Acos((float) (object) x); + return (T)(object)MathF.Acos((float)(object)x); #endif } @@ -337,7 +420,7 @@ static T Double(T x) { if (typeof(T) == typeof(double)) { - return (T) (object) Math.Acos((double) (object) x); + return (T)(object)Math.Acos((double)(object)x); } return SByte(x); @@ -348,7 +431,7 @@ static T SByte(T x) { if (typeof(T) == typeof(sbyte)) { - return (T) (object) (sbyte) Math.Acos((sbyte) (object) x); // KIPLING + return (T)(object)(sbyte)Math.Acos((sbyte)(object)x); // KIPLING } return Byte(x); @@ -359,7 +442,7 @@ static T Byte(T x) { if (typeof(T) == typeof(byte)) { - return (T) (object) (byte) Math.Acos((byte) (object) x); // KIPLING + return (T)(object)(byte)Math.Acos((byte)(object)x); // KIPLING } return Int(x); @@ -370,7 +453,7 @@ static T Int(T x) { if (typeof(T) == typeof(int)) { - return (T) (object) (int) Math.Acos((int) (object) x); // KIPLING + return (T)(object)(int)Math.Acos((int)(object)x); // KIPLING } return UInt(x); @@ -381,7 +464,7 @@ static T UInt(T x) { if (typeof(T) == typeof(uint)) { - return (T) (object) (uint) Math.Acos((uint) (object) x); // KIPLING + return (T)(object)(uint)Math.Acos((uint)(object)x); // KIPLING } return Long(x); @@ -392,7 +475,7 @@ static T Long(T x) { if (typeof(T) == typeof(long)) { - return (T) (object) (long) Math.Acos((long) (object) x); // KIPLING + return (T)(object)(long)Math.Acos((long)(object)x); // KIPLING } return ULong(x); @@ -403,7 +486,7 @@ static T ULong(T x) { if (typeof(T) == typeof(ulong)) { - return (T) (object) (ulong) Math.Acos((ulong) (object) x); // KIPLING + return (T)(object)(ulong)Math.Acos((ulong)(object)x); // KIPLING } return Short(x); @@ -414,7 +497,7 @@ static T Short(T x) { if (typeof(T) == typeof(short)) { - return (T) (object) (short) Math.Acos((short) (object) x); // KIPLING + return (T)(object)(short)Math.Acos((short)(object)x); // KIPLING } return UShort(x); @@ -425,7 +508,7 @@ static T UShort(T x) { if (typeof(T) == typeof(ushort)) { - return (T) (object) (ushort) Math.Acos((ushort) (object) x); // KIPLING + return (T)(object)(ushort)Math.Acos((ushort)(object)x); // KIPLING } return Complex(x); @@ -436,7 +519,7 @@ static T Complex(T x) { if (typeof(T) == typeof(Complex)) { - return (T) (object) (Complex) System.Numerics.Complex.Acos((Complex) (object) x); + return (T)(object)(Complex)System.Numerics.Complex.Acos((Complex)(object)x); } return Decimal(x); @@ -463,17 +546,18 @@ static T Decimal(T x) /// The type of . /// /// An angle, θ, measured in radians, such that 0 ≤ θ ≤ ∞. - /// + /// /// -or- - /// + /// /// NaN if x < 1 or x equals NaN. /// [MethodImpl(MaxOpt)] - public static T Acosh(T x) where T : notnull + public static T Acosh(T x) + where T : notnull { if (typeof(T) == typeof(Half)) { - return (T) (object) (Half) (float) CoreAcosh((float) (Half) (object) x); + return (T)(object)(Half)(float)CoreAcosh((float)(Half)(object)x); } return Float(x); @@ -483,7 +567,7 @@ static T Float(T x) { if (typeof(T) == typeof(float)) { - return (T) (object) CoreAcosh((float) (object) x); + return (T)(object)CoreAcosh((float)(object)x); } return Double(x); @@ -494,7 +578,7 @@ static T Double(T x) { if (typeof(T) == typeof(double)) { - return (T) (object) CoreAcosh((double) (object) x); + return (T)(object)CoreAcosh((double)(object)x); } return SByte(x); @@ -505,7 +589,7 @@ static T SByte(T x) { if (typeof(T) == typeof(sbyte)) { - return (T) (object) CoreAcosh((sbyte) (object) x); + return (T)(object)CoreAcosh((sbyte)(object)x); } return Byte(x); @@ -516,7 +600,7 @@ static T Byte(T x) { if (typeof(T) == typeof(byte)) { - return (T) (object) (byte) CoreAcosh((byte) (object) x); + return (T)(object)(byte)CoreAcosh((byte)(object)x); } return Int(x); @@ -527,7 +611,7 @@ static T Int(T x) { if (typeof(T) == typeof(int)) { - return (T) (object) CoreAcosh((int) (object) x); + return (T)(object)CoreAcosh((int)(object)x); } return UInt(x); @@ -538,7 +622,7 @@ static T UInt(T x) { if (typeof(T) == typeof(uint)) { - return (T) (object) (byte) CoreAcosh((byte) (object) x); + return (T)(object)(byte)CoreAcosh((byte)(object)x); } return Long(x); @@ -549,7 +633,7 @@ static T Long(T x) { if (typeof(T) == typeof(long)) { - return (T) (object) CoreAcosh((long) (object) x); + return (T)(object)CoreAcosh((long)(object)x); } return ULong(x); @@ -560,7 +644,7 @@ static T ULong(T x) { if (typeof(T) == typeof(ulong)) { - return (T) (object) CoreAcosh((ulong) (object) x); + return (T)(object)CoreAcosh((ulong)(object)x); } return Short(x); @@ -571,7 +655,7 @@ static T Short(T x) { if (typeof(T) == typeof(short)) { - return (T) (object) CoreAcosh((short) (object) x); + return (T)(object)CoreAcosh((short)(object)x); } return UShort(x); @@ -582,12 +666,12 @@ static T UShort(T x) { if (typeof(T) == typeof(ushort)) { - return (T) (object) CoreAcosh((int) (object) x); + return (T)(object)CoreAcosh((int)(object)x); } return Decimal(x); } - + [MethodImpl(MaxOpt)] static T Decimal(T x) { @@ -608,20 +692,21 @@ static T Decimal(T x) /// A number representing a sine, where must be greater than or equal to -1, but less than or equal to 1. /// The type of /// An angle, θ, measured in radians, such that -π/2 ≤ θ ≤ π/2. - /// + /// /// -or- - /// + /// /// NaN if x < -1 or x > 1 or x equals NaN. /// [MethodImpl(MaxOpt)] - public static T Asin(T x) where T : notnull + public static T Asin(T x) + where T : notnull { if (typeof(T) == typeof(Half)) { #if !MATHF - return (T) (object) (Half) (float) Math.Asin((float) (Half) (object) x); + return (T)(object)(Half)(float)Math.Asin((float)(Half)(object)x); #else - return (T) (object) (Half) MathF.Abs((float) (Half) (object) x); + return (T)(object)(Half)MathF.Abs((float)(Half)(object)x); #endif } @@ -633,9 +718,9 @@ static T Float(T x) if (typeof(T) == typeof(float)) { #if !MATHF - return (T) (object) (float) Math.Asin((float) (object) x); + return (T)(object)(float)Math.Asin((float)(object)x); #else - return (T) (object) MathF.Asin((float) (object) x); + return (T)(object)MathF.Asin((float)(object)x); #endif } @@ -647,7 +732,7 @@ static T Double(T x) { if (typeof(T) == typeof(double)) { - return (T) (object) Math.Asin((double) (object) x); + return (T)(object)Math.Asin((double)(object)x); } return SByte(x); @@ -658,7 +743,7 @@ static T SByte(T x) { if (typeof(T) == typeof(sbyte)) { - return (T) (object) (sbyte) Math.Asin((sbyte) (object) x); + return (T)(object)(sbyte)Math.Asin((sbyte)(object)x); } return Byte(x); @@ -669,7 +754,7 @@ static T Byte(T x) { if (typeof(T) == typeof(byte)) { - return (T) (object) (byte) Math.Asin((byte) (object) x); + return (T)(object)(byte)Math.Asin((byte)(object)x); } return Int(x); @@ -680,7 +765,7 @@ static T Int(T x) { if (typeof(T) == typeof(int)) { - return (T) (object) (int) Math.Asin((int) (object) x); + return (T)(object)(int)Math.Asin((int)(object)x); } return UInt(x); @@ -691,7 +776,7 @@ static T UInt(T x) { if (typeof(T) == typeof(uint)) { - return (T) (object) (uint) Math.Asin((uint) (object) x); + return (T)(object)(uint)Math.Asin((uint)(object)x); } return Long(x); @@ -702,7 +787,7 @@ static T Long(T x) { if (typeof(T) == typeof(long)) { - return (T) (object) (long) Math.Asin((long) (object) x); + return (T)(object)(long)Math.Asin((long)(object)x); } return ULong(x); @@ -713,7 +798,7 @@ static T ULong(T x) { if (typeof(T) == typeof(ulong)) { - return (T) (object) (ulong) Math.Asin((ulong) (object) x); + return (T)(object)(ulong)Math.Asin((ulong)(object)x); } return Short(x); @@ -724,7 +809,7 @@ static T Short(T x) { if (typeof(T) == typeof(short)) { - return (T) (object) (short) Math.Asin((short) (object) x); + return (T)(object)(short)Math.Asin((short)(object)x); } return UShort(x); @@ -735,7 +820,7 @@ static T UShort(T x) { if (typeof(T) == typeof(ushort)) { - return (T) (object) (ushort) Math.Asin((ushort) (object) x); + return (T)(object)(ushort)Math.Asin((ushort)(object)x); } return Complex(x); @@ -746,7 +831,7 @@ static T Complex(T x) { if (typeof(T) == typeof(Complex)) { - return (T) (object) (Complex) System.Numerics.Complex.Asin((Complex) (object) x); + return (T)(object)(Complex)System.Numerics.Complex.Asin((Complex)(object)x); } return Decimal(x); @@ -773,11 +858,12 @@ static T Decimal(T x) /// /// [MethodImpl(MaxOpt)] - public static T Asinh(T x) where T : notnull + public static T Asinh(T x) + where T : notnull { if (typeof(T) == typeof(Half)) { - return (T) (object) (Half) (float) CoreAsinh((float) (Half) (object) x); + return (T)(object)(Half)(float)CoreAsinh((float)(Half)(object)x); } return Float(x); @@ -787,7 +873,7 @@ static T Float(T x) { if (typeof(T) == typeof(float)) { - return (T) (object) CoreAsinh((float) (object) x); + return (T)(object)CoreAsinh((float)(object)x); } return Double(x); @@ -798,7 +884,7 @@ static T Double(T x) { if (typeof(T) == typeof(double)) { - return (T) (object) CoreAsinh((double) (object) x); + return (T)(object)CoreAsinh((double)(object)x); } return SByte(x); @@ -809,7 +895,7 @@ static T SByte(T x) { if (typeof(T) == typeof(sbyte)) { - return (T) (object) CoreAsinh((sbyte) (object) x); + return (T)(object)CoreAsinh((sbyte)(object)x); } return Byte(x); @@ -820,7 +906,7 @@ static T Byte(T x) { if (typeof(T) == typeof(byte)) { - return (T) (object) (byte) CoreAsinh((byte) (object) x); + return (T)(object)(byte)CoreAsinh((byte)(object)x); } return Int(x); @@ -831,7 +917,7 @@ static T Int(T x) { if (typeof(T) == typeof(int)) { - return (T) (object) CoreAsinh((int) (object) x); + return (T)(object)CoreAsinh((int)(object)x); } return UInt(x); @@ -842,7 +928,7 @@ static T UInt(T x) { if (typeof(T) == typeof(uint)) { - return (T) (object) CoreAsinh((uint) (object) x); + return (T)(object)CoreAsinh((uint)(object)x); } return Long(x); @@ -853,7 +939,7 @@ static T Long(T x) { if (typeof(T) == typeof(long)) { - return (T) (object) CoreAsinh((long) (object) x); + return (T)(object)CoreAsinh((long)(object)x); } return ULong(x); @@ -864,7 +950,7 @@ static T ULong(T x) { if (typeof(T) == typeof(ulong)) { - return (T) (object) CoreAsinh((ulong) (object) x); + return (T)(object)CoreAsinh((ulong)(object)x); } return Short(x); @@ -875,7 +961,7 @@ static T Short(T x) { if (typeof(T) == typeof(short)) { - return (T) (object) CoreAsinh((short) (object) x); + return (T)(object)CoreAsinh((short)(object)x); } return UShort(x); @@ -886,7 +972,7 @@ static T UShort(T x) { if (typeof(T) == typeof(ushort)) { - return (T) (object) CoreAsinh((ushort) (object) x); + return (T)(object)CoreAsinh((ushort)(object)x); } return Decimal(x); @@ -913,20 +999,21 @@ static T Decimal(T x) /// The type of . /// ///An angle, θ, measured in radians, such that -π/2 ≤ θ ≤ π/2. - /// + /// /// -or- - /// + /// /// NaN if equals , -π/2 rounded to double precision (-1.5707963267949) if equals , or π/2 rounded to double precision (1.5707963267949) if equals . /// [MethodImpl(MaxOpt)] - public static T Atan(T x) where T : notnull + public static T Atan(T x) + where T : notnull { if (typeof(T) == typeof(Half)) { #if !MATHF - return (T) (object) (Half) (float) Math.Atan((float) (Half) (object) x); + return (T)(object)(Half)(float)Math.Atan((float)(Half)(object)x); #else - return (T) (object) (Half) MathF.Abs((float) (Half) (object) x); + return (T)(object)(Half)MathF.Abs((float)(Half)(object)x); #endif } @@ -938,9 +1025,9 @@ static T Float(T x) if (typeof(T) == typeof(float)) { #if !MATHF - return (T) (object) (float) Math.Atan((float) (object) x); + return (T)(object)(float)Math.Atan((float)(object)x); #else - return (T) (object) MathF.Atan((float) (object) x); + return (T)(object)MathF.Atan((float)(object)x); #endif } @@ -952,7 +1039,7 @@ static T Double(T x) { if (typeof(T) == typeof(double)) { - return (T) (object) Math.Atan((double) (object) x); + return (T)(object)Math.Atan((double)(object)x); } return SByte(x); @@ -963,7 +1050,7 @@ static T SByte(T x) { if (typeof(T) == typeof(sbyte)) { - return (T) (object) (sbyte) Math.Atan((sbyte) (object) x); + return (T)(object)(sbyte)Math.Atan((sbyte)(object)x); } return Byte(x); @@ -974,7 +1061,7 @@ static T Byte(T x) { if (typeof(T) == typeof(byte)) { - return (T) (object) (byte) Math.Atan((byte) (object) x); + return (T)(object)(byte)Math.Atan((byte)(object)x); } return Int(x); @@ -985,7 +1072,7 @@ static T Int(T x) { if (typeof(T) == typeof(int)) { - return (T) (object) (int) Math.Atan((int) (object) x); + return (T)(object)(int)Math.Atan((int)(object)x); } return UInt(x); @@ -996,7 +1083,7 @@ static T UInt(T x) { if (typeof(T) == typeof(uint)) { - return (T) (object) (uint) Math.Atan((uint) (object) x); + return (T)(object)(uint)Math.Atan((uint)(object)x); } return Long(x); @@ -1007,7 +1094,7 @@ static T Long(T x) { if (typeof(T) == typeof(long)) { - return (T) (object) (long) Math.Atan((long) (object) x); + return (T)(object)(long)Math.Atan((long)(object)x); } return ULong(x); @@ -1018,7 +1105,7 @@ static T ULong(T x) { if (typeof(T) == typeof(ulong)) { - return (T) (object) (ulong) Math.Atan((ulong) (object) x); + return (T)(object)(ulong)Math.Atan((ulong)(object)x); } return Short(x); @@ -1029,7 +1116,7 @@ static T Short(T x) { if (typeof(T) == typeof(short)) { - return (T) (object) (short) Math.Atan((short) (object) x); + return (T)(object)(short)Math.Atan((short)(object)x); } return UShort(x); @@ -1040,7 +1127,7 @@ static T UShort(T x) { if (typeof(T) == typeof(ushort)) { - return (T) (object) (ushort) Math.Atan((ushort) (object) x); + return (T)(object)(ushort)Math.Atan((ushort)(object)x); } return Complex(x); @@ -1051,7 +1138,7 @@ static T Complex(T x) { if (typeof(T) == typeof(Complex)) { - return (T) (object) (Complex) System.Numerics.Complex.Atan((Complex) (object) x); + return (T)(object)(Complex)System.Numerics.Complex.Atan((Complex)(object)x); } return Decimal(x); @@ -1078,17 +1165,18 @@ static T Decimal(T x) /// The type of . /// /// An angle, θ, measured in radians, such that -∞ < θ < -1, or 1 < θ < ∞. - /// + /// /// -or- - /// + /// /// if x < -1 or x > 1 or x equals . /// [MethodImpl(MaxOpt)] - public static T Atanh(T x) where T : notnull + public static T Atanh(T x) + where T : notnull { if (typeof(T) == typeof(Half)) { - return (T) (object) (Half) Atanh((float) (Half) (object) x); + return (T)(object)(Half)Atanh((float)(Half)(object)x); } return Float(x); @@ -1098,7 +1186,7 @@ static T Float(T x) { if (typeof(T) == typeof(float)) { - return (T) (object) Atanh((float) (object) x); + return (T)(object)Atanh((float)(object)x); } return Double(x); @@ -1109,7 +1197,7 @@ static T Double(T x) { if (typeof(T) == typeof(double)) { - return (T) (object) CoreAtanh((double) (object) x); + return (T)(object)CoreAtanh((double)(object)x); } return Decimal(x); @@ -1132,7 +1220,7 @@ static T SByte(T x) { if (typeof(T) == typeof(sbyte)) { - return (T) (object) CoreAtanh((sbyte) (object) x); + return (T)(object)CoreAtanh((sbyte)(object)x); } return Byte(x); @@ -1143,7 +1231,7 @@ static T Byte(T x) { if (typeof(T) == typeof(byte)) { - return (T) (object) CoreAtanh((byte) (object) x); + return (T)(object)CoreAtanh((byte)(object)x); } return Short(x); @@ -1154,7 +1242,7 @@ static T Short(T x) { if (typeof(T) == typeof(short)) { - return (T) (object) CoreAtanh((short) (object) x); + return (T)(object)CoreAtanh((short)(object)x); } return UShort(x); @@ -1165,7 +1253,7 @@ static T UShort(T x) { if (typeof(T) == typeof(ushort)) { - return (T) (object) CoreAtanh((ushort) (object) x); + return (T)(object)CoreAtanh((ushort)(object)x); } return Int(x); @@ -1176,7 +1264,7 @@ static T Int(T x) { if (typeof(T) == typeof(int)) { - return (T) (object) CoreAtanh((int) (object) x); + return (T)(object)CoreAtanh((int)(object)x); } return UInt(x); @@ -1187,7 +1275,7 @@ static T UInt(T x) { if (typeof(T) == typeof(uint)) { - return (T) (object) CoreAtanh((uint) (object) x); + return (T)(object)CoreAtanh((uint)(object)x); } return Long(x); @@ -1198,7 +1286,7 @@ static T Long(T x) { if (typeof(T) == typeof(long)) { - return (T) (object) CoreAtanh((long) (object) x); + return (T)(object)CoreAtanh((long)(object)x); } return ULong(x); @@ -1209,7 +1297,7 @@ static T ULong(T x) { if (typeof(T) == typeof(ulong)) { - return (T) (object) CoreAtanh((ulong) (object) x); + return (T)(object)CoreAtanh((ulong)(object)x); } ThrowUnsupportedType(); @@ -1224,17 +1312,18 @@ static T ULong(T x) /// The type of /// /// The cube root of . - /// + /// /// -or- - /// + /// /// if is equals . /// [MethodImpl(MaxOpt)] - public static T Cbrt(T x) where T : notnull + public static T Cbrt(T x) + where T : notnull { if (typeof(T) == typeof(Half)) { - return (T) (object) (Half) CoreCbrt((float) (Half) (object) x); + return (T)(object)(Half)CoreCbrt((float)(Half)(object)x); } return Float(x); @@ -1244,7 +1333,7 @@ static T Float(T x) { if (typeof(T) == typeof(float)) { - return (T) (object) CoreCbrt((float) (object) x); + return (T)(object)CoreCbrt((float)(object)x); } return Double(x); @@ -1255,7 +1344,7 @@ static T Double(T x) { if (typeof(T) == typeof(double)) { - return (T) (object) CoreCbrt((double) (object) x); + return (T)(object)CoreCbrt((double)(object)x); } return Decimal(x); @@ -1278,7 +1367,7 @@ static T SByte(T x) { if (typeof(T) == typeof(sbyte)) { - return (T) (object) CoreCbrt((sbyte) (object) x); + return (T)(object)CoreCbrt((sbyte)(object)x); } return Byte(x); @@ -1289,7 +1378,7 @@ static T Byte(T x) { if (typeof(T) == typeof(byte)) { - return (T) (object) CoreCbrt((byte) (object) x); + return (T)(object)CoreCbrt((byte)(object)x); } return Short(x); @@ -1300,7 +1389,7 @@ static T Short(T x) { if (typeof(T) == typeof(short)) { - return (T) (object) CoreCbrt((short) (object) x); + return (T)(object)CoreCbrt((short)(object)x); } return UShort(x); @@ -1311,7 +1400,7 @@ static T UShort(T x) { if (typeof(T) == typeof(ushort)) { - return (T) (object) CoreCbrt((ushort) (object) x); + return (T)(object)CoreCbrt((ushort)(object)x); } return Int(x); @@ -1322,7 +1411,7 @@ static T Int(T x) { if (typeof(T) == typeof(int)) { - return (T) (object) CoreCbrt((int) (object) x); + return (T)(object)CoreCbrt((int)(object)x); } return UInt(x); @@ -1333,7 +1422,7 @@ static T UInt(T x) { if (typeof(T) == typeof(uint)) { - return (T) (object) CoreCbrt((uint) (object) x); + return (T)(object)CoreCbrt((uint)(object)x); } return Long(x); @@ -1344,7 +1433,7 @@ static T Long(T x) { if (typeof(T) == typeof(long)) { - return (T) (object) CoreCbrt((long) (object) x); + return (T)(object)CoreCbrt((long)(object)x); } return Complex(x); @@ -1355,7 +1444,8 @@ static T Complex(T x) { if (typeof(T) == typeof(Complex)) { - return (T) (object) (Complex) System.Numerics.Complex.Pow((Complex) (object) x, 1.0/3); // TODO: find a more efficient impl? + return (T) + (object)(Complex)System.Numerics.Complex.Pow((Complex)(object)x, 1.0 / 3); // TODO: find a more efficient impl? } return ULong(x); @@ -1366,7 +1456,7 @@ static T ULong(T x) { if (typeof(T) == typeof(ulong)) { - return (T) (object) CoreCbrt((ulong) (object) x); + return (T)(object)CoreCbrt((ulong)(object)x); } ThrowUnsupportedType(); @@ -1381,14 +1471,15 @@ static T ULong(T x) /// The type of . /// The smallest integral value that is greater than or equal to . If is equal to , , or , that value is returned. Note that this method returns instead of an integral type. [MethodImpl(MaxOpt)] - public static T Ceiling(T x) where T : notnull + public static T Ceiling(T x) + where T : notnull { if (typeof(T) == typeof(Half)) { #if !MATHF - return (T) (object) (Half) Math.Ceiling((float) (Half) (object) x); + return (T)(object)(Half)Math.Ceiling((float)(Half)(object)x); #else - return (T) (object) (Half) MathF.Ceiling((float) (Half) (object) x); + return (T)(object)(Half)MathF.Ceiling((float)(Half)(object)x); #endif } @@ -1400,9 +1491,9 @@ static T Float(T x) if (typeof(T) == typeof(float)) { #if !MATHF - return (T) (object) (float) Math.Ceiling((float) (object) x); + return (T)(object)(float)Math.Ceiling((float)(object)x); #else - return (T) (object) MathF.Ceiling((float) (object) x); + return (T)(object)MathF.Ceiling((float)(object)x); #endif } @@ -1414,7 +1505,7 @@ static T Double(T x) { if (typeof(T) == typeof(double)) { - return (T) (object) Math.Ceiling((double) (object) x); + return (T)(object)Math.Ceiling((double)(object)x); } return Decimal(x); @@ -1425,7 +1516,7 @@ static T Decimal(T x) { if (typeof(T) == typeof(decimal)) { - return (T) (object) Math.Ceiling((decimal) (object) x); + return (T)(object)Math.Ceiling((decimal)(object)x); } return SByte(x); @@ -1528,14 +1619,15 @@ static T ULong(T x) /// The type of . /// The cosine of . If is equal to , , or , this method returns . [MethodImpl(MaxOpt)] - public static T Cos(T x) where T : notnull + public static T Cos(T x) + where T : notnull { if (typeof(T) == typeof(Half)) { #if !MATHF - return (T) (object) (Half) Math.Cos((float) (Half) (object) x); + return (T)(object)(Half)Math.Cos((float)(Half)(object)x); #else - return (T) (object) (Half) MathF.Cos((float) (Half) (object) x); + return (T)(object)(Half)MathF.Cos((float)(Half)(object)x); #endif } @@ -1547,9 +1639,9 @@ static T Float(T x) if (typeof(T) == typeof(float)) { #if !MATHF - return (T) (object) (float) Math.Cos((float) (object) x); + return (T)(object)(float)Math.Cos((float)(object)x); #else - return (T) (object) MathF.Cos((float) (object) x); + return (T)(object)MathF.Cos((float)(object)x); #endif } @@ -1561,7 +1653,7 @@ static T Double(T x) { if (typeof(T) == typeof(double)) { - return (T) (object) Math.Cos((double) (object) x); + return (T)(object)Math.Cos((double)(object)x); } return Decimal(x); @@ -1584,7 +1676,7 @@ static T SByte(T x) { if (typeof(T) == typeof(sbyte)) { - return (T) (object) (sbyte) Math.Cos((sbyte) (object) x); + return (T)(object)(sbyte)Math.Cos((sbyte)(object)x); } return Byte(x); @@ -1595,7 +1687,7 @@ static T Byte(T x) { if (typeof(T) == typeof(byte)) { - return (T) (object) (byte) Math.Cos((byte) (object) x); + return (T)(object)(byte)Math.Cos((byte)(object)x); } return Short(x); @@ -1606,7 +1698,7 @@ static T Short(T x) { if (typeof(T) == typeof(short)) { - return (T) (object) (short) Math.Cos((short) (object) x); + return (T)(object)(short)Math.Cos((short)(object)x); } return UShort(x); @@ -1617,7 +1709,7 @@ static T UShort(T x) { if (typeof(T) == typeof(ushort)) { - return (T) (object) (ushort) Math.Cos((ushort) (object) x); + return (T)(object)(ushort)Math.Cos((ushort)(object)x); } return Int(x); @@ -1628,7 +1720,7 @@ static T Int(T x) { if (typeof(T) == typeof(int)) { - return (T) (object) (int) Math.Cos((int) (object) x); + return (T)(object)(int)Math.Cos((int)(object)x); } return UInt(x); @@ -1639,7 +1731,7 @@ static T UInt(T x) { if (typeof(T) == typeof(uint)) { - return (T) (object) (uint) Math.Cos((uint) (object) x); + return (T)(object)(uint)Math.Cos((uint)(object)x); } return Long(x); @@ -1650,7 +1742,7 @@ static T Long(T x) { if (typeof(T) == typeof(long)) { - return (T) (object) (long) Math.Cos((long) (object) x); + return (T)(object)(long)Math.Cos((long)(object)x); } return Complex(x); @@ -1661,7 +1753,7 @@ static T Complex(T x) { if (typeof(T) == typeof(Complex)) { - return (T) (object) (Complex) System.Numerics.Complex.Cos((Complex) (object) x); + return (T)(object)(Complex)System.Numerics.Complex.Cos((Complex)(object)x); } return ULong(x); @@ -1672,7 +1764,7 @@ static T ULong(T x) { if (typeof(T) == typeof(ulong)) { - return (T) (object) (ulong) Math.Cos((ulong) (object) x); + return (T)(object)(ulong)Math.Cos((ulong)(object)x); } ThrowUnsupportedType(); @@ -1687,14 +1779,15 @@ static T ULong(T x) /// The type of . /// The hyperbolic cosine of . If equal to or , is returned. If is equal to , is returned. [MethodImpl(MaxOpt)] - public static T Cosh(T x) where T : notnull + public static T Cosh(T x) + where T : notnull { if (typeof(T) == typeof(Half)) { #if !MATHF - return (T) (object) (Half) Math.Cosh((float) (Half) (object) x); + return (T)(object)(Half)Math.Cosh((float)(Half)(object)x); #else - return (T) (object) (Half) MathF.Cosh((float) (Half) (object) x); + return (T)(object)(Half)MathF.Cosh((float)(Half)(object)x); #endif } @@ -1706,9 +1799,9 @@ static T Float(T x) if (typeof(T) == typeof(float)) { #if !MATHF - return (T) (object) (float) Math.Cosh((float) (object) x); + return (T)(object)(float)Math.Cosh((float)(object)x); #else - return (T) (object) MathF.Cosh((float) (object) x); + return (T)(object)MathF.Cosh((float)(object)x); #endif } @@ -1720,7 +1813,7 @@ static T Double(T x) { if (typeof(T) == typeof(double)) { - return (T) (object) Math.Cosh((double) (object) x); + return (T)(object)Math.Cosh((double)(object)x); } return Decimal(x); @@ -1743,7 +1836,7 @@ static T SByte(T x) { if (typeof(T) == typeof(sbyte)) { - return (T) (object) (sbyte) Math.Cosh((sbyte) (object) x); + return (T)(object)(sbyte)Math.Cosh((sbyte)(object)x); } return Byte(x); @@ -1754,7 +1847,7 @@ static T Byte(T x) { if (typeof(T) == typeof(byte)) { - return (T) (object) (byte) Math.Cosh((byte) (object) x); + return (T)(object)(byte)Math.Cosh((byte)(object)x); } return Short(x); @@ -1765,7 +1858,7 @@ static T Short(T x) { if (typeof(T) == typeof(short)) { - return (T) (object) (short) Math.Cosh((short) (object) x); + return (T)(object)(short)Math.Cosh((short)(object)x); } return UShort(x); @@ -1776,7 +1869,7 @@ static T UShort(T x) { if (typeof(T) == typeof(ushort)) { - return (T) (object) (ushort) Math.Cosh((ushort) (object) x); + return (T)(object)(ushort)Math.Cosh((ushort)(object)x); } return Int(x); @@ -1787,7 +1880,7 @@ static T Int(T x) { if (typeof(T) == typeof(int)) { - return (T) (object) (int) Math.Cosh((int) (object) x); + return (T)(object)(int)Math.Cosh((int)(object)x); } return UInt(x); @@ -1798,7 +1891,7 @@ static T UInt(T x) { if (typeof(T) == typeof(uint)) { - return (T) (object) (uint) Math.Cosh((uint) (object) x); + return (T)(object)(uint)Math.Cosh((uint)(object)x); } return Long(x); @@ -1809,7 +1902,7 @@ static T Long(T x) { if (typeof(T) == typeof(long)) { - return (T) (object) (long) Math.Cosh((long) (object) x); + return (T)(object)(long)Math.Cosh((long)(object)x); } return Complex(x); @@ -1820,7 +1913,7 @@ static T Complex(T x) { if (typeof(T) == typeof(Complex)) { - return (T) (object) (Complex) System.Numerics.Complex.Cosh((Complex) (object) x); + return (T)(object)(Complex)System.Numerics.Complex.Cosh((Complex)(object)x); } return ULong(x); @@ -1831,7 +1924,7 @@ static T ULong(T x) { if (typeof(T) == typeof(ulong)) { - return (T) (object) (ulong) Math.Cosh((ulong) (object) x); + return (T)(object)(ulong)Math.Cosh((ulong)(object)x); } ThrowUnsupportedType(); @@ -1846,11 +1939,12 @@ static T ULong(T x) /// The type of . /// The number e raised to the power . If equals or , that value is returned. If equals , 0 is returned. [MethodImpl(MaxOpt)] - public static T Exp(T x) where T : notnull + public static T Exp(T x) + where T : notnull { if (typeof(T) == typeof(Half)) { - return (T) (object) (Half) CoreFastExp((float) (Half) (object) x); + return (T)(object)(Half)CoreFastExp((float)(Half)(object)x); } return Float(x); @@ -1860,7 +1954,7 @@ static T Float(T x) { if (typeof(T) == typeof(float)) { - return (T) (object) CoreFastExp((float) (object) x); + return (T)(object)CoreFastExp((float)(object)x); } return Double(x); @@ -1871,7 +1965,7 @@ static T Double(T x) { if (typeof(T) == typeof(double)) { - return (T) (object) Math.Exp((double) (object) x); + return (T)(object)Math.Exp((double)(object)x); } return Decimal(x); @@ -1894,7 +1988,7 @@ static T SByte(T x) { if (typeof(T) == typeof(sbyte)) { - return (T) (object) (sbyte) Math.Exp((sbyte) (object) x); + return (T)(object)(sbyte)Math.Exp((sbyte)(object)x); } return Byte(x); @@ -1905,7 +1999,7 @@ static T Byte(T x) { if (typeof(T) == typeof(byte)) { - return (T) (object) (byte) Math.Exp((byte) (object) x); + return (T)(object)(byte)Math.Exp((byte)(object)x); } return Short(x); @@ -1916,7 +2010,7 @@ static T Short(T x) { if (typeof(T) == typeof(short)) { - return (T) (object) (short) Math.Exp((short) (object) x); + return (T)(object)(short)Math.Exp((short)(object)x); } return UShort(x); @@ -1927,7 +2021,7 @@ static T UShort(T x) { if (typeof(T) == typeof(ushort)) { - return (T) (object) (ushort) Math.Exp((ushort) (object) x); + return (T)(object)(ushort)Math.Exp((ushort)(object)x); } return Int(x); @@ -1938,7 +2032,7 @@ static T Int(T x) { if (typeof(T) == typeof(int)) { - return (T) (object) (int) Math.Exp((int) (object) x); + return (T)(object)(int)Math.Exp((int)(object)x); } return UInt(x); @@ -1949,7 +2043,7 @@ static T UInt(T x) { if (typeof(T) == typeof(uint)) { - return (T) (object) (uint) Math.Exp((uint) (object) x); + return (T)(object)(uint)Math.Exp((uint)(object)x); } return Long(x); @@ -1960,7 +2054,7 @@ static T Long(T x) { if (typeof(T) == typeof(long)) { - return (T) (object) (long) Math.Exp((long) (object) x); + return (T)(object)(long)Math.Exp((long)(object)x); } return Complex(x); @@ -1971,7 +2065,7 @@ static T Complex(T x) { if (typeof(T) == typeof(Complex)) { - return (T) (object) (Complex) System.Numerics.Complex.Exp((Complex) (object) x); + return (T)(object)(Complex)System.Numerics.Complex.Exp((Complex)(object)x); } return ULong(x); @@ -1982,7 +2076,7 @@ static T ULong(T x) { if (typeof(T) == typeof(ulong)) { - return (T) (object) (ulong) Math.Exp((ulong) (object) x); + return (T)(object)(ulong)Math.Exp((ulong)(object)x); } ThrowUnsupportedType(); @@ -1997,26 +2091,41 @@ static T ULong(T x) /// The type of . /// The largest integral value less than or equal to . If is equal to , , or , that value is returned. [MethodImpl(MaxOpt)] - public static T Floor(T x) where T : notnull + public static T Floor(T x) + where T : notnull { if (typeof(T) == typeof(Half)) { #if SSE if (Sse41.IsSupported) { - return (T)(object)(Half)Sse41.FloorScalar(Vector128.CreateScalarUnsafe((float) (Half) (object) x)).ToScalar(); + return (T) + (object) + (Half) + Sse41 + .FloorScalar( + Vector128.CreateScalarUnsafe((float)(Half)(object)x) + ) + .ToScalar(); } #endif #if AdvSIMD if (AdvSimd.IsSupported) { - return (T)(object)(Half)AdvSimd.FloorScalar(Vector64.CreateScalarUnsafe((float) (Half) (object) x)).ToScalar(); + return (T) + (object) + (Half) + AdvSimd + .FloorScalar( + Vector64.CreateScalarUnsafe((float)(Half)(object)x) + ) + .ToScalar(); } -#endif +#endif #if !MATHF - return (T) (object) (Half) Math.Floor((float) (Half) (object) x); + return (T)(object)(Half)Math.Floor((float)(Half)(object)x); #else - return (T) (object) (Half) MathF.Floor((float) (Half) (object) x); + return (T)(object)(Half)MathF.Floor((float)(Half)(object)x); #endif } @@ -2030,19 +2139,27 @@ static T Float(T x) #if SSE if (Sse41.IsSupported) { - return (T)(object)Sse41.FloorScalar(Vector128.CreateScalarUnsafe((float) (object) x)).ToScalar(); + return (T) + (object) + Sse41 + .FloorScalar(Vector128.CreateScalarUnsafe((float)(object)x)) + .ToScalar(); } #endif #if AdvSIMD if (AdvSimd.IsSupported) { - return (T)(object)AdvSimd.FloorScalar(Vector64.CreateScalarUnsafe((float) (object) x)).ToScalar(); + return (T) + (object) + AdvSimd + .FloorScalar(Vector64.CreateScalarUnsafe((float)(object)x)) + .ToScalar(); } -#endif +#endif #if !MATHF - return (T) (object) (float) Math.Floor((float) (object) x); + return (T)(object)(float)Math.Floor((float)(object)x); #else - return (T) (object) MathF.Floor((float) (object) x); + return (T)(object)MathF.Floor((float)(object)x); #endif } @@ -2057,16 +2174,24 @@ static T Double(T x) #if SSE if (Sse41.IsSupported) { - return (T)(object)Sse41.FloorScalar(Vector128.CreateScalarUnsafe((double) (object) x)).ToScalar(); + return (T) + (object) + Sse41 + .FloorScalar(Vector128.CreateScalarUnsafe((double)(object)x)) + .ToScalar(); } #endif #if AdvSIMD if (AdvSimd.IsSupported) { - return (T)(object)AdvSimd.FloorScalar(Vector64.CreateScalar((double) (object) x)).ToScalar(); + return (T) + (object) + AdvSimd + .FloorScalar(Vector64.CreateScalar((double)(object)x)) + .ToScalar(); } #endif - return (T) (object) Math.Floor((double) (object) x); + return (T)(object)Math.Floor((double)(object)x); } return Decimal(x); @@ -2080,16 +2205,30 @@ static T Decimal(T x) #if SSE if (Sse41.IsSupported) { - return (T)(object)(decimal)Sse41.FloorScalar(Vector128.CreateScalarUnsafe((double)(decimal) (object) x)).ToScalar(); + return (T) + (object) + (decimal) + Sse41 + .FloorScalar( + Vector128.CreateScalarUnsafe((double)(decimal)(object)x) + ) + .ToScalar(); } #endif #if AdvSIMD if (AdvSimd.IsSupported) { - return (T)(object)(decimal)AdvSimd.FloorScalar(Vector64.CreateScalar((double)(decimal) (object) x)).ToScalar(); + return (T) + (object) + (decimal) + AdvSimd + .FloorScalar( + Vector64.CreateScalar((double)(decimal)(object)x) + ) + .ToScalar(); } -#endif - return (T) (object) Math.Floor((decimal) (object) x); +#endif + return (T)(object)Math.Floor((decimal)(object)x); } return SByte(x); @@ -2216,14 +2355,15 @@ static T ULong(T x) /// /// is equal to [MethodImpl(MaxOpt)] - public static int Sign(T x) where T : notnull + public static int Sign(T x) + where T : notnull { if (typeof(T) == typeof(Half)) { #if !MATHF - return Math.Sign((float) (Half) (object) x); + return Math.Sign((float)(Half)(object)x); #else - return MathF.Sign((float) (Half) (object) x); + return MathF.Sign((float)(Half)(object)x); #endif } @@ -2235,9 +2375,9 @@ static int Float(T x) if (typeof(T) == typeof(float)) { #if !MATHF - return Math.Sign((float) (object) x); + return Math.Sign((float)(object)x); #else - return MathF.Sign((float) (object) x); + return MathF.Sign((float)(object)x); #endif } @@ -2249,7 +2389,7 @@ static int Double(T x) { if (typeof(T) == typeof(double)) { - return Math.Sign((double) (object) x); + return Math.Sign((double)(object)x); } return Decimal(x); @@ -2260,7 +2400,7 @@ static int Decimal(T x) { if (typeof(T) == typeof(decimal)) { - return Math.Sign((decimal) (object) x); + return Math.Sign((decimal)(object)x); } return SByte(x); @@ -2271,7 +2411,7 @@ static int SByte(T x) { if (typeof(T) == typeof(sbyte)) { - return Math.Sign((sbyte) (object) x); + return Math.Sign((sbyte)(object)x); } return Byte(x); @@ -2282,7 +2422,7 @@ static int Byte(T x) { if (typeof(T) == typeof(byte)) { - return ((byte) (object) x) > 0 ? 1 : 0; + return ((byte)(object)x) > 0 ? 1 : 0; } return Short(x); @@ -2293,7 +2433,7 @@ static int Short(T x) { if (typeof(T) == typeof(short)) { - return Math.Sign((short) (object) x); + return Math.Sign((short)(object)x); } return UShort(x); @@ -2304,7 +2444,7 @@ static int UShort(T x) { if (typeof(T) == typeof(ushort)) { - return ((ushort) (object) x) > 0 ? 1 : 0; + return ((ushort)(object)x) > 0 ? 1 : 0; } return Int(x); @@ -2315,7 +2455,7 @@ static int Int(T x) { if (typeof(T) == typeof(int)) { - return Math.Sign((int) (object) x); + return Math.Sign((int)(object)x); } return UInt(x); @@ -2326,7 +2466,7 @@ static int UInt(T x) { if (typeof(T) == typeof(uint)) { - return ((uint) (object) x) > 0 ? 1 : 0; + return ((uint)(object)x) > 0 ? 1 : 0; } return Long(x); @@ -2337,7 +2477,7 @@ static int Long(T x) { if (typeof(T) == typeof(long)) { - return Math.Sign((long) (object) x); + return Math.Sign((long)(object)x); } return ULong(x); @@ -2348,7 +2488,7 @@ static int ULong(T x) { if (typeof(T) == typeof(ulong)) { - return ((ulong) (object) x) > 0 ? 1 : 0; + return ((ulong)(object)x) > 0 ? 1 : 0; } ThrowUnsupportedType(); @@ -2363,11 +2503,12 @@ static int ULong(T x) /// The type of . /// The sine of . If is equal to , , or , this method returns . [MethodImpl(MaxOpt)] - public static T Sin(T x) where T : notnull + public static T Sin(T x) + where T : notnull { if (typeof(T) == typeof(Half)) { - return (T) (object) (Half) (float) Sin_Ported((float) (Half) (object) x); + return (T)(object)(Half)(float)Sin_Ported((float)(Half)(object)x); } return Float(x); @@ -2377,7 +2518,7 @@ static T Float(T x) { if (typeof(T) == typeof(float)) { - return (T) (object) (float) Sin_Ported((float) (object) x); + return (T)(object)(float)Sin_Ported((float)(object)x); } return Double(x); @@ -2388,7 +2529,7 @@ static T Double(T x) { if (typeof(T) == typeof(double)) { - return (T) (object) (double) Math.Sin((double) (object) x); + return (T)(object)(double)Math.Sin((double)(object)x); } return Decimal(x); @@ -2411,7 +2552,7 @@ static T SByte(T x) { if (typeof(T) == typeof(sbyte)) { - return (T) (object) (sbyte) Math.Sin((sbyte) (object) x); + return (T)(object)(sbyte)Math.Sin((sbyte)(object)x); } return Byte(x); @@ -2422,7 +2563,7 @@ static T Byte(T x) { if (typeof(T) == typeof(byte)) { - return (T) (object) (byte) Math.Sin((byte) (object) x); + return (T)(object)(byte)Math.Sin((byte)(object)x); } return Short(x); @@ -2433,7 +2574,7 @@ static T Short(T x) { if (typeof(T) == typeof(short)) { - return (T) (object) (short) Math.Sin((short) (object) x); + return (T)(object)(short)Math.Sin((short)(object)x); } return UShort(x); @@ -2444,7 +2585,7 @@ static T UShort(T x) { if (typeof(T) == typeof(ushort)) { - return (T) (object) (ushort) Math.Sin((ushort) (object) x); + return (T)(object)(ushort)Math.Sin((ushort)(object)x); } return Int(x); @@ -2455,7 +2596,7 @@ static T Int(T x) { if (typeof(T) == typeof(int)) { - return (T) (object) (int) Math.Sin((int) (object) x); + return (T)(object)(int)Math.Sin((int)(object)x); } return UInt(x); @@ -2466,7 +2607,7 @@ static T UInt(T x) { if (typeof(T) == typeof(uint)) { - return (T) (object) (uint) Math.Sin((uint) (object) x); + return (T)(object)(uint)Math.Sin((uint)(object)x); } return Long(x); @@ -2477,7 +2618,7 @@ static T Long(T x) { if (typeof(T) == typeof(long)) { - return (T) (object) (long) Math.Sin((long) (object) x); + return (T)(object)(long)Math.Sin((long)(object)x); } return Complex(x); @@ -2488,7 +2629,7 @@ static T Complex(T x) { if (typeof(T) == typeof(Complex)) { - return (T) (object) (Complex) System.Numerics.Complex.Sin((Complex) (object) x); + return (T)(object)(Complex)System.Numerics.Complex.Sin((Complex)(object)x); } return ULong(x); @@ -2499,7 +2640,7 @@ static T ULong(T x) { if (typeof(T) == typeof(ulong)) { - return (T) (object) (ulong) Math.Sin((ulong) (object) x); + return (T)(object)(ulong)Math.Sin((ulong)(object)x); } ThrowUnsupportedType(); @@ -2514,14 +2655,15 @@ static T ULong(T x) /// Type of . /// The hyperbolic sine of . If is equal to , , or this method returns . [MethodImpl(MaxOpt)] - public static T Sinh(T x) where T : notnull + public static T Sinh(T x) + where T : notnull { if (typeof(T) == typeof(Half)) { #if !MATHF - return (T) (object) (Half) (float) Math.Sinh((float) (Half) (object) x); + return (T)(object)(Half)(float)Math.Sinh((float)(Half)(object)x); #else - return (T) (object) (Half) MathF.Sinh((float) (Half) (object) x); + return (T)(object)(Half)MathF.Sinh((float)(Half)(object)x); #endif } @@ -2533,9 +2675,9 @@ static T Float(T x) if (typeof(T) == typeof(float)) { #if !MATHF - return (T) (object) (float) Math.Sinh((float) (object) x); + return (T)(object)(float)Math.Sinh((float)(object)x); #else - return (T) (object) MathF.Sinh((float) (object) x); + return (T)(object)MathF.Sinh((float)(object)x); #endif } @@ -2547,7 +2689,7 @@ static T Double(T x) { if (typeof(T) == typeof(double)) { - return (T) (object) (double) Math.Sinh((double) (object) x); + return (T)(object)(double)Math.Sinh((double)(object)x); } return Decimal(x); @@ -2570,7 +2712,7 @@ static T SByte(T x) { if (typeof(T) == typeof(sbyte)) { - return (T) (object) (sbyte) Math.Sinh((sbyte) (object) x); + return (T)(object)(sbyte)Math.Sinh((sbyte)(object)x); } return Byte(x); @@ -2581,7 +2723,7 @@ static T Byte(T x) { if (typeof(T) == typeof(byte)) { - return (T) (object) (byte) Math.Sinh((byte) (object) x); + return (T)(object)(byte)Math.Sinh((byte)(object)x); } return Short(x); @@ -2592,7 +2734,7 @@ static T Short(T x) { if (typeof(T) == typeof(short)) { - return (T) (object) (short) Math.Sinh((short) (object) x); + return (T)(object)(short)Math.Sinh((short)(object)x); } return UShort(x); @@ -2603,7 +2745,7 @@ static T UShort(T x) { if (typeof(T) == typeof(ushort)) { - return (T) (object) (ushort) Math.Sinh((ushort) (object) x); + return (T)(object)(ushort)Math.Sinh((ushort)(object)x); } return Int(x); @@ -2614,7 +2756,7 @@ static T Int(T x) { if (typeof(T) == typeof(int)) { - return (T) (object) (int) Math.Sinh((int) (object) x); + return (T)(object)(int)Math.Sinh((int)(object)x); } return UInt(x); @@ -2625,7 +2767,7 @@ static T UInt(T x) { if (typeof(T) == typeof(uint)) { - return (T) (object) (uint) Math.Sinh((uint) (object) x); + return (T)(object)(uint)Math.Sinh((uint)(object)x); } return Long(x); @@ -2636,7 +2778,7 @@ static T Long(T x) { if (typeof(T) == typeof(long)) { - return (T) (object) (long) Math.Sinh((long) (object) x); + return (T)(object)(long)Math.Sinh((long)(object)x); } return Complex(x); @@ -2647,7 +2789,7 @@ static T Complex(T x) { if (typeof(T) == typeof(Complex)) { - return (T) (object) (Complex) System.Numerics.Complex.Sinh((Complex) (object) x); + return (T)(object)(Complex)System.Numerics.Complex.Sinh((Complex)(object)x); } return ULong(x); @@ -2658,7 +2800,7 @@ static T ULong(T x) { if (typeof(T) == typeof(ulong)) { - return (T) (object) (ulong) Math.Sinh((ulong) (object) x); + return (T)(object)(ulong)Math.Sinh((ulong)(object)x); } ThrowUnsupportedType(); @@ -2697,26 +2839,42 @@ static T ULong(T x) /// /// [MethodImpl(MaxOpt)] - public static T Sqrt(T x) where T : notnull + public static T Sqrt(T x) + where T : notnull { if (typeof(T) == typeof(Half)) { #if SSE if (Sse42.IsSupported) { - return (T)(object)(Half)(float)Sse.SqrtScalar(Vector128.CreateScalarUnsafe((float)(Half)(object)x)).ToScalar(); + return (T) + (object) + (Half) + (float) + Sse.SqrtScalar( + Vector128.CreateScalarUnsafe((float)(Half)(object)x) + ) + .ToScalar(); } #endif #if AdvSIMD if (AdvSimd.IsSupported) { - return (T)(object)(Half)(float)AdvSimd.SqrtScalar(Vector64.CreateScalarUnsafe((float)(Half)(object)x)).ToScalar(); + return (T) + (object) + (Half) + (float) + AdvSimd + .SqrtScalar( + Vector64.CreateScalarUnsafe((float)(Half)(object)x) + ) + .ToScalar(); } -#endif +#endif #if !MATHF - return (T) (object) (Half) (float) Math.Sqrt((float) (Half) (object) x); + return (T)(object)(Half)(float)Math.Sqrt((float)(Half)(object)x); #else - return (T) (object) (Half) MathF.Sqrt((float) (Half) (object) x); + return (T)(object)(Half)MathF.Sqrt((float)(Half)(object)x); #endif } @@ -2730,19 +2888,28 @@ static T Float(T x) #if SSE if (Sse.IsSupported) { - return (T)(object)(float)Sse.SqrtScalar(Vector128.CreateScalarUnsafe((float)(object)x)).ToScalar(); + return (T) + (object) + (float) + Sse.SqrtScalar(Vector128.CreateScalarUnsafe((float)(object)x)) + .ToScalar(); } #endif #if AdvSIMD if (AdvSimd.IsSupported) { - return (T)(object)(float)AdvSimd.SqrtScalar(Vector64.CreateScalarUnsafe((float)(object)x)).ToScalar(); + return (T) + (object) + (float) + AdvSimd + .SqrtScalar(Vector64.CreateScalarUnsafe((float)(object)x)) + .ToScalar(); } -#endif +#endif #if !MATHF - return (T) (object) (float) Math.Sqrt((float) (object) x); + return (T)(object)(float)Math.Sqrt((float)(object)x); #else - return (T) (object) MathF.Sqrt((float) (object) x); + return (T)(object)MathF.Sqrt((float)(object)x); #endif } @@ -2757,16 +2924,25 @@ static T Double(T x) #if SSE if (Sse2.IsSupported) { - return (T)(object)(double)Sse2.SqrtScalar(Vector128.CreateScalarUnsafe((double)(object)x)).ToScalar(); + return (T) + (object) + (double) + Sse2.SqrtScalar(Vector128.CreateScalarUnsafe((double)(object)x)) + .ToScalar(); } #endif #if AdvSIMD if (AdvSimd.IsSupported) { - return (T)(object)(double)AdvSimd.SqrtScalar(Vector64.CreateScalar((double)(object)x)).ToScalar(); + return (T) + (object) + (double) + AdvSimd + .SqrtScalar(Vector64.CreateScalar((double)(object)x)) + .ToScalar(); } -#endif - return (T) (object) (double) Math.Sqrt((double) (object) x); +#endif + return (T)(object)(double)Math.Sqrt((double)(object)x); } return Decimal(x); @@ -2792,19 +2968,36 @@ static T SByte(T x) #if SSE if (Sse.IsSupported) { - return (T)(object)(sbyte)(float)Sse.SqrtScalar(Vector128.CreateScalarUnsafe((float)(sbyte)(object)x)).ToScalar(); + return (T) + (object) + (sbyte) + (float) + Sse.SqrtScalar( + Vector128.CreateScalarUnsafe( + (float)(sbyte)(object)x + ) + ) + .ToScalar(); } #endif #if AdvSIMD if (AdvSimd.IsSupported) { - return (T)(object)(sbyte)(float)AdvSimd.SqrtScalar(Vector64.CreateScalarUnsafe((float)(sbyte)(object)x)).ToScalar(); + return (T) + (object) + (sbyte) + (float) + AdvSimd + .SqrtScalar( + Vector64.CreateScalarUnsafe((float)(sbyte)(object)x) + ) + .ToScalar(); } -#endif +#endif #if !MATHF - return (T) (object) (sbyte) (float) Math.Sqrt((float) (sbyte) (object) x); + return (T)(object)(sbyte)(float)Math.Sqrt((float)(sbyte)(object)x); #else - return (T) (object) (sbyte)(float)MathF.Sqrt((float) (sbyte)(object) x); + return (T)(object)(sbyte)(float)MathF.Sqrt((float)(sbyte)(object)x); #endif } @@ -2819,19 +3012,34 @@ static T Byte(T x) #if SSE if (Sse.IsSupported) { - return (T)(object)(byte)(float)Sse.SqrtScalar(Vector128.CreateScalarUnsafe((float)(byte)(object)x)).ToScalar(); + return (T) + (object) + (byte) + (float) + Sse.SqrtScalar( + Vector128.CreateScalarUnsafe((float)(byte)(object)x) + ) + .ToScalar(); } #endif #if AdvSIMD if (AdvSimd.IsSupported) { - return (T)(object)(byte)(float)AdvSimd.SqrtScalar(Vector64.CreateScalarUnsafe((float)(byte)(object)x)).ToScalar(); + return (T) + (object) + (byte) + (float) + AdvSimd + .SqrtScalar( + Vector64.CreateScalarUnsafe((float)(byte)(object)x) + ) + .ToScalar(); } -#endif +#endif #if !MATHF - return (T) (object) (byte) (float) Math.Sqrt((float) (byte) (object) x); + return (T)(object)(byte)(float)Math.Sqrt((float)(byte)(object)x); #else - return (T) (object) (byte)(float)MathF.Sqrt((float) (byte)(object) x); + return (T)(object)(byte)(float)MathF.Sqrt((float)(byte)(object)x); #endif } @@ -2846,19 +3054,36 @@ static T Short(T x) #if SSE if (Sse.IsSupported) { - return (T)(object)(short)(float)Sse.SqrtScalar(Vector128.CreateScalarUnsafe((float)(short)(object)x)).ToScalar(); + return (T) + (object) + (short) + (float) + Sse.SqrtScalar( + Vector128.CreateScalarUnsafe( + (float)(short)(object)x + ) + ) + .ToScalar(); } #endif #if AdvSIMD if (AdvSimd.IsSupported) { - return (T)(object)(short)(float)AdvSimd.SqrtScalar(Vector64.CreateScalarUnsafe((float)(short)(object)x)).ToScalar(); + return (T) + (object) + (short) + (float) + AdvSimd + .SqrtScalar( + Vector64.CreateScalarUnsafe((float)(short)(object)x) + ) + .ToScalar(); } -#endif +#endif #if !MATHF - return (T) (object) (short) (float) Math.Sqrt((float) (short) (object) x); + return (T)(object)(short)(float)Math.Sqrt((float)(short)(object)x); #else - return (T) (object) (short)(float)MathF.Sqrt((float) (short)(object) x); + return (T)(object)(short)(float)MathF.Sqrt((float)(short)(object)x); #endif } @@ -2873,19 +3098,38 @@ static T UShort(T x) #if SSE if (Sse.IsSupported) { - return (T)(object)(ushort)(float)Sse.SqrtScalar(Vector128.CreateScalarUnsafe((float)(ushort)(object)x)).ToScalar(); + return (T) + (object) + (ushort) + (float) + Sse.SqrtScalar( + Vector128.CreateScalarUnsafe( + (float)(ushort)(object)x + ) + ) + .ToScalar(); } #endif #if AdvSIMD if (AdvSimd.IsSupported) { - return (T)(object)(ushort)(float)AdvSimd.SqrtScalar(Vector64.CreateScalarUnsafe((float)(ushort)(object)x)).ToScalar(); + return (T) + (object) + (ushort) + (float) + AdvSimd + .SqrtScalar( + Vector64.CreateScalarUnsafe( + (float)(ushort)(object)x + ) + ) + .ToScalar(); } -#endif +#endif #if !MATHF - return (T) (object) (ushort) (float) Math.Sqrt((float) (ushort) (object) x); + return (T)(object)(ushort)(float)Math.Sqrt((float)(ushort)(object)x); #else - return (T) (object) (ushort)(float)MathF.Sqrt((float) (ushort)(object) x); + return (T)(object)(ushort)(float)MathF.Sqrt((float)(ushort)(object)x); #endif } @@ -2900,19 +3144,34 @@ static T Int(T x) #if SSE if (Sse.IsSupported) { - return (T)(object)(int)(float)Sse.SqrtScalar(Vector128.CreateScalarUnsafe((float)(int)(object)x)).ToScalar(); + return (T) + (object) + (int) + (float) + Sse.SqrtScalar( + Vector128.CreateScalarUnsafe((float)(int)(object)x) + ) + .ToScalar(); } #endif #if AdvSIMD if (AdvSimd.IsSupported) { - return (T)(object)(int)(float)AdvSimd.SqrtScalar(Vector64.CreateScalarUnsafe((float)(int)(object)x)).ToScalar(); + return (T) + (object) + (int) + (float) + AdvSimd + .SqrtScalar( + Vector64.CreateScalarUnsafe((float)(int)(object)x) + ) + .ToScalar(); } -#endif +#endif #if !MATHF - return (T) (object) (int) (float) Math.Sqrt((float) (int) (object) x); + return (T)(object)(int)(float)Math.Sqrt((float)(int)(object)x); #else - return (T) (object) (int)(float)MathF.Sqrt((float) (int)(object) x); + return (T)(object)(int)(float)MathF.Sqrt((float)(int)(object)x); #endif } @@ -2927,19 +3186,34 @@ static T UInt(T x) #if SSE if (Sse.IsSupported) { - return (T)(object)(uint)(float)Sse.SqrtScalar(Vector128.CreateScalarUnsafe((float)(uint)(object)x)).ToScalar(); + return (T) + (object) + (uint) + (float) + Sse.SqrtScalar( + Vector128.CreateScalarUnsafe((float)(uint)(object)x) + ) + .ToScalar(); } #endif #if AdvSIMD if (AdvSimd.IsSupported) { - return (T)(object)(uint)(float)AdvSimd.SqrtScalar(Vector64.CreateScalarUnsafe((float)(uint)(object)x)).ToScalar(); + return (T) + (object) + (uint) + (float) + AdvSimd + .SqrtScalar( + Vector64.CreateScalarUnsafe((float)(uint)(object)x) + ) + .ToScalar(); } -#endif +#endif #if !MATHF - return (T) (object) (uint) (float) Math.Sqrt((float) (uint) (object) x); + return (T)(object)(uint)(float)Math.Sqrt((float)(uint)(object)x); #else - return (T) (object) (uint)(float)MathF.Sqrt((float) (uint)(object) x); + return (T)(object)(uint)(float)MathF.Sqrt((float)(uint)(object)x); #endif } @@ -2954,19 +3228,34 @@ static T Long(T x) #if SSE if (Sse.IsSupported) { - return (T)(object)(long)(float)Sse.SqrtScalar(Vector128.CreateScalarUnsafe((float)(long)(object)x)).ToScalar(); + return (T) + (object) + (long) + (float) + Sse.SqrtScalar( + Vector128.CreateScalarUnsafe((float)(long)(object)x) + ) + .ToScalar(); } #endif #if AdvSIMD if (AdvSimd.IsSupported) { - return (T)(object)(long)(float)AdvSimd.SqrtScalar(Vector64.CreateScalarUnsafe((float)(long)(object)x)).ToScalar(); + return (T) + (object) + (long) + (float) + AdvSimd + .SqrtScalar( + Vector64.CreateScalarUnsafe((float)(long)(object)x) + ) + .ToScalar(); } -#endif +#endif #if !MATHF - return (T) (object) (long) (float) Math.Sqrt((float) (long) (object) x); + return (T)(object)(long)(float)Math.Sqrt((float)(long)(object)x); #else - return (T) (object) (long)(float)MathF.Sqrt((float) (long)(object) x); + return (T)(object)(long)(float)MathF.Sqrt((float)(long)(object)x); #endif } @@ -2979,7 +3268,7 @@ static T Complex(T x) // TODO: vectorized implementation? if (typeof(T) == typeof(Complex)) { - return (T) (object) (Complex) System.Numerics.Complex.Sqrt((Complex) (object) x); + return (T)(object)(Complex)System.Numerics.Complex.Sqrt((Complex)(object)x); } return ULong(x); @@ -2993,19 +3282,36 @@ static T ULong(T x) #if SSE if (Sse.IsSupported) { - return (T)(object)(ulong)(float)Sse.SqrtScalar(Vector128.CreateScalarUnsafe((float)(ulong)(object)x)).ToScalar(); + return (T) + (object) + (ulong) + (float) + Sse.SqrtScalar( + Vector128.CreateScalarUnsafe( + (float)(ulong)(object)x + ) + ) + .ToScalar(); } #endif #if AdvSIMD if (AdvSimd.IsSupported) { - return (T)(object)(ulong)(float)AdvSimd.SqrtScalar(Vector64.CreateScalarUnsafe((float)(ulong)(object)x)).ToScalar(); + return (T) + (object) + (ulong) + (float) + AdvSimd + .SqrtScalar( + Vector64.CreateScalarUnsafe((float)(ulong)(object)x) + ) + .ToScalar(); } -#endif +#endif #if !MATHF - return (T) (object) (ulong) (float) Math.Sqrt((float) (ulong) (object) x); + return (T)(object)(ulong)(float)Math.Sqrt((float)(ulong)(object)x); #else - return (T) (object) (ulong)(float)MathF.Sqrt((float) (ulong)(object) x); + return (T)(object)(ulong)(float)MathF.Sqrt((float)(ulong)(object)x); #endif } @@ -3021,14 +3327,15 @@ static T ULong(T x) /// The type of . /// The tangent of . If is equal to , , or , this method returns . [MethodImpl(MaxOpt)] - public static T Tan(T x) where T : notnull + public static T Tan(T x) + where T : notnull { if (typeof(T) == typeof(Half)) { #if !MATHF - return (T) (object) (Half) (float) Math.Tan((float) (Half) (object) x); + return (T)(object)(Half)(float)Math.Tan((float)(Half)(object)x); #else - return (T) (object) (Half) MathF.Tan((float) (Half) (object) x); + return (T)(object)(Half)MathF.Tan((float)(Half)(object)x); #endif } @@ -3040,9 +3347,9 @@ static T Float(T x) if (typeof(T) == typeof(float)) { #if !MATHF - return (T) (object) (float) Math.Tan((float) (object) x); + return (T)(object)(float)Math.Tan((float)(object)x); #else - return (T) (object) MathF.Tan((float) (object) x); + return (T)(object)MathF.Tan((float)(object)x); #endif } @@ -3054,7 +3361,7 @@ static T Double(T x) { if (typeof(T) == typeof(double)) { - return (T) (object) (double) Math.Tan((double) (object) x); + return (T)(object)(double)Math.Tan((double)(object)x); } return Decimal(x); @@ -3077,7 +3384,7 @@ static T SByte(T x) { if (typeof(T) == typeof(sbyte)) { - return (T) (object) (sbyte) Math.Tan((sbyte) (object) x); + return (T)(object)(sbyte)Math.Tan((sbyte)(object)x); } return Byte(x); @@ -3088,7 +3395,7 @@ static T Byte(T x) { if (typeof(T) == typeof(byte)) { - return (T) (object) (byte) Math.Tan((byte) (object) x); + return (T)(object)(byte)Math.Tan((byte)(object)x); } return Short(x); @@ -3099,7 +3406,7 @@ static T Short(T x) { if (typeof(T) == typeof(short)) { - return (T) (object) (short) Math.Tan((short) (object) x); + return (T)(object)(short)Math.Tan((short)(object)x); } return UShort(x); @@ -3110,7 +3417,7 @@ static T UShort(T x) { if (typeof(T) == typeof(ushort)) { - return (T) (object) (ushort) Math.Tan((ushort) (object) x); + return (T)(object)(ushort)Math.Tan((ushort)(object)x); } return Int(x); @@ -3121,7 +3428,7 @@ static T Int(T x) { if (typeof(T) == typeof(int)) { - return (T) (object) (int) Math.Tan((int) (object) x); + return (T)(object)(int)Math.Tan((int)(object)x); } return UInt(x); @@ -3132,7 +3439,7 @@ static T UInt(T x) { if (typeof(T) == typeof(uint)) { - return (T) (object) (uint) Math.Tan((uint) (object) x); + return (T)(object)(uint)Math.Tan((uint)(object)x); } return Long(x); @@ -3143,7 +3450,7 @@ static T Long(T x) { if (typeof(T) == typeof(long)) { - return (T) (object) (long) Math.Tan((long) (object) x); + return (T)(object)(long)Math.Tan((long)(object)x); } return Complex(x); @@ -3154,7 +3461,7 @@ static T Complex(T x) { if (typeof(T) == typeof(Complex)) { - return (T) (object) (Complex) System.Numerics.Complex.Tan((Complex) (object) x); + return (T)(object)(Complex)System.Numerics.Complex.Tan((Complex)(object)x); } return ULong(x); @@ -3165,7 +3472,7 @@ static T ULong(T x) { if (typeof(T) == typeof(ulong)) { - return (T) (object) (ulong) Math.Tan((ulong) (object) x); + return (T)(object)(ulong)Math.Tan((ulong)(object)x); } ThrowUnsupportedType(); @@ -3180,14 +3487,15 @@ static T ULong(T x) /// The type of . /// The hyperbolic tangent of . If is equal to , this method returns -1. If is equal to , this method returns 1. If is equal to , this method returns . [MethodImpl(MaxOpt)] - public static T Tanh(T x) where T : notnull + public static T Tanh(T x) + where T : notnull { if (typeof(T) == typeof(Half)) { #if !MATHF - return (T) (object) (Half) (float) Math.Tanh((float) (Half) (object) x); + return (T)(object)(Half)(float)Math.Tanh((float)(Half)(object)x); #else - return (T) (object) (Half) MathF.Tanh((float) (Half) (object) x); + return (T)(object)(Half)MathF.Tanh((float)(Half)(object)x); #endif } @@ -3199,9 +3507,9 @@ static T Float(T x) if (typeof(T) == typeof(float)) { #if !MATHF - return (T) (object) (float) Math.Tanh((float) (object) x); + return (T)(object)(float)Math.Tanh((float)(object)x); #else - return (T) (object) MathF.Tanh((float) (object) x); + return (T)(object)MathF.Tanh((float)(object)x); #endif } @@ -3213,7 +3521,7 @@ static T Double(T x) { if (typeof(T) == typeof(double)) { - return (T) (object) (double) Math.Tanh((double) (object) x); + return (T)(object)(double)Math.Tanh((double)(object)x); } return Decimal(x); @@ -3236,7 +3544,7 @@ static T SByte(T x) { if (typeof(T) == typeof(sbyte)) { - return (T) (object) (sbyte) Math.Tanh((sbyte) (object) x); + return (T)(object)(sbyte)Math.Tanh((sbyte)(object)x); } return Byte(x); @@ -3247,7 +3555,7 @@ static T Byte(T x) { if (typeof(T) == typeof(byte)) { - return (T) (object) (byte) Math.Tanh((byte) (object) x); + return (T)(object)(byte)Math.Tanh((byte)(object)x); } return Short(x); @@ -3258,7 +3566,7 @@ static T Short(T x) { if (typeof(T) == typeof(short)) { - return (T) (object) (short) Math.Tanh((short) (object) x); + return (T)(object)(short)Math.Tanh((short)(object)x); } return UShort(x); @@ -3269,7 +3577,7 @@ static T UShort(T x) { if (typeof(T) == typeof(ushort)) { - return (T) (object) (ushort) Math.Tanh((ushort) (object) x); + return (T)(object)(ushort)Math.Tanh((ushort)(object)x); } return Int(x); @@ -3280,7 +3588,7 @@ static T Int(T x) { if (typeof(T) == typeof(int)) { - return (T) (object) (int) Math.Tanh((int) (object) x); + return (T)(object)(int)Math.Tanh((int)(object)x); } return UInt(x); @@ -3291,7 +3599,7 @@ static T UInt(T x) { if (typeof(T) == typeof(uint)) { - return (T) (object) (uint) Math.Tanh((uint) (object) x); + return (T)(object)(uint)Math.Tanh((uint)(object)x); } return Long(x); @@ -3302,7 +3610,7 @@ static T Long(T x) { if (typeof(T) == typeof(long)) { - return (T) (object) (long) Math.Tanh((long) (object) x); + return (T)(object)(long)Math.Tanh((long)(object)x); } return Complex(x); @@ -3313,7 +3621,7 @@ static T Complex(T x) { if (typeof(T) == typeof(Complex)) { - return (T) (object) (Complex) System.Numerics.Complex.Tanh((Complex) (object) x); + return (T)(object)(Complex)System.Numerics.Complex.Tanh((Complex)(object)x); } return ULong(x); @@ -3324,7 +3632,7 @@ static T ULong(T x) { if (typeof(T) == typeof(ulong)) { - return (T) (object) (ulong) Math.Tanh((ulong) (object) x); + return (T)(object)(ulong)Math.Tanh((ulong)(object)x); } ThrowUnsupportedType(); @@ -3359,14 +3667,15 @@ static T ULong(T x) /// /// [MethodImpl(MaxOpt)] - public static T Truncate(T x) where T : notnull + public static T Truncate(T x) + where T : notnull { if (typeof(T) == typeof(Half)) { #if !MATHF - return (T) (object) (Half) (float) Math.Truncate((float) (Half) (object) x); + return (T)(object)(Half)(float)Math.Truncate((float)(Half)(object)x); #else - return (T) (object) (Half) MathF.Truncate((float) (Half) (object) x); + return (T)(object)(Half)MathF.Truncate((float)(Half)(object)x); #endif } @@ -3378,9 +3687,9 @@ static T Float(T x) if (typeof(T) == typeof(float)) { #if !MATHF - return (T) (object) (float) Math.Truncate((float) (object) x); + return (T)(object)(float)Math.Truncate((float)(object)x); #else - return (T) (object) MathF.Truncate((float) (object) x); + return (T)(object)MathF.Truncate((float)(object)x); #endif } @@ -3392,7 +3701,7 @@ static T Double(T x) { if (typeof(T) == typeof(double)) { - return (T) (object) (double) Math.Truncate((double) (object) x); + return (T)(object)(double)Math.Truncate((double)(object)x); } return Decimal(x); @@ -3403,7 +3712,7 @@ static T Decimal(T x) { if (typeof(T) == typeof(decimal)) { - return (T) (object) (decimal) Math.Truncate((decimal) (object) x); + return (T)(object)(decimal)Math.Truncate((decimal)(object)x); } return SByte(x); @@ -3534,11 +3843,12 @@ static T ULong(T x) /// /// [MethodImpl(MaxOpt)] - public static T Log(T x) where T : notnull + public static T Log(T x) + where T : notnull { if (typeof(T) == typeof(Half)) { - return (T) (object) (Half) CoreFastLog((float) (Half) (object) x); + return (T)(object)(Half)MathF.Log((float)(Half)(object)x); } return Float(x); @@ -3548,7 +3858,7 @@ static T Float(T x) { if (typeof(T) == typeof(float)) { - return (T) (object) CoreFastLog((float) (object) x); + return (T)(object)MathF.Log((float)(object)x); } return Double(x); @@ -3559,7 +3869,7 @@ static T Double(T x) { if (typeof(T) == typeof(double)) { - return (T) (object) (double) Math.Log((double) (object) x); + return (T)(object)(double)Math.Log((double)(object)x); } return Decimal(x); @@ -3582,7 +3892,7 @@ static T SByte(T x) { if (typeof(T) == typeof(sbyte)) { - return (T) (object) (sbyte) Math.Log((sbyte) (object) x); + return (T)(object)(sbyte)Math.Log((sbyte)(object)x); } return Byte(x); @@ -3593,7 +3903,7 @@ static T Byte(T x) { if (typeof(T) == typeof(byte)) { - return (T) (object) (byte) Math.Log((byte) (object) x); + return (T)(object)(byte)Math.Log((byte)(object)x); } return Short(x); @@ -3604,7 +3914,7 @@ static T Short(T x) { if (typeof(T) == typeof(short)) { - return (T) (object) (short) Math.Log((short) (object) x); + return (T)(object)(short)Math.Log((short)(object)x); } return UShort(x); @@ -3615,7 +3925,7 @@ static T UShort(T x) { if (typeof(T) == typeof(ushort)) { - return (T) (object) (ushort) Math.Log((ushort) (object) x); + return (T)(object)(ushort)Math.Log((ushort)(object)x); } return Int(x); @@ -3626,7 +3936,7 @@ static T Int(T x) { if (typeof(T) == typeof(int)) { - return (T) (object) (int) Math.Log((int) (object) x); + return (T)(object)(int)Math.Log((int)(object)x); } return UInt(x); @@ -3637,7 +3947,7 @@ static T UInt(T x) { if (typeof(T) == typeof(uint)) { - return (T) (object) (uint) Math.Log((uint) (object) x); + return (T)(object)(uint)Math.Log((uint)(object)x); } return Long(x); @@ -3648,7 +3958,7 @@ static T Long(T x) { if (typeof(T) == typeof(long)) { - return (T) (object) (long) Math.Log((long) (object) x); + return (T)(object)(long)Math.Log((long)(object)x); } return Complex(x); @@ -3659,7 +3969,7 @@ static T Complex(T x) { if (typeof(T) == typeof(Complex)) { - return (T) (object) (Complex) System.Numerics.Complex.Log((Complex) (object) x); + return (T)(object)(Complex)System.Numerics.Complex.Log((Complex)(object)x); } return ULong(x); @@ -3670,7 +3980,7 @@ static T ULong(T x) { if (typeof(T) == typeof(ulong)) { - return (T) (object) (ulong) Math.Log((ulong) (object) x); + return (T)(object)(ulong)Math.Log((ulong)(object)x); } ThrowUnsupportedType(); @@ -3713,14 +4023,15 @@ static T ULong(T x) /// /// [MethodImpl(MaxOpt)] - public static T Log10(T x) where T : notnull + public static T Log10(T x) + where T : notnull { if (typeof(T) == typeof(Half)) { #if !MATHF - return (T) (object) (Half) (float) Math.Log10((float) (Half) (object) x); + return (T)(object)(Half)(float)Math.Log10((float)(Half)(object)x); #else - return (T) (object) (Half) MathF.Log10((float) (Half) (object) x); + return (T)(object)(Half)MathF.Log10((float)(Half)(object)x); #endif } @@ -3732,9 +4043,9 @@ static T Float(T x) if (typeof(T) == typeof(float)) { #if !MATHF - return (T) (object) (float) Math.Log10((float) (object) x); + return (T)(object)(float)Math.Log10((float)(object)x); #else - return (T) (object) MathF.Log10((float) (object) x); + return (T)(object)MathF.Log10((float)(object)x); #endif } @@ -3746,7 +4057,7 @@ static T Double(T x) { if (typeof(T) == typeof(double)) { - return (T) (object) (double) Math.Log10((double) (object) x); + return (T)(object)(double)Math.Log10((double)(object)x); } return Decimal(x); @@ -3769,7 +4080,7 @@ static T SByte(T x) { if (typeof(T) == typeof(sbyte)) { - return (T) (object) (sbyte) Math.Log10((sbyte) (object) x); + return (T)(object)(sbyte)Math.Log10((sbyte)(object)x); } return Byte(x); @@ -3780,7 +4091,7 @@ static T Byte(T x) { if (typeof(T) == typeof(byte)) { - return (T) (object) (byte) Math.Log10((byte) (object) x); + return (T)(object)(byte)Math.Log10((byte)(object)x); } return Short(x); @@ -3791,7 +4102,7 @@ static T Short(T x) { if (typeof(T) == typeof(short)) { - return (T) (object) (short) Math.Log10((short) (object) x); + return (T)(object)(short)Math.Log10((short)(object)x); } return UShort(x); @@ -3802,7 +4113,7 @@ static T UShort(T x) { if (typeof(T) == typeof(ushort)) { - return (T) (object) (ushort) Math.Log10((ushort) (object) x); + return (T)(object)(ushort)Math.Log10((ushort)(object)x); } return Int(x); @@ -3813,7 +4124,7 @@ static T Int(T x) { if (typeof(T) == typeof(int)) { - return (T) (object) (int) Math.Log10((int) (object) x); + return (T)(object)(int)Math.Log10((int)(object)x); } return UInt(x); @@ -3824,7 +4135,7 @@ static T UInt(T x) { if (typeof(T) == typeof(uint)) { - return (T) (object) (uint) Math.Log10((uint) (object) x); + return (T)(object)(uint)Math.Log10((uint)(object)x); } return Long(x); @@ -3835,7 +4146,7 @@ static T Long(T x) { if (typeof(T) == typeof(long)) { - return (T) (object) (long) Math.Log10((long) (object) x); + return (T)(object)(long)Math.Log10((long)(object)x); } return Complex(x); @@ -3846,7 +4157,7 @@ static T Complex(T x) { if (typeof(T) == typeof(Complex)) { - return (T) (object) (Complex) System.Numerics.Complex.Log10((Complex) (object) x); + return (T)(object)(Complex)System.Numerics.Complex.Log10((Complex)(object)x); } return ULong(x); @@ -3857,7 +4168,7 @@ static T ULong(T x) { if (typeof(T) == typeof(ulong)) { - return (T) (object) (ulong) Math.Log10((ulong) (object) x); + return (T)(object)(ulong)Math.Log10((ulong)(object)x); } ThrowUnsupportedType(); @@ -3877,14 +4188,15 @@ static T ULong(T x) /// This method uses the default rounding convention of . /// [MethodImpl(MaxOpt)] - public static T Round(T x) where T : notnull + public static T Round(T x) + where T : notnull { if (typeof(T) == typeof(Half)) { #if !MATHF - return (T) (object) (Half) (float) Math.Round((float) (Half) (object) x); + return (T)(object)(Half)(float)Math.Round((float)(Half)(object)x); #else - return (T) (object) (Half) MathF.Round((float) (Half) (object) x); + return (T)(object)(Half)MathF.Round((float)(Half)(object)x); #endif } @@ -3898,19 +4210,33 @@ static T Float(T x) #if SSE if (Sse42.IsSupported) { - return (T)(object)(float)Sse41.RoundToNearestIntegerScalar(Vector128.CreateScalarUnsafe((float)(object)x)).ToScalar(); + return (T) + (object) + (float) + Sse41 + .RoundToNearestIntegerScalar( + Vector128.CreateScalarUnsafe((float)(object)x) + ) + .ToScalar(); } #endif #if AdvSIMD if (AdvSimd.IsSupported) { - return (T)(object)(float)AdvSimd.RoundToNearestScalar(Vector64.CreateScalar((float)(object)x)).ToScalar(); + return (T) + (object) + (float) + AdvSimd + .RoundToNearestScalar( + Vector64.CreateScalar((float)(object)x) + ) + .ToScalar(); } -#endif +#endif #if !MATHF - return (T) (object) (float) Math.Round((float) (object) x); + return (T)(object)(float)Math.Round((float)(object)x); #else - return (T) (object) MathF.Round((float) (object) x); + return (T)(object)MathF.Round((float)(object)x); #endif } @@ -3925,16 +4251,30 @@ static T Double(T x) #if SSE if (Sse42.IsSupported) { - return (T)(object)(double)Sse41.RoundToNearestIntegerScalar(Vector128.CreateScalarUnsafe((double)(object)x)).ToScalar(); + return (T) + (object) + (double) + Sse41 + .RoundToNearestIntegerScalar( + Vector128.CreateScalarUnsafe((double)(object)x) + ) + .ToScalar(); } #endif #if AdvSIMD if (AdvSimd.IsSupported) { - return (T)(object)(double)AdvSimd.RoundToNearestScalar(Vector64.CreateScalar((double)(object)x)).ToScalar(); + return (T) + (object) + (double) + AdvSimd + .RoundToNearestScalar( + Vector64.CreateScalar((double)(object)x) + ) + .ToScalar(); } -#endif - return (T) (object) (double) Math.Round((double) (object) x); +#endif + return (T)(object)(double)Math.Round((double)(object)x); } return Decimal(x); @@ -3945,7 +4285,7 @@ static T Decimal(T x) { if (typeof(T) == typeof(decimal)) { - return (T) (object) (decimal) Math.Round((decimal) (object) x); + return (T)(object)(decimal)Math.Round((decimal)(object)x); } return SByte(x); @@ -4049,21 +4389,27 @@ static T ULong(T x) /// The type of and . /// /// A number equal to - ( Q), where Q is the quotient of / rounded to the nearest integer (if / falls halfway between two integers, the even integer is returned). - /// + /// /// If - ( Q) is zero, the value +0 is returned if is positive, or -0 if is negative. - /// + /// /// If = 0, NaN is returned. /// [MethodImpl(MaxOpt)] - public static T IEEERemainder(T x, T y) where T : notnull + public static T IEEERemainder(T x, T y) + where T : notnull { if (typeof(T) == typeof(Half)) { #if !MATHF - return (T) (object) (Half) (float) Math.IEEERemainder - ((float) (Half) (object) x, (float) (Half) (object) y); + return (T) + (object) + (Half) + (float) + Math.IEEERemainder((float)(Half)(object)x, (float)(Half)(object)y); #else - return (T) (object) (Half) MathF.IEEERemainder((float) (Half) (object) x, (float) (Half) (object) y); + return (T) + (object) + (Half)MathF.IEEERemainder((float)(Half)(object)x, (float)(Half)(object)y); #endif } @@ -4075,9 +4421,9 @@ static T Float(T x, T y) if (typeof(T) == typeof(float)) { #if !MATHF - return (T) (object) (float) Math.IEEERemainder((float) (object) x, (float) (object) y); + return (T)(object)(float)Math.IEEERemainder((float)(object)x, (float)(object)y); #else - return (T) (object) MathF.IEEERemainder((float) (object) x, (float) (object) y); + return (T)(object)MathF.IEEERemainder((float)(object)x, (float)(object)y); #endif } @@ -4089,7 +4435,7 @@ static T Double(T x, T y) { if (typeof(T) == typeof(double)) { - return (T) (object) Math.IEEERemainder((double) (object) x, (double) (object) y); + return (T)(object)Math.IEEERemainder((double)(object)x, (double)(object)y); } return Decimal(x, y); @@ -4112,7 +4458,7 @@ static T SByte(T x, T y) { if (typeof(T) == typeof(sbyte)) { - return (T) (object) (sbyte) Math.IEEERemainder((sbyte) (object) x, (sbyte) (object) y); + return (T)(object)(sbyte)Math.IEEERemainder((sbyte)(object)x, (sbyte)(object)y); } return Byte(x, y); @@ -4123,7 +4469,7 @@ static T Byte(T x, T y) { if (typeof(T) == typeof(byte)) { - return (T) (object) (byte) Math.IEEERemainder((byte) (object) x, (byte) (object) y); + return (T)(object)(byte)Math.IEEERemainder((byte)(object)x, (byte)(object)y); } return Short(x, y); @@ -4134,7 +4480,7 @@ static T Short(T x, T y) { if (typeof(T) == typeof(short)) { - return (T) (object) (short) Math.IEEERemainder((short) (object) x, (short) (object) y); + return (T)(object)(short)Math.IEEERemainder((short)(object)x, (short)(object)y); } return UShort(x, y); @@ -4145,7 +4491,8 @@ static T UShort(T x, T y) { if (typeof(T) == typeof(ushort)) { - return (T) (object) (ushort) Math.IEEERemainder((ushort) (object) x, (ushort) (object) y); + return (T) + (object)(ushort)Math.IEEERemainder((ushort)(object)x, (ushort)(object)y); } return Int(x, y); @@ -4156,7 +4503,7 @@ static T Int(T x, T y) { if (typeof(T) == typeof(int)) { - return (T) (object) (int) Math.IEEERemainder((int) (object) x, (int) (object) y); + return (T)(object)(int)Math.IEEERemainder((int)(object)x, (int)(object)y); } return UInt(x, y); @@ -4167,7 +4514,7 @@ static T UInt(T x, T y) { if (typeof(T) == typeof(uint)) { - return (T) (object) (uint) Math.IEEERemainder((uint) (object) x, (uint) (object) y); + return (T)(object)(uint)Math.IEEERemainder((uint)(object)x, (uint)(object)y); } return Long(x, y); @@ -4178,7 +4525,7 @@ static T Long(T x, T y) { if (typeof(T) == typeof(long)) { - return (T) (object) (long) Math.IEEERemainder((long) (object) x, (long) (object) y); + return (T)(object)(long)Math.IEEERemainder((long)(object)x, (long)(object)y); } return ULong(x, y); @@ -4189,7 +4536,7 @@ static T ULong(T x, T y) { if (typeof(T) == typeof(ulong)) { - return (T) (object) (ulong) Math.IEEERemainder((ulong) (object) x, (ulong) (object) y); + return (T)(object)(ulong)Math.IEEERemainder((ulong)(object)x, (ulong)(object)y); } ThrowUnsupportedType(); @@ -4284,14 +4631,16 @@ static T ULong(T x, T y) /// /// [MethodImpl(MaxOpt)] - public static T Log(T x, T y) where T : notnull + public static T Log(T x, T y) + where T : notnull { if (typeof(T) == typeof(Half)) { #if !MATHF - return (T) (object) (Half) (float) Math.Log((float) (Half) (object) x, (float) (Half) (object) y); + return (T) + (object)(Half)(float)Math.Log((float)(Half)(object)x, (float)(Half)(object)y); #else - return (T) (object) (Half) MathF.Log((float) (Half) (object) x, (float) (Half) (object) y); + return (T)(object)(Half)MathF.Log((float)(Half)(object)x, (float)(Half)(object)y); #endif } @@ -4303,9 +4652,9 @@ static T Float(T x, T y) if (typeof(T) == typeof(float)) { #if !MATHF - return (T) (object) (float) Math.Log((float) (object) x, (float) (object) y); + return (T)(object)(float)Math.Log((float)(object)x, (float)(object)y); #else - return (T) (object) MathF.Log((float) (object) x, (float) (object) y); + return (T)(object)MathF.Log((float)(object)x, (float)(object)y); #endif } @@ -4317,7 +4666,7 @@ static T Double(T x, T y) { if (typeof(T) == typeof(double)) { - return (T) (object) Math.Log((double) (object) x, (double) (object) y); + return (T)(object)Math.Log((double)(object)x, (double)(object)y); } return Decimal(x, y); @@ -4340,7 +4689,7 @@ static T SByte(T x, T y) { if (typeof(T) == typeof(sbyte)) { - return (T) (object) (sbyte) Math.Log((sbyte) (object) x, (sbyte) (object) y); + return (T)(object)(sbyte)Math.Log((sbyte)(object)x, (sbyte)(object)y); } return Byte(x, y); @@ -4351,7 +4700,7 @@ static T Byte(T x, T y) { if (typeof(T) == typeof(byte)) { - return (T) (object) (byte) Math.Log((byte) (object) x, (byte) (object) y); + return (T)(object)(byte)Math.Log((byte)(object)x, (byte)(object)y); } return Short(x, y); @@ -4362,7 +4711,7 @@ static T Short(T x, T y) { if (typeof(T) == typeof(short)) { - return (T) (object) (short) Math.Log((short) (object) x, (short) (object) y); + return (T)(object)(short)Math.Log((short)(object)x, (short)(object)y); } return UShort(x, y); @@ -4373,7 +4722,7 @@ static T UShort(T x, T y) { if (typeof(T) == typeof(ushort)) { - return (T) (object) (ushort) Math.Log((ushort) (object) x, (ushort) (object) y); + return (T)(object)(ushort)Math.Log((ushort)(object)x, (ushort)(object)y); } return Int(x, y); @@ -4384,7 +4733,7 @@ static T Int(T x, T y) { if (typeof(T) == typeof(int)) { - return (T) (object) (int) Math.Log((int) (object) x, (int) (object) y); + return (T)(object)(int)Math.Log((int)(object)x, (int)(object)y); } return UInt(x, y); @@ -4395,7 +4744,7 @@ static T UInt(T x, T y) { if (typeof(T) == typeof(uint)) { - return (T) (object) (uint) Math.Log((uint) (object) x, (uint) (object) y); + return (T)(object)(uint)Math.Log((uint)(object)x, (uint)(object)y); } return Long(x, y); @@ -4406,7 +4755,7 @@ static T Long(T x, T y) { if (typeof(T) == typeof(long)) { - return (T) (object) (long) Math.Log((long) (object) x, (long) (object) y); + return (T)(object)(long)Math.Log((long)(object)x, (long)(object)y); } return Complex(x, y); @@ -4418,11 +4767,18 @@ static T Complex(T x, T y) if (typeof(T) == typeof(Complex)) { // Complex.Log is not defined on two complex numbers - var baseValue = (Complex) (object) y; + var baseValue = (Complex)(object)y; if (baseValue.Imaginary is 0) - return (T) (object) (Complex) System.Numerics.Complex.Log((Complex) (object) x, baseValue.Real); + return (T) + (object) + (Complex) + System.Numerics.Complex.Log((Complex)(object)x, baseValue.Real); // log(x, y) = log(x) / log(y) - return (T) (object) (System.Numerics.Complex.Log((Complex) (object) x) / System.Numerics.Complex.Log(baseValue)); + return (T) + (object)( + System.Numerics.Complex.Log((Complex)(object)x) + / System.Numerics.Complex.Log(baseValue) + ); } return ULong(x, y); @@ -4433,7 +4789,7 @@ static T ULong(T x, T y) { if (typeof(T) == typeof(ulong)) { - return (T) (object) (ulong) Math.Log((ulong) (object) x, (ulong) (object) y); + return (T)(object)(ulong)Math.Log((ulong)(object)x, (ulong)(object)y); } ThrowUnsupportedType(); @@ -4449,14 +4805,16 @@ static T ULong(T x, T y) /// The type of and . /// Parameter or , whichever is larger. If , or , or both and are equal to , is returned. [MethodImpl(MaxOpt)] - public static T Max(T x, T y) where T : notnull + public static T Max(T x, T y) + where T : notnull { if (typeof(T) == typeof(Half)) { #if !MATHF - return (T) (object) (Half) (float) Math.Max((float) (Half) (object) x, (float) (Half) (object) y); + return (T) + (object)(Half)(float)Math.Max((float)(Half)(object)x, (float)(Half)(object)y); #else - return (T) (object) (Half) MathF.Max((float) (Half) (object) x, (float) (Half) (object) y); + return (T)(object)(Half)MathF.Max((float)(Half)(object)x, (float)(Half)(object)y); #endif } @@ -4468,9 +4826,9 @@ static T Float(T x, T y) if (typeof(T) == typeof(float)) { #if !MATHF - return (T) (object) (float) Math.Max((float) (object) x, (float) (object) y); + return (T)(object)(float)Math.Max((float)(object)x, (float)(object)y); #else - return (T) (object) MathF.Max((float) (object) x, (float) (object) y); + return (T)(object)MathF.Max((float)(object)x, (float)(object)y); #endif } @@ -4482,7 +4840,7 @@ static T Double(T x, T y) { if (typeof(T) == typeof(double)) { - return (T) (object) Math.Max((double) (object) x, (double) (object) y); + return (T)(object)Math.Max((double)(object)x, (double)(object)y); } return Decimal(x, y); @@ -4493,7 +4851,7 @@ static T Decimal(T x, T y) { if (typeof(T) == typeof(decimal)) { - return (T) (object) (decimal) Math.Max((decimal) (object) x, (decimal) (object) y); + return (T)(object)(decimal)Math.Max((decimal)(object)x, (decimal)(object)y); } return SByte(x, y); @@ -4504,7 +4862,7 @@ static T SByte(T x, T y) { if (typeof(T) == typeof(sbyte)) { - return (T) (object) (sbyte) Math.Max((sbyte) (object) x, (sbyte) (object) y); + return (T)(object)(sbyte)Math.Max((sbyte)(object)x, (sbyte)(object)y); } return Byte(x, y); @@ -4515,7 +4873,7 @@ static T Byte(T x, T y) { if (typeof(T) == typeof(byte)) { - return (T) (object) (byte) Math.Max((byte) (object) x, (byte) (object) y); + return (T)(object)(byte)Math.Max((byte)(object)x, (byte)(object)y); } return Short(x, y); @@ -4526,7 +4884,7 @@ static T Short(T x, T y) { if (typeof(T) == typeof(short)) { - return (T) (object) (short) Math.Max((short) (object) x, (short) (object) y); + return (T)(object)(short)Math.Max((short)(object)x, (short)(object)y); } return UShort(x, y); @@ -4537,7 +4895,7 @@ static T UShort(T x, T y) { if (typeof(T) == typeof(ushort)) { - return (T) (object) (ushort) Math.Max((ushort) (object) x, (ushort) (object) y); + return (T)(object)(ushort)Math.Max((ushort)(object)x, (ushort)(object)y); } return Int(x, y); @@ -4548,7 +4906,7 @@ static T Int(T x, T y) { if (typeof(T) == typeof(int)) { - return (T) (object) (int) Math.Max((int) (object) x, (int) (object) y); + return (T)(object)(int)Math.Max((int)(object)x, (int)(object)y); } return UInt(x, y); @@ -4559,7 +4917,7 @@ static T UInt(T x, T y) { if (typeof(T) == typeof(uint)) { - return (T) (object) (uint) Math.Max((uint) (object) x, (uint) (object) y); + return (T)(object)(uint)Math.Max((uint)(object)x, (uint)(object)y); } return Long(x, y); @@ -4570,7 +4928,7 @@ static T Long(T x, T y) { if (typeof(T) == typeof(long)) { - return (T) (object) (long) Math.Max((long) (object) x, (long) (object) y); + return (T)(object)(long)Math.Max((long)(object)x, (long)(object)y); } return ULong(x, y); @@ -4581,7 +4939,7 @@ static T ULong(T x, T y) { if (typeof(T) == typeof(ulong)) { - return (T) (object) (ulong) Math.Max((ulong) (object) x, (ulong) (object) y); + return (T)(object)(ulong)Math.Max((ulong)(object)x, (ulong)(object)y); } ThrowUnsupportedType(); @@ -4597,14 +4955,16 @@ static T ULong(T x, T y) /// The type of and . /// Parameter or , whichever is smaller. If , or , or both and are equal to , is returned. [MethodImpl(MaxOpt)] - public static T Min(T x, T y) where T : notnull + public static T Min(T x, T y) + where T : notnull { if (typeof(T) == typeof(Half)) { #if !MATHF - return (T) (object) (Half) (float) Math.Min((float) (Half) (object) x, (float) (Half) (object) y); + return (T) + (object)(Half)(float)Math.Min((float)(Half)(object)x, (float)(Half)(object)y); #else - return (T) (object) (Half) MathF.Min((float) (Half) (object) x, (float) (Half) (object) y); + return (T)(object)(Half)MathF.Min((float)(Half)(object)x, (float)(Half)(object)y); #endif } @@ -4616,9 +4976,9 @@ static T Float(T x, T y) if (typeof(T) == typeof(float)) { #if !MATHF - return (T) (object) (float) Math.Min((float) (object) x, (float) (object) y); + return (T)(object)(float)Math.Min((float)(object)x, (float)(object)y); #else - return (T) (object) MathF.Min((float) (object) x, (float) (object) y); + return (T)(object)MathF.Min((float)(object)x, (float)(object)y); #endif } @@ -4630,7 +4990,7 @@ static T Double(T x, T y) { if (typeof(T) == typeof(double)) { - return (T) (object) Math.Min((double) (object) x, (double) (object) y); + return (T)(object)Math.Min((double)(object)x, (double)(object)y); } return Decimal(x, y); @@ -4641,7 +5001,7 @@ static T Decimal(T x, T y) { if (typeof(T) == typeof(decimal)) { - return (T) (object) (decimal) Math.Min((decimal) (object) x, (decimal) (object) y); + return (T)(object)(decimal)Math.Min((decimal)(object)x, (decimal)(object)y); } return SByte(x, y); @@ -4652,7 +5012,7 @@ static T SByte(T x, T y) { if (typeof(T) == typeof(sbyte)) { - return (T) (object) (sbyte) Math.Min((sbyte) (object) x, (sbyte) (object) y); + return (T)(object)(sbyte)Math.Min((sbyte)(object)x, (sbyte)(object)y); } return Byte(x, y); @@ -4663,7 +5023,7 @@ static T Byte(T x, T y) { if (typeof(T) == typeof(byte)) { - return (T) (object) (byte) Math.Min((byte) (object) x, (byte) (object) y); + return (T)(object)(byte)Math.Min((byte)(object)x, (byte)(object)y); } return Short(x, y); @@ -4674,7 +5034,7 @@ static T Short(T x, T y) { if (typeof(T) == typeof(short)) { - return (T) (object) (short) Math.Min((short) (object) x, (short) (object) y); + return (T)(object)(short)Math.Min((short)(object)x, (short)(object)y); } return UShort(x, y); @@ -4685,7 +5045,7 @@ static T UShort(T x, T y) { if (typeof(T) == typeof(ushort)) { - return (T) (object) (ushort) Math.Min((ushort) (object) x, (ushort) (object) y); + return (T)(object)(ushort)Math.Min((ushort)(object)x, (ushort)(object)y); } return Int(x, y); @@ -4696,7 +5056,7 @@ static T Int(T x, T y) { if (typeof(T) == typeof(int)) { - return (T) (object) (int) Math.Min((int) (object) x, (int) (object) y); + return (T)(object)(int)Math.Min((int)(object)x, (int)(object)y); } return UInt(x, y); @@ -4707,7 +5067,7 @@ static T UInt(T x, T y) { if (typeof(T) == typeof(uint)) { - return (T) (object) (uint) Math.Min((uint) (object) x, (uint) (object) y); + return (T)(object)(uint)Math.Min((uint)(object)x, (uint)(object)y); } return Long(x, y); @@ -4718,7 +5078,7 @@ static T Long(T x, T y) { if (typeof(T) == typeof(long)) { - return (T) (object) (long) Math.Min((long) (object) x, (long) (object) y); + return (T)(object)(long)Math.Min((long)(object)x, (long)(object)y); } return ULong(x, y); @@ -4729,7 +5089,7 @@ static T ULong(T x, T y) { if (typeof(T) == typeof(ulong)) { - return (T) (object) (ulong) Math.Min((ulong) (object) x, (ulong) (object) y); + return (T)(object)(ulong)Math.Min((ulong)(object)x, (ulong)(object)y); } ThrowUnsupportedType(); @@ -4745,38 +5105,39 @@ static T ULong(T x, T y) /// The type of and . /// The number raised to the power . /// - /// , , and . - /// - /// |Parameters|Return value| - /// |----------------|------------------| - /// |`x` or `y` = `NaN`.|`NaN`| - /// |`x` = Any value except `NaN`; `y` = 0.|1| - /// |`x` = `NegativeInfinity`; `y` < 0.|0| - /// |`x` = `NegativeInfinity`; `y` is a positive odd integer.|`NegativeInfinity`| - /// |`x` = `NegativeInfinity`; `y` is positive but not an odd integer.|`PositiveInfinity`| - /// |`x` < 0 but not `NegativeInfinity`; `y` is not an integer, `NegativeInfinity`, or `PositiveInfinity`.|`NaN`| - /// |`x` = -1; `y` = `NegativeInfinity` or `PositiveInfinity`.|`NaN`| - /// |-1 < `x` < 1; `y` = `NegativeInfinity`.|`PositiveInfinity`| - /// |-1 < `x` < 1; `y` = `PositiveInfinity`.|0| - /// |`x` < -1 or `x` > 1; `y` = `NegativeInfinity`.|0| - /// |`x` < -1 or `x` > 1; `y` = `PositiveInfinity`.|`PositiveInfinity`| - /// |`x` = 0; `y` < 0.|`PositiveInfinity`| - /// |`x` = 0; `y` > 0.|0| - /// |`x` = 1; `y` is any value except `NaN`.|1| - /// |`x` = `PositiveInfinity`; `y` < 0.|0| - /// |`x` = `PositiveInfinity`; `y` > 0.|`PositiveInfinity`| - /// + /// , , and . + /// + /// |Parameters|Return value| + /// |----------------|------------------| + /// |`x` or `y` = `NaN`.|`NaN`| + /// |`x` = Any value except `NaN`; `y` = 0.|1| + /// |`x` = `NegativeInfinity`; `y` < 0.|0| + /// |`x` = `NegativeInfinity`; `y` is a positive odd integer.|`NegativeInfinity`| + /// |`x` = `NegativeInfinity`; `y` is positive but not an odd integer.|`PositiveInfinity`| + /// |`x` < 0 but not `NegativeInfinity`; `y` is not an integer, `NegativeInfinity`, or `PositiveInfinity`.|`NaN`| + /// |`x` = -1; `y` = `NegativeInfinity` or `PositiveInfinity`.|`NaN`| + /// |-1 < `x` < 1; `y` = `NegativeInfinity`.|`PositiveInfinity`| + /// |-1 < `x` < 1; `y` = `PositiveInfinity`.|0| + /// |`x` < -1 or `x` > 1; `y` = `NegativeInfinity`.|0| + /// |`x` < -1 or `x` > 1; `y` = `PositiveInfinity`.|`PositiveInfinity`| + /// |`x` = 0; `y` < 0.|`PositiveInfinity`| + /// |`x` = 0; `y` > 0.|0| + /// |`x` = 1; `y` is any value except `NaN`.|1| + /// |`x` = `PositiveInfinity`; `y` < 0.|0| + /// |`x` = `PositiveInfinity`; `y` > 0.|`PositiveInfinity`| + /// /// ]]> /// [MethodImpl(MaxOpt)] - public static T Pow(T x, T y) where T : notnull + public static T Pow(T x, T y) + where T : notnull { if (typeof(T) == typeof(Half)) { - return (T) (object) (Half) CoreFastPow((float) (Half) (object) x, (float) (Half) (object) y); + return (T)(object)(Half)CoreFastPow((float)(Half)(object)x, (float)(Half)(object)y); } return Float(x, y); @@ -4786,7 +5147,7 @@ static T Float(T x, T y) { if (typeof(T) == typeof(float)) { - return (T) (object) CoreFastPow((float) (object) x, (float) (object) y); + return (T)(object)CoreFastPow((float)(object)x, (float)(object)y); } return Double(x, y); @@ -4797,7 +5158,7 @@ static T Double(T x, T y) { if (typeof(T) == typeof(double)) { - return (T) (object) Math.Pow((double) (object) x, (double) (object) y); + return (T)(object)Math.Pow((double)(object)x, (double)(object)y); } return Decimal(x, y); @@ -4820,8 +5181,8 @@ static T SByte(T x, T y) { if (typeof(T) == typeof(sbyte)) { - var py = (sbyte) (object) y; - var px = (sbyte) (object) x; + var py = (sbyte)(object)y; + var px = (sbyte)(object)x; if (py != 0) { var oabsy = Abs(py); @@ -4838,13 +5199,15 @@ static T SByte(T x, T y) } if (oabsy == py) - return (T) (object) result; - return (T) (object) (sbyte) Scalar.Reciprocal(result); + return (T)(object)result; + return (T)(object)(sbyte)Scalar.Reciprocal(result); } else { - if (px != 0) return (T) (object) (sbyte) 1; - else return (T) (object) (sbyte) 0; + if (px != 0) + return (T)(object)(sbyte)1; + else + return (T)(object)(sbyte)0; } } @@ -4856,8 +5219,8 @@ static T Byte(T x, T y) { if (typeof(T) == typeof(byte)) { - var py = (byte) (object) y; - var px = (byte) (object) x; + var py = (byte)(object)y; + var px = (byte)(object)x; if (py != 0) { var oabsy = py; @@ -4873,12 +5236,14 @@ static T Byte(T x, T y) px *= px; } - return (T) (object) result; + return (T)(object)result; } else { - if (px != 0) return (T) (object) (byte) 1; - else return (T) (object) (byte) 0; + if (px != 0) + return (T)(object)(byte)1; + else + return (T)(object)(byte)0; } } @@ -4890,8 +5255,8 @@ static T Short(T x, T y) { if (typeof(T) == typeof(short)) { - var py = (short) (object) y; - var px = (short) (object) x; + var py = (short)(object)y; + var px = (short)(object)x; if (py != 0) { var oabsy = Abs(py); @@ -4908,13 +5273,15 @@ static T Short(T x, T y) } if (oabsy == py) - return (T) (object) result; - return (T) (object) (short) Scalar.Reciprocal(result); + return (T)(object)result; + return (T)(object)(short)Scalar.Reciprocal(result); } else { - if (px != 0) return (T) (object) (short) 1; - else return (T) (object) (short) 0; + if (px != 0) + return (T)(object)(short)1; + else + return (T)(object)(short)0; } } @@ -4926,8 +5293,8 @@ static T UShort(T x, T y) { if (typeof(T) == typeof(ushort)) { - var py = (ushort) (object) y; - var px = (ushort) (object) x; + var py = (ushort)(object)y; + var px = (ushort)(object)x; if (py != 0) { var oabsy = py; @@ -4943,12 +5310,14 @@ static T UShort(T x, T y) px *= px; } - return (T) (object) result; + return (T)(object)result; } else { - if (px != 0) return (T) (object) (ushort) 1; - else return (T) (object) (ushort) 0; + if (px != 0) + return (T)(object)(ushort)1; + else + return (T)(object)(ushort)0; } } @@ -4960,8 +5329,8 @@ static T Int(T x, T y) { if (typeof(T) == typeof(int)) { - var py = (int) (object) y; - var px = (int) (object) x; + var py = (int)(object)y; + var px = (int)(object)x; if (py != 0) { var oabsy = Abs(py); @@ -4978,13 +5347,15 @@ static T Int(T x, T y) } if (oabsy == py) - return (T) (object) result; - return (T) (object) (int) Scalar.Reciprocal(result); + return (T)(object)result; + return (T)(object)(int)Scalar.Reciprocal(result); } else { - if (px != 0) return (T) (object) (int) 1; - else return (T) (object) (int) 0; + if (px != 0) + return (T)(object)(int)1; + else + return (T)(object)(int)0; } } @@ -4996,8 +5367,8 @@ static T UInt(T x, T y) { if (typeof(T) == typeof(uint)) { - var py = (uint) (object) y; - var px = (uint) (object) x; + var py = (uint)(object)y; + var px = (uint)(object)x; if (py != 0) { var oabsy = py; @@ -5013,12 +5384,14 @@ static T UInt(T x, T y) px *= px; } - return (T) (object) result; + return (T)(object)result; } else { - if (px != 0) return (T) (object) (uint) 1; - else return (T) (object) (uint) 0; + if (px != 0) + return (T)(object)(uint)1; + else + return (T)(object)(uint)0; } } @@ -5030,8 +5403,8 @@ static T Long(T x, T y) { if (typeof(T) == typeof(long)) { - var py = (long) (object) y; - var px = (long) (object) x; + var py = (long)(object)y; + var px = (long)(object)x; if (py != 0) { var oabsy = Abs(py); @@ -5048,13 +5421,15 @@ static T Long(T x, T y) } if (oabsy == py) - return (T) (object) result; - return (T) (object) (long) Scalar.Reciprocal(result); + return (T)(object)result; + return (T)(object)(long)Scalar.Reciprocal(result); } else { - if (px != 0) return (T) (object) (long) 1; - else return (T) (object) (long) 0; + if (px != 0) + return (T)(object)(long)1; + else + return (T)(object)(long)0; } } @@ -5066,7 +5441,10 @@ static T Complex(T x, T y) { if (typeof(T) == typeof(Complex)) { - return (T) (object) (Complex) System.Numerics.Complex.Pow((Complex) (object) x, (Complex) (object) y); + return (T) + (object) + (Complex) + System.Numerics.Complex.Pow((Complex)(object)x, (Complex)(object)y); } return ULong(x, y); @@ -5077,8 +5455,8 @@ static T ULong(T x, T y) { if (typeof(T) == typeof(ulong)) { - var py = (ulong) (object) y; - var px = (ulong) (object) x; + var py = (ulong)(object)y; + var px = (ulong)(object)x; if (py != 0) { var oabsy = py; @@ -5094,12 +5472,14 @@ static T ULong(T x, T y) px *= px; } - return (T) (object) result; + return (T)(object)result; } else { - if (px != 0) return (T) (object) (ulong) 1; - else return (T) (object) (ulong) 0; + if (px != 0) + return (T)(object)(ulong)1; + else + return (T)(object)(ulong)0; } } @@ -5134,14 +5514,16 @@ static T ULong(T x, T y) /// The return value is the angle in the Cartesian plane formed by the x-axis, and a vector starting from the origin, (0,0), and terminating at the point, (x,y). /// [MethodImpl(MaxOpt)] - public static T Atan2(T y, T x) where T : notnull + public static T Atan2(T y, T x) + where T : notnull { if (typeof(T) == typeof(Half)) { #if !MATHF - return (T) (object) (Half) (float) Math.Atan2((float) (Half) (object) x, (float) (Half) (object) y); + return (T) + (object)(Half)(float)Math.Atan2((float)(Half)(object)x, (float)(Half)(object)y); #else - return (T) (object) (Half) MathF.Atan2((float) (Half) (object) x, (float) (Half) (object) y); + return (T)(object)(Half)MathF.Atan2((float)(Half)(object)x, (float)(Half)(object)y); #endif } @@ -5153,9 +5535,9 @@ static T Float(T x, T y) if (typeof(T) == typeof(float)) { #if !MATHF - return (T) (object) (float) Math.Atan2((float) (object) x, (float) (object) y); + return (T)(object)(float)Math.Atan2((float)(object)x, (float)(object)y); #else - return (T) (object) MathF.Atan2((float) (object) x, (float) (object) y); + return (T)(object)MathF.Atan2((float)(object)x, (float)(object)y); #endif } @@ -5167,7 +5549,7 @@ static T Double(T x, T y) { if (typeof(T) == typeof(double)) { - return (T) (object) Math.Atan2((double) (object) x, (double) (object) y); + return (T)(object)Math.Atan2((double)(object)x, (double)(object)y); } return Decimal(x, y); @@ -5190,7 +5572,7 @@ static T SByte(T x, T y) { if (typeof(T) == typeof(sbyte)) { - return (T) (object) (sbyte) Math.Atan2((sbyte) (object) x, (sbyte) (object) y); + return (T)(object)(sbyte)Math.Atan2((sbyte)(object)x, (sbyte)(object)y); } return Byte(x, y); @@ -5201,7 +5583,7 @@ static T Byte(T x, T y) { if (typeof(T) == typeof(byte)) { - return (T) (object) (byte) Math.Atan2((byte) (object) x, (byte) (object) y); + return (T)(object)(byte)Math.Atan2((byte)(object)x, (byte)(object)y); } return Short(x, y); @@ -5212,7 +5594,7 @@ static T Short(T x, T y) { if (typeof(T) == typeof(short)) { - return (T) (object) (short) Math.Atan2((short) (object) x, (short) (object) y); + return (T)(object)(short)Math.Atan2((short)(object)x, (short)(object)y); } return UShort(x, y); @@ -5223,7 +5605,7 @@ static T UShort(T x, T y) { if (typeof(T) == typeof(ushort)) { - return (T) (object) (ushort) Math.Atan2((ushort) (object) x, (ushort) (object) y); + return (T)(object)(ushort)Math.Atan2((ushort)(object)x, (ushort)(object)y); } return Int(x, y); @@ -5234,7 +5616,7 @@ static T Int(T x, T y) { if (typeof(T) == typeof(int)) { - return (T) (object) (int) Math.Atan2((int) (object) x, (int) (object) y); + return (T)(object)(int)Math.Atan2((int)(object)x, (int)(object)y); } return UInt(x, y); @@ -5245,7 +5627,7 @@ static T UInt(T x, T y) { if (typeof(T) == typeof(uint)) { - return (T) (object) (uint) Math.Atan2((uint) (object) x, (uint) (object) y); + return (T)(object)(uint)Math.Atan2((uint)(object)x, (uint)(object)y); } return Long(x, y); @@ -5256,7 +5638,7 @@ static T Long(T x, T y) { if (typeof(T) == typeof(long)) { - return (T) (object) (long) Math.Atan2((long) (object) x, (long) (object) y); + return (T)(object)(long)Math.Atan2((long)(object)x, (long)(object)y); } return ULong(x, y); @@ -5267,7 +5649,7 @@ static T ULong(T x, T y) { if (typeof(T) == typeof(ulong)) { - return (T) (object) (ulong) Math.Atan2((ulong) (object) x, (ulong) (object) y); + return (T)(object)(ulong)Math.Atan2((ulong)(object)x, (ulong)(object)y); } ThrowUnsupportedType(); @@ -5289,14 +5671,15 @@ static T ULong(T x, T y) /// If is or , the method returns or , respectively. /// [MethodImpl(MaxOpt)] - public static T Round(T x, int digits) where T : notnull + public static T Round(T x, int digits) + where T : notnull { if (typeof(T) == typeof(Half)) { #if MATHF - return (T) (object) (Half) (float) MathF.Round((float)(Half) (object) x, digits); + return (T)(object)(Half)(float)MathF.Round((float)(Half)(object)x, digits); #else - return (T) (object) (Half) (float) Math.Round((float) (Half) (object) x, digits); + return (T)(object)(Half)(float)Math.Round((float)(Half)(object)x, digits); #endif } @@ -5308,9 +5691,9 @@ static T Float(T x, int digits) if (typeof(T) == typeof(float)) { #if MATHF - return (T) (object) (float) MathF.Round((float)(object) x, digits); + return (T)(object)(float)MathF.Round((float)(object)x, digits); #else - return (T) (object) (float) Math.Round((float) (object) x, digits); + return (T)(object)(float)Math.Round((float)(object)x, digits); #endif } @@ -5322,7 +5705,7 @@ static T Double(T x, int digits) { if (typeof(T) == typeof(double)) { - return (T) (object) (double) Math.Round((double) (object) x, digits); + return (T)(object)(double)Math.Round((double)(object)x, digits); } return Decimal(x, digits); @@ -5340,14 +5723,15 @@ static T Decimal(T x, int digits) [MethodImpl(MaxOpt)] static T Other(T x, int digits) { - if (typeof(T) == typeof(sbyte) - || typeof(T) == typeof(byte) - || typeof(T) == typeof(ushort) - || typeof(T) == typeof(short) - || typeof(T) == typeof(uint) - || typeof(T) == typeof(int) - || typeof(T) == typeof(ulong) - || typeof(T) == typeof(long) + if ( + typeof(T) == typeof(sbyte) + || typeof(T) == typeof(byte) + || typeof(T) == typeof(ushort) + || typeof(T) == typeof(short) + || typeof(T) == typeof(uint) + || typeof(T) == typeof(int) + || typeof(T) == typeof(ulong) + || typeof(T) == typeof(long) ) return x; @@ -5370,14 +5754,15 @@ static T Other(T x, int digits) /// If is or , the method returns or , respectively. /// [MethodImpl(MaxOpt)] - public static T Round(T x, int digits, System.MidpointRounding mode) where T : notnull + public static T Round(T x, int digits, System.MidpointRounding mode) + where T : notnull { if (typeof(T) == typeof(Half)) { #if MATHF - return (T) (object) (Half) (float) MathF.Round((float)(Half) (object) x, digits, mode); + return (T)(object)(Half)(float)MathF.Round((float)(Half)(object)x, digits, mode); #else - return (T) (object) (Half) (float) Math.Round((float) (Half) (object) x, digits, mode); + return (T)(object)(Half)(float)Math.Round((float)(Half)(object)x, digits, mode); #endif } @@ -5389,9 +5774,9 @@ static T Float(T x, int digits, MidpointRounding mode) if (typeof(T) == typeof(float)) { #if MATHF - return (T) (object) (float) MathF.Round((float)(object) x, digits, mode); + return (T)(object)(float)MathF.Round((float)(object)x, digits, mode); #else - return (T) (object) (float) Math.Round((float) (object) x, digits, mode); + return (T)(object)(float)Math.Round((float)(object)x, digits, mode); #endif } @@ -5403,7 +5788,7 @@ static T Double(T x, int digits, MidpointRounding mode) { if (typeof(T) == typeof(double)) { - return (T) (object) (double) Math.Round((double) (object) x, digits, mode); + return (T)(object)(double)Math.Round((double)(object)x, digits, mode); } return Decimal(x, digits, mode); @@ -5421,15 +5806,15 @@ static T Decimal(T x, int digits, MidpointRounding mode) [MethodImpl(MaxOpt)] static T Other(T x, int digits, MidpointRounding mode) { - if (typeof(T) == typeof(sbyte) - || typeof(T) == typeof(byte) - || typeof(T) == typeof(ushort) - || typeof(T) == typeof(short) - || typeof(T) == typeof(uint) - || typeof(T) == typeof(int) - || typeof(T) == typeof(ulong) - || typeof(T) == typeof(long) - + if ( + typeof(T) == typeof(sbyte) + || typeof(T) == typeof(byte) + || typeof(T) == typeof(ushort) + || typeof(T) == typeof(short) + || typeof(T) == typeof(uint) + || typeof(T) == typeof(int) + || typeof(T) == typeof(ulong) + || typeof(T) == typeof(long) ) return x; @@ -5451,14 +5836,15 @@ static T Other(T x, int digits, MidpointRounding mode) /// If is or , the method returns or , respectively. /// \ [MethodImpl(MaxOpt)] - public static T Round(T x, System.MidpointRounding mode) where T : notnull + public static T Round(T x, System.MidpointRounding mode) + where T : notnull { if (typeof(T) == typeof(Half)) { #if !MATHF - return (T) (object) (Half) (float) Math.Round((float) (Half) (object) x, mode); + return (T)(object)(Half)(float)Math.Round((float)(Half)(object)x, mode); #else - return (T) (object) (Half) MathF.Round((float) (Half) (object) x, mode); + return (T)(object)(Half)MathF.Round((float)(Half)(object)x, mode); #endif } @@ -5473,38 +5859,94 @@ static T Float(T x, MidpointRounding mode) if (Sse42.IsSupported) { if (mode == MidpointRounding.ToZero) - return (T)(object)(float)Sse41.RoundToZeroScalar(Vector128.CreateScalarUnsafe((float)(object)x)).ToScalar(); - + return (T) + (object) + (float) + Sse41 + .RoundToZeroScalar( + Vector128.CreateScalarUnsafe((float)(object)x) + ) + .ToScalar(); + if (mode == MidpointRounding.ToPositiveInfinity) - return (T)(object)(float)Sse41.RoundToPositiveInfinityScalar(Vector128.CreateScalarUnsafe((float)(object)x)).ToScalar(); - + return (T) + (object) + (float) + Sse41 + .RoundToPositiveInfinityScalar( + Vector128.CreateScalarUnsafe((float)(object)x) + ) + .ToScalar(); + if (mode == MidpointRounding.ToNegativeInfinity) - return (T)(object)(float)Sse41.RoundToNegativeInfinityScalar(Vector128.CreateScalarUnsafe((float)(object)x)).ToScalar(); - + return (T) + (object) + (float) + Sse41 + .RoundToNegativeInfinityScalar( + Vector128.CreateScalarUnsafe((float)(object)x) + ) + .ToScalar(); + if (mode == MidpointRounding.ToEven) - return (T)(object)(float)Sse41.RoundToNearestIntegerScalar(Vector128.CreateScalarUnsafe((float)(object)x)).ToScalar(); + return (T) + (object) + (float) + Sse41 + .RoundToNearestIntegerScalar( + Vector128.CreateScalarUnsafe((float)(object)x) + ) + .ToScalar(); } #endif #if AdvSIMD if (AdvSimd.IsSupported) { if (mode == MidpointRounding.ToZero) - return (T)(object)(float)AdvSimd.RoundToZeroScalar(Vector64.CreateScalarUnsafe((float)(object)x)).ToScalar(); - + return (T) + (object) + (float) + AdvSimd + .RoundToZeroScalar( + Vector64.CreateScalarUnsafe((float)(object)x) + ) + .ToScalar(); + if (mode == MidpointRounding.ToPositiveInfinity) - return (T)(object)(float)AdvSimd.RoundToPositiveInfinityScalar(Vector64.CreateScalarUnsafe((float)(object)x)).ToScalar(); - + return (T) + (object) + (float) + AdvSimd + .RoundToPositiveInfinityScalar( + Vector64.CreateScalarUnsafe((float)(object)x) + ) + .ToScalar(); + if (mode == MidpointRounding.ToNegativeInfinity) - return (T)(object)(float)AdvSimd.RoundToNegativeInfinityScalar(Vector64.CreateScalarUnsafe((float)(object)x)).ToScalar(); - + return (T) + (object) + (float) + AdvSimd + .RoundToNegativeInfinityScalar( + Vector64.CreateScalarUnsafe((float)(object)x) + ) + .ToScalar(); + if (mode == MidpointRounding.ToEven) - return (T)(object)(float)AdvSimd.RoundToNearestScalar(Vector64.CreateScalarUnsafe((float)(object)x)).ToScalar(); + return (T) + (object) + (float) + AdvSimd + .RoundToNearestScalar( + Vector64.CreateScalarUnsafe((float)(object)x) + ) + .ToScalar(); } #endif #if !MATHF - return (T) (object) (float) Math.Round((float) (object) x, mode); + return (T)(object)(float)Math.Round((float)(object)x, mode); #else - return (T) (object) MathF.Round((float) (object) x, mode); + return (T)(object)MathF.Round((float)(object)x, mode); #endif } @@ -5520,35 +5962,91 @@ static T Double(T x, MidpointRounding mode) if (Sse42.IsSupported) { if (mode == MidpointRounding.ToZero) - return (T)(object)(double)Sse41.RoundToZeroScalar(Vector128.CreateScalarUnsafe((double)(object)x)).ToScalar(); - + return (T) + (object) + (double) + Sse41 + .RoundToZeroScalar( + Vector128.CreateScalarUnsafe((double)(object)x) + ) + .ToScalar(); + if (mode == MidpointRounding.ToPositiveInfinity) - return (T)(object)(double)Sse41.RoundToPositiveInfinityScalar(Vector128.CreateScalarUnsafe((double)(object)x)).ToScalar(); - + return (T) + (object) + (double) + Sse41 + .RoundToPositiveInfinityScalar( + Vector128.CreateScalarUnsafe((double)(object)x) + ) + .ToScalar(); + if (mode == MidpointRounding.ToNegativeInfinity) - return (T)(object)(double)Sse41.RoundToNegativeInfinityScalar(Vector128.CreateScalarUnsafe((double)(object)x)).ToScalar(); - + return (T) + (object) + (double) + Sse41 + .RoundToNegativeInfinityScalar( + Vector128.CreateScalarUnsafe((double)(object)x) + ) + .ToScalar(); + if (mode == MidpointRounding.ToEven) - return (T)(object)(double)Sse41.RoundToNearestIntegerScalar(Vector128.CreateScalarUnsafe((double)(object)x)).ToScalar(); + return (T) + (object) + (double) + Sse41 + .RoundToNearestIntegerScalar( + Vector128.CreateScalarUnsafe((double)(object)x) + ) + .ToScalar(); } #endif #if AdvSIMD if (AdvSimd.IsSupported) { if (mode == MidpointRounding.ToZero) - return (T)(object)(double)AdvSimd.RoundToZeroScalar(Vector64.CreateScalar((double)(object)x)).ToScalar(); - + return (T) + (object) + (double) + AdvSimd + .RoundToZeroScalar( + Vector64.CreateScalar((double)(object)x) + ) + .ToScalar(); + if (mode == MidpointRounding.ToPositiveInfinity) - return (T)(object)(double)AdvSimd.RoundToPositiveInfinityScalar(Vector64.CreateScalar((double)(object)x)).ToScalar(); - + return (T) + (object) + (double) + AdvSimd + .RoundToPositiveInfinityScalar( + Vector64.CreateScalar((double)(object)x) + ) + .ToScalar(); + if (mode == MidpointRounding.ToNegativeInfinity) - return (T)(object)(double)AdvSimd.RoundToNegativeInfinityScalar(Vector64.CreateScalar((double)(object)x)).ToScalar(); - + return (T) + (object) + (double) + AdvSimd + .RoundToNegativeInfinityScalar( + Vector64.CreateScalar((double)(object)x) + ) + .ToScalar(); + if (mode == MidpointRounding.ToEven) - return (T)(object)(double)AdvSimd.RoundToNearestScalar(Vector64.CreateScalar((double)(object)x)).ToScalar(); + return (T) + (object) + (double) + AdvSimd + .RoundToNearestScalar( + Vector64.CreateScalar((double)(object)x) + ) + .ToScalar(); } #endif - return (T) (object) (double) Math.Round((double) (object) x, mode); + return (T)(object)(double)Math.Round((double)(object)x, mode); } return Decimal(x, mode); @@ -5559,7 +6057,7 @@ static T Decimal(T x, MidpointRounding mode) { if (typeof(T) == typeof(decimal)) { - return (T) (object) (decimal) Math.Round((decimal) (object) x, mode); + return (T)(object)(decimal)Math.Round((decimal)(object)x, mode); } return SByte(x); @@ -5655,4 +6153,4 @@ static T ULong(T x) } } } -} \ No newline at end of file +} diff --git a/sources/SilkTouch/SilkTouch/Caching/CacheFlags.cs b/sources/SilkTouch/SilkTouch/Caching/CacheFlags.cs index 7f046508d7..5af2fd26df 100644 --- a/sources/SilkTouch/SilkTouch/Caching/CacheFlags.cs +++ b/sources/SilkTouch/SilkTouch/Caching/CacheFlags.cs @@ -1,4 +1,5 @@ -using System; +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. namespace Silk.NET.SilkTouch.Caching; @@ -9,18 +10,22 @@ namespace Silk.NET.SilkTouch.Caching; public enum CacheFlags { /// - /// If the cache doesn't exist, allow it to be created and lock other callers from accessing the directory until it - /// is committed. + /// No flags set. /// - AllowNewLocked = 1, + None = 0, /// - /// Same as , but does not return a directory unless it is brand new. + /// If the cache doesn't exist, allow it to be created. /// - RequireNewLocked = 1 | (1 << 1), + AllowNew = 1, /// - /// Don't write cache files to disk. + /// Same as but the new cache will replace the old cache once committed. /// - NoHostDirectory = 1 << 2 + RequireNew = AllowNew | (1 << 1), + + /// + /// The cache provider needs the cache directory to reside on disk. + /// + RequireHostDirectory = 1 << 3, } diff --git a/sources/SilkTouch/SilkTouch/Caching/CacheUtils.cs b/sources/SilkTouch/SilkTouch/Caching/CacheUtils.cs new file mode 100644 index 0000000000..86985bd480 --- /dev/null +++ b/sources/SilkTouch/SilkTouch/Caching/CacheUtils.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Silk.NET.SilkTouch.Caching; + +internal static class CacheUtils +{ + internal static void ThrowAccessException() => + throw new NotSupportedException( + "The cache directory has not been opened with the correct FileAccess for this operation." + ); + + internal static void ThrowRequireHostDirectoryNeedsWrite() => + throw new NotSupportedException( + "CacheFlags.RequireHostDirectory needs FileAccess.Write due to the cache accesses being uncontrolled by " + + "the cache system." + ); + + internal static string ToCacheEntryPath(this string s) => + s.Trim('\r', '\n', '\\', '/').Replace('\\', '/'); +} diff --git a/sources/SilkTouch/SilkTouch/Caching/FileSystemArchiveCacheDirectory.cs b/sources/SilkTouch/SilkTouch/Caching/FileSystemArchiveCacheDirectory.cs new file mode 100644 index 0000000000..c408dd9743 --- /dev/null +++ b/sources/SilkTouch/SilkTouch/Caching/FileSystemArchiveCacheDirectory.cs @@ -0,0 +1,229 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.IO.Compression; +using System.Text; +using Microsoft.Extensions.Logging; +using IOPath = System.IO.Path; + +namespace Silk.NET.SilkTouch.Caching; + +internal class FileSystemArchiveCacheDirectory( + string cacheKey, + string committedPath, + CacheIntent intent, + CacheFlags flags, + FileAccess access, + FileSystemCacheProvider parent +) : ICacheDirectory +{ + private ZipArchive? _committed; + private bool _hasCommitted; + private string? _newPath; + private ZipArchive? _new; + private HashSet? _newEntries; + private SemaphoreSlim _sema = new(1, 1); + + private async ValueTask GetOrCreateCommittedAsync() + { + if ( + !File.Exists(committedPath) + || (Flags & CacheFlags.RequireNew) == CacheFlags.RequireNew && !_hasCommitted + ) + { + parent.Logger.LogDebug( + "Cache miss with key \"{0}\"! Expected ZIP archive at {1}", + CacheKey, + committedPath + ); + return null; + } + + parent.Logger.LogDebug( + "Cache hit with key \"{0}\"! ZIP archive: {1}", + CacheKey, + committedPath + ); + return _committed = await ZipArchive.CreateAsync( + File.OpenRead(committedPath), + ZipArchiveMode.Read, + false, + Encoding.UTF8 + ); + } + + // [MemberNotNull(nameof(_new))] <-- TODO WHY IS THE COMPILER NOT HAPPY? + [MemberNotNull(nameof(_newEntries))] + private async ValueTask GetOrCreateNewAsync() + { + if (_new is not null) + { + Debug.Assert(_newEntries is not null); + return _new; + } + + if ((Access & FileAccess.Write) == 0) + { + CacheUtils.ThrowAccessException(); +#pragma warning disable CS8774 // Member must have a non-null value when exiting. + return null!; +#pragma warning restore CS8774 // Member must have a non-null value when exiting. + } + + _newPath = IOPath.GetTempFileName(); + parent.Logger.LogDebug( + "Opening cache for write with key \"{0}\"! Temporary ZIP archive path: {1}", + CacheKey, + _newPath + ); + _newEntries = []; + return _new = await ZipArchive.CreateAsync( + File.OpenWrite(_newPath), + ZipArchiveMode.Create, + false, + Encoding.UTF8 + ); + } + + public string CacheKey { get; } = cacheKey; + public CacheIntent Intent { get; } = intent; + public CacheFlags Flags { get; } = flags; + public FileAccess Access { get; } = access; + public string? Path => null; + + public async IAsyncEnumerable GetCommittedFilesAsync() + { + if ((Access & FileAccess.Read) == 0) + { + CacheUtils.ThrowAccessException(); + } + + foreach ( + var entry in (await GetOrCreateCommittedAsync())?.Entries + ?? Enumerable.Empty() + ) + { + yield return entry.FullName.ToCacheEntryPath(); + } + } + + public async ValueTask GetCommittedFileAsync(string filePath) + { + if ((Access & FileAccess.Read) == 0) + { + CacheUtils.ThrowAccessException(); + } + + parent.Logger.LogTrace("Cache hit (\"{0}\", ZIP): {1}", CacheKey, filePath); + var entry = + _committed?.GetEntry(filePath.ToCacheEntryPath()) ?? throw new FileNotFoundException(); + return await entry.OpenAsync(); + } + + public async ValueTask AddFileAsync(string filePath, Stream stream) + { + filePath = filePath.ToCacheEntryPath(); + if ((Access & FileAccess.Write) == 0) + { + CacheUtils.ThrowAccessException(); + } + + await _sema.WaitAsync(); + try + { + parent.Logger.LogTrace("Cache write (\"{0}\", ZIP): {1}", CacheKey, filePath); + await using var dst = await (await GetOrCreateNewAsync()) + .CreateEntry(filePath, CompressionLevel.SmallestSize) + .OpenAsync(); + await stream.CopyToAsync(dst); + _newEntries.Add(filePath); + } + finally + { + _sema.Release(); + } + } + + public async ValueTask CommitAsync() + { + if ((Access & FileAccess.Write) == 0) + { + CacheUtils.ThrowAccessException(); + } + + await _sema.WaitAsync(); + try + { + parent.Logger.LogDebug( + "Cache write with key \"{0}\"! ZIP archive: {1}", + CacheKey, + committedPath + ); + var @new = await GetOrCreateNewAsync(); + if (_committed is not null) + { + // Copy old entries that haven't been overwritten. + // If the user doesn't want this, they can use RequireNew. + foreach (var entry in _committed.Entries) + { + if (!_newEntries.Contains(entry.FullName.ToCacheEntryPath())) + { + parent.Logger.LogTrace( + "Cache unchanged (\"{0}\", ZIP): {1}", + CacheKey, + entry.FullName + ); + await using var src = await ( + _committed?.GetEntry(entry.FullName) + ?? throw new InvalidOperationException( + "Failed to open an entry that exists." + ) + ).OpenAsync(); + await using var dst = await @new.CreateEntry( + entry.FullName, + CompressionLevel.SmallestSize + ) + .OpenAsync(); + await src.CopyToAsync(dst); + } + } + + await _committed.DisposeAsync(); + _committed = null; + } + + await @new.DisposeAsync(); + _new = null; + _hasCommitted = true; + Debug.Assert(_newPath is not null); + File.Move(_newPath, committedPath, true); + } + finally + { + _sema.Release(); + } + } + + public async ValueTask DisposeAsync() + { + if (_new is not null) + { + parent.Logger.LogWarning( + "Cache update abandoned with key \"{0}\"! ZIP archive: {1}", + CacheKey, + committedPath + ); + } + + await (_committed?.DisposeAsync() ?? ValueTask.CompletedTask); + await (_new?.DisposeAsync() ?? ValueTask.CompletedTask); + if (_newPath is not null) + { + File.Delete(_newPath); + } + + await parent.FreeAsync(CacheKey); + } +} diff --git a/sources/SilkTouch/SilkTouch/Caching/FileSystemCacheProvider.cs b/sources/SilkTouch/SilkTouch/Caching/FileSystemCacheProvider.cs index 11c7b38005..db793a9143 100644 --- a/sources/SilkTouch/SilkTouch/Caching/FileSystemCacheProvider.cs +++ b/sources/SilkTouch/SilkTouch/Caching/FileSystemCacheProvider.cs @@ -1,11 +1,4 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; +using System.Diagnostics.CodeAnalysis; using Microsoft.Extensions.Logging; namespace Silk.NET.SilkTouch.Caching; @@ -15,235 +8,101 @@ namespace Silk.NET.SilkTouch.Caching; /// public class FileSystemCacheProvider(ILogger logger) : ICacheProvider { - private readonly ConcurrentDictionary _semaphores = new(); - private readonly ConcurrentDictionary _noHostZips = new(); + private readonly SemaphoreSlim _accessSema = new(1, 1); + private readonly HashSet _openKeys = new(); internal static string CommonDir { get; set; } = Environment.CurrentDirectory; - - /// - public async Task<(string Path, bool IsNew)?> GetDirectory( - string cacheKey, - CacheIntent intent, - CacheFlags flags - ) => - await CoreGetDirectory(cacheKey, intent, intent == CacheIntent.ResolvedForeignInput, flags); + internal ILogger Logger { get; } = logger; static string GetCachePath(string cacheKey, CacheIntent intent) { + var outDir = Path.Combine(CommonDir, ".silktouch"); + if (!Directory.Exists(outDir)) + { + Directory.CreateDirectory(outDir); + } + cacheKey = cacheKey.ToLower(); var ext = intent switch { CacheIntent.ResolvedForeignInput => "stdownload", CacheIntent.StageIntermediateOutput => "stout", - _ => throw new ArgumentOutOfRangeException(nameof(intent), intent, null) + _ => throw new ArgumentOutOfRangeException(nameof(intent), intent, null), }; - return Path.Combine(CommonDir, ".silktouch", $"{cacheKey}.{ext}"); + return Path.Combine(outDir, $"{cacheKey}.{ext}"); } - async Task<(string Path, bool IsNew)?> CoreGetDirectory( + /// + public async ValueTask GetDirectoryAsync( string cacheKey, CacheIntent intent, - bool isUnstaged, - CacheFlags flags + CacheFlags flags, + FileAccess access ) { - var path = GetCachePath(cacheKey, intent); - var sema = _semaphores.GetOrAdd(path, _ => new SemaphoreSlim(1, 1)); - await (sema?.WaitAsync() ?? Task.CompletedTask); - - // If the cache file/directory doesn't exist, create it. - if ( - sema is not null - && ( - (isUnstaged && !Directory.Exists(path)) - || (!isUnstaged && !File.Exists(path)) - || (flags & CacheFlags.RequireNewLocked) == CacheFlags.RequireNewLocked - ) - ) + await _accessSema.WaitAsync(); + try { - if ((flags & CacheFlags.AllowNewLocked) == 0) + if (!_openKeys.Add(cacheKey)) { - sema.Release(); - return null; + throw new InvalidOperationException("Cache key is already open"); } - logger.LogDebug("Cache miss: {} for {}", cacheKey, intent); - if (isUnstaged) + try { - if (File.Exists(path)) + var committedPath = GetCachePath(cacheKey, intent); + if ( + (flags & CacheFlags.AllowNew) == 0 + && !Directory.Exists(committedPath) + && !File.Exists(committedPath) + ) { - File.Delete(path); + _openKeys.Remove(cacheKey); + return null; } - Directory.CreateDirectory(path); - } - else - { - if (Directory.Exists(path)) + if ( + (flags & CacheFlags.RequireHostDirectory) == 0 + && !Directory.Exists(committedPath) + ) { - Directory.Delete(path, true); + return new FileSystemArchiveCacheDirectory( + cacheKey, + committedPath, + intent, + flags, + access, + this + ); } - if (Path.GetDirectoryName(path) is { } dn && !Directory.Exists(dn)) - { - Directory.CreateDirectory(dn); - } - - if (File.Exists(path) && (flags & CacheFlags.NoHostDirectory) == 0) - { - File.Move(path, path + ".tmp"); - { - await using var fs = File.OpenRead(path); - using var arch = new ZipArchive(fs); - await Parallel.ForEachAsync( - arch.Entries, - async (entry, ct) => - { - var options = new FileStreamOptions - { - Access = FileAccess.Write, - Mode = FileMode.Create, - Share = FileShare.None, - BufferSize = 4096 - }; - var unixFileMode = (UnixFileMode)( - (entry.ExternalAttributes >> 16) & 511 - ); - if ( - unixFileMode != UnixFileMode.None - && !OperatingSystem.IsWindows() - ) - { - options.UnixCreateMode = unixFileMode; - } - - var dstPath = Path.Combine(path, entry.FullName); - Directory.CreateDirectory(Path.GetDirectoryName(dstPath) ?? path); - await using var destination = new FileStream(dstPath, options); - await using var stream = entry.Open(); - await stream.CopyToAsync(destination, ct); - await destination.FlushAsync(ct); - } - ); - } - File.Delete(path + ".tmp"); - } - else if ((flags & CacheFlags.NoHostDirectory) != 0) - { - if (File.Exists(path)) - { - File.Delete(path); - } - - var fs = File.OpenWrite(path); - var za = new ZipArchive(fs, ZipArchiveMode.Create, true); - _noHostZips.TryAdd(path, (fs, za)); - } + var ret = new FileSystemDiskCacheDirectory( + cacheKey, + committedPath, + intent, + flags, + access, + this + ); + await ret.InitAsync(); + return ret; + } + catch + { + _openKeys.Remove(cacheKey); + throw; } - - return (path, true); - } - - if ((flags & CacheFlags.RequireNewLocked) == CacheFlags.RequireNewLocked) - { - return null; - } - - if (sema is not null && (flags & CacheFlags.NoHostDirectory) != 0) - { - var fs = File.OpenRead(path); - var zip = new ZipArchive(fs, ZipArchiveMode.Read, true); - _noHostZips.TryAdd(path, (fs, zip)); - } - - if (sema is not null) - { - _semaphores[path] = null; - logger.LogInformation("Cache hit: {} for {}", cacheKey, intent); - sema.Release(); - } - - return (path, false); - } - - /// - public async Task CommitFile( - string cacheKey, - CacheIntent intent, - CacheFlags flags, - string filePath, - Stream stream - ) - { - var path = GetCachePath(cacheKey, intent); - if ((flags & CacheFlags.NoHostDirectory) != 0 && _noHostZips.TryGetValue(path, out var zip)) - { - var entry = zip.Item2.CreateEntry(filePath, CompressionLevel.SmallestSize); - await using var s = entry.Open(); - await stream.CopyToAsync(s); - } - else - { - await using var s = File.OpenWrite(Path.Combine(path, filePath)); - await stream.CopyToAsync(s); - } - } - - /// - public async Task CommitDirectory(string cacheKey, CacheIntent intent, CacheFlags flags) - { - var path = GetCachePath(cacheKey, intent); - if ( - (flags & CacheFlags.NoHostDirectory) != 0 - && _noHostZips.TryGetValue(path, out var nhzip) - ) - { - var (fs, zip) = nhzip; - zip.Dispose(); - await fs.FlushAsync(); - await fs.DisposeAsync(); - _noHostZips.TryRemove(new KeyValuePair(path, nhzip)); - } - else if (_semaphores.TryGetValue(path, out var sema)) - { - sema?.Release(); } - } - - /// - public Task> GetFiles(string cacheKey, CacheIntent intent, CacheFlags flags) - { - var path = GetCachePath(cacheKey, intent); - if ((flags & CacheFlags.NoHostDirectory) != 0 && _noHostZips.TryGetValue(path, out var zip)) + finally { - return Task.FromResult(zip.Item2.Entries.Select(x => x.FullName)); + _accessSema.Release(); } - - return Task.FromResult>( - Directory.GetFiles(path, "*", SearchOption.AllDirectories) - ); } - /// - public Task GetFile( - string cacheKey, - CacheIntent intent, - CacheFlags flags, - string filePath - ) + internal async ValueTask FreeAsync(string cacheKey) { - var path = GetCachePath(cacheKey, intent); - if ((flags & CacheFlags.NoHostDirectory) != 0 && _noHostZips.TryGetValue(path, out var zip)) - { - var file = zip.Item2.GetEntry(filePath); - if (file is null) - { - throw new FileNotFoundException(null, nameof(filePath)); - } - - return Task.FromResult(file.Open()); - } - - return Task.FromResult(File.OpenRead(Path.Combine(path, filePath))); + await _accessSema.WaitAsync(); + _openKeys.Remove(cacheKey); + _accessSema.Release(); } } diff --git a/sources/SilkTouch/SilkTouch/Caching/FileSystemDiskCacheDirectory.cs b/sources/SilkTouch/SilkTouch/Caching/FileSystemDiskCacheDirectory.cs new file mode 100644 index 0000000000..2e1e97d0e4 --- /dev/null +++ b/sources/SilkTouch/SilkTouch/Caching/FileSystemDiskCacheDirectory.cs @@ -0,0 +1,237 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.Extensions.Logging; +using IOPath = System.IO.Path; + +namespace Silk.NET.SilkTouch.Caching; + +internal class FileSystemDiskCacheDirectory( + string cacheKey, + string committedPath, + CacheIntent intent, + CacheFlags flags, + FileAccess access, + FileSystemCacheProvider parent +) : ICacheDirectory +{ + private string? _newPath; + private bool _committed; + + public async ValueTask InitAsync() + { + if ((Flags & CacheFlags.RequireHostDirectory) != 0 && (Access & FileAccess.Write) == 0) + { + CacheUtils.ThrowRequireHostDirectoryNeedsWrite(); + return; + } + + if (!Directory.Exists(committedPath)) + { + parent.Logger.LogDebug( + "Cache miss with key \"{0}\"! Expected directory at {1}", + CacheKey, + committedPath + ); + return; + } + + parent.Logger.LogDebug( + "Cache hit with key \"{0}\"! Directory: {1}", + CacheKey, + committedPath + ); + if ((Flags & CacheFlags.RequireHostDirectory) != 0) + { + // If they want to read the existing cache, do a defensive copy to ensure that we can fall back on the old + // cache if things fail. This only happens if RequireHostDirectory is set because in the case that it isn't + // set, we can just read from the old cache directory and write to the new path which is then copied into + // the old cache directory. + // TODO we should probably make this configurable i.e. "I am okay with this being clobbered on failure" + // TODO should probably check the file attributes to not copy unnecessarily + if ( + (Access & FileAccess.Read) != 0 + && (Flags & CacheFlags.RequireNew) != CacheFlags.RequireNew + ) + { + await Parallel.ForEachAsync( + Directory.GetFiles(committedPath, "*", SearchOption.AllDirectories), + async (x, ct) => + await Task.Run( + () => + File.Copy( + x, + IOPath.Combine( + NewPath, + IOPath.GetRelativePath(committedPath, x) + ) + ), + ct + ) + ); + } + } + } + + public string CacheKey { get; } = cacheKey; + public CacheIntent Intent { get; } = intent; + public CacheFlags Flags { get; } = flags; + public FileAccess Access { get; } = access; + + private string NewPath + { + get + { + if (_newPath is not null) + { + return _newPath; + } + + _newPath = IOPath.Combine(IOPath.GetTempPath(), IOPath.GetRandomFileName()); + parent.Logger.LogDebug( + "Opening cache for write with key \"{0}\"! Temporary directory: {1}", + CacheKey, + _newPath + ); + Directory.CreateDirectory(_newPath); + return _newPath; + } + } + public string? Path => (Flags & CacheFlags.RequireHostDirectory) != 0 ? NewPath : null; + + public IAsyncEnumerable GetCommittedFilesAsync() + { + if ((Access & FileAccess.Read) == 0) + { + CacheUtils.ThrowAccessException(); + } + + if ( + !Directory.Exists(committedPath) + || ((Flags & CacheFlags.RequireNew) == CacheFlags.RequireNew && !_committed) + ) + { + return AsyncEnumerable.Empty(); + } + + return Directory + .GetFiles(committedPath, "*", SearchOption.AllDirectories) + .Select(x => IOPath.GetRelativePath(committedPath, x).ToCacheEntryPath()) + .ToAsyncEnumerable(); + } + + public ValueTask GetCommittedFileAsync(string filePath) + { + if ((Access & FileAccess.Read) == 0) + { + CacheUtils.ThrowAccessException(); + } + + parent.Logger.LogTrace("Cache hit (\"{0}\", directory): {1}", CacheKey, filePath); + return ValueTask.FromResult(File.OpenRead(IOPath.Combine(committedPath, filePath))); + } + + public async ValueTask AddFileAsync(string filePath, Stream stream) + { + if ((Access & FileAccess.Write) == 0) + { + CacheUtils.ThrowAccessException(); + } + + parent.Logger.LogTrace("Cache write (\"{0}\", directory): {1}", CacheKey, filePath); + await using var dst = File.OpenWrite(IOPath.Combine(NewPath, filePath)); + await stream.CopyToAsync(dst); + } + + public async ValueTask CommitAsync() + { + if ((Access & FileAccess.Write) == 0) + { + CacheUtils.ThrowAccessException(); + } + + parent.Logger.LogDebug( + "Cache write with key \"{0}\"! Directory: {1}", + CacheKey, + committedPath + ); + + if ((Flags & CacheFlags.RequireNew) == CacheFlags.RequireNew) + { + parent.Logger.LogTrace("Erasing {0} as RequireNew is set", committedPath); + Directory.Delete(committedPath, true); + } + + if (!Directory.Exists(committedPath)) + { + Directory.CreateDirectory(committedPath); + } + + if (_newPath is null) + { + parent.Logger.LogTrace( + "There are no files for {0} as a result of this commit", + committedPath + ); + return; + } + + parent.Logger.LogTrace( + "Copying temporary directory {0} to {1} for cache key {2}", + _newPath, + committedPath, + CacheKey + ); + await Parallel.ForEachAsync( + Directory.GetFiles(_newPath, "*", SearchOption.AllDirectories), + async (x, ct) => + await Task.Run( + () => + { + if ((Flags & CacheFlags.RequireHostDirectory) != 0) + { + File.Copy( + x, + IOPath.Combine(committedPath, IOPath.GetRelativePath(_newPath, x)), + true + ); + } + else + { + File.Move( + x, + IOPath.Combine(committedPath, IOPath.GetRelativePath(_newPath, x)) + ); + } + }, + ct + ) + ); + if ((Flags & CacheFlags.RequireHostDirectory) == 0) + { + Directory.Delete(_newPath, true); + _newPath = null; + } + + _committed = true; + } + + public async ValueTask DisposeAsync() + { + if (!_committed) + { + parent.Logger.LogWarning( + "Cache update abandoned with key \"{0}\"! Directory: {1}", + CacheKey, + committedPath + ); + } + + if (_newPath is not null) + { + Directory.Delete(_newPath, true); + } + + await parent.FreeAsync(CacheKey); + } +} diff --git a/sources/SilkTouch/SilkTouch/Caching/ICacheDirectory.cs b/sources/SilkTouch/SilkTouch/Caching/ICacheDirectory.cs new file mode 100644 index 0000000000..e694a37797 --- /dev/null +++ b/sources/SilkTouch/SilkTouch/Caching/ICacheDirectory.cs @@ -0,0 +1,81 @@ +namespace Silk.NET.SilkTouch.Caching; + +/// +/// A cache directory opened by a . +/// +/// +/// Cache directories must always be disposed, even in exceptional circumstances and regardless of whether they're being +/// committed. Failing to do so may result in the cache being prematurely deleted, as SilkTouch contains protections to +/// ensure that caches from successful jobs aren't affected by writes from subsequent unsuccessful jobs. +/// +public interface ICacheDirectory : IAsyncDisposable +{ + /// + /// Gets the cache key the directory was opened with. + /// + public string CacheKey { get; } + + /// + /// Gets the intent the directory was opened with. + /// + public CacheIntent Intent { get; } + + /// + /// Gets the flags the directory was opened with. + /// + public CacheFlags Flags { get; } + + /// + /// Gets a value indicating the access level of this cache. + /// + public FileAccess Access { get; } + + /// + /// Gets the path of this cache directory on disk. null if does not have the + /// bit set. + /// + public string? Path { get; } + + /// + /// Gets the file paths of the committed files within the cache. + /// + /// The file paths asynchronously. + /// + /// If does not have the bit set. + /// + public IAsyncEnumerable GetCommittedFilesAsync(); + + /// + /// Gets the contents of the given committed file within the cache. + /// + /// + /// This can't be used to observe files that have been written + /// + /// The file path, as previously returned from + /// . + /// An asynchronous task. + /// + /// If does not have the bit set. + /// + /// + /// If the file does not exist in the cache or is not yet committed. + /// + public ValueTask GetCommittedFileAsync(string filePath); + + /// + /// Adds a file to be committed to the cache upon . + /// + /// The file path within the cache (i.e. not a filesystem path, or if it is, a relative + /// one). + /// The stream containing the data to be written. + /// An asynchronous task. + public ValueTask AddFileAsync(string filePath, Stream stream); + + /// + /// Commits the files added using to the cache. If is + /// , this makes the added files observable via + /// /. + /// + /// + public ValueTask CommitAsync(); +} diff --git a/sources/SilkTouch/SilkTouch/Caching/ICacheProvider.cs b/sources/SilkTouch/SilkTouch/Caching/ICacheProvider.cs index b0fb74edd1..2a716fbabb 100644 --- a/sources/SilkTouch/SilkTouch/Caching/ICacheProvider.cs +++ b/sources/SilkTouch/SilkTouch/Caching/ICacheProvider.cs @@ -1,7 +1,3 @@ -using System.Collections.Generic; -using System.IO; -using System.Threading.Tasks; - namespace Silk.NET.SilkTouch.Caching; /// @@ -10,61 +6,20 @@ namespace Silk.NET.SilkTouch.Caching; public interface ICacheProvider { /// - /// Gets a directory in which previous outputs with the given cache key are stored, and where new outputs should be - /// written to. - /// - /// Cache key. - /// The intent behind the cache. - /// - /// The directory and whether it is new. - Task<(string Path, bool IsNew)?> GetDirectory( - string cacheKey, - CacheIntent intent, - CacheFlags flags - ); - - /// - /// Finalises the cache output. - /// - /// Cache key. - /// The intent behind the cache. - /// The cache flags. - /// An asynchronous task. - Task CommitDirectory(string cacheKey, CacheIntent intent, CacheFlags flags); - - /// - /// Adds a file to the cache. Use this if + /// Gets a directory in which previous outputs with the given cache key are stored. /// /// Cache key. /// The intent behind the cache. - /// The cache flags. - /// The file path within the cache. - /// The stream. - /// An asynchronous task. - Task CommitFile( + /// The flags determining how the cache is stored/accessed. + /// The level of access required. + /// + /// The directory, or null if the directory did not exist in the cache already and + /// was not set. + /// + ValueTask GetDirectoryAsync( string cacheKey, CacheIntent intent, CacheFlags flags, - string filePath, - Stream stream + FileAccess access ); - - /// - /// Gets the file paths within the cache. - /// - /// Cache key. - /// The intent behind the cache. - /// The cache flags. - /// The file paths asynchronously. - Task> GetFiles(string cacheKey, CacheIntent intent, CacheFlags flags); - - /// - /// Gets the contents of the given file within the cache. - /// - /// Cache key. - /// The intent behind the cache. - /// The cache flags. - /// The file path, as previously returned from . - /// An asynchronous task. - Task GetFile(string cacheKey, CacheIntent intent, CacheFlags flags, string filePath); } diff --git a/sources/SilkTouch/SilkTouch/Caching/ICacheReadableDirectory.cs b/sources/SilkTouch/SilkTouch/Caching/ICacheReadableDirectory.cs new file mode 100644 index 0000000000..75d0950323 --- /dev/null +++ b/sources/SilkTouch/SilkTouch/Caching/ICacheReadableDirectory.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Silk.NET.SilkTouch.Caching; + +/// +/// A directory opened from a for reading. +/// +public interface ICacheReadableDirectory : ICacheDirectory +{ + /// + /// Returns a initially populated with the current contents of this directory + /// that can be used to write new data to the existing cache. + /// + /// The writable directory. + public ValueTask UpdateAsync(); +} diff --git a/sources/SilkTouch/SilkTouch/Caching/ICacheWritableDirectory.cs b/sources/SilkTouch/SilkTouch/Caching/ICacheWritableDirectory.cs new file mode 100644 index 0000000000..2a6c28098f --- /dev/null +++ b/sources/SilkTouch/SilkTouch/Caching/ICacheWritableDirectory.cs @@ -0,0 +1,9 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Silk.NET.SilkTouch.Caching; + +/// +/// A directory opened by for writing. +/// +public interface ICacheWritableDirectory : ICacheDirectory { } diff --git a/sources/SilkTouch/SilkTouch/Clang/ClangScraper.cs b/sources/SilkTouch/SilkTouch/Clang/ClangScraper.cs index 7451040f89..bd889440ae 100644 --- a/sources/SilkTouch/SilkTouch/Clang/ClangScraper.cs +++ b/sources/SilkTouch/SilkTouch/Clang/ClangScraper.cs @@ -1,16 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System; using System.Collections.Concurrent; -using System.Collections.Generic; using System.Diagnostics; -using System.IO; using System.IO.Hashing; -using System.Linq; using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; using ClangSharp; using ClangSharp.Interop; using Microsoft.CodeAnalysis; @@ -35,8 +29,8 @@ namespace Silk.NET.SilkTouch.Clang; /// The configuration to use. /// The logger to use. /// The input resolver to use. -/// The cache provider into which ClangSharp outputs are cached. /// The mods that modify response files before they are fed to ClangSharp. +/// The cache provider into which ClangSharp outputs are cached. [ModConfiguration] public sealed class ClangScraper( ResponseFileHandler rspHandler, @@ -85,6 +79,11 @@ public record Configuration /// // TODO document public string[]? SkipScrapeIf { get; init; } + + /// + /// Forces the scraper to use cache. Best used on the command line. + /// + public bool ForceCache { get; init; } } /// @@ -161,7 +160,7 @@ out var handle CXDiagnostic_Warning => LogLevel.Warning, CXDiagnostic_Error => LogLevel.Error, CXDiagnostic_Fatal => LogLevel.Critical, - _ => LogLevel.Trace + _ => LogLevel.Trace, }, " {0}", diagnostic.Format(CXDiagnostic.DefaultDisplayOptions).ToString() @@ -227,7 +226,7 @@ private async Task ScrapeBindingsAsync( IReadOnlyList rsps, IModContext job, Configuration cfg, - string? cacheKey = null, + string cacheKey, CancellationToken ct = default ) { @@ -236,12 +235,6 @@ private async Task ScrapeBindingsAsync( { parallelism = Environment.ProcessorCount; } - if (cacheProvider is null) - { - cacheKey = null; - } - - string? cacheDir = null; // Figure out what the common root is so we can aggregate the file paths without collisions var srcRoot = @@ -260,116 +253,92 @@ private async Task ScrapeBindingsAsync( // Generate all the sources and tests. var aggregatedSources = new ConcurrentDictionary(); var aggregatedTests = new ConcurrentDictionary(); - try - { - await Parallel.ForEachAsync( - rsps, - new ParallelOptions - { - CancellationToken = ct, - MaxDegreeOfParallelism = parallelism - }, - async (rsp, innerCt) => - await Task.Run( - async () => + await using var cacheDir = await ( + cacheProvider?.GetDirectoryAsync( + cacheKey, + CacheIntent.StageIntermediateOutput, + CacheFlags.RequireNew, + FileAccess.Write + ) ?? ValueTask.FromResult(null) + ); + await Parallel.ForEachAsync( + rsps, + new ParallelOptions { CancellationToken = ct, MaxDegreeOfParallelism = parallelism }, + async (rsp, innerCt) => + await Task.Run( + async () => + { + // Generate the raw bindings. + var (sources, tests, hasErrors) = ScrapeRawBindings(rsp); + static MemoryStream Reopen(MemoryStream ms) => + ms.TryGetBuffer(out var buff) && buff.Array is not null + ? new MemoryStream(buff.Array, buff.Offset, buff.Count) + : new MemoryStream(buff.ToArray()); + + // Parse and optionally cache the files for the compilation. + foreach ( + var (isTest, (path, stream)) in sources + .Select(x => (false, x)) + .Concat(tests.Select(x => (true, x))) + .Select(x => (x.Item1, (x.x.Key, Reopen((MemoryStream)x.x.Value)))) + ) { - // Generate the raw bindings. - var (sources, tests, hasErrors) = ScrapeRawBindings(rsp); - - static MemoryStream Reopen(MemoryStream ms) => - ms.TryGetBuffer(out var buff) && buff.Array is not null - ? new MemoryStream(buff.Array, buff.Offset, buff.Count) - : new MemoryStream(buff.ToArray()); - - // Parse and optionally cache the files for the compilation. - foreach ( - var (isTest, (path, stream)) in sources - .Select(x => (false, x)) - .Concat(tests.Select(x => (true, x))) - .Select(x => - (x.Item1, (x.x.Key, Reopen((MemoryStream)x.x.Value))) - ) - ) + // Make the path relative as above. + var relativeKey = Path.GetRelativePath( + isTest ? testRoot : srcRoot, + path + ) + .Replace('\\', '/') + .TrimEnd('/'); + + // Cache the output. + if (!hasErrors) { - // Make the path relative as above. - var relativeKey = Path.GetRelativePath( - isTest ? testRoot : srcRoot, - path - ) - .Replace('\\', '/') - .TrimEnd('/'); - - // Cache the output. - if (cacheKey is not null && !hasErrors) - { - cacheDir ??= ( - await cacheProvider!.GetDirectory( - cacheKey, - CacheIntent.StageIntermediateOutput, - CacheFlags.RequireNewLocked | CacheFlags.NoHostDirectory - ) - )?.Path; - await cacheProvider!.CommitFile( - cacheKey, - CacheIntent.StageIntermediateOutput, - CacheFlags.RequireNewLocked | CacheFlags.NoHostDirectory, + await ( + cacheDir?.AddFileAsync( $"{(isTest ? "tests" : "sources")}/{relativeKey}", stream - ); - stream.Seek(0, SeekOrigin.Begin); - } - - // Add it to the dictionary. - if ( - !(isTest ? aggregatedTests : aggregatedSources).TryAdd( - relativeKey, - CSharpSyntaxTree.ParseText( - SourceText.From( - cfg.ManualOverrides?.TryGetValue( - $"{(isTest ? "tests" : "sources")}/{relativeKey}", - out var @override - ) ?? false - ? File.OpenRead( - await inputResolver.ResolvePath(@override) - ) - : stream - ), - path: relativeKey - ) + ) ?? ValueTask.CompletedTask + ); + stream.Seek(0, SeekOrigin.Begin); + } + + // Add it to the dictionary. + if ( + !(isTest ? aggregatedTests : aggregatedSources).TryAdd( + relativeKey, + CSharpSyntaxTree.ParseText( + SourceText.From( + cfg.ManualOverrides?.TryGetValue( + $"{(isTest ? "tests" : "sources")}/{relativeKey}", + out var @override + ) ?? false + ? File.OpenRead( + await inputResolver.ResolvePath(@override) + ) + : stream + ), + path: relativeKey ) ) - { - logger.LogError( - "Failed to add {0} - are the response file outputs conflicting?", - relativeKey - ); - } - else - { - logger.LogTrace("ClangSharp generated {0}", relativeKey); - } + ) + { + logger.LogError( + "Failed to add {0} - are the response file outputs conflicting?", + relativeKey + ); } - }, - innerCt - ) - ); - } - catch - { - cacheKey = null; - throw; - } - finally - { - if (cacheKey is not null) - { - await cacheProvider!.CommitDirectory( - cacheKey, - CacheIntent.StageIntermediateOutput, - CacheFlags.RequireNewLocked | CacheFlags.NoHostDirectory - ); - } - } + else + { + logger.LogTrace("ClangSharp generated {0}", relativeKey); + } + } + }, + innerCt + ) + ); + + await (cacheDir?.CommitAsync() ?? ValueTask.CompletedTask); var src = job.SourceProject; foreach (var (fname, tree) in aggregatedSources) @@ -429,7 +398,7 @@ public async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default) // Others VisualStudioResolver.TryGetVisualStudioInfo(out _) ? "vs" - : "!vs" + : "!vs", }; // Read the configuration. @@ -448,19 +417,12 @@ public async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default) rsps = await mod.BeforeScrapeAsync(ctx.JobKey, rsps); } - // If we're caching the outputs from the entire job, then obtain a cache key to use. - // We need to do this before we change the file paths using the input resolver. - var cacheKey = Convert.ToHexString( - XxHash3.Hash( - MemoryMarshal.Cast(rsps.Select(x => x.FileHash).Order().ToArray()) - ) - ); - // Resolve any foreign paths referenced in the response files await inputResolver.ResolveInPlace(rsps); // Should we completely skip running ClangSharp (e.g. we can't get Windows SDK bindings on macOS) var skip = (cfg.SkipScrapeIf?.Any(applicableSkipIfs.Contains)).GetValueOrDefault(); + var cacheKey = $"{ctx.JobKey}-ClangSharp"; Exception? innerException = null; try { @@ -478,9 +440,55 @@ public async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default) } finally { - if (skip) + if (skip && cacheProvider is not null) { - await AttemptToLoadCache(); + await using var cacheDir = await cacheProvider.GetDirectoryAsync( + cacheKey, + CacheIntent.StageIntermediateOutput, + CacheFlags.None, + FileAccess.Read + ); + var src = ctx.SourceProject; + var tst = ctx.TestProject; + await foreach ( + var file in ( + cacheDir?.GetCommittedFilesAsync() ?? AsyncEnumerable.Empty() + ).WithCancellation(ct) + ) + { + await cacheDir!.GetCommittedFileAsync(file); + var isSource = file.StartsWith("sources"); + var isTest = file.StartsWith("tests"); + if (!isSource && !isTest) + { + continue; + } + + // Have to do this if statement this way as we can't have a ref var over an await point + if ((isSource && src is null) || (isTest && tst is null)) + { + continue; + } + + var rel = file[(isSource ? "sources".Length : "tests".Length)..] + .TrimStart('/', '\\'); + var content = await cacheDir.GetCommittedFileAsync(file); + var root = await CSharpSyntaxTree + .ParseText(SourceText.From(content), path: rel, cancellationToken: ct) + .GetRootAsync(ct); + ref var proj = ref isSource ? ref src : ref tst; + var filePath = proj!.FullPath(rel); + proj = proj + ?.AddDocument(Path.GetFileName(file), root, filePath: filePath) + .Project; + } + + skip = cacheDir is not null; + if (!skip) + { + ctx.SourceProject = src; + ctx.TestProject = tst; + } } } @@ -501,83 +509,6 @@ public async Task ExecuteAsync(IModContext ctx, CancellationToken ct = default) + "fall back on." ); } - - // Local function to improve readability - async Task AttemptToLoadCache() - { - var dirOpt = await cacheProvider!.GetDirectory( - cacheKey, - CacheIntent.StageIntermediateOutput, - CacheFlags.NoHostDirectory - ); - if (dirOpt is not null) - { - var files = ( - await cacheProvider.GetFiles( - cacheKey, - CacheIntent.StageIntermediateOutput, - CacheFlags.NoHostDirectory - ) - ).ToArray(); - - async Task GetSyntaxTree(string file, string startingWith) => - CSharpSyntaxTree.ParseText( - SourceText.From( - await cacheProvider.GetFile( - cacheKey, - CacheIntent.StageIntermediateOutput, - CacheFlags.NoHostDirectory, - file - ) - ), - path: file[(startingWith.Length + 1)..], - cancellationToken: ct - ); - - async Task> GetSyntaxTrees(string startingWith) => - await Task.WhenAll( - files - .Where(x => - x.StartsWith(startingWith) - && x.Length > startingWith.Length - && x[startingWith.Length] is '/' or '\\' - ) - .Select(x => GetSyntaxTree(x, startingWith)) - ); - - var src = ctx.SourceProject; - foreach (var tree in await GetSyntaxTrees("sources")) - { - src = src - ?.AddDocument( - Path.GetFileName(tree.FilePath), - await tree.GetRootAsync(ct), - filePath: src.FullPath(tree.FilePath) - ) - .Project; - } - - ctx.SourceProject = src; - var test = ctx.TestProject; - foreach (var tree in await GetSyntaxTrees("tests")) - { - test = test - ?.AddDocument( - Path.GetFileName(tree.FilePath), - await tree.GetRootAsync(ct), - filePath: test.FullPath(tree.FilePath) - ) - .Project; - } - - ctx.TestProject = test; - skip = false; - } - else - { - logger.LogError("Failed to retrieve cache."); - } - } } /// diff --git a/sources/SilkTouch/SilkTouch/Clang/ResponseFileHandler.cs b/sources/SilkTouch/SilkTouch/Clang/ResponseFileHandler.cs index 4a35d510b5..ec3bea265c 100644 --- a/sources/SilkTouch/SilkTouch/Clang/ResponseFileHandler.cs +++ b/sources/SilkTouch/SilkTouch/Clang/ResponseFileHandler.cs @@ -808,7 +808,7 @@ public ResponseFile ReadResponseFile( string? filePath = null ) { - logger.LogDebug("ClangSharp command line arguments: {0}", string.Join(" ", args)); + logger.LogTrace("ClangSharp command line arguments: {0}", string.Join(" ", args)); var context = (ParseResult: new Parser(s_rootCommand).Parse(args), Dummy: 0); // Begin verbatim ClangSharp code: https://github.com/dotnet/ClangSharp/blob/main/sources/ClangSharpPInvokeGenerator/Program.cs diff --git a/sources/SilkTouch/SilkTouch/Mods/Common/IModContext.cs b/sources/SilkTouch/SilkTouch/Mods/Common/IModContext.cs index b7fc0ee8f1..4adca0ae1a 100644 --- a/sources/SilkTouch/SilkTouch/Mods/Common/IModContext.cs +++ b/sources/SilkTouch/SilkTouch/Mods/Common/IModContext.cs @@ -16,12 +16,6 @@ public interface IModContext : IAsyncDisposable /// public string JobKey { get; } - /// - /// A cache key that can be used for the current job. Use of this key shall mean that if the job configuration - /// changes in any way, the cache is invalidated. - /// - public string JobCacheKey { get; } - /// /// Gets the directory in which the configuration file is contained. May be null if I/O is banned in the current /// generator form factor (e.g. the SilkTouch framework is running as a source generator). diff --git a/sources/SilkTouch/SilkTouch/Mods/Common/MSBuildModContext.cs b/sources/SilkTouch/SilkTouch/Mods/Common/MSBuildModContext.cs index 66639e3075..793a0ed1c7 100644 --- a/sources/SilkTouch/SilkTouch/Mods/Common/MSBuildModContext.cs +++ b/sources/SilkTouch/SilkTouch/Mods/Common/MSBuildModContext.cs @@ -28,13 +28,11 @@ internal class MSBuildModContext( ILogger logger ) : IModContext { - private string? _cacheKey; private Project? _srcProject, _testProject; private SilkTouchConfiguration? _cfg = cfg.Get(); public string JobKey { get; } = cfg.Key; - public string JobCacheKey => _cacheKey ??= ObtainCacheKey(); public string ConfigurationDirectory { get; init; } = Environment.CurrentDirectory; public Project? SourceProject diff --git a/sources/SilkTouch/SilkTouch/Program.cs b/sources/SilkTouch/SilkTouch/Program.cs index 5e14a1a6af..5e4c0bf429 100644 --- a/sources/SilkTouch/SilkTouch/Program.cs +++ b/sources/SilkTouch/SilkTouch/Program.cs @@ -20,11 +20,11 @@ "A list of job names to skip." ) { - Arity = ArgumentArity.ZeroOrMore + Arity = ArgumentArity.ZeroOrMore, }; var configs = new Argument("configs", "Path(s) to JSON SilkTouch configuration(s)") { - Arity = ArgumentArity.OneOrMore + Arity = ArgumentArity.OneOrMore, }; var configOverrides = new Argument( "overrides", @@ -32,7 +32,7 @@ "Arguments recognisable by Microsoft.Extensions.Configuration.CommandLine to override JSON configuration items." ) { - Arity = ArgumentArity.ZeroOrMore + Arity = ArgumentArity.ZeroOrMore, }; var jobs = new Option( new[] { "--max-jobs", "-j" }, diff --git a/sources/SilkTouch/SilkTouch/Sources/GitInputSource.cs b/sources/SilkTouch/SilkTouch/Sources/GitInputSource.cs index cee3c20f11..14b037b259 100644 --- a/sources/SilkTouch/SilkTouch/Sources/GitInputSource.cs +++ b/sources/SilkTouch/SilkTouch/Sources/GitInputSource.cs @@ -15,7 +15,7 @@ namespace Silk.NET.SilkTouch.Sources; /// /// The logger. /// The cache into which the repo is cloned. -public class GitInputSource(ILogger logger, ICacheProvider cache) : IInputSource +public class GitInputSource(ILogger logger, ICacheProvider? cache) : IInputSource { /// public async Task TryResolvePath(string path) @@ -24,13 +24,31 @@ public class GitInputSource(ILogger logger, ICacheProvider cache XxHash32.Hash(MemoryMarshal.Cast(path.AsSpan())) ); logger.LogDebug("Cache key for {} = {}", path, cacheKey); - var (dir, shouldClone) = ( - await cache.GetDirectory( + var cacheDir = await ( + cache?.GetDirectoryAsync( cacheKey, CacheIntent.ResolvedForeignInput, - CacheFlags.AllowNewLocked - ) - )!.Value; + CacheFlags.AllowNew | CacheFlags.RequireHostDirectory, + FileAccess.ReadWrite + ) ?? ValueTask.FromResult(null) + ); + + string dir; + var shouldClone = true; + if (cacheDir is { Path: { } fsPath }) + { + dir = fsPath; + shouldClone = !Directory.GetFiles(fsPath, "*", SearchOption.AllDirectories).Any(); + } + else + { + logger.LogWarning( + "Failed to open cache for \"{0}\" (cache key {1}), clone will not be cached.", + path, + cacheKey + ); + dir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + } path = path[4..].TrimStart('/'); var url = path; @@ -79,11 +97,7 @@ await cache.GetDirectory( ); } - await cache.CommitDirectory( - cacheKey, - CacheIntent.ResolvedForeignInput, - CacheFlags.NoHostDirectory - ); + await (cacheDir?.CommitAsync() ?? ValueTask.CompletedTask); } return Path.Combine(dir, pathInRepo); diff --git a/sources/SilkTouch/SilkTouch/Sources/NuGetInputSource.cs b/sources/SilkTouch/SilkTouch/Sources/NuGetInputSource.cs index f9b9079e44..fe72cc9107 100644 --- a/sources/SilkTouch/SilkTouch/Sources/NuGetInputSource.cs +++ b/sources/SilkTouch/SilkTouch/Sources/NuGetInputSource.cs @@ -15,7 +15,8 @@ namespace Silk.NET.SilkTouch.Sources; /// /// Uses NuGet as an input source i.e. so we can use files within NuGet packages. /// -public class NuGetInputSource(ICacheProvider cache, ILogger logger) : IInputSource +public class NuGetInputSource(ICacheProvider? cache, ILogger logger) + : IInputSource { private const string VersionsUrl = "https://api.nuget.org/v3-flatcontainer/{0}/index.json"; private const string DownloadUrl = "https://www.nuget.org/api/v2/package/{0}/{1}"; @@ -38,23 +39,38 @@ await _client.GetStringAsync(string.Format(VersionsUrl, packageName)) } var pathInPackage = uri.GetComponents(UriComponents.Path, UriFormat.Unescaped); - var (dir, needsDownload) = ( - await cache.GetDirectory( + var cacheDir = await ( + cache?.GetDirectoryAsync( $"{packageName}.{version}", CacheIntent.ResolvedForeignInput, - CacheFlags.AllowNewLocked - ) - )!.Value; + CacheFlags.AllowNew | CacheFlags.RequireHostDirectory, + FileAccess.ReadWrite + ) ?? ValueTask.FromResult(null) + ); + + string dir; + var needsDownload = true; + if (cacheDir is { Path: { } fsPath }) + { + dir = fsPath; + needsDownload = !Directory.GetFiles(fsPath, "*", SearchOption.AllDirectories).Any(); + } + else + { + logger.LogWarning( + "Failed to open cache for {0} v{1}, download will not be cached.", + packageName, + version + ); + dir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + } + if (needsDownload) { var url = string.Format(DownloadUrl, packageName, version); logger.LogInformation("Downloading & extracting {} into {}", url, dir); - new ZipArchive(await _client.GetStreamAsync(url)).ExtractToDirectory(dir); - await cache.CommitDirectory( - $"{packageName}.{version}", - CacheIntent.ResolvedForeignInput, - CacheFlags.AllowNewLocked - ); + await new ZipArchive(await _client.GetStreamAsync(url)).ExtractToDirectoryAsync(dir); + await (cacheDir?.CommitAsync() ?? ValueTask.CompletedTask); } var semver1x4 = version[..(version.IndexOf('-') is not -1 and var v ? v : ^0)]; diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props index 40b74d7678..2b8937aa66 100644 --- a/tests/Directory.Build.props +++ b/tests/Directory.Build.props @@ -14,6 +14,13 @@ $(MSBuildAllProjects);$(MSBuildThisFileDirectory)..\Directory.Build.props tests 1591;1574;1584;1581;1580 + true + Exe + false + true + + + true @@ -29,4 +36,10 @@ + + + + + + diff --git a/tests/Maths/Maths/PlaneTests.cs b/tests/Maths/Maths/PlaneTests.cs index 53a869dd4a..c9761fa32a 100644 --- a/tests/Maths/Maths/PlaneTests.cs +++ b/tests/Maths/Maths/PlaneTests.cs @@ -108,7 +108,10 @@ public void PlaneGetHashCodeTest() { Plane target = new Plane(1.0f, 2.0f, 3.0f, 4.0f); - int expected = target.Normal.GetHashCode() + target.Distance.GetHashCode(); + int expected = HashCode.Combine( + target.Normal.GetHashCode(), + target.Distance.GetHashCode() + ); int actual = target.GetHashCode(); Assert.Equal(expected, actual); } @@ -117,12 +120,19 @@ public void PlaneGetHashCodeTest() [Fact] public void PlaneConstructorTest1() { - float a = 1.0f, b = 2.0f, c = 3.0f, d = 4.0f; + float a = 1.0f, + b = 2.0f, + c = 3.0f, + d = 4.0f; Plane target = new Plane(a, b, c, d); Assert.True( - target.Normal.X == a && target.Normal.Y == b && target.Normal.Z == c && target.Distance == d, - "Plane.cstor did not return the expected value."); + target.Normal.X == a + && target.Normal.Y == b + && target.Normal.Z == c + && target.Distance == d, + "Plane.cstor did not return the expected value." + ); } // A test for Plane.CreateFromVertices @@ -149,8 +159,14 @@ public void PlaneCreateFromVerticesTest2() Plane target = Plane.CreateFromVertices(point1, point2, point3); var invRoot2 = 1.0f / Scalar.Sqrt(2); - Plane expected = new Plane(new Vector3D(invRoot2, 0, invRoot2), -invRoot2); - Assert.True(MathHelper.Equal(target, expected), "Plane.cstor did not return the expected value."); + Plane expected = new Plane( + new Vector3D(invRoot2, 0, invRoot2), + -invRoot2 + ); + Assert.True( + MathHelper.Equal(target, expected), + "Plane.cstor did not return the expected value." + ); } // A test for Plane (Vector3Df, float) @@ -163,7 +179,8 @@ public void PlaneConstructorTest3() Plane target = new Plane(normal, d); Assert.True( target.Normal == normal && target.Distance == d, - "Plane.cstor did not return the expected value."); + "Plane.cstor did not return the expected value." + ); } // A test for Plane (Vector4Df) @@ -174,8 +191,12 @@ public void PlaneConstructorTest() Plane target = new Plane(value); Assert.True( - target.Normal.X == value.X && target.Normal.Y == value.Y && target.Normal.Z == value.Z && target.Distance == value.W, - "Plane.cstor did not return the expected value."); + target.Normal.X == value.X + && target.Normal.Y == value.Y + && target.Normal.Z == value.Z + && target.Distance == value.W, + "Plane.cstor did not return the expected value." + ); } [Fact] @@ -186,7 +207,10 @@ public void PlaneDotTest() float expected = 10 + 12 + 12 + 10; float actual = Plane.Dot(target, value); - Assert.True(MathHelper.Equal(expected, actual), "Plane.Dot returns unexpected value."); + Assert.True( + MathHelper.Equal(expected, actual), + "Plane.Dot returns unexpected value." + ); } [Fact] @@ -197,7 +221,10 @@ public void PlaneDotCoordinateTest() float expected = 10 + 12 + 12 + 5; float actual = Plane.DotCoordinate(target, value); - Assert.True(MathHelper.Equal(expected, actual), "Plane.DotCoordinate returns unexpected value."); + Assert.True( + MathHelper.Equal(expected, actual), + "Plane.DotCoordinate returns unexpected value." + ); } [Fact] @@ -208,7 +235,10 @@ public void PlaneDotNormalTest() float expected = 10 + 12 + 12; float actual = Plane.DotNormal(target, value); - Assert.True(MathHelper.Equal(expected, actual), "Plane.DotCoordinate returns unexpected value."); + Assert.True( + MathHelper.Equal(expected, actual), + "Plane.DotCoordinate returns unexpected value." + ); } [Fact] @@ -221,11 +251,17 @@ public void PlaneNormalizeTest() Plane expected = new Plane(target.Normal * invF, target.Distance * invF); Plane actual = Plane.Normalize(target); - Assert.True(MathHelper.Equal(expected, actual), "Plane.Normalize returns unexpected value."); + Assert.True( + MathHelper.Equal(expected, actual), + "Plane.Normalize returns unexpected value." + ); // normalize, normalized normal. actual = Plane.Normalize(actual); - Assert.True(MathHelper.Equal(expected, actual), "Plane.Normalize returns unexpected value."); + Assert.True( + MathHelper.Equal(expected, actual), + "Plane.Normalize returns unexpected value." + ); } [Fact] @@ -236,9 +272,9 @@ public void PlaneTransformTest1() target = Plane.Normalize(target); Matrix4X4 m = - Matrix4X4.CreateRotationX(MathHelper.ToRadians(30.0f)) * - Matrix4X4.CreateRotationY(MathHelper.ToRadians(30.0f)) * - Matrix4X4.CreateRotationZ(MathHelper.ToRadians(30.0f)); + Matrix4X4.CreateRotationX(MathHelper.ToRadians(30.0f)) + * Matrix4X4.CreateRotationY(MathHelper.ToRadians(30.0f)) + * Matrix4X4.CreateRotationZ(MathHelper.ToRadians(30.0f)); m.M41 = 10.0f; m.M42 = 20.0f; m.M43 = 30.0f; @@ -247,16 +283,23 @@ public void PlaneTransformTest1() Matrix4X4 inv; Matrix4X4.Invert(m, out inv); Matrix4X4 itm = Matrix4X4.Transpose(inv); - float x = target.Normal.X, y = target.Normal.Y, z = target.Normal.Z, w = target.Distance; + float x = target.Normal.X, + y = target.Normal.Y, + z = target.Normal.Z, + w = target.Distance; expected.Normal = new Vector3D( x * itm.M11 + y * itm.M21 + z * itm.M31 + w * itm.M41, x * itm.M12 + y * itm.M22 + z * itm.M32 + w * itm.M42, - x * itm.M13 + y * itm.M23 + z * itm.M33 + w * itm.M43); + x * itm.M13 + y * itm.M23 + z * itm.M33 + w * itm.M43 + ); expected.Distance = x * itm.M14 + y * itm.M24 + z * itm.M34 + w * itm.M44; Plane actual; actual = Plane.Transform(target, m); - Assert.True(MathHelper.Equal(expected, actual), "Plane.Transform did not return the expected value."); + Assert.True( + MathHelper.Equal(expected, actual), + "Plane.Transform did not return the expected value." + ); } [Fact] @@ -267,22 +310,29 @@ public void PlaneTransformTest2() target = Plane.Normalize(target); Matrix4X4 m = - Matrix4X4.CreateRotationX(MathHelper.ToRadians(30.0f)) * - Matrix4X4.CreateRotationY(MathHelper.ToRadians(30.0f)) * - Matrix4X4.CreateRotationZ(MathHelper.ToRadians(30.0f)); + Matrix4X4.CreateRotationX(MathHelper.ToRadians(30.0f)) + * Matrix4X4.CreateRotationY(MathHelper.ToRadians(30.0f)) + * Matrix4X4.CreateRotationZ(MathHelper.ToRadians(30.0f)); Quaternion q = Quaternion.CreateFromRotationMatrix(m); Plane expected = new Plane(); - float x = target.Normal.X, y = target.Normal.Y, z = target.Normal.Z, w = target.Distance; + float x = target.Normal.X, + y = target.Normal.Y, + z = target.Normal.Z, + w = target.Distance; expected.Normal = new Vector3D( x * m.M11 + y * m.M21 + z * m.M31 + w * m.M41, x * m.M12 + y * m.M22 + z * m.M32 + w * m.M42, - x * m.M13 + y * m.M23 + z * m.M33 + w * m.M43); + x * m.M13 + y * m.M23 + z * m.M33 + w * m.M43 + ); expected.Distance = x * m.M14 + y * m.M24 + z * m.M34 + w * m.M44; Plane actual; actual = Plane.Transform(target, q); - Assert.True(MathHelper.Equal(expected, actual), "Plane.Transform did not return the expected value."); + Assert.True( + MathHelper.Equal(expected, actual), + "Plane.Transform did not return the expected value." + ); } // A test for Plane comparison involving NaN values @@ -334,7 +384,8 @@ public void PlaneToStringTest() CultureInfo.CurrentCulture, "{{Normal:{0:G} D:{1}}}", target.Normal, - target.Distance); + target.Distance + ); Assert.Equal(expected, target.ToString()); } diff --git a/tests/Maths/Maths/Scalar.Bitwise.cs b/tests/Maths/Maths/Scalar.Bitwise.cs index a61ac7a8c9..0a8de24ac8 100644 --- a/tests/Maths/Maths/Scalar.Bitwise.cs +++ b/tests/Maths/Maths/Scalar.Bitwise.cs @@ -13,99 +13,105 @@ public class ScalarBitwiseTest [Fact] public void RotateLeft1() { - Assert.Equal((byte)0b1110_0001, Scalar.RotateLeft((byte)0b1111_0000, 1)); + Assert.Equal((byte)0b1110_0001, Scalar.RotateLeft((byte)0b1111_0000, 1)); } - + [Fact] public void RotateLeft2() { - Assert.Equal((ushort)0b1100_1000_0000_0011, Scalar.RotateLeft((ushort)0b1111_0010_0000_0000, 2)); + Assert.Equal( + (ushort)0b1100_1000_0000_0011, + Scalar.RotateLeft((ushort)0b1111_0010_0000_0000, 2) + ); } - + [Fact] public void RotateRight1() { - Assert.Equal((byte)0b1111_0000, Scalar.RotateRight((byte)0b1110_0001, 1)); + Assert.Equal((byte)0b1111_0000, Scalar.RotateRight((byte)0b1110_0001, 1)); } - + [Fact] public void RotateRight2() { - Assert.Equal((ushort)0b1111_0010_0000_0000, Scalar.RotateRight((ushort)0b1100_1000_0000_0011, 2)); + Assert.Equal( + (ushort)0b1111_0010_0000_0000, + Scalar.RotateRight((ushort)0b1100_1000_0000_0011, 2) + ); } - + [Fact] public void And1() { Assert.Equal(0b1010, Scalar.And(0b1110, 0b1011)); } - + [Fact] public void And2() { Assert.Equal((byte)0b1010, Scalar.And((byte)0b1110, (byte)0b1011)); } - + [Fact] public void And3() { Assert.Equal((long)0b1010, Scalar.And((long)0b1110, (long)0b1011)); } - + [Fact] public void Or1() { Assert.Equal(0b1111, Scalar.Or(0b1110, 0b1011)); } - + [Fact] public void Or2() { Assert.Equal((byte)0b1111, Scalar.Or((byte)0b1110, (byte)0b1011)); } - + [Fact] public void Or3() { Assert.Equal((long)0b1111, Scalar.Or((long)0b1110, (long)0b1011)); } - + [Fact] public void Xor1() { Assert.Equal(0b0101, Scalar.Xor(0b1110, 0b1011)); } - + [Fact] public void Xor2() { Assert.Equal((byte)0b0101, Scalar.Xor((byte)0b1110, (byte)0b1011)); } - + [Fact] public void Xor3() { Assert.Equal((long)0b0101, Scalar.Xor((long)0b1110, (long)0b1011)); } - + [Fact] public void Not1() { Assert.Equal(~0b1110, Scalar.Not(0b1110)); } - + [Fact] public void Not2() { - var b = ~(byte)0b1110; + var b = ~(byte)0b1110 & byte.MaxValue; // ReSharper disable once IntVariableOverflowInUncheckedContext Assert.Equal((byte)b, Scalar.Not((byte)0b1110)); } - + [Fact] public void Not3() { Assert.Equal(~(ulong)0b1110, Scalar.Not((ulong)0b1110)); } } -} \ No newline at end of file +} diff --git a/tests/Maths/Maths/Silk.NET.Maths.Tests.csproj b/tests/Maths/Maths/Silk.NET.Maths.Tests.csproj index b4df4c6f0e..2d1bebe022 100644 --- a/tests/Maths/Maths/Silk.NET.Maths.Tests.csproj +++ b/tests/Maths/Maths/Silk.NET.Maths.Tests.csproj @@ -4,9 +4,8 @@ net10.0 true true - false - true true + true @@ -15,7 +14,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/tests/SilkTouch/SilkTouch/ArrayParameterTransformerTests.cs b/tests/SilkTouch/SilkTouch/ArrayParameterTransformerTests.cs index 2daa4bf31b..772f171f97 100644 --- a/tests/SilkTouch/SilkTouch/ArrayParameterTransformerTests.cs +++ b/tests/SilkTouch/SilkTouch/ArrayParameterTransformerTests.cs @@ -12,7 +12,6 @@ namespace Silk.NET.SilkTouch.UnitTests; -[TestFixture] public class ArrayParameterTransformerTests { [ @@ -247,7 +246,7 @@ public bool TryGetChildSymbolMetadata( IsOut: childNativeName.Contains('o'), IsIn: childNativeName.Contains('i') ) - ) + ), ], ElementTypeConstraints: new SymbolConstraints( [ @@ -257,7 +256,7 @@ public bool TryGetChildSymbolMetadata( null, null, new UsageConstraints() - ) + ), ] ), IsMutable: childNativeName.Contains('m') @@ -279,7 +278,7 @@ public bool TryGetChildSymbolMetadata( IsOut: childNativeName.Contains('o'), IsIn: childNativeName.Contains('i') ) - ) + ), ], ElementTypeConstraints: new SymbolConstraints( [ @@ -289,7 +288,7 @@ public bool TryGetChildSymbolMetadata( null, null, new UsageConstraints() - ) + ), ] ), IsMutable: childNativeName.Contains('m') diff --git a/tests/SilkTouch/SilkTouch/Caching/CacheTests.cs b/tests/SilkTouch/SilkTouch/Caching/CacheTests.cs new file mode 100644 index 0000000000..d31d1dcb71 --- /dev/null +++ b/tests/SilkTouch/SilkTouch/Caching/CacheTests.cs @@ -0,0 +1,214 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections; +using System.Diagnostics; +using System.IO.Compression; +using System.Runtime.CompilerServices; +using System.Text; +using Microsoft.Extensions.Logging.Abstractions; +using Silk.NET.SilkTouch.Caching; + +namespace Silk.NET.SilkTouch.UnitTests.Caching; + +public class CacheTests +{ + static CacheTests() => Init(); + + private static void Init([CallerFilePath] string filePath = "") + { + FileSystemCacheProvider.CommonDir = Path.Combine( + Path.GetDirectoryName(filePath)!, + "TestData.tmp" + ); + + if (Directory.Exists(FileSystemCacheProvider.CommonDir)) + { + Directory.Delete(FileSystemCacheProvider.CommonDir, true); + } + } + + private static string GetExpectedPath(string cacheKey, CacheIntent intent) => + Path.Combine( + FileSystemCacheProvider.CommonDir, + ".silktouch", + cacheKey.ToLower() + + (intent == CacheIntent.ResolvedForeignInput ? ".stdownload" : ".stout") + ); + + [Test] + public async Task ShouldNotCreateNewCacheWithoutAllowNewAsync() + { + var provider = new FileSystemCacheProvider(new NullLogger()); + var i = 0; + foreach ( + var intent in (IEnumerable) + [CacheIntent.ResolvedForeignInput, CacheIntent.StageIntermediateOutput] + ) + { + foreach ( + var flag in (IEnumerable) + [CacheFlags.None, CacheFlags.RequireHostDirectory] + ) + { + foreach ( + var access in (IEnumerable) + [FileAccess.Read, FileAccess.Write, FileAccess.ReadWrite] + ) + { + var cacheKey = $"{nameof(ShouldNotCreateNewCacheWithoutAllowNewAsync)}{i++}"; + var dir = await provider.GetDirectoryAsync(cacheKey, intent, flag, access); + using (Assert.EnterMultipleScope()) + { + Assert.That(dir, Is.Null); + var expectedPath = GetExpectedPath(cacheKey, intent); + Assert.That(Directory.Exists(expectedPath), Is.False); + Assert.That( + File.Exists( + Path.Combine(FileSystemCacheProvider.CommonDir, cacheKey.ToLower()) + ), + Is.False + ); + } + } + } + } + } + + // TODO this could probably be split up into lots of little tests, but it's fine for now. + [Test] + public async Task ShouldCreateCacheWhenAllowNew() + { + var provider = new FileSystemCacheProvider(new NullLogger()); + var i = 0; + var read = new byte[4]; + foreach ( + var intent in (IEnumerable) + [CacheIntent.ResolvedForeignInput, CacheIntent.StageIntermediateOutput] + ) + { + foreach ( + var flag in (IEnumerable) + [CacheFlags.None, CacheFlags.RequireHostDirectory] + ) + { + foreach ( + var access in (IEnumerable)[FileAccess.Write, FileAccess.ReadWrite] + ) + { + var cacheKey = $"{nameof(ShouldCreateCacheWhenAllowNew)}{i++}"; + var expectedPath = GetExpectedPath(cacheKey, intent); + for (var j = 0; j < 3; j++) + { + // Check we can create the cache + // If this is the third loop, we are testing RequireNew + var dir = await provider.GetDirectoryAsync( + cacheKey, + intent, + (j == 2 ? CacheFlags.RequireNew : CacheFlags.AllowNew) | flag, + access + ); + Assert.That(dir, Is.Not.Null); + Assert.That( + dir.Path is null, + Is.EqualTo((flag & CacheFlags.RequireHostDirectory) == 0) + ); + + // Check we can't access our files before we commit them + if ((access & FileAccess.ReadWrite) == FileAccess.ReadWrite) + { + Assert.That( + await dir.GetCommittedFilesAsync().ToArrayAsync(), + j == 1 + ? Is.EquivalentTo(["test.txt"]) + : Is.EquivalentTo(Array.Empty()) + ); + + if (j == 1) // if the cache has been reopened but it's not RequireNew + { + await using var es = await dir.GetCommittedFileAsync("test.txt"); + await es.ReadExactlyAsync(read); + Assert.That(read, Is.EquivalentTo("tset"u8.ToArray())); + } + } + + foreach ( + var contents in (IEnumerable) + ["test"u8.ToArray(), "tset"u8.ToArray()] + ) + { + // Add a file to ensure commit works properly. + // If this is the second loop, we are testing we can overwrite. + await dir.AddFileAsync("test.txt", new MemoryStream(contents)); + await dir.CommitAsync(); + using (Assert.EnterMultipleScope()) + { + Assert.That( + Directory.Exists(expectedPath), + Is.EqualTo((flag & CacheFlags.RequireHostDirectory) != 0) + ); + Assert.That( + File.Exists(expectedPath), + Is.EqualTo((flag & CacheFlags.RequireHostDirectory) == 0) + ); + } + + // Check that we can access our committed files immediately if ReadWrite + if ((access & FileAccess.ReadWrite) == FileAccess.ReadWrite) + { + Assert.That( + await dir.GetCommittedFilesAsync().ToArrayAsync(), + Is.EquivalentTo(["test.txt"]) + ); + + await using var es = await dir.GetCommittedFileAsync("test.txt"); + await es.ReadExactlyAsync(read); + Assert.That(read, Is.EquivalentTo(contents)); + } + + // Check the cache contents + if ((flag & CacheFlags.RequireHostDirectory) != 0) + { + Assert.That( + await File.ReadAllBytesAsync( + Path.Combine(expectedPath, "test.txt") + ), + Is.EquivalentTo(contents) + ); + } + else + { + await using var za = await ZipArchive.CreateAsync( + File.OpenRead(expectedPath), + ZipArchiveMode.Read, + false, + Encoding.UTF8 + ); + var entry = za.GetEntry("test.txt"); + Assert.That(entry, Is.Not.Null); + await using var es = await entry.OpenAsync(); + read.AsSpan().Clear(); + await es.ReadExactlyAsync(read); + Assert.That(read, Is.EquivalentTo(contents)); + } + } + + // Check that we can't reopen until we've disposed + Assert.ThrowsAsync(async () => + { + await provider.GetDirectoryAsync( + cacheKey, + intent, + CacheFlags.AllowNew | flag, + access + ); + }); + + // Check that we can reopen (in the next loop) + await dir.DisposeAsync(); + } + } + } + } + } +} diff --git a/tests/SilkTouch/SilkTouch/DummyModContext.cs b/tests/SilkTouch/SilkTouch/DummyModContext.cs index 1178166e26..197f71f229 100644 --- a/tests/SilkTouch/SilkTouch/DummyModContext.cs +++ b/tests/SilkTouch/SilkTouch/DummyModContext.cs @@ -12,7 +12,6 @@ public class DummyModContext : IModContext public ValueTask DisposeAsync() => ValueTask.CompletedTask; public string JobKey { get; set; } = string.Empty; - public string JobCacheKey { get; set; } = string.Empty; public string? ConfigurationDirectory { get; set; } public Project? SourceProject { get; set; } public Project? TestProject { get; set; } diff --git a/tests/SilkTouch/SilkTouch/Khronos/MixKhronosDataTests.cs b/tests/SilkTouch/SilkTouch/Khronos/MixKhronosDataTests.cs index ff0cca0f03..644f4b2567 100644 --- a/tests/SilkTouch/SilkTouch/Khronos/MixKhronosDataTests.cs +++ b/tests/SilkTouch/SilkTouch/Khronos/MixKhronosDataTests.cs @@ -14,9 +14,16 @@ namespace Silk.NET.SilkTouch.UnitTests.Khronos; -[TestFixture] public class MixKhronosDataTests { + static MixKhronosDataTests() + { + if (!VerifyDiffPlex.Initialized) + { + VerifyDiffPlex.Initialize(); + } + } + struct Options : IOptionsSnapshot { public required MixKhronosData.Configuration Value { get; init; } @@ -24,9 +31,6 @@ struct Options : IOptionsSnapshot public MixKhronosData.Configuration Get(string? name) => Value; } - [ModuleInitializer] - public static void Initialize() => VerifyDiffPlex.Initialize(); - public static string TestFile(string name, [CallerFilePath] string? fPath = null) => Path.Combine( Path.GetDirectoryName(fPath) @@ -50,18 +54,20 @@ private static IAsyncEnumerable TestCases() IEnumerable files = ["gl.xml", "wgl.xml", "glx.xml", "cl.xml", "vk.xml"]; return files .ToAsyncEnumerable() - .Select(async (x, ct) => - { - var mod = new MixKhronosData( - new NullLogger(), - new Options - { - Value = new MixKhronosData.Configuration { SpecPath = TestFile(x) }, - } - ); - await mod.InitializeAsync(new DummyModContext(), ct); - return (object[])[x, mod.Jobs[""]]; - }); + .Select( + async (x, ct) => + { + var mod = new MixKhronosData( + new NullLogger(), + new Options + { + Value = new MixKhronosData.Configuration { SpecPath = TestFile(x) }, + } + ); + await mod.InitializeAsync(new DummyModContext(), ct); + return (object[])[x, mod.Jobs[""]]; + } + ); } private static IAsyncEnumerable EnumTestCases() => @@ -69,22 +75,23 @@ private static IAsyncEnumerable EnumTestCases() => private static IAsyncEnumerable RegressionTestCases() => TestCases() - .Select(async (object[] s, CancellationToken ct) => - s[0] is "gl.xml" or "cl.xml" - ? (object[]) - [ - s[0], - s[1], - await Task.WhenAll( - TestFiles( - new Regex( - $@"regression\.2\.21\.{((string)s[0])[..^4]}.*\.json\.gz" + .Select( + async (object[] s, CancellationToken ct) => + s[0] is "gl.xml" or "cl.xml" + ? (object[]) + [ + s[0], + s[1], + await Task.WhenAll( + TestFiles( + new Regex( + $@"regression\.2\.21\.{((string)s[0])[..^4]}.*\.json\.gz" + ) ) - ) - .Select(ReadProfile) - ), - ] - : null + .Select(ReadProfile) + ), + ] + : null ) .OfType(); diff --git a/tests/SilkTouch/SilkTouch/MetadataUtilsTests.cs b/tests/SilkTouch/SilkTouch/MetadataUtilsTests.cs index 35306f2018..6e75bc5d49 100644 --- a/tests/SilkTouch/SilkTouch/MetadataUtilsTests.cs +++ b/tests/SilkTouch/SilkTouch/MetadataUtilsTests.cs @@ -7,7 +7,6 @@ namespace Silk.NET.SilkTouch.UnitTests; -[TestFixture] public class MetadataUtilsTests { [ diff --git a/tests/SilkTouch/SilkTouch/ModUtilsTests.cs b/tests/SilkTouch/SilkTouch/ModUtilsTests.cs index 6c0a3cbcc7..d03b7a130d 100644 --- a/tests/SilkTouch/SilkTouch/ModUtilsTests.cs +++ b/tests/SilkTouch/SilkTouch/ModUtilsTests.cs @@ -3,21 +3,32 @@ namespace Silk.NET.SilkTouch.UnitTests; -[TestFixture] public class ModUtilsTests { - private static readonly (string Input, string EffectiveName, string Directory, string Remainder)[] - GetEffectiveNameTests = [ - ("hello/GL.gen.cs", "GL", "hello/", ".gen.cs"), - ("hello/GL.Manual.cs", "GL.Manual", "hello/", ".cs"), - ("hello/GL.Interfaces.gen.cs", "GL.Interfaces", "hello/", ".gen.cs") - ]; + private static readonly ( + string Input, + string EffectiveName, + string Directory, + string Remainder + )[] GetEffectiveNameTests = + [ + ("hello/GL.gen.cs", "GL", "hello/", ".gen.cs"), + ("hello/GL.Manual.cs", "GL.Manual", "hello/", ".cs"), + ("hello/GL.Interfaces.gen.cs", "GL.Interfaces", "hello/", ".gen.cs"), + ]; [Test] public void GetEffectiveName( - [ValueSource(nameof(GetEffectiveNameTests))] (string Input, string EffectiveName, string Directory, string Remainder) testData) + [ValueSource(nameof(GetEffectiveNameTests))] + (string Input, string EffectiveName, string Directory, string Remainder) testData + ) { - ModUtils.GetEffectiveName(testData.Input, out var effectiveName, out var directory, out var remainder); + ModUtils.GetEffectiveName( + testData.Input, + out var effectiveName, + out var directory, + out var remainder + ); Assert.That(effectiveName.ToString(), Is.EqualTo(testData.EffectiveName)); Assert.That(directory.ToString(), Is.EqualTo(testData.Directory)); Assert.That(remainder.ToString(), Is.EqualTo(testData.Remainder)); diff --git a/tests/SilkTouch/SilkTouch/Naming/NameTests.cs b/tests/SilkTouch/SilkTouch/Naming/NameTests.cs index e8644c1875..3d7405909c 100644 --- a/tests/SilkTouch/SilkTouch/Naming/NameTests.cs +++ b/tests/SilkTouch/SilkTouch/Naming/NameTests.cs @@ -6,7 +6,6 @@ namespace Silk.NET.SilkTouch.UnitTests.Naming; -[TestFixture] public class NameTests : NameTrimmer { [Test, TestCase(null), TestCase("glfw")]