function clock_gettime(clock)
	local status, module = pcall(require, "posix")
	posix = status and module or nil

	if posix then
		local s, ns = posix.clock_gettime(clock)
		return s + ns / (10 ^ (math.floor(math.log10(ns)) + 1))
	else
		warn("failed to load posix module! falling back to os.time()")
		return os.time()
	end
end

function distance(p1, p2)
	return math.sqrt((p2.x - p1.x) ^ 2 + (p2.y - p1.y) ^ 2 + (p2.z - p1.z) ^ 2)
end

function table.shallow_copy(t)
	local t2 = {}
	for k, v in pairs(t) do
		t2[k] = v
	end
	return t2
end

function table.map(t, f)
	local t2 = {}
	for k, v in pairs(t) do
		t2[k] = f(v)
	end
	return t2
end

function table.contains(t, target)
	for _, v in pairs(t) do
		if v == target then
			return true
		end
	end
	return false
end

function dump(object)
	if type(object) == "table" then
		local string = "{ "
		local parts = {}
		for key, value in pairs(object) do
			table.insert(parts, key .. " = " .. dump(value))
		end
		string = string .. table.concat(parts, ", ")
		return string .. " " .. "}"
	else
		return tostring(object)
	end
end

function dumpp(object, level)
	if not level then
		level = 0
	end
	if type(object) == "table" then
		local string = "{\n" .. string.rep("  ", level + 1)
		local parts = {}
		for key, value in pairs(object) do
			table.insert(parts, key .. " = " .. dumpp(value, level + 1))
		end
		string = string .. table.concat(parts, ",\n" .. string.rep("  ", level + 1))
		return string .. "\n" .. string.rep("  ", level) .. "}"
	else
		return tostring(object)
	end
end