Skip to content

Commit

Permalink
If plotting worked, it would look like this.
Browse files Browse the repository at this point in the history
  • Loading branch information
corywalker committed Jan 3, 2018
1 parent dc6f4b4 commit 02ce0e0
Show file tree
Hide file tree
Showing 10 changed files with 183 additions and 49 deletions.
1 change: 1 addition & 0 deletions expreduce/builtin.go
Expand Up @@ -185,6 +185,7 @@ func GetAllDefinitions() (defs []NamedDefSet) {
defs = append(defs, NamedDefSet{"sort", GetSortDefinitions()})
defs = append(defs, NamedDefSet{"system", GetSystemDefinitions()})
defs = append(defs, NamedDefSet{"trig", GetTrigDefinitions()})
defs = append(defs, NamedDefSet{"plot", GetPlotDefinitions()})
defs = append(defs, NamedDefSet{"string", GetStringDefinitions()})
defs = append(defs, NamedDefSet{"time", GetTimeDefinitions()})
defs = append(defs, NamedDefSet{"pattern", GetPatternDefinitions()})
Expand Down
1 change: 1 addition & 0 deletions expreduce/builtin_comparison.go
Expand Up @@ -279,5 +279,6 @@ func getComparisonDefinitions() (defs []Definition) {
},
})
defs = append(defs, Definition{Name: "PossibleZeroQ"})
defs = append(defs, Definition{Name: "MinMax"})
return
}
63 changes: 35 additions & 28 deletions expreduce/builtin_list.go
Expand Up @@ -68,12 +68,28 @@ func validateIndex(i Ex, l int) (int64, bool) {
return iInt.Val.Int64(), true
}

func applyIndex(ex Ex, index Ex) (Ex, bool) {
func applyIndex(ex Ex, indices []Ex, currDim int) (Ex, bool) {
// Base case
if currDim >= len(indices) {
return ex, true
}
expr, isExpr := ex.(*Expression)
if !isExpr {
return nil, false
}
if iSpan, iIsSpan := HeadAssertion(index, "System`Span"); iIsSpan {

// Singular selection
if _, iIsInt := indices[currDim].(*Integer); iIsInt {
indexVal, indexOk := validateIndex(indices[currDim], len(expr.Parts))
if !indexOk {
return nil, false
}
return applyIndex(expr.Parts[indexVal], indices, currDim+1)
}

// Range selections
rangeMin, rangeMax, rangeOk := int64(0), int64(0), false
if iSpan, iIsSpan := HeadAssertion(indices[currDim], "System`Span"); iIsSpan {
if len(iSpan.Parts) != 3 {
return nil, false
}
Expand All @@ -87,23 +103,24 @@ func applyIndex(ex Ex, index Ex) (Ex, bool) {
if !startOk || !endOk {
return nil, false
}
return NewExpression(append(
[]Ex{expr.Parts[0]},
expr.Parts[start:end+1]...,
)), true
}
if _, iIsInt := index.(*Integer); iIsInt {
indexVal, indexOk := validateIndex(index, len(expr.Parts))
if !indexOk {
return nil, false
}
return expr.Parts[indexVal], true
rangeMin, rangeMax, rangeOk = start, end, true
}
iSym, iIsSym := index.(*Symbol)
iSym, iIsSym := indices[currDim].(*Symbol)
if iIsSym {
if iSym.Name == "System`All" {
return expr, true
rangeMin, rangeMax, rangeOk = 1, int64(len(expr.Parts)-1), true
}
}
if rangeOk {
toReturn := E(expr.Parts[0])
for i := rangeMin; i <= rangeMax; i++ {
applied, appOk := applyIndex(expr.Parts[i], indices, currDim+1)
if !appOk {
return nil, false
}
toReturn.appendEx(applied)
}
return toReturn, true
}
return nil, false
}
Expand Down Expand Up @@ -384,19 +401,9 @@ func GetListDefinitions() (defs []Definition) {
if len(this.Parts) == 1 {
return this
}
applied, ok := this.Parts[1], true
// This assumes that e[[a, b]] is equivalent to e[[a]][[b]]. It is
// in most cases, but try this with mat[[All, 5]]. It seems that
// the indices are aware of each other and the fact that e is a
// matrix. I will most likely need to perform this selection using
// another method. TODO
for i := 2; i < len(this.Parts); i++ {
//es.Infof("applyIndex(%v, %v)", applied, this.Parts[i])
applied, ok = applyIndex(applied, this.Parts[i])
//es.Infof("after running, applied = %v", applied)
if !ok {
return this
}
applied, ok := applyIndex(this.Parts[1], this.Parts[2:], 0)
if !ok {
return this
}
return applied
},
Expand Down
6 changes: 6 additions & 0 deletions expreduce/builtin_plot.go
@@ -0,0 +1,6 @@
package expreduce

func GetPlotDefinitions() (defs []Definition) {
defs = append(defs, Definition{Name: "Plot"})
return
}
28 changes: 28 additions & 0 deletions expreduce/evalstate.go
Expand Up @@ -161,6 +161,34 @@ func (es *EvalState) Init(loadAllDefs bool) {
es.MarkSeen("System`ArcTan")
es.MarkSeen("System`ArcTanh")

es.MarkSeen("System`AbsolutePointSize")
es.MarkSeen("System`AbsoluteThickness")
es.MarkSeen("System`AspectRatio")
es.MarkSeen("System`Automatic")
es.MarkSeen("System`Axes")
es.MarkSeen("System`AxesLabel")
es.MarkSeen("System`AxesOrigin")
es.MarkSeen("System`Directive")
es.MarkSeen("System`DisplayFunction")
es.MarkSeen("System`Frame")
es.MarkSeen("System`FrameLabel")
es.MarkSeen("System`FrameTicks")
es.MarkSeen("System`GoldenRatio")
es.MarkSeen("System`Graphics")
es.MarkSeen("System`GrayLevel")
es.MarkSeen("System`GridLines")
es.MarkSeen("System`GridLinesStyle")
es.MarkSeen("System`Line")
es.MarkSeen("System`Method")
es.MarkSeen("System`None")
es.MarkSeen("System`Opacity")
es.MarkSeen("System`PlotRange")
es.MarkSeen("System`PlotRangeClipping")
es.MarkSeen("System`PlotRangePadding")
es.MarkSeen("System`RGBColor")
es.MarkSeen("System`Scaled")
es.MarkSeen("System`Ticks")

for _, defSet := range GetAllDefinitions() {
for _, def := range defSet.Defs {
es.MarkSeen(es.GetStringDef("System`$Context", "") + def.Name)
Expand Down
49 changes: 35 additions & 14 deletions expreduce/iterspec.go
Expand Up @@ -15,10 +15,11 @@ type iterSpec interface {
type iterSpecRange struct {
i Ex
iName string
iMin *Integer
iMax *Integer
curr int64
iMaxInt int64
iMin Ex
iMax Ex
step Ex
curr Ex
es *EvalState
}

type iterSpecList struct {
Expand All @@ -28,14 +29,28 @@ type iterSpecList struct {
list *Expression
}

func tryIterParam(e Ex) (Ex, bool) {
if _, isInt := e.(*Integer); isInt {
return e, true
}
if _, isReal := e.(*Flt); isReal {
return e, true
}
if _, isRat := e.(*Rational); isRat {
return e, true
}
return nil, false
}

func iterSpecFromList(es *EvalState, listEx Ex) (iterSpec, bool) {
isr := &iterSpecRange{}
isr.es = es
isl := &iterSpecList{}

listEx = evalIterSpecCandidate(es, listEx)
list, isList := HeadAssertion(listEx, "System`List")
if isList {
iOk, iMinOk, iMaxOk := false, false, false
iOk, iMinOk, iMaxOk, stepOk := false, false, false, false
if len(list.Parts) > 2 {
iAsSymbol, iIsSymbol := list.Parts[1].(*Symbol)
if iIsSymbol {
Expand All @@ -55,12 +70,18 @@ func iterSpecFromList(es *EvalState, listEx Ex) (iterSpec, bool) {
}
if len(list.Parts) == 3 {
isr.iMin, iMinOk = NewInteger(big.NewInt(1)), true
isr.iMax, iMaxOk = list.Parts[2].(*Integer)
isr.iMax, iMaxOk = tryIterParam(list.Parts[2])
isr.step, stepOk = NewInteger(big.NewInt(1)), true
} else if len(list.Parts) == 4 {
isr.iMin, iMinOk = list.Parts[2].(*Integer)
isr.iMax, iMaxOk = list.Parts[3].(*Integer)
isr.iMin, iMinOk = tryIterParam(list.Parts[2])
isr.iMax, iMaxOk = tryIterParam(list.Parts[3])
isr.step, stepOk = NewInteger(big.NewInt(1)), true
} else if len(list.Parts) == 5 {
isr.iMin, iMinOk = tryIterParam(list.Parts[2])
isr.iMax, iMaxOk = tryIterParam(list.Parts[3])
isr.step, stepOk = tryIterParam(list.Parts[4])
}
if iOk && iMinOk && iMaxOk {
if iOk && iMinOk && iMaxOk && stepOk {
isr.reset()
return isr, true
}
Expand All @@ -79,20 +100,20 @@ func iterSpecFromList(es *EvalState, listEx Ex) (iterSpec, bool) {
}

func (this *iterSpecRange) reset() {
this.curr = this.iMin.Val.Int64()
this.iMaxInt = this.iMax.Val.Int64()
//this.curr = this.iMin
this.curr = E(S("Plus"), this.iMin, E(S("Times"), NewInt(0), this.step)).Eval(this.es)
}

func (this *iterSpecRange) next() {
this.curr++
this.curr = E(S("Plus"), this.curr, this.step).Eval(this.es)
}

func (this *iterSpecRange) cont() bool {
return this.curr <= this.iMaxInt
return ExOrder(this.curr, this.iMax) >= 0
}

func (this *iterSpecRange) getCurr() Ex {
return NewInteger(big.NewInt(this.curr))
return this.curr
}

func (this *iterSpecRange) getI() Ex {
Expand Down
31 changes: 27 additions & 4 deletions expreduce/resources.go

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions expreduce/resources/comparison.m
Expand Up @@ -294,3 +294,12 @@
ESameTest[False, PossibleZeroQ[a-b]]
]
};

MinMax::usage = "`MinMax[l]` returns `{Min[l], Max[l]}`.";
Attributes[MinMax] = {Protected};
MinMax[l_List] := {Min[l], Max[l]};
Tests`MinMax = {
ESimpleExamples[
ESameTest[{1, 5}, MinMax[Range[5]]]
]
};
8 changes: 5 additions & 3 deletions expreduce/resources/list.m
Expand Up @@ -178,7 +178,8 @@
EComment["The input need not be a `List`:"],
ESameTest[foo, Part[foo[a], 0]],
EComment["Omitting an index will return the original expression:"],
ESameTest[i, Part[i]]
ESameTest[i, Part[i]],
ESameTest[{2,4,6}, {{1, 2}, {3, 4}, {5, 6}}[[All, 2]]]
], ETests[
ESameTest[i, Part[i]],
ESameTest[Part[], Part[]],
Expand All @@ -194,9 +195,10 @@
ESameTest[{a}[[2]], Part[{a}, 2]],
ESameTest[{5, 20, 45, 80, 125}, mat[[All]][[5]]],
ESameTest[3, {{1, 2}, {3, 4}}[[2, 1]]],
ESameTest[{{1, 2}, {3}}[[2, 2]], {{1, 2}, {3}}[[2, 2]]]
ESameTest[{{1, 2}, {3}}[[2, 2]], {{1, 2}, {3}}[[2, 2]]],
ESameTest[{3,4}, {{1, 2}, {3, 4}, {5, 6}}[[2, All]]],
ESameTest[{25, 50, 75, 100, 125}, mat[[All, 5]]]
], EKnownFailures[
ESameTest[{25, 50, 75, 100, 125}, mat[[All, 5]]],
ESameTest[Integer[], Part[1, All]],
ESameTest[Symbol[], Part[a, All]]
]
Expand Down
36 changes: 36 additions & 0 deletions expreduce/resources/plot.m
@@ -0,0 +1,36 @@
Attributes[ExpreducePlotPoints] = {HoldAll};
ExpreducePlotPoints[fn_, range_List] :=
Module[{nPoints, stepSize, replacedFn, unfilteredPoints},
nPoints = 500;
stepSize = (range[[3]] - range[[2]])/nPoints // N;
replacedFn = fn /. range[[1]] -> varOfIteration;
unfilteredPoints =
Table[{varOfIteration, replacedFn // N}, {varOfIteration,
range[[2]], range[[3]], stepSize}];
Select[unfilteredPoints, (Im[#[[2]]] == 0) &]
];

Plot::usage = "`Plot[fn, {var, min, max}]` plots `fn` over the range specified.";
Attributes[Plot] = {HoldAll, Protected, ReadProtected}
Plot[fn_, range_List] := Module[{plotPoints, fullRange, displayOptions},
plotPoints = ExpreducePlotPoints[fn, range];
fullRange = {MinMax[Join[plotPoints[[All, 1]], range[[2 ;; 3]]]],
MinMax[plotPoints[[All, 2]]]};
displayOptions = {DisplayFunction -> Identity,
AspectRatio -> GoldenRatio^(-1), Axes -> {True, True},
AxesLabel -> {None, None}, AxesOrigin -> {0, 0},
DisplayFunction :> Identity,
Frame -> {{False, False}, {False, False}},
FrameLabel -> {{None, None}, {None, None}},
FrameTicks -> {{Automatic, Automatic}, {Automatic, Automatic}},
GridLines -> {None, None},
GridLinesStyle -> Directive[GrayLevel[0.5, 0.4]],
Method -> {"DefaultBoundaryStyle" -> Automatic,
"DefaultMeshStyle" -> AbsolutePointSize[6],
"ScalingFunctions" -> None}, PlotRange -> fullRange,
PlotRangeClipping -> True,
PlotRangePadding -> {{Scaled[0.02], Scaled[0.02]}, {Scaled[0.05],
Scaled[0.05]}}, Ticks -> {Automatic, Automatic}};
Graphics[{{{}, {}, {Directive[Opacity[1.],
RGBColor[0.37, 0.5, 0.71], AbsoluteThickness[1.6]],
Line[plotPoints]}}}, displayOptions]];

0 comments on commit 02ce0e0

Please sign in to comment.