<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.secondlife.com/w/index.php?action=history&amp;feed=atom&amp;title=Matrix_Functions</id>
	<title>Matrix Functions - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.secondlife.com/w/index.php?action=history&amp;feed=atom&amp;title=Matrix_Functions"/>
	<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Matrix_Functions&amp;action=history"/>
	<updated>2026-06-23T02:56:56Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.42.1</generator>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Matrix_Functions&amp;diff=1198557&amp;oldid=prev</id>
		<title>KyleFlynn Resident at 00:41, 22 December 2015</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Matrix_Functions&amp;diff=1198557&amp;oldid=prev"/>
		<updated>2015-12-22T00:41:55Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 17:41, 21 December 2015&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l1&quot;&gt;Line 1:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;source&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;source &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;lang=&quot;lsl2&quot;&lt;/ins&gt;&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;//&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;//&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;// *******************************************************************************&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;// *******************************************************************************&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>KyleFlynn Resident</name></author>
	</entry>
	<entry>
		<id>https://wiki.secondlife.com/w/index.php?title=Matrix_Functions&amp;diff=1198556&amp;oldid=prev</id>
		<title>KyleFlynn Resident: Created page with &quot;&lt;source&gt; // // ******************************************************************************* // *****************************************************************************...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.secondlife.com/w/index.php?title=Matrix_Functions&amp;diff=1198556&amp;oldid=prev"/>
		<updated>2015-12-22T00:40:43Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;&amp;lt;source&amp;gt; // // ******************************************************************************* // *****************************************************************************...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;source&amp;gt;&lt;br /&gt;
//&lt;br /&gt;
// *******************************************************************************&lt;br /&gt;
// *******************************************************************************&lt;br /&gt;
//&lt;br /&gt;
// Developed by KyleFlynn.&lt;br /&gt;
//&lt;br /&gt;
// This is free and open source code, protected by the GPLv3 license.&lt;br /&gt;
// http://www.gnu.org/licenses/gpl-3.0.html&lt;br /&gt;
// Accepting this code is conditioned upon accepting this license.&lt;br /&gt;
//&lt;br /&gt;
//&lt;br /&gt;
// The following are some core linear algebra functions.&lt;br /&gt;
// They are primarily used to develop and use 3D transformation matrices.&lt;br /&gt;
// Note that ALL matrices herein are assumed to be 3x3 matrices.&lt;br /&gt;
// And all of these 3x3 matrices are assumed to be stored as a 3 element list of vectors.&lt;br /&gt;
// In all cases, the vectors are assumed to be column (not row) vectors.&lt;br /&gt;
//&lt;br /&gt;
// For all purposes herein, rows are numbered 1,2,3 and columns are also numbered 1,2,3 (both 1 based).&lt;br /&gt;
//&lt;br /&gt;
// As a last note, there are certainly faster ways to perform these function.&lt;br /&gt;
// However, the following imposes an excellent organization when performing&lt;br /&gt;
// complex 3D transformations.&lt;br /&gt;
//&lt;br /&gt;
// The available functions are:&lt;br /&gt;
//&lt;br /&gt;
//      list    MakeMatrix(float r1c1, float r1c2, float r1c3, r2c1, ...&lt;br /&gt;
//      float   GetMatrixElement(list m, integer row, integer col)&lt;br /&gt;
//      list    SetMatrixElement(list m, integer row, integer col, float value) // Returns a new matrix with the new element set.&lt;br /&gt;
//      list    MultMatrices(list m1, list m2) &lt;br /&gt;
//      list    DivideMatrices(list m1, list m2)&lt;br /&gt;
//      list    BackDivideMatrices(list m1, list m2) &lt;br /&gt;
//      list    InvertMatrix(list m)&lt;br /&gt;
//      list    TransposeMatrix(list m)  &lt;br /&gt;
//      integer MatrixIsZero(list m) &lt;br /&gt;
//      integer MatrixIsOrthogonal(list m)&lt;br /&gt;
//      integer MatrixIsNormal(list m)&lt;br /&gt;
//&lt;br /&gt;
//      vector  SetVectorElement(vector v, integer row, float value) // Returns a new vector with the new element set.&lt;br /&gt;
//      float   GetVectorElement(vector v, integer row)&lt;br /&gt;
//      list    MatrixFrom3ColVectors(vector v1, vector v2, vector v3) &lt;br /&gt;
//      list    ZeroMatrix()&lt;br /&gt;
//      list    UnitMatrix()&lt;br /&gt;
//      vector  MakeVector(float x, float y, float z)&lt;br /&gt;
//      string  VectorString(vector v)          // For debugging.&lt;br /&gt;
//      string  MatrixString(list m)            // For debugging.&lt;br /&gt;
//&lt;br /&gt;
// *******************************************************************************&lt;br /&gt;
// *******************************************************************************&lt;br /&gt;
//&lt;br /&gt;
&lt;br /&gt;
list MakeMatrix(float r1c1, float r1c2, float r1c3,  &lt;br /&gt;
                float r2c1, float r2c2, float r2c3,  &lt;br /&gt;
                float r3c1, float r3c2, float r3c3) &lt;br /&gt;
{&lt;br /&gt;
    return [&amp;lt;r1c1, r2c1, r3c1&amp;gt;, &amp;lt;r1c2, r2c2, r3c2&amp;gt;, &amp;lt;r1c3, r2c3, r3c3&amp;gt;];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float GetMatrixElement(list m, integer row, integer col)&lt;br /&gt;
{&lt;br /&gt;
    return GetVectorElement(llList2Vector(m, col - 1), row);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
list SetMatrixElement(list m, integer row, integer col, float value) // Returns a new matrix with the new element set.&lt;br /&gt;
{&lt;br /&gt;
    return llListReplaceList(m, [SetVectorElement(llList2Vector(m, col - 1), row, value)], col - 1, col - 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
float GetVectorElement(vector v, integer row)&lt;br /&gt;
{&lt;br /&gt;
         if (row == 1) return v.x;&lt;br /&gt;
    else if (row == 2) return v.y;&lt;br /&gt;
    else if (row == 3) return v.z;&lt;br /&gt;
    //&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
vector SetVectorElement(vector v, integer row, float value) // Returns a new vector with the new element set.&lt;br /&gt;
{&lt;br /&gt;
         if (row == 1) v.x = value;&lt;br /&gt;
    else if (row == 2) v.y = value;&lt;br /&gt;
    else if (row == 3) v.z = value;&lt;br /&gt;
    //&lt;br /&gt;
    return v;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
list ZeroMatrix()&lt;br /&gt;
{&lt;br /&gt;
    return MakeMatrix(0, 0, 0,&lt;br /&gt;
                      0, 0, 0,&lt;br /&gt;
                      0, 0, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
list UnitMatrix()&lt;br /&gt;
{&lt;br /&gt;
    return MakeMatrix(1, 0, 0,&lt;br /&gt;
                      0, 1, 0,&lt;br /&gt;
                      0, 0, 1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
vector MakeVector(float x, float y, float z)&lt;br /&gt;
{&lt;br /&gt;
    return &amp;lt;x, y, z&amp;gt;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
list  MatrixFrom3ColVectors(vector v1, vector v2, vector v3) &lt;br /&gt;
{&lt;br /&gt;
    return [v1, v2, v3];&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
list DivideMatrices(list m1, list m2)&lt;br /&gt;
{&lt;br /&gt;
    // In Matlab, this is equivalent to:     X = m1 / m2;&lt;br /&gt;
    return MultMatrices(m1, InvertMatrix(m2));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
list BackDivideMatrices(list m1, list m2) &lt;br /&gt;
{&lt;br /&gt;
    // In Matlab, this is equivalent to:     X = m1 \ m2;&lt;br /&gt;
    return MultMatrices(InvertMatrix(m1), m2);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
list MultMatrices(list m1, list m2) &lt;br /&gt;
{&lt;br /&gt;
    // A matrix generalization of the vector dot product.&lt;br /&gt;
    // This procedure specifically multiplies 3x3 matrices, and returns a 3x3 matrix.&lt;br /&gt;
    integer r1Ptr;&lt;br /&gt;
    integer c1Ptr;&lt;br /&gt;
    integer c2Ptr;&lt;br /&gt;
    list m3 = ZeroMatrix();&lt;br /&gt;
    //&lt;br /&gt;
    for (r1Ptr = 1; r1Ptr &amp;lt;= 3; r1Ptr++)&lt;br /&gt;
    {    &lt;br /&gt;
        for (c2Ptr = 1; c2Ptr &amp;lt;=3; c2Ptr++)&lt;br /&gt;
        {&lt;br /&gt;
            for (c1Ptr = 1; c1Ptr &amp;lt;=3; c1Ptr++)&lt;br /&gt;
            {&lt;br /&gt;
                // This uses column ptr for row, but that&amp;#039;s okay.&lt;br /&gt;
                m3 = SetMatrixElement(m3, r1Ptr, c2Ptr, GetMatrixElement(m3, r1Ptr, c2Ptr) + GetMatrixElement(m1, r1Ptr, c1Ptr) * GetMatrixElement(m2, c1Ptr, c2Ptr));&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //&lt;br /&gt;
    return m3;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
list InvertMatrix(list m)&lt;br /&gt;
{&lt;br /&gt;
    // Don&amp;#039;t forget that InvertMatrix(m)=TransposeMatrix(m) if m is orthonormal.&lt;br /&gt;
    // And TransposeMatrix(m) would be much faster.&lt;br /&gt;
    //&lt;br /&gt;
    // This ONLY works with 3x3 matrices.&lt;br /&gt;
    integer rPtr;&lt;br /&gt;
    integer cPtr;&lt;br /&gt;
    integer ptr;&lt;br /&gt;
    integer rPtr2;&lt;br /&gt;
    integer cPtr2;&lt;br /&gt;
    float PivotMax;&lt;br /&gt;
    float dNorm;&lt;br /&gt;
    float dSwap;&lt;br /&gt;
    integer swpCnt;&lt;br /&gt;
    //&lt;br /&gt;
    for (ptr = 1; ptr &amp;lt;= 3; ptr++)&lt;br /&gt;
    {&lt;br /&gt;
        // Search max pivot.&lt;br /&gt;
        rPtr2 = ptr;&lt;br /&gt;
        cPtr2 = ptr;&lt;br /&gt;
        PivotMax = 0;&lt;br /&gt;
        for (rPtr = ptr; rPtr &amp;lt;= 3; rPtr++)&lt;br /&gt;
        {&lt;br /&gt;
            for (cPtr = ptr; cPtr &amp;lt;= 3; cPtr++)&lt;br /&gt;
            {            &lt;br /&gt;
                if (llFabs(GetMatrixElement(m, rPtr, cPtr)) &amp;gt; PivotMax)&lt;br /&gt;
                {&lt;br /&gt;
                    rPtr2 = rPtr;&lt;br /&gt;
                    cPtr2 = cPtr;&lt;br /&gt;
                    PivotMax = llFabs(GetMatrixElement(m, rPtr, cPtr));&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        // Swap rows and columns.&lt;br /&gt;
        if (rPtr2 &amp;gt; ptr)&lt;br /&gt;
        {&lt;br /&gt;
            // Swap row.&lt;br /&gt;
            for (cPtr = 1; cPtr &amp;lt;= 3; cPtr++)&lt;br /&gt;
            {&lt;br /&gt;
                dSwap = GetMatrixElement(m, rPtr2, cPtr);&lt;br /&gt;
                m = SetMatrixElement(m, rPtr2, cPtr, GetMatrixElement(m, ptr, cPtr));&lt;br /&gt;
                m = SetMatrixElement(m, ptr, cPtr, dSwap);&lt;br /&gt;
            }&lt;br /&gt;
            swpCnt++;&lt;br /&gt;
            SetSwapDiag(swpCnt, 1, ptr);&lt;br /&gt;
            SetSwapDiag(swpCnt, 2, rPtr2);&lt;br /&gt;
            SetSwapDiag(swpCnt, 3, 1);&lt;br /&gt;
        }&lt;br /&gt;
        if (cPtr2 &amp;gt; ptr)&lt;br /&gt;
        {&lt;br /&gt;
            // Swap column.&lt;br /&gt;
            for (rPtr = 1; rPtr &amp;lt;= 3; rPtr++)&lt;br /&gt;
            {&lt;br /&gt;
                dSwap = GetMatrixElement(m, rPtr, cPtr2);&lt;br /&gt;
                m = SetMatrixElement(m, rPtr, cPtr2, GetMatrixElement(m, rPtr, ptr));&lt;br /&gt;
                m = SetMatrixElement(m, rPtr, ptr, dSwap);&lt;br /&gt;
            }&lt;br /&gt;
            swpCnt++;&lt;br /&gt;
            SetSwapDiag(swpCnt, 1, ptr);&lt;br /&gt;
            SetSwapDiag(swpCnt, 2, cPtr2);&lt;br /&gt;
            SetSwapDiag(swpCnt, 3, 2);&lt;br /&gt;
        }&lt;br /&gt;
        //&lt;br /&gt;
        // Check pivot 0.&lt;br /&gt;
        if (llFabs(GetMatrixElement(m, ptr, ptr)) &amp;lt;= 0)&lt;br /&gt;
        {&lt;br /&gt;
            llSay(DEBUG_CHANNEL, &amp;quot;Matrix inversion error, script is stopped.&amp;quot;);&lt;br /&gt;
            rPtr = 1 / 0; // Crash the script.&lt;br /&gt;
        }&lt;br /&gt;
        //&lt;br /&gt;
        // Normalization.&lt;br /&gt;
        dNorm = GetMatrixElement(m, ptr, ptr);&lt;br /&gt;
        m = SetMatrixElement(m, ptr, ptr, 1);&lt;br /&gt;
        for (cPtr = 1; cPtr &amp;lt;= 3; cPtr++)&lt;br /&gt;
        {&lt;br /&gt;
            m = SetMatrixElement(m, ptr, cPtr, GetMatrixElement(m, ptr, cPtr) / dNorm);&lt;br /&gt;
        }&lt;br /&gt;
        // Linear reduction.&lt;br /&gt;
        for (rPtr = 1; rPtr &amp;lt;= 3; rPtr++)&lt;br /&gt;
        {&lt;br /&gt;
            if (rPtr != ptr &amp;amp;&amp;amp; GetMatrixElement(m, rPtr, ptr) != 0)&lt;br /&gt;
            {&lt;br /&gt;
                dNorm = GetMatrixElement(m, rPtr, ptr);&lt;br /&gt;
                m = SetMatrixElement(m, rPtr, ptr, 0);&lt;br /&gt;
                for (cPtr = 1; cPtr &amp;lt;= 3; cPtr++)&lt;br /&gt;
                {&lt;br /&gt;
                    m = SetMatrixElement(m, rPtr, cPtr, GetMatrixElement(m, rPtr, cPtr) - dNorm * GetMatrixElement(m, ptr, cPtr));&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //&lt;br /&gt;
    // Un-Scramble rows.&lt;br /&gt;
    for (ptr = swpCnt; ptr &amp;gt;= 1; ptr--)&lt;br /&gt;
    {&lt;br /&gt;
        if (GetSwapDiag(ptr, 3) == 1)&lt;br /&gt;
        {&lt;br /&gt;
            // Swap column.&lt;br /&gt;
            for (rPtr = 1; rPtr &amp;lt;=3; rPtr++)&lt;br /&gt;
            {&lt;br /&gt;
                dSwap = GetMatrixElement(m, rPtr, GetSwapDiag(ptr, 2));&lt;br /&gt;
                m = SetMatrixElement(m, rPtr, GetSwapDiag(ptr, 2), GetMatrixElement(m, rPtr, GetSwapDiag(ptr, 1)));&lt;br /&gt;
                m = SetMatrixElement(m, rPtr, GetSwapDiag(ptr, 1), dSwap);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        else if (GetSwapDiag(ptr, 3) == 2)&lt;br /&gt;
        {&lt;br /&gt;
            // Swap row.&lt;br /&gt;
            for (cPtr = 1; cPtr &amp;lt;= 3; cPtr++)&lt;br /&gt;
            {&lt;br /&gt;
                dSwap = GetMatrixElement(m, GetSwapDiag(ptr, 2), cPtr);&lt;br /&gt;
                m = SetMatrixElement(m, GetSwapDiag(ptr, 2), cPtr, GetMatrixElement(m, GetSwapDiag(ptr, 1), cPtr));&lt;br /&gt;
                m = SetMatrixElement(m, GetSwapDiag(ptr, 1), cPtr, dSwap);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //&lt;br /&gt;
    return m;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
list TransposeMatrix(list m)  &lt;br /&gt;
{&lt;br /&gt;
    list m2 = ZeroMatrix();&lt;br /&gt;
    //&lt;br /&gt;
    m2 = SetMatrixElement(m2, 1, 2, GetMatrixElement(m, 2, 1));&lt;br /&gt;
    m2 = SetMatrixElement(m2, 1, 3, GetMatrixElement(m, 3, 1));&lt;br /&gt;
    m2 = SetMatrixElement(m2, 2, 1, GetMatrixElement(m, 1, 2));&lt;br /&gt;
    m2 = SetMatrixElement(m2, 2, 3, GetMatrixElement(m, 3, 2));&lt;br /&gt;
    m2 = SetMatrixElement(m2, 3, 1, GetMatrixElement(m, 1, 3));&lt;br /&gt;
    m2 = SetMatrixElement(m2, 3, 2, GetMatrixElement(m, 2, 3));&lt;br /&gt;
    //&lt;br /&gt;
    // Don&amp;#039;t need to transpose the diagonal elements.&lt;br /&gt;
    m2 = SetMatrixElement(m2, 1, 1, GetMatrixElement(m, 1, 1));&lt;br /&gt;
    m2 = SetMatrixElement(m2, 2, 2, GetMatrixElement(m, 2, 2));&lt;br /&gt;
    m2 = SetMatrixElement(m2, 3, 3, GetMatrixElement(m, 3, 3));&lt;br /&gt;
    //&lt;br /&gt;
    return m2;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
integer MatrixIsZero(list m) &lt;br /&gt;
{&lt;br /&gt;
    return (GetMatrixElement(m, 1, 1) == 0 &amp;amp;&amp;amp; GetMatrixElement(m, 2, 1) == 0 &amp;amp;&amp;amp; GetMatrixElement(m, 3, 1) == 0 &amp;amp;&amp;amp; &lt;br /&gt;
            GetMatrixElement(m, 1, 2) == 0 &amp;amp;&amp;amp; GetMatrixElement(m, 2, 2) == 0 &amp;amp;&amp;amp; GetMatrixElement(m, 3, 2) == 0 &amp;amp;&amp;amp; &lt;br /&gt;
            GetMatrixElement(m, 1, 3) == 0 &amp;amp;&amp;amp; GetMatrixElement(m, 2, 3) == 0 &amp;amp;&amp;amp; GetMatrixElement(m, 3, 3) == 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
integer MatrixIsOrthogonal(list m)&lt;br /&gt;
{&lt;br /&gt;
    float epsilon = .00002; // Our allowed tolerance.&lt;br /&gt;
    //&lt;br /&gt;
    vector v1 = llList2Vector(m, 0);&lt;br /&gt;
    vector v2 = llList2Vector(m, 1);&lt;br /&gt;
    vector v3 = llList2Vector(m, 2);&lt;br /&gt;
    //&lt;br /&gt;
    return llFabs(llFabs(llRot2Angle(llRotBetween(v1, v2))) - 90) &amp;lt; epsilon &amp;amp;&amp;amp;&lt;br /&gt;
           llFabs(llFabs(llRot2Angle(llRotBetween(v1, v3))) - 90) &amp;lt; epsilon &amp;amp;&amp;amp;&lt;br /&gt;
           llFabs(llFabs(llRot2Angle(llRotBetween(v2, v3))) - 90) &amp;lt; epsilon;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
integer MatrixIsNormal(list m)&lt;br /&gt;
{&lt;br /&gt;
    float epsilon = .00002; // Our allowed tolerance.&lt;br /&gt;
    //&lt;br /&gt;
    vector v1 = llList2Vector(m, 0);&lt;br /&gt;
    vector v2 = llList2Vector(m, 1);&lt;br /&gt;
    vector v3 = llList2Vector(m, 2);&lt;br /&gt;
    //&lt;br /&gt;
    return llFabs(v1.x * v1.x + v1.y * v1.y + v1.z * v1.z - 1) &amp;lt; epsilon &amp;amp;&amp;amp;&lt;br /&gt;
           llFabs(v2.x * v2.x + v2.y * v2.y + v2.z * v2.z - 1) &amp;lt; epsilon &amp;amp;&amp;amp;&lt;br /&gt;
           llFabs(v3.x * v3.x + v3.y * v3.y + v3.z * v3.z - 1) &amp;lt; epsilon;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
string VectorString(vector v)  &lt;br /&gt;
// Primarily used for debugging purposes.&lt;br /&gt;
{&lt;br /&gt;
    return &amp;quot;[ &amp;quot; + Float2StringFormat(v.x, 5, TRUE) + &amp;quot;, &amp;quot; + Float2StringFormat(v.y, 5, TRUE) + &amp;quot;, &amp;quot; + Float2StringFormat(v.z, 5, TRUE) + &amp;quot; ]&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
string MatrixString(list m)&lt;br /&gt;
// Primarily used for debugging purposes.&lt;br /&gt;
{&lt;br /&gt;
    return &amp;quot;\n[ &amp;quot; + Float2StringFormat(GetMatrixElement(m, 1, 1), 5, TRUE) + &amp;quot;, &amp;quot; + Float2StringFormat(GetMatrixElement(m, 1, 2), 5, TRUE) + &amp;quot;, &amp;quot; + Float2StringFormat(GetMatrixElement(m, 1, 3), 5, TRUE) + &amp;quot; ;&amp;quot; + &amp;quot;\n&amp;quot; + &lt;br /&gt;
             &amp;quot;  &amp;quot; + Float2StringFormat(GetMatrixElement(m, 2, 1), 5, TRUE) + &amp;quot;, &amp;quot; + Float2StringFormat(GetMatrixElement(m, 2, 2), 5, TRUE) + &amp;quot;, &amp;quot; + Float2StringFormat(GetMatrixElement(m, 2, 3), 5, TRUE) + &amp;quot; ;&amp;quot; + &amp;quot;\n&amp;quot; + &lt;br /&gt;
             &amp;quot;  &amp;quot; + Float2StringFormat(GetMatrixElement(m, 3, 1), 5, TRUE) + &amp;quot;, &amp;quot; + Float2StringFormat(GetMatrixElement(m, 3, 2), 5, TRUE) + &amp;quot;, &amp;quot; + Float2StringFormat(GetMatrixElement(m, 3, 3), 5, TRUE) + &amp;quot; ]&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
string Float2StringFormat(float num, integer places, integer rnd) &lt;br /&gt;
// Allows string output of a float in a tidy text format.&lt;br /&gt;
// rnd (rounding) should be set to TRUE for rounding, FALSE for no rounding&lt;br /&gt;
{ &lt;br /&gt;
    if (rnd) &lt;br /&gt;
    {&lt;br /&gt;
        float f = llPow(10.0, places);&lt;br /&gt;
        integer i = llRound(llFabs(num) * f);&lt;br /&gt;
        string s = &amp;quot;00000&amp;quot; + (string)i; // Number of 0s is (value of max places - 1).&lt;br /&gt;
        if (num &amp;lt; 0.0) return &amp;quot;-&amp;quot; + (string)( (integer)(i / f) ) + &amp;quot;.&amp;quot; + llGetSubString(s, -places, -1);&lt;br /&gt;
        return (string)((integer)(i / f)) + &amp;quot;.&amp;quot; + llGetSubString(s, -places, -1);&lt;br /&gt;
    }&lt;br /&gt;
    if (!places) return (string)((integer)num );&lt;br /&gt;
    if ((places = (places - 7 - (places &amp;lt; 1))) &amp;amp; 0x80000000) return llGetSubString((string)num, 0, places);&lt;br /&gt;
    return (string)num;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// These globals are just used in SetSwapDiag &amp;amp; GetSwapDiag, which are used only in InvertMatrix.&lt;br /&gt;
// They emulate a 6x3 array of integers.&lt;br /&gt;
integer iSwapDiag11;&lt;br /&gt;
integer iSwapDiag21;&lt;br /&gt;
integer iSwapDiag31;&lt;br /&gt;
integer iSwapDiag41;&lt;br /&gt;
integer iSwapDiag51;&lt;br /&gt;
integer iSwapDiag61;&lt;br /&gt;
integer iSwapDiag12;&lt;br /&gt;
integer iSwapDiag22;&lt;br /&gt;
integer iSwapDiag32;&lt;br /&gt;
integer iSwapDiag42;&lt;br /&gt;
integer iSwapDiag52;&lt;br /&gt;
integer iSwapDiag62;&lt;br /&gt;
integer iSwapDiag13;&lt;br /&gt;
integer iSwapDiag23;&lt;br /&gt;
integer iSwapDiag33;&lt;br /&gt;
integer iSwapDiag43;&lt;br /&gt;
integer iSwapDiag53;&lt;br /&gt;
integer iSwapDiag63;&lt;br /&gt;
//&lt;br /&gt;
&lt;br /&gt;
SetSwapDiag(integer i, integer j, integer value)&lt;br /&gt;
// Just used for the InvertMatrix function.&lt;br /&gt;
{&lt;br /&gt;
         if (i == 1) &lt;br /&gt;
    { &lt;br /&gt;
             if (j == 1) iSwapDiag11 = value;&lt;br /&gt;
        else if (j == 2) iSwapDiag12 = value;&lt;br /&gt;
        else if (j == 3) iSwapDiag13 = value;&lt;br /&gt;
    }&lt;br /&gt;
    else if (i == 2)&lt;br /&gt;
    {&lt;br /&gt;
             if (j == 1) iSwapDiag21 = value;&lt;br /&gt;
        else if (j == 2) iSwapDiag22 = value;&lt;br /&gt;
        else if (j == 3) iSwapDiag23 = value;&lt;br /&gt;
    }&lt;br /&gt;
    else if (i == 3)&lt;br /&gt;
    {&lt;br /&gt;
             if (j == 1) iSwapDiag31 = value;&lt;br /&gt;
        else if (j == 2) iSwapDiag32 = value;&lt;br /&gt;
        else if (j == 3) iSwapDiag33 = value;&lt;br /&gt;
    }&lt;br /&gt;
    else if (i == 4)&lt;br /&gt;
    {&lt;br /&gt;
             if (j == 1) iSwapDiag41 = value;&lt;br /&gt;
        else if (j == 2) iSwapDiag42 = value;&lt;br /&gt;
        else if (j == 3) iSwapDiag43 = value;&lt;br /&gt;
    }&lt;br /&gt;
    else if (i == 5)&lt;br /&gt;
    {&lt;br /&gt;
             if (j == 1) iSwapDiag51 = value;&lt;br /&gt;
        else if (j == 2) iSwapDiag52 = value;&lt;br /&gt;
        else if (j == 3) iSwapDiag53 = value;&lt;br /&gt;
    }&lt;br /&gt;
    else if (i == 6)&lt;br /&gt;
    {&lt;br /&gt;
             if (j == 1) iSwapDiag61 = value;&lt;br /&gt;
        else if (j == 2) iSwapDiag62 = value;&lt;br /&gt;
        else if (j == 3) iSwapDiag63 = value;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
integer GetSwapDiag(integer i, integer j)&lt;br /&gt;
// Just used for the InvertMatrix function.&lt;br /&gt;
{&lt;br /&gt;
    integer i1;&lt;br /&gt;
    integer i2;&lt;br /&gt;
    integer i3;&lt;br /&gt;
    //&lt;br /&gt;
         if (i == 1) { i1 = iSwapDiag11; i2 = iSwapDiag12; i3 = iSwapDiag13; }&lt;br /&gt;
    else if (i == 2) { i1 = iSwapDiag21; i2 = iSwapDiag22; i3 = iSwapDiag23; }&lt;br /&gt;
    else if (i == 3) { i1 = iSwapDiag31; i2 = iSwapDiag32; i3 = iSwapDiag33; }&lt;br /&gt;
    else if (i == 4) { i1 = iSwapDiag41; i2 = iSwapDiag42; i3 = iSwapDiag43; }&lt;br /&gt;
    else if (i == 5) { i1 = iSwapDiag51; i2 = iSwapDiag52; i3 = iSwapDiag53; }&lt;br /&gt;
    else if (i == 6) { i1 = iSwapDiag61; i2 = iSwapDiag62; i3 = iSwapDiag63; }&lt;br /&gt;
    //&lt;br /&gt;
         if (j == 1) return i1;&lt;br /&gt;
    else if (j == 2) return i2;&lt;br /&gt;
    else if (j == 3) return i3;&lt;br /&gt;
    return 0; // Needed for compiler.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    on_rez(integer iStartParam)&lt;br /&gt;
    {&lt;br /&gt;
        llResetScript();&lt;br /&gt;
    }&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
    &lt;br /&gt;
        list m1;&lt;br /&gt;
        list m2;&lt;br /&gt;
        list m3;&lt;br /&gt;
        list m4;&lt;br /&gt;
        //&lt;br /&gt;
        m1 = MakeMatrix(1,2,3,4,5,6,7,8,9);&lt;br /&gt;
        m2 = MakeMatrix(2.2, 3.3, 4.4, &lt;br /&gt;
                        5.5, 6.6, 5.5, &lt;br /&gt;
                        4.4, 3.2, 2.1);&lt;br /&gt;
        m3 = MultMatrices(m1, m2);&lt;br /&gt;
        llSay(0, MatrixString(m3));&lt;br /&gt;
        &lt;br /&gt;
        m4 = DivideMatrices(m3, m2);&lt;br /&gt;
        llSay(0, MatrixString(m4)); // m4 should take us back to m1.&lt;br /&gt;
        &lt;br /&gt;
        // With the above, the MultMatrices and DivideMatrices functions are tested, &lt;br /&gt;
        // along with InvertMatrix via divide.  This is the core of these procedures.&lt;br /&gt;
        &lt;br /&gt;
        &lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    }&lt;br /&gt;
    touch_start(integer iNumDetected)&lt;br /&gt;
    {&lt;br /&gt;
    }&lt;br /&gt;
    timer()&lt;br /&gt;
    {&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>KyleFlynn Resident</name></author>
	</entry>
</feed>