55 lines · c
1//===-- Common header for PolyEval implementations --------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_POLYEVAL_H10#define LLVM_LIBC_SRC___SUPPORT_FPUTIL_POLYEVAL_H11 12#include "multiply_add.h"13#include "src/__support/CPP/type_traits.h"14#include "src/__support/common.h"15#include "src/__support/macros/config.h"16 17// Evaluate polynomial using Horner's Scheme:18// With polyeval(x, a_0, a_1, ..., a_n) = a_n * x^n + ... + a_1 * x + a_0, we19// evaluated it as: a_0 + x * (a_1 + x * ( ... (a_(n-1) + x * a_n) ... ) ) ).20// We will use FMA instructions if available.21// Example: to evaluate x^3 + 2*x^2 + 3*x + 4, call22// polyeval( x, 4.0, 3.0, 2.0, 1.0 )23 24namespace LIBC_NAMESPACE_DECL {25namespace fputil {26 27template <typename T>28LIBC_INLINE cpp::enable_if_t<(sizeof(T) > sizeof(void *)), T>29polyeval(const T &, const T &a0) {30 return a0;31}32 33template <typename T>34LIBC_INLINE cpp::enable_if_t<(sizeof(T) <= sizeof(void *)), T> polyeval(T,35 T a0) {36 return a0;37}38 39template <typename T, typename... Ts>40LIBC_INLINE static constexpr cpp::enable_if_t<(sizeof(T) > sizeof(void *)), T>41polyeval(const T &x, const T &a0, const Ts &...a) {42 return multiply_add(x, polyeval(x, a...), a0);43}44 45template <typename T, typename... Ts>46LIBC_INLINE cpp::enable_if_t<(sizeof(T) <= sizeof(void *)), T>47polyeval(T x, T a0, Ts... a) {48 return multiply_add(x, polyeval(x, a...), a0);49}50 51} // namespace fputil52} // namespace LIBC_NAMESPACE_DECL53 54#endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_POLYEVAL_H55