using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics.Contracts; namespace AutoDiff { /// <summary> /// Base class for all automatically-differentiable terms. /// </summary> [Serializable] [ContractClass(typeof(TermContacts))] public abstract class Term { /// <summary> /// Accepts a term visitor /// </summary> /// <param name="visitor">The term visitor to accept</param> public abstract void Accept(ITermVisitor visitor); /// <summary> /// Accepts a term visitor with a generic result /// </summary> /// <typeparam name="TResult">The type of the result from the visitor's function</typeparam> /// <param name="visitor">The visitor to accept</param> /// <returns>The result from the visitor's visit function.</returns> public abstract TResult Accept<TResult>(ITermVisitor<TResult> visitor); /// <summary> /// Converts a floating point constant to a constant term. /// </summary> /// <param name="value">The floating point constnat</param> /// <returns>The resulting term.</returns> public static implicit operator Term(double value) { return TermBuilder.Constant(value); } /// <summary> /// Constructs a sum of the two given terms. /// </summary> /// <param name="left">First term in the sum</param> /// <param name="right">Second term in the sum</param> /// <returns>A term representing the sum of <paramref name="left"/> and <paramref name="right"/>.</returns> public static Term operator+(Term left, Term right) { if (left is Zero && right is Zero) return new Zero(); else if (left is Zero) return right; else if (right is Zero) return left; else return TermBuilder.Sum(left, right); } /// <summary> /// Constructs a product term of the two given terms. /// </summary> /// <param name="left">The first term in the product</param> /// <param name="right">The second term in the product</param> /// <returns>A term representing the product of <paramref name="left"/> and <paramref name="right"/>.</returns> public static Term operator*(Term left, Term right) { return TermBuilder.Product(left, right); } /// <summary> /// Constructs a fraction term of the two given terms. /// </summary> /// <param name="numerator">The numerator of the fraction. That is, the "top" part.</param> /// <param name="denominator">The denominator of the fraction. That is, the "bottom" part.</param> /// <returns>A term representing the fraction <paramref name="numerator"/> over <paramref name="denominator"/>.</returns> public static Term operator/(Term numerator, Term denominator) { return TermBuilder.Product(numerator, TermBuilder.Power(denominator, -1)); } /// <summary> /// Constructs a difference of the two given terms. /// </summary> /// <param name="left">The first term in the difference</param> /// <param name="right">The second term in the difference.</param> /// <returns>A term representing <paramref name="left"/> - <paramref name="right"/>.</returns> public static Term operator-(Term left, Term right) { return left + (-1) * right; } /// <summary> /// Constructs a negated term /// </summary> /// <param name="term">The term to negate</param> /// <returns>A term representing <c>-term</c>.</returns> public static Term operator-(Term term) { return (-1) * term; } } [ContractClassFor(typeof(Term))] abstract class TermContacts : Term { public override void Accept(ITermVisitor visitor) { Contract.Requires(visitor != null); } public override TResult Accept<TResult>(ITermVisitor<TResult> visitor) { Contract.Requires(visitor != null); return default(TResult); } } }