_TLOSS in _matherr

I am porting a mathematics application from Borland C++ to Visual C++ 2005 Express Edition beta, but it seems that _matherr does not work as described in msdn. After some research and tries I have succedded in getting _matherr called with the _DOMAIN error (for instance when evaluating log(-1)); but it seems that _PLOSS and _TLOSS are not used and the supporting routines do not complain if things like sin(1e300) are evaluated.

Any ideas to make _matherr work as in Unix or in Borland C++

Thank you


Answer this question

_TLOSS in _matherr

  • sepehr.Beigi

    Hi,

    I have to ask you for more specific list of concerns. Is there a specific code scenario when VC _matherr is different from Borland's one

    Thanks,
    Nikola
    VC++

  • ginganinja

    Hi,

    In this sample the 1.0e300 is a valid double value (<DBL_MAX) and sin() is computed, exception is not thrown. My guess, that Borland folks assume that sin of such a big value is equal to sin(infinite) which is undefined. I guess if VC compiler was letting us enter 1e309 > DLB_MAX, then perhaps in this case CRT could throw TLOSS exception. But this literal is tranlated to a variable of double type and compiler checks for valid range. I do not think something should be change in VC CRT for this case. What kind of issues does this difference in CRTs create in your application

    Thanks,
    Nikola

  • cjarvis

    I have created issue# 536175 for tracking down the bug. As Nikola suggested, it might be hard to get it fixed in the coming release but it will sure be considered for the next one.

    Thanks for reporting the issue!

    Ayman Shoukry
    VC++

  • GerryT

    I will follow up and get the issue logged in our bug database.

    Thanks,
      Ayman.

  • Sunil S

    If you can get your code to work on vc++ 6 it is easy to get it to work on UNIXES. Usually it will just compile without any major changes with the gcc compiler.
    Unforentally I never tried these fuctions so they may now work easly.
    If you cant get the gcc compiler to work you can find help in its usage all over the place. Most open source communities can help you.

    I never used the borland compiler so I cant help you with that.

    I hope that I was of some assistance.

  • Rich_Cov

    If I compile the code fpe.cpp with Visual C++ I get

    _matherr (Domain): log(-2)
    log(-2.0) = -1.#IND00e+000

    _matherr (Domain): sqrt(-1)
    sqrt(-1.0) = -1.#IND00e+000

    sin(1.0e300) = 9.804836e-001

    but with Borland C++ I get the more sensible

    _matherr (Domain): log(-2)
    log(-2.0) = -NAN

    _matherr (Domain): sqrt(-1)
    sqrt(-1.0) = +NAN

    _matherr (Total loss of significance): sin(1e+300)
    sin(1.0e300) = +NAN

    ---------------------------------------------------------------------------
    -------------------------------------- fpe.cpp ---------------------------

    #ifdef __BORLANDC__

    #include <windows.h>

    #include <stdio.h>

    #else

    #include "stdafx.h"

    #include <fpieee.h>

    #endif

    #include <math.h>

    #include <excpt.h>

    #include <float.h>

    char *errs[] = { "Domain", "Singularity", "Overflow",

    "Partial loss of significance", "Total loss of significance",

    "Underflow" };

    #ifdef __BORLANDC__

    #define _EXC_MASK EM_UNDERFLOW + EM_OVERFLOW + EM_ZERODIVIDE + EM_INEXACT

    #define TEST(st,op) { _controlfp(_EXC_MASK, MCW_EM); \

    __try { \

    printf( st " = %e\n\n", op); \

    } \

    __except (0) {\

    printf("Exception raised: \n");\

    }}

    #else

    #define _EXC_MASK _EM_UNDERFLOW + _EM_OVERFLOW + _EM_ZERODIVIDE + _EM_INEXACT

    #define TEST(st,op) { _controlfp(_EXC_MASK, _MCW_EM); \

    __try { \

    printf( st " = %e\n\n", op); \

    } \

    __except (_fpieee_flt(GetExceptionCode(),GetExceptionInformation(),fpieee_handler)) {\

    printf("Exception raised: \n");\

    }}

    #endif

     

    int _matherr( struct _exception *e )

    {

    printf("_matherr (%s): %s(%lg)\n",errs[e->type-1],e->name,e->arg1);

    return 1;

    }

    #ifndef __BORLANDC__

    int fpieee_handler( _FPIEEE_RECORD *pieee )

    {

    return EXCEPTION_CONTINUE_EXECUTION;

    }

    #endif

     

    int main(int argc, char* argv[])

    {

    TEST("log(-2.0)",log(-2.0));

    TEST("sqrt(-1.0)",sqrt(-1.0));

    TEST("sin(1.0e300)",sin(1.0e300));

    return 0;

    }





     


  • Shlomi Meoded

    The trouble is the answer given by VC is completely wrong: the right value is

    -0.9857504251603769966...

    as can be checked by means of any program with variable precision. Not even the sign is right in VC result!

    BC does not assume sin(1.0e300) is undefined, it only warns you that it cannot be computed with double precision. I think this is the only reasonable answer, because to compute sin(1.0e300)  you have to use a lot of decimal places to reduce the argument to the right interval: maybe [0,2 pi].

  • Rohit Tela

    Agreed. But it is a very old code, I doubt we are going to change it in VS2005. But it may be a good thing to do in the next release.  Our FP-"experts" can take a look on this bug when it is in the database. Go ahead and open a bug on lab.msdn.microsoft.com, it will be re-assigned to Dev-owners accordingly. Thanks for reporting this.

    Nikola
    VC++

  • _TLOSS in _matherr