mirror of https://github.com/CGAL/cgal
256 lines
5.7 KiB
C
256 lines
5.7 KiB
C
// ============================================================================
|
|
//
|
|
// Copyright (c) 1997 The CGAL Consortium
|
|
//
|
|
// This software and related documentation is part of an INTERNAL release
|
|
// of the Computational Geometry Algorithms Library (CGAL). It is not
|
|
// intended for general use.
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
//
|
|
// release :
|
|
// release_date :
|
|
//
|
|
// file : include/CGAL/_FPU.h
|
|
// revision : 1.3
|
|
// revision_date : 6 February 1998
|
|
// author(s) : Sylvain Pion <Sylvain.Pion@sophia.inria.fr>
|
|
//
|
|
// coordinator : INRIA Sophia-Antipolis (<Herve.Bronnimann@sophia.inria.fr>)
|
|
//
|
|
// ============================================================================
|
|
|
|
#ifndef _FPU_H
|
|
#define _FPU_H
|
|
|
|
/*
|
|
* Specify some *very* platform dependant functions, regarding the FPU
|
|
* directed rounding modes. There is only support for double precision.
|
|
*
|
|
* I try to make it work with gcc/g++/cc/CC.
|
|
* And I also try to provide the equivalent assembly code for GNU C.
|
|
*
|
|
* TODO: Check the exception flags, according to Christoph's remarks/code.
|
|
* (ie should we erase all, should we save&restore, etc...)
|
|
*/
|
|
|
|
#if defined(__osf__)
|
|
#undef __osf
|
|
#define __osf
|
|
#endif
|
|
|
|
#if defined(__i386__) || defined(i386) /* Needed by egcs */
|
|
#undef __i386
|
|
#define __i386
|
|
#endif
|
|
|
|
#if (!defined(__i386)&&!defined(__sparc)&&!defined(__alpha)&&!defined(__mips))
|
|
#error "Architecture not recognized."
|
|
#endif
|
|
|
|
#if ( (defined(__i386) || defined(__sparc) || defined(__alpha)) && \
|
|
defined(__GNUC__))
|
|
#define __USE_ASSEMBLY
|
|
#endif
|
|
|
|
#ifndef __USE_ASSEMBLY
|
|
#ifdef __linux
|
|
#include <fpu_control.h>
|
|
#endif
|
|
#ifdef __osf
|
|
#include <float.h>
|
|
#endif
|
|
#ifdef __sgi
|
|
/* This #define is forced for backward compatibility with Irix 5.3. */
|
|
/* I think it slows down Irix 6.2... */
|
|
#define __SGI_ieeefph__
|
|
#ifdef __SGI_ieeefph__
|
|
#include <ieeefp.h>
|
|
#else
|
|
#include <sys/fpu.h>
|
|
#endif
|
|
#endif
|
|
#ifdef __sun
|
|
#include <ieeefp.h>
|
|
#endif
|
|
#else /* __USE_ASSEMBLY */
|
|
#ifdef __i386
|
|
#define SETFPCW(CW) asm volatile ("fldcw %0" : : "m" (*&CW))
|
|
/* x86: rounding | precision | default mask */
|
|
static unsigned int _FPU_cw_zero = 0xC00 | 0x200 | 0x107f;
|
|
static unsigned int _FPU_cw_near = 0x0 | 0x200 | 0x107f;
|
|
static unsigned int _FPU_cw_up = 0x800 | 0x200 | 0x107f;
|
|
static unsigned int _FPU_cw_down = 0x400 | 0x200 | 0x107f;
|
|
#endif
|
|
#ifdef __sparc
|
|
#define SETFPCW(CW) asm volatile ("ld %0,%%fsr" : "=m" (*&CW))
|
|
/* Sparc: rounding | precision | default mask */
|
|
static unsigned int _FPU_cw_zero = 0x40000000 | 0x20000000 | 0x1f;
|
|
static unsigned int _FPU_cw_near = 0x0 | 0x20000000 | 0x1f;
|
|
static unsigned int _FPU_cw_up = 0x80000000 | 0x20000000 | 0x1f;
|
|
static unsigned int _FPU_cw_down = 0xc0000000 | 0x20000000 | 0x1f;
|
|
#endif
|
|
#ifdef __alpha
|
|
#define SETFPCW(CW) asm volatile ("mt_fpcr %0; excb" : : "f"(CW))
|
|
/* Alpha: rounding */
|
|
static unsigned long _FPU_cw_zero = 0x0000000000000000UL;
|
|
static unsigned long _FPU_cw_near = 0x0800000000000000UL;
|
|
static unsigned long _FPU_cw_up = 0x0c00000000000000UL;
|
|
static unsigned long _FPU_cw_down = 0x0400000000000000UL;
|
|
#endif
|
|
#endif
|
|
|
|
#if !defined(__GNUC__) && !defined(__cplusplus)
|
|
#define inline /* */
|
|
#endif
|
|
|
|
static inline void _FPU_set_rounding_to_zero (void);
|
|
static inline void _FPU_set_rounding_to_nearest (void);
|
|
static inline void _FPU_set_rounding_to_infinity (void);
|
|
static inline void _FPU_set_rounding_to_minus_infinity (void);
|
|
|
|
|
|
/* Code of those inline functions: */
|
|
|
|
static inline void _FPU_set_rounding_to_zero (void)
|
|
{
|
|
#ifdef __USE_ASSEMBLY
|
|
SETFPCW(_FPU_cw_zero);
|
|
#else
|
|
#ifdef __linux
|
|
#ifdef __i386
|
|
__setfpucw(0x1e72);
|
|
#else
|
|
__setfpucw(0x1f72); /* FIX ME */
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef __osf
|
|
write_rnd(FP_RND_RZ);
|
|
#endif
|
|
|
|
#ifdef __sun
|
|
fpsetround(FP_RZ);
|
|
#endif
|
|
|
|
#ifdef __sgi
|
|
#ifdef __SGI_ieeefph__
|
|
fp_rnd mode = FP_RZ;
|
|
fpsetround(mode);
|
|
#else
|
|
union fpc_csr fpu_ctl;
|
|
fpu_ctl.fc_word = get_fpc_csr();
|
|
fpu_ctl.fc_struct.rounding_mode = ROUND_TO_ZERO;
|
|
set_fpc_csr (fpu_ctl.fc_word);
|
|
#endif
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
static inline void _FPU_set_rounding_to_nearest (void)
|
|
{
|
|
#ifdef __USE_ASSEMBLY
|
|
SETFPCW(_FPU_cw_near);
|
|
#else
|
|
#ifdef __osf
|
|
write_rnd(FP_RND_RN);
|
|
#endif
|
|
|
|
#ifdef __sun
|
|
fpsetround(FP_RN);
|
|
#endif
|
|
|
|
#ifdef __linux
|
|
#ifdef __i386
|
|
__setfpucw(0x1272);
|
|
#else
|
|
__setfpucw(0x1372);
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef __sgi
|
|
#ifdef __SGI_ieeefph__
|
|
fp_rnd mode = FP_RN;
|
|
fpsetround(mode);
|
|
#else
|
|
union fpc_csr fpu_ctl;
|
|
fpu_ctl.fc_word = get_fpc_csr();
|
|
fpu_ctl.fc_struct.rounding_mode = ROUND_TO_NEAREST;
|
|
set_fpc_csr (fpu_ctl.fc_word);
|
|
#endif
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
static inline void _FPU_set_rounding_to_infinity (void)
|
|
{
|
|
#ifdef __USE_ASSEMBLY
|
|
SETFPCW(_FPU_cw_up);
|
|
#else
|
|
#ifdef __osf
|
|
write_rnd(FP_RND_RP);
|
|
#endif
|
|
|
|
#ifdef __sun
|
|
fpsetround(FP_RP);
|
|
#endif
|
|
|
|
#ifdef __linux
|
|
#ifdef __i386
|
|
__setfpucw(0x1a72);
|
|
#else
|
|
__setfpucw(0x1b72);
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef __sgi
|
|
#ifdef __SGI_ieeefph__
|
|
fp_rnd mode = FP_RP;
|
|
fpsetround(mode);
|
|
#else
|
|
union fpc_csr fpu_ctl;
|
|
fpu_ctl.fc_word = get_fpc_csr();
|
|
fpu_ctl.fc_struct.rounding_mode = ROUND_TO_PLUS_INFINITY;
|
|
set_fpc_csr (fpu_ctl.fc_word);
|
|
#endif
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
static inline void _FPU_set_rounding_to_minus_infinity (void)
|
|
{
|
|
#ifdef __USE_ASSEMBLY
|
|
SETFPCW(_FPU_cw_down);
|
|
#else
|
|
#ifdef __osf
|
|
write_rnd(FP_RND_RM);
|
|
#endif
|
|
|
|
#ifdef __sun
|
|
fpsetround(FP_RM);
|
|
#endif
|
|
|
|
#ifdef __linux
|
|
#ifdef __i386
|
|
__setfpucw(0x1672);
|
|
#else
|
|
__setfpucw(0x1772);
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef __sgi
|
|
#ifdef __SGI_ieeefph__
|
|
fp_rnd mode = FP_RM;
|
|
fpsetround(mode);
|
|
#else
|
|
union fpc_csr fpu_ctl;
|
|
fpu_ctl.fc_word = get_fpc_csr();
|
|
fpu_ctl.fc_struct.rounding_mode = ROUND_TO_MINUS_INFINITY;
|
|
set_fpc_csr (fpu_ctl.fc_word);
|
|
#endif
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
#endif /* _FPU_H */
|