+ Reply to Thread
Page 1 of 2 1 2 LastLast
Results 1 to 15 of 20

Thread: Introducing LibLinAlg: Matrix Heaven

  1. #1
    Shadowlander Olandria's Avatar
    Join Date
    Jul 2011
    Posts
    34

    Default Introducing LibLinAlg: Matrix Heaven

    LibLinAlg
    http://rift.curseforge.com/addons/liblinalg/

    Classes
    • LibLinAlg.genMat(n, m, toZero)
    The superclass. Takes on input n and m, and generates an n x m matrix. If toZero is set to false, all elements will be initialized to nil, else they will be zero. Contains limited support as contained elements are assumed to be of any type.
    • LibLinAlg.genVec(n, toZero)
    Typedef for LinLinAlg.genMat(n, 1, toZero). Added to imporve readability and transparency.
    • LibLinAlg.strMat(n, m, blank)
    Constructor works the same way as for the genMat class. Assumes all contained elements to be strings, hence it offers special support for string manipulation such as autogeneration of strings based on indexes (see LibLinAlg.strMat.quickFill()). If blank is set to true, all elements will be initialized to empty strings.
    • LibLinAlg.strVec(n, blank)
    Typedef for LinLinAlg.strMat(n, 1, blank). Added to increase readability and transparency.
    • LibLinAlg.numMat(n, m, toZero)
    Constructor works the same way as for the genMat class. Assumes all elements to be numbers, and hence offers special support for these. Contains the most used functionality from linear algebra.
    • LibLinAlg.numRowVec(n, toZero)
    Typedef for LibLinAlg.numMat(n, 1, toZero).
    • LibLinAlg.numRowVec(m, toZero)
    Typedef for LibLinAlg.numMat(1, m, toZero).

    Example of basic usage:
    Code:
    LLA = Library.LibLinAlg
    A = LLA.genMat(2, 2) --Initialize a 2x2 matrix
    
    A.at[1][2] = 5 --Set element 1, 2 equal to 5
    
    A.at[1][1] = A(1, 2) --Supports clean indicing. Does not work on assigment.
    
    print(A(1,1))
    >5
    Last edited by Olandria; 08-02-2013 at 01:19 PM.
    "To those who do not know mathematics it is difficult to get across a real feeling as to the beauty, the deepest beauty, of nature."
    ― Richard P. Feynman

  2. #2
    Shadowlander Olandria's Avatar
    Join Date
    Jul 2011
    Posts
    34

    Default

    Member Functions

    LibLinAlg.genMat
    • .setSize(n, m, toZero, keepMem)
    Sets the size of the matrix to n x m. This is the only way to change the shape. If toZero is false, elements will be initialized to nil. If keepMem is false, the original matrix elements will be overwritten.
    • .getShape()
    Returns the shape of the matrix.
    • .fill(value)
    Sets every matrix element to the given value. Can be any object, but be aware of references if an object is passed.
    • .copy()
    Returns a deep copy of the matrix.
    • .dump()
    Sends a string containing a clean printout of the matrix to stdout.
    • .transpose()
    Returns the transposed matrix, i.e. flips the matrix across it's diagonal such that A(i,j) -> A(j, i).
    • .foreach(sendIndices, f, ...)
    Applies the function f with parameters ... to every matrix element. If sendIndices is true, the first two arguments passed to f will be i and j, i.e. the matrix indices.
    Special operators
    • Equivalence
    Allows usage like e.g. A == B. True if all the elements match, else false.
    • Easy Access
    Allows for elements to accessed like e.g. A(1,2). Does not work on assigment. Equivalent to A.at[1][2].
    • Matrix Concatination
    Allows usage like e.g. C = A .. B, where the result will be a matrix where the columns of B have been added to the columns of A.
    Example of usage:
    Code:
    LLA = Library.LibLinAlg
    --Create two matrices of size 2x2 and 2x3
    A = LLA.genMat(2,2)
    B = LLA.genMat(2,3)
    n, m = A.getShape() --Extract 2 and 2 from A
    
    --Fill A with only 2s and B with only 3s
    A.fill(2); B.fill(3)
    
    --Dump the result to stdout
    A.dump(); B.dump()
    
    > [genMat 2x2]
    > 2       2 |
    > 2       2 |
    > [genMat 2x3]
    > 3       3       3 |
    > 3       3       3 |
    
    --Generate the 2 x 5 concatenated matrix
    C = A .. B ; C.dump()
    
    > [genMat 2x5]
    > 2       2       3       3       3 |
    > 2       2       3       3       3 |
    
    --Get the transposed matrix
    C = C.transpose(); C.dump()
    
    > [genMat 5x2]
    > 2       2 |
    > 2       2 |
    > 3       3 |
    > 3       3 |
    > 3       3 |
    
    --Resize C to a 3x2 matrix, keeping the available memory
    C.setSize(3, 2); C.dump()
    
    > [genMat 3x2]
    > 2       2 |
    > 2       2 |
    > 3       3 |
    
    --Make a deep copy of A and set it to B
    B = A.copy()
    
    --Test is the matrices are equal
    print(A == B)
    > true
    
    --Using foreach to apply a string operator on every element
    B.fill("hey!")
    
    B.foreach(true, functon(i, j) return string.upper(B(i, j)) end)
    B.dump()
    
    > [genMat 3x2]
    > HEY!    HEY! |
    > HEY!    HEY! |
    > HEY!    HEY! |
    "To those who do not know mathematics it is difficult to get across a real feeling as to the beauty, the deepest beauty, of nature."
    ― Richard P. Feynman

  3. #3
    Shadowlander Olandria's Avatar
    Join Date
    Jul 2011
    Posts
    34

    Default

    LibLinAlg.strMat
    • .blank()
    Sets all the matrix elements to empty strings.
    • .quickFill(expr, xOffset, yOffset)
    Takes a pattern as first input and replaces every occurance of "$i" with the first index + xOffset, and "$j" with the second index + yOffset. Giving e.g. "group$i$j" with xOffset = yOffset = -1 results in the standard group setup matrix.
    Special operators
    • Addition
    Adding two strMat objects result in a new matrix whose elements are the concatenated strings of the added matrices (the concatination operator ".." is defined in the superclass and applies standard matrix column concatination).
    Example of usage:
    Introducing LibLinAlg: Matrix Heaven-strmat.jpg

    Disclaimers:

    It is important to note that this is a bit messy to do with the core functionality. More conveinient syntax such as "range" etc. will be implemented later.*

    Please note that using the .foreach method, all string-manipulation operations can be applied easily to the entire matrix.
    "To those who do not know mathematics it is difficult to get across a real feeling as to the beauty, the deepest beauty, of nature."
    ― Richard P. Feynman

  4. #4
    Shadowlander Olandria's Avatar
    Join Date
    Jul 2011
    Posts
    34

    Default

    LibLinAlg.numMat
    • .zeros()
    Sets every element to zero.
    • .ones()
    Sets every element to one.
    • .eye()
    Sets every element to zero, except the diagonal which is set to one. For non-quadratic matrices, the diagonal is defined as the diagonal of the upper left n x n sub-matrix. Known as the identity matrix.
    • .scalarAdd(C)
    Adds 'C' to every element in the matrix.
    • .scalarMult(C)
    Multiplies every matrix element by 'C'.
    Special operators
    • Addition
    Standard matrix addition. Returns a matrix whose elements are the sum of each of the matrices' elements.
    • Multiplication
    Standard matrix multiplication. Returns a matrix whose element i, j is the dot product of row i in the left-hand matrix with column j of the right-hand matrix.
    • Negation
    Flips the sign of all elements on assignment. Does not alter the original matrix.
    • Subtraction
    Subtracting matrices work.
    • Elementwize Multiplication
    Accesible through the mod function, elementwize multiplication means that the multiplication is done element by element, such that the resulting element is equal to the product of the corresponding matrix elements in the multiplied matrices.
    Example usage:
    Introducing LibLinAlg: Matrix Heaven-nummat.jpg
    "To those who do not know mathematics it is difficult to get across a real feeling as to the beauty, the deepest beauty, of nature."
    ― Richard P. Feynman

  5. #5
    Shadowlander Olandria's Avatar
    Join Date
    Jul 2011
    Posts
    34

    Default

    Latest changelog:

    Pretty version: https://github.com/jorgehog/LibLinAl.../Changelog.txt


    ************************************************** ************************************************** **********
    Versions ending with an odd number are unstable releases not tested (will be the case for all alpha versions).
    Version iteration at the first decimal index implies minor additions.
    Version iteration with whole numbers indicates major changes since the previous whole number change.
    ************************************************** ************************************************** **********


    ---------- Changed from 0.01 to 0.11

    * LibLinAlg is now licensed under GNU GPL v3

    * Added assertion statements to improve feedback to users.

    * Changed the class member names in the following manner:
    genMat -> Matrix
    strMat -> StringMatrix
    numMat -> MathMatrix

    * Removed using concatenation operator ".." for joining columns of matrices. This functionality is now
    available through the joinColumns method.
    * Added joinRows method.

    * Added __tostring overloading such that printing matrices directly works.

    * Matrices can be initialized directly from Lua standard tables.
    - if the table is 1D with length n, the result will be a 1 x n matrix. Post transposing will yield a column vector.
    - if the table is 2D with size n x m, the result will be a n x m matrix.

    * The following additional functionality has been implemented:
    - popColumn(i) : Removes column i from the matrix and returns it as a table.
    - popRow(i) : Same as for a column but for a row.
    - swapColumns(i, j) : Swaps the location of column i and column j in the matrix.
    - swapRows(i, j) : Same as for columns but for rows.
    - insertColumns(A, i) : Inserts the columns of matrix A into the current matrix, starting from column index i.
    - insertRows(A, i) : Same as for columns only for rows.
    - splitMatrixColumns(i) : Splits the matrix into two parts at column index i. The right split will contain column i.
    - splitMatrixRows(i) : Same as for columns only for rows.

    * Internal functions only available to developers:
    - _getNewMat() : Will return the class of the current object,
    such that A = self._getNewMat()(self.getShape()) is equal to self.
    - isMatrix : A brute force flag used to distinguish LibLinAlg instances from other tables.
    - setMatrixFromTable(t) : Given a table t, the matrix is altered to represent the table data.
    - getElementsAsTable(c) : Returns a table containing all the elements of the matrix. Rowwise if not 'c' is set to true.

    ----------
    Last edited by Olandria; 08-02-2013 at 01:22 PM.
    "To those who do not know mathematics it is difficult to get across a real feeling as to the beauty, the deepest beauty, of nature."
    ― Richard P. Feynman

  6. #6
    Shadowlander Olandria's Avatar
    Join Date
    Jul 2011
    Posts
    34

    Default

    Guys, this is the very prototype built to show the basic interface and the basic idea of the library. Additional functionality which makes creating different templates of matrices will be implemented later.

    I've never released a library before. Any help with getting the source files online would be much appreciated. If you are interested in them right away, send me a PM!

    Let me know what you think
    "To those who do not know mathematics it is difficult to get across a real feeling as to the beauty, the deepest beauty, of nature."
    ― Richard P. Feynman

  7. #7
    Shield of Telara Adelea's Avatar
    Join Date
    Mar 2011
    Posts
    734

    Default

    I almost wish I had a use for this! =)
    http://forums.riftgame.com/image.php?type=sigpic&userid=125779&dateline=13553  38065

  8. #8
    Shadowlander Olandria's Avatar
    Join Date
    Jul 2011
    Posts
    34

    Default

    Heh, well, who knows?

    The idea for creating it came from some work I did with Euler angles (a previous post asking for help). The person asking wasn't all that familiar with applying transformations etc etc., so I helped him out a little. So I built some functions to do matrix multiplications and so on.

    I make a habit out of libraryizing any general functionality I'm working on, just for the sake that next time someone needs transformations, they can google the shape of the matrix and simply use a library for all the 'don't need to know mathematical details'
    "To those who do not know mathematics it is difficult to get across a real feeling as to the beauty, the deepest beauty, of nature."
    ― Richard P. Feynman

  9. #9
    Plane Walker Imhothar's Avatar
    Join Date
    Feb 2012
    Posts
    439

    Default

    Not sure we need a general purpose linear algebra library, but who knows, maybe it gets popular.

    I think what we'd really need for Rift is a specialized 3x3/3x4 (for dimensions) and 2x2/2x3 (for upcoming Canvas) library to do translation/rotation/scaling in R/R space. Since those would be number matrices there would not be a need to distinguish __add for scalar and component-wise addition (analog for sub/mul/div).

    For dimensions it would need methods to extract the euler angles, translation and scale coefficients (unless Zorba provides an API to directly get/set 3x4 matrices for dimension objects, or even Quaternions maybe?).

    For the source files there's either CurseForge or RiftUI, both provide SVN and Git repositories.

    Some points about the API so far:
    • Sometimes a more verbose naming scheme doesn't hurt. I wouldn't mind having to write "StringMatrix" instead of "strMat". It makes the code easier to understand.
    • Don't overload operators with different meanings. When I write "A % B" I assume to do modulo, not componentwise multiplication, because that is what the operator means for numbers. To translate a Scott Meyers quote to Lua: "do as the numbers do". Unless the standard mathematical notation for componentwise multiplication is "%".
    • Same for "..": the Lua meaning for it is concatenating strings. Overriding it for a different purpose might lead to confusion and surprise (unless overloaded to concatenate a matrix with a string to produce a string). A "concat" method would be better and explicitly states intent. It would be different if ".." was the standard mathematical notation for matrix concatenation.
    • Since you already use metatables you can override __tostring to make the matrix object cast itself to strings when needed by tostring().
    • Are the matrices column- or row-major? Might be relevant for pre- or post-multiplication.

    P.S.: I had this prepared for 4(!) days but stupid forum wouldn't let me post it...
    Author of the Imhothar's Bags addon.

  10. #10
    RIFT Community Ambassador the_real_seebs's Avatar
    Join Date
    Jan 2011
    Posts
    16,859

    Default

    Idle suggestion:

    Instead of toZero as defined, how about a "default", and "all members are set to that". Possibly, if it's a function, all members are set to function(matrix, x, y).

    So you could do

    (n, m, 0) <- set to 0
    (n, m) <- set to nil
    (n, m, false) <- set to false
    (n, m, function(m, x, y) return x + y end) <-- set to x+y

    etc.
    You can play WoW in any MMO. You don't have to play WoW in RIFT. Oh, and no, RIFT is not a WoW clone. Not having fun any more? Learn to play, noob! I don't speak for Riftui, but I moderate stuff there. Just came back? Welcome back! Here's what's changed. (Updated for 2.5!)

  11. #11
    RIFT Guide Writer Redcruxs's Avatar
    Join Date
    Jan 2011
    Posts
    3,935

    Default

    what are matrices usualy used for in programing? I remember using them in my visual basic class for excel but I can't remember what I used them for...

  12. #12
    Shadowlander Olandria's Avatar
    Join Date
    Jul 2011
    Posts
    34

    Default

    Thanks for the feedback, I've been away for a while now without internet so sorry about the vanishing act.

    @Imhothar
    -Tbh this library isn't for anyone.. I am happy if a few people find a use for it, as a general addon might only require a low fraction of the functionality.
    -I already have the code for autogenerating rotational matrices, and functions for converting shifts in angles to corresponding euler angles which can be fed to the API. However this isn't perfect yet.
    -Special 44 and 33 matrices will of course be implemented when the need for it arise, I'll release it once I get rotations perfect.

    -Verbosity can be fixed, if this is what the community want I'll just change it. I come from a field in programming which is deeply influenced by old fortran code, where the names had to be compact, and thus it has become standard. I'll just have to adapt to that as well.
    -"Do as the numbers do". Well, matrices are generalized numbers, i.e. a number is a 1x1 matrix. So saying that matrix A + number C should invoke componentvize addition is mathematically wrong, hence it's not standard in the matrix libraries I use for C++ every day. The same goes for the modulo operator; the libraries I've seen in the past use this operator for componentwize multiplications. If you don't want to use this, you could always invoke the componentwizeMult function, which I didn't list, but should do. toString will be added, but currently I only have a simple 'dump' function, as I'm not 100% satisfied with the resulting string. Matrix concatenation is defined in mathematics as appending the columns of two matrices, so I kind of want that reflected in the code, however, I see your point regarding the confusion when it comes to string matrices and the much used concatenation. I'll remove the functionality for now.
    -The matrices are stored row-major, that is, simple nested tables for easy indexing,


    @the_real_seebs
    -By default all elements are set to zero unless you specify that you don't want initialization.
    -I guess you mean the row and column index with x and y? If so there is a function "foreach" that you can invoke. I don't want too crazy constructor calls, I rather you just create something like this:

    n, m = 3, 2
    A = numMat(n, m, false) --uninitialized matrix
    A.foreach(true, function (x, y, m) return x + y - m end, m) --true indicates that you want indices sent to your function. Function is second argument, the additional function arguments are then given.


    I'll get back to working on this soon. Atm I am swamped with work on some simulations for my phd thesis, which sadly cannot wait as they need to be done in less than two weeks..

    Again thanks for all the feedback! I'll read up on the upcoming canvas etc. and see if I can't work something out


    Edit: @Redcruxs

    Matrices are user everywhere in programming! On one hand, you have the mathematical functionality. If you want things to go quick in large scale computing, you ought to rewrite sums etc. as products of matrices and then use an efficient linAlg implementation, i.e. lapack, to handle to execution. On the other hand, "lists" or nested arrays, which by design handles general objects in matrices, are used frequently and perhaps most commonly in situations where you work on a grid. Excel is to first approximation nothing but a huge matrix, where you can lay down macros and stuff to handle matrix operations. In computer graphics, for example openGL or directX, matrices are the base tool to use for for example rotating objects and so on
    Last edited by Olandria; 08-02-2013 at 02:36 AM.
    "To those who do not know mathematics it is difficult to get across a real feeling as to the beauty, the deepest beauty, of nature."
    ― Richard P. Feynman

  13. #13
    Shadowlander Olandria's Avatar
    Join Date
    Jul 2011
    Posts
    34

    Default

    Untill I get everything up on Curse, here's a link to the sourcecode on github:

    https://github.com/jorgehog/LibLinAlg

    Keep in mind that the library is in it's first iteration only, but you can play around if you'dd like

    Updates coming...
    "To those who do not know mathematics it is difficult to get across a real feeling as to the beauty, the deepest beauty, of nature."
    ― Richard P. Feynman

  14. #14
    Plane Walker Imhothar's Avatar
    Join Date
    Feb 2012
    Posts
    439

    Default

    Quote Originally Posted by Olandria View Post
    -"Do as the numbers do". Well, matrices are generalized numbers, i.e. a number is a 1x1 matrix. So saying that matrix A + number C should invoke componentvize addition is mathematically wrong, hence it's not standard in the matrix libraries I use for C++ every day. The same goes for the modulo operator; the libraries I've seen in the past use this operator for componentwize multiplications. If you don't want to use this, you could always invoke the componentwizeMult function, which I didn't list, but should do. toString will be added, but currently I only have a simple 'dump' function, as I'm not 100% satisfied with the resulting string. Matrix concatenation is defined in mathematics as appending the columns of two matrices, so I kind of want that reflected in the code, however, I see your point regarding the confusion when it comes to string matrices and the much used concatenation. I'll remove the functionality for now.
    -The matrices are stored row-major, that is, simple nested tables for easy indexing,
    Just because everyone does it doesn't mean it's the right thing to do ;)
    There was a time when operator overloading was all the craze and people tried to use operators for everything, which often ended up (for example) in ^ being used for the cros product and * for dot product of vectors, which doesn't resemble the mathematical notation. Nowadays people got a bit more sane and try to avoid operator overloading unless it really makes sense, because they confused coders and (especially) maintainers. You need to know what an operator does when reading the code, therefore it should follow the rules people expect from the built-in operators (or in case of domain experts what they would write on paper). And if the operator author tried to be smart you lose since there is no function name to tell you "no, this is not XOR, but something completely different". But you can't change the old libraries as they need to be backward compatible.

    Thus came the rule "do as the ints do" (the original quote for C++). That means, if I see a ^ b in C++ I expect it to involve XOR. Seeing a % b I expect it to do something with modulo. It simply reduces the chances for confusion. Hence, for example, the guys at Khronos decided against using operators for cross- or dot products or componentwise multiplication in GLSL, and use functions instead. It lessens confusion.
    There are of course exceptions if we are dealing with a certain domain language for experts. But since no mathemagicians (I know) use % to denote componentwise multiplication on paper it probably shouldn't appear in code either.

    Plus, we aren't C++ here ;)

    Writing a new library you have the opportunity to do it "right" and less confusing than at times when "bad idioms" were mainstream.

    This is all just my oppinion of course.
    Last edited by Imhothar; 08-02-2013 at 08:03 AM.
    Author of the Imhothar's Bags addon.

  15. #15
    Shadowlander Olandria's Avatar
    Join Date
    Jul 2011
    Posts
    34

    Default

    UPDATE: The page is up at CurseForge! http://rift.curseforge.com/addons/liblinalg/

    Major changes made, I've added a section about latest changes to my reserved spaces. The full changelog and a todo list is given in the repository. Main file is awaiting approval.

    Cheers!


    @Imholthar
    Hehe, I agree on everything you say. The important thing is that the code is understandable, not that it's compact. Hence the hatred towards insane constructors, unless we're Python, where keywordarguments saves the day!

    The reason why I've chosen to stick with the productwise matrix-multiplication is the fact that I use it tons on an everyday basis, however, I can't really see much use for it in a scripting library, so no one is gonna end up doing it too much anyways. The modulus between two matrices is something I've never heard of or never used, however, come to think of it I might have heard some people use "modulus" instead of "determinant", but it doesn't matter.

    As far as additional "common operator" stuff, I will put it on a hold, as the 'foreach' method pretty much eats everything..
    "To those who do not know mathematics it is difficult to get across a real feeling as to the beauty, the deepest beauty, of nature."
    ― Richard P. Feynman

+ Reply to Thread
Page 1 of 2 1 2 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts