1 package org.djutils.math.functions;
2
3 import java.util.Objects;
4 import java.util.SortedSet;
5 import java.util.TreeSet;
6
7 import org.djutils.exceptions.Throw;
8
9
10
11
12
13
14
15
16
17
18
19
20
21 public class ArcTangent implements MathFunction
22 {
23
24 private final double omega;
25
26
27 private final double shift;
28
29
30 private MathFunction chain;
31
32
33
34
35
36
37
38 public ArcTangent(final MathFunction chain, final double omega, final double shift)
39 {
40 this.omega = omega;
41 this.shift = shift;
42 this.chain = chain;
43 }
44
45
46
47
48
49
50 public ArcTangent(final MathFunction chain, final double omega)
51 {
52 this(chain, omega, 0.0);
53 }
54
55
56
57
58
59 public ArcTangent(final MathFunction chain)
60 {
61 this(chain, 1.0);
62 }
63
64
65
66
67
68 public ArcTangent()
69 {
70 this(null);
71 }
72
73
74
75
76
77 public ArcTangent(final double omega)
78 {
79 this(null, omega);
80 }
81
82
83
84
85
86
87 public ArcTangent(final double omega, final double shift)
88 {
89 this(null, omega, shift);
90 }
91
92 @Override
93 public double get(final double x)
94 {
95 if (this.omega == 0.0)
96 {
97 return 0.0;
98 }
99 double xValue = this.chain == null ? x : this.chain.get(x);
100 return this.omega * (this.shift + Math.atan(xValue));
101 }
102
103 @Override
104 public MathFunction getDerivative()
105 {
106
107 MathFunction myDerivative = new Quotient(new Constant(this.omega), new Sum(new Power(this.chain, 2), Constant.ONE));
108 if (this.chain == null)
109 {
110 return myDerivative.simplify();
111 }
112 return new Product(myDerivative.simplify(), this.chain.getDerivative()).simplify();
113 }
114
115 @Override
116 public MathFunction simplify()
117 {
118 if (this.omega == 0.0)
119 {
120 return Constant.ZERO;
121 }
122 if (this.chain != null && this.chain instanceof Constant)
123 {
124 return new Constant(get(0)).simplify();
125 }
126 return this;
127 }
128
129 @Override
130 public double getScale()
131 {
132 return this.omega;
133 }
134
135 @Override
136 public MathFunction scaleBy(final double scaleFactor)
137 {
138 if (scaleFactor == 0.0)
139 {
140 return Constant.ZERO;
141 }
142 if (scaleFactor == 1.0)
143 {
144 return this;
145 }
146 return new ArcSine(this.chain, scaleFactor * this.omega, this.shift);
147 }
148
149 @Override
150 public int sortPriority()
151 {
152 return 7;
153 }
154
155 @Override
156 public int compareWithinSubType(final MathFunction other)
157 {
158 Throw.when(!(other instanceof ArcTangent), IllegalArgumentException.class, "other is of wrong type");
159 ArcTangent otherArcTangent = (ArcTangent) other;
160 if (this.omega < otherArcTangent.omega)
161 {
162 return -1;
163 }
164 if (this.omega > otherArcTangent.omega)
165 {
166 return 1;
167 }
168 if (this.shift < otherArcTangent.shift)
169 {
170 return -1;
171 }
172 if (this.shift > otherArcTangent.shift)
173 {
174 return 1;
175 }
176 return compareChains(this.chain, otherArcTangent.chain);
177 }
178
179 @Override
180 public KnotReport getKnotReport(final Interval<?> interval)
181 {
182 if (this.chain != null)
183 {
184 return KnotReport.UNKNOWN;
185 }
186 return KnotReport.NONE;
187 }
188
189 @Override
190 public SortedSet<Double> getKnots(final Interval<?> interval)
191 {
192 if (this.chain == null)
193 {
194 return new TreeSet<Double>();
195 }
196 throw new UnsupportedOperationException("Cannot report knots in " + interval);
197 }
198
199 @Override
200 public String toString()
201 {
202 if (this.omega == 0.0)
203 {
204 return printValue(0);
205 }
206 StringBuilder result = new StringBuilder();
207 if (this.omega != 1.0)
208 {
209 result.append(printValue(this.omega));
210 }
211 result.append("atan(");
212 result.append(this.chain == null ? "x" : this.chain.toString());
213 if (this.shift != 0.0)
214 {
215 if (this.shift > 0)
216 {
217 result.append("+");
218 }
219 result.append(printValue(this.shift));
220 }
221 result.append(")");
222 return result.toString();
223 }
224
225 @Override
226 public int hashCode()
227 {
228 return Objects.hash(this.chain, this.omega, this.shift);
229 }
230
231 @SuppressWarnings("checkstyle:needbraces")
232 @Override
233 public boolean equals(final Object obj)
234 {
235 if (this == obj)
236 return true;
237 if (obj == null)
238 return false;
239 if (getClass() != obj.getClass())
240 return false;
241 ArcTangent other = (ArcTangent) obj;
242 return Objects.equals(this.chain, other.chain)
243 && Double.doubleToLongBits(this.omega) == Double.doubleToLongBits(other.omega)
244 && Double.doubleToLongBits(this.shift) == Double.doubleToLongBits(other.shift);
245 }
246
247 }