Fundamental Redesign of Evaluation
This commit is contained in:
109
MathPad/MPElementaryFunctionTerm.m
Normal file
109
MathPad/MPElementaryFunctionTerm.m
Normal file
@@ -0,0 +1,109 @@
|
||||
//
|
||||
// MPFunctionValue.m
|
||||
// MathPad
|
||||
//
|
||||
// Created by Kim Wittenburg on 11.10.14.
|
||||
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPElementaryFunctionTerm.h"
|
||||
|
||||
#import "MPParsedExpression.h"
|
||||
#import "MPPowerFunction.h"
|
||||
#import "MPProductTerm.h"
|
||||
#import "MPTokenStream.h"
|
||||
#import "MPToken.h"
|
||||
|
||||
#import "MPExpression.h"
|
||||
#import "MPMathRules.h"
|
||||
|
||||
@implementation MPElementaryFunctionTerm {
|
||||
NSDecimalNumber *(^_function)(NSDecimalNumber *);
|
||||
}
|
||||
|
||||
- (instancetype)initWithFunctionIdentifier:(NSString *)function
|
||||
term:(MPTerm *)term
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
NSAssert(function != nil, @"function must not be nil.");
|
||||
NSAssert(term != nil, @"term must not be nil.");
|
||||
double (*func)(double);
|
||||
BOOL takesArc = NO;
|
||||
BOOL returnsArc = NO;
|
||||
if ([function isEqualToString:@"sin"]) {
|
||||
func = &sin;
|
||||
takesArc = YES;
|
||||
} else if ([function isEqualToString:@"cos"]) {
|
||||
func = &cos;
|
||||
takesArc = YES;
|
||||
} else if ([function isEqualToString:@"tan"]) {
|
||||
func = &tan;
|
||||
takesArc = YES;
|
||||
} else if ([function isEqualToString:@"asin"]) {
|
||||
func = &asin;
|
||||
returnsArc = YES;
|
||||
} else if ([function isEqualToString:@"acos"]) {
|
||||
func = &acos;
|
||||
returnsArc = YES;
|
||||
} else if ([function isEqualToString:@"atan"]) {
|
||||
func = &atan;
|
||||
returnsArc = YES;
|
||||
} else {
|
||||
NSAssert(true, @"function must be one of (sin, cos, tan, asin, acos, atan).");
|
||||
}
|
||||
[self setFunction:func
|
||||
takesArcValue:takesArc
|
||||
returnsArcValue:returnsArc];
|
||||
_term = term;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setFunction:(double (*)(double))function
|
||||
takesArcValue:(BOOL)takesArc
|
||||
returnsArcValue:(BOOL)returnsArc
|
||||
{
|
||||
id __weak weakSelf = self;
|
||||
_function = ^(NSDecimalNumber *value){
|
||||
if (takesArc) {
|
||||
value = [weakSelf convertToRadiantsIfNecessary:value];
|
||||
}
|
||||
NSDecimalNumber *returnValue = [[NSDecimalNumber alloc] initWithDouble:function(value.doubleValue)];
|
||||
if (returnsArc) {
|
||||
returnValue = [weakSelf convertToDegreesIfNecessary:returnValue];
|
||||
}
|
||||
return returnValue;
|
||||
};
|
||||
}
|
||||
|
||||
- (NSDecimalNumber *)convertToRadiantsIfNecessary:(NSDecimalNumber *)degrees
|
||||
{
|
||||
if ([MPMathRules sharedRules].isUsingDegrees) {
|
||||
// * M_PI / 180
|
||||
return [[degrees decimalNumberByMultiplyingBy:[[NSDecimalNumber alloc] initWithDouble:M_PI]] decimalNumberByDividingBy:[[NSDecimalNumber alloc] initWithInteger:180]];
|
||||
} else {
|
||||
return degrees;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSDecimalNumber *)convertToDegreesIfNecessary:(NSDecimalNumber *)radiants
|
||||
{
|
||||
if ([MPMathRules sharedRules].isUsingDegrees) {
|
||||
// * 180 / M_PI
|
||||
return [[radiants decimalNumberByMultiplyingBy:[[NSDecimalNumber alloc] initWithInteger:180]] decimalNumberByDividingBy:[[NSDecimalNumber alloc] initWithDouble:M_PI]];
|
||||
} else {
|
||||
return radiants;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSDecimalNumber *)doEvaluation:(NSError *__autoreleasing *)error
|
||||
{
|
||||
NSDecimalNumber *value = [self.term evaluate:error];
|
||||
if (!value) {
|
||||
return nil;
|
||||
}
|
||||
return _function(value);
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user