MathOp.java
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>&nbsp;+<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 }