// Copyright (C) 2026 Kiyotsugu Arai
// SPDX-License-Identifier: LGPL-3.0-or-later

// FloatOps.hpp
// Three-argument operations for arbitrary-precision floating-point numbers
// (equivalent to GMP mpf_add/sub/mul/div).
// Reuses the result buffer to avoid object-construction overhead.

#ifndef SANGI_FLOAT_OPS_HPP
#define SANGI_FLOAT_OPS_HPP

#include <math/core/mp/Float.hpp>

namespace sangi {

    /**
     * @brief Three-argument operation utilities for arbitrary-precision floating-point numbers.
     *
     * Provides an API equivalent to GMP/MPFR's mpfr_add(r, a, b, rnd).
     * By reusing the result buffer, this avoids the Float construction,
     * normalization, and move overhead associated with value-returning operators such as operator+/-.
     *
     * result may be the same object as lhs or rhs (aliasing-safe).
     */
    class SANGI_API FloatOps {
    public:
        // Three-argument add/sub/mul/div: reuses the result buffer.
        static void add(const Float& lhs, const Float& rhs, Float& result);
        static void sub(const Float& lhs, const Float& rhs, Float& result);
        static void mul(const Float& lhs, const Float& rhs, Float& result);
        static void sqr(const Float& x, Float& result);
        static void div(const Float& lhs, const Float& rhs, Float& result);

        // Three-argument transcendental functions: precision is determined by
        // result.requestedBits(), and the result is written back to result's
        // buffer via move-assign.
        // (For fair comparison against MPFR's preallocated mpfr_t in benchmark harnesses.)
        // Internally these are thin wrappers around the corresponding
        // sangi::xxx(const Float&, int), but they eliminate the cost of
        // reconstructing a Float on every benchmark iteration.
        static void sqrt(const Float& x, Float& result);
        static void cbrt(const Float& x, Float& result);
        static void exp(const Float& x, Float& result);
        static void log(const Float& x, Float& result);
        static void sin(const Float& x, Float& result);
        static void cos(const Float& x, Float& result);
        static void tan(const Float& x, Float& result);
        static void atan(const Float& x, Float& result);
        static void sinh(const Float& x, Float& result);
        static void cosh(const Float& x, Float& result);
        static void tanh(const Float& x, Float& result);
    };

} // namespace sangi

#endif // SANGI_FLOAT_OPS_HPP
