github.com/hirochachacha/plua@v0.0.0-20170217012138-c82f520cc725/stdlib/math/math.go (about) 1 package math 2 3 import ( 4 "math" 5 "math/rand" 6 7 "github.com/hirochachacha/plua/internal/arith" 8 "github.com/hirochachacha/plua/object" 9 "github.com/hirochachacha/plua/object/fnutil" 10 ) 11 12 func abs(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 13 ap := fnutil.NewArgParser(th, args) 14 15 f, err := ap.ToGoFloat64(0) 16 if err != nil { 17 return nil, err 18 } 19 20 if i, ok := args[0].(object.Integer); ok { 21 if i < 0 { 22 return []object.Value{-i}, nil 23 } 24 25 return []object.Value{i}, nil 26 } 27 28 return []object.Value{object.Number(math.Abs(f))}, nil 29 } 30 31 func acos(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 32 ap := fnutil.NewArgParser(th, args) 33 34 f, err := ap.ToGoFloat64(0) 35 if err != nil { 36 return nil, err 37 } 38 39 return []object.Value{object.Number(math.Acos(f))}, nil 40 } 41 42 func asin(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 43 ap := fnutil.NewArgParser(th, args) 44 45 f, err := ap.ToGoFloat64(0) 46 if err != nil { 47 return nil, err 48 } 49 50 return []object.Value{object.Number(math.Asin(f))}, nil 51 } 52 53 func atan(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 54 ap := fnutil.NewArgParser(th, args) 55 56 y, err := ap.ToGoFloat64(0) 57 if err != nil { 58 return nil, err 59 } 60 61 x, err := ap.OptGoFloat64(1, 1) 62 if err != nil { 63 return nil, err 64 } 65 66 return []object.Value{object.Number(math.Atan2(y, x))}, nil 67 } 68 69 func ceil(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 70 ap := fnutil.NewArgParser(th, args) 71 72 if i, err := ap.ToInteger(0); err == nil { 73 return []object.Value{i}, nil 74 } 75 76 f, err := ap.ToGoFloat64(0) 77 if err != nil { 78 return nil, err 79 } 80 81 f = math.Ceil(f) 82 83 fval := object.Number(f) 84 85 if ival, ok := object.ToInteger(fval); ok { 86 return []object.Value{ival}, nil 87 } 88 89 return []object.Value{fval}, nil 90 } 91 92 func cos(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 93 ap := fnutil.NewArgParser(th, args) 94 95 f, err := ap.ToGoFloat64(0) 96 if err != nil { 97 return nil, err 98 } 99 100 return []object.Value{object.Number(math.Cos(f))}, nil 101 } 102 103 func deg(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 104 ap := fnutil.NewArgParser(th, args) 105 106 f, err := ap.ToGoFloat64(0) 107 if err != nil { 108 return nil, err 109 } 110 111 return []object.Value{object.Number((f * 180) / math.Pi)}, nil 112 } 113 114 func exp(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 115 ap := fnutil.NewArgParser(th, args) 116 117 f, err := ap.ToGoFloat64(0) 118 if err != nil { 119 return nil, err 120 } 121 122 return []object.Value{object.Number(math.Exp(f))}, nil 123 } 124 125 func floor(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 126 ap := fnutil.NewArgParser(th, args) 127 128 if i, err := ap.ToInteger(0); err == nil { 129 return []object.Value{i}, nil 130 } 131 132 f, err := ap.ToGoFloat64(0) 133 if err != nil { 134 return nil, err 135 } 136 137 f = math.Floor(f) 138 139 fval := object.Number(f) 140 141 if ival, ok := object.ToInteger(fval); ok { 142 return []object.Value{ival}, nil 143 } 144 145 return []object.Value{fval}, nil 146 } 147 148 func fmod(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 149 ap := fnutil.NewArgParser(th, args) 150 151 if len(args) >= 2 { 152 if x, ok := args[0].(object.Integer); ok { 153 if y, ok := args[1].(object.Integer); ok { 154 if y == 0 { 155 return nil, ap.ArgError(1, "zero") 156 } 157 158 if x == object.MinInteger && y == -1 { 159 return []object.Value{object.Integer(0)}, nil 160 } 161 162 return []object.Value{x % y}, nil 163 } 164 } 165 } 166 167 x, err := ap.ToGoFloat64(0) 168 if err != nil { 169 return nil, err 170 } 171 172 y, err := ap.ToGoFloat64(1) 173 if err != nil { 174 return nil, err 175 } 176 177 return []object.Value{object.Number(math.Mod(x, y))}, nil 178 } 179 180 // log(x, [, base]) 181 func log(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 182 ap := fnutil.NewArgParser(th, args) 183 184 f, err := ap.ToGoFloat64(0) 185 if err != nil { 186 return nil, err 187 } 188 189 if len(args) == 1 { 190 return []object.Value{object.Number(math.Log(f))}, nil 191 } 192 193 base, err := ap.ToGoInt64(1) 194 if err != nil { 195 return nil, err 196 } 197 198 switch base { 199 case 2: 200 return []object.Value{object.Number(math.Log2(f))}, nil 201 case 10: 202 return []object.Value{object.Number(math.Log10(f))}, nil 203 default: 204 return []object.Value{object.Number(math.Log(f) / math.Log(float64(base)))}, nil 205 } 206 } 207 208 func max(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 209 ap := fnutil.NewArgParser(th, args) 210 211 max, err := ap.ToValue(0) 212 if err != nil { 213 return nil, err 214 } 215 216 for _, arg := range args[1:] { 217 b, err := arith.CallLessThan(th, false, max, arg) 218 if err != nil { 219 return nil, err 220 } 221 if b { 222 max = arg 223 } 224 } 225 226 return []object.Value{max}, nil 227 } 228 229 func min(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 230 ap := fnutil.NewArgParser(th, args) 231 232 min, err := ap.ToValue(0) 233 if err != nil { 234 return nil, err 235 } 236 237 for _, arg := range args[1:] { 238 b, err := arith.CallLessThan(th, false, arg, min) 239 if err != nil { 240 return nil, err 241 } 242 if b { 243 min = arg 244 } 245 } 246 247 return []object.Value{min}, nil 248 } 249 250 func modf(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 251 ap := fnutil.NewArgParser(th, args) 252 253 f, err := ap.ToGoFloat64(0) 254 if err != nil { 255 return nil, err 256 } 257 258 int, frac := math.Modf(f) 259 260 if math.IsNaN(frac) && !math.IsNaN(int) { 261 frac = 0 262 } 263 264 fval := object.Number(int) 265 266 if ival, ok := object.ToInteger(fval); ok { 267 return []object.Value{ival, object.Number(frac)}, nil 268 } 269 270 return []object.Value{fval, object.Number(frac)}, nil 271 } 272 273 func rad(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 274 ap := fnutil.NewArgParser(th, args) 275 276 f, err := ap.ToGoFloat64(0) 277 if err != nil { 278 return nil, err 279 } 280 281 return []object.Value{object.Number((math.Pi * f) / 180)}, nil 282 } 283 284 // random([m, [, n]]) 285 func random(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 286 ap := fnutil.NewArgParser(th, args) 287 288 r := rand.Float64() 289 290 switch len(args) { 291 case 0: 292 return []object.Value{object.Number(r)}, nil 293 case 1: 294 m := object.Integer(1) 295 296 n, err := ap.ToInteger(0) 297 if err != nil { 298 return nil, err 299 } 300 301 if m > n { 302 return nil, ap.ArgError(1, "interval is empty") 303 } 304 305 r *= float64(n-m) + 1.0 306 307 return []object.Value{object.Integer(r) + m}, nil 308 case 2: 309 m, err := ap.ToInteger(0) 310 if err != nil { 311 return nil, err 312 } 313 314 n, err := ap.ToInteger(1) 315 if err != nil { 316 return nil, err 317 } 318 319 if m > n { 320 return nil, ap.ArgError(1, "interval is empty") 321 } 322 if m < 0 && n > math.MaxInt64+m { 323 return nil, ap.ArgError(1, "interval too large") 324 } 325 326 r *= float64(n-m) + 1.0 327 328 return []object.Value{object.Integer(r) + m}, nil 329 default: 330 return nil, object.NewRuntimeError("wrong number of arguments") 331 } 332 } 333 334 func randomseed(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 335 ap := fnutil.NewArgParser(th, args) 336 337 i, err := ap.ToGoInt64(0) 338 if err != nil { 339 return nil, err 340 } 341 342 rand.Seed(i) 343 344 return nil, nil 345 } 346 347 func sin(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 348 ap := fnutil.NewArgParser(th, args) 349 350 f, err := ap.ToGoFloat64(0) 351 if err != nil { 352 return nil, err 353 } 354 355 return []object.Value{object.Number(math.Sin(f))}, nil 356 } 357 358 func sqrt(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 359 ap := fnutil.NewArgParser(th, args) 360 361 f, err := ap.ToGoFloat64(0) 362 if err != nil { 363 return nil, err 364 } 365 366 return []object.Value{object.Number(math.Sqrt(f))}, nil 367 } 368 369 func tan(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 370 ap := fnutil.NewArgParser(th, args) 371 372 f, err := ap.ToGoFloat64(0) 373 if err != nil { 374 return nil, err 375 } 376 377 return []object.Value{object.Number(math.Tan(f))}, nil 378 } 379 380 func tointeger(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 381 ap := fnutil.NewArgParser(th, args) 382 383 i, err := ap.ToInteger(0) 384 if err != nil { 385 if len(args) != 0 { 386 return []object.Value{nil}, nil 387 } 388 return nil, err 389 } 390 391 return []object.Value{i}, nil 392 } 393 394 func _type(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 395 ap := fnutil.NewArgParser(th, args) 396 397 val, err := ap.ToTypes(0, object.TNUMBER) 398 if err != nil { 399 if len(args) != 0 { 400 return []object.Value{nil}, nil 401 } 402 403 return nil, err 404 } 405 406 switch val.(type) { 407 case object.Integer: 408 return []object.Value{object.String("integer")}, nil 409 case object.Number: 410 return []object.Value{object.String("float")}, nil 411 } 412 413 return nil, nil 414 } 415 416 func ult(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 417 ap := fnutil.NewArgParser(th, args) 418 419 x, err := ap.ToGoInt64(0) 420 if err != nil { 421 return nil, err 422 } 423 424 y, err := ap.ToGoInt64(1) 425 if err != nil { 426 return nil, err 427 } 428 429 return []object.Value{object.Boolean(uint64(x) < uint64(y))}, nil 430 } 431 432 func Open(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) { 433 m := th.NewTableSize(0, 27) 434 435 m.Set(object.String("huge"), object.Number(math.Inf(1))) 436 m.Set(object.String("pi"), object.Number(math.Pi)) 437 m.Set(object.String("mininteger"), object.MinInteger) 438 m.Set(object.String("maxinteger"), object.MaxInteger) 439 440 m.Set(object.String("abs"), object.GoFunction(abs)) 441 m.Set(object.String("acos"), object.GoFunction(acos)) 442 m.Set(object.String("asin"), object.GoFunction(asin)) 443 m.Set(object.String("atan"), object.GoFunction(atan)) 444 m.Set(object.String("ceil"), object.GoFunction(ceil)) 445 m.Set(object.String("cos"), object.GoFunction(cos)) 446 m.Set(object.String("deg"), object.GoFunction(deg)) 447 m.Set(object.String("exp"), object.GoFunction(exp)) 448 m.Set(object.String("floor"), object.GoFunction(floor)) 449 m.Set(object.String("fmod"), object.GoFunction(fmod)) 450 m.Set(object.String("log"), object.GoFunction(log)) 451 m.Set(object.String("max"), object.GoFunction(max)) 452 m.Set(object.String("min"), object.GoFunction(min)) 453 m.Set(object.String("modf"), object.GoFunction(modf)) 454 m.Set(object.String("rad"), object.GoFunction(rad)) 455 m.Set(object.String("random"), object.GoFunction(random)) 456 m.Set(object.String("randomseed"), object.GoFunction(randomseed)) 457 m.Set(object.String("sin"), object.GoFunction(sin)) 458 m.Set(object.String("sqrt"), object.GoFunction(sqrt)) 459 m.Set(object.String("tan"), object.GoFunction(tan)) 460 m.Set(object.String("tointeger"), object.GoFunction(tointeger)) 461 m.Set(object.String("type"), object.GoFunction(_type)) 462 m.Set(object.String("ult"), object.GoFunction(ult)) 463 464 return []object.Value{m}, nil 465 }