Skip to content

Commit a602bea

Browse files
committed
Add cross and dot product functions
1 parent 14002df commit a602bea

File tree

3 files changed

+35
-3
lines changed

3 files changed

+35
-3
lines changed

docs/builtins.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,16 @@ the length of the longest vector; short arguments will repeat, so
7171
generalises to n-vectors, returning a vector the length of the longest of
7272
*x*, *y* and *z*, and repeating items from any of the vectors as necessary.
7373

74+
`cross(` *x*, *y* `)`
75+
: Compute the cross product of two 3-vectors.
76+
7477
`cos(` *x* `)`
7578
: Return cosine of *x* (with *x* expressed in *turns*).
7679

80+
`dot(` *x*, *y* `)`
81+
: Compute the dot product of two n-vectors. This is the equivalent of
82+
`sum(x * y)`.
83+
7784
`exp(` *x* `)`
7885
: Return $e$ raised to the power of *x*.
7986

src/flitter/language/functions.pyx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,14 @@ def hypot(*args):
804804
return ys
805805

806806

807+
def cross(Vector xs not None, Vector ys not None):
808+
return xs.cross(ys)
809+
810+
811+
def dot(Vector xs not None, Vector ys not None):
812+
return xs.dot(ys)
813+
814+
807815
def normalize(Vector xs not None):
808816
return xs.normalize()
809817

@@ -815,9 +823,9 @@ def quaternion(Vector axis not None, Vector angle not None):
815823

816824

817825
def qmul(Vector a not None, Vector b not None):
818-
if a.numbers == NULL or a.length != 4 or b.numbers == NULL or b.length != 4:
826+
if a.numbers == NULL or a.length != 4 or b.numbers == NULL or b.length not in (3, 4):
819827
return null_
820-
return Quaternion._coerce(a) @ Quaternion._coerce(b)
828+
return Quaternion._coerce(a) @ (Quaternion._coerce(b) if b.length == 4 else b)
821829

822830

823831
def qbetween(Vector a not None, Vector b not None):
@@ -1046,7 +1054,9 @@ STATIC_FUNCTIONS = {
10461054
'colortemp': Vector(colortemp),
10471055
'cos': Vector(cosv),
10481056
'count': Vector(count),
1057+
'cross': Vector(cross),
10491058
'cubic': Vector(cubic),
1059+
'dot': Vector(dot),
10501060
'exp': Vector(expv),
10511061
'floor': Vector(floorv),
10521062
'fract': Vector(fract),

tests/test_functions.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from flitter.language.functions import (uniform, normal, beta,
1111
lenv, sumv, accumulate, minv, maxv, minindex, maxindex, mapv, clamp, zipv, count,
1212
roundv, absv, expv, sqrtv, logv, log2v, log10v, ceilv, floorv, fract,
13-
cosv, acosv, sinv, asinv, tanv, hypot, normalize, polar, angle, length,
13+
cosv, acosv, sinv, asinv, tanv, hypot, normalize, polar, angle, length, cross, dot,
1414
quaternion, qmul, qbetween, slerp,
1515
split, ordv, chrv,
1616
colortemp, oklab, oklch)
@@ -537,6 +537,21 @@ def test_normalize(self):
537537
self.assertEqual(normalize(Vector([3, 4])), Vector([3, 4]) / Vector(5))
538538
self.assertEqual(normalize(Vector([3, 4, 5])), Vector([3, 4, 5]) / Vector(math.sqrt(50)))
539539

540+
def test_cross(self):
541+
self.assertEqual(cross(null, null), null)
542+
self.assertEqual(cross(Vector([3, 4]), Vector([3, 4, 5])), null)
543+
self.assertEqual(cross(Vector([3, 4, 5]), Vector([3, 4])), null)
544+
self.assertEqual(cross(Vector([3, 4, 5]), Vector([3, 4, 5])), Vector([0, 0, 0]))
545+
self.assertEqual(cross(Vector([1, 0, 0]), Vector([0, 1, 0])), Vector([0, 0, 1]))
546+
self.assertEqual(cross(Vector([0, 1, 0]), Vector([0, 0, 1])), Vector([1, 0, 0]))
547+
self.assertEqual(cross(Vector([0, 0, 1]), Vector([1, 0, 0])), Vector([0, 1, 0]))
548+
549+
def test_dot(self):
550+
self.assertEqual(dot(null, null), null)
551+
self.assertEqual(dot(Vector([3, 4]), Vector([3, 4, 5])), Vector(3*3 + 4*4 + 3*5))
552+
self.assertEqual(dot(Vector([3, 4, 5]), Vector([3, 4])), Vector(3*3 + 4*4 + 5*3))
553+
self.assertEqual(dot(Vector([3, 4, 5]), Vector([5, 4, 3])), Vector(3*5 + 4*4 + 5*3))
554+
540555
def test_polar(self):
541556
self.assertEqual(polar(null), null)
542557
self.assertEqual(polar(Vector('hello')), null)

0 commit comments

Comments
 (0)