News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Polynomial using SmplMath

Started by HSE, March 11, 2019, 09:59:07 AM

Previous topic - Next topic

HSE

Hi all!

Here is a little macro to solve polynomial functions of any degree simplifying writing:
    polinomica RLV, y, x, 3.63763, 0.0819586, -5.61238e-005, 1.24182e-008


First idea was:
  polinomica macro fantasyname, respuesta, variable, terminos:VARARG
     local count
     count = 0
     fldz
     FOR termino, <terminos>
fSlv8  = termino * &variable^%count
fadd
count=count+1
     ENDM
     fstp &respuesta
  endm


Very nice, elegant, etc. But there is a problem: SmplMath v2.0.2 build x^0 exactly as x^1.

Final macro is:
  polinomica macro xname, respuesta, variable, terminos:VARARG
      local count
      count = 0
      fldz
      FOR termino, <terminos>
          if count eq 0
             fSlv8  = termino
          else
             fSlv8  = termino * &variable^%count
          endif
          fadd
          count=count+1
      ENDM
      fstp &respuesta
  endm


Regards. HSE
Equations in Assembly: SmplMath

Siekmanski

Because in math, x^0 = 1 (axiom)
Creative coders use backward thinking techniques as a strategy.

HSE

Thanks Siekmanski   :t

  x^0 = 1
  x^1 = x


Problem here is that SmplMath is building  x^0 = x
Equations in Assembly: SmplMath

HSE

I found that, at least in a totally suboptimal way, is easy to prevent x^0 error:
FSLV_X86_FPU_REG0_OPRT_RCVAL macro oprt,tkn,neg_tkn
    IFIDN <&oprt>,<^>
        IF @InStr(1,<0.0>,<&tkn>) NE 0         ; +++
            EXITM <0>                          ; +++ 
        ELSE                                   ; +++
            fxsfror_pos INSTR 1,<2.0 3.0-1.0-2.0-3.0 0.5-0.5>,<&tkn>
            IF fxsfror_pos
                IF @SizeStr(<&tkn>) GE @SubStr(<100010020002000200003004000>,%fxsfror_pos,1)
                    fxsfror_powflg = @SubStr(<200030010004000500008009000>,%fxsfror_pos,1)
                    IF fxsfror_powflg EQ 2 OR fxsfror_powflg EQ 4
                        fmul st(0),st(0)
                    ELSEIF fxsfror_powflg EQ 3 OR fxsfror_powflg EQ 5
                        FSBE_STCK_CHK 1
                        fld st
                        fmul st,st
                        fmulp st(1),st(0)
                    ELSEIF fxsfror_powflg EQ 8 OR fxsfror_powflg EQ 9
                        fsqrt
                    ENDIF
                    IF (fxsfror_powflg EQ 4 OR fxsfror_powflg EQ 5 OR fxsfror_powflg EQ 1 OR fxsfror_powflg EQ 9) XOR (neg_tkn NE 0)
                        FSBE_STCK_CHK 1
                        fld1
                        fdivrp st(1),st(0)
                    ENDIF
                    EXITM <-1>
                ENDIF
            ENDIF
        ENDIF                                      ; +++
    ELSEIFIDN <&oprt>,</>
        IF @InStr(1,<1.0>,<&tkn>) EQ 1
            IF neg_tkn
                fchs
            ENDIF
            EXITM <-1>
        ELSEIF @InStr(1,<-1.0>,<&tkn>) EQ 1
            IFE neg_tkn
                fchs
            ENDIF
            EXITM <-1>
        ELSE
            fxsfror_pos INSTR <2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0 100.0 1000.0-2.0-3.0-4.0-5.0-6.0-7.0-8.0-9.0-10.0-100.0-1000.0>,<&tkn>
            IF fxsfror_pos
                IF @SizeStr(<&tkn>) GE @SubStr(<100010001000100010001000100010002000030000040000020002000200020002000200020002000300004000005000000>,%fxsfror_pos,1)
                    IF @SubStr(<100010001000100010001000100010002000030000040000020002000200020002000200020002000300004000005000000>,%fxsfror_pos,1)
                        IF neg_tkn NE 0 AND fxsfror_pos GE 50
                            fsberor_pos = fxsfror_pos-49
                        ELSEIF neg_tkn NE 0
                            fsberor_pos = fxsfror_pos5+49
                        ENDIF
                        IF fxsfror_pos GE 50
                            fsberor_pos2 = fxsfror_pos-49
                        ELSE
                            fxsfror_pos2 = fxsfror_pos
                        ENDIF
                        IF fxsfror_pos EQ 1
                            fsberor_new_const TEXTEQU <0.5>
                        ELSEIF fxsfror_pos EQ 5
                            fsberor_new_const TEXTEQU <0.3333333333333333333>
                        ELSEIF fxsfror_pos EQ 9
                            fsberor_new_const TEXTEQU <0.25>
                        ELSEIF fxsfror_pos EQ 13
                            fsberor_new_const TEXTEQU <0.2>
                        ELSEIF fxsfror_pos EQ 17
                            fsberor_new_const TEXTEQU <0.1666666666666666666>
                        ELSEIF fxsfror_pos EQ 21
                            fsberor_new_const TEXTEQU <0.1428571428571428571>
                        ELSEIF fxsfror_pos EQ 25
                            fsberor_new_const TEXTEQU <0.125>
                        ELSEIF fxsfror_pos EQ 29
                            fsberor_new_const TEXTEQU <0.1111111111111111111>
                        ELSEIF fxsfror_pos EQ 33
                            fsberor_new_const TEXTEQU <0.1>
                        ELSEIF fxsfror_pos EQ 38
                            fsberor_new_const TEXTEQU <0.01>
                        ELSEIF fxsfror_pos EQ 44
                            fsberor_new_const TEXTEQU <0.001>
                        ENDIF
                        IF fxsfror_pos GE 50
                            fsberor_new_const TEXTEQU <->,fsberor_new_const
                        ENDIF
                        fsberor_new_const_is_int = 0
                        fsberor_new_op TEXTEQU <*>
                        fsberor_new_params = 1
                        EXITM <0>
                    ENDIF
                ENDIF
            ENDIF
        ENDIF
    ENDIF
    EXITM <0>
endm


If somebody want fun, can try to find an optimal solution  :biggrin:

Regards

Equations in Assembly: SmplMath