1. petermr
  2. mathml

Commits

petermr  committed 1f7a47e

added many math functions (e.g. COS) and also differentiation

  • Participants
  • Parent commits af45181
  • Branches default

Comments (0)

Files changed (22)

File src/main/java/org/xmlcml/mathml/APPLYElement.java

View file
  • Ignore whitespace
 import nu.xom.Elements;
 import nu.xom.Node;
 
-public class APPLYElement extends AbstractMathElement {
+public class APPLYElement extends AbstractMathElement implements Differentiable {
 
 	public static String TAG = "apply";
 	
 		super(xml);
 	}
 
+	public APPLYElement(Operator operator,
+			AbstractMathElement arg) {
+		this();
+		this.appendChild((AbstractMathElement)operator);
+		this.appendNonOperator(arg);
+	}
+
+	public APPLYElement(Operator operator,
+			AbstractMathElement arg0,
+			AbstractMathElement arg1) {
+		this();
+		this.appendChild((AbstractMathElement)operator);
+		this.appendNonOperator(arg0);
+		this.appendNonOperator(arg1);
+	}
+	
+	private void appendNonOperator(AbstractMathElement arg) {
+		if (arg instanceof Operator) {
+			throw new RuntimeException("Cannot have operator as argument of operator");
+		}
+		this.appendChild(arg);
+	}
 	public Object eval() {
 		Elements childElements = this.getChildElements();
 		if (this.getChildCount() == 0) {
 		}
 		return result;
 	}
+	
+	public AbstractMathElement differentiate() {
+		Elements childElements = this.getChildElements();
+		if (childElements.size() < 2) {
+			throw new RuntimeException("not enough args to differentiate");
+		}
+		Differentiable diff = ((AbstractMathElement) childElements.get(0)).castToDifferentiable(); 
+		return diff.differentiate();
+	}
+	
 }

File src/main/java/org/xmlcml/mathml/AbstractMathElement.java

View file
  • Ignore whitespace
 package org.xmlcml.mathml;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import nu.xom.Element;
+import nu.xom.Elements;
 import nu.xom.Node;
 
 import org.xmlcml.cml.base.CMLUtil;
 
 	public abstract Object eval();
 	
+	protected List<AbstractMathElement> getFollowingElements(int count) {
+		return getFollowingElements(count,  count);
+	}
+	
+	protected List<AbstractMathElement> getFollowingElements(int min, int max) {
+		Element parent = (Element) this.getParent();
+		Elements childElements = parent.getChildElements();
+		// count only following elements
+		if (childElements.size() <= min || childElements.size() > max+1) {
+			throw new RuntimeException(
+					"bad number of following elements "+min+" > "+(childElements.size()-1)+" > "+max);
+		}
+		List<AbstractMathElement> followingList = new ArrayList<AbstractMathElement>();
+		// omit the element itself
+		for (int i = 1; i < childElements.size(); i++) {
+			followingList.add((AbstractMathElement) childElements.get(i));
+		}
+		return followingList;
+	}
+	
+	public Differentiable castToDifferentiable() {
+		if (this instanceof Differentiable) {
+			return (Differentiable) this;
+		}
+		throw new RuntimeException(""+this.getClass()+" is not differentiable");
+	}
+	
 }

File src/main/java/org/xmlcml/mathml/BVARElement.java

View file
  • Ignore whitespace
 	public Object eval() {
 		throw new RuntimeException("NYI");
 	}
+	
+	public AbstractMathElement differentiate() {
+		throw new RuntimeException("NYI/meaningless");
+	}
+	
 }

File src/main/java/org/xmlcml/mathml/CIElement.java

View file
  • Ignore whitespace
 	}
 
 	public Object eval() {
-		Object obj = null;
+		Object obj = null;		
 		if (this.getChildCount() == 1 && this.getChildElements().size() == 0) {
 			// String content
 			obj = this.getValue();
-			if (obj instanceof String) {
-				MATHElement math = MATHElement.getRootMATHElement(this);
-				if (math != null) {
-					Object obj1 = math.getValueOfSymbol((String) obj);
-					if (obj1 != null) {
-						obj = obj1;
-					}
-				} else {
+			MATHElement math = MATHElement.getRootMATHElement(this);
+			if (math != null) {
+				Object obj1 = math.getValueOfSymbol((String) obj);
+				if (obj1 != null) {
+					obj = obj1;
+				}
+			} else {
 //					System.err.println("Cannot find symbol: "+obj);
-				}
 			}
 			
 		} else if (this.getChildCount() == 1 && this.getChildElements().size() == 1 &&
 		return obj;
 	}
 
+
+	public AbstractMathElement differentiate() {
+		AbstractMathElement diff = null;
+		if (this.getChildCount() == 1 && this.getChildElements().size() == 0) {
+			// text only
+			diff = new CNElement(0);
+		} else if (this.getChildElements().size() == 1 &&
+			this.getChild(0) instanceof APPLYElement) {
+			// APPLYElement child
+			diff = ((APPLYElement) this.getChild(0)).differentiate();
+		} else {
+			System.err.println(this.getChildCount()+" : "+this.getChildElements().size());
+			CMLUtil.debug(this, "CI");
+			throw new RuntimeException("<ci/> requires String value or single <apply/> child");
+		}
+		return diff;
+	}
 }

File src/main/java/org/xmlcml/mathml/CNElement.java

View file
  • Ignore whitespace
 package org.xmlcml.mathml;
 
-public class CNElement extends AbstractMathElement {
+import nu.xom.Text;
+
+public class CNElement extends AbstractMathElement implements Differentiable {
 
 	public static String TAG = "cn";
 	
 	public CNElement(String xml) {
 		super(xml);
 	}
+	
+	/**
+	 * create an integer
+	 * @param i
+	 */
+	public CNElement(int i) {
+		this();
+		this.appendChild(new Text(""+i));
+	}
+	
+	/**
+	 * create a double
+	 * @param d
+	 */
+	public CNElement(double d) {
+		this();
+		this.appendChild(new Text(""+d));
+	}
+	
 	public Object eval() {
 		Number num;
 		if (this.getChildCount() != 1 && this.getChildElements().size() != 0) {
 		return num;
 	}
 
+	public AbstractMathElement differentiate() {
+		CNElement zero = new CNElement(0);
+		return zero;
+	}
 }

File src/main/java/org/xmlcml/mathml/COSElement.java

View file
  • Ignore whitespace
+package org.xmlcml.mathml;
+
+import java.util.List;
+
+import nu.xom.Elements;
+
+public class COSElement extends AbstractMathElement implements Operator, Differentiable {
+
+	public static String TAG = "cos";
+	
+	public COSElement() {
+		super(TAG);
+	}
+	public COSElement(String xml) {
+		super(xml);
+	}
+	public COSElement(AbstractMathElement elem) {
+		this();
+		throw new RuntimeException("NYI");
+	}
+	public Object eval() {
+		throw new RuntimeException("NYI");
+	}
+
+	public Object apply(Elements elements) {
+		if (elements.size() == 2) {
+			Object o1 = ((AbstractMathElement)elements.get(1)).eval();
+			if (o1 instanceof Double) {
+				return Math.cos((Double) o1);
+			} else if (o1 instanceof Integer) {
+				return Math.cos(new Double((Integer) o1));
+			} else {
+				return "(cos("+o1.toString()+"))";
+			}
+		} else {
+			throw new RuntimeException("<cos/> takes one arguments");
+		}
+	}
+	
+	public AbstractMathElement differentiate() {
+		List<AbstractMathElement> following = getFollowingElements(1);
+		APPLYElement result = new APPLYElement(
+			new TIMESElement(),
+			((Differentiable)following.get(0)).differentiate(),
+			new APPLYElement(new SINElement(), AbstractMathElement.copyElement(following.get(0)))
+			);
+		return new APPLYElement(
+			new MINUSElement(),
+			result
+			);
+	}
+	
+}

File src/main/java/org/xmlcml/mathml/DIFFElement.java

View file
  • Ignore whitespace
 //		}
 		throw new RuntimeException("NYI");
 	}
+	
+	public AbstractMathElement differentiate() {
+		throw new RuntimeException("NYI/meaningless");
+	}
+	public Differentiable castToDifferentiable(AbstractMathElement abstractMathElement) {
+		return null;
+	}
+	
 }

File src/main/java/org/xmlcml/mathml/DIVIDEElement.java

View file
  • Ignore whitespace
 package org.xmlcml.mathml;
 
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.management.RuntimeErrorException;
+
+import nu.xom.Element;
 import nu.xom.Elements;
 
-public class DIVIDEElement extends AbstractMathElement implements Operator {
+public class DIVIDEElement extends AbstractMathElement implements Operator, Differentiable {
 
 	public static String TAG = "divide";
 	
 		}
 	}
 
+	public AbstractMathElement differentiate() {
+		List<AbstractMathElement> following = getFollowingElements(2);
+		Differentiable num = following.get(0).castToDifferentiable();
+		Differentiable den = following.get(1).castToDifferentiable();
+		AbstractMathElement newNum0 = new APPLYElement(
+				new TIMESElement(), AbstractMathElement.copyElement((AbstractMathElement) den),
+				num.differentiate());
+		AbstractMathElement newNum1 = new APPLYElement(
+				new TIMESElement(), AbstractMathElement.copyElement((AbstractMathElement) num),
+				den.differentiate());
+		AbstractMathElement newNum = new APPLYElement(
+				new MINUSElement(), 
+				newNum0, 
+				newNum1);
+		AbstractMathElement newDen = new APPLYElement(
+				new POWERElement(), 
+				AbstractMathElement.copyElement((AbstractMathElement) den), 
+				new CNElement(2)
+				);
+
+		APPLYElement result = new APPLYElement(
+				new DIVIDEElement(),
+				newNum,
+				newDen
+				);
+		return result;
+	}
+	
 }

File src/main/java/org/xmlcml/mathml/Differentiable.java

View file
  • Ignore whitespace
+package org.xmlcml.mathml;
+
+public interface Differentiable {
+	AbstractMathElement differentiate();
+}

File src/main/java/org/xmlcml/mathml/EQElement.java

View file
  • Ignore whitespace
 		return true;
 	}
 
+	public Differentiable castToDifferentiable(AbstractMathElement abstractMathElement) {
+		return null;
+	}
+
+	
+
 }

File src/main/java/org/xmlcml/mathml/EXPElement.java

View file
  • Ignore whitespace
 package org.xmlcml.mathml;
 
+import java.util.List;
+
 import nu.xom.Elements;
 
-public class EXPElement extends AbstractMathElement implements Operator {
+public class EXPElement extends AbstractMathElement implements Operator, Differentiable {
 
 	public static String TAG = "exp";
 	
 			throw new RuntimeException("<minus/> takes one/two arguments");
 		}
 	}
+	
+	public AbstractMathElement differentiate() {
+		List<AbstractMathElement> following = getFollowingElements(1);
+		APPLYElement result = new APPLYElement(
+				new TIMESElement(),
+				((Differentiable) following.get(0)).differentiate(),
+				new APPLYElement(new EXPElement(), AbstractMathElement.copyElement(following.get(0)))
+				);
+		return result;
+	}
+	
+	
 }

File src/main/java/org/xmlcml/mathml/Operator.java

View file
  • Ignore whitespace
 	 * @param elements
 	 */
 	Object apply(Elements elements);
+
+	Differentiable castToDifferentiable();
+
 }

File src/main/java/org/xmlcml/mathml/POWERElement.java

View file
  • Ignore whitespace
 		base = ((AbstractMathElement)elements.get(1)).eval();
 		exponent = ((AbstractMathElement)elements.get(2)).eval();
 	}
-	
-//	public AbstractMathElement createDerivative() {
-//		if (exponent instanceof Number) {
-//			if (base instanceof Number)
-//			return Math.pow((Double) base,  (Double) exponent);
-//		} else if (base instanceof Double && exponent instanceof Integer) {
-//			return Math.pow((Double) base,  new Double((Integer)exponent));
-//		} else if (base instanceof Integer && base instanceof Double) {
-//			return Math.pow(new Double((Integer)base), (Double) exponent);
-//		} else if (base instanceof Integer && base instanceof Integer) {
-//			return new Integer((int)(Math.pow(new Double((Integer)base), new Double((Integer)exponent))));
-//		} else {
-//			return "("+base.toString()+"^"+exponent.toString()+")";
-//		}
-//	}
 
 }

File src/main/java/org/xmlcml/mathml/SINElement.java

View file
  • Ignore whitespace
+package org.xmlcml.mathml;
+
+import java.util.List;
+
+import nu.xom.Elements;
+
+public class SINElement extends AbstractMathElement implements Operator, Differentiable {
+
+	public static String TAG = "sin";
+	
+	public SINElement() {
+		super(TAG);
+	}
+	public SINElement(String xml) {
+		super(xml);
+	}
+	public SINElement(AbstractMathElement elem) {
+		this();
+		throw new RuntimeException("NYI");
+	}
+	public Object eval() {
+		throw new RuntimeException("NYI");
+	}
+
+	public Object apply(Elements elements) {
+		if (elements.size() == 2) {
+			Object o1 = ((AbstractMathElement)elements.get(1)).eval();
+			if (o1 instanceof Double) {
+				return Math.sin((Double) o1);
+			} else if (o1 instanceof Integer) {
+				return Math.sin(new Double((Integer) o1));
+			} else {
+				return "(sin("+o1.toString()+"))";
+			}
+		} else {
+			throw new RuntimeException("<sin/> takes one arguments");
+		}
+	}
+	
+	public AbstractMathElement differentiate() {
+		List<AbstractMathElement> following = getFollowingElements(1);
+		APPLYElement result = new APPLYElement(
+			new TIMESElement(),
+			((Differentiable)following.get(0)).differentiate(),
+			new APPLYElement(new COSElement(), AbstractMathElement.copyElement(following.get(0)))
+			);
+		return result;
+	}
+	
+	
+}

File src/main/java/org/xmlcml/mathml/TIMESElement.java

View file
  • Ignore whitespace
 package org.xmlcml.mathml;
 
+import java.util.List;
+
 import nu.xom.Elements;
 
-public class TIMESElement extends AbstractMathElement implements Operator {
+import org.xmlcml.cml.base.CMLUtil;
+
+public class TIMESElement extends AbstractMathElement implements Operator, Differentiable {
 
 	public static String TAG = "times";
 	
 	public Object eval() {
 		throw new RuntimeException("NYI");
 	}
-	
+
+	/**
+	 * although MathML allows chaing of operands we don't yet
+	 */
 	public Object apply(Elements elements) {
 		if (elements.size() != 3) {
 			throw new RuntimeException("<times/> takes two arguments");
 			return "("+o1.toString()+"*"+o2.toString()+")";
 		}
 	}
-
+	
+	public AbstractMathElement differentiate() {
+		List<AbstractMathElement> args = getFollowingElements(2, 2);
+		Differentiable argD0 = args.get(0).castToDifferentiable();
+		AbstractMathElement d0Result = argD0.differentiate();
+		Differentiable argD1 = args.get(1).castToDifferentiable();
+		AbstractMathElement d1Result = argD1.differentiate();
+		AbstractMathElement term0 = new APPLYElement(
+				new TIMESElement(), 
+				AbstractMathElement.copyElement(args.get(0)),
+				d1Result);
+		AbstractMathElement term1 = new APPLYElement(
+				new TIMESElement(), 
+				AbstractMathElement.copyElement(args.get(1)),
+				d0Result);
+		return new APPLYElement(new PLUSElement(), term0, term1);
+	}
 
 }

File src/test/java/org/xmlcml/mathml/AbstractElementTest.java

View file
  • Ignore whitespace
+package org.xmlcml.mathml;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class AbstractElementTest {
+
+	@Test
+	public void testAbstractMathElement() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:plus/>" +
+				"<m:cn>4</m:cn>" +
+				"<m:cn>3</m:cn>" +
+				"</m:apply>";
+		AbstractMathElement ame = AbstractMathElement.createElementFromXML(ss);
+		// messy - don't use toXML for robust tests
+		Assert.assertEquals(
+				"ame", "<apply xmlns=\"http://www.w3.org/1998/Math/MathML\"><plus /><cn>4</cn><cn>3</cn></apply>", ame.toXML());
+	}
+	
+	@Test
+	public void testFollowing() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:plus/>" +
+				"<m:cn>4</m:cn>" +
+				"<m:cn>3</m:cn>" +
+				"</m:apply>";
+		AbstractMathElement ame = AbstractMathElement.createElementFromXML(ss);
+		AbstractMathElement plus = (AbstractMathElement) ame.getChildElements().get(0);
+		List<AbstractMathElement> following = plus.getFollowingElements(2);
+		Assert.assertEquals("following", 2, following.size());
+	}
+	
+	@Test
+	public void testFollowing1() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:plus/>" +
+				"<m:cn>4</m:cn>" +
+				"<m:cn>3</m:cn>" +
+				"</m:apply>";
+		AbstractMathElement ame = AbstractMathElement.createElementFromXML(ss);
+		AbstractMathElement plus = (AbstractMathElement) ame.getChildElements().get(0);
+		List<AbstractMathElement> following = plus.getFollowingElements(1,3);
+		Assert.assertEquals("following", 2, following.size());
+	}
+	
+	@Test
+	public void testFollowing2() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:plus/>" +
+				"<m:cn>4</m:cn>" +
+				"<m:cn>3</m:cn>" +
+				"</m:apply>";
+		AbstractMathElement ame = AbstractMathElement.createElementFromXML(ss);
+		AbstractMathElement plus = (AbstractMathElement) ame.getChildElements().get(0);
+		List<AbstractMathElement> following = plus.getFollowingElements(2,3);
+		Assert.assertEquals("following", 2, following.size());
+	}
+	
+	@Test
+	public void testFollowing3() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:plus/>" +
+				"<m:cn>4</m:cn>" +
+				"<m:cn>3</m:cn>" +
+				"</m:apply>";
+		AbstractMathElement ame = AbstractMathElement.createElementFromXML(ss);
+		AbstractMathElement plus = (AbstractMathElement) ame.getChildElements().get(0);
+		List<AbstractMathElement> following = plus.getFollowingElements(1,2);
+		Assert.assertEquals("following", 2, following.size());
+	}
+	
+	@Test
+	public void testFollowingBad() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:plus/>" +
+				"<m:cn>4</m:cn>" +
+				"<m:cn>3</m:cn>" +
+				"</m:apply>";
+		AbstractMathElement ame = AbstractMathElement.createElementFromXML(ss);
+		AbstractMathElement plus = (AbstractMathElement) ame.getChildElements().get(0);
+		try {
+			List<AbstractMathElement> following = plus.getFollowingElements(1);
+			throw new RuntimeException("Should have failed with bad arg count");
+		} catch (Exception e) {
+			
+		}
+	}
+	
+}

File src/test/java/org/xmlcml/mathml/COSTest.java

View file
  • Ignore whitespace
+package org.xmlcml.mathml;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.xmlcml.cml.base.CMLUtil;
+import org.xmlcml.mathml.AbstractMathElement;
+
+public class COSTest {
+
+	@Test
+	public void testExp() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:cos/>" +
+				"<m:cn>2</m:cn>" +
+				"</m:apply>";
+		AbstractMathElement ci = AbstractMathElement.createElementFromXML(ss);
+		Object o = ci.eval();
+		Assert.assertNotNull("object", o);
+		Assert.assertTrue("class", o instanceof Double);
+		Assert.assertEquals("object", -0.4161468365471424, (double)(Double) o, 0.000001);
+	}
+
+	@Test
+	public void testDifferentiate() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:cos/>" +
+				"<m:cn>a</m:cn>" +
+				"</m:apply>";
+		AbstractMathElement ci = AbstractMathElement.createElementFromXML(ss);
+		Differentiable diff = ci.castToDifferentiable();
+		Assert.assertNotNull("object", diff);
+		AbstractMathElement result = diff.differentiate();
+		// fragile
+		Assert.assertEquals("exp ", 
+				"<apply xmlns=\"http://www.w3.org/1998/Math/MathML\">" +
+				"<minus /><apply><times /><cn>0</cn><apply><sin /><cn>a</cn></apply></apply></apply>", 
+				result.toXML());
+	}
+}

File src/test/java/org/xmlcml/mathml/DIVIDETest.java

View file
  • Ignore whitespace
+package org.xmlcml.mathml;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.xmlcml.cml.base.CMLUtil;
+import org.xmlcml.mathml.AbstractMathElement;
+
+public class DIVIDETest {
+
+	@Test
+	public void testDivide() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:divide/>" +
+				"<m:cn>7</m:cn>" +
+				"<m:cn>3</m:cn>" +
+				"</m:apply>";
+		AbstractMathElement ci = AbstractMathElement.createElementFromXML(ss);
+		Object o = ci.eval();
+		Assert.assertNotNull("object", o);
+		Assert.assertTrue("class", o instanceof Integer);
+		Assert.assertEquals("object", 2, (int)(Integer) o);
+	}
+	
+	@Test
+	public void testDivide1() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:divide/>" +
+				"<m:cn>6</m:cn>" +
+				"<m:cn>3</m:cn>" +
+				"</m:apply>";
+		AbstractMathElement ci = AbstractMathElement.createElementFromXML(ss);
+		Object o = ci.eval();
+		Assert.assertNotNull("object", o);
+		Assert.assertTrue("class", o instanceof Integer);
+		Assert.assertEquals("object", 2, (int)(Integer) o);
+	}
+	
+	@Test
+	public void testDivideZero() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:divide/>" +
+				"<m:cn>6</m:cn>" +
+				"<m:cn>0</m:cn>" +
+				"</m:apply>";
+		AbstractMathElement ci = AbstractMathElement.createElementFromXML(ss);
+		try {
+			Object o = ci.eval();
+			Assert.fail("should throw divide by zero");
+		} catch (Exception e) {
+			
+		}
+	}
+	
+	@Test
+	public void testDivideDouble() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:divide/>" +
+				"<m:cn>4.5</m:cn>" +
+				"<m:cn>3</m:cn>" +
+				"</m:apply>";
+		AbstractMathElement ci = AbstractMathElement.createElementFromXML(ss);
+		Object o = ci.eval();
+		Assert.assertNotNull("object", o);
+		Assert.assertTrue("class", o instanceof Double);
+		Assert.assertEquals("object", 1.5, (double) (Double) o, 0.00001);
+	}
+	
+	@Test
+	public void testDivideDouble1() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:divide/>" +
+				"<m:cn>5.25</m:cn>" +
+				"<m:cn>3.5</m:cn>" +
+				"</m:apply>";
+		AbstractMathElement ci = AbstractMathElement.createElementFromXML(ss);
+		Object o = ci.eval();
+		Assert.assertNotNull("object", o);
+		Assert.assertTrue("class", o instanceof Double);
+		Assert.assertEquals("object", 1.5, (double) (Double) o, 0.00001);
+	}
+	
+	@Test
+	public void testDivideDouble3() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:divide/>" +
+				"<m:cn>4.5</m:cn>" +
+				"<m:cn>3.5</m:cn>" +
+				"</m:apply>";
+		AbstractMathElement ci = AbstractMathElement.createElementFromXML(ss);
+		Object o = ci.eval();
+		Assert.assertNotNull("object", o);
+		Assert.assertTrue("class", o instanceof Double);
+		Assert.assertEquals("object", 1.2857142857142858, (double) (Double) o, 0.00001);
+	}
+	
+	@Test
+	public void testDivideDivide() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:divide/>" +
+				"<m:apply>" +
+				"<m:divide/>" +
+				"<m:cn>15</m:cn>" +
+				"<m:cn>3</m:cn>" +
+				"</m:apply>"+
+				"<m:apply>" +
+				"<m:divide/>" +
+				"<m:cn>7</m:cn>" +
+				"<m:cn>3</m:cn>" +
+				"</m:apply>"+
+				"</m:apply>";
+		AbstractMathElement ci = AbstractMathElement.createElementFromXML(ss);
+		Object o = ci.eval();
+		Assert.assertNotNull("object", o);
+		Assert.assertTrue("class", o instanceof Integer);
+		Assert.assertEquals("object", 2, (int)(Integer) o);
+	}
+	
+	@Test
+	public void testDifferentiate() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:divide/>" +
+				"<m:cn>a</m:cn>" +
+				"<m:cn>b</m:cn>" +
+				"</m:apply>";
+		AbstractMathElement ci = AbstractMathElement.createElementFromXML(ss);
+		Differentiable diff = ci.castToDifferentiable();
+		Assert.assertNotNull("object", diff);
+		AbstractMathElement result = diff.differentiate();
+		// fragile
+		Assert.assertEquals("diff divide", 
+				"<apply xmlns=\"http://www.w3.org/1998/Math/MathML\"><divide /><apply><minus /><apply><times /><cn>b</cn><cn>0</cn></apply><apply><times /><cn>a</cn><cn>0</cn></apply></apply><apply><power /><cn>b</cn><cn>2</cn></apply></apply>", 
+				result.toXML());
+	}
+	
+}

File src/test/java/org/xmlcml/mathml/EXPTest.java

View file
  • Ignore whitespace
+package org.xmlcml.mathml;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.xmlcml.cml.base.CMLUtil;
+import org.xmlcml.mathml.AbstractMathElement;
+
+public class EXPTest {
+
+	@Test
+	public void testExp() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:exp/>" +
+				"<m:cn>2</m:cn>" +
+				"</m:apply>";
+		AbstractMathElement ci = AbstractMathElement.createElementFromXML(ss);
+		Object o = ci.eval();
+		Assert.assertNotNull("object", o);
+		Assert.assertTrue("class", o instanceof Double);
+		Assert.assertEquals("object", 7.38905609893065, (double)(Double) o, 0.000001);
+	}
+
+	@Test
+	public void testDifferentiate() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:exp/>" +
+				"<m:cn>a</m:cn>" +
+				"</m:apply>";
+		AbstractMathElement ci = AbstractMathElement.createElementFromXML(ss);
+		Differentiable diff = ci.castToDifferentiable();
+		Assert.assertNotNull("object", diff);
+		AbstractMathElement result = diff.differentiate();
+		// fragile
+		Assert.assertEquals("exp ", 
+				"<apply xmlns=\"http://www.w3.org/1998/Math/MathML\">" +
+				"<times /><cn>0</cn><apply><exp /><cn>a</cn></apply></apply>", 
+				result.toXML());
+	}
+	
+
+	@Test
+	public void testDifferentiate1() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:exp/>" +
+				"<m:apply>" +
+				"<m:sin/>"+
+				"<m:cn>a</m:cn>" +
+				"</m:apply>"+
+				"</m:apply>";
+		AbstractMathElement ci = AbstractMathElement.createElementFromXML(ss);
+		Differentiable diff = ci.castToDifferentiable();
+		Assert.assertNotNull("object", diff);
+		AbstractMathElement result = diff.differentiate();
+		// fragile
+		Assert.assertEquals("exp ", 
+				"<apply xmlns=\"http://www.w3.org/1998/Math/MathML\">" +
+				"<times /><apply><times /><cn>0</cn><apply><cos /><cn>a</cn></apply></apply><apply><exp /><apply><sin /><cn>a</cn></apply></apply></apply>", 
+				result.toXML());
+	}
+	
+}

File src/test/java/org/xmlcml/mathml/PLUSTest.java

View file
  • Ignore whitespace
 		Assert.assertEquals("object", 16, (Number) o);
 	}
 	
+	
 }

File src/test/java/org/xmlcml/mathml/SINTest.java

View file
  • Ignore whitespace
+package org.xmlcml.mathml;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.xmlcml.cml.base.CMLUtil;
+import org.xmlcml.mathml.AbstractMathElement;
+
+public class SINTest {
+
+	@Test
+	public void testSin() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:sin/>" +
+				"<m:cn>2</m:cn>" +
+				"</m:apply>";
+		AbstractMathElement ci = AbstractMathElement.createElementFromXML(ss);
+		Object o = ci.eval();
+		Assert.assertNotNull("object", o);
+		Assert.assertTrue("class", o instanceof Double);
+		Assert.assertEquals("object", 0.9092974268256817, (double)(Double) o, 0.000001);
+	}
+
+	@Test
+	public void testDifferentiate() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:sin/>" +
+				"<m:cn>a</m:cn>" +
+				"</m:apply>";
+		AbstractMathElement ci = AbstractMathElement.createElementFromXML(ss);
+		Differentiable diff = ci.castToDifferentiable();
+		Assert.assertNotNull("object", diff);
+		AbstractMathElement result = diff.differentiate();
+		// fragile
+		Assert.assertEquals("exp ", 
+				"<apply xmlns=\"http://www.w3.org/1998/Math/MathML\">" +
+				"<times /><cn>0</cn><apply><cos /><cn>a</cn></apply></apply>", 
+				result.toXML());
+	}
+}
+	

File src/test/java/org/xmlcml/mathml/TIMESTest.java

View file
  • Ignore whitespace
+package org.xmlcml.mathml;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.xmlcml.cml.base.CMLUtil;
+import org.xmlcml.mathml.AbstractMathElement;
+
+public class TIMESTest {
+
+	@Test
+	public void testTimes() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:times/>" +
+				"<m:cn>4</m:cn>" +
+				"<m:cn>3</m:cn>" +
+				"</m:apply>";
+		AbstractMathElement ci = AbstractMathElement.createElementFromXML(ss);
+		Object o = ci.eval();
+		Assert.assertNotNull("object", o);
+		Assert.assertTrue("class", o instanceof Integer);
+		Assert.assertEquals("object", 12, (int)(Integer) o);
+	}
+	
+	@Test
+	public void testTimesDouble() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:times/>" +
+				"<m:cn>4.5</m:cn>" +
+				"<m:cn>3</m:cn>" +
+				"</m:apply>";
+		AbstractMathElement ci = AbstractMathElement.createElementFromXML(ss);
+		Object o = ci.eval();
+		Assert.assertNotNull("object", o);
+		Assert.assertTrue("class", o instanceof Double);
+		Assert.assertEquals("object", 13.5, (double) (Double) o, 0.00001);
+	}
+	
+	@Test
+	public void testTimesDouble2() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:times/>" +
+				"<m:cn>5</m:cn>" +
+				"<m:cn>3.5</m:cn>" +
+				"</m:apply>";
+		AbstractMathElement ci = AbstractMathElement.createElementFromXML(ss);
+		Object o = ci.eval();
+		Assert.assertNotNull("object", o);
+		Assert.assertTrue("class", o instanceof Double);
+		Assert.assertEquals("object", 17.5, (double) (Double) o, 0.00001);
+	}
+	
+	@Test
+	public void testTimesDouble3() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:times/>" +
+				"<m:cn>4.5</m:cn>" +
+				"<m:cn>3.5</m:cn>" +
+				"</m:apply>";
+		AbstractMathElement ci = AbstractMathElement.createElementFromXML(ss);
+		Object o = ci.eval();
+		Assert.assertNotNull("object", o);
+		Assert.assertTrue("class", o instanceof Double);
+		Assert.assertEquals("object", 15.75, (double) (Double) o, 0.00001);
+	}
+	
+	@Test
+	public void testTimesTimes() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:times/>" +
+				"<m:apply>" +
+				"<m:times/>" +
+				"<m:cn>4</m:cn>" +
+				"<m:cn>3</m:cn>" +
+				"</m:apply>"+
+				"<m:apply>" +
+				"<m:times/>" +
+				"<m:cn>2</m:cn>" +
+				"<m:cn>7</m:cn>" +
+				"</m:apply>"+
+				"</m:apply>";
+		AbstractMathElement ci = AbstractMathElement.createElementFromXML(ss);
+		Object o = ci.eval();
+		Assert.assertNotNull("object", o);
+		Assert.assertTrue("class", o instanceof Number);
+		Assert.assertEquals("object", 168, (Number) o);
+	}
+	
+	@Test
+	public void testDifferentiate() {
+		String ss = "<m:apply xmlns:m='http://www.w3.org/1998/Math/MathML'>" +
+				"<m:times/>" +
+				"<m:cn>a</m:cn>" +
+				"<m:cn>b</m:cn>" +
+				"</m:apply>";
+		AbstractMathElement ci = AbstractMathElement.createElementFromXML(ss);
+		Differentiable diff = ci.castToDifferentiable();
+		Assert.assertNotNull("object", diff);
+		AbstractMathElement result = diff.differentiate();
+	}
+	
+}