// // MPTerm.m // MathPad // // Created by Kim Wittenburg on 27.09.14. // Copyright (c) 2014 Kim Wittenburg. All rights reserved. // #import "MPTerm.h" #import "MPEvaluationContext.h" #import "MPMathRules.h" @interface MPTerm () @property (nonatomic, copy) NSDecimalNumber *(^block)(); @end @implementation MPTerm - (instancetype)initWithBlock:(NSDecimalNumber *(^)())block { self = [super init]; if (self) { self.block = block; } return self; } - (instancetype)initWithNumber:(NSDecimalNumber *)number { return [self initWithBlock:^NSDecimalNumber *{ return number; }]; } - (instancetype)initWithSummands:(NSArray *)summands { return [self initWithBlock:^NSDecimalNumber *{ NSDecimalNumber *value = [NSDecimalNumber zero]; for (MPTerm *term in summands) { value = [value decimalNumberByAdding:[term evaluate]]; } return value; }]; } - (instancetype)initWithFactors:(NSArray *)factors { return [self initWithBlock:^NSDecimalNumber *{ NSDecimalNumber *value = [NSDecimalNumber one]; for (MPTerm *term in factors) { value = [value decimalNumberByMultiplyingBy:[term evaluate]]; } return value; }]; } - (instancetype)initWithVariable:(NSString *)variable { return [self initWithBlock:^NSDecimalNumber *{ return [[MPEvaluationContext sharedContext] valueForVariable:variable]; }]; } - (instancetype)initWithFactorialOfTerm:(MPTerm *)term { return [self initWithBlock:^NSDecimalNumber *{ NSDecimalNumber *termValue = [term evaluate]; return [[NSDecimalNumber alloc] initWithDouble:tgamma(termValue.doubleValue + 1)]; }]; } - (instancetype)initWithSinOfTerm:(MPTerm *)term { return [self initWithBlock:^NSDecimalNumber *{ NSDecimalNumber *termValue = [term evaluate]; if ([MPMathRules sharedRules].isUsingDegrees) { termValue = [[termValue decimalNumberByMultiplyingBy:[[NSDecimalNumber alloc] initWithDouble:M_PI]] decimalNumberByDividingBy:[[NSDecimalNumber alloc] initWithInteger:180]]; } return [[NSDecimalNumber alloc] initWithDouble:sin(termValue.doubleValue)]; }]; } - (instancetype)initWithCosOfTerm:(MPTerm *)term { return [self initWithBlock:^NSDecimalNumber *{ NSDecimalNumber *termValue = [term evaluate]; if ([MPMathRules sharedRules].isUsingDegrees) { termValue = [[termValue decimalNumberByMultiplyingBy:[[NSDecimalNumber alloc] initWithDouble:M_PI]] decimalNumberByDividingBy:[[NSDecimalNumber alloc] initWithInteger:180]]; } return [[NSDecimalNumber alloc] initWithDouble:cos(termValue.doubleValue)]; }]; } - (instancetype)initWithTanOfTerm:(MPTerm *)term { return [self initWithBlock:^NSDecimalNumber *{ NSDecimalNumber *termValue = [term evaluate]; if ([MPMathRules sharedRules].isUsingDegrees) { termValue = [[termValue decimalNumberByMultiplyingBy:[[NSDecimalNumber alloc] initWithDouble:M_PI]] decimalNumberByDividingBy:[[NSDecimalNumber alloc] initWithInteger:180]]; } return [[NSDecimalNumber alloc] initWithDouble:tan(termValue.doubleValue)]; }]; } - (instancetype)initWithInverseSinOfTerm:(MPTerm *)term { return [self initWithBlock:^NSDecimalNumber *{ NSDecimalNumber *termValue = [term evaluate]; NSDecimalNumber *result = [[NSDecimalNumber alloc] initWithDouble:asin(termValue.doubleValue)]; if ([MPMathRules sharedRules].isUsingDegrees) { result = [[result decimalNumberByMultiplyingBy:[[NSDecimalNumber alloc] initWithInteger:180]] decimalNumberByDividingBy:[[NSDecimalNumber alloc] initWithDouble:M_PI]]; } return result; }]; } - (instancetype)initWithInverseCosOfTerm:(MPTerm *)term { return [self initWithBlock:^NSDecimalNumber *{ NSDecimalNumber *termValue = [term evaluate]; NSDecimalNumber *result = [[NSDecimalNumber alloc] initWithDouble:acos(termValue.doubleValue)]; if ([MPMathRules sharedRules].isUsingDegrees) { result = [[result decimalNumberByMultiplyingBy:[[NSDecimalNumber alloc] initWithInteger:180]] decimalNumberByDividingBy:[[NSDecimalNumber alloc] initWithDouble:M_PI]]; } return result; }]; } - (instancetype)initWithInverseTanOfTerm:(MPTerm *)term { return [self initWithBlock:^NSDecimalNumber *{ NSDecimalNumber *termValue = [term evaluate]; NSDecimalNumber *result = [[NSDecimalNumber alloc] initWithDouble:atan(termValue.doubleValue)]; if ([MPMathRules sharedRules].isUsingDegrees) { result = [[result decimalNumberByMultiplyingBy:[[NSDecimalNumber alloc] initWithInteger:180]] decimalNumberByDividingBy:[[NSDecimalNumber alloc] initWithDouble:M_PI]]; } return result; }]; } - (NSDecimalNumber *)evaluate { @try { return self.block(); } @catch (NSException *exception) { return [NSDecimalNumber notANumber]; } } @end