FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin for Harbour/xHarbour matrices multiplication
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
matrices multiplication
Posted: Sun Oct 11, 2020 11:53 AM
Code (fw): Select all Collapse
function Main()

   ? MatrixMult( { { 1, 2 }, { 3, 4 } },;
                 { { 11, 12 }, { 13, 14 } } )
          
return nil

function MatrixMult( aMatrix1, aMatrix2 )

   local nRowsMatrix1 := Len( aMatrix1 )
   local nColsMatrix2 := Len( aMatrix2[ 1 ] )
   local aRowMatrix1, aRowMatrix2, nValRowMatrix1
   local aResult := Array( nRowsMatrix1, nColsMatrix2  ), nSum
   
   aMatrix2 = ArrTranspose( aMatrix2, .F. )
   
   for each aRowMatrix1 in aMatrix1
      for each aRowMatrix2 in aMatrix2
        nSum = 0
        for each nValRowMatrix1 in aRowMatrix1
          ? nValRowMatrix1, aRowMatrix2[ nValRowMatrix1:__enumIndex ]
          nSum += nValRowMatrix1 * aRowMatrix2[ nValRowMatrix1:__enumIndex ]
        next
        aResult[ aRowMatrix1:__enumIndex, aRowMatrix2:__enumIndex ] = nSum
      next        
   next      

return aResult

function ArrTranspose( aArray, lSquare )

   local nRows, nCols, nRow, nCol, nWidth
   local aNew

   // DEFAULT lSquare := .f.

   nRows          := Len( aArray )
   if lSquare
      nCols       := Len( aArray[ 1 ] )
   else
      nCols       := 1
      for nRow := 1 to nRows
         if ValType( aArray[ nRow ] ) == 'A'
            nCols    := Max( nCols, Len( aArray[ nRow ] ) )
         endif
      next
   endif

   aNew           := Array( nCols, nRows )
   for nRow := 1 to nRows
      if ValType( aArray[ nRow ] ) == 'A'
         nWidth  := Len( aArray[ nRow ] )
         for nCol := 1 to nWidth
            aNew[ nCol, nRow ]   := aArray[ nRow, nCol ]
         next
      else
         aNew[ 1, nRow ]      := aArray[ nRow ]
      endif
   next

return aNew


1 11
2 13
1 12
2 14
3 11
4 13
3 12
4 14
{{37, 40}, {85, 92}}
regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: matrices multiplication
Posted: Mon Oct 12, 2020 10:14 AM
regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 375
Joined: Tue Feb 10, 2015 09:48 AM
Re: matrices multiplication
Posted: Mon Oct 12, 2020 10:27 AM
Nice, now some home work: :-)


I tryed:
Code (fw): Select all Collapse
function Main()
   LOCAL a := { { 1, 2, 3 }, { 4, 5, 6 } }
   LOCAL b := { { 11, 12 }, { 13, 14 }, { 15, 16 } }
   ? hb_ValToExp(MatrixMult( a,b ))
   ? hb_ValToExp(MatrixMult( b,a ))

return nil


and the result is
Posts: 375
Joined: Tue Feb 10, 2015 09:48 AM
Re: matrices multiplication
Posted: Mon Oct 12, 2020 10:54 AM
The fix is pretty simple, you swapped row and col creating the result, here the correct creation:

Code (fw): Select all Collapse
function MatrixMult( aMatrix1, aMatrix2 )

   local nRowsMatrix1 := Len( aMatrix1 )
   local nColsMatrix2 := Len( aMatrix2[ 1 ] )
   local aRowMatrix1, aRowMatrix2, nValRowMatrix1
   local aResult := Array( nRowsMatrix1, nColsMatrix2  ), nSum

in the original was
Code (fw): Select all Collapse
 local aResult := Array( nColsMatrix1, nRowsMatrix2 )
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: matrices multiplication
Posted: Mon Oct 12, 2020 11:46 AM
Dear Antonino,

Fixed in my original post

many thanks!

Mr. Rao has managed to implement an enhanced version that does not need the ArrTranspose() call.
It will be included in the next FWH build:
Code (fw): Select all Collapse
function MatrixMult( matrix1, matrix2 )

   local MatrixA, MatrixB, i, j, nRow, nCol, nRows, nCols, nSize, result, dot_product
   local cType

   // Check for scalar multiplication
   cType    := ValType( matrix1 ) + ValType( matrix2 )
   if cType != "AA"
      if cType == "NN"
         return matrix1 * matrix2
      elseif cType == "NA" .or. cType == "AN"
         if cType == "NA"
            i        := matrix1
            MatrixA  := matrix2
         else
            i        := matrix2
            MatrixA  := matrix1
         endif
         if !HB_ISARRAY( MatrixA[ 1 ] ); MatrixA := { MatrixA }; endif
         nSize       := Len( MatrixA[ 1 ] )
         for nRow := 1 to Len( MatrixA )
            for nCol := 1 to nSize
               MatrixA[ nRow, nCol ] *= i
            next
         next
         return MatrixA
      else
         ? "Invalid params"
         return nil
      endif
   endif

   if Empty( matrix1 ) .or. Empty( matrix2 )
      ? "Empty matrix"
      return nil
   endif

   // Check for single-dim arrays
   if !( HB_ISARRAY( matrix1[ 1 ] ) ); matrix1 := { matrix1 }; endif
   if !( HB_ISARRAY( matrix2[ 1 ] ) ); AEval( matrix2, { |x,i| matrix2[ i ] := { x } } ); endif

   MatrixA  := matrix1
   MatrixB  := matrix2

   // Actual Matrix Multiplication
   result   := Array( nRows := Len( MatrixA ), nCols := Len( MatrixB[ 1 ] ) )

   for nRow := 1 to nRows
      for nCol := 1 to nCols
         dot_product    := 0
         TRY
            AEval( MatrixA[ nRow ], { |n,i| dot_product += n * MatrixB[ i, nCol ] } )
         CATCH
         END
         result[ nRow, nCol ] := dot_product
      next
   next

return result
regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 10733
Joined: Sun Nov 19, 2006 05:22 AM
Re: matrices multiplication
Posted: Mon Oct 12, 2020 11:50 AM

All the new matrix functions are still under testing and may still need some fixes.

Regards



G. N. Rao.

Hyderabad, India
Posts: 6755
Joined: Wed Feb 15, 2012 08:25 PM
Re: matrices multiplication
Posted: Mon Oct 12, 2020 03:13 PM
With ArrTranspose

Code (fw): Select all Collapse
function Main()

   // [ 2, 2 ] x [ 2, 2 ] = [ 2, 2 ]
   local aMatriz1 := { { 1, 2 }, { 3, 4 } }
   local aMatriz2 := { { 11, 12 }, { 13, 14 } }

   // [ 1, 3 ] x [ 3, 1 ] = [ 2, 1 ]
   //local aMatriz1 := { { 1, -2, 3 } }
   //local aMatriz2 := { { 4 }, { 5 }, { 6 } }

   // [ 2, 3 ] x [ 3, 1 ] = [ 2, 1 ]
   //local aMatriz1 := { { 1, -2, 3 }, { 1, 0, -1 } }
   //local aMatriz2 := { { 4 }, { 5 }, { 6 } }

   // [ 1, 3 ] x [ 3, 2 ] = [ 1, 2 ]
   //local aMatriz1 := { { 1, -2, 3 } }
   //local aMatriz2 := { { 4, 2 }, { 5, 0 }, { 6, 0 } }

   // [ 1, 2 ] x [ 2, 2 ] = [ 1, 2 ]
   //local aMatriz1 := { { 1, 5 } }
   //local aMatriz2 := { { 1, 2 }, { -2, 0 } }

   // [ 2, 2 ] x [ 2, 3 ] = [ 2, 3 ]
   //local aMatriz1 := { { 1, 2 }, { -2, 0 } }
   //local aMatriz2 := { { 1, 0, 2 }, { 0, 2, 0 } }

   // [ 1, 2 ] x [ 2, 1 ] = [ 1, 1 ]
   //local aMatriz1 := { { 1, -1 } }
   //local aMatriz2 := { { 5 }, { 5 } }

   // [ 3, 2 ] x [ 2, 3 ] = [ 3, 3 ]
   //local aMatriz1 := { { 1, 2 }, { 0, -1 }, { 0, 1 } }
   //local aMatriz2 := { { 0, 3, 0 }, { 3, 0, 3 } }

   // [ 3, 3 ] x [ 3, 1 ] = [ 3, 1 ]
   //local aMatriz1 := { { 1, 0, 2 }, { 0, 2, 0 }, { 0, 1, 3 } }
   //local aMatriz2 := { { 5 }, { -1 }, { 0 } }

   // [ 3, 3 ] x [ 3, 2 ] = [ 3, 2 ]
   //local aMatriz1 := { { 1, 2, 3 }, { 0, 1, 0 }, { 3, 2, 1 } }
   //local aMatriz2 := { { 1, -1 }, { 0, 2 }, { -2, 0 } }

   // [ 3, 3 ] x [ 3, 3 ] = [ 3, 3 ]
   //local aMatriz1 := { { 1, -1, 1 }, { 2, 2, 3 }, { -2, -3, -1 } }
   //local aMatriz2 := { { 1, 0, 4 }, { 0, 2, 5 }, { 1, 3, 0 } }


   // [ 2, 3 ] x [ 3, 2 ] = [ 2, 2 ]
   //local aMatriz1 := { { 1, 2, 6 }, { 3, 4, 9 } }
   //local aMatriz2 := { { 11, 12 }, { 13, 14 }, { 6, 9 } }

   if Len( aMatriz1[ 1 ] ) = Len( aMatriz2 )
      MatrixMult( aMatriz1, aMatriz2 )
   else
      ? "Only multiply matrix if number columns first matrix equal to number rows second matrix"
   endif
         
return nil

function MatrixMult( aMatrix1, aMatrix2 )

   local x
   local y
   local z
   local nRowsMatrix1 := Len( aMatrix1 )
   local nColsMatrix1 := Len( aMatrix1[ 1 ] )
   local nRowsMatrix2 := Len( aMatrix2 )
   local nColsMatrix2 := Len( aMatrix2[ 1 ] )
   local aResult := Array( nRowsMatrix1, nColsMatrix2  )
   local nSum    := 0
   local nVal    := 0
   local nIter   := 0
   local aRowMatrix1
   local aRowMatrix2
   local nValRowMatrix1

   // Show Matrix1, Matrix2   
   ?
   For x = 1 to Len( aMatrix1 )
      ?? "[ " 
      For y = 1 to Len( aMatrix1[ x ] )
         ?? aMatrix1[ x ][ y ]
         ??  "   "
      Next y
      ?? " ]" 
      ? 
   Next x
   ?
   For x = 1 to Len( aMatrix2 )
      ?? "[ " 
      For y = 1 to Len( aMatrix2[ x ] )
         ?? aMatrix2[ x ][ y ]
         ??  "   "
      Next y
      ?? " ]" 
      ? 
   Next x

   aMatrix2 = ArrTranspose( aMatrix2, .F. )
   ? "Transpose Matrix2"
   ?
   For x = 1 to Len( aMatrix2 )
      ?? "[ " 
      For y = 1 to Len( aMatrix2[ x ] )
         ?? aMatrix2[ x ][ y ]
         ??  "   "
      Next y
      ?? " ]" 
      ? 
   Next x

   // Multiply matrix

   For x = 1 to Len( aMatrix1 )
      nSum   := 0
      aRowMatrix1 := aMatrix1[ x ]
      For y = 1 to nColsMatrix2 
          aRowMatrix2 := aMatrix2[ y ]
          nSum   := 0
          For z = 1 to Len( aRowMatrix2 )
             nVal := aRowMatrix1[ z ] * aRowMatrix2[ z ]
             nSum += nVal
          Next z
          aResult[ x ][ y ] := nSum
      Next y
   Next x

   // Show Result
   ? "Result"
   ?
   For x = 1 to Len( aResult )
      ?? "[ " 
      For y = 1 to Len( aResult[ x ] )
         ?? aResult[ x ][ y ]
         ??  "   "
      Next y
      ?? " ]" 
      ? 
   Next x

return aResult

function ArrTranspose( aArray, lSquare )

   local nRows, nCols, nRow, nCol, nWidth
   local aNew

   // DEFAULT lSquare := .f.

   nRows          := Len( aArray )
   if lSquare
      nCols       := Len( aArray[ 1 ] )
   else
      nCols       := 1
      for nRow := 1 to nRows
         if ValType( aArray[ nRow ] ) == 'A'
            nCols    := Max( nCols, Len( aArray[ nRow ] ) )
         endif
      next
   endif

   aNew           := Array( nCols, nRows )
   for nRow := 1 to nRows
      if ValType( aArray[ nRow ] ) == 'A'
         nWidth  := Len( aArray[ nRow ] )
         for nCol := 1 to nWidth
            aNew[ nCol, nRow ]   := aArray[ nRow, nCol ]
         next
      else
         aNew[ 1, nRow ]      := aArray[ nRow ]
      endif
   next

return aNew
Cristobal Navarro

Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo

El secreto de la felicidad no está en hacer lo que te gusta, sino en que te guste lo que haces
Posts: 6755
Joined: Wed Feb 15, 2012 08:25 PM
Re: matrices multiplication
Posted: Mon Oct 12, 2020 08:24 PM
Without ArrTranspose
Code (fw): Select all Collapse
function Main()

   // [ 2, 2 ] x [ 2, 2 ] = [ 2, 2 ]
   local aMatriz1 := { { 1, 2 }, { 3, 4 } }
   local aMatriz2 := { { 11, 12 }, { 13, 14 } }

   // [ 1, 3 ] x [ 3, 1 ] = [ 2, 1 ]
   //local aMatriz1 := { { 1, -2, 3 } }
   //local aMatriz2 := { { 4 }, { 5 }, { 6 } }

   // [ 2, 3 ] x [ 3, 1 ] = [ 2, 1 ]
   //local aMatriz1 := { { 1, -2, 3 }, { 1, 0, -1 } }
   //local aMatriz2 := { { 4 }, { 5 }, { 6 } }

   // [ 1, 3 ] x [ 3, 2 ] = [ 1, 2 ]
   //local aMatriz1 := { { 1, -2, 3 } }
   //local aMatriz2 := { { 4, 2 }, { 5, 0 }, { 6, 0 } }

   // [ 1, 2 ] x [ 2, 2 ] = [ 1, 2 ]
   //local aMatriz1 := { { 1, 5 } }
   //local aMatriz2 := { { 1, 2 }, { -2, 0 } }

   // [ 2, 2 ] x [ 2, 3 ] = [ 2, 3 ]
   //local aMatriz1 := { { 1, 2 }, { -2, 0 } }
   //local aMatriz2 := { { 1, 0, 2 }, { 0, 2, 0 } }

   // [ 1, 2 ] x [ 2, 1 ] = [ 1, 1 ]
   //local aMatriz1 := { { 1, -1 } }
   //local aMatriz2 := { { 5 }, { 5 } }

   // [ 3, 2 ] x [ 2, 3 ] = [ 3, 3 ]
   //local aMatriz1 := { { 1, 2 }, { 0, -1 }, { 0, 1 } }
   //local aMatriz2 := { { 0, 3, 0 }, { 3, 0, 3 } }

   // [ 3, 3 ] x [ 3, 1 ] = [ 3, 1 ]
   //local aMatriz1 := { { 1, 0, 2 }, { 0, 2, 0 }, { 0, 1, 3 } }
   //local aMatriz2 := { { 5 }, { -1 }, { 0 } }

   // [ 3, 3 ] x [ 3, 2 ] = [ 3, 2 ]
   //local aMatriz1 := { { 1, 2, 3 }, { 0, 1, 0 }, { 3, 2, 1 } }
   //local aMatriz2 := { { 1, -1 }, { 0, 2 }, { -2, 0 } }

   // [ 3, 3 ] x [ 3, 3 ] = [ 3, 3 ]
   //local aMatriz1 := { { 1, -1, 1 }, { 2, 2, 3 }, { -2, -3, -1 } }
   //local aMatriz2 := { { 1, 0, 4 }, { 0, 2, 5 }, { 1, 3, 0 } }


   // [ 2, 3 ] x [ 3, 2 ] = [ 2, 2 ]
   //local aMatriz1 := { { 1, 2, 6 }, { 3, 4, 9 } }
   //local aMatriz2 := { { 11, 12 }, { 13, 14 }, { 6, 9 } }

   if Len( aMatriz1[ 1 ] ) = Len( aMatriz2 )
      MatrixMult( aMatriz1, aMatriz2 )
   else
      ? "Only multiply matrix if number columns first matrix equal to number rows second matrix"
   endif
         
return nil

function ShowMatrix( aMatrix )

   local x
   local y

   ?
   For x = 1 to Len( aMatrix )
      ?? "[ " 
      For y = 1 to Len( aMatrix[ x ] )
         ?? aMatrix[ x ][ y ]
         ??  "   "
      Next y
      ?? " ]" 
      ? 
   Next x

Return nil


function MatrixMult( aMatrix1, aMatrix2 )

   local x
   local y
   local z
   local nRowsMatrix1 := Len( aMatrix1 )
   local nColsMatrix1 := Len( aMatrix1[ 1 ] )
   local nRowsMatrix2 := Len( aMatrix2 )
   local nColsMatrix2 := Len( aMatrix2[ 1 ] )
   local aResult := Array( nRowsMatrix1, nColsMatrix2  )
   local nSum    := 0
   local nVal0   := 0
   local nVal1   := 0
   local nIter   := 0

   ShowMatrix( aMatrix1 )
   ShowMatrix( aMatrix2 )

   For x = 1 to Len( aMatrix1 )
      For y = 1 to nColsMatrix2
         nSum   := 0
         For z = 1 to nRowsMatrix2
            nVal0  := aMatrix1[ x ][ z ]
            nVal1 := nVal0 * aMatrix2[ z ][ y ]
            nSum  += nVal1
         Next z
         aResult[ x ][ y ] := nSum
      Next y
   Next x

   ? "Resultado"
   ShowMatrix( aResult )

return aResult
Cristobal Navarro

Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo

El secreto de la felicidad no está en hacer lo que te gusta, sino en que te guste lo que haces
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: matrices multiplication
Posted: Tue Oct 13, 2020 07:36 AM
Shortest version ? :-)

Code (fw): Select all Collapse
function Main()

   ? MatrixMult( { { 1, 2 }, { 3, 4 } },;
                 { { 11, 12 }, { 13, 14 } } )

return nil

function MatrixMult( aMatrix1, aMatrix2 )

   local aRowMatrix1, nColMatrix2, nRowMatrix2
   local aResult := Array( Len( aMatrix1 ), Len( aMatrix2[ 1 ] ) )

   for each aRowMatrix1 in aMatrix1
      for nColMatrix2 = 1 to Len( aMatrix2[ 1 ] )
         nSum = 0
         for nRowMatrix2 = 1 to Len( aMatrix2 )
            nSum += aRowMatrix1[ nRowMatrix2 ] * aMatrix2[ nRowMatrix2 ][ nColMatrix2 ]
         next 
         aResult[ aRowMatrix1:__enumIndex ][ nColMatrix2 ] := nSum
      next 
   next    
   
return aResult


{{37, 40}, {85, 92}}
regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: matrices multiplication
Posted: Tue Oct 13, 2020 08:22 AM
Shortest version based on Mr. Rao version:

Code (fw): Select all Collapse
function Main()

   ? MatrixMult( { { 1, 2 }, { 3, 4 } },;
                 { { 11, 12 }, { 13, 14 } } )

return nil

function MatrixMult( aMatrix1, aMatrix2 )

   local aRowMatrix1, nSum, nCols := Len( aMatrix2[ 1 ] )
   local aResult := Array( Len( aMatrix1 ), nCols )

   for each aRowMatrix1 in aMatrix1
      for nCol := 1 to nCols
         nSum = 0
         AEval( aRowMatrix1, { |n,i| nSum += n * aMatrix2[ i, nCol ] } )
         aResult[ aRowMatrix1:__enumIndex, nCol ] = nSum
      next
   next

return aResult


{{37, 40}, {85, 92}}
{ { 1*11 + 2*13, 1*12 + 2*14 }, { 3*11 + 4*13, 3*12 + 4*14 }}
regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 7317
Joined: Thu Oct 18, 2012 07:17 PM
Re: matrices multiplication
Posted: Tue Oct 13, 2020 05:58 PM

I am very intrigued, I did not understand what you are trying to do, I want to participate too if it comes to things to eat (cakes, sweets, ..) even if I have to go on a diet I know !!!

Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)

I use : FiveWin for Harbour March-April 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: matrices multiplication
Posted: Tue Oct 13, 2020 06:09 PM
regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 7317
Joined: Thu Oct 18, 2012 07:17 PM
Re: matrices multiplication
Posted: Tue Oct 13, 2020 06:54 PM
Antonio Linares wrote:Dear Silvio,

viewtopic.php?f=44&t=39467


Dear antonio

I know that Python

it is a multi-paradigm language, which supports both procedural programming (which makes use of functions) and object-oriented programming (including features such as single and multiple inheritance, but Harbor also supports these two things. and then I don't understand what is needed to convert programs made on python to harbour that is, I do not see the need, if you have something else in mind that I do not know I raise my hands
a colleague of mine ( school) builds programs with python but uses additional tools for graphics and more (TkInter which also includes the graphical interface management system, which is what you see when you use the program. Other tools to mention are PYQt and wxPython.), he use pyton to create games (PyGame, PyKyra and the 3D rendering engines)

There are things that Python can't do well, or at all.

For example it is not a low-level language and therefore not good for creating components such as drivers.

It is not suitable for creating cross-platform executables and it is not even the ideal choice if the code must be as fast as possible.

Historically it has been mainly used for scripting and automation elements in fact my colleague uses it with Arduino
Since from 1991/1992 ( fw for clipper Rel. 14.4 - Momos)

I use : FiveWin for Harbour March-April 2024 - Harbour 3.2.0dev (harbour_bcc770_32_20240309) - Bcc7.70 - xMate ver. 1.15.3 - PellesC - mail: silvio[dot]falconi[at]gmail[dot]com
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: matrices multiplication
Posted: Tue Oct 13, 2020 09:21 PM

Dear Silvio,

My interest in porting those 9 lines from Python to Harbour is in building a small and simple neural network to be used from Harbour and mainly for learning purposes :-)

regards, saludos

Antonio Linares
www.fivetechsoft.com

Continue the discussion