Мне действительно нужно иметь целочисленный тип в Lua.
Что я имею в виду под целочисленным типом, это тип, определяющий обычные операторы (/ * + и т. Д.) И ведущий себя как целое число, внутреннее представление не имеет значения.
Делать такое с таблицами очень просто, проблема в том, что я пробовал, и производительность ужасно низкая (конечно). Вот моя частичная реализация:
function num_op(a, b, calc_func)
local atype = pytype(a)
local btype = pytype(b)
local a_val, b_val
a_val = (atype == "Integer" or atype == "Double") and a[1] or a
b_val = (btype == "Integer" or btype == "Double") and b[1] or b
val = calc_func(a_val, b_val)
if atype == "Integer" and btype == "Integer" then
return Integer:create(val)
else
return Double:create(val)
end
end
numeric_mt = {
__add = function(a, b)
return num_op(a, b, function(a,b) return a + b end)
end,
__sub = function(a, b)
return num_op(a, b, function(a,b) return a - b end)
end,
__div = function(a, b)
return num_op(a, b, function(a,b) return a / b end)
end,
__mul = function(a, b)
return num_op(a, b, function(a,b) return a * b end)
end,
__tostring = function(a)
return tostring(a[1])
end
}
-----------------------------
-- Integer type definition --
-----------------------------
Integer = {}
Integer_mt = table.copy(numeric_mt)
Integer_mt["__index"] = Integer
function Integer:create(value)
local new_inst = {math.floor(value)}
setmetatable(new_inst, Integer_mt)
return new_inst
end
function Integer:className()
return "Integer"
end
Основное снижение производительности из того, что я получаю, - это (конечно) очень многочисленные распределения. LuaJit способен довольно хорошо оптимизировать функции операторов, но не выделяет метатаблицы.
Кто-нибудь думает, что можно было бы добиться большего успеха с помощью пользовательской реализации c и пользовательских данных? Или то, что я преследую, невозможно достичь?
NB: я знаю, у lua нет целых чисел. Я также знаю, что могу получить те же результаты, используя математическую библиотеку. Что я хочу, так это полная прозрачность при использовании целых чисел, за исключением фазы создания.
РЕДАКТИРОВАТЬ: Я собираюсь добавить дополнительную информацию здесь, чтобы все было централизовано
@ Mud: Мне нужно, в определенной степени, иметь прозрачную смешанную арифметику так же, как в python / ruby / etc, но с максимально возможной производительностью. Я использую luaJIT в качестве цели для компилятора, с обычным Lua в качестве запасного варианта для платформ, не поддерживаемых luaJIT. Это очень важно для рабочих характеристик.
Это значит, что я хотел бы иметь возможность сделать это:
a = int(5) -- Integer value
b = int(2) -- Another Integer
c = 2 -- Double
d = a / b -- == 2 , integer arithmetics
e = a / c -- == 2.5, floating point arithmetics
Я могу достичь этого до определенного момента, с реализацией, показанной выше. Проблема в том, что я замедляю операции с каждым числом, так как обычные числа тоже упакованы. Я мог бы перегружать метатаблицу чисел отладочной библиотекой, но
- Я не знаю, насколько надежна эта функция для использования в программном обеспечении качества производства
- Это все равно будет замедлять работу чисел, поскольку, чтобы иметь единый интерфейс с числами, я должен буду использовать (number): get (), который в любом случае замедлит работу.
Прошлой ночью я развернул свою собственную реализацию Integer. Дело в том, что, хотя это улучшение по сравнению с моей наивной реализацией в обычном lua, а также улучшение по сравнению со встроенными вызовами math.floor, это гораздо менее очевидно при использовании LuaJIT, где встроенные вызовы по-прежнему lot быстрее, чем реализация C.
Другим решением было бы всегда использовать распакованные числа и использовать какое-то распространение типа в моем компиляторе для отслеживания целых чисел и при необходимости использовать правильные встроенные операции над ними, но сложность этого решения намного больше, и вроде побеждает всю цель использования Lua / LuaJIT в качестве бэкэнда.
Я попробую вашу реализацию, но я сомневаюсь, что это будет лучше, чем встроенные вызовы в LuaJIT. Вполне возможно, что то, для чего я стреляю (имея прозрачную операцию двойных и целых чисел и производительность, близкую к встроенным вызовам в luaJIT), просто невозможно. Большое спасибо за вашу помощь.
@ miky: Спасибо, это выглядит неплохо, но я сомневаюсь, что смогу исправить с ним luaJIT, и если я не смогу, он потеряет весь свой интерес для моей цели.