You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

259 lines
8.7 KiB

// Basic definitions of numbers
#ifndef _CL_NUMBER_H
#define _CL_NUMBER_H
#include "cln/object.h"
#include "cln/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)
// 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)
#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)
#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
#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
namespace cln {
// Constructors and assignment operators from C numeric types.
// from `float':
union ffloatjanus;
extern cl_private_thing cl_float_to_FF_pointer (const union ffloatjanus& val);
#define CL_DEFINE_FLOAT_CONSTRUCTOR(_class_) \
inline _class_ :: _class_ (const float x) \
{ \
pointer = cl_float_to_FF_pointer(*(const union ffloatjanus *)&x); \
} \
inline _class_& _class_::operator= (const float x) \
{ \
cl_dec_refcount(*this); \
pointer = cl_float_to_FF_pointer(*(const union ffloatjanus *)&x); \
return *this; \
}
// from `double':
union dfloatjanus;
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) \
{ \
cl_dec_refcount(*this); \
pointer = cl_double_to_DF_pointer(*(const union dfloatjanus *)&x); \
return *this; \
}
// Abstract class of all numbers.
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&);
// 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);
};
// Private constructors.
inline cl_number::cl_number (cl_private_thing ptr) : cl_gcobject (ptr) {}
// The assignment operators:
CL_DEFINE_ASSIGNMENT_OPERATOR(cl_number, cl_number)
// The default constructors.
inline cl_number::cl_number ()
: cl_gcobject ((cl_private_thing) cl_combine(cl_FN_tag,0)) {}
// The copy constructors.
CL_DEFINE_COPY_CONSTRUCTOR2(cl_number,cl_gcobject)
// Constructors and assignment operators from C numeric types.
CL_DEFINE_INT_CONSTRUCTORS(cl_number)
CL_DEFINE_INT_ASSIGNMENT_OPERATORS(cl_number)
CL_DEFINE_LONG_CONSTRUCTORS(cl_number)
CL_DEFINE_LONG_ASSIGNMENT_OPERATORS(cl_number)
CL_DEFINE_FLOAT_CONSTRUCTOR(cl_number)
CL_DEFINE_DOUBLE_CONSTRUCTOR(cl_number)
// Conversion:
//inline cl_N& cl_as_N (const cl_number& x)
//{ return *(cl_N*)(&x); }
// Hack section.
// Conversions to subtypes without checking, template version:
// the<cl_I>(x) converts x to a cl_I, without change of representation.
template<class type>
inline const type& the(const cl_number& x)
{
// check that sizeof(type)==sizeof(cl_number)
typedef int assertion1 [1 - 2 * (sizeof(type) != sizeof(cl_number))];
return *(const type *) &x;
}
// Conversions to subtypes without checking, macro version:
// 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; }
} // namespace cln
// 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) type##_As
#define CL_DEFINE_AS_CONVERSION(_class_) \
extern const _class_& _class_##_As (const cl_number& x); \
inline const _class_& _class_##_As (const _class_& x) { return x; }
#else // Line number information for ease of debugging.
#define As(type) type##_As cl_as_aux
#define cl_as_aux(expr) (expr,__FILE__,__LINE__)
#define CL_DEFINE_AS_CONVERSION(_class_) \
extern const _class_& _class_##_As (const cl_number& x, const char * filename, int line); \
inline const _class_& _class_##_As (const _class_& x, const char * filename, int line) { (void)filename; (void)line; return x; }
#endif
// 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 */