diff --git a/modules/_private_utils.lua b/modules/_private_utils.lua index 2c4aca0..fa64b02 100644 --- a/modules/_private_utils.lua +++ b/modules/_private_utils.lua @@ -9,4 +9,8 @@ function private.round(value, precision) return value >= 0 and floor(value+0.5) or ceil(value-0.5) end +function private.is_nan(a) + return a ~= a +end + return private diff --git a/modules/mat4.lua b/modules/mat4.lua index 25b8a39..e5bf416 100644 --- a/modules/mat4.lua +++ b/modules/mat4.lua @@ -6,6 +6,7 @@ local vec2 = require(modules .. "vec2") local vec3 = require(modules .. "vec3") local quat = require(modules .. "quat") local utils = require(modules .. "utils") +local private = require(modules .. "_private_utils") local sqrt = math.sqrt local cos = math.cos local sin = math.sin @@ -650,6 +651,18 @@ function mat4.is_mat4(a) return true end +--- Return whether any component is NaN +-- @tparam mat4 a Matrix to be tested +-- @treturn boolean if any component is NaN +function vec2.has_nan(a) + for i=1, 16 do + if private.is_nan(a[i]) then + return true + end + end + return false +end + --- Return a formatted string. -- @tparam mat4 a Matrix to be turned into a string -- @treturn string formatted diff --git a/modules/quat.lua b/modules/quat.lua index 0e1bace..4173317 100644 --- a/modules/quat.lua +++ b/modules/quat.lua @@ -4,6 +4,7 @@ local modules = (...):gsub('%.[^%.]+$', '') .. "." local constants = require(modules .. "constants") local vec3 = require(modules .. "vec3") +local private = require(modules .. "_private_utils") local DOT_THRESHOLD = constants.DOT_THRESHOLD local DBL_EPSILON = constants.DBL_EPSILON local acos = math.acos @@ -362,6 +363,16 @@ function quat.is_imaginary(a) return a.w == 0 end +--- Return whether any component is NaN +-- @tparam quat a Quaternion to be tested +-- @treturn boolean if x,y,z, or w is NaN +function quat.has_nan(a) + return private.is_nan(a.x) or + private.is_nan(a.y) or + private.is_nan(a.z) or + private.is_nan(a.w) +end + --- Convert a quaternion into an angle plus axis components. -- @tparam quat a Quaternion to convert -- @tparam identityAxis vec3 of axis to use on identity/degenerate quaternions (optional, default returns 0,0,0,1) diff --git a/modules/utils.lua b/modules/utils.lua index e6d0b8f..5b3301c 100644 --- a/modules/utils.lua +++ b/modules/utils.lua @@ -128,6 +128,12 @@ function utils.is_pot(value) return (frexp(value)) == 0.5 end +--- Check if a value is NaN +-- Returns true if a number is not a valid number +-- @param value +-- @return boolean +utils.is_nan = private.is_nan + -- Originally from vec3 function utils.project_on(a, b) local s = diff --git a/modules/vec2.lua b/modules/vec2.lua index e4d7e3c..a36e9b8 100644 --- a/modules/vec2.lua +++ b/modules/vec2.lua @@ -320,6 +320,14 @@ function vec2.is_zero(a) return a.x == 0 and a.y == 0 end +--- Return whether either value is NaN +-- @tparam vec2 a Vector to be tested +-- @treturn boolean if x or y is nan +function vec2.has_nan(a) + return private.is_nan(a.x) or + private.is_nan(a.y) +end + --- Convert point from cartesian to polar. -- @tparam vec2 a Vector to convert -- @treturn number radius diff --git a/modules/vec3.lua b/modules/vec3.lua index 032b596..bc73aee 100644 --- a/modules/vec3.lua +++ b/modules/vec3.lua @@ -332,6 +332,15 @@ function vec3.is_zero(a) return a.x == 0 and a.y == 0 and a.z == 0 end +--- Return whether any component is NaN +-- @tparam vec3 a Vector to be tested +-- @treturn boolean if x,y, or z are nan +function vec3.has_nan(a) + return private.is_nan(a.x) or + private.is_nan(a.y) or + private.is_nan(a.z) +end + --- Return a formatted string. -- @tparam vec3 a Vector to be turned into a string -- @treturn string formatted diff --git a/spec/utils_spec.lua b/spec/utils_spec.lua index 337361e..6bb89b3 100644 --- a/spec/utils_spec.lua +++ b/spec/utils_spec.lua @@ -28,6 +28,11 @@ describe("utils:", function() assert.is_true(tolerance(v, 0.39346934028737)) end) + it("checks a nan", function() + local a = 0/0 + assert.is_true(utils.is_nan(a)) + end) + it("rounds a number", function() -- round up local v = utils.round(1.3252525, 0.01) diff --git a/spec/vec2_spec.lua b/spec/vec2_spec.lua index a163b0b..4375f4c 100644 --- a/spec/vec2_spec.lua +++ b/spec/vec2_spec.lua @@ -35,6 +35,11 @@ describe("vec2:", function() assert.is.equal(5, a.y) end) + it("creates a vector from nan", function() + local a = vec2(0/0) + assert.is_true(a:has_nan()) + end) + it("clones a vector", function() local a = vec2(3, 5) local b = a:clone() diff --git a/spec/vec3_spec.lua b/spec/vec3_spec.lua index bd2659a..8621fee 100644 --- a/spec/vec3_spec.lua +++ b/spec/vec3_spec.lua @@ -40,6 +40,11 @@ describe("vec3:", function() assert.is.equal(7, a.z) end) + it("creates a vector from nan", function() + local a = vec3(0/0) + assert.is_true(a:has_nan()) + end) + it("clones a vector", function() local a = vec3(3, 5, 7) local b = a:clone()