Announcement

Collapse
No announcement yet.

Math overflow trapping

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Math overflow trapping

    Is it possible to dependably detect floating point math overflow?
    For example, if I have two EXT variables n1 and n2 and I code
    n1^n2 how can I detect a problem like n1 being, say, 156634.77
    and n2 being, say, 58799437.456?
    I have found ASM code by Calvini in these forums but it does not
    seem to work consistently. Thanks.

    ------------------

  • #2
    Gunar,
    I've never used this sort of trapping before but it looks easy.
    1) use FCLEX to clear any exception flags which happen to be already set.
    2) Don't mess with the exception mask bits in the control word, they're usually set but if not then a software trap already exists for the overflow so just let the exception happen.
    3) Do the calculation
    4) Check the required exception flags (just overflow in this case). If set, then that exception must have occurred since the FCLEX was executed.

    Paul.

    Code:
    $REGISTER NONE
    FUNCTION PBMAIN()
    REM check for overflow during a calculation
    REM PB/CC1.0 program
    
    SaveCW&=0
    MaskedCW&=0
    tmp&=0
    
    REM x# = a# ^ b#
    a#=45.6
    b#=185  'SET b#=186 or more to get an overflow
    x#=0
    
    ' Create the control WORD TO truncate when rounding and set extended precision
    !fstcw   MaskedCW&
    !OR      MaskedCW&, &b110000000000
    !fstcw   SaveCW&        ;save a copy of the initial control word so it can be put back
    !or SaveCW&, &b001100000000  ;set precision to extended
    !fldcw SaveCW&
    
    !fclex          ;clear any pending exeption flags
    
    'now do a# ^ b#
    !fld b#                 ;push the 2 operands onto the FP stack
    !fld a#
    !fyl2x                  ;Compute x*lg(y)
    
    !fldcw   MaskedCW&      ;Modify the control WORD TO truncate when rounding
    !fld     st(0)          ;Duplicate top of stack
    !frndint                ;Compute INTEGER portion.
    !fsubr    st(0), st(1)  ;Compute fractional part.
    
    !f2xm1                  ;Compute 2**FRAC(x)-1.
    !fld1
    !fadd                   ;Compute 2**FRAC(x).
    
    !fscale                 ;Compute 2**INT(x) * 2**FRAC(x).
    
    !fldcw   SaveCW&        ;Restore rounding mode.
    
    !fstp x#                ;pop the answer off the FP stack
    !fstp  st(0)            ;clean up the stack (there's 1 value left on it)
    
    'calculation done, now check if an overflow occurred anytime since FCLEX
    
    !fstsw ax           ;get status word
    !test ax,8          ;is overflow bit set?
    !jz NoOverflow
    
    PRINT "Overflow occurred!"
    
    NoOverflow:
    PRINT x#
     
    WAITKEY$
    END FUNCTION
    ------------------

    Comment


    • #3
      Gunar,
      you can also use it with BASIC calculation as well.

      Paul.
      Code:
      $REGISTER NONE
      FUNCTION PBMAIN()
      REM check FOR overflow during a calculation
      
      !fclex   ;clear any pending exception flags
      
      a##=10
      b##=4932     'set to 4933 to cause an overflow as maximum possible result is 1.2E4932
      c##= a## ^ b##
      
      
      !fstsw ax           ;get status word
      !test ax,8          ;is overflow bit set?
      !jz NoOverflow
      
      PRINT "Overflow occurred!"
      
      NoOverflow:
      PRINT c##
      
      WAITKEY$
      END FUNCTION

      Comment


      • #4
        Paul,
        Thanks a bunch. The BASIC version was just what I needed...so simple
        I should have figured it out!
        Regards,
        Gunar

        ------------------

        Comment

        Working...
        X