// Basic definitions of numbers

#ifndef _CL_NUMBER_H
#define _CL_NUMBER_H

#include "cl_object.h"
#include "cl_malloc.h"

// Type hierachy:
// Number (N) =
//    Real (R) =
//       Float (F) =
//          Short float (SF)
//          Single float (FF)
//          Double float (DF)
//          Long float (LF)
//       Rational (RA) =
//          Integer (I) =
//             Fixnum (FN)
//             Bignum (BN)
//          Ratio (RT)
//    Complex (C)


// Forward declarations.
class cl_number;
class cl_N;
class cl_R;
class cl_F;
class cl_SF;
class cl_FF;
class cl_DF;
class cl_LF;
class cl_RA;
class cl_I;


// Concrete class of all numbers.
// typedef
class cl_number : public cl_gcobject {
public:
// Default constructor. (Used for objects with no initializer.)
	cl_number ();
// Copy constructor. (Used for function argument passing and function
// return value, and of course for objects with initializers of the same type.)
	cl_number (const cl_number& x);
// Converters. (Used for function argument passing and function return values.)
// Assignment operators. (Used for assignments.)
	cl_number& operator= (const cl_number&);
	cl_number& operator= (const cl_N&);
	cl_number& operator= (const cl_R&);
	cl_number& operator= (const cl_F&);
	cl_number& operator= (const cl_SF&);
	cl_number& operator= (const cl_FF&);
	cl_number& operator= (const cl_DF&);
	cl_number& operator= (const cl_LF&);
	cl_number& operator= (const cl_RA&);
	cl_number& operator= (const cl_I&);
// Constructors and assignment operators from C numeric types.
	cl_number (const int);		// |argument| must be < 2^29
	cl_number (const unsigned int);	// argument must be < 2^29
	cl_number (const long);
	cl_number (const unsigned long);
	cl_number (const float);
	cl_number (const double);
	cl_number& operator= (const int);	// |argument| must be < 2^29
	cl_number& operator= (const unsigned int); // argument must be < 2^29
	cl_number& operator= (const long);
	cl_number& operator= (const unsigned long);
	cl_number& operator= (const float);
	cl_number& operator= (const double);
// Other constructors.
//	cl_number (const char *);
// Private pointer manipulations.
	cl_number (cl_private_thing);
	cl_private_thing _as_cl_private_thing () const;
private:
// Friend declarations. They are for the compiler. Just ignore them.
	friend cl_boolean cl_N_p (const cl_number& x);
	friend cl_boolean cl_R_p (const cl_number& x);
	friend cl_boolean cl_F_p (const cl_number& x);
	friend cl_boolean cl_SF_p (const cl_number& x);
	friend cl_boolean cl_FF_p (const cl_number& x);
	friend cl_boolean cl_DF_p (const cl_number& x);
	friend cl_boolean cl_LF_p (const cl_number& x);
	friend cl_boolean cl_RA_p (const cl_number& x);
	friend cl_boolean cl_I_p (const cl_number& x);
	friend struct cl_heap_complex* TheComplex (const cl_number& obj);
	friend struct cl_heap_complex* allocate_complex (const cl_R& real, const cl_R& imag);
	friend cl_boolean realp (const cl_N& x);
	friend cl_boolean complexp (const cl_N& x);
	friend cl_boolean eq (const cl_R& x, sint32 y);
#if !defined(CL_WIDE_POINTERS)
	friend struct cl_heap_ffloat* TheFfloat (const cl_number& obj);
#endif
	friend struct cl_heap_dfloat* TheDfloat (const cl_number& obj);
	friend struct cl_heap_lfloat* TheLfloat (const cl_number& obj);
	friend struct cl_heap_ratio* TheRatio (const cl_number& obj);
	friend struct cl_heap_ratio* allocate_ratio (const cl_I& num, const cl_I& den);
	friend cl_boolean zerop (const cl_RA& x);
	friend cl_boolean eq (const cl_RA& x, sint32 y);
	friend struct cl_heap_bignum* TheBignum (const cl_number& obj);
};

// Abstract classes for N, R, F, RA, I.

// typedef
class cl_N : public cl_number {
public:
// Default constructor.
	cl_N ();
// Copy constructor.
	cl_N (const cl_N&);
// Converters.
// Assignment operators.
	cl_N& operator= (const cl_N&);
	cl_N& operator= (const cl_R&);
	cl_N& operator= (const cl_F&);
	cl_N& operator= (const cl_SF&);
	cl_N& operator= (const cl_FF&);
	cl_N& operator= (const cl_DF&);
	cl_N& operator= (const cl_LF&);
	cl_N& operator= (const cl_RA&);
	cl_N& operator= (const cl_I&);
// Constructors and assignment operators from C numeric types.
	cl_N (const int);		// |argument| must be < 2^29
	cl_N (const unsigned int);	// argument must be < 2^29
	cl_N (const long);
	cl_N (const unsigned long);
	cl_N (const float);
	cl_N (const double);
	cl_N& operator= (const int);		// |argument| must be < 2^29
	cl_N& operator= (const unsigned int);	// argument must be < 2^29
	cl_N& operator= (const long);
	cl_N& operator= (const unsigned long);
	cl_N& operator= (const float);
	cl_N& operator= (const double);
// Other constructors.
	cl_N (const char *);
// Private constructor.
	cl_N (cl_private_thing);
	cl_N (struct cl_heap_complex *);
public:	// Ability to place an object at a given address.
	void* operator new (size_t size) { return cl_malloc_hook(size); }
	void* operator new (size_t size, cl_N* ptr) { (void)size; return ptr; }
	void operator delete (void* ptr) { cl_free_hook(ptr); }
private:
// Friend declarations. They are for the compiler. Just ignore them.
};

// typedef
class cl_R : public cl_N {
public:
// Default constructor.
	cl_R ();
// Copy constructor.
	cl_R (const cl_R&);
// Converters.
// Assignment operators.
	cl_R& operator= (const cl_R&);
	cl_R& operator= (const cl_F&);
	cl_R& operator= (const cl_SF&);
	cl_R& operator= (const cl_FF&);
	cl_R& operator= (const cl_DF&);
	cl_R& operator= (const cl_LF&);
// Constructors and assignment operators from C numeric types.
	cl_R (const int);		// |argument| must be < 2^29
	cl_R (const unsigned int);	// argument must be < 2^29
	cl_R (const long);
	cl_R (const unsigned long);
	cl_R (const float);
	cl_R (const double);
	cl_R& operator= (const int);		// |argument| must be < 2^29
	cl_R& operator= (const unsigned int);	// argument must be < 2^29
	cl_R& operator= (const long);
	cl_R& operator= (const unsigned long);
	cl_R& operator= (const float);
	cl_R& operator= (const double);
// Other constructors.
	cl_R (const char *);
// Private constructor.
	cl_R (cl_private_thing);
public:	// Ability to place an object at a given address.
	void* operator new (size_t size) { return cl_malloc_hook(size); }
	void* operator new (size_t size, cl_R* ptr) { (void)size; return ptr; }
	void operator delete (void* ptr) { cl_free_hook(ptr); }
private:
// Friend declarations. They are for the compiler. Just ignore them.
};

// typedef
class cl_F : public cl_R {
public:
// Default constructor.
	cl_F ();
// Copy constructor.
	cl_F (const cl_F&);
// Converters.
// Assignment operators.
	cl_F& operator= (const cl_F&);
	cl_F& operator= (const cl_SF&);
	cl_F& operator= (const cl_FF&);
	cl_F& operator= (const cl_DF&);
	cl_F& operator= (const cl_LF&);
// Constructors and assignment operators from C numeric types.
	cl_F (const float);
	cl_F (const double);
	cl_F& operator= (const float);
	cl_F& operator= (const double);
// Other constructors.
	cl_F (const char *);
// Private constructor.
	cl_F (cl_private_thing);
public:	// Ability to place an object at a given address.
	void* operator new (size_t size) { return cl_malloc_hook(size); }
	void* operator new (size_t size, cl_F* ptr) { (void)size; return ptr; }
	void operator delete (void* ptr) { cl_free_hook(ptr); }
private:
// Friend declarations. They are for the compiler. Just ignore them.
};

// typedef
class cl_SF : public cl_F {
public:
// Default constructor.
	cl_SF ();
// Assignment operators.
	cl_SF& operator= (const cl_SF&);
// Optimization of method pointer_p().
	cl_boolean pointer_p() const
		{ return cl_false; }
// Faster pointer_p() gives a faster copy constructor (but not destructor!!!).
	cl_SF (const cl_SF& x);
// Other constructors.
	cl_SF (const char *);
// Private constructor.
	cl_SF (cl_private_thing);
	cl_SF (struct cl_sfloat * /* NULL! */, cl_uint);
public:	// Ability to place an object at a given address.
	void* operator new (size_t size) { return cl_malloc_hook(size); }
	void* operator new (size_t size, cl_SF* ptr) { (void)size; return ptr; }
	void operator delete (void* ptr) { cl_free_hook(ptr); }
private:
// Friend declarations. They are for the compiler. Just ignore them.
	friend uintL SF_uexp (const cl_SF& x);
	friend cl_signean SF_sign (const cl_SF& x);
	friend uintL SF_mant (const cl_SF& x);
	friend cl_boolean zerop (const cl_SF& x);
	friend cl_boolean minusp (const cl_SF& x);
	friend cl_signean cl_compare (const cl_SF& x, const cl_SF& y);
	friend cl_SF operator+ (const cl_SF& x1, const cl_SF& x2);
	friend cl_SF operator- (const cl_SF& x);
	friend cl_SF operator- (const cl_SF& x1, const cl_SF& x2);
	friend cl_SF fround (const cl_SF& x);
	friend cl_SF ftruncate (const cl_SF& x);
	friend cl_SF futruncate (const cl_SF& x);
};

// typedef
class cl_FF : public cl_F {
public:
// Default constructor.
	cl_FF ();
// Assignment operators.
	cl_FF& operator= (const cl_FF&);
// Optimization of method pointer_p().
	cl_boolean pointer_p() const
#if defined(CL_WIDE_POINTERS)
		{ return cl_false; }
#else
		{ return cl_true; }
#endif
// Faster pointer_p() gives a faster copy constructor (but not destructor!!!).
	cl_FF (const cl_FF& x);
// Constructors and assignment operators from C numeric types.
	cl_FF (const float);
	cl_FF& operator= (const float);
// Other constructors.
	cl_FF (const char *);
// Private constructor.
	cl_FF (cl_private_thing);
#if defined(CL_WIDE_POINTERS)
	cl_FF (struct cl_heap_ffloat * /* NULL! */, cl_uint);
#else
	cl_FF (struct cl_heap_ffloat *);
// Private pointer manipulations.
	operator struct cl_heap_ffloat * () const;
#endif
public:	// Ability to place an object at a given address.
	void* operator new (size_t size) { return cl_malloc_hook(size); }
	void* operator new (size_t size, cl_FF* ptr) { (void)size; return ptr; }
	void operator delete (void* ptr) { cl_free_hook(ptr); }
private:
// Friend declarations. They are for the compiler. Just ignore them.
#if defined(CL_WIDE_POINTERS)
	friend uint32 cl_ffloat_value (const cl_FF& x);
	friend cl_private_thing cl_FF_pointer_value (const cl_FF& x);
#endif
};

// typedef
class cl_DF : public cl_F {
public:
// Default constructor.
	cl_DF ();
// Assignment operators.
	cl_DF& operator= (const cl_DF&);
// Optimization of method pointer_p().
	cl_boolean pointer_p() const
		{ return cl_true; }
// Faster pointer_p() gives a faster copy constructor (but not destructor!!!).
	cl_DF (const cl_DF& x);
// Constructors and assignment operators from C numeric types.
	cl_DF (const double);
	cl_DF& operator= (const double);
// Other constructors.
	cl_DF (const char *);
// Private constructor.
	cl_DF (cl_private_thing);
	cl_DF (struct cl_heap_dfloat *);
// Private pointer manipulations.
	operator struct cl_heap_dfloat * () const;
public:	// Ability to place an object at a given address.
	void* operator new (size_t size) { return cl_malloc_hook(size); }
	void* operator new (size_t size, cl_DF* ptr) { (void)size; return ptr; }
	void operator delete (void* ptr) { cl_free_hook(ptr); }
private:
// Friend declarations. They are for the compiler. Just ignore them.
};

// typedef
class cl_LF : public cl_F {
public:
// Default constructor.
	cl_LF ();
// Assignment operators.
	cl_LF& operator= (const cl_LF&);
// Optimization of method pointer_p().
	cl_boolean pointer_p() const
		{ return cl_true; }
// Faster pointer_p() gives a faster copy constructor (but not destructor!!!).
	cl_LF (const cl_LF& x);
// Other constructors.
	cl_LF (const char *);
// Private constructor.
	cl_LF (cl_private_thing);
	cl_LF (struct cl_heap_lfloat *);
// Private pointer manipulations.
	operator struct cl_heap_lfloat * () const;
public:	// Ability to place an object at a given address.
	void* operator new (size_t size) { return cl_malloc_hook(size); }
	void* operator new (size_t size, cl_LF* ptr) { (void)size; return ptr; }
	void operator delete (void* ptr) { cl_free_hook(ptr); }
private:
// Friend declarations. They are for the compiler. Just ignore them.
	friend cl_LF LF_LF_plus_LF (const cl_LF& arg1, const cl_LF& arg2);
};
// Define this if you want the elementary cl_LF operations (+, -, *, /,
// sqrt, cl_LF_I_mul) to return results which are always the correctly
// rounded exact results, i.e. results which are correct within 0.5 ulp.
// If you don't define this, results will be correct within 0.50001 ulp,
// but often the computation will be much faster.
/* #define CL_LF_PEDANTIC */

// typedef
class cl_RA : public cl_R {
public:
// Default constructor.
	cl_RA ();
// Copy constructor.
	cl_RA (const cl_RA&);
// Converters.
// Assignment operators.
	cl_RA& operator= (const cl_RA&);
	cl_RA& operator= (const cl_I&);
// Constructors and assignment operators from C numeric types.
	cl_RA (const int);		// |argument| must be < 2^29
	cl_RA (const unsigned int);	// argument must be < 2^29
	cl_RA (const long);
	cl_RA (const unsigned long);
	cl_RA& operator= (const int);		// |argument| must be < 2^29
	cl_RA& operator= (const unsigned int);	// argument must be < 2^29
	cl_RA& operator= (const long);
	cl_RA& operator= (const unsigned long);
// Other constructors.
	cl_RA (const char *);
// Private constructor.
	cl_RA (cl_private_thing);
	cl_RA (struct cl_heap_ratio *);
public:	// Ability to place an object at a given address.
	void* operator new (size_t size) { return cl_malloc_hook(size); }
	void* operator new (size_t size, cl_RA* ptr) { (void)size; return ptr; }
	void operator delete (void* ptr) { cl_free_hook(ptr); }
private:
// Friend declarations. They are for the compiler. Just ignore them.
};

// typedef
class cl_I : public cl_RA {
public:
// Default constructor.
	cl_I ();
// Copy constructor.
	cl_I (const cl_I&);
// Assignment operators.
	cl_I& operator= (const cl_I&);
// Constructors and assignment operators from C numeric types.
	cl_I (const int);		// |argument| must be < 2^29
	cl_I (const unsigned int);	// argument must be < 2^29
	cl_I (const long);
	cl_I (const unsigned long);
	cl_I& operator= (const int);		// |argument| must be < 2^29
	cl_I& operator= (const unsigned int);	// argument must be < 2^29
	cl_I& operator= (const long);
	cl_I& operator= (const unsigned long);
// Other constructors.
	cl_I (const char *);
// Private constructor.
	cl_I (cl_private_thing);
	cl_I (struct cl_fixnum * /* NULL! */, cl_uint);
	cl_I (struct cl_heap_bignum *);
public:	// Ability to place an object at a given address.
	void* operator new (size_t size) { return cl_malloc_hook(size); }
	void* operator new (size_t size, cl_I* ptr) { (void)size; return ptr; }
	void operator delete (void* ptr) { cl_free_hook(ptr); }
private:
// Friend declarations. They are for the compiler. Just ignore them.
	friend cl_boolean minusp (const cl_I& x);
	friend cl_boolean zerop (const cl_I& x);
	friend cl_boolean eq (const cl_I& x, sint32 y);
	friend cl_uint cl_FN_word (const cl_I& x);
	friend uint32 FN_to_UL (const cl_I& x);
	friend sint32 FN_to_L (const cl_I& x);
	friend cl_boolean cl_equal (const cl_I& x, const cl_I& y);
	friend cl_signean cl_compare (const cl_I& x, const cl_I& y);
	friend cl_I logior (const cl_I& x, const cl_I& y);
	friend cl_I logxor (const cl_I& x, const cl_I& y);
	friend cl_I logand (const cl_I& x, const cl_I& y);
	friend cl_I logeqv (const cl_I& x, const cl_I& y);
	friend cl_I lognand (const cl_I& x, const cl_I& y);
	friend cl_I lognor (const cl_I& x, const cl_I& y);
	friend cl_I logandc2 (const cl_I& x, const cl_I& y);
	friend cl_I logorc2 (const cl_I& x, const cl_I& y);
	friend cl_I lognot (const cl_I& x);
	friend cl_boolean logtest (const cl_I& x, const cl_I& y);
	friend cl_boolean oddp (const cl_I& x);
	friend cl_I plus1 (const cl_I& x);
	friend cl_I minus1 (const cl_I& x);
};

// Private constructors.
inline cl_number::cl_number (cl_private_thing ptr) : cl_gcobject (ptr) {}
inline cl_N::cl_N (cl_private_thing ptr) : cl_number (ptr) {}
inline cl_R::cl_R (cl_private_thing ptr) : cl_N (ptr) {}
inline cl_F::cl_F (cl_private_thing ptr) : cl_R (ptr) {}
inline cl_SF::cl_SF (cl_private_thing ptr) : cl_F (ptr) {}
inline cl_FF::cl_FF (cl_private_thing ptr) : cl_F (ptr) {}
inline cl_DF::cl_DF (cl_private_thing ptr) : cl_F (ptr) {}
inline cl_LF::cl_LF (cl_private_thing ptr) : cl_F (ptr) {}
inline cl_RA::cl_RA (cl_private_thing ptr) : cl_R (ptr) {}
inline cl_I::cl_I (cl_private_thing ptr) : cl_RA (ptr) {}

// The assignment operators:
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_number, cl_number)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_number, cl_N)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_number, cl_R)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_number, cl_F)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_number, cl_SF)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_number, cl_FF)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_number, cl_DF)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_number, cl_LF)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_number, cl_RA)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_number, cl_I)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_N, cl_N)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_N, cl_R)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_N, cl_F)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_N, cl_SF)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_N, cl_FF)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_N, cl_DF)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_N, cl_LF)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_N, cl_RA)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_N, cl_I)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_R, cl_R)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_R, cl_F)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_R, cl_SF)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_R, cl_FF)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_R, cl_DF)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_R, cl_LF)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_F, cl_F)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_F, cl_SF)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_F, cl_FF)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_F, cl_DF)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_F, cl_LF)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_SF, cl_SF)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_FF, cl_FF)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_DF, cl_DF)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_LF, cl_LF)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_RA, cl_RA)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_RA, cl_I)
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_I, cl_I)

// The default constructors.
inline cl_number::cl_number ()
	: cl_gcobject ((cl_private_thing) cl_combine(cl_FN_tag,0)) {}
inline cl_N::cl_N ()
	: cl_number ((cl_private_thing) cl_combine(cl_FN_tag,0)) {}
inline cl_R::cl_R ()
	: cl_N ((cl_private_thing) cl_combine(cl_FN_tag,0)) {}
inline cl_F::cl_F ()
	: cl_R ((cl_private_thing) cl_combine(cl_SF_tag,0)) {}
inline cl_SF::cl_SF ()
	: cl_F ((cl_private_thing) cl_combine(cl_SF_tag,0)) {}
#if defined(CL_WIDE_POINTERS)
inline cl_FF::cl_FF ()
	: cl_F ((cl_private_thing) cl_combine(cl_FF_tag,0)) {}
// `cl_FF_pointer' is just `cl_FF'.
typedef cl_FF cl_FF_pointer;
inline cl_private_thing cl_FF_pointer_value (const cl_FF& x)
	{ return (cl_private_thing)x.pointer; }
#else
// Private pointer manipulations. Never throw away a `struct cl_heap_ffloat *'!
inline cl_FF::operator struct cl_heap_ffloat * () const
{
	struct cl_heap_ffloat * hpointer = (struct cl_heap_ffloat *) pointer;
	cl_inc_refcount(*this);
	return hpointer;
}
extern cl_FF cl_FF_0;
inline cl_FF::cl_FF ()
	: cl_F ((cl_private_thing) (struct cl_heap_ffloat *) cl_FF_0) {}
CL_REQUIRE(cl_FF_globals)
#if 0 // see cl_FF.h
inline cl_FF::cl_FF (struct cl_heap_ffloat * ptr)
	: cl_F ((cl_private_thing) ptr) {}
#endif
// `cl_FF_pointer' is just `cl_FF' as a pointer, without destructor.
typedef struct cl_heap_ffloat * cl_FF_pointer;
inline cl_private_thing cl_FF_pointer_value (const cl_FF_pointer p)
	{ return (cl_private_thing)p; }
#endif
// Private pointer manipulations. Never throw away a `struct cl_heap_dfloat *'!
inline cl_DF::operator struct cl_heap_dfloat * () const
{
	struct cl_heap_dfloat * hpointer = (struct cl_heap_dfloat *) pointer;
	cl_inc_refcount(*this);
	return hpointer;
}
extern cl_DF cl_DF_0;
inline cl_DF::cl_DF ()
	: cl_F ((cl_private_thing) (struct cl_heap_dfloat *) cl_DF_0) {}
CL_REQUIRE(cl_DF_globals)
#if 0 // see cl_DF.h
inline cl_DF::cl_DF (struct cl_heap_dfloat * ptr)
	: cl_F ((cl_private_thing) ptr) {}
#endif
// Private pointer manipulations. Never throw away a `struct cl_heap_lfloat *'!
inline cl_LF::operator struct cl_heap_lfloat * () const
{
	struct cl_heap_lfloat * hpointer = (struct cl_heap_lfloat *) pointer;
	cl_inc_refcount(*this);
	return hpointer;
}
extern cl_LF cl_LF_0;
inline cl_LF::cl_LF ()
	: cl_F ((cl_private_thing) (struct cl_heap_lfloat *) cl_LF_0) {}
CL_REQUIRE(cl_LF_globals)
#if 0 // see cl_LF_impl.h
inline cl_LF::cl_LF (struct cl_heap_lfloat * ptr)
	: cl_F ((cl_private_thing) ptr) {}
#endif
inline cl_RA::cl_RA ()
	: cl_R ((cl_private_thing) cl_combine(cl_FN_tag,0)) {}
inline cl_I::cl_I ()
	: cl_RA ((cl_private_thing) cl_combine(cl_FN_tag,0)) {}

// The copy constructors.
CL_DEFINE_COPY_CONSTRUCTOR2(cl_number,cl_gcobject)
CL_DEFINE_COPY_CONSTRUCTOR2(cl_N,cl_number)
CL_DEFINE_COPY_CONSTRUCTOR2(cl_R,cl_N)
CL_DEFINE_COPY_CONSTRUCTOR2(cl_F,cl_R)
CL_DEFINE_COPY_CONSTRUCTOR2(cl_SF,cl_F)
CL_DEFINE_COPY_CONSTRUCTOR2(cl_FF,cl_F)
CL_DEFINE_COPY_CONSTRUCTOR2(cl_DF,cl_F)
CL_DEFINE_COPY_CONSTRUCTOR2(cl_LF,cl_F)
CL_DEFINE_COPY_CONSTRUCTOR2(cl_RA,cl_R)
CL_DEFINE_COPY_CONSTRUCTOR2(cl_I,cl_RA)

// Constructors and assignment operators from C numeric types.

#define CL_DEFINE_INT_CONSTRUCTOR(_class_,_type_)  \
inline _class_::_class_ (const _type_ wert)				\
{									\
	word = cl_combine(cl_FN_tag,wert);				\
}
#define CL_DEFINE_INT_CONSTRUCTORS(_class_)  \
CL_DEFINE_INT_CONSTRUCTOR(_class_, int)					\
CL_DEFINE_INT_CONSTRUCTOR(_class_, unsigned int)

CL_DEFINE_INT_CONSTRUCTORS(cl_number)
CL_DEFINE_INT_CONSTRUCTORS(cl_N)
CL_DEFINE_INT_CONSTRUCTORS(cl_R)
CL_DEFINE_INT_CONSTRUCTORS(cl_RA)
CL_DEFINE_INT_CONSTRUCTORS(cl_I)

#define CL_DEFINE_INT_ASSIGNMENT_OPERATOR(_class_,_type_)  \
inline _class_& _class_::operator= (const _type_ wert)			\
{									\
	cl_dec_refcount(*this);						\
	word = cl_combine(cl_FN_tag,wert);				\
	return *this;							\
}
#define CL_DEFINE_INT_ASSIGNMENT_OPERATORS(_class_)  \
CL_DEFINE_INT_ASSIGNMENT_OPERATOR(_class_, int)				\
CL_DEFINE_INT_ASSIGNMENT_OPERATOR(_class_, unsigned int)

CL_DEFINE_INT_ASSIGNMENT_OPERATORS(cl_number)
CL_DEFINE_INT_ASSIGNMENT_OPERATORS(cl_N)
CL_DEFINE_INT_ASSIGNMENT_OPERATORS(cl_R)
CL_DEFINE_INT_ASSIGNMENT_OPERATORS(cl_RA)
CL_DEFINE_INT_ASSIGNMENT_OPERATORS(cl_I)

#if (long_bitsize==32)
// `long' == `sintL', `unsigned long' == `uintL'.
#define CL_DEFINE_LONG_CONSTRUCTORS(_class_)  \
inline _class_::_class_ (const long wert)				\
{									\
	extern cl_private_thing cl_I_constructor_from_L (sint32 wert);	\
	pointer = cl_I_constructor_from_L(wert);			\
}									\
inline _class_::_class_ (const unsigned long wert)			\
{									\
	extern cl_private_thing cl_I_constructor_from_UL (uint32 wert);	\
	pointer = cl_I_constructor_from_UL(wert);			\
}
#elif (long_bitsize==64)
// `long' == `sintQ', `unsigned long' == `uintQ'.
#define CL_DEFINE_LONG_CONSTRUCTORS(_class_)  \
inline _class_::_class_ (const long wert)				\
{									\
	extern cl_private_thing cl_I_constructor_from_Q (sint64 wert);	\
	pointer = cl_I_constructor_from_Q(wert);			\
}									\
inline _class_::_class_ (const unsigned long wert)			\
{									\
	extern cl_private_thing cl_I_constructor_from_UQ (uint64 wert);	\
	pointer = cl_I_constructor_from_UQ(wert);			\
}
#endif

CL_DEFINE_LONG_CONSTRUCTORS(cl_number)
CL_DEFINE_LONG_CONSTRUCTORS(cl_N)
CL_DEFINE_LONG_CONSTRUCTORS(cl_R)
CL_DEFINE_LONG_CONSTRUCTORS(cl_RA)
CL_DEFINE_LONG_CONSTRUCTORS(cl_I)

#if (long_bitsize==32)
// `long' == `sintL', `unsigned long' == `uintL'.
#define CL_DEFINE_LONG_ASSIGNMENT_OPERATORS(_class_)  \
inline _class_& _class_::operator= (const long wert)			\
{									\
	extern cl_private_thing cl_I_constructor_from_L (sint32 wert);	\
	cl_dec_refcount(*this);						\
	pointer = cl_I_constructor_from_L(wert);			\
	return *this;							\
}									\
inline _class_& _class_::operator= (const unsigned long wert)		\
{									\
	extern cl_private_thing cl_I_constructor_from_UL (uint32 wert);	\
	cl_dec_refcount(*this);						\
	pointer = cl_I_constructor_from_UL(wert);			\
	return *this;							\
}
#elif (long_bitsize==64)
// `long' == `sintQ', `unsigned long' == `uintQ'.
#define CL_DEFINE_LONG_ASSIGNMENT_OPERATORS(_class_)  \
inline _class_& _class_::operator= (const long wert)			\
{									\
	extern cl_private_thing cl_I_constructor_from_Q (sint64 wert);	\
	cl_dec_refcount(*this);						\
	pointer = cl_I_constructor_from_Q(wert);			\
	return *this;							\
}									\
inline _class_& _class_::operator= (const unsigned long wert)		\
{									\
	extern cl_private_thing cl_I_constructor_from_UQ (uint64 wert);	\
	cl_dec_refcount(*this);						\
	pointer = cl_I_constructor_from_UQ(wert);			\
	return *this;							\
}
#endif

CL_DEFINE_LONG_ASSIGNMENT_OPERATORS(cl_number)
CL_DEFINE_LONG_ASSIGNMENT_OPERATORS(cl_N)
CL_DEFINE_LONG_ASSIGNMENT_OPERATORS(cl_R)
CL_DEFINE_LONG_ASSIGNMENT_OPERATORS(cl_RA)
CL_DEFINE_LONG_ASSIGNMENT_OPERATORS(cl_I)

// Conversions to subtypes:
// As(cl_I)(x) returns x as a cl_I. It first checks that x is a cl_I
// and then returns it without change of representation.
#if 0 // no debug information
  #define As(type)  as_##type
extern const cl_N& as_cl_N (const cl_number& x);
extern const cl_R& as_cl_R (const cl_number& x);
extern const cl_F& as_cl_F (const cl_number& x);
extern const cl_SF& as_cl_SF (const cl_number& x);
extern const cl_FF& as_cl_FF (const cl_number& x);
extern const cl_DF& as_cl_DF (const cl_number& x);
extern const cl_LF& as_cl_LF (const cl_number& x);
extern const cl_RA& as_cl_RA (const cl_number& x);
extern const cl_I& as_cl_I (const cl_number& x);
// These special cases need no checking.
inline const cl_N& as_cl_N (const cl_N& x) { return x; }
inline const cl_R& as_cl_R (const cl_R& x) { return x; }
inline const cl_F& as_cl_F (const cl_F& x) { return x; }
inline const cl_SF& as_cl_SF (const cl_SF& x) { return x; }
inline const cl_FF& as_cl_FF (const cl_FF& x) { return x; }
inline const cl_DF& as_cl_DF (const cl_DF& x) { return x; }
inline const cl_LF& as_cl_LF (const cl_LF& x) { return x; }
inline const cl_RA& as_cl_RA (const cl_RA& x) { return x; }
inline const cl_I& as_cl_I (const cl_I& x) { return x; }
#else // Line number information for ease of debugging.
  #define As(type)  as_##type cl_as_aux
  #define cl_as_aux(expr)  (expr,__FILE__,__LINE__)
extern const cl_N& as_cl_N (const cl_number& x, const char * filename, int line);
extern const cl_R& as_cl_R (const cl_number& x, const char * filename, int line);
extern const cl_F& as_cl_F (const cl_number& x, const char * filename, int line);
extern const cl_SF& as_cl_SF (const cl_number& x, const char * filename, int line);
extern const cl_FF& as_cl_FF (const cl_number& x, const char * filename, int line);
extern const cl_DF& as_cl_DF (const cl_number& x, const char * filename, int line);
extern const cl_LF& as_cl_LF (const cl_number& x, const char * filename, int line);
extern const cl_RA& as_cl_RA (const cl_number& x, const char * filename, int line);
extern const cl_I& as_cl_I (const cl_number& x, const char * filename, int line);
// These special cases need no checking.
inline const cl_N& as_cl_N (const cl_N& x, const char * filename, int line) { (void)filename; (void)line; return x; }
inline const cl_R& as_cl_R (const cl_R& x, const char * filename, int line) { (void)filename; (void)line; return x; }
inline const cl_F& as_cl_F (const cl_F& x, const char * filename, int line) { (void)filename; (void)line; return x; }
inline const cl_SF& as_cl_SF (const cl_SF& x, const char * filename, int line) { (void)filename; (void)line; return x; }
inline const cl_FF& as_cl_FF (const cl_FF& x, const char * filename, int line) { (void)filename; (void)line; return x; }
inline const cl_DF& as_cl_DF (const cl_DF& x, const char * filename, int line) { (void)filename; (void)line; return x; }
inline const cl_LF& as_cl_LF (const cl_LF& x, const char * filename, int line) { (void)filename; (void)line; return x; }
inline const cl_RA& as_cl_RA (const cl_RA& x, const char * filename, int line) { (void)filename; (void)line; return x; }
inline const cl_I& as_cl_I (const cl_I& x, const char * filename, int line) { (void)filename; (void)line; return x; }
#endif


// Constructors and assignment operators from C numeric types.

// from `float':
extern cl_FF_pointer cl_float_to_FF_pointer (const union ffloatjanus& val);

#define CL_DEFINE_FLOAT_CONSTRUCTOR(_class_)				\
inline _class_ :: _class_ (const float x)				\
{									\
	pointer = cl_FF_pointer_value(cl_float_to_FF_pointer(*(const union ffloatjanus *)&x)); \
}									\
inline _class_& _class_::operator= (const float x)			\
{									\
	cl_private_thing tmp = cl_FF_pointer_value(cl_float_to_FF_pointer(*(const union ffloatjanus *)&x)); \
	cl_dec_refcount(*this);						\
	pointer = tmp;							\
	return *this;							\
}

CL_DEFINE_FLOAT_CONSTRUCTOR(cl_FF)
CL_DEFINE_FLOAT_CONSTRUCTOR(cl_F)
CL_DEFINE_FLOAT_CONSTRUCTOR(cl_R)
CL_DEFINE_FLOAT_CONSTRUCTOR(cl_N)
CL_DEFINE_FLOAT_CONSTRUCTOR(cl_number)

// from `double':
extern struct cl_heap_dfloat * cl_double_to_DF_pointer (const union dfloatjanus& val);

#define CL_DEFINE_DOUBLE_CONSTRUCTOR(_class_)				\
inline _class_::_class_ (const double x)				\
{									\
	pointer = cl_double_to_DF_pointer(*(const union dfloatjanus *)&x); \
}									\
inline _class_& _class_::operator= (const double x)			\
{									\
	struct cl_heap_dfloat * tmp = cl_double_to_DF_pointer(*(const union dfloatjanus *)&x); \
	cl_dec_refcount(*this);						\
	pointer = tmp;							\
	return *this;							\
}

CL_DEFINE_DOUBLE_CONSTRUCTOR(cl_DF)
CL_DEFINE_DOUBLE_CONSTRUCTOR(cl_F)
CL_DEFINE_DOUBLE_CONSTRUCTOR(cl_R)
CL_DEFINE_DOUBLE_CONSTRUCTOR(cl_N)
CL_DEFINE_DOUBLE_CONSTRUCTOR(cl_number)


// Return type for integer_decode_float:
struct cl_idecoded_float {
	cl_I mantissa;
	cl_I exponent;
	cl_I sign;
// Constructor.
	cl_idecoded_float () {}
	cl_idecoded_float (const cl_I& m, const cl_I& e, const cl_I& s) : mantissa(m), exponent(e), sign(s) {}
};


// Conversion:
//inline cl_N& cl_as_N (const cl_number& x)
//{ return *(cl_N*)(&x); }


// Hack section.

// Conversions to subtypes without checking:
// The(cl_I)(x) converts x to a cl_I, without change of representation!
  #define The(type)  *(const type *) & cl_identity
// This inline function is for type checking purposes only.
  inline const cl_number& cl_identity (const cl_number& x) { return x; }

// Mutable(type,x);
// x should be a variable `const type x' or `const type& x'.
// This macro introduces a new variable `type& x' whose value can be
// modified. Useful for modifying the argument of a function which takes
// a `const type &x'.
// Warning: To apply this to a function's formal parameter, a block { ... }
// must be inserted.
  #define Mutable(type,x)  \
    type __copied_##x = x;						\
    type& x = __copied_##x;

// DeclareType(type,x);
// x should be a variable of some subtype of `cl_number'. type should be
// a subtype of `cl_number'. A new variable of the given type is declared,
// with name x and which refers to x (by reference, with const attribute).
  #define DeclareType(type,x)  \
    const type& __tmp_##x = *(const type*) &x;				\
    const type& x = __tmp_##x;


#endif /* _CL_NUMBER_H */
