Source Code Cross Referenced for Function.java in  » Science » jscience-4.3.1 » org » jscience » mathematics » function » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Science » jscience 4.3.1 » org.jscience.mathematics.function 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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:         */
009:        package org.jscience.mathematics.function;
010:
011:        import java.io.Serializable;
012:        import java.util.Iterator;
013:        import java.util.List;
014:
015:        import org.jscience.mathematics.structure.GroupAdditive;
016:        import org.jscience.mathematics.structure.GroupMultiplicative;
017:
018:        import javolution.context.LocalContext;
019:        import javolution.context.ObjectFactory;
020:        import javolution.util.FastList;
021:        import javolution.lang.Realtime;
022:        import javolution.text.Text;
023:        import javolution.text.TextBuilder;
024:
025:        /**
026:         * <p> This abstract class represents a mapping between two sets such that
027:         *     there is a unique element in the second set assigned to each element
028:         *     in the first set.</p>
029:         *     
030:         * <p> Functions can be discrete or continuous and multivariate functions 
031:         *     (functions with multiple variables) are also supported as illustrated 
032:         *     below:[code]
033:         *         // Defines local variables.
034:         *         Variable.Local<Rational> varX = new Variable.Local<Rational>("x");
035:         *         Variable.Local<Rational> varY = new Variable.Local<Rational>("y");
036:         *         
037:         *         // f(x, y) =  x² + x·y + 1;
038:         *         Polynomial<Rational> x = Polynomial.valueOf(Rational.ONE, varX);
039:         *         Polynomial<Rational> y = Polynomial.valueOf(Rational.ONE, varY);
040:         *         Polynomial<Rational> fx_y = x.pow(2).plus(x.times(y)).plus(Rational.ONE);
041:         *         System.out.println("f(x,y) = " + fx_y);
042:         * 
043:         *         // Evaluates f(1,0) 
044:         *         System.out.println("f(1,0) = " + fx_y.evaluate(Rational.ONE, Rational.ZERO));
045:         * 
046:         *         // Calculates df(x,y)/dx
047:         *         System.out.println("df(x,y)/dx = " + fx_y.differentiate(varX));
048:         *          
049:         *         > f(x,y) = [1/1]x^2 + [1/1]xy + [1/1]
050:         *         > f(1,0) = 2/1
051:         *         > df(x,y)/dx = [2/1]x + [1/1]y
052:         *     [/code]</p>
053:         *     
054:         * <p> Functions are often given by formula (e.g. <code>f(x) = x²-x+1,
055:         *     f(x,y)= x·y</code>) but the general function instance might tabulate
056:         *     the values, solve an equation, etc.</p>
057:         *     
058:         * @author  <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
059:         * @version 3.1, April 1, 2006
060:         * @see <a href="http://en.wikipedia.org/wiki/Function_%28mathematics%29">
061:         *      Wikipedia: Functions (mathematics)</a>
062:         */
063:        public abstract class Function<X, Y> implements  Serializable, Realtime {
064:
065:            // TODO: Implements XMLSerializable.
066:
067:            /**
068:             * Default constructor. 
069:             */
070:            protected Function() {
071:            }
072:
073:            /**
074:             * Returns a lexically ordered list of the variables (or arguments)
075:             * for this function (empty list for constant functions).
076:             * 
077:             * @return this function current unset variables (sorted).
078:             */
079:            public abstract List<Variable<X>> getVariables();
080:
081:            /**
082:             * Evaluates this function using its {@link Variable variables} current
083:             * values.
084:             *
085:             * @return the evaluation of this function.
086:             * @throws FunctionException if any of this function's variable is not set.
087:             */
088:            public abstract Y evaluate();
089:
090:            /**
091:             * Indicates if this function is equals to the specified object.
092:             *
093:             * @param obj the object to be compared with.
094:             * @return <code>true</code> if this function and the specified argument
095:             *         represent the same function; <code>false</code> otherwise.
096:             */
097:            public boolean equals(Object obj) {
098:                return super .equals(obj);
099:            }
100:
101:            /**
102:             * Returns the hash code for this function (consistent with 
103:             * {@link #equals(Object)}.
104:             *
105:             * @return this function hash code.
106:             */
107:            public int hashCode() {
108:                return super .hashCode();
109:            }
110:
111:            /**
112:             * Retrieves the variable from this function having the specified 
113:             * symbol (convenience method).
114:             *
115:             * @return the variable having the specified symbol or <code>null</code>
116:             *         if none.
117:             */
118:            public final Variable<X> getVariable(String symbol) {
119:                for (Variable<X> v : this .getVariables()) {
120:                    if (symbol.equals(v.getSymbol()))
121:                        return v;
122:                }
123:                return null;
124:            }
125:
126:            /**
127:             * Evaluates this function for the specified argument value
128:             * (convenience method). The evaluation is performed 
129:             * in a {@link javolution.context.LocalContext LocalContext} and 
130:             * can safely be called upon functions with {@link Variable.Global global
131:             * variables}.
132:             *
133:             * @param arg the single variable value used for the evaluation.
134:             * @return the evaluation of this function.
135:             * @throws FunctionException if <code>getVariables().size() != 1</code> 
136:             */
137:            public final Y evaluate(X arg) {
138:                List<Variable<X>> vars = getVariables();
139:                if (vars.size() != 1)
140:                    throw new FunctionException(
141:                            "This function is not monovariate");
142:                Variable<X> x = vars.get(0);
143:                X prev = x.get();
144:                LocalContext.enter();
145:                try {
146:                    x.set(arg);
147:                    return evaluate();
148:                } finally {
149:                    x.set(prev);
150:                    LocalContext.exit();
151:                }
152:            }
153:
154:            /**
155:             * Evaluates this function for the specified arguments values
156:             * (convenience method). The evaluation is performed 
157:             * in a {@link javolution.context.LocalContext LocalContext} and 
158:             * can safely be called upon functions with {@link Variable.Global global
159:             * variables}.
160:             *
161:             * @param args the variables values used for the evaluation.
162:             * @return the evaluation of this function.
163:             * @throws IllegalArgumentException 
164:             *         if <code>args.length != getVariables().size())</code> 
165:             */
166:            public final Y evaluate(X... args) {
167:                List<Variable<X>> vars = getVariables();
168:                if (vars.size() != args.length)
169:                    throw new IllegalArgumentException("Found " + args.length
170:                            + " arguments, but " + vars.size() + "required");
171:                LocalContext.enter();
172:                try {
173:                    return evaluate(args, vars, 0);
174:                } finally {
175:                    LocalContext.exit();
176:                }
177:            }
178:
179:            private final Y evaluate(X[] args, List<Variable<X>> vars, int i) {
180:                if (i < args.length) {
181:                    Variable<X> var = vars.get(i);
182:                    X prev = var.get();
183:                    var.set(args[i]);
184:                    try {
185:                        return evaluate(args, vars, i + 1);
186:                    } finally {
187:                        var.set(prev); // Restores previous variable value.
188:                    }
189:                } else {
190:                    return evaluate();
191:                }
192:            }
193:
194:            /**
195:             * Returns the composition of this function with the one specified.
196:             *
197:             * @param  that the function for which the return value is passed as
198:             *         argument to this function.
199:             * @return the function <code>(this o that)</code>
200:             * @throws FunctionException if this function is not monovariate.
201:             */
202:            public <Z> Function<Z, Y> compose(Function<Z, X> that) {
203:                if (getVariables().size() != 1)
204:                    throw new FunctionException(
205:                            "This function is not monovariate");
206:                return Compose.newInstance(this , that);
207:            }
208:
209:            /**
210:             * Returns the first derivative of this function with respect to 
211:             * the specified variable. 
212:             * 
213:             * @param  v the variable for which the derivative is calculated.
214:             * @return <code>d[this]/dv</code>
215:             * @see <a href="http://mathworld.wolfram.com/Derivative.html">
216:             *      Derivative -- from MathWorld</a>
217:             * @throws FunctionException if the derivative is undefined.
218:             */
219:            public Function<X, Y> differentiate(Variable<X> v) {
220:                return Derivative.newInstance(this , v);
221:            }
222:
223:            /**
224:             * Returns an integral of this function with respect to 
225:             * the specified variable. 
226:             * 
227:             * @param  v the variable for which the integral is calculated.
228:             * @return <code>S[this·dv]</code>
229:             * @see <a href="http://mathworld.wolfram.com/Integral.html">
230:             *      Integral -- from MathWorld</a>
231:             */
232:            public Function<X, Y> integrate(Variable<X> v) {
233:                return Integral.newInstance(this , v);
234:            }
235:
236:            /**
237:             * Returns the sum of this function with the one specified.
238:             *
239:             * @param  that the function to be added.
240:             * @return <code>this + that</code>.
241:             */
242:            public Function<X, Y> plus(Function<X, Y> that) {
243:                return Plus.newInstance(this , that);
244:            }
245:
246:            /**
247:             * Returns the difference of this function with the one specified.
248:             *
249:             * @param  that the function to be subtracted.
250:             * @return <code>this - that</code>.
251:             */
252:            @SuppressWarnings("unchecked")
253:            public Function<X, Y> minus(Function<X, Y> that) {
254:                if (that instanceof  GroupAdditive) {
255:                    Function thatOpposite = (Function) ((GroupAdditive) that)
256:                            .opposite();
257:                    return this .plus(thatOpposite);
258:                }
259:                return Minus.newInstance(this , that);
260:            }
261:
262:            /**
263:             * Returns the product of this function with the one specified.
264:             *
265:             * @param  that the function multiplier.
266:             * @return <code>this · that</code>.
267:             */
268:            public Function<X, Y> times(Function<X, Y> that) {
269:                return Times.newInstance(this , that);
270:            }
271:
272:            /**
273:             * Returns the quotient of this function with the one specified.
274:             * Evaluation of this function may raise an exception if the 
275:             * function result is not a {
276:             *
277:             * @param  that the function divisor.
278:             * @return <code>this / that</code>.
279:             */
280:            @SuppressWarnings("unchecked")
281:            public Function<X, Y> divide(Function<X, Y> that) {
282:                if (that instanceof  GroupMultiplicative) {
283:                    Function thatInverse = (Function) ((GroupMultiplicative) that)
284:                            .inverse();
285:                    return this .times(thatInverse);
286:                }
287:                return Divide.newInstance(this , that);
288:            }
289:
290:            /**
291:             * Returns this function raised at the specified exponent.
292:             *
293:             * @param  n the exponent.
294:             * @return <code>this<sup>n</sup></code>
295:             * @throws IllegalArgumentException if <code>n &lt;= 0</code>
296:             */
297:            public Function<X, Y> pow(int n) {
298:                if (n <= 0)
299:                    throw new IllegalArgumentException("n: " + n
300:                            + " zero or negative values not allowed");
301:                Function<X, Y> pow2 = this ;
302:                Function<X, Y> result = null;
303:                while (n >= 1) { // Iteration.
304:                    if ((n & 1) == 1) {
305:                        result = (result == null) ? pow2 : result.times(pow2);
306:                    }
307:                    pow2 = pow2.times(pow2);
308:                    n >>>= 1;
309:                }
310:                return result;
311:            }
312:
313:            /**
314:             * Returns the textual representation of this real-time object
315:             * (equivalent to <code>toString</code> except that the returned value
316:             * can be allocated from the local context space).
317:             * 
318:             * @return this object's textual representation.
319:             */
320:            public abstract Text toText();
321:
322:            /**
323:             * Returns the text representation of this function as a 
324:             * <code>java.lang.String</code>.
325:             * 
326:             * @return <code>toText().toString()</code>
327:             */
328:            public final String toString() {
329:                return toText().toString();
330:            }
331:
332:            // Merges the variable from the specified function into a single table.
333:            @SuppressWarnings("unchecked")
334:            static final List merge(List left, List right) {
335:                if (left.containsAll(right))
336:                    return left;
337:                if (right.containsAll(left))
338:                    return right;
339:                FastList result = FastList.newInstance();
340:                Iterator iLeft = left.iterator();
341:                Iterator iRight = right.iterator();
342:                Variable l = null;
343:                Variable r = null;
344:                while (true) {
345:                    if (!iLeft.hasNext()) {
346:                        while (iRight.hasNext()) {
347:                            result.add(iRight.next());
348:                        }
349:                        return result;
350:                    }
351:                    if (!iRight.hasNext()) {
352:                        while (iLeft.hasNext()) {
353:                            result.add(iLeft.next());
354:                        }
355:                        return result;
356:                    }
357:                    l = (l == null) ? (Variable) iLeft.next() : l;
358:                    r = (r == null) ? (Variable) iRight.next() : r;
359:                    if (l == r) {
360:                        result.add(l);
361:                        l = null;
362:                        r = null;
363:                        continue;
364:                    }
365:                    int comp = l.getSymbol().compareTo(r.getSymbol());
366:                    if (comp < 0) {
367:                        result.add(l);
368:                        l = null;
369:                        continue;
370:                    }
371:                    if (comp > 0) {
372:                        result.add(r);
373:                        r = null;
374:                        continue;
375:                    }
376:                    throw new FunctionException("Duplicate symbol "
377:                            + l.getSymbol());
378:                }
379:            }
380:
381:            // Function composition (default implementation).
382:            private static final class Compose extends Function {
383:
384:                private static final ObjectFactory<Compose> FACTORY = new ObjectFactory<Compose>() {
385:
386:                    protected Compose create() {
387:                        return new Compose();
388:                    }
389:
390:                    protected void cleanup(Compose compose) {
391:                        compose._f = null;
392:                        compose._g = null;
393:                    }
394:                };
395:
396:                private Function _f;
397:
398:                private Function _g;
399:
400:                @SuppressWarnings("unchecked")
401:                public static <X, Y> Function<X, Y> newInstance(Function f,
402:                        Function g) {
403:                    Compose compose = FACTORY.object();
404:                    compose._f = f;
405:                    compose._g = g;
406:                    return compose;
407:                }
408:
409:                @Override
410:                public List getVariables() {
411:                    return _g.getVariables();
412:                }
413:
414:                @Override
415:                @SuppressWarnings("unchecked")
416:                public Object evaluate() {
417:                    return evaluate(_g.evaluate());
418:                }
419:
420:                @SuppressWarnings("unchecked")
421:                public Function differentiate(Variable v) {
422:                    // Chain rule: http://en.wikipedia.org/wiki/Chain_rule
423:                    Function fd = _f.differentiate(v);
424:                    Function gd = _g.differentiate(v);
425:                    return fd.compose(_g).times(gd);
426:                }
427:
428:                public Text toText() {
429:                    return TextBuilder.newInstance().append('(').append(_f)
430:                            .append(')').append('o').append('(').append(_g)
431:                            .append(')').toText();
432:                }
433:
434:                @Override
435:                public boolean equals(Object obj) {
436:                    if (!(obj instanceof  Compose))
437:                        return false;
438:                    Compose that = (Compose) obj;
439:                    return this ._f.equals(that._f) && this ._g.equals(that._g);
440:                }
441:
442:                @Override
443:                public int hashCode() {
444:                    return _f.hashCode() + _g.hashCode();
445:                }
446:
447:                private static final long serialVersionUID = 1L;
448:
449:            }
450:
451:            // Function derivative (default implementation).
452:            private static final class Derivative extends Function {
453:
454:                private static final ObjectFactory<Derivative> FACTORY = new ObjectFactory<Derivative>() {
455:
456:                    protected Derivative create() {
457:                        return new Derivative();
458:                    }
459:
460:                    protected void cleanup(Derivative derivative) {
461:                        derivative._f = null;
462:                        derivative._v = null;
463:                    }
464:                };
465:
466:                private Function _f;
467:
468:                private Variable _v;
469:
470:                @SuppressWarnings("unchecked")
471:                public static <X, Y> Function<X, Y> newInstance(Function f,
472:                        Variable v) {
473:                    Derivative derivative = FACTORY.object();
474:                    derivative._f = f;
475:                    derivative._v = v;
476:                    return derivative;
477:                }
478:
479:                @Override
480:                public List getVariables() {
481:                    return _f.getVariables();
482:                }
483:
484:                @Override
485:                public Object evaluate() {
486:                    throw new FunctionException("Derivative of " + _f
487:                            + " undefined");
488:                }
489:
490:                public Text toText() {
491:                    return TextBuilder.newInstance().append("d[").append(_f)
492:                            .append("]/d").append(_v.getSymbol()).toText();
493:                }
494:
495:                @Override
496:                public boolean equals(Object obj) {
497:                    if (!(obj instanceof  Derivative))
498:                        return false;
499:                    Derivative that = (Derivative) obj;
500:                    return this ._f.equals(that._f) && this ._v.equals(that._v);
501:                }
502:
503:                @Override
504:                public int hashCode() {
505:                    return _f.hashCode() + _v.hashCode();
506:                }
507:
508:                private static final long serialVersionUID = 1L;
509:            }
510:
511:            // Function integral (default implementation).
512:            private static final class Integral extends Function {
513:
514:                private static final ObjectFactory<Integral> FACTORY = new ObjectFactory<Integral>() {
515:
516:                    protected Integral create() {
517:                        return new Integral();
518:                    }
519:
520:                    protected void cleanup(Integral integral) {
521:                        integral._f = null;
522:                        integral._v = null;
523:                    }
524:                };
525:
526:                private Function _f;
527:
528:                private Variable _v;
529:
530:                @SuppressWarnings("unchecked")
531:                public static <X, Y> Function<X, Y> newInstance(Function f,
532:                        Variable v) {
533:                    Integral integral = FACTORY.object();
534:                    integral._f = f;
535:                    integral._v = v;
536:                    return integral;
537:                }
538:
539:                @Override
540:                public List getVariables() {
541:                    return _f.getVariables();
542:                }
543:
544:                @Override
545:                public Object evaluate() {
546:                    throw new FunctionException("Integral of " + _f
547:                            + " undefined");
548:                }
549:
550:                public Text toText() {
551:                    return TextBuilder.newInstance().append("S[").append(_f)
552:                            .append("·d").append(_v.getSymbol()).append(']')
553:                            .toText();
554:                }
555:
556:                @Override
557:                public boolean equals(Object obj) {
558:                    if (!(obj instanceof  Integral))
559:                        return false;
560:                    Integral that = (Integral) obj;
561:                    return this ._f.equals(that._f) && this ._v.equals(that._v);
562:                }
563:
564:                @Override
565:                public int hashCode() {
566:                    return _f.hashCode() + _v.hashCode();
567:                }
568:
569:                private static final long serialVersionUID = 1L;
570:            }
571:
572:            // Function addition (default implementation).
573:            private static final class Plus extends Function {
574:
575:                private static final ObjectFactory<Plus> FACTORY = new ObjectFactory<Plus>() {
576:
577:                    protected Plus create() {
578:                        return new Plus();
579:                    }
580:
581:                    protected void cleanup(Plus plus) {
582:                        plus._f = null;
583:                        plus._g = null;
584:                    }
585:                };
586:
587:                private Function _f, _g;
588:
589:                @SuppressWarnings("unchecked")
590:                public static <X, Y> Function<X, Y> newInstance(Function f,
591:                        Function g) {
592:                    Plus plus = FACTORY.object();
593:                    plus._f = f;
594:                    plus._g = g;
595:                    return plus;
596:                }
597:
598:                @Override
599:                public List getVariables() {
600:                    return merge(_f.getVariables(), _g.getVariables());
601:                }
602:
603:                @SuppressWarnings("unchecked")
604:                @Override
605:                public Object evaluate() {
606:                    Object y2 = _g.evaluate();
607:                    Object y1 = _f.evaluate();
608:                    if (!(y1 instanceof  GroupAdditive))
609:                        throw new FunctionException(y1.getClass()
610:                                + " is not an additive group");
611:
612:                    return ((GroupAdditive) y1).plus(y2);
613:                }
614:
615:                @SuppressWarnings("unchecked")
616:                @Override
617:                public Function differentiate(Variable v) {
618:                    return _f.differentiate(v).plus(_g.differentiate(v));
619:                }
620:
621:                @SuppressWarnings("unchecked")
622:                @Override
623:                public Function integrate(Variable v) {
624:                    return _f.integrate(v).plus(_g.integrate(v));
625:                }
626:
627:                public Text toText() {
628:                    return TextBuilder.newInstance().append('(').append(_f)
629:                            .append(")").append('+').append('(').append(_g)
630:                            .append(')').toText();
631:                }
632:
633:                @Override
634:                public boolean equals(Object obj) {
635:                    if (!(obj instanceof  Plus))
636:                        return false;
637:                    Plus that = (Plus) obj;
638:                    return this ._f.equals(that._f) && this ._g.equals(that._g);
639:                }
640:
641:                @Override
642:                public int hashCode() {
643:                    return _f.hashCode() + _g.hashCode();
644:                }
645:
646:                private static final long serialVersionUID = 1L;
647:            }
648:
649:            // Function addition (default implementation).
650:            private static final class Minus extends Function {
651:
652:                private static final ObjectFactory<Minus> FACTORY = new ObjectFactory<Minus>() {
653:
654:                    protected Minus create() {
655:                        return new Minus();
656:                    }
657:
658:                    protected void cleanup(Minus minus) {
659:                        minus._f = null;
660:                        minus._g = null;
661:                    }
662:                };
663:
664:                private Function _f, _g;
665:
666:                @SuppressWarnings("unchecked")
667:                public static <X, Y> Function<X, Y> newInstance(Function f,
668:                        Function g) {
669:                    Minus minus = FACTORY.object();
670:                    minus._f = f;
671:                    minus._g = g;
672:                    return minus;
673:                }
674:
675:                @Override
676:                public List getVariables() {
677:                    return merge(_f.getVariables(), _g.getVariables());
678:                }
679:
680:                @SuppressWarnings("unchecked")
681:                @Override
682:                public Object evaluate() {
683:                    Object y2 = _g.evaluate();
684:                    if (!(y2 instanceof  GroupAdditive))
685:                        throw new FunctionException(y2.getClass()
686:                                + " is not an additive group");
687:                    y2 = ((GroupAdditive) y2).opposite();
688:
689:                    Object y1 = _f.evaluate();
690:                    if (!(y1 instanceof  GroupAdditive))
691:                        throw new FunctionException(y1.getClass()
692:                                + " is not an additive group");
693:
694:                    return ((GroupAdditive) y1).plus(y2);
695:                }
696:
697:                @SuppressWarnings("unchecked")
698:                @Override
699:                public Function differentiate(Variable v) {
700:                    return _f.differentiate(v).minus(_g.differentiate(v));
701:                }
702:
703:                @SuppressWarnings("unchecked")
704:                @Override
705:                public Function integrate(Variable v) {
706:                    return _f.integrate(v).minus(_g.integrate(v));
707:                }
708:
709:                public Text toText() {
710:                    return TextBuilder.newInstance().append('(').append(_f)
711:                            .append(")").append('-').append('(').append(_g)
712:                            .append(')').toText();
713:                }
714:
715:                @Override
716:                public boolean equals(Object obj) {
717:                    if (!(obj instanceof  Minus))
718:                        return false;
719:                    Minus that = (Minus) obj;
720:                    return this ._f.equals(that._f) && this ._g.equals(that._g);
721:                }
722:
723:                @Override
724:                public int hashCode() {
725:                    return _f.hashCode() + _g.hashCode();
726:                }
727:
728:                private static final long serialVersionUID = 1L;
729:            }
730:
731:            // Function multiplication (default implementation).
732:            private static final class Times extends Function {
733:
734:                private static final ObjectFactory<Times> FACTORY = new ObjectFactory<Times>() {
735:
736:                    protected Times create() {
737:                        return new Times();
738:                    }
739:
740:                    protected void cleanup(Times times) {
741:                        times._f = null;
742:                        times._g = null;
743:                    }
744:                };
745:
746:                private Function _f, _g;
747:
748:                @SuppressWarnings("unchecked")
749:                public static <X, Y> Function<X, Y> newInstance(Function f,
750:                        Function g) {
751:                    Times times = FACTORY.object();
752:                    times._f = f;
753:                    times._g = g;
754:                    return times;
755:                }
756:
757:                @Override
758:                public List getVariables() {
759:                    return merge(_f.getVariables(), _g.getVariables());
760:                }
761:
762:                @SuppressWarnings("unchecked")
763:                @Override
764:                public Object evaluate() {
765:                    Object y2 = _g.evaluate();
766:                    Object y1 = _f.evaluate();
767:                    if (!(y1 instanceof  GroupMultiplicative))
768:                        throw new FunctionException(y1.getClass()
769:                                + " is not a multiplicative group");
770:
771:                    return ((GroupMultiplicative) y1).times(y2);
772:                }
773:
774:                @SuppressWarnings("unchecked")
775:                @Override
776:                public Function differentiate(Variable v) {
777:                    // Product rule: http://en.wikipedia.org/wiki/Product_rule
778:                    // (support for non-commutative multiplications).
779:                    // r' = d(f·g) = f'g + fg'
780:                    Function fd = _f.differentiate(v);
781:                    Function gd = _g.differentiate(v);
782:                    return fd.times(_g).plus(_f.times(gd));
783:                }
784:
785:                public Text toText() {
786:            return TextBuilder.newInstance().append('(').append(_f).append(")")
787:            .append('·').append('(').append(_g).append(')').toText();
788:        }
789:
790:                @Override
791:                public boolean equals(Object obj) {
792:                    if (!(obj instanceof  Times))
793:                        return false;
794:                    Times that = (Times) obj;
795:                    return this ._f.equals(that._f) && this ._g.equals(that._g);
796:                }
797:
798:                @Override
799:                public int hashCode() {
800:                    return _f.hashCode() + _g.hashCode();
801:                }
802:
803:                private static final long serialVersionUID = 1L;
804:            }
805:
806:            // Function multiplication (default implementation).
807:            private static final class Divide extends Function {
808:
809:                private static final ObjectFactory<Divide> FACTORY = new ObjectFactory<Divide>() {
810:
811:                    protected Divide create() {
812:                        return new Divide();
813:                    }
814:
815:                    protected void cleanup(Divide divide) {
816:                        divide._f = null;
817:                        divide._g = null;
818:                    }
819:                };
820:
821:                private Function _f, _g;
822:
823:                @SuppressWarnings("unchecked")
824:                public static <X, Y> Function<X, Y> newInstance(Function f,
825:                        Function g) {
826:                    Divide divide = FACTORY.object();
827:                    divide._f = f;
828:                    divide._g = g;
829:                    return divide;
830:                }
831:
832:                @Override
833:                public List getVariables() {
834:                    return merge(_f.getVariables(), _g.getVariables());
835:                }
836:
837:                @SuppressWarnings("unchecked")
838:                @Override
839:                public Object evaluate() {
840:                    Object y2 = _g.evaluate();
841:                    if (!(y2 instanceof  GroupMultiplicative))
842:                        throw new FunctionException(y2.getClass()
843:                                + " is not a multiplicative group");
844:                    y2 = ((GroupMultiplicative) y2).inverse();
845:                    Object y1 = _f.evaluate();
846:                    if (!(y1 instanceof  GroupMultiplicative))
847:                        throw new FunctionException(y1.getClass()
848:                                + " is not a multiplicative group");
849:
850:                    return ((GroupMultiplicative) y1).times(y2);
851:                }
852:
853:                @SuppressWarnings("unchecked")
854:                @Override
855:                public Function differentiate(Variable v) {
856:                    // Quotient rule: http://en.wikipedia.org/wiki/Quotient_rule
857:                    // with support for non-commutative multiplications.
858:                    // r = f/g,  rg = f, r'g + rg' = f' (produt rule)
859:                    // r' = (f' - rg')/g, r' = (f' - (f/g)g')/g
860:                    Function fd = _f.differentiate(v);
861:                    Function gd = _g.differentiate(v);
862:                    return fd.minus(_f.divide(_g).times(gd)).divide(_g);
863:                }
864:
865:                public Text toText() {
866:                    return TextBuilder.newInstance().append('(').append(_f)
867:                            .append(")").append('/').append('(').append(_g)
868:                            .append(')').toText();
869:                }
870:
871:                @Override
872:                public boolean equals(Object obj) {
873:                    if (!(obj instanceof  Divide))
874:                        return false;
875:                    Divide that = (Divide) obj;
876:                    return this ._f.equals(that._f) && this ._g.equals(that._g);
877:                }
878:
879:                @Override
880:                public int hashCode() {
881:                    return _f.hashCode() + _g.hashCode();
882:                }
883:
884:                private static final long serialVersionUID = 1L;
885:            }
886:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.