diff --git a/example.py b/example.py index 32dbf17..3d51763 100644 --- a/example.py +++ b/example.py @@ -1,5 +1,5 @@ -from fabelous_math import is_even, is_odd, fabelous_sqrt +from fabelous_math import is_even, is_odd, rooting -print(fabelous_sqrt(50000000000000)) +print(rooting(0.5)) print(is_even(5)) print(is_odd(19)) diff --git a/setup.py b/setup.py index 6f6d988..3661352 100644 --- a/setup.py +++ b/setup.py @@ -23,10 +23,10 @@ simple_functions_module = Extension( sqrt_module = Extension( - 'fabelous_math.sqrt', + 'fabelous_math.rooting', sources=[ - 'src/fabelous_math/cpp/functions/sqrt.cpp', - 'src/fabelous_math/cpp/functions/bindings/sqrt_bindings.cpp' + 'src/fabelous_math/cpp/functions/rooting.cpp', + 'src/fabelous_math/cpp/functions/bindings/rooting_bindings.cpp' ], include_dirs=['src/fabelous_math/include'], extra_compile_args=extra_compile_args, diff --git a/src/fabelous_math/cpp/functions/bindings/rooting_bindings.cpp b/src/fabelous_math/cpp/functions/bindings/rooting_bindings.cpp new file mode 100644 index 0000000..5f6c1b8 --- /dev/null +++ b/src/fabelous_math/cpp/functions/bindings/rooting_bindings.cpp @@ -0,0 +1,37 @@ +#include +#include "rooting.hpp" +#include + +static PyObject* rooting_wrapper(PyObject* self, PyObject* args) { + double number; // Changed to double to accept floating-point numbers + double n = 2.0; // Default value for the second argument + + if (!PyArg_ParseTuple(args, "d|d", &number, &n)) { // First arg required, second optional + return NULL; + } + + try { + double result = rooting::nth_root(number, n); // Pass number directly as double + return PyFloat_FromDouble(result); + } catch (const std::invalid_argument& e) { + PyErr_SetString(PyExc_ValueError, e.what()); + return NULL; + } +} + +static PyMethodDef NthRootMethods[] = { + {"rooting", rooting_wrapper, METH_VARARGS, "Compute the nth root of a number"}, + {NULL, NULL, 0, NULL} +}; + +static struct PyModuleDef sqrt_module = { + PyModuleDef_HEAD_INIT, + "fabelous_math.rooting", + "Module for computing the nth root of a number", + -1, + NthRootMethods +}; + +PyMODINIT_FUNC PyInit_rooting(void) { + return PyModule_Create(&sqrt_module); +} \ No newline at end of file diff --git a/src/fabelous_math/cpp/functions/rooting.cpp b/src/fabelous_math/cpp/functions/rooting.cpp new file mode 100644 index 0000000..4db587e --- /dev/null +++ b/src/fabelous_math/cpp/functions/rooting.cpp @@ -0,0 +1,58 @@ +#include "rooting.hpp" +#include +#include +#include + +double rooting::nth_root(long double number, double n) { + // Special case handling + if (n <= 0) { + throw std::invalid_argument("The root must be positive and non-zero"); + } + + if (number < 0 && std::fmod(n, 2.0) == 0) { + throw std::invalid_argument("Cannot compute even root of a negative number"); + } + + if (number == 0) { + return 0.0; + } + + if (number == 1 || n == 1.0) { + return number; + } + + // Handle negative numbers for odd roots + bool negative = number < 0; + double abs_number = negative ? -number : number; + + // Use logarithm method for initial guess + double log_result = std::log(abs_number) / n; + double x = std::exp(log_result); + + // Constants + const double epsilon = 1e-15; + const int max_iterations = 100; + + // Newton-Raphson method + for (int i = 0; i < max_iterations; i++) { + double x_prev = x; + + // Calculate new approximation, handling potential overflow + double x_pow = std::pow(x, n - 1); + + // Prevent division by zero + if (x_pow < std::numeric_limits::min()) { + break; + } + + x = ((n - 1) * x + abs_number / x_pow) / n; + + // Check for convergence using relative error + if (std::fabs(x - x_prev) <= epsilon * std::fabs(x)) { + break; + } + } + + // Return correct sign for odd roots of negative numbers + return negative ? -x : x; +} \ No newline at end of file diff --git a/src/fabelous_math/cpp/functions/sqrt.cpp b/src/fabelous_math/cpp/functions/sqrt.cpp deleted file mode 100644 index d0d4899..0000000 --- a/src/fabelous_math/cpp/functions/sqrt.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "sqrt.hpp" -#include -#include - -double fabelous_sqrt::sqrt(long long number) { - if (number < 0) { - throw std::invalid_argument("Cannot compute square root of a negative number"); - } - // Special case for 0 and 1 - if (number == 0 || number == 1) { - return static_cast(number); - } - - long long x = number; - double y = static_cast((x + 1) / 2); - while (y < x) { - x = static_cast(y); - y = (static_cast(x) + static_cast(number) / static_cast(x)) / 2; - } - return y; -} \ No newline at end of file diff --git a/src/fabelous_math/include/rooting.hpp b/src/fabelous_math/include/rooting.hpp new file mode 100644 index 0000000..f62d9dc --- /dev/null +++ b/src/fabelous_math/include/rooting.hpp @@ -0,0 +1,5 @@ +#pragma once + +namespace rooting { + double nth_root(long double number, double n); +} \ No newline at end of file diff --git a/src/fabelous_math/include/sqrt.hpp b/src/fabelous_math/include/sqrt.hpp deleted file mode 100644 index bdd2588..0000000 --- a/src/fabelous_math/include/sqrt.hpp +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -namespace fabelous_sqrt { - double sqrt(long long number); -} \ No newline at end of file