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 ArcSine 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 ArcSine(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 ArcSine(final MathFunction chain, final double omega)
51 {
52 this(chain, omega, 0.0);
53 }
54
55
56
57
58
59 public ArcSine(final MathFunction chain)
60 {
61 this(chain, 1.0);
62 }
63
64
65
66
67
68 public ArcSine()
69 {
70 this(null);
71 }
72
73
74
75
76
77 public ArcSine(final double omega)
78 {
79 this(null, omega);
80 }
81
82
83
84
85
86
87 public ArcSine(final double omega, final double shift)
88 {
89 this(null, omega, shift);
90 }
91
92
93
94
95
96
97
98 public static ArcSine arcCosine(final MathFunction chain, final double omega)
99 {
100 return new ArcSine(chain, -omega, -Math.PI / 2);
101 }
102
103 @Override
104 public double get(final double x)
105 {
106 if (this.omega == 0.0)
107 {
108 return 0.0;
109 }
110 double xValue = this.chain == null ? x : this.chain.get(x);
111 return this.omega * (this.shift + Math.asin(xValue));
112 }
113
114 @Override
115 public MathFunction getDerivative()
116 {
117
118 MathFunction myDerivative = new Power(
119 new Sum(new Power(this.chain, -1, 2), new Power(-2 * this.shift, 1), new Constant(1 - this.shift * this.shift)),
120 1, -0.5).scaleBy(this.omega);
121 if (this.chain == null)
122 {
123 return myDerivative.simplify();
124 }
125 return new Product(myDerivative.simplify(), this.chain.getDerivative()).simplify();
126 }
127
128 @Override
129 public MathFunction simplify()
130 {
131 if (this.omega == 0.0)
132 {
133 return Constant.ZERO;
134 }
135 if (this.chain != null && this.chain instanceof Constant)
136 {
137 return new Constant(get(0)).simplify();
138 }
139 return this;
140 }
141
142 @Override
143 public double getScale()
144 {
145 return this.omega;
146 }
147
148 @Override
149 public MathFunction scaleBy(final double scaleFactor)
150 {
151 if (scaleFactor == 0.0)
152 {
153 return Constant.ZERO;
154 }
155 if (scaleFactor == 1.0)
156 {
157 return this;
158 }
159 return new ArcSine(this.chain, scaleFactor * this.omega, this.shift);
160 }
161
162 @Override
163 public int sortPriority()
164 {
165 return 5;
166 }
167
168 @Override
169 public int compareWithinSubType(final MathFunction other)
170 {
171 Throw.when(!(other instanceof ArcSine), IllegalArgumentException.class, "other is of wrong type");
172 ArcSine otherArcSine = (ArcSine) other;
173 if (this.omega < otherArcSine.omega)
174 {
175 return -1;
176 }
177 if (this.omega > otherArcSine.omega)
178 {
179 return 1;
180 }
181 if (this.shift < otherArcSine.shift)
182 {
183 return -1;
184 }
185 if (this.shift > otherArcSine.shift)
186 {
187 return 1;
188 }
189 return compareChains(this.chain, otherArcSine.chain);
190 }
191
192 @Override
193 public KnotReport getKnotReport(final Interval<?> interval)
194 {
195 if (this.chain != null)
196 {
197 return KnotReport.UNKNOWN;
198 }
199 return interval.low() >= -1.0 && interval.high() <= 1.0 ? KnotReport.NONE : KnotReport.KNOWN_INFINITE;
200 }
201
202 @Override
203 public SortedSet<Double> getKnots(final Interval<?> interval)
204 {
205 if (this.chain == null && interval.low() >= -1.0 && interval.high() <= 1.0)
206 {
207 return new TreeSet<Double>();
208 }
209 throw new UnsupportedOperationException("Cannot report knots in " + interval);
210 }
211
212 @Override
213 public String toString()
214 {
215 if (this.omega == 0.0)
216 {
217 return printValue(0);
218 }
219 StringBuilder result = new StringBuilder();
220 if (this.omega != 1.0)
221 {
222 result.append(printValue(this.omega));
223 }
224 result.append("asin(");
225 result.append(this.chain == null ? "x" : this.chain.toString());
226 if (this.shift != 0.0)
227 {
228 if (this.shift > 0)
229 {
230 result.append("+");
231 }
232 result.append(printValue(this.shift));
233 }
234 result.append(")");
235 return result.toString();
236 }
237
238 @Override
239 public int hashCode()
240 {
241 return Objects.hash(this.chain, this.omega, this.shift);
242 }
243
244 @SuppressWarnings("checkstyle:needbraces")
245 @Override
246 public boolean equals(final Object obj)
247 {
248 if (this == obj)
249 return true;
250 if (obj == null)
251 return false;
252 if (getClass() != obj.getClass())
253 return false;
254 ArcSine other = (ArcSine) obj;
255 return Objects.equals(this.chain, other.chain)
256 && Double.doubleToLongBits(this.omega) == Double.doubleToLongBits(other.omega)
257 && Double.doubleToLongBits(this.shift) == Double.doubleToLongBits(other.shift);
258 }
259
260 }