152 lines
4.7 KiB
Objective-C
152 lines
4.7 KiB
Objective-C
//
|
|
// 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
|