1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16declare interface ArkTools {
17    isAOTCompiled(args: any): boolean;
18}
19declare function print(arg:any):string;
20
21function printZero(x: any) {
22    if (Object.is(x, -0)) {
23        print("-0");
24    } else {
25        print(x);
26    }
27}
28
29function replace(a : number)
30{
31    return a;
32}
33
34// Use try to prevent inlining to main
35function printExpm1(x: any) {
36    try {
37        print(Math.expm1(x));
38    } finally {
39    }
40}
41
42let doubleObj = {
43    valueOf: () => { return 2.7; }
44}
45
46let nanObj = {
47    valueOf: () => { return "something"; }
48}
49
50let obj = {
51    valueOf: () => {
52        print("obj.valueOf")
53        return -23;
54    }
55};
56
57// Check without params
58//aot: [trace] aot inline builtin: Math.expm1, caller function name:func_main_0@builtinMathExpm1
59print(Math.expm1()); //: NaN
60
61// Check with single param
62//aot: [trace] aot inline builtin: Math.expm1, caller function name:func_main_0@builtinMathExpm1
63//aot: [trace] aot inline function name: #*#printZero@builtinMathExpm1 caller function name: func_main_0@builtinMathExpm1
64//aot: [trace] aot inline builtin: Object.is, caller function name:#*#printZero@builtinMathExpm1
65printZero(Math.expm1(0)); //: 0
66//aot: [trace] aot inline builtin: Math.expm1, caller function name:func_main_0@builtinMathExpm1
67//aot: [trace] aot inline function name: #*#printZero@builtinMathExpm1 caller function name: func_main_0@builtinMathExpm1
68//aot: [trace] aot inline builtin: Object.is, caller function name:#*#printZero@builtinMathExpm1
69printZero("1/x: " + 1 / Math.expm1(-0)); //: 1/x: -Infinity
70//aot: [trace] aot inline builtin: Math.expm1, caller function name:func_main_0@builtinMathExpm1
71print(Math.expm1(1)); //: 1.718281828459045
72//aot: [trace] aot inline builtin: Math.expm1, caller function name:func_main_0@builtinMathExpm1
73print(Math.expm1(-100)); //: -1
74//aot: [trace] aot inline builtin: Math.expm1, caller function name:func_main_0@builtinMathExpm1
75print(Math.expm1(100)); //: 2.6881171418161356e+43
76//aot: [trace] aot inline builtin: Math.expm1, caller function name:func_main_0@builtinMathExpm1
77print(Math.expm1(10e-10)); //: 1.0000000005000001e-9
78
79// Check with special float params
80//aot: [trace] aot inline builtin: Math.expm1, caller function name:func_main_0@builtinMathExpm1
81print(Math.expm1(-Infinity)); //: -1
82//aot: [trace] aot inline builtin: Math.expm1, caller function name:func_main_0@builtinMathExpm1
83print(Math.expm1(Infinity)); //: Infinity
84//aot: [trace] aot inline builtin: Math.expm1, caller function name:func_main_0@builtinMathExpm1
85print(Math.expm1(NaN)); //: NaN
86
87// Check with 2 params
88//aot: [trace] aot inline builtin: Math.expm1, caller function name:func_main_0@builtinMathExpm1
89print(Math.expm1(1, 1)); //: 1.718281828459045
90
91// Check with 3 params
92//aot: [trace] aot inline builtin: Math.expm1, caller function name:func_main_0@builtinMathExpm1
93print(Math.expm1(1, 1, 1)); //: 1.718281828459045
94
95// Check with 4 params
96//aot: [trace] aot inline builtin: Math.expm1, caller function name:func_main_0@builtinMathExpm1
97print(Math.expm1(1, 1, 1, 1)); //: 1.718281828459045
98
99// Check with 5 params
100//aot: [trace] aot inline builtin: Math.expm1, caller function name:func_main_0@builtinMathExpm1
101print(Math.expm1(1, 1, 1, 1, 1)); //: 1.718281828459045
102
103try {
104    //aot: [trace] aot inline builtin: Math.expm1, caller function name:func_main_0@builtinMathExpm1
105    print(Math.expm1(1)); //: 1.718281828459045
106} catch(e) {}
107
108// Replace standart builtin
109let trueExpm1 = Math.expm1
110Math.expm1 = replace
111print(Math.expm1(111)); //: 111
112Math.expm1 = trueExpm1
113
114//aot: [trace] aot inline builtin: Math.expm1, caller function name:#*#printExpm1@builtinMathExpm1
115printExpm1(1); //: 1.718281828459045
116
117// Call standart builtin with non-number param
118//aot: [trace] aot inline builtin: Math.expm1, caller function name:#*#printExpm1@builtinMathExpm1
119//aot: [trace] Check Type: NotNumber1
120printExpm1("1"); //: 1.718281828459045
121//aot: [trace] aot inline builtin: Math.expm1, caller function name:#*#printExpm1@builtinMathExpm1
122//aot: [trace] Check Type: NotNumber1
123printExpm1("NaN"); //: NaN
124//aot: [trace] aot inline builtin: Math.expm1, caller function name:#*#printExpm1@builtinMathExpm1
125//aot: [trace] Check Type: NotNumber1
126printExpm1("abc"); //: NaN
127
128if (ArkTools.isAOTCompiled(printExpm1)) {
129    // Replace standard builtin after call to standard builtin was profiled
130    Math.expm1 = replace
131}
132
133printExpm1(1); //pgo: 1.718281828459045
134//aot: [trace] Check Type: NotCallTarget1
135//aot: 1
136
137printExpm1(2); //pgo: 6.38905609893065
138//aot: [trace] Check Type: NotCallTarget1
139//aot: 2
140
141printExpm1("1"); //pgo: 1.718281828459045
142//aot: [trace] Check Type: NotCallTarget1
143//aot: 1
144
145printExpm1("2"); //pgo: 6.38905609893065
146//aot: [trace] Check Type: NotCallTarget1
147//aot: 2
148
149Math.expm1 = trueExpm1
150
151// Check IR correctness inside try-block
152try {
153    //aot: [trace] aot inline builtin: Math.expm1, caller function name:#*#printExpm1@builtinMathExpm1
154    printExpm1(1); //: 1.718281828459045
155    //aot: [trace] aot inline builtin: Math.expm1, caller function name:#*#printExpm1@builtinMathExpm1
156    printExpm1(1, 2); //: 1.718281828459045
157    //aot: [trace] aot inline builtin: Math.expm1, caller function name:#*#printExpm1@builtinMathExpm1
158    printExpm1(1, 2); //: 1.718281828459045
159    //aot: [trace] aot inline builtin: Math.expm1, caller function name:#*#printExpm1@builtinMathExpm1
160    //aot: [trace] Check Type: NotNumber1
161    printExpm1("abc", 3e3); //: NaN
162} catch (e) {
163}
164
165//aot: [trace] aot inline builtin: Math.expm1, caller function name:#*#printExpm1@builtinMathExpm1
166//aot: [trace] Check Type: NotNumber1
167//: obj.valueOf
168printExpm1(obj); //: -0.9999999998973812
169//aot: [trace] aot inline builtin: Math.expm1, caller function name:#*#printExpm1@builtinMathExpm1
170//aot: [trace] Check Type: NotNumber1
171printExpm1(doubleObj); //: 13.879731724872837
172//aot: [trace] aot inline builtin: Math.expm1, caller function name:#*#printExpm1@builtinMathExpm1
173//aot: [trace] Check Type: NotNumber1
174printExpm1(nanObj); //: NaN
175