1c120edc7SMichael Jones //===-- Common header for PolyEval implementations --------------*- C++ -*-===// 2c120edc7SMichael Jones // 3c120edc7SMichael Jones // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4c120edc7SMichael Jones // See https://llvm.org/LICENSE.txt for license information. 5c120edc7SMichael Jones // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6c120edc7SMichael Jones // 7c120edc7SMichael Jones //===----------------------------------------------------------------------===// 8c120edc7SMichael Jones 9270547f3SGuillaume Chatelet #ifndef LLVM_LIBC_SRC___SUPPORT_FPUTIL_POLYEVAL_H 10270547f3SGuillaume Chatelet #define LLVM_LIBC_SRC___SUPPORT_FPUTIL_POLYEVAL_H 11c120edc7SMichael Jones 12c5f8a0a1STue Ly #include "multiply_add.h" 13434bf160STue Ly #include "src/__support/CPP/type_traits.h" 1459c809cdSSiva Chandra Reddy #include "src/__support/common.h" 15*5ff3ff33SPetr Hosek #include "src/__support/macros/config.h" 16c120edc7SMichael Jones 17c120edc7SMichael Jones // Evaluate polynomial using Horner's Scheme: 18c120edc7SMichael Jones // With polyeval(x, a_0, a_1, ..., a_n) = a_n * x^n + ... + a_1 * x + a_0, we 19c120edc7SMichael Jones // evaluated it as: a_0 + x * (a_1 + x * ( ... (a_(n-1) + x * a_n) ... ) ) ). 20c5f8a0a1STue Ly // We will use FMA instructions if available. 21c120edc7SMichael Jones // Example: to evaluate x^3 + 2*x^2 + 3*x + 4, call 22c120edc7SMichael Jones // polyeval( x, 4.0, 3.0, 2.0, 1.0 ) 23c120edc7SMichael Jones 24*5ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL { 25c120edc7SMichael Jones namespace fputil { 26c120edc7SMichael Jones 276baee7f2STue Ly template <typename T> 286baee7f2STue Ly LIBC_INLINE cpp::enable_if_t<(sizeof(T) > sizeof(void *)), T> 296baee7f2STue Ly polyeval(const T &, const T &a0) { 306baee7f2STue Ly return a0; 316baee7f2STue Ly } 326baee7f2STue Ly 336baee7f2STue Ly template <typename T> 346baee7f2STue Ly LIBC_INLINE cpp::enable_if_t<(sizeof(T) <= sizeof(void *)), T> polyeval(T, 356baee7f2STue Ly T a0) { 36434bf160STue Ly return a0; 37434bf160STue Ly } 38c120edc7SMichael Jones 39c120edc7SMichael Jones template <typename T, typename... Ts> 406baee7f2STue Ly LIBC_INLINE cpp::enable_if_t<(sizeof(T) > sizeof(void *)), T> 416baee7f2STue Ly polyeval(const T &x, const T &a0, const Ts &...a) { 426baee7f2STue Ly return multiply_add(x, polyeval(x, a...), a0); 436baee7f2STue Ly } 446baee7f2STue Ly 456baee7f2STue Ly template <typename T, typename... Ts> 466baee7f2STue Ly LIBC_INLINE cpp::enable_if_t<(sizeof(T) <= sizeof(void *)), T> 476baee7f2STue Ly polyeval(T x, T a0, Ts... a) { 48c5f8a0a1STue Ly return multiply_add(x, polyeval(x, a...), a0); 49c120edc7SMichael Jones } 50c120edc7SMichael Jones 51c120edc7SMichael Jones } // namespace fputil 52*5ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL 53c120edc7SMichael Jones 54270547f3SGuillaume Chatelet #endif // LLVM_LIBC_SRC___SUPPORT_FPUTIL_POLYEVAL_H 55