Loading...
Searching...
No Matches
precision_cast.hpp
Go to the documentation of this file.
1#pragma once
2
3/**
4 * Precision cast utilities for FP64 ↔ FP32 complex number conversion.
5 *
6 * Provides CPU-side element-wise conversion between Complex (std::complex<double>)
7 * and ComplexSingle (std::complex<float>) arrays. GPU implementations may override
8 * these with CUDA kernels for device-resident data.
9 *
10 * These utilities are used by the mixed-precision Davidson loop to convert
11 * wavefunctions between FP64 (for precision-sensitive operations) and FP32
12 * (for bulk H|ψ⟩ computation on GPU).
13 */
14
15#include <complex>
16
19
20namespace q3 {
21
22namespace precision {
23
24/**
25 * Cast an array of double-precision complex values to single-precision.
26 *
27 * Element-wise narrowing conversion: each Complex element is converted to
28 * ComplexSingle by truncating the mantissa from 52 to 23 bits.
29 *
30 * @param count Number of elements to convert.
31 * @param source Input array of Complex (FP64) values.
32 * @param destination Output array of ComplexSingle (FP32) values.
33 * Must be pre-allocated with at least count elements.
34 */
35inline void cast_double_to_single(int count, const Complex* source, ComplexSingle* destination) {
36 for (int index = 0; index < count; ++index) {
37 destination[index] = ComplexSingle(static_cast<float>(source[index].real()),
38 static_cast<float>(source[index].imag()));
39 }
40}
41
42/**
43 * Cast an array of single-precision complex values to double-precision.
44 *
45 * Element-wise widening conversion: each ComplexSingle element is converted
46 * to Complex by zero-extending the mantissa.
47 *
48 * @param count Number of elements to convert.
49 * @param source Input array of ComplexSingle (FP32) values.
50 * @param destination Output array of Complex (FP64) values.
51 * Must be pre-allocated with at least count elements.
52 */
53inline void cast_single_to_double(int count, const ComplexSingle* source, Complex* destination) {
54 for (int index = 0; index < count; ++index) {
55 destination[index] = Complex(static_cast<double>(source[index].real()),
56 static_cast<double>(source[index].imag()));
57 }
58}
59
60/**
61 * Cast an array of double-precision real values to single-precision.
62 *
63 * @param count Number of elements to convert.
64 * @param source Input array of Real (FP64) values.
65 * @param destination Output array of RealSingle (FP32) values.
66 */
67inline void cast_real_double_to_single(int count, const Real* source, RealSingle* destination) {
68 for (int index = 0; index < count; ++index) {
69 destination[index] = static_cast<float>(source[index]);
70 }
71}
72
73/**
74 * Cast an array of single-precision real values to double-precision.
75 *
76 * @param count Number of elements to convert.
77 * @param source Input array of RealSingle (FP32) values.
78 * @param destination Output array of Real (FP64) values.
79 */
80inline void cast_real_single_to_double(int count, const RealSingle* source, Real* destination) {
81 for (int index = 0; index < count; ++index) {
82 destination[index] = static_cast<double>(source[index]);
83 }
84}
85
86} // namespace precision
87} // namespace q3
void cast_double_to_single(int count, const Complex *source, ComplexSingle *destination)
void cast_real_double_to_single(int count, const Real *source, RealSingle *destination)
void cast_single_to_double(int count, const ComplexSingle *source, Complex *destination)
void cast_real_single_to_double(int count, const RealSingle *source, Real *destination)
float RealSingle
double Real
std::complex< float > ComplexSingle
std::complex< double > Complex