diff --git a/expreduce/builtin_functional.go b/expreduce/builtin_functional.go index 01f26df..81d7e61 100644 --- a/expreduce/builtin_functional.go +++ b/expreduce/builtin_functional.go @@ -209,7 +209,7 @@ func parseLevelSpec(this Ex, es *EvalState) levelSpec{ //This is an optimization with regards to expressionWalkMapBackwards which only deals with level specification, //expressionWalkMapBackwards also deals with depths, but has to visit the entire expression tree. -func expressionWalkMap(f func(Ex, Ex, []int64) Ex, head Ex, partSpec[]int64, this *Expression, es *EvalState, spec levelSpec) *Expression { +func expressionWalkMap(f func(Ex, Ex, []int64, *int64, *EvalState) Ex, head Ex, partSpec[]int64, this *Expression, es *EvalState, spec levelSpec, generated *int64) *Expression { toReturn := NewExpression([]Ex{this.Parts[0]}) for i, expr := range this.Parts[1:] { @@ -223,13 +223,13 @@ func expressionWalkMap(f func(Ex, Ex, []int64) Ex, head Ex, partSpec[]int64, thi //apply expressionWalkMap recursively expression, isExpression := newExpression.(*Expression) if isExpression && level < spec.max { - newExpression = expressionWalkMap(f, head, currentPartSpec, expression, es, spec) + newExpression = expressionWalkMap(f, head, currentPartSpec, expression, es, spec, generated) } //If this part is covered by the level specification, apply the function //specified by the first argument of Map if level >= spec.min { - newExpression = f(head, newExpression, currentPartSpec) + newExpression = f(head, newExpression, currentPartSpec, generated, es) toReturn.Parts = append(toReturn.Parts, newExpression) } else { toReturn.Parts = append(toReturn.Parts, newExpression) @@ -239,7 +239,7 @@ func expressionWalkMap(f func(Ex, Ex, []int64) Ex, head Ex, partSpec[]int64, thi return toReturn } -func expressionWalkMapBackwards(f func(Ex, Ex, []int64) Ex, head Ex, partSpec[]int64, this *Expression, es *EvalState, spec levelSpec) (*Expression, int64) { +func expressionWalkMapBackwards(f func(Ex, Ex, []int64, *int64, *EvalState) Ex, head Ex, partSpec[]int64, this *Expression, es *EvalState, spec levelSpec, generated *int64) (*Expression, int64) { toReturn := NewExpression([]Ex{this.Parts[0]}) currentMaxDepth := int64(1) @@ -253,13 +253,13 @@ func expressionWalkMapBackwards(f func(Ex, Ex, []int64) Ex, head Ex, partSpec[]i expression, isExpression := newExpression.(*Expression) if isExpression { //Determine the depth of this part - newExpression, depth = expressionWalkMapBackwards(f, head, currentPartSpec, expression, es, spec) + newExpression, depth = expressionWalkMapBackwards(f, head, currentPartSpec, expression, es, spec, generated) if depth > currentMaxDepth { currentMaxDepth = depth } if spec.checkLevel(level) && spec.checkDepth(depth) { - newExpression = f(head, newExpression, currentPartSpec) + newExpression = f(head, newExpression, currentPartSpec, generated, es) toReturn.Parts = append(toReturn.Parts, newExpression) } else { toReturn.Parts = append(toReturn.Parts, newExpression) @@ -269,7 +269,7 @@ func expressionWalkMapBackwards(f func(Ex, Ex, []int64) Ex, head Ex, partSpec[]i depth = int64(1) if spec.checkLevel(level) && spec.checkDepth(depth) { - newExpression = f(head, expr, currentPartSpec) + newExpression = f(head, expr, currentPartSpec, generated, es) toReturn.Parts = append(toReturn.Parts, newExpression) } else { toReturn.Parts = append(toReturn.Parts, newExpression) @@ -280,11 +280,11 @@ func expressionWalkMapBackwards(f func(Ex, Ex, []int64) Ex, head Ex, partSpec[]i return toReturn, currentMaxDepth+1 } -func wrapWithHead(head Ex, expr Ex, partList []int64) Ex { +func wrapWithHead(head Ex, expr Ex, partList []int64, _ *int64, es *EvalState) Ex { return NewExpression([]Ex{head, expr}) } -func wrapWithHeadIndexed(head Ex, expr Ex, partList []int64) Ex { +func wrapWithHeadIndexed(head Ex, expr Ex, partList []int64, _ *int64, es *EvalState) Ex { partSpec := []Ex{NewSymbol("System`List")} for _, part := range partList { partSpec = append(partSpec, NewInt(part)) @@ -293,7 +293,7 @@ func wrapWithHeadIndexed(head Ex, expr Ex, partList []int64) Ex { return NewExpression([]Ex{head, expr, partSpecExpr}) } -func applyHead(head Ex, expr Ex, partList []int64) Ex { +func applyHead(head Ex, expr Ex, partList []int64, _ *int64, es *EvalState) Ex { expression, isExpr := expr.(*Expression) if !isExpr { return expr @@ -303,11 +303,32 @@ func applyHead(head Ex, expr Ex, partList []int64) Ex { return toReturn } -func mapFunction(f func(Ex, Ex, []int64) Ex, isApply bool) func(*Expression, *EvalState) Ex { +type levelSpecOptimizationStrategy int + +const ( + unoptimizedSimpleLevelSpec levelSpecOptimizationStrategy = iota + mapOptimizedSimpleLevelSpec + applyOptimizedSimpleLevelSpec +) + +func exOrGenerated(e Ex, generated *int64, returnGenerated bool) Ex { + if returnGenerated { + return NewInt(*generated) + } + return e +} + +func levelSpecFunction( + f func(Ex, Ex, []int64, *int64, *EvalState) Ex, + optStrat levelSpecOptimizationStrategy, + returnGenerated bool, + leveledExprIsFirst bool, +) func(*Expression, *EvalState) Ex { return func(this *Expression, es *EvalState) Ex { - // Optimization of the very common case where Map has two arguments + // Optimization of the very common case where the levelspec-ed + // operation has two arguments if len(this.Parts) == 3 { - if !isApply{ + if optStrat == mapOptimizedSimpleLevelSpec { expr, isExpr := this.Parts[2].(*Expression) if isExpr { toReturn := NewExpression([]Ex{expr.Parts[0]}) @@ -320,7 +341,7 @@ func mapFunction(f func(Ex, Ex, []int64) Ex, isApply bool) func(*Expression, *Ev return toReturn } return this.Parts[2] - } else { + } else if optStrat == applyOptimizedSimpleLevelSpec { sym, isSym := this.Parts[1].(*Symbol) expr, isExpr := this.Parts[2].(*Expression) if isSym && isExpr { @@ -341,42 +362,54 @@ func mapFunction(f func(Ex, Ex, []int64) Ex, isApply bool) func(*Expression, *Ev return this } - //If the second argument is atomic, it will be ignored except in one case - expression, nonAtomic := this.Parts[2].(*Expression) + // For example the function to apply for Map or the pattern to match + // for Count. + dataExpr := this.Parts[1] + leveledExpr := this.Parts[2] + if leveledExprIsFirst { + dataExpr = this.Parts[2] + leveledExpr = this.Parts[1] + } + generatedData := int64(0) + generated := &generatedData + + // If the leveled expression is atomic, it will be ignored except in + // one case + expression, nonAtomic := leveledExpr.(*Expression) if !nonAtomic { if spec.checkLevel(0) && spec.checkDepth(0) { - return f(this.Parts[1], this.Parts[2], []int64{}) + return exOrGenerated(f(dataExpr, leveledExpr, []int64{}, generated, es), generated, returnGenerated) } else { - return this.Parts[2] + return exOrGenerated(leveledExpr, generated, returnGenerated) } } if spec.min == 0 && spec.max == 0 { - return f(this.Parts[1], this.Parts[2], []int64{}) + return exOrGenerated(f(dataExpr, leveledExpr, []int64{}, generated, es), generated, returnGenerated) } //In this special case we do not have to keep track of depth, this can be computed faster //than when depth is required because we do not always have to recurse all the way to the //bottom of the expression if !spec.isMinDepth && !spec.isMaxDepth { - newExpression := expressionWalkMap(f, this.Parts[1], []int64{}, expression, es, spec) + newExpression := expressionWalkMap(f, dataExpr, []int64{}, expression, es, spec, generated) if spec.checkLevel(0) && spec.checkDepth(0) { - return f(this.Parts[1], newExpression, []int64{}) + return exOrGenerated(f(dataExpr, newExpression, []int64{}, generated, es), generated, returnGenerated) } else { - return newExpression + return exOrGenerated(newExpression, generated, returnGenerated) } } //We now turn to the most general case, where levels can be specified as either //positive or negative integers, where negative integers denote depth rather than level - newExpression, depth := expressionWalkMapBackwards(f, this.Parts[1], []int64{}, expression, es, spec) + newExpression, depth := expressionWalkMapBackwards(f, dataExpr, []int64{}, expression, es, spec, generated) //Whether to wrap the zeroth level with the function. if spec.checkLevel(0) && spec.checkDepth(depth) { - return f(this.Parts[1], newExpression, []int64{}) + return exOrGenerated(f(dataExpr, newExpression, []int64{}, generated, es), generated, returnGenerated) } else { - return newExpression + return exOrGenerated(newExpression, generated, returnGenerated) } } } @@ -391,30 +424,16 @@ func getFunctionalDefinitions() (defs []Definition) { }) defs = append(defs, Definition{ Name: "Apply", - /*legacyEvalFn: func(this *Expression, es *EvalState) Ex { - if len(this.Parts) != 3 { - return this - } - - sym, isSym := this.Parts[1].(*Symbol) - expr, isExpr := this.Parts[2].(*Expression) - if isSym && isExpr { - toReturn := NewExpression([]Ex{sym}) - toReturn.Parts = append(toReturn.Parts, expr.Parts[1:]...) - return toReturn.Eval(es) - } - return this.Parts[2] - },*/ - legacyEvalFn: mapFunction(applyHead, true), + legacyEvalFn: levelSpecFunction(applyHead, applyOptimizedSimpleLevelSpec, false, false), }) defs = append(defs, Definition{ Name: "Map", - legacyEvalFn: mapFunction(wrapWithHead, false), + legacyEvalFn: levelSpecFunction(wrapWithHead, mapOptimizedSimpleLevelSpec, false, false), }) defs = append(defs, Definition{ Name: "MapIndexed", - legacyEvalFn: mapFunction(wrapWithHeadIndexed, false), + legacyEvalFn: levelSpecFunction(wrapWithHeadIndexed, mapOptimizedSimpleLevelSpec, false, false), }) defs = append(defs, Definition{ diff --git a/expreduce/builtin_list.go b/expreduce/builtin_list.go index 9b5c3f8..944eab0 100644 --- a/expreduce/builtin_list.go +++ b/expreduce/builtin_list.go @@ -160,6 +160,13 @@ func ThreadExpr(expr *Expression) (*Expression, bool) { return toReturn, true } +func countFunctionLevelSpec(pattern Ex, e Ex, partList []int64, generated *int64, es *EvalState) Ex { + if isMatch, _ := IsMatchQ(e, pattern, EmptyPD(), es); isMatch { + *generated++ + } + return e +} + func GetListDefinitions() (defs []Definition) { defs = append(defs, Definition{ Name: "List", @@ -585,7 +592,15 @@ func GetListDefinitions() (defs []Definition) { defs = append(defs, Definition{Name: "Last"}) defs = append(defs, Definition{Name: "First"}) defs = append(defs, Definition{Name: "Rest"}) - defs = append(defs, Definition{Name: "Count"}) + defs = append(defs, Definition{ + Name: "Count", + legacyEvalFn: levelSpecFunction( + countFunctionLevelSpec, + unoptimizedSimpleLevelSpec, + true, + true, + ), + }) defs = append(defs, Definition{Name: "Tally"}) defs = append(defs, Definition{Name: "ConstantArray"}) defs = append(defs, Definition{ diff --git a/expreduce/resources.go b/expreduce/resources.go index be05ec3..eaef9a6 100644 --- a/expreduce/resources.go +++ b/expreduce/resources.go @@ -324,7 +324,7 @@ func resourcesInitM() (*asset, error) { return a, nil } -var _resourcesListM = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xdc\x3b\x6d\x73\xdb\x38\xce\xdf\xf3\x2b\x38\xed\x4c\x27\x69\xd5\x6c\xe4\xc4\xed\xb6\x99\xee\xf3\xf4\xba\xed\x6c\xef\xda\xed\xb6\xcd\x7e\xd2\x68\x6d\x5a\xa6\x13\x5d\x65\xc9\xab\x97\x26\xae\xc7\xff\xfd\x00\x90\x92\x48\x99\x54\xac\x74\x6f\xee\xe6\xde\xe2\x8a\x04\x40\x00\x04\x41\x10\x04\xdf\xc5\x45\xf9\xfc\x79\x55\xf0\x4b\xc1\x5e\xb0\x7b\xd3\x8d\xf0\x3d\x26\x46\x1e\x3b\x3e\x3e\xde\x4e\xd9\x65\x9e\x55\xab\x82\x89\x9b\x55\x2e\x8a\x22\xce\xd2\x82\x95\xd9\xa5\x28\xaf\x44\x7e\x7c\xef\xfc\xe0\x65\x59\xe6\xf1\xac\x2a\x45\x11\x20\xa1\x10\x48\x6c\xde\x65\xd1\x17\x31\xf7\xd8\x6f\x79\x56\x8a\xa8\x14\xf3\xed\xf9\xc1\x85\x28\xca\x62\x8a\x20\x08\x71\xc0\xe0\x3f\xaf\x3f\xc7\xcb\x55\x22\x5e\xdf\x70\xfc\x29\x02\x6a\x94\x1d\x7c\x29\x10\x21\xd8\x00\x2b\xc0\x09\xdf\x7a\x0c\x51\x03\xdf\x1b\x79\x3c\x0c\x09\x32\x3c\x00\xb2\x07\x17\x59\xc9\x13\x9d\x7d\x6a\x08\x12\xe4\x65\xca\x8a\x6a\x59\x30\x9e\x24\x0c\xd8\x65\x5f\x79\x52\x89\x82\xc5\x29\x9b\x62\xf7\x14\xd9\x57\xd0\x93\x89\x64\xfe\xf9\x0b\xf6\x72\xb5\x4a\xd6\xc1\x6f\x49\x55\x78\x2c\x09\x0d\x01\x09\x98\x24\xdc\x95\x8c\xfa\x86\x88\xe6\x9f\x78\x4c\x8e\xbe\x41\xa9\x4e\xbd\xb3\x6d\x2d\x98\xc7\x5e\xbf\xa9\x72\xd4\xb0\x85\xc0\xab\x6c\xb9\x14\x69\x19\xdc\xbb\x00\x91\x4a\x1a\x35\x5b\x30\x9e\x32\xb1\x5c\x95\x6b\x86\x92\xb1\xb8\x60\xdf\x44\x9e\x3d\xbf\x17\x7a\x96\x91\xdb\x81\xb7\x86\x2a\xdf\x0b\x9e\xea\x9a\xc4\xef\x5a\x91\x11\x4f\xa2\x2a\xe1\xa0\x05\x52\x65\x51\xf2\x12\x3a\x62\x68\x66\x4b\x00\x43\x16\x5a\xa5\x4a\x44\x4d\xa7\x4a\xcb\xe1\x0f\xef\x44\x7a\x59\x5e\x05\x1d\xbd\x22\xbc\x43\xad\xd8\x35\x48\xab\xfe\x0f\x60\x2f\xc4\xc0\x66\xec\x3d\x31\x05\xbc\xe0\xb3\x44\x18\xb6\x82\x0d\x01\x9a\xb6\xc7\x52\x90\x32\x17\x65\x95\x83\x81\x73\xa9\xc6\xeb\xb8\xbc\x62\xd3\x14\xa4\xcf\x56\x31\x48\x8e\x42\x22\xf0\xf4\xf8\xe0\xc0\xc0\xdd\x14\xeb\x25\x50\xd8\xba\x48\x10\x12\x13\x68\x80\xa0\xc2\xb9\x6a\x05\xa4\x29\xb0\xe1\xc3\x2c\xe2\x28\x76\xa2\x77\xa7\x3b\x85\xbf\x8a\x32\xcc\xc9\xe1\xc3\xdf\x0b\x01\xd8\xbf\xa7\xf1\x9f\x95\xf8\x59\x2c\xe2\x54\xcc\xa7\x0c\x16\xf5\x22\xbe\xf1\x58\x96\x33\x91\x00\x80\x64\x20\xf6\xd8\x38\x04\x6a\xb0\x70\xe4\xb8\x0f\x8f\x80\x40\x9c\x46\x59\x9e\xc3\xfc\x40\x63\x51\x25\x65\x71\x0c\xcd\x12\x81\x4f\x3c\x36\x9b\xbc\x4d\x4b\x71\x29\x72\x39\xe5\xb2\x1d\xc4\x30\x47\x04\xd2\xb0\xa6\x67\xdb\xce\xca\x42\x68\x32\x81\x5f\xb2\x64\xfe\x32\x49\x6c\xce\x83\x80\x06\x79\x0f\x18\xbe\xfd\x1f\xf8\x90\x86\xa9\x71\x68\x5d\x19\x60\x32\xec\x89\xc7\x9e\x7a\xec\x47\x8f\x3d\x03\x4e\x4f\x1a\x24\xe0\x7b\x83\x6a\xa1\x46\x03\xbb\x59\x90\xaf\x72\x01\xb3\x50\xcf\x10\x18\x0b\xae\x94\x45\x9c\xc3\x87\x7f\xc2\x8a\x3f\x2b\x0e\x7a\x73\xac\x49\x74\x74\x67\x72\x4c\x60\x60\x04\xc3\x9c\xc2\xef\x19\x7c\x3f\x81\xe6\x1f\x7d\x1c\xb6\x65\x26\xfd\x03\x8c\x7c\x93\x92\x2a\x9d\xec\xbc\x2d\x45\x0e\xab\x34\x4b\xd9\x1c\x75\x1f\x97\xe4\xbb\xe7\x19\x4b\xb3\x92\x5d\xf1\xaf\xb0\x8a\xe3\xb9\x60\x62\xb1\x00\x35\x77\xf9\x82\x99\x49\x2f\x89\xb3\x7b\xf1\x3d\x8f\xc1\x1f\x2b\xdb\x23\xe0\x03\xa5\x25\xb6\xb0\xe5\x33\x38\x06\x31\x8d\x61\x96\x46\xa3\xbf\x4e\xc5\x3a\x3b\xa3\x91\xe2\x67\x0f\x5f\xd9\x8e\x7a\xe2\x81\x93\x6d\x46\xba\x09\x9e\x3d\x03\xcc\xcd\x4d\x30\x81\x1f\xf0\x87\x23\xdd\xf7\x92\xb5\x59\x3d\x2e\x74\xc0\x8a\xc9\x56\x22\xaf\x17\x1d\xaa\x57\xcd\x74\x0c\xfa\x2e\x56\x22\x3a\xb6\xab\xea\xd7\x0a\xad\x1a\x8c\xbd\x4c\x71\x7d\x8c\xcf\x9d\x76\x00\x3a\x3d\x25\x6b\x18\x77\x55\x43\xd8\x5d\xa7\xbd\x9c\x89\xfc\xa3\xe9\xb7\xa9\x49\xb9\x91\x15\x2f\x35\xf7\x71\x91\x57\xc0\x29\xee\x17\xeb\x9a\x6f\x91\x08\x14\x4f\x6e\x8c\xd2\xa3\x2c\x79\x19\x81\x23\x01\xd4\x29\xb8\x06\x54\xee\x75\x0c\xce\xa1\x26\xf2\x86\x83\xab\xe8\x6c\xfe\x6a\x50\xa7\x1b\xa7\xde\x21\x8b\x97\x06\x41\x57\x2e\x85\xa9\x15\x03\x2a\x39\xb1\x2f\x5e\x14\xcd\x0a\xef\xdb\xe1\xdd\x03\x6c\x7c\xc7\x92\xaa\xe5\x98\xb2\xeb\x2c\xff\x52\x48\x7f\x0b\x5a\x82\x99\x4f\x5d\x2b\xdb\xc9\x56\xe3\x2e\x07\xa2\x0d\x95\x66\xf2\x49\x40\xd4\x32\x6c\x10\x34\x34\x32\x02\x3b\x93\xda\x72\x6c\x20\x71\x55\xb6\x1f\xfb\xf0\x88\x4e\x79\x2f\x61\x78\x47\xea\xc3\x87\xef\xb3\x5c\x10\x93\x18\x8c\xb2\x99\x60\x55\x01\xdb\x1f\x18\xf0\x87\x7c\x2e\x72\xb0\xa8\xe2\x6d\xf1\x1e\x19\xf9\x08\x5b\xd4\xed\xca\xe2\xb8\x23\x79\x2c\xda\x4b\x4b\x0a\x98\x0f\x8b\xd6\xac\xa6\xf3\xb7\x84\xa7\x5f\x3e\x0b\xd8\x1e\xd3\xc8\xb9\x35\xd8\x87\x9f\x4c\x1c\x86\xe0\x02\xdf\xcf\x6c\x1a\xf0\x5e\xe3\x74\x62\x0d\xb2\xe9\x16\xeb\xf3\x7a\x39\xcb\xf6\xb3\xd1\x06\x69\x20\x0e\xb8\x81\xef\x41\xb3\xc9\xd5\xce\xad\xf4\x9a\xa9\x00\x1b\xc4\xcd\x75\x86\x41\x00\x1d\xab\xf6\x99\xd1\x19\xcf\x03\x39\x54\x14\xee\xbb\x22\x4c\x1c\xf8\x32\xf6\x84\x57\xbc\x00\x6b\xd2\x76\x04\x6a\xb0\xee\x07\x1c\xb8\xbe\x66\x74\x2e\x9b\xd2\x39\x02\x42\x3e\xcb\x86\x50\x5e\xf1\x52\xdf\x15\x3a\xce\x9f\xe8\x3b\x5c\x3f\xf5\x0d\x8a\xda\xc6\xd2\x0d\x1d\xc3\x2f\x44\xa6\x6b\xd8\x0a\x61\x0a\xa4\x08\xf6\x3e\x87\x6d\x03\xf0\xc8\xbb\x15\xb7\xd7\x62\x37\x00\x7d\x1b\x01\xb7\x7b\xdd\x8c\xbc\xa8\xc5\x9e\x41\xd0\xe6\x7b\xfc\x0f\x68\x9a\xfc\x21\x26\x8f\x7f\x12\x03\x3d\x88\xcd\xca\x12\xb7\x95\x6d\x78\x33\xf6\x8e\x89\x69\xc6\xf2\x33\x4c\x77\x29\x76\x4c\x46\x6b\xee\x31\x9c\x36\x2b\x70\x9b\xf1\xa8\xb8\xd3\x6d\x43\xda\x80\x0e\x4b\xd2\x20\x06\xd9\x13\x4e\xd8\x8d\xb7\x06\x6d\xe8\x42\x91\x75\xa8\x2e\xb4\x92\x5b\x0c\x01\xa1\x15\x64\x3f\x19\xb7\x39\xdc\x3c\x5a\x9b\xb8\x80\xf6\x08\x1b\x15\x8e\x36\x29\x70\x66\xca\x8c\xb3\x38\x35\xd0\x44\x60\x72\x06\x7e\x64\x7e\xc6\x98\x90\x22\xcb\xf1\x10\x58\xa5\x66\x50\xba\xa4\xb9\xa0\x48\xaf\xcd\xe1\x74\x94\x4f\xe4\x1d\x6a\xa7\xbe\x81\xc7\x2e\x74\xd1\x92\xe5\xcd\xcc\xe3\xf0\x5f\xf8\xbb\x75\x68\x16\x3b\xd7\xde\x37\x1b\x86\xb7\xc1\x0e\x3b\xde\x22\xcb\x02\x85\x1a\xd6\xa8\xd8\xd6\x60\x87\x1e\x7e\x62\x77\x4f\x6c\xdf\x90\xb3\x12\x90\xc3\x3b\xa8\xf7\xf0\xb6\x69\x84\xb1\xf7\xef\x0a\xda\xca\x60\xb6\xba\x57\xb6\x82\x76\xaa\x15\x5d\x7a\x0b\x46\x5f\xe6\x26\x91\xe1\x04\xe2\x5a\x35\x76\x8a\xa6\xf5\xdf\x67\x6c\xed\x18\xae\x2d\xa3\x01\x18\x64\x76\x68\x74\x1a\xff\x75\xa8\xe0\x56\x51\x64\x41\x00\x17\x29\x71\xe0\xcf\xac\xef\x54\x68\x18\x62\x68\x10\x22\xd3\x84\x26\xf9\x6b\x1f\x5c\x03\x37\x91\xdd\x16\xa5\xb3\xea\x10\xc9\x00\x69\x18\xe8\xa0\xf6\x33\xb6\x51\x2a\xe8\x53\xcc\xc4\xa5\x51\x37\x2e\x6c\x94\x7f\x1d\x3a\xfc\x19\x46\x22\x22\x2a\xdf\x4b\xc2\x45\x45\x5b\x55\x9f\x78\x7a\x69\xa4\x18\xa9\x21\x30\x93\x8b\x6d\xb8\x15\xcb\x3d\xa7\x60\x8b\x3c\x5b\x1a\x99\x40\x89\xb7\xec\xe6\x25\x5d\xa8\x66\xb2\x4f\x5b\x6c\x44\x47\x66\xe5\x01\x13\x93\x09\xb6\xd4\x1a\x41\xdd\x21\x31\x8f\x67\x45\xc9\xe9\xa9\x33\x04\xd2\x92\x19\x12\x74\xe4\xce\xbf\xe9\x30\x8f\xc7\x86\x66\x7f\xe3\xb9\xe1\xa9\xd0\xbf\x04\x41\x1c\x82\x7a\xb2\x9c\x4d\xb1\x5b\x05\x2a\xb1\xa6\x31\xf4\x44\xd3\x78\x0a\x67\x2d\x15\x98\x68\x49\x5c\x53\x51\x48\x80\xf4\xf4\x2b\xa6\x20\x3f\x01\x3b\xc0\x8b\xe0\xf3\x46\x59\x36\xbd\x21\xd2\x1e\x6a\x6b\x62\xb8\x4f\xc4\x96\x4c\xa1\x8b\x28\x4b\xe7\xe4\x33\xd1\x65\xf6\x86\x72\x33\xb4\xb8\x7a\x21\xcc\xb7\x41\x30\x0a\xed\x27\x91\xf7\x55\x52\xc6\x8f\xe7\x31\x7c\xa1\xe7\xe5\x09\x90\x9e\xc7\x70\xb6\x64\x1c\x0e\xcc\x45\xb5\x5a\x91\xdb\x76\x45\x8c\xdd\x2c\x24\xda\xf7\x88\x32\x75\x3e\xfc\xff\x14\x27\x0e\xd3\x75\x1b\x98\x51\x1f\x3e\x46\x4f\x01\x1c\x3a\x9e\x12\xe0\x99\xc4\xc2\xbc\x25\xe6\x2c\x65\xbe\x92\x62\xe6\x13\x00\x83\xdf\x1f\x4f\x10\x6d\xbc\x85\x66\x08\x03\x59\x9d\x23\x56\x49\xd9\x87\x33\x4a\x6a\xce\xd0\x52\x42\x29\xef\xd8\xb1\x42\x91\x20\x50\x08\x02\x24\xee\xd0\x04\x66\xbb\xa7\x2f\x93\x84\x96\x45\x01\x93\x1f\x95\x10\x9f\x66\xe9\xa5\xdc\x9c\xd2\x32\x06\x85\x34\x8a\x72\x29\xc4\xc2\x7d\x3b\x34\x50\x0f\x87\x85\xf0\x1f\x2a\xb2\xbf\x59\x56\xa5\x73\xd8\x28\x8b\x02\xef\xa3\x28\xcd\x0e\x7b\xe5\x57\xb4\x4e\x73\xe7\x94\x6b\xbb\x4e\x35\xa6\x97\xee\x48\x9f\x4c\x02\x2c\x14\x57\x01\x39\xa7\x91\x5d\x2d\x78\x69\x14\xa7\x2b\xe0\xc3\x3c\x47\x48\xbf\xe2\xa0\x0f\xdb\x85\x22\x5d\xef\x6c\x27\x76\xea\x1f\x96\x71\x89\x7c\xe2\x75\x14\x18\x9e\xb8\xd1\xef\x10\x48\xb6\x2c\x8f\x2f\x63\xb4\xcb\x56\x48\xc7\xa0\xb1\x1a\x32\x76\x3a\x96\x33\xef\x09\x5a\x18\xb9\x22\x65\x95\x67\xca\xe4\x9e\x6c\x41\x23\x74\x8d\x30\xda\x2b\xfa\xbb\x65\x30\xea\xab\xd5\xeb\x0c\x63\x21\xda\x08\x02\xff\x78\xac\x4d\x84\x8c\x40\x64\x5b\x0f\x12\xaf\x61\x4c\x3c\xde\x83\x7a\xdb\x9c\xfc\x2f\x2d\xea\x41\xeb\xd1\x7d\x56\xa8\xcf\xbf\xfa\x17\x59\x89\x03\xcb\x07\xaa\xcd\x9c\xf8\xce\x4d\x8b\xeb\xcb\xce\x91\x6b\xbe\x7d\x85\xee\x23\x23\xb1\x4a\x4c\x59\x31\x4f\x77\x16\x03\x0e\x4a\x3c\xb9\x2d\x43\x02\x2b\x48\xe2\xd0\xda\xec\xc8\x8e\xd0\x71\xd8\xbd\x02\x47\x7d\x93\xb2\xc1\x5b\xae\xf1\x09\x5a\x1a\x19\x56\x57\x54\x52\x78\xbb\x76\xff\x91\x66\xd7\xe9\x1b\x1e\x27\x55\x6e\x0f\x49\xd4\xf9\x3d\xd0\x66\x8c\x06\xb7\x8d\x2d\xb3\x80\x0d\x28\x57\xa0\x5a\xb8\xf1\x79\x65\x5e\x86\x43\xec\x04\x5b\xfd\xf9\x39\x6c\x1d\x73\x0c\x2f\xd0\x7b\x51\x9e\xa3\x71\x75\x05\x60\x68\x9b\x4d\x55\xa0\x23\x44\xf2\x9d\x40\x03\x29\x3b\x0e\x3e\xd8\x35\xec\xc8\x53\x47\xe5\x46\x70\x80\x6c\x9e\xf6\x85\xf7\x08\x67\xc5\xd2\xb7\x34\x52\x03\x34\xe8\x5a\xa0\x0d\x95\x27\x49\x76\x5d\x28\x39\x71\x97\x92\xfb\x2a\x6f\xb7\x53\x4a\xfe\xa0\xe8\xdd\x20\x0b\xe9\xdb\x45\x87\x9e\x41\x92\xff\x77\x7b\xb5\xff\x54\x18\x22\xcb\x1c\xae\x72\x88\x5b\x8d\x3a\x07\x6a\x09\x16\x01\x07\xad\x71\x55\xda\x83\x91\x33\x5f\xad\x12\xac\x6c\x58\xb0\xec\xab\xc8\x89\x27\x9e\x5f\x56\x94\xc1\xa3\xa3\x3f\x87\xf0\x11\x98\xcd\x20\x60\xc0\x2b\x43\x8c\x51\xbb\xc7\x79\x49\xdc\x55\x16\x43\x9d\xed\xcc\x3a\x77\xe0\xcd\x22\xb8\x41\xdf\x1c\xac\xe9\xef\xb7\x10\x24\x6c\xd8\xde\xc8\x74\x2b\xa6\x5b\xec\x0a\x02\x64\xb0\x65\x89\x5f\xff\xe3\x1b\xfe\xc3\x4a\x05\x3b\x1c\x1b\x85\x0e\x84\xe7\x7f\x3b\x3a\x65\x06\x5c\x9c\x18\xc3\x18\xe3\x37\x3d\x7f\x0d\x09\x97\x10\x4a\x1b\x98\xe8\xad\x15\xa2\xeb\x04\xb7\x3d\x97\x5a\x5a\xa7\xe0\xe4\x6e\xb9\x5e\x65\x45\xf0\xd8\x07\x7a\xf2\x9f\x67\xcd\xbf\xc6\x1a\x5d\xd9\xb2\x79\xec\xab\xc3\x9f\x53\xe1\xed\xbe\xdc\x5a\xa9\x6a\x72\x8a\xe7\x9b\x02\xf8\x4e\x66\x4f\xa8\x44\x62\xd4\x42\x37\x2d\xae\x2d\xf1\x44\x56\x8a\xa0\x7b\xe1\xca\xa7\xf0\xad\x86\xaf\x91\x74\xe5\x95\x78\x03\xed\xb8\xcc\x51\xbd\xad\xc8\xa6\xcb\x5d\xad\x60\x8f\x31\xbc\x2e\xb5\x50\x29\x16\x2c\x4a\xed\x74\x2b\x4b\xae\xea\x62\x20\x5a\xce\x00\x28\xe6\x5d\xaf\x4b\xcd\x2e\xc7\x4b\x9d\x43\xf3\xbb\x74\xb1\xa1\xf8\x92\xf9\x5e\xc7\xe5\x69\x9d\xa6\xc5\x09\x56\xf0\xaa\x29\x44\x94\x1d\xb9\x2f\xb2\x5d\xc9\x2f\x32\x4d\x76\x29\x63\x41\xf2\x62\xc6\x43\xaa\x00\xfc\x94\x71\xe6\x5f\x66\xf3\x78\x11\xc3\x09\xa7\xad\x4a\x33\x68\x4d\x80\xd8\x84\x0a\x95\x0e\x13\x59\x93\xd8\x51\xf2\x91\x45\x83\x17\x59\x53\xa2\xf4\x06\xcb\x7a\x6c\x19\x81\x1a\xf2\x4e\x0a\xa5\x2d\x90\x82\xff\x73\xd6\xb2\x8b\x4b\xe1\x9c\x25\x46\x32\x04\x02\x90\x8e\x91\xa8\xa6\x3d\xac\x64\x25\x21\x77\xcc\x44\x51\x70\xd8\x89\xea\x1d\x24\x57\xe4\xc9\xab\x80\x9a\xb7\x5b\x2d\x85\x10\xc2\x16\xc1\x61\x2a\xaa\xdb\xb4\x95\xa6\x51\x53\x81\x12\xf5\x0e\xd6\x62\x52\xdb\x35\x97\xae\xba\x8f\x6c\xaa\xdc\xc7\x60\x1a\xd0\x3b\x69\x56\xb7\x18\x8d\x65\x8b\xc9\xc8\x8b\xa7\x9f\x2b\xd8\xf0\x23\xac\xe3\xdc\xbd\xec\x6b\xfb\xea\xaa\x4f\x9b\x05\xa1\xbe\xe6\x0d\x24\x80\x2c\x21\x74\xe8\x9a\x52\x97\x60\xef\x8d\x5e\x0b\x36\x30\xf6\x45\x07\xbd\xc3\x3a\xdd\x9f\xcc\x7a\x2e\x8d\xe8\xf2\x66\x17\xaf\xbe\xdd\x71\xee\xaa\xd6\xc1\x1c\xe3\x40\x44\x89\x07\x1a\x55\xee\xba\x83\x26\x73\x9c\x04\x14\x9a\xb1\xdb\x3b\x6e\x16\x63\xe3\x37\xa5\x35\x3b\x39\xcd\x84\x63\x29\x1a\x1e\x49\x8c\x7c\xa6\x04\x9f\xfc\xdf\xe1\xa1\x1a\xfa\x7e\xf8\xd3\x0b\xff\xe8\xc1\x11\xd9\xae\x08\x02\xd5\x2c\x60\x54\xb3\x76\x9b\x17\xae\xdb\x18\xec\x1a\x32\x31\x10\x54\x13\x1b\xb0\x85\xca\x0a\x5c\x47\x46\x93\x80\xf8\xa3\xd9\x3e\xf9\x19\x09\x1b\xd6\x48\x76\x9a\x72\xd4\x6d\x0d\xe5\x9a\x1b\x5e\xf7\x73\x33\x75\x4f\x2b\x54\xd7\x3d\x35\xd8\x94\x2f\x6b\x3a\x77\xb5\xaf\x10\x7a\xd4\xef\x77\xd4\x4e\x18\x0e\xbd\x53\xdf\xa0\xda\x67\x8f\x49\x0e\x7a\x35\xcf\x6b\xa8\x3d\x55\xaf\x80\xc3\x06\xcd\x51\xa0\x22\x47\xde\x36\x70\x3d\xea\x57\x00\x1d\xfd\x63\xca\xdd\xb8\x39\x11\xbb\xda\xc7\x0a\x03\xd0\x5c\xef\x2c\x48\xbc\x9e\x49\x18\x9d\x9f\xd3\x99\xc9\xbc\x27\x11\xce\x89\xc0\xae\x81\x05\x2c\x98\x98\xfc\x24\x6e\x5d\x04\x8f\x22\x05\x06\x73\xf1\x28\xda\x67\x36\x24\x74\x58\xa3\xd9\xe9\xca\x91\xb7\x35\x94\xf3\xa2\xab\x61\xb2\x33\x13\x9f\xe9\x9c\xaa\xcf\x85\x6c\x51\xf7\x2b\x78\x6f\x81\x6f\x2b\xa8\xad\x60\x59\x9a\xac\x69\x1a\xb4\x02\x79\x59\xf3\x51\xe0\x23\x81\xc5\x9a\x4d\x11\xa3\x9b\x0a\x90\x24\x5d\x89\x10\x79\x52\x1e\x76\x21\x75\x0a\xaa\x7e\xea\x3d\xf3\x7c\xdf\xf3\x4f\x3d\x7f\xec\xf9\x4f\x3d\xff\x19\x08\xa9\xb8\x57\x37\x4b\x27\xa1\xf7\x61\x3e\xff\xe8\xd0\x49\xfd\x16\xa3\xc1\x6a\x5b\x0e\xb1\x6e\xeb\xe8\x81\x1b\xb1\x07\xc9\x1b\xed\x33\xbb\x1b\x2b\x05\xaa\xfd\x72\x8e\x6b\x45\xb9\x12\x49\x92\xb9\x50\x70\xa7\x1b\x79\x78\x6c\x53\x88\xd8\xa0\x70\x43\xef\xf0\xf5\x57\x91\x7e\x84\x45\xe3\x42\xb7\x20\xd9\x49\xb9\x47\x77\x0c\x9d\x66\xe5\xa2\x4a\x29\xa7\xd4\x3b\xf4\xc8\x23\x1e\x5b\x2a\x75\x83\xb1\x93\x42\xc8\x62\x94\x45\x53\x43\xed\x50\xa2\x2b\x11\x7d\x29\xb0\x12\x5a\x19\xec\x15\xc7\xeb\xd5\x2b\x4c\x56\xa0\x15\xbf\xab\xe3\xc0\x16\x4b\xc6\x7f\xbf\xe0\x79\x8d\x88\xb0\x17\x2f\x5e\x50\x95\xdf\xce\x23\x28\x57\x15\x34\xf5\x0d\x31\x6a\x59\x28\x28\x59\x70\x96\x31\xa8\xd2\x40\x09\xe5\x3a\x71\xea\x84\x3a\x8b\x3d\x32\x13\x9d\xf8\x1d\x2c\x52\x59\xd7\x1f\xb6\xaf\x4b\x20\x0a\x5c\xa4\x01\xde\xa2\x42\xe3\x02\xdf\x8b\xf0\xa8\xbd\x55\x35\x1e\x55\xe9\xab\x3c\x72\x27\x3b\xa3\x61\xc9\x4e\x88\x2b\x88\xb7\xc3\xb7\x8b\xe0\x3e\xfb\x09\xdf\x09\xc8\xeb\x54\xb0\xd5\xf0\x88\x3d\x90\x87\x76\x80\x7a\xd6\xaf\xa8\x57\x58\x82\x46\x8c\x05\x6f\x94\xb5\x05\x40\x52\xa5\x8f\xd1\xf2\x3d\x26\x8b\xf5\xe1\x74\x9e\x5d\x4b\xb4\x90\x32\xe3\x30\x05\xe7\x54\x42\xdf\xa7\xe5\xef\xa0\x2f\x33\x13\x7d\x43\x7c\xbf\x0c\x94\xd8\x68\xc6\xd0\x0c\xe1\xef\x59\x6c\x18\x02\x7e\x07\x09\x80\x27\x4d\xf9\xcf\x3f\xa1\x49\xc5\x9f\x98\x08\xc4\x1a\x84\x0c\x6b\x81\xe2\xf4\x32\x91\x6d\x9d\xe9\x47\x1a\x34\xfd\x6f\x12\x0e\xa7\x9f\x0f\xa9\x78\x3b\xc7\xa4\x67\xb9\xb6\x1d\x85\x10\xfa\x4e\xe7\x66\x62\x15\x2f\x55\x36\xf8\xed\x76\x94\x04\x77\x7b\x9e\x82\xc0\xd4\xb5\x9a\x3c\x16\x44\x61\xa7\x76\xaa\xea\x96\x4d\x41\x03\x1e\xbb\xd4\x63\x80\x4e\xc0\x98\x56\x58\xb6\x8b\x8e\x45\x7f\x46\x49\x6b\x46\x3d\xb6\xc0\x24\xeb\x54\x21\xd3\x1a\x52\x14\xe9\x0d\x1d\x91\x95\xee\x47\x85\x34\xb2\x7e\x50\x8e\xd7\x09\x64\x08\x71\x67\xc9\x1d\x5c\x40\xe8\xb4\x36\xdf\xbe\x41\x43\xf3\xbc\x8f\x9e\x2e\x01\xb3\xd0\xa8\x5e\xba\xed\x3c\x0d\x69\xdf\x4c\x4a\xcc\xf6\x79\xdf\xe6\x3e\x56\xcb\x28\x0d\xdc\x0f\xb7\xec\x01\xfb\xe1\xff\x77\x0f\x4b\xdd\xd7\x94\x48\xc6\x95\x36\xc6\xbe\x61\xf7\x01\x5c\xdd\x41\xcd\xf0\x17\x13\x76\xc4\xa5\x7a\x02\x36\xa3\x27\x67\x8e\x94\xdf\x4c\x61\x72\x13\x73\x26\x73\xa8\xee\x3c\x9f\x81\xe9\xef\x62\x36\x68\xb5\xd1\xa4\x45\xc9\xd3\xf2\x65\x9e\xf3\xb5\x69\x3c\x5a\x47\x10\xc9\x92\x9f\x7a\x46\xda\xd7\x64\x9d\x87\x88\xd1\x4e\x11\xb6\x4e\x66\x47\xaf\x9d\x41\x26\x30\x8a\xe5\xbd\x1e\x0d\xde\x96\xe1\x69\x28\x77\x79\x77\xb7\x45\xb3\xd0\x87\x85\xc6\x53\x53\x29\x9f\xc4\x57\x91\x17\x66\xc5\x94\x6c\x0a\x76\xf6\x1f\xf2\x35\xb9\xec\x9d\xa3\x2a\xd6\xe6\xb3\x53\x23\x9a\x27\x28\x67\x40\x4f\xbd\x43\x8b\xd2\xcf\xa8\x94\x69\x24\x9f\x04\xd4\x5c\xca\xa0\xb2\xbd\x92\x25\xb1\xfe\x15\x00\x00\xff\xff\x1c\x94\x83\x6f\x53\x3d\x00\x00") +var _resourcesListM = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xdc\x3b\x7f\x73\xd4\x38\xb2\xff\xe7\x53\xa8\xa0\x8a\x4a\xc0\x64\xe3\x49\x06\x16\x52\xec\x7b\x3c\x16\x6a\x79\x0f\x96\x05\xb2\x7f\xb9\xcc\x8c\xc6\xa3\x49\xfc\xf0\xd8\xb3\xfe\x41\x32\x4c\xcd\x77\xbf\xee\x96\x6c\x4b\x1e\xc9\x19\x87\xbd\xba\xab\xbb\x5b\x92\x58\xea\x6e\x75\xb7\x5a\xad\x56\xab\xf5\x2e\x2e\xca\xe7\xcf\xab\x82\x5f\x0a\xf6\x82\xdd\x9b\x6e\x84\xef\x31\x31\xf2\xd8\xf1\xf1\xf1\x76\xca\x2e\xf3\xac\x5a\x15\x4c\xdc\xac\x72\x51\x14\x71\x96\x16\xac\xcc\x2e\x45\x79\x25\xf2\xe3\x7b\xe7\x07\x2f\xcb\x32\x8f\x67\x55\x29\x8a\x00\x09\x85\x40\x62\xf3\x2e\x8b\xbe\x8a\xb9\xc7\xfe\xc8\xb3\x52\x44\xa5\x98\x6f\xcf\x0f\x2e\x44\x51\x16\x53\x04\x41\x88\x03\x06\xff\x7b\xfd\x39\x5e\xae\x12\xf1\xfa\x86\xe3\xaf\x22\xa0\x46\xd9\xc1\x97\x02\x11\x82\x0d\xb0\x02\x9c\xf0\xad\xc7\x10\x35\xf0\xbd\x91\xc7\xc3\x90\x20\xc3\x03\x20\x7b\x70\x91\x95\x3c\xd1\xd9\xa7\x86\x20\x41\x5e\xa6\xac\xa8\x96\x05\xe3\x49\xc2\x80\x5d\xf6\x8d\x27\x95\x28\x58\x9c\xb2\x29\x76\x4f\x91\x7d\x05\x3d\x99\x48\xe6\x9f\xbf\x60\x2f\x57\xab\x64\x1d\xfc\x91\x54\x85\xc7\x92\xd0\x10\x90\x80\x49\xc2\x5d\xc9\xa8\x6f\x88\x68\xfe\x89\xc7\xe4\xe8\x1b\x94\xea\xd4\x3b\xdb\xd6\x82\x79\xec\xf5\x9b\x2a\x47\x0d\x5b\x08\xbc\xca\x96\x4b\x91\x96\xc1\xbd\x0b\x10\xa9\xa4\x51\xb3\x05\xe3\x29\x13\xcb\x55\xb9\x66\x28\x19\x8b\x0b\xf6\x5d\xe4\xd9\xf3\x7b\xa1\x67\x19\xb9\x1d\x78\x6b\xa8\xf2\xbd\xe0\xa9\xae\x49\xfc\xae\x15\x19\xf1\x24\xaa\x12\x0e\x5a\x20\x55\x16\x25\x2f\xa1\x23\x86\x66\xb6\x04\x30\x64\xa1\x55\xaa\x44\xd4\x74\xaa\xb4\x1c\xfe\xf4\x4e\xa4\x97\xe5\x55\xd0\xd1\x2b\xc2\x3b\xd4\x8a\x5d\x83\xb4\xea\xff\x04\xf6\x42\x0c\x6c\xc6\xde\x13\x53\xc0\x0b\x3e\x4b\x84\x61\x2b\xd8\x10\xa0\x69\x7b\x2c\x05\x29\x73\x51\x56\x39\x18\x38\x97\x6a\xbc\x8e\xcb\x2b\x36\x4d\x41\xfa\x6c\x15\x83\xe4\x28\x24\x02\x4f\x8f\x0f\x0e\x0c\xdc\x4d\xb1\x5e\x02\x85\xad\x8b\x04\x21\x31\x81\x06\x08\x2a\x9c\xab\x56\x40\x9a\x02\x1b\x3e\xcc\x22\x8e\x62\x27\x7a\x77\xba\x53\xf8\xa9\x28\xc3\x9c\x1c\x3e\xfc\xb3\x10\x80\xfd\x67\x1a\xff\x55\x89\x5f\xc5\x22\x4e\xc5\x7c\xca\x60\x51\x2f\xe2\x1b\x8f\x65\x39\x13\x09\x00\x48\x06\x62\x8f\x8d\x43\xa0\x06\x0b\x47\x8e\xfb\xf0\x08\x08\xc4\x69\x94\xe5\x39\xcc\x0f\x34\x16\x55\x52\x16\xc7\xd0\x2c\x11\xf8\xc4\x63\xb3\xc9\xdb\xb4\x14\x97\x22\x97\x53\x2e\xdb\x41\x0c\x73\x44\x20\x0d\x6b\x7a\xb6\xed\xac\x2c\x84\x26\x13\xf8\x2d\x4b\xe6\x2f\x93\xc4\xe6\x3c\x08\x68\x90\xf7\x80\xe1\xdb\xff\xc0\x87\x34\x4c\x8d\x43\xeb\xca\x00\x93\x61\x4f\x3c\xf6\xd4\x63\x3f\x7b\xec\x19\x70\x7a\xd2\x20\x01\xdf\x1b\x54\x0b\x35\x1a\xd8\xcd\x82\x7c\x95\x0b\x98\x85\x7a\x86\xc0\x58\x70\xa5\x2c\xe2\x1c\x3e\xfc\x13\x56\xfc\x55\x71\xd0\x9b\x63\x4d\xa2\xa3\x3b\x93\x63\x02\x03\x23\x18\xe6\x14\x7e\x9f\xc1\xf7\x13\x68\xfe\xd9\xc7\x61\x5b\x66\xd2\x2f\x60\xe4\x9b\x94\x54\xe9\x64\xe7\x6d\x29\x72\x58\xa5\x59\xca\xe6\xa8\xfb\xb8\x24\xdf\x3d\xcf\x58\x9a\x95\xec\x8a\x7f\x83\x55\x1c\xcf\x05\x13\x8b\x05\xa8\xb9\xcb\x17\xcc\x4c\x7a\x49\x9c\xdd\x8b\xef\x79\x0c\x7e\x58\xd9\x1e\x01\x1f\x28\x2d\xb1\x85\x2d\x9f\xc1\x31\x88\x69\x0c\xb3\x34\x1a\xfd\x7d\x2a\xd6\xd9\x19\x8d\x14\x3f\x7b\xf8\xca\x76\xd4\x13\x0f\x9c\x6c\x33\xd2\x4d\xf0\xec\x19\x60\x6e\x6e\x82\x09\xfc\x02\x7f\x38\xd2\x7d\x2f\x59\x9b\xd5\xe3\x42\x07\xac\x98\x6c\x25\xf2\x7a\xd1\xa1\x7a\xd5\x4c\xc7\xa0\xef\x62\x25\xa2\x63\xbb\xaa\x7e\xaf\xd0\xaa\xc1\xd8\xcb\x14\xd7\xc7\xf8\xdc\x69\x07\xa0\xd3\x53\xb2\x86\x71\x57\x35\x84\xdd\x75\xda\xcb\x99\xc8\x3f\x9a\x7e\x9b\x9a\x94\x1b\x59\xf1\x52\x73\x1f\x17\x79\x05\x9c\xe2\x7e\xb1\xae\xf9\x16\x89\x40\xf1\xe4\xc6\x28\x3d\xca\x92\x97\x11\x38\x12\x40\x9d\x82\x6b\x40\xe5\x5e\xc7\xe0\x1c\x6a\x22\x6f\x38\xb8\x8a\xce\xe6\xaf\x06\x75\xba\x71\xea\x1d\xb2\x78\x69\x10\x74\xe5\x52\x98\x5a\x31\xa0\x92\x13\xfb\xe2\x45\xd1\xac\xf0\xbe\x1d\xde\x3d\xc0\xc6\x77\x2c\xa9\x5a\x8e\x29\xbb\xce\xf2\xaf\x85\xf4\xb7\xa0\x25\x98\xf9\xd4\xb5\xb2\x9d\x6c\x35\xee\x72\x20\xda\x50\x69\x26\x9f\x04\x44\x2d\xc3\x06\x41\x43\x23\x23\xb0\x33\xa9\x2d\xc7\x06\x12\x57\x65\xfb\xb1\x0f\x8f\xe8\x94\xf7\x12\x86\x77\xa4\x3e\x7c\xf8\x3e\xcb\x05\x31\x89\xc1\x28\x9b\x09\x56\x15\xb0\xfd\x81\x01\x7f\xc8\xe7\x22\x07\x8b\x2a\xde\x16\xef\x91\x91\x8f\xb0\x45\xdd\xae\x2c\x8e\x3b\x92\xc7\xa2\xbd\xb4\xa4\x80\xf9\xb0\x68\xcd\x6a\x3a\xff\x93\xf0\xf4\xeb\x67\x01\xdb\x63\x1a\x39\xb7\x06\xfb\xf0\x93\x89\xc3\x10\x5c\xe0\xfb\x99\x4d\x03\xde\x6b\x9c\x4e\xac\x41\x36\xdd\x62\x7d\x5e\x2f\x67\xd9\x7e\x36\xda\x20\x0d\xc4\x01\x37\xf0\x23\x68\x36\xb9\xda\xb9\x95\x5e\x33\x15\x60\x83\xb8\xb9\xce\x30\x08\xa0\x63\xd5\x3e\x33\x3a\xe3\x79\x20\x87\x8a\xc2\x7d\x57\x84\x89\x03\x5f\xc6\x9e\xf0\x8a\x17\x60\x4d\xda\x8e\x40\x0d\xd6\xfd\x80\x03\xd7\xd7\x8c\xce\x65\x53\x3a\x47\x40\xc8\x67\xd9\x10\xca\x2b\x5e\xea\xbb\x42\xc7\xf9\x13\x7d\x87\xeb\xa7\xbe\x41\x51\xdb\x58\xba\xa1\x63\xf8\x0d\x91\xe9\x1a\xb6\x42\x98\x02\x29\x82\xbd\xcf\x61\xdb\x00\x3c\xf2\x6e\xc5\xed\xb5\xd8\x0d\x40\xdf\x46\xc0\xed\x5e\x37\x23\x2f\x6a\xb1\x67\x10\xb4\xf9\x1e\xff\x02\x4d\x93\x2f\x62\xf2\xf8\x17\x31\xd0\x83\xd8\xac\x2c\x71\x5b\xd9\x86\x37\x63\xef\x98\x98\x66\x2c\xbf\xc2\x74\x97\x62\xc7\x64\xb4\xe6\x1e\xc3\x69\xb3\x02\xb7\x19\x8f\x8a\x3b\xdd\x36\xa4\x0d\xe8\xb0\x24\x0d\x62\x90\x3d\xe1\x84\xdd\x78\x6b\xd0\x86\x2e\x14\x59\x87\xea\x42\x2b\xb9\xc5\x10\x10\x5a\x41\xf6\x93\x71\x9b\xc3\xcd\xa3\xb5\x89\x0b\x68\x8f\xb0\x51\xe1\x68\x93\x02\x67\xa6\xcc\x38\x8b\x53\x03\x4d\x04\x26\x67\xe0\x97\xcc\xcf\x18\x13\x52\x64\x39\x1e\x02\xab\xd4\x0c\x4a\x97\x34\x17\x14\xe9\xb5\x39\x9c\x8e\xf2\x89\xbc\x43\xed\xd4\x37\xf0\xd8\x85\x2e\x5a\xb2\xbc\x99\x79\x1c\xfe\x0f\x3f\xb7\x0e\xcd\x62\xe7\xda\xfb\x6e\xc3\xf0\x36\xd8\x61\xc7\x5b\x64\x59\xa0\x50\xc3\x1a\x15\xdb\x1a\xec\xd0\xc3\x4f\xec\xee\x89\xed\x1b\x72\x56\x02\x72\x78\x07\xf5\x1e\xde\x36\x8d\x30\xf6\xfe\x5d\x41\x5b\x19\xcc\x56\xf7\xca\x56\xd0\x4e\xb5\xa2\x4b\x6f\xc1\xe8\xcb\xdc\x24\x32\x9c\x40\x5c\xab\xc6\x4e\xd1\xb4\xfe\xf3\x8c\xad\x1d\xc3\xb5\x65\x34\x00\x83\xcc\x0e\x8d\x4e\xe3\xbf\x0e\x15\xdc\x2a\x8a\x2c\x08\xe0\x22\x25\x0e\xfc\x98\xf5\x9d\x0a\x0d\x43\x0c\x0d\x42\x64\x9a\xd0\x24\x7f\xdb\x07\xd7\xc0\x4d\x64\xb7\x45\xe9\xac\x3a\x44\x32\x40\x1a\x06\x3a\xa8\xfd\x8c\x6d\x94\x0a\xfa\x14\x33\x71\x69\xd4\x8d\x0b\x1b\xe5\xdf\x87\x0e\x3f\x86\x91\x88\x88\xca\x8f\x92\x70\x51\xd1\x56\xd5\x27\x9e\x5e\x1a\x29\x46\x6a\x08\xcc\xe4\x62\x1b\x6e\xc5\x72\xcf\x29\xd8\x22\xcf\x96\x46\x26\x50\xe2\x2d\xbb\x79\x49\x17\xaa\x99\xec\xd3\x16\x1b\xd1\x91\x59\x79\xc0\xc4\x64\x82\x2d\xb5\x46\x50\x77\x48\xcc\xe3\x59\x51\x72\x7a\xea\x0c\x81\xb4\x64\x86\x04\x1d\xb9\xf3\x6f\x3a\xcc\xe3\xb1\xa1\xd9\x3f\x78\x6e\x78\x2a\xf4\x2f\x41\x10\x87\xa0\x9e\x2c\x67\x53\xec\x56\x81\x4a\xac\x69\x0c\x3d\xd1\x34\x9e\xc2\x59\x4b\x05\x26\x5a\x12\xd7\x54\x14\x12\x20\x3d\xfd\x8e\x29\xc8\x4f\xc0\x0e\xf0\x22\xf8\xbc\x51\x96\x4d\x6f\x88\xb4\x87\xda\x9a\x18\xee\x13\xb1\x25\x53\xe8\x22\xca\xd2\x39\xf9\x4c\x74\x99\xbd\xa1\xdc\x0c\x2d\xae\x5e\x08\xf3\x6d\x10\x8c\x42\xfb\x49\xe4\x7d\x95\x94\xf1\xe3\x79\x0c\x5f\xe8\x79\x79\x02\xa4\xe7\x31\x9c\x2d\x19\x87\x03\x73\x51\xad\x56\xe4\xb6\x5d\x11\x63\x37\x0b\x89\xf6\x3d\xa2\x4c\x9d\x0f\xff\x4e\x71\xe2\x30\x5d\xb7\x81\x19\xf5\xe1\x63\xf4\x14\xc0\xa1\xe3\x29\x01\x9e\x49\x2c\xcc\x5b\x62\xce\x52\xe6\x2b\x29\x66\x3e\x01\x30\xf8\xfd\xf3\x09\xa2\x8d\xb7\xd0\x0c\x61\x20\xab\x73\xc4\x2a\x29\xfb\x70\x46\x49\xcd\x19\x5a\x4a\x28\xe5\x1d\x3b\x56\x28\x12\x04\x0a\x41\x80\xc4\x1d\x9a\xc0\x6c\xf7\xf4\x65\x92\xd0\xb2\x28\x60\xf2\xa3\x12\xe2\xd3\x2c\xbd\x94\x9b\x53\x5a\xc6\xa0\x90\x46\x51\x2e\x85\x58\xb8\x6f\x87\x06\xea\xe1\xb0\x10\xfe\x43\x45\xf6\x37\xcb\xaa\x74\x0e\x1b\x65\x51\xe0\x7d\x14\xa5\xd9\x61\xaf\xfc\x86\xd6\x69\xee\x9c\x72\x6d\xd7\xa9\xc6\xf4\xd2\x1d\xe9\x93\x49\x80\x85\xe2\x2a\x20\xe7\x34\xb2\xab\x05\x2f\x8d\xe2\x74\x05\x7c\x98\xe7\x08\xe9\x57\x1c\xf4\x61\xbb\x50\xa4\xeb\x9d\xed\xc4\x4e\xfd\xc3\x32\x2e\x91\x4f\xbc\x8e\x02\xc3\x13\x37\xfa\x1d\x02\xc9\x96\xe5\xf1\x65\x8c\x76\xd9\x0a\xe9\x18\x34\x56\x43\xc6\x4e\xc7\x72\xe6\x3d\x41\x0b\x23\x57\xa4\xac\xf2\x4c\x99\xdc\x93\x2d\x68\x84\xae\x11\x46\x7b\x45\x7f\xb7\x0c\x46\x7d\xb5\x7a\x9d\x61\x2c\x44\x1b\x41\xe0\x1f\x8f\xb5\x89\x90\x11\x88\x6c\xeb\x41\xe2\x35\x8c\x89\xc7\x7b\x50\x6f\x9b\x93\xff\xa4\x45\x3d\x68\x3d\xba\xcf\x0a\xf5\xf9\x57\xff\x22\x2b\x71\x60\xf9\x40\xb5\x99\x13\xdf\xb9\x69\x71\x7d\xd9\x39\x72\xcd\xb7\xaf\xd0\x7d\x64\x24\x56\x89\x29\x2b\xe6\xe9\xce\x62\xc0\x41\x89\x27\xb7\x65\x48\x60\x05\x49\x1c\x5a\x9b\x1d\xd9\x11\x3a\x0e\xbb\x57\xe0\xa8\x6f\x52\x36\x78\xcb\x35\x3e\x41\x4b\x23\xc3\xea\x8a\x4a\x0a\x6f\xd7\xee\xff\xa5\xd9\x75\xfa\x86\xc7\x49\x95\xdb\x43\x12\x75\x7e\x0f\xb4\x19\xa3\xc1\x6d\x63\xcb\x2c\x60\x03\xca\x15\xa8\x16\x6e\x7c\x5e\x99\x97\xe1\x10\x3b\xc1\x56\x7f\x7e\x0e\x5b\xc7\x1c\xc3\x0b\xf4\x5e\x94\xe7\x68\x5c\x5d\x01\x18\xda\x66\x53\x15\xe8\x08\x91\x7c\x27\xd0\x40\xca\x8e\x83\x0f\x76\x0d\x3b\xf2\xd4\x51\xb9\x11\x1c\x20\x9b\xa7\x7d\xe1\x3d\xc2\x59\xb1\xf4\x2d\x8d\xd4\x00\x0d\xba\x16\x68\x43\xe5\x49\x92\x5d\x17\x4a\x4e\xdc\xa5\xe4\xbe\xca\xdb\xed\x94\x92\x3f\x28\x7a\x37\xc8\x42\xfa\x76\xd1\xa1\x67\x90\xe4\xff\xde\x5e\xed\x5f\x15\x86\xc8\x32\x87\xab\x1c\xe2\x56\xa3\xce\x81\x5a\x82\x45\xc0\x41\x6b\x5c\x95\xf6\x60\xe4\xcc\x57\xab\x04\x2b\x1b\x16\x2c\xfb\x26\x72\xe2\x89\xe7\x97\x15\x65\xf0\xe8\xe8\xcf\x21\x7c\x04\x66\x33\x08\x18\xf0\xca\x10\x63\xd4\xee\x71\x5e\x12\x77\x95\xc5\x50\x67\x3b\xb3\xce\x1d\x78\xb3\x08\x6e\xd0\x37\x07\x6b\xfa\xf9\x3d\x04\x09\x1b\xb6\x37\x32\xdd\x8a\xe9\x16\xbb\x82\x00\x19\x6c\x59\xe2\xd7\x7f\x7c\xc7\x3f\xac\x54\xb0\xc3\xb1\x51\xe8\x40\x78\xfe\xb7\xa3\x53\x66\xc0\xc5\x89\x31\x8c\x31\x7e\xd3\xf3\xf7\x90\x70\x09\xa1\xb4\x81\x89\xde\x5a\x21\xba\x4e\x70\xdb\x73\xa9\xa5\x75\x0a\x4e\xee\x96\xeb\x55\x56\x04\x8f\x7d\xa0\x27\xff\x3c\x6b\xfe\x1a\x6b\x74\x65\xcb\xe6\xb1\xaf\x0e\x7f\x4e\x85\xb7\xfb\x72\x6b\xa5\xaa\xc9\x29\x9e\x6f\x0a\xe0\x3b\x99\x3d\xa1\x12\x89\x51\x0b\xdd\xb4\xb8\xb6\xc4\x13\x59\x29\x82\xee\x85\x2b\x9f\xc2\xb7\x1a\xbe\x46\xd2\x95\x57\xe2\x0d\xb4\xe3\x32\x47\xf5\xb6\x22\x9b\x2e\x77\xb5\x82\x3d\xc6\xf0\xba\xd4\x42\xa5\x58\xb0\x28\xb5\xd3\xad\x2c\xb9\xaa\x8b\x81\x68\x39\x03\xa0\x98\x77\xbd\x2e\x35\xbb\x1c\x2f\x75\x0e\xcd\xef\xd2\xc5\x86\xe2\x4b\xe6\x7b\x1d\x97\xa7\x75\x9a\x16\x27\x58\xc1\xab\xa6\x10\x51\x76\xe4\xbe\xc8\x76\x25\xbf\xc8\x34\xd9\xa5\x8c\x05\xc9\x8b\x19\x0f\xa9\x02\xf0\x53\xc6\x99\x7f\x99\xcd\xe3\x45\x0c\x27\x9c\xb6\x2a\xcd\xa0\x35\x01\x62\x13\x2a\x54\x3a\x4c\x64\x4d\x62\x47\xc9\x47\x16\x0d\x5e\x64\x4d\x89\xd2\x1b\x2c\xeb\xb1\x65\x04\x6a\xc8\x3b\x29\x94\xb6\x40\x0a\xfe\xcf\x59\xcb\x2e\x2e\x85\x73\x96\x18\xc9\x10\x08\x40\x3a\x46\xa2\x9a\xf6\xb0\x92\x95\x84\xdc\x31\x13\x45\xc1\x61\x27\xaa\x77\x90\x5c\x91\x27\xaf\x02\x6a\xde\x6e\xb5\x14\x42\x08\x5b\x04\x87\xa9\xa8\x6e\xd3\x56\x9a\x46\x4d\x05\x4a\xd4\x3b\x58\x8b\x49\x6d\xd7\x5c\xba\xea\x3e\xb2\xa9\x72\x1f\x83\x69\x40\xef\xa4\x59\xdd\x62\x34\x96\x2d\x26\x23\x2f\x9e\x7e\xad\x60\xc3\x8f\xb0\x8e\x73\xf7\xb2\xaf\xed\xab\xab\x3e\x6d\x16\x84\xfa\x9a\x37\x90\x00\xb2\x84\xd0\xa1\x6b\x4a\x5d\x82\xbd\x37\x7a\x2d\xd8\xc0\xd8\x17\x1d\xf4\x0e\xeb\x74\x7f\x32\xeb\xb9\x34\xa2\xcb\x9b\x5d\xbc\xfa\x76\xc7\xb9\xab\x5a\x07\x73\x8c\x03\x11\x25\x1e\x68\x54\xb9\xeb\x0e\x9a\xcc\x71\x12\x50\x68\xc6\x6e\xef\xb8\x59\x8c\x8d\xdf\x94\xd6\xec\xe4\x34\x13\x8e\xa5\x68\x78\x24\x31\xf2\x99\x12\x7c\xf2\x5f\x87\x87\x6a\xe8\xfb\xe1\x2f\x2f\xfc\xa3\x07\x47\x64\xbb\x22\x08\x54\xb3\x80\x51\xcd\xda\x6d\x5e\xb8\x6e\x63\xb0\x6b\xc8\xc4\x40\x50\x4d\x6c\xc0\x16\x2a\x2b\x70\x1d\x19\x4d\x02\xe2\x8f\x66\xfb\xe4\x67\x24\x6c\x58\x23\xd9\x69\xca\x51\xb7\x35\x94\x6b\x6e\x78\xdd\xcf\xcd\xd4\x3d\xad\x50\x5d\xf7\xd4\x60\x53\xbe\xac\xe9\xdc\xd5\xbe\x42\xe8\x51\xbf\xdf\x51\x3b\x61\x38\xf4\x4e\x7d\x83\x6a\x9f\x3d\x26\x39\xe8\xd5\x3c\xaf\xa1\xf6\x54\xbd\x02\x0e\x1b\x34\x47\x81\x8a\x1c\x79\xdb\xc0\xf5\xa8\x5f\x01\x74\xf4\x8f\x29\x77\xe3\xe6\x44\xec\x6a\x1f\x2b\x0c\x40\x73\xbd\xb3\x20\xf1\x7a\x26\x61\x74\x7e\x4e\x67\x26\xf3\x9e\x44\x38\x27\x02\xbb\x06\x16\xb0\x60\x62\xf2\x93\xb8\x75\x11\x3c\x8a\x14\x18\xcc\xc5\xa3\x68\x9f\xd9\x90\xd0\x61\x8d\x66\xa7\x2b\x47\xde\xd6\x50\xce\x8b\xae\x86\xc9\xce\x4c\x7c\xa6\x73\xaa\x3e\x17\xb2\x45\xdd\xaf\xe0\xbd\x05\xbe\xad\xa0\xb6\x82\x65\x69\xb2\xa6\x69\xd0\x0a\xe4\x65\xcd\x47\x81\x8f\x04\x16\x6b\x36\x45\x8c\x6e\x2a\x40\x92\x74\x25\x42\xe4\x49\x79\xd8\x85\xd4\x29\xa8\xfa\xa9\xf7\xcc\xf3\x7d\xcf\x3f\xf5\xfc\xb1\xe7\x3f\xf5\xfc\x67\x20\xa4\xe2\x5e\xdd\x2c\x9d\x84\xde\x87\xf9\xfc\xa3\x43\x27\xf5\x5b\x8c\x06\xab\x6d\x39\xc4\xba\xad\xa3\x07\x6e\xc4\x1e\x24\x6f\xb4\xcf\xec\x6e\xac\x14\xa8\xf6\xcb\x39\xae\x15\xe5\x4a\x24\x49\xe6\x42\xc1\x9d\x6e\xe4\xe1\xb1\x4d\x21\x62\x83\xc2\x0d\xbd\xc3\xd7\xdf\x44\xfa\x11\x16\x8d\x0b\xdd\x82\x64\x27\xe5\x1e\xdd\x31\x74\x9a\x95\x8b\x2a\xa5\x9c\x52\xef\xd0\x23\x8f\x78\x6c\xa9\xd4\x0d\xc6\x4e\x0a\x21\x8b\x51\x16\x4d\x0d\xb5\x43\x89\xae\x44\xf4\xb5\xc0\x4a\x68\x65\xb0\x57\x1c\xaf\x57\xaf\x30\x59\x81\x56\xfc\xae\x8e\x03\x5b\x2c\x19\xff\xfd\x86\xe7\x35\x22\xc2\x5e\xbc\x78\x41\x55\x7e\x3b\x8f\xa0\x5c\x55\xd0\xd4\x37\xc4\xa8\x65\xa1\xa0\x64\xc1\x59\xc6\xa0\x4a\x03\x25\x94\xeb\xc4\xa9\x13\xea\x2c\xf6\xc8\x4c\x74\xe2\x77\xb0\x48\x65\x5d\x7f\xd8\xbe\x2e\x81\x28\x70\x91\x06\x78\x8b\x0a\x8d\x0b\x7c\x2f\xc2\xa3\xf6\x56\xd5\x78\x54\xa5\xaf\xf2\xc8\x9d\xec\x8c\x86\x25\x3b\x21\xae\x20\xde\x0e\xdf\x2e\x82\xfb\xec\x17\x7c\x27\x20\xaf\x53\xc1\x56\xc3\x23\xf6\x40\x1e\xda\x01\xea\x59\xbf\xa2\x5e\x61\x09\x1a\x31\x16\xbc\x51\xd6\x16\x00\x49\x95\x3e\x46\xcb\xf7\x98\x2c\xd6\x87\xd3\x79\x76\x2d\xd1\x42\xca\x8c\xc3\x14\x9c\x53\x09\x7d\x9f\x96\x7f\x80\xbe\xcc\x4c\xf4\x0d\xf1\xe3\x32\x50\x62\xa3\x19\x43\x33\x84\xff\xcd\x62\xc3\x10\xf0\x3b\x48\x00\x3c\x69\xca\x7f\xfe\x1f\x9a\x54\xfc\x89\x89\x40\xac\x41\xc8\xb0\x16\x28\x4e\x2f\x13\xd9\xd6\x99\x7e\xa4\x41\xd3\xff\x26\xe1\x70\xfa\xf9\x90\x8a\xb7\x73\x4c\x7a\x96\x6b\xdb\x51\x08\xa1\xef\x74\x6e\x26\x56\xf1\x52\x65\x83\xdf\x6e\x47\x49\x70\xb7\xe7\x29\x08\x4c\x5d\xab\xc9\x63\x41\x14\x76\x6a\xa7\xaa\x6e\xd9\x14\x34\xe0\xb1\x4b\x3d\x06\xe8\x04\x8c\x69\x85\x65\xbb\xe8\x58\xf4\x67\x94\xb4\x66\xd4\x63\x0b\x4c\xb2\x4e\x15\x32\xad\x21\x45\x71\xd2\x90\x94\xee\xa7\x3b\x90\x7c\xac\xd0\x29\xaf\xaa\x7a\x2a\xab\xaa\x61\x45\x55\xa7\x9e\x1a\x92\x22\x94\x2f\x23\xcf\x51\x6b\x3b\xde\x81\xf3\x1e\x3b\xee\xc2\x2c\xa0\x6f\x53\x7a\xa0\xb4\xb6\x23\x9c\x34\x08\xc3\x40\x5d\x0c\x8c\x1a\x20\xf6\x88\x8d\xe0\x1f\x32\xd1\x14\x02\x7b\xac\x3b\x44\xfd\x78\x30\x49\xd6\xe6\xe3\x41\x68\x68\xde\x47\xd2\xdb\x2f\x98\x6d\x68\x54\x4f\x05\x77\xde\xd6\xb4\x8f\x4e\x25\x66\xfb\x3e\x72\x73\xdf\x6b\x67\xf6\x7e\xb8\x65\x0f\xd8\x4f\xff\xbd\x7b\xda\xec\x3e\x47\x45\x32\xae\xbc\x3b\xf6\x0d\xbb\x50\xe1\xea\x12\x6f\x86\xbf\x31\xe3\x49\x5c\xaa\x37\x74\x33\x7a\xb3\xe7\xc8\x99\xce\x14\x26\x37\x31\x67\x32\x09\xed\x4e\x94\x1a\x98\xfe\x2e\xe6\xd6\x9c\x81\x57\xb0\x68\x4a\x9e\x96\x2f\xf3\x9c\xaf\xcd\xd5\xa7\x75\x04\x91\xac\x99\xaa\x67\xa4\x7d\x8e\xd7\x79\xc9\x19\xed\x54\xb1\xeb\x64\x76\xf4\xda\x19\x04\x16\x66\x6a\x79\xf0\x48\x83\xb7\xab\x4d\x43\xb9\xcb\xc3\xc5\x2d\x9a\x85\x3e\x2c\x34\x9e\x9a\x4a\xf9\x24\xbe\x89\xbc\x30\x4b\xce\x64\x53\xb0\xb3\x81\x93\xb3\xce\x65\xef\x1c\x55\xb1\x36\xdf\xed\x1a\xc7\x21\x82\x72\x9e\x88\xa8\x77\x68\x55\xff\x19\xd5\x82\x8d\xe4\x9b\x8a\x9a\x4b\x19\x95\xb7\x77\xda\x24\xd6\x3f\x02\x00\x00\xff\xff\x09\x68\x9c\xfd\x94\x3e\x00\x00") func resourcesListMBytes() ([]byte, error) { return bindataRead( @@ -339,7 +339,7 @@ func resourcesListM() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "resources/list.m", size: 15699, mode: os.FileMode(420), modTime: time.Unix(1514960645, 0)} + info := bindataFileInfo{name: "resources/list.m", size: 16020, mode: os.FileMode(420), modTime: time.Unix(1515219056, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -359,7 +359,7 @@ func resourcesManipM() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "resources/manip.m", size: 9498, mode: os.FileMode(420), modTime: time.Unix(1514078804, 0)} + info := bindataFileInfo{name: "resources/manip.m", size: 9498, mode: os.FileMode(420), modTime: time.Unix(1515220323, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -1124,7 +1124,7 @@ func resourcesSimplifyM() (*asset, error) { return a, nil } -var _resourcesSolveM = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xa4\x94\x4f\x6f\x9b\x40\x10\xc5\xef\xf9\x14\xa3\x1c\x22\xc0\xbb\x21\x8a\x7a\xb2\x45\x24\xb7\x4a\xaf\x4d\xe5\xdc\xd0\x16\xf6\xcf\x38\x41\x32\x76\xb2\xe0\x74\x2d\xc4\x77\xef\xb2\x40\x6d\xc7\xb8\x21\xaa\x2f\xac\xdf\xcc\x1b\xff\x56\x9e\xc7\x62\xb3\x7a\xc3\xe9\x74\x5b\xf0\x27\x84\x08\x2e\x53\x27\xc4\xf8\xba\x26\xf0\xc6\x35\x4b\xa1\x68\x84\x02\x52\x2b\xa5\xb0\xdc\x68\x48\xad\x9e\x5e\x5f\xce\x2e\xda\x56\x93\x40\x14\x01\x9a\x17\x9d\x10\x30\x09\x83\x69\x04\x55\x65\x80\xde\x39\xb1\xae\x0f\x1a\x03\x27\x7d\x4d\xfe\x5a\xe6\x83\x9e\x39\x84\xf0\x98\xe5\x58\xc4\xae\x9d\x9d\x99\x31\x71\xa7\x6f\xff\x18\xe6\x39\x99\xba\x36\xff\xec\x50\x9e\x5c\x07\x26\xf9\x75\x6b\x07\x0a\x77\xb4\x07\xe9\xa6\xaa\xd3\x89\x54\x00\x85\xc5\xab\x2e\x63\x61\x1d\x14\xbe\x00\x07\x69\x0d\xcd\x53\x31\x3f\xf4\x6e\x81\xfb\x35\x81\x7d\xfb\xe4\xe3\x76\x8b\xe2\x05\x3f\xb4\x42\xbd\xc2\xa2\x80\x9c\x97\xf2\x39\x5b\x3f\xc1\xef\xcd\x76\xa5\x40\x20\xac\x33\x89\xf0\x8c\x1a\x03\xbf\x83\xae\x5a\xea\xc5\x2e\x17\x9b\xd5\xa4\xe1\xde\x75\x5f\xa2\x48\x26\x44\x1d\x56\xf1\xa8\xba\x4c\x6a\x52\xf5\x35\xd2\xeb\x75\x7f\x4b\x7a\x47\x3d\x4f\x02\x5a\xf2\xa5\xe5\x13\xa0\x28\x07\xf4\x7d\xb2\x73\x15\x2a\x41\x4d\xf8\x71\xa9\xae\x21\x9c\x7d\xd7\x88\x3f\x2d\x16\x11\x44\x12\x45\x90\x2c\x6b\x62\xd8\xd5\xd5\x90\xbe\x63\x9f\xbf\xc5\x08\xf0\x65\xa8\x06\x29\x1b\xc2\x13\xc0\x61\xbc\x16\x6e\x5e\x96\x3a\x13\xdb\xd2\x2e\x8b\xe3\x64\x36\x1a\xd5\x83\xde\x94\x28\x4b\x54\xf6\xdf\x7a\xc4\xa2\x2c\xda\xac\x34\xa5\x0b\xb0\x9f\xfb\x45\x96\xbf\xac\xf0\xde\xf0\xe6\x51\xc4\x4e\x6c\x0b\x3c\xc7\xc6\x11\x77\x4b\x74\x53\xdb\x05\xe9\x16\xba\x59\xb3\x1b\xbb\x65\x8c\x91\xf3\x06\xf1\xce\x20\x3e\x32\xf0\x23\x4b\xc8\x47\x99\x44\xc8\x0f\x4c\xc1\x38\x13\xf5\x44\x98\xfb\x7b\x5f\x1e\x98\x26\x47\xa3\xae\xd5\xa6\x43\xfa\x61\x3e\xe8\x97\xef\xfc\x5e\x30\x38\xe1\x34\x8e\x23\x63\xb8\x8f\x5f\xff\xe3\x3c\x30\xed\x6b\xc0\x41\xc8\x83\x4b\xd8\xdc\x7d\x1a\xe3\xbf\xdf\x0a\x04\x1e\x74\xb6\x2e\xe3\x7e\x39\x0d\x9b\x9d\xe5\x54\x8e\xb3\xc3\x64\x17\x76\x47\xff\x04\x00\x00\xff\xff\xee\xb0\x02\x30\xdb\x05\x00\x00") +var _resourcesSolveM = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xd4\x56\x5d\x73\xe2\xb8\x12\x7d\xe7\x57\xf4\x64\xee\xcd\x05\x62\x63\x48\x32\x5f\x64\x98\x1a\x26\x93\xd4\xe4\x6e\x76\x61\x43\x6a\x5f\x28\x0f\x91\xed\x76\x50\xad\xb0\x19\xd9\x4e\xa0\x28\xfe\xfb\xb6\x24\xdb\x01\x02\x13\xe6\x71\xf3\x10\x40\xd2\x69\x9d\x6e\x9d\x3e\xd2\x20\x16\x0f\xd8\x6e\x67\x09\xbb\x47\xe8\xc0\xc1\x9d\x1e\x18\xe2\x8f\xc8\x82\x07\x26\xdd\x3b\x48\xd4\x40\x02\x77\x34\x74\x07\x61\x2c\xe1\x8e\xc6\xef\x1a\x07\x67\x95\x8a\x1f\x67\x51\xfa\x17\x93\x43\x9c\x4d\xe5\x48\x03\x46\x83\xf9\xc4\x8b\x85\x0b\xed\x0e\x54\x00\xae\x42\x3d\x07\x9d\x4e\x47\xcd\x5a\xd0\xb2\xe0\x5c\xa1\xf4\xb0\x65\xc6\xec\x96\xeb\xea\x68\x51\xca\x78\x94\xf4\x22\xec\xf9\x7e\x26\x25\x46\xbe\x66\x32\xba\xf8\x91\x31\xb1\x2d\x7c\x1e\x2a\x27\xab\x23\xd1\x56\xd0\xa2\x68\xd5\x3a\xdc\x60\x9a\xc9\x08\x18\x84\x59\xe4\xa7\x3c\x8e\x20\x1d\xb3\x14\x7c\x16\xc1\x18\xc5\x14\x38\xa5\xc6\x52\x54\x50\x08\x65\x3c\x01\xc5\xa9\x0d\xf5\x5a\xa5\xc2\xa6\x53\x31\xbf\x8a\x1e\x50\x26\x38\x14\xe3\x64\xd4\x17\x59\x02\xf6\x27\x90\xf4\xfd\x19\x93\xdf\xe3\x20\x13\x38\x5c\x44\x71\x44\xd5\xe8\x33\x99\x26\x4b\x8b\xe8\xc1\xca\x00\x15\x77\x80\x02\xfd\x54\x85\xb3\xa0\x5a\xd6\xee\xb5\x29\xb4\x2e\x51\xb3\x06\x87\x54\x0a\x42\x3e\x14\x30\xfa\x7b\x11\xf9\x6a\x15\xb9\x28\xa1\x86\x2e\xd8\xab\x34\x96\xb4\xe8\x59\x72\xb7\x7c\x82\xff\xd2\xec\x9c\x8d\xdc\xe8\xd8\x6f\x7b\x5f\x7b\x6d\x60\x41\x00\x49\x36\x9d\xc6\x32\xd5\xaa\x95\x5a\x0c\x3c\xba\x87\x49\x26\x52\x3e\x15\x08\x48\xb2\x52\xb2\x48\x1a\xea\xcc\xd7\xaa\xd2\x72\x54\x5d\x76\x96\x64\x21\xc6\x9a\x40\xcb\xa1\xe9\xe5\x96\x8a\x7e\x3f\xde\x85\xd5\x49\xe4\x70\x7b\xf0\x43\xa6\x43\x5a\xe5\x5a\x90\x0f\x95\x23\x9b\x51\xaf\xe3\x7b\x1d\xd9\x7d\x91\xd4\x79\x1c\x05\x5c\xe5\xc5\xc4\x05\x09\x1a\x93\x84\xbe\x0f\x2f\xbe\x4b\x55\x5f\xbb\xcf\xe1\x23\x5c\x4d\xf4\x1e\xf0\xb1\x03\x7d\xfe\x6c\x2b\x9d\xc0\x0d\x33\x21\x86\xd4\xb1\xd1\x1e\xbb\xd2\xe4\xf7\x68\x69\x1a\xef\x0b\x4b\x90\xda\x2c\x41\xd3\x4c\x79\x9f\x0d\x9f\x90\x1a\x80\x49\xba\x25\x9c\x6a\xc6\x7c\x96\xa2\x15\xd0\x9f\x9e\x46\x21\x50\x6e\xf8\x77\x29\x17\x8e\x81\xd1\x28\xb1\x19\x3c\xf2\xd4\x1f\x43\xc2\x03\x12\x39\x0f\x21\x42\x0c\x30\x80\x34\x86\x7b\x4c\x75\xf3\x93\x33\x5c\x7f\x1b\x18\xb2\xa0\x4d\xeb\x49\x86\xba\x6a\xa5\x84\x5b\x24\xc4\xc3\x15\x91\x8a\xb5\xd9\x66\xcd\x52\xae\x04\xb9\xf3\x0c\x0b\xf6\xd2\x94\xa8\x5c\xac\xed\xce\x90\xeb\x26\x09\xca\x9c\x85\x32\xbd\x84\xc8\x88\x39\xfd\xf3\x11\xb8\x32\x2c\xdc\xa4\xf6\xaa\xba\x6b\xfb\x4d\x72\x72\x83\x5c\xcd\x5a\x25\xf7\x9f\x4b\xc6\x05\x06\x05\x97\xf5\xe2\x51\x57\x6e\x4a\x22\x2f\xbf\x89\x78\x96\x93\xf9\x86\x2c\x18\xae\x43\x4d\xc7\x5e\xf3\x24\xcd\x8b\xd1\x97\x9c\x4c\xfa\x40\x5f\x2c\x80\x52\xc6\xe4\xb1\x97\x9c\x34\x4a\xbd\x98\x43\x21\xd4\x5c\x74\xa3\x1e\x94\xbd\xa0\x77\xd3\x21\xd4\x20\x6d\xdb\xce\x3f\xdd\xb3\x22\x09\x1d\x74\x3d\x11\x26\xc4\x95\xa9\xbb\xca\xa2\x38\x82\xdc\x4d\x0e\xc1\xf9\xbc\x91\xaa\x4e\xe5\xff\x31\xa7\x60\x64\x08\xea\xce\x81\xcf\x9f\x57\xa3\xb8\x6a\x81\x6b\x94\x7d\x19\x0b\x11\x3f\x6a\x17\xc1\x74\x1c\x07\x40\x9a\xf2\x25\xf7\x68\x2f\x1e\xe9\x53\xaa\xd6\x07\x29\x4a\x41\x4b\x2c\xb8\xb6\xe0\x4b\x16\x05\x73\x0b\xba\xf4\x6d\x2e\x03\x3d\xd4\xfb\xdf\x6f\x88\x21\x5a\x70\x03\x87\x30\xe0\x94\x00\xdd\x5c\x5f\xa0\xf5\xe1\xfd\xb1\x05\x2a\x21\x15\xde\xc8\x9b\xfb\x70\x51\x98\x14\x90\x8c\xc7\xd0\xbf\xb9\x18\x0c\x1a\xb4\x99\xde\xea\x3c\x9e\x4c\x33\xda\x0e\xba\xe2\x1e\x3d\xc9\xc8\xeb\xaf\xc9\x4a\x33\x89\xf0\x47\x9c\x2a\xb9\x47\x50\xae\x19\xf8\x5c\x65\xd7\x80\x87\x58\x34\xe0\x5d\x03\xbe\xf6\xae\xda\xd0\x6a\x36\x5a\xcd\xe6\x3b\xe7\xc4\x7e\x73\xda\xb4\x5b\xad\xb7\xcd\x77\xf6\x87\x51\xeb\x44\xc7\x87\xee\x03\xd5\x96\x79\x64\x96\x2c\x6d\xc3\x38\x4d\xa7\x6d\xc7\x79\x7c\x7c\x6c\x50\x7f\x22\x93\xfe\xb8\x81\x41\x83\xf9\x8d\xec\x6f\x47\x39\x2d\x13\x4e\x48\x67\x91\x38\xa7\xad\x93\xd3\xf7\x6f\x9d\x3c\x9b\x51\x91\xcd\xa8\xcc\x66\xf4\xdf\xe3\xa6\x4a\x68\x64\x12\x9a\x06\xa1\x2a\x5e\xf9\xf8\xd8\x71\xe5\x97\x9d\x9e\x1f\x8d\xe9\x71\xd2\xe1\xce\xb7\x83\x39\x76\x23\x7c\xfe\x5c\x16\x37\x14\x4e\x1d\x77\xb9\x52\xab\x41\x45\xec\x0a\x71\x2b\x33\x2c\x7a\x98\x8e\xae\xaa\xc5\xfe\x5a\xbf\x30\x14\xae\x76\x48\xb6\x9d\xeb\x70\xf1\x7a\x69\xa4\x55\x68\x26\x0f\x94\x6b\xdf\x0c\xab\x17\xc8\x54\xc6\x3e\x06\xea\x80\x8c\xe4\x0f\xf2\x85\xeb\x8e\x51\xe0\xd7\x5a\x27\xa4\xbe\x0e\xe8\xd2\x55\x2f\xb2\x4c\x17\x31\x07\x2f\x96\x2b\x0a\x1d\x4c\xd1\xe7\x4c\x68\xfb\x4d\x74\x43\x99\x27\x9e\x76\x10\x9a\x3f\xd7\xc5\x49\xc9\x63\x72\x1f\x54\x4b\xba\x53\xba\x3f\x73\xf9\xf6\x64\x40\xfa\xa5\x5b\x03\x26\x8c\x7c\x53\x89\xf1\x31\xce\x44\x00\x1e\x42\xc4\xa9\x3b\xc6\x28\xb1\x3c\xab\x05\x1b\x35\xea\xb3\xfc\x8c\x8e\x3c\xfa\x31\xcf\x7f\x74\x3a\xfe\xc8\x0a\x56\x67\x71\x6d\x36\x1c\x2d\xad\x45\x31\x67\x15\xe3\x4b\x73\x0b\x2c\x66\xf6\x27\x9b\x8c\x0e\xd0\xf6\x20\xac\x39\x55\x0f\x02\x9b\x01\x92\x87\xcd\xf5\x8c\xed\x43\x70\xc4\xd6\xa7\x96\x4b\x70\xce\x2e\x25\xe2\x9f\x44\xcb\xf2\x2c\xdf\x0a\x2c\xb4\xc2\xa5\x35\x73\x0f\x0f\xb7\x8d\xcf\xdd\x5f\xcf\x62\x0f\xe2\xa1\x13\x6c\x65\xa9\x18\x3e\x23\xb8\x9d\x9e\x21\x57\xe9\xa6\x29\x99\x0b\x75\x6f\x62\x9c\x8e\xb4\x07\x8b\xbe\xa4\xd6\xf6\x95\xfa\xcf\x2a\xb7\x74\x4d\x26\xe6\xcd\xae\xa6\xb4\x94\x2e\x06\x7c\x42\xcf\x9b\x8b\x19\x53\x1f\xc9\xd0\x38\xa8\x9e\x60\x13\x54\x88\x21\xd1\x54\x06\xdb\x5c\x2e\x8d\xe3\xe0\x70\xa6\x54\xdd\xb4\x60\xe6\xe6\xcd\xb2\x15\xe0\x6d\x00\xbc\x97\x00\x6c\x0d\xe2\xb0\xbd\x40\x9e\xc3\x56\x40\xf5\xfd\x40\x76\xd5\x73\x26\xb5\x27\xdc\xa4\x3e\x83\x23\xf0\xf6\x4a\xab\x4a\x22\x3b\x02\xbf\xe6\x4c\xb6\xe2\xfd\x17\xf7\xd6\xaf\x36\xe6\x12\xd8\x0c\x14\xbf\x9f\xb2\xa0\x07\x21\x45\x62\x3f\x89\xc4\xf4\x83\xb2\xf1\xe6\x09\xc4\x88\x00\x0d\x28\xe0\x89\x05\x6c\x0f\x0a\xf6\x09\x41\xe6\x1b\x3c\x8a\xc1\x32\xee\x5c\x45\x54\x8c\x8e\x54\xdc\x35\x42\xd5\xfa\xd6\xe2\xd8\x26\x92\xa7\x9e\xb5\x70\x4a\xa7\xea\xbb\x24\xe9\x63\x60\xb5\x72\x2b\x53\xc3\x9d\xcb\x9e\x92\xaa\x9b\x9d\x3d\x5d\x5f\x7f\xe5\x7c\xc8\x53\x7e\x99\x06\x85\x50\x9f\xc1\x9e\x74\x9e\x2d\xa7\xf5\xc6\x63\x8b\xc6\x9b\xb9\x67\x3b\x79\x06\x9a\x67\x4e\xd3\xad\x50\xfb\xfd\x13\x00\x00\xff\xff\x00\x71\x12\xa6\x3e\x0f\x00\x00") func resourcesSolveMBytes() ([]byte, error) { return bindataRead( @@ -1139,7 +1139,7 @@ func resourcesSolveM() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "resources/solve.m", size: 1499, mode: os.FileMode(420), modTime: time.Unix(1506497089, 0)} + info := bindataFileInfo{name: "resources/solve.m", size: 3902, mode: os.FileMode(420), modTime: time.Unix(1515220308, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/expreduce/resources/list.m b/expreduce/resources/list.m index f9bdaf5..775915d 100644 --- a/expreduce/resources/list.m +++ b/expreduce/resources/list.m @@ -382,8 +382,18 @@ }; Count::usage = "`Count[l, pattern]` returns the number of expressions in `l` matching `pattern`."; -Count[l_List, pat_] := Length[Cases[l, pat]]; +Count[l_, pattern_] := Count[l, pattern, {1}]; Attributes[Count] = {Protected}; +Tests`Count = { + ESimpleExamples[ + ESameTest[3, Count[a+b+c^2,_]], + ESameTest[5, Count[a+b+c^2,_,-1]], + ESameTest[5, Count[a+b+c^2,_,Infinity]], + ESameTest[0, Count[a,_,Infinity]], + ESameTest[0, Count[a,_,-1]], + ESameTest[2, Count[a + 2 + c^2, _Integer, Infinity]], + ] +}; Tally::usage = "`Tally[list]` creates tallies of the elements in `list`."; Tally[l_List] := {#, Count[l, #]} & /@ DeleteDuplicates[l]; diff --git a/expreduce/resources/solve.m b/expreduce/resources/solve.m index 6eec3c2..6e5c4ec 100644 --- a/expreduce/resources/solve.m +++ b/expreduce/resources/solve.m @@ -1,11 +1,72 @@ Solve::usage = "`Solve[eqn, var]` solves `eqn` for `var`."; -Solve[x_ == expr_, x_] := {{x -> expr}}; -Solve[x_ * exprB__ == exprA_, x_] := {{x -> exprA / Times[exprB]}}; -Solve[x_ * exprB__ + exprC_ == exprA_, x_] := {{x -> (exprA-exprC) / Times[exprB]}}; -Solve[a_.*x_^2 + b_.*x_ + c_ == d_, x_] := {{x -> (-b - Sqrt[b^2 - 4 a c + 4 a d])/(2 a)}, {x -> (-b + Sqrt[b^2 - 4 a c + 4 a d])/(2 a)}}; + +countVar[expr_, var_Symbol] := + If[expr === var, 1, Count[expr, var, -1]]; + +containsOneOccurrence[eqn_Equal, var_Symbol] := + Count[eqn, var, -1] == 1; + +(* Return a function that can help isolate var from expr: *) + +applyInverse[lhs_Plus -> rhs_, var_Symbol] := Module[{nonVarParts}, + nonVarParts = Select[lhs, (countVar[#, var] === 0) &]; + varParts = Select[lhs, (countVar[#, var] =!= 0) &]; + {varParts -> rhs - nonVarParts}]; +applyInverse[lhs_Times -> rhs_, var_Symbol] := Module[{nonVarParts}, + nonVarParts = Select[lhs, (countVar[#, var] === 0) &]; + varParts = Select[lhs, (countVar[#, var] =!= 0) &]; + {varParts -> rhs/nonVarParts}]; +(* TODO: add support for returning multiple equations. *) +applyInverse[1/lhs_ -> rhs_, var_Symbol] := {lhs -> 1/rhs}; +applyInverse[lhs_^2 -> rhs_, var_Symbol] := + {lhs -> -Sqrt[rhs], lhs -> Sqrt[rhs]}; +applyInverse[Log[lhs_] -> rhs_, var_Symbol] := {lhs -> ConditionalExpression[E^rhs, -Pi < Im[rhs] <= Pi]}; +applyInverse[lhs_^Rational[1, n_] -> rhs_, var_Symbol] := {lhs -> rhs^n}; + +(* Base case: *) + +isolate[var_Symbol -> rest_, var_Symbol] := {var -> rest}; +isolate[lhs_ -> rhs_, var_Symbol] := Module[{inverseApplied}, + (* Switch sides if needed to get var on LHS: *) + + If[(countVar[rhs, var] === 1) && (countVar[lhs, var] === 0), + Return[isolate[rhs -> lhs, var]]]; + + (* Assert var occurs only once in the LHS: *) + + If[!((countVar[lhs, var] === 1) && (countVar[rhs, var] === 0)), + Return[$Failed]]; + + inverseApplied = applyInverse[lhs -> rhs, var]; + If[Head[inverseApplied] =!= List, + Print["Solve error: Finding inverse failed for ", lhs -> rhs, + ", var: ", var]; Return[SolveFailed]]; + + allIsolated = isolate[#, var]& /@ inverseApplied; + Join[Sequence @@ allIsolated] + ]; + +(* Following method described in: *) +(*Sterling, L, Bundy, A, Byrd, L, O'Keefe, R & Silver, B 1982, Solving Symbolic Equations with PRESS. in*) +(*Computer Algebra - Lecture Notes in Computer Science. vol. 7. DOI: 10.1007/3-540-11607-9_13*) +(* Available at: http://www.research.ed.ac.uk/portal/files/413486/Solving_Symbolic_Equations_%20with_PRESS.pdf *) +Solve[eqn_Equal, var_Symbol] := Module[{isolated}, + If[containsOneOccurrence[eqn, var], + isolated = isolate[Rule @@ eqn, var]; + If[AllTrue[isolated, (Head[#] == Rule)&], Return[{#}& /@ isolated]]; + Print["isolation procedure failed"]; + Return[isolated]]; + Print["Solve found no solutions"]; + {} + ]; + +(* Special cases for Solve: *) + +(* Currently needed for Apart: *) (*Orderless matching would be nice here*) Solve[{a_.*x_Symbol+b_.*y_Symbol==c_,d_.*x_Symbol+e_.*y_Symbol==f_},{x_Symbol,y_Symbol}] := {{x->-((c e-b f)/(b d-a e)),y->-((-c d+a f)/(b d-a e))}} /;FreeQ[{a,b,c,d,e,f},x]&&FreeQ[{a,b,c,d,e,f},y] Solve[{a_.*x_Symbol+b_.*y_Symbol==c_,d_.*x_Symbol==f_},{x_Symbol,y_Symbol}] := {{x->f/d,y->-((-c d+a f)/(b d))}}/;FreeQ[{a,b,c,d,f},x]&&FreeQ[{a,b,c,d,f},y] + Attributes[Solve] = {Protected}; Tests`Solve = { ESimpleExamples[ @@ -15,6 +76,9 @@ ESameTest[{{x -> b/a}}, Solve[x*a == b, x]], ESameTest[{{x -> -(b/m)}}, Solve[m*x + b == 0, x]], ESameTest[{{x -> (-b + c)/m}}, Solve[m*x + b == c, x]], + ESameTest[{{x -> -Sqrt[a]}, {x -> Sqrt[a]}}, Solve[x^2 == a, x]], + ESameTest[{{a -> 1.5}}, Solve[a + 1.5 == 3, a]], + ESameTest[{{x -> -Sqrt[-3 + y]}, {x -> Sqrt[-3 + y]}}, Solve[y == x^2 + 3, x]], (*ESameTest[{{x -> (-b - Sqrt[b^2 - 4 a c])/(2 a)}, {x -> (-b + Sqrt[b^2 - 4 a c])/(2 a)}}, Solve[a*x^2 + b*x + c == 0, x]],*) (*ESameTest[{{x -> (-b - Sqrt[b^2 - 4 a c + 4 a d])/(2 a)}, {x -> (-b + Sqrt[b^2 - 4 a c + 4 a d])/(2 a)}}, Print[a,b,c,d,x];Solve[a*x^2 + b*x + c == d, x]]*) ]