;MATRIX STRUCTURE TO BE PASSED TO THIS .DLL:

;struc MATRIX i,j,M
;  {
;        .i dd i  ;number of lines
;        .j dd j  ;number of columns
;        .M dd M  ;pointer to array of bytes that contains the matrix elements
;  }

format PE GUI 4.0 DLL
entry DllEntryPoint

include 'win32ax.inc'

section '.text' code readable executable

align 16

proc DllEntryPoint hinstDLL,fdwReason,lpvReserved
	mov	eax,TRUE
	ret
endp

proc getMatrixElem A,i,j,v ;OK
     ; Inputs: A - Matrix (by Ref)
     ;         i - Line number
     ;         j - Column number
     ; Output: v - Value at M(i,j) (by Ref)
     push    ebx edx ;save registers
     mov     ebx,[A] ;ebx holds matrix's structure base address
     mov     eax,[i] ;eax holds line coordinate
     dec     eax
     mul     dword [ebx+(4h*0)] ;multiply eax by the matrix's number of lines
     add     eax,[j]
     dec     eax ;eax holds M(i,j) value position
     mov     ebx,[ebx+(4h*2)] ;ebx holds the matrix's address
     movsd   xmm0,[ebx+(8h*eax)] ;move to xmm0 the value at M(i,j)
     mov     ebx,[v] ;ebx holds address at v
     movsd   [ebx],xmm0 ;move value to address that is in ebx
     pop     edx ebx ;restore saved registers
     ret
endp

proc setMatrixElem A,i,j,v ;Ok
     ; Inputs: A - Matrix (by Ref)
     ;         i - Line number
     ;         j - Column number
     ; Output: v - Value to be inserted at M(i,j) (by Ref)
     push    ebx ecx edx ;save registers
     mov     ecx,[v] ;ecx holds the address at v
     movsd   xmm0,[ecx] ;xmm0 holds the value to be inserted at M(i,j)
     mov     ebx,[A] ;ebx holds matrix's structure base address
     mov     eax,[i] ;eax holds line coordinate
     dec     eax
     mul     dword [ebx+(4h*0)] ;multiply eax by the matrix's number of lines
     add     eax,[j]
     dec     eax ;eax holds M(i,j) value position
     mov     ebx,[ebx+(4h*2)] ;ebx holds the matrix's address
     movsd   [ebx+(8h*eax)],xmm0 ;move to M(i,j) the value at xmm0
     pop     edx ecx ebx ;restore saved registers
     ret
endp

proc getSumLij L,U,i,j,v ;Ok
     ; Inputs: L - Matrix L (By Ref)
     ;         U - Matrix U (By Ref)
     ;         i - Line number
     ;         j - Column number
     ; Output: v - Sum (by Ref)
     push    ebx
     xorpd   xmm3,xmm3 ;xmm3 holds the Sum
     mov     ebx,1     ;ebx holds local variable p
  .beginsum:
     cmp     ebx,[j]
     jge     .endsum
     stdcall getMatrixElem,[L],[i],ebx,r
     movsd   xmm4,[r]  ;r holds L(i,p)
     stdcall getMatrixElem,[U],ebx,[j],r
     mulsd   xmm4,[r]  ;r holds U(p,j), xmm4 will hold L(i,p)*U(p,j)
     addsd   xmm3,xmm4	;xmm3 holds the sum
     inc     ebx  ;increase p
     jmp     .beginsum
  .endsum:
     mov     ebx,[v] ;v holds the output address
     movsd   [ebx],xmm3  ;move sum to output address
     pop     ebx
     ret
endp

proc getSumUij L,U,i,j,v  ;OK
     ; Inputs: L - Matrix L (By Ref)
     ;         U - Matrix U (By Ref)
     ;         i - Line number
     ;         j - Column number
     ; Output: v - Sum (by Ref)
     push    ebx
     xorpd   xmm3,xmm3 ;xmm3 holds the Sum
     mov     ebx,1   ;ebx holds local variable p
  .beginsum:
     cmp     ebx,[i]
     jge     .endsum
     stdcall getMatrixElem,[L],[i],ebx,r
     movsd   xmm4,[r]  ;r holds L(i,p)
     stdcall getMatrixElem,[U],ebx,[j],r
     mulsd   xmm4,[r]  ;r holds U(p,j), xmm4 will hold L(i,p)*U(p,j)
     addsd   xmm3,xmm4	;xmm3 holds the sum
     inc     ebx  ;increase p
     jmp     .beginsum
  .endsum:
     mov     ebx,[v]  ;v holds the output address
     movsd   [ebx],xmm3 ;move sum to output address
     pop     ebx
     ret
endp

proc getLij A,L,U,i,j,Lij ;Ok
     ; Inputs: A - Matrix A (By Ref)
     ;         L - Matrix L (By Ref)
     ;         U - Matrix U (By Ref)
     ;         i - Line number
     ;         j - Column number
     ; Output: Lij - L(i,j) (by Ref)
     push    ebx
     mov     ebx,[Lij]
     stdcall getMatrixElem,[A],[i],[j],tmp  ;tmp holds A(i,j)
     stdcall getSumLij,[L],[U],[i],[j],r
     movsd   xmm0,[tmp] ;tmp holds A(i,j)
     subsd   xmm0,[r]	;r holds Sum
     movsd   [tmp],xmm0 ;tmp will hold A(i,j)-Sum
     stdcall getMatrixElem,[U],[j],[j],r
     movsd   xmm0,[tmp] ;tmp holds A(i,j)-Sum
     divsd   xmm0,[r]  ;r holds U(j,j) and xmm0 wil hold (A(i,j)-Sum)/U(j,j)
     movsd   [ebx],xmm0
     pop     ebx
     ret
endp

proc getUij A,L,U,i,j,Uij
     ; Inputs: A - Matrix A (By Ref)
     ;         L - Matrix L (By Ref)
     ;         U - Matrix U (By Ref)
     ;         i - Line number
     ;         j - Column number
     ; Output: Uij - L(i,j) (by Ref)
     push    ebx
     mov     ebx,[Uij]
     stdcall getMatrixElem,[A],[i],[j],tmp ;tmp holds A(i,j)
     stdcall getSumUij,[L],[U],[i],[j],r
     movsd   xmm0,[tmp] ;tmp holds A(i,j)
     subsd   xmm0,[r]  ;r holds Sum and xmm0 will hold A(i,j)-Sum
     movsd   [ebx],xmm0
     pop     ebx
     ret
endp

proc LUdecompose A,L,U
     ; Inputs: A - Matrix A (By Ref)
     ;         L - Matrix L (By Ref)
     ;         U - Matrix U (By Ref)
     ;         i - Line number
     ;         j - Column number
     ; Output: L - Matrix L (By Ref)
     ;         U - Matrix U (By Ref)
     push    ebx ecx edx
     mov     eax,[A]
     mov     ebx,[eax+4h*0] ;ebx holds the number of lines of A (n)
     mov     ecx,1  ;Line number (i)
     mov     edx,1  ;Column number (j)
  .begin:
     cmp     ecx,ebx  ;cmp i,n
     jg      .endfill
     mov     edx,1  ;reset column number counter
  .fillcolumn:
     cmp     edx,ebx  ;cmp j,n
     jg      .endcolumn
     cmp     ecx,edx ;cmp i,j
     jle     .U
     stdcall getLij,[A],[L],[U],ecx,edx,r
     stdcall setMatrixElem,[L],ecx,edx,r
     inc     edx
     jmp     .fillcolumn
  .U:
     stdcall getUij,[A],[L],[U],ecx,edx,r
     stdcall setMatrixElem,[U],ecx,edx,r
     inc     edx
     jmp     .fillcolumn
  .endcolumn:
     inc     ecx
     jmp     .begin
  .endfill:
     pop     edx ecx ebx
     ret
endp

proc getArrayElem A,i,v ;OK
     ; Inputs: A - Matrix (by Ref)
     ;         i - index
     ; Output: v - Value at A(i) (by Ref)
     push    ebx     ;save registers
     mov     ebx,[A] ;ebx holds matrix's structure base address
     mov     ebx,[ebx+(4h*1)] ;ebx holds the array's address
     mov     eax,[i] ;eax holds line coordinate
     dec     eax
     movsd   xmm0,[ebx+(8h*eax)] ;move to xmm0 the value at M(i,j)
     mov     ebx,[v] ;ebx holds address at v
     movsd   [ebx],xmm0 ;move value to address that is in ebx
     pop     ebx ;restore saved registers
     ret
endp

proc setArrayElem A,i,v ;Ok
     ; Inputs: A - Matrix (by Ref)
     ;         i - index
     ; Output: v - Value to be inserted at A(i) (by Ref)
     push    ebx  ;save registers
     mov     ebx,[v] ;ecx holds the address at v
     movsd   xmm0,[ebx] ;xmm0 holds the value to be inserted at M(i,j)
     mov     ebx,[A] ;ebx holds matrix's structure base address
     mov     ebx,[ebx+(4h*1)] ;ebx holds the array's address
     mov     eax,[i] ;eax holds line coordinate
     dec     eax
     movsd   [ebx+(8h*eax)],xmm0 ;move to M(i,j) the value at xmm0
     pop     ebx ;restore saved registers
     ret
endp

proc getSumLy L,y,i,v
     ; Inputs: L - Matrix L (By Ref)
     ;         y - Array y (By Ref)
     ;         i - index
     ; Output: v - Sum (by Ref)
     push    ebx
     xorpd   xmm3,xmm3 ;xmm3 holds the Sum
     mov     ebx,1   ;ebx holds local variable i
  .beginsum:
     cmp     ebx,[i]
     jge     .endsum
     stdcall getMatrixElem,[L],[i],ebx,r
     movsd   xmm4,[r]  ;r holds L(i,p)
     stdcall getArrayElem,[y],ebx,r
     mulsd   xmm4,[r]  ;r holds U(p,j), xmm4 will hold L(i,p)*U(p,j)
     addsd   xmm3,xmm4	;xmm3 holds the sum
     inc     ebx  ;increase p
     jmp     .beginsum
  .endsum:
     mov     ebx,[v]  ;v holds the output address
     movsd   [ebx],xmm3 ;move sum to output address
     pop     ebx
     ret
endp

proc LybSolve L,y,b
     ; Inputs: L - Matrix L (By Ref)
     ;         y - Array y (By Ref)
     ;         b - Array b (By Ref)
     ; Output: Uij - L(i,j) (by Ref)
     push    ebx ecx
     mov     eax,[L]
     mov     ebx,[eax+4h*0] ;ebx holds the number of lines of L (n)
     mov     ecx,1  ;Line number (i)
  .begin:
     cmp     ecx,ebx  ;cmp i,n
     jg      .endfill
     stdcall getArrayElem,[b],ecx,tmp
     stdcall getSumLy,[L],[y],ecx,r
     movsd   xmm0,[tmp]
     subsd   xmm0,[r]
     movsd   [r],xmm0
     stdcall setArrayElem,[y],ecx,r
     inc     ecx
     jmp     .begin
  .endfill:
     pop     ecx ebx
     ret
endp

proc getSumUx U,x,i,v
     ; Inputs: U - Matrix U (By Ref)
     ;         x - Array x (By Ref)
     ;         i - index
     ; Output: v - Sum (by Ref)
     push    ebx
     mov     eax,[x] ;eax holds x structure base address
     mov     ebx,[eax+4h*0] ;ebx holds the size of array x
     xorpd   xmm3,xmm3 ;xmm3 holds the Sum
  .beginsum:
     cmp     ebx,[i]
     je     .endsum
     stdcall getMatrixElem,[U],[i],ebx,r
     movsd   xmm4,[r]  ;r holds L(i,p)
     stdcall getArrayElem,[x],ebx,r
     mulsd   xmm4,[r]  ;r holds U(p,j), xmm4 will hold L(i,p)*U(p,j)
     addsd   xmm3,xmm4	;xmm3 holds the sum
     dec     ebx  ;increase p
     jmp     .beginsum
  .endsum:
     mov     ebx,[v]  ;v holds the output address
     movsd   [ebx],xmm3 ;move sum to output address
     pop     ebx
     ret
endp

proc UxySolve U,x,y
     ; Inputs: U - Matrix U (By Ref)
     ;         x - Array x (By Ref)
     ;         y - Array y (By Ref)
     ; Output: Uij - L(i,j) (by Ref)
     push    ebx ecx
     mov     eax,[x]
     mov     ebx,[eax+4h*0] ;ebx holds the size of x
  .begin:
     cmp     ebx,1  ;cmp i,n
     jl      .endfill
     stdcall getArrayElem,[y],ebx,tmp
     stdcall getSumUx,[U],[x],ebx,r
     movsd   xmm0,[tmp]
     subsd   xmm0,[r]
     movsd   [tmp],xmm0
     stdcall getMatrixElem,[U],ebx,ebx,r
     movsd   xmm0,[tmp]
     divsd   xmm0,[r]
     movsd   [r],xmm0
     stdcall setArrayElem,[x],ebx,r
     dec     ebx
     jmp     .begin
  .endfill:
     pop     ecx ebx
     ret
endp

proc LUsolve A,L,U,b,y,x
     stdcall  LUdecompose,[A],[L],[U] ;Find L and U where (A = L . U)
     stdcall  LybSolve,[L],[y],[b] ;Find y where (L . y = b)
     stdcall  UxySolve,[U],[x],[y] ;Find x where (U . x = y)
     ret
endp

proc WriteArray2Buffer A,buffer
     ; Inputs: A - Array A (By Ref)
     ; Output: buffer - To recieve string (by Ref)
  locals
     ni      dd ?
     i	     dd ?
  endl
     push    ebx
     mov     ebx,[A]
     mov     eax,[ebx+(4h*0)]
     mov     [ni],eax	;nl holds the number of items
     mov     [i],1  ;index
  .beginning:
     mov     eax,[i]
     cmp     eax,[ni]
     jg      .endprint
     cmp     [i],1
     jne     .middlecolumn
     stdcall getArrayElem,[A],[i],r
     invoke  sprintf,numbuff,fmt1,double [r]
     invoke  sprintf,txtbuff,fmt2,numbuff
     invoke  lstrcat,[buffer],txtbuff
     inc     [i]
     jmp     .beginning
  .middlecolumn:
     mov     eax,[i]
     cmp     eax,[ni]
     je      .lastcolumn
     stdcall getArrayElem,[A],[i],r
     invoke  sprintf,numbuff,fmt1,double [r]
     invoke  sprintf,txtbuff,fmt3,numbuff
     invoke  lstrcat,[buffer],txtbuff
     inc     [i]
     jmp     .beginning
  .lastcolumn:
     stdcall getArrayElem,[A],[i],r
     invoke  sprintf,numbuff,fmt1,double [r]
     invoke  sprintf,txtbuff,fmt4,numbuff
     invoke  lstrcat,[buffer],txtbuff
   .endprint:
     pop     ebx
     ret
endp

proc WriteMatrix2Buffer A,buffer
     ; Inputs: A - Matrix A (By Ref)
     ; Output: buffer - To recieve string (by Ref)
  locals
     nl      dd ?
     nc      dd ?
     i	     dd ?
     j	     dd ?
  endl
     push    ebx
     mov     ebx,[A]
     mov     eax,[ebx+(4h*0)]
     mov     [nl],eax	;nl holds the number of lines
     mov     eax,[ebx+(4h*1)]
     mov     [nc],eax  ;nc holds the number of columns
     mov     [i],1  ;i holds line counter
     mov     [j],1  ;j holds column counter
  .beginning:
     mov     eax,[i]
     cmp     eax,[nl]
     jg      .endprint
     cmp     [j],1
     jne     .middlecolumn
     stdcall getMatrixElem,[A],[i],[j],r
     invoke  sprintf,numbuff,fmt1,double [r]
     invoke  sprintf,txtbuff,fmt2,numbuff
     invoke  lstrcat,[buffer],txtbuff
     inc     [j]
     jmp     .beginning
  .middlecolumn:
     mov     eax,[j]
     cmp     eax,[nc]
     je      .lastcolumn
     stdcall getMatrixElem,[A],[i],[j],r
     invoke  sprintf,numbuff,fmt1,double [r]
     invoke  sprintf,txtbuff,fmt3,numbuff
     invoke  lstrcat,[buffer],txtbuff
     inc     [j]
     jmp     .beginning
  .lastcolumn:
     stdcall getMatrixElem,[A],[i],[j],r
     invoke  sprintf,numbuff,fmt1,double [r]
     invoke  sprintf,txtbuff,fmt4,numbuff
     invoke  lstrcat,[buffer],txtbuff
     mov     [j],1
     inc     [i]
     jmp     .beginning
   .endprint:
     pop     ebx
     ret
endp

section '.bss' data readable writeable

  align 16
  r	   dq ?
  tmp	   dq ?
  numbuff  rb 1024
  txtbuff  rb 1024

section '.data' data readable writeable

  fmt1 db '%2.6f',0
  fmt2 db '    |%10s',0
  fmt3 db '    %10s',0
  fmt4 db '    %10s |',13,10,0

section '.idata' import data readable writeable

  library kernel32,'KERNEL32.DLL',\
	  advapi32,'ADVAPI32.DLL',\
	  user32,'USER32.DLL',\
	  msvcrt,'MSVCRT.DLL'

  include 'API\KERNEL32.INC'
  include 'API\ADVAPI32.INC'
  include 'API\USER32.INC'

  import msvcrt,\
	 sprintf,'sprintf'

section '.edata' export data readable

  export 'LUSOLVE.DLL',\
	 LUdecompose,'LUdecompose',\
	 LybSolve,'LybSolve',\
	 UxySolve,'UxySolve',\
	 LUsolve,'LUsolve',\
	 WriteMatrix2Buffer,'WriteMatrix2Buffer',\
	 WriteArray2Buffer,'WriteArray2Buffer'

section '.reloc' fixups data discardable
