diff --git a/libs/core/src/main/java/org/elasticsearch/common/util/ESSloppyMath.java b/libs/core/src/main/java/org/elasticsearch/common/util/ESSloppyMath.java index 9c36b3f3e17a5..d123b89e8c7b8 100644 --- a/libs/core/src/main/java/org/elasticsearch/common/util/ESSloppyMath.java +++ b/libs/core/src/main/java/org/elasticsearch/common/util/ESSloppyMath.java @@ -1,38 +1,23 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.elasticsearch.common.util; - -/* - * ============================================================================= - * - * sinh and atan ported from - * https://github.com/yannrichet/jmathplot/blob/f25426e0ab0e68647ad2b75f577c7be050ecac86/src/main/java/org/math/plot/utils/FastMath.java - * (Apache 2.0) Copyright 2012 Jeff Hain, which is partially derived from fdlibm package - * - * ============================================================================= - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunSoft, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ============================================================================= + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ +package org.elasticsearch.common.util; /** * Similar to Lucene's SloppyMath, but for additional math functions. @@ -41,140 +26,11 @@ public class ESSloppyMath { private ESSloppyMath() {} - //-------------------------------------------------------------------------- - // RE-USABLE CONSTANTS - //-------------------------------------------------------------------------- - - private static final double ONE_DIV_F2 = 1/2.0; - private static final double ONE_DIV_F3 = 1/6.0; - private static final double ONE_DIV_F4 = 1/24.0; - private static final double TWO_POW_N28 = Double.longBitsToDouble(0x3E30000000000000L); - private static final double TWO_POW_66 = Double.longBitsToDouble(0x4410000000000000L); - private static final double LOG_DOUBLE_MAX_VALUE = StrictMath.log(Double.MAX_VALUE); - - //-------------------------------------------------------------------------- - // CONSTANTS AND TABLES FOR ATAN - //-------------------------------------------------------------------------- - - // We use the formula atan(-x) = -atan(x) - // ---> we only have to compute atan(x) on [0,+infinity[. - // For values corresponding to angles not close to +-PI/2, we use look-up tables; - // for values corresponding to angles near +-PI/2, we use code derived from fdlibm. - - // Supposed to be >= tan(67.7deg), as fdlibm code is supposed to work with values > 2.4375. - private static final double ATAN_MAX_VALUE_FOR_TABS = StrictMath.tan(Math.toRadians(74.0)); - - private static final int ATAN_TABS_SIZE = 1<<12 + 1; - private static final double ATAN_DELTA = ATAN_MAX_VALUE_FOR_TABS/(ATAN_TABS_SIZE - 1); - private static final double ATAN_INDEXER = 1/ATAN_DELTA; - private static final double[] atanTab = new double[ATAN_TABS_SIZE]; - private static final double[] atanDer1DivF1Tab = new double[ATAN_TABS_SIZE]; - private static final double[] atanDer2DivF2Tab = new double[ATAN_TABS_SIZE]; - private static final double[] atanDer3DivF3Tab = new double[ATAN_TABS_SIZE]; - private static final double[] atanDer4DivF4Tab = new double[ATAN_TABS_SIZE]; - - private static final double ATAN_HI3 = Double.longBitsToDouble(0x3ff921fb54442d18L); // 1.57079632679489655800e+00 atan(inf)hi - private static final double ATAN_LO3 = Double.longBitsToDouble(0x3c91a62633145c07L); // 6.12323399573676603587e-17 atan(inf)lo - private static final double ATAN_AT0 = Double.longBitsToDouble(0x3fd555555555550dL); // 3.33333333333329318027e-01 - private static final double ATAN_AT1 = Double.longBitsToDouble(0xbfc999999998ebc4L); // -1.99999999998764832476e-01 - private static final double ATAN_AT2 = Double.longBitsToDouble(0x3fc24924920083ffL); // 1.42857142725034663711e-01 - private static final double ATAN_AT3 = Double.longBitsToDouble(0xbfbc71c6fe231671L); // -1.11111104054623557880e-01 - private static final double ATAN_AT4 = Double.longBitsToDouble(0x3fb745cdc54c206eL); // 9.09088713343650656196e-02 - private static final double ATAN_AT5 = Double.longBitsToDouble(0xbfb3b0f2af749a6dL); // -7.69187620504482999495e-02 - private static final double ATAN_AT6 = Double.longBitsToDouble(0x3fb10d66a0d03d51L); // 6.66107313738753120669e-02 - private static final double ATAN_AT7 = Double.longBitsToDouble(0xbfadde2d52defd9aL); // -5.83357013379057348645e-02 - private static final double ATAN_AT8 = Double.longBitsToDouble(0x3fa97b4b24760debL); // 4.97687799461593236017e-02 - private static final double ATAN_AT9 = Double.longBitsToDouble(0xbfa2b4442c6a6c2fL); // -3.65315727442169155270e-02 - private static final double ATAN_AT10 = Double.longBitsToDouble(0x3f90ad3ae322da11L); // 1.62858201153657823623e-02 - - static { - // atan - for (int i=0;i ATAN_MAX_VALUE_FOR_TABS, or value is NaN - // This part is derived from fdlibm. - if (value < TWO_POW_66) { - double x = -1/value; - double x2 = x*x; - double x4 = x2*x2; - double s1 = x2*(ATAN_AT0+x4*(ATAN_AT2+x4*(ATAN_AT4+x4*(ATAN_AT6+x4*(ATAN_AT8+x4*ATAN_AT10))))); - double s2 = x4*(ATAN_AT1+x4*(ATAN_AT3+x4*(ATAN_AT5+x4*(ATAN_AT7+x4*ATAN_AT9)))); - double result = ATAN_HI3-((x*(s1+s2)-ATAN_LO3)-x); - return negateResult ? -result : result; - } else { // value >= 2^66, or value is NaN - if (Double.isNaN(value)) { - return Double.NaN; - } else { - return negateResult ? -Math.PI/2 : Math.PI/2; - } - } - } + return FastMath.atan(value); } } diff --git a/libs/core/src/main/java/org/elasticsearch/common/util/FastMath.java b/libs/core/src/main/java/org/elasticsearch/common/util/FastMath.java new file mode 100644 index 0000000000000..6446e706442ee --- /dev/null +++ b/libs/core/src/main/java/org/elasticsearch/common/util/FastMath.java @@ -0,0 +1,181 @@ +/* + * Copyright 2012 Jeff Hain + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * ============================================================================= + * Notice of fdlibm package this program is partially derived from: + * + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ============================================================================= + */ + +/* + * This code sourced from: + * https://github.com/yannrichet/jmathplot/blob/f25426e0ab0e68647ad2b75f577c7be050ecac86/src/main/java/org/math/plot/utils/FastMath.java + */ + +package org.elasticsearch.common.util; + +/** + * Additions or modifications to this class should only come from the original org.math.plot.utils.FastMath source + */ +final class FastMath { + + private FastMath() { } + + //-------------------------------------------------------------------------- + // RE-USABLE CONSTANTS + //-------------------------------------------------------------------------- + + private static final double ONE_DIV_F2 = 1/2.0; + private static final double ONE_DIV_F3 = 1/6.0; + private static final double ONE_DIV_F4 = 1/24.0; + private static final double TWO_POW_N28 = Double.longBitsToDouble(0x3E30000000000000L); + private static final double TWO_POW_66 = Double.longBitsToDouble(0x4410000000000000L); + private static final double LOG_DOUBLE_MAX_VALUE = StrictMath.log(Double.MAX_VALUE); + + //-------------------------------------------------------------------------- + // CONSTANTS AND TABLES FOR ATAN + //-------------------------------------------------------------------------- + + // We use the formula atan(-x) = -atan(x) + // ---> we only have to compute atan(x) on [0,+infinity[. + // For values corresponding to angles not close to +-PI/2, we use look-up tables; + // for values corresponding to angles near +-PI/2, we use code derived from fdlibm. + + // Supposed to be >= tan(67.7deg), as fdlibm code is supposed to work with values > 2.4375. + private static final double ATAN_MAX_VALUE_FOR_TABS = StrictMath.tan(Math.toRadians(74.0)); + + private static final int ATAN_TABS_SIZE = 1<<12 + 1; + private static final double ATAN_DELTA = ATAN_MAX_VALUE_FOR_TABS/(ATAN_TABS_SIZE - 1); + private static final double ATAN_INDEXER = 1/ATAN_DELTA; + private static final double[] atanTab = new double[ATAN_TABS_SIZE]; + private static final double[] atanDer1DivF1Tab = new double[ATAN_TABS_SIZE]; + private static final double[] atanDer2DivF2Tab = new double[ATAN_TABS_SIZE]; + private static final double[] atanDer3DivF3Tab = new double[ATAN_TABS_SIZE]; + private static final double[] atanDer4DivF4Tab = new double[ATAN_TABS_SIZE]; + + private static final double ATAN_HI3 = Double.longBitsToDouble(0x3ff921fb54442d18L); // 1.57079632679489655800e+00 atan(inf)hi + private static final double ATAN_LO3 = Double.longBitsToDouble(0x3c91a62633145c07L); // 6.12323399573676603587e-17 atan(inf)lo + private static final double ATAN_AT0 = Double.longBitsToDouble(0x3fd555555555550dL); // 3.33333333333329318027e-01 + private static final double ATAN_AT1 = Double.longBitsToDouble(0xbfc999999998ebc4L); // -1.99999999998764832476e-01 + private static final double ATAN_AT2 = Double.longBitsToDouble(0x3fc24924920083ffL); // 1.42857142725034663711e-01 + private static final double ATAN_AT3 = Double.longBitsToDouble(0xbfbc71c6fe231671L); // -1.11111104054623557880e-01 + private static final double ATAN_AT4 = Double.longBitsToDouble(0x3fb745cdc54c206eL); // 9.09088713343650656196e-02 + private static final double ATAN_AT5 = Double.longBitsToDouble(0xbfb3b0f2af749a6dL); // -7.69187620504482999495e-02 + private static final double ATAN_AT6 = Double.longBitsToDouble(0x3fb10d66a0d03d51L); // 6.66107313738753120669e-02 + private static final double ATAN_AT7 = Double.longBitsToDouble(0xbfadde2d52defd9aL); // -5.83357013379057348645e-02 + private static final double ATAN_AT8 = Double.longBitsToDouble(0x3fa97b4b24760debL); // 4.97687799461593236017e-02 + private static final double ATAN_AT9 = Double.longBitsToDouble(0xbfa2b4442c6a6c2fL); // -3.65315727442169155270e-02 + private static final double ATAN_AT10 = Double.longBitsToDouble(0x3f90ad3ae322da11L); // 1.62858201153657823623e-02 + + static { + // atan + for (int i=0;i ATAN_MAX_VALUE_FOR_TABS, or value is NaN + // This part is derived from fdlibm. + if (value < TWO_POW_66) { + double x = -1/value; + double x2 = x*x; + double x4 = x2*x2; + double s1 = x2*(ATAN_AT0+x4*(ATAN_AT2+x4*(ATAN_AT4+x4*(ATAN_AT6+x4*(ATAN_AT8+x4*ATAN_AT10))))); + double s2 = x4*(ATAN_AT1+x4*(ATAN_AT3+x4*(ATAN_AT5+x4*(ATAN_AT7+x4*ATAN_AT9)))); + double result = ATAN_HI3-((x*(s1+s2)-ATAN_LO3)-x); + return negateResult ? -result : result; + } else { // value >= 2^66, or value is NaN + if (Double.isNaN(value)) { + return Double.NaN; + } else { + return negateResult ? -Math.PI/2 : Math.PI/2; + } + } + } + } + +} diff --git a/libs/core/src/test/java/org/elasticsearch/common/util/ESSloppyMathTests.java b/libs/core/src/test/java/org/elasticsearch/common/util/ESSloppyMathTests.java index 35afbe77ff882..24ac1e0176392 100644 --- a/libs/core/src/test/java/org/elasticsearch/common/util/ESSloppyMathTests.java +++ b/libs/core/src/test/java/org/elasticsearch/common/util/ESSloppyMathTests.java @@ -1,19 +1,22 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ + package org.elasticsearch.common.util; import org.elasticsearch.test.ESTestCase;