Code

inverse_matrix_calculator.lsl
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2011 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
// returns S = input \ delete
list wasSubtractSubList(list input, list delete) {
    do {
        string tok = llList2String(delete, 0);
        list clean = input;
        do {
            if(llList2String(clean, 0) == tok) {
                integer idx = llListFindList(input, (list)tok);
                input = llDeleteSubList(input, idx, idx);
            }
        } while(clean = llDeleteSubList(clean, 0, 0));
    } while(delete = llDeleteSubList(delete, 0, 0));
    return input;
}
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2011 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
// transposes a square matrix of ord columns
list wasMatrixTranspose(list matrix, integer ord) {
    list result = [];
    integer mLength = llGetListLength(matrix);
    integer j = 0;
    do {
        integer i = j;
        do {
            result += llList2String(matrix, i);
            i += ord;
        } while(i<mLength);
    } while(++j<ord);
    return result;
}
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2011 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
// returns the unsigned cofactor of matrix m with ord 
// columns with the pivot r, respectively c.
list wasMatrixCofactor(list m, integer r, integer c, integer ord) {
    integer idx = 0;
    integer i = 0;
    do {
        integer j = 0;
        do {
            if(i == r || j == c) m = llListReplaceList(m, (list)" ", idx, idx);
            ++idx;
        } while(++j<ord);
    } while(++i<ord);
    return wasSubtractSubList(m, [" "]);
}
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2011 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
// calulates the determinant of a matrix m with ord 
// columns.
float wasDeterminant(list m, integer ord) {
    float result = 0;
    integer i = 0;
    integer o = -1;
    do {
        //i * cof (i) - i * cof(i) + i * cof(i) - ...
        list cof = wasMatrixCofactor(m, 0, i, ord);
        if(llGetListLength(cof) == 2) {
            if(o = ~o) {
                result -= llList2Float(m, i) * llList2Float(cof, 0);
                jump next;
            }
            result += llList2Float(m, i) * llList2Float(cof, 0);
            jump next;
        }
        if(llGetListLength(cof) == 0) return llList2Float(m, i);
        if(o = ~o) {
            result -=  llList2Float(m, i) * wasDeterminant(cof, ord-1);
            jump next;
        }
        result +=  llList2Float(m, i) * wasDeterminant(cof, ord-1);
@next;
    } while(++i<ord);
    return result;
}
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2011 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
list wasMatrixAdjugate(list m, integer ord) {
    list result = [];
    integer i = 0;
    do {
        integer j = 0;
        integer o = -1;
        if(i % 2 == 0) jump compute;
        o = 0;
@compute;
        do {
            list cof = wasMatrixCofactor(m, i, j, ord);
            if(o = ~o) {
                result += -wasDeterminant(cof, ord-1);
                jump next;
            }
            result += wasDeterminant(cof, ord-1);      
@next;
        } while(++j<ord);
    } while(++i<ord);
    return wasMatrixTranspose(result, ord);
}
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2011 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
// returns the inverse of an matrix m with adjugate
// adjugate and determinant determinant.
list wasMatrixInverse(list adjugate, float determinant) {
    // assert(determinant) != 0
    if(llGetListLength(adjugate) == 0) return [];
    float e = llList2Float(adjugate, 0);
    adjugate = llDeleteSubList(adjugate, 0, 0);
    return e/determinant + wasMatrixInverse(adjugate, determinant);
}
 
key nQuery = NULL_KEY;
integer nLine = 0;
list matrix = [];
integer columns = 0;
//pragma inline
string nName = "";
 
default {
    state_entry() {
        integer itra = llGetInventoryNumber(INVENTORY_NOTECARD);
        if(itra >0) jump found_notecard;
        llSetText("Drop a matrix inside me!", <0,1,0>, 1);
        return;
@found_notecard;
        llSetText("Reading notecard...\nPlease wait...", <1,1,0>, 1);
        nName = llGetInventoryName(INVENTORY_NOTECARD, 0);
        nQuery = llGetNotecardLine(nName, nLine);
    }
 
    dataserver(key id, string data) {
        if(id != nQuery) return;
        if(data == EOF) {
            llSetText("Touch to compute!", <0,1,0>, 1);
            llRemoveInventory(nName);
            return;
        }
        if(data == "") jump next_line;
        list input = llParseString2List(data, [" "], []);
        matrix += input;
        columns = llGetListLength(input);
@next_line;
        nQuery = llGetNotecardLine(nName, ++nLine);
    }
 
    touch_start(integer num) {
        if(llGetListLength(matrix) == 0) return;
        state compute;
    }
 
    changed(integer change) {
        if(change & CHANGED_INVENTORY) llResetScript();
    }
    on_rez(integer num) {
        llResetScript();
    }
}
 
state compute  {
    state_entry() {
        llMessageLinked(LINK_THIS, 0, "start", NULL_KEY);
        llShout(0, "-------------------------------");
        float det_m = wasDeterminant(matrix, columns);
        llShout(0, "Determinant is: " + (string)det_m);
        list adjugate_m = wasMatrixAdjugate(matrix, columns);
        llShout(0, "Adjugate is: " + llDumpList2String(adjugate_m, " "));
        list inverse_m = wasMatrixInverse(adjugate_m, det_m);
        llShout(0, "Inverse matrix is: " + llDumpList2String(inverse_m, " "));
        llShout(0, "-------------------------------");
        llMessageLinked(LINK_THIS, 0, "stop", NULL_KEY);
        state default;
    }
    changed(integer change) {
        if(change & CHANGED_INVENTORY) llResetScript();
    }
}