Summary
-------
Relax monotonicity requirement for Vector API transcendental math operations while keeping the accuracy requirement.
Problem
-------
The SVML implementations used by the Vector API transcendental math operations are not guaranteed to be semi-monotonic.
To maximize performance the implementations avoid branching instructions, thereby allowing an optimal sequence of vector hardware instructions to be expressed. Consequently, the implementations do not produce correctly rounded results for some inputs.
Note that the SVML implementations do, however, follow accuracy specifications of the equivalent Java operations.
Solution
--------
Remove the monotonicity guarantee for the following Vector API math operations:
SIN, COS, TAN, ASIN, ACOS, ATAN, EXP, LOG, LOG10, CBRT, SINH, COSH, TANH, EXPM1, LOG1P, ATAN2, POW, HYPOT
Specification
-------------
Please see the JavaDoc linked here and attached as docs_2.tgz:
https://cr.openjdk.java.net/~sviswanathan/CSRs/CSR_for_JDK_8265783/docs_2/api/jdk.incubator.vector/jdk/incubator/vector/VectorOperators.html
The corresponding webrev is at https://cr.openjdk.java.net/~sviswanathan/CSRs/CSR_for_JDK_8265783/webrev_2/. Also it is attached as webrev_2.tgz.
The section "Operations on floating point vectors" is changed as follows:
* <h2>Operations on floating point vectors</h2>
* <ul>
* <li>Lane-wise vector operations that apply to floating point vectors
* follow the accuracy and monotonicity specifications of the equivalent
* Java operation or method mentioned in its documentation unless specified otherwise.
* If the vector element type is {@code float} and the Java operation or
* method only accepts and returns {@code double} values, then the scalar operation
* on each lane is adapted to cast operands and the result, specifically widening
* {@code float} operands to {@code double} operands and narrowing the {@code double}
* result to a {@code float}.
The description for SIN, COS, TAN, ASIN, ACOS, ATAN, EXP, LOG, LOG10, CBRT, SINH, COSH, TANH, EXPM1, LOG1P, ATAN2, POW, HYPOT is changed as follows:
/** Produce {@code sin(a)}. Floating only.
* Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
*/
public static final /*float*/ Unary SIN = unary("SIN", "sin", VectorSupport.VECTOR_OP_SIN, VO_ONLYFP);
/** Produce {@code cos(a)}. Floating only.
* Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
*/
public static final /*float*/ Unary COS = unary("COS", "cos", VectorSupport.VECTOR_OP_COS, VO_ONLYFP);
/** Produce {@code tan(a)}. Floating only.
* Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
*/
public static final /*float*/ Unary TAN = unary("TAN", "tan", VectorSupport.VECTOR_OP_TAN, VO_ONLYFP);
/** Produce {@code asin(a)}. Floating only.
* Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
*/
public static final /*float*/ Unary ASIN = unary("ASIN", "asin", VectorSupport.VECTOR_OP_ASIN, VO_ONLYFP);
/** Produce {@code acos(a)}. Floating only.
* Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
*/
public static final /*float*/ Unary ACOS = unary("ACOS", "acos", VectorSupport.VECTOR_OP_ACOS, VO_ONLYFP);
/** Produce {@code atan(a)}. Floating only.
* Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
*/
public static final /*float*/ Unary ATAN = unary("ATAN", "atan", VectorSupport.VECTOR_OP_ATAN, VO_ONLYFP);
/** Produce {@code exp(a)}. Floating only.
* Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
*/
public static final /*float*/ Unary EXP = unary("EXP", "exp", VectorSupport.VECTOR_OP_EXP, VO_ONLYFP);
/** Produce {@code log(a)}. Floating only.
* Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
*/
public static final /*float*/ Unary LOG = unary("LOG", "log", VectorSupport.VECTOR_OP_LOG, VO_ONLYFP);
/** Produce {@code log10(a)}. Floating only.
* Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
*/
public static final /*float*/ Unary LOG10 = unary("LOG10", "log10", VectorSupport.VECTOR_OP_LOG10, VO_ONLYFP);
/** Produce {@code cbrt(a)}. Floating only.
* Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
*/
public static final /*float*/ Unary CBRT = unary("CBRT", "cbrt", VectorSupport.VECTOR_OP_CBRT, VO_ONLYFP);
/** Produce {@code sinh(a)}. Floating only.
* Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
*/
public static final /*float*/ Unary SINH = unary("SINH", "sinh", VectorSupport.VECTOR_OP_SINH, VO_ONLYFP);
/** Produce {@code cosh(a)}. Floating only.
* Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
*/
public static final /*float*/ Unary COSH = unary("COSH", "cosh", VectorSupport.VECTOR_OP_COSH, VO_ONLYFP);
/** Produce {@code tanh(a)}. Floating only.
* Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
*/
public static final /*float*/ Unary TANH = unary("TANH", "tanh", VectorSupport.VECTOR_OP_TANH, VO_ONLYFP);
/** Produce {@code expm1(a)}. Floating only.
* Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
*/
public static final /*float*/ Unary EXPM1 = unary("EXPM1", "expm1", VectorSupport.VECTOR_OP_EXPM1, VO_ONLYFP);
/** Produce {@code log1p(a)}. Floating only.
* Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
*/
public static final /*float*/ Unary LOG1P = unary("LOG1P", "log1p", VectorSupport.VECTOR_OP_LOG1P, VO_ONLYFP);
/** Produce {@code atan2(a,b)}. See Floating only.
* Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
*/
public static final /*float*/ Binary ATAN2 = binary("ATAN2", "atan2", VectorSupport.VECTOR_OP_ATAN2, VO_ONLYFP);
/** Produce {@code pow(a,b)}. Floating only.
* Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
*/
public static final /*float*/ Binary POW = binary("POW", "pow", VectorSupport.VECTOR_OP_POW, VO_ONLYFP);
/** Produce {@code hypot(a,b)}. Floating only.
* Not guaranteed to be semi-monotonic. See section "Operations on floating point vectors" above
*/
public static final /*float*/ Binary HYPOT = binary("HYPOT", "hypot", VectorSupport.VECTOR_OP_HYPOT, VO_ONLYFP);