funcs_math.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. // Copyright 2022-2023 EMQ Technologies Co., Ltd.
  2. //
  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. package function
  15. import (
  16. "fmt"
  17. "math"
  18. "math/rand"
  19. "github.com/lf-edge/ekuiper/pkg/api"
  20. "github.com/lf-edge/ekuiper/pkg/ast"
  21. "github.com/lf-edge/ekuiper/pkg/cast"
  22. )
  23. func registerMathFunc() {
  24. builtins["abs"] = builtinFunc{
  25. fType: ast.FuncTypeScalar,
  26. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  27. switch v := args[0].(type) {
  28. case int:
  29. return int(math.Abs(float64(v))), true
  30. case int64:
  31. return int64(math.Abs(float64(v))), true
  32. case float64:
  33. return math.Abs(v), true
  34. default:
  35. if vi, err := cast.ToInt(v, cast.STRICT); err == nil {
  36. return int(math.Abs(float64(vi))), true
  37. }
  38. if vf, err := cast.ToFloat64(v, cast.STRICT); err == nil {
  39. return math.Abs(vf), true
  40. }
  41. return fmt.Errorf("only float64 & int type are supported"), false
  42. }
  43. },
  44. val: ValidateOneNumberArg,
  45. check: returnNilIfHasAnyNil,
  46. }
  47. builtins["acos"] = builtinFunc{
  48. fType: ast.FuncTypeScalar,
  49. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  50. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  51. r := math.Acos(v)
  52. if math.IsNaN(r) {
  53. return nil, true
  54. } else {
  55. return r, true
  56. }
  57. } else {
  58. return e, false
  59. }
  60. },
  61. val: ValidateOneNumberArg,
  62. check: returnNilIfHasAnyNil,
  63. }
  64. builtins["asin"] = builtinFunc{
  65. fType: ast.FuncTypeScalar,
  66. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  67. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  68. r := math.Asin(v)
  69. if math.IsNaN(r) {
  70. return nil, true
  71. } else {
  72. return r, true
  73. }
  74. } else {
  75. return e, false
  76. }
  77. },
  78. val: ValidateOneNumberArg,
  79. check: returnNilIfHasAnyNil,
  80. }
  81. builtins["atan"] = builtinFunc{
  82. fType: ast.FuncTypeScalar,
  83. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  84. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  85. r := math.Atan(v)
  86. if math.IsNaN(r) {
  87. return nil, true
  88. } else {
  89. return r, true
  90. }
  91. } else {
  92. return e, false
  93. }
  94. },
  95. val: ValidateOneNumberArg,
  96. check: returnNilIfHasAnyNil,
  97. }
  98. builtins["atan2"] = builtinFunc{
  99. fType: ast.FuncTypeScalar,
  100. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  101. if v1, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  102. if v2, e1 := cast.ToFloat64(args[1], cast.CONVERT_SAMEKIND); e1 == nil {
  103. r := math.Atan2(v1, v2)
  104. if math.IsNaN(r) {
  105. return nil, true
  106. } else {
  107. return r, true
  108. }
  109. } else {
  110. return e1, false
  111. }
  112. } else {
  113. return e, false
  114. }
  115. },
  116. val: ValidateTwoNumberArg,
  117. check: returnNilIfHasAnyNil,
  118. }
  119. builtins["bitand"] = builtinFunc{
  120. fType: ast.FuncTypeScalar,
  121. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  122. v1, err := cast.ToInt(args[0], cast.STRICT)
  123. if err != nil {
  124. return fmt.Errorf("Expect int type for the first operand but got %v", args[0]), false
  125. }
  126. v2, err := cast.ToInt(args[1], cast.STRICT)
  127. if err != nil {
  128. return fmt.Errorf("Expect int type for the second operand but got %v", args[1]), false
  129. }
  130. return v1 & v2, true
  131. },
  132. val: ValidateTwoIntArg,
  133. check: returnNilIfHasAnyNil,
  134. }
  135. builtins["bitor"] = builtinFunc{
  136. fType: ast.FuncTypeScalar,
  137. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  138. v1, err := cast.ToInt(args[0], cast.STRICT)
  139. if err != nil {
  140. return fmt.Errorf("Expect int type for the first operand but got %v", args[0]), false
  141. }
  142. v2, err := cast.ToInt(args[1], cast.STRICT)
  143. if err != nil {
  144. return fmt.Errorf("Expect int type for the second operand but got %v", args[1]), false
  145. }
  146. return v1 | v2, true
  147. },
  148. val: ValidateTwoIntArg,
  149. check: returnNilIfHasAnyNil,
  150. }
  151. builtins["bitxor"] = builtinFunc{
  152. fType: ast.FuncTypeScalar,
  153. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  154. v1, err := cast.ToInt(args[0], cast.STRICT)
  155. if err != nil {
  156. return fmt.Errorf("Expect int type for the first operand but got %v", args[0]), false
  157. }
  158. v2, err := cast.ToInt(args[1], cast.STRICT)
  159. if err != nil {
  160. return fmt.Errorf("Expect int type for the second operand but got %v", args[1]), false
  161. }
  162. return v1 ^ v2, true
  163. },
  164. val: ValidateTwoIntArg,
  165. check: returnNilIfHasAnyNil,
  166. }
  167. builtins["bitnot"] = builtinFunc{
  168. fType: ast.FuncTypeScalar,
  169. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  170. v1, err := cast.ToInt(args[0], cast.STRICT)
  171. if err != nil {
  172. return fmt.Errorf("Expect int type for operand but got %v", args[0]), false
  173. }
  174. return ^v1, true
  175. },
  176. val: func(_ api.FunctionContext, args []ast.Expr) error {
  177. if err := ValidateLen(1, len(args)); err != nil {
  178. return err
  179. }
  180. if ast.IsFloatArg(args[0]) || ast.IsStringArg(args[0]) || ast.IsTimeArg(args[0]) || ast.IsBooleanArg(args[0]) {
  181. return ProduceErrInfo(0, "int")
  182. }
  183. return nil
  184. },
  185. check: returnNilIfHasAnyNil,
  186. }
  187. builtins["ceil"] = builtinFunc{
  188. fType: ast.FuncTypeScalar,
  189. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  190. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  191. return math.Ceil(v), true
  192. } else {
  193. return e, false
  194. }
  195. },
  196. val: ValidateOneNumberArg,
  197. check: returnNilIfHasAnyNil,
  198. }
  199. builtins["cos"] = builtinFunc{
  200. fType: ast.FuncTypeScalar,
  201. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  202. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  203. r := math.Cos(v)
  204. if math.IsNaN(r) {
  205. return nil, true
  206. } else {
  207. return r, true
  208. }
  209. } else {
  210. return e, false
  211. }
  212. },
  213. val: ValidateOneNumberArg,
  214. check: returnNilIfHasAnyNil,
  215. }
  216. builtins["cosh"] = builtinFunc{
  217. fType: ast.FuncTypeScalar,
  218. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  219. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  220. r := math.Cosh(v)
  221. if math.IsNaN(r) {
  222. return nil, true
  223. } else {
  224. return r, true
  225. }
  226. } else {
  227. return e, false
  228. }
  229. },
  230. val: ValidateOneNumberArg,
  231. check: returnNilIfHasAnyNil,
  232. }
  233. builtins["exp"] = builtinFunc{
  234. fType: ast.FuncTypeScalar,
  235. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  236. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  237. r := math.Exp(v)
  238. if math.IsNaN(r) {
  239. return nil, true
  240. } else {
  241. return r, true
  242. }
  243. } else {
  244. return e, false
  245. }
  246. },
  247. val: ValidateOneNumberArg,
  248. check: returnNilIfHasAnyNil,
  249. }
  250. builtins["ln"] = builtinFunc{
  251. fType: ast.FuncTypeScalar,
  252. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  253. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  254. r := math.Log2(v)
  255. if math.IsNaN(r) {
  256. return nil, true
  257. } else {
  258. return r, true
  259. }
  260. } else {
  261. return e, false
  262. }
  263. },
  264. val: ValidateOneNumberArg,
  265. check: returnNilIfHasAnyNil,
  266. }
  267. builtins["log"] = builtinFunc{
  268. fType: ast.FuncTypeScalar,
  269. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  270. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  271. r := math.Log10(v)
  272. if math.IsNaN(r) {
  273. return nil, true
  274. } else {
  275. return r, true
  276. }
  277. } else {
  278. return e, false
  279. }
  280. },
  281. val: ValidateOneNumberArg,
  282. check: returnNilIfHasAnyNil,
  283. }
  284. builtins["mod"] = builtinFunc{
  285. fType: ast.FuncTypeScalar,
  286. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  287. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  288. if v1, e1 := cast.ToFloat64(args[1], cast.CONVERT_SAMEKIND); e == nil {
  289. return math.Mod(v, v1), true
  290. } else {
  291. return e1, false
  292. }
  293. } else {
  294. return e, false
  295. }
  296. },
  297. val: ValidateTwoNumberArg,
  298. check: returnNilIfHasAnyNil,
  299. }
  300. builtins["power"] = builtinFunc{
  301. fType: ast.FuncTypeScalar,
  302. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  303. if v1, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  304. if v2, e2 := cast.ToFloat64(args[1], cast.CONVERT_SAMEKIND); e2 == nil {
  305. return math.Pow(v1, v2), true
  306. } else {
  307. return e2, false
  308. }
  309. } else {
  310. return e, false
  311. }
  312. },
  313. val: ValidateTwoNumberArg,
  314. check: returnNilIfHasAnyNil,
  315. }
  316. builtins["rand"] = builtinFunc{
  317. fType: ast.FuncTypeScalar,
  318. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  319. return rand.Float64(), true
  320. },
  321. val: ValidateNoArg,
  322. }
  323. builtins["round"] = builtinFunc{
  324. fType: ast.FuncTypeScalar,
  325. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  326. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  327. return math.Round(v), true
  328. } else {
  329. return e, false
  330. }
  331. },
  332. val: ValidateOneNumberArg,
  333. check: returnNilIfHasAnyNil,
  334. }
  335. builtins["sign"] = builtinFunc{
  336. fType: ast.FuncTypeScalar,
  337. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  338. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  339. if v > 0 {
  340. return 1, true
  341. } else if v < 0 {
  342. return -1, true
  343. } else {
  344. return 0, true
  345. }
  346. } else {
  347. return e, false
  348. }
  349. },
  350. val: ValidateOneNumberArg,
  351. check: returnNilIfHasAnyNil,
  352. }
  353. builtins["sin"] = builtinFunc{
  354. fType: ast.FuncTypeScalar,
  355. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  356. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  357. r := math.Sin(v)
  358. if math.IsNaN(r) {
  359. return nil, true
  360. } else {
  361. return r, true
  362. }
  363. } else {
  364. return e, false
  365. }
  366. },
  367. val: ValidateOneNumberArg,
  368. check: returnNilIfHasAnyNil,
  369. }
  370. builtins["sinh"] = builtinFunc{
  371. fType: ast.FuncTypeScalar,
  372. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  373. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  374. r := math.Sinh(v)
  375. if math.IsNaN(r) {
  376. return nil, true
  377. } else {
  378. return r, true
  379. }
  380. } else {
  381. return e, false
  382. }
  383. },
  384. val: ValidateOneNumberArg,
  385. check: returnNilIfHasAnyNil,
  386. }
  387. builtins["sqrt"] = builtinFunc{
  388. fType: ast.FuncTypeScalar,
  389. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  390. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  391. r := math.Sqrt(v)
  392. if math.IsNaN(r) {
  393. return nil, true
  394. } else {
  395. return r, true
  396. }
  397. } else {
  398. return e, false
  399. }
  400. },
  401. val: ValidateOneNumberArg,
  402. check: returnNilIfHasAnyNil,
  403. }
  404. builtins["tan"] = builtinFunc{
  405. fType: ast.FuncTypeScalar,
  406. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  407. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  408. r := math.Tan(v)
  409. if math.IsNaN(r) {
  410. return nil, true
  411. } else {
  412. return r, true
  413. }
  414. } else {
  415. return e, false
  416. }
  417. },
  418. val: ValidateOneNumberArg,
  419. check: returnNilIfHasAnyNil,
  420. }
  421. builtins["tanh"] = builtinFunc{
  422. fType: ast.FuncTypeScalar,
  423. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  424. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  425. r := math.Tanh(v)
  426. if math.IsNaN(r) {
  427. return nil, true
  428. } else {
  429. return r, true
  430. }
  431. } else {
  432. return e, false
  433. }
  434. },
  435. val: ValidateOneNumberArg,
  436. check: returnNilIfHasAnyNil,
  437. }
  438. }