001/*
002 * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.
003 * Copyright (C) 2006 - JScience (http://jscience.org/)
004 * All rights reserved.
005 * 
006 * Permission to use, copy, modify, and distribute this software is
007 * freely granted, provided that this notice is preserved.
008 */
009package org.jscience.mathematics.function;
010
011import java.util.List;
012import org.jscience.mathematics.structure.Field;
013
014import javolution.context.ObjectFactory;
015import javolution.text.Text;
016import javolution.text.TextBuilder;
017
018/**
019 * This class represents the quotient of two {@link Polynomial}, 
020 * it is also a {@link Field field} (invertible). 
021 * 
022 * @author  <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
023 * @version 3.1, April 1, 2006
024 */
025public class RationalFunction<F extends Field<F>> extends Function<F, F>
026        implements Field<RationalFunction<F>> {
027
028    /**
029     * Holds the factory for rational functions.
030     */
031    /**
032     * Holds the dividend.
033     */
034    private Polynomial<F> _dividend;
035
036    /**
037     * Holds the divisor.
038     */
039    private Polynomial<F> _divisor;
040
041    /**
042     * Default constructor.
043     */
044    private RationalFunction() {
045    }
046
047    /**
048     * Returns the dividend of this rational function.
049     * 
050     * @return this rational function dividend. 
051     */
052    public Polynomial<F> getDividend() {
053        return _dividend;
054    }
055
056    /**
057     * Returns the divisor of this rational function.
058     * 
059     * @return this rational function divisor.
060     */
061    public Polynomial<F> getDivisor() {
062        return _divisor;
063    }
064
065    /**
066     * Returns the rational function from the specified dividend and divisor.
067     * 
068     * @param dividend the dividend value.
069     * @param divisor the divisor value.
070     * @return <code>dividend / divisor</code>
071     */
072    @SuppressWarnings("unchecked")
073    public static <F extends Field<F>> RationalFunction<F> valueOf(
074            Polynomial<F> dividend, Polynomial<F> divisor) {
075        RationalFunction<F> rf = FACTORY.object();
076        rf._dividend = dividend;
077        rf._divisor = divisor;
078        return rf;
079    }
080
081    @SuppressWarnings("unchecked")
082    private static final ObjectFactory<RationalFunction> FACTORY = new ObjectFactory<RationalFunction>() {
083
084        protected RationalFunction create() {
085            return new RationalFunction();
086        }
087
088        @SuppressWarnings("unchecked")
089        protected void cleanup(RationalFunction rf) {
090            rf._dividend = null;
091            rf._divisor = null;
092        }
093    };
094
095    /**
096     * Returns the sum of two rational functions.
097     * 
098     * @param that the rational function being added.
099     * @return <code>this + that</code>
100     */
101    public RationalFunction<F> plus(RationalFunction<F> that) {
102        return valueOf(this._dividend.times(that._divisor).plus(
103                this._divisor.times(that._dividend)), this._divisor
104                .times(that._divisor));
105    }
106
107    /**
108     * Returns the opposite of this rational function.
109     * 
110     * @return <code>- this</code>
111     */
112    public RationalFunction<F> opposite() {
113        return valueOf(_dividend.opposite(), _divisor);
114    }
115
116    /**
117     * Returns the difference of two rational functions.
118     * 
119     * @param that the rational function being subtracted.
120     * @return <code>this - that</code>
121     */
122    public RationalFunction<F> minus(RationalFunction<F> that) {
123        return this.plus(that.opposite());
124    }
125
126    /**
127     * Returns the product of two rational functions.
128     * 
129     * @param that the rational function multiplier.
130     * @return <code>this ยท that</code>
131     */
132    public RationalFunction<F> times(RationalFunction<F> that) {
133        return valueOf(this._dividend.times(that._dividend), this._divisor
134                .times(that._divisor));
135    }
136
137    /**
138     * Returns the inverse of this rational function.
139     * 
140     * @return <code>1 / this</code>
141     */
142    public RationalFunction<F> inverse() {
143        return valueOf(_divisor, _dividend);
144    }
145
146    /**
147     * Returns the quotient of two rational functions.
148     * 
149     * @param that the rational function divisor.
150     * @return <code>this / that</code>
151     */
152    public RationalFunction<F> divide(RationalFunction<F> that) {
153        return this.times(that.inverse());
154    }
155
156    @SuppressWarnings("unchecked")
157    @Override
158    public List<Variable<F>> getVariables() {
159        return merge(_dividend.getVariables(), _divisor.getVariables());
160    }
161
162    @SuppressWarnings("unchecked")
163    @Override
164    public F evaluate() {
165        return _dividend.evaluate().times(_divisor.evaluate().inverse());
166    }
167
168    @Override
169    public Text toText() {
170        TextBuilder tb = TextBuilder.newInstance();
171        tb.append('(');
172        tb.append(_dividend);
173        tb.append(")/(");
174        tb.append(_divisor);
175        tb.append(')');
176        return tb.toText();
177    }
178
179    @Override
180    public boolean equals(Object obj) {
181        if (obj instanceof RationalFunction) {
182            RationalFunction<?> that = (RationalFunction<?>) obj;
183            return this._dividend.equals(this._dividend)
184                    && this._divisor.equals(that._divisor);
185        } else {
186            return false;
187        }
188    }
189
190    @Override
191    public int hashCode() {
192        return _dividend.hashCode() - _divisor.hashCode();
193    }
194
195    //////////////////////////////////////////////////////////////////////
196    // Overrides parent method potentially returning rational functions //
197    //////////////////////////////////////////////////////////////////////
198    
199    @Override
200    public RationalFunction<F> differentiate(Variable<F> v) {
201        return valueOf(_divisor.times(_dividend.differentiate(v)).plus(
202                _dividend.times(_divisor.differentiate(v)).opposite()),
203                _dividend.pow(2));
204    }
205
206    @SuppressWarnings("unchecked")
207    @Override
208    public Function<F, F> plus(Function<F, F> that) {
209        return (that instanceof RationalFunction) ?
210                this.plus((RationalFunction<F>)that) : super.plus(that);       
211    }
212
213    @SuppressWarnings("unchecked")
214    @Override
215    public Function<F, F> minus(Function<F, F> that) {
216        return (that instanceof RationalFunction) ?
217                this.minus((RationalFunction<F>)that) : super.minus(that);       
218    }
219
220    @SuppressWarnings("unchecked")
221    @Override
222    public Function<F, F> times(Function<F, F> that) {
223        return (that instanceof RationalFunction) ?
224                this.times((RationalFunction<F>)that) : super.times(that);       
225    }
226    
227    @SuppressWarnings("unchecked")
228    @Override
229    public Function<F, F> divide(Function<F, F> that) {
230        return (that instanceof RationalFunction) ?
231                this.divide((RationalFunction<F>)that) : super.divide(that);       
232    }
233    
234    @SuppressWarnings("unchecked")
235    @Override
236    public RationalFunction<F> pow(int n) {
237        return (RationalFunction<F>) super.pow(n);
238    }
239
240
241    /**
242     * Returns a copy of this rational function. 
243     * {@link javolution.context.AllocatorContext allocated} 
244     * by the calling thread (possibly on the stack).
245     *     
246     * @return an identical and independant copy of this rational function.
247     */
248    public RationalFunction<F> copy() {
249        return RationalFunction.valueOf(_dividend.copy(), _divisor.copy());
250    }
251
252    private static final long serialVersionUID = 1L;
253
254}