const dword COMPLEX_V   = 20;

struct cdouble : std::complex<double>
{
	typedef std::complex<double> C;

	cdouble() {}
	cdouble(double r) : C(r) {}
	cdouble(double r, double i) : C(r,i) {}
	cdouble(const C& c) : C(c) {}

	cdouble(const Nuller&);
	operator Value() const;
	cdouble(const Value& v);

	bool operator==(const cdouble& c) const { return (const C&)(*this) == (const C&)c; }
	bool operator!=(const cdouble& c) const { return (const C&)(*this) != (const C&)c; }
};

template<> inline bool IsNull(const cdouble& r) { return r.real() < DOUBLE_NULL_LIM || r.imag() < DOUBLE_NULL_LIM; }
template<> inline unsigned GetHashValue(const cdouble& x) { return CombineHash(x.real(), x.imag()); }
template<> inline String AsString(const cdouble& x) { return String().Cat() << "C(" << x.real() << "," << x.imag() << ")"; }

template<> inline Stream& operator%(Stream& s, cdouble& c)
{
	double r,i;
	if(s.IsStoring()) { r = c.real(); i = c.imag(); }
	s % r % i;
	if(s.IsLoading()) { c = cdouble(r,i); }
	return s;
}

template<> inline dword ValueTypeNo(const cdouble*) { return COMPLEX_V; }

inline const cdouble& Nvl(const cdouble& a, const cdouble& b)  { return IsNull(a) ? b : a; }

NTL_MOVEABLE(cdouble)
VALUE_COMPARE(cdouble)

