diff --git a/MathKit/MPFunctionLayout.m b/MathKit/MPFunctionLayout.m old mode 100644 new mode 100755 index 926fd99..c398a7d --- a/MathKit/MPFunctionLayout.m +++ b/MathKit/MPFunctionLayout.m @@ -12,14 +12,18 @@ #import "MPFunction.h" #import "MPFractionFunction.h" +#import "MPRootFunction.h" #import "MPParenthesisFunction.h" #import "MPPowerFunction.h" #import "MPSumFunction.h" +#import "MPProductFunction.h" #import "MPFractionFunctionLayout.h" +#import "MPRootFunctionLayout.h" #import "MPParenthesisFunctionLayout.h" #import "MPPowerFunctionLayout.h" #import "MPSumFunctionLayout.h" +#import "MPProductFunctionLayout.h" #import "NSIndexPath+MPAdditions.h" @@ -42,6 +46,10 @@ return [[MPPowerFunctionLayout alloc] initWithFunction:function parent:parent]; } else if (class == [MPFractionFunction class]) { return [[MPFractionFunctionLayout alloc] initWithFunction:function parent:parent]; + } else if (class == [MPProductFunction class]) { + return [[MPProductFunctionLayout alloc] initWithFunction:function parent:parent]; + } else if (class == [MPRootFunction class]) { + return [[MPRootFunctionLayout alloc] initWithFunction:function parent:parent]; } return [[self alloc] initWithFunction:function parent:parent]; diff --git a/MathKit/MPFunctionsViewController.m b/MathKit/MPFunctionsViewController.m old mode 100644 new mode 100755 index 71008e0..ff58252 --- a/MathKit/MPFunctionsViewController.m +++ b/MathKit/MPFunctionsViewController.m @@ -10,9 +10,11 @@ #import "MPFunction.h" #import "MPFractionFunction.h" +#import "MPRootFunction.h" #import "MPParenthesisFunction.h" #import "MPPowerFunction.h" #import "MPSumFunction.h" +#import "MPProductFunction.h" #import "MPFunctionLayout.h" @@ -224,16 +226,20 @@ static void *MPFunctionTemplateViewMouseOverContext = @"MPFunctionTemplateViewMo - (void)awakeFromNib { MPFunction *sumFunction = [[MPSumFunction alloc] init]; + MPFunction *productFunction = [[MPProductFunction alloc] init]; MPFunction *parenthesisFunction = [[MPParenthesisFunction alloc] init]; MPFunction *powerFunction = [[MPPowerFunction alloc] init]; MPPowerFunction *squareFunction = [[MPPowerFunction alloc] init]; squareFunction.exponentExpression = [[MPExpression alloc] initWithElement:@"2"]; MPPowerFunction *cubicFunction = [[MPPowerFunction alloc] init]; cubicFunction.exponentExpression = [[MPExpression alloc] initWithElement:@"3"]; + MPFunction *rootFunction = [[MPRootFunction alloc] init]; MPFractionFunction *fractionFunction = [[MPFractionFunction alloc] init]; self.functionPrototypes = @[ @{@"function": sumFunction, @"name": NSLocalizedString(@"Sum", @"Sum Function Name")}, + @{@"function": productFunction, + @"name": NSLocalizedString(@"Product", @"Product Function Name")}, @{@"function": parenthesisFunction, @"name": NSLocalizedString(@"Parenthesis", @"Parenthesis Function Name")}, @{@"function": squareFunction, @@ -242,6 +248,8 @@ static void *MPFunctionTemplateViewMouseOverContext = @"MPFunctionTemplateViewMo @"name": NSLocalizedString(@"Cubic", @"Cubic Function Name")}, @{@"function": powerFunction, @"name": NSLocalizedString(@"Power", @"Power Function Name")}, + @{@"function": rootFunction, + @"name": NSLocalizedString(@"Root", "Root Function Name")}, @{@"function": fractionFunction, @"name": NSLocalizedString(@"Fraction", @"Fraction Function Name")} ]; diff --git a/MathKit/MPProductFunction.h b/MathKit/MPProductFunction.h new file mode 100755 index 0000000..e5ccc5b --- /dev/null +++ b/MathKit/MPProductFunction.h @@ -0,0 +1,70 @@ +// +// MPProductFunction.h +// MathPad +// +// Created by Kim Wittenburg on 10.01.15. +// Copyright (c) 2015 Kim Wittenburg. All rights reserved. +// + +#import "MPFunction.h" + + +/*! + @header + This file contains the MPProductFunction class. + */ + + + +@class MPProductFunction, MPExpression; + + +/*! + @class MPProductFunction + @abstract This class represents a product function (generally noted using a + capital pi). + + @discussion A product function has a start and a target expression indicating + how often the product expression should be evaluated. Both the + value of the start expression and the target expressions are + included in the iterations. + + Each iteration the iteration value is incremented by + 1. If the start and target expression evaluate to + the same value the product is evaluated once. + */ +@interface MPProductFunction : MPFunction + +/*! + @property startExpression + @abstract The value of the first iteration. + + @discussion The start expression must define a variable that may be used in + the sum expression. If the start expression does not define a + variable the product function will not be evaluatable. + */ +@property (nonatomic, strong) MPExpression *startExpression; /* Index 0 */ + + +/*! + @property targetExpression + @abstract The value if the last iteration. + + @discussion The target expression must not define a variable. + */ +@property (nonatomic, strong) MPExpression *targetExpression; /* Index 1 */ + + +/*! + @property productExpression + @abstract The product expression evaluated multiple times. + + @discussion During evaluation of the product expression the variable defined + in the start expression is available. That variable always + contains the value of the current iteration. + + The product expression itself must not define a variable. + */ +@property (nonatomic, strong) MPExpression *productExpression; /* Index 2 */ + +@end diff --git a/MathKit/MPProductFunction.m b/MathKit/MPProductFunction.m new file mode 100755 index 0000000..07a336b --- /dev/null +++ b/MathKit/MPProductFunction.m @@ -0,0 +1,46 @@ +// +// MPProductFunction.m +// MathPad +// +// Created by Kim Wittenburg on 10.01.15. +// Copyright (c) 2015 Kim Wittenburg. All rights reserved. +// + +#import "MPProductFunction.h" + +#import "MPProductFunctionTerm.h" +#import "MPExpression.h" + + + +@implementation MPProductFunction + +MPFunctionAccessorImplementation(StartExpression, _startExpression) +MPFunctionAccessorImplementation(TargetExpression, _targetExpression) +MPFunctionAccessorImplementation(ProductExpression, _productExpression) + + +- (NSArray *)childrenAccessors +{ + return @[@"startExpression", @"targetExpression", @"productExpression"]; +} + + +- (BOOL)expectsVariableDefinitionInChildAtIndex:(NSUInteger)index +{ + return index == 0; +} + + +- (Class)functionTermClass +{ + return [MPProductFunctionTerm class]; +} + + +- (NSString *)description +{ + return [NSString stringWithFormat:@"Product(From: %@; To: %@; Using: %@)", self.startExpression, self.targetExpression, self.productExpression]; +} + +@end diff --git a/MathKit/MPProductFunctionLayout.h b/MathKit/MPProductFunctionLayout.h new file mode 100755 index 0000000..a079b84 --- /dev/null +++ b/MathKit/MPProductFunctionLayout.h @@ -0,0 +1,35 @@ +// +// MPProductFunctionLayout.h +// MathPad +// +// Created by Kim Wittenburg on 10.01.15. +// Copyright (c) 2015 Kim Wittenburg. All rights reserved. +// + +#import "MPFunctionLayout.h" + + + +@class MPProductFunctionLayout, MPProductFunction; + + +/*! + @class MPProductFunctionLayout + @abstract A product function layout displays a @link + //apple_ref/occ/cl/MPProductFunction@/link. + + @discussion A product is drawn using a capital greeg pi (∏) The three + children are placed around it: The start expression below, target + expression above and product expression to the right of it. + */ +@interface MPProductFunctionLayout : MPFunctionLayout + +/*! + @method productFunction + @abstract Returns the @link + //apple_ref/occ/cl/MPProductFunction@/link represented by + the receiver. + */ +- (MPProductFunction *)productFunction; + +@end diff --git a/MathKit/MPProductFunctionLayout.m b/MathKit/MPProductFunctionLayout.m new file mode 100755 index 0000000..4a4f77c --- /dev/null +++ b/MathKit/MPProductFunctionLayout.m @@ -0,0 +1,175 @@ +// +// MPProductFunctionLayout.m +// MathPad +// +// Created by Kim Wittenburg on 10.01.15. +// Copyright (c) 2015 Kim Wittenburg. All rights reserved. +// + +#import "MPProductFunctionLayout.h" + +#import "MPProductFunction.h" +#import "NSIndexPath+MPAdditions.h" + + +#define kProductFunctionStartExpressionOffset 0 +#define kProductFunctionTargetExpressionOffset 0 +#define kProductFunctionProductExpressionOffset 3 +#define kProductFunctionTrailingOffset 5 + + + +@implementation MPProductFunctionLayout + +- (MPProductFunction *)productFunction +{ + return (MPProductFunction *)self.function; +} + + +- (NSUInteger)indexOfLeadingChild +{ + return 2; +} + + +- (NSUInteger)indexOfTrailingChild +{ + return 2; +} + + +- (NSUInteger)indexOfChildAfterChildAtIndex:(NSUInteger)index +{ + if (index != 2) { + return 2; + } + return [super indexOfChildAfterChildAtIndex:index]; +} + + +- (NSUInteger)indexOfChildBelowChildAtIndex:(NSUInteger)index +{ + return 0; +} + + +- (NSUInteger)indexOfChildAboveChildAtIndex:(NSUInteger)index +{ + return 1; +} + + +- (NSIndexSet *)indexesOfRemainingChildren +{ + return [NSIndexSet indexSetWithIndex:2]; +} + + +- (CTLineRef)line +{ + CTLineRef line = [self lineForPrivateCacheIndex:0 generator:^CTLineRef{ + return [self createLineForString:@"∏" + usingFont:[NSFont fontWithName:@"Times New Roman" + size:self.contextInferredFontSize]]; + }]; + return line; +} + + +- (NSRect)localLineBounds +{ + NSRect lineBounds = CTLineGetBoundsWithOptions(self.line, 0); + NSRect startExpressionBounds = [self childLayoutAtIndex:0].bounds; + NSRect targetExpressionBounds = [self childLayoutAtIndex:1].bounds; + CGFloat width = MAX(MAX(startExpressionBounds.size.width, targetExpressionBounds.size.width), lineBounds.size.width); + CGFloat xPosition = (width - lineBounds.size.width) / 2; + return NSMakeRect(xPosition, lineBounds.origin.y, lineBounds.size.width, lineBounds.size.height); +} + + +- (NSPoint)offsetOfChildLayoutAtIndex:(NSUInteger)index +{ + NSRect childBounds = [self childLayoutAtIndex:index].bounds; + NSRect localLineBounds = [self localLineBounds]; + NSPoint offset; + if (index == 0) { + // Start Expression + offset.x = localLineBounds.origin.x + localLineBounds.size.width / 2 - childBounds.size.width / 2; + offset.y = localLineBounds.origin.y - kProductFunctionStartExpressionOffset - childBounds.size.height - childBounds.origin.y; + } else if (index == 1) { + // Target Expression + offset.x = localLineBounds.origin.x + localLineBounds.size.width / 2 - childBounds.size.width / 2; + offset.y = kProductFunctionTargetExpressionOffset + localLineBounds.size.height + localLineBounds.origin.y - childBounds.origin.y; + } else { + // Sum Expression + MPLayout *startExpressionLayout = [self childLayoutAtIndex:0]; + MPLayout *targetExpressionLayout = [self childLayoutAtIndex:1]; + CGFloat sumWidth = MAX(MAX(localLineBounds.origin.x + localLineBounds.size.width, startExpressionLayout.bounds.size.width), targetExpressionLayout.bounds.size.width); + offset.x = sumWidth + kProductFunctionProductExpressionOffset; + offset.y = 0; + } + return offset; +} + + +- (BOOL)childAtIndexUsesSmallSize:(NSUInteger)index +{ + return (index == 0 || index == 1) ? YES : self.usesSmallSize; +} + + +- (NSIndexPath *)indexPathForLocalMousePoint:(NSPoint)point +{ + if (point.x < CTLineGetBoundsWithOptions(self.line, 0).size.width / 2) { + return [NSIndexPath indexPathWithIndex:0]; + } else { + return [NSIndexPath indexPathWithIndex:1]; + } +} + + +- (NSRect)generateBounds +{ + NSRect lineBounds = CTLineGetBoundsWithOptions(self.line, 0); + NSRect startExpressionBounds = [self childLayoutAtIndex:0].bounds; + NSRect targetExpressionBounds = [self childLayoutAtIndex:1].bounds; + NSRect sumExpressionBounds = [self childLayoutAtIndex:2].bounds; + NSRect bounds = lineBounds; + + bounds.size.width = MAX(lineBounds.size.width, startExpressionBounds.size.width); + bounds.size.height += startExpressionBounds.size.height + kProductFunctionStartExpressionOffset; + bounds.origin.y -= startExpressionBounds.size.height + kProductFunctionStartExpressionOffset; + + bounds.size.width = MAX(bounds.size.width, targetExpressionBounds.size.width); + bounds.size.height += targetExpressionBounds.size.height + kProductFunctionTargetExpressionOffset; + + bounds.size.width += kProductFunctionProductExpressionOffset + sumExpressionBounds.size.width + kProductFunctionTrailingOffset; + CGFloat yOffsetBottom = bounds.origin.y - sumExpressionBounds.origin.y; + CGFloat yOffsetTop = sumExpressionBounds.size.height - (yOffsetBottom + bounds.size.height); + bounds.size.height = MAX(yOffsetBottom, 0) + bounds.size.height + MAX(yOffsetTop, 0); + bounds.origin.y = MIN(sumExpressionBounds.origin.y, bounds.origin.y); + + return bounds; +} + + +- (void)draw +{ + // Get the current context + CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; + + // Set the text matrix + CGContextSetTextMatrix(context, CGAffineTransformIdentity); + + // Draw the sum symbol + CTLineRef line = [self line]; + CFRetain(line); + NSRect localLineBounds = [self localLineBounds]; + CGContextSetTextPosition(context, localLineBounds.origin.x, 0); + CTLineDraw(line, context); + + CFRelease(line); +} + +@end diff --git a/MathKit/MPProductFunctionTerm.h b/MathKit/MPProductFunctionTerm.h new file mode 100755 index 0000000..8b01daf --- /dev/null +++ b/MathKit/MPProductFunctionTerm.h @@ -0,0 +1,37 @@ +// +// MPProductFunctionTerm.h +// MathPad +// +// Created by Kim Wittenburg on 10.01.15. +// Copyright (c) 2015 Kim Wittenburg. All rights reserved. +// + +#import "MPFunctionTerm.h" + +/*! + @header + This file contains the MPProductFunctionTerm class. + */ + + + +@class MPProductFunctionTerm; + + +/*! + @class MPProductFunctionTerm + @abstract Represents and evaluates a @link + //apple_ref/occ/cl/MPProductFunction@/link. + + @discussion A product function evaluates its sum term n times. + How often it actually is evaluated depends on the boundary + expressions (start and target). Both are inclusive. + + A product function also features a variable that contains the + current value of the iteration. The variable is defined in the + start expression and incremented by 1 after every + iteration. + */ +@interface MPProductFunctionTerm : MPFunctionTerm + +@end diff --git a/MathKit/MPProductFunctionTerm.m b/MathKit/MPProductFunctionTerm.m new file mode 100755 index 0000000..10ba763 --- /dev/null +++ b/MathKit/MPProductFunctionTerm.m @@ -0,0 +1,40 @@ +// +// MPProductFunctionTerm.m +// MathPad +// +// Created by Kim Wittenburg on 10.01.15. +// Copyright (c) 2015 Kim Wittenburg. All rights reserved. +// + +#import "MPProductFunctionTerm.h" + +#import "MPParsedExpression.h" + + + +@implementation MPProductFunctionTerm + +- (NSDecimalNumber *)doEvaluation:(NSError *__autoreleasing *)error +{ + MPParsedExpression *startExpression = [self expressionAtIndex:0]; + NSDecimalNumber *start = [startExpression evaluate:error]; + ReturnNilIfNil(start); + + MPEvaluateExpression(target, 1); + + MPParsedExpression *sumExpression = [self expressionAtIndex:2]; + NSDecimalNumber *value = [NSDecimalNumber one]; + for (NSDecimalNumber *current = start; + [current compare:target] <= 0; + current = [current decimalNumberByAdding:[[NSDecimalNumber alloc] initWithInteger:1]]) { + if (![self defineVariable:startExpression.definedVariable value:current error:error]) { + return nil; + } + NSDecimalNumber *currentValue = [sumExpression evaluate:error]; + ReturnNilIfNil(currentValue); + value = [value decimalNumberByMultiplyingBy:currentValue]; + } + return value; +} + +@end diff --git a/MathKit/MPRootFunction.h b/MathKit/MPRootFunction.h new file mode 100755 index 0000000..1c8a66b --- /dev/null +++ b/MathKit/MPRootFunction.h @@ -0,0 +1,46 @@ +// +// MPRootFunction.h +// MathPad +// +// Created by Kim Wittenburg on 11.01.15. +// Copyright (c) 2015 Kim Wittenburg. All rights reserved. +// + +#import "MPFunction.h" + + +/*! + @header + This file contains the MPRootFunction class. + */ + + + +@class MPRootFunction, MPExpression; + + +/*! + @class MPRootFunction + @abstract This class represents an arbitrary root function. + + @discussion A root has two children: An exponent and the expression to be + rooted. + */ +@interface MPRootFunction : MPFunction + +/*! + @property exponentExpression + @abstract The receiver's exponent. + */ +@property (nonatomic, strong) MPExpression *exponentExpression; /* Index 0 */ + + +/*! + @property rootExpression + @abstract The receiver's root expression. + + @discussion The root expression is the expression that is to be rooted. + */ +@property (nonatomic, strong) MPExpression *rootExpression; /* Index 1 */ + +@end diff --git a/MathKit/MPRootFunction.m b/MathKit/MPRootFunction.m new file mode 100755 index 0000000..fe2c6c5 --- /dev/null +++ b/MathKit/MPRootFunction.m @@ -0,0 +1,39 @@ +// +// MPRootFunction.m +// MathPad +// +// Created by Kim Wittenburg on 11.01.15. +// Copyright (c) 2015 Kim Wittenburg. All rights reserved. +// + +#import "MPRootFunction.h" + +#import "MPRootTerm.h" +#import "MPExpression.h" + + + +@implementation MPRootFunction + +MPFunctionAccessorImplementation(ExponentExpression, _exponentExpression) +MPFunctionAccessorImplementation(RootExpression, _rootExpression) + + +- (NSArray *)childrenAccessors +{ + return @[@"exponentExpression", @"rootExpression"]; +} + + +- (Class)functionTermClass +{ + return [MPRootTerm class]; +} + + +- (NSString *)description +{ + return [NSString stringWithFormat:@"Root(%@, %@)", self.exponentExpression, self.rootExpression]; +} + +@end diff --git a/MathKit/MPRootFunctionLayout.h b/MathKit/MPRootFunctionLayout.h new file mode 100755 index 0000000..2c0552d --- /dev/null +++ b/MathKit/MPRootFunctionLayout.h @@ -0,0 +1,42 @@ +// +// MPRootFunctionLayout.h +// MathPad +// +// Created by Kim Wittenburg on 11.01.15. +// Copyright (c) 2015 Kim Wittenburg. All rights reserved. +// + +#import "MPFunctionLayout.h" + + +/*! + @header + This file contains the MPRootFunctionLayout class. + */ + + + +@class MPRootFunctionLayout, MPRootFunction; + + +/*! + @class MPRootFunctionLayout + @abstract A root function layout displays a @link + //apple_ref/occ/cl/MPRootFunction@/link. + + @discussion A root function is displayed in a very special way. In a way it + can be described as an exponent at the left, a "V" in the middle + and the expression that is to be rooted at the right with a bar + over it. + */ +@interface MPRootFunctionLayout : MPFunctionLayout + +/*! + @method rootFunction + @abstract Returns the @link + //apple_ref/occ/cl/MPRootFunction@/link represented by the + receiver. + */ +- (MPRootFunction *)rootFunction; + +@end diff --git a/MathKit/MPRootFunctionLayout.m b/MathKit/MPRootFunctionLayout.m new file mode 100755 index 0000000..5ceca56 --- /dev/null +++ b/MathKit/MPRootFunctionLayout.m @@ -0,0 +1,137 @@ +// +// MPRootFunctionLayout.m +// MathPad +// +// Created by Kim Wittenburg on 11.01.15. +// Copyright (c) 2015 Kim Wittenburg. All rights reserved. +// + +#import "MPRootFunctionLayout.h" + +#import "MPRootFunction.h" + + +#define kRootFunctionTrailingOffset 3 + +#define kRootFunctionLineWidth 1 +#define kRootFunctionLineFragmentLength (self.usesSmallSize ? 3 : 4) +#define kRootFunctionVWidth 5 + +#define kRootFunctionExpressionXOffset 2 +#define kRootFunctionExponentXInset kRootFunctionLineFragmentLength + + +@implementation MPRootFunctionLayout + +- (MPRootFunction *)rootFunction +{ + return (MPRootFunction *)self.function; +} + + +- (NSUInteger)indexOfLeadingChild +{ + return 1; +} + + +- (NSUInteger)indexOfTrailingChild +{ + return 1; +} + + +- (NSUInteger)indexOfChildBelowChildAtIndex:(NSUInteger)index +{ + return 1; +} + + +- (NSUInteger)indexOfChildAboveChildAtIndex:(NSUInteger)index +{ + return 0; +} + + +- (NSUInteger)indexOfChildAfterChildAtIndex:(NSUInteger)index +{ + return index == 0 ? 1 : NSNotFound; +} + + +- (NSIndexSet *)indexesOfRemainingChildren +{ + return [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 2)]; +} + + +- (BOOL)childAtIndexUsesSmallSize:(NSUInteger)index +{ + return index == 0; +} + + +- (NSPoint)offsetOfChildLayoutAtIndex:(NSUInteger)index +{ + NSRect exponentBounds = [self childLayoutAtIndex:0].bounds; + NSRect rootBounds = [self childLayoutAtIndex:1].bounds; + if (index == 0) { + CGFloat x; + if (exponentBounds.size.width > kRootFunctionExponentXInset) { + x = 0; + } else { + x = kRootFunctionExponentXInset - exponentBounds.size.width; + } + return NSMakePoint(x, rootBounds.size.height / 2.0 + rootBounds.origin.y - exponentBounds.origin.y); + } else { + CGFloat rootSymbolXOffset = exponentBounds.size.width > kRootFunctionExponentXInset ? exponentBounds.size.width - kRootFunctionExponentXInset : 0; + CGFloat x = rootSymbolXOffset + kRootFunctionLineFragmentLength + kRootFunctionVWidth + kRootFunctionExpressionXOffset; + return NSMakePoint(x, 0); + } +} + + +- (NSIndexPath *)indexPathForLocalMousePoint:(NSPoint)point +{ + return [[NSIndexPath indexPathWithIndex:1] indexPathByAddingIndex:0]; +} + +- (NSRect)generateBounds +{ + CGFloat x, y, width, height; + NSRect exponentBounds = [self childLayoutAtIndex:0].bounds; + NSRect rootBounds = [self childLayoutAtIndex:1].bounds; + + x = 0; + y = rootBounds.origin.y; + CGFloat rootSymbolXOffset = exponentBounds.size.width > kRootFunctionLineFragmentLength ? exponentBounds.size.width : kRootFunctionLineFragmentLength; + width = rootSymbolXOffset + kRootFunctionVWidth + kRootFunctionExpressionXOffset + rootBounds.size.width + kRootFunctionTrailingOffset; + CGFloat heightToExponent = rootBounds.size.height / 2.0 + exponentBounds.size.height; + height = MAX(heightToExponent, rootBounds.size.height + kRootFunctionLineWidth); + return NSMakeRect(x, y, width, height); +} + + +- (void)draw +{ + NSRect exponentBounds = [self childLayoutAtIndex:0].bounds; + NSRect rootBounds = [self childLayoutAtIndex:1].bounds; + + CGFloat rootSymbolXOffset = exponentBounds.size.width > kRootFunctionExponentXInset ? exponentBounds.size.width - kRootFunctionExponentXInset : 0; + NSBezierPath *rootPath = [NSBezierPath bezierPath]; + NSPoint currentPoint = NSMakePoint(rootSymbolXOffset, rootBounds.size.height / 2.0 + rootBounds.origin.y); + [rootPath moveToPoint:currentPoint]; + currentPoint.x += kRootFunctionLineFragmentLength; + [rootPath lineToPoint:currentPoint]; + currentPoint.x += kRootFunctionVWidth / 2.0; + currentPoint.y = rootBounds.origin.y; + [rootPath lineToPoint:currentPoint]; + currentPoint.x += kRootFunctionVWidth / 2.0; + currentPoint.y = rootBounds.size.height + rootBounds.origin.y; + [rootPath lineToPoint:currentPoint]; + currentPoint.x += rootBounds.size.width; + [rootPath lineToPoint:currentPoint]; + [rootPath stroke]; +} + +@end diff --git a/MathKit/MPRootTerm.h b/MathKit/MPRootTerm.h new file mode 100755 index 0000000..5edb573 --- /dev/null +++ b/MathKit/MPRootTerm.h @@ -0,0 +1,33 @@ +// +// MPRootTerm.h +// MathPad +// +// Created by Kim Wittenburg on 11.01.15. +// Copyright (c) 2015 Kim Wittenburg. All rights reserved. +// + +#import "MPFunctionTerm.h" + + +/*! + @header + This file contains the MPRootTerm class. + */ + + + +@class MPRootTerm; + + +/*! + @class MPRootTerm + @abstract Represents a @link + //apple_ref/occ/cl/MPRootFunction@/link. + + @discussion A root function is evaluated by evaluating the power + pow(e, 1/n) where e is the expression + to be rooted and n the exponent. + */ +@interface MPRootTerm : MPFunctionTerm + +@end diff --git a/MathKit/MPRootTerm.m b/MathKit/MPRootTerm.m new file mode 100755 index 0000000..441724f --- /dev/null +++ b/MathKit/MPRootTerm.m @@ -0,0 +1,44 @@ +// +// MPRootTerm.m +// MathPad +// +// Created by Kim Wittenburg on 11.01.15. +// Copyright (c) 2015 Kim Wittenburg. All rights reserved. +// + +#import "MPRootTerm.h" + +#import "MPParsedExpression.h" + + + +@implementation MPRootTerm + +- (NSDecimalNumber *)doEvaluation:(NSError *__autoreleasing *)error +{ + MPEvaluateExpression(exponent, 0); + MPEvaluateExpression(root, 1); + if ([root compare:[NSDecimalNumber zero]] < 0) { + // There are no negative roots. + if (error) { + *error = [NSError errorWithDomain:MPMathKitErrorDomain + code:101 + userInfo:@{NSLocalizedDescriptionKey: NSLocalizedString(@"The root of a negative number is undefined.", nil)}]; + } + return nil; + } + if ([exponent isEqualToNumber:@(0)]) { + // The C pow function returns 1 for pow(0, 0). Mathematically this should be undefined. + if (error) { + *error = [NSError errorWithDomain:MPMathKitErrorDomain + code:101 + userInfo:@{NSLocalizedDescriptionKey: NSLocalizedString(@"The 0th root is undefined.", nil)}]; + } + return nil; + } + NSDecimalNumber *actualExponent = [[NSDecimalNumber one] decimalNumberByDividingBy:exponent]; + return [[NSDecimalNumber alloc] initWithDouble:pow(root.doubleValue, actualExponent.doubleValue)]; + +} + +@end diff --git a/MathPad.xcodeproj/project.pbxproj b/MathPad.xcodeproj/project.pbxproj old mode 100644 new mode 100755 index ee31b34..f6026b7 --- a/MathPad.xcodeproj/project.pbxproj +++ b/MathPad.xcodeproj/project.pbxproj @@ -7,6 +7,16 @@ objects = { /* Begin PBXBuildFile section */ + 3B1382E91A65B16200C097B2 /* MPRootFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B1382E71A65B16200C097B2 /* MPRootFunction.h */; }; + 3B1382EA1A65B16200C097B2 /* MPRootFunction.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B1382E81A65B16200C097B2 /* MPRootFunction.m */; }; + 3B1382ED1A65B16F00C097B2 /* MPRootTerm.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B1382EB1A65B16F00C097B2 /* MPRootTerm.h */; }; + 3B1382EE1A65B16F00C097B2 /* MPRootTerm.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B1382EC1A65B16F00C097B2 /* MPRootTerm.m */; }; + 3B1382F11A65B18200C097B2 /* MPProductFunctionTerm.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B1382EF1A65B18200C097B2 /* MPProductFunctionTerm.h */; }; + 3B1382F21A65B18200C097B2 /* MPProductFunctionTerm.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B1382F01A65B18200C097B2 /* MPProductFunctionTerm.m */; }; + 3B1382F51A65B19300C097B2 /* MPProductFunctionLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B1382F31A65B19300C097B2 /* MPProductFunctionLayout.h */; }; + 3B1382F61A65B19300C097B2 /* MPProductFunctionLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B1382F41A65B19300C097B2 /* MPProductFunctionLayout.m */; }; + 3B1382F91A65B1A200C097B2 /* MPRootFunctionLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B1382F71A65B1A200C097B2 /* MPRootFunctionLayout.h */; }; + 3B1382FA1A65B1A200C097B2 /* MPRootFunctionLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B1382F81A65B1A200C097B2 /* MPRootFunctionLayout.m */; }; 3B52CEC119BB9FA900CEDCFC /* MathKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B85830D19BB5E5500D76A8D /* MathKit.framework */; }; 3B6338351A3A4B5800698BFB /* MPExpression.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B6338321A3A4B5800698BFB /* MPExpression.h */; }; 3B6338361A3A4B5800698BFB /* MPExpression.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B6338331A3A4B5800698BFB /* MPExpression.m */; }; @@ -102,6 +112,8 @@ 3B85832219BB5E5500D76A8D /* MathKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B85830D19BB5E5500D76A8D /* MathKit.framework */; }; 3B85832819BB5E5500D76A8D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3B85832619BB5E5500D76A8D /* InfoPlist.strings */; }; 3B85834C19BB661100D76A8D /* MathKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B85833219BB5F2D00D76A8D /* MathKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3BBD8CDD1A61E35C0042A68B /* MPProductFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 3BBD8CDB1A61E35C0042A68B /* MPProductFunction.h */; }; + 3BBD8CDE1A61E35C0042A68B /* MPProductFunction.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BBD8CDC1A61E35C0042A68B /* MPProductFunction.m */; }; 3BBEA92C19BB680B00133766 /* MathKit.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 3B85830D19BB5E5500D76A8D /* MathKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; 3BBEA94F19BB79EF00133766 /* MPExpressionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B0F69AB1902A82C00817707 /* MPExpressionTests.m */; }; 3BBEA95019BB79EF00133766 /* MPRangeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BBBA3941905704200824E74 /* MPRangeTests.m */; }; @@ -157,6 +169,16 @@ /* Begin PBXFileReference section */ 3B0F69AB1902A82C00817707 /* MPExpressionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; name = MPExpressionTests.m; path = ../MathPadTests/MPExpressionTests.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 3B1382E71A65B16200C097B2 /* MPRootFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPRootFunction.h; path = MathKit/MPRootFunction.h; sourceTree = SOURCE_ROOT; }; + 3B1382E81A65B16200C097B2 /* MPRootFunction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPRootFunction.m; path = MathKit/MPRootFunction.m; sourceTree = SOURCE_ROOT; }; + 3B1382EB1A65B16F00C097B2 /* MPRootTerm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPRootTerm.h; path = MathKit/MPRootTerm.h; sourceTree = SOURCE_ROOT; }; + 3B1382EC1A65B16F00C097B2 /* MPRootTerm.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPRootTerm.m; path = MathKit/MPRootTerm.m; sourceTree = SOURCE_ROOT; }; + 3B1382EF1A65B18200C097B2 /* MPProductFunctionTerm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPProductFunctionTerm.h; path = MathKit/MPProductFunctionTerm.h; sourceTree = SOURCE_ROOT; }; + 3B1382F01A65B18200C097B2 /* MPProductFunctionTerm.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPProductFunctionTerm.m; path = MathKit/MPProductFunctionTerm.m; sourceTree = SOURCE_ROOT; }; + 3B1382F31A65B19300C097B2 /* MPProductFunctionLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPProductFunctionLayout.h; path = MathKit/MPProductFunctionLayout.h; sourceTree = SOURCE_ROOT; }; + 3B1382F41A65B19300C097B2 /* MPProductFunctionLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPProductFunctionLayout.m; path = MathKit/MPProductFunctionLayout.m; sourceTree = SOURCE_ROOT; }; + 3B1382F71A65B1A200C097B2 /* MPRootFunctionLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPRootFunctionLayout.h; path = MathKit/MPRootFunctionLayout.h; sourceTree = SOURCE_ROOT; }; + 3B1382F81A65B1A200C097B2 /* MPRootFunctionLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPRootFunctionLayout.m; path = MathKit/MPRootFunctionLayout.m; sourceTree = SOURCE_ROOT; }; 3B6338321A3A4B5800698BFB /* MPExpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = MPExpression.h; path = MathKit/MPExpression.h; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 3B6338331A3A4B5800698BFB /* MPExpression.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; name = MPExpression.m; path = MathKit/MPExpression.m; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 3B6338381A3A4B7600698BFB /* NSString+MPExpressionElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = "NSString+MPExpressionElement.h"; path = "MathKit/NSString+MPExpressionElement.h"; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; @@ -253,6 +275,8 @@ 3B85832719BB5E5500D76A8D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 3B85833219BB5F2D00D76A8D /* MathKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = MathKit.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 3BBBA3941905704200824E74 /* MPRangeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; name = MPRangeTests.m; path = ../MathPadTests/MPRangeTests.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; + 3BBD8CDB1A61E35C0042A68B /* MPProductFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MPProductFunction.h; path = MathKit/MPProductFunction.h; sourceTree = SOURCE_ROOT; }; + 3BBD8CDC1A61E35C0042A68B /* MPProductFunction.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPProductFunction.m; path = MathKit/MPProductFunction.m; sourceTree = SOURCE_ROOT; }; 3BF9976B18DE623E009CF6C4 /* MathPad.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MathPad.app; sourceTree = BUILT_PRODUCTS_DIR; }; 3BF9976E18DE623E009CF6C4 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 3BF9977118DE623E009CF6C4 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; @@ -431,12 +455,16 @@ children = ( 3B6338541A3A4BE800698BFB /* MPFractionFunction.h */, 3B6338551A3A4BE800698BFB /* MPFractionFunction.m */, + 3B1382E71A65B16200C097B2 /* MPRootFunction.h */, + 3B1382E81A65B16200C097B2 /* MPRootFunction.m */, 3B63384C1A3A4BD100698BFB /* MPParenthesisFunction.h */, 3B63384D1A3A4BD100698BFB /* MPParenthesisFunction.m */, 3B6338561A3A4BE800698BFB /* MPPowerFunction.h */, 3B6338571A3A4BE800698BFB /* MPPowerFunction.m */, 3B63384E1A3A4BD100698BFB /* MPSumFunction.h */, 3B63384F1A3A4BD100698BFB /* MPSumFunction.m */, + 3BBD8CDB1A61E35C0042A68B /* MPProductFunction.h */, + 3BBD8CDC1A61E35C0042A68B /* MPProductFunction.m */, ); name = Functions; sourceTree = ""; @@ -461,12 +489,16 @@ children = ( 3B6338CC1A3A4DE100698BFB /* MPFractionFunctionLayout.h */, 3B6338CD1A3A4DE100698BFB /* MPFractionFunctionLayout.m */, + 3B1382F71A65B1A200C097B2 /* MPRootFunctionLayout.h */, + 3B1382F81A65B1A200C097B2 /* MPRootFunctionLayout.m */, 3B6338CE1A3A4DE100698BFB /* MPParenthesisFunctionLayout.h */, 3B6338CF1A3A4DE100698BFB /* MPParenthesisFunctionLayout.m */, 3B6338D01A3A4DE100698BFB /* MPPowerFunctionLayout.h */, 3B6338D11A3A4DE100698BFB /* MPPowerFunctionLayout.m */, 3B6338D21A3A4DE100698BFB /* MPSumFunctionLayout.h */, 3B6338D31A3A4DE100698BFB /* MPSumFunctionLayout.m */, + 3B1382F31A65B19300C097B2 /* MPProductFunctionLayout.h */, + 3B1382F41A65B19300C097B2 /* MPProductFunctionLayout.m */, ); name = "Function Layouts"; sourceTree = ""; @@ -521,12 +553,16 @@ children = ( 3B63389C1A3A4CEF00698BFB /* MPFractionTerm.h */, 3B63389D1A3A4CEF00698BFB /* MPFractionTerm.m */, + 3B1382EB1A65B16F00C097B2 /* MPRootTerm.h */, + 3B1382EC1A65B16F00C097B2 /* MPRootTerm.m */, 3B6338641A3A4C2B00698BFB /* MPParenthesisTerm.h */, 3B6338651A3A4C2B00698BFB /* MPParenthesisTerm.m */, 3B6338681A3A4C2B00698BFB /* MPPowerTerm.h */, 3B6338691A3A4C2B00698BFB /* MPPowerTerm.m */, 3B6338981A3A4CE100698BFB /* MPSumFunctionTerm.h */, 3B6338991A3A4CE100698BFB /* MPSumFunctionTerm.m */, + 3B1382EF1A65B18200C097B2 /* MPProductFunctionTerm.h */, + 3B1382F01A65B18200C097B2 /* MPProductFunctionTerm.m */, ); name = Functions; sourceTree = ""; @@ -624,6 +660,7 @@ buildActionMask = 2147483647; files = ( 3B6338A81A3A4D2600698BFB /* NSIndexPath+MPAdditions.h in Headers */, + 3B1382ED1A65B16F00C097B2 /* MPRootTerm.h in Headers */, 3B85834C19BB661100D76A8D /* MathKit.h in Headers */, 3B63383A1A3A4B7600698BFB /* NSString+MPExpressionElement.h in Headers */, 3B6338C21A3A4DA500698BFB /* MPLayout.h in Headers */, @@ -633,6 +670,7 @@ 3B6338AC1A3A4D3000698BFB /* NSRegularExpression+MPParsingAdditions.h in Headers */, 3B6338501A3A4BD100698BFB /* MPParenthesisFunction.h in Headers */, 3B63387E1A3A4C7E00698BFB /* MPSumTerm.h in Headers */, + 3BBD8CDD1A61E35C0042A68B /* MPProductFunction.h in Headers */, 3B6338D81A3A4DE100698BFB /* MPPowerFunctionLayout.h in Headers */, 3B6338801A3A4C7E00698BFB /* MPTerm.h in Headers */, 3B6338521A3A4BD100698BFB /* MPSumFunction.h in Headers */, @@ -652,17 +690,21 @@ 3B63389A1A3A4CE100698BFB /* MPSumFunctionTerm.h in Headers */, 3B6338921A3A4CCA00698BFB /* MPEvaluationContext.h in Headers */, 3B63386C1A3A4C2B00698BFB /* MPNegatedTerm.h in Headers */, + 3B1382F91A65B1A200C097B2 /* MPRootFunctionLayout.h in Headers */, 3B63385E1A3A4C0700698BFB /* MPExpressionParser.h in Headers */, 3B63384A1A3A4BB300698BFB /* MPFunction+MPToken.h in Headers */, 3B63383E1A3A4B8500698BFB /* MPToken.h in Headers */, 3B6338461A3A4BA500698BFB /* MPExpressionTokenizer.h in Headers */, 3B63388A1A3A4CAF00698BFB /* MPElementaryFunctionTerm.h in Headers */, + 3B1382F51A65B19300C097B2 /* MPProductFunctionLayout.h in Headers */, 3B6338861A3A4CA500698BFB /* MPFactorialTerm.h in Headers */, + 3B1382F11A65B18200C097B2 /* MPProductFunctionTerm.h in Headers */, 3B6338581A3A4BE800698BFB /* MPFractionFunction.h in Headers */, 3B6338761A3A4C2B00698BFB /* MPProductTerm.h in Headers */, 3B6338351A3A4B5800698BFB /* MPExpression.h in Headers */, 3B6338BB1A3A4D9400698BFB /* MPFunctionsViewController.h in Headers */, 3B6338D61A3A4DE100698BFB /* MPParenthesisFunctionLayout.h in Headers */, + 3B1382E91A65B16200C097B2 /* MPRootFunction.h in Headers */, 3B6338821A3A4C7E00698BFB /* MPVariable.h in Headers */, 3B6338B41A3A4D7900698BFB /* MPExpressionStorage.h in Headers */, ); @@ -832,6 +874,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 3B1382EE1A65B16F00C097B2 /* MPRootTerm.m in Sources */, 3B6338DB1A3A4DE100698BFB /* MPSumFunctionLayout.m in Sources */, 3B63385F1A3A4C0700698BFB /* MPExpressionParser.m in Sources */, 3B6338A91A3A4D2600698BFB /* NSIndexPath+MPAdditions.m in Sources */, @@ -842,10 +885,13 @@ 3B63389B1A3A4CE100698BFB /* MPSumFunctionTerm.m in Sources */, 3B6338361A3A4B5800698BFB /* MPExpression.m in Sources */, 3B6338BC1A3A4D9400698BFB /* MPFunctionsViewController.m in Sources */, + 3B1382F21A65B18200C097B2 /* MPProductFunctionTerm.m in Sources */, 3B63383B1A3A4B7600698BFB /* NSString+MPExpressionElement.m in Sources */, 3B63386D1A3A4C2B00698BFB /* MPNegatedTerm.m in Sources */, 3B6338531A3A4BD100698BFB /* MPSumFunction.m in Sources */, 3B6338A31A3A4CFC00698BFB /* MPRangePath.m in Sources */, + 3B1382EA1A65B16200C097B2 /* MPRootFunction.m in Sources */, + 3BBD8CDE1A61E35C0042A68B /* MPProductFunction.m in Sources */, 3B63383F1A3A4B8500698BFB /* MPToken.m in Sources */, 3B63389F1A3A4CEF00698BFB /* MPFractionTerm.m in Sources */, 3B6338D71A3A4DE100698BFB /* MPParenthesisFunctionLayout.m in Sources */, @@ -864,6 +910,8 @@ 3B6338BF1A3A4D9400698BFB /* MPWhiteView.m in Sources */, 3B6338931A3A4CCA00698BFB /* MPEvaluationContext.m in Sources */, 3B6338C31A3A4DA500698BFB /* MPLayout.m in Sources */, + 3B1382F61A65B19300C097B2 /* MPProductFunctionLayout.m in Sources */, + 3B1382FA1A65B1A200C097B2 /* MPRootFunctionLayout.m in Sources */, 3B63387F1A3A4C7E00698BFB /* MPSumTerm.m in Sources */, 3B6338811A3A4C7E00698BFB /* MPTerm.m in Sources */, 3B6338B11A3A4D6A00698BFB /* MPExpressionView.m in Sources */, diff --git a/MathPad.xcodeproj/project.xcworkspace/xcshareddata/MathPad.xccheckout b/MathPad.xcodeproj/project.xcworkspace/xcshareddata/MathPad.xccheckout new file mode 100755 index 0000000..35ad05d --- /dev/null +++ b/MathPad.xcodeproj/project.xcworkspace/xcshareddata/MathPad.xccheckout @@ -0,0 +1,41 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + 07AABC7B-2194-4C40-BCC8-8DC7EC28F4CC + IDESourceControlProjectName + MathPad + IDESourceControlProjectOriginsDictionary + + 3FA814D5454DEC0D84C2FC10661BDDFF5C0232AB + https://bitbucket.org/Codello/mathpad.git + + IDESourceControlProjectPath + MathPad.xcodeproj + IDESourceControlProjectRelativeInstallPathDictionary + + 3FA814D5454DEC0D84C2FC10661BDDFF5C0232AB + ../.. + + IDESourceControlProjectURL + https://bitbucket.org/Codello/mathpad.git + IDESourceControlProjectVersion + 111 + IDESourceControlProjectWCCIdentifier + 3FA814D5454DEC0D84C2FC10661BDDFF5C0232AB + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.git + IDESourceControlWCCIdentifierKey + 3FA814D5454DEC0D84C2FC10661BDDFF5C0232AB + IDESourceControlWCCName + MathPad + + + + diff --git a/MathPad.xcodeproj/project.xcworkspace/xcuserdata/Kim.xcuserdatad/WorkspaceSettings.xcsettings b/MathPad.xcodeproj/project.xcworkspace/xcuserdata/Kim.xcuserdatad/WorkspaceSettings.xcsettings new file mode 100755 index 0000000..bfffcfe --- /dev/null +++ b/MathPad.xcodeproj/project.xcworkspace/xcuserdata/Kim.xcuserdatad/WorkspaceSettings.xcsettings @@ -0,0 +1,10 @@ + + + + + HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges + + SnapshotAutomaticallyBeforeSignificantChanges + + + diff --git a/MathPad.xcodeproj/xcuserdata/kim.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/MathPad.xcodeproj/xcuserdata/kim.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100755 index 0000000..fe2b454 --- /dev/null +++ b/MathPad.xcodeproj/xcuserdata/kim.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,5 @@ + + +