fenv.h   [plain text]


/*
 * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 * 
 * The contents of this file constitute Original Code as defined in and
 * are subject to the Apple Public Source License Version 1.1 (the
 * "License").  You may not use this file except in compliance with the
 * License.  Please obtain a copy of the License at
 * http://www.apple.com/publicsource and read it before using this file.
 * 
 * This Original Code and all software distributed under the License are
 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
 * License for the specific language governing rights and limitations
 * under the License.
 * 
 * @APPLE_LICENSE_HEADER_END@
 */
 
/*******************************************************************************
*                                                                              *
*     File:  fenv.h                                                            *
*                                                                              *
*     Contains: typedefs and prototypes for C99 floating point environment.    *
*                                                                              *
*******************************************************************************/

#ifndef __FENV__
#define __FENV__

/*  We require VFP for this set of interfaces to work  */
#if !defined(__VFP_FP__) || defined(__SOFTFP__)
	#warning The <fenv.h> functions are not supported on platforms that do not have hardware floating-point.
#else
   
#if defined(__GNUC__) && (__GNUC__ >= 4)   
    #pragma GCC fenv
#endif

#ifdef __cplusplus
extern "C" {
#endif

/*
    A collection of functions designed to provide access to the floating
    point environment for numerical programming. It is compliant with
    the floating-point requirements in C99.
            
    The file <fenv.h> declares many functions in support of numerical
    programming. Programs that test flags or run under
    non-default modes must do so under the effect of an enabling
    "fenv_access" pragma:

    Note that prior to iPhone OS 2.0, these interfaces did nothing.

    #pragma STDC FENV_ACCESS on
*/

/********************************************************************************
*                                                                               *
*    fenv_t         is a type for representing the entire floating-point        *
*                   environment in a single object.                             *
*                                                                               *
*    fexcept_t      is a type for representing the floating-point               *
*                   exception flag state collectively.                          *
*                                                                               *
********************************************************************************/



typedef struct {
    union
    {
        struct
        {
            unsigned int            __fpscr;    
            unsigned int            __reserved0;
            unsigned int            __reserved1;
            unsigned int            __reserved2;
        };
#if defined( __GNUC__ )
        struct
        {
            unsigned int        __fpscr_cmp_n : 1;
            unsigned int        __fpscr_cmp_z : 1;
            unsigned int        __fpscr_cmp_c : 1;
            unsigned int        __fpscr_cmp_v : 1;
            unsigned int        __fpscr_do_not_modify_1 : 2;            /* Should be zero */
            unsigned int        __fpscr_default_nan_mode : 1;
            unsigned int        __fpscr_flush_to_zero : 1;
            unsigned int        __fpscr_rounding_mode : 2;
            unsigned int        __fpscr_stride : 2;
            unsigned int        __fpscr_do_not_modify_2 : 1;            /* Should be zero */
            unsigned int        __fpscr_len : 3 ;
            unsigned int        __fpscr_trap_enable_subnormal : 1 ;     /* Note: we run under "Run Fast Mode". Setting this bit has undefined results. */
            unsigned int        __fpscr_do_not_modfify_3 : 2;           /* Should be zero */
            unsigned int        __fpscr_trap_enable_inexact : 1;        /* Note: we run under "Run Fast Mode". Setting this bit has undefined results. */
            unsigned int        __fpscr_trap_enable_underflow : 1;      /* Note: we run under "Run Fast Mode". Setting this bit has undefined results. */
            unsigned int        __fpscr_trap_enable_overflow : 1;       /* Note: we run under "Run Fast Mode". Setting this bit has undefined results. */
            unsigned int        __fpscr_trap_enable_div_by_zero : 1;    /* Note: we run under "Run Fast Mode". Setting this bit has undefined results. */
            unsigned int        __fpscr_trap_enable_invalid : 1;        /* Note: we run under "Run Fast Mode". Setting this bit has undefined results. */
            unsigned int        __fpscr_fp_state_flag_subnormal : 1;
            unsigned int        __fpscr_do_not_modify_4 : 2;            /* Should be zero */
            unsigned int        __fpscr_fp_state_flag_inexact : 1;
            unsigned int        __fpscr_fp_state_flag_underflow : 1;
            unsigned int        __fpscr_fp_state_flag_overflow : 1;
            unsigned int        __fpscr_fp_state_flag_div_by_zero : 1;
            unsigned int        __fpscr_fp_state_flag_invalid : 1;
        } __attribute((packed));
#endif
    };
} fenv_t;

typedef unsigned short fexcept_t;

/*    Definitions of floating-point exception macros                          */
#define FE_INEXACT          0x0010
#define FE_UNDERFLOW        0x0008
#define FE_OVERFLOW         0x0004
#define FE_DIVBYZERO        0x0002
#define FE_INVALID          0x0001
#define FE_ALL_EXCEPT       0x001F

/*    Definitions of rounding direction macros                                */
#define FE_TONEAREST        0x00000000
#define FE_UPWARD           0x00400000
#define FE_DOWNWARD         0x00800000
#define FE_TOWARDZERO       0x00C00000

/* default environment object        */
extern const fenv_t _FE_DFL_ENV;
#define FE_DFL_ENV &_FE_DFL_ENV          /* pointer to default environment    */


/*******************************************************************************
*     The following functions provide high level access to the exception flags.*  
*     The "int" input argument can be constructed by bitwise ORs of the        *
*     exception macros: for example: FE_OVERFLOW | FE_INEXACT.                 *
*******************************************************************************/

/*******************************************************************************
*     The function "feclearexcept" clears the supported floating point         *
*     exceptions represented by its argument.                                  *
*******************************************************************************/

extern int  feclearexcept(int /*excepts*/);


/*******************************************************************************
*    The function "fegetexceptflag" stores a implementation-defined            *
*    representation of the states of the floating-point status flags indicated *
*    by its integer argument excepts in the object pointed to by the argument, * 
*    flagp.                                                                    *
*******************************************************************************/

extern int  fegetexceptflag(fexcept_t * /*flagp*/, int /*excepts*/);


/*******************************************************************************
*     The function "feraiseexcept" raises the supported floating-point         *
*     exceptions represented by its argument. The order in which these         *
*     floating-point exceptions are raised is unspecified.                     *
*******************************************************************************/

extern int  feraiseexcept(int /*excepts*/);


/*******************************************************************************
*     The function "fesetexceptflag" sets or clears the floating point status  *
*     flags indicated by the argument excepts to the states stored in the      *
*     object pointed to by flagp. The value of the *flagp shall have been set  *
*     by a previous call to fegetexceptflag whose second argument represented  *
*     at least those floating-point exceptions represented by the argument     *
*     excepts. This function does not raise floating-point exceptions; it just *
*     sets the state of the flags.                                             *
*******************************************************************************/

extern int  fesetexceptflag(const fexcept_t * /*flagp*/, int /*excepts*/);


/*******************************************************************************
*     The function "fetestexcept" determines which of the specified subset of  *
*     the floating-point exception flags are currently set.  The excepts       *
*     argument specifies the floating-point status flags to be queried. This   *
*     function returns the value of the bitwise OR of the floating-point       *
*     exception macros corresponding to the currently set floating-point       *
*     exceptions included in excepts.                                          *
*                                                                              *
*******************************************************************************/

extern int  fetestexcept(int /*excepts*/);


/*******************************************************************************
*     The following functions provide control of rounding direction modes.     *
*******************************************************************************/

/*******************************************************************************
*     The function "fegetround" returns the value of the rounding direction    *
*     macro which represents the current rounding direction, or a negative     *
*     if there is no such rounding direction macro or the current rounding     *
*     direction is not determinable.                                           *
*******************************************************************************/

extern int  fegetround(void);


/*******************************************************************************
*     The function "fesetround" establishes the rounding direction represented *
*     by its argument "round". If the argument is not equal to the value of a  *
*     rounding direction macro, the rounding direction is not changed.  It     *
*     returns zero if and only if the argument is equal to a rounding          *
*     direction macro.                                                         *
*******************************************************************************/

extern int  fesetround(int /*round*/);


/*******************************************************************************
*    The following functions manage the floating-point environment, exception  *
*    flags and dynamic modes, as one entity.                                   *
*******************************************************************************/

/*******************************************************************************
*    The fegetenv function stores the current floating-point enviornment in    *
*    the object pointed to by envp.                                            *
*******************************************************************************/
extern int  fegetenv(fenv_t * /*envp*/);

/*******************************************************************************
*    The feholdexcept function saves the current floating-point environment in *
*    the object pointed to by envp, clears the floating-point status flags,    *
*    and then installs a non-stop (continue on floating-point exceptions)      *
*    mode, if available, for all floating-point exceptions. The feholdexcept   *
*    function returns zero if and only if non-stop floating-point exceptions   *
*    handling was successfully installed.                                      *
*******************************************************************************/
extern int   feholdexcept(fenv_t * /*envp*/);

/*******************************************************************************
*    The fesetnv function establishes the floating-point environment           *
*    represented by the object pointed to by envp. The argument envp shall     *
*    point to an object set by a call to fegetenv or feholdexcept, or equal to *
*    a floating-point environment macro -- we define only *FE_DFL_ENV and      *
*    FE_DISABLE_SSE_DENORMS_ENV -- to be C99 standard compliant and portable   *
*    to other architectures. Note that fesetnv merely installs the state of    *
*    the floating-point status flags represented through its argument, and     *
*    does not raise these floating-point exceptions.                           *
*******************************************************************************/
extern int  fesetenv(const fenv_t * /*envp*/);

/*******************************************************************************
*    The feupdateenv function saves the currently raised floating-point        *
*    exceptions in its automatic storage, installs the floating-point          *
*    environment represented by the object pointed to by envp, and then raises *
*    the saved floating-point exceptions. The argument envp shall point to an  *
*    object set by a call to feholdexcept or fegetenv or equal a               *
*    floating-point environment macro.                                         *
*******************************************************************************/
extern int  feupdateenv(const fenv_t * /*envp*/);

#ifdef __cplusplus
}
#endif

#endif // HARDWARE FP

#endif /* __FENV__ */