// Basic definitions of numbers
+
#ifndef _CL_NUMBER_H
#define _CL_NUMBER_H
+
#include "cln/object.h"
#include "cln/malloc.h"
-namespace cln {
-
// Type hierachy:
// Number (N) =
// Real (R) =
// Constructors and assignment operators from C numeric types.
+#ifdef _MSC_VER
+// Workaround to force MSVC to tag the symbol with the cln:: namespace
+// When declaring inside an inlined function the symbol is placed in the
+// global namespace!
+namespace cln {
+extern cl_private_thing cl_I_constructor_from_L (sint32 wert);
+extern cl_private_thing cl_I_constructor_from_UL (uint32 wert);
+extern cl_private_thing cl_I_constructor_from_Q (sint64 wert);
+extern cl_private_thing cl_I_constructor_from_UQ (uint64 wert);
+}
+#endif
+
#define CL_DEFINE_INT_CONSTRUCTOR(_class_,_type_) \
inline _class_::_class_ (const _type_ wert) \
{ \
}
#endif
-
-// 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
- #define CL_DEFINE_AS_CONVERSION(_class_) \
- extern const _class_& as_##_class_ (const cl_number& x); \
- inline const _class_& as_##_class_ (const _class_& 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__)
- #define CL_DEFINE_AS_CONVERSION(_class_) \
- extern const _class_& as_##_class_ (const cl_number& x, const char * filename, int line); \
- inline const _class_& as_##_class_ (const _class_& x, const char * filename, int line) { (void)filename; (void)line; return x; }
+#ifdef HAVE_LONGLONG
+#if (long_long_bitsize==64)
+// `long' == `sintQ', `unsigned long' == `uintQ'.
+#define CL_DEFINE_LONGLONG_CONSTRUCTORS(_class_) \
+inline _class_::_class_ (const long 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 long wert) \
+{ \
+ extern cl_private_thing cl_I_constructor_from_UQ (uint64 wert); \
+ pointer = cl_I_constructor_from_UQ(wert); \
+}
+#define CL_DEFINE_LONGLONG_ASSIGNMENT_OPERATORS(_class_) \
+inline _class_& _class_::operator= (const long 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 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
#endif
+namespace cln {
// Constructors and assignment operators from C numeric types.
// from `float':
-extern cl_private_thing cl_float_to_FF_pointer (const union ffloatjanus& val);
+extern cl_private_thing cl_float_to_FF_pointer (const float val);
#define CL_DEFINE_FLOAT_CONSTRUCTOR(_class_) \
inline _class_ :: _class_ (const float x) \
{ \
- pointer = cl_float_to_FF_pointer(*(const union ffloatjanus *)&x); \
+ pointer = cl_float_to_FF_pointer(x); \
} \
inline _class_& _class_::operator= (const float x) \
{ \
cl_dec_refcount(*this); \
- pointer = cl_float_to_FF_pointer(*(const union ffloatjanus *)&x); \
+ pointer = cl_float_to_FF_pointer(x); \
return *this; \
}
// from `double':
-extern struct cl_heap_dfloat * cl_double_to_DF_pointer (const union dfloatjanus& val);
+extern struct cl_heap_dfloat * cl_double_to_DF_pointer (const double val);
#define CL_DEFINE_DOUBLE_CONSTRUCTOR(_class_) \
inline _class_::_class_ (const double x) \
{ \
- pointer = cl_double_to_DF_pointer(*(const union dfloatjanus *)&x); \
+ pointer = cl_double_to_DF_pointer(x); \
} \
inline _class_& _class_::operator= (const double x) \
{ \
cl_dec_refcount(*this); \
- pointer = cl_double_to_DF_pointer(*(const union dfloatjanus *)&x); \
+ pointer = cl_double_to_DF_pointer(x); \
return *this; \
}
cl_number (const unsigned int); // argument must be < 2^29
cl_number (const long);
cl_number (const unsigned long);
+#ifdef HAVE_LONGLONG
+ cl_number (const long long);
+ cl_number (const unsigned long long);
+#endif
cl_number (const float);
cl_number (const double);
cl_number& operator= (const int); // |argument| must be < 2^29
cl_number& operator= (const unsigned long);
cl_number& operator= (const float);
cl_number& operator= (const double);
+#ifdef HAVE_LONGLONG
+ cl_number& operator= (const long long);
+ cl_number& operator= (const unsigned long long);
+#endif
// Other constructors.
// cl_number (const char *);
// Private pointer manipulations.
cl_number (cl_private_thing);
- cl_private_thing _as_cl_private_thing () const;
};
// Private constructors.
CL_DEFINE_INT_ASSIGNMENT_OPERATORS(cl_number)
CL_DEFINE_LONG_CONSTRUCTORS(cl_number)
CL_DEFINE_LONG_ASSIGNMENT_OPERATORS(cl_number)
+#ifdef HAVE_LONGLONG
+CL_DEFINE_LONGLONG_CONSTRUCTORS(cl_number)
+CL_DEFINE_LONGLONG_ASSIGNMENT_OPERATORS(cl_number)
+#endif
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:
-// The(cl_I)(x) converts x to a cl_I, without change of representation!
+// 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)
+ static_assert(sizeof(type)==sizeof(cl_number),
+ "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
const type& __tmp_##x = *(const type*) &x; \
const type& x = __tmp_##x;
-} // namespace cln
-
#endif /* _CL_NUMBER_H */