/*
* Copyright (C) 2011 Alasdair C. Hamilton
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package ket.math;
import geom.Offset;
import geom.Position;
import java.awt.*;
import java.util.*;
import ket.display.ColourScheme;
import ket.display.ColourSchemeDecorator;
import ket.math.Argument;
import ket.math.purpose.IntegerValue;
import ket.math.purpose.Text;
/**
* Often argument transformations are of interest that go far beyond the level
* of detail that can be provided by Argument, Branch, Token etc, so this more
* involved functionality is provided here.
*/
public class ArgumentFactory {
public static Branch textToParagraph(String text) { // Chop up into sentences.
String[] parts = text.split("(?<=[\\?\\.!]) "); // TODO: ? or ! or .
Branch paragraph = new Branch(Function.PARAGRAPH);
for (String p : parts) {
String t = p.trim();
if (t.length()>0) {
paragraph.append(new Token(new Text(t)));
}
}
return paragraph;
}
public static Branch textToSentence(String text) { // Chop up into phrases.
String[] parts = text.split("(?<=[;,:-])");
Branch sentence = new Branch(Function.SENTENCE);
for (String p : parts) {
String t = p.trim();
if (t.length()>0) {
sentence.append(new Token(new Text(t))); // TODO: Remember the joining symbol.
}
}
return sentence;
}
public static Branch textToPhrase(String text) { // Chop up into words.
String[] parts = text.split("\\s");
Branch paragraph = new Branch(Function.PHRASE);
for (String p : parts) {
String t = p.trim();
if (t.length()>0) {
paragraph.append(new Token(new Text(t)));
}
}
return paragraph;
}
/**
* If the given argument is of the form branch'POWER'[mantissa,
* exponent], return exponent, and otherwise return null.
*/
private static Argument getExponent(Argument argument) {
if (argument.getFunction()==Function.POWER) {
Branch power = (Branch) argument;
Argument exponent = power.lastChild();
if (power.size()==2) {
return exponent;
}
}
return null;
}
/**
* If the given argument is an integer value token then return its
* value, otherwise return null.
*/
private static Integer getIntegerValue(Argument argument) {
if (argument==null) {
return null;
}
State state = argument.getState();
if (state instanceof IntegerValue) {
IntegerValue integerValue = (IntegerValue) state;
int value = integerValue.getInt();
return new Integer(value);
} else {
return null;
}
}
/**
* Return the order to which the given derivative is raised to of that
* order is a function so integers orders over zero are ignored.
*/
private static Argument getFunctionOrder(Argument derivative) {
Argument exponent = getExponent(derivative);
if (exponent==null) {
return null;
}
Integer intExponent = getIntegerValue(exponent);
if (intExponent==null) {
return exponent;
}
int value = intExponent.intValue();
if (value < 0) {
return exponent;
} else {
return null;
}
}
/**
* Search through the list of derivatives for non-integer (or
* non-positive) exponents and return them as in a vector.
*/
private static Vector<Argument> findFunctionOrder(int index, Vector<Argument> args) {
Vector<Argument> orderVector = new Vector<Argument>();
for (int i=index; i<args.size(); i++) {
Argument order = getFunctionOrder(args.get(i));
if (order!=null) {
orderVector.add(order);
}
}
return orderVector;
}
/**
* Given a variable, possibly raised to an arbitrary order, return
* either its value or null if the order is non-integer or
* not positive.
*/
private static Integer findIntOrder(Argument derivative) {
Argument order = getExponent(derivative);
if (order==null) {
// x
return 1;
}
Integer intExponent = getIntegerValue(order);
if (intExponent==null) {
// x^function
return null;
}
// Integer powers: e.g. x^2, x^0 or x^(-2).
int value = intExponent.intValue();
return (value>0) ? value : null;
}
private static int findIntOrder(int index, Vector<Argument> args) {
int total = 0;
for (int i=index; i<args.size(); i++) {
Integer order = findIntOrder(args.get(i));
if (order!=null) {
total += order.intValue();
}
}
return total;
}
/**
* Given a vector of arguments with which to differentiate, return an
* argument of order of differentiation: integer, function or
* combination thereof.
*/
public static Argument getOrderArgument(int lowestDerivativeIndex, Vector<Argument> args) {
// When differentiating, the combined order of derivatives is
// displayed on the numerator (i.e. d^?). Here it is split
// into integer and function parts.
int intOrder = findIntOrder(lowestDerivativeIndex, args);
Vector<Argument> orderVector = findFunctionOrder(lowestDerivativeIndex, args);
// Combine integer and non-integer derivative orders into a single argument.
if (intOrder==1 && orderVector.size()==0) { // first derivative
return null;
} else if (intOrder>1 && orderVector.size()==0) { // Only numbers.
return new Token(intOrder);
} else if (intOrder==1 && orderVector.size()==1) { // Only a single function.
return orderVector.firstElement();
} else { // Sum of two or more functions or the combination of one or more functions and a given power.
if (intOrder>1) {
orderVector.add(new Token(intOrder));
}
Branch orderBranch = new Branch(Function.ADD);
for (Argument next : orderVector) {
Argument clone = Argument.cloneArgument(next);
orderBranch.append(clone);
}
if (orderVector.size()==1) {
return orderBranch.firstChild();
}
return orderBranch;
}
}
}