funcs_math.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  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["ceiling"] = 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["ceil"] = builtins["ceiling"] // Synonym for CEILING.
  200. builtins["cos"] = builtinFunc{
  201. fType: ast.FuncTypeScalar,
  202. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  203. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  204. r := math.Cos(v)
  205. if math.IsNaN(r) {
  206. return nil, true
  207. } else {
  208. return r, true
  209. }
  210. } else {
  211. return e, false
  212. }
  213. },
  214. val: ValidateOneNumberArg,
  215. check: returnNilIfHasAnyNil,
  216. }
  217. builtins["cosh"] = builtinFunc{
  218. fType: ast.FuncTypeScalar,
  219. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  220. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  221. r := math.Cosh(v)
  222. if math.IsNaN(r) {
  223. return nil, true
  224. } else {
  225. return r, true
  226. }
  227. } else {
  228. return e, false
  229. }
  230. },
  231. val: ValidateOneNumberArg,
  232. check: returnNilIfHasAnyNil,
  233. }
  234. builtins["exp"] = builtinFunc{
  235. fType: ast.FuncTypeScalar,
  236. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  237. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  238. r := math.Exp(v)
  239. if math.IsNaN(r) {
  240. return nil, true
  241. } else {
  242. return r, true
  243. }
  244. } else {
  245. return e, false
  246. }
  247. },
  248. val: ValidateOneNumberArg,
  249. check: returnNilIfHasAnyNil,
  250. }
  251. builtins["floor"] = builtinFunc{
  252. fType: ast.FuncTypeScalar,
  253. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  254. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  255. return math.Floor(v), true
  256. } else {
  257. return e, false
  258. }
  259. },
  260. val: ValidateOneNumberArg,
  261. check: returnNilIfHasAnyNil,
  262. }
  263. builtins["ln"] = builtinFunc{
  264. fType: ast.FuncTypeScalar,
  265. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  266. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  267. r := math.Log2(v)
  268. if math.IsNaN(r) {
  269. return nil, true
  270. } else {
  271. return r, true
  272. }
  273. } else {
  274. return e, false
  275. }
  276. },
  277. val: ValidateOneNumberArg,
  278. check: returnNilIfHasAnyNil,
  279. }
  280. builtins["log"] = builtinFunc{
  281. fType: ast.FuncTypeScalar,
  282. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  283. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  284. r := math.Log10(v)
  285. if math.IsNaN(r) {
  286. return nil, true
  287. } else {
  288. return r, true
  289. }
  290. } else {
  291. return e, false
  292. }
  293. },
  294. val: ValidateOneNumberArg,
  295. check: returnNilIfHasAnyNil,
  296. }
  297. builtins["mod"] = builtinFunc{
  298. fType: ast.FuncTypeScalar,
  299. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  300. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  301. if v1, e1 := cast.ToFloat64(args[1], cast.CONVERT_SAMEKIND); e == nil {
  302. return math.Mod(v, v1), true
  303. } else {
  304. return e1, false
  305. }
  306. } else {
  307. return e, false
  308. }
  309. },
  310. val: ValidateTwoNumberArg,
  311. check: returnNilIfHasAnyNil,
  312. }
  313. builtins["pi"] = builtinFunc{
  314. fType: ast.FuncTypeScalar,
  315. exec: func(_ api.FunctionContext, _ []interface{}) (interface{}, bool) {
  316. return math.Pi, true
  317. },
  318. val: ValidateNoArg,
  319. check: returnNilIfHasAnyNil,
  320. }
  321. builtins["power"] = builtinFunc{
  322. fType: ast.FuncTypeScalar,
  323. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  324. if v1, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  325. if v2, e2 := cast.ToFloat64(args[1], cast.CONVERT_SAMEKIND); e2 == nil {
  326. return math.Pow(v1, v2), true
  327. } else {
  328. return e2, false
  329. }
  330. } else {
  331. return e, false
  332. }
  333. },
  334. val: ValidateTwoNumberArg,
  335. check: returnNilIfHasAnyNil,
  336. }
  337. builtins["pow"] = builtins["power"] // Synonym for POWER.
  338. builtins["rand"] = builtinFunc{
  339. fType: ast.FuncTypeScalar,
  340. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  341. return rand.Float64(), true
  342. },
  343. val: ValidateNoArg,
  344. }
  345. builtins["round"] = builtinFunc{
  346. fType: ast.FuncTypeScalar,
  347. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  348. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  349. return math.Round(v), true
  350. } else {
  351. return e, false
  352. }
  353. },
  354. val: ValidateOneNumberArg,
  355. check: returnNilIfHasAnyNil,
  356. }
  357. builtins["sign"] = builtinFunc{
  358. fType: ast.FuncTypeScalar,
  359. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  360. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  361. if v > 0 {
  362. return 1, true
  363. } else if v < 0 {
  364. return -1, true
  365. } else {
  366. return 0, true
  367. }
  368. } else {
  369. return e, false
  370. }
  371. },
  372. val: ValidateOneNumberArg,
  373. check: returnNilIfHasAnyNil,
  374. }
  375. builtins["sin"] = builtinFunc{
  376. fType: ast.FuncTypeScalar,
  377. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  378. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  379. r := math.Sin(v)
  380. if math.IsNaN(r) {
  381. return nil, true
  382. } else {
  383. return r, true
  384. }
  385. } else {
  386. return e, false
  387. }
  388. },
  389. val: ValidateOneNumberArg,
  390. check: returnNilIfHasAnyNil,
  391. }
  392. builtins["sinh"] = builtinFunc{
  393. fType: ast.FuncTypeScalar,
  394. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  395. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  396. r := math.Sinh(v)
  397. if math.IsNaN(r) {
  398. return nil, true
  399. } else {
  400. return r, true
  401. }
  402. } else {
  403. return e, false
  404. }
  405. },
  406. val: ValidateOneNumberArg,
  407. check: returnNilIfHasAnyNil,
  408. }
  409. builtins["sqrt"] = builtinFunc{
  410. fType: ast.FuncTypeScalar,
  411. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  412. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  413. r := math.Sqrt(v)
  414. if math.IsNaN(r) {
  415. return nil, true
  416. } else {
  417. return r, true
  418. }
  419. } else {
  420. return e, false
  421. }
  422. },
  423. val: ValidateOneNumberArg,
  424. check: returnNilIfHasAnyNil,
  425. }
  426. builtins["tan"] = builtinFunc{
  427. fType: ast.FuncTypeScalar,
  428. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  429. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  430. r := math.Tan(v)
  431. if math.IsNaN(r) {
  432. return nil, true
  433. } else {
  434. return r, true
  435. }
  436. } else {
  437. return e, false
  438. }
  439. },
  440. val: ValidateOneNumberArg,
  441. check: returnNilIfHasAnyNil,
  442. }
  443. builtins["tanh"] = builtinFunc{
  444. fType: ast.FuncTypeScalar,
  445. exec: func(ctx api.FunctionContext, args []interface{}) (interface{}, bool) {
  446. if v, e := cast.ToFloat64(args[0], cast.CONVERT_SAMEKIND); e == nil {
  447. r := math.Tanh(v)
  448. if math.IsNaN(r) {
  449. return nil, true
  450. } else {
  451. return r, true
  452. }
  453. } else {
  454. return e, false
  455. }
  456. },
  457. val: ValidateOneNumberArg,
  458. check: returnNilIfHasAnyNil,
  459. }
  460. }