func mathType(state *lua.State) int {
	if state.TypeAt(1) == lua.NumberType {
		if state.IsInt(1) {
			state.Push("integer")
		} else {
			state.Push("float")
		}
	} else {
		state.CheckAny(1)
		state.Push(nil)
	}
	return 1
}
math.type (x)

Returns "integer" if x is an integer, "float" if it is a float, or nil if x is not a number.

See https://www.lua.org/manual/5.3/manual.html#pdf-math.type
package math
import (
	"fmt"
	"math"
	"math/rand"
	"github.com/Azure/golua/lua"
)
func Open(state *lua.State) int {
	var mathFuncs = map[string]lua.Func{
		"abs":        lua.Func(mathAbs),
		"acos":       lua.Func(mathAcos),
		"asin":       lua.Func(mathAsin),
		"atan":       lua.Func(mathAtan),
		"ceil":       lua.Func(mathCeil),
		"cos":        lua.Func(mathCos),
		"deg":        lua.Func(mathDeg),
		"exp":        lua.Func(mathExp),
		"floor":      lua.Func(mathFloor),
		"fmod":       lua.Func(mathFmod),
		"log":        lua.Func(mathLog),
		"max":        lua.Func(mathMax),
		"min":        lua.Func(mathMin),
		"modf":       lua.Func(mathModf),
		"rad":        lua.Func(mathRad),
		"random":     lua.Func(mathRand),
		"randomseed": lua.Func(mathRandSeed),
		"sin":        lua.Func(mathSin),
		"sqrt":       lua.Func(mathSqrt),
		"tan":        lua.Func(mathTan),
		"tointeger":  lua.Func(mathToInt),
		"type":       lua.Func(mathType),
		"ult":        lua.Func(mathUlt),
	}
	state.NewTableSize(0, len(mathFuncs))
	state.SetFuncs(mathFuncs, 0)
	state.Push(math.Pi)
	state.SetField(-2, "pi")  
	state.Push(lua.Float(math.Inf(1)))
	state.SetField(-2, "huge")  
	state.Push(math.MaxInt64)
	state.SetField(-2, "maxinteger")  
	state.Push(math.MinInt64)
	state.SetField(-2, "mininteger")  
	return 1
}
func mathAbs(state *lua.State) int {
	if state.IsInt(1) {
		n := state.ToInt(1)
		if n < 0 {
			n = -n
		}
		state.Push(n)
	} else {
		n := state.CheckNumber(1)
		state.Push(math.Abs(n))
	}
	return 1
}
func mathAcos(state *lua.State) int {
	f64 := state.CheckNumber(1)
	state.Push(math.Acos(f64))
	return 1
}
func mathAsin(state *lua.State) int {
	f64 := state.CheckNumber(1)
	state.Push(math.Asin(f64))
	return 1
}
func mathAtan(state *lua.State) int {
	y := state.CheckNumber(1)
	x := state.OptNumber(2, 1.0)
	state.Push(math.Atan2(y, x))
	return 1
}
func mathCeil(state *lua.State) int {
	if state.IsInt(1) {
		state.SetTop(1)
		return 1
	}
	var (
		num = state.CheckNumber(1)
		f64 = math.Ceil(num)
		i64 = int64(f64)
	)
	if float64(i64) == f64 {
		state.Push(i64)
	} else {
		state.Push(f64)
	}
	return 1
}
func mathCos(state *lua.State) int {
	f64 := state.CheckNumber(1)
	state.Push(math.Cos(f64))
	return 1
}
func mathDeg(state *lua.State) int {
	f64 := state.CheckNumber(1)
	deg := f64 * 180 / math.Pi
	state.Push(deg)
	return 1
}
func mathExp(state *lua.State) int {
	f64 := state.CheckNumber(1)
	state.Push(math.Exp(f64))
	return 1
}
func mathFloor(state *lua.State) int {
	if state.IsInt(1) {
		state.SetTop(1)
		return 1
	}
	var (
		num = state.CheckNumber(1)
		f64 = math.Floor(num)
		i64 = int64(f64)
	)
	if float64(i64) == f64 {
		state.Push(i64)
	} else {
		state.Push(f64)
	}
	return 1
}
func mathFmod(state *lua.State) int {
	if state.IsInt(1) && state.IsInt(2) {
		if d := state.CheckInt(2); uint64(d)+1 <= 1 {
			if d == 0 {
				panic(fmt.Errorf("bad argument to 'fmod' (zero)"))
			}
			state.Push(0)
			return 1
		} else {
			n := state.CheckInt(1)
			state.Push(n % d)
			return 1
		}
	}
	n := state.CheckNumber(1)
	d := state.CheckNumber(2)
	state.Push(math.Mod(n, d))
	return 1
}
func mathLog(state *lua.State) int {
	num := state.CheckNumber(1)
	base := state.OptNumber(2, math.E)
	state.Push(math.Log(num) / math.Log(base))
	return 1
}
func mathMax(state *lua.State) int {
	if state.Top() < 1 {
		panic(fmt.Errorf("bad argument to 'max' (value expected)"))
	}
	var max int = 1
	for i := 1; i <= state.Top(); i++ {
		if state.Compare(lua.OpLt, max, i) {  
			max = i
		}
	}
	state.PushIndex(max)
	return 1
}
func mathMin(state *lua.State) int {
	if state.Top() < 1 {
		panic(fmt.Errorf("bad argument to 'min' (value expected)"))
	}
	var min int = 1
	for i := 1; i <= state.Top(); i++ {
		if state.Compare(lua.OpLt, i, min) {  
			min = i
		}
	}
	state.PushIndex(min)
	return 1
}
func mathModf(state *lua.State) int {
	if state.IsInt(1) {
		state.SetTop(1)
		state.Push(0.0)
		return 2
	}
	num := state.CheckNumber(1)
	i, f := math.Modf(num)
	if i64 := int64(i); float64(i64) == i {
		state.Push(i64)
	}
	if math.IsInf(num, 0) {
		state.Push(0.0)
	} else {
		state.Push(f)
	}
	return 2
}
func mathRad(state *lua.State) int {
	f64 := state.CheckNumber(1)
	rad := f64 * math.Pi / 180
	state.Push(rad)
	return 1
}
func mathRand(state *lua.State) int {
	var (
		lo, hi, rn int64
	)
	switch argc := state.Top(); argc {
	case 0:
		state.Push(rand.Float64())
		return 1
	case 1:
		lo, hi = 1, state.CheckInt(1)
	case 2:
		lo = state.CheckInt(1)
		hi = state.CheckInt(2)
	default:
		panic(fmt.Errorf("wrong number of arguments"))
	}
	if lo < 0 && hi > math.MaxInt64+lo {
		panic(fmt.Errorf("interval too large"))
	}
	if lo > hi {
		panic(fmt.Errorf("bad argument to 'random' (interval is empty)"))
	}
	if hi-lo == math.MaxInt64 {
		rn = rand.Int63() + lo
	} else {
		rn = rand.Int63n(hi-lo+1) + lo
	}
	state.Push(rn)
	return 1
}
func mathRandSeed(state *lua.State) int {
	rand.Seed(state.CheckInt(1))
	return 0
}
func mathSin(state *lua.State) int {
	f64 := state.CheckNumber(1)
	state.Push(math.Sin(f64))
	return 1
}
func mathSqrt(state *lua.State) int {
	f64 := state.CheckNumber(1)
	state.Push(math.Sqrt(f64))
	return 1
}
func mathTan(state *lua.State) int {
	f64 := state.CheckNumber(1)
	state.Push(math.Tan(f64))
	return 1
}
func mathToInt(state *lua.State) int {
	if i64, ok := state.TryInt(1); ok {
		state.Push(i64)
	} else {
		state.Push(nil)
	}
	return 1
}