// Copyright (C) 2026 Kiyotsugu Arai // SPDX-License-Identifier: LGPL-3.0-or-later // // example_doc_concepts_samples.cpp // Verification harness for samples in api/Concepts.html (ja+en). #include #include #include #include #include #include #include #include #include #include using namespace sangi; using namespace sangi::concepts; // ---- doc snippets, verbatim ---------------------------------------- template T safe_inverse(const T& x) { if (x == T(0)) return T(0); return T(1) / x; } template requires VectorSpace V linear_combination(S a, const V& v, S b, const V& w) { return a * v + b * w; } template T horner(const std::vector& coeffs, const T& x) { T result = T{0}; for (auto it = coeffs.rbegin(); it != coeffs.rend(); ++it) { result = result * x + *it; } return result; } template requires QuaternionType && DivisionRing auto rotation_axis(const T& q) { auto v_norm = std::sqrt(q.x * q.x + q.y * q.y + q.z * q.z); return std::make_tuple(q.x / v_norm, q.y / v_norm, q.z / v_norm); } template T clamp_sample(const T& x, const T& lo, const T& hi) { if (x < lo) return lo; if (x > hi) return hi; return x; } template T midpoint(const T& a, const T& b) { return (a + b) / T(2); } int main() { std::cout << std::setprecision(15); // ---- safe_inverse ---------------------------------------------- { std::cout << "[safe_inverse]\n"; auto inv_d = safe_inverse(3.14); auto inv_r = safe_inverse(Rational(3, 7)); std::cout << " safe_inverse(3.14) = " << inv_d << "\n"; std::cout << " safe_inverse(Rational(3/7)) = " << inv_r.toString() << "\n"; std::cout << " safe_inverse(0.0) = " << safe_inverse(0.0) << " (zero guard)\n"; } // ---- linear_combination --------------------------------------- { std::cout << "[linear_combination]\n"; Vector v({1.0, 2.0, 3.0}); Vector w({4.0, 5.0, 6.0}); Vector r = linear_combination, double>(2.0, v, 3.0, w); std::cout << " 2*v+3*w = {" << r[0] << "," << r[1] << "," << r[2] << "}\n"; } // ---- horner ---------------------------------------------------- { std::cout << "[horner]\n"; std::vector poly = {1.0, -2.0, 3.0}; // 3x^2 - 2x + 1 double val = horner(poly, 2.0); std::cout << " horner({1,-2,3}, x=2) = " << val << " (expected 9)\n"; } // ---- rotation_axis -------------------------------------------- { std::cout << "[rotation_axis]\n"; // Around axis (1,2,2), norm = 3 Quaternion q(0.0, 1.0, 2.0, 2.0); auto [ax, ay, az] = rotation_axis(q); std::cout << " axis = (" << ax << "," << ay << "," << az << ")\n"; std::cout << " |axis| = " << std::sqrt(ax*ax + ay*ay + az*az) << " (expected 1)\n"; } // ---- clamp / midpoint ----------------------------------------- { std::cout << "[clamp/midpoint]\n"; std::cout << " clamp(2.5, 0, 1) = " << clamp_sample(2.5, 0.0, 1.0) << "\n"; std::cout << " clamp(-0.3, 0, 1) = " << clamp_sample(-0.3, 0.0, 1.0) << "\n"; std::cout << " midpoint(1.0, 5.0) = " << midpoint(1.0, 5.0) << "\n"; auto c = midpoint(Complex(1.0, 0.0), Complex(3.0, 4.0)); std::cout << " midpoint(1, 3+4i) = " << c.re << "+" << c.im << "i\n"; } // ---- concept compile-time checks (static_assert) -------------- { std::cout << "[static_assert sanity]\n"; static_assert(Field); static_assert(Field); static_assert(Field>); static_assert(OrderedField); static_assert(!OrderedField>); static_assert(Ring); static_assert(DivisionRing>); static_assert(QuaternionType>); std::cout << " all concept static_asserts compiled OK\n"; } return 0; }