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