Skip to content

Commit c3ee896

Browse files
committed
math ops
1 parent 5d52ba0 commit c3ee896

File tree

2 files changed

+588
-2
lines changed

2 files changed

+588
-2
lines changed

src/ProvidedTypes.fs

Lines changed: 307 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13738,6 +13738,7 @@ namespace ProviderImplementation.ProvidedTypes
1373813738
let decimalTypeTgt = convTypeToTgt typeof<decimal>
1373913739
let convertTypeTgt = convTypeToTgt typeof<System.Convert>
1374013740
let stringTypeTgt = convTypeToTgt typeof<string>
13741+
let mathTypeTgt = convTypeToTgt typeof<System.Math>
1374113742

1374213743
let makeTypePattern tp =
1374313744
let tt = convTypeToTgt tp
@@ -13805,6 +13806,50 @@ namespace ProviderImplementation.ProvidedTypes
1380513806
| _ ->
1380613807
invalidArg "templateParameter" "The parameter is not a recognized method name"
1380713808

13809+
let (|MakeDecimal|_|) =
13810+
let minfo1 = languagePrimitivesType().GetNestedType("IntrinsicFunctions").GetMethod("MakeDecimal")
13811+
(fun tm ->
13812+
match tm with
13813+
| Call(None, minfo2, args)
13814+
#if FX_NO_REFLECTION_METADATA_TOKENS
13815+
when ( // if metadata tokens are not available we'll rely only on equality of method references
13816+
#else
13817+
when (minfo1.MetadataToken = minfo2.MetadataToken &&
13818+
#endif
13819+
minfo1 = minfo2) ->
13820+
Some(args)
13821+
| _ -> None)
13822+
13823+
let (|NaN|_|) =
13824+
let operatorsType = convTypeToTgt (typedefof<list<_>>.Assembly.GetType("Microsoft.FSharp.Core.Operators"))
13825+
let minfo1 = operatorsType.GetProperty("NaN").GetGetMethod()
13826+
(fun e ->
13827+
match e with
13828+
| Call(None, minfo2, [])
13829+
#if FX_NO_REFLECTION_METADATA_TOKENS
13830+
when ( // if metadata tokens are not available we'll rely only on equality of method references
13831+
#else
13832+
when (minfo1.MetadataToken = minfo2.MetadataToken &&
13833+
#endif
13834+
minfo1 = minfo2) ->
13835+
Some()
13836+
| _ -> None)
13837+
13838+
let (|NaNSingle|_|) =
13839+
let operatorsType = convTypeToTgt (typedefof<list<_>>.Assembly.GetType("Microsoft.FSharp.Core.Operators"))
13840+
let minfo1 = operatorsType.GetProperty("NaNSingle").GetGetMethod()
13841+
(fun e ->
13842+
match e with
13843+
| Call(None, minfo2, [])
13844+
#if FX_NO_REFLECTION_METADATA_TOKENS
13845+
when ( // if metadata tokens are not available we'll rely only on equality of method references
13846+
#else
13847+
when (minfo1.MetadataToken = minfo2.MetadataToken &&
13848+
#endif
13849+
minfo1 = minfo2) ->
13850+
Some()
13851+
| _ -> None)
13852+
1380813853
let (|LessThan|_|) = (|SpecificCall|_|) <@ (<) @>
1380913854
let (|GreaterThan|_|) = (|SpecificCall|_|) <@ (>) @>
1381013855
let (|LessThanOrEqual|_|) = (|SpecificCall|_|) <@ (<=) @>
@@ -13824,6 +13869,10 @@ namespace ProviderImplementation.ProvidedTypes
1382413869
let (|Or|_|) = (|SpecificCall|_|) <@ (|||) @>
1382513870
let (|Xor|_|) = (|SpecificCall|_|) <@ (^^^) @>
1382613871
let (|Not|_|) = (|SpecificCall|_|) <@ (~~~) @>
13872+
//let (|Compare|_|) = (|SpecificCall|_|) <@ compare @>
13873+
let (|Max|_|) = (|SpecificCall|_|) <@ max @>
13874+
let (|Min|_|) = (|SpecificCall|_|) <@ min @>
13875+
//let (|Hash|_|) = (|SpecificCall|_|) <@ hash @>
1382713876
let (|CallByte|_|) = (|SpecificCall|_|) <@ byte @>
1382813877
let (|CallSByte|_|) = (|SpecificCall|_|) <@ sbyte @>
1382913878
let (|CallUInt16|_|) = (|SpecificCall|_|) <@ uint16 @>
@@ -13844,7 +13893,54 @@ namespace ProviderImplementation.ProvidedTypes
1384413893
let (|GetArray2D|_|) = (|SpecificCall|_|) <@ LanguagePrimitives.IntrinsicFunctions.GetArray2D @>
1384513894
let (|GetArray3D|_|) = (|SpecificCall|_|) <@ LanguagePrimitives.IntrinsicFunctions.GetArray3D @>
1384613895
let (|GetArray4D|_|) = (|SpecificCall|_|) <@ LanguagePrimitives.IntrinsicFunctions.GetArray4D @>
13847-
13896+
13897+
let (|Abs|_|) = (|SpecificCall|_|) <@ abs @>
13898+
let (|Acos|_|) = (|SpecificCall|_|) <@ acos @>
13899+
let (|Asin|_|) = (|SpecificCall|_|) <@ asin @>
13900+
let (|Atan|_|) = (|SpecificCall|_|) <@ atan @>
13901+
let (|Atan2|_|) = (|SpecificCall|_|) <@ atan2 @>
13902+
let (|Ceil|_|) = (|SpecificCall|_|) <@ ceil @>
13903+
let (|Exp|_|) = (|SpecificCall|_|) <@ exp @>
13904+
let (|Floor|_|) = (|SpecificCall|_|) <@ floor @>
13905+
let (|Truncate|_|) = (|SpecificCall|_|) <@ truncate @>
13906+
let (|Round|_|) = (|SpecificCall|_|) <@ round @>
13907+
let (|Sign|_|) = (|SpecificCall|_|) <@ sign @>
13908+
let (|Log|_|) = (|SpecificCall|_|) <@ log @>
13909+
let (|Log10|_|) = (|SpecificCall|_|) <@ log10 @>
13910+
let (|Sqrt|_|) = (|SpecificCall|_|) <@ sqrt @>
13911+
let (|Cos|_|) = (|SpecificCall|_|) <@ cos @>
13912+
let (|Cosh|_|) = (|SpecificCall|_|) <@ cosh @>
13913+
let (|Sin|_|) = (|SpecificCall|_|) <@ sin @>
13914+
let (|Sinh|_|) = (|SpecificCall|_|) <@ sinh @>
13915+
let (|Tan|_|) = (|SpecificCall|_|) <@ tan @>
13916+
let (|Tanh|_|) = (|SpecificCall|_|) <@ tanh @>
13917+
//let (|Range|_|) = (|SpecificCall|_|) <@ (..) @>
13918+
//let (|RangeStep|_|) = (|SpecificCall|_|) <@ (.. ..) @>
13919+
let (|Pow|_|) = (|SpecificCall|_|) <@ ( ** ) @>
13920+
//let (|Pown|_|) = (|SpecificCall|_|) <@ pown @>
13921+
13922+
let mathOp t1 name =
13923+
match t1 with
13924+
| Double ->
13925+
let m = mathTypeTgt.GetMethod(name, [|t1|])
13926+
ilg.Emit(I_call(Normalcall, transMeth m, None))
13927+
| Single ->
13928+
ilg.Emit(I_conv DT_R8)
13929+
let m = mathTypeTgt.GetMethod(name, [|convTypeToTgt typeof<double>|])
13930+
ilg.Emit(I_call(Normalcall, transMeth m, None))
13931+
ilg.Emit(I_conv DT_R4)
13932+
| StaticMethod name [|t1|] m ->
13933+
ilg.Emit(I_call(Normalcall, transMeth m, None))
13934+
| _ -> failwithf "%s not supported for type %s" name t1.Name
13935+
13936+
let lessThan (a1 : Expr) (a2 : Expr) =
13937+
match <@@ (<) @@> with
13938+
| DerivedPatterns.Lambdas(vars,Call(None,meth,_)) ->
13939+
let targetType = convTypeToTgt meth.DeclaringType
13940+
let m = targetType.GetMethod(meth.Name, bindAll).MakeGenericMethod(a1.Type)
13941+
Expr.Call(m, [a1; a2])
13942+
| _ -> failwith "Unreachable"
13943+
1384813944
let isEmpty s = (s = ExpectedStackState.Empty)
1384913945
let isAddress s = (s = ExpectedStackState.Address)
1385013946
let rec emitLambda(callSiteIlg: ILGenerator, v: Var, body: Expr, freeVars: seq<Var>, lambdaLocals: Dictionary<_, ILLocalBuilder>, parameters) =
@@ -14009,6 +14105,13 @@ namespace ProviderImplementation.ProvidedTypes
1400914105

1401014106
popIfEmptyExpected expectedState
1401114107

14108+
| NaN -> emitExpr ExpectedStackState.Value <@@ Double.NaN @@>
14109+
14110+
| NaNSingle -> emitExpr ExpectedStackState.Value <@@ Single.NaN @@>
14111+
14112+
| MakeDecimal(args) ->
14113+
emitExpr ExpectedStackState.Value (Expr.NewObjectUnchecked(decimalConstructor(), args))
14114+
1401214115
| LessThan(None, [t1], [a1; a2]) ->
1401314116
emitExpr ExpectedStackState.Value a1
1401414117
emitExpr ExpectedStackState.Value a2
@@ -14311,7 +14414,83 @@ namespace ProviderImplementation.ProvidedTypes
1431114414
| StaticMethod "op_Not" [|t1; t1|] m ->
1431214415
ilg.Emit(I_call(Normalcall, transMeth m, None))
1431314416
| _ -> failwithf "Operator (~~~) not supported for type %s" t1.Name
14314-
14417+
14418+
| Max(None, [t1], [a1; a2]) ->
14419+
match t1 with
14420+
| Double ->
14421+
emitExpr ExpectedStackState.Value a1
14422+
emitExpr ExpectedStackState.Value a2
14423+
let m = mathTypeTgt.GetMethod("Max", [|t1; t1|])
14424+
ilg.Emit(I_call(Normalcall, transMeth m, None))
14425+
| Single ->
14426+
emitExpr ExpectedStackState.Value a1
14427+
emitExpr ExpectedStackState.Value a2
14428+
ilg.Emit(I_conv DT_R8)
14429+
let t = convTypeToTgt typeof<double>
14430+
let m = mathTypeTgt.GetMethod("Max", [|t;t|])
14431+
ilg.Emit(I_call(Normalcall, transMeth m, None))
14432+
ilg.Emit(I_conv DT_R4)
14433+
| _ ->
14434+
match a1,a2 with
14435+
| (Var _ | Value _), (Var _ | Value _) ->
14436+
Expr.IfThenElseUnchecked(lessThan a1 a2, a2, a1)
14437+
|> emitExpr ExpectedStackState.Value
14438+
| (Var _ | Value _), _ ->
14439+
let e2 = Var("e2", a2.Type)
14440+
Expr.Let(e2, a2,
14441+
Expr.IfThenElseUnchecked(lessThan a1 (Expr.Var e2), Expr.Var e2, a1))
14442+
|> emitExpr ExpectedStackState.Value
14443+
| _, (Var _ | Value _) ->
14444+
let e1 = Var("e1", a1.Type)
14445+
Expr.Let(e1, a1,
14446+
Expr.IfThenElseUnchecked((lessThan (Expr.Var e1) a2, a2, (Expr.Var e1))))
14447+
|> emitExpr ExpectedStackState.Value
14448+
| _ ->
14449+
let e1 = Var("e1", a1.Type)
14450+
let e2 = Var("e2", a2.Type)
14451+
Expr.Let(e1, a1,
14452+
Expr.Let(e2, a2,
14453+
Expr.IfThenElseUnchecked(lessThan (Expr.Var e1) (Expr.Var e2), Expr.Var e2, Expr.Var e1)))
14454+
|> emitExpr ExpectedStackState.Value
14455+
14456+
| Min(None, [t1], [a1; a2]) ->
14457+
match t1 with
14458+
| Double ->
14459+
emitExpr ExpectedStackState.Value a1
14460+
emitExpr ExpectedStackState.Value a2
14461+
let m = mathTypeTgt.GetMethod("Min", [|t1; t1|])
14462+
ilg.Emit(I_call(Normalcall, transMeth m, None))
14463+
| Single ->
14464+
emitExpr ExpectedStackState.Value a1
14465+
emitExpr ExpectedStackState.Value a2
14466+
ilg.Emit(I_conv DT_R8)
14467+
let t = convTypeToTgt typeof<double>
14468+
let m = mathTypeTgt.GetMethod("Min", [|t;t|])
14469+
ilg.Emit(I_call(Normalcall, transMeth m, None))
14470+
ilg.Emit(I_conv DT_R4)
14471+
| _ ->
14472+
match a1,a2 with
14473+
| (Var _ | Value _), (Var _ | Value _) ->
14474+
Expr.IfThenElseUnchecked(lessThan a1 a2, a1, a2)
14475+
|> emitExpr ExpectedStackState.Value
14476+
| (Var _ | Value _), _ ->
14477+
let e2 = Var("e2", a2.Type)
14478+
Expr.Let(e2, a2,
14479+
Expr.IfThenElseUnchecked(lessThan a1 (Expr.Var e2), a1, Expr.Var e2))
14480+
|> emitExpr ExpectedStackState.Value
14481+
| _, (Var _ | Value _) ->
14482+
let e1 = Var("e1", a1.Type)
14483+
Expr.Let(e1, a1,
14484+
Expr.IfThenElseUnchecked((lessThan (Expr.Var e1) a2, Expr.Var e1, a2)))
14485+
|> emitExpr ExpectedStackState.Value
14486+
| _ ->
14487+
let e1 = Var("e1", a1.Type)
14488+
let e2 = Var("e2", a2.Type)
14489+
Expr.Let(e1, a1,
14490+
Expr.Let(e2, a2,
14491+
Expr.IfThenElseUnchecked(lessThan (Expr.Var e1) (Expr.Var e2), Expr.Var e1, Expr.Var e2)))
14492+
|> emitExpr ExpectedStackState.Value
14493+
1431514494
| CallByte(None, [t1], [a1]) ->
1431614495
emitExpr ExpectedStackState.Value a1
1431714496
match t1 with
@@ -14552,6 +14731,132 @@ namespace ProviderImplementation.ProvidedTypes
1455214731

1455314732
popIfEmptyExpected expectedState
1455414733

14734+
| Abs(None, [t1], [a1]) ->
14735+
emitExpr ExpectedStackState.Value a1
14736+
match t1 with
14737+
| Int32 | Double | Single | Int64 | Int16 | SByte | Decimal ->
14738+
let m = mathTypeTgt.GetMethod("Abs", [|t1|])
14739+
ilg.Emit(I_call(Normalcall, transMeth m, None))
14740+
| StaticMethod "Abs" [|t1|] m ->
14741+
ilg.Emit(I_call(Normalcall, transMeth m, None))
14742+
| _ -> failwithf "Abs not supported for type %s" t1.Name
14743+
14744+
| Acos(None, [t1], [a1]) ->
14745+
emitExpr ExpectedStackState.Value a1
14746+
mathOp t1 "Acos"
14747+
14748+
| Asin(None, [t1], [a1]) ->
14749+
emitExpr ExpectedStackState.Value a1
14750+
mathOp t1 "Asin"
14751+
14752+
| Atan(None, [t1], [a1]) ->
14753+
emitExpr ExpectedStackState.Value a1
14754+
mathOp t1 "Atan"
14755+
14756+
| Atan2(None, [t1;t2], [a1; a2]) ->
14757+
emitExpr ExpectedStackState.Value a1
14758+
emitExpr ExpectedStackState.Value a2
14759+
match t1 with
14760+
| Double ->
14761+
let m = mathTypeTgt.GetMethod("Atan2", [|t1; t1|])
14762+
ilg.Emit(I_call(Normalcall, transMeth m, None))
14763+
| Single ->
14764+
ilg.Emit(I_conv DT_R8)
14765+
let t = convTypeToTgt typeof<double>
14766+
let m = mathTypeTgt.GetMethod("Atan2", [|t;t|])
14767+
ilg.Emit(I_call(Normalcall, transMeth m, None))
14768+
ilg.Emit(I_conv DT_R4)
14769+
| StaticMethod "Atan2" [|t1; t1|] m ->
14770+
ilg.Emit(I_call(Normalcall, transMeth m, None))
14771+
| _ -> failwithf "Atan2 not supported for type %s" t1.Name
14772+
14773+
| Ceil(None, [t1], [a1]) ->
14774+
emitExpr ExpectedStackState.Value a1
14775+
mathOp t1 "Ceiling"
14776+
14777+
| Exp(None, [t1], [a1]) ->
14778+
emitExpr ExpectedStackState.Value a1
14779+
mathOp t1 "Exp"
14780+
14781+
| Floor(None, [t1], [a1]) ->
14782+
emitExpr ExpectedStackState.Value a1
14783+
mathOp t1 "Floor"
14784+
14785+
| Truncate(None, [t1], [a1]) ->
14786+
emitExpr ExpectedStackState.Value a1
14787+
mathOp t1 "Truncate"
14788+
14789+
| Round(None, [t1], [a1]) ->
14790+
emitExpr ExpectedStackState.Value a1
14791+
mathOp t1 "Round"
14792+
14793+
| Sign(None, [t1], [a1]) ->
14794+
emitExpr ExpectedStackState.Value a1
14795+
match t1 with
14796+
| Int32 | Double | Single | Int64 | Int16 | SByte | Decimal ->
14797+
let m = mathTypeTgt.GetMethod("Sign", [|t1|])
14798+
ilg.Emit(I_call(Normalcall, transMeth m, None))
14799+
| Single ->
14800+
ilg.Emit(I_conv DT_R8)
14801+
let m = mathTypeTgt.GetMethod("Sign", [|convTypeToTgt typeof<double>|])
14802+
ilg.Emit(I_call(Normalcall, transMeth m, None))
14803+
ilg.Emit(I_conv DT_R4)
14804+
| StaticMethod "Sign" [|t1|] m ->
14805+
ilg.Emit(I_call(Normalcall, transMeth m, None))
14806+
| _ -> failwithf "Sign not supported for type %s" t1.Name
14807+
14808+
| Log(None, [t1], [a1]) ->
14809+
emitExpr ExpectedStackState.Value a1
14810+
mathOp t1 "Log"
14811+
14812+
| Log10(None, [t1], [a1]) ->
14813+
emitExpr ExpectedStackState.Value a1
14814+
mathOp t1 "Log10"
14815+
14816+
| Sqrt(None, [t1; t2], [a1]) ->
14817+
emitExpr ExpectedStackState.Value a1
14818+
mathOp t1 "Sqrt"
14819+
14820+
| Cos(None, [t1], [a1]) ->
14821+
emitExpr ExpectedStackState.Value a1
14822+
mathOp t1 "Cos"
14823+
14824+
| Cosh(None, [t1], [a1]) ->
14825+
emitExpr ExpectedStackState.Value a1
14826+
mathOp t1 "Cosh"
14827+
14828+
| Sin(None, [t1], [a1]) ->
14829+
emitExpr ExpectedStackState.Value a1
14830+
mathOp t1 "Sin"
14831+
14832+
| Sinh(None, [t1], [a1]) ->
14833+
emitExpr ExpectedStackState.Value a1
14834+
mathOp t1 "Sinh"
14835+
14836+
| Tan(None, [t1], [a1]) ->
14837+
emitExpr ExpectedStackState.Value a1
14838+
mathOp t1 "Tan"
14839+
14840+
| Tanh(None, [t1], [a1]) ->
14841+
emitExpr ExpectedStackState.Value a1
14842+
mathOp t1 "Tanh"
14843+
14844+
| Pow(None, [t1; t2], [a1; a2]) ->
14845+
emitExpr ExpectedStackState.Value a1
14846+
emitExpr ExpectedStackState.Value a2
14847+
match t1 with
14848+
| Double ->
14849+
let m = mathTypeTgt.GetMethod("Pow", [|t1; t1|])
14850+
ilg.Emit(I_call(Normalcall, transMeth m, None))
14851+
| Single ->
14852+
ilg.Emit(I_conv DT_R8)
14853+
let t = convTypeToTgt typeof<double>
14854+
let m = mathTypeTgt.GetMethod("Pow", [|t;t|])
14855+
ilg.Emit(I_call(Normalcall, transMeth m, None))
14856+
ilg.Emit(I_conv DT_R4)
14857+
| StaticMethod "Pow" [|t1; t2|] m ->
14858+
ilg.Emit(I_call(Normalcall, transMeth m, None))
14859+
| _ -> failwithf "Pow not supported for type %s" t1.Name
1455514860

1455614861
| FieldGet (None,field) when field.DeclaringType.IsEnum ->
1455714862
if expectedState <> ExpectedStackState.Empty then

0 commit comments

Comments
 (0)