covnerted from sqrt to nrooting
Gitea Actions For Fabelous-Math / Explore-Gitea-Actions (push) Has been cancelled Details

This commit is contained in:
Falko Victor Habel 2025-03-14 14:08:10 +01:00
parent d008db30ba
commit 2bcb4f3d3d
7 changed files with 105 additions and 31 deletions

View File

@ -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))

View File

@ -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,

View File

@ -0,0 +1,37 @@
#include <Python.h>
#include "rooting.hpp"
#include <stdexcept>
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);
}

View File

@ -0,0 +1,58 @@
#include "rooting.hpp"
#include <cmath>
#include <stdexcept>
#include <limits>
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<double>::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;
}

View File

@ -1,21 +0,0 @@
#include "sqrt.hpp"
#include <cmath>
#include <stdexcept>
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<double>(number);
}
long long x = number;
double y = static_cast<double>((x + 1) / 2);
while (y < x) {
x = static_cast<long long>(y);
y = (static_cast<double>(x) + static_cast<double>(number) / static_cast<double>(x)) / 2;
}
return y;
}

View File

@ -0,0 +1,5 @@
#pragma once
namespace rooting {
double nth_root(long double number, double n);
}

View File

@ -1,5 +0,0 @@
#pragma once
namespace fabelous_sqrt {
double sqrt(long long number);
}