source: src/main/java/agents/anac/y2019/harddealer/math3/analysis/function/Sinc.java

Last change on this file was 204, checked in by Katsuhide Fujita, 5 years ago

Fixed errors of ANAC2019 agents

  • Property svn:executable set to *
File size: 7.5 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package agents.anac.y2019.harddealer.math3.analysis.function;
19
20import agents.anac.y2019.harddealer.math3.analysis.DifferentiableUnivariateFunction;
21import agents.anac.y2019.harddealer.math3.analysis.FunctionUtils;
22import agents.anac.y2019.harddealer.math3.analysis.UnivariateFunction;
23import agents.anac.y2019.harddealer.math3.analysis.differentiation.DerivativeStructure;
24import agents.anac.y2019.harddealer.math3.analysis.differentiation.UnivariateDifferentiableFunction;
25import agents.anac.y2019.harddealer.math3.exception.DimensionMismatchException;
26import agents.anac.y2019.harddealer.math3.util.FastMath;
27
28/**
29 * <a href="http://en.wikipedia.org/wiki/Sinc_function">Sinc</a> function,
30 * defined by
31 * <pre><code>
32 * sinc(x) = 1 if x = 0,
33 * sin(x) / x otherwise.
34 * </code></pre>
35 *
36 * @since 3.0
37 */
38public class Sinc implements UnivariateDifferentiableFunction, DifferentiableUnivariateFunction {
39 /**
40 * Value below which the computations are done using Taylor series.
41 * <p>
42 * The Taylor series for sinc even order derivatives are:
43 * <pre>
44 * d^(2n)sinc/dx^(2n) = Sum_(k>=0) (-1)^(n+k) / ((2k)!(2n+2k+1)) x^(2k)
45 * = (-1)^n [ 1/(2n+1) - x^2/(4n+6) + x^4/(48n+120) - x^6/(1440n+5040) + O(x^8) ]
46 * </pre>
47 * </p>
48 * <p>
49 * The Taylor series for sinc odd order derivatives are:
50 * <pre>
51 * d^(2n+1)sinc/dx^(2n+1) = Sum_(k>=0) (-1)^(n+k+1) / ((2k+1)!(2n+2k+3)) x^(2k+1)
52 * = (-1)^(n+1) [ x/(2n+3) - x^3/(12n+30) + x^5/(240n+840) - x^7/(10080n+45360) + O(x^9) ]
53 * </pre>
54 * </p>
55 * <p>
56 * So the ratio of the fourth term with respect to the first term
57 * is always smaller than x^6/720, for all derivative orders.
58 * This implies that neglecting this term and using only the first three terms induces
59 * a relative error bounded by x^6/720. The SHORTCUT value is chosen such that this
60 * relative error is below double precision accuracy when |x| <= SHORTCUT.
61 * </p>
62 */
63 private static final double SHORTCUT = 6.0e-3;
64 /** For normalized sinc function. */
65 private final boolean normalized;
66
67 /**
68 * The sinc function, {@code sin(x) / x}.
69 */
70 public Sinc() {
71 this(false);
72 }
73
74 /**
75 * Instantiates the sinc function.
76 *
77 * @param normalized If {@code true}, the function is
78 * <code> sin(&pi;x) / &pi;x</code>, otherwise {@code sin(x) / x}.
79 */
80 public Sinc(boolean normalized) {
81 this.normalized = normalized;
82 }
83
84 /** {@inheritDoc} */
85 public double value(final double x) {
86 final double scaledX = normalized ? FastMath.PI * x : x;
87 if (FastMath.abs(scaledX) <= SHORTCUT) {
88 // use Taylor series
89 final double scaledX2 = scaledX * scaledX;
90 return ((scaledX2 - 20) * scaledX2 + 120) / 120;
91 } else {
92 // use definition expression
93 return FastMath.sin(scaledX) / scaledX;
94 }
95 }
96
97 /** {@inheritDoc}
98 * @deprecated as of 3.1, replaced by {@link #value(DerivativeStructure)}
99 */
100 @Deprecated
101 public UnivariateFunction derivative() {
102 return FunctionUtils.toDifferentiableUnivariateFunction(this).derivative();
103 }
104
105 /** {@inheritDoc}
106 * @since 3.1
107 */
108 public DerivativeStructure value(final DerivativeStructure t)
109 throws DimensionMismatchException {
110
111 final double scaledX = (normalized ? FastMath.PI : 1) * t.getValue();
112 final double scaledX2 = scaledX * scaledX;
113
114 double[] f = new double[t.getOrder() + 1];
115
116 if (FastMath.abs(scaledX) <= SHORTCUT) {
117
118 for (int i = 0; i < f.length; ++i) {
119 final int k = i / 2;
120 if ((i & 0x1) == 0) {
121 // even derivation order
122 f[i] = (((k & 0x1) == 0) ? 1 : -1) *
123 (1.0 / (i + 1) - scaledX2 * (1.0 / (2 * i + 6) - scaledX2 / (24 * i + 120)));
124 } else {
125 // odd derivation order
126 f[i] = (((k & 0x1) == 0) ? -scaledX : scaledX) *
127 (1.0 / (i + 2) - scaledX2 * (1.0 / (6 * i + 24) - scaledX2 / (120 * i + 720)));
128 }
129 }
130
131 } else {
132
133 final double inv = 1 / scaledX;
134 final double cos = FastMath.cos(scaledX);
135 final double sin = FastMath.sin(scaledX);
136
137 f[0] = inv * sin;
138
139 // the nth order derivative of sinc has the form:
140 // dn(sinc(x)/dxn = [S_n(x) sin(x) + C_n(x) cos(x)] / x^(n+1)
141 // where S_n(x) is an even polynomial with degree n-1 or n (depending on parity)
142 // and C_n(x) is an odd polynomial with degree n-1 or n (depending on parity)
143 // S_0(x) = 1, S_1(x) = -1, S_2(x) = -x^2 + 2, S_3(x) = 3x^2 - 6...
144 // C_0(x) = 0, C_1(x) = x, C_2(x) = -2x, C_3(x) = -x^3 + 6x...
145 // the general recurrence relations for S_n and C_n are:
146 // S_n(x) = x S_(n-1)'(x) - n S_(n-1)(x) - x C_(n-1)(x)
147 // C_n(x) = x C_(n-1)'(x) - n C_(n-1)(x) + x S_(n-1)(x)
148 // as per polynomials parity, we can store both S_n and C_n in the same array
149 final double[] sc = new double[f.length];
150 sc[0] = 1;
151
152 double coeff = inv;
153 for (int n = 1; n < f.length; ++n) {
154
155 double s = 0;
156 double c = 0;
157
158 // update and evaluate polynomials S_n(x) and C_n(x)
159 final int kStart;
160 if ((n & 0x1) == 0) {
161 // even derivation order, S_n is degree n and C_n is degree n-1
162 sc[n] = 0;
163 kStart = n;
164 } else {
165 // odd derivation order, S_n is degree n-1 and C_n is degree n
166 sc[n] = sc[n - 1];
167 c = sc[n];
168 kStart = n - 1;
169 }
170
171 // in this loop, k is always even
172 for (int k = kStart; k > 1; k -= 2) {
173
174 // sine part
175 sc[k] = (k - n) * sc[k] - sc[k - 1];
176 s = s * scaledX2 + sc[k];
177
178 // cosine part
179 sc[k - 1] = (k - 1 - n) * sc[k - 1] + sc[k -2];
180 c = c * scaledX2 + sc[k - 1];
181
182 }
183 sc[0] *= -n;
184 s = s * scaledX2 + sc[0];
185
186 coeff *= inv;
187 f[n] = coeff * (s * sin + c * scaledX * cos);
188
189 }
190
191 }
192
193 if (normalized) {
194 double scale = FastMath.PI;
195 for (int i = 1; i < f.length; ++i) {
196 f[i] *= scale;
197 scale *= FastMath.PI;
198 }
199 }
200
201 return t.compose(f);
202
203 }
204
205}
Note: See TracBrowser for help on using the repository browser.