View Javadoc
1   package org.djutils.math.functions;
2   
3   import java.util.SortedSet;
4   
5   /**
6    * MathFunction interface.
7    * <p>
8    * Copyright (c) 2024-2025 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
9    * for project information <a href="https://djutils.org" target="_blank"> https://djutils.org</a>. The DJUTILS project is
10   * distributed under a three-clause BSD-style license, which can be found at
11   * <a href="https://djutils.org/docs/license.html" target="_blank"> https://djutils.org/docs/license.html</a>.
12   * </p>
13   * @author <a href="https://github.com/averbraeck">Alexander Verbraeck</a>
14   * @author <a href="https://github.com/peter-knoppers">Peter Knoppers</a>
15   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
16   */
17  public interface MathFunction extends Comparable<MathFunction>
18  {
19  
20      /**
21       * Returns the data at given fractional length. If only data beyond the fractional length is available, the first available
22       * value is returned. If only data before the fractional length is available, the last available value is returned.
23       * Otherwise data is linearly interpolated.
24       * @param fraction fractional length, may be outside range <code>[0.0, 1.0]</code>, but below 0.0 and above 1.1 the result
25       *            will be constant
26       * @return interpolated or extended value, at knots, or discontinuities, the result will be <code>NaN</code>
27       */
28      double get(double fraction);
29  
30      /**
31       * Returns the derivative of the data with respect to fractional length.
32       * @return derivative of this MathFunction
33       */
34      MathFunction getDerivative();
35  
36      /**
37       * Attempts to find a simplified version of this MathFunction (e.g. replace <code>1 - 5</code> by <code>-4</code>).
38       * @return <code>this</code>, or a simplified version thereof
39       */
40      default MathFunction simplify()
41      {
42          return this;
43      }
44  
45      /**
46       * Get the scale factor of this MathFunction.
47       * @return the scale factor of this MathFunction
48       */
49      default double getScale()
50      {
51          return 1.0;
52      }
53  
54      /**
55       * Incorporate a multiplication factor to this MathFunction.
56       * @param factor the factor to incorporate
57       * @return a new MathFunction that yields the same result as the original function multiplied by the <code>factor</code>
58       */
59      MathFunction scaleBy(double factor);
60  
61      /**
62       * Format a numerical value. If the value is integer, format it without decimal point. If the value is not integer, use a
63       * reasonable format.
64       * @param value the value to format
65       * @return the formatted value
66       */
67      default String printValue(final double value)
68      {
69          if (value <= Long.MAX_VALUE && value >= Long.MIN_VALUE && value == Math.ceil(value))
70          {
71              return String.format("%d", (long) value);
72          }
73          return "" + value;
74      }
75  
76      /**
77       * Compare chains for sorting.
78       * @param chain1 chain <code>MathFunction</code> of first <code>MathFunction</code> (may be <code>null</code>)
79       * @param chain2 chain <code>MathFunction</code> of second <code>MathFunction</code> (may be <code>null</code>)
80       * @return int <code>&lt; 0</code> when <code>chain1</code> sorts before <code>chain2</code>; <code>&gt; 0</code> when
81       *         <code>chain1</code> sorts after <code>chain2</code>; <code>0</code> when <code>chain1</code> is equal to
82       *         <code>chain2</code>
83       */
84      default int compareChains(final MathFunction chain1, final MathFunction chain2)
85      {
86          if (chain1 == null && chain2 != null)
87          {
88              return 1;
89          }
90          if (chain1 != null && chain2 == null)
91          {
92              return -1;
93          }
94          if (chain1 != null)
95          {
96              return chain1.compareTo(chain2);
97          }
98          return 0;
99      }
100 
101     /**
102      * Sorting priority of this type of MathFunction (low values shall sort before higher).
103      * @return sorting priority of this type of MathFunction
104      */
105     int sortPriority();
106 
107     /**
108      * Determine sorting order among instances of a particular sub type of <code>MathFunction</code>. The sorting order should
109      * sort <code>MathFunction</code>s that may be combined next to one another. Because <code>MathFunction</code>s are also
110      * used in <code>SortedSet</code>s, this comparator may return 0 <b>if and only if</b> this and other are entirely equal!
111      * @param other the other <code>MathFunction</code> that must be of the same type
112      * @return int; &lt; 0 when this sorts before other; &gt; 0 when this sorts after other; 0 when this and other are identical
113      */
114     int compareWithinSubType(MathFunction other);
115 
116     /**
117      * This MathFunction is added to another; try to replace both by a combined <code>MathFunction</code>.
118      * @param other the other <code>MathFunction</code>
119      * @return combined MathFunction, or null when the two could not be combined
120      */
121     default MathFunction mergeAdd(final MathFunction other)
122     {
123         return null;
124     }
125 
126     /**
127      * This MathFunction is multiplied by another; try to replace both by a combined MathFunction.
128      * @param other the other MathFunction
129      * @return combined MathFunction, or null when the two could not be combined
130      */
131     default MathFunction mergeMultiply(final MathFunction other)
132     {
133         return null;
134     }
135 
136     /**
137      * This MathFunction is divided by another; try to replace both by a combined MathFunction.
138      * @param other the other MathFunction
139      * @return combined MathFunction, or null when the two could not be combined
140      */
141     default MathFunction mergeDivide(final MathFunction other)
142     {
143         return null;
144     }
145 
146     @Override
147     default int compareTo(final MathFunction other)
148     {
149         int result = this.sortPriority() - other.sortPriority();
150         if (result == 0)
151         {
152             return compareWithinSubType(other);
153         }
154         return result;
155     }
156 
157     /**
158      * Report what is known about knots of this <code>MathFunction</code> in some <code>Interval</code>. The report does
159      * <b>not</b> take chained functions into account.
160      * @param interval the <code>Interval</code> on which knowledge of knots is requested
161      * @return summary of what is known about knots in the Interval
162      */
163     KnotReport getKnotReport(Interval<?> interval);
164 
165     /**
166      * Report all knots of this <code>MathFunction</code> in some <code>Interval</code>. Throws
167      * <code>IllegalStateException</code> when the number of knots in the <code>Interval</code> is not known, or infinite.
168      * @param interval the <code>Interval</code> over which the knots must be reported
169      * @return all the knots of this <code>MathFunction</code> in the requested <code>Interval</code>
170      * @throws UnsupportedOperationException when the number of knots cannot be returned in a set because it is not known, or
171      *             infinite
172      */
173     SortedSet<Double> getKnots(Interval<?> interval);
174 
175     /**
176      * Wrapper for one domain and function value pair.
177      * @param s double; value in the domain of the function
178      * @param t double; value of the function for <code>s</code>
179      */
180     record TupleSt(double s, double t)
181     {
182     }
183 
184 }