News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

ISFLOAT? MACRO

Started by GoneFishing, October 18, 2015, 08:30:45 PM

Previous topic - Next topic

GoneFishing

Excuse me , I meant that this condition was not met:
Quote
   if ISFLOAT?QW(-7.4)
           %echo QWORD IS MACRO WIZARD
   endif

qWord

Quote from: GoneFishing on October 19, 2015, 01:57:24 AM
Excuse me , I meant that this condition was not met:
Quoteif ISFLOAT?QW(-7.4)
does work here (ML v6&8,jWasm). However, in the code from your previous post there is a missing ENDIF (I guess copy&past error).
MREAL macros - when you need floating point arithmetic while assembling!

GoneFishing

I'm so sorry ,as a poor noob can only be
yes, it was copy-paste error
now I've got expected line
QuoteQWORD IS MACRO WIZARD
Thanks  :t

GoneFishing

We were sorting out structure members. Now new question erises : what if that structure member is FLOAT and we need it?

I have another weak macro-embrion :

ISNUM? MACRO arg
    ch SUBSTR <arg>,1,1
    if @INSTR(1, <0123456789>,<ch>)
       %echo ch is numeric
    endif
ENDM



if ISNUM?(1.0)
    %echo -----------
endif


Got:
QuoteISFLOAT.asm(87) : Error A2243: Invalid symbol type in expression: ISNUM?
What's wrong with it?

jj2007

You are using it as a function, so you need to return something:

ISNUM? MACRO arg
    ch SUBSTR <arg>,1,1
    if @INSTR(1, <0123456789>,<ch>)
       %echo ch is numeric
       EXITM <1>
    else
       EXITM <0>
    endif
ENDM

GoneFishing

Indeed, Jochen ! Thanks
Probably I ran out of oxigen in my BLACK CHAMBER LOL  ... and totally out of beer since yesterday  :biggrin:


ISNUM? MACRO arg
    chr SUBSTR <arg>,1,1
   
    if @INSTR( 1,<0123456789>,<chr>)
       %echo is numeric
        EXITM <1>
    endif
     %echo ch is not numeric
     EXITM <0>
ENDM



  if ISNUM?(1.0)
       %echo -----------
  endif

getting weird reply :
Quote
ch is not numeric


GoneFishing

Got it!
Instead of
Quoteif @INSTR( 1,<0123456789>,<chr>)
I need
Quoteif @INSTR( <0123456789>,<chr>)

jj2007

#22
Your last version throws an error with ML. Try this:
include \masm32\include\masm32rt.inc

ISNUM? MACRO arg
LOCAL chr, ins
  chr SUBSTR <arg>,1,1
  ins INSTR <0123456789>, chr ; no good: if @InStr(1, <0123456789>, chr)
  if ins
% echo chr is numeric
EXITM <1>
  else
% echo chr is not numeric
EXITM <0>
  endif
ENDM

.code
start:
  if ISNUM?(1.0)
% echo -----------
  endif
  .err ; don't run this code
  exit
end start


EDIT: Tim found an error in my code - corrected version above. The built-in @InStr() macro often plays foul, in my experience it is safer to use e.g. ins INSTR <string>, <match> :(

Attention also to this trap:
  chr SUBSTR <arg>,1,1
  ins INSTR <0123456789>, <chr>


With arg=1.0, you expect ins>0, right? Nope, it won't find the 1 in <0123456789>, simply because you are not passing 1 - you are passing <1>...! chr is already a text item, so the correct version is
  chr SUBSTR <arg>,1,1
  ins INSTR <0123456789>, chr


GoneFishing

Quote from: jj2007 on October 19, 2015, 03:01:27 AM
Your last version throws an error with ML.
Yes. didn't notice it.
I'd take a break for developing good habbits. It take efforts to start coding again, Jochen.

qWord

GoneFishing,
before starting coding, it might be useful to have a list of requirements. Currently I see these points:

  • Def.: true is 1, false is 0 (I would recommend true = -1 BTW)
  • return true if FP literal; e.g. 3.0E8
  • return true if REAL4/8/10 variable
  • if none of the above applies, return false
Any other points? The third point can be done using OPATTR (see previous posts).
What I see critical, is that your macro accepts FP literals and variables, but in later code FP literals maybe requires a special handling. For that reason, I would separate the test for literals and memory operands.

BTW: as already said, do not declare text macros with names like "q" and "ch", unless they are LOCAL!
MREAL macros - when you need floating point arithmetic while assembling!

GoneFishing

Ok, Qword, I'm agree today's session was too spontaneous , without proper planning work .
Points you see are even more complete than I've taken into consideration. 
For the timebeing I would not talk about FP literals since they require special handling .
By the way, we didn't consider the possibility when  REAL4/8/10 variable resides inside the structure.
For example:
Quote
mystructure STRUCT
f1 REAL10
f2 REAL10
mystructure ENDS

.data
mys mystructure<1.0,1.0>

your and my current code will not recognize float in mys.f1:
Quoteif ISFLOAT?(mys.f1)
                ; ...

Point about using LOCAL is taken .
Again , thank you for the help . 





nidud

#26
deleted

jj2007

Quote from: GoneFishing on October 19, 2015, 03:10:50 AMI'd take a break for developing good habits. It takes efforts to start coding again, Jochen.

Yes, I know, but don't forget the fun factor ;-)

Please note my edits to reply #22 - there was a bug.

GoneFishing

#28
Thank you, Jochen . Corrected now .
First mile stone. Code contains only few tests out of all possible .
-----------------------------------------------------
NOTE:
-----------------------------------------------------
---  FP literals are NOT SUPPORTED yet
---  float members of structure are not identified as floats
---  hex format 3F800000r mentioned by nidud is NOT SUPPORTED yet
-----------------------------------------------------
ISFLOAT.ASM:

include \masm32\include\masm32rt.inc

;-----------------
; ISSIGNED? MACRO: returns TRUE if the argument has '+' or '-' sign
;-----------------
ISSIGNED? MACRO arg
     LOCAL sign
     sign SUBSTR <arg>,1,1
     IFIDN sign,<+>            ; if first charachter is "+"
        %echo arg is SIGNED    ; exit with TRUE
        EXITM <-1>       
     ELSEIFIDN sign,<->
        %echo arg is SIGNED    ; or if first charachter is "-"
        EXITM <-1>             ; return TRUE
     ELSE
        %echo arg is NOT SIGNED
        %echo -----------
        EXITM <0>              ; otherwise return FALSE 
    ENDIF 
ENDM 
;-----------------
; ISNUM?    MACRO: returns TRUE if the character at <position> is numeric
;-----------------
ISNUM? MACRO arg, position:=<1>       
    LOCAL chr, pos 
    chr SUBSTR <arg>,1,position
    pos INSTR <0123456789>,chr
    IF  pos                     ; if the character at <position> is numeric
        %echo chr is numeric   
        EXITM <-1>              ; return TRUE
    ENDIF
        %echo chr is not numeric
        %echo -----------
        EXITM <0>               ; otherwise return FALSE 
    ENDM
;-----------------
; ISFLOAT?  MACRO: returns TRUE if the argument is REAL4/8/10
;-----------------     
ISFLOAT? MACRO arg
         LOCAL quote
         IF @InStr(1, <arg>, <.>) ; if argument has dot ->
            quote SUBSTR <arg>,1,1
               IFIDN quote,<">    ; and its first character is quote ->
                   %echo arg is not FLOAT!
                   %echo ----------- ; then argument is a string ->
                   EXITM <0>         ; return FALSE                 
               ENDIF                 ; if it's not a quote ->
               ;----------------------
                  IF ISNUM?(arg)         ; check if it's numeric ->
                     %echo arg is  FLOAT!; if so ->
                     %echo -----------
                     EXITM <-1>          ; return TRUE
               ;----------------------   ; if the first character is   
                  ELSE                   ; not numeric ->
                    IF ISSIGNED?(arg)    ; check if it's "+" or "-",if so ->
                      IF ISNUM?(arg,2)   ; check if the next character 
                         %echo arg is  FLOAT! ; is numeric ->
                         %echo -----------    ; if so ->
                         EXITM <-1>           ; return TRUE
               ;----------------------        ; if second character       
                      ELSE                    ; is not numeric  ->
                         %echo arg is not FLOAT!
                         %echo -----------
                         EXITM <0>   ; return FALSE                 
                      ENDIF          ; END IF ISNUM?(arg,2)
               ;----------------------         
                    ENDIF            ; END IF ISSIGNED?(arg)
               ;----------------------     
                  ENDIF              ; END IF ISNUM?(arg)
               ;----------------------                 
         ENDIF                       ; if argument has no dot ->
         %echo arg is not FLOAT!     
         %echo -----------
         EXITM <0>                   ; return FALSE
     ENDM     
;-----------------
;ISFLOAT?QW MACRO: written by QWORD , 10h lines of code 
;-----------------
ISFLOAT?QW MACRO arg:=<invalidToken?$?$?$>
    IF OPATTR arg
    EXITM <0>
    ENDIF
    iflt_str TEXTEQU <&arg  >
    iflt_c1 SUBSTR iflt_str,1,1
    iflt_c2 SUBSTR iflt_str,2,1
    iflt_pos1 INSTR iflt_str,<.>
    iflt_pos2 INSTR <+-0123456789>,iflt_c1
    iflt_pos3 INSTR <0123456789>,iflt_c2
   
    ;; if (sign and digit and dot) OR (digit and dot)
    IF (iflt_pos2 LE 2 AND iflt_pos3 NE 0 AND iflt_pos1 NE 0) OR (iflt_pos2 GT 2 AND iflt_pos1 NE 0)
    EXITM <-1>
    ELSE
    EXITM <0>
    ENDIF
   ENDM
;--------------------
; mystructure STRUCT: for testing
;--------------------
mystructure STRUCT
      f1    REAL10 ?
      f2    REAL10 ?
      item1 DD ?
      item2 DD ?
mystructure ENDS 

.data

    mys mystructure<5.0,2.7,3,4>

.code
     start:
;-----------------
; ISFLOAT?  tests:
;-----------------
         IF ISFLOAT?(mys.item1)
            %echo mys.item1 is taken as a float
            %echo -----------
         ENDIF
         
         IF ISFLOAT?(-mys.f1)
            %echo mys.f1 is taken as a float by mistake
            %echo -----------
         ENDIF
         
         IF ISFLOAT?QW(-7.4)
            %echo QWORD IS MACRO WIZARD
            %echo -----------         
         ENDIF
;-----------------
; ISSIGNED? tests:
;-----------------           
         IF ISSIGNED?(-13245.345)
            %echo -----------
         ENDIF
       
         IF ISSIGNED?(+13245.345)
            %echo -----------
         ENDIF
         
         IF ISSIGNED?(13245.345)
            %echo -----------
         ENDIF
;-----------------
; ISNUM?    tests:
;-----------------         
         IF ISNUM?(1.0)
            %echo -----------
         ENDIF
         
         IF ISNUM?("sad.saa")
            %echo -----------
         ENDIF
         
         IF ISNUM?(1234)
            %echo -----------
         ENDIF
;-----------------
        .ERR     ; FORCE ERROR
;-----------------         
end start

qWord

quickly worked out:
;
; Returns true for any REAL4/8/10 variable or decimal FP literal
;
ISFLOAT? MACRO arg
   
    ; handle memory operands and integer values
    IF (OPATTR arg) AND 2
    IF (TYPE arg) EQ (TYPE REAL4) OR (TYPE arg) EQ (TYPE REAL8) OR (TYPE arg) EQ (TYPE REAL10)
    EXITM <-1>
    ENDIF
    EXITM <0>
    ELSEIF OPATTR arg
    EXITM <0>
    ENDIF
   
    ;; Test for valid FP literal
    ;;
    ;; Used state machine
    ;;  state | end state | description
    ;;  ------+-----------+------------
    ;;   1    |    no     |   initial state
    ;;   2    |    no     |   sign
    ;;   3    |    no     |   integer digits
    ;;   4    |    yes    |   decimal dot and (optional) fraction digits
    ;;   5    |    no     |   exponent indicator
    ;;   6    |    no     |   exponent sign
    ;;   7    |    yes    |   exponent digits
    ;;
    ;; Transitions
    ;;  state | characters | new state
    ;;  ------+------------+------------
    ;;   1    |    +-      |  2
    ;;   1    |    0-9     |  3
    ;;   2    |    0-9     |  3
    ;;   3    |    0-9     |  3
    ;;   3    |    .       |  4
    ;;   4    |    0-9     |  4
    ;;   4    |    eE      |  5
    ;;   5    |    +-      |  6
    ;;   5    |    0-9     |  7
    ;;   6    |    0-9     |  7
    ;;   7    |    0-9     |  7
    ;;
    isflt_pos   = 1
    isflt_state = 1
    FORC char,<&arg>
    ; %echo CHAR <char>, STATE: @CatStr(%isflt_state), POS: @CatStr(%isflt_pos)
    isflt_sigma SUBSTR <23 3344567 7 7>,isflt_state*2-1,2
    isflt_pos INSTR isflt_pos,<+-0123456789.0123456789Ee+-0123456789>,<&char>
    isflt_new_state SUBSTR <02233333333334444444444455667777777777>,isflt_pos+1,1
    isflt_transition INSTR isflt_sigma,isflt_new_state
    IFE isflt_transition
    isflt_state = 0
    EXITM
    ENDIF
    isflt_state = isflt_new_state
    isflt_pos = @SubStr(<03030303030303030303030314141414141414141414142626282828282828282828282828>,%isflt_pos*2-1,2)
    ENDM
   
    IF isflt_state EQ 4 OR isflt_state EQ 7
    EXITM <-1>
    ENDIF
    EXITM <0>
ENDM

The pattern test is implemented as state machine.
MREAL macros - when you need floating point arithmetic while assembling!