# MathUtils
mathematical utilities with C++ backend for high-performance numerical computations.
# Create build venv
python -m venv .venv/mathutils_build
source .venv/mathutils_build/bin/activate
pip install build twine
# Clean previous builds
rm -rf dist/ build/ *.egg-info .venv/mathutils_test
# Build source distribution and wheel
python -m build
# Verify files were created
ls -la dist/
# Check package validity
python -m twine check dist/*
# Upload only .tar.gz to avoid platform-specific wheel issues
python -m twine upload dist/*.tar.gz
# test
deactivate
python -m venv .venv/mathutils_test
source .venv/mathutils_test/bin/activate
pip install -r requirements_testing.txt
<!-- # MathUtils
Fast mathematical utilities with optimized C++ backend for high-performance numerical computations.
## Features
- **Fast factorial computations**: Optimized log-factorial with lookup tables
- **Spherical harmonics**: High-performance Ylm calculations
- **C++ backend**: Optimized implementations with Python bindings
- **NumPy integration**: Seamless array operations
- **Vectorized operations**: Process arrays efficiently
## Installation
```bash
pip install mathutils-fast
```
## Quick Start
```python
import mathutils
import numpy as np
# Fast log factorial
result = mathutils.log_factorial(100)
print(f"log(100!) = {result}")
# Vectorized spherical harmonics
theta = np.linspace(0, np.pi, 100)
phi = np.linspace(0, 2*np.pi, 100)
ylm = mathutils.Ylm_vectorized(2, 1, theta, phi)
print(f"Y_2^1 shape: {ylm.shape}, dtype: {ylm.dtype}")
```
## Spherical Harmonics
The spherical harmonics $Y_{\ell}^m(\theta, \phi)$ are defined as:
$$
Y_{\ell}^m(\theta, \phi) = \sqrt{\frac{2\ell+1}{4\pi} \frac{(\ell-|m|)!}{(\ell+|m|)!}} P_{\ell}^{|m|}(\cos\theta) e^{im\phi}
$$
where:
- $\ell \geq 0$ is the degree (angular momentum quantum number)
- $-\ell \leq m \leq \ell$ is the order (magnetic quantum number)
- $P_{\ell}^{|m|}$ are the associated Legendre polynomials
- $\theta \in [0, \pi]$ is the polar angle
- $\phi \in [0, 2\pi]$ is the azimuthal angle
From the Herglotz generating function, we find
$$
e^{-im\phi}Y_{\ell}^m(\theta, \phi)
=
r_{\ell, m, \theta}
\sum_{k=1}^{k_{max}}
Q_{k}
$$
$$
\log(q_0)
=
(1/2)\log(2\ell+1)
+
(1/2)\log((\ell+|m|)!)
-(1/2)\log((\ell-|m|)!)
-\log(|m|!)
-|m|\log(2)
$$
$$
\log(q_k)
=
(\ell-|m|)\log|\cos\theta|
+
|m|\log|\sin\theta|
$$
where:
- $k_{max} = \lfloor(\ell-|m|)/2\rfloor$
$$
e^{-im\phi}Y_{\ell}^m(\theta, \phi)
=
(-1)^{(m+|m|)/2}
\sqrt{
\frac{
(2\ell+1)(\ell+|m|)!(\ell-|m|)!
}{
4^{|m|+1}
\pi
}
}
\sum_{k=0?}^{\lfloor(\ell-m)/2\rfloor}
\frac{
(-1)^k
\cos[k](\theta)
}
{
4^k
(\ell-|m|-2k)!
(|m|+k)!
k!
}
$$
### Special Properties
- **Orthonormality**: $\int_0^{2\pi} d\phi \int_0^{\pi} \sin\theta \, d\theta \, Y_{\ell}^m(\theta,\phi)^* Y_{\ell'}^{m'}(\theta,\phi) = \delta_{\ell\ell'}\delta_{mm'}$
- **Completeness**: Any function on the sphere can be expanded in spherical harmonics
- **Symmetry**: $Y_{\ell}^{-m}(\theta,\phi) = (-1)^m [Y_{\ell}^m(\theta,\phi)]^*$
## API Reference
### Core Functions
#### `log_factorial(n)`
Compute the natural logarithm of n!
```python
result = mathutils.log_factorial(50) # Uses optimized C++ implementation
```
**Parameters:**
- `n` (int): Non-negative integer
**Returns:**
- `float`: ln(n!)
#### `Ylm_vectorized(l, m, theta, phi)`
Compute spherical harmonics for arrays of angles
```python
theta = np.linspace(0, np.pi, 50)
phi = np.linspace(0, 2*np.pi, 100)
ylm = mathutils.Ylm_vectorized(3, 2, theta, phi)
```
**Parameters:**
- `l` (int): Degree (l ≥ 0)
- `m` (int): Order (-l ≤ m ≤ l)
- `theta` (array_like): Polar angles in radians
- `phi` (array_like): Azimuthal angles in radians
**Returns:**
- `ndarray`: Complex array of Y_l^m values
### Indexing Functions
#### `spherical_harmonic_index_n_LM(l, m)`
Convert (l,m) quantum numbers to linear index
```python
index = mathutils.spherical_harmonic_index_n_LM(2, 1) # Returns 5
```
#### `spherical_harmonic_index_lm_N(n)`
Convert linear index back to (l,m) quantum numbers
```python
l, m = mathutils.spherical_harmonic_index_lm_N(5) # Returns (2, 1)
```
## Performance
MathUtils provides significant speedups over pure Python implementations:
```python
import time
import numpy as np
import mathutils
# Benchmark log_factorial
n = 1000
start = time.time()
for i in range(10000):
result = mathutils.log_factorial(n)
cpp_time = time.time() - start
# Compare with Python
import math
start = time.time()
for i in range(10000):
result = math.lgamma(n + 1)
python_time = time.time() - start
print(f"Speedup: {python_time/cpp_time:.2f}x")
```
## Examples
### Plotting Spherical Harmonics
```python
import numpy as np
import matplotlib.pyplot as plt
import mathutils
# Create sphere coordinates
theta = np.linspace(0, np.pi, 100)
phi = np.linspace(0, 2*np.pi, 200)
theta_grid, phi_grid = np.meshgrid(theta, phi, indexing='ij')
# Compute Y_2^1
l, m = 2, 1
ylm = mathutils.Ylm_vectorized(l, m, theta_grid.flatten(), phi_grid.flatten())
ylm = ylm.reshape(theta_grid.shape)
# Plot real part
fig, ax = plt.subplots(subplot_kw=dict(projection='3d'))
x = np.sin(theta_grid) * np.cos(phi_grid)
y = np.sin(theta_grid) * np.sin(phi_grid)
z = np.cos(theta_grid)
colors = plt.cm.seismic(ylm.real / np.max(np.abs(ylm.real)))
ax.plot_surface(x, y, z, facecolors=colors, alpha=0.8)
ax.set_title(f'$Y_{{{l}}}^{{{m}}}$ (Real Part)')
plt.show()
```
### Spherical Harmonic Analysis
```python
import numpy as np
import mathutils
def analyze_function_on_sphere(func, l_max=10):
"""Decompose a function into spherical harmonic coefficients."""
# Create integration grid
n_theta, n_phi = 2*l_max+1, 4*l_max+1
theta = np.linspace(0, np.pi, n_theta)
phi = np.linspace(0, 2*np.pi, n_phi)
theta_grid, phi_grid = np.meshgrid(theta, phi, indexing='ij')
# Evaluate function on grid
f_values = func(theta_grid, phi_grid)
# Compute coefficients
coefficients = {}
for l in range(l_max + 1):
for m in range(-l, l + 1):
ylm = mathutils.Ylm_vectorized(l, m, theta_grid.flatten(), phi_grid.flatten())
ylm = ylm.reshape(theta_grid.shape)
# Numerical integration
integrand = f_values * np.conj(ylm) * np.sin(theta_grid)
coeff = np.trapz(np.trapz(integrand, phi), theta)
coefficients[(l, m)] = coeff
return coefficients
# Example: analyze a simple function
def my_function(theta, phi):
return np.cos(theta) + np.sin(theta) * np.cos(phi)
coeffs = analyze_function_on_sphere(my_function, l_max=5)
print("Dominant coefficients:")
for (l, m), coeff in sorted(coeffs.items(), key=lambda x: abs(x[1]), reverse=True)[:5]:
print(f"Y_{l}^{m}: {coeff:.6f}")
```
## Requirements
- Python ≥ 3.8
- NumPy ≥ 1.20.0
- C++17 compatible compiler (for building from source)
## Building from Source
```bash
git clone https://github.com/yourusername/mathutils.git
cd mathutils
pip install -e .
```
### Dependencies for Building
- CMake ≥ 3.15
- Eigen3 library
- pybind11
## Testing
```bash
# Install test dependencies
pip install pytest numpy
# Run tests
pytest tests/
```
## Contributing
1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## Citation
If you use MathUtils in your research, please cite:
```bibtex
@software{mathutils2024,
title={MathUtils: Fast Mathematical Utilities with C++ Backend},
author={Your Name},
year={2024},
url={https://github.com/yourusername/mathutils}
}
```
## Acknowledgments
- Built with [pybind11](https://github.com/pybind/pybind11)
- Uses [Eigen](https://eigen.tuxfamily.org/) for linear algebra
- Inspired by [SciPy](https://scipy.org/) special functions
# Step-by-Step Guide: Publishing Python Package with C++ Extensions to PyPI
## Prerequisites
- Python package with C++ extensions (using pybind11)
- GitHub repository
- C++ code compiles successfully locally
## Step 1: Package Configuration
### 1.1 Create/Update `pyproject.toml`
```toml
[build-system]
requires = ["setuptools>=61.0", "pybind11", "numpy"]
build-backend = "setuptools.build_meta"
[project]
name = "your-unique-package-name" # Check if name is available on PyPI
version = "0.1.0"
description = "Your package description"
authors = [{ name = "Your Name", email = "your.email@example.com" }]
license = {text = "MIT"}
readme = "README.md"
requires-python = ">=3.7"
dependencies = ["numpy", "scipy"] # Add your dependencies
keywords = ["mathematics", "scientific-computing"]
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Science/Research",
"Programming Language :: Python :: 3",
"Topic :: Scientific/Engineering :: Mathematics",
]
[project.urls]
Homepage = "https://github.com/yourusername/yourrepo"
Repository = "https://github.com/yourusername/yourrepo"
Issues = "https://github.com/yourusername/yourrepo/issues"
[project.optional-dependencies]
dev = ["pytest", "build", "twine"]
[tool.setuptools]
packages = ["your_module_name"]
[tool.setuptools.package-dir]
your_module_name = "your_module_name"
```
### 1.2 Create `MANIFEST.in`
```plaintext
include README.md
include pyproject.toml
recursive-include include *.hpp
recursive-include src *.cpp
```
### 1.3 Fix `__init__.py` imports
```python
"""Your Package - Description."""
try:
from .your_backend import *
except ImportError as e:
raise ImportError(f"Failed to import C++ backend: {e}")
__version__ = "0.1.0"
```
### 1.4 Ensure `setup.py` has correct paths
```python
from setuptools import setup, Extension
from pybind11.setup_helpers import Pybind11Extension, build_ext
import pybind11
ext_modules = [
Pybind11Extension(
"your_module.your_backend",
["src/cpp/bindings.cpp"],
include_dirs=[
"include",
"/usr/include/eigen3", # If using Eigen
],
cxx_std=17,
define_macros=[("VERSION_INFO", '"dev"')],
),
]
setup(
ext_modules=ext_modules,
cmdclass={"build_ext": build_ext},
zip_safe=False,
)
```
## Step 2: Build Setup
### 2.1 Install build tools
```bash
pip install build twine
```
### 2.2 Clean and build package
```bash
# Clean previous builds
rm -rf dist/ build/ *.egg-info
# Build source distribution and wheel
python -m build
```
### 2.3 Check build results
```bash
# Verify files were created
ls -la dist/
# Check package validity
python -m twine check dist/*
```
## Step 3: PyPI Account Setup
### 3.1 Create PyPI account
- Go to https://pypi.org/account/register/
- Create account and verify email
### 3.2 Create API token
- Go to https://pypi.org/manage/account/token/
- Create new token with scope "Entire account"
- Copy the token (starts with `pypi-`)
## Step 4: Upload to PyPI
### 4.1 Upload source distribution only
```bash
# Upload only .tar.gz to avoid platform-specific wheel issues
python -m twine upload dist/*.tar.gz
```
### 4.2 Enter credentials when prompted
- Username: `__token__`
- Password: Your API token
## Step 5: Test Installation
### 5.1 Test install
```bash
pip install your-package-name
```
### 5.2 Test import
```python
import your_module
print("Success!")
```
## Step 6: (Optional) GitHub Actions for Automated Publishing
### 6.1 Create `.github/workflows/publish.yml`
```yaml
name: Publish to PyPI
on:
release:
types: [published]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y libeigen3-dev # If using Eigen
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build twine
- name: Build package
run: python -m build
- name: Publish to PyPI
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
run: twine upload dist/*.tar.gz
```
### 6.2 Add PyPI token to GitHub secrets
- Go to GitHub repo → Settings → Secrets and variables → Actions
- Add secret: `PYPI_API_TOKEN` = your PyPI token
## Step 7: Future Releases
### 7.1 For new versions
```bash
# 1. Update version in pyproject.toml
# 2. Clean and rebuild
rm -rf dist/ build/ *.egg-info
python -m build
# 3. Upload
python -m twine upload dist/*.tar.gz
```
### 7.2 Or use GitHub releases (if using Actions)
- Create new GitHub release with tag like `v0.2.0`
- GitHub Actions will automatically publish to PyPI
## Common Issues and Solutions
### Issue: "Binary wheel has unsupported platform tag"
**Solution**: Upload only source distribution (`*.tar.gz`)
### Issue: "Invalid authentication"
**Solutions**:
- Verify email on PyPI
- Create fresh API token
- Use `__token__` as username
### Issue: "Package name already exists"
**Solution**: Choose unique name like `yourpackage-username`
### Issue: C++ compilation fails
**Solutions**:
- Check `include_dirs` in `setup.py`
- Ensure `MANIFEST.in` includes all necessary files
- Install system dependencies (like Eigen)
## Verification Checklist
- [ ] Package builds successfully (`python -m build`)
- [ ] Package checks pass (`python -m twine check dist/*`)
- [ ] PyPI account created and email verified
- [ ] API token created and saved
- [ ] Package name is unique
- [ ] Upload successful
- [ ] Package installs via pip
- [ ] Package imports correctly
## Result
Your package will be available at:
`https://pypi.org/project/your-package-name/`
Users can install with:
```bash
pip install your-package-name
``` -->
Raw data
{
"_id": null,
"home_page": null,
"name": "pymathutils",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": null,
"keywords": "mathematics, scientific-computing, numerical-methods",
"author": null,
"author_email": "wlough <wilson.lough@colorado.edu>",
"download_url": "https://files.pythonhosted.org/packages/12/99/75bbabb1f0875e0013fb4e4789ef5d09b5720ba3900fb5afa3bac34a2b02/pymathutils-0.1.3.tar.gz",
"platform": null,
"description": "# MathUtils\n\nmathematical utilities with C++ backend for high-performance numerical computations.\n\n\n\n# Create build venv\npython -m venv .venv/mathutils_build\nsource .venv/mathutils_build/bin/activate\npip install build twine\n# Clean previous builds\nrm -rf dist/ build/ *.egg-info .venv/mathutils_test\n# Build source distribution and wheel\npython -m build\n# Verify files were created\nls -la dist/\n# Check package validity\npython -m twine check dist/*\n# Upload only .tar.gz to avoid platform-specific wheel issues\npython -m twine upload dist/*.tar.gz\n# test\ndeactivate\npython -m venv .venv/mathutils_test\nsource .venv/mathutils_test/bin/activate\npip install -r requirements_testing.txt\n\n\n\n\n<!-- # MathUtils\n\nFast mathematical utilities with optimized C++ backend for high-performance numerical computations.\n\n## Features\n\n- **Fast factorial computations**: Optimized log-factorial with lookup tables\n- **Spherical harmonics**: High-performance Ylm calculations \n- **C++ backend**: Optimized implementations with Python bindings\n- **NumPy integration**: Seamless array operations\n- **Vectorized operations**: Process arrays efficiently\n\n## Installation\n\n```bash\npip install mathutils-fast\n```\n\n## Quick Start\n\n```python\nimport mathutils\nimport numpy as np\n\n# Fast log factorial\nresult = mathutils.log_factorial(100)\nprint(f\"log(100!) = {result}\")\n\n# Vectorized spherical harmonics\ntheta = np.linspace(0, np.pi, 100)\nphi = np.linspace(0, 2*np.pi, 100)\nylm = mathutils.Ylm_vectorized(2, 1, theta, phi)\nprint(f\"Y_2^1 shape: {ylm.shape}, dtype: {ylm.dtype}\")\n```\n\n## Spherical Harmonics\n\nThe spherical harmonics $Y_{\\ell}^m(\\theta, \\phi)$ are defined as:\n\n$$\nY_{\\ell}^m(\\theta, \\phi) = \\sqrt{\\frac{2\\ell+1}{4\\pi} \\frac{(\\ell-|m|)!}{(\\ell+|m|)!}} P_{\\ell}^{|m|}(\\cos\\theta) e^{im\\phi}\n$$\n\nwhere:\n- $\\ell \\geq 0$ is the degree (angular momentum quantum number)\n- $-\\ell \\leq m \\leq \\ell$ is the order (magnetic quantum number) \n- $P_{\\ell}^{|m|}$ are the associated Legendre polynomials\n- $\\theta \\in [0, \\pi]$ is the polar angle\n- $\\phi \\in [0, 2\\pi]$ is the azimuthal angle\n\nFrom the Herglotz generating function, we find\n$$\ne^{-im\\phi}Y_{\\ell}^m(\\theta, \\phi)\n= \nr_{\\ell, m, \\theta}\n\\sum_{k=1}^{k_{max}}\nQ_{k}\n$$\n\n$$\n\\log(q_0)\n=\n(1/2)\\log(2\\ell+1)\n+\n(1/2)\\log((\\ell+|m|)!)\n-(1/2)\\log((\\ell-|m|)!)\n-\\log(|m|!)\n-|m|\\log(2)\n$$\n\n$$\n\\log(q_k)\n=\n(\\ell-|m|)\\log|\\cos\\theta|\n+\n|m|\\log|\\sin\\theta|\n$$\n\nwhere:\n- $k_{max} = \\lfloor(\\ell-|m|)/2\\rfloor$ \n\n$$\ne^{-im\\phi}Y_{\\ell}^m(\\theta, \\phi)\n= \n(-1)^{(m+|m|)/2}\n\\sqrt{\n\\frac{\n(2\\ell+1)(\\ell+|m|)!(\\ell-|m|)!\n}{\n4^{|m|+1}\n\\pi\n}\n}\n\\sum_{k=0?}^{\\lfloor(\\ell-m)/2\\rfloor}\n\\frac{\n(-1)^k\n\\cos[k](\\theta)\n}\n{\n4^k\n(\\ell-|m|-2k)!\n(|m|+k)!\nk!\n}\n$$\n\n\n\n\n### Special Properties\n\n- **Orthonormality**: $\\int_0^{2\\pi} d\\phi \\int_0^{\\pi} \\sin\\theta \\, d\\theta \\, Y_{\\ell}^m(\\theta,\\phi)^* Y_{\\ell'}^{m'}(\\theta,\\phi) = \\delta_{\\ell\\ell'}\\delta_{mm'}$\n- **Completeness**: Any function on the sphere can be expanded in spherical harmonics\n- **Symmetry**: $Y_{\\ell}^{-m}(\\theta,\\phi) = (-1)^m [Y_{\\ell}^m(\\theta,\\phi)]^*$\n\n## API Reference\n\n### Core Functions\n\n#### `log_factorial(n)`\nCompute the natural logarithm of n!\n\n```python\nresult = mathutils.log_factorial(50) # Uses optimized C++ implementation\n```\n\n**Parameters:**\n- `n` (int): Non-negative integer\n\n**Returns:**\n- `float`: ln(n!)\n\n#### `Ylm_vectorized(l, m, theta, phi)`\nCompute spherical harmonics for arrays of angles\n\n```python\ntheta = np.linspace(0, np.pi, 50)\nphi = np.linspace(0, 2*np.pi, 100)\nylm = mathutils.Ylm_vectorized(3, 2, theta, phi)\n```\n\n**Parameters:**\n- `l` (int): Degree (l \u2265 0)\n- `m` (int): Order (-l \u2264 m \u2264 l)\n- `theta` (array_like): Polar angles in radians\n- `phi` (array_like): Azimuthal angles in radians\n\n**Returns:**\n- `ndarray`: Complex array of Y_l^m values\n\n### Indexing Functions\n\n#### `spherical_harmonic_index_n_LM(l, m)`\nConvert (l,m) quantum numbers to linear index\n\n```python\nindex = mathutils.spherical_harmonic_index_n_LM(2, 1) # Returns 5\n```\n\n#### `spherical_harmonic_index_lm_N(n)`\nConvert linear index back to (l,m) quantum numbers\n\n```python\nl, m = mathutils.spherical_harmonic_index_lm_N(5) # Returns (2, 1)\n```\n\n## Performance\n\nMathUtils provides significant speedups over pure Python implementations:\n\n```python\nimport time\nimport numpy as np\nimport mathutils\n\n# Benchmark log_factorial\nn = 1000\nstart = time.time()\nfor i in range(10000):\n result = mathutils.log_factorial(n)\ncpp_time = time.time() - start\n\n# Compare with Python\nimport math\nstart = time.time()\nfor i in range(10000):\n result = math.lgamma(n + 1)\npython_time = time.time() - start\n\nprint(f\"Speedup: {python_time/cpp_time:.2f}x\")\n```\n\n## Examples\n\n### Plotting Spherical Harmonics\n\n```python\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport mathutils\n\n# Create sphere coordinates\ntheta = np.linspace(0, np.pi, 100)\nphi = np.linspace(0, 2*np.pi, 200)\ntheta_grid, phi_grid = np.meshgrid(theta, phi, indexing='ij')\n\n# Compute Y_2^1\nl, m = 2, 1\nylm = mathutils.Ylm_vectorized(l, m, theta_grid.flatten(), phi_grid.flatten())\nylm = ylm.reshape(theta_grid.shape)\n\n# Plot real part\nfig, ax = plt.subplots(subplot_kw=dict(projection='3d'))\nx = np.sin(theta_grid) * np.cos(phi_grid)\ny = np.sin(theta_grid) * np.sin(phi_grid) \nz = np.cos(theta_grid)\n\ncolors = plt.cm.seismic(ylm.real / np.max(np.abs(ylm.real)))\nax.plot_surface(x, y, z, facecolors=colors, alpha=0.8)\nax.set_title(f'$Y_{{{l}}}^{{{m}}}$ (Real Part)')\nplt.show()\n```\n\n### Spherical Harmonic Analysis\n\n```python\nimport numpy as np\nimport mathutils\n\ndef analyze_function_on_sphere(func, l_max=10):\n \"\"\"Decompose a function into spherical harmonic coefficients.\"\"\"\n \n # Create integration grid\n n_theta, n_phi = 2*l_max+1, 4*l_max+1\n theta = np.linspace(0, np.pi, n_theta)\n phi = np.linspace(0, 2*np.pi, n_phi)\n theta_grid, phi_grid = np.meshgrid(theta, phi, indexing='ij')\n \n # Evaluate function on grid\n f_values = func(theta_grid, phi_grid)\n \n # Compute coefficients\n coefficients = {}\n for l in range(l_max + 1):\n for m in range(-l, l + 1):\n ylm = mathutils.Ylm_vectorized(l, m, theta_grid.flatten(), phi_grid.flatten())\n ylm = ylm.reshape(theta_grid.shape)\n \n # Numerical integration\n integrand = f_values * np.conj(ylm) * np.sin(theta_grid)\n coeff = np.trapz(np.trapz(integrand, phi), theta)\n coefficients[(l, m)] = coeff\n \n return coefficients\n\n# Example: analyze a simple function\ndef my_function(theta, phi):\n return np.cos(theta) + np.sin(theta) * np.cos(phi)\n\ncoeffs = analyze_function_on_sphere(my_function, l_max=5)\nprint(\"Dominant coefficients:\")\nfor (l, m), coeff in sorted(coeffs.items(), key=lambda x: abs(x[1]), reverse=True)[:5]:\n print(f\"Y_{l}^{m}: {coeff:.6f}\")\n```\n\n## Requirements\n\n- Python \u2265 3.8\n- NumPy \u2265 1.20.0\n- C++17 compatible compiler (for building from source)\n\n## Building from Source\n\n```bash\ngit clone https://github.com/yourusername/mathutils.git\ncd mathutils\npip install -e .\n```\n\n### Dependencies for Building\n- CMake \u2265 3.15\n- Eigen3 library\n- pybind11\n\n## Testing\n\n```bash\n# Install test dependencies\npip install pytest numpy\n\n# Run tests\npytest tests/\n```\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feature/amazing-feature`)\n3. Commit your changes (`git commit -m 'Add amazing feature'`)\n4. Push to the branch (`git push origin feature/amazing-feature`)\n5. Open a Pull Request\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## Citation\n\nIf you use MathUtils in your research, please cite:\n\n```bibtex\n@software{mathutils2024,\n title={MathUtils: Fast Mathematical Utilities with C++ Backend},\n author={Your Name},\n year={2024},\n url={https://github.com/yourusername/mathutils}\n}\n```\n\n## Acknowledgments\n\n- Built with [pybind11](https://github.com/pybind/pybind11)\n- Uses [Eigen](https://eigen.tuxfamily.org/) for linear algebra\n- Inspired by [SciPy](https://scipy.org/) special functions\n\n\n# Step-by-Step Guide: Publishing Python Package with C++ Extensions to PyPI\n\n## Prerequisites\n- Python package with C++ extensions (using pybind11)\n- GitHub repository\n- C++ code compiles successfully locally\n\n## Step 1: Package Configuration\n\n### 1.1 Create/Update `pyproject.toml`\n```toml\n[build-system]\nrequires = [\"setuptools>=61.0\", \"pybind11\", \"numpy\"]\nbuild-backend = \"setuptools.build_meta\"\n\n[project]\nname = \"your-unique-package-name\" # Check if name is available on PyPI\nversion = \"0.1.0\"\ndescription = \"Your package description\"\nauthors = [{ name = \"Your Name\", email = \"your.email@example.com\" }]\nlicense = {text = \"MIT\"}\nreadme = \"README.md\"\nrequires-python = \">=3.7\"\ndependencies = [\"numpy\", \"scipy\"] # Add your dependencies\nkeywords = [\"mathematics\", \"scientific-computing\"]\nclassifiers = [\n \"Development Status :: 3 - Alpha\",\n \"Intended Audience :: Science/Research\",\n \"Programming Language :: Python :: 3\",\n \"Topic :: Scientific/Engineering :: Mathematics\",\n]\n\n[project.urls]\nHomepage = \"https://github.com/yourusername/yourrepo\"\nRepository = \"https://github.com/yourusername/yourrepo\"\nIssues = \"https://github.com/yourusername/yourrepo/issues\"\n\n[project.optional-dependencies]\ndev = [\"pytest\", \"build\", \"twine\"]\n\n[tool.setuptools]\npackages = [\"your_module_name\"]\n\n[tool.setuptools.package-dir]\nyour_module_name = \"your_module_name\"\n```\n\n### 1.2 Create `MANIFEST.in`\n```plaintext\ninclude README.md\ninclude pyproject.toml\nrecursive-include include *.hpp\nrecursive-include src *.cpp\n```\n\n### 1.3 Fix `__init__.py` imports\n```python\n\"\"\"Your Package - Description.\"\"\"\n\ntry:\n from .your_backend import *\nexcept ImportError as e:\n raise ImportError(f\"Failed to import C++ backend: {e}\")\n\n__version__ = \"0.1.0\"\n```\n\n### 1.4 Ensure `setup.py` has correct paths\n```python\nfrom setuptools import setup, Extension\nfrom pybind11.setup_helpers import Pybind11Extension, build_ext\nimport pybind11\n\next_modules = [\n Pybind11Extension(\n \"your_module.your_backend\",\n [\"src/cpp/bindings.cpp\"],\n include_dirs=[\n \"include\",\n \"/usr/include/eigen3\", # If using Eigen\n ],\n cxx_std=17,\n define_macros=[(\"VERSION_INFO\", '\"dev\"')],\n ),\n]\n\nsetup(\n ext_modules=ext_modules,\n cmdclass={\"build_ext\": build_ext},\n zip_safe=False,\n)\n```\n\n## Step 2: Build Setup\n\n### 2.1 Install build tools\n```bash\npip install build twine\n```\n\n### 2.2 Clean and build package\n```bash\n# Clean previous builds\nrm -rf dist/ build/ *.egg-info\n\n# Build source distribution and wheel\npython -m build\n```\n\n### 2.3 Check build results\n```bash\n# Verify files were created\nls -la dist/\n\n# Check package validity\npython -m twine check dist/*\n```\n\n## Step 3: PyPI Account Setup\n\n### 3.1 Create PyPI account\n- Go to https://pypi.org/account/register/\n- Create account and verify email\n\n### 3.2 Create API token\n- Go to https://pypi.org/manage/account/token/\n- Create new token with scope \"Entire account\"\n- Copy the token (starts with `pypi-`)\n\n## Step 4: Upload to PyPI\n\n### 4.1 Upload source distribution only\n```bash\n# Upload only .tar.gz to avoid platform-specific wheel issues\npython -m twine upload dist/*.tar.gz\n```\n\n### 4.2 Enter credentials when prompted\n- Username: `__token__`\n- Password: Your API token\n\n## Step 5: Test Installation\n\n### 5.1 Test install\n```bash\npip install your-package-name\n```\n\n### 5.2 Test import\n```python\nimport your_module\nprint(\"Success!\")\n```\n\n## Step 6: (Optional) GitHub Actions for Automated Publishing\n\n### 6.1 Create `.github/workflows/publish.yml`\n```yaml\nname: Publish to PyPI\n\non:\n release:\n types: [published]\n\njobs:\n publish:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n \n - name: Set up Python\n uses: actions/setup-python@v4\n with:\n python-version: '3.11'\n \n - name: Install system dependencies\n run: |\n sudo apt-get update\n sudo apt-get install -y libeigen3-dev # If using Eigen\n \n - name: Install dependencies\n run: |\n python -m pip install --upgrade pip\n pip install build twine\n \n - name: Build package\n run: python -m build\n \n - name: Publish to PyPI\n env:\n TWINE_USERNAME: __token__\n TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}\n run: twine upload dist/*.tar.gz\n```\n\n### 6.2 Add PyPI token to GitHub secrets\n- Go to GitHub repo \u2192 Settings \u2192 Secrets and variables \u2192 Actions\n- Add secret: `PYPI_API_TOKEN` = your PyPI token\n\n## Step 7: Future Releases\n\n### 7.1 For new versions\n```bash\n# 1. Update version in pyproject.toml\n# 2. Clean and rebuild\nrm -rf dist/ build/ *.egg-info\npython -m build\n\n# 3. Upload\npython -m twine upload dist/*.tar.gz\n```\n\n### 7.2 Or use GitHub releases (if using Actions)\n- Create new GitHub release with tag like `v0.2.0`\n- GitHub Actions will automatically publish to PyPI\n\n## Common Issues and Solutions\n\n### Issue: \"Binary wheel has unsupported platform tag\"\n**Solution**: Upload only source distribution (`*.tar.gz`)\n\n### Issue: \"Invalid authentication\"\n**Solutions**:\n- Verify email on PyPI\n- Create fresh API token\n- Use `__token__` as username\n\n### Issue: \"Package name already exists\"\n**Solution**: Choose unique name like `yourpackage-username`\n\n### Issue: C++ compilation fails\n**Solutions**:\n- Check `include_dirs` in `setup.py`\n- Ensure `MANIFEST.in` includes all necessary files\n- Install system dependencies (like Eigen)\n\n## Verification Checklist\n\n- [ ] Package builds successfully (`python -m build`)\n- [ ] Package checks pass (`python -m twine check dist/*`)\n- [ ] PyPI account created and email verified\n- [ ] API token created and saved\n- [ ] Package name is unique\n- [ ] Upload successful\n- [ ] Package installs via pip\n- [ ] Package imports correctly\n\n## Result\n\nYour package will be available at:\n`https://pypi.org/project/your-package-name/`\n\nUsers can install with:\n```bash\npip install your-package-name\n``` -->\n\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Fast mathematical utilities",
"version": "0.1.3",
"project_urls": {
"Homepage": "https://github.com/wlough/MathUtils",
"Issues": "https://github.com/wlough/MathUtils/issues",
"Repository": "https://github.com/wlough/MathUtils"
},
"split_keywords": [
"mathematics",
" scientific-computing",
" numerical-methods"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "129975bbabb1f0875e0013fb4e4789ef5d09b5720ba3900fb5afa3bac34a2b02",
"md5": "139a2e3121422f4decb5048fff9d09ac",
"sha256": "cbd598d12d56077419e57107cb6297470d94c337e9eb78c41454c3cd8552fac0"
},
"downloads": -1,
"filename": "pymathutils-0.1.3.tar.gz",
"has_sig": false,
"md5_digest": "139a2e3121422f4decb5048fff9d09ac",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 22523,
"upload_time": "2025-07-29T22:24:26",
"upload_time_iso_8601": "2025-07-29T22:24:26.939047Z",
"url": "https://files.pythonhosted.org/packages/12/99/75bbabb1f0875e0013fb4e4789ef5d09b5720ba3900fb5afa3bac34a2b02/pymathutils-0.1.3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-29 22:24:26",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "wlough",
"github_project": "MathUtils",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "pymathutils"
}