Numbers.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-7.1.1).
003  * Copyright (c) 2007-2022 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.util.Objects.requireNonNull;
023 
024 import java.util.Optional;
025 import java.util.regex.Pattern;
026 
027 /**
028  @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
029  @version 4.4
030  @since 4.4
031  */
032 final class Numbers {
033     private Numbers() {}
034 
035     // Regex for checking if parsable as double as described in
036     // Double.valueOf Java documentation.
037 
038     private static final String DIGITS = "(\\p{Digit}+)";
039 
040     private static final String HEX_DIGITS = "(\\p{XDigit}+)";
041 
042     // an exponent is 'e' or 'E' followed by an optionally
043     // signed decimal integer.
044     private static final String EXP = "[eE][+-]?"+ DIGITS;
045 
046     private static final String FP_REGEX =
047         "[\\x00-\\x20]*"+  // Optional leading "whitespace"
048         "[+-]?(" +         // Optional sign character
049         "NaN|" +           // "NaN" string
050         "Infinity|" +      // "Infinity" string
051 
052         // A decimal floating-point string representing a finite positive
053         // number without a leading sign has at most five basic pieces:
054         // Digits . Digits ExponentPart FloatTypeSuffix
055         //
056         // Since this method allows integer-only strings as input
057         // in addition to strings of floating-point literals, the
058         // two sub-patterns below are simplifications of the grammar
059         // productions from section 3.10.2 of
060         // The Java Language Specification.
061 
062         // Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
063         "((("+ DIGITS +"(\\.)?("+ DIGITS +"?)("+ EXP +")?)|"+
064 
065         // . Digits ExponentPart_opt FloatTypeSuffix_opt
066         "(\\.("+ DIGITS +")("+ EXP +")?)|"+
067 
068         // Hexadecimal strings
069         "((" +
070         // 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt
071         "(0[xX]" + HEX_DIGITS + "(\\.)?)|" +
072 
073         // 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt
074         "(0[xX]" + HEX_DIGITS + "?(\\.)" + HEX_DIGITS + ")" +
075 
076         ")[pP][+-]?" + DIGITS + "))" +
077         "[fFdD]?))" +
078         "[\\x00-\\x20]*";// Optional trailing "whitespace"
079 
080     private static final Pattern FP_PATTERN = Pattern.compile(FP_REGEX);
081 
082     static boolean isNumber(final String value) {
083         requireNonNull(value);
084         return FP_PATTERN.matcher(value).matches();
085     }
086 
087     static Optional<Double> toDoubleOptional(final String value) {
088         return isNumber(value)
089             ? Optional.of(Double.parseDouble(value))
090             : Optional.empty();
091     }
092 
093     static Double[] box(final double... values) {
094         final Double[] result = new Double[values.length];
095         for (int i = values.length; --i >= 0;) {
096             result[i= values[i];
097         }
098         return result;
099     }
100 
101 }