зеркало из https://github.com/mozilla/pjs.git
122 строки
4.1 KiB
C
122 строки
4.1 KiB
C
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
|
|
#ifndef FLOATUTILS_H
|
|
#define FLOATUTILS_H
|
|
|
|
#include "Fundamentals.h"
|
|
|
|
// Wrapper around fmod() is necessary because some implementations doesn't
|
|
// handle infinities properly, e.g. MSVC.
|
|
double javaFMod(double dividend, double divisor);
|
|
|
|
// Simple queries on IEEE floating-point values.
|
|
// It's amazing that the standard C headers don't have these operations
|
|
// standardized...
|
|
|
|
#ifdef WIN32
|
|
// Microsoft's compiler is quite buggy when it comes to handling floating
|
|
// point zeros and NaNs, so we need workarounds here...
|
|
extern Flt32 floatPositiveInfinity;
|
|
extern Flt64 doublePositiveInfinity;
|
|
extern Flt32 floatNegativeInfinity;
|
|
extern Flt64 doubleNegativeInfinity;
|
|
extern Flt32 floatNegativeZero;
|
|
extern Flt64 doubleNegativeZero;
|
|
extern Flt32 floatNaN;
|
|
extern Flt64 doubleNaN;
|
|
#elif defined __GNUC__
|
|
// GCC is also broken when it comes to immediate floating point expressions.
|
|
extern Flt32 floatPositiveInfinity;
|
|
extern Flt64 doublePositiveInfinity;
|
|
extern Flt32 floatNegativeInfinity;
|
|
extern Flt64 doubleNegativeInfinity;
|
|
const Flt32 floatNegativeZero = -0.0f;
|
|
const Flt64 doubleNegativeZero = -0.0;
|
|
extern Flt32 floatNaN;
|
|
extern Flt64 doubleNaN;
|
|
#else
|
|
const Flt32 floatPositiveInfinity = 1.0f/0.0f;
|
|
const Flt64 doublePositiveInfinity = 1.0/0.0;
|
|
const Flt32 floatNegativeInfinity = -1.0f/0.0f;
|
|
const Flt64 doubleNegativeInfinity = -1.0/0.0;
|
|
const Flt32 floatNegativeZero = -0.0f;
|
|
const Flt64 doubleNegativeZero = -0.0;
|
|
const Flt32 floatNaN = 0.0f/0.0f;
|
|
const Flt64 doubleNaN = 0.0/0.0;
|
|
#endif
|
|
|
|
inline bool isPositiveZero(Flt32 x);
|
|
inline bool isPositiveZero(Flt64 x);
|
|
inline bool isNegativeZero(Flt32 x);
|
|
inline bool isNegativeZero(Flt64 x);
|
|
inline bool isNaN(Flt32 x);
|
|
inline bool isNaN(Flt64 x);
|
|
|
|
DEBUG_ONLY(void testFloatUtils();)
|
|
|
|
// Conversions between integral and floating point types
|
|
// These may need to be defined specially on platforms that handle rounding
|
|
// or out-of-range values weirdly.
|
|
|
|
// Rounds to nearest when result is inexact.
|
|
inline Flt32 int32ToFlt32(Int32 i) {return (Flt32)i;}
|
|
inline Flt64 int32ToFlt64(Int32 i) {return (Flt64)i;}
|
|
inline Flt32 int64ToFlt32(Int64 l) {return (Flt32)l;}
|
|
inline Flt64 int64ToFlt64(Int64 l) {return (Flt64)l;}
|
|
|
|
// Ordinary values round towards zero.
|
|
// NaN becomes zero.
|
|
// -inf or values below -2^31 (or -2^63) become -2^31 (or -2^63).
|
|
// +inf or values above 2^31-1 (or 2^63-1) become 2^31-1 (or 2^63-1).
|
|
extern Int32 flt64ToInt32(Flt64 d);
|
|
extern Int64 flt64ToInt64(Flt64 d);
|
|
inline Int32 flt32ToInt32(Flt32 f) {return flt64ToInt32((Flt64)f);}
|
|
inline Int64 flt32ToInt64(Flt32 f) {return flt64ToInt64((Flt64)f);}
|
|
|
|
|
|
|
|
// --- INLINES ----------------------------------------------------------------
|
|
|
|
|
|
inline bool isPositiveZero(Flt32 x)
|
|
{return *(Uint32 *)&x == 0x00000000;}
|
|
|
|
inline bool isPositiveZero(Flt64 x)
|
|
{return *(Uint64 *)&x == CONST64(0x0000000000000000);}
|
|
|
|
inline bool isNegativeZero(Flt32 x)
|
|
{return *(Uint32 *)&x == 0x80000000;}
|
|
|
|
inline bool isNegativeZero(Flt64 x)
|
|
{return *(Uint64 *)&x == CONST64(0x8000000000000000);}
|
|
|
|
inline bool isNaN(Flt32 x)
|
|
{return (~(*(Uint32 *)&x) & 0x7fc00000) == 0;}
|
|
|
|
inline bool isNaN(Flt64 x)
|
|
{return (~(*(Uint64 *)&x) & CONST64(0x7ff8000000000000)) == 0;}
|
|
|
|
inline bool isInfinite(Flt32 v)
|
|
{return v == floatPositiveInfinity || v == floatNegativeInfinity;}
|
|
|
|
inline bool isInfinite(Flt64 v)
|
|
{return v == doublePositiveInfinity || v == doubleNegativeInfinity;}
|
|
|
|
#endif
|