From e1a48c60b6d30308f165dbacfa94836cc910b855 Mon Sep 17 00:00:00 2001 From: Lukas Rieger Date: Wed, 14 Nov 2018 14:38:10 +0100 Subject: [PATCH 01/21] add replacements for System.Numerics Vector3 / Quaternion --- .../Fable.Compiler/Transforms/Replacements.fs | 2 + src/js/fable-core/Fable.Core.JS.fsproj | 1 + src/js/fable-core/System.Numerics.fs | 242 ++++++++++++++++++ tests/Main/Fable.Tests.fsproj | 1 + tests/Main/Main.fs | 1 + tests/Main/SystemNumericsTest.fs | 35 +++ 6 files changed, 282 insertions(+) create mode 100644 src/js/fable-core/System.Numerics.fs create mode 100644 tests/Main/SystemNumericsTest.fs diff --git a/src/dotnet/Fable.Compiler/Transforms/Replacements.fs b/src/dotnet/Fable.Compiler/Transforms/Replacements.fs index e581231c7c..8f13763e83 100644 --- a/src/dotnet/Fable.Compiler/Transforms/Replacements.fs +++ b/src/dotnet/Fable.Compiler/Transforms/Replacements.fs @@ -2546,6 +2546,8 @@ let private replacedModules = "Microsoft.FSharp.Control.ObservableModule", observable Types.type_, types "System.Reflection.TypeInfo", types + "System.Numerics.Vector3", bclType + "System.Numerics.Quaternion", bclType ] let tryCall (com: ICompiler) (ctx: Context) r t (info: CallInfo) (thisArg: Expr option) (args: Expr list) = diff --git a/src/js/fable-core/Fable.Core.JS.fsproj b/src/js/fable-core/Fable.Core.JS.fsproj index ccf77042e8..5cd4023de1 100644 --- a/src/js/fable-core/Fable.Core.JS.fsproj +++ b/src/js/fable-core/Fable.Core.JS.fsproj @@ -7,6 +7,7 @@ + diff --git a/src/js/fable-core/System.Numerics.fs b/src/js/fable-core/System.Numerics.fs new file mode 100644 index 0000000000..c3c6f4734b --- /dev/null +++ b/src/js/fable-core/System.Numerics.fs @@ -0,0 +1,242 @@ +namespace System.Numerics + +// contains the types Vector3 and Quaternion. +// feel free to add the rest as required + + + +[] +type Vector3(x : single, y : single, z : single) = + + new (value : single) = Vector3(value, value, value) + + member __.X = x + member __.Y = y + member __.Z = z + + member __.Abs() = Vector3(System.Math.Abs(x), System.Math.Abs(y), System.Math.Abs(z)) + + member __.CopyTo(arr : single array, index : int) = + arr.[index + 0] <- x + arr.[index + 1] <- y + arr.[index + 2] <- z + + member __.CopyTo(arr : single array) = __.CopyTo(arr, 0) + + //member __.Equals(other : Vector3) = + // x = other.X && + // y = other.Y && + // z = other.Z + + //override this.Equals(other : obj) = + // match other with + // | :? Vector3 as vother -> + // this.Equals(vother) + // | _ -> false + + //override __.GetHashCode() = + // hash(x, y, z) + + // -------------------------------- + // Static members of Vector3 + + static member One = Vector3(1.f, 1.f, 1.f) + + static member UnitX = Vector3(1.f, 0.f, 0.f) + static member UnitY = Vector3(0.f, 1.f, 0.f) + static member UnitZ = Vector3(0.f, 0.f, 1.f) + + static member Zero = Vector3(0.f, 0.f, 0.f) + + static member Add(left : Vector3, right : Vector3) = + Vector3(left.X + right.X, left.Y + right.Y, left.Z + right.Z) + + static member Divide(left : Vector3, right : Vector3) = + Vector3(left.X / right.X, left.Y / right.Y, left.Z / right.Z) + + static member Divide(left : Vector3, right : single) = + Vector3(left.X / right, left.Y / right, left.Z / right) + + static member Clamp(value : Vector3, min : Vector3, max : Vector3) = + let inline clamp v min max = + if v < min then min + else if v > max then max + else v + Vector3(clamp value.X min.X max.X, + clamp value.Y min.Y max.Y, + clamp value.Z min.Z max.Z) + + static member Cross(vector1 : Vector3, vector2 : Vector3) = + Vector3(vector1.Y * vector2.Z - vector1.Z * vector2.Y, + vector1.Z * vector2.X - vector1.X * vector2.Z, + vector1.X * vector2.Y - vector1.Y * vector2.X) + + static member Distance(value1 : Vector3, value2 : Vector3) : single = + let num2 = value1.X - value2.X + let num3 = value1.Y - value2.Y + let num4 = value1.Z - value2.Z + let num5 = num2 * num2 + num3 * num3 + num4 * num4; + single ( System.Math.Sqrt(float num5) ) + + static member DistanceSquared(value1 : Vector3, value2 : Vector3) : single = + let num2 = value1.X - value2.X + let num3 = value1.Y - value2.Y + let num4 = value1.Z - value2.Z + let num5 = num2 * num2 + num3 * num3 + num4 * num4; + num5 + + // -------------------------------- + // Operators of Vector3 + + static member (+) (left:Vector3, right:Vector3) : Vector3 = + Vector3.Add(left, right) + + static member (/) (left:Vector3, right:Vector3) : Vector3 = + Vector3.Divide(left, right) + + static member (/) (left:Vector3, right:single) : Vector3 = + Vector3.Divide(left, right) + + +[] +type Quaternion(x : single, y : single, z : single, w : single) = + + new(vectorPart : Vector3, scalarPart : single) = + Quaternion(vectorPart.X, vectorPart.Y, vectorPart.Z, scalarPart) + + member __.X = x + member __.Y = y + member __.Z = z + member __.W = w + + member __.IsIdentity = + x = 0.f && + y = 0.f && + z = 0.f && + w = 1.f + + member this.Length() : single = + let ls = this.LengthSquared() + single ( System.Math.Sqrt(float ls) ) + + member __.LengthSquared() : single = + x * x + y * y + z * z + w * w + + // -------------------------------- + // static members of Quaternion + + static member Identity = Quaternion(0.f, 0.f, 0.f, 1.f) + + static member Add(value1 : Quaternion, value2 : Quaternion) = + Quaternion( + value1.X + value2.X, + value1.Y + value2.Y, + value1.Z + value2.Z, + value1.W + value2.W + ) + + static member Concatenate(value1 : Quaternion, value2 : Quaternion) = + let x = value2.X; + let y = value2.Y; + let z = value2.Z; + let w = value2.W; + let x2 = value1.X; + let y2 = value1.Y; + let z2 = value1.Z; + let w2 = value1.W; + let num = y * z2 - z * y2; + let num2 = z * x2 - x * z2; + let num3 = x * y2 - y * x2; + let num4 = x * x2 + y * y2 + z * z2; + Quaternion( + x * w2 + x2 * w + num, + y * w2 + y2 * w + num2, + z * w2 + z2 * w + num3, + w * w2 - num4 + ) + + static member Conjugate(value : Quaternion) = + Quaternion( + 0.f - value.X, + 0.f - value.Y, + 0.f - value.Z, + value.W + ) + + static member Divide(value1 : Quaternion, value2 : Quaternion) = + let x = value1.X; + let y = value1.Y; + let z = value1.Z; + let w = value1.W; + let num = value2.X * value2.X + value2.Y * value2.Y + value2.Z * value2.Z + value2.W * value2.W; + let num2 = 1.f / num; + let num3 = (0.f - value2.X) * num2; + let num4 = (0.f - value2.Y) * num2; + let num5 = (0.f - value2.Z) * num2; + let num6 = value2.W * num2; + let num7 = y * num5 - z * num4; + let num8 = z * num3 - x * num5; + let num9 = x * num4 - y * num3; + let num10 = x * num3 + y * num4 + z * num5; + Quaternion( + x * num6 + num3 * w + num7, + y * num6 + num4 * w + num8, + z * num6 + num5 * w + num9, + w * num6 - num10 + ) + + static member Dot(quaternion1 : Quaternion, quaternion2 : Quaternion) : single = + quaternion1.X * quaternion2.X + quaternion1.Y * quaternion2.Y + quaternion1.Z * quaternion2.Z + quaternion1.W * quaternion2.W + + static member Inverse(value : Quaternion) : Quaternion = + let num = value.X * value.X + value.Y * value.Y + value.Z * value.Z + value.W * value.W; + let num2 = 1.f / num; + Quaternion( + (0.f - value.X) * num2, + (0.f - value.Y) * num2, + (0.f - value.Z) * num2, + value.W * num2 + ) + + static member Multiply(value1 : Quaternion, value2 : Quaternion) : Quaternion = + let x = value1.X; + let y = value1.Y; + let z = value1.Z; + let w = value1.W; + let x2 = value2.X; + let y2 = value2.Y; + let z2 = value2.Z; + let w2 = value2.W; + let num = y * z2 - z * y2; + let num2 = z * x2 - x * z2; + let num3 = x * y2 - y * x2; + let num4 = x * x2 + y * y2 + z * z2; + Quaternion( + x * w2 + x2 * w + num, + y * w2 + y2 * w + num2, + z * w2 + z2 * w + num3, + w * w2 - num4 + ) + + static member Multiply(value1 : Quaternion, value2 : single) : Quaternion = + Quaternion( + value1.X * value2, + value1.Y * value2, + value1.Z * value2, + value1.W * value2 + ) + + // -------------------------------- + // Operators of Quaternion + + static member (+) (left:Quaternion, right:Quaternion) : Quaternion = + Quaternion.Add(left, right) + + static member (/) (left:Quaternion, right:Quaternion) : Quaternion = + Quaternion.Divide(left, right) + + static member (*) (left:Quaternion, right:Quaternion) : Quaternion = + Quaternion.Multiply(left, right) + + static member (*) (left:Quaternion, right:single) : Quaternion = + Quaternion.Multiply(left, right) \ No newline at end of file diff --git a/tests/Main/Fable.Tests.fsproj b/tests/Main/Fable.Tests.fsproj index e710037ddb..294b6bc6a7 100644 --- a/tests/Main/Fable.Tests.fsproj +++ b/tests/Main/Fable.Tests.fsproj @@ -60,6 +60,7 @@ + diff --git a/tests/Main/Main.fs b/tests/Main/Main.fs index 2de3bb97aa..73c3dd9cba 100644 --- a/tests/Main/Main.fs +++ b/tests/Main/Main.fs @@ -36,6 +36,7 @@ let allTests = SeqExpressions.tests Seqs.tests Sets.tests + SystemNumerics.tests Strings.tests Sudoku.tests TailCalls.tests diff --git a/tests/Main/SystemNumericsTest.fs b/tests/Main/SystemNumericsTest.fs new file mode 100644 index 0000000000..5d316db2f0 --- /dev/null +++ b/tests/Main/SystemNumericsTest.fs @@ -0,0 +1,35 @@ +module Fable.Tests.SystemNumerics + +open System +open Util.Testing +#if FABLE_COMPILER +open Fable.Core.JsInterop +#endif + + + +let tests = + testList "System.Numerics" [ + + + // vector3 + + testCase "Vector3.Zero works" <| fun () -> + let v1 = System.Numerics.Vector3(0.f, 0.f, 0.f) + v1 |> equal System.Numerics.Vector3.Zero + [| v1.X; v1.Y; v1.Z |] |> equal [| 0.f; 0.f; 0.f |] + + + testCase "Vector3.One works" <| fun () -> + let v1 = System.Numerics.Vector3(1.f, 1.f, 1.f) + v1 |> equal System.Numerics.Vector3.One + [| v1.X; v1.Y; v1.Z |] |> equal [| 1.f; 1.f; 1.f |] + + + // Quaternion + + testCase "Quaternion.Identity works" <| fun () -> + let q1 = System.Numerics.Quaternion(0.f, 0.f, 0.f, 1.f) + q1 |> equal System.Numerics.Quaternion.Identity + [| q1.X; q1.Y; q1.Z; q1.W |] |> equal [| 0.f; 0.f; 0.f; 1.f |] +] \ No newline at end of file From 33979c4e7c854da31d067c150f1bcd9851b21cd1 Mon Sep 17 00:00:00 2001 From: Lukas Rieger Date: Wed, 14 Nov 2018 16:05:19 +0100 Subject: [PATCH 02/21] v3 / q use public fields, not properties --- src/js/fable-core/System.Numerics.fs | 64 ++++++++++++++++------------ 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/src/js/fable-core/System.Numerics.fs b/src/js/fable-core/System.Numerics.fs index c3c6f4734b..348eaf3b85 100644 --- a/src/js/fable-core/System.Numerics.fs +++ b/src/js/fable-core/System.Numerics.fs @@ -5,23 +5,24 @@ -[] -type Vector3(x : single, y : single, z : single) = +type Vector3 = + struct - new (value : single) = Vector3(value, value, value) + val mutable public X : single + val mutable public Y : single + val mutable public Z : single - member __.X = x - member __.Y = y - member __.Z = z + new (value : single) = { X = value; Y = value; Z = value } + new (x : single, y : single, z : single) = { X = x; Y = y; Z = z } - member __.Abs() = Vector3(System.Math.Abs(x), System.Math.Abs(y), System.Math.Abs(z)) + member this.Abs() = Vector3(System.Math.Abs(this.X), System.Math.Abs(this.Y), System.Math.Abs(this.Z)) - member __.CopyTo(arr : single array, index : int) = - arr.[index + 0] <- x - arr.[index + 1] <- y - arr.[index + 2] <- z + member this.CopyTo(arr : single array, index : int) = + arr.[index + 0] <- this.X + arr.[index + 1] <- this.Y + arr.[index + 2] <- this.Z - member __.CopyTo(arr : single array) = __.CopyTo(arr, 0) + member this.CopyTo(arr : single array) = this.CopyTo(arr, 0) //member __.Equals(other : Vector3) = // x = other.X && @@ -37,6 +38,7 @@ type Vector3(x : single, y : single, z : single) = //override __.GetHashCode() = // hash(x, y, z) + // -------------------------------- // Static members of Vector3 @@ -85,6 +87,7 @@ type Vector3(x : single, y : single, z : single) = let num5 = num2 * num2 + num3 * num3 + num4 * num4; num5 + // -------------------------------- // Operators of Vector3 @@ -96,32 +99,34 @@ type Vector3(x : single, y : single, z : single) = static member (/) (left:Vector3, right:single) : Vector3 = Vector3.Divide(left, right) + end + +type Quaternion = + struct + val mutable public X : single + val mutable public Y : single + val mutable public Z : single + val mutable public W : single -[] -type Quaternion(x : single, y : single, z : single, w : single) = - + new (x : single, y : single, z : single, w : single) = { X = x; Y = y; Z = z; W = w } new(vectorPart : Vector3, scalarPart : single) = Quaternion(vectorPart.X, vectorPart.Y, vectorPart.Z, scalarPart) - member __.X = x - member __.Y = y - member __.Z = z - member __.W = w - - member __.IsIdentity = - x = 0.f && - y = 0.f && - z = 0.f && - w = 1.f + member this.IsIdentity = + this.X = 0.f && + this.Y = 0.f && + this.Z = 0.f && + this.W = 1.f member this.Length() : single = let ls = this.LengthSquared() single ( System.Math.Sqrt(float ls) ) - member __.LengthSquared() : single = - x * x + y * y + z * z + w * w + member this.LengthSquared() : single = + this.X * this.X + this.Y * this.Y + this.Z * this.Z + this.W * this.W + // -------------------------------- // static members of Quaternion @@ -226,6 +231,7 @@ type Quaternion(x : single, y : single, z : single, w : single) = value1.W * value2 ) + // -------------------------------- // Operators of Quaternion @@ -239,4 +245,6 @@ type Quaternion(x : single, y : single, z : single, w : single) = Quaternion.Multiply(left, right) static member (*) (left:Quaternion, right:single) : Quaternion = - Quaternion.Multiply(left, right) \ No newline at end of file + Quaternion.Multiply(left, right) + + end \ No newline at end of file From 04f4fc654dfc518bfefecd617420ae1c63902ce9 Mon Sep 17 00:00:00 2001 From: Lukas Rieger Date: Wed, 14 Nov 2018 16:13:40 +0100 Subject: [PATCH 03/21] add transforms for ILFieldGet / ILFieldSet --- .../Fable.Compiler/Transforms/FSharp2Fable.fs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs b/src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs index b6de78b878..ad06de9a0c 100644 --- a/src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs +++ b/src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs @@ -493,6 +493,7 @@ let private transformExpr (com: IFableCompiler) (ctx: Context) fsExpr = | _ -> return failwith "makeFunctionArgs returns args with different length" // Getters and Setters + | BasicPatterns.FSharpFieldGet(callee, calleeType, field) -> let! callee = transformExprOpt com ctx callee let callee = @@ -502,6 +503,17 @@ let private transformExpr (com: IFableCompiler) (ctx: Context) fsExpr = let kind = Fable.FieldGet(field.Name, field.IsMutable, makeType com Map.empty field.FieldType) let typ = makeType com ctx.GenericArgs fsExpr.Type return Fable.Get(callee, kind, typ, makeRangeFrom fsExpr) + + | BasicPatterns.ILFieldGet(callee, calleeType, field) -> + let! callee = transformExprOpt com ctx callee + let callee = + match callee with + | Some callee -> callee + | None -> entityRef com calleeType.TypeDefinition + let fsField = calleeType.TypeDefinition.FSharpFields |> Seq.filter (fun f -> f.Name = field) |> Seq.exactlyOne + let kind = Fable.FieldGet(field, true, makeType com Map.empty fsField.FieldType) + let typ = makeType com ctx.GenericArgs fsExpr.Type + return Fable.Get(callee, kind, typ, makeRangeFrom fsExpr) | BasicPatterns.TupleGet(_tupleType, tupleElemIndex, tupleExpr) -> let! tupleExpr = transformExpr com ctx tupleExpr @@ -540,6 +552,16 @@ let private transformExpr (com: IFableCompiler) (ctx: Context) fsExpr = | None -> entityRef com calleeType.TypeDefinition return Fable.Set(callee, Fable.FieldSet(field.Name, makeType com Map.empty field.FieldType), value, makeRangeFrom fsExpr) + | BasicPatterns.ILFieldSet(callee, calleeType, field, value) -> + let! callee = transformExprOpt com ctx callee + let! value = transformExpr com ctx value + let callee = + match callee with + | Some callee -> callee + | None -> entityRef com calleeType.TypeDefinition + let fsField = calleeType.TypeDefinition.FSharpFields |> Seq.filter (fun f -> f.Name = field) |> Seq.exactlyOne + return Fable.Set(callee, Fable.FieldSet(field, makeType com Map.empty fsField.FieldType), value, makeRangeFrom fsExpr) + | BasicPatterns.UnionCaseTag(unionExpr, _unionType) -> let! unionExpr = transformExpr com ctx unionExpr return Fable.Get(unionExpr, Fable.UnionTag, Fable.Any, makeRangeFrom fsExpr) From 38fc343348ed9d2350ec90026c7a7cbc7e13ecb8 Mon Sep 17 00:00:00 2001 From: Lukas Rieger Date: Wed, 14 Nov 2018 16:44:08 +0100 Subject: [PATCH 04/21] ILFieldGet / Set --- .../Fable.Compiler/Transforms/FSharp2Fable.fs | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs b/src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs index ad06de9a0c..455aebb964 100644 --- a/src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs +++ b/src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs @@ -503,17 +503,6 @@ let private transformExpr (com: IFableCompiler) (ctx: Context) fsExpr = let kind = Fable.FieldGet(field.Name, field.IsMutable, makeType com Map.empty field.FieldType) let typ = makeType com ctx.GenericArgs fsExpr.Type return Fable.Get(callee, kind, typ, makeRangeFrom fsExpr) - - | BasicPatterns.ILFieldGet(callee, calleeType, field) -> - let! callee = transformExprOpt com ctx callee - let callee = - match callee with - | Some callee -> callee - | None -> entityRef com calleeType.TypeDefinition - let fsField = calleeType.TypeDefinition.FSharpFields |> Seq.filter (fun f -> f.Name = field) |> Seq.exactlyOne - let kind = Fable.FieldGet(field, true, makeType com Map.empty fsField.FieldType) - let typ = makeType com ctx.GenericArgs fsExpr.Type - return Fable.Get(callee, kind, typ, makeRangeFrom fsExpr) | BasicPatterns.TupleGet(_tupleType, tupleElemIndex, tupleExpr) -> let! tupleExpr = transformExpr com ctx tupleExpr @@ -552,16 +541,6 @@ let private transformExpr (com: IFableCompiler) (ctx: Context) fsExpr = | None -> entityRef com calleeType.TypeDefinition return Fable.Set(callee, Fable.FieldSet(field.Name, makeType com Map.empty field.FieldType), value, makeRangeFrom fsExpr) - | BasicPatterns.ILFieldSet(callee, calleeType, field, value) -> - let! callee = transformExprOpt com ctx callee - let! value = transformExpr com ctx value - let callee = - match callee with - | Some callee -> callee - | None -> entityRef com calleeType.TypeDefinition - let fsField = calleeType.TypeDefinition.FSharpFields |> Seq.filter (fun f -> f.Name = field) |> Seq.exactlyOne - return Fable.Set(callee, Fable.FieldSet(field, makeType com Map.empty fsField.FieldType), value, makeRangeFrom fsExpr) - | BasicPatterns.UnionCaseTag(unionExpr, _unionType) -> let! unionExpr = transformExpr com ctx unionExpr return Fable.Get(unionExpr, Fable.UnionTag, Fable.Any, makeRangeFrom fsExpr) @@ -699,8 +678,28 @@ let private transformExpr (com: IFableCompiler) (ctx: Context) fsExpr = | BasicPatterns.AddressOf(expr) -> let! expr = transformExpr com ctx expr return expr + + //| BasicPatterns.ILFieldGet(callee, calleeType, field) -> + // let! callee = transformExprOpt com ctx callee + // let callee = + // match callee with + // | Some callee -> callee + // | None -> entityRef com calleeType.TypeDefinition + // let fsField = calleeType.TypeDefinition.FSharpFields |> Seq.filter (fun f -> f.Name = field) |> Seq.exactlyOne + // let kind = Fable.FieldGet(field, true, makeType com Map.empty fsField.FieldType) + // let typ = makeType com ctx.GenericArgs fsExpr.Type + // return Fable.Get(callee, kind, typ, makeRangeFrom fsExpr) - // | BasicPatterns.ILFieldSet _ + | BasicPatterns.ILFieldSet(callee, calleeType, field, value) -> + let! callee = transformExprOpt com ctx callee + let! value = transformExpr com ctx value + let callee = + match callee with + | Some callee -> callee + | None -> entityRef com calleeType.TypeDefinition + let fsField = calleeType.TypeDefinition.FSharpFields |> Seq.filter (fun f -> f.Name = field) |> Seq.exactlyOne + return Fable.Set(callee, Fable.FieldSet(field, makeType com Map.empty fsField.FieldType), value, makeRangeFrom fsExpr) + // | BasicPatterns.AddressSet _ // | BasicPatterns.ILAsm _ | expr -> From e5cf89477a150793e72897a8725e5fe4fde2c7a6 Mon Sep 17 00:00:00 2001 From: Lukas Rieger Date: Thu, 15 Nov 2018 11:13:20 +0100 Subject: [PATCH 05/21] ILFieldGet --- .../Fable.Compiler/Transforms/FSharp2Fable.fs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs b/src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs index 455aebb964..157f051970 100644 --- a/src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs +++ b/src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs @@ -679,16 +679,16 @@ let private transformExpr (com: IFableCompiler) (ctx: Context) fsExpr = let! expr = transformExpr com ctx expr return expr - //| BasicPatterns.ILFieldGet(callee, calleeType, field) -> - // let! callee = transformExprOpt com ctx callee - // let callee = - // match callee with - // | Some callee -> callee - // | None -> entityRef com calleeType.TypeDefinition - // let fsField = calleeType.TypeDefinition.FSharpFields |> Seq.filter (fun f -> f.Name = field) |> Seq.exactlyOne - // let kind = Fable.FieldGet(field, true, makeType com Map.empty fsField.FieldType) - // let typ = makeType com ctx.GenericArgs fsExpr.Type - // return Fable.Get(callee, kind, typ, makeRangeFrom fsExpr) + | BasicPatterns.ILFieldGet(callee, calleeType, field) -> + let! callee = transformExprOpt com ctx callee + let callee = + match callee with + | Some callee -> callee + | None -> entityRef com calleeType.TypeDefinition + let fsField = calleeType.TypeDefinition.FSharpFields |> Seq.filter (fun f -> f.Name = field) |> Seq.exactlyOne + let kind = Fable.FieldGet(field, true, makeType com Map.empty fsField.FieldType) + let typ = makeType com ctx.GenericArgs fsExpr.Type + return Fable.Get(callee, kind, typ, makeRangeFrom fsExpr) | BasicPatterns.ILFieldSet(callee, calleeType, field, value) -> let! callee = transformExprOpt com ctx callee From 64b2b57a9a881f3a2e585bd393da5c0416721dd0 Mon Sep 17 00:00:00 2001 From: Lukas Rieger Date: Fri, 16 Nov 2018 15:32:26 +0100 Subject: [PATCH 06/21] add (hopefully) correct transforms for ILFieldGet / ILFieldSet --- .../Fable.Compiler/Transforms/FSharp2Fable.fs | 39 +++++++++++-------- .../Fable.Compiler/Transforms/Fable2Babel.fs | 2 + .../Fable.Compiler/Transforms/Replacements.fs | 15 +++++++ .../Transforms/Transforms.Util.fs | 2 + 4 files changed, 41 insertions(+), 17 deletions(-) diff --git a/src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs b/src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs index 157f051970..a76528234e 100644 --- a/src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs +++ b/src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs @@ -661,6 +661,7 @@ let private transformExpr (com: IFableCompiler) (ctx: Context) fsExpr = let typ = makeType com ctx.GenericArgs fsExpr.Type return Fable.DecisionTreeSuccess(targetIndex, boundValues, typ) + // read a static field (Example: Decimal.Zero) | BasicPatterns.ILFieldGet(None, ownerTyp, fieldName) -> let ownerTyp = makeType com ctx.GenericArgs ownerTyp let typ = makeType com ctx.GenericArgs fsExpr.Type @@ -670,35 +671,39 @@ let private transformExpr (com: IFableCompiler) (ctx: Context) fsExpr = return sprintf "Cannot compile ILFieldGet(%A, %s)" ownerTyp fieldName |> addErrorAndReturnNull com ctx.InlinePath (makeRangeFrom fsExpr) - | BasicPatterns.Quote _ -> - return "Quotes are not currently supported by Fable" - |> addErrorAndReturnNull com ctx.InlinePath (makeRangeFrom fsExpr) - - // TODO: Ask. I see this when accessing Result types (all structs?) - | BasicPatterns.AddressOf(expr) -> - let! expr = transformExpr com ctx expr - return expr - - | BasicPatterns.ILFieldGet(callee, calleeType, field) -> - let! callee = transformExprOpt com ctx callee + // read a member field (Example: Vector3.X) + | BasicPatterns.ILFieldGet(Some callee, calleeType, fieldName) + when (Replacements.isILMemberFieldSupported (makeType com ctx.GenericArgs fsExpr.Type) fieldName) -> + let! callee = transformExprOpt com ctx (Some callee) let callee = match callee with | Some callee -> callee | None -> entityRef com calleeType.TypeDefinition - let fsField = calleeType.TypeDefinition.FSharpFields |> Seq.filter (fun f -> f.Name = field) |> Seq.exactlyOne - let kind = Fable.FieldGet(field, true, makeType com Map.empty fsField.FieldType) + let typ = makeType com ctx.GenericArgs fsExpr.Type + let kind = Fable.FieldGet(fieldName, true, typ) let typ = makeType com ctx.GenericArgs fsExpr.Type return Fable.Get(callee, kind, typ, makeRangeFrom fsExpr) - | BasicPatterns.ILFieldSet(callee, calleeType, field, value) -> - let! callee = transformExprOpt com ctx callee + // write a member field (example: Vector3.X) + | BasicPatterns.ILFieldSet(Some callee, calleeType, fieldName, value) + when (Replacements.isILMemberFieldSupported (makeType com ctx.GenericArgs fsExpr.Type) fieldName) -> + let! callee = transformExprOpt com ctx (Some callee) let! value = transformExpr com ctx value let callee = match callee with | Some callee -> callee | None -> entityRef com calleeType.TypeDefinition - let fsField = calleeType.TypeDefinition.FSharpFields |> Seq.filter (fun f -> f.Name = field) |> Seq.exactlyOne - return Fable.Set(callee, Fable.FieldSet(field, makeType com Map.empty fsField.FieldType), value, makeRangeFrom fsExpr) + let typ = makeType com ctx.GenericArgs fsExpr.Type + return Fable.Set(callee, Fable.FieldSet(fieldName, typ), value, makeRangeFrom fsExpr) + + | BasicPatterns.Quote _ -> + return "Quotes are not currently supported by Fable" + |> addErrorAndReturnNull com ctx.InlinePath (makeRangeFrom fsExpr) + + // TODO: Ask. I see this when accessing Result types (all structs?) + | BasicPatterns.AddressOf(expr) -> + let! expr = transformExpr com ctx expr + return expr // | BasicPatterns.AddressSet _ // | BasicPatterns.ILAsm _ diff --git a/src/dotnet/Fable.Compiler/Transforms/Fable2Babel.fs b/src/dotnet/Fable.Compiler/Transforms/Fable2Babel.fs index 9d56bedb8c..45d0319c7e 100644 --- a/src/dotnet/Fable.Compiler/Transforms/Fable2Babel.fs +++ b/src/dotnet/Fable.Compiler/Transforms/Fable2Babel.fs @@ -873,6 +873,8 @@ module Util = | Replacements.BclUInt64 -> jsInstanceof (coreValue com ctx "Long" "default") expr | Replacements.BclDecimal -> jsInstanceof (coreValue com ctx "Decimal" "default") expr | Replacements.BclBigInt -> coreLibCall com ctx "BigInt" "isBigInt" [|com.TransformAsExpr(ctx, expr)|] + | Replacements.BclQuaternion -> jsInstanceof (coreValue com ctx "Quaternion" "default") expr + | Replacements.BclVector3 -> jsInstanceof (coreValue com ctx "Vector3" "default") expr | Replacements.BclHashSet _ | Replacements.BclDictionary _ | Replacements.FSharpSet _ diff --git a/src/dotnet/Fable.Compiler/Transforms/Replacements.fs b/src/dotnet/Fable.Compiler/Transforms/Replacements.fs index 520a7764bc..cfa76900fd 100644 --- a/src/dotnet/Fable.Compiler/Transforms/Replacements.fs +++ b/src/dotnet/Fable.Compiler/Transforms/Replacements.fs @@ -127,6 +127,8 @@ type BuiltinType = | BclUInt64 | BclDecimal | BclBigInt + | BclQuaternion + | BclVector3 | BclHashSet of Type | BclDictionary of key:Type * value:Type | FSharpSet of Type @@ -147,6 +149,8 @@ let (|Builtin|_|) = function | Some Types.decimal, _ | Some "Microsoft.FSharp.Core.decimal`1", _ -> Some BclDecimal | Some Types.bigint, _ -> Some BclBigInt + | Some Types.quaternion, _ -> Some BclQuaternion + | Some Types.vector3, _ -> Some BclVector3 | Some Types.fsharpSet, [t] -> Some(FSharpSet(t)) | Some Types.fsharpMap, [k;v] -> Some(FSharpMap(k,v)) | Some Types.hashset, [t] -> Some(BclHashSet(t)) @@ -228,6 +232,8 @@ let coreModFor = function | BclUInt64 -> "Long" | BclDecimal -> "Decimal" | BclBigInt -> "BigInt" + | BclQuaternion _ -> "Quaternion" + | BclVector3 _ -> "Vector3" | BclTimeSpan -> "Int32" | FSharpSet _ -> "Set" | FSharpMap _ -> "Map" @@ -2503,6 +2509,7 @@ let partialApplyAtRuntime t arity (fn: Expr) (args: Expr list) = let args = NewArray(ArrayValues args, Any) |> Value Helper.CoreCall("Util", "partialApply", t, [makeIntConst arity; fn; args]) +/// try to map a static field (e.g. Decimal.Zero) let tryField returnTyp ownerTyp fieldName = match ownerTyp, fieldName with | Builtin BclDecimal, "Zero" -> makeIntConst 0 |> makeDecimalFromExpr returnTyp |> Some @@ -2516,6 +2523,14 @@ let tryField returnTyp ownerTyp fieldName = Helper.CoreCall(coreModFor BclDateTimeOffset, Naming.lowerFirst fieldName, returnTyp, []) |> Some | _ -> None +// this is queried when an IL member field is read / written. +// at the moment member fields are only supported for Vector3 / Quaternion, all other supported BCL types expose properties instead of fields. +let isILMemberFieldSupported ownerTyp _fieldName = + match ownerTyp with + | Builtin BclQuaternion + | Builtin BclVector3 -> true + | _ -> false + let private replacedModules = dict [ "System.Math", operators diff --git a/src/dotnet/Fable.Compiler/Transforms/Transforms.Util.fs b/src/dotnet/Fable.Compiler/Transforms/Transforms.Util.fs index 3b7ad0f79d..269c2ca08c 100644 --- a/src/dotnet/Fable.Compiler/Transforms/Transforms.Util.fs +++ b/src/dotnet/Fable.Compiler/Transforms/Transforms.Util.fs @@ -44,6 +44,8 @@ module Types = let [] float64 = "System.Double" let [] decimal = "System.Decimal" let [] bigint = "System.Numerics.BigInteger" + let [] quaternion = "System.Numerics.Quaternion" + let [] vector3 = "System.Numerics.Vector3" let [] regex = "System.Text.RegularExpressions.Regex" let [] unit = "Microsoft.FSharp.Core.Unit" let [] option = "Microsoft.FSharp.Core.FSharpOption`1" From 7b472ed0a3eca4efaf1f011ceb4d6ee396f1afc6 Mon Sep 17 00:00:00 2001 From: Lukas Rieger Date: Fri, 16 Nov 2018 15:45:21 +0100 Subject: [PATCH 07/21] oops --- src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs b/src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs index a76528234e..8b68e5bbc2 100644 --- a/src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs +++ b/src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs @@ -673,7 +673,7 @@ let private transformExpr (com: IFableCompiler) (ctx: Context) fsExpr = // read a member field (Example: Vector3.X) | BasicPatterns.ILFieldGet(Some callee, calleeType, fieldName) - when (Replacements.isILMemberFieldSupported (makeType com ctx.GenericArgs fsExpr.Type) fieldName) -> + when (Replacements.isILMemberFieldSupported (makeType com ctx.GenericArgs calleeType) fieldName) -> let! callee = transformExprOpt com ctx (Some callee) let callee = match callee with @@ -686,7 +686,7 @@ let private transformExpr (com: IFableCompiler) (ctx: Context) fsExpr = // write a member field (example: Vector3.X) | BasicPatterns.ILFieldSet(Some callee, calleeType, fieldName, value) - when (Replacements.isILMemberFieldSupported (makeType com ctx.GenericArgs fsExpr.Type) fieldName) -> + when (Replacements.isILMemberFieldSupported (makeType com ctx.GenericArgs calleeType) fieldName) -> let! callee = transformExprOpt com ctx (Some callee) let! value = transformExpr com ctx value let callee = From d40283962ea32ab49198f5859ce896782cf62b7a Mon Sep 17 00:00:00 2001 From: Lukas Rieger Date: Fri, 16 Nov 2018 16:00:40 +0100 Subject: [PATCH 08/21] add tests for field read / write --- tests/Main/SystemNumericsTest.fs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/Main/SystemNumericsTest.fs b/tests/Main/SystemNumericsTest.fs index 5d316db2f0..5e33437a57 100644 --- a/tests/Main/SystemNumericsTest.fs +++ b/tests/Main/SystemNumericsTest.fs @@ -24,6 +24,15 @@ let tests = let v1 = System.Numerics.Vector3(1.f, 1.f, 1.f) v1 |> equal System.Numerics.Vector3.One [| v1.X; v1.Y; v1.Z |] |> equal [| 1.f; 1.f; 1.f |] + + + testCase "Vector3 writing fields works" <| fun () -> + let mutable v1 = System.Numerics.Vector3(1.f, 1.f, 1.f) + v1.X <- 5.f + v1.X |> equal 5.f + v1.Y <- 6.f + v1.Z <- 7.f + v1 |> equal (System.Numerics.Vector3(5.f, 6.f, 7.f)) // Quaternion @@ -32,4 +41,14 @@ let tests = let q1 = System.Numerics.Quaternion(0.f, 0.f, 0.f, 1.f) q1 |> equal System.Numerics.Quaternion.Identity [| q1.X; q1.Y; q1.Z; q1.W |] |> equal [| 0.f; 0.f; 0.f; 1.f |] + + + testCase "Quaternion writing fields works" <| fun () -> + let mutable q1 = System.Numerics.Quaternion(1.f, 1.f, 1.f, 1.f) + q1.X <- 5.f + q1.X |> equal 5.f + q1.Y <- 6.f + q1.Z <- 7.f + q1.W <- 8.f + q1 |> equal (System.Numerics.Quaternion(5.f, 6.f, 7.f, 8.f)) ] \ No newline at end of file From 6b0db68042378ac90b94c56ce617d54345ed6f70 Mon Sep 17 00:00:00 2001 From: Lukas Rieger Date: Fri, 21 Dec 2018 18:01:51 +0100 Subject: [PATCH 09/21] minor comment --- src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs b/src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs index a3346b7e69..44fc1dfd48 100644 --- a/src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs +++ b/src/dotnet/Fable.Compiler/Transforms/FSharp2Fable.fs @@ -681,11 +681,7 @@ let private transformExpr (com: IFableCompiler) (ctx: Context) fsExpr = // read a member field (Example: Vector3.X) | BasicPatterns.ILFieldGet(Some callee, calleeType, fieldName) when (Replacements.isILMemberFieldSupported (makeType com ctx.GenericArgs calleeType) fieldName) -> - let! callee = transformExprOpt com ctx (Some callee) - let callee = - match callee with - | Some callee -> callee - | None -> entityRef com calleeType.TypeDefinition + let! callee = transformExpr com ctx callee let typ = makeType com ctx.GenericArgs fsExpr.Type let kind = Fable.FieldGet(fieldName, true, typ) let typ = makeType com ctx.GenericArgs fsExpr.Type @@ -694,12 +690,8 @@ let private transformExpr (com: IFableCompiler) (ctx: Context) fsExpr = // write a member field (example: Vector3.X) | BasicPatterns.ILFieldSet(Some callee, calleeType, fieldName, value) when (Replacements.isILMemberFieldSupported (makeType com ctx.GenericArgs calleeType) fieldName) -> - let! callee = transformExprOpt com ctx (Some callee) + let! callee = transformExpr com ctx callee let! value = transformExpr com ctx value - let callee = - match callee with - | Some callee -> callee - | None -> entityRef com calleeType.TypeDefinition let typ = makeType com ctx.GenericArgs fsExpr.Type return Fable.Set(callee, Fable.FieldSet(fieldName, typ), value, makeRangeFrom fsExpr) From 31fbbbcbdfd29e94805dc739149d84092f00d526 Mon Sep 17 00:00:00 2001 From: Lukas Rieger Date: Fri, 21 Dec 2018 18:04:42 +0100 Subject: [PATCH 10/21] adapt to rename fable-core => fable-library --- src/js/{fable-core => fable-library}/System.Numerics.fs | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/js/{fable-core => fable-library}/System.Numerics.fs (100%) diff --git a/src/js/fable-core/System.Numerics.fs b/src/js/fable-library/System.Numerics.fs similarity index 100% rename from src/js/fable-core/System.Numerics.fs rename to src/js/fable-library/System.Numerics.fs From 8271537b1809a6c90fa599233494acf913657311 Mon Sep 17 00:00:00 2001 From: Lukas Rieger Date: Fri, 21 Dec 2018 18:42:48 +0100 Subject: [PATCH 11/21] implement some more members of Vector3 --- src/js/fable-library/System.Numerics.fs | 117 +++++++++++++++++++++++- 1 file changed, 116 insertions(+), 1 deletion(-) diff --git a/src/js/fable-library/System.Numerics.fs b/src/js/fable-library/System.Numerics.fs index 348eaf3b85..5d9a95552f 100644 --- a/src/js/fable-library/System.Numerics.fs +++ b/src/js/fable-library/System.Numerics.fs @@ -1,9 +1,19 @@ namespace System.Numerics +open System + // contains the types Vector3 and Quaternion. // feel free to add the rest as required +// WIP Notes: +// need to check if auto-generated equality is OK +// Vector3: +// TODO ToString +// TODO Transform +// Quaternion: +// TODO lots of stuff + type Vector3 = struct @@ -15,7 +25,7 @@ type Vector3 = new (value : single) = { X = value; Y = value; Z = value } new (x : single, y : single, z : single) = { X = x; Y = y; Z = z } - member this.Abs() = Vector3(System.Math.Abs(this.X), System.Math.Abs(this.Y), System.Math.Abs(this.Z)) + //member this.Abs() = Vector3(System.Math.Abs(this.X), System.Math.Abs(this.Y), System.Math.Abs(this.Z)) member this.CopyTo(arr : single array, index : int) = arr.[index + 0] <- this.X @@ -24,6 +34,36 @@ type Vector3 = member this.CopyTo(arr : single array) = this.CopyTo(arr, 0) + member this.Length() : single = + sqrt( this.X * this.X + this.Y * this.Y + this.Z * this.Z ) + + member this.LengthSquared() : single = + this.X * this.X + this.Y * this.Y + this.Z * this.Z + + override this.ToString() = + // note: net-fx passes CultureInfo.CurrentCulture + this.ToString("G", null) + + member this.ToString(format : string) = + // note: net-fx passes CultureInfo.CurrentCulture + this.ToString(format, null) + + member this.ToString(format : string, formatProvider : IFormatProvider) = + let stringBuilder = new System.Text.StringBuilder() + // note: net-fx uses System.Globalization.NumberFormatInfo.GetInstance(formatProvider).NumberGroupSeparator + let numberGroupSeparator = "." + stringBuilder.Append('<') + //.Append(((IFormattable)X).ToString(format, formatProvider)) + //.Append(numberGroupSeparator) + //.Append(' ') + //.Append(((IFormattable)Y).ToString(format, formatProvider)) + //.Append(numberGroupSeparator) + //.Append(' ') + //.Append(((IFormattable)Z).ToString(format, formatProvider)) + //.Append('>') + |> ignore + stringBuilder.ToString() + //member __.Equals(other : Vector3) = // x = other.X && // y = other.Y && @@ -50,6 +90,9 @@ type Vector3 = static member Zero = Vector3(0.f, 0.f, 0.f) + static member Abs(value : Vector3) : Vector3 = + Vector3(System.Math.Abs(value.X), System.Math.Abs(value.Y), System.Math.Abs(value.Z)) + static member Add(left : Vector3, right : Vector3) = Vector3(left.X + right.X, left.Y + right.Y, left.Z + right.Z) @@ -58,6 +101,18 @@ type Vector3 = static member Divide(left : Vector3, right : single) = Vector3(left.X / right, left.Y / right, left.Z / right) + + static member Multiply(left : Vector3, right : Vector3) = + Vector3(left.X * right.X, left.Y * right.Y, left.Z * right.Z) + + static member Multiply(left : Vector3, right : single) = + Vector3(left.X * right, left.Y * right, left.Z * right) + + static member Multiply(left : single, right : Vector3) = + Vector3(left * right.X, left * right.Y, left * right.Z) + + static member Subtract(left : Vector3, right : Vector3) = + Vector3(left.X - right.X, left.Y - right.Y, left.Z - right.Z) static member Clamp(value : Vector3, min : Vector3, max : Vector3) = let inline clamp v min max = @@ -87,6 +142,45 @@ type Vector3 = let num5 = num2 * num2 + num3 * num3 + num4 * num4; num5 + static member Dot(vector1 : Vector3, vector2 : Vector3) : single = + vector1.X * vector2.X + vector1.Y * vector2.Y + vector1.Z * vector2.Z + + static member Lerp(value1 : Vector3, value2 : Vector3, amount : single) : Vector3 = + Vector3(value1.X + (value2.X - value1.X) * amount, value1.Y + (value2.Y - value1.Y) * amount, value1.Z + (value2.Z - value1.Z) * amount) + + static member Max(value1 : Vector3, value2 : Vector3) : Vector3 = + let x = max value1.X value2.X + let y = max value1.Y value2.Y + let z = max value1.Z value2.Z + Vector3(x, y, z) + + static member Min(value1 : Vector3, value2 : Vector3) : Vector3 = + let x = min value1.X value2.X + let y = min value1.Y value2.Y + let z = min value1.Z value2.Z + Vector3(x, y, z) + + static member Negate(value : Vector3) : Vector3 = + Vector3.Zero - value + + static member Normalize(value : Vector3) : Vector3 = + let num = value.X * value.X + value.Y * value.Y + value.Z * value.Z + let num2 = sqrt (num) + Vector3(value.X / num2, value.Y / num2, value.Z / num2) + + static member Reflect(vector : Vector3, normal : Vector3) : Vector3 = + let num = vector.X * normal.X + vector.Y * normal.Y + vector.Z * normal.Z + let num2 = normal.X * num * 2.f + let num3 = normal.Y * num * 2.f + let num4 = normal.Z * num * 2.f + Vector3(vector.X - num2, vector.Y - num3, vector.Z - num4) + + static member SquareRoot(value : Vector3) : Vector3 = + let x = sqrt value.X + let y = sqrt value.Y + let z = sqrt value.Z + Vector3(x, y, z) + // -------------------------------- // Operators of Vector3 @@ -99,6 +193,27 @@ type Vector3 = static member (/) (left:Vector3, right:single) : Vector3 = Vector3.Divide(left, right) + + static member (==) (left:Vector3, right:single) : bool = + left.Equals(right) + + static member (!=) (left:Vector3, right:single) : bool = + not (left.Equals(right)) + + static member (*) (left:Vector3, right:Vector3) : Vector3 = + Vector3.Multiply(left, right) + + static member (*) (left:Vector3, right:single) : Vector3 = + Vector3.Multiply(left, right) + + static member (*) (left:single, right:Vector3) : Vector3 = + Vector3.Multiply(left, right) + + //static member (-) (value:Vector3) : Vector3 = + // Vector3.Negate(value) + + static member (-) (left:Vector3, right:Vector3) : Vector3 = + Vector3.Subtract(left, right) end type Quaternion = From 7dc6c314b44b29ec14653a521d63f6a766bfaf50 Mon Sep 17 00:00:00 2001 From: Lukas Rieger Date: Fri, 21 Dec 2018 18:57:01 +0100 Subject: [PATCH 12/21] wip comments --- src/js/fable-library/System.Numerics.fs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/js/fable-library/System.Numerics.fs b/src/js/fable-library/System.Numerics.fs index 5d9a95552f..819294cdff 100644 --- a/src/js/fable-library/System.Numerics.fs +++ b/src/js/fable-library/System.Numerics.fs @@ -13,6 +13,9 @@ open System // TODO Transform // Quaternion: // TODO lots of stuff +// for tests, take inspiration from +// - https://github.com/dotnet/corefx/blob/master/src/System.Numerics.Vectors/tests/QuaternionTests.cs +// - https://github.com/dotnet/corefx/blob/master/src/System.Numerics.Vectors/tests/Vector3Tests.cs type Vector3 = From c6a5b3acd9f464248af7e50d47ef12b51dbcbbac Mon Sep 17 00:00:00 2001 From: Lukas Rieger Date: Tue, 30 Apr 2019 14:40:05 +0200 Subject: [PATCH 13/21] fable-library was moved --- src/{js => }/fable-library/System.Numerics.fs | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{js => }/fable-library/System.Numerics.fs (100%) diff --git a/src/js/fable-library/System.Numerics.fs b/src/fable-library/System.Numerics.fs similarity index 100% rename from src/js/fable-library/System.Numerics.fs rename to src/fable-library/System.Numerics.fs From 1e3a33d630644c667f68b507f1d4385dbcd98324 Mon Sep 17 00:00:00 2001 From: Lukas Rieger Date: Tue, 7 May 2019 19:31:21 +0200 Subject: [PATCH 14/21] Vector3.ToString --- src/fable-library/System.Numerics.fs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/fable-library/System.Numerics.fs b/src/fable-library/System.Numerics.fs index 819294cdff..dea471c4fd 100644 --- a/src/fable-library/System.Numerics.fs +++ b/src/fable-library/System.Numerics.fs @@ -9,7 +9,6 @@ open System // WIP Notes: // need to check if auto-generated equality is OK // Vector3: -// TODO ToString // TODO Transform // Quaternion: // TODO lots of stuff @@ -56,14 +55,14 @@ type Vector3 = // note: net-fx uses System.Globalization.NumberFormatInfo.GetInstance(formatProvider).NumberGroupSeparator let numberGroupSeparator = "." stringBuilder.Append('<') - //.Append(((IFormattable)X).ToString(format, formatProvider)) - //.Append(numberGroupSeparator) - //.Append(' ') - //.Append(((IFormattable)Y).ToString(format, formatProvider)) - //.Append(numberGroupSeparator) - //.Append(' ') - //.Append(((IFormattable)Z).ToString(format, formatProvider)) - //.Append('>') + .Append(this.X.ToString(format, formatProvider)) + .Append(numberGroupSeparator) + .Append(' ') + .Append(this.Y.ToString(format, formatProvider)) + .Append(numberGroupSeparator) + .Append(' ') + .Append(this.Z.ToString(format, formatProvider)) + .Append('>') |> ignore stringBuilder.ToString() From 2cef223ea23a1bb2c8392bbed59251a35ab7ce19 Mon Sep 17 00:00:00 2001 From: Lukas Rieger Date: Mon, 5 Aug 2019 19:46:04 +0200 Subject: [PATCH 15/21] Fable.Tests: add PackageReference to System.Numerics.Vectors --- tests/Main/Fable.Tests.fsproj | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/tests/Main/Fable.Tests.fsproj b/tests/Main/Fable.Tests.fsproj index 8f80e205b7..5b00a175d4 100644 --- a/tests/Main/Fable.Tests.fsproj +++ b/tests/Main/Fable.Tests.fsproj @@ -1,4 +1,4 @@ - + netcoreapp2.0 Exe @@ -8,6 +8,7 @@ + @@ -71,19 +72,9 @@ - - - - + + + + From 444a9c67a218f0f076b86b9026233cef3256b38e Mon Sep 17 00:00:00 2001 From: Lukas Rieger Date: Mon, 5 Aug 2019 20:15:13 +0200 Subject: [PATCH 16/21] add support for nested "testList", fixes https://github.com/fable-compiler/Fable/issues/1873 --- tests/Main/Main.fs | 27 ++++++++++++++++++--------- tests/Main/Util/Util.fs | 10 +++++++--- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/tests/Main/Main.fs b/tests/Main/Main.fs index ffb1ec2e6e..90588646c6 100644 --- a/tests/Main/Main.fs +++ b/tests/Main/Main.fs @@ -56,14 +56,23 @@ open Fable.Core.JsInterop // but not available in node.js runtime importSideEffects "./js/polyfill" -let [] describe (name: string) (f: unit->unit) = jsNative -let [] it (msg: string) (f: unit->unit) = jsNative +let [] describe (name: string) (f: unit->unit) : unit = jsNative +let [] it (msg: string) (f: unit->unit) : unit = jsNative -let run () = - for (name, tests) in allTests do + +let rec flattenTest (test:Fable.Tests.Util.Testing.TestKind) : unit = + match test with + | Fable.Tests.Util.Testing.TestKind.TestList(name, tests) -> describe name (fun () -> - for (msg, test) in tests do - it msg (unbox test)) + for t in tests do + flattenTest t) + | Fable.Tests.Util.Testing.TestKind.TestCase (name, test) -> + it name (unbox test) + + +let run () = + for t in allTests do + flattenTest t run() #else @@ -72,8 +81,8 @@ open Expecto [] let main args = - Array.toList allTests - |> testList "All" - |> runTestsWithArgs defaultConfig args + Array.toList allTests + |> testList "All" + |> runTestsWithArgs defaultConfig args #endif diff --git a/tests/Main/Util/Util.fs b/tests/Main/Util/Util.fs index 229d2148fb..afd391762e 100644 --- a/tests/Main/Util/Util.fs +++ b/tests/Main/Util/Util.fs @@ -4,12 +4,16 @@ open System module Testing = #if FABLE_COMPILER + type TestKind = + | TestList of string * TestKind seq + | TestCase of (string*obj) + open Fable.Core open Fable.Core.Testing - let testList (name: string) (tests: (string * obj) seq) = name, tests - let testCase (msg: string) (test: unit->unit) = msg, box test - let testCaseAsync (msg: string) (test: unit->Async) = msg, box(fun () -> test () |> Async.StartAsPromise) + let testList (name: string) (tests: TestKind seq) = TestList( name, tests ) + let testCase (msg: string) (test: unit->unit) = TestCase( msg, box test ) + let testCaseAsync (msg: string) (test: unit->Async) = TestCase( msg, box(fun () -> test () |> Async.StartAsPromise) ) let equal expected actual: unit = Assert.AreEqual(actual, expected) let notEqual expected actual: unit = Assert.NotEqual(actual, expected) From 250c63e1acc2a5b733248c57ac7062646d3dd6cf Mon Sep 17 00:00:00 2001 From: Lukas Rieger Date: Mon, 5 Aug 2019 20:16:56 +0200 Subject: [PATCH 17/21] add equality tests --- tests/Main/SystemNumericsTest.fs | 51 +++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/tests/Main/SystemNumericsTest.fs b/tests/Main/SystemNumericsTest.fs index 5e33437a57..42170e032e 100644 --- a/tests/Main/SystemNumericsTest.fs +++ b/tests/Main/SystemNumericsTest.fs @@ -33,7 +33,32 @@ let tests = v1.Y <- 6.f v1.Z <- 7.f v1 |> equal (System.Numerics.Vector3(5.f, 6.f, 7.f)) - + + testList "Vector3 equality" [ + let v1 = System.Numerics.Vector3(1.f, 2.f, 3.f) + let v2 = System.Numerics.Vector3(1.f, 2.f, 3.f) + + yield testCase "operator (=) works" <| fun () -> + (v1 = v2) |> equal true + yield testCase ".Equals works" <| fun () -> + (v1.Equals v2) |> equal true + yield testCase "operator (<>) works" <| fun () -> + (v1 <> v2) |> equal false + ] + + testList "Vector3 inequality" [ + let v1 = System.Numerics.Vector3(1.f, 2.f, 3.f) + let v2 = System.Numerics.Vector3(4.f, 5.f, 6.f) + + yield testCase "operator (=) works" <| fun () -> + (v1 = v2) |> equal false + yield testCase ".Equals works" <| fun () -> + (v1.Equals v2) |> equal false + yield testCase "operator (<>) works" <| fun () -> + (v1 <> v2) |> equal false + ] + + // Quaternion @@ -51,4 +76,28 @@ let tests = q1.Z <- 7.f q1.W <- 8.f q1 |> equal (System.Numerics.Quaternion(5.f, 6.f, 7.f, 8.f)) + + testList "Quaternion equality" [ + let q1 = System.Numerics.Quaternion(1.f, 2.f, 3.f, 4.f) + let q2 = System.Numerics.Quaternion(1.f, 2.f, 3.f, 4.f) + + yield testCase "operator (=) works" <| fun () -> + (q1 = q2) |> equal true + yield testCase ".Equals works" <| fun () -> + (q1.Equals q2) |> equal true + yield testCase "operator (<>) works" <| fun () -> + (q1 <> q2) |> equal false + ] + + testList "Quaternion inequality" [ + let q1 = System.Numerics.Quaternion(1.f, 2.f, 3.f, 4.f) + let q2 = System.Numerics.Quaternion(4.f, 5.f, 6.f, 7.f) + + yield testCase "operator (=) works" <| fun () -> + (q1 = q2) |> equal false + yield testCase ".Equals works" <| fun () -> + (q1.Equals q2) |> equal false + yield testCase "operator (<>) works" <| fun () -> + (q1 <> q2) |> equal false + ] ] \ No newline at end of file From 0d4cfc17776b9b0585a3e142671b08057aee5ed7 Mon Sep 17 00:00:00 2001 From: Lukas Rieger Date: Mon, 5 Aug 2019 20:58:46 +0200 Subject: [PATCH 18/21] override equality and comparison for Vector3 --- src/fable-library/System.Numerics.fs | 42 +++++++++++++++++----------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/src/fable-library/System.Numerics.fs b/src/fable-library/System.Numerics.fs index dea471c4fd..fdd626c0d1 100644 --- a/src/fable-library/System.Numerics.fs +++ b/src/fable-library/System.Numerics.fs @@ -16,7 +16,7 @@ open System // - https://github.com/dotnet/corefx/blob/master/src/System.Numerics.Vectors/tests/QuaternionTests.cs // - https://github.com/dotnet/corefx/blob/master/src/System.Numerics.Vectors/tests/Vector3Tests.cs - +[] type Vector3 = struct @@ -66,19 +66,29 @@ type Vector3 = |> ignore stringBuilder.ToString() - //member __.Equals(other : Vector3) = - // x = other.X && - // y = other.Y && - // z = other.Z - - //override this.Equals(other : obj) = - // match other with - // | :? Vector3 as vother -> - // this.Equals(vother) - // | _ -> false - - //override __.GetHashCode() = - // hash(x, y, z) + member this.Equals(other : Vector3) = + this.X = other.X && + this.Y = other.Y && + this.Z = other.Z + + override this.Equals(other : obj) = + match other with + | :? Vector3 as vother -> + this.Equals(vother) + | _ -> false + + override this.GetHashCode() = + let o = obj() + hash(this.X, this.Y, this.Z) + + + interface System.IComparable with + member this.CompareTo(other) = + match other with + | null -> failwithf "other is null" + | :? Vector3 as vother -> + compare (this.X, this.Y, this.Z) (vother.X, vother.Y, vother.Z) + | _ -> failwithf "invalid type, expected 'other' to be a Vector, but it is '%O'" (other.GetType()) // -------------------------------- @@ -196,10 +206,10 @@ type Vector3 = static member (/) (left:Vector3, right:single) : Vector3 = Vector3.Divide(left, right) - static member (==) (left:Vector3, right:single) : bool = + static member (==) (left:Vector3, right:Vector3) : bool = left.Equals(right) - static member (!=) (left:Vector3, right:single) : bool = + static member (!=) (left:Vector3, right:Vector3) : bool = not (left.Equals(right)) static member (*) (left:Vector3, right:Vector3) : Vector3 = From 1b928ca568acb99596444bb110255cd2c6531b8b Mon Sep 17 00:00:00 2001 From: Lukas Rieger Date: Mon, 5 Aug 2019 21:12:03 +0200 Subject: [PATCH 19/21] split file into Vector3.fs and Quaternion.fs --- src/fable-library/Fable.Library.fsproj | 3 +- src/fable-library/Quaternion.fs | 152 ++++++++++++++++++ .../{System.Numerics.fs => Vector3.fs} | 149 +---------------- 3 files changed, 155 insertions(+), 149 deletions(-) create mode 100644 src/fable-library/Quaternion.fs rename src/fable-library/{System.Numerics.fs => Vector3.fs} (63%) diff --git a/src/fable-library/Fable.Library.fsproj b/src/fable-library/Fable.Library.fsproj index 018229d6ef..992237ead2 100644 --- a/src/fable-library/Fable.Library.fsproj +++ b/src/fable-library/Fable.Library.fsproj @@ -7,7 +7,8 @@ - + + diff --git a/src/fable-library/Quaternion.fs b/src/fable-library/Quaternion.fs new file mode 100644 index 0000000000..860a8d595c --- /dev/null +++ b/src/fable-library/Quaternion.fs @@ -0,0 +1,152 @@ +namespace System.Numerics + +open System + + +type Quaternion = + struct + + val mutable public X : single + val mutable public Y : single + val mutable public Z : single + val mutable public W : single + + new (x : single, y : single, z : single, w : single) = { X = x; Y = y; Z = z; W = w } + new(vectorPart : Vector3, scalarPart : single) = + Quaternion(vectorPart.X, vectorPart.Y, vectorPart.Z, scalarPart) + + member this.IsIdentity = + this.X = 0.f && + this.Y = 0.f && + this.Z = 0.f && + this.W = 1.f + + member this.Length() : single = + let ls = this.LengthSquared() + single ( System.Math.Sqrt(float ls) ) + + member this.LengthSquared() : single = + this.X * this.X + this.Y * this.Y + this.Z * this.Z + this.W * this.W + + + // -------------------------------- + // static members of Quaternion + + static member Identity = Quaternion(0.f, 0.f, 0.f, 1.f) + + static member Add(value1 : Quaternion, value2 : Quaternion) = + Quaternion( + value1.X + value2.X, + value1.Y + value2.Y, + value1.Z + value2.Z, + value1.W + value2.W + ) + + static member Concatenate(value1 : Quaternion, value2 : Quaternion) = + let x = value2.X; + let y = value2.Y; + let z = value2.Z; + let w = value2.W; + let x2 = value1.X; + let y2 = value1.Y; + let z2 = value1.Z; + let w2 = value1.W; + let num = y * z2 - z * y2; + let num2 = z * x2 - x * z2; + let num3 = x * y2 - y * x2; + let num4 = x * x2 + y * y2 + z * z2; + Quaternion( + x * w2 + x2 * w + num, + y * w2 + y2 * w + num2, + z * w2 + z2 * w + num3, + w * w2 - num4 + ) + + static member Conjugate(value : Quaternion) = + Quaternion( + 0.f - value.X, + 0.f - value.Y, + 0.f - value.Z, + value.W + ) + + static member Divide(value1 : Quaternion, value2 : Quaternion) = + let x = value1.X; + let y = value1.Y; + let z = value1.Z; + let w = value1.W; + let num = value2.X * value2.X + value2.Y * value2.Y + value2.Z * value2.Z + value2.W * value2.W; + let num2 = 1.f / num; + let num3 = (0.f - value2.X) * num2; + let num4 = (0.f - value2.Y) * num2; + let num5 = (0.f - value2.Z) * num2; + let num6 = value2.W * num2; + let num7 = y * num5 - z * num4; + let num8 = z * num3 - x * num5; + let num9 = x * num4 - y * num3; + let num10 = x * num3 + y * num4 + z * num5; + Quaternion( + x * num6 + num3 * w + num7, + y * num6 + num4 * w + num8, + z * num6 + num5 * w + num9, + w * num6 - num10 + ) + + static member Dot(quaternion1 : Quaternion, quaternion2 : Quaternion) : single = + quaternion1.X * quaternion2.X + quaternion1.Y * quaternion2.Y + quaternion1.Z * quaternion2.Z + quaternion1.W * quaternion2.W + + static member Inverse(value : Quaternion) : Quaternion = + let num = value.X * value.X + value.Y * value.Y + value.Z * value.Z + value.W * value.W; + let num2 = 1.f / num; + Quaternion( + (0.f - value.X) * num2, + (0.f - value.Y) * num2, + (0.f - value.Z) * num2, + value.W * num2 + ) + + static member Multiply(value1 : Quaternion, value2 : Quaternion) : Quaternion = + let x = value1.X; + let y = value1.Y; + let z = value1.Z; + let w = value1.W; + let x2 = value2.X; + let y2 = value2.Y; + let z2 = value2.Z; + let w2 = value2.W; + let num = y * z2 - z * y2; + let num2 = z * x2 - x * z2; + let num3 = x * y2 - y * x2; + let num4 = x * x2 + y * y2 + z * z2; + Quaternion( + x * w2 + x2 * w + num, + y * w2 + y2 * w + num2, + z * w2 + z2 * w + num3, + w * w2 - num4 + ) + + static member Multiply(value1 : Quaternion, value2 : single) : Quaternion = + Quaternion( + value1.X * value2, + value1.Y * value2, + value1.Z * value2, + value1.W * value2 + ) + + + // -------------------------------- + // Operators of Quaternion + + static member (+) (left:Quaternion, right:Quaternion) : Quaternion = + Quaternion.Add(left, right) + + static member (/) (left:Quaternion, right:Quaternion) : Quaternion = + Quaternion.Divide(left, right) + + static member (*) (left:Quaternion, right:Quaternion) : Quaternion = + Quaternion.Multiply(left, right) + + static member (*) (left:Quaternion, right:single) : Quaternion = + Quaternion.Multiply(left, right) + + end \ No newline at end of file diff --git a/src/fable-library/System.Numerics.fs b/src/fable-library/Vector3.fs similarity index 63% rename from src/fable-library/System.Numerics.fs rename to src/fable-library/Vector3.fs index fdd626c0d1..b186255dbf 100644 --- a/src/fable-library/System.Numerics.fs +++ b/src/fable-library/Vector3.fs @@ -227,151 +227,4 @@ type Vector3 = static member (-) (left:Vector3, right:Vector3) : Vector3 = Vector3.Subtract(left, right) end - -type Quaternion = - struct - - val mutable public X : single - val mutable public Y : single - val mutable public Z : single - val mutable public W : single - - new (x : single, y : single, z : single, w : single) = { X = x; Y = y; Z = z; W = w } - new(vectorPart : Vector3, scalarPart : single) = - Quaternion(vectorPart.X, vectorPart.Y, vectorPart.Z, scalarPart) - - member this.IsIdentity = - this.X = 0.f && - this.Y = 0.f && - this.Z = 0.f && - this.W = 1.f - - member this.Length() : single = - let ls = this.LengthSquared() - single ( System.Math.Sqrt(float ls) ) - - member this.LengthSquared() : single = - this.X * this.X + this.Y * this.Y + this.Z * this.Z + this.W * this.W - - - // -------------------------------- - // static members of Quaternion - - static member Identity = Quaternion(0.f, 0.f, 0.f, 1.f) - - static member Add(value1 : Quaternion, value2 : Quaternion) = - Quaternion( - value1.X + value2.X, - value1.Y + value2.Y, - value1.Z + value2.Z, - value1.W + value2.W - ) - - static member Concatenate(value1 : Quaternion, value2 : Quaternion) = - let x = value2.X; - let y = value2.Y; - let z = value2.Z; - let w = value2.W; - let x2 = value1.X; - let y2 = value1.Y; - let z2 = value1.Z; - let w2 = value1.W; - let num = y * z2 - z * y2; - let num2 = z * x2 - x * z2; - let num3 = x * y2 - y * x2; - let num4 = x * x2 + y * y2 + z * z2; - Quaternion( - x * w2 + x2 * w + num, - y * w2 + y2 * w + num2, - z * w2 + z2 * w + num3, - w * w2 - num4 - ) - - static member Conjugate(value : Quaternion) = - Quaternion( - 0.f - value.X, - 0.f - value.Y, - 0.f - value.Z, - value.W - ) - - static member Divide(value1 : Quaternion, value2 : Quaternion) = - let x = value1.X; - let y = value1.Y; - let z = value1.Z; - let w = value1.W; - let num = value2.X * value2.X + value2.Y * value2.Y + value2.Z * value2.Z + value2.W * value2.W; - let num2 = 1.f / num; - let num3 = (0.f - value2.X) * num2; - let num4 = (0.f - value2.Y) * num2; - let num5 = (0.f - value2.Z) * num2; - let num6 = value2.W * num2; - let num7 = y * num5 - z * num4; - let num8 = z * num3 - x * num5; - let num9 = x * num4 - y * num3; - let num10 = x * num3 + y * num4 + z * num5; - Quaternion( - x * num6 + num3 * w + num7, - y * num6 + num4 * w + num8, - z * num6 + num5 * w + num9, - w * num6 - num10 - ) - - static member Dot(quaternion1 : Quaternion, quaternion2 : Quaternion) : single = - quaternion1.X * quaternion2.X + quaternion1.Y * quaternion2.Y + quaternion1.Z * quaternion2.Z + quaternion1.W * quaternion2.W - - static member Inverse(value : Quaternion) : Quaternion = - let num = value.X * value.X + value.Y * value.Y + value.Z * value.Z + value.W * value.W; - let num2 = 1.f / num; - Quaternion( - (0.f - value.X) * num2, - (0.f - value.Y) * num2, - (0.f - value.Z) * num2, - value.W * num2 - ) - - static member Multiply(value1 : Quaternion, value2 : Quaternion) : Quaternion = - let x = value1.X; - let y = value1.Y; - let z = value1.Z; - let w = value1.W; - let x2 = value2.X; - let y2 = value2.Y; - let z2 = value2.Z; - let w2 = value2.W; - let num = y * z2 - z * y2; - let num2 = z * x2 - x * z2; - let num3 = x * y2 - y * x2; - let num4 = x * x2 + y * y2 + z * z2; - Quaternion( - x * w2 + x2 * w + num, - y * w2 + y2 * w + num2, - z * w2 + z2 * w + num3, - w * w2 - num4 - ) - - static member Multiply(value1 : Quaternion, value2 : single) : Quaternion = - Quaternion( - value1.X * value2, - value1.Y * value2, - value1.Z * value2, - value1.W * value2 - ) - - - // -------------------------------- - // Operators of Quaternion - - static member (+) (left:Quaternion, right:Quaternion) : Quaternion = - Quaternion.Add(left, right) - - static member (/) (left:Quaternion, right:Quaternion) : Quaternion = - Quaternion.Divide(left, right) - - static member (*) (left:Quaternion, right:Quaternion) : Quaternion = - Quaternion.Multiply(left, right) - - static member (*) (left:Quaternion, right:single) : Quaternion = - Quaternion.Multiply(left, right) - - end \ No newline at end of file + \ No newline at end of file From 5c27ea281ea05c98f9a8fe2563886c59c15a9276 Mon Sep 17 00:00:00 2001 From: Lukas Rieger Date: Mon, 5 Aug 2019 21:20:24 +0200 Subject: [PATCH 20/21] add missing cases to transformTypeInfo --- src/Fable.Transforms/Fable2Babel.fs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Fable.Transforms/Fable2Babel.fs b/src/Fable.Transforms/Fable2Babel.fs index 6fb4bd0585..dc1831fc24 100644 --- a/src/Fable.Transforms/Fable2Babel.fs +++ b/src/Fable.Transforms/Fable2Babel.fs @@ -471,6 +471,8 @@ module Util = | Replacements.BuiltinEntity kind -> match kind with | Replacements.BclGuid + | Replacements.BclVector3 + | Replacements.BclQuaternion | Replacements.BclTimeSpan | Replacements.BclDateTime | Replacements.BclDateTimeOffset From 50aa0a9d9f4a36bd9b213c737166cd9508a15328 Mon Sep 17 00:00:00 2001 From: Lukas Rieger Date: Mon, 5 Aug 2019 21:31:08 +0200 Subject: [PATCH 21/21] Revert "split file into Vector3.fs and Quaternion.fs" This reverts commit 1b928ca568acb99596444bb110255cd2c6531b8b. --- src/fable-library/Fable.Library.fsproj | 3 +- src/fable-library/Quaternion.fs | 152 ------------------ .../{Vector3.fs => System.Numerics.fs} | 149 ++++++++++++++++- 3 files changed, 149 insertions(+), 155 deletions(-) delete mode 100644 src/fable-library/Quaternion.fs rename src/fable-library/{Vector3.fs => System.Numerics.fs} (63%) diff --git a/src/fable-library/Fable.Library.fsproj b/src/fable-library/Fable.Library.fsproj index 992237ead2..018229d6ef 100644 --- a/src/fable-library/Fable.Library.fsproj +++ b/src/fable-library/Fable.Library.fsproj @@ -7,8 +7,7 @@ - - + diff --git a/src/fable-library/Quaternion.fs b/src/fable-library/Quaternion.fs deleted file mode 100644 index 860a8d595c..0000000000 --- a/src/fable-library/Quaternion.fs +++ /dev/null @@ -1,152 +0,0 @@ -namespace System.Numerics - -open System - - -type Quaternion = - struct - - val mutable public X : single - val mutable public Y : single - val mutable public Z : single - val mutable public W : single - - new (x : single, y : single, z : single, w : single) = { X = x; Y = y; Z = z; W = w } - new(vectorPart : Vector3, scalarPart : single) = - Quaternion(vectorPart.X, vectorPart.Y, vectorPart.Z, scalarPart) - - member this.IsIdentity = - this.X = 0.f && - this.Y = 0.f && - this.Z = 0.f && - this.W = 1.f - - member this.Length() : single = - let ls = this.LengthSquared() - single ( System.Math.Sqrt(float ls) ) - - member this.LengthSquared() : single = - this.X * this.X + this.Y * this.Y + this.Z * this.Z + this.W * this.W - - - // -------------------------------- - // static members of Quaternion - - static member Identity = Quaternion(0.f, 0.f, 0.f, 1.f) - - static member Add(value1 : Quaternion, value2 : Quaternion) = - Quaternion( - value1.X + value2.X, - value1.Y + value2.Y, - value1.Z + value2.Z, - value1.W + value2.W - ) - - static member Concatenate(value1 : Quaternion, value2 : Quaternion) = - let x = value2.X; - let y = value2.Y; - let z = value2.Z; - let w = value2.W; - let x2 = value1.X; - let y2 = value1.Y; - let z2 = value1.Z; - let w2 = value1.W; - let num = y * z2 - z * y2; - let num2 = z * x2 - x * z2; - let num3 = x * y2 - y * x2; - let num4 = x * x2 + y * y2 + z * z2; - Quaternion( - x * w2 + x2 * w + num, - y * w2 + y2 * w + num2, - z * w2 + z2 * w + num3, - w * w2 - num4 - ) - - static member Conjugate(value : Quaternion) = - Quaternion( - 0.f - value.X, - 0.f - value.Y, - 0.f - value.Z, - value.W - ) - - static member Divide(value1 : Quaternion, value2 : Quaternion) = - let x = value1.X; - let y = value1.Y; - let z = value1.Z; - let w = value1.W; - let num = value2.X * value2.X + value2.Y * value2.Y + value2.Z * value2.Z + value2.W * value2.W; - let num2 = 1.f / num; - let num3 = (0.f - value2.X) * num2; - let num4 = (0.f - value2.Y) * num2; - let num5 = (0.f - value2.Z) * num2; - let num6 = value2.W * num2; - let num7 = y * num5 - z * num4; - let num8 = z * num3 - x * num5; - let num9 = x * num4 - y * num3; - let num10 = x * num3 + y * num4 + z * num5; - Quaternion( - x * num6 + num3 * w + num7, - y * num6 + num4 * w + num8, - z * num6 + num5 * w + num9, - w * num6 - num10 - ) - - static member Dot(quaternion1 : Quaternion, quaternion2 : Quaternion) : single = - quaternion1.X * quaternion2.X + quaternion1.Y * quaternion2.Y + quaternion1.Z * quaternion2.Z + quaternion1.W * quaternion2.W - - static member Inverse(value : Quaternion) : Quaternion = - let num = value.X * value.X + value.Y * value.Y + value.Z * value.Z + value.W * value.W; - let num2 = 1.f / num; - Quaternion( - (0.f - value.X) * num2, - (0.f - value.Y) * num2, - (0.f - value.Z) * num2, - value.W * num2 - ) - - static member Multiply(value1 : Quaternion, value2 : Quaternion) : Quaternion = - let x = value1.X; - let y = value1.Y; - let z = value1.Z; - let w = value1.W; - let x2 = value2.X; - let y2 = value2.Y; - let z2 = value2.Z; - let w2 = value2.W; - let num = y * z2 - z * y2; - let num2 = z * x2 - x * z2; - let num3 = x * y2 - y * x2; - let num4 = x * x2 + y * y2 + z * z2; - Quaternion( - x * w2 + x2 * w + num, - y * w2 + y2 * w + num2, - z * w2 + z2 * w + num3, - w * w2 - num4 - ) - - static member Multiply(value1 : Quaternion, value2 : single) : Quaternion = - Quaternion( - value1.X * value2, - value1.Y * value2, - value1.Z * value2, - value1.W * value2 - ) - - - // -------------------------------- - // Operators of Quaternion - - static member (+) (left:Quaternion, right:Quaternion) : Quaternion = - Quaternion.Add(left, right) - - static member (/) (left:Quaternion, right:Quaternion) : Quaternion = - Quaternion.Divide(left, right) - - static member (*) (left:Quaternion, right:Quaternion) : Quaternion = - Quaternion.Multiply(left, right) - - static member (*) (left:Quaternion, right:single) : Quaternion = - Quaternion.Multiply(left, right) - - end \ No newline at end of file diff --git a/src/fable-library/Vector3.fs b/src/fable-library/System.Numerics.fs similarity index 63% rename from src/fable-library/Vector3.fs rename to src/fable-library/System.Numerics.fs index b186255dbf..fdd626c0d1 100644 --- a/src/fable-library/Vector3.fs +++ b/src/fable-library/System.Numerics.fs @@ -227,4 +227,151 @@ type Vector3 = static member (-) (left:Vector3, right:Vector3) : Vector3 = Vector3.Subtract(left, right) end - \ No newline at end of file + +type Quaternion = + struct + + val mutable public X : single + val mutable public Y : single + val mutable public Z : single + val mutable public W : single + + new (x : single, y : single, z : single, w : single) = { X = x; Y = y; Z = z; W = w } + new(vectorPart : Vector3, scalarPart : single) = + Quaternion(vectorPart.X, vectorPart.Y, vectorPart.Z, scalarPart) + + member this.IsIdentity = + this.X = 0.f && + this.Y = 0.f && + this.Z = 0.f && + this.W = 1.f + + member this.Length() : single = + let ls = this.LengthSquared() + single ( System.Math.Sqrt(float ls) ) + + member this.LengthSquared() : single = + this.X * this.X + this.Y * this.Y + this.Z * this.Z + this.W * this.W + + + // -------------------------------- + // static members of Quaternion + + static member Identity = Quaternion(0.f, 0.f, 0.f, 1.f) + + static member Add(value1 : Quaternion, value2 : Quaternion) = + Quaternion( + value1.X + value2.X, + value1.Y + value2.Y, + value1.Z + value2.Z, + value1.W + value2.W + ) + + static member Concatenate(value1 : Quaternion, value2 : Quaternion) = + let x = value2.X; + let y = value2.Y; + let z = value2.Z; + let w = value2.W; + let x2 = value1.X; + let y2 = value1.Y; + let z2 = value1.Z; + let w2 = value1.W; + let num = y * z2 - z * y2; + let num2 = z * x2 - x * z2; + let num3 = x * y2 - y * x2; + let num4 = x * x2 + y * y2 + z * z2; + Quaternion( + x * w2 + x2 * w + num, + y * w2 + y2 * w + num2, + z * w2 + z2 * w + num3, + w * w2 - num4 + ) + + static member Conjugate(value : Quaternion) = + Quaternion( + 0.f - value.X, + 0.f - value.Y, + 0.f - value.Z, + value.W + ) + + static member Divide(value1 : Quaternion, value2 : Quaternion) = + let x = value1.X; + let y = value1.Y; + let z = value1.Z; + let w = value1.W; + let num = value2.X * value2.X + value2.Y * value2.Y + value2.Z * value2.Z + value2.W * value2.W; + let num2 = 1.f / num; + let num3 = (0.f - value2.X) * num2; + let num4 = (0.f - value2.Y) * num2; + let num5 = (0.f - value2.Z) * num2; + let num6 = value2.W * num2; + let num7 = y * num5 - z * num4; + let num8 = z * num3 - x * num5; + let num9 = x * num4 - y * num3; + let num10 = x * num3 + y * num4 + z * num5; + Quaternion( + x * num6 + num3 * w + num7, + y * num6 + num4 * w + num8, + z * num6 + num5 * w + num9, + w * num6 - num10 + ) + + static member Dot(quaternion1 : Quaternion, quaternion2 : Quaternion) : single = + quaternion1.X * quaternion2.X + quaternion1.Y * quaternion2.Y + quaternion1.Z * quaternion2.Z + quaternion1.W * quaternion2.W + + static member Inverse(value : Quaternion) : Quaternion = + let num = value.X * value.X + value.Y * value.Y + value.Z * value.Z + value.W * value.W; + let num2 = 1.f / num; + Quaternion( + (0.f - value.X) * num2, + (0.f - value.Y) * num2, + (0.f - value.Z) * num2, + value.W * num2 + ) + + static member Multiply(value1 : Quaternion, value2 : Quaternion) : Quaternion = + let x = value1.X; + let y = value1.Y; + let z = value1.Z; + let w = value1.W; + let x2 = value2.X; + let y2 = value2.Y; + let z2 = value2.Z; + let w2 = value2.W; + let num = y * z2 - z * y2; + let num2 = z * x2 - x * z2; + let num3 = x * y2 - y * x2; + let num4 = x * x2 + y * y2 + z * z2; + Quaternion( + x * w2 + x2 * w + num, + y * w2 + y2 * w + num2, + z * w2 + z2 * w + num3, + w * w2 - num4 + ) + + static member Multiply(value1 : Quaternion, value2 : single) : Quaternion = + Quaternion( + value1.X * value2, + value1.Y * value2, + value1.Z * value2, + value1.W * value2 + ) + + + // -------------------------------- + // Operators of Quaternion + + static member (+) (left:Quaternion, right:Quaternion) : Quaternion = + Quaternion.Add(left, right) + + static member (/) (left:Quaternion, right:Quaternion) : Quaternion = + Quaternion.Divide(left, right) + + static member (*) (left:Quaternion, right:Quaternion) : Quaternion = + Quaternion.Multiply(left, right) + + static member (*) (left:Quaternion, right:single) : Quaternion = + Quaternion.Multiply(left, right) + + end \ No newline at end of file