move complex to its own header

This commit is contained in:
Kelvin Sherlock 2015-02-22 19:11:39 -05:00
parent 8d40559a62
commit 1bbcf1cc39
2 changed files with 145 additions and 115 deletions

139
toolbox/complex.h Normal file
View File

@ -0,0 +1,139 @@
#ifndef __complex_h__
#define __complex_h__
#include <cmath>
#include <string>
// comp is an int64_t but 0x8000_0000_0000_0000 is NaN
//typedef int64_t complex;
struct complex {
public:
const uint64_t NaN = 0x8000000000000000;
complex(const complex &rhs) = default;
complex(uint64_t rhs) : _data(rhs)
{}
template <class T>
complex(T t)
{
*this = t;
}
bool isnan() const
{
return _data == NaN;
}
complex &operator=(const complex &rhs) = default;
complex &operator=(uint64_t rhs)
{
_data = rhs;
return *this;
}
template <class T>
complex &operator=(T ld)
{
switch(std::fpclassify(ld))
{
case FP_NAN:
_data = NaN;
break;
case FP_INFINITE:
if (std::signbit(ld))
{
_data = -INT64_MAX;
}
else
{
_data = INT64_MAX;
}
break;
default:
_data = ld;
break;
}
return *this;
}
operator uint64_t() const {
return _data;
}
operator int64_t() const {
return _data;
}
operator long double() const {
if (_data == NaN)
return NAN;
return _data;
}
operator double() const {
if (_data == NaN)
return NAN;
return _data;
}
operator float() const {
if (_data == NaN)
return NAN;
return _data;
}
private:
int64_t _data = 0;
};
namespace its_complicated {
std::string to_string(complex c)
{
if (c.isnan()) return std::string("nan");
return std::to_string((int64_t)c);
}
inline int fpclassify(complex c) {
if (c.isnan()) return FP_NAN;
if ((uint64_t)c == (uint64_t)0) return FP_ZERO;
return FP_NORMAL;
}
inline int signbit(complex c) {
if (c.isnan()) return 0;
return ((int64_t)c < (int64_t)0) ? 1 : 0;
}
inline int isnan(complex c) {
return c.isnan();
}
inline int isinf(complex c) {
return false;
}
inline int isfinite(complex c) {
if (c.isnan()) return false;
return true;
}
inline int isnormal(complex c) {
if (c.isnan()) return false;
if ((uint64_t)c == 0) return false;
return true;
}
}
#endif

View File

@ -38,6 +38,7 @@
#include <cmath>
#include "stackframe.h"
#include "complex.h"
using ToolBox::Log;
@ -46,7 +47,12 @@ namespace SANE
{
using std::to_string;
using std::fpclassify;
using std::signbit;
using its_complicated::to_string;
using its_complicated::fpclassify;
using its_complicated::signbit;
namespace {
// default environment is:
@ -103,121 +109,6 @@ using std::to_string;
// long double is an 80-bit extended with an extra 48-bits of 0 padding.
typedef long double extended;
// comp is an int64_t but 0x8000_0000_0000_0000 is NaN
//typedef int64_t complex;
struct complex {
public:
const uint64_t NaN = 0x8000000000000000;
complex(const complex &rhs) : _data(rhs._data)
{}
complex(uint64_t rhs) : _data(rhs)
{}
bool isnan() const
{
return _data == NaN;
}
complex &operator=(const complex &rhs)
{
_data = rhs._data;
return *this;
}
complex &operator=(uint64_t rhs)
{
_data = rhs;
return *this;
}
complex &operator=(long double ld)
{
switch(std::fpclassify(ld))
{
case FP_NAN:
_data = NaN;
break;
case FP_INFINITE:
if (std::signbit(ld))
{
_data = -INT64_MAX;
}
else
{
_data = INT64_MAX;
}
break;
default:
_data = ld;
break;
}
return *this;
}
complex &operator=(double d)
{
switch(std::fpclassify(d))
{
case FP_NAN:
_data = NaN;
break;
case FP_INFINITE:
if (std::signbit(d))
{
_data = -INT64_MAX;
}
else
{
_data = INT64_MAX;
}
break;
default:
_data = d;
break;
}
return *this;
}
operator uint64_t() const {
return _data;
}
operator int64_t() const {
return _data;
}
operator long double() const {
if (_data == NaN)
return NAN;
return _data;
}
operator double() const {
if (_data == NaN)
return NAN;
return _data;
}
private:
int64_t _data;
};
// can't override std::to_string, but can import std::to_string
// then override SANE::to_string.
std::string to_string(complex c)
{
if (c.isnan()) return std::string("nan");
return std::to_string((int64_t)c);
}
template <class T>