Author Topic: Matrice operation (v1[x] = v[0][x] - v[1][x])  (Read 369 times)

TouEnMasm

  • Member
  • *****
  • Posts: 1805
    • EditMasm
Matrice operation (v1[x] = v[0][x] - v[1][x])
« on: July 28, 2021, 06:21:13 PM »
Hello,
Is someone  have written macros to solve this form of operations: v1
  • = v[0]
  • - v[1]
  •     ?

Fa is a musical note to play with CL

HSE

  • Member
  • *****
  • Posts: 1744
  • <AMD>< 7-32>
Re: Matrice operation (v1[x] = v[0][x] - v[1][x])
« Reply #1 on: July 28, 2021, 10:33:30 PM »
Hi Yves!

Using macros in mtx.inc : http://masm32.com/board/index.php?topic=8398.0. Requiere JWasm family because there are macros creating macros.

 Using Matrix.inc in ObjAsm: http://masm32.com/board/index.php?topic=8583.0.  Examples of use are in ObjAsm32. This Matrix.inc is a modification in progress of that.

A litle more specific and in development, perhaps using a more advanced mtx.inc (I have to see :biggrin:). Also in ObjAsm I'm translating some C++ code:
Code: (Matri2D_OOP.inc) [Select]
;/*!
; * \file
; * Scanline edge-flag algorithm for antialiasing <br>
; * Copyright (c) 2005-2007 Kiia Kallio
; *
; * http://mlab.uiah.fi/~kkallio/antialiasing/
; *
; * This code is distributed under the three-clause BSD license.
; * Read the LICENSE file or visit the URL above for details.
; *
; * \brief A simple 2d matrix class.
; *
; *
; * $Id: $
; * $Date: $
; * $Revision: $
; */


MATRIX2D textequ <POINTER>
defMATRIX2D macro var1
DefineVariable &var1, MATRIX2D, 0
endm

;//! A simple 2d matrix class.
Object Matrix2D,, Primer

    ; Makes a rotation matrix.
    ;void makeRotation(RATIONAL aAngle);
    VirtualMethod makeRotation, RATIONAL

    ; Makes a translation matrix.
    ;void makeTranslation(const Vector2d &aTranslation);
    VirtualMethod makeTranslation, POINTER
   
    ; Makes a scaling matrix.
    ;void makeScaling(const Vector2d &aScale);
    VirtualMethod makeScaling, POINTER

    ; Makes an identity matrix.
    ;void makeIdentity();
    VirtualMethod makeIdentity

    ; Rotates the matrix by an angle
    ;void rotate(RATIONAL rotate);
    VirtualMethod rotate, RATIONAL

    ; Translates the matrix with a vector.
    ;void translate(const Vector2d &aTranslation);
    VirtualMethod translate, POINTER

    ; Scales the matrix with a vector.
    ;void scale(const Vector2d &aScale);
    VirtualMethod scale, POINTER

    ; Multiplies the matrix with another matrix.
    ;void multiply(const Matrix2d &aMatrix);
    VirtualMethod multiply, POINTER

    ; Transforms a point with the matrix.
    ;void transform(const Vector2d &aSource, Vector2d &aTarget) const;
    VirtualMethod transform, POINTER, POINTER

    DIMOA mMatrix, RATIONAL, 3, 2
   
ObjectEnd

;#define MATRIX2D_MAKEROTATION(aMatrix,aAngle) aMatrix.makeRotation(aAngle)
;#define MATRIX2D_MAKETRANSLATION(aMatrix,aTranslation) aMatrix.makeTranslation(aTranslation)
MATRIX2D_MAKESCALING macro aMatrix, aScale
OCall &aMatrix::Matrix2D.makeScaling, &aScale
endm
MATRIX2D_MAKEIDENTITY macro aMatrix
OCall &aMatrix::Matrix2D.makeIdentity
endm
;#define MATRIX2D_ROTATE(aMatrix,aAngle) aMatrix.rotate(aAngle)
MATRIX2D_TRANSLATE macro aMatrix, aTranslation
OCall &aMatrix::Matrix2D.translate, &aTranslation
endm
;#define MATRIX2D_SCALE(aMatrix,aScale) aMatrix.scale(aScale)
MATRIX2D_MULTIPLY macro aMatrix, aMultiplier
OCall &aMatrix::Matrix2D.multiply, &aMultiplier
endm

MATRIX2D_TRANSFORM macro aMatrix,aSource,aResult
  OCall &aMatrix::Matrix2D.transform, &aSource, &aResult
endm
;#define MATRIX2D_GET_M11(aMatrix) aMatrix.mMatrix[0][0]
;#define MATRIX2D_GET_M12(aMatrix) aMatrix.mMatrix[0][1]
;#define MATRIX2D_GET_M21(aMatrix) aMatrix.mMatrix[1][0]
;#define MATRIX2D_GET_M22(aMatrix) aMatrix.mMatrix[1][1]
;#define MATRIX2D_GET_DX(aMatrix) aMatrix.mMatrix[2][0]
;#define MATRIX2D_GET_DY(aMatrix) aMatrix.mMatrix[2][1]

Code: (Matrix2D_PROC.inc) [Select]
; * Scanline edge-flag algorithm for antialiasing <br>
; * Copyright (c) 2005-2007 Kiia Kallio
; *
; * http:;mlab.uiah.fi/~kkallio/antialiasing/
; *
; * This code is distributed under the three-clause BSD license.
; * Read the LICENSE file or visit the URL above for details.
; *
; * \brief A simple 2d matrix class.


; Makes a rotation matrix.
Method Matrix2D.makeRotation, uses xsi, aAngle : RATIONAL
local sinRot : RATIONAL
local cosRot : RATIONAL

SetObject xsi
   
    fSlv8 sinRot = sin(aAngle)
    fSlv8 cosRot = cos(aAngle)

    fSlv8 mMatrix(0,0) = cosRot
    fSlv8 mMatrix(0,1) = sinRot
    fSlv8 mMatrix(1,0) = -sinRot
    fSlv8 mMatrix(1,1) = cosRot
    fSlv8 mMatrix(2,0) = 0
    fSlv8 mMatrix(2,1) = 0
   
MethodEnd

; Makes a translation matrix.
Method Matrix2D.makeTranslation, uses xsi, aTranslation : POINTER

SetObject xsi
SetObject xdx, Vector2D, aTranslation

    fSlv8 mMatrix(0,0) = 1
    fSlv8 mMatrix(0,1) = 0
    fSlv8 mMatrix(1,0) = 0
    fSlv8 mMatrix(1,1) = 1
    fSlv8 mMatrix(2,0) = [xdx].mX
    fSlv8 mMatrix(2,1) = [xdx].mY

MethodEnd

; Makes a scaling matrix.
Method Matrix2D.makeScaling, uses xsi, aScale :POINTER

    SetObject xsi
    SetObject xdx, Vector2D, aScale
   
    fSlv8 mMatrix(0,0) = [xdx].mX;
    fSlv8 mMatrix(0,1) = 0
    fSlv8 mMatrix(1,0) = 0
    fSlv8 mMatrix(1,1) = [xdx].mY;
    fSlv8 mMatrix(2,0) = 0
    fSlv8 mMatrix(2,1) = 0
   
MethodEnd

; Makes an identity matrix.
Method Matrix2D.makeIdentity, uses xsi

    SetObject xsi
   
    fSlv8 mMatrix(0,0) = 1
    fSlv8 mMatrix(0,1) = 0
    fSlv8 mMatrix(1,0) = 0
    fSlv8 mMatrix(1,1) = 1
    fSlv8 mMatrix(2,0) = 0
    fSlv8 mMatrix(2,1) = 0
   
MethodEnd

; Rotates the matrix by an angle
Method Matrix2D.rotate, uses xsi, rotate : RATIONAL
local tmp : POINTER

    SetObject xsi

    New Matrix2D
    mov tmp, xax
    OCall tmp::Matrix2D.makeRotation, rotate
    OCall xsi.multiply, tmp
    Destroy tmp
MethodEnd


; Translates the matrix with a vector.
Method Matrix2D.translate, uses xsi, aTranslation : POINTER
local tmp : POINTER

    SetObject xsi

;SetObject xdx, Vector2D, aTranslation ;pointer to Vector2d
    New Matrix2D
    mov tmp, xax
    OCall tmp::Matrix2D.makeTranslation, aTranslation
    OCall xsi.multiply, tmp
    Destroy tmp
   
MethodEnd

; Scales the matrix with a vector.
Method Matrix2D.scale, uses xsi, aScale : POINTER
local tmp : POINTER

    SetObject xsi
;Vector2d
    New Matrix2D; tmp;
    mov tmp, xax
    OCall tmp::Matrix2D.makeScaling, aScale
    OCall xsi.multiply, tmp
    Destroy tmp
   
MethodEnd


; Multiplies the matrix with another matrix.
Method Matrix2D.multiply, uses xsi xdi, aMatrix : POINTER
local tmp : POINTER

SetObject xsi

New Matrix2D
    mov tmp, eax
   
    CopiaObjeto OA_Matrix2D, tmp
   
SetObject xdi, Matrix2D, aMatrix
SetObject xdx, Matrix2D, tmp
   
    fSlv8 mMatrix(0,0) = mMatrixP(xdx,0,0) * mMatrixP(xdi,0,0) +\
                    mMatrixP(xdx,0,1) * mMatrixP(xdi,1,0);
    fSlv8 mMatrix(0,1) = mMatrixP(xdx,0,0) * mMatrixP(xdi,0,1) +\
                    mMatrixP(xdx,0,1) * mMatrixP(xdi,1,1);
    fSlv8 mMatrix(1,0) = mMatrixP(xdx,1,0) * mMatrixP(xdi,0,0) +\
                    mMatrixP(xdx,1,1) * mMatrixP(xdi,1,0);
    fSlv8 mMatrix(1,1) = mMatrixP(xdx,1,0) * mMatrixP(xdi,0,1) +\
                    mMatrixP(xdx,1,1) * mMatrixP(xdi,1,1);
    fSlv8 mMatrix(2,0) = mMatrixP(xdx,2,0) * mMatrixP(xdi,0,0) +\
                    mMatrixP(xdx,2,1) * mMatrixP(xdi,1,0) +\
                    mMatrixP(xdi,2,0);
    fSlv8 mMatrix(2,1) = mMatrixP(xdx,2,0) * mMatrixP(xdi,0,1) +\
                    mMatrixP(xdx,2,1) * mMatrixP(xdi,1,1) +\
                    mMatrixP(xdi,2,1);
   DbgFloat mMatrix(0,0)                 
   DbgFloat mMatrix(0,1)                 
   DbgFloat mMatrix(1,0)                 
   DbgFloat mMatrix(1,1)                 
   DbgFloat mMatrix(2,0)                 
   DbgFloat mMatrix(2,1)                 
             ;Ç
    Destroy tmp
             
MethodEnd


; Transforms a point with the matrix.
Method Matrix2D.transform, uses xsi xdi, aSource : POINTER, aTarget :POINTER
local vector2D : $Obj(Vector2D)

DbgMtit
    SetObject xsi

SetObject xdi, Vector2D, aSource
DbgHex xdi
DbgHex aTarget

.if xdi == aTarget
lea xax, vector2D
SetObject xdx, Vector2D, xax
.else
SetObject xdx, Vector2D, aTarget
.endif
DbgHex xdx

    fSlv8 [xdx].mX = mMatrix(0,0) * [xdi].mX + mMatrix(1,0) * [xdi].mY + mMatrix(2,0)
fSlv8 [xdx].mY = mMatrix(0,1) * [xdi].mX + mMatrix(1,1) * [xdi].mY + mMatrix(2,1)
.if xdi == aTarget
lea xax, vector2D
SetObject xdi, Vector2D, xax
SetObject xdx, Vector2D, aTarget
fSlv8 [xdx].mX = [xdi].mX
fSlv8 [xdx].mY = [xdi].mY
.endif

DbgMsal
MethodEnd

Yes. To include matrix in objects  requiere this:
Code: (mtx.inc) [Select]
;* @ArgI - Macro function returns an argument specified by number
;* from a VARARG list.
;*
;* Params:  index - one-based number of the argument to be returned
;*          arglist - argument list
@ArgI MACRO index:REQ, arglist:VARARG
    LOCAL count,retstr
    count = 0
    FOR arg,<arglist>
        count = count + 1
        IF count EQ index
            retstr TEXTEQU <arg>
        ENDIF
    ENDM
    EXITM retstr
ENDM


;mtx_tls_warning_line = -1
;@mtxTLS_warning macro
; IF mtx_tls_warning_line NE @Line
; %echo @FileCur: WARNING: code not thread save: line @CatStr(%@Line)
; ENDIF
; mtx_tls_warning_line = @Line
;endm

mtxTLS_curr_line = -1
mtxTLS_curr_file textequ <>


; mod1 0 = variable, 1 = structure
; mod2 0 = standard, 1 = SmplMath
; mod3 0 = plain, 1 = ObjAsm

DIM_MASTER macro isStruct, isSmpMth, isOA, nombre, tipo, dimensions:VARARG
   local value1
   value1 textequ <1>
   count = 0
    FOR dimension, <&dimensions>
        value1 CATSTR value1 , <*>, %dimension
    ENDM
    if isOA eq 0
    if isStruct eq 0
        nombre&_mtx &tipo value1 dup (?)
    else
        nombre&_mtx &tipo value1 dup (<?>)
    endif
    else
    nombre&_mtx_type textequ <&tipo>
    if isStruct eq 0
        DefineVariable nombre&_mtx, &tipo, value1 dup (?)
    else
        DefineVariable nombre&_mtx, &tipo, value1 dup (<?>)
    endif
    endif

    &nombre MACRO dimensionsn:VARARG
        LOCAL count, dwidth, dist, hayc, hayv, dewidth2, nombrestore

        count = 0
        dwidth = 1
        dist = 0
        hayc = 0
        hayv = 0

        if 0   
        if &isSmpMth eq 1
        IF mtxTLS_curr_line NE @Line
        mtxTLS_curr_line = @Line
        mtxTLS_usados = 0
        ENDIF
        endif
        endif

        FOR arg,<&dimensionsn>
            oa = OPATTR arg
            if oa and 0100b
                hayc = 1
            else
                hayv = 1
            endif
        ENDM

        if hayv
            mov eax, 0
        endif

        FOR arg,<&dimensionsn>
            count = count + 1
            oa = OPATTR arg
            if oa and 0100b
            if isOA eq 0
                dwidth2 = dwidth * TYPE nombre&_mtx
                else
                dwidth2 = dwidth * TYPE nombre&_mtx_type
                endif
                dist = dist + (arg * dwidth2)
            else
                push eax
                mov eax, arg
                mov ecx, dwidth
                mul ecx       
                pop ecx
                add eax, ecx
            endif
            dwidth = dwidth * @ArgI(%count, <dimensions>)
 
        ENDM

        if hayv
            if isStruct eq 1
            if isOA eq 0
                mov ecx,  TYPE nombre&_mtx
                else
                mov ecx,  TYPE nombre&_mtx_type
                endif
                mul ecx
            endif
            if isSmpMth eq 1
            %   add eax, offset @CatStr(&nombre,<_mtx>)
                mtxTLS_usados = mtxTLS_usados + 1
           ;;     % echo @CatStr(%mtxTLS_usados)
           %     if mtxTLS_usados gt mtxTLS_reservados
                    .err   incrementar reserva mtxTLS() en @FileCur
                endif
                if hayc
                %    add eax, dist
                endif
           %     mov dword ptr SS:[ebp - mtxTLS_usados*@WordSize ], eax
            endif
        endif

        if hayv and hayc
            if isStruct eq 0   
                if isSmpMth eq 0
                if isOA eq 0
                    EXITM @CatStr(&nombre,<_mtx>,<[>,eax * TYPE nombre&_mtx+ %dist ,<]>)
                    else
                    EXITM @CatStr(<[esi].>,&nombre,<_mtx>,<[>,eax * TYPE nombre&_mtx_type+ %dist ,<]>)
                    endif
                else
                   % echo @CatStr(<add dword ptr [ebp - >,%mtxTLS_usados*@WordSize,< ],>, %dist)
                   % @CatStr(<add dword ptr SS:[ebp - >,%mtxTLS_usados*@WordSize,< ],>, %dist)
     % echo                   EXITM <@CatStr(tipo,< ptr [ebp->,%mtxTLS_usados*@WordSize,<]>)>

                    EXITM <@CatStr(tipo,< ptr [ebp->,%mtxTLS_usados*@WordSize,<]>)>
                endif
            else
                if isSmpMth eq 0
                    EXITM @CatStr(&nombre,<_mtx>,<[>,eax + %dist ,<]>)
                else
                    add dword ptr SS:[ebp - mtxTLS_usados*@WordSize ], %dist
                    EXITM <@CatStr(<[ebp->,mtxTLS_usados*@WordSize,<].>,&tipo)>
                endif
            endif

        elseif hayv
            if isStruct eq 0   
                if isSmpMth eq 0
                if isOA eq 0
                    EXITM @CatStr(&nombre,<_mtx>,<[>,eax * TYPE nombre&_mtx ,<]>)
                    else
                    EXITM @CatStr(<[esi].>,&nombre,<_mtx>,<[>,eax * TYPE nombre&_mtx_type ,<]>)
                    endif
                else
                    EXITM <@CatStr(&nombre,<_mtx>,<[ebp->,mtxTLS_usados*@WordSize,<]>)>
                endif
            else
                if isSmpMth eq 0
                if isOA eq 0
                    EXITM @CatStr(&nombre,<_mtx>,<[>,eax,<]>)
                    else
                    EXITM @CatStr(<[esi].>,&nombre,<_mtx>,<[>,eax,<]>)
                    endif
                else
                    EXITM <@CatStr(<[ebp->,mtxTLS_usados*@WordSize,<].>,&tipo)>
                endif
            endif
        elseif hayc
        if isOA eq 0
            EXITM @CatStr(&nombre,<_mtx>,<[>, %dist ,<]>)
            else
                EXITM @CatStr(<[esi].>,&nombre,<_mtx>,<[>, %dist ,<]>)
endif
        endif
    ENDM

;-------------------------------------------------------------------------------
    &nombre&P MACRO PuntReg:=<esi>, dimensionsn:VARARG
        LOCAL count, dwidth, dist, hayc, hayv, dewidth2, nombrestore

        count = 0
        dwidth = 1
        dist = 0
        hayc = 0
        hayv = 0

        if 0   
        if &isSmpMth eq 1
        IF mtxTLS_curr_line NE @Line
        mtxTLS_curr_line = @Line
        mtxTLS_usados = 0
        ENDIF
        endif
        endif

        FOR arg,<&dimensionsn>
            oa = OPATTR arg
            if oa and 0100b
                hayc = 1
            else
                hayv = 1
            endif
        ENDM

        if hayv
            mov eax, 0
        endif

        FOR arg,<&dimensionsn>
            count = count + 1
            oa = OPATTR arg
            if oa and 0100b
            if isOA eq 0
                dwidth2 = dwidth * TYPE nombre&_mtx
                else
                dwidth2 = dwidth * TYPE nombre&_mtx_type
                endif
                dist = dist + (arg * dwidth2)
            else
                push eax
                mov eax, arg
                mov ecx, dwidth
                mul ecx       
                pop ecx
                add eax, ecx
            endif
            dwidth = dwidth * @ArgI(%count, <dimensions>)
 
        ENDM

        if hayv
            if isStruct eq 1
            if isOA eq 0
                mov ecx,  TYPE nombre&_mtx
                else
                mov ecx,  TYPE nombre&_mtx_type
                endif
                mul ecx
            endif
            if isSmpMth eq 1
            %   add eax, offset @CatStr(&nombre,<_mtx>)
                mtxTLS_usados = mtxTLS_usados + 1
           ;;     % echo @CatStr(%mtxTLS_usados)
           %     if mtxTLS_usados gt mtxTLS_reservados
                    .err   incrementar reserva mtxTLS() en @FileCur
                endif
                if hayc
                %    add eax, dist
                endif
           %     mov dword ptr SS:[ebp - mtxTLS_usados*@WordSize ], eax
            endif
        endif

        if hayv and hayc
            if isStruct eq 0   
                if isSmpMth eq 0
                if isOA eq 0
                    EXITM @CatStr(&nombre,<_mtx>,<[>,eax * TYPE nombre&_mtx+ %dist ,<]>)
                    else
                    EXITM @CatStr(<[>,&PuntReg,<].>,&nombre,<_mtx>,<[>,eax * TYPE nombre&_mtx_type+ %dist ,<]>)
                    endif
                else
                   % echo @CatStr(<add dword ptr [ebp - >,%mtxTLS_usados*@WordSize,< ],>, %dist)
                   % @CatStr(<add dword ptr SS:[ebp - >,%mtxTLS_usados*@WordSize,< ],>, %dist)
     % echo                   EXITM <@CatStr(tipo,< ptr [ebp->,%mtxTLS_usados*@WordSize,<]>)>

                    EXITM <@CatStr(tipo,< ptr [ebp->,%mtxTLS_usados*@WordSize,<]>)>
                endif
            else
                if isSmpMth eq 0
                    EXITM @CatStr(&nombre,<_mtx>,<[>,eax + %dist ,<]>)
                else
                    add dword ptr SS:[ebp - mtxTLS_usados*@WordSize ], %dist
                    EXITM <@CatStr(<[ebp->,mtxTLS_usados*@WordSize,<].>,&tipo)>
                endif
            endif

        elseif hayv
            if isStruct eq 0   
                if isSmpMth eq 0
                if isOA eq 0
                    EXITM @CatStr(&nombre,<_mtx>,<[>,eax * TYPE nombre&_mtx ,<]>)
                    else
                    EXITM @CatStr(<[>,&PuntReg,<].>,&nombre,<_mtx>,<[>,eax * TYPE nombre&_mtx_type ,<]>)
                    endif
                else
                    EXITM <@CatStr(&nombre,<_mtx>,<[ebp->,mtxTLS_usados*@WordSize,<]>)>
                endif
            else
                if isSmpMth eq 0
                if isOA eq 0
                    EXITM @CatStr(&nombre,<_mtx>,<[>,eax,<]>)
                    else
                    EXITM @CatStr(<[>,&PuntReg,<].>,&nombre,<_mtx>,<[>,eax,<]>)
                    endif
                else
                    EXITM <@CatStr(<[ebp->,mtxTLS_usados*@WordSize,<].>,&tipo)>
                endif
            endif
        elseif hayc
        if isOA eq 0
            EXITM @CatStr(&nombre,<_mtx>,<[>, %dist ,<]>)
            else
                EXITM @CatStr(<[>,&PuntReg,<].>,&nombre,<_mtx>,<[>, %dist ,<]>)
endif
        endif
    ENDM




endm

DIM macro nombre, tipo, dimensions:VARARG
%    DIM_MASTER 0, 0, 0, nombre, tipo, <dimensions>
ENDM

DIMS macro nombre, tipo, dimensions:VARARG
%    DIM_MASTER 1, 0, 0, nombre, tipo, <dimensions>
ENDM

DIMOA macro nombre, tipo, dimensions:VARARG
%    DIM_MASTER 0, 0, 1, nombre, tipo, <dimensions>
ENDM
DIMSOA macro nombre, tipo, dimensions:VARARG
%    DIM_MASTER 0, 0, 1, nombre, tipo, <dimensions>
ENDM



mtxTLS macro punteros
    ifb <punteros>
    %    mtxTLS_reservados = 4*@WordSize
    else
    %    mtxTLS_reservados = &punteros*@WordSize
    endif
    mtxTLS_usados = 0
    %EXITM <mtxTLS_puntero[mtxTLS_reservados]:byte>
endm

Regards, HSE.

daydreamer

  • Member
  • *****
  • Posts: 1721
  • building nextdoor
Re: Matrice operation (v1[x] = v[0][x] - v[1][x])
« Reply #2 on: July 30, 2021, 02:38:27 AM »
Yves
I expected the kind of matrice masm macro you use, when cpu don't support dotproduct
D3d matrices library
SIMD fan and macro fan
why assembly is fastest is because its switch has no (brakes) breaks
:P
only in 16bit assembly you can get away with "Only words" :P

TouEnMasm

  • Member
  • *****
  • Posts: 1805
    • EditMasm
Re: Matrice operation (v1[x] = v[0][x] - v[1][x])
« Reply #3 on: July 30, 2021, 05:27:02 PM »

I search Macro to do it.My prefered method is to let it done by the c compiler (mixed langage c asm).
Perhap's smplmath is abble to do it but i need a demo.
After stay to write macro to do that.

Fa is a musical note to play with CL

HSE

  • Member
  • *****
  • Posts: 1744
  • <AMD>< 7-32>
Re: Matrice operation (v1[x] = v[0][x] - v[1][x])
« Reply #4 on: July 30, 2021, 10:39:26 PM »
I search Macro to do it

Only macros in Mtx.inc

Perhap's smplmath is abble to do it but i need a demo.

It's not SmplMath and, because macro expansion, only work with SmplMath in limited cases. Of course, is very interesting when can work together, how you can see in some Hydrograph lines.

Don't need SmplMath:
Code: [Select]
fild v2
                        fmul varD
                        fsub descargaunidad(v1ant, 0)
            fld descargaunidad(v1, 0)
                fsub descargaunidad(v1ant, 0)
                fdiv
                fld descargaunidad(v1, 1)
                fsub descargaunidad(v1ant, 1)
        fmul
                fadd descargaunidad(v1ant, 1)
fstp tablero2(v2, 0)
In this case I'm using real8, but you can use any type or structure.

··············································································

If you have no mind for this advanced matrix  :dazzled: (or you are using ML), you still can use the 20 years old method  :thumbsup::
Code: [Select]
        matrix macro p1 , p2 , p3, regaux, no1
            mov  eax ,  p3
            imul p1
            add  eax , p2
            ifb <no1>
                ifnb <regaux>
                    mov  &regaux , eax
                else
                    mov  ebx , eax
                endif
            endif
        endm
Code: [Select]
.data
            mat_ET1 dd 100 dup (0)
   
            mat_ATL_max equ 3
            mat_ATL real4 3*100 dup (0.0)

            mat_UTL_max equ 4
            mat_UTL real4 4*100 dup (0.0)
.code
            ···
            fild mat_ET1[ecx*4]
            matrix nn, 0, mat_ATL_max
            fst real4 ptr mat_ATL[ebx*4]
            fstp real4 ptr mat_UAT[ebx*4]
            ···
This is used in now corrected http://masm32.com/board/index.php?topic=9439.msg103363#new

Regards, HSE