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.
 
 
 
 
 

600 lines
21 KiB

// Public integer operations.
#ifndef _CL_INTEGER_H
#define _CL_INTEGER_H
#include "cln/number.h"
#include "cln/integer_class.h"
#include "cln/random.h"
namespace cln {
CL_DEFINE_AS_CONVERSION(cl_I)
// Konversion Integer >=0, <2^32 nach uintL.
// Wandelt Integer >=0 in Unsigned Longword um.
// cl_I_to_UL(obj)
// > obj: Integer, sollte >=0, <2^32 sein
// < ergebnis: der Wert des Integer als 32-Bit-Zahl.
extern uint32 cl_I_to_UL (const cl_I& obj);
// Konversion Integer >=-2^31, <2^31 nach sintL.
// Wandelt Integer in Signed Longword um.
// cl_I_to_L(obj)
// > obj: Integer, sollte >=-2^31, <2^31 sein
// < ergebnis: der Wert des Integer als 32-Bit-Zahl.
extern sint32 cl_I_to_L (const cl_I& obj);
// Convert an integer to a C `int' or `unsigned int'.
#if (int_bitsize==32)
inline int cl_I_to_int (const cl_I& x) { return cl_I_to_L(x); }
inline unsigned int cl_I_to_uint (const cl_I& x) { return cl_I_to_UL(x); }
#endif
// Convert an integer to a C `long' or `unsigned long'.
#if (long_bitsize==32)
inline long cl_I_to_long (const cl_I& x) { return cl_I_to_L(x); }
inline unsigned long cl_I_to_ulong (const cl_I& x) { return cl_I_to_UL(x); }
#elif (long_bitsize==64)
extern uint64 cl_I_to_UQ (const cl_I& obj);
extern sint64 cl_I_to_Q (const cl_I& obj);
inline long cl_I_to_long (const cl_I& x) { return cl_I_to_Q(x); }
inline unsigned long cl_I_to_ulong (const cl_I& x) { return cl_I_to_UQ(x); }
#endif
// Logische Operationen auf Integers:
// (LOGIOR x y), wenn x, y Integers sind.
// Ergebnis Integer.
extern const cl_I logior (const cl_I& x, const cl_I& y);
// (LOGXOR x y), wenn x, y Integers sind.
// Ergebnis Integer.
extern const cl_I logxor (const cl_I& x, const cl_I& y);
// (LOGAND x y), wenn x, y Integers sind.
// Ergebnis Integer.
extern const cl_I logand (const cl_I& x, const cl_I& y);
// (LOGEQV x y), wenn x, y Integers sind.
// Ergebnis Integer.
extern const cl_I logeqv (const cl_I& x, const cl_I& y);
// (LOGNAND x y), wenn x, y Integers sind.
// Ergebnis Integer.
extern const cl_I lognand (const cl_I& x, const cl_I& y);
// (LOGNOR x y), wenn x, y Integers sind.
// Ergebnis Integer.
extern const cl_I lognor (const cl_I& x, const cl_I& y);
// (LOGANDC2 x y), wenn x, y Integers sind.
// Ergebnis Integer.
extern const cl_I logandc2 (const cl_I& x, const cl_I& y);
// (LOGANDC1 x y), wenn x, y Integers sind.
// Ergebnis Integer.
inline const cl_I logandc1 (const cl_I& x, const cl_I& y)
{
return logandc2(y,x);
}
// (LOGORC2 x y), wenn x, y Integers sind.
// Ergebnis Integer.
extern const cl_I logorc2 (const cl_I& x, const cl_I& y);
// (LOGORC1 x y), wenn x, y Integers sind.
// Ergebnis Integer.
inline const cl_I logorc1 (const cl_I& x, const cl_I& y)
{
return logorc2(y,x);
}
// (LOGNOT x), wenn x ein Integer sind.
// Ergebnis Integer.
extern const cl_I lognot (const cl_I& x);
// Konstanten für BOOLE:
typedef enum {
boole_clr,
boole_set,
boole_1,
boole_2,
boole_c1,
boole_c2,
boole_and,
boole_ior,
boole_xor,
boole_eqv,
boole_nand,
boole_nor,
boole_andc1,
boole_andc2,
boole_orc1,
boole_orc2
} cl_boole;
// (BOOLE op x y), wenn x und y Integers und op ein Objekt sind.
// Ergebnis Integer.
extern const cl_I boole (cl_boole op, const cl_I& x, const cl_I& y);
// Prüft, ob (LOGTEST x y), wo x und y Integers sind.
// (LOGTEST x y) = (NOT (ZEROP (LOGAND x y))).
// < ergebnis: /=0, falls ja; =0, falls nein.
extern cl_boolean logtest (const cl_I& x, const cl_I& y);
// Prüft, ob (LOGBITP x y), wo x und y Integers sind.
// Ergebnis: /=0, wenn ja; =0, wenn nein.
extern cl_boolean logbitp (uintL x, const cl_I& y);
extern cl_boolean logbitp (const cl_I& x, const cl_I& y);
// Prüft, ob (ODDP x), wo x ein Integer ist.
// Ergebnis: /=0, falls ja; =0, falls nein.
extern cl_boolean oddp (const cl_I& x);
// Prüft, ob (EVENP x), wo x ein Integer ist.
// Ergebnis: /=0, falls ja; =0, falls nein.
inline cl_boolean evenp (const cl_I& x)
{ return (cl_boolean) (!oddp(x)); }
// (ASH x y), wo x und y Integers sind. Ergebnis Integer.
extern const cl_I ash (const cl_I& x, sintL y);
extern const cl_I ash (const cl_I& x, const cl_I& y);
// (LOGCOUNT x), wo x ein Integer ist. Ergebnis uintL.
extern uintL logcount (const cl_I& x);
// (INTEGER-LENGTH x), wo x ein Integer ist. Ergebnis uintL.
extern uintL integer_length (const cl_I& x);
// (ORD2 x) = max{n>=0: 2^n | x }, wo x ein Integer /=0 ist. Ergebnis uintL.
extern uintL ord2 (const cl_I& x);
// power2p(x) stellt fest, ob ein Integer x>0 eine Zweierpotenz ist.
// Ergebnis: n>0, wenn x=2^(n-1), 0 sonst.
extern uintL power2p (const cl_I& x);
inline const cl_I operator| (const cl_I& x, const cl_I& y)
{ return logior(x,y); }
inline const cl_I operator^ (const cl_I& x, const cl_I& y)
{ return logxor(x,y); }
inline const cl_I operator& (const cl_I& x, const cl_I& y)
{ return logand(x,y); }
inline const cl_I operator~ (const cl_I& x)
{ return lognot(x); }
#ifdef WANT_OBFUSCATING_OPERATORS
// This could be optimized to use in-place operations.
inline cl_I& operator|= (cl_I& x, const cl_I& y) { return x = x | y; }
inline cl_I& operator^= (cl_I& x, const cl_I& y) { return x = x ^ y; }
inline cl_I& operator&= (cl_I& x, const cl_I& y) { return x = x & y; }
#endif
// Addition/Subtraktion von Integers
// (1+ x), wo x ein Integer ist. Ergebnis Integer.
extern const cl_I plus1 (const cl_I& x);
// (1- x), wo x ein Integer ist. Ergebnis Integer.
extern const cl_I minus1 (const cl_I& x);
// (+ x y), wo x und y Integers sind. Ergebnis Integer.
extern const cl_I operator+ (const cl_I& x, const cl_I& y);
// Dem C++-Compiler muß man auch das Folgende sagen:
inline const cl_I operator+ (const int x, const cl_I& y)
{ return cl_I(x) + y; }
inline const cl_I operator+ (const unsigned int x, const cl_I& y)
{ return cl_I(x) + y; }
inline const cl_I operator+ (const long x, const cl_I& y)
{ return cl_I(x) + y; }
inline const cl_I operator+ (const unsigned long x, const cl_I& y)
{ return cl_I(x) + y; }
inline const cl_I operator+ (const cl_I& x, const int y)
{ return x + cl_I(y); }
inline const cl_I operator+ (const cl_I& x, const unsigned int y)
{ return x + cl_I(y); }
inline const cl_I operator+ (const cl_I& x, const long y)
{ return x + cl_I(y); }
inline const cl_I operator+ (const cl_I& x, const unsigned long y)
{ return x + cl_I(y); }
// (- x), wenn x ein Integer ist. Ergebnis Integer.
extern const cl_I operator- (const cl_I& x);
// (- x y), wo x und y Integers sind. Ergebnis Integer.
extern const cl_I operator- (const cl_I& x, const cl_I& y);
// Dem C++-Compiler muß man auch das Folgende sagen:
inline const cl_I operator- (const int x, const cl_I& y)
{ return cl_I(x) - y; }
inline const cl_I operator- (const unsigned int x, const cl_I& y)
{ return cl_I(x) - y; }
inline const cl_I operator- (const long x, const cl_I& y)
{ return cl_I(x) - y; }
inline const cl_I operator- (const unsigned long x, const cl_I& y)
{ return cl_I(x) - y; }
inline const cl_I operator- (const cl_I& x, const int y)
{ return x - cl_I(y); }
inline const cl_I operator- (const cl_I& x, const unsigned int y)
{ return x - cl_I(y); }
inline const cl_I operator- (const cl_I& x, const long y)
{ return x - cl_I(y); }
inline const cl_I operator- (const cl_I& x, const unsigned long y)
{ return x - cl_I(y); }
// (abs x), wenn x ein Integer ist. Ergebnis Integer.
extern const cl_I abs (const cl_I& x);
// Shifts.
inline const cl_I operator<< (const cl_I& x, sintL y) // assume 0 <= y < 2^31
{ return ash(x,y); }
inline const cl_I operator<< (const cl_I& x, const cl_I& y) // assume y >= 0
{ return ash(x,y); }
inline const cl_I operator>> (const cl_I& x, sintL y) // assume 0 <= y < 2^31
{ return ash(x,-y); }
inline const cl_I operator>> (const cl_I& x, const cl_I& y) // assume y >= 0
{ return ash(x,-y); }
// Vergleich von Integers
// equal(x,y) vergleicht zwei Integers x und y auf Gleichheit.
extern cl_boolean equal (const cl_I& x, const cl_I& y);
// equal_hashcode(x) liefert einen equal-invarianten Hashcode für x.
extern uint32 equal_hashcode (const cl_I& x);
// compare(x,y) vergleicht zwei Integers x und y.
// Ergebnis: 0 falls x=y, +1 falls x>y, -1 falls x<y.
extern cl_signean compare (const cl_I& x, const cl_I& y);
inline bool operator== (const cl_I& x, const cl_I& y)
{ return equal(x,y); }
inline bool operator!= (const cl_I& x, const cl_I& y)
{ return !equal(x,y); }
inline bool operator<= (const cl_I& x, const cl_I& y)
{ return compare(x,y)<=0; }
inline bool operator<