Fixed implicit multiplication symbols, zoom is now 1x, debug steps are printed, fixed missing numeric chars, changed RootSquare base class to FunctionSingle, added two hardcoded multiplication rules, added rootsquarerule, isolated the swing engine from the window, added 2 Fractions rules and 1 exponent rule
This commit is contained in:
Andrea Cavalli 2019-11-16 01:32:47 +01:00
parent 26dc8369a7
commit 4c29eeb31c
20 changed files with 219 additions and 75 deletions

View File

@ -12,7 +12,7 @@ public class StaticVars {
public static final boolean zoomed = true;
public static int outputLevel = 0;
public static boolean debugWindow2x = false;
public static EventSubmitter<Float> windowZoom = new EventSubmitter<>(2F);
public static EventSubmitter<Float> windowZoom = new EventSubmitter<>(1F);
public static Function<Float, Float> windowZoomFunction = (val) -> {
if (StaticVars.debugWindow2x) {
return val + 1;

View File

@ -45,7 +45,6 @@ public class TetrisScreen extends Screen {
@Override
public void initialized() {
StaticVars.windowZoom.submit(2f);
}
@Override

View File

@ -3,6 +3,7 @@ package it.cavallium.warppi.gui.expression.containers;
import it.cavallium.warppi.gui.expression.InputContext;
import it.cavallium.warppi.gui.expression.blocks.Block;
import it.cavallium.warppi.gui.expression.blocks.BlockChar;
import it.cavallium.warppi.gui.expression.blocks.BlockNumericChar;
public class InlineInputContainer extends InputContainer {
@ -30,6 +31,21 @@ public class InlineInputContainer extends InputContainer {
@Override
public Block parseChar(final char c) {
switch (c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.':
return new BlockNumericChar(c);
default:
return new BlockChar(c);
}
}
}

View File

@ -33,10 +33,13 @@ public class LoadingScreen extends Screen {
@Override
public void initialized() throws InterruptedException {
previousZoomValue = StaticVars.windowZoomFunction.apply(StaticVars.windowZoom.getLastValue());
float lastZoomValue = StaticVars.windowZoom.getLastValue();
previousZoomValue = StaticVars.windowZoomFunction.apply(lastZoomValue);
WarpPI.INSTANCE.getHardwareDevice().getDisplayManager().getHUD().hide();
if (lastZoomValue != 1.0f) {
StaticVars.windowZoom.submit(1f);
}
}
@Override
public void graphicInitialized(ScreenContext ctx) throws InterruptedException {}
@ -48,7 +51,9 @@ public class LoadingScreen extends Screen {
endLoading += dt;
if (!ended && loaded && ((WarpPI.getPlatform().getSettings().isDebugEnabled() && endLoading >= 1.5f) || endLoading >= 3.5f)) {
ended = true;
if (previousZoomValue != 1.0f) {
StaticVars.windowZoom.submit(previousZoomValue);
}
WarpPI.INSTANCE.getHardwareDevice().getDisplayManager().getHUD().show();
WarpPI.INSTANCE.getHardwareDevice().getDisplayManager().setScreen(new MathInputScreen());
}

View File

@ -552,6 +552,14 @@ public class MathInputScreen extends Screen {
final MathSolver ms = new MathSolver(expr);
final ObjectArrayList<ObjectArrayList<Function>> resultSteps = ms.solveAllSteps();
resultSteps.add(0, Utils.newArrayList(expr));
int stepNumber = 0;
for (ObjectArrayList<Function> resultStep : resultSteps) {
stepNumber++;
WarpPI.getPlatform().getConsoleUtils().out().println(0, "STEP " + stepNumber);
for (Function function : resultStep) {
WarpPI.getPlatform().getConsoleUtils().out().println(0, " :: " + function.toString());
}
}
final ObjectArrayList<Function> resultExpressions = resultSteps.get(resultSteps.size() - 1);
for (final Function rr : resultExpressions) {
WarpPI.getPlatform().getConsoleUtils().out().println(0, "RESULT: " + rr.toString());

View File

@ -44,7 +44,7 @@ public interface Function {
/**
* Deep clone this function, also change mathContext.
*
* @param mathContext new mathContext
* @param newMathContext new mathContext
* @return A clone of this function.
*/
Function clone(MathContext newMathContext);

View File

@ -66,7 +66,7 @@ public abstract class FunctionSingle implements Function {
/**
*
* @param var
* @param value
* Parameter.
* @return A new instance of this function.
*/
@ -124,4 +124,9 @@ public abstract class FunctionSingle implements Function {
@Override
public abstract boolean equals(Object o);
@Override
public String toString() {
return this.getClass().getSimpleName() + "(" + getParameter() + ")";
}
}

View File

@ -2,6 +2,7 @@ package it.cavallium.warppi.math.functions;
import it.cavallium.warppi.gui.expression.blocks.Block;
import it.cavallium.warppi.gui.expression.blocks.BlockChar;
import it.cavallium.warppi.gui.expression.blocks.BlockNumericChar;
import it.cavallium.warppi.gui.expression.blocks.BlockParenthesis;
import it.cavallium.warppi.math.*;
import it.cavallium.warppi.util.Error;
@ -64,7 +65,7 @@ public class Multiplication extends FunctionOperator {
} else {
result.addAll(sub1);
}
if (nearLeft instanceof BlockChar && nearRight instanceof BlockChar && !(par2 instanceof Negative) && !(par1 instanceof Number && par2 instanceof Number) && !(par1 instanceof Number && par2 instanceof Multiplication && ((Multiplication)par2).getParameter1() instanceof Number)) {
if (nearLeft instanceof BlockChar && nearRight instanceof BlockChar && !(nearLeft instanceof BlockNumericChar && nearRight instanceof BlockNumericChar) && !(par2 instanceof Negative) && !(par1 instanceof Number && par2 instanceof Number) && !(par1 instanceof Number && par2 instanceof Multiplication && ((Multiplication)par2).getParameter1() instanceof Number)) {
} else {
result.add(new BlockChar(MathematicalSymbols.MULTIPLICATION));

View File

@ -4,13 +4,9 @@ import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.LinkedList;
import it.cavallium.warppi.gui.expression.blocks.*;
import org.nevec.rjm.BigDecimalMath;
import it.cavallium.warppi.gui.expression.blocks.Block;
import it.cavallium.warppi.gui.expression.blocks.BlockChar;
import it.cavallium.warppi.gui.expression.blocks.BlockContainer;
import it.cavallium.warppi.gui.expression.blocks.BlockExponentialNotation;
import it.cavallium.warppi.gui.expression.blocks.BlockPower;
import it.cavallium.warppi.math.Function;
import it.cavallium.warppi.math.MathContext;
import it.cavallium.warppi.math.rules.Rule;
@ -256,10 +252,10 @@ public class Number implements Function {
final BlockPower bp = new BlockExponentialNotation();
final BlockContainer bpec = bp.getExponentContainer();
for (final char c : numberParts[0].toCharArray()) {
result.add(new BlockChar(c));
result.add(new BlockNumericChar(c));
}
for (final char c : numberParts[1].toCharArray()) {
bpec.appendBlockUnsafe(new BlockChar(c));
bpec.appendBlockUnsafe(new BlockNumericChar(c));
} ;
bpec.recomputeDimensions();
bp.recomputeDimensions();
@ -267,7 +263,7 @@ public class Number implements Function {
return result;
} else {
for (final char c : numberString.toCharArray()) {
result.add(new BlockChar(c));
result.add(new BlockNumericChar(c));
}
}
return result;

View File

@ -5,33 +5,37 @@ import it.cavallium.warppi.gui.expression.blocks.BlockContainer;
import it.cavallium.warppi.gui.expression.blocks.BlockSquareRoot;
import it.cavallium.warppi.math.Function;
import it.cavallium.warppi.math.FunctionOperator;
import it.cavallium.warppi.math.FunctionSingle;
import it.cavallium.warppi.math.MathContext;
import it.cavallium.warppi.util.Error;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
public class RootSquare extends FunctionOperator {
public class RootSquare extends FunctionSingle {
public RootSquare(final MathContext root, final Function value2) {
super(root, new Number(root, 2), value2);
private final Number degree;
public RootSquare(final MathContext root, final Function value) {
super(root, value);
this.degree = new Number(root, 2);
}
@Override
public boolean equals(final Object o) {
if (o instanceof RootSquare) {
final FunctionOperator f = (FunctionOperator) o;
return parameter1.equals(f.getParameter1()) && parameter2.equals(f.getParameter2());
final RootSquare f = (RootSquare) o;
return parameter.equals(f.getParameter());
}
return false;
}
@Override
public RootSquare clone() {
return new RootSquare(mathContext, parameter2 == null ? null : parameter2.clone());
return new RootSquare(mathContext, parameter == null ? null : parameter.clone());
}
@Override
public RootSquare clone(MathContext c) {
return new RootSquare(c, parameter2 == null ? null : parameter2.clone(c));
return new RootSquare(c, parameter == null ? null : parameter.clone(c));
}
@Override
@ -39,7 +43,7 @@ public class RootSquare extends FunctionOperator {
final ObjectArrayList<Block> result = new ObjectArrayList<>();
final BlockSquareRoot bsqr = new BlockSquareRoot();
final BlockContainer bsqrc = bsqr.getNumberContainer();
for (final Block b : getParameter2().toBlock(context)) {
for (final Block b : getParameter().toBlock(context)) {
bsqrc.appendBlockUnsafe(b);
}
bsqrc.recomputeDimensions();
@ -52,4 +56,8 @@ public class RootSquare extends FunctionOperator {
public <Argument, Result> Result accept(final Function.Visitor<Argument, Result> visitor, final Argument argument) {
return visitor.visit(this, argument);
}
public Number getDegree() {
return degree;
}
}

View File

@ -1,8 +1,8 @@
package it.cavallium.warppi.math.rules;
import it.cavallium.warppi.WarpPI;
import it.cavallium.warppi.Platform;
import it.cavallium.warppi.Platform.ConsoleUtils;
import it.cavallium.warppi.WarpPI;
import it.cavallium.warppi.math.Function;
import it.cavallium.warppi.math.MathContext;
import it.cavallium.warppi.math.functions.Expression;
@ -24,9 +24,10 @@ public class RulesManager {
public static ObjectArrayList<Rule>[] rules;
private RulesManager() {}
private RulesManager() {
}
@SuppressWarnings({ "unchecked" })
@SuppressWarnings({"unchecked"})
public static void initialize() {
WarpPI.getPlatform().getConsoleUtils().out().println(ConsoleUtils.OUTPUTLEVEL_NODEBUG, "RulesManager", "Loading the rules");
RulesManager.rules = new ObjectArrayList[RuleType.values().length];
@ -59,6 +60,7 @@ public class RulesManager {
new NumberRule(),
new PowerRule(),
new RootRule(),
new RootSquareRule(),
new SubtractionRule(),
new SumRule(),
new SumSubtractionRule(),

View File

@ -35,8 +35,8 @@ public class RootPattern extends VisitorPattern {
@Override
public Boolean visit(final RootSquare rootSquare, final Map<String, Function> subFunctions) {
return degree.match(rootSquare.getParameter1(), subFunctions)
&& radicand.match(rootSquare.getParameter2(), subFunctions);
return degree.match(rootSquare.getDegree(), subFunctions)
&& radicand.match(rootSquare.getParameter(), subFunctions);
}
@Override

View File

@ -46,6 +46,14 @@ public class MultiplicationRule implements Rule {
//multiply a by b (a*b = c)
result.add(((Number) variable1).multiply((Number) variable2));
return result;
} else if (!(variable1 instanceof Number) && variable2 instanceof Number) {
//fix order: x*n -> n*x
result.add(new Multiplication(f.getMathContext(), variable2, variable1));
return result;
} else if (!(variable1 instanceof Multiplication) && variable2 instanceof Multiplication) {
//fix order: x*(y*z) -> (x*y)*z
result.add(new Multiplication(f.getMathContext(), new Multiplication(f.getMathContext(), variable1, ((Multiplication) variable2).getParameter1()), ((Multiplication) variable2).getParameter2()));
return result;
}
}
return null;

View File

@ -46,8 +46,7 @@ public class RootRule implements Rule {
*/
@Override
public ObjectArrayList<Function> execute(final Function f) throws Error, InterruptedException {
boolean isSquare = false;
if ((isSquare = f instanceof RootSquare) || f instanceof Root) {
if (f instanceof Root) {
final ObjectArrayList<Function> result = new ObjectArrayList<>();
final MathContext mathContext = f.getMathContext();
final Function variable1 = ((FunctionOperator) f).getParameter1();
@ -69,7 +68,7 @@ public class RootRule implements Rule {
throw (Error) new Error(Errors.ERROR, ex.getMessage()).initCause(ex);
}
}
if (!isSquare && !isSolvable && variable1 instanceof Number && variable1.equals(new Number(mathContext, 2)))
if (!isSolvable && variable1 instanceof Number && variable1.equals(new Number(mathContext, 2)))
canBePorted = true;
if (isSolvable) {

View File

@ -0,0 +1,79 @@
package it.cavallium.warppi.math.rules.functions;
/*
SETTINGS: (please don't move this part)
PATH=functions.RootSquareRule
*/
import it.cavallium.warppi.math.Function;
import it.cavallium.warppi.math.FunctionOperator;
import it.cavallium.warppi.math.MathContext;
import it.cavallium.warppi.math.functions.Number;
import it.cavallium.warppi.math.functions.Root;
import it.cavallium.warppi.math.functions.RootSquare;
import it.cavallium.warppi.math.rules.Rule;
import it.cavallium.warppi.math.rules.RuleType;
import it.cavallium.warppi.util.Error;
import it.cavallium.warppi.util.Errors;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import java.math.BigDecimal;
import java.math.BigInteger;
/**
* Root Square
* b = c
*
* @author Andrea Cavalli
*
*/
public class RootSquareRule implements Rule {
// Rule name
@Override
public String getRuleName() {
return "RootSquare";
}
// Rule type
@Override
public RuleType getRuleType() {
return RuleType.CALCULATION;
}
/* Rule function
Returns:
- null if it's not executable on the function "f"
- An ObjectArrayList<Function> if it did something
*/
@Override
public ObjectArrayList<Function> execute(final Function f) throws Error, InterruptedException {
if (f instanceof RootSquare) {
final ObjectArrayList<Function> result = new ObjectArrayList<>();
final MathContext mathContext = f.getMathContext();
final Function variable = ((RootSquare) f).getParameter();
final var degree = ((RootSquare) f).getDegree();
boolean isSolvable = false, canBePorted = false;
if (variable instanceof Number) {
/*if (mathContext.exactMode) {
result.add(((Number) variable).pow(new Number(mathContext, BigDecimal.ONE).divide(degree)));
return result;
}*/
isSolvable = isSolvable | !mathContext.exactMode;
if (!isSolvable)
try {
final Number resultVar = ((Number) variable).pow(new Number(mathContext, BigDecimal.ONE).divide(degree));
final Function originalVariable = resultVar.pow(new Number(mathContext, 2));
if (originalVariable.equals(((RootSquare) f).getParameter()))
isSolvable = true;
} catch (final Exception ex) {
throw (Error) new Error(Errors.ERROR, ex.getMessage()).initCause(ex);
}
}
if (isSolvable) {
result.add(((Number) variable).pow(new Number(mathContext, BigInteger.ONE).divide(degree)));
return result;
}
}
return null;
}
}

View File

@ -87,7 +87,8 @@ public class MathSolver {
if (WarpPI.getPlatform().getSettings().isDebugEnabled()) {
WarpPI.getPlatform().getConsoleUtils().out().println(ConsoleUtils.OUTPUTLEVEL_DEBUG_VERBOSE, "Math Solver", stepName, currFnc + " is " + (checkEquals(currFnc, lastFunctions[1][endStepState]) ? "" : "not ") + "equals to [1]:" + lastFunctions[1][endStepState]);
}
} while (consecutiveNullSteps < stepStates.length && !checkEquals(currFnc, lastFunctions[0][endStepState]) && !checkEquals(currFnc, lastFunctions[1][endStepState]));
//todo: check if the while condition is good with the OR or the AND in the second part. Before it was AND but it was terminating if it can do only two consecutive reductions, right before the second.
} while (consecutiveNullSteps < stepStates.length && (!checkEquals(currFnc, lastFunctions[0][endStepState]) || !checkEquals(currFnc, lastFunctions[1][endStepState])));
if (consecutiveNullSteps >= stepStates.length) {
WarpPI.getPlatform().getConsoleUtils().out().println(ConsoleUtils.OUTPUTLEVEL_DEBUG_VERBOSE, "Math Solver", "Loop ended because " + consecutiveNullSteps + " >= " + stepStates.length);
} else if (checkEquals(currFnc, lastFunctions[0][endStepState])) {

View File

@ -4,8 +4,6 @@ import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;
import it.cavallium.warppi.WarpPI;
import it.cavallium.warppi.StaticVars;
@ -59,7 +57,7 @@ public class SwingEngine implements GraphicEngine {
r = new SwingRenderer();
g = new BufferedImage(r.size[0], r.size[1], BufferedImage.TYPE_INT_RGB);
initialized = false;
INSTANCE = new SwingWindow(this, defaultWidth, defaultHeight);
INSTANCE = new SwingWindow(r, g, this::destroyEngine, defaultWidth, defaultHeight);
setResizable(WarpPI.getPlatform().getSettings().isDebugEnabled());
INSTANCE.setVisible(true);
initialized = true;
@ -119,7 +117,7 @@ public class SwingEngine implements GraphicEngine {
@Deprecated()
public void refresh() {
if (WarpPI.INSTANCE.getHardwareDevice().getDisplayManager().getScreen() == null || WarpPI.INSTANCE.getHardwareDevice().getDisplayManager().error != null && WarpPI.INSTANCE.getHardwareDevice().getDisplayManager().error.length() > 0 || WarpPI.INSTANCE.getHardwareDevice().getDisplayManager().getScreen() == null || WarpPI.INSTANCE.getHardwareDevice().getDisplayManager().getScreen().mustBeRefreshed()) {
if (WarpPI.INSTANCE.getHardwareDevice().getDisplayManager().getScreen() == null || WarpPI.INSTANCE.getHardwareDevice().getDisplayManager().error != null && WarpPI.INSTANCE.getHardwareDevice().getDisplayManager().error.length() > 0 || WarpPI.INSTANCE.getHardwareDevice().getDisplayManager().getScreen().mustBeRefreshed()) {
INSTANCE.c.paintImmediately(0, 0, getWidth(), getHeight());
}
}

View File

@ -19,9 +19,11 @@ public class SwingWindow extends JFrame {
private static final long serialVersionUID = 2945898937634075491L;
private final int defaultWidth;
private final int defaultHeight;
private final SwingRenderer renderer;
private final Runnable destroyEngine;
private BufferedImage graphics;
public CustomCanvas c;
private RenderingLoop renderingLoop;
private final SwingEngine display;
private int mult = 1;
private final EventSubmitter<Integer[]> onResize;
private final EventSubmitter<Integer[]> onResize$;
@ -31,8 +33,10 @@ public class SwingWindow extends JFrame {
private volatile boolean windowShown;
private volatile boolean forceRepaint;
public SwingWindow(final SwingEngine disp, int defaultWidth, int defaultHeight) {
display = disp;
public SwingWindow(final SwingRenderer renderer, final BufferedImage graphics, Runnable destroyEngine, int defaultWidth, int defaultHeight) {
this.renderer = renderer;
this.graphics = graphics;
this.destroyEngine = destroyEngine;
this.defaultWidth = defaultWidth;
this.defaultHeight = defaultHeight;
setLayout(new BorderLayout());
@ -75,16 +79,16 @@ public class SwingWindow extends JFrame {
if (newSize[1] <= 0)
newSize[1] = 1;
var oldSize = disp.r.size;
disp.r.size = new int[]{newSize[0], newSize[1]};
var oldSize = renderer.size;
renderer.size = new int[]{newSize[0], newSize[1]};
SwingRenderer.canvas2d = new int[disp.r.size[0] * disp.r.size[1]];
var oldG = disp.g;
disp.g = new BufferedImage(disp.r.size[0], disp.r.size[1], BufferedImage.TYPE_INT_RGB);
Graphics2D g = (Graphics2D) disp.g.getGraphics();
SwingRenderer.canvas2d = new int[renderer.size[0] * renderer.size[1]];
var oldG = graphics;
this.graphics = new BufferedImage(renderer.size[0], renderer.size[1], BufferedImage.TYPE_INT_RGB);
Graphics2D g = (Graphics2D) graphics.getGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g.setColor(Color.BLACK);
g.clearRect(0, 0, disp.r.size[0], disp.r.size[1]);
g.clearRect(0, 0, renderer.size[0], renderer.size[1]);
double oldRatio = (double) oldSize[0] / (double) oldSize[1];
double newRatio = (double) newSize[0] / (double) newSize[1];
int newFrameWidth;
@ -98,7 +102,7 @@ public class SwingWindow extends JFrame {
}
g.drawImage(oldG, 0, 0, newFrameWidth, newFrameHeight, null);
forceRepaint = true;
display.repaint();
this.c.repaint();
return newSize;
});
@ -147,11 +151,9 @@ public class SwingWindow extends JFrame {
}
});
StaticVars.windowZoom$.subscribe((newZoomValue) -> {
if (newZoomValue != mult) {
mult = (int) newZoomValue.floatValue();
onResize.submit(new Integer[]{getWWidth(), getWHeight()});
WarpPI.getPlatform().getConsoleUtils().out().println(3, "Engine", "CPU", "Zoom changed");
}
});
}
@ -209,7 +211,7 @@ public class SwingWindow extends JFrame {
b.setText(Keyboard.getKeyName(row, col));
b.setBasicForeground(Color.BLACK);
Font f = b.getFont();
f = f.deriveFont(Font.BOLD, BTN_SIZE / 3);
f = f.deriveFont(Font.BOLD, BTN_SIZE / 3f);
b.setFont(f);
b.setBackground(new Color(200, 200, 200));
b.setFocusable(true);
@ -334,7 +336,7 @@ public class SwingWindow extends JFrame {
}
public void sendPowerOffSignal() {
display.destroyEngine();
destroyEngine.run();
this.setVisible(false);
this.dispose();
}
@ -357,10 +359,10 @@ public class SwingWindow extends JFrame {
renderingLoop.refresh(forceRepaint);
final int[] a = ((DataBufferInt) display.g.getRaster().getDataBuffer()).getData();
final int[] a = ((DataBufferInt) graphics.getRaster().getDataBuffer()).getData();
SwingRenderer.canvas2d = a;
g.clearRect(0, 0, display.r.size[0] * mult, display.r.size[1] * mult);
g.drawImage(display.g, 0, 0, display.r.size[0] * mult, display.r.size[1] * mult, null);
g.clearRect(0, 0, renderer.size[0] * mult, renderer.size[1] * mult);
g.drawImage(graphics, 0, 0, renderer.size[0] * mult, renderer.size[1] * mult, null);
// long time2 = System.nanoTime();
// double timeDelta = ((double)(time2-time1))/1000000000d;
// double mediaAttuale = timeDelta;

View File

@ -28,3 +28,14 @@ reduction ExponentRule16c:
expansion ExponentRule17:
root(a, x) -> x ^ (1 / a)
reduction ExponentRule18:
(a * b) * b -> a * (b^2)
reduction ExponentRule18a:
(a * (b^c)) * b -> a * (b^(c + 1))
reduction ExponentRule18b:
(a * b) * (b^c) -> a * (b^(c + 1))
reduction ExponentRule18c:
(a * (b^c)) * (b^d) -> a * (b^(c + d))
reduction ExponentRule18d:
(a * (b^2)) * b -> a * (b^3)

View File

@ -54,3 +54,9 @@ expansion FractionsRule14b:
(a / b) * c -> (a * c) / b
expansion FractionsRule14c:
a * (c / d) -> (a * c) / d
reduction FractionsRule15:
(a / b) ^ 2 -> (a * a) / (b * b)
reduction FractionsRule16:
(a / b) ^ c -> (a ^ c) / (b ^ c)