From 787ed1399dc7f44438af7c23f6df6e897dafa1ec Mon Sep 17 00:00:00 2001 From: serperu Date: Tue, 5 Oct 2021 12:58:13 +0200 Subject: [PATCH] Timed Run: * Measured the generation time of the different graph edges * Added EKnife.timedRun to evaluate the slicer against all the possible slicing criteria of a program * Added intraprocedural bencher suite --- EDG/src/main/java/edg/EDGFactory.java | 33 +++-- .../java/edg/edge/SummaryEdgeGenerator.java | 29 +++++ EDG/src/main/java/edg/graph/EDG.java | 34 +++-- EDG/src/main/java/edg/graph/LAST.java | 14 +++ .../edg/slicing/AdaptedStandardAlgorithm.java | 92 ++++++++++++++ e-Knife/src/main/java/eknife/EKnife.java | 18 ++- .../java/eknife/erlang/ErlangLASTFactory.java | 12 +- .../eknife/erlang/ValueEdgeGenerator.java | 5 + .../bencher_intraprocedural/bench1.erl | 117 ++++++++++++++++++ .../bencher_intraprocedural/bench11.erl | 13 ++ .../bencher_intraprocedural/bench12.erl | 100 +++++++++++++++ .../bencher_intraprocedural/bench14.erl | 83 +++++++++++++ .../bencher_intraprocedural/bench15.erl | 60 +++++++++ .../bencher_intraprocedural/bench16.erl | 50 ++++++++ .../bencher_intraprocedural/bench17.erl | 24 ++++ .../bencher_intraprocedural/bench18.erl | 21 ++++ .../bencher_intraprocedural/bench3.erl | 21 ++++ .../bencher_intraprocedural/bench4.erl | 15 +++ .../bencher_intraprocedural/bench5.erl | 18 +++ .../bencher_intraprocedural/bench6.erl | 51 ++++++++ .../bencher_intraprocedural/bench9.erl | 29 +++++ 21 files changed, 816 insertions(+), 23 deletions(-) create mode 100644 EDG/src/main/java/edg/slicing/AdaptedStandardAlgorithm.java create mode 100644 e-Knife/src/test/resources/regression/bencher_intraprocedural/bench1.erl create mode 100644 e-Knife/src/test/resources/regression/bencher_intraprocedural/bench11.erl create mode 100644 e-Knife/src/test/resources/regression/bencher_intraprocedural/bench12.erl create mode 100644 e-Knife/src/test/resources/regression/bencher_intraprocedural/bench14.erl create mode 100644 e-Knife/src/test/resources/regression/bencher_intraprocedural/bench15.erl create mode 100644 e-Knife/src/test/resources/regression/bencher_intraprocedural/bench16.erl create mode 100644 e-Knife/src/test/resources/regression/bencher_intraprocedural/bench17.erl create mode 100644 e-Knife/src/test/resources/regression/bencher_intraprocedural/bench18.erl create mode 100644 e-Knife/src/test/resources/regression/bencher_intraprocedural/bench3.erl create mode 100644 e-Knife/src/test/resources/regression/bencher_intraprocedural/bench4.erl create mode 100644 e-Knife/src/test/resources/regression/bencher_intraprocedural/bench5.erl create mode 100644 e-Knife/src/test/resources/regression/bencher_intraprocedural/bench6.erl create mode 100644 e-Knife/src/test/resources/regression/bencher_intraprocedural/bench9.erl diff --git a/EDG/src/main/java/edg/EDGFactory.java b/EDG/src/main/java/edg/EDGFactory.java index 1ff3804..7d9ebbc 100755 --- a/EDG/src/main/java/edg/EDGFactory.java +++ b/EDG/src/main/java/edg/EDGFactory.java @@ -15,7 +15,7 @@ import edg.graph.LAST; public class EDGFactory { private final LAST last; private EDG edg; - + private boolean interproceduralGraph = false; public EDGFactory(LAST last) { @@ -75,15 +75,34 @@ public class EDGFactory { } } private void generateDependencies() { + + long initialControl = System.nanoTime(); new ControlEdgeGenerator(edg).generate(); + long finalControl = System.nanoTime(); + edg.getGenerationTime().setControlTime((finalControl-initialControl) / 1000000.0); + + // WE ARE NOT GENERATING INTERPROCEDURAL EDGES + if (interproceduralGraph) { + if (isOOLanguage) + new InterproceduralEdgeGenerator(edg).generate(); // Specially Generated for OOPrograms + else { + long initialInputOutput = System.nanoTime(); + new InterproceduralEdgeGenerator(edg).generateErlang(); // + long finalInputOutput = System.nanoTime(); + edg.getGenerationTime().setInterproceduralTime((finalInputOutput-initialInputOutput) / 1000000.0); + } - if (isOOLanguage) - new InterproceduralEdgeGenerator(edg).generate(); // Specially Generated for OOPrograms + } + long initialFlow = System.nanoTime(); + new FlowEdgeGenerator(edg).generate(); + long finalFlow = System.nanoTime(); + edg.getGenerationTime().setFlowTime((finalFlow-initialFlow) / 1000000.0); + + // WE ARE NOT GENERATING SUMMARIES + if (interproceduralGraph) + new SummaryEdgeGenerator(edg).generate(); else - new InterproceduralEdgeGenerator(edg).generateErlang(); // -// - new FlowEdgeGenerator(edg).generate(); // TODO: Testear varios escenarios del POST-IT - new SummaryEdgeGenerator(edg).generate(); + new SummaryEdgeGenerator(edg).generateAsExternal(); // new ExceptionEdgeGenerator(edg).generate(); } diff --git a/EDG/src/main/java/edg/edge/SummaryEdgeGenerator.java b/EDG/src/main/java/edg/edge/SummaryEdgeGenerator.java index 1cd9263..9581f52 100755 --- a/EDG/src/main/java/edg/edge/SummaryEdgeGenerator.java +++ b/EDG/src/main/java/edg/edge/SummaryEdgeGenerator.java @@ -24,6 +24,35 @@ public class SummaryEdgeGenerator extends EdgeGenerator this.generateInternalSummaryEdges(); } + public void generateAsExternal(){ + this.generateSummaryEdgesAsExternal(); + } + + private void generateSummaryEdgesAsExternal() { + final List calls = edg.getNodes(Node.Type.Call); + + for (Node call : calls) + { + final Node callee = edg.getChild(call, Node.Type.Callee); + + if (isKnownModuleFunction(callee)) { + buildSummaryEdges(call, callee); + continue; + } + + final Node callResult = edg.getResFromNode(call); + final Node argumentsNode = edg.getChild(call, Node.Type.Arguments); + final List arguments = edg.getChildren(argumentsNode); + arguments.removeIf(n -> n.getType() == Node.Type.Result); + + for (Node argument : arguments) + { + final Node argumentResult = edg.getResFromNode(argument); + this.edg.addEdge(argumentResult, callResult, new Edge(Edge.Type.Summary, AsteriskConstraint.getConstraint())); + } + } + } + /* ********************************** */ /* ************ External ************ */ /* ********************************** */ diff --git a/EDG/src/main/java/edg/graph/EDG.java b/EDG/src/main/java/edg/graph/EDG.java index d9ec2cc..d8f1c11 100644 --- a/EDG/src/main/java/edg/graph/EDG.java +++ b/EDG/src/main/java/edg/graph/EDG.java @@ -23,6 +23,10 @@ public class EDG extends LAST { this.rootNode = last.rootNode; this.nextId = last.nextId; this.fictitiousId = last.fictitiousId; + this.getGenerationTime().setStructureTime(last.getStructuralTime()); + this.getGenerationTime().setControlFlowTime(last.getControlFlowTime()); + this.getGenerationTime().setValueTime(last.getValueTime()); + this.getGenerationTime().setCompositeTime(last.getCompositeStructureTime()); } // ================================================= // @@ -79,13 +83,15 @@ public class EDG extends LAST { } public static class GraphGeneratorTimer - { + { + // MILISECONDS (1*10^(-3)) private double structureTime; private double controlFlowTime; private double controlTime; private double interproceduralTime; private double flowTime; private double valueTime; + private double compositeTime; private double summaryTime; private double exceptionTime; @@ -93,46 +99,50 @@ public class EDG extends LAST { { this.structureTime = structureTime; } - public void setControlFlowTime(double controlFlowTime) { this.controlFlowTime = controlFlowTime; } - - public void setControlTime(double controlTime) - { - this.controlTime = controlTime; - } - + public void setControlTime(double controlTime) { this.controlTime = controlTime; } public void setInterproceduralTime(double interproceduralTime) { this.interproceduralTime = interproceduralTime; } - public void setFlowTime(double flowTime) { this.flowTime = flowTime; } - public void setValueTime(double valueTime) { this.valueTime = valueTime; } - + public void setCompositeTime(double compositeTime) + { + this.compositeTime = compositeTime; + } public void setSummaryTime(double summaryTime) { this.summaryTime = summaryTime; } - public void setExceptionTime(double exceptionTime) { this.exceptionTime = exceptionTime; } + public double getStructureTime() { return this.structureTime; } + public double getControlFlowTime() { return this.controlFlowTime; } + public double getValueTime() { return this.valueTime; } + public double getCompositeTime() { return this.compositeTime; } + public double getControlTime() { return this.controlTime; } + public double getFlowTime() { return this.flowTime; } + public double getGenerationEDGTime() { return structureTime + controlFlowTime + controlTime + interproceduralTime + flowTime + valueTime + summaryTime + exceptionTime; } + public double getGenerationIntraproceduralEDGTime() { + return structureTime + controlFlowTime + controlTime + flowTime + valueTime ; + } } } diff --git a/EDG/src/main/java/edg/graph/LAST.java b/EDG/src/main/java/edg/graph/LAST.java index a3f7f68..c8154ad 100644 --- a/EDG/src/main/java/edg/graph/LAST.java +++ b/EDG/src/main/java/edg/graph/LAST.java @@ -929,4 +929,18 @@ public class LAST extends GraphWithRoot { return false; return true; } + + private double structuralGenerationTime = 0; + private double controlFlowGenerationTime = 0; + private double valueGenerationTime = 0; + private double compositeStructureTime = 0; + + public void setStructuralTime(double time) { structuralGenerationTime = time; } + public void setControlFlowTime(double time) { controlFlowGenerationTime = time; } + public void setValueTime(double time) { valueGenerationTime = time; } + public void setCompositeStructureEdges(double time) { compositeStructureTime = time; } + public double getStructuralTime() { return structuralGenerationTime; } + public double getControlFlowTime() { return controlFlowGenerationTime; } + public double getValueTime() { return valueGenerationTime; } + public double getCompositeStructureTime() { return compositeStructureTime; } } diff --git a/EDG/src/main/java/edg/slicing/AdaptedStandardAlgorithm.java b/EDG/src/main/java/edg/slicing/AdaptedStandardAlgorithm.java new file mode 100644 index 0000000..a0bab1f --- /dev/null +++ b/EDG/src/main/java/edg/slicing/AdaptedStandardAlgorithm.java @@ -0,0 +1,92 @@ +package edg.slicing; + +import edg.graph.EDG; +import edg.graph.Edge; +import edg.graph.LAST; +import edg.graph.Node; + +import java.util.*; + +public class AdaptedStandardAlgorithm extends StandardAlgorithm{ + + public AdaptedStandardAlgorithm(EDG edg) { + super(edg); + } + + public Set slice(Node slicingCriterion) + { + final Set slice = new HashSet<>(); + if (slicingCriterion == null) + return slice; + + slice.add(slicingCriterion); + this.traverse(slicingCriterion, slice); + + return slice; + } + + protected void traverse(Node slicingCriterion, Set slice, Edge.Type... ignoreEdgeTypes) { + final Deque pendingNodes = new LinkedList<>(slice); + final Set ignoreEdgeTypesSet = new HashSet<>(Arrays.asList(ignoreEdgeTypes)); + + while (!pendingNodes.isEmpty()) + { + final Node pendingNode = pendingNodes.removeFirst(); + final Set nextEdges = edg.getEdges(pendingNode, sliceDirection); + + nextEdges.removeIf(e -> ignoreEdgeTypesSet.contains(e.getType())); + nextEdges.removeIf(Edge::isControlFlowEdge); + nextEdges.removeIf(e -> !e.isTraversable()); + for (Edge nextEdge : nextEdges) + { + final Node nextNode = sliceDirection == LAST.Direction.Backwards ? + edg.getEdgeSource(nextEdge): edg.getEdgeTarget(nextEdge); + if (!slice.contains(nextNode)) + { + Node outerStructureNode = this.getOuterCompositeNode(nextNode); + if (outerStructureNode != null) { + List nextNodes = edg.getDescendants(outerStructureNode); + nextNodes.add(outerStructureNode); + + if (nextNodes.contains(slicingCriterion)) + nextNodes.removeIf(n -> n.getType() == Node.Type.Result); + nextNodes.add(edg.getResFromNode(nextNode)); + + for (Node next : nextNodes) { + pendingNodes.addLast(next); + slice.add(next); + } + } + else { + pendingNodes.addLast(nextNode); + slice.add(nextNode); + } + } + } + } + } + public Node getOuterCompositeNode(Node node) { + Node lastDataContainerParent = null; + Node nextParent = edg.getParent(node); + while (nextParent != null && isPossibleDataContainer(nextParent)){ + if (nextParent.getType() == Node.Type.List || nextParent.getType() == Node.Type.DataConstructor) + lastDataContainerParent = nextParent; + nextParent = edg.getParent(nextParent); + } + return lastDataContainerParent; + } + + public boolean isPossibleDataContainer(Node parent) { + switch (parent.getType()){ + case Equality: + case Arguments: + case Call: + case Operation: + case List: + case DataConstructor: + return true; + default: + return false; + } + } +} diff --git a/e-Knife/src/main/java/eknife/EKnife.java b/e-Knife/src/main/java/eknife/EKnife.java index b6418fd..8b9244b 100644 --- a/e-Knife/src/main/java/eknife/EKnife.java +++ b/e-Knife/src/main/java/eknife/EKnife.java @@ -22,11 +22,10 @@ import edg.DotFactory; import edg.EDGFactory; import edg.PdfFactory; import edg.graph.EDG; +import edg.graph.Edge; import edg.graph.LAST; import edg.graph.Node; -import edg.slicing.ConstrainedAlgorithm; -import edg.slicing.SlicingAlgorithm; -import edg.slicing.SlicingCriterion; +import edg.slicing.*; import java.io.File; import java.util.LinkedList; @@ -208,4 +207,17 @@ public class EKnife return errors.isEmpty(); } } + + private static class SlicingCriterionState{ + private final double slicingPerformance; + private final double slicingTime; + + public SlicingCriterionState(double performance, double time) { + slicingPerformance = performance; + slicingTime = time; + } + public double getPerformance() { return this.slicingPerformance; } + public double getTime() { return this.slicingTime; } + + } } diff --git a/e-Knife/src/main/java/eknife/erlang/ErlangLASTFactory.java b/e-Knife/src/main/java/eknife/erlang/ErlangLASTFactory.java index 5a50af6..5569c70 100644 --- a/e-Knife/src/main/java/eknife/erlang/ErlangLASTFactory.java +++ b/e-Knife/src/main/java/eknife/erlang/ErlangLASTFactory.java @@ -68,14 +68,24 @@ public class ErlangLASTFactory extends LASTFactory { try { final LDASTNodeInfo ldNodeInfo = new LDASTNodeInfo(0, "LAST", this.codebase); + long initialStructural = System.nanoTime(); final LAST last = super.createLAST(generateArcs, asts, ldNodeInfo); + long finalStructural = System.nanoTime(); + last.setStructuralTime((finalStructural - initialStructural)/ 1000000.0); if (generateArcs){ if (Config.PPDG || Config.APDG) new AugmentedControlFlowGenerator(last).generate(); - if (Config.PDG) + if (Config.PDG) { + long initialCFG = System.nanoTime(); new ControlFlowGenerator(last).generate(); + long finalCFG = System.nanoTime(); + last.setControlFlowTime((finalCFG - initialCFG) / 1000000.0); + } + long initialValue = System.nanoTime(); new ValueEdgeGenerator(last).generate(); + long finalValue = System.nanoTime(); + last.setValueTime((finalValue - initialValue) / 1000000.0); } return last; } catch (Exception e) diff --git a/e-Knife/src/main/java/eknife/erlang/ValueEdgeGenerator.java b/e-Knife/src/main/java/eknife/erlang/ValueEdgeGenerator.java index f07267a..c7a4184 100644 --- a/e-Knife/src/main/java/eknife/erlang/ValueEdgeGenerator.java +++ b/e-Knife/src/main/java/eknife/erlang/ValueEdgeGenerator.java @@ -38,8 +38,13 @@ public class ValueEdgeGenerator { public void generate() { this.generateEqualityEdges(); + + long initListTuple = System.nanoTime(); this.generateDataConstructorEdges(); this.generateListEdges(); + long finalListTuple = System.nanoTime(); + this.last.setCompositeStructureEdges((finalListTuple - initListTuple) / 1000000.0); + this.generateOperationEdges(); this.generateSwitchEdges(); this.generateListComprehensionEdges(); diff --git a/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench1.erl b/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench1.erl new file mode 100644 index 0000000..85515ed --- /dev/null +++ b/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench1.erl @@ -0,0 +1,117 @@ +-module(bench1). +-export([main/1]). + +main(Number) when Number > 0 andalso Number < 7-> + Database = [ + ["Rihanna",28, + {albums,[{"Music of the Sun",2005},{"A Girl like me",2006},{"Good Girl Gone Bad",2007},{"Rater D",2009},{"Loud",2010},{"Talk That Talk",2011},{"Unapologetic",2012},{"ANTi",2016}]}, + {concerts,[{"Amsterdam",{2016,6,17}}, {"Manchester",{2016,6,29}}, {"Barcelona",{2016,7,21}}, {"Bucarest",{2017,8,14}}]}], + ["Christina Aguilera",35, + {albums,[{"Christina Aguilera",1999},{"Mi Reflejo",2000},{"Stripped",2002},{"Back to Basics",2006},{"Bionic",2010},{"Lotus",2012}]}, + {concerts,[{"Tokio",{2007,6,21}},{"Abu Dabi",{2008,10,28}}]}], + ["Bruno Mars",30, + {albums,[{"Doo-Wops & Hooligans",2010},{"Unorthodox Jukebox",2012}]}, + {concerts,[{"Santo Domingo",{2014,10,4}},{"Las Vegas",{2014,10,18}},{"Liverpool",{2013,11,24}}]}], + ["Daddy Yankee",39, + {albums,[{"No Mercy",1995},{"El Cangri.Com",2002},{"Barrio Fino",2004},{"El Cartel: The Big Boss",2007},{"Mundial",2010},{"Prestige",2012},{"Cartel IV",2015}]}, + {concerts,[{"Mexico City",{2015,11,8}},{"Las Vegas",{2016,5,6}},{"New York",{2017,7,30}}]}], + ["Justin Bieber",22, + {albums,[{"My World 2.0",2010},{"Under the mistletoe",2011},{"Believe",2012},{"Purpose",2015}]}, + {concerts,[{"Miami",{2016,7,3}},{"Munich",{2016,9,16}},{"Birmingham",{2017,10,24}}]}], + ["Adele",28, + {albums,[{"19",2008},{"21",2011},{"25",2015}]}, + {concerts,[{"Lisboa",{2016,5,22}},{"Paris",{2016,6,10}},{"Oakland",{2016,8,2}},{"Toronto",{2017,10,6}}]}] + ], + Artist = lists:nth(Number,Database), + [ArtistName|_] = Artist, + [_,Age|_] = Artist, + LastAlbum = begin + [_,_,{albums,Albums}|_] = Artist, + case getLast(Albums,empty) of + empty -> "No albums published"; + Album -> Album + end + end, + {AlbumName,_} = LastAlbum, + NextConcert = begin + CurrentDate = {2017,3,28}, + [_,_,_,{concerts,Concerts}] = Artist, + case getNext(Concerts,CurrentDate,empty) of + empty -> "No future concerts planned"; + Concert -> Concert + end + end, + Info = case NextConcert of + "No future concerts planned" -> + {"an undefined City", "Not planned yet"}; + _ -> + {L,Date} = NextConcert, + {Y,M,D} = Date, + {L,Y} + end, + {Location,Year} = Info, + {ArtistName,Age,AlbumName,Location,Year}. % Slice here + + +getLast(AlbumList,Newest) -> + case {AlbumList,Newest} of + {[],A} -> A; + {[Album|Albums],empty} -> + getLast(Albums,Album); + {[Album,Albums], Newest} -> + {_,YearN} = Newest, + {_,YearA} = Album, + case YearA > YearN of + true -> getLast(Albums,Album); + _ -> getLast(Albums,Newest) + end + end. + + +getNext(ConcertList,Current,NextConcert) -> + case {ConcertList,Current,NextConcert} of + {[],_,NextConcert} -> + NextConcert; + {[Concert|Concerts],Current,empty} -> + {YearA,MonthA,DayA} = Current, + {_,Date}=Concert, + {YearC,MonthC,DayC} = Date, + case {YearA,YearC,MonthA,MonthC,DayA,DayC} of + {YA,YC,_,_,_,_} when YC > YA -> getNext(Concerts,Current,Concert); + {Y,Y,MA,MC,_,_} when MC > MA -> getNext(Concerts,Current,Concert); + {Y,Y,M,M,DA,DC} when DC >= DA -> getNext(Concerts,Current,Concert); + _ -> getNext(Concerts,Current,empty) + end; + {[Concert|Concerts],Current,NextConcert} -> + {YearA,MonthA,DayA} = Current, + {_,DateN}=NextConcert, + {YearN,MonthN,DayN} = DateN, + {_,DateC}=Concert, + {YearC,MonthC,DayC} = DateC, + + Next = case {YearA,YearC,MonthA,MonthC,DayA,DayC} of + {YA,YC,_,_,_,_} when YC < YA -> getNext(Concerts,Current,NextConcert); + {Y,Y,MA,MC,_,_} when MC < MA -> getNext(Concerts,Current,NextConcert); + {Y,Y,M,M,DA,DC} when DC < DA -> getNext(Concerts,Current,NextConcert); + _ -> empty + end, + case Next of + empty -> + case {YearN,YearC,MonthN,MonthC,DayN,DayC} of + {YN,YC2,_,_,_,_} when YC2 < YN -> getNext(Concerts,Current,Concert); + {Y2,Y2,MN,MC2,_,_} when MC2 < MN -> getNext(Concerts,Current,Concert); + {Y2,Y2,M2,M2,DN,DC2} when DC2 < DN -> getNext(Concerts,Current,Concert); + _ -> getNext(Concerts,Current,NextConcert) + end; + _ -> Next + end + end. + + + +getStringDate(Concert) -> + {_,Date} = Concert, + {Y,M,D} = Date, + integer_to_list(D)++"/"++integer_to_list(M)++"/"++integer_to_list(Y). + + diff --git a/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench11.erl b/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench11.erl new file mode 100644 index 0000000..027f125 --- /dev/null +++ b/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench11.erl @@ -0,0 +1,13 @@ +-module(bench11). +-export([lists/2]). + +lists(A,B) -> + [H1|T1] = A, + [H2|T2] = B, + C = if % Slice C + H1 >= 3 -> + H2; + true -> + [H|_] = T2, + H1 - H % Slice H + end. \ No newline at end of file diff --git a/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench12.erl b/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench12.erl new file mode 100644 index 0000000..ffe26c5 --- /dev/null +++ b/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench12.erl @@ -0,0 +1,100 @@ + +-module(bench12). +-export([main/3]). + +main(AS,B,CS) -> + AT = [case X of + $- -> -1; + $0 -> 0; + $+ -> 1 + end || X <- AS], + A = from_ternary(AT), + BT = to_ternary(B), + BS = [case X of + -1 -> $-; + 0 -> $0; + 1 -> $+ + end || X <- BT], + CT = [case X of + $- -> -1; + $0 -> 0; + $+ -> 1 + end || X <- CS], + C = from_ternary(CT), + RT = mul(AT,sub(BT,CT)), + R = from_ternary(RT), + RS = [case X of + -1 -> $-; + 0 -> $0; + 1 -> $+ + end || X <- RT], + [{AS,A},{BS,B},{CS,C},{RS,R}]. % Slice here + +to_ternary(N) -> + if (N > 0) -> to_ternary(N,[]); + true -> [ -H || H <- to_ternary(-N)] + end. + +to_ternary(N,Acc) -> + if (N == 0) -> Acc; + (N rem 3 == 0) -> + to_ternary(N div 3, [0|Acc]); + (N rem 3 == 1) -> + to_ternary(N div 3, [1|Acc]); + true -> + X = to_ternary((N+1) div 3, [-1|Acc]) + end. + +from_ternary(T) -> from_ternary(T,0). + +from_ternary(L,Acc) -> + case L of + [] -> Acc; + [H|T] -> + from_ternary(T, Acc*3 + H) + end. + +mul(A,B) -> mul(B,A,[]). + +mul(B,L,Acc) -> + case L of + [] -> Acc; + [A|As] -> + BP = case A of + -1 -> [ -H || H <- B]; + 0 -> [0]; + 1 -> B + end, + A1 = Acc ++ [0], + A2 = add(BP,A1), + mul(B,As,A2) + end. + +sub(A,B) -> + add(A,[ -H || H <- B]). % Slice here + +add(A,B) -> + if (length(A) < length(B)) -> + add(lists:duplicate(length(B)-length(A),0)++A,B); + (length(A) > length(B)) -> + add(B,A); + true -> + add(lists:reverse(A),lists:reverse(B),0,[]) + end. + +add(L1, L2, N, Acc) -> + case {L1,L2,N} of + {[],[],0} -> Acc; + {[],[],C} -> [C|Acc]; + {[A|As],[B|Bs],C} -> + [C1,D] = case A + B + C of % SLICE HERE C1 / D + (-3) -> [-1,0]; + (-2) -> [-1,1]; + (-1) -> [0,-1]; + 3 -> [1,0]; + 2 -> [1,-1]; + 1 -> [0,1]; + 0 -> [0,0] + end, + add(As,Bs,C1,[D|Acc]) + end. \ No newline at end of file diff --git a/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench14.erl b/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench14.erl new file mode 100644 index 0000000..7cb5115 --- /dev/null +++ b/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench14.erl @@ -0,0 +1,83 @@ +-module(bench14). +-export([main/2]). + +main(X,Y) -> + Z = case X of + terminate -> "the end"; + {A1,B1} -> + {[A1+B1, B1-A1], 3}; + {3,C1} -> + [_,_,{R1,S1}] = C1, + case R1 of + [1,3] -> 21; + [A1,B1] -> (A1 * B1) / 9; + T1 -> T1; + _ -> case 4 of + 7 -> + L1 = 2 + 9, + F1 = L1 * 3, + F1 + L1; + 4 -> 9; + 2 -> 7; + FVar1 -> FVar1 + end + end; + _ -> {20 * 3,8} + end, + T2 = 2, + V = % Slice V + case T2 of + 7 -> + L2 = 2 + 9, + F2 = L2 * 3, + F2 + L2; + 4 -> 9; + 2 -> 7; + FVar2 -> FVar2 + end + + case 2 of + 2-> + A2_1 = {2,4}, + {X2_1,_} = A2_1, + X2_1; + 3-> + B2_1 = [4,8], + [H2_1|T2_1] = B2_1, + H2_1; + 1-> + C2_1 = 107, + C2_1 - 1 + end + + case 3 of + 2-> + A2_2 = {2,4}, + {X2_2,_} = A2_2, + X2_2; + 3-> + B2_2 = [4,8], + [H2_2|T2_2] = B2_2, + H2_2; + 1-> + C2_2 = 107, + C2_2 - 1 + end, + W = begin % SLICE W + FVar3_1 = [X,Y,{X,Y}], + [_,_,{R3,S3}] = FVar3_1, + case R3 of + [1,3] -> 21; + [A3,B3] -> (A3 * B3) / 9; + T3 -> T3; + _ -> case 4 of + 7 -> + L3 = 2 + 9, + F3 = L3 * 3, + F3 + L3; + 4 -> 9; + 2 -> 7; + FVar3_2 -> FVar3_2 + end + end + end, + Tuple = {Z,W,V}, % Slice Z + Tuple. diff --git a/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench15.erl b/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench15.erl new file mode 100644 index 0000000..8ff931a --- /dev/null +++ b/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench15.erl @@ -0,0 +1,60 @@ +-module(bench15). +-export([main/4]). + +main(PFrom,PTo,CFrom,CTo) -> + IncremP = if (PTo - PFrom >= 10) -> (PTo-PFrom) div 10; + true -> 1 + end, + IncremC = if (CTo - CFrom >= 10) -> (CTo-CFrom) div 10; + true -> 1 + end, + io:format("\nPermutations from ~p to ~p:\n",[PFrom,PTo]), + L1 = [ begin + K = N div 3, + StrFun = "perm", + io:format("~s(~p, ~p) = ~s\n",[StrFun, N, K, + begin + Limit = 40, + StrN = integer_to_list( + lists:foldl( + fun(N, Acc) -> + N * Acc + end, + 1, + lists:seq(N - K + 1, N))), + case length(StrN) < Limit of + true -> + StrN; + false -> + {Shown, Hidden} = lists:split(Limit, StrN), % Slice here + io_lib:format("~s... (~p more digits)", [Shown, length(Hidden)]) + end + end]) + end || N <- lists:seq(PFrom, PTo, IncremP)], + io:format("\nCombinations from ~p to ~p:\n",[CFrom,CTo]), + L2 = [ begin + K = N div 3, + StrFun = "comb", + io:format("~s(~p, ~p) = ~s\n",[StrFun, N, K, + begin + Limit = 40, + StrN = integer_to_list( + lists:foldl( + fun(N, Acc) -> N * Acc end, + 1, + lists:seq(N - K + 1, N)) + div + lists:foldl( + fun(N, Acc) -> N * Acc end, + 1, + lists:seq(1, K))), + case length(StrN) < Limit of + true -> + StrN; + false -> + {Shown, Hidden} = lists:split(Limit, StrN), % Slice here + io_lib:format("~s... (~p more digits)", [Shown, length(Hidden)]) + end + end]) + end || N <- lists:seq(CFrom, CTo, IncremC)], + {L1,L2}. \ No newline at end of file diff --git a/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench16.erl b/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench16.erl new file mode 100644 index 0000000..685433b --- /dev/null +++ b/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench16.erl @@ -0,0 +1,50 @@ +-module(bench16). +-export([word_count/1]). + +-spec word_count(string()) -> any(). +word_count(Text) -> + word_count(Text,0,0,0,false). + +word_count(L,Chars,Lines,Words,Inword) -> + case L of + [] -> + {Chars,Lines,Words,Inword}; + [C | Text] -> + NewChars = Chars+1, + NewLines = + case C of + $\n -> + Lines + 1; + _ -> + Lines + end, + {NewWords,NewInword} = + case + begin io:format("~c ",[C]), % Slice here + if + ((C >= $A andalso C =< $Z) + orelse + (C >= $a andalso C =< $z)) -> true; + true -> false + end + end + of + true -> + case Inword of + false -> + {Words+1,true}; + true -> + {Words,Inword} + end; + false -> + {Words,false} + end, + word_count(Text,NewChars,NewLines,NewWords,NewInword) + end. + + + + + + + \ No newline at end of file diff --git a/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench17.erl b/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench17.erl new file mode 100644 index 0000000..2be6467 --- /dev/null +++ b/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench17.erl @@ -0,0 +1,24 @@ +-module(bench17). +-export([mug/3]). + +-define(CONSTANT_F,10). +-define(CONSTANT_G,12). + +-spec mug(integer(),integer(),integer()) -> any(). +mug(I,C,X) -> + case I < 10 of + true -> + {NewX,NewC} = + case C < 20 of + true -> + TempX = ?CONSTANT_F, + TempC = ?CONSTANT_G, + {TempX,TempC}; + false -> + {X,C} + end, + NewI = I + 1, + mug(NewI,NewC,NewX); % SLICE NewX, NewC, NewI + false -> + io:format("~p\n",[X]) + end. diff --git a/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench18.erl b/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench18.erl new file mode 100644 index 0000000..4a8eed1 --- /dev/null +++ b/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench18.erl @@ -0,0 +1,21 @@ +-module(bench18). +-export([mbe/2]). + +-spec mbe(integer(),integer()) -> any(). +mbe(J,K) -> + case J < 15 of + true -> + {NewJ,NewK} = + case K < 6 of + true -> + TempK = K + 2, + {J,TempK}; + false -> + TempK = K - 1, + TempJ = J + rand:uniform(5), + {TempJ,TempK} + end, + mbe(NewJ,NewK); % Slice NewJ, NewK + false -> + io:format("~p\n",[J]) + end. \ No newline at end of file diff --git a/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench3.erl b/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench3.erl new file mode 100644 index 0000000..e3383fd --- /dev/null +++ b/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench3.erl @@ -0,0 +1,21 @@ +-module(bench3). +-export([tuples/2]). +tuples(A,B) -> + {X1,X2} = A, + {Y1,Y2} = B, + if + X1 =< Y2 -> + R = X1; + true -> + R = X2 + end, + if + X1 > X2 -> + Z= Y2 + 3, + S = 5; + true -> + S = X2; + X2 < 7 -> + S = 53 + end, + S. % Slice here \ No newline at end of file diff --git a/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench4.erl b/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench4.erl new file mode 100644 index 0000000..f0daf28 --- /dev/null +++ b/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench4.erl @@ -0,0 +1,15 @@ +-module(bench4). +-export([main/2]). + +main(Elements,Temp) -> + List = [begin + T1=T*7+1, + T2=T*2, + T3=T2/2, + {Name,T3} + end || {Name,Abb,T} <- Elements, T > Temp], + Abb = % Slice Abb (1) + [Abb || {RN,RT} <- List, + {Name,Abb,T} <- Elements, + RN == Name andalso erlang:length(atom_to_list(Abb)) == 1], + {List,Abb}. \ No newline at end of file diff --git a/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench5.erl b/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench5.erl new file mode 100644 index 0000000..eb90fa6 --- /dev/null +++ b/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench5.erl @@ -0,0 +1,18 @@ +-module(bench5). +-export([lists/2]). +lists(A,B) -> + [H1|T1] = A, + [H2|T2] = B, + C = if + H1 >= 3 -> + H2; + true -> + H1 + case T2 of + 0 -> 3; + [] -> 5; + [1|_] -> 0; + [H|T] -> 1; + _ -> 7 + end + end, + C. % Slice here diff --git a/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench6.erl b/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench6.erl new file mode 100644 index 0000000..f9aa55d --- /dev/null +++ b/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench6.erl @@ -0,0 +1,51 @@ + +-module(bench6). +-export([ft/2, ht/2]). +ft(A,B) -> + {X,Y} = A, + {X,Z,W} = B, + C = case Y of + W -> + case {1,X} of + {1,2,X} -> X + 4; + {0,_} -> 4; + _ -> 16; + {X,Y} -> Y; + {} -> 0; + X -> element(1,X) + end; + Y -> + case {0,Y} of + {1,2,X} -> X + 4; + {0,_} -> 4; + _ -> 16; + {X,Y} -> Y; + {} -> 0; + X -> element(1,X) + end; + _ -> + U = Z + X, + case {U,Z} of + {1,2,X} -> X + 4; + {0,_} -> 4; + _ -> 16; + {X,Y} -> Y; + {} -> 0; + X -> element(1,X) + end + end, + C. % Slice here + +ht(E,F) -> + {X,Y,Z} = E, + {A,B} = F, + D = case Z of + _ -> + A + Z * B; + Y -> + X * 2 + A; + A -> + U = Y + Z, + Z + U + end, + D. % Slice here \ No newline at end of file diff --git a/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench9.erl b/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench9.erl new file mode 100644 index 0000000..8031eb7 --- /dev/null +++ b/e-Knife/src/test/resources/regression/bencher_intraprocedural/bench9.erl @@ -0,0 +1,29 @@ +-module(bench9). +-export([main/2]). +-define(ERROR,failure). +-define(ON,enable). +-define(OFF,disable). + + +main(N,State) when (N > -480 andalso N =< 520) andalso (State == ?ON orelse State == ?OFF) -> + if + State == ?ON -> + {Res,Reply} = if + N > 20 andalso State == ?ON -> + {'ok', "Success switching ON"}; + N =< 20 andalso State == ?ON -> + {'error', ?ERROR}; + true -> + {'ok', "Success switching OFF"} + end; + true -> + {Res,Reply} = if + N > 20 andalso ?OFF == ?ON -> + {'ok', "Success switching ON"}; + N =< 20 andalso ?OFF == ?ON -> + {'error', ?ERROR}; + true -> + {'ok', "Success switching OFF"} + end + end, + Reply. % Slice here \ No newline at end of file -- GitLab