1 /**
2 * Copyright (c) 2021-2025 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
16 #include <climits>
17 #include <cstdint>
18 #include <cstdlib>
19 #include <limits>
20 #include <random>
21 #include <cmath>
22
23 #include "libpandabase/utils/bit_utils.h"
24 #include "macros.h"
25 #include "plugins/ets/runtime/ets_coroutine.h"
26 #include "plugins/ets/runtime/ets_vm.h"
27
28 namespace ark::ets::intrinsics {
29
30 namespace {
31 constexpr int INT_MAX_SIZE = 63;
32 constexpr double ROUND_BIAS = 0.5;
33
ToInt32(double x)34 int32_t ToInt32(double x)
35 {
36 if (std::isinf(x)) {
37 return 0;
38 }
39
40 if ((std::isfinite(x)) && (x <= INT_MAX) && (x >= INT_MIN)) {
41 return static_cast<int32_t>(x);
42 }
43
44 double intPart = 0.0;
45 std::modf(x, &intPart);
46 double int64Max = std::pow(2, INT_MAX_SIZE);
47 intPart = std::fmod(intPart, int64Max);
48 return static_cast<int32_t>(static_cast<int64_t>(intPart));
49 }
50
ToUint32(double x)51 uint32_t ToUint32(double x)
52 {
53 return static_cast<uint32_t>(ToInt32(x));
54 }
55 } // namespace
56
StdMathRandom()57 extern "C" double StdMathRandom()
58 {
59 std::uniform_real_distribution<double> urd(0.0, 1.0);
60 auto *coro = EtsCoroutine::GetCurrent();
61 ASSERT(coro != nullptr);
62 auto *pandaVM = coro->GetPandaVM();
63 ASSERT(pandaVM != nullptr);
64 return urd(pandaVM->GetRandomEngine());
65 }
66
StdMathAcos(double val)67 extern "C" double StdMathAcos(double val)
68 {
69 return std::acos(val);
70 }
71
StdMathAcosh(double val)72 extern "C" double StdMathAcosh(double val)
73 {
74 return std::acosh(val);
75 }
76
StdMathAsin(double val)77 extern "C" double StdMathAsin(double val)
78 {
79 return std::asin(val);
80 }
81
StdMathAsinh(double val)82 extern "C" double StdMathAsinh(double val)
83 {
84 return std::asinh(val);
85 }
86
StdMathAtan2(double val1,double val2)87 extern "C" double StdMathAtan2(double val1, double val2)
88 {
89 return std::atan2(val1, val2);
90 }
91
StdMathAtanh(double val)92 extern "C" double StdMathAtanh(double val)
93 {
94 return std::atanh(val);
95 }
96
StdMathAtan(double val)97 extern "C" double StdMathAtan(double val)
98 {
99 return std::atan(val);
100 }
101
StdMathSinh(double val)102 extern "C" double StdMathSinh(double val)
103 {
104 return std::sinh(val);
105 }
106
StdMathCosh(double val)107 extern "C" double StdMathCosh(double val)
108 {
109 return std::cosh(val);
110 }
111
StdMathFloor(double val)112 extern "C" double StdMathFloor(double val)
113 {
114 return std::floor(val);
115 }
116
StdMathRound(double val)117 extern "C" double StdMathRound(double val)
118 {
119 double res = std::ceil(val);
120 if (res - val > ROUND_BIAS) {
121 res -= 1.0;
122 }
123 return res;
124 }
125
StdMathTrunc(double val)126 extern "C" double StdMathTrunc(double val)
127 {
128 return std::trunc(val);
129 }
130
StdMathCbrt(double val)131 extern "C" double StdMathCbrt(double val)
132 {
133 return std::cbrt(val);
134 }
135
StdMathTan(double val)136 extern "C" double StdMathTan(double val)
137 {
138 return std::tan(val);
139 }
140
StdMathTanh(double val)141 extern "C" double StdMathTanh(double val)
142 {
143 return std::tanh(val);
144 }
145
StdMathExp(double val)146 extern "C" double StdMathExp(double val)
147 {
148 return std::exp(val);
149 }
150
StdMathLog10(double val)151 extern "C" double StdMathLog10(double val)
152 {
153 return std::log10(val);
154 }
155
StdMathExpm1(double val)156 extern "C" double StdMathExpm1(double val)
157 {
158 return std::expm1(val);
159 }
160
StdMathCeil(double val)161 extern "C" double StdMathCeil(double val)
162 {
163 return std::ceil(val);
164 }
165
StdMathClz64(int64_t val)166 extern "C" int32_t StdMathClz64(int64_t val)
167 {
168 if (val != 0) {
169 return Clz(static_cast<uint64_t>(val));
170 }
171 return std::numeric_limits<uint64_t>::digits;
172 }
173
StdMathClz32(int32_t val)174 extern "C" int32_t StdMathClz32(int32_t val)
175 {
176 if (val != 0) {
177 return Clz(static_cast<uint32_t>(val));
178 }
179 return std::numeric_limits<uint32_t>::digits;
180 }
181
StdMathClz32Double(double val)182 extern "C" double StdMathClz32Double(double val)
183 {
184 auto intValue = ToUint32(val);
185 if (intValue != 0) {
186 return static_cast<double>(Clz(intValue));
187 }
188 return std::numeric_limits<uint32_t>::digits;
189 }
190
StdMathLog(double val)191 extern "C" double StdMathLog(double val)
192 {
193 return std::log(val);
194 }
195
StdMathRem(double val,double val2)196 extern "C" double StdMathRem(double val, double val2)
197 {
198 return std::remainder(val, val2);
199 }
200
StdMathMod(double val,double val2)201 extern "C" double StdMathMod(double val, double val2)
202 {
203 return std::fmod(val, val2);
204 }
205
StdMathSignbit(double val)206 extern "C" bool StdMathSignbit(double val)
207 {
208 return std::signbit(val);
209 }
210
StdMathImul(double val,double val2)211 extern "C" int StdMathImul(double val, double val2)
212 {
213 if (!std::isfinite(val) || !std::isfinite(val2)) {
214 return 0;
215 }
216 return static_cast<int32_t>(static_cast<int64_t>(val) * static_cast<int64_t>(val2));
217 }
218
StdMathFround(double val)219 extern "C" double StdMathFround(double val)
220 {
221 if (std::isnan(val)) {
222 return std::numeric_limits<float>::quiet_NaN();
223 }
224
225 return static_cast<float>(val);
226 }
StdMathHypot(double val1,double val2)227 extern "C" double StdMathHypot(double val1, double val2)
228 {
229 return std::hypot(val1, val2);
230 }
231 } // namespace ark::ets::intrinsics
232