ソースを参照

Implement real::is_zero and a few others for code clarity.

legacy
Sam Hocevar 7年前
コミット
74f174b6d7
2個のファイルの変更35行の追加30行の削除
  1. +12
    -6
      src/lol/math/real.h
  2. +23
    -24
      src/math/real.cpp

+ 12
- 6
src/lol/math/real.h ファイルの表示

@@ -1,11 +1,13 @@
//
// Lol Engine
// Lol Engine
//
// Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2010—2017 Sam Hocevar <sam@hocevar.net>
//
// Lol Engine is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
//

#pragma once
@@ -51,6 +53,10 @@ public:

Real(char const *str);

LOL_ATTR_NODISCARD bool is_zero() const { return m_mantissa.count() == 0; }
LOL_ATTR_NODISCARD bool is_nan() const { return m_nan; }
LOL_ATTR_NODISCARD bool is_inf() const { return m_inf; }

LOL_ATTR_NODISCARD operator float() const;
LOL_ATTR_NODISCARD operator double() const;
LOL_ATTR_NODISCARD operator long double() const;


+ 23
- 24
src/math/real.cpp ファイルの表示

@@ -160,7 +160,7 @@ template<> real::operator double() const
/* Compute new exponent (FIXME: handle Inf/NaN) */
int64_t e = m_exponent + ((1 << 10) - 1);

if (m_mantissa.count() == 0)
if (is_zero())
u.x <<= 52;
else if (e < 0) /* if exponent underflows, set to zero */
u.x <<= 52;
@@ -297,10 +297,10 @@ template<> real real::operator -() const

template<> real real::operator +(real const &x) const
{
if (x.m_mantissa.count() == 0)
if (x.is_zero())
return *this;

if (m_mantissa.count() == 0)
if (is_zero())
return x;

/* Ensure both arguments are positive. Otherwise, switch signs,
@@ -365,10 +365,10 @@ template<> real real::operator +(real const &x) const

template<> real real::operator -(real const &x) const
{
if (x.m_mantissa.count() == 0)
if (x.is_zero())
return *this;

if (m_mantissa.count() == 0)
if (is_zero())
return -x;

/* Ensure both arguments are positive. Otherwise, switch signs,
@@ -478,8 +478,8 @@ template<> real real::operator *(real const &x) const
/* The sign is easy to compute */
ret.m_sign = m_sign ^ x.m_sign;

/* If any operand is zero, return zero. */
if (m_mantissa.count() == 0 || x.m_mantissa.count() == 0)
/* If any operand is zero, return zero. FIXME: 0 * Inf? */
if (is_zero() || x.is_zero())
return ret;

ret.m_mantissa.resize(m_mantissa.count());
@@ -573,9 +573,9 @@ template<> real const &real::operator /=(real const &x)

template<> bool real::operator ==(real const &x) const
{
/* If both zero, they are equal */
if (m_mantissa.count() == 0 && x.m_mantissa.count() == 0)
return true;
/* If both zero, they are equal; if either is zero, they are different */
if (is_zero() || x.is_zero())
return is_zero() && x.is_zero();

/* FIXME: handle NaN/Inf */
return m_exponent == x.m_exponent && m_mantissa == x.m_mantissa;
@@ -593,11 +593,11 @@ template<> bool real::operator <(real const &x) const
return -*this > -x;

/* If x is zero or negative, we can’t be < x */
if (x.m_sign || x.m_mantissa.count() == 0)
if (x.m_sign || x.is_zero())
return false;

/* If we are zero, we must be < x */
if (m_mantissa.count() == 0)
if (is_zero())
return true;

/* Compare exponents */
@@ -623,16 +623,16 @@ template<> bool real::operator >(real const &x) const
if (m_sign)
return -*this < -x;

/* If x is zero, we’re > x iff we’re non-zero */
if (x.m_mantissa.count() == 0)
return m_mantissa.count() != 0;
/* If x is zero, we’re > x iff we’re non-zero since we’re positive */
if (x.is_zero())
return !is_zero();

/* If x is strictly negative, we’re > x */
if (x.m_sign)
return true;

/* If we are zero, we can’t be > x */
if (m_mantissa.count() == 0)
if (is_zero())
return false;

/* Compare exponents */
@@ -659,9 +659,8 @@ template<> bool real::operator !() const

template<> real::operator bool() const
{
/* A real is "true" if it is non-zero (mantissa is non-zero) AND
* not NaN */
return m_mantissa.count() && !m_nan;
/* A real is "true" if it is non-zero AND not NaN */
return !is_zero() && !is_nan();
}

template<> real min(real const &a, real const &b)
@@ -684,7 +683,7 @@ template<> real inverse(real const &x)
real ret;

/* If zero, return infinite */
if (!x.m_mantissa.count())
if (x.is_zero())
{
ret.m_sign = x.m_sign;
ret.m_inf = true;
@@ -712,7 +711,7 @@ template<> real inverse(real const &x)
template<> real sqrt(real const &x)
{
/* if zero, return x (FIXME: negative zero?) */
if (!x.m_mantissa.count())
if (x.is_zero())
return x;

/* if negative, return NaN */
@@ -755,7 +754,7 @@ template<> real sqrt(real const &x)
template<> real cbrt(real const &x)
{
/* if zero, return x */
if (!x.m_mantissa.count())
if (x.is_zero())
return x;

int tweak = x.m_exponent % 3;
@@ -952,7 +951,7 @@ template<> real log(real const &x)
/* Strategy for log(x): if x = 2^E*M then log(x) = E log(2) + log(M),
* with the property that M is in [1..2[, so fast_log() applies here. */
real tmp;
if (x.m_sign || x.m_mantissa.count() == 0)
if (x.m_sign || x.is_zero())
{
tmp.m_nan = true;
return tmp;
@@ -966,7 +965,7 @@ template<> real log2(real const &x)
{
/* Strategy for log2(x): see log(x). */
real tmp;
if (x.m_sign || x.m_mantissa.count() == 0)
if (x.m_sign || x.is_zero())
{
tmp.m_nan = true;
return tmp;


読み込み中…
キャンセル
保存