Skip to content

Maybe small improvement for accuracy for cos for regular angles #6

@mhvk

Description

@mhvk

@seiko2plus - Came here out of curiosity from numpy/numpy#29699 (comment), to see how things get done. For cos, the following transformation is done before any real calculation:

const V x_abs = And(abs_mask, x);
const V x_sign = AndNot(x_abs, x);
// Transform cosine to sine using identity: cos(x) = sin(x + π/2)
const V half_pi = Set(d, data::kHalfPi<T>);
V x_trans = x_abs;
if constexpr (OP == Operation::kCos) {
x_trans = Add(x_abs, half_pi);
}

This would seem to loose some precision for the common case where angle input will be between -pi and pi, by moving those angles to pi/2 to 3*pi/2. Instead, one can move those angles to near zero and thus get optimal precision near both crossings by using that cos(x) = sin(pi/2 - |x|) , i.e. do something like,

  // Transform cosine to sine using identity cos(x) = sin(π/2 - |x|)
  // where |x| ensures optimal precision near both -pi/2 and pi/2.
  const V half_pi = Set(d, data::kHalfPi<T>);
  V x_trans = x;
  if constexpr (OP == Operation::kCos) {
    x_trans = And(abs_mask, x);
    x_trans = Sub(half_pi, x_trans);
  }
  const V x_abs = And(abs_mask, x_trans);
  const V x_sign = AndNot(x_abs, x_trans);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions