  
A single-header C library implementing arbitrary precision complex numbers with reference counting. Supports three distinct complex number types: integer (Gaussian), rational, and floating-point complexes.
Features
- Three Complex Types: Gaussian integers, rational complex, and floating-point complex
- Single Header: Easy integration - just include
dynamic_complex.h
- Arbitrary Precision: Built on dynamic_int.h and dynamic_fraction.h for exact arithmetic
- Reference Counting: Atomic memory management with configurable thread safety
- Separate APIs: Distinct function sets for each type (
dc_int_*, dc_frac_*, dc_double_*)
- Type Conversions: Lossless upward conversions, rounding downward conversions
- C99 Complex Integration: Full transcendental function support for floating-point complex
- Mathematical String Format: Clean output like "3+4i", "2-3i", "i", "-i"
- Fail-Fast Error Handling: Assertions on invalid inputs for immediate bug detection
- Comprehensive Testing: 25 test cases with 100% function coverage
Quick Start
First, ensure you have the required dependencies available in your include path:
dynamic_int.h
dynamic_fraction.h
Then include and use the library:
#define DI_IMPLEMENTATION
#include "dynamic_int.h"
#define DF_IMPLEMENTATION
#include "dynamic_fraction.h"
#define DC_IMPLEMENTATION
int main() {
printf("Sum: %s\n", str);
free(str);
return 0;
}
Reference-counted arbitrary precision complex number library.
dc_complex_double dc_frac_to_double(dc_complex_frac c)
Convert rational complex to floating-point complex.
dc_complex_frac dc_int_to_frac(dc_complex_int c)
Convert Gaussian integer to rational complex (lossless)
dc_complex_double dc_double_exp(dc_complex_double c)
Complex exponential function.
dc_complex_double dc_double_from_doubles(double real, double imag)
Create a floating-point complex number from real and imaginary parts.
void dc_double_release(dc_complex_double *c)
Decrement reference count and possibly free memory.
dc_complex_frac dc_frac_add(dc_complex_frac a, dc_complex_frac b)
Add two rational complex numbers.
void dc_frac_release(dc_complex_frac *c)
Decrement reference count and possibly free memory.
dc_complex_frac dc_frac_from_ints(int64_t real_num, int64_t real_den, int64_t imag_num, int64_t imag_den)
Create a rational complex number from integer components.
dc_complex_int dc_int_from_ints(int64_t real, int64_t imag)
Create a Gaussian integer from int64_t real and imaginary parts.
dc_complex_int dc_int_add(dc_complex_int a, dc_complex_int b)
Add two Gaussian integers.
dc_complex_frac dc_int_div(dc_complex_int a, dc_complex_int b)
Divide two Gaussian integers (returns exact rational result)
void dc_int_release(dc_complex_int *c)
Decrement reference count and possibly free memory.
char * dc_int_to_string(dc_complex_int c)
Convert Gaussian integer to mathematical string representation.
Internal structure for a floating-point complex number.
Internal structure for a rational complex number.
Internal structure for a Gaussian integer.
Complex Types
Integer Complex (<tt>dc_complex_int</tt>)
- Purpose: Gaussian integers (complex numbers with integer real and imaginary parts)
- Backend: Uses dynamic_int.h for arbitrary precision
- Operations: Exact arithmetic, division returns rational result
- Example:
3 + 4i, -7 + 2i
Rational Complex (<tt>dc_complex_frac</tt>)
- Purpose: Complex numbers with rational real and imaginary parts
- Backend: Uses dynamic_fraction.h for exact fraction arithmetic
- Operations: Exact rational arithmetic, automatic reduction to lowest terms
- Example:
1/2 + 3/4i, -2/3 + 5/7i
Floating-Point Complex (<tt>dc_complex_double</tt>)
- Purpose: IEEE 754 floating-point complex numbers
- Backend: Uses C99 complex.h for transcendental functions
- Operations: Standard complex arithmetic plus exp, log, sin, cos, etc.
- Example:
1.5 + 2.7i, 3.14159 - 1.41421i
API Design
Separate Function Families
Each complex type has its own complete API:
double dc_double_abs(dc_complex_double c)
Get the absolute value (magnitude) of a complex number.
dc_complex_double dc_double_from_polar(double magnitude, double angle)
Create a floating-point complex number from polar coordinates.
dc_complex_frac dc_frac_mul(dc_complex_frac a, dc_complex_frac b)
Multiply two rational complex numbers.
bool dc_frac_is_gaussian_int(dc_complex_frac c)
Test if a rational complex number is actually a Gaussian integer.
Type Conversions
dc_complex_double dc_int_to_double(dc_complex_int c)
Convert Gaussian integer to floating-point complex (lossless for small integers)
dc_complex_int dc_frac_to_int(dc_complex_frac c)
Convert rational complex to Gaussian integer (with rounding)
dc_complex_int dc_double_to_int(dc_complex_double c)
Convert floating-point complex to Gaussian integer (with rounding)
dc_complex_frac dc_double_to_frac(dc_complex_double c, int64_t max_denominator)
Convert floating-point complex to rational complex (with approximation)
Configuration
#define DC_MALLOC custom_malloc
#define DC_FREE custom_free
#define DC_ASSERT custom_assert
#define DC_ATOMIC_REFCOUNT 1
#define DC_STATIC
#define DC_IMPLEMENTATION
Dependencies
Required Dependencies
You must have these header files available in your include path:
- dynamic_int.h: Required for integer complex arithmetic
- dynamic_fraction.h: Required for rational complex arithmetic
- C99 complex.h: Used for floating-point transcendental functions (standard library)
Development Dependencies (optional)
- Unity: Testing framework (included in devDeps/ for development)
Dependency Setup
You have several options for managing dependencies:
- Manual Download: Download the header files and place them in your include path
- Git Submodules: Add dependencies as git submodules
- Package Manager: Use a C package manager like CPM or Conan
- System Install: Install headers system-wide
- CMake Include Directories: Add dependency paths to your CMakeLists.txt
Example with git submodules:
git submodule add https://github.com/edadma/dynamic_int.h.git deps/dynamic_int
git submodule add https://github.com/edadma/dynamic_fraction.h.git deps/dynamic_fraction
Example CMakeLists.txt setup:
include_directories(deps/dynamic_int.h)
include_directories(deps/dynamic_fraction.h)
Building
# Build the test suite
mkdir build && cd build
cmake ..
make
# Run tests
./tests
# All 25 tests should pass with 100% function coverage
Test Organization
The test suite is organized into logical groups:
- Integer Complex Tests (6 test functions)
- Basic functionality, arithmetic, memory management, missing functions coverage
- Rational Complex Tests (7 test functions)
- Creation, arithmetic, memory management, comparisons, string formatting
- Floating-Point Complex Tests (8 test functions)
- Creation, arithmetic, transcendentals, special values, comprehensive coverage
- Type Conversion Tests (2 test functions)
- All conversion paths between the three types
- Edge Cases and Formatting (2 test functions)
- Mathematical identities, string formatting, boundary conditions
Each test function thoroughly exercises multiple related functions to ensure complete coverage and mathematical correctness.
Integration with Interpreters
This library is designed for language interpreters with separate numeric types:
typedef enum {
TYPE_INT_COMPLEX,
TYPE_RATIONAL_COMPLEX,
TYPE_FLOAT_COMPLEX
} complex_type_t;
}
Mathematical Properties
- Gaussian Integer Division:
dc_int_div() returns exact rational results
- Automatic Reduction: Rational complex numbers kept in lowest terms
- Sign Normalization: Denominators always positive, sign in numerator
- IEEE 754 Compliance: Floating-point complex follows C99 standard
- String Format: Mathematical notation ("3+4i", "2-3i", "i", "-i")
Error Handling
The library uses a fail-fast approach:
- NULL pointer assertions (except in release functions)
- Memory allocation failure assertions
- Division by zero assertions
- All errors provide descriptive messages
Performance Features
- Cached Constants: Singleton objects for 0, 1, i, -1, -i
- Reference Counting: Efficient memory sharing
- Atomic Operations: Optional thread-safe reference counting
- C99 Integration: Hardware-accelerated transcendental functions
Testing
Comprehensive test suite with 25 test cases achieving 100% function coverage:
Integer Complex Tests (dc_int_*)
- Creation functions (
dc_int_from_ints, dc_int_from_di, constants)
- Complete arithmetic operations (add, sub, mul, div, negate, conjugate)
- Memory management (retain, release, copy)
- Comparison predicates and string formatting
- Edge cases and mathematical identities
Rational Complex Tests (dc_frac_*)
- Creation from integers and fractions (
dc_frac_from_ints, dc_frac_from_df)
- Complete arithmetic suite (add, sub, mul, div, negate, conjugate, reciprocal)
- Gaussian integer detection predicate
- Memory management and equality testing
- String representation with fraction notation
Floating-Point Complex Tests (dc_double_*)
- Creation from Cartesian and polar coordinates
- Basic and complete arithmetic operations
- Full transcendental function suite: exp, log, pow, sqrt, sin, cos, tan, sinh, cosh, tanh
- Special value detection (NaN, infinity)
- Memory management and string formatting
- Mathematical identity verification (e^(iπ/2) = i, sqrt(-1) = i)
Type Conversion Tests
- Lossless upward conversions (int→frac→double)
- Lossy downward conversions with rounding
- Exact and approximate fraction conversion from doubles
- Conversion accuracy validation
Comprehensive Coverage
- All 65+ functions tested across three complex types
- Memory management (reference counting, retain/release, copy)
- Mathematical correctness validation
- String formatting for all representations
- Edge cases, special values, and error conditions
- Cross-type operations and conversions
Version History
v0.1.0 (2025-09-16) - Initial Release
Features:
- Three distinct complex number types:
- Gaussian integers (
dc_complex_int) - arbitrary precision integer complex
- Rational complex (
dc_complex_frac) - exact fraction arithmetic
- Floating-point complex (
dc_complex_double) - IEEE 754 with transcendentals
- Complete arithmetic operations for all types
- Full C99 complex.h transcendental function support
- Type conversions between all three types
- Reference counting memory management with optional atomic operations
- Mathematical string formatting ("3+4i", "1/2+3/4i")
- Fail-fast error handling with descriptive assertions
API:
- 65+ functions across three complete APIs (
dc_int_*, dc_frac_*, dc_double_*)
- Separate function families for clean interpreter integration
- Lossless upward conversions, rounding downward conversions
- Gaussian integer division returns exact rational results
Quality:
- 100% function coverage with 25 comprehensive test cases
- Mathematical correctness validation
- Complete Doxygen documentation
- Cross-platform support (Linux, Windows, macOS, embedded)
- Single-header library design
Dependencies:
- Requires
dynamic_int.h and dynamic_fraction.h
- Uses C99
complex.h for transcendental functions
- CMake build system with flexible dependency management
License
Dual licensed under your choice of:
- [MIT License](LICENSE)
- [Unlicense (Public Domain)](LICENSE)
Choose the license that best fits your project's needs.
Contributing
This library follows strict design principles:
- Fail-fast error handling
- Comprehensive testing required
- Mathematical correctness over convenience