• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

excessive / cpml / 13079282556

07 May 2022 10:53PM UTC coverage: 57.717% (+43.7%) from 14.013%
13079282556

push

github

shakesoda
fix typo in mat4.mul

0 of 1 new or added line in 1 file covered. (0.0%)

527 existing lines in 19 files now uncovered.

4581 of 7937 relevant lines covered (57.72%)

52.86 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.71
/modules/vec2.lua
1
--- A 2 component vector.
2
-- @module vec2
3

4
local modules = (...):gsub('%.[^%.]+$', '') .. "."
8✔
5
local vec3    = require(modules .. "vec3")
8✔
6
local precond = require(modules .. "_private_precond")
8✔
7
local private = require(modules .. "_private_utils")
8✔
8
local acos    = math.acos
8✔
9
local atan2   = math.atan2 or math.atan
8✔
10
local sqrt    = math.sqrt
8✔
11
local cos     = math.cos
8✔
12
local sin     = math.sin
8✔
13
local vec2    = {}
8✔
14
local vec2_mt = {}
8✔
15

16
-- Private constructor.
17
local function new(x, y)
18
        return setmetatable({
548✔
19
                x = x or 0,
274✔
20
                y = y or 0
274✔
21
        }, vec2_mt)
548✔
22
end
23

24
-- Do the check to see if JIT is enabled. If so use the optimized FFI structs.
25
local status, ffi
26
if type(jit) == "table" and jit.status() then
8✔
27
        status, ffi = pcall(require, "ffi")
×
28
        if status then
×
29
                ffi.cdef "typedef struct { double x, y;} cpml_vec2;"
×
UNCOV
30
                new = ffi.typeof("cpml_vec2")
×
31
        end
32
end
33

34
--- Constants
35
-- @table vec2
36
-- @field unit_x X axis of rotation
37
-- @field unit_y Y axis of rotation
38
-- @field zero Empty vector
39
vec2.unit_x = new(1, 0)
8✔
40
vec2.unit_y = new(0, 1)
8✔
41
vec2.zero   = new(0, 0)
8✔
42

43
--- The public constructor.
44
-- @param x Can be of three types: </br>
45
-- number X component
46
-- table {x, y} or {x = x, y = y}
47
-- scalar to fill the vector eg. {x, x}
48
-- @tparam number y Y component
49
-- @treturn vec2 out
50
function vec2.new(x, y)
8✔
51
        -- number, number
52
        if x and y then
120✔
53
                precond.typeof(x, "number", "new: Wrong argument type for x")
112✔
54
                precond.typeof(y, "number", "new: Wrong argument type for y")
112✔
55

56
                return new(x, y)
112✔
57

58
        -- {x, y} or {x=x, y=y}
59
        elseif type(x) == "table" or type(x) == "cdata" then -- table in vanilla lua, cdata in luajit
8✔
60
                local xx, yy = x.x or x[1], x.y or x[2]
4✔
61
                precond.typeof(xx, "number", "new: Wrong argument type for x")
4✔
62
                precond.typeof(yy, "number", "new: Wrong argument type for y")
4✔
63

64
                return new(xx, yy)
4✔
65

66
        -- number
67
        elseif type(x) == "number" then
4✔
68
                return new(x, x)
2✔
69
        else
70
                return new()
2✔
71
        end
72
end
73

74
--- Convert point from polar to cartesian.
75
-- @tparam number radius Radius of the point
76
-- @tparam number theta Angle of the point (in radians)
77
-- @treturn vec2 out
78
function vec2.from_cartesian(radius, theta)
8✔
79
        return new(radius * cos(theta), radius * sin(theta))
1✔
80
end
81

82
--- Clone a vector.
83
-- @tparam vec2 a Vector to be cloned
84
-- @treturn vec2 out
85
function vec2.clone(a)
8✔
86
        return new(a.x, a.y)
71✔
87
end
88

89
--- Add two vectors.
90
-- @tparam vec2 a Left hand operand
91
-- @tparam vec2 b Right hand operand
92
-- @treturn vec2 out
93
function vec2.add(a, b)
8✔
94
        return new(
28✔
95
                a.x + b.x,
14✔
96
                a.y + b.y
14✔
97
        )
98
end
99

100
--- Subtract one vector from another.
101
-- Order: If a and b are positions, computes the direction and distance from b
102
-- to a.
103
-- @tparam vec2 a Left hand operand
104
-- @tparam vec2 b Right hand operand
105
-- @treturn vec2 out
106
function vec2.sub(a, b)
8✔
107
        return new(
18✔
108
                a.x - b.x,
9✔
109
                a.y - b.y
9✔
110
        )
111
end
112

113
--- Multiply a vector by another vector.
114
-- Component-size multiplication not matrix multiplication.
115
-- @tparam vec2 a Left hand operand
116
-- @tparam vec2 b Right hand operand
117
-- @treturn vec2 out
118
function vec2.mul(a, b)
8✔
119
        return new(
×
120
                a.x * b.x,
×
UNCOV
121
                a.y * b.y
×
122
        )
123
end
124

125
--- Divide a vector by another vector.
126
-- Component-size inv multiplication. Like a non-uniform scale().
127
-- @tparam vec2 a Left hand operand
128
-- @tparam vec2 b Right hand operand
129
-- @treturn vec2 out
130
function vec2.div(a, b)
8✔
131
        return new(
4✔
132
                a.x / b.x,
2✔
133
                a.y / b.y
2✔
134
        )
135
end
136

137
--- Get the normal of a vector.
138
-- @tparam vec2 a Vector to normalize
139
-- @treturn vec2 out
140
function vec2.normalize(a)
8✔
141
        if a:is_zero() then
2✔
UNCOV
142
                return new()
×
143
        end
144
        return a:scale(1 / a:len())
2✔
145
end
146

147
--- Trim a vector to a given length.
148
-- @tparam vec2 a Vector to be trimmed
149
-- @tparam number len Length to trim the vector to
150
-- @treturn vec2 out
151
function vec2.trim(a, len)
8✔
152
        return a:normalize():scale(math.min(a:len(), len))
1✔
153
end
154

155
--- Get the cross product of two vectors.
156
-- Order: Positive if a is clockwise from b. Magnitude is the area spanned by
157
-- the parallelograms that a and b span.
158
-- @tparam vec2 a Left hand operand
159
-- @tparam vec2 b Right hand operand
160
-- @treturn number magnitude
161
function vec2.cross(a, b)
8✔
162
        return a.x * b.y - a.y * b.x
1✔
163
end
164

165
--- Get the dot product of two vectors.
166
-- @tparam vec2 a Left hand operand
167
-- @tparam vec2 b Right hand operand
168
-- @treturn number dot
169
function vec2.dot(a, b)
8✔
170
        return a.x * b.x + a.y * b.y
17✔
171
end
172

173
--- Get the length of a vector.
174
-- @tparam vec2 a Vector to get the length of
175
-- @treturn number len
176
function vec2.len(a)
8✔
177
        return sqrt(a.x * a.x + a.y * a.y)
38✔
178
end
179

180
--- Get the squared length of a vector.
181
-- @tparam vec2 a Vector to get the squared length of
182
-- @treturn number len
183
function vec2.len2(a)
8✔
184
        return a.x * a.x + a.y * a.y
1✔
185
end
186

187
--- Get the distance between two vectors.
188
-- @tparam vec2 a Left hand operand
189
-- @tparam vec2 b Right hand operand
190
-- @treturn number dist
191
function vec2.dist(a, b)
8✔
192
        local dx = a.x - b.x
1✔
193
        local dy = a.y - b.y
1✔
194
        return sqrt(dx * dx + dy * dy)
1✔
195
end
196

197
--- Get the squared distance between two vectors.
198
-- @tparam vec2 a Left hand operand
199
-- @tparam vec2 b Right hand operand
200
-- @treturn number dist
201
function vec2.dist2(a, b)
8✔
202
        local dx = a.x - b.x
1✔
203
        local dy = a.y - b.y
1✔
204
        return dx * dx + dy * dy
1✔
205
end
206

207
--- Scale a vector by a scalar.
208
-- @tparam vec2 a Left hand operand
209
-- @tparam number b Right hand operand
210
-- @treturn vec2 out
211
function vec2.scale(a, b)
8✔
212
        return new(
22✔
213
                a.x * b,
11✔
214
                a.y * b
11✔
215
        )
216
end
217

218
--- Rotate a vector.
219
-- @tparam vec2 a Vector to rotate
220
-- @tparam number phi Angle to rotate vector by (in radians)
221
-- @treturn vec2 out
222
function vec2.rotate(a, phi)
8✔
223
        local c = cos(phi)
2✔
224
        local s = sin(phi)
2✔
225
        return new(
4✔
226
                c * a.x - s * a.y,
2✔
227
                s * a.x + c * a.y
2✔
228
        )
229
end
230

231
--- Get the perpendicular vector of a vector.
232
-- @tparam vec2 a Vector to get perpendicular axes from
233
-- @treturn vec2 out
234
function vec2.perpendicular(a)
8✔
235
        return new(-a.y, a.x)
1✔
236
end
237

238
--- Signed angle from one vector to another.
239
-- Rotations from +x to +y are positive.
240
-- @tparam vec2 a Vector
241
-- @tparam vec2 b Vector
242
-- @treturn number angle in (-pi, pi]
243
function vec2.angle_to(a, b)
8✔
244
        if b then
16✔
245
                local angle = atan2(b.y, b.x) - atan2(a.y, a.x)
16✔
246
                -- convert to (-pi, pi]
247
                if angle > math.pi       then
16✔
248
                        angle = angle - 2 * math.pi
1✔
249
                elseif angle <= -math.pi then
15✔
250
                        angle = angle + 2 * math.pi
3✔
251
                end
252
                return angle
16✔
253
        end
254

UNCOV
255
        return atan2(a.y, a.x)
×
256
end
257

258
--- Unsigned angle between two vectors.
259
-- Directionless and thus commutative.
260
-- @tparam vec2 a Vector
261
-- @tparam vec2 b Vector
262
-- @treturn number angle in [0, pi]
263
function vec2.angle_between(a, b)
8✔
264
        if b then
16✔
265
                if vec2.is_vec2(a) then
16✔
266
                        return acos(a:dot(b) / (a:len() * b:len()))
16✔
267
                end
268

UNCOV
269
                return acos(vec3.dot(a, b) / (vec3.len(a) * vec3.len(b)))
×
270
        end
271

UNCOV
272
        return 0
×
273
end
274

275
--- Lerp between two vectors.
276
-- @tparam vec2 a Left hand operand
277
-- @tparam vec2 b Right hand operand
278
-- @tparam number s Step value
279
-- @treturn vec2 out
280
function vec2.lerp(a, b, s)
8✔
281
        return a + (b - a) * s
1✔
282
end
283

284
--- Unpack a vector into individual components.
285
-- @tparam vec2 a Vector to unpack
286
-- @treturn number x
287
-- @treturn number y
288
function vec2.unpack(a)
8✔
289
        return a.x, a.y
1✔
290
end
291

292
--- Return the component-wise minimum of two vectors.
293
-- @tparam vec2 a Left hand operand
294
-- @tparam vec2 b Right hand operand
295
-- @treturn vec2 A vector where each component is the lesser value for that component between the two given vectors.
296
function vec2.component_min(a, b)
8✔
297
        return new(math.min(a.x, b.x), math.min(a.y, b.y))
9✔
298
end
299

300
--- Return the component-wise maximum of two vectors.
301
-- @tparam vec2 a Left hand operand
302
-- @tparam vec2 b Right hand operand
303
-- @treturn vec2 A vector where each component is the lesser value for that component between the two given vectors.
304
function vec2.component_max(a, b)
8✔
305
        return new(math.max(a.x, b.x), math.max(a.y, b.y))
9✔
306
end
307

308

309
--- Return a boolean showing if a table is or is not a vec2.
310
-- @tparam vec2 a Vector to be tested
311
-- @treturn boolean is_vec2
312
function vec2.is_vec2(a)
8✔
313
        if type(a) == "cdata" then
131✔
UNCOV
314
                return ffi.istype("cpml_vec2", a)
×
315
        end
316

317
        return
×
318
                type(a)   == "table"  and
131✔
319
                type(a.x) == "number" and
117✔
320
                type(a.y) == "number"
131✔
321
end
322

323
--- Return a boolean showing if a table is or is not a zero vec2.
324
-- @tparam vec2 a Vector to be tested
325
-- @treturn boolean is_zero
326
function vec2.is_zero(a)
8✔
327
        return a.x == 0 and a.y == 0
3✔
328
end
329

330
--- Return whether either value is NaN
331
-- @tparam vec2 a Vector to be tested
332
-- @treturn boolean if x or y is nan
333
function vec2.has_nan(a)
8✔
334
        return private.is_nan(a.x) or
1✔
335
                private.is_nan(a.y)
1✔
336
end
337

338
--- Convert point from cartesian to polar.
339
-- @tparam vec2 a Vector to convert
340
-- @treturn number radius
341
-- @treturn number theta
342
function vec2.to_polar(a)
8✔
343
        local radius = sqrt(a.x^2 + a.y^2)
1✔
344
        local theta  = atan2(a.y, a.x)
1✔
345
        theta = theta > 0 and theta or theta + 2 * math.pi
1✔
346
        return radius, theta
1✔
347
end
348

349
-- Round all components to nearest int (or other precision).
350
-- @tparam vec2 a Vector to round.
351
-- @tparam precision Digits after the decimal (integer if unspecified)
352
-- @treturn vec2 Rounded vector
353
function vec2.round(a, precision)
8✔
354
        return vec2.new(private.round(a.x, precision), private.round(a.y, precision))
3✔
355
end
356

357
-- Negate x axis only of vector.
358
-- @tparam vec2 a Vector to x-flip.
359
-- @treturn vec2 x-flipped vector
360
function vec2.flip_x(a)
8✔
361
        return vec2.new(-a.x, a.y)
1✔
362
end
363

364
-- Negate y axis only of vector.
365
-- @tparam vec2 a Vector to y-flip.
366
-- @treturn vec2 y-flipped vector
367
function vec2.flip_y(a)
8✔
368
        return vec2.new(a.x, -a.y)
1✔
369
end
370

371
-- Convert vec2 to vec3.
372
-- @tparam vec2 a Vector to convert.
373
-- @tparam number the new z component, or nil for 0
374
-- @treturn vec3 Converted vector
375
function vec2.to_vec3(a, z)
8✔
376
        return vec3(a.x, a.y, z or 0)
2✔
377
end
378

379
--- Return a formatted string.
380
-- @tparam vec2 a Vector to be turned into a string
381
-- @treturn string formatted
382
function vec2.to_string(a)
8✔
383
        return string.format("(%+0.3f,%+0.3f)", a.x, a.y)
1✔
384
end
385

386
vec2_mt.__index    = vec2
8✔
387
vec2_mt.__tostring = vec2.to_string
8✔
388

389
function vec2_mt.__call(_, x, y)
8✔
390
        return vec2.new(x, y)
114✔
391
end
392

393
function vec2_mt.__unm(a)
8✔
394
        return new(-a.x, -a.y)
1✔
395
end
396

397
function vec2_mt.__eq(a, b)
8✔
398
        if not vec2.is_vec2(a) or not vec2.is_vec2(b) then
24✔
UNCOV
399
                return false
×
400
        end
401
        return a.x == b.x and a.y == b.y
24✔
402
end
403

404
function vec2_mt.__add(a, b)
8✔
405
        precond.assert(vec2.is_vec2(a), "__add: Wrong argument type '%s' for left hand operand. (<cpml.vec2> expected)", type(a))
13✔
406
        precond.assert(vec2.is_vec2(b), "__add: Wrong argument type '%s' for right hand operand. (<cpml.vec2> expected)", type(b))
13✔
407
        return a:add(b)
13✔
408
end
409

410
function vec2_mt.__sub(a, b)
8✔
411
        precond.assert(vec2.is_vec2(a), "__add: Wrong argument type '%s' for left hand operand. (<cpml.vec2> expected)", type(a))
8✔
412
        precond.assert(vec2.is_vec2(b), "__add: Wrong argument type '%s' for right hand operand. (<cpml.vec2> expected)", type(b))
8✔
413
        return a:sub(b)
8✔
414
end
415

416
function vec2_mt.__mul(a, b)
8✔
417
        precond.assert(vec2.is_vec2(a), "__mul: Wrong argument type '%s' for left hand operand. (<cpml.vec2> expected)", type(a))
2✔
418
        assert(vec2.is_vec2(b) or type(b) == "number", "__mul: Wrong argument type for right hand operand. (<cpml.vec2> or <number> expected)")
2✔
419

420
        if vec2.is_vec2(b) then
2✔
UNCOV
421
                return a:mul(b)
×
422
        end
423

424
        return a:scale(b)
2✔
425
end
426

427
function vec2_mt.__div(a, b)
8✔
428
        precond.assert(vec2.is_vec2(a), "__div: Wrong argument type '%s' for left hand operand. (<cpml.vec2> expected)", type(a))
6✔
429
        assert(vec2.is_vec2(b) or type(b) == "number", "__div: Wrong argument type for right hand operand. (<cpml.vec2> or <number> expected)")
6✔
430

431
        if vec2.is_vec2(b) then
6✔
432
                return a:div(b)
1✔
433
        end
434

435
        return a:scale(1 / b)
5✔
436
end
437

438
if status then
8✔
439
        xpcall(function() -- Allow this to silently fail; assume failure means someone messed with package.loaded
×
440
                ffi.metatype(new, vec2_mt)
×
UNCOV
441
        end, function() end)
×
442
end
443

444
return setmetatable({}, vec2_mt)
8✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc