From 9c3236394224167b31eeb402fa78928a0e3eb7fe Mon Sep 17 00:00:00 2001 From: Matthias Andreas Benkard Date: Tue, 29 Jul 2008 19:56:21 +0200 Subject: Add a non-trivial number of arithmetic methods to number classes. --- MLKDoubleFloat.h | 19 ++++++++++++++ MLKDoubleFloat.m | 46 ++++++++++++++++++++++++++++++++ MLKInteger.h | 14 ++++++++++ MLKInteger.m | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ MLKNumber.h | 2 ++ MLKNumber.m | 2 ++ MLKRatio.h | 9 +++++++ MLKRatio.m | 42 +++++++++++++++++++++++++++++ MLKSingleFloat.h | 3 +++ MLKSingleFloat.m | 16 ++++++++++++ 10 files changed, 233 insertions(+) diff --git a/MLKDoubleFloat.h b/MLKDoubleFloat.h index deba097..88254ab 100644 --- a/MLKDoubleFloat.h +++ b/MLKDoubleFloat.h @@ -49,6 +49,25 @@ -(MLKNumber *) multiplyWith:(MLKNumber *)arg; -(MLKNumber *) divideBy:(MLKNumber *)arg; +-(NSComparisonResult) compare:(MLKDoubleFloat *)arg; +-(BOOL) isEqual:(id)arg; + +-(MLKDoubleFloat *) sin; +-(MLKDoubleFloat *) cos; +-(MLKDoubleFloat *) tan; +-(MLKDoubleFloat *) asin; +-(MLKDoubleFloat *) acos; +-(MLKDoubleFloat *) atan; +-(MLKDoubleFloat *) sinh; +-(MLKDoubleFloat *) cosh; +-(MLKDoubleFloat *) tanh; +-(MLKDoubleFloat *) exp; +-(MLKDoubleFloat *) log; +-(MLKDoubleFloat *) sqrt; +-(MLKDoubleFloat *) ceil; +-(MLKDoubleFloat *) floor; +-(MLKDoubleFloat *) pow:(MLKDoubleFloat *)exponent; + -(NSString *) description; -(NSString *) descriptionForLisp; @end diff --git a/MLKDoubleFloat.m b/MLKDoubleFloat.m index 3a598fd..a60bd8c 100644 --- a/MLKDoubleFloat.m +++ b/MLKDoubleFloat.m @@ -24,6 +24,7 @@ #import +#include #include #include #include @@ -114,6 +115,51 @@ return [MLKDoubleFloat doubleFloatWithDouble:(value / [(MLKFloat*)arg doubleValue])]; } +-(NSComparisonResult) compare:(MLKDoubleFloat *)arg +{ + if (self->value == arg->value) + return NSOrderedSame; + else if (self->value < arg->value) + return NSOrderedAscending; + else + return NSOrderedDescending; +} + +-(BOOL) isEqual:(id)arg +{ + return ([arg isKindOfClass:[MLKDoubleFloat class]] + && self->value == ((MLKDoubleFloat *)arg)->value); +} + + +#define DEFINE_NULLARY_OPERATOR(NAME) \ + -(MLKDoubleFloat *) NAME \ + { \ + return [MLKDoubleFloat doubleFloatWithDouble:(NAME (value))]; \ + } + +DEFINE_NULLARY_OPERATOR (sin); +DEFINE_NULLARY_OPERATOR (cos); +DEFINE_NULLARY_OPERATOR (tan); +DEFINE_NULLARY_OPERATOR (asin); +DEFINE_NULLARY_OPERATOR (acos); +DEFINE_NULLARY_OPERATOR (atan); +DEFINE_NULLARY_OPERATOR (sinh); +DEFINE_NULLARY_OPERATOR (cosh); +DEFINE_NULLARY_OPERATOR (tanh); +DEFINE_NULLARY_OPERATOR (exp); +DEFINE_NULLARY_OPERATOR (log); +DEFINE_NULLARY_OPERATOR (sqrt); +DEFINE_NULLARY_OPERATOR (ceil); +DEFINE_NULLARY_OPERATOR (floor); + + +-(MLKDoubleFloat *) pow:(MLKDoubleFloat *)exponent +{ + return [MLKDoubleFloat doubleFloatWithDouble: + (pow (self->value, exponent->value))]; +} + -(NSString *) description { NSString *str = [NSString stringWithFormat:@"%e", value]; diff --git a/MLKInteger.h b/MLKInteger.h index d0decb6..25eea87 100644 --- a/MLKInteger.h +++ b/MLKInteger.h @@ -43,12 +43,26 @@ +(MLKInteger *) integerWithInt:(int)intValue; -(int) intValue; +-(double) doubleValue; -(MLKNumber *) add:(MLKNumber *)arg; -(MLKNumber *) subtract:(MLKNumber *)arg; -(MLKNumber *) multiplyWith:(MLKNumber *)arg; -(MLKNumber *) divideBy:(MLKNumber *)arg; +-(NSComparisonResult) compare:(MLKInteger *)arg; +-(BOOL) isEqual:(id)arg; + +-(BOOL) evenp; +-(BOOL) oddp; + +-(MLKInteger *) mod:(MLKInteger *)arg; +-(MLKInteger *) exactlyDivideBy:(MLKInteger *)arg; +-(MLKInteger *) isqrt; +-(MLKInteger *) pow:(MLKInteger *)exponent; +-(MLKInteger *) gcd:(MLKInteger *)arg; +-(MLKInteger *) lcm:(MLKInteger *)arg; + -(NSString *) description; -(NSString *) descriptionWithBase:(int)base; -(NSString *) descriptionForLisp; diff --git a/MLKInteger.m b/MLKInteger.m index 345235a..c2a3f92 100644 --- a/MLKInteger.m +++ b/MLKInteger.m @@ -83,11 +83,91 @@ DEFINE_MPZ_TWOARG_OPERATION (multiplyWith:, mpz_mul) DEFINE_MPZ_TWOARG_OPERATION (divideBy:, mpz_div) +#define DEFINE_MPZ_TWOARG_INTONLY_OPERATION(SELECTOR, GMPFUN) \ + DEFINE_GMP_OPERATION (SELECTOR (MLKInteger *)arg, \ + mpz, \ + GMPFUN (mpval, self->value, ((MLKInteger*)arg)->value), \ + MLKInteger, \ + MLKInteger, \ + integerWithMPZ:) + +DEFINE_MPZ_TWOARG_INTONLY_OPERATION (mod:, mpz_mod) +DEFINE_MPZ_TWOARG_INTONLY_OPERATION (exactlyDivideBy:, mpz_divexact) +DEFINE_MPZ_TWOARG_INTONLY_OPERATION (gcd:, mpz_gcd) +DEFINE_MPZ_TWOARG_INTONLY_OPERATION (lcm:, mpz_lcm) + + +-(MLKInteger *) pow:(MLKInteger *)exponent +{ + mpz_t mpz; + mpz_t i; + + mpz_init_set_ui (mpz, 1); + mpz_init_set (i, exponent->value); + + while (mpz_sgn (i) > 0) + { + mpz_mul (mpz, mpz, self->value); + mpz_sub_ui (i, i, 1); + } + + MLKInteger *obj = [MLKInteger integerWithMPZ:mpz]; + mpz_clear (mpz); + mpz_clear (i); + + return obj; +} + +-(BOOL) evenp +{ + return mpz_even_p (self->value); +} + +-(BOOL) oddp +{ + return mpz_odd_p (self->value); +} + +-(MLKInteger *) isqrt +{ + mpz_t mpz; + + mpz_init (mpz); + mpz_sqrt (mpz, self->value); + MLKInteger *obj = [MLKInteger integerWithMPZ:mpz]; + mpz_clear (mpz); + + return obj; +} + -(int) intValue { return mpz_get_si (value); } +-(double) doubleValue +{ + return mpz_get_d (value); +} + +-(NSComparisonResult) compare:(MLKInteger *)arg +{ + int cmp = mpz_cmp (self->value, arg->value); + + if (cmp == 0) + return NSOrderedSame; + else if (cmp < 0) + return NSOrderedAscending; + else + return NSOrderedDescending; +} + +-(BOOL) isEqual:(id)arg +{ + return ([arg isKindOfClass:[MLKInteger class]] + && [self compare:arg] == 0); +} + -(NSString *) description { return [self descriptionWithBase:10]; diff --git a/MLKNumber.h b/MLKNumber.h index 94ec819..6006606 100644 --- a/MLKNumber.h +++ b/MLKNumber.h @@ -24,4 +24,6 @@ -(MLKNumber *) subtract:(MLKNumber *)arg; -(MLKNumber *) multiplyWith:(MLKNumber *)arg; -(MLKNumber *) divideBy:(MLKNumber *)arg; + +-(double) doubleValue; @end diff --git a/MLKNumber.m b/MLKNumber.m index c190be6..2dbac4d 100644 --- a/MLKNumber.m +++ b/MLKNumber.m @@ -35,4 +35,6 @@ DECLARE_ABSTRACT (-(MLKNumber *) add:(MLKNumber *)arg, nil) DECLARE_ABSTRACT (-(MLKNumber *) subtract:(MLKNumber *)arg, nil) DECLARE_ABSTRACT (-(MLKNumber *) multiplyWith:(MLKNumber *)arg, nil) DECLARE_ABSTRACT (-(MLKNumber *) divideBy:(MLKNumber *)arg, nil) + +DECLARE_ABSTRACT (-(double) doubleValue, 0.0) @end diff --git a/MLKRatio.h b/MLKRatio.h index 7d4768b..e2bf06e 100644 --- a/MLKRatio.h +++ b/MLKRatio.h @@ -17,6 +17,7 @@ */ #import "MLKNumber.h" +#import "MLKInteger.h" #include #include @@ -42,11 +43,19 @@ negative:(BOOL)negative base:(unsigned int)base; +-(double) doubleValue; + -(MLKNumber *) add:(MLKNumber *)arg; -(MLKNumber *) subtract:(MLKNumber *)arg; -(MLKNumber *) multiplyWith:(MLKNumber *)arg; -(MLKNumber *) divideBy:(MLKNumber *)arg; +-(NSComparisonResult) compare:(MLKRatio *)arg; +-(BOOL) isEqual:(id)arg; + +-(MLKInteger *) numerator; +-(MLKInteger *) denominator; + -(NSString *) description; -(NSString *) descriptionWithBase:(int)base; -(NSString *) descriptionForLisp; diff --git a/MLKRatio.m b/MLKRatio.m index 604b457..4b0b23e 100644 --- a/MLKRatio.m +++ b/MLKRatio.m @@ -89,6 +89,48 @@ DEFINE_MPQ_TWOARG_OPERATION (divideBy:, mpq_div) return mpq_get_d (value); } +-(MLKInteger *) numerator +{ + mpz_t numer; + MLKInteger *obj; + + mpz_init_set (numer, mpq_numref (self->value)); + obj = [MLKInteger integerWithMPZ:numer]; + mpz_clear (numer); + + return obj; +} + +-(MLKInteger *) denominator +{ + mpz_t denom; + MLKInteger *obj; + + mpz_init_set (denom, mpq_denref (self->value)); + obj = [MLKInteger integerWithMPZ:denom]; + mpz_clear (denom); + + return obj; +} + +-(NSComparisonResult) compare:(MLKRatio *)arg +{ + int cmp = mpq_cmp (self->value, arg->value); + + if (cmp == 0) + return NSOrderedSame; + else if (cmp < 0) + return NSOrderedAscending; + else + return NSOrderedDescending; +} + +-(BOOL) isEqual:(id)arg +{ + return ([arg isKindOfClass:[MLKRatio class]] + && mpq_equal (self->value, ((MLKRatio *)arg)->value)); +} + -(NSString *) description { return [self descriptionWithBase:10]; diff --git a/MLKSingleFloat.h b/MLKSingleFloat.h index 2a4fca6..789dd25 100644 --- a/MLKSingleFloat.h +++ b/MLKSingleFloat.h @@ -46,6 +46,9 @@ -(MLKNumber *) multiplyWith:(MLKNumber *)arg; -(MLKNumber *) divideBy:(MLKNumber *)arg; +-(NSComparisonResult) compare:(MLKSingleFloat *)arg; +-(BOOL) isEqual:(id)arg; + -(NSString *) description; -(NSString *) descriptionForLisp; @end diff --git a/MLKSingleFloat.m b/MLKSingleFloat.m index 9c2902f..1d3f957 100644 --- a/MLKSingleFloat.m +++ b/MLKSingleFloat.m @@ -126,6 +126,22 @@ return [MLKSingleFloat singleFloatWithFloat:(value / [(MLKFloat*)arg floatValue])]; } +-(NSComparisonResult) compare:(MLKSingleFloat *)arg +{ + if (self->value == arg->value) + return NSOrderedSame; + else if (self->value < arg->value) + return NSOrderedAscending; + else + return NSOrderedDescending; +} + +-(BOOL) isEqual:(id)arg +{ + return ([arg isKindOfClass:[MLKSingleFloat class]] + && self->value == ((MLKSingleFloat *)arg)->value); +} + -(NSString *) description { NSString *str = [NSString stringWithFormat:@"%e", value]; -- cgit v1.2.3