diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2e8caf7a..bd637ecf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -522,6 +522,7 @@ jobs: CYTHON: ${{matrix.cython}} CC: ${{matrix.cc}} CXX: ${{matrix.cxx}} + CXXFLAGS: -stdc=c++11 LIBS: ${{matrix.libs}} XRL_PYTHON3: /usr/bin/python3 LUA: ${{matrix.lua}} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..5b9b4a59 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,16 @@ +{ + "files.associations": { + "new": "cpp", + "stdexcept": "cpp", + "array": "cpp", + "string": "cpp", + "string_view": "cpp", + "ranges": "cpp" + }, + "files.exclude": { + "**/.classpath": true, + "**/.project": true, + "**/.settings": true, + "**/.factorypath": true + } +} \ No newline at end of file diff --git a/Makefile.am b/Makefile.am index 31a110a4..9676d537 100644 --- a/Makefile.am +++ b/Makefile.am @@ -13,6 +13,7 @@ SUBDIRS = include \ src \ + cplusplus \ idl \ python \ doc \ diff --git a/configure.ac b/configure.ac index e9ecb56a..17bb1630 100644 --- a/configure.ac +++ b/configure.ac @@ -747,7 +747,7 @@ if test x$CXX_FULL != "xnone" ; then AC_CHECK_HEADERS([cstdio cstdlib], ,[CXX=""]) AC_LANG_POP([C++]) if test x$CXX != x ; then - AC_MSG_NOTICE([C++ example enabled]) + AC_MSG_NOTICE([C++ example and tests enabled]) AC_SUBST(CXX) fi fi @@ -1045,6 +1045,8 @@ AC_CONFIG_FILES([Makefile src/Makefile include/Makefile example/Makefile + cplusplus/Makefile + cplusplus/tests/Makefile idl/Makefile python/Makefile doc/Makefile diff --git a/cplusplus/Makefile.am b/cplusplus/Makefile.am new file mode 100644 index 00000000..9b410676 --- /dev/null +++ b/cplusplus/Makefile.am @@ -0,0 +1,9 @@ +xraylibincludedir = ${includedir}/xraylib + +xraylibinclude_HEADERS = xraylib++.h + +if ENABLE_CXX +SUBDIRS = tests +endif + +EXTRA_DIST = meson.build \ No newline at end of file diff --git a/cplusplus/meson.build b/cplusplus/meson.build new file mode 100644 index 00000000..96f5fc86 --- /dev/null +++ b/cplusplus/meson.build @@ -0,0 +1,9 @@ +install_headers(files('xraylib++.h'), subdir: 'xraylib') + +cplusplus_source_dir = meson.current_source_dir() + +if add_languages('cpp', required: false, native: false) + subdir('tests') +else + warning('The C++ tests will not get built and run') +endif \ No newline at end of file diff --git a/cplusplus/tests/Makefile.am b/cplusplus/tests/Makefile.am new file mode 100644 index 00000000..1ec3d68d --- /dev/null +++ b/cplusplus/tests/Makefile.am @@ -0,0 +1,40 @@ + +AM_CPPFLAGS = -I${top_srcdir}/include -I${top_builddir}/include -I${top_srcdir}/src -I${top_srcdir}/cplusplus + +NULL= + +check_PROGRAMS = \ + test-atomicweight \ + test-atomiclevelwidth \ + test-refractive_indices \ + test-compoundparser \ + test-nist-compounds \ + test-radionuclides \ + test-crystal_diffraction \ + $(NULL) + +TESTS = $(check_PROGRAMS) + + +test_atomicweight_SOURCES = test-atomicweight.cpp +test_atomicweight_LDADD = ../../src/libxrl.la + +test_atomiclevelwidth_SOURCES = test-atomiclevelwidth.cpp +test_atomiclevelwidth_LDADD = ../../src/libxrl.la + +test_refractive_indices_SOURCES = test-refractive_indices.cpp +test_refractive_indices_LDADD = ../../src/libxrl.la + +test_compoundparser_SOURCES = test-compoundparser.cpp +test_compoundparser_LDADD = ../../src/libxrl.la + +test_radionuclides_SOURCES = test-radionuclides.cpp +test_radionuclides_LDADD = ../../src/libxrl.la + +test_nist_compounds_SOURCES = test-nist-compounds.cpp +test_nist_compounds_LDADD = ../../src/libxrl.la + +test_crystal_diffraction_SOURCES = test-crystal_diffraction.cpp +test_crystal_diffraction_LDADD = ../../src/libxrl.la + +EXTRA_DIST = meson.build \ No newline at end of file diff --git a/cplusplus/tests/meson.build b/cplusplus/tests/meson.build new file mode 100644 index 00000000..ae5ab81f --- /dev/null +++ b/cplusplus/tests/meson.build @@ -0,0 +1,14 @@ +tests = [ + 'atomiclevelwidth', + 'atomicweight', + 'compoundparser', + 'crystal_diffraction', + 'nist-compounds', + 'radionuclides', + 'refractive_indices', +] + +foreach _test : tests + _test_exec = executable(_test, files('test-' + _test + '.cpp'), dependencies: [xraylib_lib_dep, ], include_directories: ['..']) + test('c++-' + _test, _test_exec, timeout: 30) +endforeach diff --git a/cplusplus/tests/test-atomiclevelwidth.cpp b/cplusplus/tests/test-atomiclevelwidth.cpp new file mode 100644 index 00000000..a140ecd3 --- /dev/null +++ b/cplusplus/tests/test-atomiclevelwidth.cpp @@ -0,0 +1,57 @@ +/* Copyright (c) 2020, Tom Schoonjans +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY Tom Schoonjans ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Tom Schoonjans BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifdef NDEBUG + #undef NDEBUG +#endif +#include "xraylib++.h" +#include "xraylib-error-private.h" +#include +#include +#include + +int main(int argc, char **argv) { + double width; + + width = xrlpp::AtomicLevelWidth(26, K_SHELL); + assert(fabs(width - 1.19E-3) < 1E-6); + + width = xrlpp::AtomicLevelWidth(92, N7_SHELL); + assert(fabs(width - 0.31E-3) < 1E-8); + + try { + width = xrlpp::AtomicLevelWidth(185, K_SHELL); + abort(); + } + catch (std::invalid_argument &e) { + assert(strcmp(e.what(), Z_OUT_OF_RANGE) == 0); + } + + try { + width = xrlpp::AtomicLevelWidth(26, -5); + abort(); + } + catch (std::invalid_argument &e) { + assert(strcmp(e.what(), UNKNOWN_SHELL) == 0); + } + + try { + width = xrlpp::AtomicLevelWidth(26, N3_SHELL); + abort(); + } + catch (std::invalid_argument &e) { + assert(strcmp(e.what(), INVALID_SHELL) == 0); + } + + return 0; +} diff --git a/cplusplus/tests/test-atomicweight.cpp b/cplusplus/tests/test-atomicweight.cpp new file mode 100644 index 00000000..6c6d62b2 --- /dev/null +++ b/cplusplus/tests/test-atomicweight.cpp @@ -0,0 +1,42 @@ +/* Copyright (c) 2020, Tom Schoonjans +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY Tom Schoonjans ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Tom Schoonjans BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifdef NDEBUG + #undef NDEBUG +#endif +#include "xraylib++.h" +#include "xraylib-error-private.h" +#include +#include +#include + +int main(int argc, char **argv) { + double weight; + + weight = xrlpp::AtomicWeight(26); + assert(fabs(weight - 55.850) < 1E-6); + + weight = xrlpp::AtomicWeight(92); + assert(fabs(weight - 238.070) < 1E-6); + + try { + weight = xrlpp::AtomicWeight(185); + abort(); + } + catch (std::invalid_argument &e) { + assert(strcmp(e.what(), Z_OUT_OF_RANGE) == 0); + } + + return 0; +} + diff --git a/cplusplus/tests/test-compoundparser.cpp b/cplusplus/tests/test-compoundparser.cpp new file mode 100644 index 00000000..6e55984b --- /dev/null +++ b/cplusplus/tests/test-compoundparser.cpp @@ -0,0 +1,131 @@ +/* Copyright (c) 2017, Tom Schoonjans +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY Tom Schoonjans ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Tom Schoonjans BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifdef NDEBUG + #undef NDEBUG +#endif +#include "xraylib++.h" +#include "xraylib-error-private.h" +#include +#include +#include + +int main(int argc, char *argv[]) { + + std::vector good_compounds = { + "C19H29COOH", + "C12H10", + "C12H6O2", + "C6H5Br", + "C3H4OH(COOH)3", + "HOCH2CH2OH", + "C5H11NO2", + "CH3CH(CH3)CH3", + "NH2CH(C4H5N2)COOH", + "H2O", + "Ca5(PO4)3F", + "Ca5(PO4)3OH", + "Ca5.522(PO4.48)3OH", + "Ca5.522(PO.448)3OH", + }; + + std::vector bad_compounds = { + "CuI2ww", + "0C", + "2O", + "13Li", + "2(NO3)", + "H(2)", + "Ba(12)", + "Cr(5)3", + "Pb(13)2", + "Au(22)11", + "Au11(H3PO4)2)", + "Au11(H3PO4))2", + "Au(11(H3PO4))2", + "Ca5.522(PO.44.8)3OH", + "Ba[12]", + "Auu1", + "AuL1", + " ", + "\t", + "\n", + "Au L1", + "Au\tFe", + }; + + for (auto compound : good_compounds) { + xrlpp::CompoundParser(compound); + } + + for (auto compound : bad_compounds) { + try { + xrlpp::CompoundParser(compound); + abort(); + } + catch (std::invalid_argument &e) { + continue; + } + } + + xrlpp::compoundData cd = xrlpp::CompoundParser("H2SO4"); + assert(cd.nElements == 3); + assert(fabs(cd.molarMass - 98.09) < 1E-6); + assert(fabs(cd.nAtomsAll- 7.0) < 1E-6); + assert(cd.Elements[0] == 1); + assert(cd.Elements[1] == 8); + assert(cd.Elements[2] == 16); + assert(fabs(cd.massFractions[0] - 0.02059333265368539) < 1E-6); + assert(fabs(cd.massFractions[1] - 0.6524620246712203) < 1E-6); + assert(fabs(cd.massFractions[2] - 0.32694464267509427) < 1E-6); + assert(fabs(cd.nAtoms[0] - 2.0) < 1E-6); + assert(fabs(cd.nAtoms[1] - 4.0) < 1E-6); + assert(fabs(cd.nAtoms[2] - 1.0) < 1E-6); + + assert(xrlpp::SymbolToAtomicNumber("Fe") == 26); + + try { + xrlpp::SymbolToAtomicNumber("Uu"); + abort(); + } + catch (std::invalid_argument &e) { + assert(strcmp(e.what(), "Invalid chemical symbol") == 0); + } + + assert(xrlpp::AtomicNumberToSymbol(26) == "Fe"); + + try { + xrlpp::AtomicNumberToSymbol(-2); + abort(); + } + catch (std::invalid_argument &e) { + assert(strcmp(e.what(), Z_OUT_OF_RANGE) == 0); + } + + /* database currently goes up to Bh */ + try { + xrlpp::AtomicNumberToSymbol(108); + abort(); + } + catch (std::invalid_argument &e) { + assert(strcmp(e.what(), Z_OUT_OF_RANGE) == 0); + } + + /* cross validation */ + for (int Z = 1 ; Z <= 107 ; Z++) { + std::string symbol = xrlpp::AtomicNumberToSymbol(Z); + assert(xrlpp::SymbolToAtomicNumber(symbol) == Z); + } + + return 0; +} diff --git a/cplusplus/tests/test-crystal_diffraction.cpp b/cplusplus/tests/test-crystal_diffraction.cpp new file mode 100644 index 00000000..772225ba --- /dev/null +++ b/cplusplus/tests/test-crystal_diffraction.cpp @@ -0,0 +1,85 @@ +/* Copyright (c) 2017, Tom Schoonjans +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY Tom Schoonjans ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Tom Schoonjans BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifdef NDEBUG + #undef NDEBUG +#endif +#define _USE_MATH_DEFINES +#include "xraylib++.h" +#include "xraylib-error-private.h" +#include +#include +#include + +int main(int argc, char *argv[]) { + + std::vector crystals_list = xrlpp::Crystal::GetCrystalsList(); + assert(crystals_list.size() == 38); + + for (auto crystal_name : crystals_list) { + auto cs = xrlpp::Crystal::GetCrystal(crystal_name); + assert(cs.name == crystal_name); + } + + try { + xrlpp::Crystal::GetCrystal("non-existent-crystal"); + abort(); + } + catch (std::invalid_argument &e) { + } + + auto cs = xrlpp::Crystal::GetCrystal("Diamond"); + auto cs_copy(cs); + auto *cs_copy2 = new xrlpp::Crystal::Struct(cs_copy); + delete cs_copy2; + + try { + xrlpp::Crystal::AddCrystal(cs); + abort(); + } + catch (std::invalid_argument &e) { + } + + try { + xrlpp::Crystal::AddCrystal(cs_copy); + abort(); + } + catch (std::invalid_argument &e) { + } + + auto *cs_new = new xrlpp::Crystal::Struct("Diamond Copy", cs.a, cs.b, cs.c, cs.alpha, cs.beta, cs.gamma, cs.volume, cs.atom); + xrlpp::Crystal::AddCrystal(*cs_new); + delete cs_new; + crystals_list = xrlpp::Crystal::GetCrystalsList(); + assert(crystals_list.size() == 39); + + double angle = cs.Bragg_angle(10.0, 1, 1, 1); + assert(fabs(angle - 0.3057795845795849) < 1E-6); + + double tmp = cs.Q_scattering_amplitude(10.0, 1, 1, 1, M_PI_4); + assert(fabs(tmp - 0.19184445408324474) < 1E-6); + + double f0, f_prime, f_prime2; + xrlpp::Crystal::Atomic_Factors(26, 10.0, 1.0, 10.0, &f0, &f_prime, &f_prime2); + assert(fabs(f0 - 65.15) < 1E-6); + assert(fabs(f_prime + 0.22193271025027966) < 1E-6); + assert(fabs(f_prime2 - 22.420270655080493) < 1E-6); + + double volume = xrlpp::Crystal::UnitCellVolume(cs); + assert(fabs(volume - 45.376673902751) < 1E-6); + + double dSpacing = cs.dSpacing(1, 1, 1); + assert(fabs(dSpacing - 2.0592870875248344) < 1E-6); + + return 0; +} \ No newline at end of file diff --git a/cplusplus/tests/test-nist-compounds.cpp b/cplusplus/tests/test-nist-compounds.cpp new file mode 100644 index 00000000..f92a3782 --- /dev/null +++ b/cplusplus/tests/test-nist-compounds.cpp @@ -0,0 +1,76 @@ +/* Copyright (c) 2020, Tom Schoonjans +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY Tom Schoonjans ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Tom Schoonjans BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifdef NDEBUG + #undef NDEBUG +#endif +#include "xraylib++.h" +#include "xraylib-error-private.h" +#include +#include +#include + +int main(int argc, char *argv[]) { + std::vector compounds = xrlpp::GetCompoundDataNISTList(); + assert(compounds.size() == 180); + + for (int i = 0 ; i < compounds.size() ; i++) { + auto compound = compounds[i]; + auto cdn1 = xrlpp::GetCompoundDataNISTByName(compound); + assert(cdn1.name == compound); + auto cdn2 = xrlpp::GetCompoundDataNISTByIndex(i); + assert(cdn2.name == compound); + } + + auto cdn1 = xrlpp::GetCompoundDataNISTByIndex(5); + assert(cdn1.nElements == 4); + assert(cdn1.Elements == std::vector({6, 7, 8, 18})); + assert(fabs(cdn1.massFractions[0] - 0.000124) < 1E-6); + assert(fabs(cdn1.density - 0.001205) < 1E-6); + assert(cdn1.name == "Air, Dry (near sea level)"); + + auto cdn2 = xrlpp::GetCompoundDataNISTByName("Air, Dry (near sea level)"); + assert(cdn2.nElements == 4); + assert(cdn2.Elements == std::vector({6, 7, 8, 18})); + assert(fabs(cdn2.massFractions[0] - 0.000124) < 1E-6); + assert(fabs(cdn2.density - 0.001205) < 1E-6); + assert(cdn2.name == "Air, Dry (near sea level)"); + + + /* bad input */ + try { + xrlpp::GetCompoundDataNISTByIndex(-1); + abort(); + } + catch (std::invalid_argument &e) { + + } + + try { + xrlpp::GetCompoundDataNISTByIndex(180); + abort(); + } + catch (std::invalid_argument &e) { + + } + + try { + xrlpp::GetCompoundDataNISTByName(""); + abort(); + } + catch (std::invalid_argument &e) { + + } + + return 0; +} diff --git a/cplusplus/tests/test-radionuclides.cpp b/cplusplus/tests/test-radionuclides.cpp new file mode 100644 index 00000000..7a459b91 --- /dev/null +++ b/cplusplus/tests/test-radionuclides.cpp @@ -0,0 +1,83 @@ +/* Copyright (c) 2018, Tom Schoonjans +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY Tom Schoonjans ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Tom Schoonjans BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifdef NDEBUG + #undef NDEBUG +#endif +#include "xraylib++.h" +#include "xraylib-error-private.h" +#include +#include +#include + +int main(int argc, char *argv[]) { + + std::vector nuclides = xrlpp::GetRadioNuclideDataList(); + assert(nuclides.size() == 10); + + for (int i = 0 ; i < nuclides.size() ; i++) { + auto nuclide = nuclides[i]; + auto rnd1 = xrlpp::GetRadioNuclideDataByName(nuclide); + assert(rnd1.name == nuclide); + auto rnd2 = xrlpp::GetRadioNuclideDataByIndex(i); + assert(rnd2.name == nuclide); + } + + auto rnd = xrlpp::GetRadioNuclideDataByIndex(3); + assert(rnd.name == "125I"); + assert(rnd.A == 125); + assert(rnd.N == 72); + assert(rnd.Z == 53); + assert(rnd.Z_xray == 52); + assert(rnd.nGammas== 1); + assert(fabs(rnd.GammaEnergies[0] - 35.4919) < 1E-4); + assert(fabs(rnd.GammaIntensities[0] - 0.0668) < 1E-4); + assert(rnd.nXrays== 20); + assert(rnd.XrayLines[0] == -86); + assert(fabs(rnd.XrayIntensities[0] - 0.0023) < 1E-4); + + try { + xrlpp::GetRadioNuclideDataByIndex(-1); + abort(); + } + catch (std::invalid_argument &e) { + + } + + try { + xrlpp::GetRadioNuclideDataByIndex(10); + abort(); + } + catch (std::invalid_argument &e) { + + } + + try { + xrlpp::GetRadioNuclideDataByName(""); + abort(); + } + catch (std::invalid_argument &e) { + + } + + try { + xrlpp::GetRadioNuclideDataByName("jwefhjoehoeoehr"); + abort(); + } + catch (std::invalid_argument &e) { + + } + + return 0; +} + diff --git a/cplusplus/tests/test-refractive_indices.cpp b/cplusplus/tests/test-refractive_indices.cpp new file mode 100644 index 00000000..d9d749a6 --- /dev/null +++ b/cplusplus/tests/test-refractive_indices.cpp @@ -0,0 +1,139 @@ +/* Copyright (c) 2020, Tom Schoonjans +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY Tom Schoonjans ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Tom Schoonjans BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifdef NDEBUG + #undef NDEBUG +#endif +#include "xraylib++.h" +#include "xraylib-error-private.h" +#include +#include +#include + +int main(int argc, char **argv) { + double re, im; + std::complex cplx; + + /* The refractive index funtions accept both chemical formulas and NIST catalog entries. + * If the latter is used, it is possible to use the NIST density, if the density that gets passed is 0 or less + */ + + re = xrlpp::Refractive_Index_Re("H2O", 1.0, 1.0); + assert(fabs(re - 0.999763450676632) < 1E-9); + + im = xrlpp::Refractive_Index_Im("H2O", 1.0, 1.0); + assert(fabs(im - 4.021660592312145e-05) < 1E-9); + + cplx = xrlpp::Refractive_Index("H2O", 1.0, 1.0); + assert(fabs(cplx.real() - 0.999763450676632) < 1E-9); + assert(fabs(cplx.imag() - 4.021660592312145e-05) < 1E-9); + + re = xrlpp::Refractive_Index_Re("Air, Dry (near sea level)", 1.0, 1.0); + assert(fabs(re - 0.999782559048) < 1E-9); + + im = xrlpp::Refractive_Index_Im("Air, Dry (near sea level)", 1.0, 1.0); + assert(fabs(im - 0.000035578193) < 1E-9); + + cplx = xrlpp::Refractive_Index("Air, Dry (near sea level)", 1.0, 1.0); + assert(fabs(cplx.real() - 0.999782559048) < 1E-9); + assert(fabs(cplx.imag() - 0.000035578193) < 1E-9); + + re = xrlpp::Refractive_Index_Re("Air, Dry (near sea level)", 1.0, 0.0); + assert(fabs(re - 0.999999737984) < 1E-12); + + im = xrlpp::Refractive_Index_Im("Air, Dry (near sea level)", 1.0, 0.0); + assert(fabs(im - 0.000000042872) < 1E-12); + + cplx = xrlpp::Refractive_Index("Air, Dry (near sea level)", 1.0, 0.0); + assert(fabs(cplx.real() - 0.999999737984) < 1E-12); + assert(fabs(cplx.imag() - 0.000000042872) < 1E-12); + + cplx = xrlpp::Refractive_Index("Air, Dry (near sea level)", 1.0, -1.0); + assert(fabs(cplx.real() - re) < 1E-12); + assert(fabs(cplx.imag() - im) < 1E-12); + + /* bad input */ + try { + re = xrlpp::Refractive_Index_Re("", 1.0, 1.0); + abort(); + } + catch (std::invalid_argument &e) { + assert(strcmp(e.what(), UNKNOWN_COMPOUND) == 0); + } + + try { + im = xrlpp::Refractive_Index_Im("", 1.0, 1.0); + abort(); + } + catch (std::invalid_argument &e) { + assert(strcmp(e.what(), UNKNOWN_COMPOUND) == 0); + } + + try { + cplx = xrlpp::Refractive_Index("", 1.0, 1.0); + abort(); + } + catch (std::invalid_argument &e) { + assert(strcmp(e.what(), UNKNOWN_COMPOUND) == 0); + } + + try { + re = xrlpp::Refractive_Index_Re("H2O", 0.0, 1.0); + abort(); + } + catch (std::invalid_argument &e) { + assert(strcmp(e.what(), NEGATIVE_ENERGY) == 0); + } + + try { + im = xrlpp::Refractive_Index_Im("H2O", 0.0, 1.0); + abort(); + } + catch (std::invalid_argument &e) { + assert(strcmp(e.what(), NEGATIVE_ENERGY) == 0); + } + + try { + cplx = xrlpp::Refractive_Index("H2O", 0.0, 1.0); + abort(); + } + catch (std::invalid_argument &e) { + assert(strcmp(e.what(), NEGATIVE_ENERGY) == 0); + } + + try { + re = xrlpp::Refractive_Index_Re("H2O", 1.0, 0.0); + abort(); + } + catch (std::invalid_argument &e) { + assert(strcmp(e.what(), NEGATIVE_DENSITY) == 0); + } + + try { + im = xrlpp::Refractive_Index_Im("H2O", 1.0, 0.0); + abort(); + } + catch (std::invalid_argument &e) { + assert(strcmp(e.what(), NEGATIVE_DENSITY) == 0); + } + + try { + cplx = xrlpp::Refractive_Index("H2O", 1.0, 0.0); + abort(); + } + catch (std::invalid_argument &e) { + assert(strcmp(e.what(), NEGATIVE_DENSITY) == 0); + } + + return 0; +} diff --git a/cplusplus/xraylib++.h b/cplusplus/xraylib++.h new file mode 100644 index 00000000..48da95d6 --- /dev/null +++ b/cplusplus/xraylib++.h @@ -0,0 +1,621 @@ +/* Copyright (c) 2020, Tom Schoonjans +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY Tom Schoonjans ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Tom Schoonjans BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef XRAYLIB_PLUSPLUS_H +#define XRAYLIB_PLUSPLUS_H + +#include +#include +#include +#include + +using _compoundDataPod = struct compoundData; +using _radioNuclideDataPod = struct radioNuclideData; +using _compoundDataNISTPod = struct compoundDataNIST; + +#define _XRL_FUNCTION_1I(_name) \ + double _name(int arg1) { \ + xrl_error *error = nullptr; \ + double rv = ::_name(arg1, &error); \ + _process_error(error); \ + return rv; \ + } + +#define _XRL_FUNCTION_1D(_name) \ + double _name(double arg1) { \ + xrl_error *error = nullptr; \ + double rv = ::_name(arg1, &error); \ + _process_error(error); \ + return rv; \ + } + +#define _XRL_FUNCTION_2ID(_name) \ + double _name(int arg1, double arg2) { \ + xrl_error *error = nullptr; \ + double rv = ::_name(arg1, arg2, &error); \ + _process_error(error); \ + return rv; \ + } + +#define _XRL_FUNCTION_2DD(_name) \ + double _name(double arg1, double arg2) { \ + xrl_error *error = nullptr; \ + double rv = ::_name(arg1, arg2, &error); \ + _process_error(error); \ + return rv; \ + } + +#define _XRL_FUNCTION_2II(_name) \ + double _name(int arg1, int arg2) { \ + xrl_error *error = nullptr; \ + double rv = ::_name(arg1, arg2, &error); \ + _process_error(error); \ + return rv; \ + } + +#define _XRL_FUNCTION_3IDD(_name) \ + double _name(int arg1, double arg2, double arg3) { \ + xrl_error *error = nullptr; \ + double rv = ::_name(arg1, arg2, arg3, &error); \ + _process_error(error); \ + return rv; \ + } + +#define _XRL_FUNCTION_3IID(_name) \ + double _name(int arg1, int arg2, double arg3) { \ + xrl_error *error = nullptr; \ + double rv = ::_name(arg1, arg2, arg3, &error); \ + _process_error(error); \ + return rv; \ + } + +#define _XRL_FUNCTION_3DDD(_name) \ + double _name(double arg1, double arg2, double arg3) { \ + xrl_error *error = nullptr; \ + double rv = ::_name(arg1, arg2, arg3, &error); \ + _process_error(error); \ + return rv; \ + } + +#define _XRL_FUNCTION_4IDDD(_name) \ + double _name(int arg1, double arg2, double arg3, double arg4) { \ + xrl_error *error = nullptr; \ + double rv = ::_name(arg1, arg2, arg3, arg4, &error); \ + _process_error(error); \ + return rv; \ + } + +#define _XRL_FUNCTION_2SD(_name) \ + double _name(const std::string &arg1, double arg2) { \ + xrl_error *error = nullptr; \ + double rv = ::_name(arg1.c_str(), arg2, &error); \ + _process_error(error); \ + return rv; \ + } + +#define _XRL_FUNCTION_3SDD(_name) \ + double _name(const std::string &arg1, double arg2, double arg3) { \ + xrl_error *error = nullptr; \ + double rv = ::_name(arg1.c_str(), arg2, arg3, &error); \ + _process_error(error); \ + return rv; \ + } + +#define _XRL_FUNCTION_4SDDD(_name) \ + double _name(const std::string &arg1, double arg2, double arg3, double arg4) { \ + xrl_error *error = nullptr; \ + double rv = ::_name(arg1.c_str(), arg2, arg3, arg4, &error); \ + _process_error(error); \ + return rv; \ + } + + +namespace xrlpp { + void _process_error(xrl_error *error) { + if (!error) + return; + switch (error->code) { + case XRL_ERROR_MEMORY: + throw std::bad_alloc(); + case XRL_ERROR_INVALID_ARGUMENT: + throw std::invalid_argument(error->message); + default: + throw std::runtime_error(error->message); + } + } + + void XrayInit(void) { + ::XRayInit(); + } + + std::complex Refractive_Index(const std::string &compound, double E, double density) { + xrl_error *error = nullptr; + xrlComplex rv = ::Refractive_Index(compound.c_str(), E, density, &error); + _process_error(error); + return std::complex(rv.re, rv.im); + } + + int SymbolToAtomicNumber(const std::string &symbol) { + xrl_error *error = nullptr; + int rv = ::SymbolToAtomicNumber(symbol.c_str(), &error); + _process_error(error); + return rv; + } + + std::string AtomicNumberToSymbol(int Z) { + xrl_error *error = nullptr; + char *rv = ::AtomicNumberToSymbol(Z, &error); + _process_error(error); + std::string rv2(rv); + ::xrlFree(rv); + return rv2; + } + + class compoundData { + public: + const int nElements; + const std::vector Elements; + const std::vector massFractions; + const double nAtomsAll; + const std::vector nAtoms; + const double molarMass; + + friend compoundData CompoundParser(const std::string &compoundString); + + private: + compoundData(_compoundDataPod *cd) : + nElements(cd->nElements), + Elements(cd->Elements, cd->Elements + cd->nElements), + massFractions(cd->massFractions, cd->massFractions + cd->nElements), + nAtomsAll(cd->nAtomsAll), + nAtoms(cd->nAtoms, cd->nAtoms + cd->nElements), + molarMass(cd->molarMass) + {} + }; + + class radioNuclideData { + public: + const std::string name; + const int Z; + const int A; + const int N; + const int Z_xray; + const int nXrays; + const std::vector XrayLines; + const std::vector XrayIntensities; + const int nGammas; + const std::vector GammaEnergies; + const std::vector GammaIntensities; + + friend radioNuclideData GetRadioNuclideDataByName(const std::string &radioNuclideString); + friend radioNuclideData GetRadioNuclideDataByIndex(int radioNuclideIndex); + + private: + radioNuclideData(_radioNuclideDataPod *rnd) : + name(rnd->name), + Z(rnd->Z), + A(rnd->A), + N(rnd->N), + Z_xray(rnd->Z_xray), + nXrays(rnd->nXrays), + XrayLines(rnd->XrayLines, rnd->XrayLines + rnd->nXrays), + XrayIntensities(rnd->XrayIntensities, rnd->XrayIntensities+ rnd->nXrays), + nGammas(rnd->nGammas), + GammaEnergies(rnd->GammaEnergies, rnd->GammaEnergies + rnd->nGammas), + GammaIntensities(rnd->GammaIntensities, rnd->GammaIntensities + rnd->nGammas) + {} + }; + + class compoundDataNIST { + public: + const std::string name; + const int nElements; + const std::vector Elements; + const std::vector massFractions; + const double density; + + friend compoundDataNIST GetCompoundDataNISTByName(const std::string &compoundString); + friend compoundDataNIST GetCompoundDataNISTByIndex(int compoundIndex); + + private: + compoundDataNIST(_compoundDataNISTPod *cdn) : + name(cdn->name), + nElements(cdn->nElements), + Elements(cdn->Elements, cdn->Elements + cdn->nElements), + massFractions(cdn->massFractions, cdn->massFractions + cdn->nElements), + density(cdn->density) + {} + }; + + namespace Crystal { + class Atom { + public: + const int Zatom; + const double fraction; + const double x, y, z; + + friend std::vector _create_atom_vector(Crystal_Atom *atoms, int n_atom); + + private: + Atom(const Crystal_Atom &atom) : + Zatom(atom.Zatom), + fraction(atom.fraction), + x(atom.x), + y(atom.y), + z(atom.z) + {} + }; + + std::vector _create_atom_vector(Crystal_Atom *atoms, int n_atom) { + std::vector rv; + + for (int i = 0 ; i < n_atom ; i++) + rv.push_back(atoms[i]); + + return rv; + } + + class Struct { + public: + const std::string name; + const double a, b, c; + const double alpha, beta, gamma; + const double volume; + const int n_atom; + const std::vector atom; + + double Bragg_angle(double energy, int i_miller, int j_miller, int k_miller) { + xrl_error *error = nullptr; + double rv = ::Bragg_angle(cs, energy, i_miller, j_miller, k_miller, &error); + _process_error(error); + return rv; + } + + double Q_scattering_amplitude(double energy, int i_miller, int j_miller, int k_miller, double rel_angle) { + xrl_error *error = nullptr; + double rv = ::Q_scattering_amplitude(cs, energy, i_miller, j_miller, k_miller, rel_angle, &error); + _process_error(error); + return rv; + } + + std::complex F_H_StructureFactor(double energy, int i_miller, int j_miller, int k_miller, double debye_factor, double rel_angle) { + xrl_error *error = nullptr; + xrlComplex rv = ::Crystal_F_H_StructureFactor(cs, energy, i_miller, j_miller, k_miller, debye_factor, rel_angle, &error); + _process_error(error); + return std::complex(rv.re, rv.im); + } + + std::complex F_H_StructureFactor_Partial(double energy, int i_miller, int j_miller, int k_miller, double debye_factor, double rel_angle, int f0_flag, int f_prime_flag, int f_prime2_flag) { + xrl_error *error = nullptr; + xrlComplex rv = ::Crystal_F_H_StructureFactor_Partial(cs, energy, i_miller, j_miller, k_miller, debye_factor, rel_angle, f0_flag, f_prime_flag, f_prime2_flag, &error); + _process_error(error); + return std::complex(rv.re, rv.im); + } + + double UnitCellVolume(void) { + xrl_error *error = nullptr; + double rv = ::Crystal_UnitCellVolume(cs, &error); + _process_error(error); + return rv; + } + + double dSpacing(int i_miller, int j_miller, int k_miller) { + xrl_error *error = nullptr; + double rv = ::Crystal_dSpacing(cs, i_miller, j_miller, k_miller, &error); + _process_error(error); + return rv; + } + + int AddCrystal(void) { + xrl_error *error = nullptr; + int rv = ::Crystal_AddCrystal(cs, nullptr, &error); + _process_error(error); + return rv; + } + + // constructor -> this needs to generate the underlying cs pointer! + Struct(const std::string &name, double a, double b, double c, double alpha, double beta, double gamma, double volume, const std::vector &atoms) : + name(name), + a(a), + b(b), + c(c), + alpha(alpha), + beta(beta), + gamma(gamma), + volume(volume), + n_atom(atoms.size()), + atom(atoms) + { + cs = (Crystal_Struct *) xrl_malloc(sizeof(Crystal_Struct)); + cs->name = xrl_strdup(name.c_str()); + cs->a = a; + cs->b = b; + cs->c = c; + cs->alpha = alpha; + cs->beta = beta; + cs->gamma = gamma; + cs->volume = volume; + cs->n_atom = n_atom; + cs->atom = (Crystal_Atom *) xrl_malloc(sizeof(Crystal_Atom) * n_atom); + for (int i = 0 ; i < n_atom ; i++) { + cs->atom[i].Zatom = atoms[i].Zatom; + cs->atom[i].fraction = atoms[i].fraction; + cs->atom[i].x = atoms[i].x; + cs->atom[i].y = atoms[i].y; + cs->atom[i].z = atoms[i].z; + } + } + + // copy constructor + Struct(const Struct &_struct) : + name(_struct.name), + a(_struct.a), + b(_struct.b), + c(_struct.c), + alpha(_struct.alpha), + beta(_struct.beta), + gamma(_struct.gamma), + volume(_struct.volume), + n_atom(_struct.n_atom), + atom(_struct.atom) { + + xrl_error *error = nullptr; + cs = ::Crystal_MakeCopy(_struct.cs, &error); + _process_error(error); + } + + // destructor + ~Struct() { + ::Crystal_Free(cs); + } + + friend Struct GetCrystal(const std::string &material); + + private: + Crystal_Struct *cs; + + Struct(Crystal_Struct *_struct) : + name(_struct->name), + a(_struct->a), + b(_struct->b), + c(_struct->c), + alpha(_struct->alpha), + beta(_struct->beta), + gamma(_struct->gamma), + volume(_struct->volume), + n_atom(_struct->n_atom), + atom(_create_atom_vector(_struct->atom, _struct->n_atom)), + cs(_struct) + {} + + }; + + Struct GetCrystal(const std::string &material) { + xrl_error *error = nullptr; + Crystal_Struct *cs = ::Crystal_GetCrystal(material.c_str(), nullptr, &error); + _process_error(error); + Struct rv(cs); + return rv; + } + + double Bragg_angle(Struct &cs, double energy, int i_miller, int j_miller, int k_miller) { + return cs.Bragg_angle(energy, i_miller, j_miller, k_miller); + } + + double Q_scattering_amplitude(Struct &cs, double energy, int i_miller, int j_miller, int k_miller, double rel_angle) { + return cs.Q_scattering_amplitude(energy, i_miller, j_miller, k_miller, rel_angle); + } + + int Atomic_Factors(int Z, double energy, double q, double debye_factor, double *f0, double *f_prime, double *f_prime2) { + xrl_error *error = nullptr; + int rv = ::Atomic_Factors(Z, energy, q, debye_factor, f0, f_prime, f_prime2, &error); + _process_error(error); + return rv; + } + + std::complex F_H_StructureFactor(Struct &cs, double energy, int i_miller, int j_miller, int k_miller, double debye_factor, double rel_angle) { + return cs.F_H_StructureFactor(energy, i_miller, j_miller, k_miller, debye_factor, rel_angle); + } + + std::complex F_H_StructureFactor_Partial(Struct &cs, double energy, int i_miller, int j_miller, int k_miller, double debye_factor, double rel_angle, int f0_flag, int f_prime_flag, int f_prime2_flag) { + return cs.F_H_StructureFactor_Partial(energy, i_miller, j_miller, k_miller, debye_factor, rel_angle, f0_flag, f_prime_flag, f_prime2_flag); + } + + double UnitCellVolume(Struct &cs) { + return cs.UnitCellVolume(); + } + + double dSpacing(Struct &cs, int i_miller, int j_miller, int k_miller) { + return cs.dSpacing(i_miller, j_miller, k_miller); + } + + std::vector GetCrystalsList(void) { + std::vector rv; + xrl_error *error = nullptr; + int nCrystals; + char **list = ::Crystal_GetCrystalsList(nullptr, &nCrystals, &error); + _process_error(error); + for (int i = 0 ; i < nCrystals ; i++) { + rv.push_back(list[i]); + ::xrlFree(list[i]); + } + ::xrlFree(list); + return rv; + } + + int AddCrystal(Struct &cs) { + return cs.AddCrystal(); + } + } + + compoundData CompoundParser(const std::string &compoundString) { + xrl_error *error = nullptr; + _compoundDataPod *cd = ::CompoundParser(compoundString.c_str(), &error); + _process_error(error); + compoundData rv(cd); + ::FreeCompoundData(cd); + return rv; + } + + radioNuclideData GetRadioNuclideDataByName(const std::string &radioNuclideString) { + xrl_error *error = nullptr; + _radioNuclideDataPod *rnd = ::GetRadioNuclideDataByName(radioNuclideString.c_str(), &error); + _process_error(error); + radioNuclideData rv(rnd); + ::FreeRadioNuclideData(rnd); + return rv; + } + + radioNuclideData GetRadioNuclideDataByIndex(int radioNuclideIndex) { + xrl_error *error = nullptr; + _radioNuclideDataPod *rnd = ::GetRadioNuclideDataByIndex(radioNuclideIndex, &error); + _process_error(error); + radioNuclideData rv(rnd); + ::FreeRadioNuclideData(rnd); + return rv; + } + + std::vector GetRadioNuclideDataList(void) { + std::vector rv; + xrl_error *error = nullptr; + int nRadioNuclides; + char **list = ::GetRadioNuclideDataList(&nRadioNuclides, &error); + _process_error(error); + for (int i = 0 ; i < nRadioNuclides ; i++) { + rv.push_back(list[i]); + ::xrlFree(list[i]); + } + ::xrlFree(list); + return rv; + } + + compoundDataNIST GetCompoundDataNISTByName(const std::string &compoundString) { + xrl_error *error = nullptr; + _compoundDataNISTPod *cdn = ::GetCompoundDataNISTByName(compoundString.c_str(), &error); + _process_error(error); + compoundDataNIST rv(cdn); + ::FreeCompoundDataNIST(cdn); + return rv; + } + + compoundDataNIST GetCompoundDataNISTByIndex(int compoundIndex) { + xrl_error *error = nullptr; + _compoundDataNISTPod *cdn = ::GetCompoundDataNISTByIndex(compoundIndex, &error); + _process_error(error); + compoundDataNIST rv(cdn); + ::FreeCompoundDataNIST(cdn); + return rv; + } + + std::vector GetCompoundDataNISTList(void) { + std::vector rv; + xrl_error *error = nullptr; + int nCompounds; + char **list = ::GetCompoundDataNISTList(&nCompounds, &error); + _process_error(error); + for (int i = 0 ; i < nCompounds; i++) { + rv.push_back(list[i]); + ::xrlFree(list[i]); + } + ::xrlFree(list); + return rv; + } + + _XRL_FUNCTION_1I(AtomicWeight) + _XRL_FUNCTION_1I(ElementDensity) + _XRL_FUNCTION_1D(CS_KN) + _XRL_FUNCTION_1D(DCS_Thoms) + _XRL_FUNCTION_2ID(CS_Total) + _XRL_FUNCTION_2ID(CS_Photo) + _XRL_FUNCTION_2ID(CS_Rayl) + _XRL_FUNCTION_2ID(CS_Compt) + _XRL_FUNCTION_2ID(CS_Energy) + _XRL_FUNCTION_2ID(CSb_Total) + _XRL_FUNCTION_2ID(CSb_Photo) + _XRL_FUNCTION_2ID(CSb_Rayl) + _XRL_FUNCTION_2ID(CSb_Compt) + _XRL_FUNCTION_2ID(FF_Rayl) + _XRL_FUNCTION_2ID(SF_Compt) + _XRL_FUNCTION_2ID(Fi) + _XRL_FUNCTION_2ID(Fii) + _XRL_FUNCTION_2ID(CS_Photo_Total) + _XRL_FUNCTION_2ID(CSb_Photo_Total) + _XRL_FUNCTION_2ID(CS_Total_Kissel) + _XRL_FUNCTION_2ID(CSb_Total_Kissel) + _XRL_FUNCTION_2II(LineEnergy) + _XRL_FUNCTION_2II(FluorYield) + _XRL_FUNCTION_2II(CosKronTransProb) + _XRL_FUNCTION_2II(EdgeEnergy) + _XRL_FUNCTION_2II(JumpFactor) + _XRL_FUNCTION_2II(RadRate) + _XRL_FUNCTION_2DD(DCS_KN) + _XRL_FUNCTION_2DD(DCSP_Thoms) + _XRL_FUNCTION_2DD(MomentTransf) + _XRL_FUNCTION_2DD(ComptonEnergy) + _XRL_FUNCTION_3IDD(DCS_Rayl) + _XRL_FUNCTION_3IDD(DCS_Compt) + _XRL_FUNCTION_3IDD(DCSb_Rayl) + _XRL_FUNCTION_3IDD(DCSb_Compt) + _XRL_FUNCTION_3DDD(DCSP_KN) + _XRL_FUNCTION_3IID(CS_FluorLine) + _XRL_FUNCTION_3IID(CSb_FluorLine) + _XRL_FUNCTION_3IID(CS_Photo_Partial) + _XRL_FUNCTION_3IID(CSb_Photo_Partial) + _XRL_FUNCTION_4IDDD(DCSP_Rayl) + _XRL_FUNCTION_4IDDD(DCSP_Compt) + _XRL_FUNCTION_4IDDD(DCSPb_Rayl) + _XRL_FUNCTION_4IDDD(DCSPb_Compt) + _XRL_FUNCTION_2ID(ComptonProfile) + _XRL_FUNCTION_3IID(ComptonProfile_Partial) + _XRL_FUNCTION_2II(ElectronConfig) + _XRL_FUNCTION_2II(AtomicLevelWidth) + _XRL_FUNCTION_2II(AugerRate) + _XRL_FUNCTION_2II(AugerYield) + _XRL_FUNCTION_3IID(CS_FluorLine_Kissel) + _XRL_FUNCTION_3IID(CSb_FluorLine_Kissel) + _XRL_FUNCTION_3IID(CS_FluorLine_Kissel_Cascade) + _XRL_FUNCTION_3IID(CSb_FluorLine_Kissel_Cascade) + _XRL_FUNCTION_3IID(CS_FluorLine_Kissel_no_Cascade) + _XRL_FUNCTION_3IID(CSb_FluorLine_Kissel_no_Cascade) + _XRL_FUNCTION_3IID(CS_FluorLine_Kissel_Nonradiative_Cascade) + _XRL_FUNCTION_3IID(CSb_FluorLine_Kissel_Nonradiative_Cascade) + _XRL_FUNCTION_3IID(CS_FluorLine_Kissel_Radiative_Cascade) + _XRL_FUNCTION_3IID(CSb_FluorLine_Kissel_Radiative_Cascade) + + _XRL_FUNCTION_2SD(CS_Total_CP) + _XRL_FUNCTION_2SD(CS_Photo_CP) + _XRL_FUNCTION_2SD(CS_Rayl_CP) + _XRL_FUNCTION_2SD(CS_Compt_CP) + _XRL_FUNCTION_2SD(CS_Energy_CP) + _XRL_FUNCTION_2SD(CSb_Total_CP) + _XRL_FUNCTION_2SD(CSb_Photo_CP) + _XRL_FUNCTION_2SD(CSb_Rayl_CP) + _XRL_FUNCTION_2SD(CSb_Compt_CP) + _XRL_FUNCTION_3SDD(DCS_Rayl_CP) + _XRL_FUNCTION_3SDD(DCS_Compt_CP) + _XRL_FUNCTION_3SDD(DCSb_Rayl_CP) + _XRL_FUNCTION_3SDD(DCSb_Compt_CP) + _XRL_FUNCTION_4SDDD(DCSP_Rayl_CP) + _XRL_FUNCTION_4SDDD(DCSP_Compt_CP) + _XRL_FUNCTION_4SDDD(DCSPb_Rayl_CP) + _XRL_FUNCTION_4SDDD(DCSPb_Compt_CP) + _XRL_FUNCTION_2SD(CS_Photo_Total_CP) + _XRL_FUNCTION_2SD(CSb_Photo_Total_CP) + _XRL_FUNCTION_2SD(CS_Total_Kissel_CP) + _XRL_FUNCTION_2SD(CSb_Total_Kissel_CP) + _XRL_FUNCTION_3SDD(Refractive_Index_Re) + _XRL_FUNCTION_3SDD(Refractive_Index_Im) + +} + +#endif diff --git a/example/Makefile.am b/example/Makefile.am index 99fbc76f..284761fc 100644 --- a/example/Makefile.am +++ b/example/Makefile.am @@ -12,7 +12,7 @@ #Makefile.am for the examples. These can be used to verify that the compilation went ok by typing in "make check" -AM_CPPFLAGS = -I${top_srcdir}/include -I${top_builddir}/include +AM_CPPFLAGS = -I${top_srcdir}/include -I${top_builddir}/include -I${top_srcdir}/cplusplus #since the C lib will always be built, always check xrlexample1 diff --git a/example/xrlexample6.cpp b/example/xrlexample6.cpp index cb3cc6ad..f549627a 100644 --- a/example/xrlexample6.cpp +++ b/example/xrlexample6.cpp @@ -14,298 +14,259 @@ THIS SOFTWARE IS PROVIDED BY Tom Schoonjans ''AS IS'' AND ANY EXPRESS OR IMPLIED #include #include #include -#include "xraylib.h" +#include "xraylib++.h" using namespace std; int main() { - struct compoundData *cdtest, *cdtest1, *cdtest2, *cdtest3; - int i; - char *symbol; - Crystal_Struct* cryst; - Crystal_Atom* atom; double energy = 8; double debye_temp_factor = 1.0; double rel_angle = 1.0; double bragg, q, dw; double f0, fp, fpp; - xrlComplex FH, F0; - xrlComplex FHbar; - char **crystalNames; - struct compoundDataNIST *cdn; - char **nistCompounds; - struct radioNuclideData *rnd; - char **radioNuclides; + std::complex FH, F0, FHbar; + std::vector crystalNames, nistCompounds, radioNuclides; XRayInit(); printf("Example of C++ program using xraylib\n"); - printf("Density of pure Al: %f g/cm3\n", ElementDensity(13, NULL)); - printf("Ca K-alpha Fluorescence Line Energy: %f\n", LineEnergy(20, KA_LINE, NULL)); - printf("Fe partial photoionization cs of L3 at 6.0 keV: %f\n", CS_Photo_Partial(26, L3_SHELL, 6.0, NULL)); - printf("Zr L1 edge energy: %f\n", EdgeEnergy(40, L1_SHELL, NULL)); - printf("Pb Lalpha XRF production cs at 20.0 keV (jump approx): %f\n", CS_FluorLine(82, LA_LINE, 20.0, NULL)); - printf("Pb Lalpha XRF production cs at 20.0 keV (Kissel): %f\n", CS_FluorLine_Kissel(82, LA_LINE, 20.0, NULL)); - printf("Bi M1N2 radiative rate: %f\n", RadRate(83, M1N2_LINE, NULL)); - printf("U M3O3 Fluorescence Line Energy: %f\n", LineEnergy(92, M3O3_LINE, NULL)); + printf("Density of pure Al: %f g/cm3\n", xrlpp::ElementDensity(13)); + printf("Ca K-alpha Fluorescence Line Energy: %f\n", xrlpp::LineEnergy(20, KA_LINE)); + printf("Fe partial photoionization cs of L3 at 6.0 keV: %f\n", xrlpp::CS_Photo_Partial(26, L3_SHELL, 6.0)); + printf("Zr L1 edge energy: %f\n", xrlpp::EdgeEnergy(40, L1_SHELL)); + printf("Pb Lalpha XRF production cs at 20.0 keV (jump approx): %f\n", xrlpp::CS_FluorLine(82, LA_LINE, 20.0)); + printf("Pb Lalpha XRF production cs at 20.0 keV (Kissel): %f\n", xrlpp::CS_FluorLine_Kissel(82, LA_LINE, 20.0)); + printf("Bi M1N2 radiative rate: %f\n", xrlpp::RadRate(83, M1N2_LINE)); + printf("U M3O3 Fluorescence Line Energy: %f\n", xrlpp::LineEnergy(92, M3O3_LINE)); /*parser test for Ca(HCO3)2 (calcium bicarbonate)*/ - if ((cdtest = CompoundParser("Ca(HCO3)2", NULL)) == NULL) - return 1; - printf("Ca(HCO3)2 contains %g atoms, %i elements and has a molar mass of %g g/mol\n", cdtest->nAtomsAll, cdtest->nElements, cdtest->molarMass); - for (i = 0 ; i < cdtest->nElements ; i++) - printf("Element %i: %f %% and %g atoms\n", cdtest->Elements[i], cdtest->massFractions[i]*100.0, cdtest->nAtoms[i]); - - FreeCompoundData(cdtest); + { + auto cdtest = xrlpp::CompoundParser("Ca(HCO3)2"); + printf("Ca(HCO3)2 contains %g atoms, %i elements and has a molar mass of %g g/mol\n", cdtest.nAtomsAll, cdtest.nElements, cdtest.molarMass); + for (int i = 0 ; i < cdtest.nElements ; i++) + printf("Element %i: %f %% and %g atoms\n", cdtest.Elements[i], cdtest.massFractions[i]*100.0, cdtest.nAtoms[i]); + } /*parser test for SiO2 (quartz)*/ - if ((cdtest = CompoundParser("SiO2", NULL)) == NULL) - return 1; - - printf("SiO2 contains %g atoms, %i elements and has a molar mass of %g g/mol\n", cdtest->nAtomsAll, cdtest->nElements, cdtest->molarMass); - for (i = 0 ; i < cdtest->nElements ; i++) - printf("Element %i: %f %% and %g atoms\n", cdtest->Elements[i], cdtest->massFractions[i]*100.0, cdtest->nAtoms[i]); - - FreeCompoundData(cdtest); - - printf("Ca(HCO3)2 Rayleigh cs at 10.0 keV: %f\n", CS_Rayl_CP("Ca(HCO3)2", 10.0f, NULL)); - - printf("CS2 Refractive Index at 10.0 keV : %f - %f i\n", Refractive_Index_Re("CS2", 10.0f, 1.261f, NULL), Refractive_Index_Im("CS2", 10.0f, 1.261f, NULL)); - printf("C16H14O3 Refractive Index at 1 keV : %f - %f i\n", Refractive_Index_Re("C16H14O3", 1.0f, 1.2f, NULL), Refractive_Index_Im("C16H14O3", 1.0f, 1.2f, NULL)); - printf("SiO2 Refractive Index at 5 keV : %f - %f i\n", Refractive_Index_Re("SiO2", 5.0f, 2.65f, NULL), Refractive_Index_Im("SiO2",5.0f, 2.65f, NULL)); - - printf("Compton profile for Fe at pz = 1.1 : %f\n", ComptonProfile(26, 1.1f, NULL)); - printf("M5 Compton profile for Fe at pz = 1.1 : %f\n", ComptonProfile_Partial(26, M5_SHELL, 1.1f, NULL)); - printf("M1->M5 Coster-Kronig transition probability for Au : %f\n", CosKronTransProb(79, FM15_TRANS, NULL)); - printf("L1->L3 Coster-Kronig transition probability for Fe : %f\n", CosKronTransProb(26, FL13_TRANS, NULL)); - printf("Au Ma1 XRF production cs at 10.0 keV (Kissel): %f\n", CS_FluorLine_Kissel(79, MA1_LINE, 10.0f, NULL)); - printf("Au Mb XRF production cs at 10.0 keV (Kissel): %f\n", CS_FluorLine_Kissel(79, MB_LINE, 10.0f, NULL)); - printf("Au Mg XRF production cs at 10.0 keV (Kissel): %f\n", CS_FluorLine_Kissel(79, MG_LINE, 10.0f, NULL)); - - printf("K atomic level width for Fe: %f\n", AtomicLevelWidth(26, K_SHELL, NULL)); - printf("Bi L2-M5M5 Auger non-radiative rate: %f\n", AugerRate(86, L2_M5M5_AUGER, NULL)); - printf("Bi L3 Auger yield: %f\n", AugerYield(86, L3_SHELL, NULL)); + { + auto cdtest = xrlpp::CompoundParser("SiO2"); + printf("SiO2 contains %g atoms, %i elements and has a molar mass of %g g/mol\n", cdtest.nAtomsAll, cdtest.nElements, cdtest.molarMass); + for (int i = 0 ; i < cdtest.nElements ; i++) + printf("Element %i: %f %% and %g atoms\n", cdtest.Elements[i], cdtest.massFractions[i]*100.0, cdtest.nAtoms[i]); + } - if ((cdtest1 = CompoundParser("SiO2", NULL)) == NULL) - return 1; + printf("Ca(HCO3)2 Rayleigh cs at 10.0 keV: %f\n", xrlpp::CS_Rayl_CP("Ca(HCO3)2", 10.0f)); - if ((cdtest2 = CompoundParser("Ca(HCO3)2", NULL)) == NULL) - return 1; + printf("CS2 Refractive Index at 10.0 keV : %f - %f i\n", xrlpp::Refractive_Index_Re("CS2", 10.0f, 1.261f), xrlpp::Refractive_Index_Im("CS2", 10.0f, 1.261f)); + printf("C16H14O3 Refractive Index at 1 keV : %f - %f i\n", xrlpp::Refractive_Index_Re("C16H14O3", 1.0f, 1.2f), xrlpp::Refractive_Index_Im("C16H14O3", 1.0f, 1.2f)); + printf("SiO2 Refractive Index at 5 keV : %f - %f i\n", xrlpp::Refractive_Index_Re("SiO2", 5.0f, 2.65f), xrlpp::Refractive_Index_Im("SiO2",5.0f, 2.65f)); - cdtest3 = add_compound_data(*cdtest1, 0.4, *cdtest2, 0.6); - for (i = 0 ; i < cdtest3->nElements ; i++) - printf("Element %i: %f %%\n",cdtest3->Elements[i],cdtest3->massFractions[i]*100.0); + printf("Compton profile for Fe at pz = 1.1 : %f\n", xrlpp::ComptonProfile(26, 1.1f)); + printf("M5 Compton profile for Fe at pz = 1.1 : %f\n", xrlpp::ComptonProfile_Partial(26, M5_SHELL, 1.1f)); + printf("M1->M5 Coster-Kronig transition probability for Au : %f\n", xrlpp::CosKronTransProb(79, FM15_TRANS)); + printf("L1->L3 Coster-Kronig transition probability for Fe : %f\n", xrlpp::CosKronTransProb(26, FL13_TRANS)); + printf("Au Ma1 XRF production cs at 10.0 keV (Kissel): %f\n", xrlpp::CS_FluorLine_Kissel(79, MA1_LINE, 10.0f)); + printf("Au Mb XRF production cs at 10.0 keV (Kissel): %f\n", xrlpp::CS_FluorLine_Kissel(79, MB_LINE, 10.0f)); + printf("Au Mg XRF production cs at 10.0 keV (Kissel): %f\n", xrlpp::CS_FluorLine_Kissel(79, MG_LINE, 10.0f)); - FreeCompoundData(cdtest1); - FreeCompoundData(cdtest2); - FreeCompoundData(cdtest3); + printf("K atomic level width for Fe: %f\n", xrlpp::AtomicLevelWidth(26, K_SHELL)); + printf("Bi L2-M5M5 Auger non-radiative rate: %f\n", xrlpp::AugerRate(86, L2_M5M5_AUGER)); + printf("Bi L3 Auger yield: %f\n", xrlpp::AugerYield(86, L3_SHELL)); - printf("Sr anomalous scattering factor Fi at 10.0 keV: %f\n", Fi(38, 10.0, NULL)); - printf("Sr anomalous scattering factor Fii at 10.0 keV: %f\n", Fii(38, 10.0, NULL)); + printf("Sr anomalous scattering factor Fi at 10.0 keV: %f\n", xrlpp::Fi(38, 10.0)); + printf("Sr anomalous scattering factor Fii at 10.0 keV: %f\n", xrlpp::Fii(38, 10.0)); - symbol = AtomicNumberToSymbol(26, NULL); - printf("Symbol of element 26 is: %s\n",symbol); - xrlFree(symbol); + auto symbol = xrlpp::AtomicNumberToSymbol(26); + printf("Symbol of element 26 is: %s\n", symbol.c_str()); - printf("Number of element Fe is: %i\n",SymbolToAtomicNumber("Fe", NULL)); + printf("Number of element Fe is: %i\n", xrlpp::SymbolToAtomicNumber("Fe")); - printf("Pb Malpha XRF production cs at 20.0 keV with cascade effect: %f\n", CS_FluorLine_Kissel(82, MA1_LINE, 20.0, NULL)); - printf("Pb Malpha XRF production cs at 20.0 keV with radiative cascade effect: %f\n", CS_FluorLine_Kissel_Radiative_Cascade(82, MA1_LINE, 20.0, NULL)); - printf("Pb Malpha XRF production cs at 20.0 keV with non-radiative cascade effect: %f\n", CS_FluorLine_Kissel_Nonradiative_Cascade(82, MA1_LINE, 20.0, NULL)); - printf("Pb Malpha XRF production cs at 20.0 keV without cascade effect: %f\n", CS_FluorLine_Kissel_no_Cascade(82, MA1_LINE, 20.0, NULL)); + printf("Pb Malpha XRF production cs at 20.0 keV with cascade effect: %f\n", xrlpp::CS_FluorLine_Kissel(82, MA1_LINE, 20.0)); + printf("Pb Malpha XRF production cs at 20.0 keV with radiative cascade effect: %f\n", xrlpp::CS_FluorLine_Kissel_Radiative_Cascade(82, MA1_LINE, 20.0)); + printf("Pb Malpha XRF production cs at 20.0 keV with non-radiative cascade effect: %f\n", xrlpp::CS_FluorLine_Kissel_Nonradiative_Cascade(82, MA1_LINE, 20.0)); + printf("Pb Malpha XRF production cs at 20.0 keV without cascade effect: %f\n", xrlpp::CS_FluorLine_Kissel_no_Cascade(82, MA1_LINE, 20.0)); - printf("Al mass energy-absorption cs at 20.0 keV: %f\n", CS_Energy(13, 20.0, NULL)); - printf("Pb mass energy-absorption cs at 40.0 keV: %f\n", CS_Energy(82, 40.0, NULL)); - printf("CdTe mass energy-absorption cs at 40.0 keV: %f\n", CS_Energy_CP("CdTe", 40.0, NULL)); + printf("Al mass energy-absorption cs at 20.0 keV: %f\n", xrlpp::CS_Energy(13, 20.0)); + printf("Pb mass energy-absorption cs at 40.0 keV: %f\n", xrlpp::CS_Energy(82, 40.0)); + printf("CdTe mass energy-absorption cs at 40.0 keV: %f\n", xrlpp::CS_Energy_CP("CdTe", 40.0)); /* Si Crystal structure */ - cryst = Crystal_GetCrystal("Si", NULL, NULL); - if (cryst == NULL) return 1; - printf ("Si unit cell dimensions are %f %f %f\n", cryst->a, cryst->b, cryst->c); - printf ("Si unit cell angles are %f %f %f\n", cryst->alpha, cryst->beta, cryst->gamma); - printf ("Si unit cell volume is %f\n", cryst->volume); + auto cryst = xrlpp::Crystal::GetCrystal("Si"); + printf ("Si unit cell dimensions are %f %f %f\n", cryst.a, cryst.b, cryst.c); + printf ("Si unit cell angles are %f %f %f\n", cryst.alpha, cryst.beta, cryst.gamma); + printf ("Si unit cell volume is %f\n", cryst.volume); printf ("Si atoms at:\n"); printf (" Z fraction X Y Z\n"); - for (i = 0; i < cryst->n_atom; i++) { - atom = &cryst->atom[i]; - printf (" %3i %f %f %f %f\n", atom->Zatom, atom->fraction, atom->x, atom->y, atom->z); + for (int i = 0; i < cryst.n_atom; i++) { + auto atom = cryst.atom[i]; + printf (" %3i %f %f %f %f\n", atom.Zatom, atom.fraction, atom.x, atom.y, atom.z); } /* Si diffraction parameters */ printf ("\nSi111 at 8 KeV. Incidence at the Bragg angle:\n"); - bragg = Bragg_angle (cryst, energy, 1, 1, 1, NULL); + bragg = cryst.Bragg_angle(energy, 1, 1, 1); printf (" Bragg angle: Rad: %f Deg: %f\n", bragg, bragg*180/PI); - q = Q_scattering_amplitude (cryst, energy, 1, 1, 1, rel_angle, NULL); + q = cryst.Q_scattering_amplitude(energy, 1, 1, 1, rel_angle); printf (" Q Scattering amplitude: %f\n", q); - Atomic_Factors (14, energy, q, debye_temp_factor, &f0, &fp, &fpp, NULL); + xrlpp::Crystal::Atomic_Factors(14, energy, q, debye_temp_factor, &f0, &fp, &fpp); printf (" Atomic factors (Z = 14) f0, fp, fpp: %f, %f, i*%f\n", f0, fp, fpp); - FH = Crystal_F_H_StructureFactor (cryst, energy, 1, 1, 1, debye_temp_factor, rel_angle, NULL); - printf (" FH(1,1,1) structure factor: (%f, %f)\n", FH.re, FH.im); - - F0 = Crystal_F_H_StructureFactor (cryst, energy, 0, 0, 0, debye_temp_factor, rel_angle, NULL); - printf (" F0=FH(0,0,0) structure factor: (%f, %f)\n", F0.re, F0.im); - + FH = cryst.F_H_StructureFactor(energy, 1, 1, 1, debye_temp_factor, rel_angle); + printf (" FH(1,1,1) structure factor: (%f, %f)\n", FH.real(), FH.imag()); + F0 = cryst.F_H_StructureFactor(energy, 0, 0, 0, debye_temp_factor, rel_angle); + printf (" F0=FH(0,0,0) structure factor: (%f, %f)\n", F0.real(), F0.imag()); /* Diamond diffraction parameters */ - cryst = Crystal_GetCrystal("Diamond", NULL, NULL); + auto cryst2 = xrlpp::Crystal::GetCrystal("Diamond"); printf ("\nDiamond 111 at 8 KeV. Incidence at the Bragg angle:\n"); - bragg = Bragg_angle (cryst, energy, 1, 1, 1, NULL); + bragg = xrlpp::Crystal::Bragg_angle(cryst2, energy, 1, 1, 1); printf (" Bragg angle: Rad: %f Deg: %f\n", bragg, bragg*180/PI); - q = Q_scattering_amplitude (cryst, energy, 1, 1, 1, rel_angle, NULL); + q = xrlpp::Crystal::Q_scattering_amplitude(cryst2, energy, 1, 1, 1, rel_angle); printf (" Q Scattering amplitude: %f\n", q); - Atomic_Factors (6, energy, q, debye_temp_factor, &f0, &fp, &fpp, NULL); + xrlpp::Crystal::Atomic_Factors(6, energy, q, debye_temp_factor, &f0, &fp, &fpp); printf (" Atomic factors (Z = 6) f0, fp, fpp: %f, %f, i*%f\n", f0, fp, fpp); - FH = Crystal_F_H_StructureFactor (cryst, energy, 1, 1, 1, debye_temp_factor, rel_angle, NULL); - printf (" FH(1,1,1) structure factor: (%f, %f)\n", FH.re, FH.im); + FH = xrlpp::Crystal::F_H_StructureFactor(cryst2, energy, 1, 1, 1, debye_temp_factor, rel_angle); + printf (" FH(1,1,1) structure factor: (%f, %f)\n", FH.real(), FH.imag()); - F0 = Crystal_F_H_StructureFactor (cryst, energy, 0, 0, 0, debye_temp_factor, rel_angle, NULL); - printf (" F0=FH(0,0,0) structure factor: (%f, %f)\n", F0.re, F0.im); + F0 = xrlpp::Crystal::F_H_StructureFactor(cryst2, energy, 0, 0, 0, debye_temp_factor, rel_angle); + printf (" F0=FH(0,0,0) structure factor: (%f, %f)\n", F0.real(), F0.imag()); - FHbar = Crystal_F_H_StructureFactor (cryst, energy, -1, -1, -1, debye_temp_factor, rel_angle, NULL); - dw = 1e10 * 2 * (R_E / cryst->volume) * (KEV2ANGST * KEV2ANGST/ (energy * energy)) * - sqrt(c_abs(c_mul(FH, FHbar))) / PI / sin(2*bragg); + FHbar = xrlpp::Crystal::F_H_StructureFactor(cryst2, energy, -1, -1, -1, debye_temp_factor, rel_angle); + dw = 1e10 * 2 * (R_E / cryst.volume) * (KEV2ANGST * KEV2ANGST/ (energy * energy)) * + sqrt(std::abs(FH * FHbar)) / PI / sin(2*bragg); printf (" Darwin width: %f micro-radians\n", 1e6*dw); /* Alpha Quartz diffraction parameters */ - cryst = Crystal_GetCrystal("AlphaQuartz", NULL, NULL); + auto cryst3 = xrlpp::Crystal::GetCrystal("AlphaQuartz"); printf ("\nAlpha Quartz 020 at 8 KeV. Incidence at the Bragg angle:\n"); - bragg = Bragg_angle (cryst, energy, 0, 2, 0, NULL); + bragg = cryst3.Bragg_angle(energy, 0, 2, 0); printf (" Bragg angle: Rad: %f Deg: %f\n", bragg, bragg*180/PI); - q = Q_scattering_amplitude (cryst, energy, 0, 2, 0, rel_angle, NULL); + q = cryst3.Q_scattering_amplitude(energy, 0, 2, 0, rel_angle); printf (" Q Scattering amplitude: %f\n", q); - Atomic_Factors (8, energy, q, debye_temp_factor, &f0, &fp, &fpp, NULL); + xrlpp::Crystal::Atomic_Factors(8, energy, q, debye_temp_factor, &f0, &fp, &fpp); printf (" Atomic factors (Z = 8) f0, fp, fpp: %f, %f, i*%f\n", f0, fp, fpp); - FH = Crystal_F_H_StructureFactor (cryst, energy, 0, 2, 0, debye_temp_factor, rel_angle, NULL); - printf (" FH(0,2,0) structure factor: (%f, %f)\n", FH.re, FH.im); + FH = cryst3.F_H_StructureFactor(energy, 0, 2, 0, debye_temp_factor, rel_angle); + printf (" FH(0,2,0) structure factor: (%f, %f)\n", FH.real(), FH.imag()); - F0 = Crystal_F_H_StructureFactor (cryst, energy, 0, 0, 0, debye_temp_factor, rel_angle, NULL); - printf (" F0=FH(0,0,0) structure factor: (%f, %f)\n", F0.re, F0.im); + F0 = cryst3.F_H_StructureFactor(energy, 0, 0, 0, debye_temp_factor, rel_angle); + printf (" F0=FH(0,0,0) structure factor: (%f, %f)\n", F0.real(), F0.imag()); /* Muscovite diffraction parameters */ - cryst = Crystal_GetCrystal("Muscovite", NULL, NULL); + auto cryst4 = xrlpp::Crystal::GetCrystal("Muscovite"); printf ("\nMuscovite 331 at 8 KeV. Incidence at the Bragg angle:\n"); - bragg = Bragg_angle (cryst, energy, 3, 3, 1, NULL); + bragg = cryst4.Bragg_angle(energy, 3, 3, 1); printf (" Bragg angle: Rad: %f Deg: %f\n", bragg, bragg*180/PI); - q = Q_scattering_amplitude (cryst, energy, 3, 3, 1, rel_angle, NULL); + q = cryst4.Q_scattering_amplitude(energy, 3, 3, 1, rel_angle); printf (" Q Scattering amplitude: %f\n", q); - Atomic_Factors (19, energy, q, debye_temp_factor, &f0, &fp, &fpp, NULL); + xrlpp::Crystal::Atomic_Factors(19, energy, q, debye_temp_factor, &f0, &fp, &fpp); printf (" Atomic factors (Z = 19) f0, fp, fpp: %f, %f, i*%f\n", f0, fp, fpp); - FH = Crystal_F_H_StructureFactor (cryst, energy, 3, 3, 1, debye_temp_factor, rel_angle, NULL); - printf (" FH(3,3,1) structure factor: (%f, %f)\n", FH.re, FH.im); + FH = cryst4.F_H_StructureFactor(energy, 3, 3, 1, debye_temp_factor, rel_angle); + printf (" FH(3,3,1) structure factor: (%f, %f)\n", FH.real(), FH.imag()); - F0 = Crystal_F_H_StructureFactor (cryst, energy, 0, 0, 0, debye_temp_factor, rel_angle, NULL); - printf (" F0=FH(0,0,0) structure factor: (%f, %f)\n", F0.re, F0.im); + F0 = cryst4.F_H_StructureFactor(energy, 0, 0, 0, debye_temp_factor, rel_angle); + printf (" F0=FH(0,0,0) structure factor: (%f, %f)\n", F0.real(), F0.imag()); - crystalNames = Crystal_GetCrystalsList(NULL, NULL, NULL); + crystalNames = xrlpp::Crystal::GetCrystalsList(); printf ("List of available crystals:\n"); - for (i = 0 ; crystalNames[i] != NULL ; i++) { - printf (" Crystal %i: %s\n", i, crystalNames[i]); - xrlFree(crystalNames[i]); + for (int i = 0 ; i < crystalNames.size() ; i++) { + printf (" Crystal %i: %s\n", i, crystalNames[i].c_str()); } - xrlFree(crystalNames); printf ("\n"); /* compoundDataNIST tests */ - cdn = GetCompoundDataNISTByName("Uranium Monocarbide", NULL); - printf ("Uranium Monocarbide\n"); - printf (" Name: %s\n", cdn->name); - printf (" Density: %f g/cm3\n", cdn->density); - for (i = 0 ; i < cdn->nElements ; i++) { - printf(" Element %i: %f %%\n",cdn->Elements[i],cdn->massFractions[i]*100.0); + { + auto cdn = xrlpp::GetCompoundDataNISTByName("Uranium Monocarbide"); + printf ("Uranium Monocarbide\n"); + printf (" Name: %s\n", cdn.name.c_str()); + printf (" Density: %f g/cm3\n", cdn.density); + for (int i = 0 ; i < cdn.nElements ; i++) { + printf(" Element %i: %f %%\n", cdn.Elements[i], cdn.massFractions[i]*100.0); + } } - FreeCompoundDataNIST(cdn); - cdn = NULL; - - cdn = GetCompoundDataNISTByIndex(NIST_COMPOUND_BRAIN_ICRP, NULL); - printf ("NIST_COMPOUND_BRAIN_ICRP\n"); - printf (" Name: %s\n", cdn->name); - printf (" Density: %f g/cm3\n", cdn->density); - for (i = 0 ; i < cdn->nElements ; i++) { - printf(" Element %i: %f %%\n",cdn->Elements[i],cdn->massFractions[i]*100.0); + { + auto cdn = xrlpp::GetCompoundDataNISTByIndex(NIST_COMPOUND_BRAIN_ICRP); + printf ("NIST_COMPOUND_BRAIN_ICRP\n"); + printf(" Name: %s\n", cdn.name.c_str()); + printf (" Density: %f g/cm3\n", cdn.density); + for (int i = 0 ; i < cdn.nElements ; i++) { + printf(" Element %i: %f %%\n", cdn.Elements[i], cdn.massFractions[i]*100.0); + } } - FreeCompoundDataNIST(cdn); - cdn = NULL; - - nistCompounds = GetCompoundDataNISTList(NULL, NULL); + nistCompounds = xrlpp::GetCompoundDataNISTList(); printf ("List of available NIST compounds:\n"); - for (i = 0 ; nistCompounds[i] != NULL ; i++) { - printf (" Compound %i: %s\n", i, nistCompounds[i]); - xrlFree(nistCompounds[i]); + for (int i = 0 ; i < nistCompounds.size() ; i++) { + printf (" Compound %i: %s\n", i, nistCompounds[i].c_str()); } - xrlFree(nistCompounds); printf ("\n"); /* radioNuclideData tests */ - rnd = GetRadioNuclideDataByName("109Cd", NULL); - printf ("109Cd\n"); - printf (" Name: %s\n", rnd->name); - printf (" Z: %i\n", rnd->Z); - printf (" A: %i\n", rnd->A); - printf (" N: %i\n", rnd->N); - printf (" Z_xray: %i\n", rnd->Z_xray); - printf (" X-rays:\n"); - for (i = 0 ; i < rnd->nXrays ; i++) - printf (" %f keV -> %f\n", LineEnergy(rnd->Z_xray, rnd->XrayLines[i], NULL), rnd->XrayIntensities[i]); - printf (" Gamma rays:\n"); - for (i = 0 ; i < rnd->nGammas ; i++) - printf (" %f keV -> %f\n", rnd->GammaEnergies[i], rnd->GammaIntensities[i]); - - FreeRadioNuclideData(rnd); - - rnd = GetRadioNuclideDataByIndex(RADIO_NUCLIDE_125I, NULL); - printf ("RADIO_NUCLIDE_125I\n"); - printf (" Name: %s\n", rnd->name); - printf (" Z: %i\n", rnd->Z); - printf (" A: %i\n", rnd->A); - printf (" N: %i\n", rnd->N); - printf (" Z_xray: %i\n", rnd->Z_xray); - printf (" X-rays:\n"); - for (i = 0 ; i < rnd->nXrays ; i++) - printf (" %f keV -> %f\n", LineEnergy(rnd->Z_xray, rnd->XrayLines[i], NULL), rnd->XrayIntensities[i]); - printf (" Gamma rays:\n"); - for (i = 0 ; i < rnd->nGammas ; i++) - printf (" %f keV -> %f\n", rnd->GammaEnergies[i], rnd->GammaIntensities[i]); - - FreeRadioNuclideData(rnd); - - radioNuclides = GetRadioNuclideDataList(NULL, NULL); + { + auto rnd = xrlpp::GetRadioNuclideDataByName("109Cd"); + printf ("109Cd\n"); + printf (" Name: %s\n", rnd.name.c_str()); + printf (" Z: %i\n", rnd.Z); + printf (" A: %i\n", rnd.A); + printf (" N: %i\n", rnd.N); + printf (" Z_xray: %i\n", rnd.Z_xray); + printf (" X-rays:\n"); + for (int i = 0 ; i < rnd.nXrays ; i++) + printf (" %f keV -> %f\n", xrlpp::LineEnergy(rnd.Z_xray, rnd.XrayLines[i]), rnd.XrayIntensities[i]); + printf (" Gamma rays:\n"); + for (int i = 0 ; i < rnd.nGammas ; i++) + printf (" %f keV -> %f\n", rnd.GammaEnergies[i], rnd.GammaIntensities[i]); + } + + { + auto rnd = xrlpp::GetRadioNuclideDataByIndex(RADIO_NUCLIDE_125I); + printf ("RADIO_NUCLIDE_125I\n"); + printf (" Name: %s\n", rnd.name.c_str()); + printf (" Z: %i\n", rnd.Z); + printf (" A: %i\n", rnd.A); + printf (" N: %i\n", rnd.N); + printf (" Z_xray: %i\n", rnd.Z_xray); + printf (" X-rays:\n"); + for (int i = 0 ; i < rnd.nXrays ; i++) + printf (" %f keV -> %f\n", xrlpp::LineEnergy(rnd.Z_xray, rnd.XrayLines[i]), rnd.XrayIntensities[i]); + printf (" Gamma rays:\n"); + for (int i = 0 ; i < rnd.nGammas ; i++) + printf (" %f keV -> %f\n", rnd.GammaEnergies[i], rnd.GammaIntensities[i]); + } + + radioNuclides = xrlpp::GetRadioNuclideDataList(); printf ("List of available radionuclides:\n"); - for (i = 0 ; radioNuclides[i] != NULL ; i++) { - printf (" Radionuclide %i: %s\n", i, radioNuclides[i]); - xrlFree(radioNuclides[i]); + for (int i = 0 ; i < radioNuclides.size() ; i++) { + printf (" Radionuclide %i: %s\n", i, radioNuclides[i].c_str()); } - xrlFree(radioNuclides); printf ("\n--------------------------- END OF XRLEXAMPLE6 -------------------------------\n"); return 0; } diff --git a/include/Makefile.am b/include/Makefile.am index 469cd712..75a88e97 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -10,6 +10,7 @@ xraylibinclude_HEADERS = xraylib.h \ xraylib-nist-compounds.h \ xraylib-radionuclides.h \ xraylib-error.h \ - xraylib-deprecated.h + xraylib-deprecated.h \ + xraylib-aux.h EXTRA_DIST = meson.build diff --git a/include/meson.build b/include/meson.build index 2c7d2d14..d8a24efd 100644 --- a/include/meson.build +++ b/include/meson.build @@ -10,6 +10,7 @@ xraylib_headers = files( 'xraylib-radionuclides.h', 'xraylib-error.h', 'xraylib-deprecated.h', + 'xraylib-aux.h', ) install_headers(xraylib_headers, subdir: 'xraylib') diff --git a/src/xraylib-aux.h b/include/xraylib-aux.h similarity index 96% rename from src/xraylib-aux.h rename to include/xraylib-aux.h index cde7ec57..8b6f04bc 100644 --- a/src/xraylib-aux.h +++ b/include/xraylib-aux.h @@ -14,7 +14,7 @@ THIS SOFTWARE IS PROVIDED BY Tom Schoonjans ''AS IS'' AND ANY EXPRESS OR IMPLIED #ifndef _XRAYLIB_AUX_H #define _XRAYLIB_AUX_H -#include "xraylib.h" +#ifndef SWIG #include XRL_EXTERN @@ -23,4 +23,8 @@ char *xrl_strdup(const char *str); XRL_EXTERN char *xrl_strndup(const char *str, size_t len); +XRL_EXTERN +void *xrl_malloc(size_t size); + +#endif #endif diff --git a/include/xraylib-crystal-diffraction.h b/include/xraylib-crystal-diffraction.h index bc0629bc..ab4e8df6 100644 --- a/include/xraylib-crystal-diffraction.h +++ b/include/xraylib-crystal-diffraction.h @@ -87,7 +87,7 @@ double Q_scattering_amplitude(Crystal_Struct* crystal, double energy, */ XRL_EXTERN -int Atomic_Factors (int Z, double energy, double q, double debye_factor, double* f0, double* f_primep, double* f_prime2, xrl_error **error); +int Atomic_Factors (int Z, double energy, double q, double debye_factor, double *f0, double *f_primep, double *f_prime2, xrl_error **error); /*-------------------------------------------------------------------------------- * Compute F_H diff --git a/include/xraylib-nist-compounds.h b/include/xraylib-nist-compounds.h index b704872a..889bfe62 100644 --- a/include/xraylib-nist-compounds.h +++ b/include/xraylib-nist-compounds.h @@ -24,10 +24,10 @@ THIS SOFTWARE IS PROVIDED BY Tom Schoonjans ''AS IS'' AND ANY EXPRESS OR IMPLIED struct compoundDataNIST { char *name; - int nElements; - int *Elements; - double *massFractions; - double density; + int nElements; + int *Elements; + double *massFractions; + double density; }; /* diff --git a/include/xraylib.h b/include/xraylib.h index 1b65f3dc..27543112 100644 --- a/include/xraylib.h +++ b/include/xraylib.h @@ -63,6 +63,7 @@ extern "C" { #include "xraylib-nist-compounds.h" #include "xraylib-radionuclides.h" #include "xraylib-deprecated.h" +#include "xraylib-aux.h" /* * Siegbahn notation diff --git a/meson.build b/meson.build index 7673251d..6045f60f 100644 --- a/meson.build +++ b/meson.build @@ -1,8 +1,11 @@ project('xraylib', - ['c'], + 'c', meson_version: '>= 0.56.0', version:'4.0.0', - license: 'BSD') + license: 'BSD', + default_options: ['cpp_std=c++11',] +) + # versioning stuff -> maintain compatibility with libtool! # # a) If binary compatibility has been broken (eg removed or changed interfaces) @@ -95,6 +98,7 @@ pkgconfig = import('pkgconfig') subdir('include') subdir('src') subdir('tests') +subdir('cplusplus') if not (get_option('python-bindings').disabled() and get_option('python-numpy-bindings').disabled()) pymod = import('python') diff --git a/src/Makefile.am b/src/Makefile.am index e57d741a..5d8b12e4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -48,9 +48,8 @@ libprdata_la_SOURCES = \ radrate.c \ auger_trans.c \ kissel_pe.c \ - cross_sections.c \ - xraylib-aux.c \ - xraylib-aux.h + cross_sections.c \ + xraylib-aux.c libprdata_la_LIBADD = $(LIBM) @@ -80,7 +79,6 @@ libxrl_la_SOURCES = xrayvars.c \ xrayglob.h \ xrayvars.h \ xraylib-aux.c \ - xraylib-aux.h \ xraylib-parser.c \ cs_cp.c \ refractive_indices.c \ diff --git a/src/meson.build b/src/meson.build index ccc95c38..59ccc7a0 100644 --- a/src/meson.build +++ b/src/meson.build @@ -37,19 +37,18 @@ shared_sources = files( 'splint.c', 'splint.h', 'xraylib-aux.c', - 'xraylib-aux.h', 'xraylib-error.c', 'xraylib-error-private.h', 'xrayglob.h', 'xrayvars.c', 'xrayvars.h', - 'xrf_cross_sections_aux-private.h', - 'xrf_cross_sections_aux-private.c', ) libprdata_sources = shared_sources + files( 'xrayglob.c', 'xrayfiles.c', + 'xrf_cross_sections_aux-private.h', + 'xrf_cross_sections_aux-private.c', ) prdata_sources = files( diff --git a/src/xraylib-aux.c b/src/xraylib-aux.c index 0c2f170d..99343c79 100644 --- a/src/xraylib-aux.c +++ b/src/xraylib-aux.c @@ -40,3 +40,7 @@ char *xrl_strndup(const char *str, size_t len) { return strndup(str, len); #endif } + +void *xrl_malloc(size_t size) { + return malloc(size); +} \ No newline at end of file diff --git a/src/xraylib.i b/src/xraylib.i index 5cd44d4f..b942bb63 100644 --- a/src/xraylib.i +++ b/src/xraylib.i @@ -61,7 +61,6 @@ __version__ = VERSION XRL_GNUC_BEGIN_IGNORE_DEPRECATIONS #include "xraylib.h" -#include "xraylib-aux.h" #include "xrf_cross_sections_aux.h"