Added the MPExpressionTree Classes
This commit is contained in:
151
MathPad/MPFunctionValue.m
Normal file
151
MathPad/MPFunctionValue.m
Normal file
@@ -0,0 +1,151 @@
|
||||
//
|
||||
// MPFunctionValue.m
|
||||
// MathPad
|
||||
//
|
||||
// Created by Kim Wittenburg on 11.10.14.
|
||||
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPFunctionValue.h"
|
||||
#import "MPMathRules.h"
|
||||
|
||||
double defaultFunction(double value) {return value;};
|
||||
|
||||
@implementation MPFunctionValue {
|
||||
NSDecimalNumber *(^_function)(NSDecimalNumber *);
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithTokenStream:(MPTokenStream *)tokenStream
|
||||
{
|
||||
switch (tokenStream.currentToken.tokenType) {
|
||||
case MPSinToken:
|
||||
[tokenStream currentTokenConsumed];
|
||||
self.functionName = @"sin";
|
||||
return [self initWithTokenStream:tokenStream
|
||||
function:&sin
|
||||
takesArcValue:YES
|
||||
returnsArcValue:NO];
|
||||
|
||||
case MPCosToken:
|
||||
[tokenStream currentTokenConsumed];
|
||||
self.functionName = @"cos";
|
||||
return [self initWithTokenStream:tokenStream
|
||||
function:&cos
|
||||
takesArcValue:YES
|
||||
returnsArcValue:NO];
|
||||
|
||||
case MPTanToken:
|
||||
[tokenStream currentTokenConsumed];
|
||||
self.functionName = @"tan";
|
||||
return [self initWithTokenStream:tokenStream
|
||||
function:&tan
|
||||
takesArcValue:YES
|
||||
returnsArcValue:NO];
|
||||
|
||||
case MPASinToken:
|
||||
[tokenStream currentTokenConsumed];
|
||||
self.functionName = @"asin";
|
||||
return [self initWithTokenStream:tokenStream
|
||||
function:&asin
|
||||
takesArcValue:YES
|
||||
returnsArcValue:NO];
|
||||
|
||||
case MPACosToken:
|
||||
[tokenStream currentTokenConsumed];
|
||||
self.functionName = @"acos";
|
||||
return [self initWithTokenStream:tokenStream
|
||||
function:&acos
|
||||
takesArcValue:YES
|
||||
returnsArcValue:NO];
|
||||
|
||||
case MPATanToken:
|
||||
[tokenStream currentTokenConsumed];
|
||||
self.functionName = @"atan";
|
||||
return [self initWithTokenStream:tokenStream
|
||||
function:&atan
|
||||
takesArcValue:YES
|
||||
returnsArcValue:NO];
|
||||
|
||||
default:
|
||||
@throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"Expected Function" userInfo:nil];
|
||||
break;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithTokenStream:(MPTokenStream *)tokenStream
|
||||
function:(double (*)(double))function
|
||||
takesArcValue:(BOOL)takesArc
|
||||
returnsArcValue:(BOOL)returnsArc
|
||||
{
|
||||
self = [self init];
|
||||
if (self) {
|
||||
_valueGroup = [[MPValueGroup alloc] initWithTokenStream:tokenStream];
|
||||
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;
|
||||
};
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (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;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSRange)range
|
||||
{
|
||||
return NSMakeRange(0, 0);
|
||||
}
|
||||
|
||||
- (BOOL)validate:(MPParseError *__autoreleasing *)error
|
||||
{
|
||||
return [self.valueGroup validate:error];
|
||||
}
|
||||
|
||||
- (NSDecimalNumber *)evaluate
|
||||
{
|
||||
return _function([self.valueGroup evaluate]);
|
||||
}
|
||||
|
||||
- (NSArray *)expressionElements
|
||||
{
|
||||
NSMutableArray *elements = [[NSMutableArray alloc] init];
|
||||
[elements addObject:self.functionName];
|
||||
[elements addObjectsFromArray:self.valueGroup.expressionElements];
|
||||
return elements;
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user