1
// ---------------------------------------------------------------------------
3
// - standard object library - integer class implementation -
4
// ---------------------------------------------------------------------------
5
// - This program is free software; you can redistribute it and/or modify -
6
// - it provided that this copyright notice is kept intact. -
8
// - This program is distributed in the hope that it will be useful, but -
9
// - without any warranty; without even the implied warranty of -
10
// - merchantability or fitness for a particular purpose. In no event shall -
11
// - the copyright holder be liable for any direct, indirect, incidental or -
12
// - special damages arising in any way out of the use of this software. -
13
// ---------------------------------------------------------------------------
14
// - copyright (c) 1999-2011 amaury darsch -
15
// ---------------------------------------------------------------------------
20
#include "Utility.hpp"
21
#include "Boolean.hpp"
22
#include "Runnable.hpp"
23
#include "QuarkZone.hpp"
24
#include "Character.hpp"
25
#include "Exception.hpp"
26
#include "InputStream.hpp"
27
#include "OutputStream.hpp"
32
// -------------------------------------------------------------------------
34
// -------------------------------------------------------------------------
36
// compute the opposite of the current integer
38
Integer operator - (const Integer& x) {
41
Integer result = -x.d_value;
50
// add two integers together from two integers
52
Integer operator + (const Integer& x, const Integer& y) {
56
Integer result = x.d_value + y.d_value;
67
// substract two integers together from two integers
69
Integer operator - (const Integer& x, const Integer& y) {
73
Integer result = x.d_value - y.d_value;
84
// multiply two integers together from two integers
86
Integer operator * (const Integer& x, const Integer& y) {
90
Integer result = x.d_value * y.d_value;
101
// divide two integers together from two integers
103
Integer operator / (const Integer& x, const Integer& y) {
107
if (y.d_value == 0) {
108
throw Exception ("integer-error","division by zero");
110
Integer result = x.d_value / y.d_value;
121
// return the remainder of this number with its argument
123
Integer operator % (const Integer& x, const Integer& y) {
127
if (y.d_value == 0) {
128
throw Exception ("integer-error","division by zero");
130
Integer result = x.d_value % y.d_value;
141
// bitwise negate an integer
142
Integer operator ~ (const Integer& x) {
145
Integer result = ~x.d_value;
154
// bitwise and an integer with another one
156
Integer operator & (const Integer& x, const Integer& y) {
160
Integer result = x.d_value & y.d_value;
171
// bitwise or an integer with another one
173
Integer operator | (const Integer& x, const Integer& y) {
177
Integer result = x.d_value | y.d_value;
188
// bitwise xor an integer with another one
190
Integer operator ^ (const Integer& x, const Integer& y) {
194
Integer result = x.d_value ^ y.d_value;
205
// -------------------------------------------------------------------------
207
// -------------------------------------------------------------------------
209
// create a new default integer
211
Integer::Integer (void) {
215
// create a new integer from a long integer
217
Integer::Integer (const t_long value) {
221
// create a new integer from a string
223
Integer::Integer (const String& value) {
224
d_value = Utility::tolong (value);
227
// copy constructor for this integer
229
Integer::Integer (const Integer& that) {
232
d_value = that.d_value;
240
// return the class name
242
String Integer::repr (void) const {
246
// return a clone of this object
248
Object* Integer::clone (void) const {
249
return new Integer (*this);
252
// return a literal representation of this integer
254
String Integer::toliteral (void) const {
257
String result = tostring ();
266
// get a string representation on this integer
268
String Integer::tostring (void) const {
271
String result = Utility::tostring (d_value);
280
// return the integer serial code
282
t_byte Integer::serialid (void) const {
283
return SERIAL_INTG_ID;
286
// serialize this integer
288
void Integer::wrstream (OutputStream& os) const {
292
c_ohton (d_value, data);
293
os.write ((char*) data, 8);
301
// deserialize this integer
303
void Integer::rdstream (InputStream& is) {
307
for (long i = 0; i < 8; i++) data[i] = (t_byte) is.read ();
308
d_value = c_ontoh (data);
316
// set an integer with a value
318
Integer& Integer::operator = (const t_long value) {
330
// set an integer with a value
332
Integer& Integer::operator = (const Integer& that) {
333
// check for self assignation
334
if (this == &that) return *this;
339
d_value = that.d_value;
350
// add an integer to this one
352
Integer& Integer::operator += (const Integer& x) {
356
d_value += x.d_value;
367
// substract an integer to this one
369
Integer& Integer::operator -= (const Integer& x) {
373
d_value -= x.d_value;
384
// multiply an integer with this one
386
Integer& Integer::operator *= (const Integer& x) {
390
d_value *= x.d_value;
401
// divide an integer with this one
403
Integer& Integer::operator /= (const Integer& x) {
407
if (x.d_value == 0) {
408
throw Exception ("integer-error","division by zero");
410
d_value /= x.d_value;
421
// prefix add one to the integer
423
Integer& Integer::operator ++ (void) {
435
// postfix add one to the integer
437
Integer Integer::operator ++ (int) {
440
Integer result = *this;
450
// prefix sub one to the integer
452
Integer& Integer::operator -- (void) {
464
// postfix sub one to the integer
466
Integer Integer::operator -- (int) {
469
Integer result = *this;
479
// shift left this integer
481
Integer Integer::operator << (const long asl) const {
484
Integer result = d_value << (asl % 64);
493
// shift right this integer
495
Integer Integer::operator >> (const long asr) const {
498
Integer result = d_value >> (asr % 64);
507
// compare an integer with a native value
509
bool Integer::operator == (const t_long value) const {
512
bool result = (d_value == value);
521
bool Integer::operator != (const t_long value) const {
524
bool result = (d_value != value);
533
// compare two integers
535
bool Integer::operator == (const Integer& value) const {
539
bool result = (d_value == value.d_value);
550
// compare two integers
552
bool Integer::operator != (const Integer& value) const {
556
bool result = (d_value != value.d_value);
567
// compare two integers
569
bool Integer::operator < (const Integer& value) const {
573
bool result = (d_value < value.d_value);
584
// compare two integers
586
bool Integer::operator <= (const Integer& value) const {
590
bool result = (d_value <= value.d_value);
601
// compare two integers
603
bool Integer::operator > (const Integer& value) const {
607
bool result = (d_value > value.d_value);
618
// compare two integers
620
bool Integer::operator >= (const Integer& value) const {
624
bool result = (d_value >= value.d_value);
635
// return true if the integer is zero
637
bool Integer::iszero (void) const {
640
bool result = (d_value == 0);
649
// return true if the integer is even
651
bool Integer::iseven (void) const {
654
bool result = ((d_value & 1) == 0);
663
// return true if the integer is odd
665
bool Integer::isodd (void) const {
668
bool result = ((d_value & 1) == 1);
677
// return the absolute value of this number
679
Integer Integer::abs (void) const {
682
Integer result = (d_value < 0) ? -d_value : d_value;
691
// convert this integer into a hexadecimal representation
693
String Integer::tohexa (void) const {
696
// prepare result string
697
String result = (d_value < 0) ? "-0x" : "0x";
698
// bind the integer value
699
t_octa data = d_value < 0 ? -d_value : d_value;
700
result += Utility::tohexa (data);
710
// convert this integer into a hexadecimal string
712
String Integer::tohstr (void) const {
715
// bind the integer value
716
t_octa data = d_value < 0 ? -d_value : d_value;
717
String result = Utility::tohexa (data);
727
// return a native integer value
729
t_long Integer::tolong (void) const {
732
t_long result = d_value;
741
// -------------------------------------------------------------------------
742
// - object section -
743
// -------------------------------------------------------------------------
746
static const long QUARK_ZONE_LENGTH = 27;
747
static QuarkZone zone (QUARK_ZONE_LENGTH);
749
// the object supported quarks
750
static const long QUARK_OR = zone.intern ("or");
751
static const long QUARK_OPP = zone.intern ("++");
752
static const long QUARK_OMM = zone.intern ("--");
753
static const long QUARK_ADD = zone.intern ("+");
754
static const long QUARK_SUB = zone.intern ("-");
755
static const long QUARK_MUL = zone.intern ("*");
756
static const long QUARK_DIV = zone.intern ("/");
757
static const long QUARK_EQL = zone.intern ("==");
758
static const long QUARK_NEQ = zone.intern ("!=");
759
static const long QUARK_LTH = zone.intern ("<");
760
static const long QUARK_LEQ = zone.intern ("<=");
761
static const long QUARK_GTH = zone.intern (">");
762
static const long QUARK_GEQ = zone.intern (">=");
763
static const long QUARK_AEQ = zone.intern ("+=");
764
static const long QUARK_SEQ = zone.intern ("-=");
765
static const long QUARK_MEQ = zone.intern ("*=");
766
static const long QUARK_DEQ = zone.intern ("/=");
767
static const long QUARK_ABS = zone.intern ("abs");
768
static const long QUARK_AND = zone.intern ("and");
769
static const long QUARK_SHL = zone.intern ("shl");
770
static const long QUARK_SHR = zone.intern ("shr");
771
static const long QUARK_XOR = zone.intern ("xor");
772
static const long QUARK_MOD = zone.intern ("mod");
773
static const long QUARK_NOT = zone.intern ("not");
774
static const long QUARK_ODDP = zone.intern ("odd-p");
775
static const long QUARK_EVENP = zone.intern ("even-p");
776
static const long QUARK_ZEROP = zone.intern ("zero-p");
778
// evaluate an object to a native value
780
t_long Integer::evalto (Runnable* robj, Nameset* nset, Object* object) {
781
Object* obj = (object == nilp) ? nilp : object->eval (robj, nset);
782
Integer* val = dynamic_cast <Integer*> (obj);
783
if (val == nilp) throw Exception ("type-error", "nil object to evaluate");
784
return val->tolong ();
787
// create a new object in a generic way
789
Object* Integer::mknew (Vector* argv) {
790
if ((argv == nilp) || (argv->length () == 0)) return new Integer;
791
if (argv->length () != 1)
792
throw Exception ("argument-error",
793
"too many argument with integer constructor");
794
// try to map the integer argument
795
Object* obj = argv->get (0);
796
if (obj == nilp) return new Integer;
798
// try an integer object
799
Integer* ival = dynamic_cast <Integer*> (obj);
800
if (ival != nilp) return new Integer (*ival);
803
Real* rval = dynamic_cast <Real*> (obj);
804
if (rval != nilp) return new Integer (rval->tolong ());
806
// try a character object
807
Character* cval = dynamic_cast <Character*> (obj);
808
if (cval != nilp) return new Integer (cval->toquad ());
810
// try a string object
811
String* sval = dynamic_cast <String*> (obj);
812
if (sval != nilp) return new Integer (*sval);
815
throw Exception ("type-error", "illegal object with integer constructor",
819
// return true if the given quark is defined
821
bool Integer::isquark (const long quark, const bool hflg) const {
823
if (zone.exists (quark) == true) {
827
bool result = hflg ? Number::isquark (quark, hflg) : false;
832
// operate this object with another object
834
Object* Integer::oper (t_oper type, Object* object) {
835
Integer* iobj = dynamic_cast <Integer*> (object);
836
Real* dobj = dynamic_cast <Real*> (object);
839
if (iobj != nilp) return new Integer (*this + *iobj);
840
if (dobj != nilp) return new Integer (*this + dobj->tolong ());
843
if (iobj != nilp) return new Integer (*this - *iobj);
844
if (dobj != nilp) return new Integer (*this - dobj->tolong ());
847
if (iobj != nilp) return new Integer (*this * *iobj);
848
if (dobj != nilp) return new Integer (*this * dobj->tolong ());
851
if (iobj != nilp) return new Integer (*this / *iobj);
852
if (dobj != nilp) return new Integer (*this / dobj->tolong ());
855
return new Integer (-(*this));
858
if (iobj != nilp) return new Boolean (*this == *iobj);
859
if (dobj != nilp) return new Boolean (*this == dobj->tolong ());
862
if (iobj != nilp) return new Boolean (*this != *iobj);
863
if (dobj != nilp) return new Boolean (*this != dobj->tolong ());
866
if (iobj != nilp) return new Boolean (*this >= *iobj);
867
if (dobj != nilp) return new Boolean (*this >= dobj->tolong ());
870
if (iobj != nilp) return new Boolean (*this > *iobj);
871
if (dobj != nilp) return new Boolean (*this > dobj->tolong ());
874
if (iobj != nilp) return new Boolean (*this <= *iobj);
875
if (dobj != nilp) return new Boolean (*this <= dobj->tolong ());
878
if (iobj != nilp) return new Boolean (*this < *iobj);
879
if (dobj != nilp) return new Boolean (*this < dobj->tolong ());
882
throw Exception ("type-error", "invalid operand with integer",
883
Object::repr (object));
886
// set an object to this integer
888
Object* Integer::vdef (Runnable* robj, Nameset* nset, Object* object) {
891
Integer* iobj = dynamic_cast <Integer*> (object);
898
Real* dobj = dynamic_cast <Real*> (object);
900
*this = dobj->tolong ();
905
Character* cobj = dynamic_cast <Character*> (object);
907
*this = (t_long) cobj->toquad ();
912
throw Exception ("type-error", "invalid object with integer vdef",
913
Object::repr (object));
920
// apply this object with a set of arguments and a quark
922
Object* Integer::apply (Runnable* robj, Nameset* nset, const long quark,
924
// get the number of arguments
925
long argc = (argv == nilp) ? 0 : argv->length ();
927
// dispatch 0 argument
929
if (quark == QUARK_ABS) return new Integer (abs ());
930
if (quark == QUARK_EVENP) return new Boolean (iseven ());
931
if (quark == QUARK_ODDP) return new Boolean (isodd ());
932
if (quark == QUARK_ZEROP) return new Boolean (iszero ());
934
if (quark == QUARK_NOT) return new Integer (~(*this));
935
if (quark == QUARK_OPP) {
947
if (quark == QUARK_OMM) {
960
// dispatch 1 argument
962
if (quark == QUARK_ADD) return oper (Object::ADD, argv->get (0));
963
if (quark == QUARK_SUB) return oper (Object::SUB, argv->get (0));
964
if (quark == QUARK_MUL) return oper (Object::MUL, argv->get (0));
965
if (quark == QUARK_DIV) return oper (Object::DIV, argv->get (0));
966
if (quark == QUARK_EQL) return oper (Object::EQL, argv->get (0));
967
if (quark == QUARK_NEQ) return oper (Object::NEQ, argv->get (0));
968
if (quark == QUARK_LTH) return oper (Object::LTH, argv->get (0));
969
if (quark == QUARK_LEQ) return oper (Object::LEQ, argv->get (0));
970
if (quark == QUARK_GTH) return oper (Object::GTH, argv->get (0));
971
if (quark == QUARK_GEQ) return oper (Object::GEQ, argv->get (0));
973
if (quark == QUARK_AEQ) {
976
t_long val = argv->getlong (0);
986
if (quark == QUARK_SEQ) {
989
t_long val = argv->getlong (0);
999
if (quark == QUARK_MEQ) {
1002
t_long val = argv->getlong (0);
1012
if (quark == QUARK_DEQ) {
1015
t_long val = argv->getlong (0);
1025
if (quark == QUARK_MOD) {
1026
t_long val = argv->getlong (0);
1027
return new Integer (*this % val);
1029
if (quark == QUARK_SHL) {
1030
t_long asl = argv->getlong (0);
1031
Object* result = new Integer (*this << asl);
1034
if (quark == QUARK_SHR) {
1035
t_long asr = argv->getlong (0);
1036
Object* result = new Integer (*this >> asr);
1039
if (quark == QUARK_XOR) {
1040
t_long val = argv->getlong (0);
1041
Object* result = new Integer (*this ^ val);
1044
if (quark == QUARK_AND) {
1045
t_long val = argv->getlong (0);
1046
Object* result = new Integer (*this & val);
1049
if (quark == QUARK_OR) {
1050
t_long val = argv->getlong (0);
1051
Object* result = new Integer (*this | val);
1055
// call the number method
1056
return Number::apply (robj, nset, quark, argv);