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
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< |