001 /*
002 * Java Genetic Algorithm Library (jenetics-4.4.0).
003 * Copyright (c) 2007-2019 Franz Wilhelmstötter
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 * Author:
018 * Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
019 */
020 package io.jenetics.prog.op;
021
022 import static java.lang.Math.abs;
023 import static java.lang.Math.acos;
024 import static java.lang.Math.asin;
025 import static java.lang.Math.atan;
026 import static java.lang.Math.cbrt;
027 import static java.lang.Math.ceil;
028 import static java.lang.Math.cos;
029 import static java.lang.Math.cosh;
030 import static java.lang.Math.exp;
031 import static java.lang.Math.floor;
032 import static java.lang.Math.hypot;
033 import static java.lang.Math.log;
034 import static java.lang.Math.log10;
035 import static java.lang.Math.max;
036 import static java.lang.Math.min;
037 import static java.lang.Math.pow;
038 import static java.lang.Math.rint;
039 import static java.lang.Math.signum;
040 import static java.lang.Math.sin;
041 import static java.lang.Math.sinh;
042 import static java.lang.Math.sqrt;
043 import static java.lang.Math.tan;
044 import static java.lang.Math.tanh;
045 import static java.util.Objects.requireNonNull;
046
047 import java.util.Objects;
048 import java.util.Optional;
049 import java.util.OptionalDouble;
050 import java.util.function.Function;
051 import java.util.stream.Stream;
052
053 /**
054 * This class contains operations for performing basic numeric operations.
055 *
056 * @see Math
057 *
058 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
059 * @version 3.9
060 * @since 3.9
061 */
062 public enum MathOp implements Op<Double> {
063
064
065 /* *************************************************************************
066 * Arithmetic operations
067 * ************************************************************************/
068
069 /**
070 * Return the absolute value of a double value.
071 * <em>This operation has arity 1.</em>
072 *
073 * @see Math#abs(double)
074 */
075 ABS("abs", 1, v -> abs(v[0])),
076
077 /**
078 * Return the negation value of a double value.
079 * <em>This operation has arity 1.</em>
080 */
081 NEG("neg", 1, v -> -v[0]),
082
083 /**
084 * Return the minimum of two values.
085 * <em>This operation has arity 2.</em>
086 *
087 * @see Math#min(double, double)
088 */
089 MIN("min", 2, v -> min(v[0], v[1])),
090
091 /**
092 * Return the maximum of two values
093 * <em>This operation has arity 2.</em>
094 *
095 * @see Math#max(double, double)
096 */
097 MAX("max", 2, v -> max(v[0], v[1])),
098
099 /**
100 * Returns the smallest (closest to negative infinity) double value that is
101 * greater than or equal to the argument and is equal to a mathematical
102 * integer.
103 * <em>This operation has arity 1.</em>
104 *
105 * @see Math#ceil(double)
106 */
107 CEIL("ceil", 1, v -> ceil(v[0])),
108
109 /**
110 * Returns the largest (closest to positive infinity) double value that is
111 * less than or equal to the argument and is equal to a mathematical integer.
112 * <em>This operation has arity 1.</em>
113 *
114 * @see Math#floor(double)
115 */
116 FLOOR("floor", 1, v -> floor(v[0])),
117
118 /**
119 * Returns the signum function of the argument; zero if the argument is
120 * zero, 1.0 if the argument is greater than zero, -1.0 if the argument is
121 * less than zero.
122 * <em>This operation has arity 1.</em>
123 *
124 * @see Math#signum(double)
125 */
126 SIGNUM("signum", 1, v -> signum(v[0])),
127
128 /**
129 * Returns the double value that is closest in value to the argument and is
130 * equal to a mathematical integer.
131 * <em>This operation has arity 1.</em>
132 *
133 * @see Math#rint(double)
134 */
135 RINT("rint", 1, v -> rint(v[0])),
136
137 /**
138 * Returns the sum of its arguments.
139 * <em>This operation has arity 2.</em>
140 */
141 ADD("add", 2, v -> v[0] + v[1]),
142
143 /**
144 * Return the diff of its arguments.
145 * <em>This operation has arity 2.</em>
146 */
147 SUB("sub", 2, v -> v[0] - v[1]),
148
149 /**
150 * Returns the product of its arguments.
151 * <em>This operation has arity 2.</em>
152 */
153 MUL("mul", 2, v -> v[0]*v[1]),
154
155 /**
156 * Returns the quotient of its arguments.
157 * <em>This operation has arity 2.</em>
158 */
159 DIV("div", 2, v -> v[0]/v[1]),
160
161 /**
162 * Returns the modulo of its arguments.
163 * <em>This operation has arity 2.</em>
164 */
165 MOD("mod", 2, v -> v[0]%v[1]),
166
167 /**
168 * Returns the value of the first argument raised to the power of the second
169 * argument.
170 * <em>This operation has arity 2.</em>
171 *
172 * @see Math#pow(double, double)
173 */
174 POW("pow", 2, v -> pow(v[0], v[1])),
175
176 /**
177 * Returns the square value of a given double value.
178 * <em>This operation has arity 1.</em>
179 */
180 SQR("sqr", 1, v -> v[0]*v[0]),
181
182 /**
183 * Returns the correctly rounded positive square root of a double value.
184 * <em>This operation has arity 1.</em>
185 *
186 * @see Math#sqrt(double)
187 */
188 SQRT("sqrt", 1, v -> sqrt(v[0])),
189
190 /**
191 * Returns the cube root of a double value.
192 * <em>This operation has arity 1.</em>
193 *
194 * @see Math#cbrt(double)
195 */
196 CBRT("cbrt", 1, v -> cbrt(v[0])),
197
198 /**
199 * Returns sqrt(<i>x</i><sup>2</sup> +<i>y</i><sup>2</sup>) without
200 * intermediate overflow or underflow.
201 * <em>This operation has arity 2.</em>
202 *
203 * @see Math#hypot(double, double)
204 */
205 HYPOT("hypot", 2, v -> hypot(v[0], v[1])),
206
207
208 /* *************************************************************************
209 * Exponential/logarithmic operations
210 * ************************************************************************/
211
212 /**
213 * Returns Euler's number e raised to the power of a double value.
214 * <em>This operation has arity 1.</em>
215 *
216 * @see Math#exp(double)
217 */
218 EXP("exp", 1, v -> exp(v[0])),
219
220 /**
221 * Returns the natural logarithm (base e) of a double value.
222 * <em>This operation has arity 1.</em>
223 *
224 * @see Math#log(double)
225 */
226 LOG("log", 1, v -> log(v[0])),
227
228 /**
229 * Returns the base 10 logarithm of a double value.
230 * <em>This operation has arity 1.</em>
231 *
232 * @see Math#log10(double)
233 */
234 LOG10("log10", 1, v -> log10(v[0])),
235
236
237 /* *************************************************************************
238 * Trigonometric operations
239 * ************************************************************************/
240
241 /**
242 * Returns the trigonometric sine of an angle.
243 * <em>This operation has arity 1.</em>
244 *
245 * @see Math#sin(double)
246 */
247 SIN("sin", 1, v -> sin(v[0])),
248
249 /**
250 * Returns the trigonometric cosine of an angle.
251 * <em>This operation has arity 1.</em>
252 *
253 * @see Math#cos(double)
254 */
255 COS("cos", 1, v -> cos(v[0])),
256
257 /**
258 * Returns the trigonometric tangent of an angle.
259 * <em>This operation has arity 1.</em>
260 *
261 * @see Math#tan(double)
262 */
263 TAN("tan", 1, v -> tan(v[0])),
264
265 /**
266 * Returns the arc cosine of a double value.
267 * <em>This operation has arity 1.</em>
268 *
269 * @see Math#acos(double)
270 */
271 ACOS("acos", 1, v -> acos(v[0])),
272
273 /**
274 * Returns the arc sine of a double value.
275 * <em>This operation has arity 1.</em>
276 *
277 * @see Math#asin(double)
278 */
279 ASIN("asin", 1, v -> asin(v[0])),
280
281 /**
282 * Returns the arc tangent of a value.
283 * <em>This operation has arity 1.</em>
284 *
285 * @see Math#atan(double)
286 */
287 ATAN("atan", 1, v -> atan(v[0])),
288
289 /**
290 * Returns the hyperbolic cosine of a double value.
291 * <em>This operation has arity 1.</em>
292 *
293 * @see Math#cosh(double)
294 */
295 COSH("cosh", 1, v -> cosh(v[0])),
296
297 /**
298 * Returns the hyperbolic sine of a double value.
299 * <em>This operation has arity 1.</em>
300 *
301 * @see Math#sinh(double)
302 */
303 SINH("sinh", 1, v -> sinh(v[0])),
304
305 /**
306 * Returns the hyperbolic tangent of a double value.
307 * <em>This operation has arity 1.</em>
308 *
309 * @see Math#tanh(double)
310 */
311 TANH("tanh", 1, v -> tanh(v[0]));
312
313
314 /**
315 * The double value that is closer than any other to pi, the ratio of the
316 * circumference of a circle to its diameter. <em>This is a terminal
317 * operation.</em>
318 *
319 * @see Math#PI
320 */
321 public static final Const<Double> PI = Const.of("π", Math.PI);
322
323 /**
324 * The double value that is closer than any other to e, the base of the
325 * natural logarithms. <em>This is a terminal operation.</em>
326 *
327 * @see Math#E
328 */
329 public static final Const<Double> E = Const.of("e", Math.E);
330
331
332 private final String _name;
333 private final int _arity;
334 private final Function<Double[], Double> _function;
335
336 private MathOp(
337 final String name,
338 final int arity,
339 final Function<Double[], Double> function
340 ) {
341 assert name != null;
342 assert arity >= 0;
343 assert function != null;
344
345 _name = name;
346 _function = function;
347 _arity = arity;
348 }
349
350 @Override
351 public int arity() {
352 return _arity;
353 }
354
355 @Override
356 public Double apply(final Double[] doubles) {
357 return _function.apply(doubles);
358 }
359
360 @Override
361 public String toString() {
362 return _name;
363 }
364
365
366 /**
367 * Tests whether the given operation is equal with the given string
368 * representation.
369 *
370 * @param op the operation to test
371 * @param value the string representation of the operation to test
372 * @return {@code true} if the given string {@code value} is the string
373 * representation of the given {@code op}, {@code false} otherwise
374 * @throws NullPointerException if one of the arguments is {@code null}
375 */
376 static boolean equals(final Op<Double> op, final String value) {
377 final Optional<Double> number = Numbers.tryParseDouble(value);
378 if (number.isPresent() && op instanceof Const) {
379 final double d = number.orElseThrow(AssertionError::new);
380 final Const<Double> c = (Const<Double>)op;
381
382 return Double.compare(d, c.value()) == 0;
383 }
384
385 return Objects.equals(op.toString(), value);
386 }
387
388 /**
389 * Converts the string representation of an operation to the operation
390 * object.
391 *
392 * @param string the string representation of an operation which should be
393 * converted
394 * @return the operation, converted from the given string
395 * @throws IllegalArgumentException if the given {@code value} doesn't
396 * represent a mathematical expression
397 * @throws NullPointerException if the given string {@code value} is
398 * {@code null}
399 */
400 static Op<Double> convert(final String string) {
401 requireNonNull(string);
402
403 final Op<Double> result;
404 final Optional<Op<Double>> cop = toConst(string);
405 if (cop.isPresent()) {
406 result = cop.orElseThrow(AssertionError::new);
407 } else {
408 final Optional<Op<Double>> mop = toMathOp(string);
409 result = mop.isPresent()
410 ? mop.orElseThrow(AssertionError::new)
411 : Var.of(string, 0);
412 }
413
414 return result;
415 }
416
417 private static Optional<Op<Double>> toConst(final String string) {
418 return Numbers
419 .tryParseDouble(string)
420 .map(Const::of);
421 }
422
423 private static Optional<Op<Double>> toMathOp(final String string) {
424 return Stream.of(values())
425 .filter(op -> Objects.equals(op._name, string))
426 .map(op -> (Op<Double>)op)
427 .findFirst();
428 }
429
430 }
|