|
-
Sep 12th, 2022, 08:07 PM
#1
Thread Starter
Junior Member
Should I use a Class or a Structure, (Matrix Tool)
I made a Class for matrix operations, [MatrixObject]. I am mainly concerned with the inverse; I need to calculate many large matrix inverse's for this application.( size:~[R100xC100])
Right now the performance for computing the inverse is:
size:50x50 ---- time:~200ms
size:100x100 - time:~2.3s
size:200x200 - time:~29s
That sounds slow but its not, try beating that without purchasing libraries, its hard...
I can probably squeeze out a tiny bit more speed by cleaning the loops... But I'm wondering if turning this into a Structure would have major performance gains and makes sense ('would a smarter better looking programmer do this?').
The matrix code has the following charactistics:
- Large dynamic array member (for matrix values)
- Does not include any class members.
- will be used/declared within a method, copy's made will be minimal.
- speed of operation is important for the application
The speed of this inverse calculation is essential to the application but it contains a large dynamic array. The internet says large arrays are a no go for Structs... But are there circumstances where you would use a Struct anyway? Also, what happens if the Struct w/ methods is wrapped in Class?
My knowledge of stack and heap is to the extent of stuff said in youtube videos. I don't have a deep enough understanding to answer this question.
I would like to get some more info on exactly what can happen if a structure is too large. Does the complexity of the methods also affect stack usage? Do structures get compiled differently than classes do? (different assembly generated)
Here as example of the Code
As a Class (current version)
Code:
' Every thing inside a Class ----------------
Public Class MatrixObject1
Private Structure Matrix4F_Array
Dim A() As Matrix4x4
End Structure
Private m_ROW_Arrays() As Matrix4F_Array '<-- array of [Matrix4x4] arrays
'
' m_ROW_Arrays(0) .A(0) .A(1) .A(3) ...
' M11 M12 M13
' m_ROW_Arrays(1) .A(0) .A(1) .A(3) ...
' M21 M22 M23
' m_ROW_Arrays(2) .A(0) .A(1) .A(3) ...
' : M31 M32 M33
' :
Public Sub New()
'...
End Sub
Public Shared Function Multiply(ByRef Mat1 As MatrixObject1, ByRef Mat2 As MatrixObject1) As MatrixObject1
' ....
End Function
Public Shared Function Inverse(ByRef i_Mat As MatrixObject1, ByRef success As Boolean) As MatrixObject1
' ....
End Function
' * also includes propertys for size and shared operators: *,+,-
' and misc. functions.
End Class
As a Structure w/methods, and wrapper Class (for non essiential/slow methods); what i'm considering doing.
Code:
' Structure with only essential, tight functions
Public Structure MatrixStruct
Private Structure Matrix4F_Array
Dim A() As Matrix4x4
End Structure
Private m_ROW_Arrays() As Matrix4F_Array '<-- array of [Matrix4x4] arrays
Public Shared Function Multiply(ByRef Mat1 As MatrixStruct, ByRef Mat2 As MatrixStruct) As MatrixStruct
' ....
End Function
Public Shared Function Inverse(ByRef i_Mat As MatrixStruct, ByRef success As Boolean) As MatrixStruct
' ....
End Function
End Structure
'
' Matrix Class that inlcudes [MatrixStruct] member
' -Class Methods have error checks and other misc. stuff
Public Class MatrixObject2
Private m_Struct As MatrixStruct
Public Sub New()
'...
End Sub
Public Shared Function Multiply(ByRef Mat1 As MatrixObject2, ByRef Mat2 As MatrixObject2) As MatrixObject2
' ....
Dim ret As New MatrixObject2
ret.m_Struct = MatrixStruct.Multiply(Mat1.m_Struct, Mat2.m_Struct)
Return ret
End Function
' :
' :
' :
' * also includes propertys for size and shared operators: *,+,-
' and misc. functions.
End Class
-
Sep 12th, 2022, 09:59 PM
#2
Re: Should I use a Class or a Structure, (Matrix Tool)
I don't think turning it into a structure would help any at all, and might end up costing too much. If you make it a structure, it is a value item, which means that if you were to pass it as an argument to a method, you'd be copying in the whole thing. For the larger matrices you are talking about, that could mean a significant chunk of memory being passed around. If you will NEVER pass it as an argument to anything, then you might see some trivial gain, but that's all.
My usual boring signature: Nothing
 
-
Sep 13th, 2022, 05:06 PM
#3
Thread Starter
Junior Member
Re: Should I use a Class or a Structure, (Matrix Tool)
Ok,
What if the Structure w/ methods is private within a wrapper Class... So that it is controlled and never unnecessarily copied.
Is that any different then just using a Class?
All the matrix operations (+,-,*) require scanning through a dynamic array(s), getting and setting values. I'm trying to prevent those arrays from being fragmented.
Also, saw a video that implied Structures methods generate different, more efficient assembly than Class methods, is that correct?
-
Sep 13th, 2022, 05:27 PM
#4
Re: Should I use a Class or a Structure, (Matrix Tool)
I suppose the easiest way would be to try both approaches and time them.
https://benchmarkdotnet.org/ is a great tool for benchmarking dotnet code.
Last edited by PlausiblyDamp; Sep 13th, 2022 at 06:32 PM.
-
Sep 13th, 2022, 05:27 PM
#5
Re: Should I use a Class or a Structure, (Matrix Tool)
There are differences between classes and structures, but largely at a level that won't matter much, as far as I am aware. For example, if you have a simple loop in a method, that loop will look the same whether in a class or a structure. How you get to the loop might be different, but the loop won't be, and the cost of the loop will out weigh the differences.
You ought to test it out, though. Create a simplified version (or not simplified) of both a class and a structure, then call the method over and over in a loop while timing it using a Stopwatch object. I have a test project that I use for that purpose. It has Test1 and Test2, which I call in the order Test1, Test2, Test2, Test1, then show the timing of each. By running those tests a few times, it is possible to see the cost and the variation within the runs. Inside the TextX methods, most timing requires a loop, because any one call can be too fast to time.
My usual boring signature: Nothing
 
-
Sep 13th, 2022, 07:58 PM
#6
Thread Starter
Junior Member
Re: Should I use a Class or a Structure, (Matrix Tool)
-
Sep 16th, 2022, 12:14 AM
#7
Thread Starter
Junior Member
Re: Should I use a Class or a Structure, (Matrix Tool)
Initial results indicate the Structure w/methods wrapped in a Class is many many times faster.
I need to verify this with more testing. I'll post the code and performance time when finished.
-
Sep 16th, 2022, 12:40 AM
#8
Re: Should I use a Class or a Structure, (Matrix Tool)
 Originally Posted by Shaggy Hiker
For the larger matrices you are talking about, that could mean a significant chunk of memory being passed around.
Structures are value types but arrays are classes and therefore reference types. Copying a structure that contains an array will not copy the array; only the reference to the array. If you then modify an element in that array in the copy, it will affect the original. If you assign a new array in the copy, that would not affect the original.
-
Sep 16th, 2022, 08:54 AM
#9
Re: Should I use a Class or a Structure, (Matrix Tool)
 Originally Posted by jmcilhinney
Structures are value types but arrays are classes and therefore reference types. Copying a structure that contains an array will not copy the array; only the reference to the array. If you then modify an element in that array in the copy, it will affect the original. If you assign a new array in the copy, that would not affect the original.
Right. I didn't read the code much at all. For some reason, I was thinking back to a time when a simple matrix (it could ONLY be simple) was built without using arrays. That would be totally unworkable for a matrix of the size described.
My usual boring signature: Nothing
 
-
Sep 16th, 2022, 08:55 AM
#10
Re: Should I use a Class or a Structure, (Matrix Tool)
 Originally Posted by tonyd5
Initial results indicate the Structure w/methods wrapped in a Class is many many times faster.
I need to verify this with more testing. I'll post the code and performance time when finished.
That sounds suspicious. Fractionally different would be understandable. Something like this being many times faster sounds like you aren't comparing apples to apples.
My usual boring signature: Nothing
 
-
Sep 16th, 2022, 09:07 AM
#11
Thread Starter
Junior Member
Re: Should I use a Class or a Structure, (Matrix Tool)
 Originally Posted by jmcilhinney
Structures are value types but arrays are classes and therefore reference types. Copying a structure that contains an array will not copy the array; only the reference to the array. If you then modify an element in that array in the copy, it will affect the original. If you assign a new array in the copy, that would not affect the original.
Yep, figured that out. Had to make copy methods... annoying.
I made structures with arrays members in another program I'm working on; Did NOT have this problem, arrays members were copied just fine...
My suspicion is because the array member is nested (array of array's), it copies byref... Because the value of each array item is a pointer to another array, the pointer value gets copied but still points to the same thing.
Code:
Public Structure MatrixStruct
Private Structure Matrix4F_Array
Dim A() As Matrix4x4
End Structure
Private m_ROW_Arrays() As Matrix4F_Array '<-- array of [Matrix4x4] arrays
'
' m_ROW_Arrays(0) .A(0) .A(1) .A(3) ...
' (4x4)11 (4x4)12 (4x4)13
' m_ROW_Arrays(1) .A(0) .A(1) .A(3) ...
' (4x4)21 (4x4)22 (4x4)23
' m_ROW_Arrays(2) .A(0) .A(1) .A(3) ...
' : (4x4)31 (4x4)32 (4x4)33
' :
' :
' :
' :
End Structure
-
Sep 16th, 2022, 02:23 PM
#12
Re: Should I use a Class or a Structure, (Matrix Tool)
There is no method that can copy classes that is generic enough to use on everything and efficient enough that it is justified, so having people write copy methods, while annoying, is probably a good design decision. Some languages will take other routes, though, if they are willing to make a few sacrifices.
My usual boring signature: Nothing
 
-
Sep 16th, 2022, 11:14 PM
#13
Thread Starter
Junior Member
Re: Should I use a Class or a Structure, (Matrix Tool)
 Originally Posted by Shaggy Hiker
There is no method that can copy classes that is generic enough to use on everything and efficient enough that it is justified, so having people write copy methods, while annoying, is probably a good design decision. Some languages will take other routes, though, if they are willing to make a few sacrifices.
... I have made a universial clone function for anything. makes deep sea copys of all members(any type including objects) and can handle arrays of arrays of arrays....
Its monster, very slow. I only use it as a band aid when I don't want to think.
Code:
Public Module UtilitiesXXX
'--- Clone object to get new instance with identical member values ------
'
' returns a new instance of the object
'
Public Function clone(Of K)(copyObj As K) As K
Dim newObj As K
'--- for cloning arrays -----------------------------
If copyObj.GetType.IsArray Then
Dim arrObj As Object = copyObj
Dim tArr As Array = Array.CreateInstance(arrObj(0).GetType, UBound(arrObj) + 1)
'-- for all objects in array clone values -----
For i As Integer = 0 To UBound(arrObj)
tArr(i) = clone(arrObj(i))
Next
'----------------------------------------------
newObj = CTypeDynamic(tArr, copyObj.GetType)
Return newObj
End If
'--- for cloning non-arrays ------------------------
newObj = get_new_instance_ofObject(newObj, copyObj)
clone_members(newObj, copyObj)
Return newObj
End Function
'--- returns new instance of Class or Value Type passed in
Private Function get_new_instance_ofObject(Of K)(ByRef newVal As Object, ByVal of_obj As K) As K
Dim ty As Type = of_obj.GetType
If ty.IsArray Then _
Throw New Exception("attmepting to create of a non array instance of an array object")
If ty.IsClass Then _
Return ty.GetConstructor(New System.Type() {}).Invoke(New K() {})
If ty.IsValueType Then _
Return CTypeDynamic(newVal, ty)
Return Nothing
End Function
'--- sets field info value for Classes, Structs, and System types
'---
Private Sub SmartSetValue(Of K, T)(finfo As System.Reflection.FieldInfo,
ByRef newObj As K,
copyVal As T)
Dim ty As Type = newObj.GetType
'---- see if type is a standard system type ----
Dim str As String = "System"
Dim is_system_type As Boolean =
ty.IsPrimitive Or
Strings.Left(ty.Namespace, Len(str)) = str Or
ty.IsEnum
If is_system_type Then
finfo.SetValue(newObj, copyVal)
Exit Sub
End If
'----------------------------------------
If ty.IsClass Then
finfo.SetValue(newObj, copyVal)
Exit Sub
End If
'----------------------------------------
If ty.IsValueType Then
Dim x As ValueType = CTypeDynamic(newObj, newObj.GetType)
finfo.SetValue(x, copyVal)
newObj = CTypeDynamic(x, newObj.GetType)
Exit Sub
End If
End Sub
'--- Clone object (1 member deep) to get new instance with identical member values ------
'
' updates 'newObj' by ref
' returns True if @ no more seeded members
'
Private Sub clone_members(ByRef newObj_ As Object, ByVal baseObj As Object)
Dim myObj As New Object '<-- memeber feild as object
Dim newObj As Object = newObj_
Dim objType As Type '<-- type name for feild
Dim fInfo As System.Reflection.FieldInfo '<-- feild info object
Dim fInfo_arr() As System.Reflection.FieldInfo '<-- feild info object
Dim newfInfo_arr() As System.Reflection.FieldInfo
objType = baseObj.GetType()
fInfo_arr = objType.GetFields()
For Each fInfo In fInfo_arr
myObj = fInfo.GetValue(baseObj) '<-- get field object of "baseObj"
'-- set null values case -----------------
If IsNothing(myObj) Then
SmartSetValue(fInfo, newObj_, myObj)
Continue For
End If
'-----------------------------------------
'-- get reference to 'newObj_' feild -----
'-- and Type of 'myObj'
objType = myObj.GetType
'-------------------------------------------
'--- for standard system types case -------------------
'------------------------------------------------------
Dim str As String = "System"
Dim is_system_type As Boolean =
objType.IsPrimitive Or
Strings.Left(objType.Namespace, Len(str)) = str Or
objType.IsEnum
If is_system_type Then
SmartSetValue(fInfo, newObj_, myObj)
Continue For
End If
'------------------------------------------------------
'------------------------------------------------------
'-- see if member feild is an array -------------------
'-- if so recall 'clone_members' for all
'-- objects in array
If myObj.GetType.IsArray Then
'-- make sure array is declared ----
Try
Dim i = UBound(myObj)
Catch ex As Exception
myObj = Nothing
SmartSetValue(fInfo, newObj_, myObj)
Continue For
End Try
'-----------------------------------
'-- create an array instance for new values --
objType = myObj(0).GetType
Dim tArr As Array = Array.CreateInstance(objType, UBound(myObj) + 1)
'-- for all objects in array clone values -----
For i As Integer = 0 To UBound(myObj)
tArr(i) = clone(myObj(i))
Next
'----------------------------------------------
SmartSetValue(fInfo, newObj_, tArr)
Continue For
End If
'------------------------------------------------------
'------------------------------------------------------
'-- see if member feild has seeded values -----
'-- if so recall 'clone_members' for object
newfInfo_arr = objType.GetFields()
If newfInfo_arr.Length > 0 And Not (IsNothing(newfInfo_arr)) Then
Dim currObj As New Object
currObj = clone(myObj)
SmartSetValue(fInfo, newObj_, currObj)
End If
'-----------------------------------------------
Next
End Sub
End Module
Current time performance
50x50: 5ms
100x100: 50ms
125x125: 90ms
150x150: 134ms
200x200: 290ms (but the result is incorrect, weird)
~100x faster.
Don't know for certain if this is 100% due to the Struct yet.
I'm still working on this. Adding print functions so I can actually see the Matrix while debugging and write to a CSV... I want it to be nice before posting it.
-
Sep 17th, 2022, 10:02 AM
#14
Re: Should I use a Class or a Structure, (Matrix Tool)
That universal clone won't work for EVERYTHING, it will work for certain things. For example, what happens if the array is an array of Object, where the actual items in the array are a variety of things, such as the first being an integer, the second being a string, and so forth. What type will arrObj(0).GetType return for such an array?
Another, more contrived, variation would be: What happens if the array is an array of classes that maintain a DB connection? What should the state of those connections be in the cloned array?
My usual boring signature: Nothing
 
-
Sep 17th, 2022, 02:57 PM
#15
Re: Should I use a Class or a Structure, (Matrix Tool)
 Originally Posted by tonyd5
Don't know for certain if this is 100% due to the Struct yet.
I'm still working on this. Adding print functions so I can actually see the Matrix while debugging and write to a CSV... I want it to be nice before posting it.
Looking at this and your original post, I am not convinced that switching between a struct and a class would yield much of a performance difference. If there are speedups to be had they are probably more likely to be found in the implementation of the various methods that manipulate the matricies (Inverse etc.) or in the choice of data structure / access. Arrays and nested arrays can have performance issues depending on how they are accessed , there might be cleaner approaches compared to arrays of arrays perhaps.
-
Sep 19th, 2022, 07:59 PM
#16
Thread Starter
Junior Member
Re: Should I use a Class or a Structure, (Matrix Tool)
Your suspiscions are correct, The Structure was NOT the cause of the major performance gain... The changing the Structure to a Class was only few % points slower...
What was change:
In the old version, in all the matrix operations (+,-,*) the size of the matrix's was checked. Like, before multipling these matrices check that the size's are vaild first... Real quick If statments in every operation method.
In the new version, A Structure w/ (+,-,*,..) methods was made. These methods did NOT have any if statements... Just assumed the matrices were of correct size and went right into scanning arrays and doing math.
The Structure was also conertrained to only do operations on (4x4) blocks (Matrix4x4)
So for the inverse method, which is hundreds of multiplications and adding & subtracting, hundreds of reduntant If statements were no longer executed...
I don't think the If checks were soaking up time but rather messing up the LUT or whatever... preventing next predictable memory location being ready to go in RAM.
The structure of arrays was NOT changed.
The matrix operations (+,-,*) were not changed significantly, other than removing reduntant If statements.
The biggest change was converting the seocond matrix into Column Major form when multipling, Which may or may not save time.
The inverse operation was not changed...
-----------------------
Whatever, below is the code and Demo. The only problem I encounted is that for matrices >150x150 the inverse because less accurate to invently invalid. Probably because a single does not have precission.
For example the array is 256x256... =2^16... A float (24b + 8exp), will only have 24b-16b=8b of precision for each value in matrix.
Demo of [MatrixObject] Class
Code:
Module MatrixObject_DEMO_MODULE
Public Sub MatrixObject_demo()
'~~~~~~~~ Properties: copy() , matrix_item(,) , row() , col() ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'~~~~~
'~~
Dim x1 As New MatrixObject
Dim Rsize As Integer
Dim Csize As Integer
Dim Rarr() As Single
Dim Carr() As Single
Dim valS As Single
x1.matrix_item(row:=1, col:=1) = 11.0!
x1.matrix_item(row:=1, col:=2) = 12.0!
x1.matrix_item(row:=1, col:=3) = 13.0!
Rsize = x1.RowSize
Csize = x1.ColSize
Rarr = x1.row(1)
Carr = x1.col(3)
x1.matrix_item(row:=2, col:=3) = 23.0!
x1.matrix_item(row:=2, col:=4) = 24.0!
x1.Print2Console() '<-- prints to debug output when in debug mode
For i As Integer = 1 To x1.RowSize
Rarr = x1.row(i)
Next
For i As Integer = 1 To x1.ColSize
Carr = x1.col(i)
Next
x1.row(1) = New Single() {11, 12, 13, 14, 15, 16}
x1.row(2) = New Single() {21, 22, 23, 24, 25, 26}
x1.row(3) = New Single() {31, 32, 33, 34, 35, 36}
x1.row(4) = New Single() {41, 42, 43, 44, 45, 46}
x1.col(7) = New Single() _
{17,
27,
37,
47}
x1.Print2Console()
Dim xCopy As MatrixObject = x1.copy
xCopy *= 100
xCopy.RowSize = 3
'
For i As Integer = 1 To xCopy.RowSize
For j As Integer = 1 To xCopy.ColSize
valS = xCopy.matrix_item(i, j)
Next
Next
Console.WriteLine("xCopy")
xCopy.Print2Console()
'
Console.WriteLine("x1")
x1.Print2Console()
'~~~~~~~~ Operators: + , - , * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'~~~~~
'~~
' add, subtract, scaler multiple --------------------------
Dim x2 As New MatrixObject
Dim x3 As New MatrixObject
Dim x4 As New MatrixObject
Dim x5 As New MatrixObject
Dim x6 As New MatrixObject
Dim x7 As New MatrixObject
'
x2.row(1) = New Single() {10, 10, 10, 10, 10, 10}
x2.row(2) = New Single() {20, 20, 20, 20, 20, 20}
x2.row(3) = New Single() {30, 30, 30, 30, 30, 30}
x2.row(4) = New Single() {40, 40, 40, 40, 40, 40}
'
x3.row(1) = New Single() {1, 2, 3, 4, 5, 6}
x3.row(2) = New Single() {1, 2, 3, 4, 5, 6}
x3.row(3) = New Single() {1, 2, 3, 4, 5, 6}
x3.row(4) = New Single() {1, 2, 3, 4, 5, 6}
x4 = x2 + x3
Console.WriteLine("x4")
x4.Print2Console()
' x5=x4 * 4
x5 = x4.copy
x5 = x5 + x4
x5 += x4
x5 = MatrixObject.Add(x5, x4)
Console.WriteLine("x5")
x5.Print2Console()
' x6=x4 * 4
x6 = x4 * 1.0!
x6 *= 2.0!
x6 = MatrixObject.Multiply(x6, 2.0!)
Console.WriteLine("x6")
x6.Print2Console()
x7 = x6 - x5
x7 = MatrixObject.Subtract(x7, x5)
x7 -= (x5 * (-1.0!))
Console.WriteLine("x7")
x7.Print2Console()
' matrix multiply ---------------------------------------
x2 = New MatrixObject
x3 = New MatrixObject
'
x2.row(1) = New Single() {1, 2, 3}
x3.col(1) = New Single() {1, 2, 3}
x4 = x2 * x3
Console.WriteLine("x4")
x4.Print2Console()
'----
x2 = New MatrixObject
x3 = New MatrixObject
'
x2.row(1) = New Single() {2, 2, 2, 2}
x2.row(2) = New Single() {3, 3, 3, 3}
'
x3.col(1) = New Single() {1, 2, 3, 4}
x3.col(2) = New Single() {1, 2, 3, 4}
x4 = x2 * x3
Console.WriteLine("x4")
x4.Print2Console()
'~~~~~~~~ Methods: Transpose(), Invert(), CSV_view() ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'~~~~~
'~~
' Transpose() --------------------------------------
x1 = New MatrixObject
x2 = New MatrixObject
x1.row(1) = New Single() {11, 12, 13, 14, 15, 16}
x1.row(2) = New Single() {21, 22, 23, 24, 25, 26}
x1.row(3) = New Single() {31, 32, 33, 34, 35, 36}
x1.row(4) = New Single() {41, 42, 43, 44, 45, 46}
x2 = x1.Transpose
Console.WriteLine("x1")
x1.Print2Console()
'
Console.WriteLine("transpose")
x2.Print2Console()
' Invert() -----------------------------------------
Dim startSize As Integer = 40
Dim endSize As Integer = 160
Dim stepSize As Integer = 20
Dim durrMS() As Single : ReDim durrMS(0)
Dim matCNT() As Single : ReDim matCNT(0)
Dim k As Integer = 0
Dim Xmat As New MatrixObject
Dim Ymat As New MatrixObject
Dim Zmat As New MatrixObject
For currSize As Integer = startSize To endSize Step stepSize
'MatrixObject.m_dummy = 0
Xmat.Size = currSize
For i As Integer = 1 To currSize
For j As Integer = 1 To currSize
Xmat.matrix_item(i, j) = CInt((Rnd()) * endSize)
Next
Next
Dim timer As New System.Diagnostics.Stopwatch
Dim success As Boolean
timer.Start()
Ymat = Xmat.Invert(success)
timer.Stop()
If success = False Then
MsgBox("unable to find inverse")
End If
'Zmat = Ymat * Xmat
'Console.WriteLine("XMAT")
'Xmat.Print2Console("G2")
'Console.WriteLine("YMAT")
'Ymat.Print2Console("G2")
'Console.WriteLine("ZMAT")
'Zmat.Print2Console("G2")
ReDim Preserve durrMS(k)
ReDim Preserve matCNT(k)
durrMS(k) = timer.ElapsedMilliseconds
matCNT(k) = currSize
k += 1
Next
Zmat = Ymat * Xmat
Console.WriteLine("XMAT")
Xmat.Print2Console("G2")
Console.WriteLine("YMAT")
Ymat.Print2Console("G2")
Console.WriteLine("ZMAT")
Zmat.Print2Console("G2")
' create CSV of Inverse*MAT, should equal Identity matrix
Zmat.ToCSV(filename:="newCSV")
' create CSV of performance results
Dim prfrmnceMAT As New MatrixObject
prfrmnceMAT.col(1) = matCNT
prfrmnceMAT.col(2) = durrMS
prfrmnceMAT.ToCSV(filename:="MatrixDemo_InvertPerformance")
End Sub
End Module
-
Sep 19th, 2022, 08:04 PM
#17
Thread Starter
Junior Member
Re: Should I use a Class or a Structure, (Matrix Tool)
Could not fit everything in 1 post....
Code for Structure & Class
Code:
Imports System.Numerics
Imports System.Runtime.InteropServices
' Structure with only essential, tight functions
Public Structure MatrixStruct
Public Structure Matrix4F_Array
Dim A() As Matrix4x4
End Structure
Private m_ROW_Arrays() As Matrix4F_Array '<-- array of [Matrix4x4] arrays
Private p_BR_size As Integer
Private p_BC_size As Integer
Public Sub setSize(RowBlck_sz As Integer, ColBlck_sz As Integer)
If Me.p_BR_size < 1 Then
ReDim Me.m_ROW_Arrays(0)
ReDim Me.m_ROW_Arrays(0).A(0)
End If
Dim chg_row As Boolean = False
Dim chg_col As Boolean = False
If Me.p_BR_size <> RowBlck_sz Then
chg_row = True
If Me.p_BR_size < RowBlck_sz Then
chg_col = True
End If
End If
'
If Me.p_BC_size <> ColBlck_sz Then
chg_col = True
End If
If chg_row Then
Me.p_BR_size = RowBlck_sz
ReDim Preserve Me.m_ROW_Arrays(Me.p_BR_size - 1)
End If
If chg_col Then
Me.p_BC_size = ColBlck_sz
For i As Integer = 0 To Me.p_BR_size - 1
ReDim Preserve Me.m_ROW_Arrays(i).A(Me.p_BC_size - 1)
Next
End If
End Sub
Public Function RowBlockSize() As Integer
Return Me.p_BR_size
End Function
Public Function ColBlockSize() As Integer
Return Me.p_BC_size
End Function
Public Property MatBlock(rowb As Integer, colb As Integer) As Matrix4x4
Get
Return Me.m_ROW_Arrays(rowb - 1).A(colb - 1)
End Get
Set(value As Matrix4x4)
Me.m_ROW_Arrays(rowb - 1).A(colb - 1) = value
End Set
End Property
Public Function copy() As MatrixStruct
Dim o_res = New MatrixStruct
o_res.setSize(Me.p_BR_size, Me.p_BC_size)
For i As Integer = 0 To Me.p_BR_size - 1
o_res.m_ROW_Arrays(i).A = Me.m_ROW_Arrays(i).A.Clone
Next
Return o_res
End Function
Private Property row_BLOCKS(i As Integer) As Matrix4x4()
Get
Return Me.m_ROW_Arrays(i - 1).A
End Get
Set(value As Matrix4x4())
Me.m_ROW_Arrays(i - 1).A = value
End Set
End Property
Private Property col_BLOCKS(i As Integer) As Matrix4x4()
Get
Dim ret() As Matrix4x4 : ReDim ret(p_BR_size - 1)
For j As Integer = 0 To (p_BR_size - 1)
ret(j) = Me.m_ROW_Arrays(j).A(i - 1)
Next
Return ret
End Get
Set(value As Matrix4x4())
For j As Integer = 0 To (p_BR_size - 1)
Me.m_ROW_Arrays(j).A(i - 1) = value(j)
Next
End Set
End Property
' Public Operator Methods ===========================================
Public Shared Function Multiply(ByRef Mat1 As MatrixStruct, ByRef Mat2 As MatrixStruct) As MatrixStruct
Dim row_len As Integer = Mat1.p_BR_size - 1
Dim col_len As Integer = Mat2.p_BC_size - 1
Dim len2 As Integer = Mat1.p_BC_size
Dim o_RES As New MatrixStruct
ReDim o_RES.m_ROW_Arrays(row_len)
For i As Integer = 0 To row_len
ReDim o_RES.m_ROW_Arrays(i).A(col_len)
Next
'
o_RES.p_BR_size = row_len + 1
o_RES.p_BC_size = col_len + 1
Dim col_MAJOR As New MatrixStruct
ReDim col_MAJOR.m_ROW_Arrays(col_len)
For i As Integer = 1 To (col_len + 1)
col_MAJOR.row_BLOCKS(i) = Mat2.col_BLOCKS(i)
Next
Dim r As Integer = 0
For Each row_ARRAY As Matrix4F_Array In Mat1.m_ROW_Arrays
Dim c As Integer = 0
For Each col_ARRAY As Matrix4F_Array In col_MAJOR.m_ROW_Arrays
o_RES.m_ROW_Arrays(r).A(c) = MatrixStruct.DOTproduct(row_ARRAY.A, col_ARRAY.A, len2)
c += 1
Next
r += 1
Next
Return o_RES
End Function
Public Shared Function MultiplyScaler(ByRef Mat1 As MatrixStruct, ByRef S As Single) As MatrixStruct
Dim o_RES As MatrixStruct = Mat1.copy
Dim r As Integer = 0
For Each row_ARRAY As Matrix4F_Array In o_RES.m_ROW_Arrays
Dim c As Integer = 0
For Each col_MAT As Matrix4x4 In row_ARRAY.A
o_RES.m_ROW_Arrays(r).A(c) = Matrix4x4.Multiply(col_MAT, S)
c += 1
Next
r += 1
Next
Return o_RES
End Function
Public Shared Function Add(ByRef Mat1 As MatrixStruct, ByRef Mat2 As MatrixStruct) As MatrixStruct
Dim o_RES As MatrixStruct = Mat1.copy
For i As Integer = 0 To o_RES.p_BR_size - 1
o_RES.m_ROW_Arrays(i).A = MatrixStruct.ADDvector(Mat1.m_ROW_Arrays(i).A, Mat2.m_ROW_Arrays(i).A, o_RES.p_BC_size)
Next
Return o_RES
End Function
Public Shared Function Subtract(ByRef Mat1 As MatrixStruct, ByRef Mat2 As MatrixStruct) As MatrixStruct
Dim o_RES As MatrixStruct = Mat1.copy
For i As Integer = 0 To o_RES.p_BR_size - 1
o_RES.m_ROW_Arrays(i).A = MatrixStruct.SUBTRACTvector(Mat1.m_ROW_Arrays(i).A, Mat2.m_ROW_Arrays(i).A, o_RES.p_BC_size)
Next
Return o_RES
End Function
Public Shared Sub Inverse(ByRef i_Mat As MatrixStruct, ByRef invA As MatrixStruct, ByRef success As Boolean)
Dim N_blocks As Integer = i_Mat.p_BR_size
Dim B As MatrixStruct
Dim C As MatrixStruct
Dim D As MatrixStruct
Dim x1 As MatrixStruct
Dim x2 As MatrixStruct
Dim x3 As MatrixStruct
Dim x4 As MatrixStruct
ReDim invA.m_ROW_Arrays(0)
ReDim invA.m_ROW_Arrays(0).A(0)
invA.p_BR_size = 1
invA.p_BC_size = 1
success = Matrix4x4.Invert(i_Mat.m_ROW_Arrays(0).A(0), invA.m_ROW_Arrays(0).A(0))
If success = False Then Exit Sub
For i As Integer = 2 To N_blocks
B = MatrixStruct.get_sub_BLOCKS(i_Mat, 1, i, i - 1, i)
C = MatrixStruct.get_sub_BLOCKS(i_Mat, i, 1, i, i - 1)
D = MatrixStruct.get_sub_BLOCKS(i_Mat, i, i, i, i)
x4 = MatrixStruct.Multiply(invA, B)
x4 = MatrixStruct.Multiply(C, x4)
x4 = MatrixStruct.Subtract(D, x4)
success = Matrix4x4.Invert(x4.m_ROW_Arrays(0).A(0), x4.m_ROW_Arrays(0).A(0))
If success = False Then Exit Sub
'----------------------------------------
x1 = MatrixStruct.Multiply(x4, C)
x1 = MatrixStruct.Multiply(x1, invA)
x1 = MatrixStruct.Multiply(B, x1)
x1 = MatrixStruct.Multiply(invA, x1)
x1 = MatrixStruct.Add(invA, x1)
'----------------------------------------
x2 = MatrixStruct.Multiply(B, x4)
x2 = MatrixStruct.Multiply(invA, x2)
x2 = MatrixStruct.MultiplyScaler(x2, -1.0!)
'----------------------------------------
x3 = MatrixStruct.MultiplyScaler(x4, -1.0!)
x3 = MatrixStruct.Multiply(x3, C)
x3 = MatrixStruct.Multiply(x3, invA)
'----------------------------------------
invA = x1
invA.p_BR_size = x1.p_BR_size + 1
invA.p_BC_size = x1.p_BC_size + 1
ReDim Preserve invA.m_ROW_Arrays(invA.p_BR_size - 1)
invA.m_ROW_Arrays(invA.p_BR_size - 1) = x3.m_ROW_Arrays(0)
For j As Integer = 0 To (invA.p_BR_size - 2)
ReDim Preserve invA.m_ROW_Arrays(j).A(invA.p_BC_size - 1)
invA.m_ROW_Arrays(j).A(invA.p_BC_size - 1) = x2.m_ROW_Arrays(j).A(0)
Next
ReDim Preserve invA.m_ROW_Arrays(invA.p_BR_size - 1).A(invA.p_BC_size - 1)
invA.m_ROW_Arrays(invA.p_BR_size - 1).A(invA.p_BC_size - 1) = x4.m_ROW_Arrays(0).A(0)
' _ _ __
' | | | |
' | X1 | |x2|
' |_ _| |__|
' _ _ __
' |_ x3 _| |x4|
'
Next
End Sub
'=== private methods used by operators ================================
Private Shared Function DOTproduct(ByRef x1() As Matrix4x4, ByRef x2() As Matrix4x4, ByRef len As Integer) As Matrix4x4
Dim res As New Matrix4x4
For i As Integer = 0 To len - 1
res = Matrix4x4.Add(res, Matrix4x4.Multiply(x1(i), x2(i)))
Next
Return res
End Function
Private Shared Function ADDvector(ByRef x1() As Matrix4x4, ByRef x2() As Matrix4x4, ByRef len As Integer) As Matrix4x4()
Dim res() As Matrix4x4 : ReDim res(len - 1)
For i As Integer = 0 To len - 1
res(i) = Matrix4x4.Add(x1(i), x2(i))
Next
Return res
End Function
Private Shared Function SUBTRACTvector(ByRef x1() As Matrix4x4, ByRef x2() As Matrix4x4, ByRef len As Integer) As Matrix4x4()
Dim res() As Matrix4x4 : ReDim res(len - 1)
For i As Integer = 0 To len - 1
res(i) = Matrix4x4.Subtract(x1(i), x2(i))
Next
Return res
End Function
Private Shared Function get_sub_BLOCKS(ByRef i_MAT As MatrixStruct,
ByRef i_row_block1 As Integer, ByRef i_col_block1 As Integer,
ByRef i_row_block2 As Integer, ByRef i_col_block2 As Integer) As MatrixStruct
Dim row_len As Integer = i_row_block2 - i_row_block1
Dim col_len As Integer = i_col_block2 - i_col_block1
Dim o_RES As New MatrixStruct
ReDim o_RES.m_ROW_Arrays(row_len)
For i As Integer = 0 To row_len
ReDim o_RES.m_ROW_Arrays(i).A(col_len)
Next
o_RES.p_BR_size = row_len + 1
o_RES.p_BC_size = col_len + 1
Dim r As Integer = 0
For i As Integer = (i_row_block1 - 1) To (i_row_block2 - 1)
Dim c As Integer = 0
For j As Integer = (i_col_block1 - 1) To (i_col_block2 - 1)
o_RES.m_ROW_Arrays(r).A(c) = i_MAT.m_ROW_Arrays(i).A(j)
c += 1
Next
r += 1
Next
Return o_RES
End Function
End Structure
-
Sep 19th, 2022, 08:04 PM
#18
Thread Starter
Junior Member
Re: Should I use a Class or a Structure, (Matrix Tool)
Wrapper Class..
Code:
' Matrix wrapper Class, uses MatrixStruct
' has methods and properties that allow matrix to be easily edited and viewed by user
Public Class MatrixObject
Private m_Struct As MatrixStruct
Private p_R_size As Integer
Private p_C_size As Integer
Public Sub New()
Me.m_Struct = New MatrixStruct
Me.m_Struct.setSize(0, 0)
'
Me.p_R_size = 0
Me.p_C_size = 0
End Sub
Public Function copy() As MatrixObject
Dim ret As New MatrixObject
ret.m_Struct = Me.m_Struct.copy
'
ret.p_R_size = Me.p_R_size
ret.p_C_size = Me.p_C_size
Return ret
End Function
Public Property RowSize() As Integer
Get
Return Me.p_R_size
End Get
Set(value As Integer)
Me.p_R_size = value
Dim a As Integer
Dim v As Integer
MatrixObject.index2_block(value, a, v)
Me.m_Struct.setSize(a, Me.m_Struct.ColBlockSize)
For j As Integer = 1 To (Me.m_Struct.ColBlockSize)
MatrixObject.keep_rows(v, Me.m_Struct.MatBlock(a, j))
Next
End Set
End Property
Public Property ColSize() As Integer
Get
Return Me.p_C_size
End Get
Set(value As Integer)
Me.p_C_size = value
Dim a As Integer
Dim v As Integer
MatrixObject.index2_block(value, a, v)
Me.m_Struct.setSize(Me.m_Struct.RowBlockSize, a)
For j As Integer = 1 To (Me.m_Struct.RowBlockSize)
MatrixObject.keep_cols(v, Me.m_Struct.MatBlock(j, a))
Next
End Set
End Property
Public Property Size() As Integer
Get
If Me.RowSize <> Me.ColSize Then
Return -1
Else
Return Me.RowSize
End If
End Get
Set(value As Integer)
Me.RowSize = value
Me.ColSize = value
End Set
End Property
Private Property prv_matrix_item(row As Integer, col As Integer) As Single
Get
Dim rowB As Integer
Dim colB As Integer
Dim rowV As Integer
Dim colV As Integer
MatrixObject.index2_block(row, rowB, rowV)
MatrixObject.index2_block(col, colB, colV)
Dim ret As Single
MatrixObject.Matrix4x4_value_IO(MAT4x4_IO.GET_, rowV, colV, Me.m_Struct.MatBlock(rowB, colB), ret)
Return ret
End Get
Set(value As Single)
Dim rowB As Integer
Dim colB As Integer
Dim rowV As Integer
Dim colV As Integer
MatrixObject.index2_block(row, rowB, rowV)
MatrixObject.index2_block(col, colB, colV)
MatrixObject.Matrix4x4_value_IO(MAT4x4_IO.SET_, rowV, colV, Me.m_Struct.MatBlock(rowB, colB), value)
End Set
End Property
Public Property matrix_item(row As Integer, col As Integer) As Single
Get
If row > Me.RowSize Then Return 0
If col > Me.ColSize Then Return 0
Return Me.prv_matrix_item(row, col)
End Get
Set(value As Single)
If Me.RowSize < row Then Me.RowSize = row
If Me.ColSize < col Then Me.ColSize = col
Me.prv_matrix_item(row, col) = value
End Set
End Property
Public Property row(i As Integer) As Single()
Get
Dim array As Single()
If i < 1 Then Return array
If Me.RowSize < i Then Return array
If Me.ColSize < 1 Then Return array
ReDim array(Me.ColSize - 1)
For j As Integer = 1 To Me.ColSize
array(j - 1) = Me.prv_matrix_item(i, j)
Next
Return array
End Get
Set(value As Single())
If i < 1 Then Exit Property
If Me.RowSize < i Then Me.RowSize = i
If Me.ColSize < value.Length Then Me.ColSize = value.Length
For j As Integer = 1 To value.Length
Me.prv_matrix_item(i, j) = value(j - 1)
Next
End Set
End Property
Public Property col(i As Integer) As Single()
Get
Dim array As Single()
If i < 1 Then Return array
If Me.ColSize < i Then Return array
If Me.RowSize < 1 Then Return array
ReDim array(Me.RowSize - 1)
For j As Integer = 1 To Me.RowSize
array(j - 1) = Me.prv_matrix_item(j, i)
Next
Return array
End Get
Set(value As Single())
If i < 1 Then Exit Property
If Me.ColSize < i Then Me.ColSize = i
If Me.RowSize < value.Length Then Me.RowSize = value.Length
For j As Integer = 1 To value.Length
Me.prv_matrix_item(j, i) = value(j - 1)
Next
End Set
End Property
Public Shared Function Multiply(ByRef i_MatObj1 As MatrixObject, ByRef i_MatObj2 As MatrixObject) As MatrixObject
If i_MatObj1.RowSize < 1 Then Return New MatrixObject
If i_MatObj2.RowSize < 1 Then Return New MatrixObject
If i_MatObj1.ColSize < 1 Then Return New MatrixObject
If i_MatObj2.ColSize < 1 Then Return New MatrixObject
If i_MatObj1.ColSize <> i_MatObj2.RowSize Then Return New MatrixObject
Dim o_res As New MatrixObject
o_res.m_Struct = MatrixStruct.Multiply(i_MatObj1.m_Struct, i_MatObj2.m_Struct)
o_res.RowSize = i_MatObj1.RowSize
o_res.ColSize = i_MatObj2.ColSize
Return o_res
End Function
Public Shared Function Multiply(ByRef i_MatObj As MatrixObject, ByRef C As Single) As MatrixObject
If i_MatObj.RowSize < 1 Then Return New MatrixObject
If i_MatObj.ColSize < 1 Then Return New MatrixObject
Dim o_res As New MatrixObject
o_res.m_Struct = MatrixStruct.MultiplyScaler(i_MatObj.m_Struct, C)
o_res.RowSize = i_MatObj.RowSize
o_res.ColSize = i_MatObj.ColSize
Return o_res
End Function
Public Shared Function Add(ByRef i_MatObj1 As MatrixObject, ByRef i_MatObj2 As MatrixObject) As MatrixObject
If i_MatObj1.RowSize < 1 Then Return New MatrixObject
If i_MatObj1.ColSize < 1 Then Return New MatrixObject
If i_MatObj1.RowSize <> i_MatObj2.RowSize Then Return New MatrixObject
If i_MatObj1.ColSize <> i_MatObj2.ColSize Then Return New MatrixObject
Dim o_res As New MatrixObject
o_res.m_Struct = MatrixStruct.Add(i_MatObj1.m_Struct, i_MatObj2.m_Struct)
o_res.RowSize = i_MatObj1.RowSize
o_res.ColSize = i_MatObj1.ColSize
Return o_res
End Function
Public Shared Function Subtract(ByRef i_MatObj1 As MatrixObject, ByRef i_MatObj2 As MatrixObject) As MatrixObject
If i_MatObj1.RowSize < 1 Then Return New MatrixObject
If i_MatObj1.ColSize < 1 Then Return New MatrixObject
If i_MatObj1.RowSize <> i_MatObj2.RowSize Then Return New MatrixObject
If i_MatObj1.ColSize <> i_MatObj2.ColSize Then Return New MatrixObject
Dim o_res As New MatrixObject
o_res.m_Struct = MatrixStruct.Subtract(i_MatObj1.m_Struct, i_MatObj2.m_Struct)
o_res.RowSize = i_MatObj1.RowSize
o_res.ColSize = i_MatObj1.ColSize
Return o_res
End Function
Public Shared Operator *(A1 As MatrixObject, A2 As MatrixObject) As MatrixObject
Return MatrixObject.Multiply(A1, A2)
End Operator
Public Shared Operator *(A1 As MatrixObject, x As Single) As MatrixObject
Return MatrixObject.Multiply(A1, x)
End Operator
Public Shared Operator +(A1 As MatrixObject, A2 As MatrixObject) As MatrixObject
Return MatrixObject.Add(A1, A2)
End Operator
Public Shared Operator -(A1 As MatrixObject, A2 As MatrixObject) As MatrixObject
Return MatrixObject.Subtract(A1, A2)
End Operator
Public Shared Function Invert(ByRef i_MAT As MatrixObject, ByRef o_res As MatrixObject) As Boolean
If i_MAT.RowSize < 1 Then o_res = New MatrixObject : Return False
If i_MAT.RowSize <> i_MAT.ColSize Then o_res = New MatrixObject : Return False
Dim org_size As Integer = i_MAT.Size
i_MAT.Size = i_MAT.m_Struct.RowBlockSize * 4%
' make extra row/cols identity
For j As Integer = (org_size + 1) To i_MAT.Size
i_MAT.matrix_item(j, j) = 1
Next
o_res = New MatrixObject
Dim success As Boolean
MatrixStruct.Inverse(i_MAT.m_Struct, o_res.m_Struct, success)
i_MAT.Size = org_size
If success Then o_res.Size = org_size
Return success
End Function
Public Function Invert(ByRef success As Boolean) As MatrixObject
Dim o_res As MatrixObject
success = MatrixObject.Invert(Me, o_res)
Return o_res
End Function
'' --https://www.youtube.com/watch?v=vGowBXcur1k
''
Public Function Transpose() As MatrixObject
Dim newObj As New MatrixObject
newObj.m_Struct.setSize(Me.m_Struct.ColBlockSize, Me.m_Struct.RowBlockSize)
For i As Integer = 1 To Me.m_Struct.RowBlockSize
For j As Integer = 1 To Me.m_Struct.ColBlockSize
newObj.m_Struct.MatBlock(j, i) = Matrix4x4.Transpose(Me.m_Struct.MatBlock(i, j))
Next
Next
newObj.RowSize = Me.ColSize
newObj.ColSize = Me.RowSize
Return newObj
End Function
Private Shared Sub index2_block(ByRef i_index As Integer, ByRef o_array4x4 As Integer, ByRef o_vector4x4 As Integer)
If i_index < 1 Then o_array4x4 = 0 : o_vector4x4 = 0 : Exit Sub
Dim n As Integer = (i_index - 1) \ 4%
o_array4x4 = n + 1
o_vector4x4 = i_index - (n) * 4%
End Sub
Private Shared Sub keep_rows(ByRef i_row As Integer, ByRef io_MAT As Matrix4x4)
If i_row = 4 Then Exit Sub
If i_row = 0 Then io_MAT = New Matrix4x4
io_MAT = Matrix4x4.Multiply(c_Identity(i_row), io_MAT)
End Sub
Private Shared Sub keep_cols(ByRef i_col As Integer, ByRef io_MAT As Matrix4x4)
If i_col = 4 Then Exit Sub
If i_col = 0 Then io_MAT = New Matrix4x4
io_MAT = Matrix4x4.Multiply(io_MAT, c_Identity(i_col))
End Sub
Private Shared ReadOnly c_Identity() As Matrix4x4 = New Matrix4x4() {
New Matrix4x4 With {.M11 = 1, .M22 = 1, .M33 = 1, .M44 = 1},
New Matrix4x4 With {.M11 = 1, .M22 = 0, .M33 = 0, .M44 = 0},
New Matrix4x4 With {.M11 = 1, .M22 = 1, .M33 = 0, .M44 = 0},
New Matrix4x4 With {.M11 = 1, .M22 = 1, .M33 = 1, .M44 = 0},
New Matrix4x4 With {.M11 = 1, .M22 = 1, .M33 = 1, .M44 = 1}}
Private Shared Sub Matrix4x4_value_IO(ByRef i_GetSet As MAT4x4_IO,
ByRef i_row As Integer, ByRef i_col As Integer,
ByRef io_MAT As Matrix4x4, ByRef io_val As Single)
Select Case i_row
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Case 1
Select Case i_col
Case 1
Select Case i_GetSet
Case MAT4x4_IO.SET_ : io_MAT.M11 = io_val : Exit Sub
Case MAT4x4_IO.GET_ : io_val = io_MAT.M11 : Exit Sub
End Select
Case 2
Select Case i_GetSet
Case MAT4x4_IO.SET_ : io_MAT.M12 = io_val : Exit Sub
Case MAT4x4_IO.GET_ : io_val = io_MAT.M12 : Exit Sub
End Select
Case 3
Select Case i_GetSet
Case MAT4x4_IO.SET_ : io_MAT.M13 = io_val : Exit Sub
Case MAT4x4_IO.GET_ : io_val = io_MAT.M13 : Exit Sub
End Select
Case 4
Select Case i_GetSet
Case MAT4x4_IO.SET_ : io_MAT.M14 = io_val : Exit Sub
Case MAT4x4_IO.GET_ : io_val = io_MAT.M14 : Exit Sub
End Select
End Select
'------------------------------------
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Case 2
Select Case i_col
Case 1
Select Case i_GetSet
Case MAT4x4_IO.SET_ : io_MAT.M21 = io_val : Exit Sub
Case MAT4x4_IO.GET_ : io_val = io_MAT.M21 : Exit Sub
End Select
Case 2
Select Case i_GetSet
Case MAT4x4_IO.SET_ : io_MAT.M22 = io_val : Exit Sub
Case MAT4x4_IO.GET_ : io_val = io_MAT.M22 : Exit Sub
End Select
Case 3
Select Case i_GetSet
Case MAT4x4_IO.SET_ : io_MAT.M23 = io_val : Exit Sub
Case MAT4x4_IO.GET_ : io_val = io_MAT.M23 : Exit Sub
End Select
Case 4
Select Case i_GetSet
Case MAT4x4_IO.SET_ : io_MAT.M24 = io_val : Exit Sub
Case MAT4x4_IO.GET_ : io_val = io_MAT.M24 : Exit Sub
End Select
End Select
'------------------------------------
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Case 3
Select Case i_col
Case 1
Select Case i_GetSet
Case MAT4x4_IO.SET_ : io_MAT.M31 = io_val : Exit Sub
Case MAT4x4_IO.GET_ : io_val = io_MAT.M31 : Exit Sub
End Select
Case 2
Select Case i_GetSet
Case MAT4x4_IO.SET_ : io_MAT.M32 = io_val : Exit Sub
Case MAT4x4_IO.GET_ : io_val = io_MAT.M32 : Exit Sub
End Select
Case 3
Select Case i_GetSet
Case MAT4x4_IO.SET_ : io_MAT.M33 = io_val : Exit Sub
Case MAT4x4_IO.GET_ : io_val = io_MAT.M33 : Exit Sub
End Select
Case 4
Select Case i_GetSet
Case MAT4x4_IO.SET_ : io_MAT.M34 = io_val : Exit Sub
Case MAT4x4_IO.GET_ : io_val = io_MAT.M34 : Exit Sub
End Select
End Select
'------------------------------------
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Case 4
Select Case i_col
Case 1
Select Case i_GetSet
Case MAT4x4_IO.SET_ : io_MAT.M41 = io_val : Exit Sub
Case MAT4x4_IO.GET_ : io_val = io_MAT.M41 : Exit Sub
End Select
Case 2
Select Case i_GetSet
Case MAT4x4_IO.SET_ : io_MAT.M42 = io_val : Exit Sub
Case MAT4x4_IO.GET_ : io_val = io_MAT.M42 : Exit Sub
End Select
Case 3
Select Case i_GetSet
Case MAT4x4_IO.SET_ : io_MAT.M43 = io_val : Exit Sub
Case MAT4x4_IO.GET_ : io_val = io_MAT.M43 : Exit Sub
End Select
Case 4
Select Case i_GetSet
Case MAT4x4_IO.SET_ : io_MAT.M44 = io_val : Exit Sub
Case MAT4x4_IO.GET_ : io_val = io_MAT.M44 : Exit Sub
End Select
End Select
'------------------------------------
End Select
End Sub
Private Enum MAT4x4_IO
NA = 0
SET_ = 1
GET_ = 2
End Enum
' Matrix View/String Convert methods ==================================================
Public Shared Narrowing Operator CType(ByVal MatObj As MatrixObject) As String
Return MatObj.ToString("G3")
End Operator
Public Sub Print2Console(Optional format As String = "G")
Static k As Integer = 0
If k = 0 Then
k = 1
Win32.AllocConsole()
End If
Console.WriteLine(Me.ToString(format))
End Sub
Public Overloads Function ToString(Optional format As String = "") As String
Dim maxlen As Integer = Me.MaxStringLength(format)
Dim val As Single
Dim str As String
Dim len As Integer
Dim ret_str As String = ""
For i As Integer = 1 To Me.RowSize
For j As Integer = 1 To Me.ColSize
val = Me.matrix_item(i, j)
str = val.ToString(format)
len = str.Length
Do While len < maxlen
str &= " "
len += 1
Loop
ret_str &= str & vbTab
Next
ret_str &= vbCrLf
Next
Return ret_str
End Function
Public Sub ToCSV(Optional filename As String = "", Optional fullpath As String = "", Optional format As String = "")
If fullpath = "" Then
If filename = "" Then filename = "matrix_view"
fullpath = AppDomain.CurrentDomain.BaseDirectory & filename & ".csv"
End If
Dim str As String = Me.ToString(format)
str = Strings.Replace(str, vbTab, " ")
Do While InStr(str, " ") <> 0
str = Strings.Replace(str, " ", " ")
Loop
str = Strings.Replace(str, " " & vbCrLf, vbCrLf)
str = Strings.Replace(str, " ", ",")
Dim str_rows() As String = Strings.Split(str, vbCrLf)
Dim csv_str As String
csv_str = ""
csv_str &= ",,col" & vbCrLf
csv_str &= ",row"
For i As Integer = 1 To Me.ColSize
csv_str &= "," & CStr(i)
Next
csv_str &= vbCrLf
For i As Integer = 1 To Me.RowSize
csv_str &= "," & CStr(i) & "," & str_rows(i - 1) & vbCrLf
Next
Dim sw As System.IO.StreamWriter
fullpath = Strings.Replace(fullpath, ".csv", "")
Dim fullpath2 As String = fullpath
Dim j As Integer = 0
Do
Try
sw = New System.IO.StreamWriter(fullpath2 & ".csv")
Exit Do
Catch ex As Exception
j += 1
fullpath2 &= fullpath & CStr(j)
End Try
Loop While (1)
fullpath2 &= ".csv"
sw.WriteLine(csv_str)
sw.Close()
Process.Start(fullpath2)
End Sub
Private Function MaxStringLength(format As String) As Integer
Dim val As Single
Dim str As String
Dim len As Integer
Dim N_len As Integer
N_len = 0
For i As Integer = 1 To Me.RowSize
For j As Integer = 1 To Me.ColSize
val = Me.matrix_item(i, j)
str = val.ToString(format)
len = str.Length
If N_len < len Then N_len = len
Next
Next
Return N_len
End Function
End Class
Public Class Win32
<DllImport("kernel32.dll")> Public Shared Function AllocConsole() As Boolean
End Function
<DllImport("kernel32.dll")> Public Shared Function FreeConsole() As Boolean
End Function
End Class
-
Sep 19th, 2022, 08:16 PM
#19
Thread Starter
Junior Member
Re: Should I use a Class or a Structure, (Matrix Tool)
 Originally Posted by Shaggy Hiker
That universal clone won't work for EVERYTHING, it will work for certain things. For example, what happens if the array is an array of Object, where the actual items in the array are a variety of things, such as the first being an integer, the second being a string, and so forth. What type will arrObj(0).GetType return for such an array?
Another, more contrived, variation would be: What happens if the array is an array of classes that maintain a DB connection? What should the state of those connections be in the cloned array?
It'll work for the first 2 examples. Every item in the array calls 'Clone' again... its recursive.
Every member in a object calls Clone again... keeps going and going until it gets to the valuetype.
-
Sep 20th, 2022, 07:22 AM
#20
Re: Should I use a Class or a Structure, (Matrix Tool)
Right, and it WILL clone most everything, but not absolutely everything. I think there's a faster method to accomplish the same thing, but whether or not it is simpler is certainly debatable. I haven't tried it, just seen it, and I may not be remembering it right, but I think the idea was to binary serialize to a memory stream, then restore to a new location. I think that's slightly wrong, as the binary serialization sounds a bit off, but it was something like that.
My usual boring signature: Nothing
 
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|