Vector and Matrix Utils #85

Parent #72Owner #29Flags readSource hellcore/hellcore.db

Aliases: Vector and Matrix Utils, vector, matrix

31 verbs · 12 properties · 0 children

Verbs

VerbSpecFlagsDefinerLines
vector_add vector_sub vector_mul vector_divthis none thisrxd#8557
matrix_add matrix_subthis none thisrxd#8517
transposethis none thisrxd#8512
determinantthis none thisrxd#8538
inversethis none thisrxd#8518
identitythis none thisrxd#8511
nullthis none thisrxd#8514
is_squarethis none thisrxd#853
is_nullthis none thisrxd#8513
is_identitythis none thisrxd#8513
cross_prod outer_prod vector_prodthis none thisrxd#8531
norm lengththis none thisrxd#858
submatrixthis none thisrxd#8516
dot_prod inner_prod scalar_prodthis none thisrxd#8519
dimension*sthis none thisrxd#856
orderthis none thisrxd#852
scalar_vector_add scalar_vector_sub scalar_vector_mul scalar_vector_divthis none thisrxd#8531
subtended_anglethis none thisrxd#8511
columnthis none thisrxd#858
matrix_multhis none thisrxd#8519
scalar_matrix_mul scalar_matrix_divthis none thisrxd#8526
is_matrixthis none thisrxd#8512
is_vectorthis none thisrxd#8513
is_reflexive is_areflexivethis none thisrxd#8516
is_symmetric is_asymmetricthis none thisrxd#8518
is_transitive is_atransitivethis none thisrxd#8524
_relation_resultthis none thisrxd#8510
is_partial_orderingthis none thisrxd#853
xyzr_collisionthis none thisrxd#857
xyz_distancethis none thisrxd#854
xyz_linethis none thisrxd#8566

Properties

PropertyDefinerFlagsOwnerValue
note#85rc#29"Please contact Uther@LambdaMOO if you make changes to this object, so he can make the changes on Lambda and elsewhere."
help_msg#72rc#29
list of 62{"Utility verbs for manipulating lists as vectors (one dimensional lists) or as matrices (two dimensional lists).", "", "Some definitions:", "A VECTOR is a list of INTs or a list of FLOATs. Each element in the list represents the vector's cartesian coordinate as measured from its tail to its tip. (For instance, {3, 4} represents a vector in the x-y plane with an x component of 3 and a y component of 4. {-2, 5, 10} represents a vector in 3-space with a x component of -2, a y component of 5 and a z component of 10.)", "A MATRIX is a list of VECTORs, all of which have the same number (and type) of components.", "", "Vector verbs:", ":vector_add (V1 [,V2 ...]) => VN such that VN[n] = V1[n] + V2[n]...", ":vector_sub (V1 [,V2 ...]) => VN such that VN[n] = V1[n] - V2[n]...", ":scalar_vector_mul (V, S) => VN such that VN[n] = V[n] * S...", ":scalar_vector_div (V, S) => VN such that VN[n] = V[n] / S...", ":dot_prod (V1, V2) => NUM sum of the products of the ", ":inner_prod corresponding elements of the two", " vectors.", ":cross_prod (V1, V2) => VN, the vector perpendicular to both V1", ":outer_prod and V2 with length equal to the area of", " the parallelogram spanned by V1 and V2.", ":subtended_angle (V1, V2) => FLOAT smallest radian angle defined by", " V1 and V2.", ":length (V) => FLOAT length of the vector. ", ":norm", "", "Matrix and Vector verbs:", ":dimensions (M) => LIST of dimensional sizes", ":order (M) => NUM of dimensions", "", "Matrix verbs:", ":matrix_add (M1 [,M2 ...]) => MN such that MN[m][n] = M1[m][n] + M2[m][n]...", ":matrix_sub (M1 [,M2 ...]) => MN such that MN[m][n] = M1[m][n] - M2[m][n]...", ":matrix_mul (M1, M2) => MN such than MN[m][n] = the dot product of the ", " mth row of M1 and the nth column of M2.", ":scalar_matrix_mul (M, S) => MN such that MN[m][n] = M[m][n] * S...", ":scalar_matrix_div (M, S) => MN such that MN[m][n] = M[m][n] / S...", ":transpose (M1) => M2 such that the rows in M1 are the columns in", " M2 and vice versa.", ":identity (INT <size>) => Identity matrix (I) of dimensions <size> by ", " <size>.", ":null (INT <size>) => Null matrix (O) of dimensions <size> by <size>.", ":is_square (M) => 1 iff dimensions of M are equal.", ":column (M, INT <n>) => LIST the nth column of M.", "", "Square Matrix verbs:", ":determinant (M) => NUM the determinant of the square matrix.", ":inverse (M) => the matrix that M multiplied by :inverse(M) yields I.", ":is_identity (M) => 1 iff M is I.", ":is_null (M) => 1 iff M is O.", "", "Relation verbs:", ":is_reflexive (M) => 1 if M is a reflexive relation, -1 if areflexive,", " 0 otherwise.", ":is_areflexive (M) => 1 if M is an areflexive relation, -1 if reflexive,", " 0 otherwise.", ":is_symmetric (M) => 1 if M is a symmetric relation, -1 if asymmetric,", " 0 otherwise.", ":is_asymmetric (M) => 1 if M is an asymmetric relation, -1 if symmetric,", " 0 otherwise.", ":is_transitive (M) => 1 if M is a transitive relation, -1 if atransitive,", " 0 otherwise.", ":is_atransitive (M) => 1 if M is an atransitive relation, -1 if transitive,", " 0 otherwise.", ":is_partial_ordering (M) => 1 if M is a reflexive, asymmetric, transitive", " relation."}
aliases#1rc#29{"Vector and Matrix Utils", "vector", "matrix"}
description#1rc#29"This is a utilities package for dealing with lists as representations of vectors and matrices. Type `help $matrix_utils' for more details."
object_size#1r#29{32446, 1298433815}
hidden_verbs#1rc#29<clear>
phelp_msg#1rc#29<clear>
weight#1rc#29<clear>
owner_verbs#1rc#29<clear>
plural_name#1rc#29<clear>
client_image#1rc#29<clear>
listening#1rc#29<clear>

Ancestry

Ancestors (nearest first): #72 Generic Utilities Package#1 root

Children: none

Call graph

calls n85_1 #85:matrix_add n47_16 #47:slice n85_1->n47_16 n85_2 #85:transpose n85_21 #85:is_matrix n85_2->n85_21 n85_18 #85:column n85_2->n85_18 n85_22 #85:is_vector n85_21->n85_22 n85_3 #85:determinant n85_3->n85_3 n85_7 #85:is_square n85_3->n85_7 n85_12 #85:submatrix n85_3->n85_12 n85_7->n85_21 n85_15 #85:order n85_7->n85_15 n85_4 #85:inverse n85_4->n85_3 n85_4->n85_12 n18_3 #18:pow n85_4->n18_3 n85_5 #85:identity n85_6 #85:null n85_5->n85_6 n85_8 #85:is_null n85_8->n85_7 n85_9 #85:is_identity n85_9->n85_7 n85_10 #85:cross_prod n85_10->n85_3 n85_10->n85_12 n85_10->n85_22 n85_11 #85:norm n85_11->n85_22 n85_13 #85:dot_prod n85_11->n85_13 n85_13->n85_22 n85_0 #85:vector_add n85_13->n85_0 n85_16 #85:scalar_vector_add n85_16->n85_22 n85_17 #85:subtended_angle n85_17->n85_22 n85_17->n85_11 n85_17->n85_13 n85_19 #85:matrix_mul n85_19->n85_21 n85_19->n85_18 n85_19->n85_13 n85_20 #85:scalar_matrix_mul n85_20->n85_21 n85_23 #85:is_reflexive n85_23->n85_7 n85_26 #85:_relation_result n85_23->n85_26 n85_24 #85:is_symmetric n85_24->n85_7 n85_24->n85_26 n85_25 #85:is_transitive n85_25->n85_7 n85_25->n85_26 n85_27 #85:is_partial_ordering n85_27->n85_23 n85_27->n85_24 n85_27->n85_25

Source

vector_add vector_sub vector_mul vector_div

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

Source

1":vector_add(V1 [,V2 ...]) => VN such that VN[n] = V1[n] + V2[n]...";
2":vector_sub(V1 [,V2 ...]) => VN such that VN[n] = V1[n] - V2[n]...";
3":vector_mul(V1 [,V2 ...]) => VN such that VN[n] = V1[n] * V2[n]...";
4":vector_div(V1 [,V2 ...]) => VN such that VN[n] = V1[n] / V2[n]...";
5"Vectors do not need to be the same length, but they should be. VN's length will be the length of the longest vector in the arguments. :vector_add and :vector_sub will pad out the smaller vectors with 0's or 0.0's. :vector_mul and :vector_div will pad out the smaller vectors with 1's or 1.0's. Vectors do not need to contain homogeneous data, but the nth term of each vector must be of the same type.";
6"I can see a reason for wanting to do vector addition or subtraction, but multiplication and divareion is usually handled in other ways. I've included them here for novelty, and becuase it was easy enough to do.";
7"";
8"Vector addition is used when two or more similar vector quantities are at work and need to be resolved into a single vector. For instance, a ship travelling in a current will be acted upon by (at least) two forces: a force propelling it forward (its engine), and a force pushing it off course (the current). The sum of these two forces gives the resultant net force acting upon the ship and, since Force = Mass * Acceleration, the direction the ship is accelerating.";
9"";
10"Vector subtraction can be used to reverse the process of vector addition. In the ship problem above, let's say the actual resultant force is known, but it does not match the result of adding the propelling force and the drifting force. Friction is probably acting against the motion of the ship. Subtracting the computed resultant force from the known net force will yield the frictional force acting against the progress of the ship.";
11"";
12"Vector multiplication and division do not have RL examples, but vector multiplication of this type makes computing the dot product of two vectors simple.";
13"";
14if (length(args) == 1)
15return args;
16elseif (!args)
17return raise(E_INVARG);
18endif
19type = verb[$ - 2..$];
20lresult = max = length(args[1]);
21results = args[1];
22for n in [2..length(args)]
23if (type == "add")
24for m in [1..min(lcurr = length(args[n]), lresult)]
25results[m] = results[m] + args[n][m];
26endfor
27if (lcurr > lresult)
28results[lresult + 1..lcurr] = args[n][lresult + 1..lcurr];
29endif
30elseif (type == "sub")
31for m in [1..min(lcurr = length(args[n]), lresult)]
32results[m] = results[m] - args[n][m];
33endfor
34if (lcurr > lresult)
35for m in [lresult + 1..lcurr]
36results = {@results, -args[n][m]};
37endfor
38endif
39elseif (type == "mul")
40for m in [1..min(lcurr = length(args[n]), lresult)]
41results[m] = results[m] * args[n][m];
42endfor
43if (lcurr > lresult)
44results[lresult + 1..lcurr] = args[n][lresult + 1..lcurr];
45endif
46else
47for m in [1..min(lcurr = length(args[n]), lresult)]
48results[m] = results[m] / args[n][m];
49endfor
50if (lcurr > lresult)
51for m in [lresult + 1..lcurr]
52results = {@results, (typeof(foo = args[n][m]) == INT) ? 1 / foo | (1.0 / foo)};
53endfor
54endif
55endif
56endfor
57return results;

matrix_add matrix_sub

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

none

Source

1":matrix_add(M1 [, M2 ...]) => MN such that MN[m][n] = M1[m][n] + M2[m][n]...";
2":matrix_sub(M1 [, M2 ...]) => MN such that MN[m][n] = M1[m][n] - M2[m][n]...";
3"Matrices should all be of the same size.";
4"";
5"Matrix addition and subtraction is simply the addition or subtraction of the vectors contained in the matrices. See 'help $matrix_utils:vector:add' for more help.";
6type = verb[$ - 2..$];
7results = args[1];
8if (typeof(results[1][1]) == LIST)
9for n in [1..length(results)]
10results[n] = this:(verb)(results[n], @$list_utils:slice(args[2..$], n));
11endfor
12else
13for n in [1..length(results)]
14results[n] = this:("vector_" + type)(results[n], @$list_utils:slice(args[2..$], n));
15endfor
16endif
17return results;

transpose

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

none

Source

1":transpose(Mmn) => Mnm";
2"Transpose an m by n matrix into an n by m matrix by making the rows in the original the columns in the output.";
3{mat} = args;
4if (!this:is_matrix(mat))
5return raise("E_INVMAT", "Invalid Matrix Format");
6endif
7j = this:dimensions(mat)[2];
8result = {};
9for n in [1..j]
10result = {@result, this:column(mat, n)};
11endfor
12return result;

determinant

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

Source

1":determinant(M) => NUM the determinant of the matrix.";
2"";
3"There are several properties of a matrix's determinant. Adding or subtracting a row or column from another row or colum of a matrix does not hange the value of its determinant. Multiplying a row or column of a matrix by a single scalar value has the effect of multiplying the matrix's determinant by the same scalar.";
4"";
5"However, the most dramatic use of determinants is in solving linear equations. For example, the solution to this system of equations:";
6"";
7"Ax1 + Bx2 + Cx3 = D";
8"Ex1 + Fx2 + Gx3 = H";
9"Ix1 + Jx2 + Kx3 = L";
10"";
11"is";
12"";
13"     1 |D B C|         1 |A D C|        1 |A B D|";
14"x1 = - |H F G|    x2 = - |E H G|   x3 = - |E F H|";
15"     Z |L J K|         Z |I L K|        Z |I J L|";
16"";
17"          |A B C|";
18"where Z = |E F G|";
19"          |I J K|";
20"";
21"or, in other words, x1, x2, and x3 are some determinant divided by Z, another determinant.";
22"";
23"Determinants are also used in computing the cross product of two vectors. See 'help $matrix_utils:cross_prod' for more info.";
24"";
25{mat} = args;
26if (!this:is_square(mat))
27return raise("E_INVMAT", "Invalid Matrix Format");
28elseif (this:dimensions(mat)[1] == 2)
29return (mat[1][1] * mat[2][2]) - (mat[1][2] * mat[2][1]);
30else
31result = 0;
32coeff = 1;
33for n in [1..length(mat[1])]
34result = result + ((coeff * mat[1][n]) * this:determinant(this:submatrix(1, n, mat)));
35coeff = -coeff;
36endfor
37return result;
38endif

inverse

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

none

Source

1":inverse(M) => MN such that M * MN = I";
2"";
3"The inverse of a matrix is very similar to the reciprocal of a scalar number. If two numbers, A and B, equal 1 (the scalar identity number) when multiplied together (AB=1), then B is said the be the reciprocal of A, and A is the reciprocal of B. If A and B are matrices, and the result of multiplying them togeter is the Identity Matrix, then B is the inverse of A, and A is the inverse of B.";
4"";
5"Computing the inverse involves the solutions of several linear equations. Since linear equations can be easily solved with determinants, this is rather simple. See 'help $matrix_utils:determinant' for more on how determinants solve linear equations.";
6"";
7{mat} = args;
8{i, j} = this:dimensions(mat);
9det = this:determinant(mat);
10result = {};
11for k in [1..i]
12sub = {};
13for l in [1..j]
14sub = {@sub, (tofloat($math_utils:pow(-1, i + j)) * this:determinant(this:submatrix(j, i, mat))) / det};
15endfor
16result = {@result, sub};
17endfor
18return result;

identity

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

none

Source

1":identity(INT <size>) => Identity matrix (I) of dimensions <size> by <size>.";
2"All elements of I are 0, except for the diagonal elements which are 1.";
3"";
4"The Identity Matrix has the unique property such that when another matrix is multiplied by it, the other matrix remains unchanged. This is similar to the number 1. a*1 = a. A * I = A, if the dimensions of I and A are the same.";
5"";
6n = args[1];
7result = this:null(n, n);
8for i in [1..n]
9result[i][i] = 1;
10endfor
11return result;

null

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

Source

1":null(INT <size>) => Null matrix (O) of dimensions <size> by <size>.";
2"All elements of O are 0.";
3"";
4"The Null Matrix has the property that is equivalent to the number 0; it reduces the original matrix to itself. a * 0 = 0. A * N = N.";
5"";
6{m, ?n = m} = args;
7result = {};
8for i in [1..m]
9result = {@result, {}};
10for j in [1..n]
11result[i] = {@result[i], 0};
12endfor
13endfor
14return result;

is_square

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

Source

1":is_square(M) => 1 iff dimensions of M are equal to each other.";
2{m} = args;
3return (this:is_matrix(m) && (this:order(m) == 2)) && ((dim = this:dimensions(m))[1] == dim[2]);

is_null

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

none

Source

1":is_null(M) => 1 iff M is O.";
2m = length(mat = args[1]);
3if (!this:is_square(mat))
4return 0;
5endif
6for i in [1..m]
7for j in [1..m]
8if (mat[i][j] != 0)
9return 0;
10endif
11endfor
12endfor
13return 1;

is_identity

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

none

Source

1":is_identity(M) => 1 iff M is I.";
2m = length(mat = args[1]);
3if (!this:is_square(mat))
4return 0;
5endif
6for i in [1..m]
7for j in [1..m]
8if ((mat[i][j] != 0) && ((i != j) ? 1 | (mat[i][j] != 1)))
9return 0;
10endif
11endfor
12endfor
13return 1;

cross_prod outer_prod vector_prod

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

none

Source

1":cross_prod(V1, V2) => VN, the vector perpendicular to both V1 and V2 with length equal to the area of the parallelogram spanned by V1 and V2, and direction governed by the rule of thumb.";
2"";
3"If A = a1i + a2j + a3k, represented as a list as {a1, a2, a3}";
4"and B = b1i + b2j + b3k, or {b1, b2, b3}, then";
5"";
6"        |i  j  k |";
7"A x B = |a1 a2 a3| = |a2 a3|i - |a1 a3|j + |a1 a2|k";
8"        |b1 b2 b3| = |b2 b3|    |b1 b3|    |b1 b2|";
9"";
10"or, in list terms, as the list of the coefficients of i, j, and k.";
11"";
12"Note: i, j, and k are unit vectors in the x, y, and z direction respectively.";
13"";
14"The rule of thumb: A x B = C  If you hold your right hand out so that your fingers point in the direction of A, and so that you can curl them through B as you make a hitchhiking fist, your thumb will point in the direction of C.";
15"";
16"Put another way, A x B = ABsin(THETA) (A cross B equals the magnitude of A times the magnitude of B times the sin of the angle between them) This is expressed as a vector perpendicular the the A-B plane, pointing `up' if you curl your right hand fingers from A to B, and `down' if your right hand fingers curl from B to A.";
17"";
18"The cross product has many uses in physics. Angular momentum is the cross product of a particles position vector from the point it is rotating around and it's linear momentum (L = r x p). Torque is the cross product of position and Force (t = r x F).";
19"";
20{v1, v2} = args;
21if (((((l = length(v1)) != length(v2)) || (l != 3)) || (!this:is_vector(v1))) || (!this:is_vector(v2)))
22return raise("E_INVVEC", "Invalid Vector Format");
23endif
24mat = {{1, 1, 1}, v1, v2};
25coeff = 1;
26result = {};
27for n in [1..3]
28result = {@result, coeff * this:determinant(this:submatrix(1, n, mat))};
29coeff = -coeff;
30endfor
31return result;

norm length

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

Source

1":norm(V) => FLOAT";
2":length(V) => FLOAT";
3"The norm is the length of a vector, the square root of the sum of the squares of its elements.";
4"";
5"In school, we all should have learned the Pythagorean Theorem of right triangles: The sum of the squares of the sides of a right triagle is equal to the square of the hypoteneuse. The Theorem holds true no matter how many dimensions are being considered. The length of a vector is equal to the square root of the sum of the squares of its components. The dot product of a vector with itself happens to be the sum of the squares of its components.";
6"";
7{v} = args;
8return this:is_vector(v) ? sqrt(tofloat(this:dot_prod(v, v))) | E_TYPE;

submatrix

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

Source

1":submatrix(i, j, M1) => M2, the matrix formed from deleting the ith row and jth column from M1.";
2{i, j, mat} = args;
3{k, l} = this:dimensions(mat);
4result = {};
5for m in [1..k]
6sub = {};
7for n in [1..l]
8if ((m != i) && (n != j))
9sub = {@sub, mat[m][n]};
10endif
11endfor
12if (sub)
13result = {@result, sub};
14endif
15endfor
16return result;

dot_prod inner_prod scalar_prod

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

Source

1":dot_prod(V1, V2) => NUM";
2":inner_prod(V1, V2) => NUM";
3"The dot, or inner, product of two vectors is the sum of the products of the corresponding elements of the vectors.";
4"If V1 = {1, 2, 3} and V2 = {4, 5, 6}, then V1.V2 = 1*4 + 2*5 + 3*6 = 32";
5"";
6"The dot product is useful in computing the angle between two vectors, and the length of a vector. See 'help $matrix_utils:subtended_angle' and 'help $matrix_utils:length'.";
7"";
8"A . B = ABcos(THETA)  (A dot B equals the magnitude of A times the magnitude of B times the cosine of the angle between them.)";
9"";
10{v1, v2} = args;
11if ((((l = length(v1)) != length(v2)) || (!this:is_vector(v1))) || (!this:is_vector(v2)))
12return raise("E_INVVEC", "Invalid Vector Format");
13endif
14temp = this:vector_mul(v1, v2);
15result = (typeof(temp[1]) == INT) ? 0 | 0.0;
16for n in [1..l]
17result = result + temp[n];
18endfor
19return result;

dimension*s

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

none

Source

1":dimensions(M) => LIST of dimensional sizes.";
2l = {length(m = args[1])};
3if (typeof(m[1]) == LIST)
4l = {@l, @this:dimensions(m[1])};
5endif
6return l;

order

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

Source

1":order(M) => INT how many dimensions does this matrix have? 1 means vector";
2return length(this:dimensions(args[1]));

scalar_vector_add scalar_vector_sub scalar_vector_mul scalar_vector_div

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

none

Source

1":scalar_vector_add(S, V) => VN such that VN[n] = V[n] + S...";
2":scalar_vector_sub(S, V) => VN such that VN[n] = V[n] - S...";
3":scalar_vector_mul(S, V) => VN such that VN[n] = V[n] * S...";
4":scalar_vector_div(S, V) => VN such that VN[n] = V[n] / S...";
5"Actually, arguments can be (S, V) or (V, S). Each element of V is augmented by S. S should be either an INT or a FLOAT, as appropriate to the values in V.";
6"";
7"I can see a reason for wanting to do scalar/vector multiplcation or division, but addition and subtraction between vector and scalar types is not done. I've included them here for novelty, and because it was easy enough to to.";
8"";
9"Scalar-vector multiplication stretches a vector along its direction, generating points along a line. One of the more famous uses from physics is Force equals mass times acceleration. F = ma. Force and acceleration are both vectors. Mass is a scalar quantity.";
10"";
11if (typeof(args[1]) == LIST)
12{vval, sval} = args;
13else
14{sval, vval} = args;
15endif
16if (!this:is_vector(vval))
17return raise("E_INVVEC", "Invalid Vector Format");
18endif
19type = verb[$ - 2..$];
20for n in [1..length(vval)]
21if (type == "add")
22vval[n] = vval[n] + sval;
23elseif (type == "sub")
24vval[n] = vval[n] - sval;
25elseif (type == "mul")
26vval[n] = vval[n] * sval;
27else
28vval[n] = vval[n] / sval;
29endif
30endfor
31return vval;

subtended_angle

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

none

Source

1":subtended_angle(V1, V2) => FLOAT smallest angle defined by V1, V2 in radians";
2"";
3"Any two vectors define two angles, one less than or equal to 180 degrees, the other 180 degrees or more. The larger can be determined from the smaller, since their sum must be 360 degrees.";
4"";
5"The dot product of the two angles, divided by the lengths of each of the vectors is the cosine of the smaller angle defined by the two vectors.";
6"";
7{v1, v2} = args;
8if ((((l = length(v1)) != length(v2)) || (!this:is_vector(v1))) || (!this:is_vector(v2)))
9return raise("E_INVVEC", "Invalid Vector Format");
10endif
11return acos(tofloat(this:dot_prod(v1, v2)) / (this:norm(v1) * this:norm(v2)));

column

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

Source

1":column(M, INT <n>) => LIST the nth column of M.";
2{mat, i} = args;
3j = this:dimensions(mat)[1];
4result = {};
5for m in [1..j]
6result = {@result, mat[m][i]};
7endfor
8return result;

matrix_mul

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

none

Source

1":matrix_mul(M1, M2) => MN such that MN[m][n] = the dot product of the mth row of M1 and the transpose of thenth column of M2.";
2"";
3"Matrix multiplication is the most common and complex operation performed on two matrices. First, matrices can only be multiplied if they are of compatible sizes. An i by j matrix can only be multiplied by a j by k matrix, and the results of this multiplication will be a matrix of size i by k. Each element in the resulting matrix is the dot product of a row from the first matrix and a column from the second matrix. (See 'help $matrix_utils:dot_prod'.)";
4"";
5{m1, m2} = args;
6{i, j} = this:dimensions(m1);
7{k, l} = this:dimensions(m2);
8if (((j != k) || (!this:is_matrix(m1))) || (!this:is_matrix(m2)))
9return raise("E_INVMAT", "Invalid Matrix Format");
10endif
11result = {};
12for m in [1..i]
13sub = {};
14for n in [1..l]
15sub = {@sub, this:dot_prod(m1[m], this:column(m2, n))};
16endfor
17result = {@result, sub};
18endfor
19return result;

scalar_matrix_mul scalar_matrix_div

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

none

Source

1":scalar_matrix_add(S, M) => MN such that MN[m][n] = MN[m][n] + S...";
2":scalar_matrix_sub(S, M) => MN such that MN[m][n] = MN[m][n] - S...";
3":scalar_matrix_mul(S, M) => MN such that MN[m][n] = MN[m][n] * S...";
4":scalar_matrix_div(S, M) => MN such that MN[m][n] = MN[m][n] / S...";
5"Actually, arguments can be (S, M) or (M, S). Each element of M is augmented by S. S should be either an INT or a FLOAT, as appropriate to the values in M.";
6"I can see a reason for wanting to do scalar/matrix multiplication or division, but addition and subtraction between matrix and scalar types is not done. I've included them here for novelty, and because it was easy enough to do.";
7type = verb[$ - 2..$];
8if (typeof(args[1]) == LIST)
9{mval, sval} = args;
10else
11{sval, mval} = args;
12endif
13if (!this:is_matrix(mval))
14return raise("E_INVMAT", "Invalid Matrix Format");
15endif
16results = {};
17if (typeof(mval[1][1] == LIST))
18for n in [1..length(mval)]
19results = {@results, this:(verb)(mval[n], sval)};
20endfor
21else
22for n in [1..length(mval)]
23results = {@results, this:("scalar_vector_" + type)(mval[n], sval)};
24endfor
25endif
26return results;

is_matrix

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

Source

1"A matrix is defined as a list of vectors, each having the smae number of elements.";
2{m} = args;
3if ((typeof(m) != LIST) || (typeof(m[1]) != LIST))
4return 0;
5endif
6len = length(m[1]);
7for v in (m)
8if ((!this:is_vector(v)) || (length(v) != len))
9return 0;
10endif
11endfor
12return 1;

is_vector

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

Source

1"A vector shall be defined as a list of INTs or FLOATs. (I'm not gonna worry about them all being the same type.)";
2flag = 1;
3{v} = args;
4if (typeof(v) != LIST)
5return 0;
6endif
7for n in (v)
8if (((ntype = typeof(n)) != INT) && (ntype != FLOAT))
9flag = 0;
10break;
11endif
12endfor
13return flag;

is_reflexive is_areflexive

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

Source

1":is_reflexive   (M) => 1 if M is a reflexive relation, -1 if areflexive,";
2"                       0 otherwise.";
3":is_areflexive does the same, but with 1 and -1 reversed.";
4{m} = args;
5if (!this:is_square(m))
6return raise("E_INVMAT", "Invalid Matrix Format");
7endif
8good = bad = 0;
9for n in [1..length(m)]
10if (!m[n][n])
11bad = 1;
12else
13good = 1;
14endif
15endfor
16return this:_relation_result(good, bad, verb[4] == "a");

is_symmetric is_asymmetric

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

Source

1":is_symmetric   (M) => 1 if M is a symmetric relation, -1 if asymmetric,";
2"                       0 otherwise.";
3":is_asymmetric does the same, but with 1 and -1 reversed.";
4{mat} = args;
5if (!this:is_square(mat))
6return raise("E_INVMAT", "Invalid Matrix Format");
7endif
8good = bad = 0;
9for m in [1..len = length(mat)]
10for n in [m + 1..len]
11if (mat[m][n] == mat[n][m])
12good = 1;
13else
14bad = 1;
15endif
16endfor
17endfor
18return this:_relation_result(good, bad, verb[4] == "a");

is_transitive is_atransitive

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

Source

1":is_transitive  (M) => 1 if M is a transitive relation, -1 if atransitive,";
2"                       0 otherwise.";
3":is_atransitive does the same, but with 1 and -1 reversed.";
4{mat} = args;
5if (!this:is_square(mat))
6return raise("E_INVMAT", "Invalid Matrix Format");
7endif
8good = bad = 0;
9for m in [1..len = length(mat)]
10for n in [1..len]
11if (mat[m][n])
12for l in [1..len]
13if (mat[n][l])
14if (mat[m][l])
15good = 1;
16else
17bad = 1;
18endif
19endif
20endfor
21endif
22endfor
23endfor
24return this:_relation_result(good, bad, verb[4] == "a");

_relation_result

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

Source

1"Common code for is_reflexive, is_symmetric, and is_transitive.";
2{good, bad, flag} = args;
3if (good && (!bad))
4result = 1;
5elseif ((!good) && bad)
6result = -1;
7else
8result = 0;
9endif
10return flag * result;

is_partial_ordering

Spec this none thisFlags rxdOwner #29Definer #85

Referenced by

none

Source

1":is_partial_ordering(M) => 1 iff M is a reflexive, asymmetric, transitive relation.";
2{mat} = args;
3return ((this:is_asymmetric(mat) == this:is_reflexive(mat)) == this:is_transitive(mat)) == 1;

xyzr_collision

Spec this none thisFlags rxdOwner #361Definer #85

Referenced by

none

Source

1":xyzr_collision({x1,y1,z1,r1},{x2,y2,z2,r2}) => 1|0";
2{a, b} = args;
3{x, y, z} = {b[1] - a[1], b[2] - a[2], b[3] - a[3]};
4dist2 = ((x * x) + (y * y)) + (z * z);
5radsum = a[4] + b[4];
6"spheres collide if squared distance is less than squared radii";
7return dist2 <= (radsum * radsum);

xyz_distance

Spec this none thisFlags rxdOwner #361Definer #85

Referenced by

Source

1":xyz_distance({x1,y1,z1},{x2,y2,z2}) => float dist";
2{a, b} = args;
3{x, y, z} = {b[1] - a[1], b[2] - a[2], b[3] - a[3]};
4return sqrt(tofloat(((x * x) + (y * y)) + (z * z)));

xyz_line

Spec this none thisFlags rxdOwner #361Definer #85

Referenced by

none

Source

1":xyz_line({x1,y1,z1},{x2,y2,z2}) => { {x,y,z}, {x,y,z}, ... }";
2"returns a list of xyz coordinates through which one would travel to get from args[1] to args[2]. i.e. how to get from A to B on an integer grid.";
3"internally, the function uses Bresenham's Line Algorithm.";
4{a, b} = args;
5cursor = a;
6result = {};
7dist = {b[1] - a[1], b[2] - a[2], b[3] - a[3]};
8x_inc = (dist[1] < 0) ? -1 | 1;
9y_inc = (dist[2] < 0) ? -1 | 1;
10z_inc = (dist[3] < 0) ? -1 | 1;
11lmn = {abs(dist[1]), abs(dist[2]), abs(dist[3])};
12dist2 = {2.0 ^ lmn[1], 2.0 ^ lmn[2], 2.0 ^ lmn[3]};
13if ((lmn[1] >= lmn[2]) && (lmn[1] >= lmn[3]))
14err1 = dist2[2] - tofloat(lmn[1]);
15err2 = dist2[3] - tofloat(lmn[1]);
16for i in [1..lmn[1]]
17result = {@result, cursor};
18if (err1 > 0.0)
19cursor[2] = cursor[2] + y_inc;
20err1 = err1 - dist2[1];
21endif
22if (err2 > 0.0)
23cursor[3] = cursor[3] + z_inc;
24err2 = err2 - dist2[1];
25endif
26err1 = err1 + dist2[2];
27err2 = err2 + dist2[3];
28cursor[1] = cursor[1] + x_inc;
29endfor
30elseif ((lmn[2] >= lmn[1]) && (lmn[2] >= lmn[3]))
31err1 = dist2[1] - tofloat(lmn[2]);
32err2 = dist2[3] - tofloat(lmn[2]);
33for i in [1..lmn[2]]
34result = {@result, cursor};
35if (err1 > 0.0)
36cursor[1] = cursor[1] + x_inc;
37err1 = err1 - dist2[2];
38endif
39if (err2 > 0.0)
40cursor[3] = cursor[3] + z_inc;
41err2 = err2 - dist2[2];
42endif
43err1 = err1 + dist2[1];
44err2 = err2 + dist3[2];
45cursor[2] = cursor[2] + y_inc;
46endfor
47else
48err1 = dist2[2] - tofloat(lmn[3]);
49err2 = dist2[1] - tofloat(lmn[3]);
50for i in [1..lmn[3]]
51result = {@result, cursor};
52if (err1 > 0.0)
53cursor[2] = cursor[2] + y_inc;
54err1 = err1 - dist2[3];
55endif
56if (err2 > 0.0)
57cursor[1] = cursor[1] + x_inc;
58err2 = err2 - dist2[3];
59endif
60err1 = err1 + dist2[2];
61err2 = err2 + dist2[1];
62cursor[3] = cursor[3] + z_inc;
63endfor
64endif
65result = {@result, cursor};
66return result;