From a2bec33dc3a8514c65c60df8396578e70b311cfe Mon Sep 17 00:00:00 2001 From: Martin Date: Tue, 20 Aug 2024 16:20:46 +0200 Subject: [PATCH] [FSharp] Optimize and rework type patterns --- .../Aardvark.Base.FSharp.fsproj | 2 + src/Aardvark.Base.FSharp/Ag.fs | 1 - .../Reflection/TypeInfo.fs | 67 +--- .../Reflection/TypeMeta_auto.fs | 309 ++++++++++++++++++ .../Reflection/TypeMeta_template.fs | 197 +++++++++++ src/Aardvark.Base.FSharp/Runtime/Fragments.fs | 2 +- src/Aardvark.Base/AlgoDat/Meta.cs | 16 + .../Aardvark.Base.FSharp.Benchmarks.fsproj | 1 + .../TypePatternsBench.fs | 99 ++++++ .../Aardvark.Base.FSharp.Tests.fsproj | 1 + .../TypePatternsTests.fs | 50 +++ 11 files changed, 689 insertions(+), 56 deletions(-) create mode 100644 src/Aardvark.Base.FSharp/Reflection/TypeMeta_auto.fs create mode 100644 src/Aardvark.Base.FSharp/Reflection/TypeMeta_template.fs create mode 100644 src/Tests/Aardvark.Base.FSharp.Benchmarks/TypePatternsBench.fs create mode 100644 src/Tests/Aardvark.Base.FSharp.Tests/TypePatternsTests.fs diff --git a/src/Aardvark.Base.FSharp/Aardvark.Base.FSharp.fsproj b/src/Aardvark.Base.FSharp/Aardvark.Base.FSharp.fsproj index 205813f29..b8baa2b35 100644 --- a/src/Aardvark.Base.FSharp/Aardvark.Base.FSharp.fsproj +++ b/src/Aardvark.Base.FSharp/Aardvark.Base.FSharp.fsproj @@ -60,6 +60,8 @@ + + diff --git a/src/Aardvark.Base.FSharp/Ag.fs b/src/Aardvark.Base.FSharp/Ag.fs index b124b15ad..4eedeb088 100644 --- a/src/Aardvark.Base.FSharp/Ag.fs +++ b/src/Aardvark.Base.FSharp/Ag.fs @@ -234,7 +234,6 @@ module Ag = [] module private Helpers = open System.Reflection.Emit - open Aardvark.Base.TypeInfo type NewRootDelegate = delegate of obj -> obj type SynDelegateStatic = delegate of obj * Scope -> obj diff --git a/src/Aardvark.Base.FSharp/Reflection/TypeInfo.fs b/src/Aardvark.Base.FSharp/Reflection/TypeInfo.fs index aae8d4378..3a8221bb1 100644 --- a/src/Aardvark.Base.FSharp/Reflection/TypeInfo.fs +++ b/src/Aardvark.Base.FSharp/Reflection/TypeInfo.fs @@ -9,6 +9,7 @@ namespace Aardvark.Base /// TypeInfo contains metadata associated with types and provides active patterns /// deconstructing vector/matrix types etc. /// +[] module TypeInfo = open System open System.Collections.Generic @@ -266,93 +267,51 @@ module TypeInfo = [] let inline (|Integral|_|) (t : Type) = - if Set.contains (typeInfo t) IntegralTypes then - ValueSome () - else - ValueNone + TypeMeta.Patterns.(|Integral|_|) t [] let inline (|Fractional|_|) (t : Type) = - if Set.contains (typeInfo t) FractionalTypes then - ValueSome () - else - ValueNone + TypeMeta.Patterns.(|Fractional|_|) t [] let inline (|Num|_|) (t : Type) = - if Set.contains (typeInfo t) NumTypes then - ValueSome () - else - ValueNone + TypeMeta.Patterns.(|Numeric|_|) t [] let inline (|Vector|_|) (t : Type) = - if Set.contains (typeInfo t) VectorTypes then - ValueSome () - else - ValueNone + TypeMeta.Patterns.(|Vector|_|) t [] let inline (|Color|_|) (t : Type) = - if Set.contains (typeInfo t) ColorTypes then - ValueSome () - else - ValueNone + TypeMeta.Patterns.(|Color|_|) t [] let inline (|Matrix|_|) (t : Type) = - if Set.contains (typeInfo t) MatrixTypes then - ValueSome () - else - ValueNone + TypeMeta.Patterns.(|Matrix|_|) t [] let inline (|VectorOf|_|) (t : Type) = - VectorTypes - |> Seq.tryFindV (fun vi -> vi.Type.Name = t.Name) - |> ValueOption.map (fun t -> - let vt = unbox t - vt.dimension, vt.baseType.Type - ) + TypeMeta.Patterns.(|VectorOf|_|) t |> ValueOption.map (fun struct (d, t) -> d, t) [] let inline (|ColorOf|_|) (t : Type) = - ColorTypes - |> Seq.tryFindV (fun ti -> ti.Type.Name = t.Name) - |> ValueOption.map (fun t -> - let vt = unbox t - vt.dimension, vt.baseType.Type - ) + TypeMeta.Patterns.(|ColorOf|_|) t |> ValueOption.map (fun struct (d, t) -> d, t) [] let inline (|MatrixOf|_|) (t : Type) = - MatrixTypes - |> Seq.tryFindV (fun vi -> vi.Type.Name = t.Name) - |> ValueOption.map (fun t -> - let mt = unbox t - mt.dimension, mt.baseType.Type - ) + TypeMeta.Patterns.(|MatrixOf|_|) t |> ValueOption.map (fun struct (d, t) -> d, t) [] let inline (|Ref|_|) (t : Type) = - if t.IsGenericType && t.GetGenericTypeDefinition() = TRef.simpleType then - ValueSome <| t.GetGenericArguments().[0] - else - ValueNone + TypeMeta.Patterns.(|RefOf|_|) t [] let inline (|List|_|) (t : Type) = - if t.IsGenericType && t.GetGenericTypeDefinition() = TList.simpleType then - ValueSome <| t.GetGenericArguments().[0] - else - ValueNone + TypeMeta.Patterns.(|ListOf|_|) t [] let inline (|Seq|_|) (t : Type) = - if t.IsGenericType && t.GetGenericTypeDefinition() = TSeq.simpleType then - ValueSome <| t.GetGenericArguments().[0] - else - ValueNone + TypeMeta.Patterns.(|SeqOf|_|) t [] [] diff --git a/src/Aardvark.Base.FSharp/Reflection/TypeMeta_auto.fs b/src/Aardvark.Base.FSharp/Reflection/TypeMeta_auto.fs new file mode 100644 index 000000000..f625047eb --- /dev/null +++ b/src/Aardvark.Base.FSharp/Reflection/TypeMeta_auto.fs @@ -0,0 +1,309 @@ +namespace Aardvark.Base + +open System + +/// Contains metadata associated with types and provides active patterns deconstructing vector/matrix types etc. +module TypeMeta = + + [] + type VectorType = + { + Type : Type + FieldType : Type + Dimension : int + } + + [] + type MatrixType = + { + Type : Type + FieldType : Type + Dimension : V2i + } + + let VectorTypes : VectorType list = + [ + { Type = typeof; FieldType = typeof; Dimension = 2 } + { Type = typeof; FieldType = typeof; Dimension = 2 } + { Type = typeof; FieldType = typeof; Dimension = 2 } + { Type = typeof; FieldType = typeof; Dimension = 2 } + { Type = typeof; FieldType = typeof; Dimension = 2 } + { Type = typeof; FieldType = typeof; Dimension = 3 } + { Type = typeof; FieldType = typeof; Dimension = 3 } + { Type = typeof; FieldType = typeof; Dimension = 3 } + { Type = typeof; FieldType = typeof; Dimension = 3 } + { Type = typeof; FieldType = typeof; Dimension = 3 } + { Type = typeof; FieldType = typeof; Dimension = 4 } + { Type = typeof; FieldType = typeof; Dimension = 4 } + { Type = typeof; FieldType = typeof; Dimension = 4 } + { Type = typeof; FieldType = typeof; Dimension = 4 } + { Type = typeof; FieldType = typeof; Dimension = 4 } + ] + + let ColorTypes : VectorType list = + [ + { Type = typeof; FieldType = typeof; Dimension = 3 } + { Type = typeof; FieldType = typeof; Dimension = 3 } + { Type = typeof; FieldType = typeof; Dimension = 3 } + { Type = typeof; FieldType = typeof; Dimension = 3 } + { Type = typeof; FieldType = typeof; Dimension = 3 } + { Type = typeof; FieldType = typeof; Dimension = 4 } + { Type = typeof; FieldType = typeof; Dimension = 4 } + { Type = typeof; FieldType = typeof; Dimension = 4 } + { Type = typeof; FieldType = typeof; Dimension = 4 } + { Type = typeof; FieldType = typeof; Dimension = 4 } + ] + + let MatrixTypes : MatrixType list = + [ + { Type = typeof; FieldType = typeof; Dimension = V2i(2, 2) } + { Type = typeof; FieldType = typeof; Dimension = V2i(2, 2) } + { Type = typeof; FieldType = typeof; Dimension = V2i(2, 2) } + { Type = typeof; FieldType = typeof; Dimension = V2i(2, 2) } + { Type = typeof; FieldType = typeof; Dimension = V2i(3, 2) } + { Type = typeof; FieldType = typeof; Dimension = V2i(3, 2) } + { Type = typeof; FieldType = typeof; Dimension = V2i(3, 2) } + { Type = typeof; FieldType = typeof; Dimension = V2i(3, 2) } + { Type = typeof; FieldType = typeof; Dimension = V2i(3, 3) } + { Type = typeof; FieldType = typeof; Dimension = V2i(3, 3) } + { Type = typeof; FieldType = typeof; Dimension = V2i(3, 3) } + { Type = typeof; FieldType = typeof; Dimension = V2i(3, 3) } + { Type = typeof; FieldType = typeof; Dimension = V2i(4, 3) } + { Type = typeof; FieldType = typeof; Dimension = V2i(4, 3) } + { Type = typeof; FieldType = typeof; Dimension = V2i(4, 3) } + { Type = typeof; FieldType = typeof; Dimension = V2i(4, 3) } + { Type = typeof; FieldType = typeof; Dimension = V2i(4, 4) } + { Type = typeof; FieldType = typeof; Dimension = V2i(4, 4) } + { Type = typeof; FieldType = typeof; Dimension = V2i(4, 4) } + { Type = typeof; FieldType = typeof; Dimension = V2i(4, 4) } + ] + + let IntegralTypes : Type list = + [ + typeof + typeof + typeof + typeof + typeof + typeof + typeof + typeof + ] + + let FractionalTypes : Type list = + [ typeof; typeof; typeof; typeof ] + + let NumericTypes : Type list = + IntegralTypes @ FractionalTypes + + module Patterns = + + [] + module private Lookup = + + let vectorTypes = + VectorTypes + |> List.map (fun vt -> struct (vt.Type, struct (vt.Dimension, vt.FieldType))) + |> Dictionary.ofListV + + let colorTypes = + ColorTypes + |> List.map (fun ct -> struct (ct.Type, struct (ct.Dimension, ct.FieldType))) + |> Dictionary.ofListV + + let matrixTypes = + MatrixTypes + |> List.map (fun mt -> struct (mt.Type, struct (mt.Dimension, mt.FieldType))) + |> Dictionary.ofListV + + let integralTypes = + IntegralTypes |> HashSet.ofList + + let fractionalTypes = + FractionalTypes |> HashSet.ofList + + let numericTypes = + NumericTypes |> HashSet.ofList + + /// Determines if the given type is a bool. + [] + let inline (|Bool|_|) (t: Type) = + if t = typeof then ValueSome () + else ValueNone + + /// Determines if the given type is a uint8. + [] + let inline (|UInt8|_|) (t: Type) = + if t = typeof then ValueSome () + else ValueNone + + /// Determines if the given type is a int8. + [] + let inline (|Int8|_|) (t: Type) = + if t = typeof then ValueSome () + else ValueNone + + /// Determines if the given type is a int16. + [] + let inline (|Int16|_|) (t: Type) = + if t = typeof then ValueSome () + else ValueNone + + /// Determines if the given type is a uint16. + [] + let inline (|UInt16|_|) (t: Type) = + if t = typeof then ValueSome () + else ValueNone + + /// Determines if the given type is a int32. + [] + let inline (|Int32|_|) (t: Type) = + if t = typeof then ValueSome () + else ValueNone + + /// Determines if the given type is a uint32. + [] + let inline (|UInt32|_|) (t: Type) = + if t = typeof then ValueSome () + else ValueNone + + /// Determines if the given type is a int64. + [] + let inline (|Int64|_|) (t: Type) = + if t = typeof then ValueSome () + else ValueNone + + /// Determines if the given type is a uint64. + [] + let inline (|UInt64|_|) (t: Type) = + if t = typeof then ValueSome () + else ValueNone + + /// Determines if the given type is a float32. + [] + let inline (|Float32|_|) (t: Type) = + if t = typeof then ValueSome () + else ValueNone + + /// Determines if the given type is a float. + [] + let inline (|Float64|_|) (t: Type) = + if t = typeof then ValueSome () + else ValueNone + + /// Determines if the given type is a float16. + [] + let inline (|Float16|_|) (t: Type) = + if t = typeof then ValueSome () + else ValueNone + + /// Determines if the given type is a decimal. + [] + let inline (|Decimal|_|) (t: Type) = + if t = typeof then ValueSome () + else ValueNone + + /// Determines if the given type is a char. + [] + let inline (|Char|_|) (t: Type) = + if t = typeof then ValueSome () + else ValueNone + + /// Determines if the given type is a string. + [] + let inline (|String|_|) (t: Type) = + if t = typeof then ValueSome () + else ValueNone + + /// Determines if the given type is a IntPtr. + [] + let inline (|IntPtr|_|) (t : Type) = + if t = typeof then ValueSome () + else ValueNone + + /// Determines if the given type is unit. + [] + let inline (|Unit|_|) (t : Type) = + if t = typeof then ValueSome () + else ValueNone + + /// Determines if the given type is an enumeration. + [] + let inline (|Enum|_|) (t : Type) = + if t.IsEnum then ValueSome () + else ValueNone + + /// Determines if the given type is an integral type. + [] + let (|Integral|_|) (t : Type) = + if integralTypes.Contains t then ValueSome () + else ValueNone + + /// Determines if the given type is half, float, double, or decimal. + [] + let (|Fractional|_|) (t : Type) = + if fractionalTypes.Contains t then ValueSome () + else ValueNone + + /// Determines if the given type is a numeric type (i.e. half, float, double, decimal, or an integral type). + [] + let (|Numeric|_|) (t : Type) = + if numericTypes.Contains t then ValueSome () + else ValueNone + + /// Determines if the given type is a vector type. + [] + let (|Vector|_|) (t: Type) = + if vectorTypes.ContainsKey t then ValueSome () + else ValueNone + + /// Determines if the given type is a color type. + [] + let (|Color|_|) (t: Type) = + if colorTypes.ContainsKey t then ValueSome () + else ValueNone + + /// Determines if the given type is a matrix type. + [] + let (|Matrix|_|) (t: Type) = + if matrixTypes.ContainsKey t then ValueSome () + else ValueNone + + /// Determines if the given type is a vector type. + /// Returns the dimension and the underlying type. + [] + let (|VectorOf|_|) (t: Type) = + vectorTypes.TryFindV t + + /// Determines if the given type is a color type. + /// Returns the dimension and the underlying type. + [] + let (|ColorOf|_|) (t: Type) = + colorTypes.TryFindV t + + /// Determines if the given type is a matrix type. + /// Returns the dimension (columns, rows) and the underlying type. + [] + let (|MatrixOf|_|) (t: Type) = + matrixTypes.TryFindV t + + /// Determines if the given type is a reference type. + /// Returns the underlying type. + [] + let inline (|RefOf|_|) (t : Type) = + if t.IsGenericType && t.GetGenericTypeDefinition() = typedefof then ValueSome <| t.GetGenericArguments().[0] + else ValueNone + + /// Determines if the given type is a list type. + /// Returns the underlying type. + [] + let inline (|ListOf|_|) (t : Type) = + if t.IsGenericType && t.GetGenericTypeDefinition() = typedefof then ValueSome <| t.GetGenericArguments().[0] + else ValueNone + + /// Determines if the given type is a sequence type. + /// Returns the underlying type. + [] + let inline (|SeqOf|_|) (t : Type) = + if t.IsGenericType && t.GetGenericTypeDefinition() = typedefof then ValueSome <| t.GetGenericArguments().[0] + else ValueNone \ No newline at end of file diff --git a/src/Aardvark.Base.FSharp/Reflection/TypeMeta_template.fs b/src/Aardvark.Base.FSharp/Reflection/TypeMeta_template.fs new file mode 100644 index 000000000..91ac38a93 --- /dev/null +++ b/src/Aardvark.Base.FSharp/Reflection/TypeMeta_template.fs @@ -0,0 +1,197 @@ +namespace Aardvark.Base + +open System + +/// Contains metadata associated with types and provides active patterns deconstructing vector/matrix types etc. +module TypeMeta = + + [] + type VectorType = + { + Type : Type + FieldType : Type + Dimension : int + } + + [] + type MatrixType = + { + Type : Type + FieldType : Type + Dimension : V2i + } + + let VectorTypes : VectorType list = + [ + //# foreach (var vt in Meta.VecTypes) { + { Type = typeof<__vt.Name__>; FieldType = typeof<__vt.FieldType.FSharpName__>; Dimension = __vt.Len__ } + //# } + ] + + let ColorTypes : VectorType list = + [ + //# foreach (var ct in Meta.ColorTypes) { + { Type = typeof<__ct.Name__>; FieldType = typeof<__ct.FieldType.FSharpName__>; Dimension = __ct.Len__ } + //# } + ] + + let MatrixTypes : MatrixType list = + [ + //# foreach (var mt in Meta.MatTypes) { + { Type = typeof<__mt.Name__>; FieldType = typeof<__mt.FieldType.FSharpName__>; Dimension = V2i(__mt.Cols__, __mt.Rows__) } + //# } + ] + + let IntegralTypes : Type list = + [ + //# foreach(var t in Meta.IntegerTypes) { + typeof<__t.FSharpName__> + //# } + ] + + let FractionalTypes : Type list = + [ typeof; typeof; typeof; typeof ] + + let NumericTypes : Type list = + IntegralTypes @ FractionalTypes + + module Patterns = + + [] + module private Lookup = + + let vectorTypes = + VectorTypes + |> List.map (fun vt -> struct (vt.Type, struct (vt.Dimension, vt.FieldType))) + |> Dictionary.ofListV + + let colorTypes = + ColorTypes + |> List.map (fun ct -> struct (ct.Type, struct (ct.Dimension, ct.FieldType))) + |> Dictionary.ofListV + + let matrixTypes = + MatrixTypes + |> List.map (fun mt -> struct (mt.Type, struct (mt.Dimension, mt.FieldType))) + |> Dictionary.ofListV + + let integralTypes = + IntegralTypes |> HashSet.ofList + + let fractionalTypes = + FractionalTypes |> HashSet.ofList + + let numericTypes = + NumericTypes |> HashSet.ofList + + //# var patternTypes = + //# Meta.BuiltInTypes + //# .Concat(Meta.HalfType.IntoArray()) + //# .Concat(Meta.DecimalType.IntoArray()) + //# .Concat(Meta.CharType.IntoArray()) + //# .Concat(Meta.StringType.IntoArray()); + //# foreach (var t in patternTypes) { + //# var name = t.FSharpName; + //# var caps = name.StartsWith("uint") ? 2 : 1; + //# var patternName = name.Substring(0, caps).ToUpperInvariant() + name.Substring(caps); + //# if (patternName == "Float") patternName = "Float64"; + //# var pattern = $"(|{patternName}|_|)"; + /// Determines if the given type is a __name__. + [] + let inline __pattern__ (t: Type) = + if t = typeof<__name__> then ValueSome () + else ValueNone + + //# } + /// Determines if the given type is a IntPtr. + [] + let inline (|IntPtr|_|) (t : Type) = + if t = typeof then ValueSome () + else ValueNone + + /// Determines if the given type is unit. + [] + let inline (|Unit|_|) (t : Type) = + if t = typeof then ValueSome () + else ValueNone + + /// Determines if the given type is an enumeration. + [] + let inline (|Enum|_|) (t : Type) = + if t.IsEnum then ValueSome () + else ValueNone + + /// Determines if the given type is an integral type. + [] + let (|Integral|_|) (t : Type) = + if integralTypes.Contains t then ValueSome () + else ValueNone + + /// Determines if the given type is half, float, double, or decimal. + [] + let (|Fractional|_|) (t : Type) = + if fractionalTypes.Contains t then ValueSome () + else ValueNone + + /// Determines if the given type is a numeric type (i.e. half, float, double, decimal, or an integral type). + [] + let (|Numeric|_|) (t : Type) = + if numericTypes.Contains t then ValueSome () + else ValueNone + + /// Determines if the given type is a vector type. + [] + let (|Vector|_|) (t: Type) = + if vectorTypes.ContainsKey t then ValueSome () + else ValueNone + + /// Determines if the given type is a color type. + [] + let (|Color|_|) (t: Type) = + if colorTypes.ContainsKey t then ValueSome () + else ValueNone + + /// Determines if the given type is a matrix type. + [] + let (|Matrix|_|) (t: Type) = + if matrixTypes.ContainsKey t then ValueSome () + else ValueNone + + /// Determines if the given type is a vector type. + /// Returns the dimension and the underlying type. + [] + let (|VectorOf|_|) (t: Type) = + vectorTypes.TryFindV t + + /// Determines if the given type is a color type. + /// Returns the dimension and the underlying type. + [] + let (|ColorOf|_|) (t: Type) = + colorTypes.TryFindV t + + /// Determines if the given type is a matrix type. + /// Returns the dimension (columns, rows) and the underlying type. + [] + let (|MatrixOf|_|) (t: Type) = + matrixTypes.TryFindV t + + /// Determines if the given type is a reference type. + /// Returns the underlying type. + [] + let inline (|RefOf|_|) (t : Type) = + if t.IsGenericType && t.GetGenericTypeDefinition() = typedefof then ValueSome <| t.GetGenericArguments().[0] + else ValueNone + + /// Determines if the given type is a list type. + /// Returns the underlying type. + [] + let inline (|ListOf|_|) (t : Type) = + if t.IsGenericType && t.GetGenericTypeDefinition() = typedefof then ValueSome <| t.GetGenericArguments().[0] + else ValueNone + + /// Determines if the given type is a sequence type. + /// Returns the underlying type. + [] + let inline (|SeqOf|_|) (t : Type) = + if t.IsGenericType && t.GetGenericTypeDefinition() = typedefof then ValueSome <| t.GetGenericArguments().[0] + else ValueNone \ No newline at end of file diff --git a/src/Aardvark.Base.FSharp/Runtime/Fragments.fs b/src/Aardvark.Base.FSharp/Runtime/Fragments.fs index bf56d8428..c1cc7bbcb 100644 --- a/src/Aardvark.Base.FSharp/Runtime/Fragments.fs +++ b/src/Aardvark.Base.FSharp/Runtime/Fragments.fs @@ -82,7 +82,7 @@ module AMD64 = let getArgumentLocation (arg : int) (argType : Type) (cc : CallingConvention) = match argType with - | TypeInfo.Patterns.Fractional -> + | TypeMeta.Patterns.Fractional -> if arg < cc.floatRegisters.Length then RegisterArgument cc.floatRegisters.[arg] else StackArgument | _ -> diff --git a/src/Aardvark.Base/AlgoDat/Meta.cs b/src/Aardvark.Base/AlgoDat/Meta.cs index 96d448ca6..d6ebb9e71 100644 --- a/src/Aardvark.Base/AlgoDat/Meta.cs +++ b/src/Aardvark.Base/AlgoDat/Meta.cs @@ -19,6 +19,9 @@ public class SimpleType public bool IsReal { get; set; } public bool IsCharOrString { get; set; } + private string m_fsharpName; + public string FSharpName { get => m_fsharpName ?? Name; set => m_fsharpName = value; } + public SimpleType() { } @@ -135,6 +138,7 @@ public ColorType(string name) Caps = "Byte", Char = "b", Read = "ReadByte", + FSharpName = "uint8", IsInteger = true, }; @@ -144,6 +148,7 @@ public ColorType(string name) Caps = "SByte", Char = "sb", Read = "ReadSByte", + FSharpName = "int8", IsInteger = true, }; @@ -153,6 +158,7 @@ public ColorType(string name) Caps = "Short", Char = "s", Read = "ReadInt16", + FSharpName = "int16", IsInteger = true, }; @@ -162,6 +168,7 @@ public ColorType(string name) Caps = "UShort", Char = "us", Read = "ReadUInt16", + FSharpName = "uint16", IsInteger = true, }; @@ -171,6 +178,7 @@ public ColorType(string name) Caps = "Int", Char = "i", Read = "ReadInt32", + FSharpName = "int32", IsInteger = true, }; @@ -180,6 +188,7 @@ public ColorType(string name) Caps = "UInt", Char = "ui", Read = "ReadUInt32", + FSharpName = "uint32", IsInteger = true, }; @@ -189,6 +198,7 @@ public ColorType(string name) Caps = "Long", Char = "l", Read = "ReadInt64", + FSharpName = "int64", IsInteger = true, }; @@ -198,6 +208,7 @@ public ColorType(string name) Caps = "ULong", Char = "ul", Read = "ReadUInt64", + FSharpName = "uint64", IsInteger = true, }; @@ -207,6 +218,7 @@ public ColorType(string name) Caps = "Half", Char = "h", Read = "ReadHalf", + FSharpName = "float16", IsReal = true, }; @@ -216,6 +228,7 @@ public ColorType(string name) Caps = "Float", Char = "f", Read = "ReadSingle", + FSharpName = "float32", IsReal = true, }; @@ -225,6 +238,7 @@ public ColorType(string name) Caps = "Double", Char = "d", Read = "ReadDouble", + FSharpName = "float", IsReal = true, }; @@ -239,6 +253,7 @@ public ColorType(string name) { Name = "Char", Read = "ReadChar", + FSharpName = "char", IsCharOrString = true, }; @@ -246,6 +261,7 @@ public ColorType(string name) { Name = "String", Read = "ReadString", + FSharpName = "string", IsCharOrString = true, }; diff --git a/src/Tests/Aardvark.Base.FSharp.Benchmarks/Aardvark.Base.FSharp.Benchmarks.fsproj b/src/Tests/Aardvark.Base.FSharp.Benchmarks/Aardvark.Base.FSharp.Benchmarks.fsproj index b85a25551..80bcc1114 100644 --- a/src/Tests/Aardvark.Base.FSharp.Benchmarks/Aardvark.Base.FSharp.Benchmarks.fsproj +++ b/src/Tests/Aardvark.Base.FSharp.Benchmarks/Aardvark.Base.FSharp.Benchmarks.fsproj @@ -28,6 +28,7 @@ + diff --git a/src/Tests/Aardvark.Base.FSharp.Benchmarks/TypePatternsBench.fs b/src/Tests/Aardvark.Base.FSharp.Benchmarks/TypePatternsBench.fs new file mode 100644 index 000000000..b935c5fe5 --- /dev/null +++ b/src/Tests/Aardvark.Base.FSharp.Benchmarks/TypePatternsBench.fs @@ -0,0 +1,99 @@ +namespace Aardvark.Base.FSharp.Benchmarks + +#nowarn "44" + +open System +open Aardvark.Base +open Aardvark.Base.TypeInfo +open BenchmarkDotNet.Attributes + +module PatternsImpl = + + module PatternsNaive = + let inline private typeInfo t = { simpleType = t } :> ITypeInfo + + [] + let inline (|Matrix|_|) (t : Type) = + if Set.contains (typeInfo t) MatrixTypes then + ValueSome () + else + ValueNone + + [] + let inline (|MatrixOf|_|) (t : Type) = + MatrixTypes + |> Seq.tryFindV (fun vi -> vi.Type.Name = t.Name) + |> ValueOption.map (fun t -> + let mt = unbox t + mt.dimension, mt.baseType.Type + ) + + [] + let inline (|List|_|) (t : Type) = + if t.IsGenericType && t.GetGenericTypeDefinition() = TList.simpleType then + ValueSome <| t.GetGenericArguments().[0] + else + ValueNone + +[] +type ``TypePatterns Matrix``() = + + member inline x.IsMatrixNaive (t: Type) = + match t with + | PatternsImpl.PatternsNaive.Matrix -> true + | _ -> false + + member inline x.IsMatrixOptimized (t: Type) = + match t with + | TypeMeta.Patterns.Matrix -> true + | _ -> false + + [] + member x.Naive() = + x.IsMatrixNaive typeof && x.IsMatrixNaive typeof + + [] + member x.Optimized() = + x.IsMatrixOptimized typeof && x.IsMatrixOptimized typeof + +[] +type ``TypePatterns MatrixOf``() = + + member inline x.IsMatrixNaive (t: Type) = + match t with + | PatternsImpl.PatternsNaive.MatrixOf(dim, baseType) -> true + | _ -> false + + member inline x.IsMatrixOptimized (t: Type) = + match t with + | TypeMeta.Patterns.MatrixOf(dim, baseType) -> true + | _ -> false + + [] + member x.Naive() = + x.IsMatrixNaive typeof && x.IsMatrixNaive typeof + + [] + member x.Optimized() = + x.IsMatrixOptimized typeof && x.IsMatrixOptimized typeof + +[] +type ``TypePatterns List``() = + + member inline x.IsListNaive (t: Type) = + match t with + | PatternsImpl.PatternsNaive.List(baseType) -> true + | _ -> false + + member inline x.IsListOptimized (t: Type) = + match t with + | TypeMeta.Patterns.ListOf(baseType) -> true + | _ -> false + + [] + member x.Naive() = + x.IsListNaive typeof> && x.IsListNaive typeof + + [] + member x.Optimized() = + x.IsListOptimized typeof> && x.IsListOptimized typeof \ No newline at end of file diff --git a/src/Tests/Aardvark.Base.FSharp.Tests/Aardvark.Base.FSharp.Tests.fsproj b/src/Tests/Aardvark.Base.FSharp.Tests/Aardvark.Base.FSharp.Tests.fsproj index 854a7c3fd..4dcbc73fc 100644 --- a/src/Tests/Aardvark.Base.FSharp.Tests/Aardvark.Base.FSharp.Tests.fsproj +++ b/src/Tests/Aardvark.Base.FSharp.Tests/Aardvark.Base.FSharp.Tests.fsproj @@ -34,6 +34,7 @@ + diff --git a/src/Tests/Aardvark.Base.FSharp.Tests/TypePatternsTests.fs b/src/Tests/Aardvark.Base.FSharp.Tests/TypePatternsTests.fs new file mode 100644 index 000000000..ff1bdd5c6 --- /dev/null +++ b/src/Tests/Aardvark.Base.FSharp.Tests/TypePatternsTests.fs @@ -0,0 +1,50 @@ +namespace Aardvark.Base.FSharp.Tests + +open System +open Aardvark.Base +open Aardvark.Base.TypeMeta + +open FsUnit +open NUnit.Framework + +module ``TypePatterns Tests`` = + + [] + let ``[TypePatterns] Matrix``() = + let test43 (t: Type) = + match t with + | MatrixOf (s, Integral) -> s |> should equal (V2i(4, 3)) + | _ -> failwith $"failed pattern {t}" + + test43 typeof + test43 typeof + + [] + let ``[TypePatterns] List``() = + let test (t: Type) = + match t with + | ListOf Fractional -> () + | _ -> failwithf $"failed pattern {t}" + + test typeof> + test typeof> + + [] + let ``[TypePatterns] Seq``() = + let test (t: Type) = + match t with + | SeqOf Numeric -> () + | _ -> failwithf $"failed pattern {t}" + + test typeof> + test typeof> + + [] + let ``[TypePatterns] Ref``() = + let test (t: Type) = + match t with + | RefOf Vector -> () + | _ -> failwithf $"failed pattern {t}" + + test typeof> + test typeof> \ No newline at end of file