mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-27 13:45:36 -04:00
Merge pull request #1042 from paulromano/cpp-nucdata
Move many nuclear data-related classes to C++
This commit is contained in:
commit
0ff0568a10
151 changed files with 50272 additions and 2113 deletions
16
.travis.yml
16
.travis.yml
|
|
@ -1,16 +1,18 @@
|
|||
sudo: required
|
||||
dist: trusty
|
||||
dist: xenial
|
||||
language: python
|
||||
python:
|
||||
- "3.4"
|
||||
- "3.5"
|
||||
- "3.6"
|
||||
- "3.7"
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- gfortran
|
||||
- mpich
|
||||
- libmpich-dev
|
||||
- gfortran
|
||||
- mpich
|
||||
- libmpich-dev
|
||||
- libhdf5-serial-dev
|
||||
- libhdf5-mpich-dev
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/nndc_hdf5
|
||||
|
|
@ -31,10 +33,6 @@ env:
|
|||
- OMP=y MPI=n PHDF5=n
|
||||
- OMP=n MPI=y PHDF5=n
|
||||
- OMP=n MPI=y PHDF5=y
|
||||
before_install:
|
||||
- sudo add-apt-repository ppa:nschloe/hdf5-backports -y
|
||||
- sudo apt-get update -q
|
||||
- sudo apt-get install libhdf5-serial-dev libhdf5-mpich-dev -y
|
||||
install:
|
||||
- ./tools/ci/travis-install.sh
|
||||
before_script:
|
||||
|
|
|
|||
|
|
@ -84,8 +84,8 @@ if(CMAKE_Fortran_COMPILER_ID STREQUAL GNU)
|
|||
# Make sure version is sufficient
|
||||
execute_process(COMMAND ${CMAKE_Fortran_COMPILER} -dumpversion
|
||||
OUTPUT_VARIABLE GCC_VERSION)
|
||||
if(GCC_VERSION VERSION_LESS 4.8)
|
||||
message(FATAL_ERROR "gfortran version must be 4.8 or higher")
|
||||
if(GCC_VERSION VERSION_LESS 4.9)
|
||||
message(FATAL_ERROR "gcc version must be 4.9 or higher")
|
||||
endif()
|
||||
|
||||
# GCC compiler options
|
||||
|
|
@ -210,7 +210,7 @@ elseif(CMAKE_C_COMPILER_ID MATCHES Clang)
|
|||
|
||||
endif()
|
||||
|
||||
list(APPEND cxxflags -std=c++11 -O2)
|
||||
list(APPEND cxxflags -std=c++14 -O2)
|
||||
if(debug)
|
||||
list(REMOVE_ITEM cxxflags -O2)
|
||||
list(APPEND cxxflags -g -O0)
|
||||
|
|
@ -236,6 +236,14 @@ message(STATUS "Linker flags: ${ldflags}")
|
|||
add_library(pugixml vendor/pugixml/pugixml.cpp)
|
||||
target_include_directories(pugixml PUBLIC vendor/pugixml/)
|
||||
|
||||
#===============================================================================
|
||||
# xtensor header-only library
|
||||
#===============================================================================
|
||||
|
||||
add_subdirectory(vendor/xtl)
|
||||
add_subdirectory(vendor/xtensor)
|
||||
target_link_libraries(xtensor INTERFACE xtl)
|
||||
|
||||
#===============================================================================
|
||||
# RPATH information
|
||||
#===============================================================================
|
||||
|
|
@ -280,7 +288,6 @@ set_target_properties(faddeeva PROPERTIES
|
|||
|
||||
add_library(libopenmc SHARED
|
||||
src/algorithm.F90
|
||||
src/angle_distribution.F90
|
||||
src/angleenergy_header.F90
|
||||
src/bank_header.F90
|
||||
src/api.F90
|
||||
|
|
@ -298,7 +305,6 @@ add_library(libopenmc SHARED
|
|||
src/eigenvalue.F90
|
||||
src/endf.F90
|
||||
src/endf_header.F90
|
||||
src/energy_distribution.F90
|
||||
src/error.F90
|
||||
src/geometry.F90
|
||||
src/geometry_header.F90
|
||||
|
|
@ -326,7 +332,6 @@ add_library(libopenmc SHARED
|
|||
src/physics_mg.F90
|
||||
src/plot.F90
|
||||
src/plot_header.F90
|
||||
src/product_header.F90
|
||||
src/progress_header.F90
|
||||
src/pugixml/pugixml_f.F90
|
||||
src/random_lcg.F90
|
||||
|
|
@ -334,9 +339,6 @@ add_library(libopenmc SHARED
|
|||
src/relaxng
|
||||
src/sab_header.F90
|
||||
src/secondary_correlated.F90
|
||||
src/secondary_kalbach.F90
|
||||
src/secondary_nbody.F90
|
||||
src/secondary_uncorrelated.F90
|
||||
src/set_header.F90
|
||||
src/settings.F90
|
||||
src/simulation_header.F90
|
||||
|
|
@ -384,6 +386,12 @@ add_library(libopenmc SHARED
|
|||
src/tallies/trigger.F90
|
||||
src/tallies/trigger_header.F90
|
||||
src/cell.cpp
|
||||
src/distribution.cpp
|
||||
src/distribution_angle.cpp
|
||||
src/distribution_energy.cpp
|
||||
src/distribution_multi.cpp
|
||||
src/distribution_spatial.cpp
|
||||
src/endf.cpp
|
||||
src/initialize.cpp
|
||||
src/finalize.cpp
|
||||
src/geometry_aux.cpp
|
||||
|
|
@ -398,6 +406,12 @@ add_library(libopenmc SHARED
|
|||
src/position.cpp
|
||||
src/pugixml/pugixml_c.cpp
|
||||
src/random_lcg.cpp
|
||||
src/reaction.cpp
|
||||
src/reaction_product.cpp
|
||||
src/secondary_correlated.cpp
|
||||
src/secondary_kalbach.cpp
|
||||
src/secondary_nbody.cpp
|
||||
src/secondary_uncorrelated.cpp
|
||||
src/scattdata.cpp
|
||||
src/settings.cpp
|
||||
src/simulation.cpp
|
||||
|
|
@ -450,7 +464,7 @@ endif()
|
|||
# target_link_libraries treats any arguments starting with - but not -l as
|
||||
# linker flags. Thus, we can pass both linker flags and libraries together.
|
||||
target_link_libraries(libopenmc ${ldflags} ${HDF5_LIBRARIES} pugixml
|
||||
faddeeva)
|
||||
faddeeva xtensor)
|
||||
|
||||
#===============================================================================
|
||||
# openmc executable
|
||||
|
|
|
|||
|
|
@ -174,9 +174,7 @@ Follow the `C++ Core Guidelines`_ except when they conflict with another
|
|||
guideline listed here. For convenience, many important guidelines from that
|
||||
list are repeated here.
|
||||
|
||||
Conform to the C++11 standard. Note that this is a significant difference
|
||||
between our style and the C++ Core Guidelines. Many suggestions in those
|
||||
Guidelines require C++14.
|
||||
Conform to the C++14 standard.
|
||||
|
||||
Always use C++-style comments (``//``) as opposed to C-style (``/**/``). (It
|
||||
is more difficult to comment out a large section of code that uses C-style
|
||||
|
|
|
|||
|
|
@ -1,130 +0,0 @@
|
|||
module angle_distribution
|
||||
|
||||
use algorithm, only: binary_search
|
||||
use constants, only: ZERO, ONE, HISTOGRAM, LINEAR_LINEAR
|
||||
use distribution_univariate, only: DistributionContainer, Tabular
|
||||
use hdf5_interface, only: read_attribute, get_shape, read_dataset, &
|
||||
open_dataset, close_dataset, HID_T, HSIZE_T
|
||||
use random_lcg, only: prn
|
||||
|
||||
implicit none
|
||||
private
|
||||
|
||||
!===============================================================================
|
||||
! ANGLEDISTRIBUTION represents an angular distribution that is to be used in an
|
||||
! uncorrelated angle-energy distribution. This occurs whenever the angle
|
||||
! distrbution is given in File 4 in an ENDF file. The distribution of angles
|
||||
! depends on the incoming energy of the neutron, so this type stores a
|
||||
! distribution for each of a set of incoming energies.
|
||||
!===============================================================================
|
||||
|
||||
type, public :: AngleDistribution
|
||||
real(8), allocatable :: energy(:)
|
||||
type(DistributionContainer), allocatable :: distribution(:)
|
||||
contains
|
||||
procedure :: sample => angle_sample
|
||||
procedure :: from_hdf5 => angle_from_hdf5
|
||||
end type AngleDistribution
|
||||
|
||||
contains
|
||||
|
||||
function angle_sample(this, E) result(mu)
|
||||
class(AngleDistribution), intent(in) :: this
|
||||
real(8), intent(in) :: E ! incoming energy
|
||||
real(8) :: mu ! sampled cosine of scattering angle
|
||||
|
||||
integer :: i ! index on incoming energy grid
|
||||
integer :: n ! number of incoming energies
|
||||
real(8) :: r ! interpolation factor on incoming energy grid
|
||||
|
||||
! Determine number of incoming energies
|
||||
n = size(this%energy)
|
||||
|
||||
! Find energy bin and calculate interpolation factor -- if the energy is
|
||||
! outside the range of the tabulated energies, choose the first or last bins
|
||||
if (E < this%energy(1)) then
|
||||
i = 1
|
||||
r = ZERO
|
||||
elseif (E > this%energy(n)) then
|
||||
i = n - 1
|
||||
r = ONE
|
||||
else
|
||||
i = binary_search(this%energy, n, E)
|
||||
r = (E - this%energy(i))/(this%energy(i+1) - this%energy(i))
|
||||
end if
|
||||
|
||||
! Sample between the ith and (i+1)th bin
|
||||
if (r > prn()) i = i + 1
|
||||
|
||||
! Sample i-th distribution
|
||||
mu = this%distribution(i)%obj%sample()
|
||||
|
||||
! Make sure mu is in range [-1,1]
|
||||
if (abs(mu) > ONE) mu = sign(ONE, mu)
|
||||
end function angle_sample
|
||||
|
||||
subroutine angle_from_hdf5(this, group_id)
|
||||
class(AngleDistribution), intent(inout) :: this
|
||||
integer(HID_T), intent(in) :: group_id
|
||||
|
||||
integer :: i, j
|
||||
integer :: n
|
||||
integer :: n_energy
|
||||
integer(HID_T) :: dset_id
|
||||
integer(HSIZE_T) :: dims(1), dims2(2)
|
||||
integer, allocatable :: offsets(:)
|
||||
integer, allocatable :: interp(:)
|
||||
real(8), allocatable :: temp(:,:)
|
||||
|
||||
! Get incoming energies
|
||||
dset_id = open_dataset(group_id, 'energy')
|
||||
call get_shape(dset_id, dims)
|
||||
n_energy = int(dims(1), 4)
|
||||
allocate(this % energy(n_energy))
|
||||
allocate(this % distribution(n_energy))
|
||||
call read_dataset(this % energy, dset_id)
|
||||
call close_dataset(dset_id)
|
||||
|
||||
! Get outgoing energy distribution data
|
||||
dset_id = open_dataset(group_id, 'mu')
|
||||
call read_attribute(offsets, dset_id, 'offsets')
|
||||
call read_attribute(interp, dset_id, 'interpolation')
|
||||
call get_shape(dset_id, dims2)
|
||||
allocate(temp(dims2(1), dims2(2)))
|
||||
call read_dataset(temp, dset_id)
|
||||
call close_dataset(dset_id)
|
||||
|
||||
do i = 1, n_energy
|
||||
! Determine number of outgoing energies
|
||||
j = offsets(i)
|
||||
if (i < n_energy) then
|
||||
n = offsets(i+1) - j
|
||||
else
|
||||
n = size(temp, 1) - j
|
||||
end if
|
||||
|
||||
! Create and initialize tabular distribution
|
||||
allocate(Tabular :: this % distribution(i) % obj)
|
||||
select type (mudist => this % distribution(i) % obj)
|
||||
type is (Tabular)
|
||||
mudist % interpolation = interp(i)
|
||||
allocate(mudist % x(n), mudist % p(n), mudist % c(n))
|
||||
mudist % x(:) = temp(j+1:j+n, 1)
|
||||
mudist % p(:) = temp(j+1:j+n, 2)
|
||||
|
||||
! To get answers that match ACE data, for now we still use the tabulated
|
||||
! CDF values that were passed through to the HDF5 library. At a later
|
||||
! time, we can remove the CDF values from the HDF5 library and
|
||||
! reconstruct them using the PDF
|
||||
if (.true.) then
|
||||
mudist % c(:) = temp(j+1:j+n, 3)
|
||||
else
|
||||
call mudist % initialize(temp(j+1:j+n, 1), temp(j+1:j+n, 2), interp(i))
|
||||
end if
|
||||
end select
|
||||
|
||||
j = j + n
|
||||
end do
|
||||
end subroutine angle_from_hdf5
|
||||
|
||||
end module angle_distribution
|
||||
21
src/angle_energy.h
Normal file
21
src/angle_energy.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef OPENMC_ANGLE_ENERGY_H
|
||||
#define OPENMC_ANGLE_ENERGY_H
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
//! Abstract type that defines a correlated or uncorrelated angle-energy
|
||||
//! distribution that is a function of incoming energy. Each derived type must
|
||||
//! implement a sample() method that returns an outgoing energy and
|
||||
//! scattering cosine given an incoming energy.
|
||||
//==============================================================================
|
||||
|
||||
class AngleEnergy {
|
||||
public:
|
||||
virtual void sample(double E_in, double& E_out, double& mu) const = 0;
|
||||
virtual ~AngleEnergy() = default;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // OPENMC_ANGLE_ENERGY_H
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
#include "cell.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
|
|
@ -19,14 +18,13 @@ namespace openmc {
|
|||
// Constants
|
||||
//==============================================================================
|
||||
|
||||
// TODO: Convert to enum
|
||||
constexpr int32_t OP_LEFT_PAREN {std::numeric_limits<int32_t>::max()};
|
||||
constexpr int32_t OP_RIGHT_PAREN {std::numeric_limits<int32_t>::max() - 1};
|
||||
constexpr int32_t OP_COMPLEMENT {std::numeric_limits<int32_t>::max() - 2};
|
||||
constexpr int32_t OP_INTERSECTION {std::numeric_limits<int32_t>::max() - 3};
|
||||
constexpr int32_t OP_UNION {std::numeric_limits<int32_t>::max() - 4};
|
||||
|
||||
extern "C" double FP_PRECISION;
|
||||
|
||||
//==============================================================================
|
||||
// Global variables
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#define OPENMC_CELL_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
|
@ -18,6 +19,7 @@ namespace openmc {
|
|||
// Constants
|
||||
//==============================================================================
|
||||
|
||||
// TODO: Convert to enum
|
||||
extern "C" int FILL_MATERIAL;
|
||||
extern "C" int FILL_UNIVERSE;
|
||||
extern "C" int FILL_LATTICE;
|
||||
|
|
|
|||
|
|
@ -131,34 +131,6 @@ module constants
|
|||
! Void material
|
||||
integer, parameter :: MATERIAL_VOID = -1
|
||||
|
||||
! Lattice types
|
||||
integer, parameter :: &
|
||||
LATTICE_RECT = 1, & ! Rectangular lattice
|
||||
LATTICE_HEX = 2 ! Hexagonal lattice
|
||||
|
||||
! Lattice boundary crossings
|
||||
integer, parameter :: &
|
||||
LATTICE_LEFT = 1, & ! Flag for crossing left (x) lattice boundary
|
||||
LATTICE_RIGHT = 2, & ! Flag for crossing right (x) lattice boundary
|
||||
LATTICE_BACK = 3, & ! Flag for crossing back (y) lattice boundary
|
||||
LATTICE_FRONT = 4, & ! Flag for crossing front (y) lattice boundary
|
||||
LATTICE_BOTTOM = 5, & ! Flag for crossing bottom (z) lattice boundary
|
||||
LATTICE_TOP = 6 ! Flag for crossing top (z) lattice boundary
|
||||
|
||||
! Surface types
|
||||
integer, parameter :: &
|
||||
SURF_PX = 1, & ! Plane parallel to x-plane
|
||||
SURF_PY = 2, & ! Plane parallel to y-plane
|
||||
SURF_PZ = 3, & ! Plane parallel to z-plane
|
||||
SURF_PLANE = 4, & ! Arbitrary plane
|
||||
SURF_CYL_X = 5, & ! Cylinder along x-axis
|
||||
SURF_CYL_Y = 6, & ! Cylinder along y-axis
|
||||
SURF_CYL_Z = 7, & ! Cylinder along z-axis
|
||||
SURF_SPHERE = 8, & ! Sphere
|
||||
SURF_CONE_X = 9, & ! Cone parallel to x-axis
|
||||
SURF_CONE_Y = 10, & ! Cone parallel to y-axis
|
||||
SURF_CONE_Z = 11 ! Cone parallel to z-axis
|
||||
|
||||
! Flag to say that the outside of a lattice is not defined
|
||||
integer, parameter :: NO_OUTER_UNIVERSE = -1
|
||||
|
||||
|
|
@ -238,12 +210,6 @@ module constants
|
|||
! Depletion reactions
|
||||
integer, parameter :: DEPLETION_RX(6) = [N_GAMMA, N_P, N_A, N_2N, N_3N, N_4N]
|
||||
|
||||
! ACE table types
|
||||
integer, parameter :: &
|
||||
ACE_NEUTRON = 1, & ! continuous-energy neutron
|
||||
ACE_THERMAL = 2, & ! thermal S(a,b) scattering data
|
||||
ACE_DOSIMETRY = 3 ! dosimetry cross sections
|
||||
|
||||
! MGXS Table Types
|
||||
integer, parameter :: &
|
||||
MGXS_ISOTROPIC = 1, & ! Isotropically Weighted Data
|
||||
|
|
@ -265,11 +231,6 @@ module constants
|
|||
EMISSION_DELAYED = 2, & ! Delayed emission of secondary particle
|
||||
EMISSION_TOTAL = 3 ! Yield represents total emission (prompt + delayed)
|
||||
|
||||
! Cross section filetypes
|
||||
integer, parameter :: &
|
||||
ASCII = 1, & ! ASCII cross section file
|
||||
BINARY = 2 ! Binary cross section file
|
||||
|
||||
! Library types
|
||||
integer, parameter :: &
|
||||
LIBRARY_NEUTRON = 1, &
|
||||
|
|
@ -350,9 +311,6 @@ module constants
|
|||
SCORE_FISS_Q_RECOV = -15, & ! recoverable fission Q-value
|
||||
SCORE_DECAY_RATE = -16 ! delayed neutron precursor decay rate
|
||||
|
||||
! Maximum scattering order supported
|
||||
integer, parameter :: MAX_ANG_ORDER = 10
|
||||
|
||||
! Tally map bin finding
|
||||
integer, parameter :: NO_BIN_FOUND = -1
|
||||
|
||||
|
|
|
|||
402
src/constants.h
402
src/constants.h
|
|
@ -1,8 +1,8 @@
|
|||
//! \file constants.h
|
||||
//! A collection of constants
|
||||
|
||||
#ifndef CONSTANTS_H
|
||||
#define CONSTANTS_H
|
||||
#ifndef OPENMC_CONSTANTS_H
|
||||
#define OPENMC_CONSTANTS_H
|
||||
|
||||
#include <cmath>
|
||||
#include <array>
|
||||
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
namespace openmc {
|
||||
|
||||
// TODO: Replace with xtensor/other library?
|
||||
typedef std::vector<double> double_1dvec;
|
||||
typedef std::vector<std::vector<double> > double_2dvec;
|
||||
typedef std::vector<std::vector<std::vector<double> > > double_3dvec;
|
||||
|
|
@ -21,29 +22,283 @@ typedef std::vector<int> int_1dvec;
|
|||
typedef std::vector<std::vector<int> > int_2dvec;
|
||||
typedef std::vector<std::vector<std::vector<int> > > int_3dvec;
|
||||
|
||||
constexpr int MAX_SAMPLE {10000};
|
||||
// ============================================================================
|
||||
// VERSIONING NUMBERS
|
||||
|
||||
constexpr std::array<int, 3> VERSION {0, 10, 0};
|
||||
// OpenMC major, minor, and release numbers
|
||||
constexpr int VERSION_MAJOR {0};
|
||||
constexpr int VERSION_MINOR {10};
|
||||
constexpr int VERSION_RELEASE {0};
|
||||
constexpr std::array<int, 3> VERSION {VERSION_MAJOR, VERSION_MINOR, VERSION_RELEASE};
|
||||
|
||||
// HDF5 data format
|
||||
constexpr int HDF5_VERSION[] {1, 0};
|
||||
|
||||
// Version numbers for binary files
|
||||
constexpr std::array<int, 2> VERSION_PARTICLE_RESTART {2, 0};
|
||||
constexpr std::array<int, 2> VERSION_TRACK {2, 0};
|
||||
constexpr std::array<int, 2> VERSION_SUMMARY {6, 0};
|
||||
constexpr std::array<int, 2> VERSION_VOLUME {1, 0};
|
||||
constexpr std::array<int, 2> VERSION_VOXEL {1, 0};
|
||||
constexpr std::array<int, 2> VERSION_MGXS_LIBRARY {1, 0};
|
||||
constexpr char VERSION_MULTIPOLE[] {"v0.2"};
|
||||
|
||||
// ============================================================================
|
||||
// ADJUSTABLE PARAMETERS
|
||||
|
||||
// NOTE: This is the only section of the constants module that should ever be
|
||||
// adjusted. Modifying constants in other sections may cause the code to fail.
|
||||
|
||||
// Monoatomic ideal-gas scattering treatment threshold
|
||||
constexpr double FREE_GAS_THRESHOLD {400.0};
|
||||
|
||||
// Significance level for confidence intervals
|
||||
constexpr double CONFIDENCE_LEVEL {0.95};
|
||||
|
||||
// Used for surface current tallies
|
||||
constexpr double TINY_BIT {1e-8};
|
||||
|
||||
// User for precision in geometry
|
||||
constexpr double FP_PRECISION {1e-14};
|
||||
constexpr double FP_REL_PRECISION {1e-5};
|
||||
constexpr double FP_COINCIDENT {1e-12};
|
||||
|
||||
// Maximum number of collisions/crossings
|
||||
constexpr int MAX_EVENTS {1000000};
|
||||
constexpr int MAX_SAMPLE {100000};
|
||||
|
||||
// Maximum number of words in a single line, length of line, and length of
|
||||
// single word
|
||||
constexpr int MAX_WORDS {500};
|
||||
constexpr int MAX_LINE_LEN {250};
|
||||
constexpr int MAX_WORD_LEN {150};
|
||||
constexpr int MAX_FILE_LEN {255};
|
||||
|
||||
// Physical Constants
|
||||
constexpr double K_BOLTZMANN {8.6173303e-5}; // Boltzmann constant in eV/K
|
||||
// Maximum number of external source spatial resamples to encounter before an
|
||||
// error is thrown.
|
||||
constexpr int EXTSRC_REJECT_THRESHOLD {10000};
|
||||
constexpr double EXTSRC_REJECT_FRACTION {0.05};
|
||||
|
||||
// ============================================================================
|
||||
// MATH AND PHYSICAL CONSTANTS
|
||||
|
||||
// Values here are from the Committee on Data for Science and Technology
|
||||
// (CODATA) 2014 recommendation (doi:10.1103/RevModPhys.88.035009).
|
||||
|
||||
// TODO: cmath::M_PI has 3 more digits precision than the Fortran constant we
|
||||
// use so for now we will reuse the Fortran constant until we are OK with
|
||||
// modifying test results
|
||||
constexpr double PI {3.1415926535898};
|
||||
const double SQRT_PI {std::sqrt(PI)};
|
||||
constexpr double INFTY {std::numeric_limits<double>::max()};
|
||||
|
||||
// Physical constants
|
||||
constexpr double MASS_NEUTRON {1.00866491588}; // mass of a neutron in amu
|
||||
constexpr double MASS_NEUTRON_EV {939.5654133e6}; // mass of a neutron in eV/c^2
|
||||
constexpr double MASS_PROTON {1.007276466879}; // mass of a proton in amu
|
||||
constexpr double MASS_ELECTRON_EV {0.5109989461e6}; // electron mass energy equivalent in eV/c^2
|
||||
constexpr double FINE_STRUCTURE {137.035999139}; // inverse fine structure constant
|
||||
constexpr double PLANCK_C {1.2398419739062977e4}; // Planck's constant times c in eV-Angstroms
|
||||
constexpr double AMU {1.660539040e-27}; // 1 amu in kg
|
||||
constexpr double C_LIGHT {2.99792458e8}; // speed of light in m/s
|
||||
constexpr double N_AVOGADRO {0.6022140857}; // Avogadro's number in 10^24/mol
|
||||
constexpr double K_BOLTZMANN {8.6173303e-5}; // Boltzmann constant in eV/K
|
||||
|
||||
// Electron subshell labels
|
||||
constexpr char SUBSHELLS[][4] {
|
||||
"K ", "L1 ", "L2 ", "L3 ", "M1 ", "M2 ", "M3 ", "M4 ", "M5 ",
|
||||
"N1 ", "N2 ", "N3 ", "N4 ", "N5 ", "N6 ", "N7 ", "O1 ", "O2 ",
|
||||
"O3 ", "O4 ", "O5 ", "O6 ", "O7 ", "O8 ", "O9 ", "P1 ", "P2 ",
|
||||
"P3 ", "P4 ", "P5 ", "P6 ", "P7 ", "P8 ", "P9 ", "P10", "P11",
|
||||
"Q1 ", "Q2 ", "Q3 "
|
||||
};
|
||||
|
||||
// Void material
|
||||
// TODO: refactor and remove
|
||||
constexpr int MATERIAL_VOID {-1};
|
||||
|
||||
// ============================================================================
|
||||
// CROSS SECTION RELATED CONSTANTS
|
||||
|
||||
// Angular distribution type
|
||||
// TODO: Convert to enum
|
||||
constexpr int ANGLE_ISOTROPIC {1};
|
||||
constexpr int ANGLE_32_EQUI {2};
|
||||
constexpr int ANGLE_TABULAR {3};
|
||||
constexpr int ANGLE_LEGENDRE {4};
|
||||
constexpr int ANGLE_HISTOGRAM {5};
|
||||
|
||||
// Temperature treatment method
|
||||
// TODO: Convert to enum?
|
||||
constexpr int TEMPERATURE_NEAREST {1};
|
||||
constexpr int TEMPERATURE_INTERPOLATION {2};
|
||||
|
||||
// Secondary energy mode for S(a,b) inelastic scattering
|
||||
// TODO: Convert to enum
|
||||
constexpr int SAB_SECONDARY_EQUAL {0}; // Equally-likely outgoing energy bins
|
||||
constexpr int SAB_SECONDARY_SKEWED {1}; // Skewed outgoing energy bins
|
||||
constexpr int SAB_SECONDARY_CONT {2}; // Continuous, linear-linear interpolation
|
||||
|
||||
// Elastic mode for S(a,b) elastic scattering
|
||||
// TODO: Convert to enum
|
||||
constexpr int SAB_ELASTIC_DISCRETE {3}; // Sample from discrete cosines
|
||||
constexpr int SAB_ELASTIC_EXACT {4}; // Exact treatment for coherent elastic
|
||||
|
||||
// Reaction types
|
||||
// TODO: Convert to enum
|
||||
constexpr int TOTAL_XS {1};
|
||||
constexpr int ELASTIC {2};
|
||||
constexpr int N_NONELASTIC {3};
|
||||
constexpr int N_LEVEL {4};
|
||||
constexpr int MISC {5};
|
||||
constexpr int N_2ND {11};
|
||||
constexpr int N_2N {16};
|
||||
constexpr int N_3N {17};
|
||||
constexpr int N_FISSION {18};
|
||||
constexpr int N_F {19};
|
||||
constexpr int N_NF {20};
|
||||
constexpr int N_2NF {21};
|
||||
constexpr int N_NA {22};
|
||||
constexpr int N_N3A {23};
|
||||
constexpr int N_2NA {24};
|
||||
constexpr int N_3NA {25};
|
||||
constexpr int N_NP {28};
|
||||
constexpr int N_N2A {29};
|
||||
constexpr int N_2N2A {30};
|
||||
constexpr int N_ND {32};
|
||||
constexpr int N_NT {33};
|
||||
constexpr int N_N3HE {34};
|
||||
constexpr int N_ND2A {35};
|
||||
constexpr int N_NT2A {36};
|
||||
constexpr int N_4N {37};
|
||||
constexpr int N_3NF {38};
|
||||
constexpr int N_2NP {41};
|
||||
constexpr int N_3NP {42};
|
||||
constexpr int N_N2P {44};
|
||||
constexpr int N_NPA {45};
|
||||
constexpr int N_N1 {51};
|
||||
constexpr int N_N40 {90};
|
||||
constexpr int N_NC {91};
|
||||
constexpr int N_DISAPPEAR {101};
|
||||
constexpr int N_GAMMA {102};
|
||||
constexpr int N_P {103};
|
||||
constexpr int N_D {104};
|
||||
constexpr int N_T {105};
|
||||
constexpr int N_3HE {106};
|
||||
constexpr int N_A {107};
|
||||
constexpr int N_2A {108};
|
||||
constexpr int N_3A {109};
|
||||
constexpr int N_2P {111};
|
||||
constexpr int N_PA {112};
|
||||
constexpr int N_T2A {113};
|
||||
constexpr int N_D2A {114};
|
||||
constexpr int N_PD {115};
|
||||
constexpr int N_PT {116};
|
||||
constexpr int N_DA {117};
|
||||
constexpr int N_5N {152};
|
||||
constexpr int N_6N {153};
|
||||
constexpr int N_2NT {154};
|
||||
constexpr int N_TA {155};
|
||||
constexpr int N_4NP {156};
|
||||
constexpr int N_3ND {157};
|
||||
constexpr int N_NDA {158};
|
||||
constexpr int N_2NPA {159};
|
||||
constexpr int N_7N {160};
|
||||
constexpr int N_8N {161};
|
||||
constexpr int N_5NP {162};
|
||||
constexpr int N_6NP {163};
|
||||
constexpr int N_7NP {164};
|
||||
constexpr int N_4NA {165};
|
||||
constexpr int N_5NA {166};
|
||||
constexpr int N_6NA {167};
|
||||
constexpr int N_7NA {168};
|
||||
constexpr int N_4ND {169};
|
||||
constexpr int N_5ND {170};
|
||||
constexpr int N_6ND {171};
|
||||
constexpr int N_3NT {172};
|
||||
constexpr int N_4NT {173};
|
||||
constexpr int N_5NT {174};
|
||||
constexpr int N_6NT {175};
|
||||
constexpr int N_2N3HE {176};
|
||||
constexpr int N_3N3HE {177};
|
||||
constexpr int N_4N3HE {178};
|
||||
constexpr int N_3N2P {179};
|
||||
constexpr int N_3N3A {180};
|
||||
constexpr int N_3NPA {181};
|
||||
constexpr int N_DT {182};
|
||||
constexpr int N_NPD {183};
|
||||
constexpr int N_NPT {184};
|
||||
constexpr int N_NDT {185};
|
||||
constexpr int N_NP3HE {186};
|
||||
constexpr int N_ND3HE {187};
|
||||
constexpr int N_NT3HE {188};
|
||||
constexpr int N_NTA {189};
|
||||
constexpr int N_2N2P {190};
|
||||
constexpr int N_P3HE {191};
|
||||
constexpr int N_D3HE {192};
|
||||
constexpr int N_3HEA {193};
|
||||
constexpr int N_4N2P {194};
|
||||
constexpr int N_4N2A {195};
|
||||
constexpr int N_4NPA {196};
|
||||
constexpr int N_3P {197};
|
||||
constexpr int N_N3P {198};
|
||||
constexpr int N_3N2PA {199};
|
||||
constexpr int N_5N2P {200};
|
||||
constexpr int COHERENT {502};
|
||||
constexpr int INCOHERENT {504};
|
||||
constexpr int PAIR_PROD_ELEC {515};
|
||||
constexpr int PAIR_PROD {516};
|
||||
constexpr int PAIR_PROD_NUC {517};
|
||||
constexpr int PHOTOELECTRIC {522};
|
||||
constexpr int N_P0 {600};
|
||||
constexpr int N_PC {649};
|
||||
constexpr int N_D0 {650};
|
||||
constexpr int N_DC {699};
|
||||
constexpr int N_T0 {700};
|
||||
constexpr int N_TC {749};
|
||||
constexpr int N_3HE0 {750};
|
||||
constexpr int N_3HEC {799};
|
||||
constexpr int N_A0 {800};
|
||||
constexpr int N_AC {849};
|
||||
constexpr int N_2N0 {875};
|
||||
constexpr int N_2NC {891};
|
||||
|
||||
// Fission neutron emission (nu) type
|
||||
constexpr int NU_NONE {0}; // No nu values (non-fissionable)
|
||||
constexpr int NU_POLYNOMIAL {1}; // Nu values given by polynomial
|
||||
constexpr int NU_TABULAR {2}; // Nu values given by tabular distribution
|
||||
|
||||
// Library types
|
||||
constexpr int LIBRARY_NEUTRON {1};
|
||||
constexpr int LIBRARY_THERMAL {2};
|
||||
constexpr int LIBRARY_PHOTON {3};
|
||||
constexpr int LIBRARY_MULTIGROUP {4};
|
||||
|
||||
// Probability table parameters
|
||||
constexpr int URR_CUM_PROB {1};
|
||||
constexpr int URR_TOTAL {2};
|
||||
constexpr int URR_ELASTIC {3};
|
||||
constexpr int URR_FISSION {4};
|
||||
constexpr int URR_N_GAMMA {5};
|
||||
constexpr int URR_HEATING {6};
|
||||
|
||||
// Maximum number of partial fission reactions
|
||||
constexpr int PARTIAL_FISSION_MAX {4};
|
||||
|
||||
// Resonance elastic scattering methods
|
||||
// TODO: Convert to enum
|
||||
constexpr int RES_SCAT_ARES {1};
|
||||
constexpr int RES_SCAT_DBRC {2};
|
||||
constexpr int RES_SCAT_WCM {3};
|
||||
constexpr int RES_SCAT_CXS {4};
|
||||
|
||||
// Electron treatments
|
||||
// TODO: Convert to enum
|
||||
constexpr int ELECTRON_LED {1}; // Local Energy Deposition
|
||||
constexpr int ELECTRON_TTB {2}; // Thick Target Bremsstrahlung
|
||||
|
||||
// ============================================================================
|
||||
// MULTIGROUP RELATED
|
||||
|
||||
// MGXS Table Types
|
||||
// TODO: Convert to enum
|
||||
constexpr int MGXS_ISOTROPIC {1}; // Isotroically weighted data
|
||||
constexpr int MGXS_ANGLE {2}; // Data by angular bins
|
||||
|
||||
|
|
@ -53,18 +308,8 @@ constexpr double MACROSCOPIC_AWR {-2.};
|
|||
// Number of mu bins to use when converting Legendres to tabular type
|
||||
constexpr int DEFAULT_NMU {33};
|
||||
|
||||
// Temperature treatment method
|
||||
constexpr int TEMPERATURE_NEAREST {1};
|
||||
constexpr int TEMPERATURE_INTERPOLATION {2};
|
||||
|
||||
// TODO: cmath::M_PI has 3 more digits precision than the Fortran constant we
|
||||
// use so for now we will reuse the Fortran constant until we are OK with
|
||||
// modifying test results
|
||||
constexpr double PI {3.1415926535898};
|
||||
|
||||
const double SQRT_PI {std::sqrt(PI)};
|
||||
|
||||
// Mgxs::get_xs enumerated types
|
||||
// TODO: Convert to enum
|
||||
constexpr int MG_GET_XS_TOTAL {0};
|
||||
constexpr int MG_GET_XS_ABSORPTION {1};
|
||||
constexpr int MG_GET_XS_INVERSE_VELOCITY {2};
|
||||
|
|
@ -81,11 +326,120 @@ constexpr int MG_GET_XS_NU_FISSION {12};
|
|||
constexpr int MG_GET_XS_CHI_PROMPT {13};
|
||||
constexpr int MG_GET_XS_CHI_DELAYED {14};
|
||||
|
||||
extern "C" double FP_COINCIDENT;
|
||||
extern "C" double FP_PRECISION;
|
||||
constexpr double INFTY {std::numeric_limits<double>::max()};
|
||||
// ============================================================================
|
||||
// TALLY-RELATED CONSTANTS
|
||||
|
||||
// Tally result entries
|
||||
constexpr int RESULT_VALUE {1};
|
||||
constexpr int RESULT_SUM {2};
|
||||
constexpr int RESULT_SUM_SQ {3};
|
||||
|
||||
// Tally type
|
||||
// TODO: Convert to enum
|
||||
constexpr int TALLY_VOLUME {1};
|
||||
constexpr int TALLY_MESH_SURFACE {2};
|
||||
constexpr int TALLY_SURFACE {3};
|
||||
|
||||
// Tally estimator types
|
||||
// TODO: Convert to enum
|
||||
constexpr int ESTIMATOR_ANALOG {1};
|
||||
constexpr int ESTIMATOR_TRACKLENGTH {2};
|
||||
constexpr int ESTIMATOR_COLLISION {3};
|
||||
|
||||
// Event types for tallies
|
||||
// TODO: Convert to enum
|
||||
constexpr int EVENT_SURFACE {-2};
|
||||
constexpr int EVENT_LATTICE {-1};
|
||||
constexpr int EVENT_SCATTER {1};
|
||||
constexpr int EVENT_ABSORB {2};
|
||||
|
||||
// Tally score type -- if you change these, make sure you also update the
|
||||
// _SCORES dictionary in openmc/capi/tally.py
|
||||
// TODO: Convert to enum
|
||||
constexpr int SCORE_FLUX {-1}; // flux
|
||||
constexpr int SCORE_TOTAL {-2}; // total reaction rate
|
||||
constexpr int SCORE_SCATTER {-3}; // scattering rate
|
||||
constexpr int SCORE_NU_SCATTER {-4}; // scattering production rate
|
||||
constexpr int SCORE_ABSORPTION {-5}; // absorption rate
|
||||
constexpr int SCORE_FISSION {-6}; // fission rate
|
||||
constexpr int SCORE_NU_FISSION {-7}; // neutron production rate
|
||||
constexpr int SCORE_KAPPA_FISSION {-8}; // fission energy production rate
|
||||
constexpr int SCORE_CURRENT {-9}; // current
|
||||
constexpr int SCORE_EVENTS {-10}; // number of events
|
||||
constexpr int SCORE_DELAYED_NU_FISSION {-11}; // delayed neutron production rate
|
||||
constexpr int SCORE_PROMPT_NU_FISSION {-12}; // prompt neutron production rate
|
||||
constexpr int SCORE_INVERSE_VELOCITY {-13}; // flux-weighted inverse velocity
|
||||
constexpr int SCORE_FISS_Q_PROMPT {-14}; // prompt fission Q-value
|
||||
constexpr int SCORE_FISS_Q_RECOV {-15}; // recoverable fission Q-value
|
||||
constexpr int SCORE_DECAY_RATE {-16}; // delayed neutron precursor decay rate
|
||||
|
||||
// Tally map bin finding
|
||||
constexpr int NO_BIN_FOUND {-1};
|
||||
|
||||
// Tally filter and map types
|
||||
// TODO: Refactor to remove or convert to enum
|
||||
constexpr int FILTER_UNIVERSE {1};
|
||||
constexpr int FILTER_MATERIAL {2};
|
||||
constexpr int FILTER_CELL {3};
|
||||
constexpr int FILTER_CELLBORN {4};
|
||||
constexpr int FILTER_SURFACE {5};
|
||||
constexpr int FILTER_MESH {6};
|
||||
constexpr int FILTER_ENERGYIN {7};
|
||||
constexpr int FILTER_ENERGYOUT {8};
|
||||
constexpr int FILTER_DISTRIBCELL {9};
|
||||
constexpr int FILTER_MU {10};
|
||||
constexpr int FILTER_POLAR {11};
|
||||
constexpr int FILTER_AZIMUTHAL {12};
|
||||
constexpr int FILTER_DELAYEDGROUP {13};
|
||||
constexpr int FILTER_ENERGYFUNCTION {14};
|
||||
constexpr int FILTER_CELLFROM {15};
|
||||
constexpr int FILTER_MESHSURFACE {16};
|
||||
constexpr int FILTER_LEGENDRE {17};
|
||||
constexpr int FILTER_SPH_HARMONICS {18};
|
||||
constexpr int FILTER_SPTL_LEGENDRE {19};
|
||||
constexpr int FILTER_ZERNIKE {20};
|
||||
constexpr int FILTER_PARTICLE {21};
|
||||
|
||||
// Mesh types
|
||||
constexpr int MESH_REGULAR {1};
|
||||
|
||||
// Tally surface current directions
|
||||
constexpr int OUT_LEFT {1}; // x min
|
||||
constexpr int IN_LEFT {2}; // x min
|
||||
constexpr int OUT_RIGHT {3}; // x max
|
||||
constexpr int IN_RIGHT {4}; // x max
|
||||
constexpr int OUT_BACK {5}; // y min
|
||||
constexpr int IN_BACK {6}; // y min
|
||||
constexpr int OUT_FRONT {7}; // y max
|
||||
constexpr int IN_FRONT {8}; // y max
|
||||
constexpr int OUT_BOTTOM {9}; // z min
|
||||
constexpr int IN_BOTTOM {10}; // z min
|
||||
constexpr int OUT_TOP {11}; // z max
|
||||
constexpr int IN_TOP {12}; // z max
|
||||
|
||||
// Tally trigger types and threshold
|
||||
constexpr int VARIANCE {1};
|
||||
constexpr int RELATIVE_ERROR {2};
|
||||
constexpr int STANDARD_DEVIATION {3};
|
||||
|
||||
// Global tally parameters
|
||||
constexpr int K_COLLISION {1};
|
||||
constexpr int K_ABSORPTION {2};
|
||||
constexpr int K_TRACKLENGTH {3};
|
||||
constexpr int LEAKAGE {4};
|
||||
|
||||
// Differential tally independent variables
|
||||
constexpr int DIFF_DENSITY {1};
|
||||
constexpr int DIFF_NUCLIDE_DENSITY {2};
|
||||
constexpr int DIFF_TEMPERATURE {3};
|
||||
|
||||
constexpr int C_NONE {-1};
|
||||
|
||||
// Interpolation rules
|
||||
enum class Interpolation {
|
||||
histogram, lin_lin, lin_log, log_lin, log_log
|
||||
};
|
||||
|
||||
} // namespace openmc
|
||||
|
||||
#endif // CONSTANTS_H
|
||||
#endif // OPENMC_CONSTANTS_H
|
||||
|
|
|
|||
266
src/distribution.cpp
Normal file
266
src/distribution.cpp
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
#include "distribution.h"
|
||||
|
||||
#include <algorithm> // for copy
|
||||
#include <cmath> // for sqrt, floor, max
|
||||
#include <iterator> // for back_inserter
|
||||
#include <numeric> // for accumulate
|
||||
#include <string> // for string, stod
|
||||
|
||||
#include "error.h"
|
||||
#include "math_functions.h"
|
||||
#include "random_lcg.h"
|
||||
#include "xml_interface.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
// Discrete implementation
|
||||
//==============================================================================
|
||||
|
||||
Discrete::Discrete(pugi::xml_node node)
|
||||
{
|
||||
auto params = get_node_array<double>(node, "parameters");
|
||||
|
||||
std::size_t n = params.size();
|
||||
std::copy(params.begin(), params.begin() + n/2, std::back_inserter(x_));
|
||||
std::copy(params.begin() + n/2, params.end(), std::back_inserter(p_));
|
||||
|
||||
normalize();
|
||||
}
|
||||
|
||||
Discrete::Discrete(const double* x, const double* p, int n)
|
||||
: x_{x, x+n}, p_{p, p+n}
|
||||
{
|
||||
normalize();
|
||||
}
|
||||
|
||||
double Discrete::sample() const
|
||||
{
|
||||
int n = x_.size();
|
||||
if (n > 1) {
|
||||
double xi = prn();
|
||||
double c = 0.0;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
c += p_[i];
|
||||
if (xi < c) return x_[i];
|
||||
}
|
||||
// throw exception?
|
||||
} else {
|
||||
return x_[0];
|
||||
}
|
||||
}
|
||||
|
||||
void Discrete::normalize()
|
||||
{
|
||||
// Renormalize density function so that it sums to unity
|
||||
double norm = std::accumulate(p_.begin(), p_.end(), 0.0);
|
||||
for (auto& p_i : p_)
|
||||
p_i /= norm;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// Uniform implementation
|
||||
//==============================================================================
|
||||
|
||||
Uniform::Uniform(pugi::xml_node node)
|
||||
{
|
||||
auto params = get_node_array<double>(node, "parameters");
|
||||
if (params.size() != 2)
|
||||
openmc::fatal_error("Uniform distribution must have two "
|
||||
"parameters specified.");
|
||||
|
||||
a_ = params.at(0);
|
||||
b_ = params.at(1);
|
||||
}
|
||||
|
||||
double Uniform::sample() const
|
||||
{
|
||||
return a_ + prn()*(b_ - a_);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// Maxwell implementation
|
||||
//==============================================================================
|
||||
|
||||
Maxwell::Maxwell(pugi::xml_node node)
|
||||
{
|
||||
theta_ = std::stod(get_node_value(node, "parameters"));
|
||||
}
|
||||
|
||||
double Maxwell::sample() const
|
||||
{
|
||||
return maxwell_spectrum_c(theta_);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// Watt implementation
|
||||
//==============================================================================
|
||||
|
||||
Watt::Watt(pugi::xml_node node)
|
||||
{
|
||||
auto params = get_node_array<double>(node, "parameters");
|
||||
if (params.size() != 2)
|
||||
openmc::fatal_error("Watt energy distribution must have two "
|
||||
"parameters specified.");
|
||||
|
||||
a_ = params.at(0);
|
||||
b_ = params.at(1);
|
||||
}
|
||||
|
||||
double Watt::sample() const
|
||||
{
|
||||
return watt_spectrum_c(a_, b_);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// Tabular implementation
|
||||
//==============================================================================
|
||||
|
||||
Tabular::Tabular(pugi::xml_node node)
|
||||
{
|
||||
if (check_for_node(node, "interpolation")) {
|
||||
std::string temp = get_node_value(node, "interpolation");
|
||||
if (temp == "histogram") {
|
||||
interp_ = Interpolation::histogram;
|
||||
} else if (temp == "linear-linear") {
|
||||
interp_ = Interpolation::lin_lin;
|
||||
} else {
|
||||
openmc::fatal_error("Unknown interpolation type for distribution: " + temp);
|
||||
}
|
||||
} else {
|
||||
interp_ = Interpolation::histogram;
|
||||
}
|
||||
|
||||
// Read and initialize tabular distribution
|
||||
auto params = get_node_array<double>(node, "parameters");
|
||||
std::size_t n = params.size() / 2;
|
||||
const double* x = params.data();
|
||||
const double* p = x + n;
|
||||
init(x, p, n);
|
||||
}
|
||||
|
||||
Tabular::Tabular(const double* x, const double* p, int n, Interpolation interp, const double* c)
|
||||
: interp_{interp}
|
||||
{
|
||||
init(x, p, n, c);
|
||||
}
|
||||
|
||||
void Tabular::init(const double* x, const double* p, std::size_t n, const double* c)
|
||||
{
|
||||
// Copy x/p arrays into vectors
|
||||
std::copy(x, x + n, std::back_inserter(x_));
|
||||
std::copy(p, p + n, std::back_inserter(p_));
|
||||
|
||||
// Check interpolation parameter
|
||||
if (interp_ != Interpolation::histogram &&
|
||||
interp_ != Interpolation::lin_lin) {
|
||||
openmc::fatal_error("Only histogram and linear-linear interpolation "
|
||||
"for tabular distribution is supported.");
|
||||
}
|
||||
|
||||
// Calculate cumulative distribution function
|
||||
if (c) {
|
||||
std::copy(c, c + n, std::back_inserter(c_));
|
||||
} else {
|
||||
c_.resize(n);
|
||||
c_[0] = 0.0;
|
||||
for (int i = 1; i < n; ++i) {
|
||||
if (interp_ == Interpolation::histogram) {
|
||||
c_[i] = c_[i-1] + p_[i-1]*(x_[i] - x_[i-1]);
|
||||
} else if (interp_ == Interpolation::lin_lin) {
|
||||
c_[i] = c_[i-1] + 0.5*(p_[i-1] + p_[i]) * (x_[i] - x_[i-1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize density and distribution functions
|
||||
for (int i = 0; i < n; ++i) {
|
||||
p_[i] = p_[i]/c_[n-1];
|
||||
c_[i] = c_[i]/c_[n-1];
|
||||
}
|
||||
}
|
||||
|
||||
double Tabular::sample() const
|
||||
{
|
||||
// Sample value of CDF
|
||||
double c = prn();
|
||||
|
||||
// Find first CDF bin which is above the sampled value
|
||||
double c_i = c_[0];
|
||||
int i;
|
||||
std::size_t n = c_.size();
|
||||
for (i = 0; i < n - 1; ++i) {
|
||||
if (c <= c_[i+1]) break;
|
||||
c_i = c_[i+1];
|
||||
}
|
||||
|
||||
// Determine bounding PDF values
|
||||
double x_i = x_[i];
|
||||
double p_i = p_[i];
|
||||
|
||||
if (interp_ == Interpolation::histogram) {
|
||||
// Histogram interpolation
|
||||
if (p_i > 0.0) {
|
||||
return x_i + (c - c_i)/p_i;
|
||||
} else {
|
||||
return x_i;
|
||||
}
|
||||
} else {
|
||||
// Linear-linear interpolation
|
||||
double x_i1 = x_[i + 1];
|
||||
double p_i1 = p_[i + 1];
|
||||
|
||||
double m = (p_i1 - p_i)/(x_i1 - x_i);
|
||||
if (m == 0.0) {
|
||||
return x_i + (c - c_i)/p_i;
|
||||
} else {
|
||||
return x_i + (std::sqrt(std::max(0.0, p_i*p_i + 2*m*(c - c_i))) - p_i)/m;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// Equiprobable implementation
|
||||
//==============================================================================
|
||||
|
||||
double Equiprobable::sample() const
|
||||
{
|
||||
std::size_t n = x_.size();
|
||||
|
||||
double r = prn();
|
||||
int i = std::floor((n - 1)*r);
|
||||
|
||||
double xl = x_[i];
|
||||
double xr = x_[i+i];
|
||||
return xl + ((n - 1)*r - i) * (xr - xl);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// Helper function
|
||||
//==============================================================================
|
||||
|
||||
UPtrDist distribution_from_xml(pugi::xml_node node)
|
||||
{
|
||||
if (!check_for_node(node, "type"))
|
||||
openmc::fatal_error("Distribution type must be specified.");
|
||||
|
||||
// Determine type of distribution
|
||||
std::string type = get_node_value(node, "type", true, true);
|
||||
|
||||
// Allocate extension of Distribution
|
||||
if (type == "uniform") {
|
||||
return UPtrDist{new Uniform(node)};
|
||||
} else if (type == "maxwell") {
|
||||
return UPtrDist{new Maxwell(node)};
|
||||
} else if (type == "watt") {
|
||||
return UPtrDist{new Watt(node)};
|
||||
} else if (type == "discrete") {
|
||||
return UPtrDist{new Discrete(node)};
|
||||
} else if (type == "tabular") {
|
||||
return UPtrDist{new Tabular(node)};
|
||||
} else {
|
||||
openmc::fatal_error("Invalid distribution type: " + type);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace openmc
|
||||
150
src/distribution.h
Normal file
150
src/distribution.h
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
//! \file distribution.h
|
||||
//! Univariate probability distributions
|
||||
|
||||
#ifndef OPENMC_DISTRIBUTION_H
|
||||
#define OPENMC_DISTRIBUTION_H
|
||||
|
||||
#include <cstddef> // for size_t
|
||||
#include <memory> // for unique_ptr
|
||||
#include <vector> // for vector
|
||||
|
||||
#include "pugixml.hpp"
|
||||
|
||||
#include "constants.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
//! Abstract class representing a univariate probability distribution
|
||||
//==============================================================================
|
||||
|
||||
class Distribution {
|
||||
public:
|
||||
virtual ~Distribution() = default;
|
||||
virtual double sample() const = 0;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
//! A discrete distribution (probability mass function)
|
||||
//==============================================================================
|
||||
|
||||
class Discrete : public Distribution {
|
||||
public:
|
||||
explicit Discrete(pugi::xml_node node);
|
||||
Discrete(const double* x, const double* p, int n);
|
||||
|
||||
//! Sample a value from the distribution
|
||||
//! \return Sampled value
|
||||
double sample() const;
|
||||
private:
|
||||
std::vector<double> x_; //!< Possible outcomes
|
||||
std::vector<double> p_; //!< Probability of each outcome
|
||||
|
||||
//! Normalize distribution so that probabilities sum to unity
|
||||
void normalize();
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
//! Uniform distribution over the interval [a,b]
|
||||
//==============================================================================
|
||||
|
||||
class Uniform : public Distribution {
|
||||
public:
|
||||
explicit Uniform(pugi::xml_node node);
|
||||
Uniform(double a, double b) : a_{a}, b_{b} {};
|
||||
|
||||
//! Sample a value from the distribution
|
||||
//! \return Sampled value
|
||||
double sample() const;
|
||||
private:
|
||||
double a_; //!< Lower bound of distribution
|
||||
double b_; //!< Upper bound of distribution
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
//! Maxwellian distribution of form c*E*exp(-E/theta)
|
||||
//==============================================================================
|
||||
|
||||
class Maxwell : public Distribution {
|
||||
public:
|
||||
explicit Maxwell(pugi::xml_node node);
|
||||
Maxwell(double theta) : theta_{theta} { };
|
||||
|
||||
//! Sample a value from the distribution
|
||||
//! \return Sampled value
|
||||
double sample() const;
|
||||
private:
|
||||
double theta_; //!< Factor in exponential [eV]
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
//! Watt fission spectrum with form c*exp(-E/a)*sinh(sqrt(b*E))
|
||||
//==============================================================================
|
||||
|
||||
class Watt : public Distribution {
|
||||
public:
|
||||
explicit Watt(pugi::xml_node node);
|
||||
Watt(double a, double b) : a_{a}, b_{b} { };
|
||||
|
||||
//! Sample a value from the distribution
|
||||
//! \return Sampled value
|
||||
double sample() const;
|
||||
private:
|
||||
double a_; //!< Factor in exponential [eV]
|
||||
double b_; //!< Factor in square root [1/eV]
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
//! Histogram or linear-linear interpolated tabular distribution
|
||||
//==============================================================================
|
||||
|
||||
class Tabular : public Distribution {
|
||||
public:
|
||||
explicit Tabular(pugi::xml_node node);
|
||||
Tabular(const double* x, const double* p, int n, Interpolation interp,
|
||||
const double* c=nullptr);
|
||||
|
||||
//! Sample a value from the distribution
|
||||
//! \return Sampled value
|
||||
double sample() const;
|
||||
private:
|
||||
std::vector<double> x_; //!< tabulated independent variable
|
||||
std::vector<double> p_; //!< tabulated probability density
|
||||
std::vector<double> c_; //!< cumulative distribution at tabulated values
|
||||
Interpolation interp_; //!< interpolation rule
|
||||
|
||||
//! Initialize tabulated probability density function
|
||||
//! \param x Array of values for independent variable
|
||||
//! \param p Array of tabulated probabilities
|
||||
//! \param n Number of tabulated values
|
||||
void init(const double* x, const double* p, std::size_t n,
|
||||
const double* c=nullptr);
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
//! Equiprobable distribution
|
||||
//==============================================================================
|
||||
|
||||
class Equiprobable : public Distribution {
|
||||
public:
|
||||
explicit Equiprobable(pugi::xml_node node);
|
||||
Equiprobable(const double* x, int n) : x_{x, x+n} { };
|
||||
|
||||
//! Sample a value from the distribution
|
||||
//! \return Sampled value
|
||||
double sample() const;
|
||||
private:
|
||||
std::vector<double> x_; //! Possible outcomes
|
||||
};
|
||||
|
||||
|
||||
using UPtrDist = std::unique_ptr<Distribution>;
|
||||
|
||||
//! Return univariate probability distribution specified in XML file
|
||||
//! \param[in] node XML node representing distribution
|
||||
//! \return Unique pointer to distribution
|
||||
UPtrDist distribution_from_xml(pugi::xml_node node);
|
||||
|
||||
} // namespace openmc
|
||||
|
||||
#endif // OPENMC_DISTRIBUTION_H
|
||||
95
src/distribution_angle.cpp
Normal file
95
src/distribution_angle.cpp
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
#include "distribution_angle.h"
|
||||
|
||||
#include <cmath> // for abs, copysign
|
||||
#include <vector> // for vector
|
||||
|
||||
#include "endf.h"
|
||||
#include "hdf5_interface.h"
|
||||
#include "random_lcg.h"
|
||||
#include "search.h"
|
||||
#include "xtensor/xarray.hpp"
|
||||
#include "xtensor/xview.hpp"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
// AngleDistribution implementation
|
||||
//==============================================================================
|
||||
|
||||
AngleDistribution::AngleDistribution(hid_t group)
|
||||
{
|
||||
// Get incoming energies
|
||||
read_dataset(group, "energy", energy_);
|
||||
int n_energy = energy_.size();
|
||||
|
||||
// Get outgoing energy distribution data
|
||||
std::vector<int> offsets;
|
||||
std::vector<int> interp;
|
||||
hid_t dset = open_dataset(group, "mu");
|
||||
read_attribute(dset, "offsets", offsets);
|
||||
read_attribute(dset, "interpolation", interp);
|
||||
xt::xarray<double> temp;
|
||||
read_dataset(dset, temp);
|
||||
close_dataset(dset);
|
||||
|
||||
for (int i = 0; i < n_energy; ++i) {
|
||||
// Determine number of outgoing energies
|
||||
int j = offsets[i];
|
||||
int n;
|
||||
if (i < n_energy - 1) {
|
||||
n = offsets[i+1] - j;
|
||||
} else {
|
||||
n = temp.shape()[1] - j;
|
||||
}
|
||||
|
||||
// Create and initialize tabular distribution
|
||||
auto xs = xt::view(temp, 0, xt::range(j, j+n));
|
||||
auto ps = xt::view(temp, 1, xt::range(j, j+n));
|
||||
auto cs = xt::view(temp, 2, xt::range(j, j+n));
|
||||
std::vector<double> x {xs.begin(), xs.end()};
|
||||
std::vector<double> p {ps.begin(), ps.end()};
|
||||
std::vector<double> c {cs.begin(), cs.end()};
|
||||
|
||||
// To get answers that match ACE data, for now we still use the tabulated
|
||||
// CDF values that were passed through to the HDF5 library. At a later
|
||||
// time, we can remove the CDF values from the HDF5 library and
|
||||
// reconstruct them using the PDF
|
||||
Tabular* mudist = new Tabular{x.data(), p.data(), n, int2interp(interp[i]),
|
||||
c.data()};
|
||||
|
||||
distribution_.emplace_back(mudist);
|
||||
}
|
||||
}
|
||||
|
||||
double AngleDistribution::sample(double E) const
|
||||
{
|
||||
// Determine number of incoming energies
|
||||
auto n = energy_.size();
|
||||
|
||||
// Find energy bin and calculate interpolation factor -- if the energy is
|
||||
// outside the range of the tabulated energies, choose the first or last bins
|
||||
int i;
|
||||
double r;
|
||||
if (E < energy_[0]) {
|
||||
i = 0;
|
||||
r = 0.0;
|
||||
} else if (E > energy_[n - 1]) {
|
||||
i = n - 2;
|
||||
r = 1.0;
|
||||
} else {
|
||||
i = lower_bound_index(energy_.begin(), energy_.end(), E);
|
||||
r = (E - energy_[i])/(energy_[i+1] - energy_[i]);
|
||||
}
|
||||
|
||||
// Sample between the ith and (i+1)th bin
|
||||
if (r > prn()) ++i;
|
||||
|
||||
// Sample i-th distribution
|
||||
double mu = distribution_[i]->sample();
|
||||
|
||||
// Make sure mu is in range [-1,1] and return
|
||||
if (std::abs(mu) > 1.0) mu = std::copysign(1.0, mu);
|
||||
return mu;
|
||||
}
|
||||
|
||||
} // namespace openmc
|
||||
39
src/distribution_angle.h
Normal file
39
src/distribution_angle.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
//! \file distribution_angle.h
|
||||
//! Angle distribution dependent on incident particle energy
|
||||
|
||||
#ifndef OPENMC_DISTRIBUTION_ANGLE_H
|
||||
#define OPENMC_DISTRIBUTION_ANGLE_H
|
||||
|
||||
#include <vector> // for vector
|
||||
|
||||
#include "distribution.h"
|
||||
#include "hdf5.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
//! Angle distribution that depends on incident particle energy
|
||||
//==============================================================================
|
||||
|
||||
class AngleDistribution {
|
||||
public:
|
||||
AngleDistribution() = default;
|
||||
explicit AngleDistribution(hid_t group);
|
||||
|
||||
//! Sample an angle given an incident particle energy
|
||||
//! \param[in] E Particle energy in [eV]
|
||||
//! \return Cosine of the angle in the range [-1,1]
|
||||
double sample(double E) const;
|
||||
|
||||
//! Determine whether angle distribution is empty
|
||||
//! \return Whether distribution is empty
|
||||
bool empty() const { return energy_.empty(); }
|
||||
|
||||
private:
|
||||
std::vector<double> energy_;
|
||||
std::vector<UPtrDist> distribution_;
|
||||
};
|
||||
|
||||
} // namespace openmc
|
||||
|
||||
#endif // OPENMC_DISTRIBUTION_ANGLE_H
|
||||
337
src/distribution_energy.cpp
Normal file
337
src/distribution_energy.cpp
Normal file
|
|
@ -0,0 +1,337 @@
|
|||
#include "distribution_energy.h"
|
||||
|
||||
#include <algorithm> // for max, min, copy, move
|
||||
#include <cstddef> // for size_t
|
||||
#include <iterator> // for back_inserter
|
||||
|
||||
#include "endf.h"
|
||||
#include "hdf5_interface.h"
|
||||
#include "math_functions.h"
|
||||
#include "random_lcg.h"
|
||||
#include "search.h"
|
||||
#include "xtensor/xview.hpp"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
// DiscretePhoton implementation
|
||||
//==============================================================================
|
||||
|
||||
DiscretePhoton::DiscretePhoton(hid_t group)
|
||||
{
|
||||
read_attribute(group, "primary_flag", primary_flag_);
|
||||
read_attribute(group, "energy", energy_);
|
||||
read_attribute(group, "atomic_weight_ratio", A_);
|
||||
}
|
||||
|
||||
double DiscretePhoton::sample(double E) const
|
||||
{
|
||||
if (primary_flag_ == 2) {
|
||||
return energy_ + A_/(A_+ 1)*E;
|
||||
} else {
|
||||
return energy_;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// LevelInelastic implementation
|
||||
//==============================================================================
|
||||
|
||||
LevelInelastic::LevelInelastic(hid_t group)
|
||||
{
|
||||
read_attribute(group, "threshold", threshold_);
|
||||
read_attribute(group, "mass_ratio", mass_ratio_);
|
||||
}
|
||||
|
||||
double LevelInelastic::sample(double E) const
|
||||
{
|
||||
return mass_ratio_*(E - threshold_);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// ContinuousTabular implementation
|
||||
//==============================================================================
|
||||
|
||||
ContinuousTabular::ContinuousTabular(hid_t group)
|
||||
{
|
||||
// Open incoming energy dataset
|
||||
hid_t dset = open_dataset(group, "energy");
|
||||
|
||||
// Get interpolation parameters
|
||||
xt::xarray<int> temp;
|
||||
read_attribute(dset, "interpolation", temp);
|
||||
|
||||
auto temp_b = xt::view(temp, 0); // view of breakpoints
|
||||
auto temp_i = xt::view(temp, 1); // view of interpolation parameters
|
||||
|
||||
std::copy(temp_b.begin(), temp_b.end(), std::back_inserter(breakpoints_));
|
||||
for (const auto i : temp_i)
|
||||
interpolation_.push_back(int2interp(i));
|
||||
n_region_ = breakpoints_.size();
|
||||
|
||||
// Get incoming energies
|
||||
read_dataset(dset, energy_);
|
||||
std::size_t n_energy = energy_.size();
|
||||
close_dataset(dset);
|
||||
|
||||
// Get outgoing energy distribution data
|
||||
dset = open_dataset(group, "distribution");
|
||||
std::vector<int> offsets;
|
||||
std::vector<int> interp;
|
||||
std::vector<int> n_discrete;
|
||||
read_attribute(dset, "offsets", offsets);
|
||||
read_attribute(dset, "interpolation", interp);
|
||||
read_attribute(dset, "n_discrete_lines", n_discrete);
|
||||
|
||||
xt::xarray<double> eout;
|
||||
read_dataset(dset, eout);
|
||||
close_dataset(dset);
|
||||
|
||||
for (int i = 0; i < n_energy; ++i) {
|
||||
// Determine number of outgoing energies
|
||||
int j = offsets[i];
|
||||
int n;
|
||||
if (i < n_energy - 1) {
|
||||
n = offsets[i+1] - j;
|
||||
} else {
|
||||
n = eout.shape()[1] - j;
|
||||
}
|
||||
|
||||
// Assign interpolation scheme and number of discrete lines
|
||||
CTTable d;
|
||||
d.interpolation = int2interp(interp[i]);
|
||||
d.n_discrete = n_discrete[i];
|
||||
|
||||
// Copy data
|
||||
d.e_out = xt::view(eout, 0, xt::range(j, j+n));
|
||||
d.p = xt::view(eout, 1, xt::range(j, j+n));
|
||||
|
||||
// To get answers that match ACE data, for now we still use the tabulated
|
||||
// CDF values that were passed through to the HDF5 library. At a later
|
||||
// time, we can remove the CDF values from the HDF5 library and
|
||||
// reconstruct them using the PDF
|
||||
if (true) {
|
||||
d.c = xt::view(eout, 2, xt::range(j, j+n));
|
||||
} else {
|
||||
// Calculate cumulative distribution function -- discrete portion
|
||||
for (int k = 0; k < d.n_discrete; ++k) {
|
||||
if (k == 0) {
|
||||
d.c[k] = d.p[k];
|
||||
} else {
|
||||
d.c[k] = d.c[k-1] + d.p[k];
|
||||
}
|
||||
}
|
||||
|
||||
// Continuous portion
|
||||
for (int k = d.n_discrete; k < n; ++k) {
|
||||
if (k == d.n_discrete) {
|
||||
d.c[k] = d.c[k-1] + d.p[k];
|
||||
} else {
|
||||
if (d.interpolation == Interpolation::histogram) {
|
||||
d.c[k] = d.c[k-1] + d.p[k-1]*(d.e_out[k] - d.e_out[k-1]);
|
||||
} else if (d.interpolation == Interpolation::lin_lin) {
|
||||
d.c[k] = d.c[k-1] + 0.5*(d.p[k-1] + d.p[k]) *
|
||||
(d.e_out[k] - d.e_out[k-1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize density and distribution functions
|
||||
d.p /= d.c[n - 1];
|
||||
d.c /= d.c[n - 1];
|
||||
}
|
||||
|
||||
distribution_.push_back(std::move(d));
|
||||
} // incoming energies
|
||||
}
|
||||
|
||||
double ContinuousTabular::sample(double E) const
|
||||
{
|
||||
// Read number of interpolation regions and incoming energies
|
||||
bool histogram_interp;
|
||||
if (n_region_ == 1) {
|
||||
histogram_interp = (interpolation_[0] == Interpolation::histogram);
|
||||
} else {
|
||||
histogram_interp = false;
|
||||
}
|
||||
|
||||
// Find energy bin and calculate interpolation factor -- if the energy is
|
||||
// outside the range of the tabulated energies, choose the first or last bins
|
||||
auto n_energy_in = energy_.size();
|
||||
int i;
|
||||
double r;
|
||||
if (E < energy_[0]) {
|
||||
i = 0;
|
||||
r = 0.0;
|
||||
} else if (E > energy_[n_energy_in - 1]) {
|
||||
i = n_energy_in - 2;
|
||||
r = 1.0;
|
||||
} else {
|
||||
i = lower_bound_index(energy_.begin(), energy_.end(), E);
|
||||
r = (E - energy_[i]) / (energy_[i+1] - energy_[i]);
|
||||
}
|
||||
|
||||
// Sample between the ith and [i+1]th bin
|
||||
int l;
|
||||
if (histogram_interp) {
|
||||
l = i;
|
||||
} else {
|
||||
l = r > prn() ? i + 1 : i;
|
||||
}
|
||||
|
||||
// Interpolation for energy E1 and EK
|
||||
int n_energy_out = distribution_[i].e_out.size();
|
||||
double E_i_1 = distribution_[i].e_out[0];
|
||||
double E_i_K = distribution_[i].e_out[n_energy_out - 1];
|
||||
|
||||
n_energy_out = distribution_[i+1].e_out.size();
|
||||
double E_i1_1 = distribution_[i+1].e_out[0];
|
||||
double E_i1_K = distribution_[i+1].e_out[n_energy_out - 1];
|
||||
|
||||
double E_1 = E_i_1 + r*(E_i1_1 - E_i_1);
|
||||
double E_K = E_i_K + r*(E_i1_K - E_i_K);
|
||||
|
||||
// Determine outgoing energy bin
|
||||
n_energy_out = distribution_[l].e_out.size();
|
||||
double r1 = prn();
|
||||
double c_k = distribution_[l].c[0];
|
||||
double c_k1;
|
||||
int k;
|
||||
for (k = 0; k < n_energy_out - 2; ++k) {
|
||||
c_k1 = distribution_[l].c[k+1];
|
||||
if (r1 < c_k1) break;
|
||||
c_k = c_k1;
|
||||
}
|
||||
|
||||
// Check to make sure 1 <= k <= NP - 1
|
||||
k = std::max(0, std::min(k, n_energy_out - 2));
|
||||
|
||||
double E_l_k = distribution_[l].e_out[k];
|
||||
double p_l_k = distribution_[l].p[k];
|
||||
double E_out;
|
||||
if (distribution_[l].interpolation == Interpolation::histogram) {
|
||||
// Histogram interpolation
|
||||
if (p_l_k > 0.0) {
|
||||
E_out = E_l_k + (r1 - c_k)/p_l_k;
|
||||
} else {
|
||||
E_out = E_l_k;
|
||||
}
|
||||
|
||||
} else if (distribution_[l].interpolation == Interpolation::lin_lin) {
|
||||
// Linear-linear interpolation
|
||||
double E_l_k1 = distribution_[l].e_out[k+1];
|
||||
double p_l_k1 = distribution_[l].p[k+1];
|
||||
|
||||
double frac = (p_l_k1 - p_l_k)/(E_l_k1 - E_l_k);
|
||||
if (frac == 0.0) {
|
||||
E_out = E_l_k + (r1 - c_k)/p_l_k;
|
||||
} else {
|
||||
E_out = E_l_k + (std::sqrt(std::max(0.0, p_l_k*p_l_k +
|
||||
2.0*frac*(r1 - c_k))) - p_l_k)/frac;
|
||||
}
|
||||
}
|
||||
|
||||
// Now interpolate between incident energy bins i and i + 1
|
||||
if (!histogram_interp && n_energy_out > 1) {
|
||||
if (l == i) {
|
||||
return E_1 + (E_out - E_i_1)*(E_K - E_1)/(E_i_K - E_i_1);
|
||||
} else {
|
||||
return E_1 + (E_out - E_i1_1)*(E_K - E_1)/(E_i1_K - E_i1_1);
|
||||
}
|
||||
} else {
|
||||
return E_out;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// MaxwellEnergy implementation
|
||||
//==============================================================================
|
||||
|
||||
MaxwellEnergy::MaxwellEnergy(hid_t group)
|
||||
{
|
||||
read_attribute(group, "u", u_);
|
||||
hid_t dset = open_dataset(group, "theta");
|
||||
theta_ = Tabulated1D{dset};
|
||||
close_dataset(dset);
|
||||
}
|
||||
|
||||
double MaxwellEnergy::sample(double E) const
|
||||
{
|
||||
// Get temperature corresponding to incoming energy
|
||||
double theta = theta_(E);
|
||||
|
||||
while (true) {
|
||||
// Sample maxwell fission spectrum
|
||||
double E_out = maxwell_spectrum_c(theta);
|
||||
|
||||
// Accept energy based on restriction energy
|
||||
if (E_out <= E - u_) return E_out;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// Evaporation implementation
|
||||
//==============================================================================
|
||||
|
||||
Evaporation::Evaporation(hid_t group)
|
||||
{
|
||||
read_attribute(group, "u", u_);
|
||||
hid_t dset = open_dataset(group, "theta");
|
||||
theta_ = Tabulated1D{dset};
|
||||
close_dataset(dset);
|
||||
}
|
||||
|
||||
double Evaporation::sample(double E) const
|
||||
{
|
||||
// Get temperature corresponding to incoming energy
|
||||
double theta = theta_(E);
|
||||
|
||||
double y = (E - u_)/theta;
|
||||
double v = 1.0 - std::exp(-y);
|
||||
|
||||
// Sample outgoing energy based on evaporation spectrum probability
|
||||
// density function
|
||||
double x;
|
||||
while (true) {
|
||||
x = -std::log((1.0 - v*prn())*(1.0 - v*prn()));
|
||||
if (x <= y) break;
|
||||
}
|
||||
|
||||
return x*theta;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// WattEnergy implementation
|
||||
//==============================================================================
|
||||
|
||||
WattEnergy::WattEnergy(hid_t group)
|
||||
{
|
||||
// Read restriction energy
|
||||
read_attribute(group, "u", u_);
|
||||
|
||||
// Read tabulated functions
|
||||
hid_t dset = open_dataset(group, "a");
|
||||
a_ = Tabulated1D{dset};
|
||||
close_dataset(dset);
|
||||
dset = open_dataset(group, "b");
|
||||
b_ = Tabulated1D{dset};
|
||||
close_dataset(dset);
|
||||
}
|
||||
|
||||
double WattEnergy::sample(double E) const
|
||||
{
|
||||
// Determine Watt parameters at incident energy
|
||||
double a = a_(E);
|
||||
double b = b_(E);
|
||||
|
||||
while (true) {
|
||||
// Sample energy-dependent Watt fission spectrum
|
||||
double E_out = watt_spectrum_c(a, b);
|
||||
|
||||
// Accept energy based on restriction energy
|
||||
if (E_out <= E - u_) return E_out;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
152
src/distribution_energy.h
Normal file
152
src/distribution_energy.h
Normal file
|
|
@ -0,0 +1,152 @@
|
|||
//! \file distribution_energy.h
|
||||
//! Energy distributions that depend on incident particle energy
|
||||
|
||||
#ifndef OPENMC_DISTRIBUTION_ENERGY_H
|
||||
#define OPENMC_DISTRIBUTION_ENERGY_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "xtensor/xtensor.hpp"
|
||||
#include "hdf5.h"
|
||||
|
||||
#include "constants.h"
|
||||
#include "endf.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//===============================================================================
|
||||
//! Abstract class defining an energy distribution that is a function of the
|
||||
//! incident energy of a projectile. Each derived type must implement a sample()
|
||||
//! function that returns a sampled outgoing energy given an incoming energy
|
||||
//===============================================================================
|
||||
|
||||
class EnergyDistribution {
|
||||
public:
|
||||
virtual double sample(double E) const = 0;
|
||||
virtual ~EnergyDistribution() = default;
|
||||
};
|
||||
|
||||
//===============================================================================
|
||||
//! Discrete photon energy distribution
|
||||
//===============================================================================
|
||||
|
||||
class DiscretePhoton : public EnergyDistribution {
|
||||
public:
|
||||
explicit DiscretePhoton(hid_t group);
|
||||
|
||||
//! Sample energy distribution
|
||||
//! \param[in] E Incident particle energy in [eV]
|
||||
//! \return Sampled energy in [eV]
|
||||
double sample(double E) const;
|
||||
private:
|
||||
int primary_flag_; //!< Indicator of whether the photon is a primary or
|
||||
//!< non-primary photon.
|
||||
double energy_; //!< Photon energy or binding energy
|
||||
double A_; //!< Atomic weight ratio of the target nuclide
|
||||
};
|
||||
|
||||
//===============================================================================
|
||||
//! Level inelastic scattering distribution
|
||||
//===============================================================================
|
||||
|
||||
class LevelInelastic : public EnergyDistribution {
|
||||
public:
|
||||
explicit LevelInelastic(hid_t group);
|
||||
|
||||
//! Sample energy distribution
|
||||
//! \param[in] E Incident particle energy in [eV]
|
||||
//! \return Sampled energy in [eV]
|
||||
double sample(double E) const;
|
||||
private:
|
||||
double threshold_; //!< Energy threshold in lab, (A + 1)/A * |Q|
|
||||
double mass_ratio_; //!< (A/(A+1))^2
|
||||
};
|
||||
|
||||
//===============================================================================
|
||||
//! An energy distribution represented as a tabular distribution with histogram
|
||||
//! or linear-linear interpolation. This corresponds to ACE law 4, which NJOY
|
||||
//! produces for a number of ENDF energy distributions.
|
||||
//===============================================================================
|
||||
|
||||
class ContinuousTabular : public EnergyDistribution {
|
||||
public:
|
||||
explicit ContinuousTabular(hid_t group);
|
||||
|
||||
//! Sample energy distribution
|
||||
//! \param[in] E Incident particle energy in [eV]
|
||||
//! \return Sampled energy in [eV]
|
||||
double sample(double E) const;
|
||||
private:
|
||||
//! Outgoing energy for a single incoming energy
|
||||
struct CTTable {
|
||||
Interpolation interpolation; //!< Interpolation law
|
||||
int n_discrete; //!< Number of of discrete energies
|
||||
xt::xtensor<double, 1> e_out; //!< Outgoing energies in [eV]
|
||||
xt::xtensor<double, 1> p; //!< Probability density
|
||||
xt::xtensor<double, 1> c; //!< Cumulative distribution
|
||||
};
|
||||
|
||||
int n_region_; //!< Number of inteprolation regions
|
||||
std::vector<int> breakpoints_; //!< Breakpoints between regions
|
||||
std::vector<Interpolation> interpolation_; //!< Interpolation laws
|
||||
std::vector<double> energy_; //!< Incident energy in [eV]
|
||||
std::vector<CTTable> distribution_; //!< Distributions for each incident energy
|
||||
};
|
||||
|
||||
//===============================================================================
|
||||
//! Evaporation spectrum corresponding to ACE law 9 and ENDF File 5, LF=9.
|
||||
//===============================================================================
|
||||
|
||||
class Evaporation : public EnergyDistribution {
|
||||
public:
|
||||
explicit Evaporation(hid_t group);
|
||||
|
||||
//! Sample energy distribution
|
||||
//! \param[in] E Incident particle energy in [eV]
|
||||
//! \return Sampled energy in [eV]
|
||||
double sample(double E) const;
|
||||
private:
|
||||
Tabulated1D theta_; //!< Incoming energy dependent parameter
|
||||
double u_; //!< Restriction energy
|
||||
};
|
||||
|
||||
//===============================================================================
|
||||
//! Energy distribution of neutrons emitted from a Maxwell fission spectrum.
|
||||
//! This corresponds to ACE law 7 and ENDF File 5, LF=7.
|
||||
//===============================================================================
|
||||
|
||||
class MaxwellEnergy : public EnergyDistribution {
|
||||
public:
|
||||
explicit MaxwellEnergy(hid_t group);
|
||||
|
||||
//! Sample energy distribution
|
||||
//! \param[in] E Incident particle energy in [eV]
|
||||
//! \return Sampled energy in [eV]
|
||||
double sample(double E) const;
|
||||
private:
|
||||
Tabulated1D theta_; //!< Incoming energy dependent parameter
|
||||
double u_; //!< Restriction energy
|
||||
};
|
||||
|
||||
//===============================================================================
|
||||
//! Energy distribution of neutrons emitted from a Watt fission spectrum. This
|
||||
//! corresponds to ACE law 11 and ENDF File 5, LF=11.
|
||||
//===============================================================================
|
||||
|
||||
class WattEnergy : public EnergyDistribution {
|
||||
public:
|
||||
explicit WattEnergy(hid_t group);
|
||||
|
||||
//! Sample energy distribution
|
||||
//! \param[in] E Incident particle energy in [eV]
|
||||
//! \return Sampled energy in [eV]
|
||||
double sample(double E) const;
|
||||
private:
|
||||
Tabulated1D a_; //!< Energy-dependent 'a' parameter
|
||||
Tabulated1D b_; //!< Energy-dependent 'b' parameter
|
||||
double u_; //!< Restriction energy
|
||||
};
|
||||
|
||||
} // namespace openmc
|
||||
|
||||
#endif // OPENMC_DISTRIBUTION_ENERGY_H
|
||||
51
src/distribution_multi.cpp
Normal file
51
src/distribution_multi.cpp
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#include "distribution_multi.h"
|
||||
|
||||
#include <algorithm> // for move
|
||||
#include <cmath> // for sqrt, sin, cos, max
|
||||
|
||||
#include "constants.h"
|
||||
#include "math_functions.h"
|
||||
#include "random_lcg.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
// PolarAzimuthal implementation
|
||||
//==============================================================================
|
||||
|
||||
PolarAzimuthal::PolarAzimuthal(Direction u, UPtrDist mu, UPtrDist phi) :
|
||||
UnitSphereDistribution{u}, mu_{std::move(mu)}, phi_{std::move(phi)} { }
|
||||
|
||||
Direction PolarAzimuthal::sample() const
|
||||
{
|
||||
// Sample cosine of polar angle
|
||||
double mu = mu_->sample();
|
||||
if (mu == 1.0) return u_ref;
|
||||
|
||||
// Sample azimuthal angle
|
||||
double phi = phi_->sample();
|
||||
return rotate_angle(u_ref, mu, &phi);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// Isotropic implementation
|
||||
//==============================================================================
|
||||
|
||||
Direction Isotropic::sample() const
|
||||
{
|
||||
double phi = 2.0*PI*prn();
|
||||
double mu = 2.0*prn() - 1.0;
|
||||
return {mu, std::sqrt(1.0 - mu*mu) * std::cos(phi),
|
||||
std::sqrt(1.0 - mu*mu) * std::sin(phi)};
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// Monodirectional implementation
|
||||
//==============================================================================
|
||||
|
||||
Direction Monodirectional::sample() const
|
||||
{
|
||||
return u_ref;
|
||||
}
|
||||
|
||||
} // namespace openmc
|
||||
73
src/distribution_multi.h
Normal file
73
src/distribution_multi.h
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
#ifndef DISTRIBUTION_MULTI_H
|
||||
#define DISTRIBUTION_MULTI_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "distribution.h"
|
||||
#include "position.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
//! Probability density function for points on the unit sphere. Extensions of
|
||||
//! this type are used to sample angular distributions for starting sources
|
||||
//==============================================================================
|
||||
|
||||
class UnitSphereDistribution {
|
||||
public:
|
||||
UnitSphereDistribution() { };
|
||||
explicit UnitSphereDistribution(Direction u) : u_ref{u} { };
|
||||
virtual ~UnitSphereDistribution() = default;
|
||||
|
||||
//! Sample a direction from the distribution
|
||||
//! \return Direction sampled
|
||||
virtual Direction sample() const = 0;
|
||||
|
||||
Direction u_ref {0.0, 0.0, 1.0}; //!< reference direction
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
//! Explicit distribution of polar and azimuthal angles
|
||||
//==============================================================================
|
||||
|
||||
class PolarAzimuthal : public UnitSphereDistribution {
|
||||
public:
|
||||
PolarAzimuthal(Direction u, UPtrDist mu, UPtrDist phi);
|
||||
|
||||
//! Sample a direction from the distribution
|
||||
//! \return Direction sampled
|
||||
Direction sample() const;
|
||||
private:
|
||||
UPtrDist mu_; //!< Distribution of polar angle
|
||||
UPtrDist phi_; //!< Distribution of azimuthal angle
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
//! Uniform distribution on the unit sphere
|
||||
//==============================================================================
|
||||
|
||||
class Isotropic : public UnitSphereDistribution {
|
||||
public:
|
||||
Isotropic() { };
|
||||
|
||||
//! Sample a direction from the distribution
|
||||
//! \return Sampled direction
|
||||
Direction sample() const;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
//! Monodirectional distribution
|
||||
//==============================================================================
|
||||
|
||||
class Monodirectional : public UnitSphereDistribution {
|
||||
public:
|
||||
Monodirectional(Direction u) : UnitSphereDistribution{u} { };
|
||||
|
||||
//! Sample a direction from the distribution
|
||||
//! \return Sampled direction
|
||||
Direction sample() const;
|
||||
};
|
||||
|
||||
} // namespace openmc
|
||||
|
||||
#endif // DISTRIBUTION_MULTI_H
|
||||
97
src/distribution_spatial.cpp
Normal file
97
src/distribution_spatial.cpp
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
#include "distribution_spatial.h"
|
||||
|
||||
#include "error.h"
|
||||
#include "random_lcg.h"
|
||||
#include "xml_interface.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
// CartesianIndependent implementation
|
||||
//==============================================================================
|
||||
|
||||
CartesianIndependent::CartesianIndependent(pugi::xml_node node)
|
||||
{
|
||||
// Read distribution for x coordinate
|
||||
if (check_for_node(node, "x")) {
|
||||
pugi::xml_node node_dist = node.child("x");
|
||||
x_ = distribution_from_xml(node_dist);
|
||||
} else {
|
||||
// If no distribution was specified, default to a single point at x=0
|
||||
double x[] {0.0};
|
||||
double p[] {1.0};
|
||||
x_ = UPtrDist{new Discrete{x, p, 1}};
|
||||
}
|
||||
|
||||
// Read distribution for y coordinate
|
||||
if (check_for_node(node, "y")) {
|
||||
pugi::xml_node node_dist = node.child("y");
|
||||
y_ = distribution_from_xml(node_dist);
|
||||
} else {
|
||||
// If no distribution was specified, default to a single point at y=0
|
||||
double x[] {0.0};
|
||||
double p[] {1.0};
|
||||
y_ = UPtrDist{new Discrete{x, p, 1}};
|
||||
}
|
||||
|
||||
// Read distribution for z coordinate
|
||||
if (check_for_node(node, "z")) {
|
||||
pugi::xml_node node_dist = node.child("z");
|
||||
z_ = distribution_from_xml(node_dist);
|
||||
} else {
|
||||
// If no distribution was specified, default to a single point at z=0
|
||||
double x[] {0.0};
|
||||
double p[] {1.0};
|
||||
z_ = UPtrDist{new Discrete{x, p, 1}};
|
||||
}
|
||||
}
|
||||
|
||||
Position CartesianIndependent::sample() const
|
||||
{
|
||||
return {x_->sample(), y_->sample(), z_->sample()};
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// SpatialBox implementation
|
||||
//==============================================================================
|
||||
|
||||
SpatialBox::SpatialBox(pugi::xml_node node)
|
||||
{
|
||||
// Read lower-right/upper-left coordinates
|
||||
auto params = get_node_array<double>(node, "parameters");
|
||||
if (params.size() != 6)
|
||||
openmc::fatal_error("Box/fission spatial source must have six "
|
||||
"parameters specified.");
|
||||
|
||||
lower_left_ = Position{params[0], params[1], params[2]};
|
||||
upper_right_ = Position{params[3], params[4], params[5]};
|
||||
}
|
||||
|
||||
Position SpatialBox::sample() const
|
||||
{
|
||||
Position xi {prn(), prn(), prn()};
|
||||
return lower_left_ + xi*(upper_right_ - lower_left_);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// SpatialPoint implementation
|
||||
//==============================================================================
|
||||
|
||||
SpatialPoint::SpatialPoint(pugi::xml_node node)
|
||||
{
|
||||
// Read location of point source
|
||||
auto params = get_node_array<double>(node, "parameters");
|
||||
if (params.size() != 3)
|
||||
openmc::fatal_error("Point spatial source must have three "
|
||||
"parameters specified.");
|
||||
|
||||
// Set position
|
||||
r_ = Position{params.data()};
|
||||
}
|
||||
|
||||
Position SpatialPoint::sample() const
|
||||
{
|
||||
return r_;
|
||||
}
|
||||
|
||||
} // namespace openmc
|
||||
74
src/distribution_spatial.h
Normal file
74
src/distribution_spatial.h
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
#ifndef OPENMC_DISTRIBTUION_SPATIAL_H
|
||||
#define OPENMC_DISTRIBUTION_SPATIAL_H
|
||||
|
||||
#include "pugixml.hpp"
|
||||
|
||||
#include "distribution.h"
|
||||
#include "position.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
//! Probability density function for points in Euclidean space
|
||||
//==============================================================================
|
||||
|
||||
class SpatialDistribution {
|
||||
public:
|
||||
virtual ~SpatialDistribution() = default;
|
||||
|
||||
//! Sample a position from the distribution
|
||||
virtual Position sample() const = 0;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
//! Distribution of points specified by independent distributions in x,y,z
|
||||
//==============================================================================
|
||||
|
||||
class CartesianIndependent : public SpatialDistribution {
|
||||
public:
|
||||
explicit CartesianIndependent(pugi::xml_node node);
|
||||
|
||||
//! Sample a position from the distribution
|
||||
//! \return Sampled position
|
||||
Position sample() const;
|
||||
private:
|
||||
UPtrDist x_; //!< Distribution of x coordinates
|
||||
UPtrDist y_; //!< Distribution of y coordinates
|
||||
UPtrDist z_; //!< Distribution of z coordinates
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
//! Uniform distribution of points over a box
|
||||
//==============================================================================
|
||||
|
||||
class SpatialBox : public SpatialDistribution {
|
||||
public:
|
||||
explicit SpatialBox(pugi::xml_node node);
|
||||
|
||||
//! Sample a position from the distribution
|
||||
//! \return Sampled position
|
||||
Position sample() const;
|
||||
private:
|
||||
Position lower_left_; //!< Lower-left coordinates of box
|
||||
Position upper_right_; //!< Upper-right coordinates of box
|
||||
bool only_fissionable {false}; //!< Only accept sites in fissionable region?
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
//! Distribution at a single point
|
||||
//==============================================================================
|
||||
|
||||
class SpatialPoint : public SpatialDistribution {
|
||||
public:
|
||||
explicit SpatialPoint(pugi::xml_node node);
|
||||
|
||||
//! Sample a position from the distribution
|
||||
//! \return Sampled position
|
||||
Position sample() const;
|
||||
private:
|
||||
Position r_; //!< Single position at which sites are generated
|
||||
};
|
||||
|
||||
} // namespace openmc
|
||||
|
||||
#endif // OPENMC_DISTRIBUTION_SPATIAL_H
|
||||
147
src/endf.cpp
Normal file
147
src/endf.cpp
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
#include "endf.h"
|
||||
|
||||
#include <algorithm> // for copy
|
||||
#include <cmath> // for log, exp
|
||||
#include <iterator> // for back_inserter
|
||||
|
||||
#include "constants.h"
|
||||
#include "hdf5_interface.h"
|
||||
#include "search.h"
|
||||
#include "xtensor/xarray.hpp"
|
||||
#include "xtensor/xview.hpp"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
// Functions
|
||||
//==============================================================================
|
||||
|
||||
Interpolation int2interp(int i)
|
||||
{
|
||||
switch (i) {
|
||||
case 1:
|
||||
return Interpolation::histogram;
|
||||
case 2:
|
||||
return Interpolation::lin_lin;
|
||||
case 3:
|
||||
return Interpolation::lin_log;
|
||||
case 4:
|
||||
return Interpolation::log_lin;
|
||||
case 5:
|
||||
return Interpolation::log_log;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_fission(int mt)
|
||||
{
|
||||
return mt == 18 || mt == 19 || mt == 20 || mt == 21 || mt == 38;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// Polynomial implementation
|
||||
//==============================================================================
|
||||
|
||||
Polynomial::Polynomial(hid_t dset)
|
||||
{
|
||||
// Read coefficients into a vector
|
||||
read_dataset(dset, coef_);
|
||||
}
|
||||
|
||||
double Polynomial::operator()(double x) const
|
||||
{
|
||||
// Use Horner's rule to evaluate polynomial. Note that coefficients are
|
||||
// ordered in increasing powers of x.
|
||||
double y = 0.0;
|
||||
for (auto c = coef_.crbegin(); c != coef_.crend(); ++c) {
|
||||
y = y*x + *c;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// Tabulated1D implementation
|
||||
//==============================================================================
|
||||
|
||||
Tabulated1D::Tabulated1D(hid_t dset)
|
||||
{
|
||||
read_attribute(dset, "breakpoints", nbt_);
|
||||
n_regions_ = nbt_.size();
|
||||
|
||||
// Change 1-indexing to 0-indexing
|
||||
for (auto& b : nbt_) --b;
|
||||
|
||||
std::vector<int> int_temp;
|
||||
read_attribute(dset, "interpolation", int_temp);
|
||||
|
||||
// Convert vector of ints into Interpolation
|
||||
for (const auto i : int_temp)
|
||||
int_.push_back(int2interp(i));
|
||||
|
||||
xt::xarray<double> arr;
|
||||
read_dataset(dset, arr);
|
||||
|
||||
auto xs = xt::view(arr, 0);
|
||||
auto ys = xt::view(arr, 1);
|
||||
|
||||
std::copy(xs.begin(), xs.end(), std::back_inserter(x_));
|
||||
std::copy(ys.begin(), ys.end(), std::back_inserter(y_));
|
||||
n_pairs_ = x_.size();
|
||||
}
|
||||
|
||||
double Tabulated1D::operator()(double x) const
|
||||
{
|
||||
// find which bin the abscissa is in -- if the abscissa is outside the
|
||||
// tabulated range, the first or last point is chosen, i.e. no interpolation
|
||||
// is done outside the energy range
|
||||
int i;
|
||||
if (x < x_[0]) {
|
||||
return y_[0];
|
||||
} else if (x > x_[n_pairs_ - 1]) {
|
||||
return y_[n_pairs_ - 1];
|
||||
} else {
|
||||
i = lower_bound_index(x_.begin(), x_.end(), x);
|
||||
}
|
||||
|
||||
// determine interpolation scheme
|
||||
Interpolation interp;
|
||||
if (n_regions_ == 0) {
|
||||
interp = Interpolation::lin_lin;
|
||||
} else if (n_regions_ == 1) {
|
||||
interp = int_[0];
|
||||
} else if (n_regions_ > 1) {
|
||||
for (int j = 0; j < n_regions_; ++j) {
|
||||
if (i < nbt_[j]) {
|
||||
interp = int_[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// handle special case of histogram interpolation
|
||||
if (interp == Interpolation::histogram) return y_[i];
|
||||
|
||||
// determine bounding values
|
||||
double x0 = x_[i];
|
||||
double x1 = x_[i + 1];
|
||||
double y0 = y_[i];
|
||||
double y1 = y_[i + 1];
|
||||
|
||||
// determine interpolation factor and interpolated value
|
||||
double r;
|
||||
switch (interp) {
|
||||
case Interpolation::lin_lin:
|
||||
r = (x - x0)/(x1 - x0);
|
||||
return y0 + r*(y1 - y0);
|
||||
case Interpolation::lin_log:
|
||||
r = log(x/x0)/log(x1/x0);
|
||||
return y0 + r*(y1 - y0);
|
||||
case Interpolation::log_lin:
|
||||
r = (x - x0)/(x1 - x0);
|
||||
return y0*exp(r*log(y1/y0));
|
||||
case Interpolation::log_log:
|
||||
r = log(x/x0)/log(x1/x0);
|
||||
return y0*exp(r*log(y1/y0));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace openmc
|
||||
78
src/endf.h
Normal file
78
src/endf.h
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
//! \file endf.h
|
||||
//! Classes and functions related to the ENDF-6 format
|
||||
|
||||
#ifndef OPENMC_ENDF_H
|
||||
#define OPENMC_ENDF_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "constants.h"
|
||||
#include "hdf5.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//! Convert integer representing interpolation law to enum
|
||||
//! \param[in] i Intereger (e.g. 1=histogram, 2=lin-lin)
|
||||
//! \return Corresponding enum value
|
||||
Interpolation int2interp(int i);
|
||||
|
||||
//! Determine whether MT number corresponds to a fission reaction
|
||||
//! \param[in] MT ENDF MT value
|
||||
//! \return Whether corresponding reaction is a fission reaction
|
||||
bool is_fission(int MT);
|
||||
|
||||
//==============================================================================
|
||||
//! Abstract one-dimensional function
|
||||
//==============================================================================
|
||||
|
||||
class Function1D {
|
||||
public:
|
||||
virtual double operator()(double x) const = 0;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
//! One-dimensional function expressed as a polynomial
|
||||
//==============================================================================
|
||||
|
||||
class Polynomial : public Function1D {
|
||||
public:
|
||||
//! Construct polynomial from HDF5 data
|
||||
//! \param[in] dset Dataset containing coefficients
|
||||
explicit Polynomial(hid_t dset);
|
||||
|
||||
//! Evaluate the polynomials
|
||||
//! \param[in] x independent variable
|
||||
//! \return Polynomial evaluated at x
|
||||
double operator()(double x) const;
|
||||
private:
|
||||
std::vector<double> coef_; //!< Polynomial coefficients
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
//! One-dimensional interpolable function
|
||||
//==============================================================================
|
||||
|
||||
class Tabulated1D : public Function1D {
|
||||
public:
|
||||
Tabulated1D() = default;
|
||||
|
||||
//! Construct function from HDF5 data
|
||||
//! \param[in] dset Dataset containing tabulated data
|
||||
explicit Tabulated1D(hid_t dset);
|
||||
|
||||
//! Evaluate the tabulated function
|
||||
//! \param[in] x independent variable
|
||||
//! \return Function evaluated at x
|
||||
double operator()(double x) const;
|
||||
private:
|
||||
std::size_t n_regions_ {0}; //!< number of interpolation regions
|
||||
std::vector<int> nbt_; //!< values separating interpolation regions
|
||||
std::vector<Interpolation> int_; //!< interpolation schemes
|
||||
std::size_t n_pairs_; //!< number of (x,y) pairs
|
||||
std::vector<double> x_; //!< values of abscissa
|
||||
std::vector<double> y_; //!< values of ordinate
|
||||
};
|
||||
|
||||
} // namespace openmc
|
||||
|
||||
#endif // OPENMC_ENDF_H
|
||||
|
|
@ -1,583 +0,0 @@
|
|||
module energy_distribution
|
||||
|
||||
use algorithm, only: binary_search
|
||||
use constants, only: ZERO, ONE, HALF, TWO, PI, HISTOGRAM, LINEAR_LINEAR
|
||||
use endf_header, only: Tabulated1D
|
||||
use hdf5_interface
|
||||
use math, only: maxwell_spectrum, watt_spectrum
|
||||
use random_lcg, only: prn
|
||||
|
||||
!===============================================================================
|
||||
! ENERGYDISTRIBUTION (abstract) defines an energy distribution that is a
|
||||
! function of the incident energy of a projectile. Each derived type must
|
||||
! implement a sample() function that returns a sampled outgoing energy given an
|
||||
! incoming energy
|
||||
!===============================================================================
|
||||
|
||||
type, abstract :: EnergyDistribution
|
||||
contains
|
||||
procedure(energy_distribution_sample_), deferred :: sample
|
||||
procedure(energy_distribution_from_hdf5_), deferred :: from_hdf5
|
||||
end type EnergyDistribution
|
||||
|
||||
abstract interface
|
||||
function energy_distribution_sample_(this, E_in) result(E_out)
|
||||
import EnergyDistribution
|
||||
class(EnergyDistribution), intent(in) :: this
|
||||
real(8), intent(in) :: E_in
|
||||
real(8) :: E_out
|
||||
end function energy_distribution_sample_
|
||||
|
||||
subroutine energy_distribution_from_hdf5_(this, group_id)
|
||||
import EnergyDistribution
|
||||
import HID_T
|
||||
class(EnergyDistribution), intent(inout) :: this
|
||||
integer(HID_T), intent(in) :: group_id
|
||||
end subroutine energy_distribution_from_hdf5_
|
||||
end interface
|
||||
|
||||
type :: EnergyDistributionContainer
|
||||
class(EnergyDistribution), allocatable :: obj
|
||||
end type EnergyDistributionContainer
|
||||
|
||||
!===============================================================================
|
||||
! Derived classes
|
||||
!===============================================================================
|
||||
|
||||
!===============================================================================
|
||||
! TABULAREQUIPROBABLE represents an energy distribution with tabular
|
||||
! equiprobable energy bins as given in ACE law 1. This is an older
|
||||
! representation that has largely been replaced with ACE laws 4, 44, and 61.
|
||||
!===============================================================================
|
||||
|
||||
type, extends(EnergyDistribution) :: TabularEquiprobable
|
||||
integer :: n_region ! number of interpolation regions
|
||||
integer, allocatable :: breakpoints(:) ! breakpoints of interpolation regions
|
||||
integer, allocatable :: interpolation(:) ! interpolation region codes
|
||||
real(8), allocatable :: energy_in(:) ! incoming energies
|
||||
real(8), allocatable :: energy_out(:,:) ! table of outgoing energies for
|
||||
! each incoming energy
|
||||
contains
|
||||
procedure :: sample => equiprobable_sample
|
||||
procedure :: from_hdf5 => equiprobable_from_hdf5
|
||||
end type TabularEquiprobable
|
||||
|
||||
!===============================================================================
|
||||
! DISCRETEPHOTON gives the energy distribution for a discrete photon (usually
|
||||
! used for photon production from an incident-neutron reaction)
|
||||
!===============================================================================
|
||||
|
||||
type, extends(EnergyDistribution) :: DiscretePhoton
|
||||
integer :: primary_flag
|
||||
real(8) :: energy
|
||||
real(8) :: A
|
||||
contains
|
||||
procedure :: sample => discrete_photon_sample
|
||||
procedure :: from_hdf5 => discrete_photon_from_hdf5
|
||||
end type DiscretePhoton
|
||||
|
||||
!===============================================================================
|
||||
! LEVELINELASTIC gives the energy distribution for level inelastic scattering by
|
||||
! neutrons as in ENDF MT=51--90.
|
||||
!===============================================================================
|
||||
|
||||
type, extends(EnergyDistribution) :: LevelInelastic
|
||||
real(8) :: threshold
|
||||
real(8) :: mass_ratio
|
||||
contains
|
||||
procedure :: sample => level_inelastic_sample
|
||||
procedure :: from_hdf5 => level_inelastic_from_hdf5
|
||||
end type LevelInelastic
|
||||
|
||||
!===============================================================================
|
||||
! CONTINUOUSTABULAR gives an energy distribution represented as a tabular
|
||||
! distribution with histogram or linear-linear interpolation. This corresponds
|
||||
! to ACE law 4, which NJOY produces for a number of ENDF energy distributions.
|
||||
!===============================================================================
|
||||
|
||||
type CTTable
|
||||
integer :: interpolation
|
||||
integer :: n_discrete
|
||||
real(8), allocatable :: e_out(:)
|
||||
real(8), allocatable :: p(:)
|
||||
real(8), allocatable :: c(:)
|
||||
end type CTTable
|
||||
|
||||
type, extends(EnergyDistribution) :: ContinuousTabular
|
||||
integer :: n_region
|
||||
integer, allocatable :: breakpoints(:)
|
||||
integer, allocatable :: interpolation(:)
|
||||
real(8), allocatable :: energy(:)
|
||||
type(CTTable), allocatable :: distribution(:)
|
||||
contains
|
||||
procedure :: sample => continuous_sample
|
||||
procedure :: from_hdf5 => continuous_from_hdf5
|
||||
end type ContinuousTabular
|
||||
|
||||
!===============================================================================
|
||||
! MAXWELLENERGY gives the energy distribution of neutrons emitted from a Maxwell
|
||||
! fission spectrum. This corresponds to ACE law 7 and ENDF File 5, LF=7.
|
||||
!===============================================================================
|
||||
|
||||
type, extends(EnergyDistribution) :: MaxwellEnergy
|
||||
type(Tabulated1D) :: theta ! incoming-energy-dependent parameter
|
||||
real(8) :: u ! restriction energy
|
||||
contains
|
||||
procedure :: sample => maxwellenergy_sample
|
||||
procedure :: from_hdf5 => maxwellenergy_from_hdf5
|
||||
end type MaxwellEnergy
|
||||
|
||||
!===============================================================================
|
||||
! EVAPORATION represents an evaporation spectrum corresponding to ACE law 9 and
|
||||
! ENDF File 5, LF=9.
|
||||
!===============================================================================
|
||||
|
||||
type, extends(EnergyDistribution) :: Evaporation
|
||||
type(Tabulated1D) :: theta
|
||||
real(8) :: u
|
||||
contains
|
||||
procedure :: sample => evaporation_sample
|
||||
procedure :: from_hdf5 => evaporation_from_hdf5
|
||||
end type Evaporation
|
||||
|
||||
!===============================================================================
|
||||
! WATTENERGY gives the energy distribution of neutrons emitted from a Watt
|
||||
! fission spectrum. This corresponds to ACE law 11 and ENDF File 5, LF=11.
|
||||
!===============================================================================
|
||||
|
||||
type, extends(EnergyDistribution) :: WattEnergy
|
||||
type(Tabulated1D) :: a
|
||||
type(Tabulated1D) :: b
|
||||
real(8) :: u
|
||||
contains
|
||||
procedure :: sample => watt_sample
|
||||
procedure :: from_hdf5 => watt_from_hdf5
|
||||
end type WattEnergy
|
||||
|
||||
contains
|
||||
|
||||
function equiprobable_sample(this, E_in) result(E_out)
|
||||
class(TabularEquiprobable), intent(in) :: this
|
||||
real(8), intent(in) :: E_in ! incoming energy
|
||||
real(8) :: E_out ! sampled outgoing energy
|
||||
|
||||
integer :: i, k, l ! indices
|
||||
integer :: n_energy_in ! number of incoming energies
|
||||
integer :: n_energy_out ! number of outgoing energies
|
||||
real(8) :: r ! interpolation factor on incoming energy
|
||||
real(8) :: E_i_1, E_i_K ! endpoints on outgoing grid i
|
||||
real(8) :: E_i1_1, E_i1_K ! endpoints on outgoing grid i+1
|
||||
real(8) :: E_1, E_K ! endpoints interpolated between i and i+1
|
||||
real(8) :: E_l_k, E_l_k1 ! adjacent E on outgoing grid l
|
||||
|
||||
! Determine number of incoming/outgoing energies
|
||||
n_energy_in = size(this%energy_in)
|
||||
n_energy_out = size(this%energy_out, 1)
|
||||
|
||||
! Determine index on incoming energy grid and interpolation factor
|
||||
i = binary_search(this%energy_in, size(this%energy_in), E_in)
|
||||
r = (E_in - this%energy_in(i)) / &
|
||||
(this%energy_in(i+1) - this%energy_in(i))
|
||||
|
||||
! Sample outgoing energy bin
|
||||
k = 1 + int(n_energy_out * prn())
|
||||
|
||||
! Determine E_1 and E_K
|
||||
E_i_1 = this%energy_out(1, i)
|
||||
E_i_K = this%energy_out(n_energy_out, i)
|
||||
|
||||
E_i1_1 = this%energy_out(1, i+1)
|
||||
E_i1_K = this%energy_out(n_energy_out, i+1)
|
||||
|
||||
E_1 = E_i_1 + r*(E_i1_1 - E_i_1)
|
||||
E_K = E_i_K + r*(E_i1_K - E_i_K)
|
||||
|
||||
! Randomly select between the outgoing table for incoming energy E_i and
|
||||
! E_(i+1)
|
||||
if (prn() < r) then
|
||||
l = i + 1
|
||||
else
|
||||
l = i
|
||||
end if
|
||||
|
||||
! Determine E_l_k and E_l_k+1
|
||||
E_l_k = this%energy_out(k, l)
|
||||
E_l_k1 = this%energy_out(k+1, l)
|
||||
|
||||
! Determine E' (denoted here as E_out)
|
||||
E_out = E_l_k + prn()*(E_l_k1 - E_l_k)
|
||||
|
||||
! Now interpolate between incident energy bins i and i + 1
|
||||
if (l == i) then
|
||||
E_out = E_1 + (E_out - E_i_1)*(E_K - E_1)/(E_i_K - E_i_1)
|
||||
else
|
||||
E_out = E_1 + (E_out - E_i1_1)*(E_K - E_1)/(E_i1_K - E_i1_1)
|
||||
end if
|
||||
end function equiprobable_sample
|
||||
|
||||
subroutine equiprobable_from_hdf5(this, group_id)
|
||||
class(TabularEquiprobable), intent(inout) :: this
|
||||
integer(HID_T), intent(in) :: group_id
|
||||
end subroutine equiprobable_from_hdf5
|
||||
|
||||
function discrete_photon_sample(this, E_in) result(E_out)
|
||||
class(DiscretePhoton), intent(in) :: this
|
||||
real(8), intent(in) :: E_in
|
||||
real(8) :: E_out
|
||||
|
||||
if (this % primary_flag == 2) then
|
||||
E_out = this % energy + this % A/(this % A + 1)*E_in
|
||||
else
|
||||
E_out = this % energy
|
||||
end if
|
||||
end function discrete_photon_sample
|
||||
|
||||
subroutine discrete_photon_from_hdf5(this, group_id)
|
||||
class(DiscretePhoton), intent(inout) :: this
|
||||
integer(HID_T), intent(in) :: group_id
|
||||
|
||||
call read_attribute(this % primary_flag, group_id, 'primary_flag')
|
||||
call read_attribute(this % energy, group_id, 'energy')
|
||||
call read_attribute(this % A, group_id, 'atomic_weight_ratio')
|
||||
end subroutine discrete_photon_from_hdf5
|
||||
|
||||
function level_inelastic_sample(this, E_in) result(E_out)
|
||||
class(LevelInelastic), intent(in) :: this
|
||||
real(8), intent(in) :: E_in
|
||||
real(8) :: E_out
|
||||
|
||||
E_out = this%mass_ratio*(E_in - this%threshold)
|
||||
end function level_inelastic_sample
|
||||
|
||||
subroutine level_inelastic_from_hdf5(this, group_id)
|
||||
class(LevelInelastic), intent(inout) :: this
|
||||
integer(HID_T), intent(in) :: group_id
|
||||
|
||||
call read_attribute(this%threshold, group_id, 'threshold')
|
||||
call read_attribute(this%mass_ratio, group_id, 'mass_ratio')
|
||||
end subroutine level_inelastic_from_hdf5
|
||||
|
||||
function continuous_sample(this, E_in) result(E_out)
|
||||
class(ContinuousTabular), intent(in) :: this
|
||||
real(8), intent(in) :: E_in ! incoming energy
|
||||
real(8) :: E_out ! sampled outgoing energy
|
||||
|
||||
integer :: i, k, l ! indices
|
||||
integer :: n_energy_in ! number of incoming energies
|
||||
integer :: n_energy_out ! number of outgoing energies
|
||||
real(8) :: r ! interpolation factor on incoming energy
|
||||
real(8) :: r1 ! random number on [0,1)
|
||||
real(8) :: frac ! interpolation factor on outgoing energy
|
||||
real(8) :: E_i_1, E_i_K ! endpoints on outgoing grid i
|
||||
real(8) :: E_i1_1, E_i1_K ! endpoints on outgoing grid i+1
|
||||
real(8) :: E_1, E_K ! endpoints interpolated between i and i+1
|
||||
real(8) :: E_l_k, E_l_k1 ! adjacent E on outgoing grid l
|
||||
real(8) :: p_l_k, p_l_k1 ! adjacent p on outgoing grid l
|
||||
real(8) :: c_k, c_k1 ! cumulative probability
|
||||
logical :: histogram_interp ! whether histogram interpolation is used
|
||||
|
||||
! Read number of interpolation regions and incoming energies
|
||||
if (this%n_region == 1) then
|
||||
histogram_interp = (this%interpolation(1) == 1)
|
||||
else
|
||||
histogram_interp = .false.
|
||||
end if
|
||||
|
||||
! Find energy bin and calculate interpolation factor -- if the energy is
|
||||
! outside the range of the tabulated energies, choose the first or last bins
|
||||
n_energy_in = size(this%energy)
|
||||
if (E_in < this%energy(1)) then
|
||||
i = 1
|
||||
r = ZERO
|
||||
elseif (E_in > this%energy(n_energy_in)) then
|
||||
i = n_energy_in - 1
|
||||
r = ONE
|
||||
else
|
||||
i = binary_search(this%energy, n_energy_in, E_in)
|
||||
r = (E_in - this%energy(i)) / &
|
||||
(this%energy(i+1) - this%energy(i))
|
||||
end if
|
||||
|
||||
! Sample between the ith and (i+1)th bin
|
||||
if (histogram_interp) then
|
||||
l = i
|
||||
else
|
||||
if (r > prn()) then
|
||||
l = i + 1
|
||||
else
|
||||
l = i
|
||||
end if
|
||||
end if
|
||||
|
||||
! Interpolation for energy E1 and EK
|
||||
n_energy_out = size(this%distribution(i)%e_out)
|
||||
E_i_1 = this%distribution(i)%e_out(1)
|
||||
E_i_K = this%distribution(i)%e_out(n_energy_out)
|
||||
|
||||
n_energy_out = size(this%distribution(i+1)%e_out)
|
||||
E_i1_1 = this%distribution(i+1)%e_out(1)
|
||||
E_i1_K = this%distribution(i+1)%e_out(n_energy_out)
|
||||
|
||||
E_1 = E_i_1 + r*(E_i1_1 - E_i_1)
|
||||
E_K = E_i_K + r*(E_i1_K - E_i_K)
|
||||
|
||||
! Determine outgoing energy bin
|
||||
n_energy_out = size(this%distribution(l)%e_out)
|
||||
r1 = prn()
|
||||
c_k = this%distribution(l)%c(1)
|
||||
do k = 1, n_energy_out - 1
|
||||
c_k1 = this%distribution(l)%c(k+1)
|
||||
if (r1 < c_k1) exit
|
||||
c_k = c_k1
|
||||
end do
|
||||
|
||||
! Check to make sure 1 <= k <= NP - 1
|
||||
k = max(1, min(k, n_energy_out - 1))
|
||||
|
||||
E_l_k = this%distribution(l)%e_out(k)
|
||||
p_l_k = this%distribution(l)%p(k)
|
||||
if (this%distribution(l)%interpolation == HISTOGRAM) then
|
||||
! Histogram interpolation
|
||||
if (p_l_k > ZERO) then
|
||||
E_out = E_l_k + (r1 - c_k)/p_l_k
|
||||
else
|
||||
E_out = E_l_k
|
||||
end if
|
||||
|
||||
elseif (this%distribution(l)%interpolation == LINEAR_LINEAR) then
|
||||
! Linear-linear interpolation
|
||||
E_l_k1 = this%distribution(l)%e_out(k+1)
|
||||
p_l_k1 = this%distribution(l)%p(k+1)
|
||||
|
||||
frac = (p_l_k1 - p_l_k)/(E_l_k1 - E_l_k)
|
||||
if (frac == ZERO) then
|
||||
E_out = E_l_k + (r1 - c_k)/p_l_k
|
||||
else
|
||||
E_out = E_l_k + (sqrt(max(ZERO, p_l_k*p_l_k + &
|
||||
TWO*frac*(r1 - c_k))) - p_l_k)/frac
|
||||
end if
|
||||
end if
|
||||
|
||||
! Now interpolate between incident energy bins i and i + 1
|
||||
if (.not. histogram_interp .and. n_energy_out > 1) then
|
||||
if (l == i) then
|
||||
E_out = E_1 + (E_out - E_i_1)*(E_K - E_1)/(E_i_K - E_i_1)
|
||||
else
|
||||
E_out = E_1 + (E_out - E_i1_1)*(E_K - E_1)/(E_i1_K - E_i1_1)
|
||||
end if
|
||||
end if
|
||||
end function continuous_sample
|
||||
|
||||
subroutine continuous_from_hdf5(this, group_id)
|
||||
class(ContinuousTabular), intent(inout) :: this
|
||||
integer(HID_T), intent(in) :: group_id
|
||||
|
||||
integer :: i, j, k
|
||||
integer :: n
|
||||
integer :: n_energy
|
||||
integer(HID_T) :: dset_id
|
||||
integer(HSIZE_T) :: dims(1), dims2(2)
|
||||
integer, allocatable :: temp(:,:)
|
||||
integer, allocatable :: offsets(:)
|
||||
integer, allocatable :: interp(:)
|
||||
integer, allocatable :: n_discrete(:)
|
||||
real(8), allocatable :: eout(:,:)
|
||||
|
||||
! Open incoming energy dataset
|
||||
dset_id = open_dataset(group_id, 'energy')
|
||||
|
||||
! Get interpolation parameters
|
||||
call read_attribute(temp, dset_id, 'interpolation')
|
||||
allocate(this%breakpoints(size(temp, 1)))
|
||||
allocate(this%interpolation(size(temp, 1)))
|
||||
this%breakpoints(:) = temp(:, 1)
|
||||
this%interpolation(:) = temp(:, 2)
|
||||
this%n_region = size(this%breakpoints)
|
||||
|
||||
! Get incoming energies
|
||||
call get_shape(dset_id, dims)
|
||||
n_energy = int(dims(1), 4)
|
||||
allocate(this%energy(n_energy))
|
||||
allocate(this%distribution(n_energy))
|
||||
call read_dataset(this%energy, dset_id)
|
||||
call close_dataset(dset_id)
|
||||
|
||||
! Get outgoing energy distribution data
|
||||
dset_id = open_dataset(group_id, 'distribution')
|
||||
call read_attribute(offsets, dset_id, 'offsets')
|
||||
call read_attribute(interp, dset_id, 'interpolation')
|
||||
call read_attribute(n_discrete, dset_id, 'n_discrete_lines')
|
||||
call get_shape(dset_id, dims2)
|
||||
allocate(eout(dims2(1), dims2(2)))
|
||||
call read_dataset(eout, dset_id)
|
||||
call close_dataset(dset_id)
|
||||
|
||||
do i = 1, n_energy
|
||||
! Determine number of outgoing energies
|
||||
j = offsets(i)
|
||||
if (i < n_energy) then
|
||||
n = offsets(i+1) - j
|
||||
else
|
||||
n = size(eout, 1) - j
|
||||
end if
|
||||
|
||||
associate (d => this % distribution(i))
|
||||
! Assign interpolation scheme and number of discrete lines
|
||||
d % interpolation = interp(i)
|
||||
d % n_discrete = n_discrete(i)
|
||||
|
||||
! Allocate arrays for energies and PDF/CDF
|
||||
allocate(d % e_out(n))
|
||||
allocate(d % p(n))
|
||||
allocate(d % c(n))
|
||||
|
||||
! Copy data
|
||||
d % e_out(:) = eout(j+1:j+n, 1)
|
||||
d % p(:) = eout(j+1:j+n, 2)
|
||||
|
||||
! To get answers that match ACE data, for now we still use the tabulated
|
||||
! CDF values that were passed through to the HDF5 library. At a later
|
||||
! time, we can remove the CDF values from the HDF5 library and
|
||||
! reconstruct them using the PDF
|
||||
if (.true.) then
|
||||
d % c(:) = eout(j+1:j+n, 3)
|
||||
else
|
||||
! Calculate cumulative distribution function -- discrete portion
|
||||
do k = 1, n_discrete(i)
|
||||
if (k == 1) then
|
||||
d % c(k) = d % p(k)
|
||||
else
|
||||
d % c(k) = d % c(k-1) + d % p(k)
|
||||
end if
|
||||
end do
|
||||
|
||||
! Continuous portion
|
||||
do k = d % n_discrete + 1, n
|
||||
if (k == d % n_discrete + 1) then
|
||||
d % c(k) = sum(d % p(1:d % n_discrete))
|
||||
else
|
||||
if (d % interpolation == HISTOGRAM) then
|
||||
d % c(k) = d % c(k-1) + d % p(k-1) * &
|
||||
(d % e_out(k) - d % e_out(k-1))
|
||||
elseif (d % interpolation == LINEAR_LINEAR) then
|
||||
d % c(k) = d % c(k-1) + HALF*(d % p(k-1) + d % p(k)) * &
|
||||
(d % e_out(k) - d % e_out(k-1))
|
||||
end if
|
||||
end if
|
||||
end do
|
||||
|
||||
! Normalize density and distribution functions
|
||||
d % p(:) = d % p(:)/d % c(n)
|
||||
d % c(:) = d % c(:)/d % c(n)
|
||||
end if
|
||||
end associate
|
||||
end do
|
||||
end subroutine continuous_from_hdf5
|
||||
|
||||
function maxwellenergy_sample(this, E_in) result(E_out)
|
||||
class(MaxwellEnergy), intent(in) :: this
|
||||
real(8), intent(in) :: E_in ! incoming energy
|
||||
real(8) :: E_out ! sampled outgoing energy
|
||||
|
||||
real(8) :: theta ! Maxwell distribution parameter
|
||||
|
||||
! Get temperature corresponding to incoming energy
|
||||
theta = this % theta % evaluate(E_in)
|
||||
|
||||
do
|
||||
! Sample maxwell fission spectrum
|
||||
E_out = maxwell_spectrum(theta)
|
||||
|
||||
! Accept energy based on restriction energy
|
||||
if (E_out <= E_in - this%u) exit
|
||||
end do
|
||||
end function maxwellenergy_sample
|
||||
|
||||
subroutine maxwellenergy_from_hdf5(this, group_id)
|
||||
class(MaxwellEnergy), intent(inout) :: this
|
||||
integer(HID_T), intent(in) :: group_id
|
||||
|
||||
integer(HID_T) :: dset_id
|
||||
|
||||
call read_attribute(this%u, group_id, 'u')
|
||||
dset_id = open_dataset(group_id, 'theta')
|
||||
call this%theta%from_hdf5(dset_id)
|
||||
call close_dataset(dset_id)
|
||||
end subroutine maxwellenergy_from_hdf5
|
||||
|
||||
function evaporation_sample(this, E_in) result(E_out)
|
||||
class(Evaporation), intent(in) :: this
|
||||
real(8), intent(in) :: E_in ! incoming energy
|
||||
real(8) :: E_out ! sampled outgoing energy
|
||||
|
||||
real(8) :: theta ! evaporation spectrum parameter
|
||||
real(8) :: x, y, v
|
||||
|
||||
! Get temperature corresponding to incoming energy
|
||||
theta = this % theta % evaluate(E_in)
|
||||
|
||||
y = (E_in - this%u)/theta
|
||||
v = 1 - exp(-y)
|
||||
|
||||
! Sample outgoing energy based on evaporation spectrum probability
|
||||
! density function
|
||||
do
|
||||
x = -log((ONE - v*prn())*(ONE - v*prn()))
|
||||
if (x <= y) exit
|
||||
end do
|
||||
|
||||
E_out = x*theta
|
||||
end function evaporation_sample
|
||||
|
||||
subroutine evaporation_from_hdf5(this, group_id)
|
||||
class(Evaporation), intent(inout) :: this
|
||||
integer(HID_T), intent(in) :: group_id
|
||||
|
||||
integer(HID_T) :: dset_id
|
||||
|
||||
call read_attribute(this%u, group_id, 'u')
|
||||
dset_id = open_dataset(group_id, 'theta')
|
||||
call this%theta%from_hdf5(dset_id)
|
||||
call close_dataset(dset_id)
|
||||
end subroutine evaporation_from_hdf5
|
||||
|
||||
function watt_sample(this, E_in) result(E_out)
|
||||
class(WattEnergy), intent(in) :: this
|
||||
real(8), intent(in) :: E_in ! incoming energy
|
||||
real(8) :: E_out ! sampled outgoing energy
|
||||
|
||||
real(8) :: a, b ! Watt spectrum parameters
|
||||
|
||||
! Determine Watt parameter 'a' from tabulated function
|
||||
a = this % a % evaluate(E_in)
|
||||
|
||||
! Determine Watt parameter 'b' from tabulated function
|
||||
b = this % b % evaluate(E_in)
|
||||
|
||||
do
|
||||
! Sample energy-dependent Watt fission spectrum
|
||||
E_out = watt_spectrum(a, b)
|
||||
|
||||
! Accept energy based on restriction energy
|
||||
if (E_out <= E_in - this%u) exit
|
||||
end do
|
||||
end function watt_sample
|
||||
|
||||
subroutine watt_from_hdf5(this, group_id)
|
||||
class(WattEnergy), intent(inout) :: this
|
||||
integer(HID_T), intent(in) :: group_id
|
||||
|
||||
integer(HID_T) :: dset_id
|
||||
|
||||
call read_attribute(this%u, group_id, 'u')
|
||||
|
||||
dset_id = open_dataset(group_id, 'a')
|
||||
call this%a%from_hdf5(dset_id)
|
||||
call close_dataset(dset_id)
|
||||
|
||||
dset_id = open_dataset(group_id, 'b')
|
||||
call this%b%from_hdf5(dset_id)
|
||||
call close_dataset(dset_id)
|
||||
end subroutine watt_from_hdf5
|
||||
|
||||
end module energy_distribution
|
||||
|
|
@ -51,6 +51,35 @@ get_shape(hid_t obj_id, hsize_t* dims)
|
|||
}
|
||||
|
||||
|
||||
std::vector<hsize_t> attribute_shape(hid_t obj_id, const char* name)
|
||||
{
|
||||
hid_t attr = H5Aopen(obj_id, name, H5P_DEFAULT);
|
||||
std::vector<hsize_t> shape = object_shape(attr);
|
||||
H5Aclose(attr);
|
||||
return shape;
|
||||
}
|
||||
|
||||
std::vector<hsize_t> object_shape(hid_t obj_id)
|
||||
{
|
||||
// Get number of dimensions
|
||||
auto type = H5Iget_type(obj_id);
|
||||
hid_t dspace;
|
||||
if (type == H5I_DATASET) {
|
||||
dspace = H5Dget_space(obj_id);
|
||||
} else if (type == H5I_ATTR) {
|
||||
dspace = H5Aget_space(obj_id);
|
||||
}
|
||||
int n = H5Sget_simple_extent_ndims(dspace);
|
||||
|
||||
// Get shape of array
|
||||
std::vector<hsize_t> shape(n);
|
||||
H5Sget_simple_extent_dims(dspace, shape.data(), nullptr);
|
||||
|
||||
// Free resources and return
|
||||
H5Sclose(dspace);
|
||||
return shape;
|
||||
}
|
||||
|
||||
void
|
||||
get_shape_attr(hid_t obj_id, const char* name, hsize_t* dims)
|
||||
{
|
||||
|
|
@ -116,6 +145,18 @@ dataset_typesize(hid_t dset)
|
|||
}
|
||||
|
||||
|
||||
void
|
||||
ensure_exists(hid_t group_id, const char* name)
|
||||
{
|
||||
if (!object_exists(group_id, name)) {
|
||||
std::stringstream err_msg;
|
||||
err_msg << "Object \"" << name << "\" does not exist in group "
|
||||
<< object_name(group_id);
|
||||
fatal_error(err_msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
hid_t
|
||||
file_open(const char* filename, char mode, bool parallel)
|
||||
{
|
||||
|
|
@ -285,6 +326,36 @@ get_groups(hid_t group_id, char* name[])
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<std::string>
|
||||
group_names(hid_t group_id)
|
||||
{
|
||||
// Determine number of links in the group
|
||||
H5G_info_t info;
|
||||
H5Gget_info(group_id, &info);
|
||||
|
||||
// Iterate over links to get names
|
||||
H5O_info_t oinfo;
|
||||
size_t size;
|
||||
std::vector<std::string> names;
|
||||
for (hsize_t i = 0; i < info.nlinks; ++i) {
|
||||
// Determine type of object (and skip non-group)
|
||||
H5Oget_info_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i, &oinfo,
|
||||
H5P_DEFAULT);
|
||||
if (oinfo.type != H5O_TYPE_GROUP) continue;
|
||||
|
||||
// Get size of name
|
||||
size = 1 + H5Lget_name_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC,
|
||||
i, nullptr, 0, H5P_DEFAULT);
|
||||
|
||||
// Read name
|
||||
char buffer[size];
|
||||
H5Lget_name_by_idx(group_id, ".", H5_INDEX_NAME, H5_ITER_INC, i,
|
||||
buffer, size, H5P_DEFAULT);
|
||||
names.emplace_back(&buffer[0], size);
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
object_exists(hid_t object_id, const char* name)
|
||||
|
|
@ -299,14 +370,23 @@ object_exists(hid_t object_id, const char* name)
|
|||
}
|
||||
|
||||
|
||||
std::string
|
||||
object_name(hid_t obj_id)
|
||||
{
|
||||
// Determine size and create buffer
|
||||
size_t size = 1 + H5Iget_name(obj_id, nullptr, 0);
|
||||
char buffer[size];
|
||||
|
||||
// Read and return name
|
||||
H5Iget_name(obj_id, buffer, size);
|
||||
return {buffer, size};
|
||||
}
|
||||
|
||||
|
||||
hid_t
|
||||
open_dataset(hid_t group_id, const char* name)
|
||||
{
|
||||
if (!object_exists(group_id, name)) {
|
||||
std::stringstream err_msg;
|
||||
err_msg << "Group \"" << name << "\" does not exist";
|
||||
fatal_error(err_msg);
|
||||
}
|
||||
ensure_exists(group_id, name);
|
||||
return H5Dopen(group_id, name, H5P_DEFAULT);
|
||||
}
|
||||
|
||||
|
|
@ -314,11 +394,7 @@ open_dataset(hid_t group_id, const char* name)
|
|||
hid_t
|
||||
open_group(hid_t group_id, const char* name)
|
||||
{
|
||||
if (!object_exists(group_id, name)) {
|
||||
std::stringstream err_msg;
|
||||
err_msg << "Group \"" << name << "\" does not exist";
|
||||
fatal_error(err_msg);
|
||||
}
|
||||
ensure_exists(group_id, name);
|
||||
return H5Gopen(group_id, name, H5P_DEFAULT);
|
||||
}
|
||||
|
||||
|
|
@ -425,7 +501,7 @@ read_string(hid_t obj_id, const char* name, size_t slen, char* buffer, bool inde
|
|||
|
||||
|
||||
void
|
||||
read_complex(hid_t obj_id, const char* name, double _Complex* buffer, bool indep)
|
||||
read_complex(hid_t obj_id, const char* name, std::complex<double>* buffer, bool indep)
|
||||
{
|
||||
// Create compound datatype for complex numbers
|
||||
struct complex_t {
|
||||
|
|
|
|||
|
|
@ -1,19 +1,20 @@
|
|||
#ifndef OPENMC_HDF5_INTERFACE_H
|
||||
#define OPENMC_HDF5_INTERFACE_H
|
||||
|
||||
#include "hdf5.h"
|
||||
#include "hdf5_hl.h"
|
||||
|
||||
#include <array>
|
||||
#include <complex>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <complex.h>
|
||||
|
||||
#include "hdf5.h"
|
||||
#include "hdf5_hl.h"
|
||||
#include "xtensor/xadapt.hpp"
|
||||
#include "xtensor/xarray.hpp"
|
||||
|
||||
#include "position.h"
|
||||
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -21,7 +22,7 @@ namespace openmc {
|
|||
//==============================================================================
|
||||
|
||||
void read_attr(hid_t obj_id, const char* name, hid_t mem_type_id,
|
||||
const void* buffer);
|
||||
void* buffer);
|
||||
void write_attr(hid_t obj_id, int ndim, const hsize_t* dims, const char* name,
|
||||
hid_t mem_type_id, const void* buffer);
|
||||
void read_dataset(hid_t obj_id, const char* name, hid_t mem_type_id,
|
||||
|
|
@ -72,6 +73,12 @@ read_nd_vector(hid_t obj_id, const char* name,
|
|||
std::vector<std::vector<std::vector<std::vector<std::vector<double> > > > >& result,
|
||||
bool must_have = false);
|
||||
|
||||
std::vector<hsize_t> attribute_shape(hid_t obj_id, const char* name);
|
||||
void ensure_exists(hid_t group_id, const char* name);
|
||||
std::vector<std::string> group_names(hid_t group_id);
|
||||
std::vector<hsize_t> object_shape(hid_t obj_id);
|
||||
std::string object_name(hid_t obj_id);
|
||||
|
||||
//==============================================================================
|
||||
// Fortran compatibility functions
|
||||
//==============================================================================
|
||||
|
|
@ -101,7 +108,7 @@ extern "C" {
|
|||
void read_attr_string(hid_t obj_id, const char* name, size_t slen,
|
||||
char* buffer);
|
||||
void read_complex(hid_t obj_id, const char* name,
|
||||
double _Complex* buffer, bool indep);
|
||||
std::complex<double>* buffer, bool indep);
|
||||
void read_double(hid_t obj_id, const char* name, double* buffer,
|
||||
bool indep);
|
||||
void read_int(hid_t obj_id, const char* name, int* buffer,
|
||||
|
|
@ -142,7 +149,127 @@ template<typename T>
|
|||
struct H5TypeMap { static const hid_t type_id; };
|
||||
|
||||
//==============================================================================
|
||||
// Template functions used to provide simple interface to lower-level functions
|
||||
// Templates/overloads for read_attribute
|
||||
//==============================================================================
|
||||
|
||||
// Scalar version
|
||||
template<typename T>
|
||||
void read_attribute(hid_t obj_id, const char* name, T& buffer)
|
||||
{
|
||||
read_attr(obj_id, name, H5TypeMap<T>::type_id, &buffer);
|
||||
}
|
||||
|
||||
// vector version
|
||||
template<typename T>
|
||||
void read_attribute(hid_t obj_id, const char* name, std::vector<T>& vec)
|
||||
{
|
||||
// Get shape of attribute array
|
||||
auto shape = attribute_shape(obj_id, name);
|
||||
|
||||
// Allocate new array to read data into
|
||||
std::size_t size = 1;
|
||||
for (const auto x : shape)
|
||||
size *= x;
|
||||
vec.resize(size);
|
||||
|
||||
// Read data from attribute
|
||||
read_attr(obj_id, name, H5TypeMap<T>::type_id, vec.data());
|
||||
}
|
||||
|
||||
// Generic array version
|
||||
template<typename T>
|
||||
void read_attribute(hid_t obj_id, const char* name, xt::xarray<T>& arr)
|
||||
{
|
||||
// Get shape of attribute array
|
||||
auto shape = attribute_shape(obj_id, name);
|
||||
|
||||
// Allocate new array to read data into
|
||||
std::size_t size = 1;
|
||||
for (const auto x : shape)
|
||||
size *= x;
|
||||
T* buffer = new T[size];
|
||||
|
||||
// Read data from attribute
|
||||
read_attr(obj_id, name, H5TypeMap<T>::type_id, buffer);
|
||||
|
||||
// Adapt array into xarray
|
||||
arr = xt::adapt(buffer, size, xt::acquire_ownership(), shape);
|
||||
}
|
||||
|
||||
// overload for std::string
|
||||
inline void
|
||||
read_attribute(hid_t obj_id, const char* name, std::string& str)
|
||||
{
|
||||
// Create buffer to read data into
|
||||
auto n = attribute_typesize(obj_id, name);
|
||||
char buffer[n];
|
||||
|
||||
// Read attribute and set string
|
||||
read_attr_string(obj_id, name, n, buffer);
|
||||
str = std::string{buffer, n};
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// Templates/overloads for read_dataset
|
||||
//==============================================================================
|
||||
|
||||
template<typename T>
|
||||
void read_dataset(hid_t obj_id, const char* name, T buffer, bool indep=false)
|
||||
{
|
||||
read_dataset(obj_id, name, H5TypeMap<T>::type_id, &buffer, indep);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void read_dataset(hid_t dset, std::vector<T>& vec, bool indep=false)
|
||||
{
|
||||
// Get shape of dataset
|
||||
std::vector<hsize_t> shape = object_shape(dset);
|
||||
|
||||
// Resize vector to appropriate size
|
||||
vec.resize(shape[0]);
|
||||
|
||||
// Read data into vector
|
||||
read_dataset(dset, nullptr, H5TypeMap<T>::type_id, vec.data(), indep);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void read_dataset(hid_t obj_id, const char* name, std::vector<T>& vec, bool indep=false)
|
||||
{
|
||||
hid_t dset = open_dataset(obj_id, name);
|
||||
read_dataset(dset, vec, indep);
|
||||
close_dataset(dset);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void read_dataset(hid_t dset, xt::xarray<T>& arr, bool indep=false)
|
||||
{
|
||||
// Get shape of dataset
|
||||
std::vector<hsize_t> shape = object_shape(dset);
|
||||
|
||||
// Allocate new array to read data into
|
||||
std::size_t size = 1;
|
||||
for (const auto x : shape)
|
||||
size *= x;
|
||||
T* buffer = new T[size];
|
||||
|
||||
// Read data from attribute
|
||||
read_dataset(dset, nullptr, H5TypeMap<T>::type_id, buffer, indep);
|
||||
|
||||
// Adapt into xarray
|
||||
arr = xt::adapt(buffer, size, xt::acquire_ownership(), shape);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void read_dataset(hid_t obj_id, const char* name, xt::xarray<T>& arr, bool indep=false)
|
||||
{
|
||||
// Open dataset and read array
|
||||
hid_t dset = open_dataset(obj_id, name);
|
||||
read_dataset(dset, arr, indep);
|
||||
close_dataset(dset);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// Templates/overloads for write_attribute
|
||||
//==============================================================================
|
||||
|
||||
template<typename T> inline void
|
||||
|
|
@ -151,8 +278,8 @@ write_attribute(hid_t obj_id, const char* name, T buffer)
|
|||
write_attr(obj_id, name, 0, nullptr, H5TypeMap<T>::type_id, &buffer);
|
||||
}
|
||||
|
||||
template<> inline void
|
||||
write_attribute<const char*>(hid_t obj_id, const char* name, const char* buffer)
|
||||
inline void
|
||||
write_attribute(hid_t obj_id, const char* name, const char* buffer)
|
||||
{
|
||||
write_attr_string(obj_id, name, buffer);
|
||||
}
|
||||
|
|
@ -164,14 +291,18 @@ write_attribute(hid_t obj_id, const char* name, const std::array<T, N>& buffer)
|
|||
write_attr(obj_id, 1, dims, name, H5TypeMap<T>::type_id, buffer.data());
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// Templates/overloads for write_dataset
|
||||
//==============================================================================
|
||||
|
||||
template<typename T> inline void
|
||||
write_dataset(hid_t obj_id, const char* name, T buffer)
|
||||
{
|
||||
write_dataset(obj_id, 0, nullptr, name, H5TypeMap<T>::type_id, &buffer, false);
|
||||
}
|
||||
|
||||
template<> inline void
|
||||
write_dataset<const char*>(hid_t obj_id, const char* name, const char* buffer)
|
||||
inline void
|
||||
write_dataset(hid_t obj_id, const char* name, const char* buffer)
|
||||
{
|
||||
write_string(obj_id, name, buffer, false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3254,7 +3254,7 @@ contains
|
|||
! Check if the specified tally mesh exists
|
||||
if (mesh_dict % has(meshid)) then
|
||||
pl % meshlines_mesh => meshes(mesh_dict % get(meshid))
|
||||
if (meshes(meshid) % type /= LATTICE_RECT) then
|
||||
if (meshes(meshid) % type /= MESH_REGULAR) then
|
||||
call fatal_error("Non-rectangular mesh specified in &
|
||||
&meshlines for plot " // trim(to_str(pl % id)))
|
||||
end if
|
||||
|
|
|
|||
|
|
@ -650,6 +650,14 @@ void rotate_angle_c(double uvw[3], double mu, double* phi) {
|
|||
}
|
||||
|
||||
|
||||
Direction rotate_angle(Direction u, double mu, double* phi)
|
||||
{
|
||||
double uvw[] {u.x, u.y, u.z};
|
||||
rotate_angle_c(uvw, mu, phi);
|
||||
return {uvw[0], uvw[1], uvw[2]};
|
||||
}
|
||||
|
||||
|
||||
double maxwell_spectrum_c(double T) {
|
||||
// Set the random numbers
|
||||
double r1 = prn();
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
//! \file math_functions.h
|
||||
//! A collection of elementary math functions.
|
||||
|
||||
#ifndef MATH_FUNCTIONS_H
|
||||
#define MATH_FUNCTIONS_H
|
||||
#ifndef OPENMC_MATH_FUNCTIONS_H
|
||||
#define OPENMC_MATH_FUNCTIONS_H
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "constants.h"
|
||||
#include "position.h"
|
||||
#include "random_lcg.h"
|
||||
|
||||
|
||||
|
|
@ -124,6 +125,8 @@ extern "C" void calc_zn_rad_c(int n, double rho, double zn_rad[]);
|
|||
|
||||
extern "C" void rotate_angle_c(double uvw[3], double mu, double* phi);
|
||||
|
||||
Direction rotate_angle(Direction u, double mu, double* phi);
|
||||
|
||||
//==============================================================================
|
||||
//! Samples an energy from the Maxwell fission distribution based on a direct
|
||||
//! sampling scheme.
|
||||
|
|
@ -220,4 +223,4 @@ extern "C" double spline_integrate_c(int n, const double x[], const double y[],
|
|||
const double z[], double xa, double xb);
|
||||
|
||||
} // namespace openmc
|
||||
#endif // MATH_FUNCTIONS_H
|
||||
#endif // OPENMC_MATH_FUNCTIONS_H
|
||||
|
|
|
|||
|
|
@ -17,11 +17,9 @@ module nuclide_header
|
|||
FIT_T, FIT_A, FIT_F, MultipoleArray
|
||||
use message_passing
|
||||
use multipole_header, only: MultipoleArray
|
||||
use product_header, only: AngleEnergyContainer
|
||||
use random_lcg, only: prn, future_prn, prn_set_stream
|
||||
use reaction_header, only: Reaction
|
||||
use sab_header, only: SAlphaBeta, sab_tables
|
||||
use secondary_uncorrelated, only: UncorrelatedAngleEnergy
|
||||
use settings
|
||||
use stl_vector, only: VectorInt, VectorReal
|
||||
use string
|
||||
|
|
@ -642,29 +640,33 @@ contains
|
|||
if (rx % MT >= N_2N0 .and. rx % MT <= N_2NC .and. find(MTs, N_2N) /= -1) cycle
|
||||
|
||||
do t = 1, n_temperature
|
||||
j = rx % xs(t) % threshold
|
||||
n = size(rx % xs(t) % value)
|
||||
j = rx % xs_threshold(t)
|
||||
n = rx % xs_size(t)
|
||||
|
||||
! Add contribution to total cross section
|
||||
this % xs(t) % value(XS_TOTAL,j:j+n-1) = this % xs(t) % &
|
||||
value(XS_TOTAL,j:j+n-1) + rx % xs(t) % value
|
||||
do k = j, j + n - 1
|
||||
this % xs(t) % value(XS_TOTAL,k) = this % xs(t) % &
|
||||
value(XS_TOTAL,k) + rx % xs(t, k - j + 1)
|
||||
end do
|
||||
|
||||
! Calculate photon production cross section
|
||||
do k = 1, size(rx % products)
|
||||
if (rx % products(k) % particle == PHOTON) then
|
||||
do k = 1, rx % products_size()
|
||||
if (rx % product_particle(k) == PHOTON) then
|
||||
do l = 1, n
|
||||
this % xs(t) % value(XS_PHOTON_PROD,l+j-1) = &
|
||||
this % xs(t) % value(XS_PHOTON_PROD,l+j-1) + &
|
||||
rx % xs(t) % value(l) * rx % products(k) % &
|
||||
yield % evaluate(this % grid(t) % energy(l+j-1))
|
||||
rx % xs(t, l) * rx % product_yield(k, &
|
||||
this % grid(t) % energy(l+j-1))
|
||||
end do
|
||||
end if
|
||||
end do
|
||||
|
||||
! Add contribution to absorption cross section
|
||||
if (is_disappearance(rx % MT)) then
|
||||
this % xs(t) % value(XS_ABSORPTION,j:j+n-1) = this % xs(t) % &
|
||||
value(XS_ABSORPTION,j:j+n-1) + rx % xs(t) % value
|
||||
do k = j, j + n - 1
|
||||
this % xs(t) % value(XS_ABSORPTION,k) = this % xs(t) % &
|
||||
value(XS_ABSORPTION,k) + rx % xs(t, k - j + 1)
|
||||
end do
|
||||
end if
|
||||
|
||||
! Information about fission reactions
|
||||
|
|
@ -680,39 +682,20 @@ contains
|
|||
! Add contribution to fission cross section
|
||||
if (is_fission(rx % MT)) then
|
||||
this % fissionable = .true.
|
||||
this % xs(t) % value(XS_FISSION,j:j+n-1) = this % xs(t) % &
|
||||
value(XS_FISSION,j:j+n-1) + rx % xs(t) % value
|
||||
do k = j, j + n - 1
|
||||
this % xs(t) % value(XS_FISSION,k) = this % xs(t) % &
|
||||
value(XS_FISSION,k) + rx % xs(t, k - j + 1)
|
||||
|
||||
! Also need to add fission cross sections to absorption
|
||||
this % xs(t) % value(XS_ABSORPTION,j:j+n-1) = this % xs(t) % &
|
||||
value(XS_ABSORPTION,j:j+n-1) + rx % xs(t) % value
|
||||
! Also need to add fission cross sections to absorption
|
||||
this % xs(t) % value(XS_ABSORPTION,k) = this % xs(t) % &
|
||||
value(XS_ABSORPTION,k) + rx % xs(t, k - j + 1)
|
||||
end do
|
||||
|
||||
! Keep track of this reaction for easy searching later
|
||||
if (t == 1) then
|
||||
i_fission = i_fission + 1
|
||||
this % index_fission(i_fission) = i
|
||||
this % n_fission = this % n_fission + 1
|
||||
|
||||
! <<<<<<<<<<<<<<<<<<<<<<<<<<<< REMOVE THIS <<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
! Before the secondary distribution refactor, when the angle/energy
|
||||
! distribution was uncorrelated, no angle was actually sampled. With
|
||||
! the refactor, an angle is always sampled for an uncorrelated
|
||||
! distribution even when no angle distribution exists in the ACE file
|
||||
! (isotropic is assumed). To preserve the RNG stream, we explicitly
|
||||
! mark fission reactions so that we avoid the angle sampling.
|
||||
do k = 1, size(rx % products)
|
||||
if (rx % products(k) % particle == NEUTRON) then
|
||||
do m = 1, size(rx % products(k) % distribution)
|
||||
associate (aedist => rx % products(k) % distribution(m) % obj)
|
||||
select type (aedist)
|
||||
type is (UncorrelatedAngleEnergy)
|
||||
aedist % fission = .true.
|
||||
end select
|
||||
end associate
|
||||
end do
|
||||
end if
|
||||
end do
|
||||
! <<<<<<<<<<<<<<<<<<<<<<<<<<<< REMOVE THIS <<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
end if
|
||||
end if ! fission
|
||||
end do ! temperature
|
||||
|
|
@ -721,12 +704,13 @@ contains
|
|||
|
||||
! Determine number of delayed neutron precursors
|
||||
if (this % fissionable) then
|
||||
do i = 1, size(this % reactions(this % index_fission(1)) % products)
|
||||
if (this % reactions(this % index_fission(1)) % products(i) % &
|
||||
emission_mode == EMISSION_DELAYED) then
|
||||
this % n_precursor = this % n_precursor + 1
|
||||
end if
|
||||
end do
|
||||
associate (rx => this % reactions(this % index_fission(1)))
|
||||
do i = 1, rx % products_size()
|
||||
if (rx % product_emission_mode(i) == EMISSION_DELAYED) then
|
||||
this % n_precursor = this % n_precursor + 1
|
||||
end if
|
||||
end do
|
||||
end associate
|
||||
end if
|
||||
|
||||
! Calculate nu-fission cross section
|
||||
|
|
@ -761,36 +745,30 @@ contains
|
|||
|
||||
select case (emission_mode)
|
||||
case (EMISSION_PROMPT)
|
||||
associate (product => this % reactions(this % index_fission(1)) % products(1))
|
||||
nu = product % yield % evaluate(E)
|
||||
associate (rx => this % reactions(this % index_fission(1)))
|
||||
nu = rx % product_yield(1, E)
|
||||
end associate
|
||||
|
||||
case (EMISSION_DELAYED)
|
||||
if (this % n_precursor > 0) then
|
||||
if (present(group) .and. group < &
|
||||
size(this % reactions(this % index_fission(1)) % products)) then
|
||||
! If delayed group specified, determine yield immediately
|
||||
associate(p => this % reactions(this % index_fission(1)) % products(1 + group))
|
||||
nu = p % yield % evaluate(E)
|
||||
end associate
|
||||
associate(rx => this % reactions(this % index_fission(1)))
|
||||
if (present(group) .and. group < rx % products_size()) then
|
||||
! If delayed group specified, determine yield immediately
|
||||
nu = rx % product_yield(1 + group, E)
|
||||
else
|
||||
nu = ZERO
|
||||
|
||||
else
|
||||
nu = ZERO
|
||||
do i = 2, rx % products_size()
|
||||
! Skip any non-neutron products
|
||||
if (rx % product_particle(i) /= NEUTRON) exit
|
||||
|
||||
associate (rx => this % reactions(this % index_fission(1)))
|
||||
do i = 2, size(rx % products)
|
||||
associate (product => rx % products(i))
|
||||
! Skip any non-neutron products
|
||||
if (product % particle /= NEUTRON) exit
|
||||
|
||||
! Evaluate yield
|
||||
if (product % emission_mode == EMISSION_DELAYED) then
|
||||
nu = nu + product % yield % evaluate(E)
|
||||
end if
|
||||
end associate
|
||||
! Evaluate yield
|
||||
if (rx % product_emission_mode(i) == EMISSION_DELAYED) then
|
||||
nu = nu + rx % product_yield(i, E)
|
||||
end if
|
||||
end do
|
||||
end associate
|
||||
end if
|
||||
end if
|
||||
end associate
|
||||
else
|
||||
nu = ZERO
|
||||
end if
|
||||
|
|
@ -799,8 +777,8 @@ contains
|
|||
if (allocated(this % total_nu)) then
|
||||
nu = this % total_nu % evaluate(E)
|
||||
else
|
||||
associate (product => this % reactions(this % index_fission(1)) % products(1))
|
||||
nu = product % yield % evaluate(E)
|
||||
associate (rx => this % reactions(this % index_fission(1)))
|
||||
nu = rx % product_yield(1, E)
|
||||
end associate
|
||||
end if
|
||||
end select
|
||||
|
|
@ -868,6 +846,7 @@ contains
|
|||
integer :: i_high ! upper logarithmic mapping index
|
||||
integer :: i_rxn ! reaction index
|
||||
integer :: j ! index in DEPLETION_RX
|
||||
integer :: threshold ! threshold energy index
|
||||
real(8) :: f ! interp factor on nuclide energy grid
|
||||
real(8) :: kT ! temperature in eV
|
||||
real(8) :: sig_t, sig_a, sig_f ! Intermediate multipole variables
|
||||
|
|
@ -1009,10 +988,11 @@ contains
|
|||
! need to specifically check its threshold index
|
||||
i_rxn = this % reaction_index(DEPLETION_RX(1))
|
||||
if (i_rxn > 0) then
|
||||
associate (xs => this % reactions(i_rxn) % xs(i_temp))
|
||||
associate (rx => this % reactions(i_rxn))
|
||||
threshold = rx % xs_threshold(i_temp)
|
||||
micro_xs % reaction(1) = (ONE - f) * &
|
||||
xs % value(i_grid - xs % threshold + 1) + &
|
||||
f * xs % value(i_grid - xs % threshold + 2)
|
||||
rx % xs(i_temp, i_grid - threshold + 1) + &
|
||||
f * rx % xs(i_temp, i_grid - threshold + 2)
|
||||
end associate
|
||||
end if
|
||||
|
||||
|
|
@ -1022,11 +1002,12 @@ contains
|
|||
! reaction xs appropriately
|
||||
i_rxn = this % reaction_index(DEPLETION_RX(j))
|
||||
if (i_rxn > 0) then
|
||||
associate (xs => this % reactions(i_rxn) % xs(i_temp))
|
||||
if (i_grid >= xs % threshold) then
|
||||
associate (rx => this % reactions(i_rxn))
|
||||
threshold = rx % xs_threshold(i_temp)
|
||||
if (i_grid >= threshold) then
|
||||
micro_xs % reaction(j) = (ONE - f) * &
|
||||
xs % value(i_grid - xs % threshold + 1) + &
|
||||
f * xs % value(i_grid - xs % threshold + 2)
|
||||
rx % xs(i_temp, i_grid - threshold + 1) + &
|
||||
f * rx % xs(i_temp, i_grid - threshold + 2)
|
||||
elseif (j >= 4) then
|
||||
! One can show that the the threshold for (n,(x+1)n) is always
|
||||
! higher than the threshold for (n,xn). Thus, if we are below
|
||||
|
|
@ -1091,8 +1072,9 @@ contains
|
|||
f = micro_xs % interp_factor
|
||||
|
||||
if (i_temp > 0) then
|
||||
associate (xs => this % reactions(1) % xs(i_temp) % value)
|
||||
micro_xs % elastic = (ONE - f) * xs(i_grid) + f * xs(i_grid + 1)
|
||||
associate (rx => this % reactions(1))
|
||||
micro_xs % elastic = (ONE - f) * rx % xs(i_temp, i_grid) + &
|
||||
f * rx % xs(i_temp, i_grid + 1)
|
||||
end associate
|
||||
else
|
||||
! For multipole, elastic is total - absorption
|
||||
|
|
@ -1459,6 +1441,7 @@ contains
|
|||
integer :: i_energy ! index for energy
|
||||
integer :: i_low ! band index at lower bounding energy
|
||||
integer :: i_up ! band index at upper bounding energy
|
||||
integer :: threshold ! threshold energy index
|
||||
real(8) :: f ! interpolation factor
|
||||
real(8) :: r ! pseudo-random number
|
||||
real(8) :: elastic ! elastic cross section
|
||||
|
|
@ -1551,10 +1534,11 @@ contains
|
|||
f = micro_xs % interp_factor
|
||||
|
||||
! Determine inelastic scattering cross section
|
||||
associate (xs => this % reactions(this % urr_inelastic) % xs(i_temp))
|
||||
if (i_energy >= xs % threshold) then
|
||||
inelastic = (ONE - f) * xs % value(i_energy - xs % threshold + 1) + &
|
||||
f * xs % value(i_energy - xs % threshold + 2)
|
||||
associate (rx => this % reactions(this % urr_inelastic))
|
||||
threshold = rx % xs_threshold(i_temp)
|
||||
if (i_energy >= threshold) then
|
||||
inelastic = (ONE - f) * rx % xs(i_temp, i_energy - threshold + 1) + &
|
||||
f * rx % xs(i_temp, i_energy - threshold + 2)
|
||||
end if
|
||||
end associate
|
||||
end if
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ Particle::initialize()
|
|||
clear();
|
||||
|
||||
// Set particle to neutron that's alive
|
||||
type = NEUTRON;
|
||||
type = static_cast<int>(ParticleType::neutron);
|
||||
alive = true;
|
||||
|
||||
// clear attributes
|
||||
|
|
|
|||
|
|
@ -15,12 +15,27 @@ namespace openmc {
|
|||
// Constants
|
||||
//==============================================================================
|
||||
|
||||
// Since cross section libraries come with different numbers of delayed groups
|
||||
// (e.g. ENDF/B-VII.1 has 6 and JEFF 3.1.1 has 8 delayed groups) and we don't
|
||||
// yet know what cross section library is being used when the tallies.xml file
|
||||
// is read in, we want to have an upper bound on the size of the array we
|
||||
// use to store the bins for delayed group tallies.
|
||||
constexpr int MAX_DELAYED_GROUPS {8};
|
||||
|
||||
// Maximum number of secondary particles created
|
||||
constexpr int MAX_SECONDARY {1000};
|
||||
constexpr int NEUTRON {1};
|
||||
|
||||
// Maximum number of lost particles
|
||||
constexpr int MAX_LOST_PARTICLES {10};
|
||||
|
||||
// Maximum number of lost particles, relative to the total number of particles
|
||||
constexpr double REL_MAX_LOST_PARTICLES {1.0e-6};
|
||||
|
||||
//! Particle types
|
||||
enum class ParticleType {
|
||||
neutron, photon, electron, positron
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
|
||||
struct LocalCoord {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ module physics
|
|||
use random_lcg, only: prn, advance_prn_seed, prn_set_stream
|
||||
use reaction_header, only: Reaction
|
||||
use sab_header, only: sab_tables
|
||||
use secondary_uncorrelated, only: UncorrelatedAngleEnergy
|
||||
use settings
|
||||
use simulation_header
|
||||
use string, only: to_str
|
||||
|
|
@ -506,6 +505,7 @@ contains
|
|||
integer :: i
|
||||
integer :: i_grid
|
||||
integer :: i_temp
|
||||
integer :: threshold
|
||||
real(8) :: f
|
||||
real(8) :: prob
|
||||
real(8) :: cutoff
|
||||
|
|
@ -545,13 +545,14 @@ contains
|
|||
FISSION_REACTION_LOOP: do i = 1, nuc % n_fission
|
||||
i_reaction = nuc % index_fission(i)
|
||||
|
||||
associate (xs => nuc % reactions(i_reaction) % xs(i_temp))
|
||||
associate (rx => nuc % reactions(i_reaction))
|
||||
! if energy is below threshold for this reaction, skip it
|
||||
if (i_grid < xs % threshold) cycle
|
||||
threshold = rx % xs_threshold(i_temp)
|
||||
if (i_grid < threshold) cycle
|
||||
|
||||
! add to cumulative probability
|
||||
prob = prob + ((ONE - f) * xs % value(i_grid - xs % threshold + 1) &
|
||||
+ f*(xs % value(i_grid - xs % threshold + 2)))
|
||||
prob = prob + ((ONE - f) * rx % xs(i_temp, i_grid - threshold + 1) &
|
||||
+ f*(rx % xs(i_temp, i_grid - threshold + 2)))
|
||||
end associate
|
||||
|
||||
! Create fission bank sites if fission occurs
|
||||
|
|
@ -593,17 +594,17 @@ contains
|
|||
! Loop through each reaction type
|
||||
REACTION_LOOP: do i_reaction = 1, size(nuc % reactions)
|
||||
associate (rx => nuc % reactions(i_reaction))
|
||||
threshold = rx % xs(i_temp) % threshold
|
||||
threshold = rx % xs_threshold(i_temp)
|
||||
|
||||
! if energy is below threshold for this reaction, skip it
|
||||
if (i_grid < threshold) cycle
|
||||
|
||||
do i_product = 1, size(rx % products)
|
||||
if (rx % products(i_product) % particle == PHOTON) then
|
||||
do i_product = 1, rx % products_size()
|
||||
if (rx % product_particle(i_product) == PHOTON) then
|
||||
! add to cumulative probability
|
||||
yield = rx % products(i_product) % yield % evaluate(E)
|
||||
prob = prob + ((ONE - f) * rx % xs(i_temp) % value(i_grid - threshold + 1) &
|
||||
+ f*(rx % xs(i_temp) % value(i_grid - threshold + 2))) * yield
|
||||
yield = rx % product_yield(i_product, E)
|
||||
prob = prob + ((ONE - f) * rx % xs(i_temp, i_grid - threshold + 1) &
|
||||
+ f*(rx % xs(i_temp, i_grid - threshold + 2))) * yield
|
||||
|
||||
if (prob > cutoff) return
|
||||
last_valid_reaction = i_reaction
|
||||
|
|
@ -672,6 +673,7 @@ contains
|
|||
integer :: j
|
||||
integer :: i_temp
|
||||
integer :: i_grid
|
||||
integer :: threshold
|
||||
real(8) :: f
|
||||
real(8) :: prob
|
||||
real(8) :: cutoff
|
||||
|
|
@ -750,14 +752,14 @@ contains
|
|||
&// trim(nuc % name))
|
||||
end if
|
||||
|
||||
associate (rx => nuc % reactions(i), &
|
||||
xs => nuc % reactions(i) % xs(i_temp))
|
||||
associate (rx => nuc % reactions(i))
|
||||
! if energy is below threshold for this reaction, skip it
|
||||
if (i_grid < xs % threshold) cycle
|
||||
threshold = rx % xs_threshold(i_temp)
|
||||
if (i_grid < threshold) cycle
|
||||
|
||||
! add to cumulative probability
|
||||
prob = prob + ((ONE - f)*xs % value(i_grid - xs % threshold + 1) &
|
||||
+ f*(xs % value(i_grid - xs % threshold + 2)))
|
||||
prob = prob + ((ONE - f)*rx % xs(i_temp, i_grid - threshold + 1) &
|
||||
+ f*(rx % xs(i_temp, i_grid - threshold + 2)))
|
||||
end associate
|
||||
end do
|
||||
|
||||
|
|
@ -839,14 +841,7 @@ contains
|
|||
vel = sqrt(dot_product(v_n, v_n))
|
||||
|
||||
! Sample scattering angle
|
||||
select type (dist => rxn % products(1) % distribution(1) % obj)
|
||||
type is (UncorrelatedAngleEnergy)
|
||||
if (allocated(dist % angle % energy)) then
|
||||
mu_cm = dist % angle % sample(E)
|
||||
else
|
||||
mu_cm = TWO*prn() - ONE
|
||||
end if
|
||||
end select
|
||||
mu_cm = rxn % sample_elastic_mu(E)
|
||||
|
||||
! Determine direction cosines in CM
|
||||
uvw_cm = v_n/vel
|
||||
|
|
@ -1581,7 +1576,7 @@ contains
|
|||
do group = 1, nuc % n_precursor
|
||||
|
||||
! determine delayed neutron precursor yield for group j
|
||||
yield = rxn % products(1 + group) % yield % evaluate(E_in)
|
||||
yield = rxn % product_yield(1 + group, E_in)
|
||||
|
||||
! Check if this group is sampled
|
||||
prob = prob + yield
|
||||
|
|
@ -1600,7 +1595,7 @@ contains
|
|||
do
|
||||
! sample from energy/angle distribution -- note that mu has already been
|
||||
! sampled above and doesn't need to be resampled
|
||||
call rxn % products(1 + group) % sample(E_in, site % E, mu)
|
||||
call rxn % product_sample(1 + group, E_in, site % E, mu)
|
||||
|
||||
! resample if energy is greater than maximum neutron energy
|
||||
if (site % E < energy_max(NEUTRON)) exit
|
||||
|
|
@ -1624,7 +1619,7 @@ contains
|
|||
! sample from prompt neutron energy distribution
|
||||
n_sample = 0
|
||||
do
|
||||
call rxn % products(1) % sample(E_in, site % E, mu)
|
||||
call rxn % product_sample(1, E_in, site % E, mu)
|
||||
|
||||
! resample if energy is greater than maximum neutron energy
|
||||
if (site % E < energy_max(NEUTRON)) exit
|
||||
|
|
@ -1663,7 +1658,7 @@ contains
|
|||
E_in = p % E
|
||||
|
||||
! sample outgoing energy and scattering cosine
|
||||
call rxn % products(1) % sample(E_in, E, mu)
|
||||
call rxn % product_sample(1, E_in, E, mu)
|
||||
|
||||
! if scattering system is in center-of-mass, transfer cosine of scattering
|
||||
! angle and outgoing energy from CM to LAB
|
||||
|
|
@ -1692,7 +1687,7 @@ contains
|
|||
p % coord(1) % uvw = rotate_angle(p % coord(1) % uvw, mu)
|
||||
|
||||
! evaluate yield
|
||||
yield = rxn % products(1) % yield % evaluate(E_in)
|
||||
yield = rxn % product_yield(1, E_in)
|
||||
if (mod(yield, ONE) == ZERO) then
|
||||
! If yield is integral, create exactly that many secondary particles
|
||||
do i = 1, nint(yield) - 1
|
||||
|
|
@ -1740,8 +1735,8 @@ contains
|
|||
call sample_photon_product(i_nuclide, p % E, i_reaction, i_product)
|
||||
|
||||
! Sample the outgoing energy and angle
|
||||
call nuclides(i_nuclide) % reactions(i_reaction) % products(i_product) &
|
||||
% sample(p % E, E, mu)
|
||||
call nuclides(i_nuclide) % reactions(i_reaction) % &
|
||||
product_sample(i_product, p % E, E, mu)
|
||||
|
||||
! Sample the new direction
|
||||
uvw = rotate_angle(p % coord(1) % uvw, mu)
|
||||
|
|
|
|||
|
|
@ -1,153 +0,0 @@
|
|||
module product_header
|
||||
|
||||
use angleenergy_header, only: AngleEnergyContainer
|
||||
use constants, only: ZERO, MAX_WORD_LEN, EMISSION_PROMPT, EMISSION_DELAYED, &
|
||||
EMISSION_TOTAL, NEUTRON, PHOTON
|
||||
use endf_header, only: Tabulated1D, Function1D, Polynomial
|
||||
use hdf5_interface, only: read_attribute, open_group, close_group, &
|
||||
open_dataset, close_dataset, read_dataset, HID_T
|
||||
use random_lcg, only: prn
|
||||
use secondary_correlated, only: CorrelatedAngleEnergy
|
||||
use secondary_kalbach, only: KalbachMann
|
||||
use secondary_nbody, only: NBodyPhaseSpace
|
||||
use secondary_uncorrelated, only: UncorrelatedAngleEnergy
|
||||
use string, only: to_str
|
||||
|
||||
!===============================================================================
|
||||
! REACTIONPRODUCT stores a data for a reaction product including its yield and
|
||||
! angle-energy distributions, each of which has a given probability of occurring
|
||||
! for a given incoming energy. In general, most products only have one
|
||||
! angle-energy distribution, but for some cases (e.g., (n,2n) in certain
|
||||
! nuclides) multiple distinct distributions exist.
|
||||
!===============================================================================
|
||||
|
||||
type :: ReactionProduct
|
||||
integer :: particle
|
||||
integer :: emission_mode ! prompt, delayed, or total emission
|
||||
real(8) :: decay_rate ! Decay rate for delayed neutron precursors
|
||||
class(Function1D), pointer :: yield => null() ! Energy-dependent neutron yield
|
||||
type(Tabulated1D), allocatable :: applicability(:)
|
||||
type(AngleEnergyContainer), allocatable :: distribution(:)
|
||||
contains
|
||||
procedure :: sample => reactionproduct_sample
|
||||
procedure :: from_hdf5 => reactionproduct_from_hdf5
|
||||
end type ReactionProduct
|
||||
|
||||
contains
|
||||
|
||||
subroutine reactionproduct_sample(this, E_in, E_out, mu)
|
||||
class(ReactionProduct), intent(in) :: this
|
||||
real(8), intent(in) :: E_in ! incoming energy
|
||||
real(8), intent(out) :: E_out ! sampled outgoing energy
|
||||
real(8), intent(out) :: mu ! sampled scattering cosine
|
||||
|
||||
integer :: i ! loop counter
|
||||
integer :: n ! number of angle-energy distributions
|
||||
real(8) :: prob ! cumulative probability
|
||||
real(8) :: c ! sampled cumulative probability
|
||||
|
||||
n = size(this%applicability)
|
||||
if (n > 1) then
|
||||
prob = ZERO
|
||||
c = prn()
|
||||
do i = 1, n
|
||||
! Determine probability that i-th energy distribution is sampled
|
||||
prob = prob + this % applicability(i) % evaluate(E_in)
|
||||
|
||||
! If i-th distribution is sampled, sample energy from the distribution
|
||||
if (c <= prob) then
|
||||
call this%distribution(i)%obj%sample(E_in, E_out, mu)
|
||||
exit
|
||||
end if
|
||||
end do
|
||||
else
|
||||
! If only one distribution is present, go ahead and sample it
|
||||
call this%distribution(1)%obj%sample(E_in, E_out, mu)
|
||||
end if
|
||||
|
||||
end subroutine reactionproduct_sample
|
||||
|
||||
subroutine reactionproduct_from_hdf5(this, group_id)
|
||||
class(ReactionProduct), intent(inout) :: this
|
||||
integer(HID_T), intent(in) :: group_id
|
||||
|
||||
integer :: i
|
||||
integer :: n
|
||||
integer(HID_T) :: dgroup
|
||||
integer(HID_T) :: app
|
||||
integer(HID_T) :: yield
|
||||
character(MAX_WORD_LEN) :: temp
|
||||
|
||||
! Read particle type
|
||||
call read_attribute(temp, group_id, 'particle')
|
||||
select case (temp)
|
||||
case ('neutron')
|
||||
this % particle = NEUTRON
|
||||
case ('photon')
|
||||
this % particle = PHOTON
|
||||
end select
|
||||
|
||||
! Read emission mode and decay rate
|
||||
call read_attribute(temp, group_id, 'emission_mode')
|
||||
select case (temp)
|
||||
case ('prompt')
|
||||
this % emission_mode = EMISSION_PROMPT
|
||||
case ('delayed')
|
||||
this % emission_mode = EMISSION_DELAYED
|
||||
case ('total')
|
||||
this % emission_mode = EMISSION_TOTAL
|
||||
end select
|
||||
|
||||
! Read decay rate for delayed emission
|
||||
if (this % emission_mode == EMISSION_DELAYED) then
|
||||
call read_attribute(this % decay_rate, group_id, 'decay_rate')
|
||||
end if
|
||||
|
||||
! Read secondary particle yield
|
||||
yield = open_dataset(group_id, 'yield')
|
||||
call read_attribute(temp, yield, 'type')
|
||||
select case (temp)
|
||||
case ('Tabulated1D')
|
||||
allocate(Tabulated1D :: this % yield)
|
||||
case ('Polynomial')
|
||||
allocate(Polynomial :: this % yield)
|
||||
end select
|
||||
call this % yield % from_hdf5(yield)
|
||||
call close_dataset(yield)
|
||||
|
||||
call read_attribute(n, group_id, 'n_distribution')
|
||||
allocate(this%applicability(n))
|
||||
allocate(this%distribution(n))
|
||||
|
||||
do i = 1, n
|
||||
dgroup = open_group(group_id, trim('distribution_' // to_str(i - 1)))
|
||||
|
||||
! Read applicability
|
||||
if (n > 1) then
|
||||
app = open_dataset(dgroup, 'applicability')
|
||||
call this%applicability(i)%from_hdf5(app)
|
||||
call close_dataset(app)
|
||||
end if
|
||||
|
||||
! Read type of distribution and allocate accordingly
|
||||
call read_attribute(temp, dgroup, 'type')
|
||||
select case (temp)
|
||||
case ('uncorrelated')
|
||||
allocate(UncorrelatedAngleEnergy :: this%distribution(i)%obj)
|
||||
case ('correlated')
|
||||
allocate(CorrelatedAngleEnergy :: this%distribution(i)%obj)
|
||||
case ('nbody')
|
||||
allocate(NBodyPhaseSpace :: this%distribution(i)%obj)
|
||||
case ('kalbach-mann')
|
||||
allocate(KalbachMann :: this%distribution(i)%obj)
|
||||
end select
|
||||
|
||||
! Read distribution data
|
||||
call this%distribution(i)%obj%from_hdf5(dgroup)
|
||||
|
||||
call close_group(dgroup)
|
||||
end do
|
||||
|
||||
end subroutine reactionproduct_from_hdf5
|
||||
|
||||
end module product_header
|
||||
161
src/reaction.cpp
Normal file
161
src/reaction.cpp
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
#include "reaction.h"
|
||||
|
||||
#include <string>
|
||||
#include <utility> // for move
|
||||
|
||||
#include "hdf5_interface.h"
|
||||
#include "endf.h"
|
||||
#include "random_lcg.h"
|
||||
#include "secondary_uncorrelated.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
Reaction::Reaction(hid_t group, const std::vector<int>& temperatures)
|
||||
{
|
||||
read_attribute(group, "Q_value", q_value_);
|
||||
read_attribute(group, "mt", mt_);
|
||||
int cm;
|
||||
read_attribute(group, "center_of_mass", cm);
|
||||
scatter_in_cm_ = (cm == 1);
|
||||
|
||||
// Read cross section and threshold_idx data
|
||||
for (auto t : temperatures) {
|
||||
// Get group corresponding to temperature
|
||||
std::string temp_str {std::to_string(t) + "K"};
|
||||
hid_t temp_group = open_group(group, temp_str.c_str());
|
||||
hid_t dset = open_dataset(temp_group, "xs");
|
||||
|
||||
// Get threshold index
|
||||
TemperatureXS xs;
|
||||
read_attribute(dset, "threshold_idx", xs.threshold);
|
||||
|
||||
// Read cross section values
|
||||
read_dataset(dset, xs.value);
|
||||
close_dataset(dset);
|
||||
close_group(temp_group);
|
||||
|
||||
// create new entry in xs vector
|
||||
xs_.push_back(std::move(xs));
|
||||
}
|
||||
|
||||
// Read products
|
||||
for (const auto& name : group_names(group)) {
|
||||
if (name.rfind("product_", 0) == 0) {
|
||||
hid_t pgroup = open_group(group, name.c_str());
|
||||
products_.emplace_back(pgroup);
|
||||
close_group(pgroup);
|
||||
}
|
||||
}
|
||||
|
||||
// <<<<<<<<<<<<<<<<<<<<<<<<<<<< REMOVE THIS <<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
// Before the secondary distribution refactor, when the angle/energy
|
||||
// distribution was uncorrelated, no angle was actually sampled. With
|
||||
// the refactor, an angle is always sampled for an uncorrelated
|
||||
// distribution even when no angle distribution exists in the ACE file
|
||||
// (isotropic is assumed). To preserve the RNG stream, we explicitly
|
||||
// mark fission reactions so that we avoid the angle sampling.
|
||||
if (is_fission(mt_)) {
|
||||
for (auto& p : products_) {
|
||||
if (p.particle_ == ParticleType::neutron) {
|
||||
for (auto& d : p.distribution_) {
|
||||
auto d_ = dynamic_cast<UncorrelatedAngleEnergy*>(d.get());
|
||||
if (d_) d_->fission() = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// <<<<<<<<<<<<<<<<<<<<<<<<<<<< REMOVE THIS <<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
// Fortran compatibility functions
|
||||
//==============================================================================
|
||||
|
||||
Reaction* reaction_from_hdf5(hid_t group, int* temperatures, int n)
|
||||
{
|
||||
std::vector<int> temps {temperatures, temperatures + n};
|
||||
return new Reaction{group, temps};
|
||||
}
|
||||
|
||||
void reaction_delete(Reaction* rx) { delete rx; }
|
||||
|
||||
int reaction_mt(Reaction* rx) { return rx->mt_; }
|
||||
|
||||
double reaction_q_value(Reaction* rx) { return rx->q_value_; }
|
||||
|
||||
bool reaction_scatter_in_cm(Reaction* rx) { return rx->scatter_in_cm_; }
|
||||
|
||||
double reaction_product_decay_rate(Reaction* rx, int product)
|
||||
{
|
||||
return rx->products_[product - 1].decay_rate_;
|
||||
}
|
||||
|
||||
int reaction_product_emission_mode(Reaction* rx, int product)
|
||||
{
|
||||
switch (rx->products_[product - 1].emission_mode_) {
|
||||
case ReactionProduct::EmissionMode::prompt:
|
||||
return 1;
|
||||
case ReactionProduct::EmissionMode::delayed:
|
||||
return 2;
|
||||
case ReactionProduct::EmissionMode::total:
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
int reaction_product_particle(Reaction* rx, int product)
|
||||
{
|
||||
switch (rx->products_[product - 1].particle_) {
|
||||
case ParticleType::neutron:
|
||||
return 1;
|
||||
case ParticleType::photon:
|
||||
return 2;
|
||||
case ParticleType::electron:
|
||||
return 3;
|
||||
case ParticleType::positron:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
void reaction_product_sample(Reaction* rx, int product, double E_in, double* E_out, double* mu)
|
||||
{
|
||||
rx->products_[product - 1].sample(E_in, *E_out, *mu);
|
||||
}
|
||||
|
||||
double reaction_product_yield(Reaction* rx, int product, double E)
|
||||
{
|
||||
return (*rx->products_[product - 1].yield_)(E);
|
||||
}
|
||||
|
||||
int reaction_products_size(Reaction* rx) { return rx->products_.size(); }
|
||||
|
||||
double reaction_xs(Reaction* rx, int temperature, int energy)
|
||||
{
|
||||
return rx->xs_[temperature - 1].value[energy - 1];
|
||||
}
|
||||
|
||||
double reaction_sample_elastic_mu(Reaction* rx, double E)
|
||||
{
|
||||
// Get elastic scattering distribution
|
||||
auto& d = rx->products_[0].distribution_[0];
|
||||
|
||||
// Check if it is an uncorrelated angle-energy distribution
|
||||
auto d_ = dynamic_cast<UncorrelatedAngleEnergy*>(d.get());
|
||||
if (d_) {
|
||||
return d_->angle().sample(E);
|
||||
} else {
|
||||
return 2.0*prn() - 1.0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int reaction_xs_size(Reaction* rx, int temperature)
|
||||
{
|
||||
return rx->xs_[temperature - 1].value.size();
|
||||
}
|
||||
|
||||
int reaction_xs_threshold(Reaction* rx, int temperature)
|
||||
{
|
||||
return rx->xs_[temperature - 1].threshold;
|
||||
}
|
||||
|
||||
}
|
||||
65
src/reaction.h
Normal file
65
src/reaction.h
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
//! \file reaction.h
|
||||
//! Data for an incident neutron reaction
|
||||
|
||||
#ifndef OPENMC_REACTION_H
|
||||
#define OPENMC_REACTION_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "hdf5.h"
|
||||
#include "reaction_product.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
//! Data for a single reaction including cross sections (possibly at multiple
|
||||
//! temperatures) and reaction products (with secondary angle-energy
|
||||
//! distributions)
|
||||
//==============================================================================
|
||||
|
||||
class Reaction {
|
||||
public:
|
||||
//! Construct reaction from HDF5 data
|
||||
//! \param[in] group HDF5 group containing reaction data
|
||||
//! \param[in] temperatures Desired temperatures for cross sections
|
||||
explicit Reaction(hid_t group, const std::vector<int>& temperatures);
|
||||
|
||||
//! Cross section at a single temperature
|
||||
struct TemperatureXS {
|
||||
int threshold;
|
||||
std::vector<double> value;
|
||||
};
|
||||
|
||||
int mt_; //!< ENDF MT value
|
||||
double q_value_; //!< Reaction Q value in [eV]
|
||||
bool scatter_in_cm_; //!< scattering system in center-of-mass?
|
||||
std::vector<TemperatureXS> xs_; //!< Cross section at each temperature
|
||||
std::vector<ReactionProduct> products_; //!< Reaction products
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
// Fortran compatibility functions
|
||||
//==============================================================================
|
||||
|
||||
extern "C" {
|
||||
Reaction* reaction_from_hdf5(hid_t group, int* temperatures, int n);
|
||||
void reaction_delete(Reaction* rx);
|
||||
int reaction_mt(Reaction* rx);
|
||||
double reaction_q_value(Reaction* rx);
|
||||
bool reaction_scatter_in_cm(Reaction* rx);
|
||||
double reaction_product_decay_rate(Reaction* rx, int product);
|
||||
int reaction_product_emission_mode(Reaction* rx, int product);
|
||||
int reaction_product_particle(Reaction* rx, int product);
|
||||
void reaction_product_sample(Reaction* rx, int product, double E_in,
|
||||
double* E_out, double* mu);
|
||||
int reaction_products_size(Reaction* rx);
|
||||
double reaction_product_yield(Reaction* rx, int product, double E);
|
||||
double reaction_sample_elastic_mu(Reaction* rx, double E);
|
||||
double reaction_xs(Reaction* xs, int temperature, int energy);
|
||||
int reaction_xs_size(Reaction* xs, int temperature);
|
||||
int reaction_xs_threshold(Reaction* xs, int temperature);
|
||||
}
|
||||
|
||||
} // namespace openmc
|
||||
|
||||
#endif // OPENMC_REACTION_H
|
||||
|
|
@ -1,83 +1,268 @@
|
|||
module reaction_header
|
||||
|
||||
use, intrinsic :: ISO_C_BINDING
|
||||
|
||||
use constants, only: MAX_WORD_LEN
|
||||
use hdf5_interface
|
||||
use product_header, only: ReactionProduct
|
||||
use stl_vector, only: VectorInt
|
||||
use string, only: to_str, starts_with
|
||||
|
||||
implicit none
|
||||
private
|
||||
|
||||
!===============================================================================
|
||||
! REACTION contains the cross-section and secondary energy and angle
|
||||
! distributions for a single reaction in a continuous-energy ACE-format table
|
||||
!===============================================================================
|
||||
|
||||
type TemperatureXS
|
||||
integer :: threshold ! Energy grid index of threshold
|
||||
real(8), allocatable :: value(:) ! Cross section values
|
||||
end type TemperatureXS
|
||||
|
||||
type Reaction
|
||||
integer :: MT ! ENDF MT value
|
||||
real(8) :: Q_value ! Reaction Q value
|
||||
logical :: scatter_in_cm ! scattering system in center-of-mass?
|
||||
type(TemperatureXS), allocatable :: xs(:)
|
||||
type(ReactionProduct), allocatable :: products(:)
|
||||
type, public :: Reaction
|
||||
type(C_PTR) :: ptr
|
||||
integer(C_INT) :: MT ! ENDF MT value
|
||||
real(C_DOUBLE) :: Q_value ! Reaction Q value
|
||||
logical(C_BOOL) :: scatter_in_cm ! scattering system in center-of-mass?
|
||||
contains
|
||||
procedure :: from_hdf5 => reaction_from_hdf5
|
||||
procedure :: from_hdf5
|
||||
procedure :: mt_
|
||||
procedure :: q_value_
|
||||
procedure :: scatter_in_cm_
|
||||
procedure :: product_decay_rate
|
||||
procedure :: product_emission_mode
|
||||
procedure :: product_particle
|
||||
procedure :: product_sample
|
||||
procedure :: product_yield
|
||||
procedure :: products_size
|
||||
procedure :: sample_elastic_mu
|
||||
procedure :: xs
|
||||
procedure :: xs_size
|
||||
procedure :: xs_threshold
|
||||
end type Reaction
|
||||
|
||||
interface
|
||||
function reaction_from_hdf5(group, temperatures, n) result(ptr) bind(C)
|
||||
import C_PTR, HID_T, C_INT
|
||||
integer(HID_T), value :: group
|
||||
integer(C_INT), intent(in) :: temperatures
|
||||
integer(C_INT), value :: n
|
||||
type(C_PTR) :: ptr
|
||||
end function
|
||||
|
||||
function reaction_mt(ptr) result(mt) bind(C)
|
||||
import C_PTR, C_INT
|
||||
type(C_PTR), value :: ptr
|
||||
integer(C_INT) :: mt
|
||||
end function
|
||||
|
||||
function reaction_q_value(ptr) result(q_value) bind(C)
|
||||
import C_PTR, C_DOUBLE
|
||||
type(C_PTR), value :: ptr
|
||||
real(C_DOUBLE) :: q_value
|
||||
end function
|
||||
|
||||
function reaction_scatter_in_cm(ptr) result(b) bind(C)
|
||||
import C_PTR, C_BOOL
|
||||
type(C_PTR), value :: ptr
|
||||
logical(C_BOOL) :: b
|
||||
end function
|
||||
|
||||
pure function reaction_product_decay_rate(ptr, product) result(rate) bind(C)
|
||||
import C_PTR, C_INT, C_DOUBLE
|
||||
type(C_PTR), value :: ptr
|
||||
integer(C_INT), value :: product
|
||||
real(C_DOUBLE) :: rate
|
||||
end function
|
||||
|
||||
pure function reaction_product_emission_mode(ptr, product) result(m) bind(C)
|
||||
import C_PTR, C_INT
|
||||
type(C_PTR), value :: ptr
|
||||
integer(C_INT), value :: product
|
||||
integer(C_INT) :: m
|
||||
end function
|
||||
|
||||
pure function reaction_product_particle(ptr, product) result(particle) bind(C)
|
||||
import C_PTR, C_INT
|
||||
type(C_PTR), value :: ptr
|
||||
integer(C_INT), value :: product
|
||||
integer(C_INT) :: particle
|
||||
end function
|
||||
|
||||
subroutine reaction_product_sample(ptr, product, E_in, E_out, mu) bind(C)
|
||||
import C_PTR, C_INT, C_DOUBLE
|
||||
type(C_PTR), value :: ptr
|
||||
integer(C_INT), value :: product
|
||||
real(C_DOUBLE), value :: E_in
|
||||
real(C_DOUBLE), intent(out) :: E_out
|
||||
real(C_DOUBLE), intent(out) :: mu
|
||||
end subroutine
|
||||
|
||||
pure function reaction_product_yield(ptr, product, E) result(val) bind(C)
|
||||
import C_PTR, C_INT, C_DOUBLE
|
||||
type(C_PTR), value :: ptr
|
||||
integer(C_INT), value :: product
|
||||
real(C_DOUBLE), value :: E
|
||||
real(C_DOUBLE) :: val
|
||||
end function
|
||||
|
||||
pure function reaction_products_size(ptr) result(sz) bind(C)
|
||||
import C_PTR, C_INT
|
||||
type(C_PTR), value :: ptr
|
||||
integer(C_INT) :: sz
|
||||
end function
|
||||
|
||||
function reaction_sample_elastic_mu(ptr, E) result(mu) bind(C)
|
||||
import C_PTR, C_INT, C_DOUBLE
|
||||
type(C_PTR), value :: ptr
|
||||
real(C_DOUBLE), value :: E
|
||||
real(C_DOUBLE) :: mu
|
||||
end function
|
||||
|
||||
function reaction_xs(ptr, temperature, energy) result(xs) bind(C)
|
||||
import C_PTR, C_INT, C_DOUBLE
|
||||
type(C_PTR), value :: ptr
|
||||
integer(C_INT), value :: temperature
|
||||
integer(C_INT), value :: energy
|
||||
real(C_DOUBLE) :: xs
|
||||
end function
|
||||
|
||||
function reaction_xs_size(ptr, temperature) result(sz) bind(C)
|
||||
import C_PTR, C_INT
|
||||
type(C_PTR), value :: ptr
|
||||
integer(C_INT), value :: temperature
|
||||
integer(C_INT) :: sz
|
||||
end function
|
||||
|
||||
function reaction_xs_threshold(ptr, temperature) result(threshold) bind(C)
|
||||
import C_PTR, C_INT
|
||||
type(C_PTR), value :: ptr
|
||||
integer(C_INT), value :: temperature
|
||||
integer(C_INT) :: threshold
|
||||
end function
|
||||
end interface
|
||||
|
||||
contains
|
||||
|
||||
subroutine reaction_from_hdf5(this, group_id, temperatures)
|
||||
subroutine from_hdf5(this, group_id, temperatures)
|
||||
class(Reaction), intent(inout) :: this
|
||||
integer(HID_T), intent(in) :: group_id
|
||||
type(VectorInt), intent(in) :: temperatures
|
||||
|
||||
integer :: i
|
||||
integer :: cm
|
||||
integer :: n_product
|
||||
integer(HID_T) :: pgroup
|
||||
integer(HID_T) :: xs, temp_group
|
||||
integer(HSIZE_T) :: dims(1)
|
||||
integer(HSIZE_T) :: j
|
||||
character(MAX_WORD_LEN) :: temp_str ! temperature dataset name, e.g. '294K'
|
||||
character(MAX_WORD_LEN), allocatable :: grp_names(:)
|
||||
integer(C_INT) :: dummy
|
||||
integer(C_INT) :: n
|
||||
|
||||
call read_attribute(this % Q_value, group_id, 'Q_value')
|
||||
call read_attribute(this % MT, group_id, 'mt')
|
||||
call read_attribute(cm, group_id, 'center_of_mass')
|
||||
this % scatter_in_cm = (cm == 1)
|
||||
n = temperatures % size()
|
||||
if (n > 0) then
|
||||
this % ptr = reaction_from_hdf5(group_id, temperatures % data(1), n)
|
||||
else
|
||||
! In this case, temperatures % data(1) doesn't exist, so we just pass a
|
||||
! dummy value
|
||||
this % ptr = reaction_from_hdf5(group_id, dummy, n)
|
||||
end if
|
||||
this % MT = reaction_mt(this % ptr)
|
||||
this % Q_value = reaction_q_value(this % ptr)
|
||||
this % scatter_in_cm = reaction_scatter_in_cm(this % ptr)
|
||||
end subroutine from_hdf5
|
||||
|
||||
! Read cross section and threshold_idx data
|
||||
allocate(this % xs(temperatures % size()))
|
||||
do i = 1, temperatures % size()
|
||||
temp_str = trim(to_str(temperatures % data(i))) // "K"
|
||||
temp_group = open_group(group_id, temp_str)
|
||||
xs = open_dataset(temp_group, 'xs')
|
||||
call read_attribute(this % xs(i) % threshold, xs, 'threshold_idx')
|
||||
call get_shape(xs, dims)
|
||||
allocate(this % xs(i) % value(dims(1)))
|
||||
call read_dataset(this % xs(i) % value, xs)
|
||||
call close_dataset(xs)
|
||||
call close_group(temp_group)
|
||||
end do
|
||||
function mt_(this) result(mt)
|
||||
class(Reaction), intent(in) :: this
|
||||
integer(C_INT) :: MT
|
||||
|
||||
! Determine number of products
|
||||
n_product = 0
|
||||
call get_groups(group_id, grp_names)
|
||||
do j = 1, size(grp_names)
|
||||
if (starts_with(grp_names(j), "product_")) n_product = n_product + 1
|
||||
end do
|
||||
mt = reaction_mt(this % ptr)
|
||||
end function
|
||||
|
||||
! Read products
|
||||
allocate(this % products(n_product))
|
||||
do i = 1, n_product
|
||||
pgroup = open_group(group_id, 'product_' // trim(to_str(i - 1)))
|
||||
call this % products(i) % from_hdf5(pgroup)
|
||||
call close_group(pgroup)
|
||||
end do
|
||||
end subroutine reaction_from_hdf5
|
||||
function q_value_(this) result(q_value)
|
||||
class(Reaction), intent(in) :: this
|
||||
real(C_DOUBLE) :: q_value
|
||||
|
||||
q_value = reaction_q_value(this % ptr)
|
||||
end function
|
||||
|
||||
function scatter_in_cm_(this) result(cm)
|
||||
class (Reaction), intent(in) :: this
|
||||
logical(C_BOOL) :: cm
|
||||
|
||||
cm = reaction_scatter_in_cm(this % ptr)
|
||||
end function
|
||||
|
||||
pure function product_decay_rate(this, product) result(rate)
|
||||
class(Reaction), intent(in) :: this
|
||||
integer(C_INT), intent(in) :: product
|
||||
real(C_DOUBLE) :: rate
|
||||
|
||||
rate = reaction_product_decay_rate(this % ptr, product)
|
||||
end function
|
||||
|
||||
pure function product_emission_mode(this, product) result(m)
|
||||
class(Reaction), intent(in) :: this
|
||||
integer(C_INT), intent(in) :: product
|
||||
integer(C_INT) :: m
|
||||
|
||||
m = reaction_product_emission_mode(this % ptr, product)
|
||||
end function
|
||||
|
||||
pure function product_particle(this, product) result(p)
|
||||
class(Reaction), intent(in) :: this
|
||||
integer(C_INT), intent(in) :: product
|
||||
integer(C_INT) :: p
|
||||
|
||||
p = reaction_product_particle(this % ptr, product)
|
||||
end function
|
||||
|
||||
subroutine product_sample(this, product, E_in, E_out, mu)
|
||||
class(Reaction), intent(in) :: this
|
||||
integer(C_INT), intent(in) :: product
|
||||
real(C_DOUBLE), intent(in) :: E_in
|
||||
real(C_DOUBLE), intent(out) :: E_out
|
||||
real(C_DOUBLE), intent(out) :: mu
|
||||
|
||||
call reaction_product_sample(this % ptr, product, E_in, E_out, mu)
|
||||
end subroutine
|
||||
|
||||
pure function product_yield(this, product, E) result(val)
|
||||
class(Reaction), intent(in) :: this
|
||||
integer(C_INT), intent(in) :: product
|
||||
real(C_DOUBLE), intent(in) :: E
|
||||
real(C_DOUBLE) :: val
|
||||
|
||||
val = reaction_product_yield(this % ptr, product, E)
|
||||
end function
|
||||
|
||||
pure function products_size(this) result(sz)
|
||||
class(Reaction), intent(in) :: this
|
||||
integer(C_INT) :: sz
|
||||
|
||||
sz = reaction_products_size(this % ptr)
|
||||
end function
|
||||
|
||||
function sample_elastic_mu(this, E) result(mu)
|
||||
class(Reaction), intent(in) :: this
|
||||
real(C_DOUBLE), intent(in) :: E
|
||||
real(C_DOUBLE) :: mu
|
||||
|
||||
mu = reaction_sample_elastic_mu(this % ptr, E)
|
||||
end function
|
||||
|
||||
function xs(this, temperature, energy) result(val)
|
||||
class(Reaction), intent(in) :: this
|
||||
integer(C_INT), intent(in) :: temperature
|
||||
integer(C_INT), intent(in) :: energy
|
||||
real(C_DOUBLE) :: val
|
||||
|
||||
val = reaction_xs(this % ptr, temperature, energy)
|
||||
end function
|
||||
|
||||
function xs_size(this, temperature) result(sz)
|
||||
class(Reaction), intent(in) :: this
|
||||
integer(C_INT) :: temperature
|
||||
integer(C_INT) :: sz
|
||||
|
||||
sz = reaction_xs_size(this % ptr, temperature)
|
||||
end function
|
||||
|
||||
function xs_threshold(this, temperature) result(val)
|
||||
class(Reaction), intent(in) :: this
|
||||
integer(C_INT), intent(in) :: temperature
|
||||
integer(C_INT) :: val
|
||||
|
||||
val = reaction_xs_threshold(this % ptr, temperature)
|
||||
end function
|
||||
|
||||
end module reaction_header
|
||||
|
|
|
|||
107
src/reaction_product.cpp
Normal file
107
src/reaction_product.cpp
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
#include "reaction_product.h"
|
||||
|
||||
#include <memory> // for unique_ptr
|
||||
#include <string> // for string
|
||||
|
||||
#include "hdf5_interface.h"
|
||||
#include "random_lcg.h"
|
||||
#include "secondary_correlated.h"
|
||||
#include "secondary_kalbach.h"
|
||||
#include "secondary_nbody.h"
|
||||
#include "secondary_uncorrelated.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
// ReactionProduct implementation
|
||||
//==============================================================================
|
||||
|
||||
ReactionProduct::ReactionProduct(hid_t group)
|
||||
{
|
||||
// Read particle type
|
||||
std::string temp;
|
||||
read_attribute(group, "particle", temp);
|
||||
if (temp == "neutron") {
|
||||
particle_ = ParticleType::neutron;
|
||||
} else if (temp == "photon") {
|
||||
particle_ = ParticleType::photon;
|
||||
}
|
||||
|
||||
// Read emission mode and decay rate
|
||||
read_attribute(group, "emission_mode", temp);
|
||||
if (temp == "prompt") {
|
||||
emission_mode_ = EmissionMode::prompt;
|
||||
} else if (temp == "delayed") {
|
||||
emission_mode_ = EmissionMode::delayed;
|
||||
} else if (temp == "total") {
|
||||
emission_mode_ = EmissionMode::total;
|
||||
}
|
||||
|
||||
// Read decay rate for delayed emission
|
||||
if (emission_mode_ == EmissionMode::delayed)
|
||||
read_attribute(group, "decay_rate", decay_rate_);
|
||||
|
||||
// Read secondary particle yield
|
||||
hid_t yield = open_dataset(group, "yield");
|
||||
read_attribute(yield, "type", temp);
|
||||
if (temp == "Tabulated1D") {
|
||||
yield_ = std::unique_ptr<Function1D>{new Tabulated1D{yield}};
|
||||
} else if (temp == "Polynomial") {
|
||||
yield_ = std::unique_ptr<Function1D>{new Polynomial{yield}};
|
||||
}
|
||||
close_dataset(yield);
|
||||
|
||||
int n;
|
||||
read_attribute(group, "n_distribution", n);
|
||||
|
||||
for (int i = 0; i < n; ++i) {
|
||||
std::string s {"distribution_"};
|
||||
s.append(std::to_string(i));
|
||||
hid_t dgroup = open_group(group, s.c_str());
|
||||
|
||||
// Read applicability
|
||||
if (n > 1) {
|
||||
hid_t app = open_dataset(dgroup, "applicability");
|
||||
applicability_.emplace_back(app);
|
||||
close_dataset(app);
|
||||
}
|
||||
|
||||
// Determine distribution type and read data
|
||||
read_attribute(dgroup, "type", temp);
|
||||
if (temp == "uncorrelated") {
|
||||
distribution_.emplace_back(new UncorrelatedAngleEnergy{dgroup});
|
||||
} else if (temp == "correlated") {
|
||||
distribution_.emplace_back(new CorrelatedAngleEnergy{dgroup});
|
||||
} else if (temp == "nbody") {
|
||||
distribution_.emplace_back(new NBodyPhaseSpace{dgroup});
|
||||
} else if (temp == "kalbach-mann") {
|
||||
distribution_.emplace_back(new KalbachMann{dgroup});
|
||||
}
|
||||
|
||||
close_group(dgroup);
|
||||
}
|
||||
}
|
||||
|
||||
void ReactionProduct::sample(double E_in, double& E_out, double& mu) const
|
||||
{
|
||||
auto n = applicability_.size();
|
||||
if (n > 1) {
|
||||
double prob = 0.0;
|
||||
double c = prn();
|
||||
for (int i = 0; i < n; ++i) {
|
||||
// Determine probability that i-th energy distribution is sampled
|
||||
prob += applicability_[i](E_in);
|
||||
|
||||
// If i-th distribution is sampled, sample energy from the distribution
|
||||
if (c <= prob) {
|
||||
distribution_[i]->sample(E_in, E_out, mu);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If only one distribution is present, go ahead and sample it
|
||||
distribution_[0]->sample(E_in, E_out, mu);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
56
src/reaction_product.h
Normal file
56
src/reaction_product.h
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
//! \file reaction_product.h
|
||||
//! Data for a reaction product
|
||||
|
||||
#ifndef OPENMC_REACTION_PRODUCT_H
|
||||
#define OPENMC_REACTION_PRODUCT_H
|
||||
|
||||
#include <memory> // for unique_ptr
|
||||
#include <vector> // for vector
|
||||
|
||||
#include "hdf5.h"
|
||||
#include "angle_energy.h"
|
||||
#include "endf.h"
|
||||
#include "particle.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
//! Data for a reaction product including its yield and angle-energy
|
||||
//! distributions, each of which has a given probability of occurring for a
|
||||
//! given incoming energy. In general, most products only have one angle-energy
|
||||
//! distribution, but for some cases (e.g., (n,2n) in certain nuclides) multiple
|
||||
//! distinct distributions exist.
|
||||
//==============================================================================
|
||||
|
||||
class ReactionProduct {
|
||||
public:
|
||||
//! Emission mode for product
|
||||
enum class EmissionMode {
|
||||
prompt, // Prompt emission of secondary particle
|
||||
total, // Delayed emission of secondary particle
|
||||
delayed // Yield represents total emission (prompt + delayed)
|
||||
};
|
||||
|
||||
using Secondary = std::unique_ptr<AngleEnergy>;
|
||||
|
||||
//! Construct reaction product from HDF5 data
|
||||
//! \param[in] group HDF5 group containing data
|
||||
explicit ReactionProduct(hid_t group);
|
||||
|
||||
//! Sample an outgoing angle and energy
|
||||
//! \param[in] E_in Incoming energy in [eV]
|
||||
//! \param[out] E_out Outgoing energy in [eV]
|
||||
//! \param[out] mu Outgoing cosine with respect to current direction
|
||||
void sample(double E_in, double& E_out, double& mu) const;
|
||||
|
||||
ParticleType particle_; //!< Particle type
|
||||
EmissionMode emission_mode_; //!< Emission mode
|
||||
double decay_rate_; //!< Decay rate (for delayed neutron precursors) in [1/s]
|
||||
std::unique_ptr<Function1D> yield_; //!< Yield as a function of energy
|
||||
std::vector<Tabulated1D> applicability_; //!< Applicability of distribution
|
||||
std::vector<Secondary> distribution_; //!< Secondary angle-energy distribution
|
||||
};
|
||||
|
||||
} // namespace opemc
|
||||
|
||||
#endif // OPENMC_REACTION_PRODUCT_H
|
||||
|
|
@ -18,6 +18,8 @@ class ScattDataTabular;
|
|||
//==============================================================================
|
||||
|
||||
class ScattData {
|
||||
public:
|
||||
virtual ~ScattData() = default;
|
||||
protected:
|
||||
//! \brief Initializes the attributes of the base class.
|
||||
void
|
||||
|
|
|
|||
23
src/search.h
Normal file
23
src/search.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
//! \file search.h
|
||||
//! Search algorithms
|
||||
|
||||
#ifndef OPENMC_SEARCH_H
|
||||
#define OPENMC_SEARCH_H
|
||||
|
||||
#include <algorithm> // for lower_bound
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//! Perform binary search
|
||||
|
||||
template<class It, class T>
|
||||
typename std::iterator_traits<It>::difference_type
|
||||
lower_bound_index(It first, It last, const T& value)
|
||||
{
|
||||
It index = std::lower_bound(first, last, value) - 1;
|
||||
return (index == last) ? -1 : index - first;
|
||||
}
|
||||
|
||||
} // namespace openmc
|
||||
|
||||
#endif // OPENMC_SEARCH_H
|
||||
244
src/secondary_correlated.cpp
Normal file
244
src/secondary_correlated.cpp
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
#include "secondary_correlated.h"
|
||||
|
||||
#include <algorithm> // for copy
|
||||
#include <cmath>
|
||||
#include <cstddef> // for size_t
|
||||
#include <iterator> // for back_inserter
|
||||
|
||||
#include "hdf5_interface.h"
|
||||
#include "xtensor/xarray.hpp"
|
||||
#include "xtensor/xview.hpp"
|
||||
#include "endf.h"
|
||||
#include "random_lcg.h"
|
||||
#include "search.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
//! CorrelatedAngleEnergy implementation
|
||||
//==============================================================================
|
||||
|
||||
CorrelatedAngleEnergy::CorrelatedAngleEnergy(hid_t group)
|
||||
{
|
||||
// Open incoming energy dataset
|
||||
hid_t dset = open_dataset(group, "energy");
|
||||
|
||||
// Get interpolation parameters
|
||||
xt::xarray<int> temp;
|
||||
read_attribute(dset, "interpolation", temp);
|
||||
|
||||
auto temp_b = xt::view(temp, 0); // view of breakpoints
|
||||
auto temp_i = xt::view(temp, 1); // view of interpolation parameters
|
||||
|
||||
std::copy(temp_b.begin(), temp_b.end(), std::back_inserter(breakpoints_));
|
||||
for (const auto i : temp_i)
|
||||
interpolation_.push_back(int2interp(i));
|
||||
n_region_ = breakpoints_.size();
|
||||
|
||||
// Get incoming energies
|
||||
read_dataset(dset, energy_);
|
||||
std::size_t n_energy = energy_.size();
|
||||
close_dataset(dset);
|
||||
|
||||
// Get outgoing energy distribution data
|
||||
dset = open_dataset(group, "energy_out");
|
||||
std::vector<int> offsets;
|
||||
std::vector<int> interp;
|
||||
std::vector<int> n_discrete;
|
||||
read_attribute(dset, "offsets", offsets);
|
||||
read_attribute(dset, "interpolation", interp);
|
||||
read_attribute(dset, "n_discrete_lines", n_discrete);
|
||||
|
||||
xt::xarray<double> eout;
|
||||
read_dataset(dset, eout);
|
||||
close_dataset(dset);
|
||||
|
||||
// Read angle distributions
|
||||
xt::xarray<double> mu;
|
||||
read_dataset(group, "mu", mu);
|
||||
|
||||
for (int i = 0; i < n_energy; ++i) {
|
||||
// Determine number of outgoing energies
|
||||
int j = offsets[i];
|
||||
int n;
|
||||
if (i < n_energy - 1) {
|
||||
n = offsets[i+1] - j;
|
||||
} else {
|
||||
n = eout.shape()[1] - j;
|
||||
}
|
||||
|
||||
// Assign interpolation scheme and number of discrete lines
|
||||
CorrTable d;
|
||||
d.interpolation = int2interp(interp[i]);
|
||||
d.n_discrete = n_discrete[i];
|
||||
|
||||
// Copy data
|
||||
d.e_out = xt::view(eout, 0, xt::range(j, j+n));
|
||||
d.p = xt::view(eout, 1, xt::range(j, j+n));
|
||||
d.c = xt::view(eout, 2, xt::range(j, j+n));
|
||||
|
||||
// To get answers that match ACE data, for now we still use the tabulated
|
||||
// CDF values that were passed through to the HDF5 library. At a later
|
||||
// time, we can remove the CDF values from the HDF5 library and
|
||||
// reconstruct them using the PDF
|
||||
if (false) {
|
||||
// Calculate cumulative distribution function -- discrete portion
|
||||
for (int k = 0; k < d.n_discrete; ++k) {
|
||||
if (k == 0) {
|
||||
d.c[k] = d.p[k];
|
||||
} else {
|
||||
d.c[k] = d.c[k-1] + d.p[k];
|
||||
}
|
||||
}
|
||||
|
||||
// Continuous portion
|
||||
for (int k = d.n_discrete; k < n; ++k) {
|
||||
if (k == d.n_discrete) {
|
||||
d.c[k] = d.c[k-1] + d.p[k];
|
||||
} else {
|
||||
if (d.interpolation == Interpolation::histogram) {
|
||||
d.c[k] = d.c[k-1] + d.p[k-1]*(d.e_out[k] - d.e_out[k-1]);
|
||||
} else if (d.interpolation == Interpolation::lin_lin) {
|
||||
d.c[k] = d.c[k-1] + 0.5*(d.p[k-1] + d.p[k]) *
|
||||
(d.e_out[k] - d.e_out[k-1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize density and distribution functions
|
||||
d.p /= d.c[n - 1];
|
||||
d.c /= d.c[n - 1];
|
||||
}
|
||||
|
||||
for (j = 0; j < n; ++j) {
|
||||
// Get interpolation scheme
|
||||
int interp_mu = std::lround(eout(3, offsets[i] + j));
|
||||
|
||||
// Determine offset and size of distribution
|
||||
int offset_mu = std::lround(eout(4, offsets[i] + j));
|
||||
int m;
|
||||
if (offsets[i] + j + 1 < eout.shape()[1]) {
|
||||
m = std::lround(eout(4, offsets[i]+j+1)) - offset_mu;
|
||||
} else {
|
||||
m = mu.shape()[1] - offset_mu;
|
||||
}
|
||||
|
||||
auto interp = int2interp(interp_mu);
|
||||
auto xs = xt::view(mu, 0, xt::range(offset_mu, offset_mu + m));
|
||||
auto ps = xt::view(mu, 1, xt::range(offset_mu, offset_mu + m));
|
||||
auto cs = xt::view(mu, 2, xt::range(offset_mu, offset_mu + m));
|
||||
|
||||
std::vector<double> x {xs.begin(), xs.end()};
|
||||
std::vector<double> p {ps.begin(), ps.end()};
|
||||
std::vector<double> c {cs.begin(), cs.end()};
|
||||
|
||||
// To get answers that match ACE data, for now we still use the tabulated
|
||||
// CDF values that were passed through to the HDF5 library. At a later
|
||||
// time, we can remove the CDF values from the HDF5 library and
|
||||
// reconstruct them using the PDF
|
||||
Tabular* mudist = new Tabular{x.data(), p.data(), m, interp, c.data()};
|
||||
|
||||
d.angle.emplace_back(mudist);
|
||||
} // outgoing energies
|
||||
|
||||
distribution_.push_back(std::move(d));
|
||||
} // incoming energies
|
||||
}
|
||||
|
||||
void CorrelatedAngleEnergy::sample(double E_in, double& E_out, double& mu) const
|
||||
{
|
||||
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< REMOVE THIS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
// Before the secondary distribution refactor, an isotropic polar cosine was
|
||||
// always sampled but then overwritten with the polar cosine sampled from the
|
||||
// correlated distribution. To preserve the random number stream, we keep
|
||||
// this dummy sampling here but can remove it later (will change answers)
|
||||
mu = 2.0*prn() - 1.0;
|
||||
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< REMOVE THIS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
|
||||
// Find energy bin and calculate interpolation factor -- if the energy is
|
||||
// outside the range of the tabulated energies, choose the first or last bins
|
||||
auto n_energy_in = energy_.size();
|
||||
int i;
|
||||
double r;
|
||||
if (E_in < energy_[0]) {
|
||||
i = 0;
|
||||
r = 0.0;
|
||||
} else if (E_in > energy_[n_energy_in - 1]) {
|
||||
i = n_energy_in - 2;
|
||||
r = 1.0;
|
||||
} else {
|
||||
i = lower_bound_index(energy_.begin(), energy_.end(), E_in);
|
||||
r = (E_in - energy_[i]) / (energy_[i+1] - energy_[i]);
|
||||
}
|
||||
|
||||
// Sample between the ith and [i+1]th bin
|
||||
int l = r > prn() ? i + 1 : i;
|
||||
|
||||
// Interpolation for energy E1 and EK
|
||||
int n_energy_out = distribution_[i].e_out.size();
|
||||
double E_i_1 = distribution_[i].e_out[0];
|
||||
double E_i_K = distribution_[i].e_out[n_energy_out - 1];
|
||||
|
||||
n_energy_out = distribution_[i+1].e_out.size();
|
||||
double E_i1_1 = distribution_[i+1].e_out[0];
|
||||
double E_i1_K = distribution_[i+1].e_out[n_energy_out - 1];
|
||||
|
||||
double E_1 = E_i_1 + r*(E_i1_1 - E_i_1);
|
||||
double E_K = E_i_K + r*(E_i1_K - E_i_K);
|
||||
|
||||
// Determine outgoing energy bin
|
||||
n_energy_out = distribution_[l].e_out.size();
|
||||
double r1 = prn();
|
||||
double c_k = distribution_[l].c[0];
|
||||
double c_k1;
|
||||
int k;
|
||||
for (k = 0; k < n_energy_out - 2; ++k) {
|
||||
c_k1 = distribution_[l].c[k+1];
|
||||
if (r1 < c_k1) break;
|
||||
c_k = c_k1;
|
||||
}
|
||||
|
||||
// Check to make sure 1 <= k <= NP - 1
|
||||
k = std::max(0, std::min(k, n_energy_out - 2));
|
||||
|
||||
double E_l_k = distribution_[l].e_out[k];
|
||||
double p_l_k = distribution_[l].p[k];
|
||||
if (distribution_[l].interpolation == Interpolation::histogram) {
|
||||
// Histogram interpolation
|
||||
if (p_l_k > 0.0) {
|
||||
E_out = E_l_k + (r1 - c_k)/p_l_k;
|
||||
} else {
|
||||
E_out = E_l_k;
|
||||
}
|
||||
|
||||
} else if (distribution_[l].interpolation == Interpolation::lin_lin) {
|
||||
// Linear-linear interpolation
|
||||
double E_l_k1 = distribution_[l].e_out[k+1];
|
||||
double p_l_k1 = distribution_[l].p[k+1];
|
||||
|
||||
double frac = (p_l_k1 - p_l_k)/(E_l_k1 - E_l_k);
|
||||
if (frac == 0.0) {
|
||||
E_out = E_l_k + (r1 - c_k)/p_l_k;
|
||||
} else {
|
||||
E_out = E_l_k + (std::sqrt(std::max(0.0, p_l_k*p_l_k +
|
||||
2.0*frac*(r1 - c_k))) - p_l_k)/frac;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Now interpolate between incident energy bins i and i + 1
|
||||
if (l == i) {
|
||||
E_out = E_1 + (E_out - E_i_1)*(E_K - E_1)/(E_i_K - E_i_1);
|
||||
} else {
|
||||
E_out = E_1 + (E_out - E_i1_1)*(E_K - E_1)/(E_i1_K - E_i1_1);
|
||||
}
|
||||
|
||||
// Find correlated angular distribution for closest outgoing energy bin
|
||||
if (r1 - c_k < c_k1 - r1) {
|
||||
mu = distribution_[l].angle[k]->sample();
|
||||
} else {
|
||||
mu = distribution_[l].angle[k + 1]->sample();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace openmc
|
||||
52
src/secondary_correlated.h
Normal file
52
src/secondary_correlated.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
//! \file secondary_correlated.h
|
||||
//! Correlated angle-energy distribution
|
||||
|
||||
#ifndef OPENMC_SECONDARY_CORRELATED_H
|
||||
#define OPENMC_SECONDARY_CORRELATED_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "hdf5.h"
|
||||
#include "xtensor/xtensor.hpp"
|
||||
#include "angle_energy.h"
|
||||
#include "endf.h"
|
||||
#include "distribution.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
//! Correlated angle-energy distribution corresponding to ACE law 61 and ENDF
|
||||
//! File 6, LAW=1, LANG!=2.
|
||||
//==============================================================================
|
||||
|
||||
class CorrelatedAngleEnergy : public AngleEnergy {
|
||||
public:
|
||||
explicit CorrelatedAngleEnergy(hid_t group);
|
||||
|
||||
//! Sample distribution for an angle and energy
|
||||
//! \param[in] E_in Incoming energy in [eV]
|
||||
//! \param[out] E_out Outgoing energy in [eV]
|
||||
//! \param[out] mu Outgoing cosine with respect to current direction
|
||||
void sample(double E_in, double& E_out, double& mu) const;
|
||||
private:
|
||||
//! Outgoing energy/angle at a single incoming energy
|
||||
struct CorrTable {
|
||||
int n_discrete; //!< Number of discrete lines
|
||||
Interpolation interpolation; //!< Interpolation law
|
||||
xt::xtensor<double, 1> e_out; //!< Outgoing energies [eV]
|
||||
xt::xtensor<double, 1> p; //!< Probability density
|
||||
xt::xtensor<double, 1> c; //!< Cumulative distribution
|
||||
std::vector<UPtrDist> angle; //!< Angle distribution
|
||||
};
|
||||
|
||||
int n_region_; //!< Number of interpolation regions
|
||||
std::vector<int> breakpoints_; //!< Breakpoints between regions
|
||||
std::vector<Interpolation> interpolation_; //!< Interpolation laws
|
||||
std::vector<double> energy_; //!< Energies [eV] at which distributions
|
||||
//!< are tabulated
|
||||
std::vector<CorrTable> distribution_; //!< Distribution at each energy
|
||||
};
|
||||
|
||||
} // namespace openmc
|
||||
|
||||
#endif // OPENMC_SECONDARY_CORRELATED_H
|
||||
|
|
@ -1,278 +0,0 @@
|
|||
module secondary_kalbach
|
||||
|
||||
use algorithm, only: binary_search
|
||||
use angleenergy_header, only: AngleEnergy
|
||||
use constants, only: ZERO, HALF, ONE, TWO, HISTOGRAM, LINEAR_LINEAR
|
||||
use hdf5_interface
|
||||
use random_lcg, only: prn
|
||||
|
||||
!===============================================================================
|
||||
! KalbachMann represents a correlated angle-energy distribution with the angular
|
||||
! distribution represented using Kalbach-Mann systematics. This corresponds to
|
||||
! ACE law 44 and ENDF File 6, LAW=1, LANG=2.
|
||||
!===============================================================================
|
||||
|
||||
type KalbachMannTable
|
||||
integer :: n_discrete
|
||||
integer :: interpolation
|
||||
real(8), allocatable :: e_out(:)
|
||||
real(8), allocatable :: p(:)
|
||||
real(8), allocatable :: c(:)
|
||||
real(8), allocatable :: r(:)
|
||||
real(8), allocatable :: a(:)
|
||||
end type KalbachMannTable
|
||||
|
||||
type, extends(AngleEnergy) :: KalbachMann
|
||||
integer :: n_region ! number of interpolation regions
|
||||
integer, allocatable :: breakpoints(:) ! breakpoints of interpolation regions
|
||||
integer, allocatable :: interpolation(:) ! interpolation region codes
|
||||
real(8), allocatable :: energy(:) ! incoming energies
|
||||
type(KalbachMannTable), allocatable :: distribution(:) ! outgoing E/mu parameters
|
||||
contains
|
||||
procedure :: sample => kalbachmann_sample
|
||||
procedure :: from_hdf5 => kalbachmann_from_hdf5
|
||||
end type KalbachMann
|
||||
|
||||
contains
|
||||
|
||||
subroutine kalbachmann_sample(this, E_in, E_out, mu)
|
||||
class(KalbachMann), intent(in) :: this
|
||||
real(8), intent(in) :: E_in ! incoming energy
|
||||
real(8), intent(out) :: E_out ! sampled outgoing energy
|
||||
real(8), intent(out) :: mu ! sampled scattering cosine
|
||||
|
||||
integer :: i, k, l ! indices
|
||||
integer :: n_energy_in ! number of incoming energies
|
||||
integer :: n_energy_out ! number of outgoing energies
|
||||
real(8) :: r ! interpolation factor on incoming energy
|
||||
real(8) :: r1 ! random number on [0,1)
|
||||
real(8) :: frac ! interpolation factor on outgoing energy
|
||||
real(8) :: E_i_1, E_i_K ! endpoints on outgoing grid i
|
||||
real(8) :: E_i1_1, E_i1_K ! endpoints on outgoing grid i+1
|
||||
real(8) :: E_1, E_K ! endpoints interpolated between i and i+1
|
||||
real(8) :: E_l_k, E_l_k1 ! adjacent E on outgoing grid l
|
||||
real(8) :: p_l_k, p_l_k1 ! adjacent p on outgoing grid l
|
||||
real(8) :: c_k, c_k1 ! cumulative probability
|
||||
real(8) :: km_r, km_a ! Kalbach-Mann parameters
|
||||
real(8) :: T
|
||||
|
||||
! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< REMOVE THIS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
! Before the secondary distribution refactor, an isotropic polar cosine was
|
||||
! always sampled but then overwritten with the polar cosine sampled from the
|
||||
! correlated distribution. To preserve the random number stream, we keep
|
||||
! this dummy sampling here but can remove it later (will change answers)
|
||||
mu = TWO*prn() - ONE
|
||||
! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< REMOVE THIS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
|
||||
! find energy bin and calculate interpolation factor -- if the energy is
|
||||
! outside the range of the tabulated energies, choose the first or last bins
|
||||
n_energy_in = size(this%energy)
|
||||
if (E_in < this%energy(1)) then
|
||||
i = 1
|
||||
r = ZERO
|
||||
elseif (E_in > this%energy(n_energy_in)) then
|
||||
i = n_energy_in - 1
|
||||
r = ONE
|
||||
else
|
||||
i = binary_search(this%energy, n_energy_in, E_in)
|
||||
r = (E_in - this%energy(i)) / &
|
||||
(this%energy(i+1) - this%energy(i))
|
||||
end if
|
||||
|
||||
! Sample between the ith and (i+1)th bin
|
||||
if (r > prn()) then
|
||||
l = i + 1
|
||||
else
|
||||
l = i
|
||||
end if
|
||||
|
||||
! interpolation for energy E1 and EK
|
||||
n_energy_out = size(this%distribution(i)%e_out)
|
||||
E_i_1 = this%distribution(i)%e_out(1)
|
||||
E_i_K = this%distribution(i)%e_out(n_energy_out)
|
||||
|
||||
n_energy_out = size(this%distribution(i+1)%e_out)
|
||||
E_i1_1 = this%distribution(i+1)%e_out(1)
|
||||
E_i1_K = this%distribution(i+1)%e_out(n_energy_out)
|
||||
|
||||
E_1 = E_i_1 + r*(E_i1_1 - E_i_1)
|
||||
E_K = E_i_K + r*(E_i1_K - E_i_K)
|
||||
|
||||
! determine outgoing energy bin
|
||||
n_energy_out = size(this%distribution(l)%e_out)
|
||||
r1 = prn()
|
||||
c_k = this%distribution(l)%c(1)
|
||||
do k = 1, n_energy_out - 1
|
||||
c_k1 = this%distribution(l)%c(k+1)
|
||||
if (r1 < c_k1) exit
|
||||
c_k = c_k1
|
||||
end do
|
||||
|
||||
! check to make sure k is <= NP - 1
|
||||
k = min(k, n_energy_out - 1)
|
||||
|
||||
E_l_k = this%distribution(l)%e_out(k)
|
||||
p_l_k = this%distribution(l)%p(k)
|
||||
if (this%distribution(l)%interpolation == HISTOGRAM) then
|
||||
! Histogram interpolation
|
||||
if (p_l_k > ZERO) then
|
||||
E_out = E_l_k + (r1 - c_k)/p_l_k
|
||||
else
|
||||
E_out = E_l_k
|
||||
end if
|
||||
|
||||
! Determine Kalbach-Mann parameters
|
||||
km_r = this%distribution(l)%r(k)
|
||||
km_a = this%distribution(l)%a(k)
|
||||
|
||||
elseif (this%distribution(l)%interpolation == LINEAR_LINEAR) then
|
||||
! Linear-linear interpolation
|
||||
E_l_k1 = this%distribution(l)%e_out(k+1)
|
||||
p_l_k1 = this%distribution(l)%p(k+1)
|
||||
|
||||
frac = (p_l_k1 - p_l_k)/(E_l_k1 - E_l_k)
|
||||
if (frac == ZERO) then
|
||||
E_out = E_l_k + (r1 - c_k)/p_l_k
|
||||
else
|
||||
E_out = E_l_k + (sqrt(max(ZERO, p_l_k*p_l_k + &
|
||||
TWO*frac*(r1 - c_k))) - p_l_k)/frac
|
||||
end if
|
||||
|
||||
! Determine Kalbach-Mann parameters
|
||||
km_r = this%distribution(l)%r(k) + (E_out - E_l_k)/(E_l_k1 - E_l_k) * &
|
||||
(this%distribution(l)%r(k+1) - this%distribution(l)%r(k))
|
||||
km_a = this%distribution(l)%a(k) + (E_out - E_l_k)/(E_l_k1 - E_l_k) * &
|
||||
(this%distribution(l)%a(k+1) - this%distribution(l)%a(k))
|
||||
end if
|
||||
|
||||
! Now interpolate between incident energy bins i and i + 1
|
||||
if (l == i) then
|
||||
E_out = E_1 + (E_out - E_i_1)*(E_K - E_1)/(E_i_K - E_i_1)
|
||||
else
|
||||
E_out = E_1 + (E_out - E_i1_1)*(E_K - E_1)/(E_i1_K - E_i1_1)
|
||||
end if
|
||||
|
||||
! Sampled correlated angle from Kalbach-Mann parameters
|
||||
if (prn() > km_r) then
|
||||
T = (TWO*prn() - ONE) * sinh(km_a)
|
||||
mu = log(T + sqrt(T*T + ONE))/km_a
|
||||
else
|
||||
r1 = prn()
|
||||
mu = log(r1*exp(km_a) + (ONE - r1)*exp(-km_a))/km_a
|
||||
end if
|
||||
|
||||
end subroutine kalbachmann_sample
|
||||
|
||||
subroutine kalbachmann_from_hdf5(this, group_id)
|
||||
class(KalbachMann), intent(inout) :: this
|
||||
integer(HID_T), intent(in) :: group_id
|
||||
|
||||
integer :: i, j, k
|
||||
integer :: n
|
||||
integer :: n_energy
|
||||
integer(HID_T) :: dset_id
|
||||
integer(HSIZE_T) :: dims(1), dims2(2)
|
||||
integer, allocatable :: temp(:,:)
|
||||
integer, allocatable :: offsets(:)
|
||||
integer, allocatable :: interp(:)
|
||||
integer, allocatable :: n_discrete(:)
|
||||
real(8), allocatable :: eout(:,:)
|
||||
|
||||
! Open incoming energy dataset
|
||||
dset_id = open_dataset(group_id, 'energy')
|
||||
|
||||
! Get interpolation parameters
|
||||
call read_attribute(temp, dset_id, 'interpolation')
|
||||
allocate(this%breakpoints(size(temp, 1)))
|
||||
allocate(this%interpolation(size(temp, 1)))
|
||||
this%breakpoints(:) = temp(:, 1)
|
||||
this%interpolation(:) = temp(:, 2)
|
||||
this%n_region = size(this%breakpoints)
|
||||
|
||||
! Get incoming energies
|
||||
call get_shape(dset_id, dims)
|
||||
n_energy = int(dims(1), 4)
|
||||
allocate(this%energy(n_energy))
|
||||
allocate(this%distribution(n_energy))
|
||||
call read_dataset(this%energy, dset_id)
|
||||
call close_dataset(dset_id)
|
||||
|
||||
! Get outgoing energy distribution data
|
||||
dset_id = open_dataset(group_id, 'distribution')
|
||||
call read_attribute(offsets, dset_id, 'offsets')
|
||||
call read_attribute(interp, dset_id, 'interpolation')
|
||||
call read_attribute(n_discrete, dset_id, 'n_discrete_lines')
|
||||
call get_shape(dset_id, dims2)
|
||||
allocate(eout(dims2(1), dims2(2)))
|
||||
call read_dataset(eout, dset_id)
|
||||
call close_dataset(dset_id)
|
||||
|
||||
do i = 1, n_energy
|
||||
! Determine number of outgoing energies
|
||||
j = offsets(i)
|
||||
if (i < n_energy) then
|
||||
n = offsets(i+1) - j
|
||||
else
|
||||
n = size(eout, 1) - j
|
||||
end if
|
||||
|
||||
associate (d => this%distribution(i))
|
||||
! Assign interpolation scheme and number of discrete lines
|
||||
d % interpolation = interp(i)
|
||||
d % n_discrete = n_discrete(i)
|
||||
|
||||
! Allocate arrays for energies and PDF/CDF
|
||||
allocate(d % e_out(n))
|
||||
allocate(d % p(n))
|
||||
allocate(d % c(n))
|
||||
allocate(d % r(n))
|
||||
allocate(d % a(n))
|
||||
|
||||
! Copy data
|
||||
d % e_out(:) = eout(j+1:j+n, 1)
|
||||
d % p(:) = eout(j+1:j+n, 2)
|
||||
d % c(:) = eout(j+1:j+n, 3)
|
||||
d % r(:) = eout(j+1:j+n, 4)
|
||||
d % a(:) = eout(j+1:j+n, 5)
|
||||
|
||||
|
||||
! To get answers that match ACE data, for now we still use the tabulated
|
||||
! CDF values that were passed through to the HDF5 library. At a later
|
||||
! time, we can remove the CDF values from the HDF5 library and
|
||||
! reconstruct them using the PDF
|
||||
if (.false.) then
|
||||
! Calculate cumulative distribution function -- discrete portion
|
||||
do k = 1, d % n_discrete
|
||||
if (k == 1) then
|
||||
d % c(k) = d % p(k)
|
||||
else
|
||||
d % c(k) = d % c(k-1) + d % p(k)
|
||||
end if
|
||||
end do
|
||||
|
||||
! Continuous portion
|
||||
do k = d % n_discrete + 1, n
|
||||
if (k == d % n_discrete + 1) then
|
||||
d % c(k) = sum(d % p(1:d % n_discrete))
|
||||
else
|
||||
if (d % interpolation == HISTOGRAM) then
|
||||
d % c(k) = d % c(k-1) + d % p(k-1) * &
|
||||
(d % e_out(k) - d % e_out(k-1))
|
||||
elseif (d % interpolation == LINEAR_LINEAR) then
|
||||
d % c(k) = d % c(k-1) + HALF*(d % p(k-1) + d % p(k)) * &
|
||||
(d % e_out(k) - d % e_out(k-1))
|
||||
end if
|
||||
end if
|
||||
end do
|
||||
|
||||
! Normalize density and distribution functions
|
||||
d % p(:) = d % p(:)/d % c(n)
|
||||
d % c(:) = d % c(:)/d % c(n)
|
||||
end if
|
||||
end associate
|
||||
|
||||
j = j + n
|
||||
end do
|
||||
end subroutine kalbachmann_from_hdf5
|
||||
|
||||
end module secondary_kalbach
|
||||
223
src/secondary_kalbach.cpp
Normal file
223
src/secondary_kalbach.cpp
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
#include "secondary_kalbach.h"
|
||||
|
||||
#include <algorithm> // for copy, move
|
||||
#include <cmath> // for log, sqrt, sinh
|
||||
#include <cstddef> // for size_t
|
||||
#include <iterator> // for back_inserter
|
||||
#include <vector>
|
||||
|
||||
#include "xtensor/xarray.hpp"
|
||||
#include "xtensor/xview.hpp"
|
||||
#include "hdf5_interface.h"
|
||||
#include "random_lcg.h"
|
||||
#include "search.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
//! KalbachMann implementation
|
||||
//==============================================================================
|
||||
|
||||
KalbachMann::KalbachMann(hid_t group)
|
||||
{
|
||||
// Open incoming energy dataset
|
||||
hid_t dset = open_dataset(group, "energy");
|
||||
|
||||
// Get interpolation parameters
|
||||
xt::xarray<int> temp;
|
||||
read_attribute(dset, "interpolation", temp);
|
||||
|
||||
auto temp_b = xt::view(temp, 0); // view of breakpoints
|
||||
auto temp_i = xt::view(temp, 1); // view of interpolation parameters
|
||||
|
||||
std::copy(temp_b.begin(), temp_b.end(), std::back_inserter(breakpoints_));
|
||||
for (const auto i : temp_i)
|
||||
interpolation_.push_back(int2interp(i));
|
||||
n_region_ = breakpoints_.size();
|
||||
|
||||
// Get incoming energies
|
||||
read_dataset(dset, energy_);
|
||||
std::size_t n_energy = energy_.size();
|
||||
close_dataset(dset);
|
||||
|
||||
// Get outgoing energy distribution data
|
||||
dset = open_dataset(group, "distribution");
|
||||
std::vector<int> offsets;
|
||||
std::vector<int> interp;
|
||||
std::vector<int> n_discrete;
|
||||
read_attribute(dset, "offsets", offsets);
|
||||
read_attribute(dset, "interpolation", interp);
|
||||
read_attribute(dset, "n_discrete_lines", n_discrete);
|
||||
|
||||
xt::xarray<double> eout;
|
||||
read_dataset(dset, eout);
|
||||
close_dataset(dset);
|
||||
|
||||
for (int i = 0; i < n_energy; ++i) {
|
||||
// Determine number of outgoing energies
|
||||
int j = offsets[i];
|
||||
int n;
|
||||
if (i < n_energy - 1) {
|
||||
n = offsets[i+1] - j;
|
||||
} else {
|
||||
n = eout.shape()[1] - j;
|
||||
}
|
||||
|
||||
// Assign interpolation scheme and number of discrete lines
|
||||
KMTable d;
|
||||
d.interpolation = int2interp(interp[i]);
|
||||
d.n_discrete = n_discrete[i];
|
||||
|
||||
// Copy data
|
||||
d.e_out = xt::view(eout, 0, xt::range(j, j+n));
|
||||
d.p = xt::view(eout, 1, xt::range(j, j+n));
|
||||
d.c = xt::view(eout, 2, xt::range(j, j+n));
|
||||
d.r = xt::view(eout, 3, xt::range(j, j+n));
|
||||
d.a = xt::view(eout, 4, xt::range(j, j+n));
|
||||
|
||||
// To get answers that match ACE data, for now we still use the tabulated
|
||||
// CDF values that were passed through to the HDF5 library. At a later
|
||||
// time, we can remove the CDF values from the HDF5 library and
|
||||
// reconstruct them using the PDF
|
||||
if (false) {
|
||||
// Calculate cumulative distribution function -- discrete portion
|
||||
for (int k = 0; k < d.n_discrete; ++k) {
|
||||
if (k == 0) {
|
||||
d.c[k] = d.p[k];
|
||||
} else {
|
||||
d.c[k] = d.c[k-1] + d.p[k];
|
||||
}
|
||||
}
|
||||
|
||||
// Continuous portion
|
||||
for (int k = d.n_discrete; k < n; ++k) {
|
||||
if (k == d.n_discrete) {
|
||||
d.c[k] = d.c[k-1] + d.p[k];
|
||||
} else {
|
||||
if (d.interpolation == Interpolation::histogram) {
|
||||
d.c[k] = d.c[k-1] + d.p[k-1]*(d.e_out[k] - d.e_out[k-1]);
|
||||
} else if (d.interpolation == Interpolation::lin_lin) {
|
||||
d.c[k] = d.c[k-1] + 0.5*(d.p[k-1] + d.p[k]) *
|
||||
(d.e_out[k] - d.e_out[k-1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize density and distribution functions
|
||||
d.p /= d.c[n - 1];
|
||||
d.c /= d.c[n - 1];
|
||||
}
|
||||
|
||||
distribution_.push_back(std::move(d));
|
||||
} // incoming energies
|
||||
}
|
||||
|
||||
void KalbachMann::sample(double E_in, double& E_out, double& mu) const
|
||||
{
|
||||
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< REMOVE THIS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
// Before the secondary distribution refactor, an isotropic polar cosine was
|
||||
// always sampled but then overwritten with the polar cosine sampled from the
|
||||
// correlated distribution. To preserve the random number stream, we keep
|
||||
// this dummy sampling here but can remove it later (will change answers)
|
||||
mu = 2.0*prn() - 1.0;
|
||||
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< REMOVE THIS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
|
||||
// Find energy bin and calculate interpolation factor -- if the energy is
|
||||
// outside the range of the tabulated energies, choose the first or last bins
|
||||
auto n_energy_in = energy_.size();
|
||||
int i;
|
||||
double r;
|
||||
if (E_in < energy_[0]) {
|
||||
i = 0;
|
||||
r = 0.0;
|
||||
} else if (E_in > energy_[n_energy_in - 1]) {
|
||||
i = n_energy_in - 2;
|
||||
r = 1.0;
|
||||
} else {
|
||||
i = lower_bound_index(energy_.begin(), energy_.end(), E_in);
|
||||
r = (E_in - energy_[i]) / (energy_[i+1] - energy_[i]);
|
||||
}
|
||||
|
||||
// Sample between the ith and [i+1]th bin
|
||||
int l = r > prn() ? i + 1 : i;
|
||||
|
||||
// Interpolation for energy E1 and EK
|
||||
int n_energy_out = distribution_[i].e_out.size();
|
||||
double E_i_1 = distribution_[i].e_out[0];
|
||||
double E_i_K = distribution_[i].e_out[n_energy_out - 1];
|
||||
|
||||
n_energy_out = distribution_[i+1].e_out.size();
|
||||
double E_i1_1 = distribution_[i+1].e_out[0];
|
||||
double E_i1_K = distribution_[i+1].e_out[n_energy_out - 1];
|
||||
|
||||
double E_1 = E_i_1 + r*(E_i1_1 - E_i_1);
|
||||
double E_K = E_i_K + r*(E_i1_K - E_i_K);
|
||||
|
||||
// Determine outgoing energy bin
|
||||
n_energy_out = distribution_[l].e_out.size();
|
||||
double r1 = prn();
|
||||
double c_k = distribution_[l].c[0];
|
||||
double c_k1;
|
||||
int k;
|
||||
for (k = 0; k < n_energy_out - 2; ++k) {
|
||||
c_k1 = distribution_[l].c[k+1];
|
||||
if (r1 < c_k1) break;
|
||||
c_k = c_k1;
|
||||
}
|
||||
|
||||
// Check to make sure 1 <= k <= NP - 1
|
||||
k = std::max(0, std::min(k, n_energy_out - 2));
|
||||
|
||||
double E_l_k = distribution_[l].e_out[k];
|
||||
double p_l_k = distribution_[l].p[k];
|
||||
double km_r, km_a;
|
||||
if (distribution_[l].interpolation == Interpolation::histogram) {
|
||||
// Histogram interpolation
|
||||
if (p_l_k > 0.0) {
|
||||
E_out = E_l_k + (r1 - c_k)/p_l_k;
|
||||
} else {
|
||||
E_out = E_l_k;
|
||||
}
|
||||
|
||||
// Determine Kalbach-Mann parameters
|
||||
km_r = distribution_[l].r[k];
|
||||
km_a = distribution_[l].a[k];
|
||||
|
||||
} else if (distribution_[l].interpolation == Interpolation::lin_lin) {
|
||||
// Linear-linear interpolation
|
||||
double E_l_k1 = distribution_[l].e_out[k+1];
|
||||
double p_l_k1 = distribution_[l].p[k+1];
|
||||
|
||||
double frac = (p_l_k1 - p_l_k)/(E_l_k1 - E_l_k);
|
||||
if (frac == 0.0) {
|
||||
E_out = E_l_k + (r1 - c_k)/p_l_k;
|
||||
} else {
|
||||
E_out = E_l_k + (std::sqrt(std::max(0.0, p_l_k*p_l_k +
|
||||
2.0*frac*(r1 - c_k))) - p_l_k)/frac;
|
||||
}
|
||||
|
||||
// Determine Kalbach-Mann parameters
|
||||
km_r = distribution_[l].r[k] + (E_out - E_l_k)/(E_l_k1 - E_l_k) *
|
||||
(distribution_[l].r[k+1] - distribution_[l].r[k]);
|
||||
km_a = distribution_[l].a[k] + (E_out - E_l_k)/(E_l_k1 - E_l_k) *
|
||||
(distribution_[l].a[k+1] - distribution_[l].a[k]);
|
||||
}
|
||||
|
||||
// Now interpolate between incident energy bins i and i + 1
|
||||
if (l == i) {
|
||||
E_out = E_1 + (E_out - E_i_1)*(E_K - E_1)/(E_i_K - E_i_1);
|
||||
} else {
|
||||
E_out = E_1 + (E_out - E_i1_1)*(E_K - E_1)/(E_i1_K - E_i1_1);
|
||||
}
|
||||
|
||||
// Sampled correlated angle from Kalbach-Mann parameters
|
||||
if (prn() > km_r) {
|
||||
double T = (2.0*prn() - 1.0) * std::sinh(km_a);
|
||||
mu = std::log(T + std::sqrt(T*T + 1.0))/km_a;
|
||||
} else {
|
||||
double r1 = prn();
|
||||
mu = std::log(r1*std::exp(km_a) + (1.0 - r1)*std::exp(-km_a))/km_a;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
54
src/secondary_kalbach.h
Normal file
54
src/secondary_kalbach.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
//! \file secondary_kalbach.h
|
||||
//! Kalbach-Mann angle-energy distribution
|
||||
|
||||
#ifndef OPENMC_SECONDARY_KALBACH_H
|
||||
#define OPENMC_SECONDARY_KALBACH_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "hdf5.h"
|
||||
#include "xtensor/xtensor.hpp"
|
||||
#include "angle_energy.h"
|
||||
#include "constants.h"
|
||||
#include "endf.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
//! Correlated angle-energy distribution with the angular distribution
|
||||
//! represented using Kalbach-Mann systematics. This corresponds to ACE law 44
|
||||
//! and ENDF File 6, LAW=1, LANG=2.
|
||||
//==============================================================================
|
||||
|
||||
class KalbachMann : public AngleEnergy {
|
||||
public:
|
||||
explicit KalbachMann(hid_t group);
|
||||
|
||||
//! Sample distribution for an angle and energy
|
||||
//! \param[in] E_in Incoming energy in [eV]
|
||||
//! \param[out] E_out Outgoing energy in [eV]
|
||||
//! \param[out] mu Outgoing cosine with respect to current direction
|
||||
void sample(double E_in, double& E_out, double& mu) const;
|
||||
private:
|
||||
//! Outgoing energy/angle at a single incoming energy
|
||||
struct KMTable {
|
||||
int n_discrete; //!< Number of discrete lines
|
||||
Interpolation interpolation; //!< Interpolation law
|
||||
xt::xtensor<double, 1> e_out; //!< Outgoing energies [eV]
|
||||
xt::xtensor<double, 1> p; //!< Probability density
|
||||
xt::xtensor<double, 1> c; //!< Cumulative distribution
|
||||
xt::xtensor<double, 1> r; //!< Pre-compound fraction
|
||||
xt::xtensor<double, 1> a; //!< Parameterized function
|
||||
};
|
||||
|
||||
int n_region_; //!< Number of interpolation regions
|
||||
std::vector<int> breakpoints_; //!< Breakpoints between regions
|
||||
std::vector<Interpolation> interpolation_; //!< Interpolation laws
|
||||
std::vector<double> energy_; //!< Energies [eV] at which distributions
|
||||
//!< are tabulated
|
||||
std::vector<KMTable> distribution_; //!< Distribution at each energy
|
||||
};
|
||||
|
||||
} // namespace openmc
|
||||
|
||||
#endif // OPENMC_SECONDARY_KALBACH_H
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
module secondary_nbody
|
||||
|
||||
use angleenergy_header, only: AngleEnergy
|
||||
use constants, only: ONE, TWO, PI
|
||||
use hdf5_interface, only: read_attribute, HID_T
|
||||
use math, only: maxwell_spectrum
|
||||
use random_lcg, only: prn
|
||||
|
||||
!===============================================================================
|
||||
! NBODYPHASESPACE gives the energy distribution for particles emitted from
|
||||
! neutron and charged-particle reactions. This corresponds to ACE law 66 and
|
||||
! ENDF File 6, LAW=6.
|
||||
!===============================================================================
|
||||
|
||||
type, extends(AngleEnergy) :: NBodyPhaseSpace
|
||||
integer :: n_bodies
|
||||
real(8) :: mass_ratio
|
||||
real(8) :: A
|
||||
real(8) :: Q
|
||||
contains
|
||||
procedure :: sample => nbody_sample
|
||||
procedure :: from_hdf5 => nbody_from_hdf5
|
||||
end type NBodyPhaseSpace
|
||||
|
||||
contains
|
||||
|
||||
subroutine nbody_sample(this, E_in, E_out, mu)
|
||||
class(NBodyPhaseSpace), intent(in) :: this
|
||||
real(8), intent(in) :: E_in ! incoming energy
|
||||
real(8), intent(out) :: E_out ! sampled outgoing energy
|
||||
real(8), intent(out) :: mu ! sampled outgoing energy
|
||||
|
||||
real(8) :: Ap ! total mass of particles in neutron masses
|
||||
real(8) :: E_max ! maximum possible COM energy
|
||||
real(8) :: x, y, v
|
||||
real(8) :: r1, r2, r3, r4, r5, r6
|
||||
|
||||
! By definition, the distribution of the angle is isotropic for an N-body
|
||||
! phase space distribution
|
||||
mu = TWO*prn() - ONE
|
||||
|
||||
! Determine E_max parameter
|
||||
Ap = this%mass_ratio
|
||||
E_max = (Ap - ONE)/Ap * (this%A/(this%A + ONE)*E_in + this%Q)
|
||||
|
||||
! x is essentially a Maxwellian distribution
|
||||
x = maxwell_spectrum(ONE)
|
||||
|
||||
select case (this%n_bodies)
|
||||
case (3)
|
||||
y = maxwell_spectrum(ONE)
|
||||
case (4)
|
||||
r1 = prn()
|
||||
r2 = prn()
|
||||
r3 = prn()
|
||||
y = -log(r1*r2*r3)
|
||||
case (5)
|
||||
r1 = prn()
|
||||
r2 = prn()
|
||||
r3 = prn()
|
||||
r4 = prn()
|
||||
r5 = prn()
|
||||
r6 = prn()
|
||||
y = -log(r1*r2*r3*r4) - log(r5) * cos(PI/TWO*r6)**2
|
||||
end select
|
||||
|
||||
! Now determine v and E_out
|
||||
v = x/(x+y)
|
||||
E_out = E_max * v
|
||||
end subroutine nbody_sample
|
||||
|
||||
subroutine nbody_from_hdf5(this, group_id)
|
||||
class(NBodyPhaseSpace), intent(inout) :: this
|
||||
integer(HID_T), intent(in) :: group_id
|
||||
|
||||
call read_attribute(this%mass_ratio, group_id, 'total_mass')
|
||||
call read_attribute(this%n_bodies, group_id, 'n_particles')
|
||||
call read_attribute(this%A, group_id, 'atomic_weight_ratio')
|
||||
call read_attribute(this%Q, group_id, 'q_value')
|
||||
end subroutine nbody_from_hdf5
|
||||
|
||||
end module secondary_nbody
|
||||
65
src/secondary_nbody.cpp
Normal file
65
src/secondary_nbody.cpp
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
#include "secondary_nbody.h"
|
||||
|
||||
#include <cmath> // for log
|
||||
|
||||
#include "constants.h"
|
||||
#include "hdf5_interface.h"
|
||||
#include "math_functions.h"
|
||||
#include "random_lcg.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
// NBodyPhaseSpace implementation
|
||||
//==============================================================================
|
||||
|
||||
NBodyPhaseSpace::NBodyPhaseSpace(hid_t group)
|
||||
{
|
||||
read_attribute(group, "n_particles", n_bodies_);
|
||||
read_attribute(group, "total_mass", mass_ratio_);
|
||||
read_attribute(group, "atomic_weight_ratio", A_);
|
||||
read_attribute(group, "q_value", Q_);
|
||||
}
|
||||
|
||||
void NBodyPhaseSpace::sample(double E_in, double& E_out, double& mu) const
|
||||
{
|
||||
// By definition, the distribution of the angle is isotropic for an N-body
|
||||
// phase space distribution
|
||||
mu = 2.0*prn() - 1.0;
|
||||
|
||||
// Determine E_max parameter
|
||||
double Ap = mass_ratio_;
|
||||
double E_max = (Ap - 1.0)/Ap * (A_/(A_ + 1.0)*E_in + Q_);
|
||||
|
||||
// x is essentially a Maxwellian distribution
|
||||
double x = maxwell_spectrum_c(1.0);
|
||||
|
||||
double y;
|
||||
double r1, r2, r3, r4, r5, r6;
|
||||
switch (n_bodies_) {
|
||||
case 3:
|
||||
y = maxwell_spectrum_c(1.0);
|
||||
break;
|
||||
case 4:
|
||||
r1 = prn();
|
||||
r2 = prn();
|
||||
r3 = prn();
|
||||
y = -std::log(r1*r2*r3);
|
||||
break;
|
||||
case 5:
|
||||
r1 = prn();
|
||||
r2 = prn();
|
||||
r3 = prn();
|
||||
r4 = prn();
|
||||
r5 = prn();
|
||||
r6 = prn();
|
||||
y = -std::log(r1*r2*r3*r4) - std::log(r5) * std::pow(std::cos(PI/2.0*r6), 2);
|
||||
break;
|
||||
}
|
||||
|
||||
// Now determine v and E_out
|
||||
double v = x/(x + y);
|
||||
E_out = E_max * v;
|
||||
}
|
||||
|
||||
} // namespace openmc
|
||||
37
src/secondary_nbody.h
Normal file
37
src/secondary_nbody.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
//! \file secondary_nbody.h
|
||||
//! N-body phase space distribution
|
||||
|
||||
#ifndef OPENMC_SECONDARY_NBODY_H
|
||||
#define OPENMC_SECONDARY_NBODY_H
|
||||
|
||||
#include "hdf5.h"
|
||||
|
||||
#include "angle_energy.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
//! Angle-energy distribution for particles emitted from neutron and
|
||||
//! charged-particle reactions. This corresponds to ACE law 66 and ENDF File 6,
|
||||
//! LAW=6.
|
||||
//==============================================================================
|
||||
|
||||
class NBodyPhaseSpace : public AngleEnergy {
|
||||
public:
|
||||
explicit NBodyPhaseSpace(hid_t group);
|
||||
|
||||
//! Sample distribution for an angle and energy
|
||||
//! \param[in] E_in Incoming energy in [eV]
|
||||
//! \param[out] E_out Outgoing energy in [eV]
|
||||
//! \param[out] mu Outgoing cosine with respect to current direction
|
||||
void sample(double E_in, double& E_out, double& mu) const;
|
||||
private:
|
||||
int n_bodies_; //!< Number of particles distributed
|
||||
double mass_ratio_; //!< Total mass of particles [neutron mass]
|
||||
double A_; //!< Atomic weight ratio
|
||||
double Q_; //!< Reaction Q-value [eV]
|
||||
};
|
||||
|
||||
} // namespace openmc
|
||||
|
||||
#endif // OPENMC_SECONDARY_NBODY_H
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
module secondary_uncorrelated
|
||||
|
||||
use angle_distribution, only: AngleDistribution
|
||||
use angleenergy_header, only: AngleEnergy
|
||||
use constants, only: ONE, TWO, MAX_WORD_LEN
|
||||
use energy_distribution, only: EnergyDistribution, LevelInelastic, &
|
||||
ContinuousTabular, MaxwellEnergy, Evaporation, WattEnergy, DiscretePhoton
|
||||
use error, only: warning
|
||||
use hdf5_interface, only: read_attribute, open_group, close_group, &
|
||||
object_exists, HID_T
|
||||
use random_lcg, only: prn
|
||||
|
||||
!===============================================================================
|
||||
! UNCORRELATEDANGLEENERGY represents an uncorrelated angle-energy
|
||||
! distribution. This corresponds to when an energy distribution is given in ENDF
|
||||
! File 5/6 and an angular distribution is given in ENDF File 4.
|
||||
!===============================================================================
|
||||
|
||||
type, extends(AngleEnergy) :: UncorrelatedAngleEnergy
|
||||
logical :: fission = .false.
|
||||
type(AngleDistribution) :: angle
|
||||
class(EnergyDistribution), allocatable :: energy
|
||||
contains
|
||||
procedure :: sample => uncorrelated_sample
|
||||
procedure :: from_hdf5 => uncorrelated_from_hdf5
|
||||
end type UncorrelatedAngleEnergy
|
||||
|
||||
contains
|
||||
|
||||
subroutine uncorrelated_sample(this, E_in, E_out, mu)
|
||||
class(UncorrelatedAngleEnergy), intent(in) :: this
|
||||
real(8), intent(in) :: E_in ! incoming energy
|
||||
real(8), intent(out) :: E_out ! sampled outgoing energy
|
||||
real(8), intent(out) :: mu ! sampled scattering cosine
|
||||
|
||||
! Sample cosine of scattering angle
|
||||
if (this%fission) then
|
||||
! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< REMOVE THIS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
! For fission, the angle is not used, so just assign a dummy value
|
||||
mu = ONE
|
||||
! <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< REMOVE THIS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
elseif (allocated(this%angle%energy)) then
|
||||
mu = this%angle%sample(E_in)
|
||||
else
|
||||
! no angle distribution given => assume isotropic for all energies
|
||||
mu = TWO*prn() - ONE
|
||||
end if
|
||||
|
||||
! Sample outgoing energy
|
||||
E_out = this%energy%sample(E_in)
|
||||
end subroutine uncorrelated_sample
|
||||
|
||||
subroutine uncorrelated_from_hdf5(this, group_id)
|
||||
class(UncorrelatedAngleEnergy), intent(inout) :: this
|
||||
integer(HID_T), intent(in) :: group_id
|
||||
|
||||
integer(HID_T) :: energy_group
|
||||
integer(HID_T) :: angle_group
|
||||
character(MAX_WORD_LEN) :: type
|
||||
|
||||
! Check if angle group is present & read
|
||||
if (object_exists(group_id, 'angle')) then
|
||||
angle_group = open_group(group_id, 'angle')
|
||||
call this%angle%from_hdf5(angle_group)
|
||||
call close_group(angle_group)
|
||||
end if
|
||||
|
||||
! Check if energy group is present & read
|
||||
if (object_exists(group_id, 'energy')) then
|
||||
energy_group = open_group(group_id, 'energy')
|
||||
call read_attribute(type, energy_group, 'type')
|
||||
select case (type)
|
||||
case ('discrete_photon')
|
||||
allocate(DiscretePhoton :: this%energy)
|
||||
case ('level')
|
||||
allocate(LevelInelastic :: this%energy)
|
||||
case ('continuous')
|
||||
allocate(ContinuousTabular :: this%energy)
|
||||
case ('maxwell')
|
||||
allocate(MaxwellEnergy :: this%energy)
|
||||
case ('evaporation')
|
||||
allocate(Evaporation :: this%energy)
|
||||
case ('watt')
|
||||
allocate(WattEnergy :: this%energy)
|
||||
case default
|
||||
call warning("Energy distribution type '" // trim(type) &
|
||||
// "' not implemented.")
|
||||
end select
|
||||
|
||||
if (allocated(this % energy)) then
|
||||
call this%energy%from_hdf5(energy_group)
|
||||
end if
|
||||
|
||||
call close_group(energy_group)
|
||||
end if
|
||||
end subroutine uncorrelated_from_hdf5
|
||||
|
||||
end module secondary_uncorrelated
|
||||
74
src/secondary_uncorrelated.cpp
Normal file
74
src/secondary_uncorrelated.cpp
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
#include "secondary_uncorrelated.h"
|
||||
|
||||
#include <sstream> // for stringstream
|
||||
#include <string> // for string
|
||||
|
||||
#include "error.h"
|
||||
#include "hdf5_interface.h"
|
||||
#include "random_lcg.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
// UncorrelatedAngleEnergy implementation
|
||||
//==============================================================================
|
||||
|
||||
UncorrelatedAngleEnergy::UncorrelatedAngleEnergy(hid_t group)
|
||||
{
|
||||
// Check if angle group is present & read
|
||||
if (object_exists(group, "angle")) {
|
||||
hid_t angle_group = open_group(group, "angle");
|
||||
angle_ = AngleDistribution{angle_group};
|
||||
close_group(angle_group);
|
||||
}
|
||||
|
||||
// Check if energy group is present & read
|
||||
if (object_exists(group, "energy")) {
|
||||
hid_t energy_group = open_group(group, "energy");
|
||||
|
||||
std::string type;
|
||||
read_attribute(energy_group, "type", type);
|
||||
using UPtrEDist = std::unique_ptr<EnergyDistribution>;
|
||||
if (type == "discrete_photon") {
|
||||
energy_ = UPtrEDist{new DiscretePhoton{energy_group}};
|
||||
} else if (type == "level") {
|
||||
energy_ = UPtrEDist{new LevelInelastic{energy_group}};
|
||||
} else if (type == "continuous") {
|
||||
energy_ = UPtrEDist{new ContinuousTabular{energy_group}};
|
||||
} else if (type == "maxwell") {
|
||||
energy_ = UPtrEDist{new MaxwellEnergy{energy_group}};
|
||||
} else if (type == "evaporation") {
|
||||
energy_ = UPtrEDist{new Evaporation{energy_group}};
|
||||
} else if (type == "watt") {
|
||||
energy_ = UPtrEDist{new WattEnergy{energy_group}};
|
||||
} else {
|
||||
std::stringstream msg;
|
||||
msg << "Energy distribution type '" << type << "' not implemented.";
|
||||
warning(msg);
|
||||
}
|
||||
close_group(energy_group);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
UncorrelatedAngleEnergy::sample(double E_in, double& E_out, double& mu) const
|
||||
{
|
||||
// Sample cosine of scattering angle
|
||||
if (fission_) {
|
||||
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< REMOVE THIS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
// For fission, the angle is not used, so just assign a dummy value
|
||||
mu = 1.0;
|
||||
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<< REMOVE THIS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
} else if (!angle_.empty()) {
|
||||
mu = angle_.sample(E_in);
|
||||
} else {
|
||||
// no angle distribution given => assume isotropic for all energies
|
||||
mu = 2.0*prn() - 1.0;
|
||||
}
|
||||
|
||||
// Sample outgoing energy
|
||||
E_out = energy_->sample(E_in);
|
||||
}
|
||||
|
||||
} // namespace openmc
|
||||
44
src/secondary_uncorrelated.h
Normal file
44
src/secondary_uncorrelated.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
//! \file secondary_uncorrelated.h
|
||||
//! Uncorrelated angle-energy distribution
|
||||
|
||||
#ifndef OPENMC_SECONDARY_UNCORRELATED_H
|
||||
#define OPENMC_SECONDARY_UNCORRELATED_H
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "hdf5.h"
|
||||
#include "angle_energy.h"
|
||||
#include "distribution_angle.h"
|
||||
#include "distribution_energy.h"
|
||||
|
||||
namespace openmc {
|
||||
|
||||
//==============================================================================
|
||||
//! Uncorrelated angle-energy distribution. This corresponds to when an energy
|
||||
//! distribution is given in ENDF File 5/6 and an angular distribution is given
|
||||
//! in ENDF File 4.
|
||||
//==============================================================================
|
||||
|
||||
class UncorrelatedAngleEnergy : public AngleEnergy {
|
||||
public:
|
||||
explicit UncorrelatedAngleEnergy(hid_t group);
|
||||
|
||||
//! Sample distribution for an angle and energy
|
||||
//! \param[in] E_in Incoming energy in [eV]
|
||||
//! \param[out] E_out Outgoing energy in [eV]
|
||||
//! \param[out] mu Outgoing cosine with respect to current direction
|
||||
void sample(double E_in, double& E_out, double& mu) const;
|
||||
|
||||
// Accessors
|
||||
AngleDistribution& angle() { return angle_; }
|
||||
bool& fission() { return fission_; }
|
||||
private:
|
||||
AngleDistribution angle_; //!< Angle distribution
|
||||
std::unique_ptr<EnergyDistribution> energy_; //!< Energy distribution
|
||||
bool fission_ {false}; //!< Whether distribution is use for fission
|
||||
};
|
||||
|
||||
} // namespace openmc
|
||||
|
||||
#endif // OPENMC_SECONDARY_UNCORRELATED_H
|
||||
|
|
@ -151,7 +151,7 @@ Surface::Surface(pugi::xml_node surf_node)
|
|||
}
|
||||
|
||||
if (check_for_node(surf_node, "boundary")) {
|
||||
std::string surf_bc = get_node_value(surf_node, "boundary");
|
||||
std::string surf_bc = get_node_value(surf_node, "boundary", true, true);
|
||||
|
||||
if (surf_bc == "transmission" || surf_bc == "transmit" ||surf_bc.empty()) {
|
||||
bc = BC_TRANSMIT;
|
||||
|
|
@ -1040,7 +1040,7 @@ read_surfaces(pugi::xml_node *node)
|
|||
int i_surf;
|
||||
for (surf_node = node->child("surface"), i_surf = 0; surf_node;
|
||||
surf_node = surf_node.next_sibling("surface"), i_surf++) {
|
||||
std::string surf_type = get_node_value(surf_node, "type");
|
||||
std::string surf_type = get_node_value(surf_node, "type", true, true);
|
||||
|
||||
if (surf_type == "x-plane") {
|
||||
surfaces_c[i_surf] = new SurfaceXPlane(surf_node);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ namespace openmc {
|
|||
// Module constant declarations (defined in .cpp)
|
||||
//==============================================================================
|
||||
|
||||
// TODO: Convert to enum
|
||||
extern "C" const int BC_TRANSMIT;
|
||||
extern "C" const int BC_VACUUM;
|
||||
extern "C" const int BC_REFLECT;
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ contains
|
|||
integer :: k ! loop index for bank sites
|
||||
integer :: d_bin ! delayed group bin index
|
||||
integer :: dg_filter ! index of delayed group filter
|
||||
integer :: threshold ! threshold energy index
|
||||
real(8) :: yield ! delayed neutron yield
|
||||
real(8) :: atom_density_ ! atom/b-cm
|
||||
real(8) :: f ! interpolation factor
|
||||
|
|
@ -227,7 +228,7 @@ contains
|
|||
! Get yield and apply to score
|
||||
associate (rxn => nuclides(p % event_nuclide) % reactions(m))
|
||||
score = p % last_wgt * flux &
|
||||
* rxn % products(1) % yield % evaluate(E)
|
||||
* rxn % product_yield(1, E)
|
||||
end associate
|
||||
end if
|
||||
|
||||
|
|
@ -633,7 +634,7 @@ contains
|
|||
score = p % absorb_wgt * yield * &
|
||||
micro_xs(p % event_nuclide) % fission &
|
||||
/ micro_xs(p % event_nuclide) % absorption &
|
||||
* rxn % products(1 + d) % decay_rate * flux
|
||||
* rxn % product_decay_rate(1 + d) * flux
|
||||
end associate
|
||||
|
||||
! Tally to bin
|
||||
|
|
@ -657,9 +658,8 @@ contains
|
|||
! rxn % products array to be exceeded. Hence, we use the size
|
||||
! of this array and not the MAX_DELAYED_GROUPS constant for
|
||||
! this loop.
|
||||
do d = 1, size(rxn % products) - 2
|
||||
|
||||
score = score + rxn % products(1 + d) % decay_rate * &
|
||||
do d = 1, rxn % products_size() - 2
|
||||
score = score + rxn % product_decay_rate(1 + d) * &
|
||||
p % absorb_wgt &
|
||||
* micro_xs(p % event_nuclide) % fission &
|
||||
* nuclides(p % event_nuclide) % &
|
||||
|
|
@ -699,7 +699,7 @@ contains
|
|||
|
||||
! determine score based on bank site weight and keff.
|
||||
score = score + keff * fission_bank(n_bank - p % n_bank + k) &
|
||||
% wgt * rxn % products(1 + g) % decay_rate * flux
|
||||
% wgt * rxn % product_decay_rate(1 + g) * flux
|
||||
end associate
|
||||
|
||||
! if the delayed group filter is present, tally to corresponding
|
||||
|
|
@ -755,7 +755,7 @@ contains
|
|||
|
||||
! Compute the score and tally to bin
|
||||
score = micro_xs(i_nuclide) % fission * yield * flux * &
|
||||
atom_density * rxn % products(1 + d) % decay_rate
|
||||
atom_density * rxn % product_decay_rate(1 + d)
|
||||
end associate
|
||||
|
||||
! Tally to bin
|
||||
|
|
@ -778,11 +778,10 @@ contains
|
|||
! groups since this could cause the range of the rxn % products
|
||||
! array to be exceeded. Hence, we use the size of this array
|
||||
! and not the MAX_DELAYED_GROUPS constant for this loop.
|
||||
do d = 1, size(rxn % products) - 2
|
||||
|
||||
do d = 1, rxn % products_size() - 2
|
||||
score = score + micro_xs(i_nuclide) % fission * flux * &
|
||||
nuclides(i_nuclide) % nu(E, EMISSION_DELAYED) * &
|
||||
atom_density * rxn % products(1 + d) % decay_rate
|
||||
atom_density * rxn % product_decay_rate(1 + d)
|
||||
end do
|
||||
end associate
|
||||
end if
|
||||
|
|
@ -824,7 +823,7 @@ contains
|
|||
! Compute the score
|
||||
score = micro_xs(i_nuc) % fission * yield * flux * &
|
||||
atom_density_ &
|
||||
* rxn % products(1 + d) % decay_rate
|
||||
* rxn % product_decay_rate(1 + d)
|
||||
end associate
|
||||
|
||||
! Tally to bin
|
||||
|
|
@ -860,13 +859,13 @@ contains
|
|||
! rxn % products array to be exceeded. Hence, we use the
|
||||
! size of this array and not the MAX_DELAYED_GROUPS
|
||||
! constant for this loop.
|
||||
do d = 1, size(rxn % products) - 2
|
||||
do d = 1, rxn % products_size() - 2
|
||||
|
||||
! Accumulate the contribution from each nuclide
|
||||
score = score + micro_xs(i_nuc) % fission &
|
||||
* nuclides(i_nuc) % nu(E, EMISSION_DELAYED) &
|
||||
* atom_density_ * flux &
|
||||
* rxn % products(1 + d) % decay_rate
|
||||
* rxn % product_decay_rate(1 + d)
|
||||
end do
|
||||
end associate
|
||||
end if
|
||||
|
|
@ -1132,12 +1131,12 @@ contains
|
|||
i_energy = micro_xs(i_nuclide) % index_grid
|
||||
f = micro_xs(i_nuclide) % interp_factor
|
||||
|
||||
associate (xs => nuclides(i_nuclide) % reactions(m) &
|
||||
% xs(i_temp))
|
||||
if (i_energy >= xs % threshold) then
|
||||
score = ((ONE - f) * xs % value(i_energy - &
|
||||
xs % threshold + 1) + f * xs % value(i_energy - &
|
||||
xs % threshold + 2)) * atom_density * flux
|
||||
associate (rx => nuclides(i_nuclide) % reactions(m))
|
||||
threshold = rx % xs_threshold(i_temp)
|
||||
if (i_energy >= threshold) then
|
||||
score = ((ONE - f) * rx % xs(i_temp, i_energy - &
|
||||
threshold + 1) + f * rx % xs(i_temp, i_energy - &
|
||||
threshold + 2)) * atom_density * flux
|
||||
end if
|
||||
end associate
|
||||
else
|
||||
|
|
@ -1165,12 +1164,12 @@ contains
|
|||
i_energy = micro_xs(i_nuc) % index_grid
|
||||
f = micro_xs(i_nuc) % interp_factor
|
||||
|
||||
associate (xs => nuclides(i_nuc) % reactions(m) &
|
||||
% xs(i_temp))
|
||||
if (i_energy >= xs % threshold) then
|
||||
score = score + ((ONE - f) * xs % value(i_energy - &
|
||||
xs % threshold + 1) + f * xs % value(i_energy - &
|
||||
xs % threshold + 2)) * atom_density_ * flux
|
||||
associate (rx => nuclides(i_nuc) % reactions(m))
|
||||
threshold = rx % xs_threshold(i_temp)
|
||||
if (i_energy >= threshold) then
|
||||
score = score + ((ONE - f) * rx % xs(i_temp, i_energy - &
|
||||
threshold + 1) + f * rx % xs(i_temp, i_energy - &
|
||||
threshold + 2)) * atom_density_ * flux
|
||||
end if
|
||||
end associate
|
||||
else
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "xml_interface.h"
|
||||
|
||||
#include <algorithm> // for std::transform
|
||||
#include <algorithm> // for transform
|
||||
#include <sstream>
|
||||
|
||||
#include "error.h"
|
||||
|
|
@ -9,10 +9,11 @@
|
|||
namespace openmc {
|
||||
|
||||
std::string
|
||||
get_node_value(pugi::xml_node node, const char *name)
|
||||
get_node_value(pugi::xml_node node, const char* name, bool lowercase,
|
||||
bool strip)
|
||||
{
|
||||
// Search for either an attribute or child tag and get the data as a char*.
|
||||
const pugi::char_t *value_char;
|
||||
const pugi::char_t* value_char;
|
||||
if (node.attribute(name)) {
|
||||
value_char = node.attribute(name).value();
|
||||
} else if (node.child(name)) {
|
||||
|
|
@ -23,14 +24,18 @@ get_node_value(pugi::xml_node node, const char *name)
|
|||
<< node.name() << "\" XML node";
|
||||
fatal_error(err_msg);
|
||||
}
|
||||
std::string value {value_char};
|
||||
|
||||
// Convert to lowercase string.
|
||||
std::string value(value_char);
|
||||
std::transform(value.begin(), value.end(), value.begin(), ::tolower);
|
||||
// Convert to lower-case if needed
|
||||
if (lowercase) {
|
||||
std::transform(value.begin(), value.end(), value.begin(), ::tolower);
|
||||
}
|
||||
|
||||
// Remove whitespace.
|
||||
value.erase(0, value.find_first_not_of(" \t\r\n"));
|
||||
value.erase(value.find_last_not_of(" \t\r\n") + 1);
|
||||
// Strip leading/trailing whitespace if needed
|
||||
if (strip) {
|
||||
value.erase(0, value.find_first_not_of(" \t\r\n"));
|
||||
value.erase(value.find_last_not_of(" \t\r\n") + 1);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef XML_INTERFACE_H
|
||||
#define XML_INTERFACE_H
|
||||
|
||||
#include <sstream> // for stringstream
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -15,7 +16,24 @@ check_for_node(pugi::xml_node node, const char *name)
|
|||
return node.attribute(name) || node.child(name);
|
||||
}
|
||||
|
||||
std::string get_node_value(pugi::xml_node node, const char *name);
|
||||
std::string get_node_value(pugi::xml_node node, const char *name,
|
||||
bool lowercase=false, bool strip=false);
|
||||
|
||||
template <typename T>
|
||||
std::vector<T> get_node_array(pugi::xml_node node, const char* name)
|
||||
{
|
||||
// Get value of node attribute/child
|
||||
std::string s {get_node_value(node, name)};
|
||||
|
||||
// Read values one by one into vector
|
||||
std::stringstream iss {s};
|
||||
T value;
|
||||
std::vector<T> values;
|
||||
while (iss >> value)
|
||||
values.push_back(value);
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
} // namespace openmc
|
||||
#endif // XML_INTERFACE_H
|
||||
|
|
|
|||
|
|
@ -1,7 +1,15 @@
|
|||
import numpy as np
|
||||
import openmc
|
||||
from pkg_resources import parse_version
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture(scope='module', autouse=True)
|
||||
def numpy_version_requirement():
|
||||
assert parse_version(np.__version__) >= parse_version("1.14"), \
|
||||
"Regression tests require NumPy 1.14 or greater"
|
||||
|
||||
|
||||
@pytest.fixture(scope='module', autouse=True)
|
||||
def setup_regression_test(request):
|
||||
# Reset autogenerated IDs assigned to OpenMC objects
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
energyfunction nuclide score mean std. dev.
|
||||
0 02180f5f310ee4 Am241 ((n,gamma) / (n,gamma)) 1.00e-01 9.97e-03
|
||||
0 d2effa26cb3cf2 Am241 ((n,gamma) / (n,gamma)) 1.00e-01 9.97e-03
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@
|
|||
<bins>0.0 0.625 20000000.0</bins>
|
||||
</filter>
|
||||
<filter id="4" type="mu">
|
||||
<bins>-1.0 -0.818181818182 -0.636363636364 -0.454545454545 -0.272727272727 -0.0909090909091 0.0909090909091 0.272727272727 0.454545454545 0.636363636364 0.818181818182 1.0</bins>
|
||||
<bins>-1.0 -0.8181818181818181 -0.6363636363636364 -0.4545454545454546 -0.2727272727272727 -0.09090909090909083 0.09090909090909083 0.2727272727272727 0.4545454545454546 0.6363636363636365 0.8181818181818183 1.0</bins>
|
||||
</filter>
|
||||
<filter id="17" type="material">
|
||||
<bins>2</bins>
|
||||
|
|
|
|||
|
|
@ -37,5 +37,5 @@ Cell
|
|||
Fill = Material 2
|
||||
Region = -1
|
||||
Rotation = None
|
||||
Temperature = [ 500. 700. 0. 800.]
|
||||
Temperature = [500. 700. 0. 800.]
|
||||
Translation = None
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
</space>
|
||||
<angle type="isotropic" />
|
||||
<energy interpolation="histogram" type="tabular">
|
||||
<parameters>1.0 1.38949549437 1.93069772888 2.68269579528 3.72759372031 5.17947467923 7.19685673001 10.0 13.8949549437 19.3069772888 26.8269579528 37.2759372031 51.7947467923 71.9685673001 100.0 138.949549437 193.069772888 268.269579528 372.759372031 517.947467923 719.685673001 1000.0 1389.49549437 1930.69772888 2682.69579528 3727.59372031 5179.47467923 7196.85673001 10000.0 13894.9549437 19306.9772888 26826.9579528 37275.9372031 51794.7467923 71968.5673001 100000.0 138949.549437 193069.772888 268269.579528 372759.372031 517947.467923 719685.673001 1000000.0 1389495.49437 1930697.72888 2682695.79528 3727593.72031 5179474.67923 7196856.73001 10000000.0 0.0 2.90864392994e-08 5.80533561806e-08 8.67817193689e-08 1.15153477858e-07 1.43052046006e-07 1.70362782612e-07 1.96973462002e-07 2.22774735186e-07 2.47660579198e-07 2.71528732767e-07 2.9428111653e-07 3.15824236062e-07 3.36069566065e-07 3.54933914133e-07 3.72339762616e-07 3.88215587147e-07 4.02496150558e-07 4.15122770952e-07 4.26043562837e-07 4.35213650335e-07 4.42595351592e-07 4.48158333612e-07 4.5187973691e-07 4.53744269441e-07 4.53744269441e-07 4.5187973691e-07 4.48158333612e-07 4.42595351592e-07 4.35213650335e-07 4.26043562837e-07 4.15122770952e-07 4.02496150558e-07 3.88215587147e-07 3.72339762616e-07 3.54933914133e-07 3.36069566065e-07 3.15824236062e-07 2.9428111653e-07 2.71528732767e-07 2.47660579198e-07 2.22774735186e-07 1.96973462002e-07 1.70362782612e-07 1.43052046006e-07 1.15153477858e-07 8.67817193689e-08 5.80533561806e-08 2.90864392994e-08 5.55962111528e-23</parameters>
|
||||
<parameters>1.0 1.3894954943731377 1.93069772888325 2.6826957952797255 3.72759372031494 5.17947467923121 7.196856730011519 10.0 13.894954943731374 19.306977288832496 26.826957952797247 37.2759372031494 51.7947467923121 71.96856730011518 100.0 138.94954943731375 193.06977288832496 268.26957952797244 372.7593720314938 517.9474679231207 719.6856730011514 1000.0 1389.4954943731375 1930.6977288832495 2682.6957952797247 3727.593720314938 5179.474679231207 7196.856730011514 10000.0 13894.95494373136 19306.977288832495 26826.95795279722 37275.93720314938 51794.74679231213 71968.56730011514 100000.0 138949.5494373136 193069.77288832495 268269.5795279722 372759.3720314938 517947.4679231202 719685.6730011514 1000000.0 1389495.494373136 1930697.7288832497 2682695.7952797217 3727593.720314938 5179474.679231202 7196856.730011513 10000000.0 0.0 2.9086439299358713e-08 5.80533561806147e-08 8.67817193689187e-08 1.1515347785771536e-07 1.4305204600565115e-07 1.7036278261198208e-07 1.9697346200185813e-07 2.227747351856934e-07 2.4766057919761985e-07 2.715287327665956e-07 2.9428111652990295e-07 3.1582423606228735e-07 3.360695660646056e-07 3.549339141332686e-07 3.723397626156721e-07 3.882155871468592e-07 4.024961505584776e-07 4.151227709522976e-07 4.260435628367196e-07 4.3521365033538783e-07 4.4259535159179273e-07 4.4815833361210174e-07 4.5187973690993757e-07 4.5374426944091084e-07 4.5374426944091084e-07 4.5187973690993757e-07 4.4815833361210174e-07 4.4259535159179273e-07 4.352136503353879e-07 4.2604356283671966e-07 4.1512277095229767e-07 4.0249615055847764e-07 3.8821558714685926e-07 3.723397626156722e-07 3.5493391413326864e-07 3.360695660646057e-07 3.158242360622874e-07 2.942811165299031e-07 2.715287327665957e-07 2.4766057919762e-07 2.2277473518569352e-07 1.9697346200185819e-07 1.7036278261198226e-07 1.4305204600565126e-07 1.1515347785771556e-07 8.678171936891881e-08 5.805335618061493e-08 2.9086439299358858e-08 5.559621115282002e-23</parameters>
|
||||
</energy>
|
||||
</source>
|
||||
</settings>
|
||||
|
|
|
|||
|
|
@ -48,10 +48,10 @@
|
|||
<bins>0.0 4000000.0 20000000.0</bins>
|
||||
</filter>
|
||||
<filter id="2" type="polar">
|
||||
<bins>0.0 0.785398163397 3.14159265359</bins>
|
||||
<bins>0.0 0.7853981633974483 3.141592653589793</bins>
|
||||
</filter>
|
||||
<filter id="3" type="azimuthal">
|
||||
<bins>0.0 0.785398163397 3.14159265359</bins>
|
||||
<bins>0.0 0.7853981633974483 3.141592653589793</bins>
|
||||
</filter>
|
||||
<filter id="4" type="surface">
|
||||
<bins>1</bins>
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
8294c7481b3433a4beb25541ae72c1ea915def0c0d0f393f7585371877187f4a2a25e70bb602232e2bc1e877e78db0e9384591e5c71575659f95abb10fae0af3
|
||||
c8fb043c5321e698040544dbb0baa9ce82df0e189738fb6013b4f3ff7e05a989a7a59b9b55034b8c9de6bc604ba9f969dc08ad2752fc74da205c19ff5974c9a2
|
||||
|
|
@ -1,134 +1,139 @@
|
|||
[[[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]]
|
||||
[[[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]]
|
||||
|
||||
[[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]]
|
||||
[[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]]
|
||||
|
||||
[[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]]
|
||||
[[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]]
|
||||
|
||||
...,
|
||||
[[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]]
|
||||
...
|
||||
|
||||
[[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]]
|
||||
[[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]]
|
||||
|
||||
[[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]]][[[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]]
|
||||
[[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]]
|
||||
|
||||
[[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]]
|
||||
[[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]]][[[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]]
|
||||
|
||||
[[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]]
|
||||
[[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]]
|
||||
|
||||
...,
|
||||
[[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]]
|
||||
[[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]]
|
||||
|
||||
[[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]]
|
||||
...
|
||||
|
||||
[[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]]][[[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]]
|
||||
[[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]]
|
||||
|
||||
[[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]]
|
||||
[[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]]
|
||||
|
||||
[[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]]
|
||||
[[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]]][[[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]]
|
||||
|
||||
...,
|
||||
[[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]]
|
||||
[[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]]
|
||||
|
||||
[[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]]
|
||||
[[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]]
|
||||
|
||||
[[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]
|
||||
[ 0. 0. 0. 0.]]][[[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]]
|
||||
...
|
||||
|
||||
[[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]]
|
||||
[[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]]
|
||||
|
||||
[[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]]
|
||||
[[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]]
|
||||
|
||||
...,
|
||||
[[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]]
|
||||
[[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]
|
||||
[0. 0. 0. 0.]]][[[0. 0. 0.]
|
||||
[0. 0. 0.]
|
||||
[0. 0. 0.]
|
||||
[0. 0. 0.]]
|
||||
|
||||
[[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]]
|
||||
[[0. 0. 0.]
|
||||
[0. 0. 0.]
|
||||
[0. 0. 0.]
|
||||
[0. 0. 0.]]
|
||||
|
||||
[[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]]][[[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]]
|
||||
[[0. 0. 0.]
|
||||
[0. 0. 0.]
|
||||
[0. 0. 0.]
|
||||
[0. 0. 0.]]
|
||||
|
||||
[[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]]
|
||||
...
|
||||
|
||||
[[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]]
|
||||
[[0. 0. 0.]
|
||||
[0. 0. 0.]
|
||||
[0. 0. 0.]
|
||||
[0. 0. 0.]]
|
||||
|
||||
...,
|
||||
[[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]]
|
||||
[[0. 0. 0.]
|
||||
[0. 0. 0.]
|
||||
[0. 0. 0.]
|
||||
[0. 0. 0.]]
|
||||
|
||||
[[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]]
|
||||
[[0. 0. 0.]
|
||||
[0. 0. 0.]
|
||||
[0. 0. 0.]
|
||||
[0. 0. 0.]]][[[0. 0. 0.]
|
||||
[0. 0. 0.]
|
||||
[0. 0. 0.]]
|
||||
|
||||
[[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]
|
||||
[ 0. 0. 0.]]]
|
||||
[[0. 0. 0.]
|
||||
[0. 0. 0.]
|
||||
[0. 0. 0.]]
|
||||
|
||||
[[0. 0. 0.]
|
||||
[0. 0. 0.]
|
||||
[0. 0. 0.]]
|
||||
|
||||
...
|
||||
|
||||
[[0. 0. 0.]
|
||||
[0. 0. 0.]
|
||||
[0. 0. 0.]]
|
||||
|
||||
[[0. 0. 0.]
|
||||
[0. 0. 0.]
|
||||
[0. 0. 0.]]
|
||||
|
||||
[[0. 0. 0.]
|
||||
[0. 0. 0.]
|
||||
[0. 0. 0.]]]
|
||||
Binary file not shown.
|
|
@ -6,170 +6,170 @@
|
|||
<cell id="16" material="16" region="11 -12" universe="9" />
|
||||
<cell id="17" material="17" region="12" universe="9" />
|
||||
<cell fill="10" id="134" region="122 -123 124 -125 126 -127" universe="0" />
|
||||
<cell fill="9" id="135" region="-128" translation="-0.00140620118176 -0.0152577471673 -0.0918476696602" universe="35" />
|
||||
<cell fill="9" id="136" region="-129" translation="0.109099026398 -0.00417917776733 -0.0462409301859" universe="23" />
|
||||
<cell fill="9" id="137" region="-130" translation="0.138783366528 -0.0690071053688 -0.0384882149749" universe="18" />
|
||||
<cell fill="9" id="138" region="-131" translation="-0.194549966806 -0.0690071053688 -0.0384882149749" universe="19" />
|
||||
<cell fill="9" id="139" region="-132" translation="-0.0984645519108 -0.0259403806947 -0.0615517493329" universe="26" />
|
||||
<cell fill="9" id="140" region="-133" translation="-0.0932159178431 -0.122488574824 -0.0499980238428" universe="22" />
|
||||
<cell fill="9" id="141" region="-134" translation="0.202819899608 0.0850151469064 0.0743119884463" universe="30" />
|
||||
<cell fill="9" id="142" region="-135" translation="-0.130513433725 0.0850151469064 0.0743119884463" universe="31" />
|
||||
<cell fill="9" id="143" region="-136" translation="0.03417350411 -0.0964115371994 -0.101120980927" universe="13" />
|
||||
<cell fill="9" id="144" region="-137" translation="0.0379131188424 0.0687077251904 -0.108757520396" universe="27" />
|
||||
<cell fill="9" id="145" region="-138" translation="0.0738800814064 -0.071302275054 -0.0978298256419" universe="14" />
|
||||
<cell fill="9" id="146" region="-139" translation="0.0889721475441 0.0869416521141 0.075877373016" universe="11" />
|
||||
<cell fill="9" id="147" region="-140" translation="-0.0369830271171 0.140878401491 -0.104742841496" universe="12" />
|
||||
<cell fill="9" id="148" region="-141" translation="-0.0369830271171 -0.192454931842 -0.104742841496" universe="15" />
|
||||
<cell fill="9" id="149" region="-142" translation="-0.0242806966142 0.0516839323883 0.130270489265" universe="25" />
|
||||
<cell fill="9" id="150" region="-143" translation="-0.0242806966142 0.0516839323883 -0.203062844069" universe="34" />
|
||||
<cell fill="9" id="151" region="-144" translation="0.0457805197599 0.117590160514 -0.00380228622125" universe="35" />
|
||||
<cell fill="9" id="152" region="-145" translation="-0.0137419084645 0.180165775531 0.202768975142" universe="20" />
|
||||
<cell fill="9" id="153" region="-146" translation="-0.0137419084645 -0.153167557803 0.202768975142" universe="23" />
|
||||
<cell fill="9" id="154" region="-147" translation="-0.0137419084645 0.180165775531 -0.130564358191" universe="29" />
|
||||
<cell fill="9" id="155" region="-148" translation="-0.0137419084645 -0.153167557803 -0.130564358191" universe="32" />
|
||||
<cell fill="9" id="156" region="-149" translation="0.193346065156 0.0662280238816 -0.0713110415353" universe="27" />
|
||||
<cell fill="9" id="157" region="-150" translation="-0.139987268177 0.0662280238816 -0.0713110415353" universe="28" />
|
||||
<cell fill="9" id="158" region="-151" translation="-0.0311856561407 0.155914746052 0.153317205092" universe="16" />
|
||||
<cell fill="9" id="159" region="-152" translation="-0.0311856561407 -0.177418587281 0.153317205092" universe="19" />
|
||||
<cell fill="9" id="160" region="-153" translation="-0.0311856561407 0.155914746052 -0.180016128241" universe="25" />
|
||||
<cell fill="9" id="161" region="-154" translation="-0.0311856561407 -0.177418587281 -0.180016128241" universe="28" />
|
||||
<cell fill="9" id="162" region="-155" translation="0.0801800449244 0.0168261919282 -0.0163895967622" universe="36" />
|
||||
<cell fill="9" id="163" region="-156" translation="0.00483733774062 0.081481567183 -0.0928082691631" universe="15" />
|
||||
<cell fill="9" id="164" region="-157" translation="0.097811779112 -0.0610597446974 -0.0784455336401" universe="26" />
|
||||
<cell fill="9" id="165" region="-158" translation="0.033971609479 0.0446752660509 0.185883817671" universe="23" />
|
||||
<cell fill="9" id="166" region="-159" translation="0.033971609479 0.0446752660509 -0.147449515662" universe="32" />
|
||||
<cell fill="9" id="167" region="-160" translation="0.159741777825 -0.114709384731 -0.0558806276942" universe="24" />
|
||||
<cell fill="9" id="168" region="-161" translation="-0.173591555508 -0.114709384731 -0.0558806276942" universe="25" />
|
||||
<cell fill="9" id="169" region="-162" translation="0.00771444999286 -0.0784191193007 0.0191691213248" universe="27" />
|
||||
<cell fill="9" id="170" region="-163" translation="-0.0977249605603 -0.0094355820168 -0.097340787155" universe="15" />
|
||||
<cell fill="9" id="171" region="-164" translation="-0.0846040523453 0.186196302117 0.109025021864" universe="32" />
|
||||
<cell fill="9" id="172" region="-165" translation="-0.0846040523453 -0.147137031217 0.109025021864" universe="35" />
|
||||
<cell fill="9" id="173" region="-166" translation="0.0853097051629 -0.097409487121 0.0315380230547" universe="15" />
|
||||
<cell fill="9" id="174" region="-167" translation="0.00204940024585 0.108007828333 -0.0856693988182" universe="36" />
|
||||
<cell fill="9" id="175" region="-168" translation="0.0362697740558 -0.00348804073157 0.088140578575" universe="18" />
|
||||
<cell fill="9" id="176" region="-169" translation="0.0126079576483 0.0809005606263 0.071221146542" universe="27" />
|
||||
<cell fill="9" id="177" region="-170" translation="-0.0374148994358 0.122108694931 0.0439406213164" universe="21" />
|
||||
<cell fill="9" id="178" region="-171" translation="0.0851566223435 -0.119189958655 -0.0736469678739" universe="31" />
|
||||
<cell fill="9" id="179" region="-172" translation="-0.0399284809656 0.0202140729129 -0.1131524598" universe="37" />
|
||||
<cell fill="9" id="180" region="-173" translation="-0.0503157540846 0.0170999685653 0.0561731252046" universe="25" />
|
||||
<cell fill="9" id="181" region="-174" translation="-0.0676639827455 -0.0730357877864 0.00541096373088" universe="30" />
|
||||
<cell fill="9" id="182" region="-175" translation="0.0640843901638 0.0585363225055 0.00432158793112" universe="21" />
|
||||
<cell fill="9" id="183" region="-176" translation="-0.0138010597555 0.202224545874 0.192417668194" universe="12" />
|
||||
<cell fill="9" id="184" region="-177" translation="-0.0138010597555 -0.131108787459 0.192417668194" universe="15" />
|
||||
<cell fill="9" id="185" region="-178" translation="-0.0138010597555 0.202224545874 -0.140915665139" universe="21" />
|
||||
<cell fill="9" id="186" region="-179" translation="-0.0138010597555 -0.131108787459 -0.140915665139" universe="24" />
|
||||
<cell fill="9" id="187" region="-180" translation="0.035227337498 0.113054594036 0.102950231509" universe="24" />
|
||||
<cell fill="9" id="188" region="-181" translation="-0.0383166045087 -0.0988055687379 0.0857867394674" universe="12" />
|
||||
<cell fill="9" id="189" region="-182" translation="0.0378202408916 0.0773239271977 -0.00282972122211" universe="32" />
|
||||
<cell fill="9" id="190" region="-183" translation="-0.0601124832347 -0.0613405147405 -0.043634920585" universe="37" />
|
||||
<cell fill="9" id="191" region="-184" translation="0.109305027033 -0.0204659393864 0.158485432539" universe="26" />
|
||||
<cell fill="9" id="192" region="-185" translation="0.109305027033 -0.0204659393864 -0.174847900794" universe="35" />
|
||||
<cell fill="9" id="193" region="-186" translation="-0.0482158135072 -0.109136394796 -0.111087009623" universe="11" />
|
||||
<cell fill="9" id="194" region="-187" translation="-0.0993436405899 0.104054804419 -0.0241798283787" universe="13" />
|
||||
<cell fill="9" id="195" region="-188" translation="0.114256308042 0.190902465414 -0.0607753376217" universe="12" />
|
||||
<cell fill="9" id="196" region="-189" translation="0.114256308042 -0.14243086792 -0.0607753376217" universe="15" />
|
||||
<cell fill="9" id="197" region="-190" translation="0.0217205011906 0.0250667553285 0.0295200316" universe="14" />
|
||||
<cell fill="9" id="198" region="-191" translation="0.125436500241 0.193710578338 -0.0414706576932" universe="23" />
|
||||
<cell fill="9" id="199" region="-192" translation="-0.207896833092 0.193710578338 -0.0414706576932" universe="24" />
|
||||
<cell fill="9" id="200" region="-193" translation="0.125436500241 -0.139622754995 -0.0414706576932" universe="26" />
|
||||
<cell fill="9" id="201" region="-194" translation="-0.207896833092 -0.139622754995 -0.0414706576932" universe="27" />
|
||||
<cell fill="9" id="202" region="-195" translation="-0.103856970591 -0.0723989491841 0.0477333168332" universe="15" />
|
||||
<cell fill="9" id="203" region="-196" translation="-0.0248453372329 0.0327005037426 0.0092611805402" universe="26" />
|
||||
<cell fill="9" id="204" region="-197" translation="-0.105357688326 -0.108061697849 0.00966905666893" universe="11" />
|
||||
<cell fill="9" id="205" region="-198" translation="0.200343875313 0.0222716943858 0.187316452299" universe="21" />
|
||||
<cell fill="9" id="206" region="-199" translation="-0.13298945802 0.0222716943858 0.187316452299" universe="22" />
|
||||
<cell fill="9" id="207" region="-200" translation="0.200343875313 0.0222716943858 -0.146016881035" universe="30" />
|
||||
<cell fill="9" id="208" region="-201" translation="-0.13298945802 0.0222716943858 -0.146016881035" universe="31" />
|
||||
<cell fill="9" id="209" region="-202" translation="0.163119940576 0.0409248307565 0.0775424026481" universe="15" />
|
||||
<cell fill="9" id="210" region="-203" translation="-0.170213392757 0.0409248307565 0.0775424026481" universe="16" />
|
||||
<cell fill="9" id="211" region="-204" translation="0.102073447729 -0.0606874931034 0.0151968577672" universe="28" />
|
||||
<cell fill="9" id="212" region="-205" translation="0.0799190701492 0.13595762577 -0.0962208719747" universe="23" />
|
||||
<cell fill="9" id="213" region="-206" translation="0.0799190701492 -0.197375707563 -0.0962208719747" universe="26" />
|
||||
<cell fill="9" id="214" region="-207" translation="0.0694369789325 0.169683871789 0.119882766994" universe="21" />
|
||||
<cell fill="9" id="215" region="-208" translation="0.0694369789325 -0.163649461545 0.119882766994" universe="24" />
|
||||
<cell fill="9" id="216" region="-209" translation="-0.0705988927796 0.148957080213 0.0950321471098" universe="29" />
|
||||
<cell fill="9" id="217" region="-210" translation="-0.0705988927796 -0.18437625312 0.0950321471098" universe="32" />
|
||||
<cell fill="9" id="218" region="-211" translation="0.010468267264 0.156080284248 -0.0051133943139" universe="31" />
|
||||
<cell fill="9" id="219" region="-212" translation="0.010468267264 -0.177253049085 -0.0051133943139" universe="34" />
|
||||
<cell fill="9" id="220" region="-213" translation="0.159721234175 0.0688352262865 -0.110095873694" universe="35" />
|
||||
<cell fill="9" id="221" region="-214" translation="-0.173612099158 0.0688352262865 -0.110095873694" universe="36" />
|
||||
<cell fill="9" id="222" region="-215" translation="0.0898117967697 0.0643418620595 0.0326072339685" universe="16" />
|
||||
<cell fill="9" id="223" region="-216" translation="0.0033702311569 0.100407895371 0.186783186803" universe="28" />
|
||||
<cell fill="9" id="224" region="-217" translation="0.0033702311569 0.100407895371 -0.14655014653" universe="37" />
|
||||
<cell fill="9" id="225" region="-218" translation="0.0532989528173 -0.0288162906553 0.151934117139" universe="20" />
|
||||
<cell fill="9" id="226" region="-219" translation="0.0532989528173 -0.0288162906553 -0.181399216194" universe="29" />
|
||||
<cell fill="9" id="227" region="-220" translation="0.146637865541 -0.000183171192208 0.173437280372" universe="14" />
|
||||
<cell fill="9" id="228" region="-221" translation="-0.186695467792 -0.000183171192208 0.173437280372" universe="15" />
|
||||
<cell fill="9" id="229" region="-222" translation="0.146637865541 -0.000183171192208 -0.159896052961" universe="23" />
|
||||
<cell fill="9" id="230" region="-223" translation="-0.186695467792 -0.000183171192208 -0.159896052961" universe="24" />
|
||||
<cell fill="9" id="231" region="-224" translation="0.00688615671293 0.0325721225173 -0.107852540144" universe="19" />
|
||||
<cell fill="9" id="232" region="-225" translation="0.0594642653073 0.175629948849 0.11256068343" universe="29" />
|
||||
<cell fill="9" id="233" region="-226" translation="0.0594642653073 -0.157703384484 0.11256068343" universe="32" />
|
||||
<cell fill="9" id="234" region="-227" translation="-0.0745211393531 0.186025398941 0.07061211192" universe="13" />
|
||||
<cell fill="9" id="235" region="-228" translation="-0.0745211393531 -0.147307934392 0.07061211192" universe="16" />
|
||||
<cell fill="9" id="236" region="-229" translation="0.159713616332 -0.0241680036074 0.0623342971853" universe="36" />
|
||||
<cell fill="9" id="237" region="-230" translation="-0.173619717001 -0.0241680036074 0.0623342971853" universe="37" />
|
||||
<cell fill="9" id="238" region="-231" translation="-0.0141914194483 0.111149451072 0.0903966514578" universe="18" />
|
||||
<cell fill="9" id="239" region="-232" translation="0.206413378004 -0.0468919157204 0.0309383201461" universe="12" />
|
||||
<cell fill="9" id="240" region="-233" translation="-0.126919955329 -0.0468919157204 0.0309383201461" universe="13" />
|
||||
<cell fill="9" id="241" region="-234" translation="0.0429259824683 0.070555715848 -0.0961124680564" universe="31" />
|
||||
<cell fill="9" id="242" region="-235" translation="0.0917411839861 -0.0210268081646 -0.120747126544" universe="27" />
|
||||
<cell fill="9" id="243" region="-236" translation="0.187114465978 0.142190928958 0.00303951516048" universe="29" />
|
||||
<cell fill="9" id="244" region="-237" translation="-0.146218867356 0.142190928958 0.00303951516048" universe="30" />
|
||||
<cell fill="9" id="245" region="-238" translation="0.187114465978 -0.191142404375 0.00303951516048" universe="32" />
|
||||
<cell fill="9" id="246" region="-239" translation="-0.146218867356 -0.191142404375 0.00303951516048" universe="33" />
|
||||
<cell fill="9" id="247" region="-240" translation="-0.0885860120512 -0.0574080917257 0.00189379783576" universe="29" />
|
||||
<cell fill="9" id="248" region="-241" translation="-0.0695627245254 -0.0325861164534 0.187674961732" universe="19" />
|
||||
<cell fill="9" id="249" region="-242" translation="-0.0695627245254 -0.0325861164534 -0.145658371601" universe="28" />
|
||||
<cell fill="9" id="250" region="-243" translation="0.0648004866859 0.0803935669348 -0.0495807099831" universe="12" />
|
||||
<cell fill="9" id="251" region="-244" translation="0.119768828483 0.0244148877182 0.0590010758314" universe="26" />
|
||||
<cell fill="9" id="252" region="-245" translation="0.055815690197 -0.0386622433477 0.129344155705" universe="16" />
|
||||
<cell fill="9" id="253" region="-246" translation="0.055815690197 -0.0386622433477 -0.203989177628" universe="25" />
|
||||
<cell fill="9" id="254" region="-247" translation="-0.0705714088439 -0.0332615859242 -0.113081179589" universe="19" />
|
||||
<cell fill="9" id="255" region="-248" translation="0.0191891610992 -0.0877751186437 0.0949676788695" universe="13" />
|
||||
<cell fill="9" id="256" region="-249" translation="0.11357577214 -0.0723120607076 -0.0186231523344" universe="16" />
|
||||
<cell fill="9" id="257" region="-250" translation="0.0288228703292 0.0966036043404 -0.109945458994" universe="29" />
|
||||
<cell fill="9" id="258" region="-251" translation="-0.0302720060162 0.0427214916014 -0.111437158817" universe="26" />
|
||||
<cell fill="9" id="259" region="-252" translation="0.0971933921082 0.0413100742886 0.144761925354" universe="19" />
|
||||
<cell fill="9" id="260" region="-253" translation="0.0971933921082 0.0413100742886 -0.18857140798" universe="28" />
|
||||
<cell fill="9" id="261" region="-254" translation="0.107580312879 -0.0210472571374 -0.03274843538" universe="14" />
|
||||
<cell fill="9" id="262" region="-255" translation="0.139201957633 -0.0881443612864 -0.114798284951" universe="12" />
|
||||
<cell fill="9" id="263" region="-256" translation="-0.194131375701 -0.0881443612864 -0.114798284951" universe="13" />
|
||||
<cell fill="9" id="264" region="-257" translation="0.108471976774 0.146159230208 0.088410423839" universe="22" />
|
||||
<cell fill="9" id="265" region="-258" translation="0.108471976774 -0.187174103125 0.088410423839" universe="25" />
|
||||
<cell fill="9" id="266" region="-259" translation="0.0451270583821 0.096780721612 0.0967653665332" universe="37" />
|
||||
<cell fill="9" id="267" region="-260" translation="-0.0224644717455 0.0725927720514 0.107852198651" universe="20" />
|
||||
<cell fill="9" id="268" region="-261" translation="0.106063533699 0.0392870322973 0.172287769268" universe="25" />
|
||||
<cell fill="9" id="269" region="-262" translation="0.106063533699 0.0392870322973 -0.161045564066" universe="34" />
|
||||
<cell fill="9" id="270" region="-263" translation="0.148159419635 0.112776558875 0.0380868716968" universe="21" />
|
||||
<cell fill="9" id="271" region="-264" translation="-0.185173913698 0.112776558875 0.0380868716968" universe="22" />
|
||||
<cell fill="9" id="272" region="-265" translation="0.156935816691 0.101145318349 -0.0499235619578" universe="11" />
|
||||
<cell fill="9" id="273" region="-266" translation="-0.176397516643 0.101145318349 -0.0499235619578" universe="12" />
|
||||
<cell fill="9" id="274" region="-267" translation="0.132643578757 0.109198051281 -0.0476954987918" universe="26" />
|
||||
<cell fill="9" id="275" region="-268" translation="-0.200689754577 0.109198051281 -0.0476954987918" universe="27" />
|
||||
<cell fill="9" id="276" region="-269" translation="0.139165644346 0.131343196487 0.0701591217856" universe="33" />
|
||||
<cell fill="9" id="277" region="-270" translation="-0.194167688987 0.131343196487 0.0701591217856" universe="34" />
|
||||
<cell fill="9" id="278" region="-271" translation="0.139165644346 -0.201990136846 0.0701591217856" universe="36" />
|
||||
<cell fill="9" id="279" region="-272" translation="-0.194167688987 -0.201990136846 0.0701591217856" universe="37" />
|
||||
<cell fill="9" id="280" region="-273" translation="-0.100266886432 0.15644435527 0.175172848479" universe="12" />
|
||||
<cell fill="9" id="281" region="-274" translation="-0.100266886432 -0.176888978063 0.175172848479" universe="15" />
|
||||
<cell fill="9" id="282" region="-275" translation="-0.100266886432 0.15644435527 -0.158160484854" universe="21" />
|
||||
<cell fill="9" id="283" region="-276" translation="-0.100266886432 -0.176888978063 -0.158160484854" universe="24" />
|
||||
<cell fill="9" id="284" region="-277" translation="0.165554360307 -0.0155314552194 0.0269161414417" universe="35" />
|
||||
<cell fill="9" id="285" region="-278" translation="-0.167778973026 -0.0155314552194 0.0269161414417" universe="36" />
|
||||
<cell fill="9" id="286" region="-279" translation="0.152805274649 0.181665566207 0.0404883666838" universe="20" />
|
||||
<cell fill="9" id="287" region="-280" translation="-0.180528058685 0.181665566207 0.0404883666838" universe="21" />
|
||||
<cell fill="9" id="288" region="-281" translation="0.152805274649 -0.151667767127 0.0404883666838" universe="23" />
|
||||
<cell fill="9" id="289" region="-282" translation="-0.180528058685 -0.151667767127 0.0404883666838" universe="24" />
|
||||
<cell fill="9" id="290" region="-283" translation="0.0723111669483 0.0878537053709 0.0999705558994" universe="15" />
|
||||
<cell fill="9" id="291" region="-284" translation="-0.105764243624 0.0987449723258 -0.0582008094074" universe="11" />
|
||||
<cell fill="9" id="292" region="-285" translation="0.0468779531251 -0.0594927321842 -0.0556353418577" universe="12" />
|
||||
<cell fill="9" id="293" region="-286" translation="0.123942306657 0.141830462742 -0.0658381874921" universe="30" />
|
||||
<cell fill="9" id="294" region="-287" translation="0.123942306657 -0.191502870591 -0.0658381874921" universe="33" />
|
||||
<cell fill="9" id="295" region="-288" translation="0.0013087859342 -0.0632759448088 -0.0538252207421" universe="18" />
|
||||
<cell fill="9" id="296" region="-289" translation="0.110588836699 -0.0389541758206 0.16834558789" universe="19" />
|
||||
<cell fill="9" id="297" region="-290" translation="0.110588836699 -0.0389541758206 -0.164987745443" universe="28" />
|
||||
<cell fill="9" id="298" region="-291" translation="-0.0265701006572 0.0131449788411 0.0505879445141" universe="32" />
|
||||
<cell fill="9" id="135" region="-128" translation="-0.0014062011817633224 -0.015257747167296776 -0.09184766966024316" universe="35" />
|
||||
<cell fill="9" id="136" region="-129" translation="0.10909902639777394 -0.004179177767328068 -0.046240930185910245" universe="23" />
|
||||
<cell fill="9" id="137" region="-130" translation="0.13878336652768952 -0.06900710536877097 -0.03848821497485455" universe="18" />
|
||||
<cell fill="9" id="138" region="-131" translation="-0.19454996680564374 -0.06900710536877097 -0.03848821497485455" universe="19" />
|
||||
<cell fill="9" id="139" region="-132" translation="-0.09846455191076986 -0.02594038069469251 -0.06155174933292362" universe="26" />
|
||||
<cell fill="9" id="140" region="-133" translation="-0.09321591784308736 -0.12248857482372477 -0.04999802384282931" universe="22" />
|
||||
<cell fill="9" id="141" region="-134" translation="0.2028198996079864 0.08501514690643278 0.07431198844628262" universe="30" />
|
||||
<cell fill="9" id="142" region="-135" translation="-0.13051343372534685 0.08501514690643278 0.07431198844628262" universe="31" />
|
||||
<cell fill="9" id="143" region="-136" translation="0.03417350410997999 -0.09641153719944834 -0.10112098092715327" universe="13" />
|
||||
<cell fill="9" id="144" region="-137" translation="0.037913118842446136 0.06870772519039314 -0.10875752039644154" universe="27" />
|
||||
<cell fill="9" id="145" region="-138" translation="0.07388008140640989 -0.07130227505402231 -0.09782982564187503" universe="14" />
|
||||
<cell fill="9" id="146" region="-139" translation="0.08897214754414112 0.08694165211410448 0.07587737301598729" universe="11" />
|
||||
<cell fill="9" id="147" region="-140" translation="-0.03698302711710488 0.1408784014909229 -0.10474284149572705" universe="12" />
|
||||
<cell fill="9" id="148" region="-141" translation="-0.03698302711710488 -0.19245493184241047 -0.10474284149572705" universe="15" />
|
||||
<cell fill="9" id="149" region="-142" translation="-0.02428069661424781 0.05168393238830282 0.1302704892646539" universe="25" />
|
||||
<cell fill="9" id="150" region="-143" translation="-0.02428069661424781 0.05168393238830282 -0.20306284406867936" universe="34" />
|
||||
<cell fill="9" id="151" region="-144" translation="0.04578051975994746 0.1175901605138544 -0.0038022862212453434" universe="35" />
|
||||
<cell fill="9" id="152" region="-145" translation="-0.013741908464450836 0.18016577553053154 0.20276897514248216" universe="20" />
|
||||
<cell fill="9" id="153" region="-146" translation="-0.013741908464450836 -0.15316755780280183 0.20276897514248216" universe="23" />
|
||||
<cell fill="9" id="154" region="-147" translation="-0.013741908464450836 0.18016577553053154 -0.1305643581908511" universe="29" />
|
||||
<cell fill="9" id="155" region="-148" translation="-0.013741908464450836 -0.15316755780280183 -0.1305643581908511" universe="32" />
|
||||
<cell fill="9" id="156" region="-149" translation="0.19334606515602848 0.066228023881572 -0.07131104153532436" universe="27" />
|
||||
<cell fill="9" id="157" region="-150" translation="-0.13998726817730478 0.066228023881572 -0.07131104153532436" universe="28" />
|
||||
<cell fill="9" id="158" region="-151" translation="-0.031185656140686913 0.155914746052082 0.15331720509241947" universe="16" />
|
||||
<cell fill="9" id="159" region="-152" translation="-0.031185656140686913 -0.17741858728125126 0.15331720509241947" universe="19" />
|
||||
<cell fill="9" id="160" region="-153" translation="-0.031185656140686913 0.155914746052082 -0.1800161282409139" universe="25" />
|
||||
<cell fill="9" id="161" region="-154" translation="-0.031185656140686913 -0.17741858728125126 -0.1800161282409139" universe="28" />
|
||||
<cell fill="9" id="162" region="-155" translation="0.08018004492442865 0.016826191928232426 -0.016389596762212966" universe="36" />
|
||||
<cell fill="9" id="163" region="-156" translation="0.00483733774062417 0.08148156718302602 -0.09280826916311341" universe="15" />
|
||||
<cell fill="9" id="164" region="-157" translation="0.0978117791120118 -0.06105974469736897 -0.07844553364014112" universe="26" />
|
||||
<cell fill="9" id="165" region="-158" translation="0.0339716094789545 0.044675266050854034 0.18588381767108564" universe="23" />
|
||||
<cell fill="9" id="166" region="-159" translation="0.0339716094789545 0.044675266050854034 -0.14744951566224762" universe="32" />
|
||||
<cell fill="9" id="167" region="-160" translation="0.15974177782488064 -0.11470938473074832 -0.055880627694202434" universe="24" />
|
||||
<cell fill="9" id="168" region="-161" translation="-0.17359155550845262 -0.11470938473074832 -0.055880627694202434" universe="25" />
|
||||
<cell fill="9" id="169" region="-162" translation="0.007714449992858363 -0.07841911930069978 0.019169121324834393" universe="27" />
|
||||
<cell fill="9" id="170" region="-163" translation="-0.09772496056025104 -0.009435582016802613 -0.0973407871549632" universe="15" />
|
||||
<cell fill="9" id="171" region="-164" translation="-0.08460405234526575 0.18619630211681182 0.10902502186367324" universe="32" />
|
||||
<cell fill="9" id="172" region="-165" translation="-0.08460405234526575 -0.14713703121652144 0.10902502186367324" universe="35" />
|
||||
<cell fill="9" id="173" region="-166" translation="0.08530970516294267 -0.09740948712101977 0.031538023054709596" universe="15" />
|
||||
<cell fill="9" id="174" region="-167" translation="0.002049400245853761 0.10800782833319489 -0.08566939881823532" universe="36" />
|
||||
<cell fill="9" id="175" region="-168" translation="0.036269774055772475 -0.0034880407315701634 0.08814057857502322" universe="18" />
|
||||
<cell fill="9" id="176" region="-169" translation="0.012607957648281654 0.08090056062626749 0.0712211465420014" universe="27" />
|
||||
<cell fill="9" id="177" region="-170" translation="-0.03741489943578313 0.1221086949309545 0.0439406213163509" universe="21" />
|
||||
<cell fill="9" id="178" region="-171" translation="0.0851566223435044 -0.1191899586548319 -0.07364696787394387" universe="31" />
|
||||
<cell fill="9" id="179" region="-172" translation="-0.03992848096555457 0.020214072912877246 -0.11315245980004196" universe="37" />
|
||||
<cell fill="9" id="180" region="-173" translation="-0.050315754084578224 0.017099968565308377 0.056173125204605934" universe="25" />
|
||||
<cell fill="9" id="181" region="-174" translation="-0.06766398274549851 -0.07303578778642877 0.005410963730880458" universe="30" />
|
||||
<cell fill="9" id="182" region="-175" translation="0.06408439016382617 0.05853632250550789 0.00432158793112436" universe="21" />
|
||||
<cell fill="9" id="183" region="-176" translation="-0.013801059755509382 0.20222454587424032 0.19241766819445416" universe="12" />
|
||||
<cell fill="9" id="184" region="-177" translation="-0.013801059755509382 -0.13110878745909305 0.19241766819445416" universe="15" />
|
||||
<cell fill="9" id="185" region="-178" translation="-0.013801059755509382 0.20222454587424032 -0.1409156651388792" universe="21" />
|
||||
<cell fill="9" id="186" region="-179" translation="-0.013801059755509382 -0.13110878745909305 -0.1409156651388792" universe="24" />
|
||||
<cell fill="9" id="187" region="-180" translation="0.03522733749799645 0.11305459403611595 0.10295023150858529" universe="24" />
|
||||
<cell fill="9" id="188" region="-181" translation="-0.03831660450870228 -0.09880556873790897 0.08578673946744877" universe="12" />
|
||||
<cell fill="9" id="189" region="-182" translation="0.03782024089160585 0.07732392719766301 -0.002829721222114334" universe="32" />
|
||||
<cell fill="9" id="190" region="-183" translation="-0.060112483234699754 -0.06134051474053648 -0.04363492058502072" universe="37" />
|
||||
<cell fill="9" id="191" region="-184" translation="0.10930502703326198 -0.020465939386398402 0.15848543253913627" universe="26" />
|
||||
<cell fill="9" id="192" region="-185" translation="0.10930502703326198 -0.020465939386398402 -0.174847900794197" universe="35" />
|
||||
<cell fill="9" id="193" region="-186" translation="-0.04821581350719811 -0.10913639479587178 -0.11108700962300094" universe="11" />
|
||||
<cell fill="9" id="194" region="-187" translation="-0.09934364058994583 0.10405480441904197 -0.0241798283786806" universe="13" />
|
||||
<cell fill="9" id="195" region="-188" translation="0.11425630804159204 0.19090246541367445 -0.06077533762167586" universe="12" />
|
||||
<cell fill="9" id="196" region="-189" translation="0.11425630804159204 -0.14243086791965892 -0.06077533762167586" universe="15" />
|
||||
<cell fill="9" id="197" region="-190" translation="0.0217205011905508 0.02506675532845576 0.029520031599966412" universe="14" />
|
||||
<cell fill="9" id="198" region="-191" translation="0.12543650024083502 0.19371057833811733 -0.04147065769319469" universe="23" />
|
||||
<cell fill="9" id="199" region="-192" translation="-0.20789683309249835 0.19371057833811733 -0.04147065769319469" universe="24" />
|
||||
<cell fill="9" id="200" region="-193" translation="0.12543650024083502 -0.13962275499521593 -0.04147065769319469" universe="26" />
|
||||
<cell fill="9" id="201" region="-194" translation="-0.20789683309249835 -0.13962275499521593 -0.04147065769319469" universe="27" />
|
||||
<cell fill="9" id="202" region="-195" translation="-0.10385697059087434 -0.07239894918409101 0.047733316833160344" universe="15" />
|
||||
<cell fill="9" id="203" region="-196" translation="-0.02484533723289073 0.03270050374260325 0.009261180540203251" universe="26" />
|
||||
<cell fill="9" id="204" region="-197" translation="-0.10535768832641407 -0.10806169784882003 0.009669056668934639" universe="11" />
|
||||
<cell fill="9" id="205" region="-198" translation="0.20034387531341857 0.02227169438582799 0.18731645229850835" universe="21" />
|
||||
<cell fill="9" id="206" region="-199" translation="-0.13298945801991469 0.02227169438582799 0.18731645229850835" universe="22" />
|
||||
<cell fill="9" id="207" region="-200" translation="0.20034387531341857 0.02227169438582799 -0.1460168810348249" universe="30" />
|
||||
<cell fill="9" id="208" region="-201" translation="-0.13298945801991469 0.02227169438582799 -0.1460168810348249" universe="31" />
|
||||
<cell fill="9" id="209" region="-202" translation="0.1631199405760454 0.04092483075648701 0.07754240264809376" universe="15" />
|
||||
<cell fill="9" id="210" region="-203" translation="-0.17021339275728786 0.04092483075648701 0.07754240264809376" universe="16" />
|
||||
<cell fill="9" id="211" region="-204" translation="0.102073447728939 -0.060687493103351975 0.01519685776716928" universe="28" />
|
||||
<cell fill="9" id="212" region="-205" translation="0.07991907014916044 0.13595762576986914 -0.09622087197472673" universe="23" />
|
||||
<cell fill="9" id="213" region="-206" translation="0.07991907014916044 -0.19737570756346412 -0.09622087197472673" universe="26" />
|
||||
<cell fill="9" id="214" region="-207" translation="0.06943697893246592 0.16968387178879557 0.11988276699391809" universe="21" />
|
||||
<cell fill="9" id="215" region="-208" translation="0.06943697893246592 -0.1636494615445378 0.11988276699391809" universe="24" />
|
||||
<cell fill="9" id="216" region="-209" translation="-0.07059889277962383 0.1489570802132021 0.09503214710980579" universe="29" />
|
||||
<cell fill="9" id="217" region="-210" translation="-0.07059889277962383 -0.18437625312013128 0.09503214710980579" universe="32" />
|
||||
<cell fill="9" id="218" region="-211" translation="0.010468267263955 0.15608028424842002 -0.00511339431390323" universe="31" />
|
||||
<cell fill="9" id="219" region="-212" translation="0.010468267263955 -0.17725304908491335 -0.00511339431390323" universe="34" />
|
||||
<cell fill="9" id="220" region="-213" translation="0.15972123417512762 0.06883522628651784 -0.11009587369358387" universe="35" />
|
||||
<cell fill="9" id="221" region="-214" translation="-0.17361209915820575 0.06883522628651784 -0.11009587369358387" universe="36" />
|
||||
<cell fill="9" id="222" region="-215" translation="0.08981179676970563 0.06434186205946246 0.032607233968534766" universe="16" />
|
||||
<cell fill="9" id="223" region="-216" translation="0.0033702311569031584 0.10040789537086448 0.1867831868031803" universe="28" />
|
||||
<cell fill="9" id="224" region="-217" translation="0.0033702311569031584 0.10040789537086448 -0.14655014653015297" universe="37" />
|
||||
<cell fill="9" id="225" region="-218" translation="0.05329895281727448 -0.02881629065525937 0.15193411713913396" universe="20" />
|
||||
<cell fill="9" id="226" region="-219" translation="0.05329895281727448 -0.02881629065525937 -0.1813992161941993" universe="29" />
|
||||
<cell fill="9" id="227" region="-220" translation="0.14663786554095865 -0.0001831711922081758 0.173437280372308" universe="14" />
|
||||
<cell fill="9" id="228" region="-221" translation="-0.18669546779237473 -0.0001831711922081758 0.173437280372308" universe="15" />
|
||||
<cell fill="9" id="229" region="-222" translation="0.14663786554095865 -0.0001831711922081758 -0.15989605296102538" universe="23" />
|
||||
<cell fill="9" id="230" region="-223" translation="-0.18669546779237473 -0.0001831711922081758 -0.15989605296102538" universe="24" />
|
||||
<cell fill="9" id="231" region="-224" translation="0.006886156712931468 0.0325721225173089 -0.10785254014381473" universe="19" />
|
||||
<cell fill="9" id="232" region="-225" translation="0.05946426530734861 0.17562994884896627 0.11256068342977466" universe="29" />
|
||||
<cell fill="9" id="233" region="-226" translation="0.05946426530734861 -0.1577033844843671 0.11256068342977466" universe="32" />
|
||||
<cell fill="9" id="234" region="-227" translation="-0.0745211393530899 0.18602539894086317 0.07061211191996841" universe="13" />
|
||||
<cell fill="9" id="235" region="-228" translation="-0.0745211393530899 -0.1473079343924702 0.07061211191996841" universe="16" />
|
||||
<cell fill="9" id="236" region="-229" translation="0.15971361633210523 -0.02416800360737892 0.062334297185282495" universe="36" />
|
||||
<cell fill="9" id="237" region="-230" translation="-0.17361971700122802 -0.02416800360737892 0.062334297185282495" universe="37" />
|
||||
<cell fill="9" id="238" region="-231" translation="-0.014191419448261688 0.11114945107218455 0.0903966514577691" universe="18" />
|
||||
<cell fill="9" id="239" region="-232" translation="0.20641337800388493 -0.04689191572037532 0.03093832014609521" universe="12" />
|
||||
<cell fill="9" id="240" region="-233" translation="-0.12691995532944833 -0.04689191572037532 0.03093832014609521" universe="13" />
|
||||
<cell fill="9" id="241" region="-234" translation="0.042925982468302815 0.0705557158479822 -0.09611246805643225" universe="31" />
|
||||
<cell fill="9" id="242" region="-235" translation="0.09174118398607445 -0.02102680816462299 -0.12074712654412828" universe="27" />
|
||||
<cell fill="9" id="243" region="-236" translation="0.1871144659776534 0.14219092895822716 0.0030395151604761805" universe="29" />
|
||||
<cell fill="9" id="244" region="-237" translation="-0.14621886735567996 0.14219092895822716 0.0030395151604761805" universe="30" />
|
||||
<cell fill="9" id="245" region="-238" translation="0.1871144659776534 -0.1911424043751062 0.0030395151604761805" universe="32" />
|
||||
<cell fill="9" id="246" region="-239" translation="-0.14621886735567996 -0.1911424043751062 0.0030395151604761805" universe="33" />
|
||||
<cell fill="9" id="247" region="-240" translation="-0.08858601205119498 -0.05740809172565153 0.0018937978357634888" universe="29" />
|
||||
<cell fill="9" id="248" region="-241" translation="-0.06956272452538859 -0.03258611645335985 0.1876749617320655" universe="19" />
|
||||
<cell fill="9" id="249" region="-242" translation="-0.06956272452538859 -0.03258611645335985 -0.14565837160126788" universe="28" />
|
||||
<cell fill="9" id="250" region="-243" translation="0.06480048668590577 0.08039356693483157 -0.0495807099830502" universe="12" />
|
||||
<cell fill="9" id="251" region="-244" translation="0.11976882848311299 0.024414887718198774 0.059001075831400684" universe="26" />
|
||||
<cell fill="9" id="252" region="-245" translation="0.055815690196973966 -0.03866224334773988 0.12934415570493119" universe="16" />
|
||||
<cell fill="9" id="253" region="-246" translation="0.055815690196973966 -0.03866224334773988 -0.20398917762840219" universe="25" />
|
||||
<cell fill="9" id="254" region="-247" translation="-0.07057140884385227 -0.033261585924167725 -0.11308117958912334" universe="19" />
|
||||
<cell fill="9" id="255" region="-248" translation="0.0191891610992464 -0.08777511864372084 0.09496767886953814" universe="13" />
|
||||
<cell fill="9" id="256" region="-249" translation="0.11357577214048964 -0.07231206070759028 -0.01862315233444045" universe="16" />
|
||||
<cell fill="9" id="257" region="-250" translation="0.028822870329182626 0.09660360434040871 -0.10994545899370212" universe="29" />
|
||||
<cell fill="9" id="258" region="-251" translation="-0.030272006016200004 0.04272149160139638 -0.11143715881676097" universe="26" />
|
||||
<cell fill="9" id="259" region="-252" translation="0.09719339210824351 0.04131007428864286 0.14476192535372884" universe="19" />
|
||||
<cell fill="9" id="260" region="-253" translation="0.09719339210824351 0.04131007428864286 -0.18857140797960453" universe="28" />
|
||||
<cell fill="9" id="261" region="-254" translation="0.1075803128789849 -0.02104725713738881 -0.03274843538002781" universe="14" />
|
||||
<cell fill="9" id="262" region="-255" translation="0.1392019576325615 -0.08814436128642017 -0.11479828495132216" universe="12" />
|
||||
<cell fill="9" id="263" region="-256" translation="-0.19413137570077177 -0.08814436128642017 -0.11479828495132216" universe="13" />
|
||||
<cell fill="9" id="264" region="-257" translation="0.10847197677361597 0.1461592302081176 0.08841042383901798" universe="22" />
|
||||
<cell fill="9" id="265" region="-258" translation="0.10847197677361597 -0.18717410312521576 0.08841042383901798" universe="25" />
|
||||
<cell fill="9" id="266" region="-259" translation="0.045127058382085194 0.0967807216119615 0.0967653665331849" universe="37" />
|
||||
<cell fill="9" id="267" region="-260" translation="-0.022464471745497094 0.07259277205138148 0.10785219865057927" universe="20" />
|
||||
<cell fill="9" id="268" region="-261" translation="0.10606353369903221 0.03928703229725711 0.17228776926768086" universe="25" />
|
||||
<cell fill="9" id="269" region="-262" translation="0.10606353369903221 0.03928703229725711 -0.1610455640656524" universe="34" />
|
||||
<cell fill="9" id="270" region="-263" translation="0.14815941963538226 0.11277655887534538 0.03808687169681996" universe="21" />
|
||||
<cell fill="9" id="271" region="-264" translation="-0.185173913697951 0.11277655887534538 0.03808687169681996" universe="22" />
|
||||
<cell fill="9" id="272" region="-265" translation="0.15693581669068946 0.10114531834923532 -0.04992356195780889" universe="11" />
|
||||
<cell fill="9" id="273" region="-266" translation="-0.17639751664264391 0.10114531834923532 -0.04992356195780889" universe="12" />
|
||||
<cell fill="9" id="274" region="-267" translation="0.13264357875679378 0.10919805128102966 -0.04769549879176793" universe="26" />
|
||||
<cell fill="9" id="275" region="-268" translation="-0.2006897545765396 0.10919805128102966 -0.04769549879176793" universe="27" />
|
||||
<cell fill="9" id="276" region="-269" translation="0.13916564434634993 0.13134319648704007 0.07015912178562622" universe="33" />
|
||||
<cell fill="9" id="277" region="-270" translation="-0.19416768898698333 0.13134319648704007 0.07015912178562622" universe="34" />
|
||||
<cell fill="9" id="278" region="-271" translation="0.13916564434634993 -0.2019901368462932 0.07015912178562622" universe="36" />
|
||||
<cell fill="9" id="279" region="-272" translation="-0.19416768898698333 -0.2019901368462932 0.07015912178562622" universe="37" />
|
||||
<cell fill="9" id="280" region="-273" translation="-0.10026688643231585 0.1564443552698941 0.1751728484794038" universe="12" />
|
||||
<cell fill="9" id="281" region="-274" translation="-0.10026688643231585 -0.17688897806343928 0.1751728484794038" universe="15" />
|
||||
<cell fill="9" id="282" region="-275" translation="-0.10026688643231585 0.1564443552698941 -0.15816048485392958" universe="21" />
|
||||
<cell fill="9" id="283" region="-276" translation="-0.10026688643231585 -0.17688897806343928 -0.15816048485392958" universe="24" />
|
||||
<cell fill="9" id="284" region="-277" translation="0.16555436030710213 -0.015531455219433332 0.02691614144169241" universe="35" />
|
||||
<cell fill="9" id="285" region="-278" translation="-0.16777897302623124 -0.015531455219433332 0.02691614144169241" universe="36" />
|
||||
<cell fill="9" id="286" region="-279" translation="0.152805274648522 0.18166556620660584 0.040488366683789634" universe="20" />
|
||||
<cell fill="9" id="287" region="-280" translation="-0.18052805868481137 0.18166556620660584 0.040488366683789634" universe="21" />
|
||||
<cell fill="9" id="288" region="-281" translation="0.152805274648522 -0.15166776712672753 0.040488366683789634" universe="23" />
|
||||
<cell fill="9" id="289" region="-282" translation="-0.18052805868481137 -0.15166776712672753 0.040488366683789634" universe="24" />
|
||||
<cell fill="9" id="290" region="-283" translation="0.07231116694829032 0.08785370537091952 0.09997055589943346" universe="15" />
|
||||
<cell fill="9" id="291" region="-284" translation="-0.10576424362412257 0.09874497232579027 -0.05820080940738992" universe="11" />
|
||||
<cell fill="9" id="292" region="-285" translation="0.046877953125145755 -0.059492732184222796 -0.055635341857650844" universe="12" />
|
||||
<cell fill="9" id="293" region="-286" translation="0.1239423066569788 0.14183046274229005 -0.06583818749209458" universe="30" />
|
||||
<cell fill="9" id="294" region="-287" translation="0.1239423066569788 -0.19150287059104332 -0.06583818749209458" universe="33" />
|
||||
<cell fill="9" id="295" region="-288" translation="0.0013087859341976982 -0.06327594480884835 -0.05382522074205143" universe="18" />
|
||||
<cell fill="9" id="296" region="-289" translation="0.11058883669906516 -0.038954175820645864 0.16834558789033005" universe="19" />
|
||||
<cell fill="9" id="297" region="-290" translation="0.11058883669906516 -0.038954175820645864 -0.16498774544300332" universe="28" />
|
||||
<cell fill="9" id="298" region="-291" translation="-0.02657010065724863 0.013144978841080679 0.050587944514051575" universe="32" />
|
||||
<cell id="299" material="18" region="139 186 197 265 284" universe="11" />
|
||||
<cell id="300" material="18" region="140 176 181 188 232 243 255 266 273 285" universe="12" />
|
||||
<cell id="301" material="18" region="136 187 227 233 248 256" universe="13" />
|
||||
|
|
@ -199,7 +199,7 @@
|
|||
<cell id="325" material="18" region="172 183 217 230 259 272" universe="37" />
|
||||
<cell id="326" material="18" universe="38" />
|
||||
<lattice id="10">
|
||||
<pitch>0.333333333333 0.333333333333 0.333333333333</pitch>
|
||||
<pitch>0.3333333333333333 0.3333333333333333 0.3333333333333333</pitch>
|
||||
<outer>38</outer>
|
||||
<dimension>3 3 3</dimension>
|
||||
<lower_left>-0.5 -0.5 -0.5</lower_left>
|
||||
|
|
@ -226,170 +226,170 @@
|
|||
<surface boundary="reflective" coeffs="0.5" id="125" type="y-plane" />
|
||||
<surface boundary="reflective" coeffs="-0.5" id="126" type="z-plane" />
|
||||
<surface boundary="reflective" coeffs="0.5" id="127" type="z-plane" />
|
||||
<surface coeffs="-0.00140620118176 -0.0152577471673 -0.0918476696602 0.04225" id="128" type="sphere" />
|
||||
<surface coeffs="0.109099026398 -0.00417917776733 -0.0462409301859 0.04225" id="129" type="sphere" />
|
||||
<surface coeffs="0.138783366528 -0.0690071053688 -0.0384882149749 0.04225" id="130" type="sphere" />
|
||||
<surface coeffs="-0.194549966806 -0.0690071053688 -0.0384882149749 0.04225" id="131" type="sphere" />
|
||||
<surface coeffs="-0.0984645519108 -0.0259403806947 -0.0615517493329 0.04225" id="132" type="sphere" />
|
||||
<surface coeffs="-0.0932159178431 -0.122488574824 -0.0499980238428 0.04225" id="133" type="sphere" />
|
||||
<surface coeffs="0.202819899608 0.0850151469064 0.0743119884463 0.04225" id="134" type="sphere" />
|
||||
<surface coeffs="-0.130513433725 0.0850151469064 0.0743119884463 0.04225" id="135" type="sphere" />
|
||||
<surface coeffs="0.03417350411 -0.0964115371994 -0.101120980927 0.04225" id="136" type="sphere" />
|
||||
<surface coeffs="0.0379131188424 0.0687077251904 -0.108757520396 0.04225" id="137" type="sphere" />
|
||||
<surface coeffs="0.0738800814064 -0.071302275054 -0.0978298256419 0.04225" id="138" type="sphere" />
|
||||
<surface coeffs="0.0889721475441 0.0869416521141 0.075877373016 0.04225" id="139" type="sphere" />
|
||||
<surface coeffs="-0.0369830271171 0.140878401491 -0.104742841496 0.04225" id="140" type="sphere" />
|
||||
<surface coeffs="-0.0369830271171 -0.192454931842 -0.104742841496 0.04225" id="141" type="sphere" />
|
||||
<surface coeffs="-0.0242806966142 0.0516839323883 0.130270489265 0.04225" id="142" type="sphere" />
|
||||
<surface coeffs="-0.0242806966142 0.0516839323883 -0.203062844069 0.04225" id="143" type="sphere" />
|
||||
<surface coeffs="0.0457805197599 0.117590160514 -0.00380228622125 0.04225" id="144" type="sphere" />
|
||||
<surface coeffs="-0.0137419084645 0.180165775531 0.202768975142 0.04225" id="145" type="sphere" />
|
||||
<surface coeffs="-0.0137419084645 -0.153167557803 0.202768975142 0.04225" id="146" type="sphere" />
|
||||
<surface coeffs="-0.0137419084645 0.180165775531 -0.130564358191 0.04225" id="147" type="sphere" />
|
||||
<surface coeffs="-0.0137419084645 -0.153167557803 -0.130564358191 0.04225" id="148" type="sphere" />
|
||||
<surface coeffs="0.193346065156 0.0662280238816 -0.0713110415353 0.04225" id="149" type="sphere" />
|
||||
<surface coeffs="-0.139987268177 0.0662280238816 -0.0713110415353 0.04225" id="150" type="sphere" />
|
||||
<surface coeffs="-0.0311856561407 0.155914746052 0.153317205092 0.04225" id="151" type="sphere" />
|
||||
<surface coeffs="-0.0311856561407 -0.177418587281 0.153317205092 0.04225" id="152" type="sphere" />
|
||||
<surface coeffs="-0.0311856561407 0.155914746052 -0.180016128241 0.04225" id="153" type="sphere" />
|
||||
<surface coeffs="-0.0311856561407 -0.177418587281 -0.180016128241 0.04225" id="154" type="sphere" />
|
||||
<surface coeffs="0.0801800449244 0.0168261919282 -0.0163895967622 0.04225" id="155" type="sphere" />
|
||||
<surface coeffs="0.00483733774062 0.081481567183 -0.0928082691631 0.04225" id="156" type="sphere" />
|
||||
<surface coeffs="0.097811779112 -0.0610597446974 -0.0784455336401 0.04225" id="157" type="sphere" />
|
||||
<surface coeffs="0.033971609479 0.0446752660509 0.185883817671 0.04225" id="158" type="sphere" />
|
||||
<surface coeffs="0.033971609479 0.0446752660509 -0.147449515662 0.04225" id="159" type="sphere" />
|
||||
<surface coeffs="0.159741777825 -0.114709384731 -0.0558806276942 0.04225" id="160" type="sphere" />
|
||||
<surface coeffs="-0.173591555508 -0.114709384731 -0.0558806276942 0.04225" id="161" type="sphere" />
|
||||
<surface coeffs="0.00771444999286 -0.0784191193007 0.0191691213248 0.04225" id="162" type="sphere" />
|
||||
<surface coeffs="-0.0977249605603 -0.0094355820168 -0.097340787155 0.04225" id="163" type="sphere" />
|
||||
<surface coeffs="-0.0846040523453 0.186196302117 0.109025021864 0.04225" id="164" type="sphere" />
|
||||
<surface coeffs="-0.0846040523453 -0.147137031217 0.109025021864 0.04225" id="165" type="sphere" />
|
||||
<surface coeffs="0.0853097051629 -0.097409487121 0.0315380230547 0.04225" id="166" type="sphere" />
|
||||
<surface coeffs="0.00204940024585 0.108007828333 -0.0856693988182 0.04225" id="167" type="sphere" />
|
||||
<surface coeffs="0.0362697740558 -0.00348804073157 0.088140578575 0.04225" id="168" type="sphere" />
|
||||
<surface coeffs="0.0126079576483 0.0809005606263 0.071221146542 0.04225" id="169" type="sphere" />
|
||||
<surface coeffs="-0.0374148994358 0.122108694931 0.0439406213164 0.04225" id="170" type="sphere" />
|
||||
<surface coeffs="0.0851566223435 -0.119189958655 -0.0736469678739 0.04225" id="171" type="sphere" />
|
||||
<surface coeffs="-0.0399284809656 0.0202140729129 -0.1131524598 0.04225" id="172" type="sphere" />
|
||||
<surface coeffs="-0.0503157540846 0.0170999685653 0.0561731252046 0.04225" id="173" type="sphere" />
|
||||
<surface coeffs="-0.0676639827455 -0.0730357877864 0.00541096373088 0.04225" id="174" type="sphere" />
|
||||
<surface coeffs="0.0640843901638 0.0585363225055 0.00432158793112 0.04225" id="175" type="sphere" />
|
||||
<surface coeffs="-0.0138010597555 0.202224545874 0.192417668194 0.04225" id="176" type="sphere" />
|
||||
<surface coeffs="-0.0138010597555 -0.131108787459 0.192417668194 0.04225" id="177" type="sphere" />
|
||||
<surface coeffs="-0.0138010597555 0.202224545874 -0.140915665139 0.04225" id="178" type="sphere" />
|
||||
<surface coeffs="-0.0138010597555 -0.131108787459 -0.140915665139 0.04225" id="179" type="sphere" />
|
||||
<surface coeffs="0.035227337498 0.113054594036 0.102950231509 0.04225" id="180" type="sphere" />
|
||||
<surface coeffs="-0.0383166045087 -0.0988055687379 0.0857867394674 0.04225" id="181" type="sphere" />
|
||||
<surface coeffs="0.0378202408916 0.0773239271977 -0.00282972122211 0.04225" id="182" type="sphere" />
|
||||
<surface coeffs="-0.0601124832347 -0.0613405147405 -0.043634920585 0.04225" id="183" type="sphere" />
|
||||
<surface coeffs="0.109305027033 -0.0204659393864 0.158485432539 0.04225" id="184" type="sphere" />
|
||||
<surface coeffs="0.109305027033 -0.0204659393864 -0.174847900794 0.04225" id="185" type="sphere" />
|
||||
<surface coeffs="-0.0482158135072 -0.109136394796 -0.111087009623 0.04225" id="186" type="sphere" />
|
||||
<surface coeffs="-0.0993436405899 0.104054804419 -0.0241798283787 0.04225" id="187" type="sphere" />
|
||||
<surface coeffs="0.114256308042 0.190902465414 -0.0607753376217 0.04225" id="188" type="sphere" />
|
||||
<surface coeffs="0.114256308042 -0.14243086792 -0.0607753376217 0.04225" id="189" type="sphere" />
|
||||
<surface coeffs="0.0217205011906 0.0250667553285 0.0295200316 0.04225" id="190" type="sphere" />
|
||||
<surface coeffs="0.125436500241 0.193710578338 -0.0414706576932 0.04225" id="191" type="sphere" />
|
||||
<surface coeffs="-0.207896833092 0.193710578338 -0.0414706576932 0.04225" id="192" type="sphere" />
|
||||
<surface coeffs="0.125436500241 -0.139622754995 -0.0414706576932 0.04225" id="193" type="sphere" />
|
||||
<surface coeffs="-0.207896833092 -0.139622754995 -0.0414706576932 0.04225" id="194" type="sphere" />
|
||||
<surface coeffs="-0.103856970591 -0.0723989491841 0.0477333168332 0.04225" id="195" type="sphere" />
|
||||
<surface coeffs="-0.0248453372329 0.0327005037426 0.0092611805402 0.04225" id="196" type="sphere" />
|
||||
<surface coeffs="-0.105357688326 -0.108061697849 0.00966905666893 0.04225" id="197" type="sphere" />
|
||||
<surface coeffs="0.200343875313 0.0222716943858 0.187316452299 0.04225" id="198" type="sphere" />
|
||||
<surface coeffs="-0.13298945802 0.0222716943858 0.187316452299 0.04225" id="199" type="sphere" />
|
||||
<surface coeffs="0.200343875313 0.0222716943858 -0.146016881035 0.04225" id="200" type="sphere" />
|
||||
<surface coeffs="-0.13298945802 0.0222716943858 -0.146016881035 0.04225" id="201" type="sphere" />
|
||||
<surface coeffs="0.163119940576 0.0409248307565 0.0775424026481 0.04225" id="202" type="sphere" />
|
||||
<surface coeffs="-0.170213392757 0.0409248307565 0.0775424026481 0.04225" id="203" type="sphere" />
|
||||
<surface coeffs="0.102073447729 -0.0606874931034 0.0151968577672 0.04225" id="204" type="sphere" />
|
||||
<surface coeffs="0.0799190701492 0.13595762577 -0.0962208719747 0.04225" id="205" type="sphere" />
|
||||
<surface coeffs="0.0799190701492 -0.197375707563 -0.0962208719747 0.04225" id="206" type="sphere" />
|
||||
<surface coeffs="0.0694369789325 0.169683871789 0.119882766994 0.04225" id="207" type="sphere" />
|
||||
<surface coeffs="0.0694369789325 -0.163649461545 0.119882766994 0.04225" id="208" type="sphere" />
|
||||
<surface coeffs="-0.0705988927796 0.148957080213 0.0950321471098 0.04225" id="209" type="sphere" />
|
||||
<surface coeffs="-0.0705988927796 -0.18437625312 0.0950321471098 0.04225" id="210" type="sphere" />
|
||||
<surface coeffs="0.010468267264 0.156080284248 -0.0051133943139 0.04225" id="211" type="sphere" />
|
||||
<surface coeffs="0.010468267264 -0.177253049085 -0.0051133943139 0.04225" id="212" type="sphere" />
|
||||
<surface coeffs="0.159721234175 0.0688352262865 -0.110095873694 0.04225" id="213" type="sphere" />
|
||||
<surface coeffs="-0.173612099158 0.0688352262865 -0.110095873694 0.04225" id="214" type="sphere" />
|
||||
<surface coeffs="0.0898117967697 0.0643418620595 0.0326072339685 0.04225" id="215" type="sphere" />
|
||||
<surface coeffs="0.0033702311569 0.100407895371 0.186783186803 0.04225" id="216" type="sphere" />
|
||||
<surface coeffs="0.0033702311569 0.100407895371 -0.14655014653 0.04225" id="217" type="sphere" />
|
||||
<surface coeffs="0.0532989528173 -0.0288162906553 0.151934117139 0.04225" id="218" type="sphere" />
|
||||
<surface coeffs="0.0532989528173 -0.0288162906553 -0.181399216194 0.04225" id="219" type="sphere" />
|
||||
<surface coeffs="0.146637865541 -0.000183171192208 0.173437280372 0.04225" id="220" type="sphere" />
|
||||
<surface coeffs="-0.186695467792 -0.000183171192208 0.173437280372 0.04225" id="221" type="sphere" />
|
||||
<surface coeffs="0.146637865541 -0.000183171192208 -0.159896052961 0.04225" id="222" type="sphere" />
|
||||
<surface coeffs="-0.186695467792 -0.000183171192208 -0.159896052961 0.04225" id="223" type="sphere" />
|
||||
<surface coeffs="0.00688615671293 0.0325721225173 -0.107852540144 0.04225" id="224" type="sphere" />
|
||||
<surface coeffs="0.0594642653073 0.175629948849 0.11256068343 0.04225" id="225" type="sphere" />
|
||||
<surface coeffs="0.0594642653073 -0.157703384484 0.11256068343 0.04225" id="226" type="sphere" />
|
||||
<surface coeffs="-0.0745211393531 0.186025398941 0.07061211192 0.04225" id="227" type="sphere" />
|
||||
<surface coeffs="-0.0745211393531 -0.147307934392 0.07061211192 0.04225" id="228" type="sphere" />
|
||||
<surface coeffs="0.159713616332 -0.0241680036074 0.0623342971853 0.04225" id="229" type="sphere" />
|
||||
<surface coeffs="-0.173619717001 -0.0241680036074 0.0623342971853 0.04225" id="230" type="sphere" />
|
||||
<surface coeffs="-0.0141914194483 0.111149451072 0.0903966514578 0.04225" id="231" type="sphere" />
|
||||
<surface coeffs="0.206413378004 -0.0468919157204 0.0309383201461 0.04225" id="232" type="sphere" />
|
||||
<surface coeffs="-0.126919955329 -0.0468919157204 0.0309383201461 0.04225" id="233" type="sphere" />
|
||||
<surface coeffs="0.0429259824683 0.070555715848 -0.0961124680564 0.04225" id="234" type="sphere" />
|
||||
<surface coeffs="0.0917411839861 -0.0210268081646 -0.120747126544 0.04225" id="235" type="sphere" />
|
||||
<surface coeffs="0.187114465978 0.142190928958 0.00303951516048 0.04225" id="236" type="sphere" />
|
||||
<surface coeffs="-0.146218867356 0.142190928958 0.00303951516048 0.04225" id="237" type="sphere" />
|
||||
<surface coeffs="0.187114465978 -0.191142404375 0.00303951516048 0.04225" id="238" type="sphere" />
|
||||
<surface coeffs="-0.146218867356 -0.191142404375 0.00303951516048 0.04225" id="239" type="sphere" />
|
||||
<surface coeffs="-0.0885860120512 -0.0574080917257 0.00189379783576 0.04225" id="240" type="sphere" />
|
||||
<surface coeffs="-0.0695627245254 -0.0325861164534 0.187674961732 0.04225" id="241" type="sphere" />
|
||||
<surface coeffs="-0.0695627245254 -0.0325861164534 -0.145658371601 0.04225" id="242" type="sphere" />
|
||||
<surface coeffs="0.0648004866859 0.0803935669348 -0.0495807099831 0.04225" id="243" type="sphere" />
|
||||
<surface coeffs="0.119768828483 0.0244148877182 0.0590010758314 0.04225" id="244" type="sphere" />
|
||||
<surface coeffs="0.055815690197 -0.0386622433477 0.129344155705 0.04225" id="245" type="sphere" />
|
||||
<surface coeffs="0.055815690197 -0.0386622433477 -0.203989177628 0.04225" id="246" type="sphere" />
|
||||
<surface coeffs="-0.0705714088439 -0.0332615859242 -0.113081179589 0.04225" id="247" type="sphere" />
|
||||
<surface coeffs="0.0191891610992 -0.0877751186437 0.0949676788695 0.04225" id="248" type="sphere" />
|
||||
<surface coeffs="0.11357577214 -0.0723120607076 -0.0186231523344 0.04225" id="249" type="sphere" />
|
||||
<surface coeffs="0.0288228703292 0.0966036043404 -0.109945458994 0.04225" id="250" type="sphere" />
|
||||
<surface coeffs="-0.0302720060162 0.0427214916014 -0.111437158817 0.04225" id="251" type="sphere" />
|
||||
<surface coeffs="0.0971933921082 0.0413100742886 0.144761925354 0.04225" id="252" type="sphere" />
|
||||
<surface coeffs="0.0971933921082 0.0413100742886 -0.18857140798 0.04225" id="253" type="sphere" />
|
||||
<surface coeffs="0.107580312879 -0.0210472571374 -0.03274843538 0.04225" id="254" type="sphere" />
|
||||
<surface coeffs="0.139201957633 -0.0881443612864 -0.114798284951 0.04225" id="255" type="sphere" />
|
||||
<surface coeffs="-0.194131375701 -0.0881443612864 -0.114798284951 0.04225" id="256" type="sphere" />
|
||||
<surface coeffs="0.108471976774 0.146159230208 0.088410423839 0.04225" id="257" type="sphere" />
|
||||
<surface coeffs="0.108471976774 -0.187174103125 0.088410423839 0.04225" id="258" type="sphere" />
|
||||
<surface coeffs="0.0451270583821 0.096780721612 0.0967653665332 0.04225" id="259" type="sphere" />
|
||||
<surface coeffs="-0.0224644717455 0.0725927720514 0.107852198651 0.04225" id="260" type="sphere" />
|
||||
<surface coeffs="0.106063533699 0.0392870322973 0.172287769268 0.04225" id="261" type="sphere" />
|
||||
<surface coeffs="0.106063533699 0.0392870322973 -0.161045564066 0.04225" id="262" type="sphere" />
|
||||
<surface coeffs="0.148159419635 0.112776558875 0.0380868716968 0.04225" id="263" type="sphere" />
|
||||
<surface coeffs="-0.185173913698 0.112776558875 0.0380868716968 0.04225" id="264" type="sphere" />
|
||||
<surface coeffs="0.156935816691 0.101145318349 -0.0499235619578 0.04225" id="265" type="sphere" />
|
||||
<surface coeffs="-0.176397516643 0.101145318349 -0.0499235619578 0.04225" id="266" type="sphere" />
|
||||
<surface coeffs="0.132643578757 0.109198051281 -0.0476954987918 0.04225" id="267" type="sphere" />
|
||||
<surface coeffs="-0.200689754577 0.109198051281 -0.0476954987918 0.04225" id="268" type="sphere" />
|
||||
<surface coeffs="0.139165644346 0.131343196487 0.0701591217856 0.04225" id="269" type="sphere" />
|
||||
<surface coeffs="-0.194167688987 0.131343196487 0.0701591217856 0.04225" id="270" type="sphere" />
|
||||
<surface coeffs="0.139165644346 -0.201990136846 0.0701591217856 0.04225" id="271" type="sphere" />
|
||||
<surface coeffs="-0.194167688987 -0.201990136846 0.0701591217856 0.04225" id="272" type="sphere" />
|
||||
<surface coeffs="-0.100266886432 0.15644435527 0.175172848479 0.04225" id="273" type="sphere" />
|
||||
<surface coeffs="-0.100266886432 -0.176888978063 0.175172848479 0.04225" id="274" type="sphere" />
|
||||
<surface coeffs="-0.100266886432 0.15644435527 -0.158160484854 0.04225" id="275" type="sphere" />
|
||||
<surface coeffs="-0.100266886432 -0.176888978063 -0.158160484854 0.04225" id="276" type="sphere" />
|
||||
<surface coeffs="0.165554360307 -0.0155314552194 0.0269161414417 0.04225" id="277" type="sphere" />
|
||||
<surface coeffs="-0.167778973026 -0.0155314552194 0.0269161414417 0.04225" id="278" type="sphere" />
|
||||
<surface coeffs="0.152805274649 0.181665566207 0.0404883666838 0.04225" id="279" type="sphere" />
|
||||
<surface coeffs="-0.180528058685 0.181665566207 0.0404883666838 0.04225" id="280" type="sphere" />
|
||||
<surface coeffs="0.152805274649 -0.151667767127 0.0404883666838 0.04225" id="281" type="sphere" />
|
||||
<surface coeffs="-0.180528058685 -0.151667767127 0.0404883666838 0.04225" id="282" type="sphere" />
|
||||
<surface coeffs="0.0723111669483 0.0878537053709 0.0999705558994 0.04225" id="283" type="sphere" />
|
||||
<surface coeffs="-0.105764243624 0.0987449723258 -0.0582008094074 0.04225" id="284" type="sphere" />
|
||||
<surface coeffs="0.0468779531251 -0.0594927321842 -0.0556353418577 0.04225" id="285" type="sphere" />
|
||||
<surface coeffs="0.123942306657 0.141830462742 -0.0658381874921 0.04225" id="286" type="sphere" />
|
||||
<surface coeffs="0.123942306657 -0.191502870591 -0.0658381874921 0.04225" id="287" type="sphere" />
|
||||
<surface coeffs="0.0013087859342 -0.0632759448088 -0.0538252207421 0.04225" id="288" type="sphere" />
|
||||
<surface coeffs="0.110588836699 -0.0389541758206 0.16834558789 0.04225" id="289" type="sphere" />
|
||||
<surface coeffs="0.110588836699 -0.0389541758206 -0.164987745443 0.04225" id="290" type="sphere" />
|
||||
<surface coeffs="-0.0265701006572 0.0131449788411 0.0505879445141 0.04225" id="291" type="sphere" />
|
||||
<surface coeffs="-0.0014062011817633224 -0.015257747167296776 -0.09184766966024316 0.04225" id="128" type="sphere" />
|
||||
<surface coeffs="0.10909902639777394 -0.004179177767328068 -0.046240930185910245 0.04225" id="129" type="sphere" />
|
||||
<surface coeffs="0.13878336652768952 -0.06900710536877097 -0.03848821497485455 0.04225" id="130" type="sphere" />
|
||||
<surface coeffs="-0.19454996680564374 -0.06900710536877097 -0.03848821497485455 0.04225" id="131" type="sphere" />
|
||||
<surface coeffs="-0.09846455191076986 -0.02594038069469251 -0.06155174933292362 0.04225" id="132" type="sphere" />
|
||||
<surface coeffs="-0.09321591784308736 -0.12248857482372477 -0.04999802384282931 0.04225" id="133" type="sphere" />
|
||||
<surface coeffs="0.2028198996079864 0.08501514690643278 0.07431198844628262 0.04225" id="134" type="sphere" />
|
||||
<surface coeffs="-0.13051343372534685 0.08501514690643278 0.07431198844628262 0.04225" id="135" type="sphere" />
|
||||
<surface coeffs="0.03417350410997999 -0.09641153719944834 -0.10112098092715327 0.04225" id="136" type="sphere" />
|
||||
<surface coeffs="0.037913118842446136 0.06870772519039314 -0.10875752039644154 0.04225" id="137" type="sphere" />
|
||||
<surface coeffs="0.07388008140640989 -0.07130227505402231 -0.09782982564187503 0.04225" id="138" type="sphere" />
|
||||
<surface coeffs="0.08897214754414112 0.08694165211410448 0.07587737301598729 0.04225" id="139" type="sphere" />
|
||||
<surface coeffs="-0.03698302711710488 0.1408784014909229 -0.10474284149572705 0.04225" id="140" type="sphere" />
|
||||
<surface coeffs="-0.03698302711710488 -0.19245493184241047 -0.10474284149572705 0.04225" id="141" type="sphere" />
|
||||
<surface coeffs="-0.02428069661424781 0.05168393238830282 0.1302704892646539 0.04225" id="142" type="sphere" />
|
||||
<surface coeffs="-0.02428069661424781 0.05168393238830282 -0.20306284406867936 0.04225" id="143" type="sphere" />
|
||||
<surface coeffs="0.04578051975994746 0.1175901605138544 -0.0038022862212453434 0.04225" id="144" type="sphere" />
|
||||
<surface coeffs="-0.013741908464450836 0.18016577553053154 0.20276897514248216 0.04225" id="145" type="sphere" />
|
||||
<surface coeffs="-0.013741908464450836 -0.15316755780280183 0.20276897514248216 0.04225" id="146" type="sphere" />
|
||||
<surface coeffs="-0.013741908464450836 0.18016577553053154 -0.1305643581908511 0.04225" id="147" type="sphere" />
|
||||
<surface coeffs="-0.013741908464450836 -0.15316755780280183 -0.1305643581908511 0.04225" id="148" type="sphere" />
|
||||
<surface coeffs="0.19334606515602848 0.066228023881572 -0.07131104153532436 0.04225" id="149" type="sphere" />
|
||||
<surface coeffs="-0.13998726817730478 0.066228023881572 -0.07131104153532436 0.04225" id="150" type="sphere" />
|
||||
<surface coeffs="-0.031185656140686913 0.155914746052082 0.15331720509241947 0.04225" id="151" type="sphere" />
|
||||
<surface coeffs="-0.031185656140686913 -0.17741858728125126 0.15331720509241947 0.04225" id="152" type="sphere" />
|
||||
<surface coeffs="-0.031185656140686913 0.155914746052082 -0.1800161282409139 0.04225" id="153" type="sphere" />
|
||||
<surface coeffs="-0.031185656140686913 -0.17741858728125126 -0.1800161282409139 0.04225" id="154" type="sphere" />
|
||||
<surface coeffs="0.08018004492442865 0.016826191928232426 -0.016389596762212966 0.04225" id="155" type="sphere" />
|
||||
<surface coeffs="0.00483733774062417 0.08148156718302602 -0.09280826916311341 0.04225" id="156" type="sphere" />
|
||||
<surface coeffs="0.0978117791120118 -0.06105974469736897 -0.07844553364014112 0.04225" id="157" type="sphere" />
|
||||
<surface coeffs="0.0339716094789545 0.044675266050854034 0.18588381767108564 0.04225" id="158" type="sphere" />
|
||||
<surface coeffs="0.0339716094789545 0.044675266050854034 -0.14744951566224762 0.04225" id="159" type="sphere" />
|
||||
<surface coeffs="0.15974177782488064 -0.11470938473074832 -0.055880627694202434 0.04225" id="160" type="sphere" />
|
||||
<surface coeffs="-0.17359155550845262 -0.11470938473074832 -0.055880627694202434 0.04225" id="161" type="sphere" />
|
||||
<surface coeffs="0.007714449992858363 -0.07841911930069978 0.019169121324834393 0.04225" id="162" type="sphere" />
|
||||
<surface coeffs="-0.09772496056025104 -0.009435582016802613 -0.0973407871549632 0.04225" id="163" type="sphere" />
|
||||
<surface coeffs="-0.08460405234526575 0.18619630211681182 0.10902502186367324 0.04225" id="164" type="sphere" />
|
||||
<surface coeffs="-0.08460405234526575 -0.14713703121652144 0.10902502186367324 0.04225" id="165" type="sphere" />
|
||||
<surface coeffs="0.08530970516294267 -0.09740948712101977 0.031538023054709596 0.04225" id="166" type="sphere" />
|
||||
<surface coeffs="0.002049400245853761 0.10800782833319489 -0.08566939881823532 0.04225" id="167" type="sphere" />
|
||||
<surface coeffs="0.036269774055772475 -0.0034880407315701634 0.08814057857502322 0.04225" id="168" type="sphere" />
|
||||
<surface coeffs="0.012607957648281654 0.08090056062626749 0.0712211465420014 0.04225" id="169" type="sphere" />
|
||||
<surface coeffs="-0.03741489943578313 0.1221086949309545 0.0439406213163509 0.04225" id="170" type="sphere" />
|
||||
<surface coeffs="0.0851566223435044 -0.1191899586548319 -0.07364696787394387 0.04225" id="171" type="sphere" />
|
||||
<surface coeffs="-0.03992848096555457 0.020214072912877246 -0.11315245980004196 0.04225" id="172" type="sphere" />
|
||||
<surface coeffs="-0.050315754084578224 0.017099968565308377 0.056173125204605934 0.04225" id="173" type="sphere" />
|
||||
<surface coeffs="-0.06766398274549851 -0.07303578778642877 0.005410963730880458 0.04225" id="174" type="sphere" />
|
||||
<surface coeffs="0.06408439016382617 0.05853632250550789 0.00432158793112436 0.04225" id="175" type="sphere" />
|
||||
<surface coeffs="-0.013801059755509382 0.20222454587424032 0.19241766819445416 0.04225" id="176" type="sphere" />
|
||||
<surface coeffs="-0.013801059755509382 -0.13110878745909305 0.19241766819445416 0.04225" id="177" type="sphere" />
|
||||
<surface coeffs="-0.013801059755509382 0.20222454587424032 -0.1409156651388792 0.04225" id="178" type="sphere" />
|
||||
<surface coeffs="-0.013801059755509382 -0.13110878745909305 -0.1409156651388792 0.04225" id="179" type="sphere" />
|
||||
<surface coeffs="0.03522733749799645 0.11305459403611595 0.10295023150858529 0.04225" id="180" type="sphere" />
|
||||
<surface coeffs="-0.03831660450870228 -0.09880556873790897 0.08578673946744877 0.04225" id="181" type="sphere" />
|
||||
<surface coeffs="0.03782024089160585 0.07732392719766301 -0.002829721222114334 0.04225" id="182" type="sphere" />
|
||||
<surface coeffs="-0.060112483234699754 -0.06134051474053648 -0.04363492058502072 0.04225" id="183" type="sphere" />
|
||||
<surface coeffs="0.10930502703326198 -0.020465939386398402 0.15848543253913627 0.04225" id="184" type="sphere" />
|
||||
<surface coeffs="0.10930502703326198 -0.020465939386398402 -0.174847900794197 0.04225" id="185" type="sphere" />
|
||||
<surface coeffs="-0.04821581350719811 -0.10913639479587178 -0.11108700962300094 0.04225" id="186" type="sphere" />
|
||||
<surface coeffs="-0.09934364058994583 0.10405480441904197 -0.0241798283786806 0.04225" id="187" type="sphere" />
|
||||
<surface coeffs="0.11425630804159204 0.19090246541367445 -0.06077533762167586 0.04225" id="188" type="sphere" />
|
||||
<surface coeffs="0.11425630804159204 -0.14243086791965892 -0.06077533762167586 0.04225" id="189" type="sphere" />
|
||||
<surface coeffs="0.0217205011905508 0.02506675532845576 0.029520031599966412 0.04225" id="190" type="sphere" />
|
||||
<surface coeffs="0.12543650024083502 0.19371057833811733 -0.04147065769319469 0.04225" id="191" type="sphere" />
|
||||
<surface coeffs="-0.20789683309249835 0.19371057833811733 -0.04147065769319469 0.04225" id="192" type="sphere" />
|
||||
<surface coeffs="0.12543650024083502 -0.13962275499521593 -0.04147065769319469 0.04225" id="193" type="sphere" />
|
||||
<surface coeffs="-0.20789683309249835 -0.13962275499521593 -0.04147065769319469 0.04225" id="194" type="sphere" />
|
||||
<surface coeffs="-0.10385697059087434 -0.07239894918409101 0.047733316833160344 0.04225" id="195" type="sphere" />
|
||||
<surface coeffs="-0.02484533723289073 0.03270050374260325 0.009261180540203251 0.04225" id="196" type="sphere" />
|
||||
<surface coeffs="-0.10535768832641407 -0.10806169784882003 0.009669056668934639 0.04225" id="197" type="sphere" />
|
||||
<surface coeffs="0.20034387531341857 0.02227169438582799 0.18731645229850835 0.04225" id="198" type="sphere" />
|
||||
<surface coeffs="-0.13298945801991469 0.02227169438582799 0.18731645229850835 0.04225" id="199" type="sphere" />
|
||||
<surface coeffs="0.20034387531341857 0.02227169438582799 -0.1460168810348249 0.04225" id="200" type="sphere" />
|
||||
<surface coeffs="-0.13298945801991469 0.02227169438582799 -0.1460168810348249 0.04225" id="201" type="sphere" />
|
||||
<surface coeffs="0.1631199405760454 0.04092483075648701 0.07754240264809376 0.04225" id="202" type="sphere" />
|
||||
<surface coeffs="-0.17021339275728786 0.04092483075648701 0.07754240264809376 0.04225" id="203" type="sphere" />
|
||||
<surface coeffs="0.102073447728939 -0.060687493103351975 0.01519685776716928 0.04225" id="204" type="sphere" />
|
||||
<surface coeffs="0.07991907014916044 0.13595762576986914 -0.09622087197472673 0.04225" id="205" type="sphere" />
|
||||
<surface coeffs="0.07991907014916044 -0.19737570756346412 -0.09622087197472673 0.04225" id="206" type="sphere" />
|
||||
<surface coeffs="0.06943697893246592 0.16968387178879557 0.11988276699391809 0.04225" id="207" type="sphere" />
|
||||
<surface coeffs="0.06943697893246592 -0.1636494615445378 0.11988276699391809 0.04225" id="208" type="sphere" />
|
||||
<surface coeffs="-0.07059889277962383 0.1489570802132021 0.09503214710980579 0.04225" id="209" type="sphere" />
|
||||
<surface coeffs="-0.07059889277962383 -0.18437625312013128 0.09503214710980579 0.04225" id="210" type="sphere" />
|
||||
<surface coeffs="0.010468267263955 0.15608028424842002 -0.00511339431390323 0.04225" id="211" type="sphere" />
|
||||
<surface coeffs="0.010468267263955 -0.17725304908491335 -0.00511339431390323 0.04225" id="212" type="sphere" />
|
||||
<surface coeffs="0.15972123417512762 0.06883522628651784 -0.11009587369358387 0.04225" id="213" type="sphere" />
|
||||
<surface coeffs="-0.17361209915820575 0.06883522628651784 -0.11009587369358387 0.04225" id="214" type="sphere" />
|
||||
<surface coeffs="0.08981179676970563 0.06434186205946246 0.032607233968534766 0.04225" id="215" type="sphere" />
|
||||
<surface coeffs="0.0033702311569031584 0.10040789537086448 0.1867831868031803 0.04225" id="216" type="sphere" />
|
||||
<surface coeffs="0.0033702311569031584 0.10040789537086448 -0.14655014653015297 0.04225" id="217" type="sphere" />
|
||||
<surface coeffs="0.05329895281727448 -0.02881629065525937 0.15193411713913396 0.04225" id="218" type="sphere" />
|
||||
<surface coeffs="0.05329895281727448 -0.02881629065525937 -0.1813992161941993 0.04225" id="219" type="sphere" />
|
||||
<surface coeffs="0.14663786554095865 -0.0001831711922081758 0.173437280372308 0.04225" id="220" type="sphere" />
|
||||
<surface coeffs="-0.18669546779237473 -0.0001831711922081758 0.173437280372308 0.04225" id="221" type="sphere" />
|
||||
<surface coeffs="0.14663786554095865 -0.0001831711922081758 -0.15989605296102538 0.04225" id="222" type="sphere" />
|
||||
<surface coeffs="-0.18669546779237473 -0.0001831711922081758 -0.15989605296102538 0.04225" id="223" type="sphere" />
|
||||
<surface coeffs="0.006886156712931468 0.0325721225173089 -0.10785254014381473 0.04225" id="224" type="sphere" />
|
||||
<surface coeffs="0.05946426530734861 0.17562994884896627 0.11256068342977466 0.04225" id="225" type="sphere" />
|
||||
<surface coeffs="0.05946426530734861 -0.1577033844843671 0.11256068342977466 0.04225" id="226" type="sphere" />
|
||||
<surface coeffs="-0.0745211393530899 0.18602539894086317 0.07061211191996841 0.04225" id="227" type="sphere" />
|
||||
<surface coeffs="-0.0745211393530899 -0.1473079343924702 0.07061211191996841 0.04225" id="228" type="sphere" />
|
||||
<surface coeffs="0.15971361633210523 -0.02416800360737892 0.062334297185282495 0.04225" id="229" type="sphere" />
|
||||
<surface coeffs="-0.17361971700122802 -0.02416800360737892 0.062334297185282495 0.04225" id="230" type="sphere" />
|
||||
<surface coeffs="-0.014191419448261688 0.11114945107218455 0.0903966514577691 0.04225" id="231" type="sphere" />
|
||||
<surface coeffs="0.20641337800388493 -0.04689191572037532 0.03093832014609521 0.04225" id="232" type="sphere" />
|
||||
<surface coeffs="-0.12691995532944833 -0.04689191572037532 0.03093832014609521 0.04225" id="233" type="sphere" />
|
||||
<surface coeffs="0.042925982468302815 0.0705557158479822 -0.09611246805643225 0.04225" id="234" type="sphere" />
|
||||
<surface coeffs="0.09174118398607445 -0.02102680816462299 -0.12074712654412828 0.04225" id="235" type="sphere" />
|
||||
<surface coeffs="0.1871144659776534 0.14219092895822716 0.0030395151604761805 0.04225" id="236" type="sphere" />
|
||||
<surface coeffs="-0.14621886735567996 0.14219092895822716 0.0030395151604761805 0.04225" id="237" type="sphere" />
|
||||
<surface coeffs="0.1871144659776534 -0.1911424043751062 0.0030395151604761805 0.04225" id="238" type="sphere" />
|
||||
<surface coeffs="-0.14621886735567996 -0.1911424043751062 0.0030395151604761805 0.04225" id="239" type="sphere" />
|
||||
<surface coeffs="-0.08858601205119498 -0.05740809172565153 0.0018937978357634888 0.04225" id="240" type="sphere" />
|
||||
<surface coeffs="-0.06956272452538859 -0.03258611645335985 0.1876749617320655 0.04225" id="241" type="sphere" />
|
||||
<surface coeffs="-0.06956272452538859 -0.03258611645335985 -0.14565837160126788 0.04225" id="242" type="sphere" />
|
||||
<surface coeffs="0.06480048668590577 0.08039356693483157 -0.0495807099830502 0.04225" id="243" type="sphere" />
|
||||
<surface coeffs="0.11976882848311299 0.024414887718198774 0.059001075831400684 0.04225" id="244" type="sphere" />
|
||||
<surface coeffs="0.055815690196973966 -0.03866224334773988 0.12934415570493119 0.04225" id="245" type="sphere" />
|
||||
<surface coeffs="0.055815690196973966 -0.03866224334773988 -0.20398917762840219 0.04225" id="246" type="sphere" />
|
||||
<surface coeffs="-0.07057140884385227 -0.033261585924167725 -0.11308117958912334 0.04225" id="247" type="sphere" />
|
||||
<surface coeffs="0.0191891610992464 -0.08777511864372084 0.09496767886953814 0.04225" id="248" type="sphere" />
|
||||
<surface coeffs="0.11357577214048964 -0.07231206070759028 -0.01862315233444045 0.04225" id="249" type="sphere" />
|
||||
<surface coeffs="0.028822870329182626 0.09660360434040871 -0.10994545899370212 0.04225" id="250" type="sphere" />
|
||||
<surface coeffs="-0.030272006016200004 0.04272149160139638 -0.11143715881676097 0.04225" id="251" type="sphere" />
|
||||
<surface coeffs="0.09719339210824351 0.04131007428864286 0.14476192535372884 0.04225" id="252" type="sphere" />
|
||||
<surface coeffs="0.09719339210824351 0.04131007428864286 -0.18857140797960453 0.04225" id="253" type="sphere" />
|
||||
<surface coeffs="0.1075803128789849 -0.02104725713738881 -0.03274843538002781 0.04225" id="254" type="sphere" />
|
||||
<surface coeffs="0.1392019576325615 -0.08814436128642017 -0.11479828495132216 0.04225" id="255" type="sphere" />
|
||||
<surface coeffs="-0.19413137570077177 -0.08814436128642017 -0.11479828495132216 0.04225" id="256" type="sphere" />
|
||||
<surface coeffs="0.10847197677361597 0.1461592302081176 0.08841042383901798 0.04225" id="257" type="sphere" />
|
||||
<surface coeffs="0.10847197677361597 -0.18717410312521576 0.08841042383901798 0.04225" id="258" type="sphere" />
|
||||
<surface coeffs="0.045127058382085194 0.0967807216119615 0.0967653665331849 0.04225" id="259" type="sphere" />
|
||||
<surface coeffs="-0.022464471745497094 0.07259277205138148 0.10785219865057927 0.04225" id="260" type="sphere" />
|
||||
<surface coeffs="0.10606353369903221 0.03928703229725711 0.17228776926768086 0.04225" id="261" type="sphere" />
|
||||
<surface coeffs="0.10606353369903221 0.03928703229725711 -0.1610455640656524 0.04225" id="262" type="sphere" />
|
||||
<surface coeffs="0.14815941963538226 0.11277655887534538 0.03808687169681996 0.04225" id="263" type="sphere" />
|
||||
<surface coeffs="-0.185173913697951 0.11277655887534538 0.03808687169681996 0.04225" id="264" type="sphere" />
|
||||
<surface coeffs="0.15693581669068946 0.10114531834923532 -0.04992356195780889 0.04225" id="265" type="sphere" />
|
||||
<surface coeffs="-0.17639751664264391 0.10114531834923532 -0.04992356195780889 0.04225" id="266" type="sphere" />
|
||||
<surface coeffs="0.13264357875679378 0.10919805128102966 -0.04769549879176793 0.04225" id="267" type="sphere" />
|
||||
<surface coeffs="-0.2006897545765396 0.10919805128102966 -0.04769549879176793 0.04225" id="268" type="sphere" />
|
||||
<surface coeffs="0.13916564434634993 0.13134319648704007 0.07015912178562622 0.04225" id="269" type="sphere" />
|
||||
<surface coeffs="-0.19416768898698333 0.13134319648704007 0.07015912178562622 0.04225" id="270" type="sphere" />
|
||||
<surface coeffs="0.13916564434634993 -0.2019901368462932 0.07015912178562622 0.04225" id="271" type="sphere" />
|
||||
<surface coeffs="-0.19416768898698333 -0.2019901368462932 0.07015912178562622 0.04225" id="272" type="sphere" />
|
||||
<surface coeffs="-0.10026688643231585 0.1564443552698941 0.1751728484794038 0.04225" id="273" type="sphere" />
|
||||
<surface coeffs="-0.10026688643231585 -0.17688897806343928 0.1751728484794038 0.04225" id="274" type="sphere" />
|
||||
<surface coeffs="-0.10026688643231585 0.1564443552698941 -0.15816048485392958 0.04225" id="275" type="sphere" />
|
||||
<surface coeffs="-0.10026688643231585 -0.17688897806343928 -0.15816048485392958 0.04225" id="276" type="sphere" />
|
||||
<surface coeffs="0.16555436030710213 -0.015531455219433332 0.02691614144169241 0.04225" id="277" type="sphere" />
|
||||
<surface coeffs="-0.16777897302623124 -0.015531455219433332 0.02691614144169241 0.04225" id="278" type="sphere" />
|
||||
<surface coeffs="0.152805274648522 0.18166556620660584 0.040488366683789634 0.04225" id="279" type="sphere" />
|
||||
<surface coeffs="-0.18052805868481137 0.18166556620660584 0.040488366683789634 0.04225" id="280" type="sphere" />
|
||||
<surface coeffs="0.152805274648522 -0.15166776712672753 0.040488366683789634 0.04225" id="281" type="sphere" />
|
||||
<surface coeffs="-0.18052805868481137 -0.15166776712672753 0.040488366683789634 0.04225" id="282" type="sphere" />
|
||||
<surface coeffs="0.07231116694829032 0.08785370537091952 0.09997055589943346 0.04225" id="283" type="sphere" />
|
||||
<surface coeffs="-0.10576424362412257 0.09874497232579027 -0.05820080940738992 0.04225" id="284" type="sphere" />
|
||||
<surface coeffs="0.046877953125145755 -0.059492732184222796 -0.055635341857650844 0.04225" id="285" type="sphere" />
|
||||
<surface coeffs="0.1239423066569788 0.14183046274229005 -0.06583818749209458 0.04225" id="286" type="sphere" />
|
||||
<surface coeffs="0.1239423066569788 -0.19150287059104332 -0.06583818749209458 0.04225" id="287" type="sphere" />
|
||||
<surface coeffs="0.0013087859341976982 -0.06327594480884835 -0.05382522074205143 0.04225" id="288" type="sphere" />
|
||||
<surface coeffs="0.11058883669906516 -0.038954175820645864 0.16834558789033005 0.04225" id="289" type="sphere" />
|
||||
<surface coeffs="0.11058883669906516 -0.038954175820645864 -0.16498774544300332 0.04225" id="290" type="sphere" />
|
||||
<surface coeffs="-0.02657010065724863 0.013144978841080679 0.050587944514051575 0.04225" id="291" type="sphere" />
|
||||
</geometry>
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<materials>
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
k-combined:
|
||||
1.681659E+00 7.262745E-02
|
||||
1.683226E+00 7.383559E-02
|
||||
|
|
|
|||
|
|
@ -19,21 +19,22 @@ def test_get_atoms(res):
|
|||
t, n = res.get_atoms("1", "Xe135")
|
||||
|
||||
t_ref = [0.0, 1296000.0, 2592000.0, 3888000.0]
|
||||
n_ref = [6.6747328233649218e+08, 3.5421791038348462e+14,
|
||||
3.6208592242443462e+14, 3.3799758969347038e+14]
|
||||
n_ref = [6.6747328233649218e+08, 3.4589992012016338e+14,
|
||||
3.5635060369969225e+14, 3.5195113630100188e+14]
|
||||
|
||||
np.testing.assert_allclose(t, t_ref)
|
||||
np.testing.assert_allclose(n, n_ref)
|
||||
|
||||
|
||||
def test_get_reaction_rate(res):
|
||||
"""Tests evaluating reaction rate."""
|
||||
t, r = res.get_reaction_rate("1", "Xe135", "(n,gamma)")
|
||||
|
||||
t_ref = [0.0, 1296000.0, 2592000.0, 3888000.0]
|
||||
n_ref = np.array([6.6747328233649218e+08, 3.5421791038348462e+14,
|
||||
3.6208592242443462e+14, 3.3799758969347038e+14])
|
||||
xs_ref = np.array([4.0594392323131994e-05, 3.9249546927524987e-05,
|
||||
3.8394587728581798e-05, 4.1521845978371697e-05])
|
||||
n_ref = np.array([6.6747328233649218e+08, 3.4589992012016338e+14,
|
||||
3.5635060369969225e+14, 3.5195113630100188e+14])
|
||||
xs_ref = np.array([4.1340608491478010e-05, 4.1120938620476115e-05,
|
||||
4.3341529708654921e-05, 3.8716623651147821e-05])
|
||||
|
||||
np.testing.assert_allclose(t, t_ref)
|
||||
np.testing.assert_allclose(r, n_ref * xs_ref)
|
||||
|
|
@ -44,8 +45,8 @@ def test_get_eigenvalue(res):
|
|||
t, k = res.get_eigenvalue()
|
||||
|
||||
t_ref = [0.0, 1296000.0, 2592000.0, 3888000.0]
|
||||
k_ref = [1.181281798790367, 1.1798750921988739, 1.1965943696058159,
|
||||
1.2207119847790813]
|
||||
k_ref = [1.1798617938070866, 1.1745713141097096, 1.1732427763487678,
|
||||
1.213699703239334]
|
||||
|
||||
np.testing.assert_allclose(t, t_ref)
|
||||
np.testing.assert_allclose(k, k_ref)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,5 @@ set -ex
|
|||
cd $HOME
|
||||
git clone https://github.com/njoy/NJOY2016
|
||||
cd NJOY2016
|
||||
sed -i -e 's/5\.1/4.8/' CMakeLists.txt
|
||||
mkdir build && cd build
|
||||
cmake -Dstatic=on .. && make 2>/dev/null && sudo make install
|
||||
|
|
|
|||
|
|
@ -7,20 +7,13 @@ set -ex
|
|||
# Upgrade pip before doing anything else
|
||||
pip install --upgrade pip
|
||||
|
||||
# Running OpenMC's setup.py requires numpy/cython already. NumPy float
|
||||
# formatting changed in version 1.14, so stick with a lower version until we can
|
||||
# handle it in our test suite
|
||||
pip install 'numpy<1.14'
|
||||
# Running OpenMC's setup.py requires numpy/cython already
|
||||
pip install numpy
|
||||
pip install cython
|
||||
|
||||
# pytest installed by default -- make sure we get latest
|
||||
pip install --upgrade pytest
|
||||
|
||||
# Pandas stopped supporting Python 3.4 with version 0.21
|
||||
if [[ $TRAVIS_PYTHON_VERSION == "3.4" ]]; then
|
||||
pip install pandas==0.20.3
|
||||
fi
|
||||
|
||||
# Install mpi4py for MPI configurations
|
||||
if [[ $MPI == 'y' ]]; then
|
||||
pip install --no-binary=mpi4py mpi4py
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
set -ex
|
||||
|
||||
# Run source check
|
||||
if [[ $TRAVIS_PYTHON_VERSION == "3.4" && $OMP == 'n' && $MPI == 'n' ]]; then
|
||||
if [[ $TRAVIS_PYTHON_VERSION == "3.5" && $OMP == 'n' && $MPI == 'n' ]]; then
|
||||
pushd tests && python check_source.py && popd
|
||||
fi
|
||||
|
||||
|
|
|
|||
191
vendor/xtensor/CMakeLists.txt
vendored
Normal file
191
vendor/xtensor/CMakeLists.txt
vendored
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
############################################################################
|
||||
# Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht #
|
||||
# #
|
||||
# Distributed under the terms of the BSD 3-Clause License. #
|
||||
# #
|
||||
# The full license is in the file LICENSE, distributed with this software. #
|
||||
############################################################################
|
||||
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
project(xtensor)
|
||||
|
||||
set(XTENSOR_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
# Versionning
|
||||
# ===========
|
||||
|
||||
file(STRINGS "${XTENSOR_INCLUDE_DIR}/xtensor/xtensor_config.hpp" xtensor_version_defines
|
||||
REGEX "#define XTENSOR_VERSION_(MAJOR|MINOR|PATCH)")
|
||||
foreach(ver ${xtensor_version_defines})
|
||||
if(ver MATCHES "#define XTENSOR_VERSION_(MAJOR|MINOR|PATCH) +([^ ]+)$")
|
||||
set(XTENSOR_VERSION_${CMAKE_MATCH_1} "${CMAKE_MATCH_2}" CACHE INTERNAL "")
|
||||
endif()
|
||||
endforeach()
|
||||
set(${PROJECT_NAME}_VERSION
|
||||
${XTENSOR_VERSION_MAJOR}.${XTENSOR_VERSION_MINOR}.${XTENSOR_VERSION_PATCH})
|
||||
message(STATUS "Building xtensor v${${PROJECT_NAME}_VERSION}")
|
||||
|
||||
# Dependencies
|
||||
# ============
|
||||
|
||||
#find_package(xtl 0.4.9 REQUIRED)
|
||||
|
||||
#message(STATUS "Found xtl: ${xtl_INCLUDE_DIRS}/xtl")
|
||||
|
||||
#find_package(nlohmann_json 3.1.1)
|
||||
|
||||
# Build
|
||||
# =====
|
||||
|
||||
set(XTENSOR_HEADERS
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xaccumulator.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xadapt.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xarray.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xassign.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xaxis_iterator.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xbroadcast.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xbuffer_adaptor.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xbuilder.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xcomplex.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xconcepts.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xcontainer.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xcsv.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xeval.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xexception.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xexpression.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xfixed.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xfunction.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xfunctor_view.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xgenerator.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xindex_view.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xinfo.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xio.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xiterable.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xiterator.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xjson.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xlayout.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xmath.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xnoalias.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xnorm.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xnpy.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xoffset_view.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xoperation.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xoptional.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xoptional_assembly.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xoptional_assembly_base.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xoptional_assembly_storage.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xrandom.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xreducer.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xscalar.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xsemantic.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xshape.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xslice.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xsort.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xstorage.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xstrided_view.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xstrided_view_base.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xstrides.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xtensor.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xtensor_config.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xtensor_forward.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xtensor_simd.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xutils.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xvectorize.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xview.hpp
|
||||
${XTENSOR_INCLUDE_DIR}/xtensor/xview_utils.hpp
|
||||
)
|
||||
|
||||
add_library(xtensor INTERFACE)
|
||||
target_include_directories(xtensor INTERFACE $<BUILD_INTERFACE:${XTENSOR_INCLUDE_DIR}>
|
||||
$<INSTALL_INTERFACE:include>)
|
||||
target_link_libraries(xtensor INTERFACE xtl)
|
||||
|
||||
OPTION(XTENSOR_ENABLE_ASSERT "xtensor bound check" OFF)
|
||||
OPTION(XTENSOR_CHECK_DIMENSION "xtensor dimension check" OFF)
|
||||
OPTION(XTENSOR_USE_XSIMD "simd acceleration for xtensor" OFF)
|
||||
OPTION(BUILD_TESTS "xtensor test suite" OFF)
|
||||
OPTION(BUILD_BENCHMARK "xtensor benchmark" OFF)
|
||||
OPTION(DOWNLOAD_GTEST "build gtest from downloaded sources" OFF)
|
||||
OPTION(DOWNLOAD_GBENCHMARK "download google benchmark and build from source" ON)
|
||||
OPTION(DEFAULT_COLUMN_MAJOR "set default layout to column major" OFF)
|
||||
OPTION(DISABLE_VS2017 "disables the compilation of some test with Visual Studio 2017" OFF)
|
||||
|
||||
if(DOWNLOAD_GTEST OR GTEST_SRC_DIR)
|
||||
set(BUILD_TESTS ON)
|
||||
endif()
|
||||
|
||||
if(XTENSOR_ENABLE_ASSERT OR XTENSOR_CHECK_DIMENSION)
|
||||
add_definitions(-DXTENSOR_ENABLE_ASSERT)
|
||||
endif()
|
||||
|
||||
if(XTENSOR_CHECK_DIMENSION)
|
||||
add_definitions(-DXTENSOR_ENABLE_CHECK_DIMENSION)
|
||||
endif()
|
||||
|
||||
if(XTENSOR_USE_XSIMD)
|
||||
add_definitions(-DXTENSOR_USE_XSIMD)
|
||||
find_package(xsimd 4.1.6 REQUIRED)
|
||||
message(STATUS "Found xsimd: ${xsimd_INCLUDE_DIRS}/xsimd")
|
||||
target_link_libraries(xtensor INTERFACE xsimd)
|
||||
endif()
|
||||
|
||||
if(DEFAULT_COLUMN_MAJOR)
|
||||
add_definitions(-DXTENSOR_DEFAULT_LAYOUT=layout_type::column_major)
|
||||
endif()
|
||||
|
||||
if(DISABLE_VS2017)
|
||||
add_definitions(-DDISABLE_VS2017)
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTS)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
if(BUILD_BENCHMARK)
|
||||
add_subdirectory(benchmark)
|
||||
endif()
|
||||
|
||||
# Installation
|
||||
# ============
|
||||
|
||||
include(GNUInstallDirs)
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
install(TARGETS xtensor
|
||||
EXPORT ${PROJECT_NAME}-targets)
|
||||
|
||||
# Makes the project importable from the build directory
|
||||
export(EXPORT ${PROJECT_NAME}-targets
|
||||
FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake")
|
||||
|
||||
install(FILES ${XTENSOR_HEADERS}
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/xtensor)
|
||||
|
||||
set(XTENSOR_CMAKECONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" CACHE
|
||||
STRING "install path for xtensorConfig.cmake")
|
||||
|
||||
configure_package_config_file(${PROJECT_NAME}Config.cmake.in
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||
INSTALL_DESTINATION ${XTENSOR_CMAKECONFIG_INSTALL_DIR})
|
||||
|
||||
# xtensor is header-only and does not depend on the architecture.
|
||||
# Remove CMAKE_SIZEOF_VOID_P from xtensorConfigVersion.cmake so that an xtensorConfig.cmake
|
||||
# generated for a 64 bit target can be used for 32 bit targets and vice versa.
|
||||
set(_XTENSOR_CMAKE_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P})
|
||||
unset(CMAKE_SIZEOF_VOID_P)
|
||||
write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
|
||||
VERSION ${${PROJECT_NAME}_VERSION}
|
||||
COMPATIBILITY AnyNewerVersion)
|
||||
set(CMAKE_SIZEOF_VOID_P ${_XTENSOR_CMAKE_SIZEOF_VOID_P})
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
|
||||
DESTINATION ${XTENSOR_CMAKECONFIG_INSTALL_DIR})
|
||||
install(EXPORT ${PROJECT_NAME}-targets
|
||||
FILE ${PROJECT_NAME}Targets.cmake
|
||||
DESTINATION ${XTENSOR_CMAKECONFIG_INSTALL_DIR})
|
||||
|
||||
configure_file(${PROJECT_NAME}.pc.in
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc"
|
||||
@ONLY)
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.pc"
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig/")
|
||||
266
vendor/xtensor/include/xtensor/xaccumulator.hpp
vendored
Normal file
266
vendor/xtensor/include/xtensor/xaccumulator.hpp
vendored
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTENSOR_ACCUMULATOR_HPP
|
||||
#define XTENSOR_ACCUMULATOR_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <numeric>
|
||||
#include <type_traits>
|
||||
|
||||
#include "xexpression.hpp"
|
||||
#include "xstrides.hpp"
|
||||
#include "xtensor_forward.hpp"
|
||||
|
||||
namespace xt
|
||||
{
|
||||
|
||||
#define DEFAULT_STRATEGY_ACCUMULATORS evaluation_strategy::immediate
|
||||
|
||||
/**************
|
||||
* accumulate *
|
||||
**************/
|
||||
|
||||
template <class ACCUMULATE_FUNC, class INIT_FUNC = xtl::identity>
|
||||
struct xaccumulator_functor
|
||||
: public std::tuple<ACCUMULATE_FUNC, INIT_FUNC>
|
||||
{
|
||||
using self_type = xaccumulator_functor<ACCUMULATE_FUNC, INIT_FUNC>;
|
||||
using base_type = std::tuple<ACCUMULATE_FUNC, INIT_FUNC>;
|
||||
using accumulate_functor_type = ACCUMULATE_FUNC;
|
||||
using init_functor_type = INIT_FUNC;
|
||||
|
||||
xaccumulator_functor()
|
||||
: base_type()
|
||||
{
|
||||
}
|
||||
|
||||
template <class RF>
|
||||
xaccumulator_functor(RF&& accumulate_func)
|
||||
: base_type(std::forward<RF>(accumulate_func), INIT_FUNC())
|
||||
{
|
||||
}
|
||||
|
||||
template <class RF, class IF>
|
||||
xaccumulator_functor(RF&& accumulate_func, IF&& init_func)
|
||||
: base_type(std::forward<RF>(accumulate_func), std::forward<IF>(init_func))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <class RF>
|
||||
auto make_xaccumulator_functor(RF&& accumulate_func)
|
||||
{
|
||||
using accumulator_type = xaccumulator_functor<std::remove_reference_t<RF>>;
|
||||
return accumulator_type(std::forward<RF>(accumulate_func));
|
||||
}
|
||||
|
||||
template <class RF, class IF>
|
||||
auto make_xaccumulator_functor(RF&& accumulate_func, IF&& init_func)
|
||||
{
|
||||
using accumulator_type = xaccumulator_functor<std::remove_reference_t<RF>, std::remove_reference_t<IF>>;
|
||||
return accumulator_type(std::forward<RF>(accumulate_func), std::forward<IF>(init_func));
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class F, class E, class EVS>
|
||||
xarray<typename std::decay_t<E>::value_type> accumulator_impl(F&&, E&&, std::size_t, EVS)
|
||||
{
|
||||
static_assert(!std::is_same<evaluation_strategy::lazy, EVS>::value, "Lazy accumulators not yet implemented.");
|
||||
}
|
||||
|
||||
template <class F, class E, class EVS>
|
||||
xarray<typename std::decay_t<E>::value_type> accumulator_impl(F&&, E&&, EVS)
|
||||
{
|
||||
static_assert(!std::is_same<evaluation_strategy::lazy, EVS>::value, "Lazy accumulators not yet implemented.");
|
||||
}
|
||||
|
||||
template <class T, class R>
|
||||
struct xaccumulator_return_type
|
||||
{
|
||||
using type = xarray<R>;
|
||||
};
|
||||
|
||||
template <class T, std::size_t N, class R>
|
||||
struct xaccumulator_return_type<xtensor<T, N>, R>
|
||||
{
|
||||
using type = xtensor<R, N>;
|
||||
};
|
||||
|
||||
template <class T, class R>
|
||||
using xaccumulator_return_type_t = typename xaccumulator_return_type<T, R>::type;
|
||||
|
||||
template <class F, class E>
|
||||
inline auto accumulator_init_with_f(F&& f, E& e, std::size_t axis)
|
||||
{
|
||||
// this function is the equivalent (but hopefully faster) to (if axis == 1)
|
||||
// e[:, 0, :, :, ...] = f(e[:, 0, :, :, ...])
|
||||
// so that all "first" values are initialized in a first pass
|
||||
|
||||
std::size_t outer_loop_size, inner_loop_size, outer_stride, inner_stride, pos = 0;
|
||||
|
||||
auto set_loop_sizes = [&outer_loop_size, &inner_loop_size](auto first, auto last, std::ptrdiff_t ax) {
|
||||
outer_loop_size = std::accumulate(first, first + ax,
|
||||
std::size_t(1), std::multiplies<std::size_t>());
|
||||
inner_loop_size = std::accumulate(first + ax + 1, last,
|
||||
std::size_t(1), std::multiplies<std::size_t>());
|
||||
};
|
||||
|
||||
auto set_loop_strides = [&outer_stride, &inner_stride](auto first, auto last, std::ptrdiff_t ax) {
|
||||
outer_stride = ax == 0 ? 1 : *std::min_element(first, first + ax);
|
||||
inner_stride = (ax == std::distance(first, last) - 1) ? 1 : *std::min_element(first + ax + 1, last);
|
||||
};
|
||||
|
||||
set_loop_sizes(e.shape().begin(), e.shape().end(), static_cast<std::ptrdiff_t>(axis));
|
||||
set_loop_strides(e.strides().begin(), e.strides().end(), static_cast<std::ptrdiff_t>(axis));
|
||||
|
||||
if (e.layout() == layout_type::column_major)
|
||||
{
|
||||
// swap for better memory locality (smaller stride in the inner loop)
|
||||
std::swap(outer_loop_size, inner_loop_size);
|
||||
std::swap(outer_stride, inner_stride);
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < outer_loop_size; ++i)
|
||||
{
|
||||
pos = i * outer_stride;
|
||||
for (std::size_t j = 0; j < inner_loop_size; ++j)
|
||||
{
|
||||
e.storage()[pos] = f(e.storage()[pos]);
|
||||
pos += inner_stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class F, class E>
|
||||
inline auto accumulator_impl(F&& f, E&& e, std::size_t axis, evaluation_strategy::immediate)
|
||||
{
|
||||
using accumulate_functor = std::decay_t<decltype(std::get<0>(f))>;
|
||||
using function_return_type = typename accumulate_functor::result_type;
|
||||
using result_type = xaccumulator_return_type_t<std::decay_t<E>, function_return_type>;
|
||||
|
||||
if (axis >= e.dimension())
|
||||
{
|
||||
throw std::runtime_error("Axis larger than expression dimension in accumulator.");
|
||||
}
|
||||
|
||||
result_type result = e; // assign + make a copy, we need it anyways
|
||||
|
||||
std::size_t inner_stride = result.strides()[axis];
|
||||
std::size_t outer_stride = 1; // this is either going row- or column-wise (strides.back / strides.front)
|
||||
std::size_t outer_loop_size = 0;
|
||||
std::size_t inner_loop_size = 0;
|
||||
|
||||
auto set_loop_sizes = [&outer_loop_size, &inner_loop_size](auto first, auto last, std::ptrdiff_t ax) {
|
||||
outer_loop_size = std::accumulate(first,
|
||||
first + ax,
|
||||
std::size_t(1), std::multiplies<std::size_t>());
|
||||
|
||||
inner_loop_size = std::accumulate(first + ax,
|
||||
last,
|
||||
std::size_t(1), std::multiplies<std::size_t>());
|
||||
};
|
||||
|
||||
if (result_type::static_layout == layout_type::row_major)
|
||||
{
|
||||
set_loop_sizes(result.shape().cbegin(), result.shape().cend(), static_cast<std::ptrdiff_t>(axis));
|
||||
}
|
||||
else
|
||||
{
|
||||
set_loop_sizes(result.shape().cbegin(), result.shape().cend(), static_cast<std::ptrdiff_t>(axis + 1));
|
||||
std::swap(inner_loop_size, outer_loop_size);
|
||||
}
|
||||
|
||||
std::size_t pos = 0;
|
||||
|
||||
inner_loop_size = inner_loop_size - inner_stride;
|
||||
|
||||
// activate the init loop if we have an init function other than identity
|
||||
if (!std::is_same<decltype(std::get<1>(f)), xtl::identity>::value)
|
||||
{
|
||||
accumulator_init_with_f(std::get<1>(f), result, axis);
|
||||
}
|
||||
|
||||
pos = 0;
|
||||
for (std::size_t i = 0; i < outer_loop_size; ++i)
|
||||
{
|
||||
for (std::size_t j = 0; j < inner_loop_size; ++j)
|
||||
{
|
||||
result.storage()[pos + inner_stride] = std::get<0>(f)(result.storage()[pos],
|
||||
result.storage()[pos + inner_stride]);
|
||||
pos += outer_stride;
|
||||
}
|
||||
pos += inner_stride;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class F, class E>
|
||||
inline auto accumulator_impl(F&& f, E&& e, evaluation_strategy::immediate)
|
||||
{
|
||||
using accumulate_functor = std::decay_t<decltype(std::get<0>(f))>;
|
||||
using T = typename accumulate_functor::result_type;
|
||||
|
||||
using result_type = xtensor<T, 1>;
|
||||
std::size_t sz = e.size();
|
||||
auto result = result_type::from_shape({sz});
|
||||
|
||||
auto it = e.template begin<XTENSOR_DEFAULT_LAYOUT>();
|
||||
|
||||
result.storage()[0] = std::get<1>(f)(*it);
|
||||
++it;
|
||||
|
||||
for (std::size_t idx = 0; it != e.template end<XTENSOR_DEFAULT_LAYOUT>(); ++it)
|
||||
{
|
||||
result.storage()[idx + 1] = std::get<0>(f)(result.storage()[idx], *it);
|
||||
++idx;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Accumulate and flatten array
|
||||
* **NOTE** This function is not lazy!
|
||||
*
|
||||
* @param f functor to use for accumulation
|
||||
* @param e xexpression to be accumulated
|
||||
* @param evaluation_strategy evaluation strategy of the accumulation
|
||||
*
|
||||
* @return returns xarray<T> filled with accumulated values
|
||||
*/
|
||||
template <class F, class E, class EVS = DEFAULT_STRATEGY_ACCUMULATORS,
|
||||
typename std::enable_if_t<!std::is_integral<EVS>::value, int> = 0>
|
||||
inline auto accumulate(F&& f, E&& e, EVS evaluation_strategy = EVS())
|
||||
{
|
||||
// Note we need to check is_integral above in order to prohibit EVS = int, and not taking the std::size_t
|
||||
// overload below!
|
||||
return detail::accumulator_impl(std::forward<F>(f), std::forward<E>(e), evaluation_strategy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Accumulate over axis
|
||||
* **NOTE** This function is not lazy!
|
||||
*
|
||||
* @param f Functor to use for accumulation
|
||||
* @param e xexpression to accumulate
|
||||
* @param axis Axis to perform accumulation over
|
||||
* @param evaluation_strategy evaluation strategy of the accumulation
|
||||
*
|
||||
* @return returns xarray<T> filled with accumulated values
|
||||
*/
|
||||
template <class F, class E, class EVS = DEFAULT_STRATEGY_ACCUMULATORS>
|
||||
inline auto accumulate(F&& f, E&& e, std::size_t axis, EVS evaluation_strategy = EVS())
|
||||
{
|
||||
return detail::accumulator_impl(std::forward<F>(f), std::forward<E>(e), axis, evaluation_strategy);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
322
vendor/xtensor/include/xtensor/xadapt.hpp
vendored
Normal file
322
vendor/xtensor/include/xtensor/xadapt.hpp
vendored
Normal file
|
|
@ -0,0 +1,322 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTENSOR_ADAPT_HPP
|
||||
#define XTENSOR_ADAPT_HPP
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
#include <xtl/xsequence.hpp>
|
||||
|
||||
#include "xarray.hpp"
|
||||
#include "xtensor.hpp"
|
||||
|
||||
namespace xt
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <class>
|
||||
struct array_size_impl;
|
||||
|
||||
template <class T, std::size_t N>
|
||||
struct array_size_impl<std::array<T, N>>
|
||||
{
|
||||
static constexpr std::size_t value = N;
|
||||
};
|
||||
|
||||
template <class C>
|
||||
using array_size = array_size_impl<std::decay_t<C>>;
|
||||
}
|
||||
|
||||
/**************************
|
||||
* xarray_adaptor builder *
|
||||
**************************/
|
||||
|
||||
/**
|
||||
* Constructs an xarray_adaptor of the given stl-like container,
|
||||
* with the specified shape and layout.
|
||||
* @param container the container to adapt
|
||||
* @param shape the shape of the xarray_adaptor
|
||||
* @param l the layout_type of the xarray_adaptor
|
||||
*/
|
||||
template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class C, class SC,
|
||||
typename std::enable_if_t<!detail::is_array<std::decay_t<SC>>::value, int> = 0>
|
||||
xarray_adaptor<xtl::closure_type_t<C>, L, std::decay_t<SC>>
|
||||
adapt(C&& container, const SC& shape, layout_type l = L);
|
||||
|
||||
/**
|
||||
* Constructs an xarray_adaptor of the given stl-like container,
|
||||
* with the specified shape and strides.
|
||||
* @param container the container to adapt
|
||||
* @param shape the shape of the xarray_adaptor
|
||||
* @param strides the strides of the xarray_adaptor
|
||||
*/
|
||||
template <class C, class SC, class SS,
|
||||
typename std::enable_if_t<!detail::is_array<std::decay_t<SC>>::value, int> = 0,
|
||||
typename std::enable_if_t<!std::is_same<layout_type, std::decay_t<SS>>::value, int> = 0>
|
||||
xarray_adaptor<xtl::closure_type_t<C>, layout_type::dynamic, std::decay_t<SC>>
|
||||
adapt(C&& container, SC&& shape, SS&& strides);
|
||||
|
||||
/**
|
||||
* Constructs an xarray_adaptor of the given dynamically allocated C array,
|
||||
* with the specified shape and layout.
|
||||
* @param pointer the pointer to the beginning of the dynamic array
|
||||
* @param size the size of the dynamic array
|
||||
* @param ownership indicates whether the adaptor takes ownership of the array.
|
||||
* Possible values are ``no_ownerhsip()`` or ``acquire_ownership()``
|
||||
* @param shape the shape of the xarray_adaptor
|
||||
* @param l the layout_type of the xarray_adaptor
|
||||
* @param alloc the allocator used for allocating / deallocating the dynamic array
|
||||
*/
|
||||
template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class P, class O, class SC, class A = std::allocator<std::remove_const_t<std::remove_pointer_t<std::remove_reference_t<P>>>>,
|
||||
typename std::enable_if_t<!detail::is_array<std::decay_t<SC>>::value, int> = 0>
|
||||
xarray_adaptor<xbuffer_adaptor<xtl::closure_type_t<P>, O, A>, L, SC>
|
||||
adapt(P&& pointer, typename A::size_type size, O ownership, const SC& shape, layout_type l = L, const A& alloc = A());
|
||||
|
||||
/**
|
||||
* Constructs an xarray_adaptor of the given dynamically allocated C array,
|
||||
* with the specified shape and layout.
|
||||
* @param pointer the pointer to the beginning of the dynamic array
|
||||
* @param size the size of the dynamic array
|
||||
* @param ownership indicates whether the adaptor takes ownership of the array.
|
||||
* Possible values are ``no_ownerhsip()`` or ``acquire_ownership()``
|
||||
* @param shape the shape of the xarray_adaptor
|
||||
* @param strides the strides of the xarray_adaptor
|
||||
* @param alloc the allocator used for allocating / deallocating the dynamic array
|
||||
*/
|
||||
template <class P, class O, class SC, class SS, class A = std::allocator<std::remove_const_t<std::remove_pointer_t<std::remove_reference_t<P>>>>,
|
||||
typename std::enable_if_t<!detail::is_array<std::decay_t<SC>>::value, int> = 0,
|
||||
typename std::enable_if_t<!std::is_same<layout_type, std::decay_t<SS>>::value, int> = 0>
|
||||
xarray_adaptor<xbuffer_adaptor<xtl::closure_type_t<P>, O, A>, layout_type::dynamic, std::decay_t<SC>>
|
||||
adapt(P&& pointer, typename A::size_type size, O ownership, SC&& shape, SS&& strides, const A& alloc = A());
|
||||
|
||||
/***************************
|
||||
* xtensor_adaptor builder *
|
||||
***************************/
|
||||
|
||||
/**
|
||||
* Constructs a 1-D xtensor_adaptor of the given stl-like container,
|
||||
* with the specified layout_type.
|
||||
* @param container the container to adapt
|
||||
* @param l the layout_type of the xtensor_adaptor
|
||||
*/
|
||||
template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class C>
|
||||
xtensor_adaptor<C, 1, L>
|
||||
adapt(C&& container, layout_type l = L);
|
||||
|
||||
/**
|
||||
* Constructs an xtensor_adaptor of the given stl-like container,
|
||||
* with the specified shape and layout_type.
|
||||
* @param container the container to adapt
|
||||
* @param shape the shape of the xtensor_adaptor
|
||||
* @param l the layout_type of the xtensor_adaptor
|
||||
*/
|
||||
template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class C, class SC,
|
||||
typename std::enable_if_t<detail::is_array<std::decay_t<SC>>::value, int> = 0>
|
||||
xtensor_adaptor<C, detail::array_size<SC>::value, L>
|
||||
adapt(C&& container, const SC& shape, layout_type l = L);
|
||||
|
||||
/**
|
||||
* Constructs an xtensor_adaptor of the given stl-like container,
|
||||
* with the specified shape and strides.
|
||||
* @param container the container to adapt
|
||||
* @param shape the shape of the xtensor_adaptor
|
||||
* @param strides the strides of the xtensor_adaptor
|
||||
*/
|
||||
template <class C, class SC, class SS,
|
||||
typename std::enable_if_t<detail::is_array<std::decay_t<SC>>::value, int> = 0,
|
||||
typename std::enable_if_t<!std::is_same<layout_type, std::decay_t<SS>>::value, int> = 0>
|
||||
xtensor_adaptor<C, detail::array_size<SC>::value, layout_type::dynamic>
|
||||
adapt(C&& container, SC&& shape, SS&& strides);
|
||||
|
||||
/**
|
||||
* Constructs a 1-D xtensor_adaptor of the given dynamically allocated C array,
|
||||
* with the specified layout.
|
||||
* @param pointer the pointer to the beginning of the dynamic array
|
||||
* @param size the size of the dynamic array
|
||||
* @param ownership indicates whether the adaptor takes ownership of the array.
|
||||
* Possible values are ``no_ownerhsip()`` or ``acquire_ownership()``
|
||||
* @param l the layout_type of the xtensor_adaptor
|
||||
* @param alloc the allocator used for allocating / deallocating the dynamic array
|
||||
*/
|
||||
template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class P, class O, class A = std::allocator<std::remove_const_t<std::remove_pointer_t<std::remove_reference_t<P>>>>>
|
||||
xtensor_adaptor<xbuffer_adaptor<xtl::closure_type_t<P>, O, A>, 1, L>
|
||||
adapt(P&& pointer, typename A::size_type size, O ownership, layout_type l = L, const A& alloc = A());
|
||||
|
||||
/**
|
||||
* Constructs an xtensor_adaptor of the given dynamically allocated C array,
|
||||
* with the specified shape and layout.
|
||||
* @param pointer the pointer to the beginning of the dynamic array
|
||||
* @param size the size of the dynamic array
|
||||
* @param ownership indicates whether the adaptor takes ownership of the array.
|
||||
* Possible values are ``no_ownerhsip()`` or ``acquire_ownership()``
|
||||
* @param shape the shape of the xtensor_adaptor
|
||||
* @param l the layout_type of the xtensor_adaptor
|
||||
* @param alloc the allocator used for allocating / deallocating the dynamic array
|
||||
*/
|
||||
template <layout_type L = XTENSOR_DEFAULT_LAYOUT, class P, class O, class SC, class A = std::allocator<std::remove_const_t<std::remove_pointer_t<std::remove_reference_t<P>>>>,
|
||||
typename std::enable_if_t<detail::is_array<std::decay_t<SC>>::value, int> = 0>
|
||||
xtensor_adaptor<xbuffer_adaptor<xtl::closure_type_t<P>, O, A>, detail::array_size<SC>::value, L>
|
||||
adapt(P&& pointer, typename A::size_type size, O ownership, const SC& shape, layout_type l = L, const A& alloc = A());
|
||||
|
||||
/**
|
||||
* Constructs an xtensor_adaptor of the given dynamically allocated C array,
|
||||
* with the specified shape and strides.
|
||||
* @param pointer the pointer to the beginning of the dynamic array
|
||||
* @param size the size of the dynamic array
|
||||
* @param ownership indicates whether the adaptor takes ownership of the array.
|
||||
* Possible values are ``no_ownerhsip()`` or ``acquire_ownership()``
|
||||
* @param shape the shape of the xtensor_adaptor
|
||||
* @param strides the strides of the xtensor_adaptor
|
||||
* @param alloc the allocator used for allocating / deallocating the dynamic array
|
||||
*/
|
||||
template <class P, class O, class SC, class SS, class A = std::allocator<std::remove_const_t<std::remove_pointer_t<std::remove_reference_t<P>>>>,
|
||||
typename std::enable_if_t<detail::is_array<std::decay_t<SC>>::value, int> = 0,
|
||||
typename std::enable_if_t<!std::is_same<layout_type, std::decay_t<SS>>::value, int> = 0>
|
||||
xtensor_adaptor<xbuffer_adaptor<xtl::closure_type_t<P>, O, A>, detail::array_size<SC>::value, layout_type::dynamic>
|
||||
adapt(P&& pointer, typename A::size_type size, O ownership, SC&& shape, SS&& strides, const A& alloc = A());
|
||||
|
||||
/*****************************************
|
||||
* xarray_adaptor builder implementation *
|
||||
*****************************************/
|
||||
|
||||
// shape only - container version
|
||||
template <layout_type L, class C, class SC,
|
||||
typename std::enable_if_t<!detail::is_array<std::decay_t<SC>>::value, int>>
|
||||
inline xarray_adaptor<xtl::closure_type_t<C>, L, std::decay_t<SC>>
|
||||
adapt(C&& container, const SC& shape, layout_type l)
|
||||
{
|
||||
using return_type = xarray_adaptor<xtl::closure_type_t<C>, L, std::decay_t<SC>>;
|
||||
return return_type(std::forward<C>(container), shape, l);
|
||||
}
|
||||
|
||||
// shape and strides - container version
|
||||
template <class C, class SC, class SS,
|
||||
typename std::enable_if_t<!detail::is_array<std::decay_t<SC>>::value, int>,
|
||||
typename std::enable_if_t<!std::is_same<layout_type, std::decay_t<SS>>::value, int>>
|
||||
inline xarray_adaptor<xtl::closure_type_t<C>, layout_type::dynamic, std::decay_t<SC>>
|
||||
adapt(C&& container, SC&& shape, SS&& strides)
|
||||
{
|
||||
using return_type = xarray_adaptor<xtl::closure_type_t<C>, layout_type::dynamic, std::decay_t<SC>>;
|
||||
return return_type(std::forward<C>(container),
|
||||
xtl::forward_sequence<typename return_type::inner_shape_type>(shape),
|
||||
xtl::forward_sequence<typename return_type::inner_strides_type>(strides));
|
||||
}
|
||||
|
||||
// shape only - buffer version
|
||||
template <layout_type L, class P, class O, class SC, class A,
|
||||
typename std::enable_if_t<!detail::is_array<std::decay_t<SC>>::value, int>>
|
||||
inline xarray_adaptor<xbuffer_adaptor<xtl::closure_type_t<P>, O, A>, L, SC>
|
||||
adapt(P&& pointer, typename A::size_type size, O, const SC& shape, layout_type l, const A& alloc)
|
||||
{
|
||||
using buffer_type = xbuffer_adaptor<xtl::closure_type_t<P>, O, A>;
|
||||
using return_type = xarray_adaptor<buffer_type, L, SC>;
|
||||
buffer_type buf(std::forward<P>(pointer), size, alloc);
|
||||
return return_type(std::move(buf), shape, l);
|
||||
}
|
||||
|
||||
// shape and strides - buffer version
|
||||
template <class P, class O, class SC, class SS, class A,
|
||||
typename std::enable_if_t<!detail::is_array<std::decay_t<SC>>::value, int>,
|
||||
typename std::enable_if_t<!std::is_same<layout_type, std::decay_t<SS>>::value, int>>
|
||||
inline xarray_adaptor<xbuffer_adaptor<xtl::closure_type_t<P>, O, A>, layout_type::dynamic, std::decay_t<SC>>
|
||||
adapt(P&& pointer, typename A::size_type size, O, SC&& shape, SS&& strides, const A& alloc)
|
||||
{
|
||||
using buffer_type = xbuffer_adaptor<xtl::closure_type_t<P>, O, A>;
|
||||
using return_type = xarray_adaptor<buffer_type, layout_type::dynamic, std::decay_t<SC>>;
|
||||
buffer_type buf(std::forward<P>(pointer), size, alloc);
|
||||
return return_type(std::move(buf),
|
||||
xtl::forward_sequence<typename return_type::inner_shape_type>(shape),
|
||||
xtl::forward_sequence<typename return_type::inner_strides_type>(strides));
|
||||
}
|
||||
|
||||
/******************************************
|
||||
* xtensor_adaptor builder implementation *
|
||||
******************************************/
|
||||
|
||||
// 1-D case - container version
|
||||
template <layout_type L, class C>
|
||||
inline xtensor_adaptor<C, 1, L>
|
||||
adapt(C&& container, layout_type l)
|
||||
{
|
||||
const std::array<typename std::decay_t<C>::size_type, 1> shape{container.size()};
|
||||
using return_type = xtensor_adaptor<xtl::closure_type_t<C>, 1, L>;
|
||||
return return_type(std::forward<C>(container), shape, l);
|
||||
}
|
||||
|
||||
// shape only - container version
|
||||
template <layout_type L, class C, class SC,
|
||||
typename std::enable_if_t<detail::is_array<std::decay_t<SC>>::value, int>>
|
||||
inline xtensor_adaptor<C, detail::array_size<SC>::value, L>
|
||||
adapt(C&& container, const SC& shape, layout_type l)
|
||||
{
|
||||
constexpr std::size_t N = detail::array_size<SC>::value;
|
||||
using return_type = xtensor_adaptor<xtl::closure_type_t<C>, N, L>;
|
||||
return return_type(std::forward<C>(container), shape, l);
|
||||
}
|
||||
|
||||
// shape and strides - container version
|
||||
template <class C, class SC, class SS,
|
||||
typename std::enable_if_t<detail::is_array<std::decay_t<SC>>::value, int>,
|
||||
typename std::enable_if_t<!std::is_same<layout_type, std::decay_t<SS>>::value, int>>
|
||||
inline xtensor_adaptor<C, detail::array_size<SC>::value, layout_type::dynamic>
|
||||
adapt(C&& container, SC&& shape, SS&& strides)
|
||||
{
|
||||
constexpr std::size_t N = detail::array_size<SC>::value;
|
||||
using return_type = xtensor_adaptor<xtl::closure_type_t<C>, N, layout_type::dynamic>;
|
||||
return return_type(std::forward<C>(container),
|
||||
xtl::forward_sequence<typename return_type::inner_shape_type>(shape),
|
||||
xtl::forward_sequence<typename return_type::inner_strides_type>(strides));
|
||||
}
|
||||
|
||||
// 1-D case - buffer version
|
||||
template <layout_type L, class P, class O, class A>
|
||||
inline xtensor_adaptor<xbuffer_adaptor<xtl::closure_type_t<P>, O, A>, 1, L>
|
||||
adapt(P&& pointer, typename A::size_type size, O, layout_type l, const A& alloc)
|
||||
{
|
||||
using buffer_type = xbuffer_adaptor<xtl::closure_type_t<P>, O, A>;
|
||||
using return_type = xtensor_adaptor<buffer_type, 1, L>;
|
||||
buffer_type buf(std::forward<P>(pointer), size, alloc);
|
||||
const std::array<typename A::size_type, 1> shape{size};
|
||||
return return_type(std::move(buf), shape, l);
|
||||
}
|
||||
|
||||
// shape only - buffer version
|
||||
template <layout_type L, class P, class O, class SC, class A,
|
||||
typename std::enable_if_t<detail::is_array<std::decay_t<SC>>::value, int>>
|
||||
inline xtensor_adaptor<xbuffer_adaptor<xtl::closure_type_t<P>, O, A>, detail::array_size<SC>::value, L>
|
||||
adapt(P&& pointer, typename A::size_type size, O, const SC& shape, layout_type l, const A& alloc)
|
||||
{
|
||||
using buffer_type = xbuffer_adaptor<xtl::closure_type_t<P>, O, A>;
|
||||
constexpr std::size_t N = detail::array_size<SC>::value;
|
||||
using return_type = xtensor_adaptor<buffer_type, N, L>;
|
||||
buffer_type buf(std::forward<P>(pointer), size, alloc);
|
||||
return return_type(std::move(buf), shape, l);
|
||||
}
|
||||
|
||||
// shape and strides - buffer version
|
||||
template <class P, class O, class SC, class SS, class A,
|
||||
typename std::enable_if_t<detail::is_array<std::decay_t<SC>>::value, int>,
|
||||
typename std::enable_if_t<!std::is_same<layout_type, std::decay_t<SS>>::value, int>>
|
||||
inline xtensor_adaptor<xbuffer_adaptor<xtl::closure_type_t<P>, O, A>, detail::array_size<SC>::value, layout_type::dynamic>
|
||||
adapt(P&& pointer, typename A::size_type size, O, SC&& shape, SS&& strides, const A& alloc)
|
||||
{
|
||||
using buffer_type = xbuffer_adaptor<xtl::closure_type_t<P>, O, A>;
|
||||
constexpr std::size_t N = detail::array_size<SC>::value;
|
||||
using return_type = xtensor_adaptor<buffer_type, N, layout_type::dynamic>;
|
||||
buffer_type buf(std::forward<P>(pointer), size, alloc);
|
||||
return return_type(std::move(buf),
|
||||
xtl::forward_sequence<typename return_type::inner_shape_type>(shape),
|
||||
xtl::forward_sequence<typename return_type::inner_strides_type>(strides));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
550
vendor/xtensor/include/xtensor/xarray.hpp
vendored
Normal file
550
vendor/xtensor/include/xtensor/xarray.hpp
vendored
Normal file
|
|
@ -0,0 +1,550 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTENSOR_ARRAY_HPP
|
||||
#define XTENSOR_ARRAY_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <initializer_list>
|
||||
#include <utility>
|
||||
|
||||
#include <xtl/xsequence.hpp>
|
||||
|
||||
#include "xbuffer_adaptor.hpp"
|
||||
#include "xcontainer.hpp"
|
||||
#include "xsemantic.hpp"
|
||||
|
||||
namespace xt
|
||||
{
|
||||
|
||||
/********************************
|
||||
* xarray_container declaration *
|
||||
********************************/
|
||||
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
struct xcontainer_inner_types<xarray_container<EC, L, SC, Tag>>
|
||||
{
|
||||
using storage_type = EC;
|
||||
using shape_type = SC;
|
||||
using strides_type = shape_type;
|
||||
using backstrides_type = shape_type;
|
||||
using inner_shape_type = shape_type;
|
||||
using inner_strides_type = strides_type;
|
||||
using inner_backstrides_type = backstrides_type;
|
||||
using temporary_type = xarray_container<EC, L, SC, Tag>;
|
||||
static constexpr layout_type layout = L;
|
||||
};
|
||||
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
struct xiterable_inner_types<xarray_container<EC, L, SC, Tag>>
|
||||
: xcontainer_iterable_types<xarray_container<EC, L, SC, Tag>>
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* @class xarray_container
|
||||
* @brief Dense multidimensional container with tensor semantic.
|
||||
*
|
||||
* The xarray_container class implements a dense multidimensional container
|
||||
* with tensor semantic.
|
||||
*
|
||||
* @tparam EC The type of the container holding the elements.
|
||||
* @tparam L The layout_type of the container.
|
||||
* @tparam SC The type of the containers holding the shape and the strides.
|
||||
* @tparam Tag The expression tag.
|
||||
* @sa xarray
|
||||
*/
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
class xarray_container : public xstrided_container<xarray_container<EC, L, SC, Tag>>,
|
||||
public xcontainer_semantic<xarray_container<EC, L, SC, Tag>>
|
||||
{
|
||||
public:
|
||||
|
||||
using self_type = xarray_container<EC, L, SC, Tag>;
|
||||
using base_type = xstrided_container<self_type>;
|
||||
using semantic_base = xcontainer_semantic<self_type>;
|
||||
using storage_type = typename base_type::storage_type;
|
||||
using allocator_type = typename base_type::allocator_type;
|
||||
using value_type = typename base_type::value_type;
|
||||
using reference = typename base_type::reference;
|
||||
using const_reference = typename base_type::const_reference;
|
||||
using pointer = typename base_type::pointer;
|
||||
using const_pointer = typename base_type::const_pointer;
|
||||
using shape_type = typename base_type::shape_type;
|
||||
using inner_shape_type = typename base_type::inner_shape_type;
|
||||
using strides_type = typename base_type::strides_type;
|
||||
using backstrides_type = typename base_type::backstrides_type;
|
||||
using inner_strides_type = typename base_type::inner_strides_type;
|
||||
using temporary_type = typename semantic_base::temporary_type;
|
||||
using expression_tag = Tag;
|
||||
|
||||
xarray_container();
|
||||
explicit xarray_container(const shape_type& shape, layout_type l = L);
|
||||
explicit xarray_container(const shape_type& shape, const_reference value, layout_type l = L);
|
||||
explicit xarray_container(const shape_type& shape, const strides_type& strides);
|
||||
explicit xarray_container(const shape_type& shape, const strides_type& strides, const_reference value);
|
||||
explicit xarray_container(storage_type&& storage, inner_shape_type&& shape, inner_strides_type&& strides);
|
||||
|
||||
xarray_container(const value_type& t);
|
||||
xarray_container(nested_initializer_list_t<value_type, 1> t);
|
||||
xarray_container(nested_initializer_list_t<value_type, 2> t);
|
||||
xarray_container(nested_initializer_list_t<value_type, 3> t);
|
||||
xarray_container(nested_initializer_list_t<value_type, 4> t);
|
||||
xarray_container(nested_initializer_list_t<value_type, 5> t);
|
||||
|
||||
template <class S = shape_type>
|
||||
static xarray_container from_shape(S&& s);
|
||||
|
||||
~xarray_container() = default;
|
||||
|
||||
xarray_container(const xarray_container&) = default;
|
||||
xarray_container& operator=(const xarray_container&) = default;
|
||||
|
||||
xarray_container(xarray_container&&) = default;
|
||||
xarray_container& operator=(xarray_container&&) = default;
|
||||
|
||||
template <class E>
|
||||
xarray_container(const xexpression<E>& e);
|
||||
|
||||
template <class E>
|
||||
xarray_container& operator=(const xexpression<E>& e);
|
||||
|
||||
private:
|
||||
|
||||
storage_type m_storage;
|
||||
|
||||
storage_type& storage_impl() noexcept;
|
||||
const storage_type& storage_impl() const noexcept;
|
||||
|
||||
friend class xcontainer<xarray_container<EC, L, SC, Tag>>;
|
||||
};
|
||||
|
||||
/******************************
|
||||
* xarray_adaptor declaration *
|
||||
******************************/
|
||||
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
struct xcontainer_inner_types<xarray_adaptor<EC, L, SC, Tag>>
|
||||
{
|
||||
using storage_type = std::remove_reference_t<EC>;
|
||||
using shape_type = SC;
|
||||
using strides_type = shape_type;
|
||||
using backstrides_type = shape_type;
|
||||
using inner_shape_type = shape_type;
|
||||
using inner_strides_type = strides_type;
|
||||
using inner_backstrides_type = backstrides_type;
|
||||
using temporary_type = xarray_container<temporary_container_t<storage_type>, L, SC, Tag>;
|
||||
static constexpr layout_type layout = L;
|
||||
};
|
||||
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
struct xiterable_inner_types<xarray_adaptor<EC, L, SC, Tag>>
|
||||
: xcontainer_iterable_types<xarray_adaptor<EC, L, SC, Tag>>
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* @class xarray_adaptor
|
||||
* @brief Dense multidimensional container adaptor with
|
||||
* tensor semantic.
|
||||
*
|
||||
* The xarray_adaptor class implements a dense multidimensional
|
||||
* container adaptor with tensor semantic. It is used to provide
|
||||
* a multidimensional container semantic and a tensor semantic to
|
||||
* stl-like containers.
|
||||
*
|
||||
* @tparam EC The closure for the container type to adapt.
|
||||
* @tparam L The layout_type of the adaptor.
|
||||
* @tparam SC The type of the containers holding the shape and the strides.
|
||||
* @tparam Tag The expression tag.
|
||||
*/
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
class xarray_adaptor : public xstrided_container<xarray_adaptor<EC, L, SC, Tag>>,
|
||||
public xcontainer_semantic<xarray_adaptor<EC, L, SC, Tag>>
|
||||
{
|
||||
public:
|
||||
|
||||
using container_closure_type = EC;
|
||||
|
||||
using self_type = xarray_adaptor<EC, L, SC, Tag>;
|
||||
using base_type = xstrided_container<self_type>;
|
||||
using semantic_base = xcontainer_semantic<self_type>;
|
||||
using storage_type = typename base_type::storage_type;
|
||||
using allocator_type = typename base_type::allocator_type;
|
||||
using shape_type = typename base_type::shape_type;
|
||||
using strides_type = typename base_type::strides_type;
|
||||
using backstrides_type = typename base_type::backstrides_type;
|
||||
using temporary_type = typename semantic_base::temporary_type;
|
||||
using expression_tag = Tag;
|
||||
|
||||
xarray_adaptor(storage_type&& storage);
|
||||
xarray_adaptor(const storage_type& storage);
|
||||
|
||||
template <class D>
|
||||
xarray_adaptor(D&& storage, const shape_type& shape, layout_type l = L);
|
||||
|
||||
template <class D>
|
||||
xarray_adaptor(D&& storage, const shape_type& shape, const strides_type& strides);
|
||||
|
||||
~xarray_adaptor() = default;
|
||||
|
||||
xarray_adaptor(const xarray_adaptor&) = default;
|
||||
xarray_adaptor& operator=(const xarray_adaptor&);
|
||||
|
||||
xarray_adaptor(xarray_adaptor&&) = default;
|
||||
xarray_adaptor& operator=(xarray_adaptor&&);
|
||||
xarray_adaptor& operator=(temporary_type&&);
|
||||
|
||||
template <class E>
|
||||
xarray_adaptor& operator=(const xexpression<E>& e);
|
||||
|
||||
private:
|
||||
|
||||
container_closure_type m_storage;
|
||||
|
||||
storage_type& storage_impl() noexcept;
|
||||
const storage_type& storage_impl() const noexcept;
|
||||
|
||||
|
||||
friend class xcontainer<xarray_adaptor<EC, L, SC, Tag>>;
|
||||
};
|
||||
|
||||
/***********************************
|
||||
* xarray_container implementation *
|
||||
***********************************/
|
||||
|
||||
/**
|
||||
* @name Constructors
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* Allocates an uninitialized xarray_container that holds 0 element.
|
||||
*/
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
inline xarray_container<EC, L, SC, Tag>::xarray_container()
|
||||
: base_type(), m_storage(1, value_type())
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates an uninitialized xarray_container with the specified shape and
|
||||
* layout_type.
|
||||
* @param shape the shape of the xarray_container
|
||||
* @param l the layout_type of the xarray_container
|
||||
*/
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
inline xarray_container<EC, L, SC, Tag>::xarray_container(const shape_type& shape, layout_type l)
|
||||
: base_type()
|
||||
{
|
||||
base_type::resize(shape, l);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates an xarray_container with the specified shape and layout_type. Elements
|
||||
* are initialized to the specified value.
|
||||
* @param shape the shape of the xarray_container
|
||||
* @param value the value of the elements
|
||||
* @param l the layout_type of the xarray_container
|
||||
*/
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
inline xarray_container<EC, L, SC, Tag>::xarray_container(const shape_type& shape, const_reference value, layout_type l)
|
||||
: base_type()
|
||||
{
|
||||
base_type::resize(shape, l);
|
||||
std::fill(m_storage.begin(), m_storage.end(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates an uninitialized xarray_container with the specified shape and strides.
|
||||
* @param shape the shape of the xarray_container
|
||||
* @param strides the strides of the xarray_container
|
||||
*/
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
inline xarray_container<EC, L, SC, Tag>::xarray_container(const shape_type& shape, const strides_type& strides)
|
||||
: base_type()
|
||||
{
|
||||
base_type::resize(shape, strides);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates an uninitialized xarray_container with the specified shape and strides.
|
||||
* Elements are initialized to the specified value.
|
||||
* @param shape the shape of the xarray_container
|
||||
* @param strides the strides of the xarray_container
|
||||
* @param value the value of the elements
|
||||
*/
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
inline xarray_container<EC, L, SC, Tag>::xarray_container(const shape_type& shape, const strides_type& strides, const_reference value)
|
||||
: base_type()
|
||||
{
|
||||
base_type::resize(shape, strides);
|
||||
std::fill(m_storage.begin(), m_storage.end(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates an xarray_container that holds a single element initialized to the
|
||||
* specified value.
|
||||
* @param t the value of the element
|
||||
*/
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
inline xarray_container<EC, L, SC, Tag>::xarray_container(const value_type& t)
|
||||
: base_type()
|
||||
{
|
||||
base_type::resize(xt::shape<shape_type>(t), true);
|
||||
nested_copy(m_storage.begin(), t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates an xarray_container by moving specified data, shape and strides
|
||||
*
|
||||
* @param storage the data for the xarray_container
|
||||
* @param shape the shape of the xarray_container
|
||||
* @param strides the strides of the xarray_container
|
||||
*/
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
inline xarray_container<EC, L, SC, Tag>::xarray_container(storage_type&& storage, inner_shape_type&& shape, inner_strides_type&& strides)
|
||||
: base_type(std::move(shape), std::move(strides)), m_storage(std::move(storage))
|
||||
{
|
||||
}
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @name Constructors from initializer list
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* Allocates a one-dimensional xarray_container.
|
||||
* @param t the elements of the xarray_container
|
||||
*/
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
inline xarray_container<EC, L, SC, Tag>::xarray_container(nested_initializer_list_t<value_type, 1> t)
|
||||
: base_type()
|
||||
{
|
||||
base_type::resize(xt::shape<shape_type>(t));
|
||||
L == layout_type::row_major ? nested_copy(m_storage.begin(), t) : nested_copy(this->template begin<layout_type::row_major>(), t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a two-dimensional xarray_container.
|
||||
* @param t the elements of the xarray_container
|
||||
*/
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
inline xarray_container<EC, L, SC, Tag>::xarray_container(nested_initializer_list_t<value_type, 2> t)
|
||||
: base_type()
|
||||
{
|
||||
base_type::resize(xt::shape<shape_type>(t));
|
||||
L == layout_type::row_major ? nested_copy(m_storage.begin(), t) : nested_copy(this->template begin<layout_type::row_major>(), t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a three-dimensional xarray_container.
|
||||
* @param t the elements of the xarray_container
|
||||
*/
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
inline xarray_container<EC, L, SC, Tag>::xarray_container(nested_initializer_list_t<value_type, 3> t)
|
||||
: base_type()
|
||||
{
|
||||
base_type::resize(xt::shape<shape_type>(t));
|
||||
L == layout_type::row_major ? nested_copy(m_storage.begin(), t) : nested_copy(this->template begin<layout_type::row_major>(), t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a four-dimensional xarray_container.
|
||||
* @param t the elements of the xarray_container
|
||||
*/
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
inline xarray_container<EC, L, SC, Tag>::xarray_container(nested_initializer_list_t<value_type, 4> t)
|
||||
: base_type()
|
||||
{
|
||||
base_type::resize(xt::shape<shape_type>(t));
|
||||
L == layout_type::row_major ? nested_copy(m_storage.begin(), t) : nested_copy(this->template begin<layout_type::row_major>(), t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a five-dimensional xarray_container.
|
||||
* @param t the elements of the xarray_container
|
||||
*/
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
inline xarray_container<EC, L, SC, Tag>::xarray_container(nested_initializer_list_t<value_type, 5> t)
|
||||
: base_type()
|
||||
{
|
||||
base_type::resize(xt::shape<shape_type>(t));
|
||||
L == layout_type::row_major ? nested_copy(m_storage.begin(), t) : nested_copy(this->template begin<layout_type::row_major>(), t);
|
||||
}
|
||||
//@}
|
||||
|
||||
/**
|
||||
* Allocates and returns an xarray_container with the specified shape.
|
||||
* @param s the shape of the xarray_container
|
||||
*/
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
template <class S>
|
||||
inline xarray_container<EC, L, SC, Tag> xarray_container<EC, L, SC, Tag>::from_shape(S&& s)
|
||||
{
|
||||
shape_type shape = xtl::forward_sequence<shape_type>(s);
|
||||
return self_type(shape);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name Extended copy semantic
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* The extended copy constructor.
|
||||
*/
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
template <class E>
|
||||
inline xarray_container<EC, L, SC, Tag>::xarray_container(const xexpression<E>& e)
|
||||
: base_type()
|
||||
{
|
||||
// Avoids unintialized data because of (m_shape == shape) condition
|
||||
// in resize (called by assign), which is always true when dimension == 0.
|
||||
if (e.derived_cast().dimension() == 0)
|
||||
{
|
||||
detail::resize_data_container(m_storage, std::size_t(1));
|
||||
}
|
||||
semantic_base::assign(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* The extended assignment operator.
|
||||
*/
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
template <class E>
|
||||
inline auto xarray_container<EC, L, SC, Tag>::operator=(const xexpression<E>& e) -> self_type&
|
||||
{
|
||||
return semantic_base::operator=(e);
|
||||
}
|
||||
//@}
|
||||
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
inline auto xarray_container<EC, L, SC, Tag>::storage_impl() noexcept -> storage_type&
|
||||
{
|
||||
return m_storage;
|
||||
}
|
||||
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
inline auto xarray_container<EC, L, SC, Tag>::storage_impl() const noexcept -> const storage_type&
|
||||
{
|
||||
return m_storage;
|
||||
}
|
||||
|
||||
/******************
|
||||
* xarray_adaptor *
|
||||
******************/
|
||||
|
||||
/**
|
||||
* @name Constructors
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* Constructs an xarray_adaptor of the given stl-like container.
|
||||
* @param storage the container to adapt
|
||||
*/
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
inline xarray_adaptor<EC, L, SC, Tag>::xarray_adaptor(storage_type&& storage)
|
||||
: base_type(), m_storage(std::move(storage))
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an xarray_adaptor of the given stl-like container.
|
||||
* @param storage the container to adapt
|
||||
*/
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
inline xarray_adaptor<EC, L, SC, Tag>::xarray_adaptor(const storage_type& storage)
|
||||
: base_type(), m_storage(storage)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an xarray_adaptor of the given stl-like container,
|
||||
* with the specified shape and layout_type.
|
||||
* @param storage the container to adapt
|
||||
* @param shape the shape of the xarray_adaptor
|
||||
* @param l the layout_type of the xarray_adaptor
|
||||
*/
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
template <class D>
|
||||
inline xarray_adaptor<EC, L, SC, Tag>::xarray_adaptor(D&& storage, const shape_type& shape, layout_type l)
|
||||
: base_type(), m_storage(std::forward<D>(storage))
|
||||
{
|
||||
base_type::resize(shape, l);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an xarray_adaptor of the given stl-like container,
|
||||
* with the specified shape and strides.
|
||||
* @param storage the container to adapt
|
||||
* @param shape the shape of the xarray_adaptor
|
||||
* @param strides the strides of the xarray_adaptor
|
||||
*/
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
template <class D>
|
||||
inline xarray_adaptor<EC, L, SC, Tag>::xarray_adaptor(D&& storage, const shape_type& shape, const strides_type& strides)
|
||||
: base_type(), m_storage(std::forward<D>(storage))
|
||||
{
|
||||
base_type::resize(shape, strides);
|
||||
}
|
||||
//@}
|
||||
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
inline auto xarray_adaptor<EC, L, SC, Tag>::operator=(const xarray_adaptor& rhs) -> self_type&
|
||||
{
|
||||
base_type::operator=(rhs);
|
||||
m_storage = rhs.m_storage;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
inline auto xarray_adaptor<EC, L, SC, Tag>::operator=(xarray_adaptor&& rhs) -> self_type&
|
||||
{
|
||||
base_type::operator=(std::move(rhs));
|
||||
m_storage = rhs.m_storage;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
inline auto xarray_adaptor<EC, L, SC, Tag>::operator=(temporary_type&& rhs) -> self_type&
|
||||
{
|
||||
base_type::shape_impl() = std::move(const_cast<shape_type&>(rhs.shape()));
|
||||
base_type::strides_impl() = std::move(const_cast<strides_type&>(rhs.strides()));
|
||||
base_type::backstrides_impl() = std::move(const_cast<backstrides_type&>(rhs.backstrides()));
|
||||
m_storage = std::move(rhs.storage());
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @name Extended copy semantic
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* The extended assignment operator.
|
||||
*/
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
template <class E>
|
||||
inline auto xarray_adaptor<EC, L, SC, Tag>::operator=(const xexpression<E>& e) -> self_type&
|
||||
{
|
||||
return semantic_base::operator=(e);
|
||||
}
|
||||
//@}
|
||||
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
inline auto xarray_adaptor<EC, L, SC, Tag>::storage_impl() noexcept -> storage_type&
|
||||
{
|
||||
return m_storage;
|
||||
}
|
||||
|
||||
template <class EC, layout_type L, class SC, class Tag>
|
||||
inline auto xarray_adaptor<EC, L, SC, Tag>::storage_impl() const noexcept -> const storage_type&
|
||||
{
|
||||
return m_storage;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
783
vendor/xtensor/include/xtensor/xassign.hpp
vendored
Normal file
783
vendor/xtensor/include/xtensor/xassign.hpp
vendored
Normal file
|
|
@ -0,0 +1,783 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTENSOR_ASSIGN_HPP
|
||||
#define XTENSOR_ASSIGN_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include <xtl/xsequence.hpp>
|
||||
|
||||
#include "xconcepts.hpp"
|
||||
#include "xexpression.hpp"
|
||||
#include "xiterator.hpp"
|
||||
#include "xstrides.hpp"
|
||||
#include "xtensor_forward.hpp"
|
||||
#include "xutils.hpp"
|
||||
|
||||
namespace xt
|
||||
{
|
||||
|
||||
/********************
|
||||
* Assign functions *
|
||||
********************/
|
||||
|
||||
template <class E1, class E2>
|
||||
void assign_data(xexpression<E1>& e1, const xexpression<E2>& e2, bool trivial);
|
||||
|
||||
template <class E1, class E2>
|
||||
void assign_xexpression(xexpression<E1>& e1, const xexpression<E2>& e2);
|
||||
|
||||
template <class E1, class E2>
|
||||
void computed_assign(xexpression<E1>& e1, const xexpression<E2>& e2);
|
||||
|
||||
template <class E1, class E2, class F>
|
||||
void scalar_computed_assign(xexpression<E1>& e1, const E2& e2, F&& f);
|
||||
|
||||
template <class E1, class E2>
|
||||
void assert_compatible_shape(const xexpression<E1>& e1, const xexpression<E2>& e2);
|
||||
|
||||
template <class E1, class E2>
|
||||
void strided_assign(E1& e1, const E2& e2, std::false_type /*disable*/);
|
||||
|
||||
template <class E1, class E2>
|
||||
void strided_assign(E1& e1, const E2& e2, std::true_type /*enable*/);
|
||||
|
||||
/************************
|
||||
* xexpression_assigner *
|
||||
************************/
|
||||
|
||||
template <class Tag>
|
||||
class xexpression_assigner_base;
|
||||
|
||||
template <>
|
||||
class xexpression_assigner_base<xtensor_expression_tag>
|
||||
{
|
||||
public:
|
||||
|
||||
template <class E1, class E2>
|
||||
static void assign_data(xexpression<E1>& e1, const xexpression<E2>& e2, bool trivial);
|
||||
};
|
||||
|
||||
template <class Tag>
|
||||
class xexpression_assigner : public xexpression_assigner_base<Tag>
|
||||
{
|
||||
public:
|
||||
|
||||
using base_type = xexpression_assigner_base<Tag>;
|
||||
|
||||
template <class E1, class E2>
|
||||
static void assign_xexpression(xexpression<E1>& e1, const xexpression<E2>& e2);
|
||||
|
||||
template <class E1, class E2>
|
||||
static void computed_assign(xexpression<E1>& e1, const xexpression<E2>& e2);
|
||||
|
||||
template <class E1, class E2, class F>
|
||||
static void scalar_computed_assign(xexpression<E1>& e1, const E2& e2, F&& f);
|
||||
|
||||
template <class E1, class E2>
|
||||
static void assert_compatible_shape(const xexpression<E1>& e1, const xexpression<E2>& e2);
|
||||
|
||||
private:
|
||||
|
||||
template <class E1, class E2>
|
||||
static bool resize(xexpression<E1>& e1, const xexpression<E2>& e2);
|
||||
};
|
||||
|
||||
/*****************
|
||||
* data_assigner *
|
||||
*****************/
|
||||
|
||||
template <class E1, class E2, layout_type L>
|
||||
class data_assigner
|
||||
{
|
||||
public:
|
||||
|
||||
using lhs_iterator = typename E1::stepper;
|
||||
using rhs_iterator = typename E2::const_stepper;
|
||||
using shape_type = typename E1::shape_type;
|
||||
using index_type = xindex_type_t<shape_type>;
|
||||
using size_type = typename lhs_iterator::size_type;
|
||||
using difference_type = typename lhs_iterator::difference_type;
|
||||
|
||||
data_assigner(E1& e1, const E2& e2);
|
||||
|
||||
void run();
|
||||
|
||||
void step(size_type i);
|
||||
void step(size_type i, size_type n);
|
||||
void reset(size_type i);
|
||||
|
||||
void to_end(layout_type);
|
||||
|
||||
private:
|
||||
|
||||
E1& m_e1;
|
||||
|
||||
lhs_iterator m_lhs;
|
||||
rhs_iterator m_rhs;
|
||||
|
||||
index_type m_index;
|
||||
};
|
||||
|
||||
/********************
|
||||
* trivial_assigner *
|
||||
********************/
|
||||
|
||||
template <bool simd_assign>
|
||||
struct trivial_assigner
|
||||
{
|
||||
template <class E1, class E2>
|
||||
static void run(E1& e1, const E2& e2);
|
||||
};
|
||||
|
||||
/***********************************
|
||||
* Assign functions implementation *
|
||||
***********************************/
|
||||
|
||||
template <class E1, class E2>
|
||||
inline void assign_data(xexpression<E1>& e1, const xexpression<E2>& e2, bool trivial)
|
||||
{
|
||||
using tag = xexpression_tag_t<E1, E2>;
|
||||
xexpression_assigner<tag>::assign_data(e1, e2, trivial);
|
||||
}
|
||||
|
||||
template <class E1, class E2>
|
||||
inline void assign_xexpression(xexpression<E1>& e1, const xexpression<E2>& e2)
|
||||
{
|
||||
xtl::mpl::static_if<has_assign_to<E1, E2>::value>([&](auto self)
|
||||
{
|
||||
self(e2).derived_cast().assign_to(e1);
|
||||
}, /*else*/ [&](auto /*self*/)
|
||||
{
|
||||
using tag = xexpression_tag_t<E1, E2>;
|
||||
xexpression_assigner<tag>::assign_xexpression(e1, e2);
|
||||
});
|
||||
}
|
||||
|
||||
template <class E1, class E2>
|
||||
inline void computed_assign(xexpression<E1>& e1, const xexpression<E2>& e2)
|
||||
{
|
||||
using tag = xexpression_tag_t<E1, E2>;
|
||||
xexpression_assigner<tag>::computed_assign(e1, e2);
|
||||
}
|
||||
|
||||
template <class E1, class E2, class F>
|
||||
inline void scalar_computed_assign(xexpression<E1>& e1, const E2& e2, F&& f)
|
||||
{
|
||||
using tag = xexpression_tag_t<E1, E2>;
|
||||
xexpression_assigner<tag>::scalar_computed_assign(e1, e2, std::forward<F>(f));
|
||||
}
|
||||
|
||||
template <class E1, class E2>
|
||||
inline void assert_compatible_shape(const xexpression<E1>& e1, const xexpression<E2>& e2)
|
||||
{
|
||||
using tag = xexpression_tag_t<E1, E2>;
|
||||
xexpression_assigner<tag>::assert_compatible_shape(e1, e2);
|
||||
}
|
||||
|
||||
/***************************************
|
||||
* xexpression_assigner implementation *
|
||||
***************************************/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class E1, class E2>
|
||||
inline bool is_trivial_broadcast(const E1& e1, const E2& e2)
|
||||
{
|
||||
return (E1::contiguous_layout && E2::contiguous_layout && (E1::static_layout == E2::static_layout))
|
||||
|| e2.is_trivial_broadcast(e1.strides());
|
||||
}
|
||||
|
||||
template <class D, class E2, class... SL>
|
||||
inline bool is_trivial_broadcast(const xview<D, SL...>&, const E2&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class E, class = void_t<>>
|
||||
struct forbid_simd_assign
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
||||
// Double steps check for xfunction because the default
|
||||
// parameter void_t of forbid_simd_assign prevents additional
|
||||
// specializations.
|
||||
template <class E>
|
||||
struct xfunction_forbid_simd;
|
||||
|
||||
template <class E>
|
||||
struct forbid_simd_assign<E,
|
||||
void_t<decltype(std::declval<E>().template load_simd<aligned_mode>(typename E::size_type(0)))>>
|
||||
{
|
||||
static constexpr bool value = false || xfunction_forbid_simd<E>::value;
|
||||
};
|
||||
|
||||
template <class E>
|
||||
struct xfunction_forbid_simd
|
||||
{
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
|
||||
template <class F, class R, class... CT>
|
||||
struct xfunction_forbid_simd<xfunction<F, R, CT...>>
|
||||
{
|
||||
static constexpr bool value = xtl::disjunction<
|
||||
std::integral_constant<bool, forbid_simd_assign<typename std::decay<CT>::type>::value>...>::value;
|
||||
};
|
||||
|
||||
template <class F, class B, class = void>
|
||||
struct has_simd_apply : std::false_type {};
|
||||
|
||||
template <class F, class B>
|
||||
struct has_simd_apply<F, B, void_t<decltype(&F::template simd_apply<B>)>>
|
||||
: std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class E, class = void>
|
||||
struct has_step_leading : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class E>
|
||||
struct has_step_leading<E, void_t<decltype(std::declval<E>().step_leading())>>
|
||||
: std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct use_strided_loop
|
||||
{
|
||||
static constexpr bool stepper_deref() { return std::is_reference<typename T::stepper::reference>::value; }
|
||||
static constexpr bool value = has_strides<T>::value && has_step_leading<typename T::stepper>::value && stepper_deref();
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct use_strided_loop<xscalar<T>>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
||||
template <class F, class R, class... CT>
|
||||
struct use_strided_loop<xfunction<F, R, CT...>>
|
||||
{
|
||||
static constexpr bool value = xtl::conjunction<use_strided_loop<std::decay_t<CT>>...>::value &&
|
||||
has_simd_apply<F, xsimd::simd_type<R>>::value;
|
||||
};
|
||||
}
|
||||
|
||||
template <class E1, class E2>
|
||||
struct xassign_traits
|
||||
{
|
||||
// constexpr methods instead of constexpr data members avoid the need of difinitions at namespace
|
||||
// scope of these data members (since they are odr-used).
|
||||
static constexpr bool contiguous_layout() { return E1::contiguous_layout && E2::contiguous_layout; }
|
||||
static constexpr bool same_type() { return std::is_same<typename E1::value_type, typename E2::value_type>::value; }
|
||||
static constexpr bool simd_size() { return xsimd::simd_traits<typename E1::value_type>::size > 1; }
|
||||
static constexpr bool forbid_simd() { return detail::forbid_simd_assign<E2>::value; }
|
||||
static constexpr bool simd_assign() { return contiguous_layout() && same_type() && simd_size() && !forbid_simd(); }
|
||||
static constexpr bool simd_strided_loop() { return same_type() && simd_size() && detail::use_strided_loop<E2>::value && detail::use_strided_loop<E1>::value; }
|
||||
};
|
||||
|
||||
template <class E1, class E2>
|
||||
inline void xexpression_assigner_base<xtensor_expression_tag>::assign_data(xexpression<E1>& e1, const xexpression<E2>& e2, bool trivial)
|
||||
{
|
||||
E1& de1 = e1.derived_cast();
|
||||
const E2& de2 = e2.derived_cast();
|
||||
|
||||
bool trivial_broadcast = trivial && detail::is_trivial_broadcast(de1, de2);
|
||||
|
||||
if (trivial_broadcast)
|
||||
{
|
||||
constexpr bool simd_assign = xassign_traits<E1, E2>::simd_assign();
|
||||
trivial_assigner<simd_assign>::run(de1, de2);
|
||||
}
|
||||
else if (xassign_traits<E1, E2>::simd_strided_loop())
|
||||
{
|
||||
strided_assign(de1, de2, std::integral_constant<bool, xassign_traits<E1, E2>::simd_strided_loop()>{});
|
||||
}
|
||||
else
|
||||
{
|
||||
data_assigner<E1, E2, default_assignable_layout(E1::static_layout)> assigner(de1, de2);
|
||||
assigner.run();
|
||||
}
|
||||
}
|
||||
|
||||
template <class Tag>
|
||||
template <class E1, class E2>
|
||||
inline void xexpression_assigner<Tag>::assign_xexpression(xexpression<E1>& e1, const xexpression<E2>& e2)
|
||||
{
|
||||
bool trivial_broadcast = resize(e1, e2);
|
||||
base_type::assign_data(e1, e2, trivial_broadcast);
|
||||
}
|
||||
|
||||
template <class Tag>
|
||||
template <class E1, class E2>
|
||||
inline void xexpression_assigner<Tag>::computed_assign(xexpression<E1>& e1, const xexpression<E2>& e2)
|
||||
{
|
||||
using shape_type = typename E1::shape_type;
|
||||
using size_type = typename E1::size_type;
|
||||
|
||||
E1& de1 = e1.derived_cast();
|
||||
const E2& de2 = e2.derived_cast();
|
||||
|
||||
size_type dim = de2.dimension();
|
||||
shape_type shape = xtl::make_sequence<shape_type>(dim, size_type(0));
|
||||
bool trivial_broadcast = de2.broadcast_shape(shape, true);
|
||||
|
||||
if (dim > de1.dimension() || shape > de1.shape())
|
||||
{
|
||||
typename E1::temporary_type tmp(shape);
|
||||
base_type::assign_data(tmp, e2, trivial_broadcast);
|
||||
de1.assign_temporary(std::move(tmp));
|
||||
}
|
||||
else
|
||||
{
|
||||
base_type::assign_data(e1, e2, trivial_broadcast);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Tag>
|
||||
template <class E1, class E2, class F>
|
||||
inline void xexpression_assigner<Tag>::scalar_computed_assign(xexpression<E1>& e1, const E2& e2, F&& f)
|
||||
{
|
||||
E1& d = e1.derived_cast();
|
||||
using size_type = typename E1::size_type;
|
||||
auto dst = d.storage().begin();
|
||||
for (size_type i = d.size(); i > 0; --i)
|
||||
{
|
||||
*dst = f(*dst, e2);
|
||||
++dst;
|
||||
}
|
||||
}
|
||||
|
||||
template <class Tag>
|
||||
template <class E1, class E2>
|
||||
inline void xexpression_assigner<Tag>::assert_compatible_shape(const xexpression<E1>& e1, const xexpression<E2>& e2)
|
||||
{
|
||||
const E1& de1 = e1.derived_cast();
|
||||
const E2& de2 = e2.derived_cast();
|
||||
if (!broadcastable(de2.shape(), de1.shape()))
|
||||
{
|
||||
throw_broadcast_error(de2.shape(), de1.shape());
|
||||
}
|
||||
}
|
||||
|
||||
template <class Tag>
|
||||
template <class E1, class E2>
|
||||
inline bool xexpression_assigner<Tag>::resize(xexpression<E1>& e1, const xexpression<E2>& e2)
|
||||
{
|
||||
using shape_type = typename E1::shape_type;
|
||||
using size_type = typename E1::size_type;
|
||||
const E2& de2 = e2.derived_cast();
|
||||
size_type size = de2.dimension();
|
||||
shape_type shape = xtl::make_sequence<shape_type>(size, size_type(0));
|
||||
bool trivial_broadcast = de2.broadcast_shape(shape, true);
|
||||
e1.derived_cast().resize(std::move(shape));
|
||||
return trivial_broadcast;
|
||||
}
|
||||
|
||||
/********************************
|
||||
* data_assigner implementation *
|
||||
********************************/
|
||||
|
||||
template <class E1, class E2, layout_type L>
|
||||
inline data_assigner<E1, E2, L>::data_assigner(E1& e1, const E2& e2)
|
||||
: m_e1(e1), m_lhs(e1.stepper_begin(e1.shape())),
|
||||
m_rhs(e2.stepper_begin(e1.shape())),
|
||||
m_index(xtl::make_sequence<index_type>(e1.shape().size(), size_type(0)))
|
||||
{
|
||||
}
|
||||
|
||||
template <class E1, class E2, layout_type L>
|
||||
inline void data_assigner<E1, E2, L>::run()
|
||||
{
|
||||
using size_type = typename E1::size_type;
|
||||
using argument_type = std::decay_t<decltype(*m_rhs)>;
|
||||
using result_type = std::decay_t<decltype(*m_lhs)>;
|
||||
constexpr bool is_narrowing = is_narrowing_conversion<argument_type, result_type>::value;
|
||||
|
||||
size_type s = m_e1.size();
|
||||
for (size_type i = 0; i < s; ++i)
|
||||
{
|
||||
*m_lhs = conditional_cast<is_narrowing, result_type>(*m_rhs);
|
||||
stepper_tools<L>::increment_stepper(*this, m_index, m_e1.shape());
|
||||
}
|
||||
}
|
||||
|
||||
template <class E1, class E2, layout_type L>
|
||||
inline void data_assigner<E1, E2, L>::step(size_type i)
|
||||
{
|
||||
m_lhs.step(i);
|
||||
m_rhs.step(i);
|
||||
}
|
||||
|
||||
template <class E1, class E2, layout_type L>
|
||||
inline void data_assigner<E1, E2, L>::step(size_type i, size_type n)
|
||||
{
|
||||
m_lhs.step(i, n);
|
||||
m_rhs.step(i, n);
|
||||
}
|
||||
|
||||
template <class E1, class E2, layout_type L>
|
||||
inline void data_assigner<E1, E2, L>::reset(size_type i)
|
||||
{
|
||||
m_lhs.reset(i);
|
||||
m_rhs.reset(i);
|
||||
}
|
||||
|
||||
template <class E1, class E2, layout_type L>
|
||||
inline void data_assigner<E1, E2, L>::to_end(layout_type l)
|
||||
{
|
||||
m_lhs.to_end(l);
|
||||
m_rhs.to_end(l);
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* trivial_assigner implementation *
|
||||
***********************************/
|
||||
|
||||
template <bool simd_assign>
|
||||
template <class E1, class E2>
|
||||
inline void trivial_assigner<simd_assign>::run(E1& e1, const E2& e2)
|
||||
{
|
||||
using lhs_align_mode = xsimd::container_alignment_t<E1>;
|
||||
constexpr bool is_aligned = std::is_same<lhs_align_mode, aligned_mode>::value;
|
||||
using rhs_align_mode = std::conditional_t<is_aligned, inner_aligned_mode, unaligned_mode>;
|
||||
using value_type = std::common_type_t<typename E1::value_type, typename E2::value_type>;
|
||||
using simd_type = xsimd::simd_type<value_type>;
|
||||
using size_type = typename E1::size_type;
|
||||
size_type size = e1.size();
|
||||
size_type simd_size = simd_type::size;
|
||||
|
||||
size_type align_begin = is_aligned ? 0 : xsimd::get_alignment_offset(e1.data(), size, simd_size);
|
||||
size_type align_end = align_begin + ((size - align_begin) & ~(simd_size - 1));
|
||||
|
||||
for (size_type i = 0; i < align_begin; ++i)
|
||||
{
|
||||
e1.data_element(i) = e2.data_element(i);
|
||||
}
|
||||
for (size_type i = align_begin; i < align_end; i += simd_size)
|
||||
{
|
||||
e1.template store_simd<lhs_align_mode, simd_type>(i, e2.template load_simd<rhs_align_mode, simd_type>(i));
|
||||
}
|
||||
for (size_type i = align_end; i < size; ++i)
|
||||
{
|
||||
e1.data_element(i) = e2.data_element(i);
|
||||
}
|
||||
}
|
||||
|
||||
namespace assigner_detail
|
||||
{
|
||||
template <class C, class It, class Ot>
|
||||
inline void assign_loop(It src, Ot dst, std::size_t n)
|
||||
{
|
||||
for(; n > 0; --n)
|
||||
{
|
||||
*dst = static_cast<C>(*src);
|
||||
++src;
|
||||
++dst;
|
||||
}
|
||||
}
|
||||
|
||||
template <class E1, class E2>
|
||||
inline void trivial_assigner_run_impl(E1& e1, const E2& e2, std::true_type)
|
||||
{
|
||||
using size_type = typename E1::size_type;
|
||||
auto src = e2.storage_cbegin();
|
||||
auto dst = e1.storage_begin();
|
||||
assign_loop<typename E1::value_type>(src, dst, e1.size());
|
||||
}
|
||||
|
||||
template <class E1, class E2>
|
||||
inline void trivial_assigner_run_impl(E1&, const E2&, std::false_type)
|
||||
{
|
||||
XTENSOR_PRECONDITION(false,
|
||||
"Internal error: trivial_assigner called with unrelated types.");
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
template <class E1, class E2>
|
||||
inline void trivial_assigner<false>::run(E1& e1, const E2& e2)
|
||||
{
|
||||
using is_convertible = std::is_convertible<typename std::decay_t<E1>::value_type,
|
||||
typename std::decay_t<E2>::value_type>;
|
||||
// If the types are not compatible, this function is still instantiated but never called.
|
||||
// To avoid compilation problems in effectively unused code trivial_assigner_run_impl is
|
||||
// empty in this case.
|
||||
assigner_detail::trivial_assigner_run_impl(e1, e2, is_convertible());
|
||||
}
|
||||
|
||||
/***********************
|
||||
* Strided assign loop *
|
||||
***********************/
|
||||
|
||||
namespace strided_assign_detail
|
||||
{
|
||||
template <layout_type layout>
|
||||
struct idx_tools;
|
||||
|
||||
template <>
|
||||
struct idx_tools<layout_type::row_major>
|
||||
{
|
||||
template <class T>
|
||||
static void next_idx(T& outer_index, T& outer_shape)
|
||||
{
|
||||
auto i = outer_index.size();
|
||||
for (; i > 0; --i)
|
||||
{
|
||||
if (outer_index[i - 1] + 1 >= outer_shape[i - 1])
|
||||
{
|
||||
outer_index[i - 1] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
outer_index[i - 1]++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct idx_tools<layout_type::column_major>
|
||||
{
|
||||
template <class T>
|
||||
static void next_idx(T& outer_index, T& outer_shape)
|
||||
{
|
||||
using size_type = typename T::size_type;
|
||||
size_type i = 0;
|
||||
auto sz = outer_index.size();
|
||||
for (; i < sz; ++i)
|
||||
{
|
||||
if (outer_index[i] + 1 >= outer_shape[i])
|
||||
{
|
||||
outer_index[i] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
outer_index[i]++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <layout_type L, class S>
|
||||
struct check_strides_functor
|
||||
{
|
||||
using strides_type = S;
|
||||
|
||||
check_strides_functor(const S& strides)
|
||||
: m_cut(L == layout_type::row_major ? 0 : strides.size()),
|
||||
m_strides(strides)
|
||||
{
|
||||
}
|
||||
|
||||
template <class T, layout_type LE = L>
|
||||
std::enable_if_t<LE == layout_type::row_major, std::size_t>
|
||||
operator()(const T& el)
|
||||
{
|
||||
auto var = check_strides_overlap<layout_type::row_major>::get(m_strides, el.strides());
|
||||
if (var > m_cut)
|
||||
{
|
||||
m_cut = var;
|
||||
}
|
||||
return m_cut;
|
||||
}
|
||||
|
||||
template <class T, layout_type LE = L>
|
||||
std::enable_if_t<LE == layout_type::column_major, std::size_t>
|
||||
operator()(const T& el)
|
||||
{
|
||||
auto var = check_strides_overlap<layout_type::column_major>::get(m_strides, el.strides());
|
||||
if (var < m_cut)
|
||||
{
|
||||
m_cut = var;
|
||||
}
|
||||
return m_cut;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::size_t operator()(const xt::xscalar<T>& /*el*/)
|
||||
{
|
||||
return m_cut;
|
||||
}
|
||||
|
||||
template <class F, class R, class... CT>
|
||||
std::size_t operator()(const xt::xfunction<F, R, CT...>& xf)
|
||||
{
|
||||
xt::for_each(*this, xf.arguments());
|
||||
return m_cut;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::size_t m_cut;
|
||||
const strides_type& m_strides;
|
||||
};
|
||||
|
||||
template <class E1, class E2>
|
||||
auto get_loop_sizes(const E1& e1, const E2& e2)
|
||||
{
|
||||
std::size_t cut = 0;
|
||||
|
||||
// TODO! if E1 is !contigous --> initialize cut to sensible value!
|
||||
if (e1.strides().back() == 1)
|
||||
{
|
||||
auto csf = check_strides_functor<layout_type::row_major, decltype(e1.strides())>(e1.strides());
|
||||
cut = csf(e2);
|
||||
}
|
||||
else if (e1.strides().front() == 1)
|
||||
{
|
||||
auto csf = check_strides_functor<layout_type::column_major, decltype(e1.strides())>(e1.strides());
|
||||
cut = csf(e2);
|
||||
}
|
||||
|
||||
using shape_value_type = typename E1::shape_type::value_type;
|
||||
std::size_t outer_loop_size = static_cast<std::size_t>(
|
||||
std::accumulate(e1.shape().begin(), e1.shape().begin() + static_cast<std::ptrdiff_t>(cut),
|
||||
shape_value_type(1), std::multiplies<shape_value_type>{}));
|
||||
std::size_t inner_loop_size = static_cast<std::size_t>(
|
||||
std::accumulate(e1.shape().begin() + static_cast<std::ptrdiff_t>(cut), e1.shape().end(),
|
||||
shape_value_type(1), std::multiplies<shape_value_type>{}));
|
||||
|
||||
if (e1.strides().back() != 1) // column major mode
|
||||
{
|
||||
std::swap(outer_loop_size, inner_loop_size);
|
||||
}
|
||||
|
||||
return std::make_tuple(inner_loop_size, outer_loop_size, cut);
|
||||
}
|
||||
}
|
||||
|
||||
template <class E1, class E2>
|
||||
void strided_assign(E1& e1, const E2& e2, std::true_type /*enable*/)
|
||||
{
|
||||
bool fallback = false, is_row_major = true;
|
||||
|
||||
std::size_t inner_loop_size, outer_loop_size, cut;
|
||||
std::tie(inner_loop_size, outer_loop_size, cut) = strided_assign_detail::get_loop_sizes(e1, e2);
|
||||
|
||||
if (E1::static_layout == layout_type::row_major || e1.strides().back() == 1) // row major case
|
||||
{
|
||||
if (cut == e1.dimension())
|
||||
{
|
||||
fallback = true;
|
||||
}
|
||||
}
|
||||
else if (E1::static_layout == layout_type::column_major || e1.strides().front() == 1) // col major case
|
||||
{
|
||||
is_row_major = false;
|
||||
if (cut == 0)
|
||||
{
|
||||
fallback = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fallback = true;
|
||||
}
|
||||
|
||||
if (fallback)
|
||||
{
|
||||
data_assigner<E1, E2, default_assignable_layout(E1::static_layout)> assigner(e1, e2);
|
||||
assigner.run();
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO can we get rid of this and use `shape_type`?
|
||||
dynamic_shape<std::size_t> idx;
|
||||
|
||||
using iterator_type = decltype(e1.shape().begin());
|
||||
iterator_type max_shape_begin, max_shape_end;
|
||||
if (is_row_major)
|
||||
{
|
||||
xt::resize_container(idx, cut);
|
||||
max_shape_begin = e1.shape().begin();
|
||||
max_shape_end = e1.shape().begin() + static_cast<std::ptrdiff_t>(cut);
|
||||
}
|
||||
else
|
||||
{
|
||||
xt::resize_container(idx, e1.shape().size() - cut);
|
||||
max_shape_begin = e1.shape().begin() + static_cast<std::ptrdiff_t>(cut);
|
||||
max_shape_end = e1.shape().end();
|
||||
}
|
||||
|
||||
// add this when we have std::array index!
|
||||
// std::fill(idx.begin(), idx.end(), 0);
|
||||
|
||||
dynamic_shape<std::size_t> max(max_shape_begin, max_shape_end);
|
||||
|
||||
using simd_type = xsimd::simd_type<typename E1::value_type>;
|
||||
|
||||
std::size_t simd_size = inner_loop_size / simd_type::size;
|
||||
std::size_t simd_rest = inner_loop_size % simd_type::size;
|
||||
|
||||
auto fct_stepper = e2.stepper_begin(e1.shape());
|
||||
auto res_stepper = e1.stepper_begin(e1.shape());
|
||||
|
||||
// TODO in 1D case this is ambigous -- could be RM or CM.
|
||||
// Use default layout to make decision
|
||||
std::size_t step_dim = 0;
|
||||
if (!is_row_major) // row major case
|
||||
{
|
||||
step_dim = cut;
|
||||
}
|
||||
|
||||
for (std::size_t ox = 0; ox < outer_loop_size; ++ox)
|
||||
{
|
||||
for (std::size_t i = 0; i < simd_size; i++)
|
||||
{
|
||||
res_stepper.template store_simd<simd_type>(fct_stepper.template step_simd<simd_type>());
|
||||
}
|
||||
for (std::size_t i = 0; i < simd_rest; ++i)
|
||||
{
|
||||
*(res_stepper) = *(fct_stepper);
|
||||
res_stepper.step_leading();
|
||||
fct_stepper.step_leading();
|
||||
}
|
||||
|
||||
is_row_major ?
|
||||
strided_assign_detail::idx_tools<layout_type::row_major>::next_idx(idx, max) :
|
||||
strided_assign_detail::idx_tools<layout_type::column_major>::next_idx(idx, max);
|
||||
|
||||
fct_stepper.to_begin();
|
||||
|
||||
// need to step E1 as well if not contigous assign (e.g. view)
|
||||
if (!E1::contiguous_layout)
|
||||
{
|
||||
res_stepper.to_begin();
|
||||
for (std::size_t i = 0; i < idx.size(); ++i)
|
||||
{
|
||||
fct_stepper.step(i + step_dim, idx[i]);
|
||||
res_stepper.step(i + step_dim, idx[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (std::size_t i = 0; i < idx.size(); ++i)
|
||||
{
|
||||
fct_stepper.step(i + step_dim, idx[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class E1, class E2>
|
||||
inline void strided_assign(E1& /*e1*/, const E2& /*e2*/, std::false_type /*disable*/)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
197
vendor/xtensor/include/xtensor/xaxis_iterator.hpp
vendored
Normal file
197
vendor/xtensor/include/xtensor/xaxis_iterator.hpp
vendored
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTENSOR_AXIS_ITERATOR_HPP
|
||||
#define XTENSOR_AXIS_ITERATOR_HPP
|
||||
|
||||
#include <xtl/xclosure.hpp>
|
||||
|
||||
#include "xview.hpp"
|
||||
|
||||
namespace xt
|
||||
{
|
||||
|
||||
/******************
|
||||
* xaxis_iterator *
|
||||
******************/
|
||||
|
||||
template <class CT>
|
||||
class xaxis_iterator
|
||||
{
|
||||
public:
|
||||
|
||||
using self_type = xaxis_iterator<CT>;
|
||||
|
||||
using xexpression_type = std::decay_t<CT>;
|
||||
using size_type = typename xexpression_type::size_type;
|
||||
using difference_type = typename xexpression_type::difference_type;
|
||||
using value_type = xview<CT, size_type>;
|
||||
using reference = std::remove_reference_t<apply_cv_t<CT, value_type>>;
|
||||
using pointer = xtl::xclosure_pointer<std::remove_reference_t<apply_cv_t<CT, value_type>>>;
|
||||
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
|
||||
xaxis_iterator();
|
||||
template <class CTA>
|
||||
xaxis_iterator(CTA&& e, size_type index);
|
||||
|
||||
self_type& operator++();
|
||||
self_type operator++(int);
|
||||
|
||||
reference operator*() const;
|
||||
pointer operator->() const;
|
||||
|
||||
bool equal(const self_type& rhs) const;
|
||||
|
||||
private:
|
||||
|
||||
using storing_type = xtl::ptr_closure_type_t<CT>;
|
||||
mutable storing_type p_expression;
|
||||
size_type m_index;
|
||||
|
||||
template <class T>
|
||||
std::enable_if_t<std::is_pointer<T>::value, std::add_lvalue_reference_t<std::remove_pointer_t<T>>>
|
||||
deref(T val) const;
|
||||
|
||||
template <class T>
|
||||
std::enable_if_t<!std::is_pointer<T>::value, T>
|
||||
deref(T& val) const;
|
||||
|
||||
template <class T, class CTA>
|
||||
std::enable_if_t<std::is_pointer<T>::value, T>
|
||||
get_storage_init(CTA&& e) const;
|
||||
|
||||
template <class T, class CTA>
|
||||
std::enable_if_t<!std::is_pointer<T>::value, T>
|
||||
get_storage_init(CTA&& e) const;
|
||||
};
|
||||
|
||||
template <class CT>
|
||||
bool operator==(const xaxis_iterator<CT>& lhs, const xaxis_iterator<CT>& rhs);
|
||||
|
||||
template <class CT>
|
||||
bool operator!=(const xaxis_iterator<CT>& lhs, const xaxis_iterator<CT>& rhs);
|
||||
|
||||
template <class E>
|
||||
auto axis_begin(E&& e);
|
||||
|
||||
template <class E>
|
||||
auto axis_end(E&& e);
|
||||
|
||||
/*********************************
|
||||
* xaxis_iterator implementation *
|
||||
*********************************/
|
||||
|
||||
template <class CT>
|
||||
template <class T>
|
||||
inline std::enable_if_t<std::is_pointer<T>::value, std::add_lvalue_reference_t<std::remove_pointer_t<T>>>
|
||||
xaxis_iterator<CT>::deref(T val) const
|
||||
{
|
||||
return *val;
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
template <class T>
|
||||
inline std::enable_if_t<!std::is_pointer<T>::value, T>
|
||||
xaxis_iterator<CT>::deref(T& val) const
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
template <class T, class CTA>
|
||||
inline std::enable_if_t<std::is_pointer<T>::value, T>
|
||||
xaxis_iterator<CT>::get_storage_init(CTA&& e) const
|
||||
{
|
||||
return &e;
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
template <class T, class CTA>
|
||||
inline std::enable_if_t<!std::is_pointer<T>::value, T>
|
||||
xaxis_iterator<CT>::get_storage_init(CTA&& e) const
|
||||
{
|
||||
return e;
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
inline xaxis_iterator<CT>::xaxis_iterator()
|
||||
: p_expression(nullptr), m_index(0)
|
||||
{
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
template <class CTA>
|
||||
inline xaxis_iterator<CT>::xaxis_iterator(CTA&& e, size_type index)
|
||||
: p_expression(get_storage_init<storing_type>(std::forward<CTA>(e))), m_index(index)
|
||||
{
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
inline auto xaxis_iterator<CT>::operator++() -> self_type&
|
||||
{
|
||||
++m_index;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
inline auto xaxis_iterator<CT>::operator++(int) -> self_type
|
||||
{
|
||||
self_type tmp(*this);
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
inline auto xaxis_iterator<CT>::operator*() const -> reference
|
||||
{
|
||||
return view(deref(p_expression), size_type(m_index));
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
inline auto xaxis_iterator<CT>::operator->() const -> pointer
|
||||
{
|
||||
return xtl::closure_pointer(operator*());
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
inline bool xaxis_iterator<CT>::equal(const self_type& rhs) const
|
||||
{
|
||||
return p_expression == rhs.p_expression && m_index == rhs.m_index;
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
inline bool operator==(const xaxis_iterator<CT>& lhs, const xaxis_iterator<CT>& rhs)
|
||||
{
|
||||
return lhs.equal(rhs);
|
||||
}
|
||||
|
||||
template <class CT>
|
||||
inline bool operator!=(const xaxis_iterator<CT>& lhs, const xaxis_iterator<CT>& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template <class E>
|
||||
inline auto axis_begin(E&& e)
|
||||
{
|
||||
using return_type = xaxis_iterator<xtl::closure_type_t<E>>;
|
||||
using size_type = typename std::decay_t<E>::size_type;
|
||||
return return_type(std::forward<E>(e), size_type(0));
|
||||
}
|
||||
|
||||
template <class E>
|
||||
inline auto axis_end(E&& e)
|
||||
{
|
||||
using return_type = xaxis_iterator<xtl::closure_type_t<E>>;
|
||||
using size_type = typename std::decay_t<E>::size_type;
|
||||
return return_type(std::forward<E>(e), size_type(e.shape()[0]));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
412
vendor/xtensor/include/xtensor/xbroadcast.hpp
vendored
Normal file
412
vendor/xtensor/include/xtensor/xbroadcast.hpp
vendored
Normal file
|
|
@ -0,0 +1,412 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTENSOR_BROADCAST_HPP
|
||||
#define XTENSOR_BROADCAST_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <numeric>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include <xtl/xsequence.hpp>
|
||||
|
||||
#include "xexpression.hpp"
|
||||
#include "xiterable.hpp"
|
||||
#include "xscalar.hpp"
|
||||
#include "xstrides.hpp"
|
||||
#include "xutils.hpp"
|
||||
|
||||
namespace xt
|
||||
{
|
||||
|
||||
/*************
|
||||
* broadcast *
|
||||
*************/
|
||||
|
||||
template <class E, class S>
|
||||
auto broadcast(E&& e, const S& s);
|
||||
|
||||
#ifdef X_OLD_CLANG
|
||||
template <class E, class I>
|
||||
auto broadcast(E&& e, std::initializer_list<I> s);
|
||||
#else
|
||||
template <class E, class I, std::size_t L>
|
||||
auto broadcast(E&& e, const I (&s)[L]);
|
||||
#endif
|
||||
|
||||
/**************
|
||||
* xbroadcast *
|
||||
**************/
|
||||
|
||||
template <class CT, class X>
|
||||
class xbroadcast;
|
||||
|
||||
template <class CT, class X>
|
||||
struct xiterable_inner_types<xbroadcast<CT, X>>
|
||||
{
|
||||
using xexpression_type = std::decay_t<CT>;
|
||||
using inner_shape_type = promote_shape_t<typename xexpression_type::shape_type, X>;
|
||||
using const_stepper = typename xexpression_type::const_stepper;
|
||||
using stepper = const_stepper;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class xbroadcast
|
||||
* @brief Broadcasted xexpression to a specified shape.
|
||||
*
|
||||
* The xbroadcast class implements the broadcasting of an \ref xexpression
|
||||
* to a specified shape. xbroadcast is not meant to be used directly, but
|
||||
* only with the \ref broadcast helper functions.
|
||||
*
|
||||
* @tparam CT the closure type of the \ref xexpression to broadcast
|
||||
* @tparam X the type of the specified shape.
|
||||
*
|
||||
* @sa broadcast
|
||||
*/
|
||||
template <class CT, class X>
|
||||
class xbroadcast : public xexpression<xbroadcast<CT, X>>,
|
||||
public xconst_iterable<xbroadcast<CT, X>>
|
||||
{
|
||||
public:
|
||||
|
||||
using self_type = xbroadcast<CT, X>;
|
||||
using xexpression_type = std::decay_t<CT>;
|
||||
|
||||
using value_type = typename xexpression_type::value_type;
|
||||
using reference = typename xexpression_type::reference;
|
||||
using const_reference = typename xexpression_type::const_reference;
|
||||
using pointer = typename xexpression_type::pointer;
|
||||
using const_pointer = typename xexpression_type::const_pointer;
|
||||
using size_type = typename xexpression_type::size_type;
|
||||
using difference_type = typename xexpression_type::difference_type;
|
||||
|
||||
using iterable_base = xconst_iterable<self_type>;
|
||||
using inner_shape_type = typename iterable_base::inner_shape_type;
|
||||
using shape_type = inner_shape_type;
|
||||
|
||||
using stepper = typename iterable_base::stepper;
|
||||
using const_stepper = typename iterable_base::const_stepper;
|
||||
|
||||
static constexpr layout_type static_layout = xexpression_type::static_layout;
|
||||
//static constexpr bool contiguous_layout = xexpression_type::contiguous_layout;
|
||||
static constexpr bool contiguous_layout = false;
|
||||
|
||||
template <class CTA, class S>
|
||||
xbroadcast(CTA&& e, S&& s);
|
||||
|
||||
size_type size() const noexcept;
|
||||
size_type dimension() const noexcept;
|
||||
const inner_shape_type& shape() const noexcept;
|
||||
layout_type layout() const noexcept;
|
||||
|
||||
template <class... Args>
|
||||
const_reference operator()(Args... args) const;
|
||||
|
||||
template <class... Args>
|
||||
const_reference at(Args... args) const;
|
||||
|
||||
template <class... Args>
|
||||
const_reference unchecked(Args... args) const;
|
||||
|
||||
template <class S>
|
||||
disable_integral_t<S, const_reference> operator[](const S& index) const;
|
||||
template <class I>
|
||||
const_reference operator[](std::initializer_list<I> index) const;
|
||||
const_reference operator[](size_type i) const;
|
||||
|
||||
template <class It>
|
||||
const_reference element(It first, It last) const;
|
||||
|
||||
template <class S>
|
||||
bool broadcast_shape(S& shape, bool reuse_cache = false) const;
|
||||
|
||||
template <class S>
|
||||
bool is_trivial_broadcast(const S& strides) const noexcept;
|
||||
|
||||
template <class S>
|
||||
const_stepper stepper_begin(const S& shape) const noexcept;
|
||||
template <class S>
|
||||
const_stepper stepper_end(const S& shape, layout_type l) const noexcept;
|
||||
|
||||
template <class E, class XCT = CT, class = std::enable_if_t<xt::is_xscalar<XCT>::value>>
|
||||
void assign_to(xexpression<E>& e) const;
|
||||
|
||||
private:
|
||||
|
||||
CT m_e;
|
||||
inner_shape_type m_shape;
|
||||
};
|
||||
|
||||
/****************************
|
||||
* broadcast implementation *
|
||||
****************************/
|
||||
|
||||
/**
|
||||
* @brief Returns an \ref xexpression broadcasting the given expression to
|
||||
* a specified shape.
|
||||
*
|
||||
* @tparam e the \ref xexpression to broadcast
|
||||
* @tparam s the specified shape to broadcast.
|
||||
*
|
||||
* The returned expression either hold a const reference to \p e or a copy
|
||||
* depending on whether \p e is an lvalue or an rvalue.
|
||||
*/
|
||||
template <class E, class S>
|
||||
inline auto broadcast(E&& e, const S& s)
|
||||
{
|
||||
using broadcast_type = xbroadcast<const_xclosure_t<E>, S>;
|
||||
using shape_type = typename broadcast_type::shape_type;
|
||||
return broadcast_type(std::forward<E>(e), xtl::forward_sequence<shape_type>(s));
|
||||
}
|
||||
|
||||
#ifdef X_OLD_CLANG
|
||||
template <class E, class I>
|
||||
inline auto broadcast(E&& e, std::initializer_list<I> s)
|
||||
{
|
||||
using broadcast_type = xbroadcast<const_xclosure_t<E>, std::vector<std::size_t>>;
|
||||
using shape_type = typename broadcast_type::shape_type;
|
||||
return broadcast_type(std::forward<E>(e), xtl::forward_sequence<shape_type>(s));
|
||||
}
|
||||
#else
|
||||
template <class E, class I, std::size_t L>
|
||||
inline auto broadcast(E&& e, const I (&s)[L])
|
||||
{
|
||||
using broadcast_type = xbroadcast<const_xclosure_t<E>, std::array<std::size_t, L>>;
|
||||
using shape_type = typename broadcast_type::shape_type;
|
||||
return broadcast_type(std::forward<E>(e), xtl::forward_sequence<shape_type>(s));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************
|
||||
* xbroadcast implementation *
|
||||
*****************************/
|
||||
|
||||
/**
|
||||
* @name Constructor
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* Constructs an xbroadcast expression broadcasting the specified
|
||||
* \ref xexpression to the given shape
|
||||
*
|
||||
* @param e the expression to broadcast
|
||||
* @param s the shape to apply
|
||||
*/
|
||||
template <class CT, class X>
|
||||
template <class CTA, class S>
|
||||
inline xbroadcast<CT, X>::xbroadcast(CTA&& e, S&& s)
|
||||
: m_e(std::forward<CTA>(e)), m_shape(std::forward<S>(s))
|
||||
{
|
||||
xt::broadcast_shape(m_e.shape(), m_shape);
|
||||
}
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @name Size and shape
|
||||
*/
|
||||
/**
|
||||
* Returns the size of the expression.
|
||||
*/
|
||||
template <class CT, class X>
|
||||
inline auto xbroadcast<CT, X>::size() const noexcept -> size_type
|
||||
{
|
||||
return compute_size(shape());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of dimensions of the expression.
|
||||
*/
|
||||
template <class CT, class X>
|
||||
inline auto xbroadcast<CT, X>::dimension() const noexcept -> size_type
|
||||
{
|
||||
return m_shape.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the shape of the expression.
|
||||
*/
|
||||
template <class CT, class X>
|
||||
inline auto xbroadcast<CT, X>::shape() const noexcept -> const inner_shape_type&
|
||||
{
|
||||
return m_shape;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the layout_type of the expression.
|
||||
*/
|
||||
template <class CT, class X>
|
||||
inline layout_type xbroadcast<CT, X>::layout() const noexcept
|
||||
{
|
||||
return m_e.layout();
|
||||
}
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @name Data
|
||||
*/
|
||||
/**
|
||||
* Returns a constant reference to the element at the specified position in the expression.
|
||||
* @param args a list of indices specifying the position in the function. Indices
|
||||
* must be unsigned integers, the number of indices should be equal or greater than
|
||||
* the number of dimensions of the expression.
|
||||
*/
|
||||
template <class CT, class X>
|
||||
template <class... Args>
|
||||
inline auto xbroadcast<CT, X>::operator()(Args... args) const -> const_reference
|
||||
{
|
||||
return m_e(args...);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a constant reference to the element at the specified position in the expression,
|
||||
* after dimension and bounds checking.
|
||||
* @param args a list of indices specifying the position in the function. Indices
|
||||
* must be unsigned integers, the number of indices should be equal to the number of dimensions
|
||||
* of the expression.
|
||||
* @exception std::out_of_range if the number of argument is greater than the number of dimensions
|
||||
* or if indices are out of bounds.
|
||||
*/
|
||||
template <class CT, class X>
|
||||
template <class... Args>
|
||||
inline auto xbroadcast<CT, X>::at(Args... args) const -> const_reference
|
||||
{
|
||||
check_access(shape(), static_cast<size_type>(args)...);
|
||||
return this->operator()(args...);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a constant reference to the element at the specified position in the expression.
|
||||
* @param args a list of indices specifying the position in the expression. Indices
|
||||
* must be unsigned integers, the number of indices must be equal to the number of
|
||||
* dimensions of the expression, else the behavior is undefined.
|
||||
*
|
||||
* @warning This method is meant for performance, for expressions with a dynamic
|
||||
* number of dimensions (i.e. not known at compile time). Since it may have
|
||||
* undefined behavior (see parameters), operator() should be prefered whenever
|
||||
* it is possible.
|
||||
* @warning This method is NOT compatible with broadcasting, meaning the following
|
||||
* code has undefined behavior:
|
||||
* \code{.cpp}
|
||||
* xt::xarray<double> a = {{0, 1}, {2, 3}};
|
||||
* xt::xarray<double> b = {0, 1};
|
||||
* auto fd = a + b;
|
||||
* double res = fd.uncheked(0, 1);
|
||||
* \endcode
|
||||
*/
|
||||
template <class CT, class X>
|
||||
template <class... Args>
|
||||
inline auto xbroadcast<CT, X>::unchecked(Args... args) const -> const_reference
|
||||
{
|
||||
return this->operator()(args...);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a constant reference to the element at the specified position in the expression.
|
||||
* @param index a sequence of indices specifying the position in the function. Indices
|
||||
* must be unsigned integers, the number of indices in the sequence should be equal or greater
|
||||
* than the number of dimensions of the container.
|
||||
*/
|
||||
template <class CT, class X>
|
||||
template <class S>
|
||||
inline auto xbroadcast<CT, X>::operator[](const S& index) const
|
||||
-> disable_integral_t<S, const_reference>
|
||||
{
|
||||
return element(index.cbegin(), index.cend());
|
||||
}
|
||||
|
||||
template <class CT, class X>
|
||||
template <class I>
|
||||
inline auto xbroadcast<CT, X>::operator[](std::initializer_list<I> index) const -> const_reference
|
||||
{
|
||||
return element(index.begin(), index.end());
|
||||
}
|
||||
|
||||
template <class CT, class X>
|
||||
inline auto xbroadcast<CT, X>::operator[](size_type i) const -> const_reference
|
||||
{
|
||||
return operator()(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a constant reference to the element at the specified position in the expression.
|
||||
* @param first iterator starting the sequence of indices
|
||||
* @param last iterator ending the sequence of indices
|
||||
* The number of indices in the sequence should be equal to or greater
|
||||
* than the number of dimensions of the function.
|
||||
*/
|
||||
template <class CT, class X>
|
||||
template <class It>
|
||||
inline auto xbroadcast<CT, X>::element(It, It last) const -> const_reference
|
||||
{
|
||||
return m_e.element(last - dimension(), last);
|
||||
}
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @name Broadcasting
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* Broadcast the shape of the function to the specified parameter.
|
||||
* @param shape the result shape
|
||||
* @param reuse_cache parameter for internal optimization
|
||||
* @return a boolean indicating whether the broadcasting is trivial
|
||||
*/
|
||||
template <class CT, class X>
|
||||
template <class S>
|
||||
inline bool xbroadcast<CT, X>::broadcast_shape(S& shape, bool) const
|
||||
{
|
||||
return xt::broadcast_shape(m_shape, shape);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the specified strides with those of the container to see whether
|
||||
* the broadcasting is trivial.
|
||||
* @return a boolean indicating whether the broadcasting is trivial
|
||||
*/
|
||||
template <class CT, class X>
|
||||
template <class S>
|
||||
inline bool xbroadcast<CT, X>::is_trivial_broadcast(const S& strides) const noexcept
|
||||
{
|
||||
return dimension() == m_e.dimension() &&
|
||||
std::equal(m_shape.cbegin(), m_shape.cend(), m_e.shape().cbegin()) &&
|
||||
m_e.is_trivial_broadcast(strides);
|
||||
}
|
||||
//@}
|
||||
|
||||
template <class CT, class X>
|
||||
template <class S>
|
||||
inline auto xbroadcast<CT, X>::stepper_begin(const S& shape) const noexcept -> const_stepper
|
||||
{
|
||||
// Could check if (broadcastable(shape, m_shape)
|
||||
return m_e.stepper_begin(shape);
|
||||
}
|
||||
|
||||
template <class CT, class X>
|
||||
template <class S>
|
||||
inline auto xbroadcast<CT, X>::stepper_end(const S& shape, layout_type l) const noexcept -> const_stepper
|
||||
{
|
||||
// Could check if (broadcastable(shape, m_shape)
|
||||
return m_e.stepper_end(shape, l);
|
||||
}
|
||||
|
||||
template <class CT, class X>
|
||||
template <class E, class XCT, class>
|
||||
inline void xbroadcast<CT, X>::assign_to(xexpression<E>& e) const
|
||||
{
|
||||
auto& ed = e.derived_cast();
|
||||
ed.resize(m_shape);
|
||||
std::fill(ed.begin(), ed.end(), m_e());
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
623
vendor/xtensor/include/xtensor/xbuffer_adaptor.hpp
vendored
Normal file
623
vendor/xtensor/include/xtensor/xbuffer_adaptor.hpp
vendored
Normal file
|
|
@ -0,0 +1,623 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTENSOR_BUFFER_ADAPTOR_HPP
|
||||
#define XTENSOR_BUFFER_ADAPTOR_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <xtl/xclosure.hpp>
|
||||
|
||||
#include "xstorage.hpp"
|
||||
|
||||
namespace xt
|
||||
{
|
||||
/******************************
|
||||
* xbuffer_adator declaration *
|
||||
******************************/
|
||||
|
||||
struct no_ownership
|
||||
{
|
||||
};
|
||||
|
||||
struct acquire_ownership
|
||||
{
|
||||
};
|
||||
|
||||
template <class CP, class O = no_ownership, class A = std::allocator<std::remove_pointer_t<std::remove_reference_t<CP>>>>
|
||||
class xbuffer_adaptor;
|
||||
|
||||
/*********************************
|
||||
* xbuffer_adator implementation *
|
||||
*********************************/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class CP, class A>
|
||||
class xbuffer_storage
|
||||
{
|
||||
public:
|
||||
|
||||
using self_type = xbuffer_storage<CP, A>;
|
||||
using allocator_type = A;
|
||||
using value_type = typename allocator_type::value_type;
|
||||
using reference = std::conditional_t<std::is_const<std::remove_pointer_t<std::remove_reference_t<CP>>>::value,
|
||||
typename allocator_type::const_reference,
|
||||
typename allocator_type::reference>;
|
||||
using const_reference = typename allocator_type::const_reference;
|
||||
using pointer = std::conditional_t<std::is_const<std::remove_pointer_t<std::remove_reference_t<CP>>>::value,
|
||||
typename allocator_type::const_pointer,
|
||||
typename allocator_type::pointer>;
|
||||
using const_pointer = typename allocator_type::const_pointer;
|
||||
using size_type = typename allocator_type::size_type;
|
||||
using difference_type = typename allocator_type::difference_type;
|
||||
|
||||
xbuffer_storage();
|
||||
|
||||
template <class P>
|
||||
xbuffer_storage(P&& data, size_type size, const allocator_type& alloc = allocator_type());
|
||||
|
||||
size_type size() const noexcept;
|
||||
void resize(size_type size);
|
||||
|
||||
pointer data() noexcept;
|
||||
const_pointer data() const noexcept;
|
||||
|
||||
void swap(self_type& rhs) noexcept;
|
||||
|
||||
private:
|
||||
|
||||
pointer p_data;
|
||||
size_type m_size;
|
||||
};
|
||||
|
||||
template <class CP, class A>
|
||||
class xbuffer_owner_storage
|
||||
{
|
||||
public:
|
||||
|
||||
using self_type = xbuffer_owner_storage<CP, A>;
|
||||
using allocator_type = A;
|
||||
using value_type = typename allocator_type::value_type;
|
||||
using reference = std::conditional_t<std::is_const<std::remove_pointer_t<std::remove_reference_t<CP>>>::value,
|
||||
typename allocator_type::const_reference,
|
||||
typename allocator_type::reference>;
|
||||
using const_reference = typename allocator_type::const_reference;
|
||||
using pointer = std::conditional_t<std::is_const<std::remove_pointer_t<std::remove_reference_t<CP>>>::value,
|
||||
typename allocator_type::const_pointer,
|
||||
typename allocator_type::pointer>;
|
||||
using const_pointer = typename allocator_type::const_pointer;
|
||||
using size_type = typename allocator_type::size_type;
|
||||
using difference_type = typename allocator_type::difference_type;
|
||||
|
||||
xbuffer_owner_storage() = default;
|
||||
|
||||
template <class P>
|
||||
xbuffer_owner_storage(P&& data, size_type size, const allocator_type& alloc = allocator_type());
|
||||
|
||||
~xbuffer_owner_storage();
|
||||
|
||||
xbuffer_owner_storage(const self_type&) = delete;
|
||||
self_type& operator=(const self_type&);
|
||||
|
||||
xbuffer_owner_storage(self_type&&);
|
||||
self_type& operator=(self_type&&);
|
||||
|
||||
size_type size() const noexcept;
|
||||
void resize(size_type size);
|
||||
|
||||
pointer data() noexcept;
|
||||
const_pointer data() const noexcept;
|
||||
|
||||
allocator_type get_allocator() const noexcept;
|
||||
|
||||
void swap(self_type& rhs) noexcept;
|
||||
|
||||
private:
|
||||
|
||||
xtl::xclosure_wrapper<CP> m_data;
|
||||
size_type m_size;
|
||||
bool m_moved_from;
|
||||
allocator_type m_allocator;
|
||||
};
|
||||
|
||||
template <class CP, class A, class O>
|
||||
struct get_buffer_storage
|
||||
{
|
||||
using type = xbuffer_storage<CP, A>;
|
||||
};
|
||||
|
||||
template <class CP, class A>
|
||||
struct get_buffer_storage<CP, A, acquire_ownership>
|
||||
{
|
||||
using type = xbuffer_owner_storage<CP, A>;
|
||||
};
|
||||
|
||||
template <class CP, class A, class O>
|
||||
using buffer_storage_t = typename get_buffer_storage<CP, A, O>::type;
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
class xbuffer_adaptor : private detail::buffer_storage_t<CP, A, O>
|
||||
{
|
||||
public:
|
||||
|
||||
using base_type = detail::buffer_storage_t<CP, A, O>;
|
||||
using self_type = xbuffer_adaptor<CP, O, A>;
|
||||
using allocator_type = typename base_type::allocator_type;
|
||||
using value_type = typename base_type::value_type;
|
||||
using reference = typename base_type::reference;
|
||||
using const_reference = typename base_type::const_reference;
|
||||
using pointer = typename base_type::pointer;
|
||||
using const_pointer = typename base_type::const_pointer;
|
||||
using temporary_type = uvector<value_type, allocator_type>;
|
||||
|
||||
using size_type = typename base_type::size_type;
|
||||
using difference_type = typename base_type::difference_type;
|
||||
|
||||
using iterator = pointer;
|
||||
using const_iterator = const_pointer;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
xbuffer_adaptor() = default;
|
||||
|
||||
template <class P>
|
||||
xbuffer_adaptor(P&& data, size_type size, const allocator_type& alloc = allocator_type());
|
||||
|
||||
~xbuffer_adaptor() = default;
|
||||
|
||||
xbuffer_adaptor(const self_type&) = default;
|
||||
self_type& operator=(const self_type&) = default;
|
||||
|
||||
xbuffer_adaptor(self_type&&) = default;
|
||||
xbuffer_adaptor& operator=(self_type&&) = default;
|
||||
|
||||
self_type& operator=(temporary_type&&);
|
||||
|
||||
bool empty() const noexcept;
|
||||
using base_type::size;
|
||||
using base_type::resize;
|
||||
|
||||
reference operator[](size_type i);
|
||||
const_reference operator[](size_type i) const;
|
||||
|
||||
reference front();
|
||||
const_reference front() const;
|
||||
|
||||
reference back();
|
||||
const_reference back() const;
|
||||
|
||||
iterator begin();
|
||||
iterator end();
|
||||
|
||||
const_iterator begin() const;
|
||||
const_iterator end() const;
|
||||
const_iterator cbegin() const;
|
||||
const_iterator cend() const;
|
||||
|
||||
reverse_iterator rbegin();
|
||||
reverse_iterator rend();
|
||||
|
||||
const_reverse_iterator rbegin() const;
|
||||
const_reverse_iterator rend() const;
|
||||
const_reverse_iterator crbegin() const;
|
||||
const_reverse_iterator crend() const;
|
||||
|
||||
using base_type::data;
|
||||
using base_type::swap;
|
||||
};
|
||||
|
||||
template <class CP, class O, class A>
|
||||
bool operator==(const xbuffer_adaptor<CP, O, A>& lhs,
|
||||
const xbuffer_adaptor<CP, O, A>& rhs);
|
||||
|
||||
template <class CP, class O, class A>
|
||||
bool operator!=(const xbuffer_adaptor<CP, O, A>& lhs,
|
||||
const xbuffer_adaptor<CP, O, A>& rhs);
|
||||
|
||||
template <class CP, class O, class A>
|
||||
bool operator<(const xbuffer_adaptor<CP, O, A>& lhs,
|
||||
const xbuffer_adaptor<CP, O, A>& rhs);
|
||||
|
||||
template <class CP, class O, class A>
|
||||
bool operator<=(const xbuffer_adaptor<CP, O, A>& lhs,
|
||||
const xbuffer_adaptor<CP, O, A>& rhs);
|
||||
|
||||
template <class CP, class O, class A>
|
||||
bool operator>(const xbuffer_adaptor<CP, O, A>& lhs,
|
||||
const xbuffer_adaptor<CP, O, A>& rhs);
|
||||
|
||||
template <class CP, class O, class A>
|
||||
bool operator>=(const xbuffer_adaptor<CP, O, A>& lhs,
|
||||
const xbuffer_adaptor<CP, O, A>& rhs);
|
||||
|
||||
template <class CP, class O, class A>
|
||||
void swap(xbuffer_adaptor<CP, O, A>& lhs,
|
||||
xbuffer_adaptor<CP, O, A>& rhs) noexcept;
|
||||
|
||||
/************************************
|
||||
* temporary_container metafunction *
|
||||
************************************/
|
||||
|
||||
template <class C>
|
||||
struct temporary_container
|
||||
{
|
||||
using type = C;
|
||||
};
|
||||
|
||||
template <class CP, class O, class A>
|
||||
struct temporary_container<xbuffer_adaptor<CP, O, A>>
|
||||
{
|
||||
using type = typename xbuffer_adaptor<CP, O, A>::temporary_type;
|
||||
};
|
||||
|
||||
template <class C>
|
||||
using temporary_container_t = typename temporary_container<C>::type;
|
||||
|
||||
/**********************************
|
||||
* xbuffer_storage implementation *
|
||||
**********************************/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class CP, class A>
|
||||
inline xbuffer_storage<CP, A>::xbuffer_storage()
|
||||
: p_data(nullptr), m_size(0)
|
||||
{
|
||||
}
|
||||
|
||||
template <class CP, class A>
|
||||
template <class P>
|
||||
inline xbuffer_storage<CP, A>::xbuffer_storage(P&& data, size_type size, const allocator_type&)
|
||||
: p_data(std::forward<P>(data)), m_size(size)
|
||||
{
|
||||
}
|
||||
|
||||
template <class CP, class A>
|
||||
inline auto xbuffer_storage<CP, A>::size() const noexcept -> size_type
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
template <class CP, class A>
|
||||
inline void xbuffer_storage<CP, A>::resize(size_type size)
|
||||
{
|
||||
if (size != m_size)
|
||||
{
|
||||
throw std::runtime_error("xbuffer_storage not resizable");
|
||||
}
|
||||
}
|
||||
|
||||
template <class CP, class A>
|
||||
inline auto xbuffer_storage<CP, A>::data() noexcept -> pointer
|
||||
{
|
||||
return p_data;
|
||||
}
|
||||
|
||||
template <class CP, class A>
|
||||
inline auto xbuffer_storage<CP, A>::data() const noexcept -> const_pointer
|
||||
{
|
||||
return p_data;
|
||||
}
|
||||
|
||||
template <class CP, class A>
|
||||
inline void xbuffer_storage<CP, A>::swap(self_type& rhs) noexcept
|
||||
{
|
||||
using std::swap;
|
||||
swap(p_data, rhs.p_data);
|
||||
swap(m_size, rhs.m_size);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************
|
||||
* xbuffer_owner_storage implementation *
|
||||
****************************************/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class CP, class A>
|
||||
template <class P>
|
||||
inline xbuffer_owner_storage<CP, A>::xbuffer_owner_storage(P&& data, size_type size, const allocator_type& alloc)
|
||||
: m_data(std::forward<P>(data)), m_size(size), m_moved_from(false), m_allocator(alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class CP, class A>
|
||||
inline xbuffer_owner_storage<CP, A>::~xbuffer_owner_storage()
|
||||
{
|
||||
if (!m_moved_from)
|
||||
{
|
||||
safe_destroy_deallocate(m_allocator, m_data.get(), m_size);
|
||||
m_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <class CP, class A>
|
||||
inline auto xbuffer_owner_storage<CP, A>::operator=(const self_type& rhs) -> self_type&
|
||||
{
|
||||
using std::swap;
|
||||
if (this != &rhs)
|
||||
{
|
||||
allocator_type al = std::allocator_traits<allocator_type>::select_on_container_copy_construction(rhs.get_allocator());
|
||||
pointer tmp = safe_init_allocate(al, rhs.m_size);
|
||||
if (xtrivially_default_constructible<value_type>::value)
|
||||
{
|
||||
std::uninitialized_copy(rhs.m_data.get(), rhs.m_data.get() + rhs.m_size, tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::copy(rhs.m_data.get(), rhs.m_data.get() + rhs.m_size, tmp);
|
||||
}
|
||||
swap(m_data.get(), tmp);
|
||||
m_size = rhs.m_size;
|
||||
swap(m_allocator, al);
|
||||
safe_destroy_deallocate(al, tmp, m_size);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class CP, class A>
|
||||
inline xbuffer_owner_storage<CP, A>::xbuffer_owner_storage(self_type&& rhs)
|
||||
: m_data(std::move(rhs.m_data)), m_size(std::move(rhs.m_size)), m_moved_from(std::move(rhs.m_moved_from)), m_allocator(std::move(rhs.m_allocator))
|
||||
{
|
||||
rhs.m_moved_from = true;
|
||||
rhs.m_size = 0;
|
||||
}
|
||||
|
||||
template <class CP, class A>
|
||||
inline auto xbuffer_owner_storage<CP, A>::operator=(self_type&& rhs) -> self_type&
|
||||
{
|
||||
swap(rhs);
|
||||
rhs.m_moved_from = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class CP, class A>
|
||||
inline auto xbuffer_owner_storage<CP, A>::size() const noexcept -> size_type
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
template <class CP, class A>
|
||||
void xbuffer_owner_storage<CP, A>::resize(size_type size)
|
||||
{
|
||||
using std::swap;
|
||||
if (size != m_size)
|
||||
{
|
||||
pointer tmp = safe_init_allocate(m_allocator, size);
|
||||
swap(m_data.get(), tmp);
|
||||
swap(m_size, size);
|
||||
safe_destroy_deallocate(m_allocator, tmp, size);
|
||||
}
|
||||
}
|
||||
|
||||
template <class CP, class A>
|
||||
inline auto xbuffer_owner_storage<CP, A>::data() noexcept -> pointer
|
||||
{
|
||||
return m_data.get();
|
||||
}
|
||||
|
||||
template <class CP, class A>
|
||||
inline auto xbuffer_owner_storage<CP, A>::data() const noexcept -> const_pointer
|
||||
{
|
||||
return m_data.get();
|
||||
}
|
||||
|
||||
template <class CP, class A>
|
||||
inline auto xbuffer_owner_storage<CP, A>::get_allocator() const noexcept -> allocator_type
|
||||
{
|
||||
return allocator_type(m_allocator);
|
||||
}
|
||||
|
||||
template <class CP, class A>
|
||||
inline void xbuffer_owner_storage<CP, A>::swap(self_type& rhs) noexcept
|
||||
{
|
||||
using std::swap;
|
||||
swap(m_data, rhs.m_data);
|
||||
swap(m_size, rhs.m_size);
|
||||
swap(m_allocator, rhs.m_allocator);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* xbuffer_adaptor implementation *
|
||||
**********************************/
|
||||
|
||||
template <class CP, class O, class A>
|
||||
template <class P>
|
||||
inline xbuffer_adaptor<CP, O, A>::xbuffer_adaptor(P&& data, size_type size, const allocator_type& alloc)
|
||||
: base_type(std::forward<P>(data), size, alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
inline auto xbuffer_adaptor<CP, O, A>::operator=(temporary_type&& tmp) -> self_type&
|
||||
{
|
||||
base_type::resize(tmp.size());
|
||||
std::copy(tmp.cbegin(), tmp.cend(), begin());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
bool xbuffer_adaptor<CP, O, A>::empty() const noexcept
|
||||
{
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
inline auto xbuffer_adaptor<CP, O, A>::operator[](size_type i) -> reference
|
||||
{
|
||||
return data()[i];
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
inline auto xbuffer_adaptor<CP, O, A>::operator[](size_type i) const -> const_reference
|
||||
{
|
||||
return data()[i];
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
inline auto xbuffer_adaptor<CP, O, A>::front() -> reference
|
||||
{
|
||||
return data()[0];
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
inline auto xbuffer_adaptor<CP, O, A>::front() const -> const_reference
|
||||
{
|
||||
return data()[0];
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
inline auto xbuffer_adaptor<CP, O, A>::back() -> reference
|
||||
{
|
||||
return data()[size() - 1];
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
inline auto xbuffer_adaptor<CP, O, A>::back() const -> const_reference
|
||||
{
|
||||
return data()[size() - 1];
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
inline auto xbuffer_adaptor<CP, O, A>::begin() -> iterator
|
||||
{
|
||||
return data();
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
inline auto xbuffer_adaptor<CP, O, A>::end() -> iterator
|
||||
{
|
||||
return data() + size();
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
inline auto xbuffer_adaptor<CP, O, A>::begin() const -> const_iterator
|
||||
{
|
||||
return data();
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
inline auto xbuffer_adaptor<CP, O, A>::end() const -> const_iterator
|
||||
{
|
||||
return data() + size();
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
inline auto xbuffer_adaptor<CP, O, A>::cbegin() const -> const_iterator
|
||||
{
|
||||
return begin();
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
inline auto xbuffer_adaptor<CP, O, A>::cend() const -> const_iterator
|
||||
{
|
||||
return end();
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
inline auto xbuffer_adaptor<CP, O, A>::rbegin() -> reverse_iterator
|
||||
{
|
||||
return reverse_iterator(end());
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
inline auto xbuffer_adaptor<CP, O, A>::rend() -> reverse_iterator
|
||||
{
|
||||
return reverse_iterator(begin());
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
inline auto xbuffer_adaptor<CP, O, A>::rbegin() const -> const_reverse_iterator
|
||||
{
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
inline auto xbuffer_adaptor<CP, O, A>::rend() const -> const_reverse_iterator
|
||||
{
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
inline auto xbuffer_adaptor<CP, O, A>::crbegin() const -> const_reverse_iterator
|
||||
{
|
||||
return rbegin();
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
inline auto xbuffer_adaptor<CP, O, A>::crend() const -> const_reverse_iterator
|
||||
{
|
||||
return rend();
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
inline bool operator==(const xbuffer_adaptor<CP, O, A>& lhs,
|
||||
const xbuffer_adaptor<CP, O, A>& rhs)
|
||||
{
|
||||
return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
inline bool operator!=(const xbuffer_adaptor<CP, O, A>& lhs,
|
||||
const xbuffer_adaptor<CP, O, A>& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
inline bool operator<(const xbuffer_adaptor<CP, O, A>& lhs,
|
||||
const xbuffer_adaptor<CP, O, A>& rhs)
|
||||
{
|
||||
return std::lexicographical_compare(lhs.begin(), lhs.end(),
|
||||
rhs.begin(), rhs.end(),
|
||||
std::less<typename A::value_type>());
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
inline bool operator<=(const xbuffer_adaptor<CP, O, A>& lhs,
|
||||
const xbuffer_adaptor<CP, O, A>& rhs)
|
||||
{
|
||||
return std::lexicographical_compare(lhs.begin(), lhs.end(),
|
||||
rhs.begin(), rhs.end(),
|
||||
std::less_equal<typename A::value_type>());
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
inline bool operator>(const xbuffer_adaptor<CP, O, A>& lhs,
|
||||
const xbuffer_adaptor<CP, O, A>& rhs)
|
||||
{
|
||||
return std::lexicographical_compare(lhs.begin(), lhs.end(),
|
||||
rhs.begin(), rhs.end(),
|
||||
std::greater<typename A::value_type>());
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
inline bool operator>=(const xbuffer_adaptor<CP, O, A>& lhs,
|
||||
const xbuffer_adaptor<CP, O, A>& rhs)
|
||||
{
|
||||
return std::lexicographical_compare(lhs.begin(), lhs.end(),
|
||||
rhs.begin(), rhs.end(),
|
||||
std::greater_equal<typename A::value_type>());
|
||||
}
|
||||
|
||||
template <class CP, class O, class A>
|
||||
inline void swap(xbuffer_adaptor<CP, O, A>& lhs,
|
||||
xbuffer_adaptor<CP, O, A>& rhs) noexcept
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
918
vendor/xtensor/include/xtensor/xbuilder.hpp
vendored
Normal file
918
vendor/xtensor/include/xtensor/xbuilder.hpp
vendored
Normal file
|
|
@ -0,0 +1,918 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief standard mathematical functions for xexpressions
|
||||
*/
|
||||
|
||||
#ifndef XTENSOR_BUILDER_HPP
|
||||
#define XTENSOR_BUILDER_HPP
|
||||
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#ifdef X_OLD_CLANG
|
||||
#include <initializer_list>
|
||||
#endif
|
||||
|
||||
#include <xtl/xclosure.hpp>
|
||||
#include <xtl/xsequence.hpp>
|
||||
|
||||
#include "xbroadcast.hpp"
|
||||
#include "xfunction.hpp"
|
||||
#include "xgenerator.hpp"
|
||||
#include "xoperation.hpp"
|
||||
|
||||
namespace xt
|
||||
{
|
||||
|
||||
/********
|
||||
* ones *
|
||||
********/
|
||||
|
||||
/**
|
||||
* Returns an \ref xexpression containing ones of the specified shape.
|
||||
* @tparam shape the shape of the returned expression.
|
||||
*/
|
||||
template <class T, class S>
|
||||
inline auto ones(S shape) noexcept
|
||||
{
|
||||
return broadcast(T(1), std::forward<S>(shape));
|
||||
}
|
||||
|
||||
#ifdef X_OLD_CLANG
|
||||
template <class T, class I>
|
||||
inline auto ones(std::initializer_list<I> shape) noexcept
|
||||
{
|
||||
return broadcast(T(1), shape);
|
||||
}
|
||||
#else
|
||||
template <class T, class I, std::size_t L>
|
||||
inline auto ones(const I (&shape)[L]) noexcept
|
||||
{
|
||||
return broadcast(T(1), shape);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*********
|
||||
* zeros *
|
||||
*********/
|
||||
|
||||
/**
|
||||
* Returns an \ref xexpression containing zeros of the specified shape.
|
||||
* @tparam shape the shape of the returned expression.
|
||||
*/
|
||||
template <class T, class S>
|
||||
inline auto zeros(S shape) noexcept
|
||||
{
|
||||
return broadcast(T(0), std::forward<S>(shape));
|
||||
}
|
||||
|
||||
#ifdef X_OLD_CLANG
|
||||
template <class T, class I>
|
||||
inline auto zeros(std::initializer_list<I> shape) noexcept
|
||||
{
|
||||
return broadcast(T(0), shape);
|
||||
}
|
||||
#else
|
||||
template <class T, class I, std::size_t L>
|
||||
inline auto zeros(const I (&shape)[L]) noexcept
|
||||
{
|
||||
return broadcast(T(0), shape);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Create a xcontainer (xarray, xtensor or xtensor_fixed) with uninitialized values of
|
||||
* with value_type T and shape. Selects the best container match automatically
|
||||
* from the supplied shape.
|
||||
*
|
||||
* - ``std::vector`` → ``xarray<T>``
|
||||
* - ``std::array`` or ``initializer_list`` → ``xtensor<T, N>``
|
||||
* - ``xshape<N...>`` → ``xtensor_fixed<T, xshape<N...>>``
|
||||
*
|
||||
* @param shape shape of the new xcontainer
|
||||
*/
|
||||
template <class T, layout_type L = XTENSOR_DEFAULT_LAYOUT, class S>
|
||||
inline xarray<T, L> empty(const S& shape)
|
||||
{
|
||||
return xarray<T, L>::from_shape(shape);
|
||||
}
|
||||
|
||||
template <class T, layout_type L = XTENSOR_DEFAULT_LAYOUT, class ST, std::size_t N>
|
||||
inline xtensor<T, N, L> empty(const std::array<ST, N>& shape)
|
||||
{
|
||||
using shape_type = typename xtensor<T, N>::shape_type;
|
||||
return xtensor<T, N, L>(xtl::forward_sequence<shape_type>(shape));
|
||||
}
|
||||
|
||||
#ifndef X_OLD_CLANG
|
||||
template <class T, layout_type L = XTENSOR_DEFAULT_LAYOUT, class I, std::size_t N>
|
||||
inline xtensor<T, N, L> empty(const I(&shape)[N])
|
||||
{
|
||||
using shape_type = typename xtensor<T, N>::shape_type;
|
||||
return xtensor<T, N, L>(xtl::forward_sequence<shape_type>(shape));
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class T, layout_type L = XTENSOR_DEFAULT_LAYOUT, std::size_t... N>
|
||||
inline xtensor_fixed<T, fixed_shape<N...>, L> empty(const fixed_shape<N...>& /*shape*/)
|
||||
{
|
||||
return xtensor_fixed<T, fixed_shape<N...>, L>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a xcontainer (xarray, xtensor or xtensor_fixed) with uninitialized values of
|
||||
* the same shape, value type and layout as the input xexpression *e*.
|
||||
*
|
||||
* @param e the xexpression from which to extract shape, value type and layout.
|
||||
*/
|
||||
template <class E>
|
||||
inline typename E::temporary_type empty_like(const xexpression<E>& e)
|
||||
{
|
||||
typename E::temporary_type res(e.derived_cast().shape());
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a xcontainer (xarray, xtensor or xtensor_fixed), filled with *fill_value* and of
|
||||
* the same shape, value type and layout as the input xexpression *e*.
|
||||
*
|
||||
* @param e the xexpression from which to extract shape, value type and layout.
|
||||
* @param fill_value the value used to set each element of the returned xcontainer.
|
||||
*/
|
||||
template <class E>
|
||||
inline typename E::temporary_type full_like(const xexpression<E>& e, typename E::value_type fill_value)
|
||||
{
|
||||
typename E::temporary_type res(e.derived_cast().shape(), fill_value);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a xcontainer (xarray, xtensor or xtensor_fixed), filled with zeros and of
|
||||
* the same shape, value type and layout as the input xexpression *e*.
|
||||
*
|
||||
* Note: contrary to zeros(shape), this function returns a non-lazy, allocated container!
|
||||
* Use ``xt::zeros<double>(e.shape());` for a lazy version.
|
||||
*
|
||||
* @param e the xexpression from which to extract shape, value type and layout.
|
||||
*/
|
||||
template <class E>
|
||||
inline typename E::temporary_type zeros_like(const xexpression<E>& e)
|
||||
{
|
||||
return full_like(e, typename E::value_type(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a xcontainer (xarray, xtensor or xtensor_fixed), filled with ones and of
|
||||
* the same shape, value type and layout as the input xexpression *e*.
|
||||
*
|
||||
* Note: contrary to ones(shape), this function returns a non-lazy, evaluated container!
|
||||
* Use ``xt::ones<double>(e.shape());`` for a lazy version.
|
||||
*
|
||||
* @param e the xexpression from which to extract shape, value type and layout.
|
||||
*/
|
||||
template <class E>
|
||||
inline typename E::temporary_type ones_like(const xexpression<E>& e)
|
||||
{
|
||||
return full_like(e, typename E::value_type(1));
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
class arange_impl
|
||||
{
|
||||
public:
|
||||
|
||||
using value_type = T;
|
||||
|
||||
arange_impl(T start, T stop, T step)
|
||||
: m_start(start), m_stop(stop), m_step(step)
|
||||
{
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
inline T operator()(Args... args) const
|
||||
{
|
||||
return access_impl(args...);
|
||||
}
|
||||
|
||||
template <class It>
|
||||
inline T element(It first, It) const
|
||||
{
|
||||
return m_start + m_step * T(*first);
|
||||
}
|
||||
|
||||
template <class E>
|
||||
inline void assign_to(xexpression<E>& e) const noexcept
|
||||
{
|
||||
auto& de = e.derived_cast();
|
||||
value_type value = m_start;
|
||||
|
||||
for (auto& el : de.storage())
|
||||
{
|
||||
el = value;
|
||||
value += m_step;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
value_type m_start;
|
||||
value_type m_stop;
|
||||
value_type m_step;
|
||||
|
||||
template <class T1, class... Args>
|
||||
inline T access_impl(T1 t, Args...) const
|
||||
{
|
||||
return m_start + m_step * T(t);
|
||||
}
|
||||
|
||||
inline T access_impl() const
|
||||
{
|
||||
return m_start;
|
||||
}
|
||||
};
|
||||
|
||||
template <class F>
|
||||
class fn_impl
|
||||
{
|
||||
public:
|
||||
|
||||
using value_type = typename F::value_type;
|
||||
using size_type = std::size_t;
|
||||
|
||||
fn_impl(F&& f)
|
||||
: m_ft(f)
|
||||
{
|
||||
}
|
||||
|
||||
inline value_type operator()() const
|
||||
{
|
||||
size_type idx[1] = {0ul};
|
||||
return access_impl(std::begin(idx), std::end(idx));
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
inline value_type operator()(Args... args) const
|
||||
{
|
||||
size_type idx[sizeof...(Args)] = {static_cast<size_type>(args)...};
|
||||
return access_impl(std::begin(idx), std::end(idx));
|
||||
}
|
||||
|
||||
template <class It>
|
||||
inline value_type element(It first, It last) const
|
||||
{
|
||||
return access_impl(first, last);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
F m_ft;
|
||||
template <class It>
|
||||
inline value_type access_impl(const It& begin, const It& end) const
|
||||
{
|
||||
return m_ft(begin, end);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class eye_fn
|
||||
{
|
||||
public:
|
||||
|
||||
using value_type = T;
|
||||
|
||||
eye_fn(int k)
|
||||
: m_k(k)
|
||||
{
|
||||
}
|
||||
|
||||
template <class It>
|
||||
inline T operator()(const It& /*begin*/, const It& end) const
|
||||
{
|
||||
using lvalue_type = typename std::iterator_traits<It>::value_type;
|
||||
return *(end - 1) == *(end - 2) + static_cast<lvalue_type>(static_cast<unsigned int>(m_k)) ? T(1) : T(0);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
int m_k;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an array with ones on the diagonal.
|
||||
* @param shape shape of the resulting expression
|
||||
* @param k index of the diagonal. 0 (default) refers to the main diagonal,
|
||||
* a positive value refers to an upper diagonal, and a negative
|
||||
* value to a lower diagonal.
|
||||
* @tparam T value_type of xexpression
|
||||
* @return xgenerator that generates the values on access
|
||||
*/
|
||||
template <class T = bool>
|
||||
inline auto eye(const std::vector<std::size_t>& shape, int k = 0)
|
||||
{
|
||||
return detail::make_xgenerator(detail::fn_impl<detail::eye_fn<T>>(detail::eye_fn<T>(k)), shape);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a (n x n) array with ones on the diagonal.
|
||||
* @param n length of the diagonal.
|
||||
* @param k index of the diagonal. 0 (default) refers to the main diagonal,
|
||||
* a positive value refers to an upper diagonal, and a negative
|
||||
* value to a lower diagonal.
|
||||
* @tparam T value_type of xexpression
|
||||
* @return xgenerator that generates the values on access
|
||||
*/
|
||||
template <class T = bool>
|
||||
inline auto eye(std::size_t n, int k = 0)
|
||||
{
|
||||
return eye<T>({n, n}, k);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates numbers evenly spaced within given half-open interval [start, stop).
|
||||
* @param start start of the interval
|
||||
* @param stop stop of the interval
|
||||
* @param step stepsize
|
||||
* @tparam T value_type of xexpression
|
||||
* @return xgenerator that generates the values on access
|
||||
*/
|
||||
template <class T>
|
||||
inline auto arange(T start, T stop, T step = 1) noexcept
|
||||
{
|
||||
std::size_t shape = static_cast<std::size_t>(std::ceil((stop - start) / step));
|
||||
return detail::make_xgenerator(detail::arange_impl<T>(start, stop, step), {shape});
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate numbers evenly spaced within given half-open interval [0, stop)
|
||||
* with a step size of 1.
|
||||
* @param stop stop of the interval
|
||||
* @tparam T value_type of xexpression
|
||||
* @return xgenerator that generates the values on access
|
||||
*/
|
||||
template <class T>
|
||||
inline auto arange(T stop) noexcept
|
||||
{
|
||||
return arange<T>(T(0), stop, T(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates @a num_samples evenly spaced numbers over given interval
|
||||
* @param start start of interval
|
||||
* @param stop stop of interval
|
||||
* @param num_samples number of samples (defaults to 50)
|
||||
* @param endpoint if true, include endpoint (defaults to true)
|
||||
* @tparam T value_type of xexpression
|
||||
* @return xgenerator that generates the values on access
|
||||
*/
|
||||
template <class T>
|
||||
inline auto linspace(T start, T stop, std::size_t num_samples = 50, bool endpoint = true) noexcept
|
||||
{
|
||||
using fp_type = std::common_type_t<T, double>;
|
||||
fp_type step = fp_type(stop - start) / fp_type(num_samples - (endpoint ? 1 : 0));
|
||||
return cast<T>(detail::make_xgenerator(detail::arange_impl<fp_type>(fp_type(start), fp_type(stop), step), {num_samples}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates @a num_samples numbers evenly spaced on a log scale over given interval
|
||||
* @param start start of interval (pow(base, start) is the first value).
|
||||
* @param stop stop of interval (pow(base, stop) is the final value, except if endpoint = false)
|
||||
* @param num_samples number of samples (defaults to 50)
|
||||
* @param base the base of the log space.
|
||||
* @param endpoint if true, include endpoint (defaults to true)
|
||||
* @tparam T value_type of xexpression
|
||||
* @return xgenerator that generates the values on access
|
||||
*/
|
||||
template <class T>
|
||||
inline auto logspace(T start, T stop, std::size_t num_samples, T base = 10, bool endpoint = true) noexcept
|
||||
{
|
||||
return cast<T>(pow(std::move(base), linspace(start, stop, num_samples, endpoint)));
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class... CT>
|
||||
class concatenate_impl
|
||||
{
|
||||
public:
|
||||
|
||||
using size_type = std::size_t;
|
||||
using value_type = promote_type_t<typename std::decay_t<CT>::value_type...>;
|
||||
|
||||
inline concatenate_impl(std::tuple<CT...>&& t, size_type axis)
|
||||
: m_t(t), m_axis(axis)
|
||||
{
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
inline value_type operator()(Args... args) const
|
||||
{
|
||||
// TODO: avoid memory allocation
|
||||
return access_impl(xindex({static_cast<size_type>(args)...}));
|
||||
}
|
||||
|
||||
template <class It>
|
||||
inline value_type element(It first, It last) const
|
||||
{
|
||||
// TODO: avoid memory allocation
|
||||
return access_impl(xindex(first, last));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
inline value_type access_impl(xindex idx) const
|
||||
{
|
||||
auto match = [this, &idx](auto& arr) {
|
||||
if (idx[this->m_axis] >= arr.shape()[this->m_axis])
|
||||
{
|
||||
idx[this->m_axis] -= arr.shape()[this->m_axis];
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
auto get = [&idx](auto& arr) {
|
||||
return arr[idx];
|
||||
};
|
||||
|
||||
size_type i = 0;
|
||||
for (; i < sizeof...(CT); ++i)
|
||||
{
|
||||
if (apply<bool>(i, match, m_t))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return apply<value_type>(i, get, m_t);
|
||||
}
|
||||
|
||||
std::tuple<CT...> m_t;
|
||||
size_type m_axis;
|
||||
};
|
||||
|
||||
template <class... CT>
|
||||
class stack_impl
|
||||
{
|
||||
public:
|
||||
|
||||
using size_type = std::size_t;
|
||||
using value_type = promote_type_t<typename std::decay_t<CT>::value_type...>;
|
||||
|
||||
inline stack_impl(std::tuple<CT...>&& t, size_type axis)
|
||||
: m_t(t), m_axis(axis)
|
||||
{
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
inline value_type operator()(Args... args) const
|
||||
{
|
||||
// TODO: avoid memory allocation
|
||||
return access_impl(xindex({static_cast<size_type>(args)...}));
|
||||
}
|
||||
|
||||
template <class It>
|
||||
inline value_type element(It first, It last) const
|
||||
{
|
||||
// TODO: avoid memory allocation
|
||||
return access_impl(xindex(first, last));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
inline value_type access_impl(xindex idx) const
|
||||
{
|
||||
auto get_item = [&idx](auto& arr) {
|
||||
return arr[idx];
|
||||
};
|
||||
size_type i = idx[m_axis];
|
||||
idx.erase(idx.begin() + std::ptrdiff_t(m_axis));
|
||||
return apply<value_type>(i, get_item, m_t);
|
||||
}
|
||||
|
||||
const std::tuple<CT...> m_t;
|
||||
const size_type m_axis;
|
||||
};
|
||||
|
||||
template <class CT>
|
||||
class repeat_impl
|
||||
{
|
||||
public:
|
||||
|
||||
using xexpression_type = std::decay_t<CT>;
|
||||
using size_type = typename xexpression_type::size_type;
|
||||
using value_type = typename xexpression_type::value_type;
|
||||
|
||||
template <class CTA>
|
||||
repeat_impl(CTA&& source, size_type axis)
|
||||
: m_source(std::forward<CTA>(source)), m_axis(axis)
|
||||
{
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
value_type operator()(Args... args) const
|
||||
{
|
||||
std::array<size_type, sizeof...(Args)> args_arr = {static_cast<size_type>(args)...};
|
||||
return m_source(args_arr[m_axis]);
|
||||
}
|
||||
|
||||
template <class It>
|
||||
inline value_type element(It first, It) const
|
||||
{
|
||||
return m_source(*(first + static_cast<std::ptrdiff_t>(m_axis)));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
CT m_source;
|
||||
size_type m_axis;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates tuples from arguments for \ref concatenate and \ref stack.
|
||||
* Very similar to std::make_tuple.
|
||||
*/
|
||||
template <class... Types>
|
||||
inline auto xtuple(Types&&... args)
|
||||
{
|
||||
return std::tuple<xtl::const_closure_type_t<Types>...>(std::forward<Types>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Concatenates xexpressions along \em axis.
|
||||
*
|
||||
* @param t \ref xtuple of xexpressions to concatenate
|
||||
* @param axis axis along which elements are concatenated
|
||||
* @returns xgenerator evaluating to concatenated elements
|
||||
*
|
||||
* \code{.cpp}
|
||||
* xt::xarray<double> a = {{1, 2, 3}};
|
||||
* xt::xarray<double> b = {{2, 3, 4}};
|
||||
* xt::xarray<double> c = xt::concatenate(xt::xtuple(a, b)); // => {{1, 2, 3},
|
||||
* {2, 3, 4}}
|
||||
* xt::xarray<double> d = xt::concatenate(xt::xtuple(a, b), 1); // => {{1, 2, 3, 2, 3, 4}}
|
||||
* \endcode
|
||||
*/
|
||||
template <class... CT>
|
||||
inline auto concatenate(std::tuple<CT...>&& t, std::size_t axis = 0)
|
||||
{
|
||||
using shape_type = promote_shape_t<typename std::decay_t<CT>::shape_type...>;
|
||||
shape_type new_shape = xtl::forward_sequence<shape_type>(std::get<0>(t).shape());
|
||||
auto shape_at_axis = [&axis](std::size_t prev, auto& arr) -> std::size_t {
|
||||
return prev + arr.shape()[axis];
|
||||
};
|
||||
new_shape[axis] += accumulate(shape_at_axis, std::size_t(0), t) - new_shape[axis];
|
||||
return detail::make_xgenerator(detail::concatenate_impl<CT...>(std::forward<std::tuple<CT...>>(t), axis), new_shape);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T, std::size_t N>
|
||||
inline std::array<T, N + 1> add_axis(std::array<T, N> arr, std::size_t axis, std::size_t value)
|
||||
{
|
||||
std::array<T, N + 1> temp;
|
||||
std::copy(arr.begin(), arr.begin() + axis, temp.begin());
|
||||
temp[axis] = value;
|
||||
std::copy(arr.begin() + axis, arr.end(), temp.begin() + axis + 1);
|
||||
return temp;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T add_axis(T arr, std::size_t axis, std::size_t value)
|
||||
{
|
||||
T temp(arr);
|
||||
temp.insert(temp.begin() + std::ptrdiff_t(axis), value);
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stack xexpressions along \em axis.
|
||||
* Stacking always creates a new dimension along which elements are stacked.
|
||||
*
|
||||
* @param t \ref xtuple of xexpressions to concatenate
|
||||
* @param axis axis along which elements are stacked
|
||||
* @returns xgenerator evaluating to stacked elements
|
||||
*
|
||||
* \code{.cpp}
|
||||
* xt::xarray<double> a = {1, 2, 3};
|
||||
* xt::xarray<double> b = {5, 6, 7};
|
||||
* xt::xarray<double> s = xt::stack(xt::xtuple(a, b)); // => {{1, 2, 3},
|
||||
* {5, 6, 7}}
|
||||
* xt::xarray<double> t = xt::stack(xt::xtuple(a, b), 1); // => {{1, 5},
|
||||
* {2, 6},
|
||||
* {3, 7}}
|
||||
* \endcode
|
||||
*/
|
||||
template <class... CT>
|
||||
inline auto stack(std::tuple<CT...>&& t, std::size_t axis = 0)
|
||||
{
|
||||
using shape_type = promote_shape_t<typename std::decay_t<CT>::shape_type...>;
|
||||
auto new_shape = detail::add_axis(xtl::forward_sequence<shape_type>(std::get<0>(t).shape()), axis, sizeof...(CT));
|
||||
return detail::make_xgenerator(detail::stack_impl<CT...>(std::forward<std::tuple<CT...>>(t), axis), new_shape);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <std::size_t... I, class... E>
|
||||
inline auto meshgrid_impl(std::index_sequence<I...>, E&&... e) noexcept
|
||||
{
|
||||
#if defined X_OLD_CLANG || defined _MSC_VER
|
||||
const std::array<std::size_t, sizeof...(E)> shape = {e.shape()[0]...};
|
||||
return std::make_tuple(
|
||||
detail::make_xgenerator(
|
||||
detail::repeat_impl<xclosure_t<E>>(std::forward<E>(e), I),
|
||||
shape
|
||||
)...
|
||||
);
|
||||
#else
|
||||
return std::make_tuple(
|
||||
detail::make_xgenerator(
|
||||
detail::repeat_impl<xclosure_t<E>>(std::forward<E>(e), I),
|
||||
{e.shape()[0]...}
|
||||
)...
|
||||
);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return coordinate tensors from coordinate vectors.
|
||||
* Make N-D coordinate tensor expressions for vectorized evaluations of N-D scalar/vector
|
||||
* fields over N-D grids, given one-dimensional coordinate arrays x1, x2,..., xn.
|
||||
*
|
||||
* @param e xexpressions to concatenate
|
||||
* @returns tuple of xgenerator expressions.
|
||||
*/
|
||||
template <class... E>
|
||||
inline auto meshgrid(E&&... e) noexcept
|
||||
{
|
||||
return detail::meshgrid_impl(std::make_index_sequence<sizeof...(E)>(), std::forward<E>(e)...);
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class CT>
|
||||
class diagonal_fn
|
||||
{
|
||||
public:
|
||||
|
||||
using xexpression_type = std::decay_t<CT>;
|
||||
using value_type = typename xexpression_type::value_type;
|
||||
|
||||
template <class CTA>
|
||||
diagonal_fn(CTA&& source, int offset, std::size_t axis_1, std::size_t axis_2)
|
||||
: m_source(std::forward<CTA>(source)), m_offset(offset), m_axis_1(axis_1), m_axis_2(axis_2)
|
||||
{
|
||||
}
|
||||
|
||||
template <class It>
|
||||
inline value_type operator()(It begin, It) const
|
||||
{
|
||||
xindex idx(m_source.shape().size());
|
||||
|
||||
for (std::size_t i = 0; i < idx.size(); i++)
|
||||
{
|
||||
if (i != m_axis_1 && i != m_axis_2)
|
||||
{
|
||||
idx[i] = *begin++;
|
||||
}
|
||||
}
|
||||
using it_vtype = typename std::iterator_traits<It>::value_type;
|
||||
it_vtype uoffset = static_cast<it_vtype>(m_offset);
|
||||
if (m_offset >= 0)
|
||||
{
|
||||
idx[m_axis_1] = *(begin);
|
||||
idx[m_axis_2] = *(begin) + uoffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
idx[m_axis_1] = *(begin) - uoffset;
|
||||
idx[m_axis_2] = *(begin);
|
||||
}
|
||||
return m_source[idx];
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
CT m_source;
|
||||
const int m_offset;
|
||||
const std::size_t m_axis_1;
|
||||
const std::size_t m_axis_2;
|
||||
};
|
||||
|
||||
template <class CT>
|
||||
class diag_fn
|
||||
{
|
||||
public:
|
||||
|
||||
using xexpression_type = std::decay_t<CT>;
|
||||
using value_type = typename xexpression_type::value_type;
|
||||
|
||||
template <class CTA>
|
||||
diag_fn(CTA&& source, int k)
|
||||
: m_source(std::forward<CTA>(source)), m_k(k)
|
||||
{
|
||||
}
|
||||
|
||||
template <class It>
|
||||
inline value_type operator()(It begin, It) const
|
||||
{
|
||||
using it_vtype = typename std::iterator_traits<It>::value_type;
|
||||
it_vtype umk = static_cast<it_vtype>(m_k);
|
||||
if (m_k > 0)
|
||||
{
|
||||
return *begin + umk == *(begin + 1) ? m_source(*begin) : value_type(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return *begin + umk == *(begin + 1) ? m_source(*begin + umk) : value_type(0);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
CT m_source;
|
||||
const int m_k;
|
||||
};
|
||||
|
||||
template <class CT, class Comp>
|
||||
class trilu_fn
|
||||
{
|
||||
public:
|
||||
|
||||
using xexpression_type = std::decay_t<CT>;
|
||||
using value_type = typename xexpression_type::value_type;
|
||||
using signed_idx_type = long int;
|
||||
|
||||
template <class CTA>
|
||||
trilu_fn(CTA&& source, int k, Comp comp)
|
||||
: m_source(std::forward<CTA>(source)), m_k(k), m_comp(comp)
|
||||
{
|
||||
}
|
||||
|
||||
template <class It>
|
||||
inline value_type operator()(It begin, It end) const
|
||||
{
|
||||
// have to cast to signed int otherwise -1 can lead to overflow
|
||||
return m_comp(signed_idx_type(*begin) + m_k, signed_idx_type(*(begin + 1))) ? m_source.element(begin, end) : value_type(0);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
CT m_source;
|
||||
const signed_idx_type m_k;
|
||||
const Comp m_comp;
|
||||
};
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// meta-function returning the shape type for a diagonal
|
||||
template <class ST, class... S>
|
||||
struct diagonal_shape_type
|
||||
{
|
||||
using type = ST;
|
||||
};
|
||||
|
||||
template <class I, std::size_t L>
|
||||
struct diagonal_shape_type<std::array<I, L>>
|
||||
{
|
||||
using type = std::array<I, L - 1>;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the elements on the diagonal of arr
|
||||
* If arr has more than two dimensions, then the axes specified by
|
||||
* axis_1 and axis_2 are used to determine the 2-D sub-array whose
|
||||
* diagonal is returned. The shape of the resulting array can be
|
||||
* determined by removing axis1 and axis2 and appending an index
|
||||
* to the right equal to the size of the resulting diagonals.
|
||||
*
|
||||
* @param arr the input array
|
||||
* @param offset offset of the diagonal from the main diagonal. Can
|
||||
* be positive or negative.
|
||||
* @param axis_1 Axis to be used as the first axis of the 2-D sub-arrays
|
||||
* from which the diagonals should be taken.
|
||||
* @param axis_2 Axis to be used as the second axis of the 2-D sub-arrays
|
||||
* from which the diagonals should be taken.
|
||||
* @returns xexpression with values of the diagonal
|
||||
*
|
||||
* \code{.cpp}
|
||||
* xt::xarray<double> a = {{1, 2, 3},
|
||||
* {4, 5, 6}
|
||||
* {7, 8, 9}};
|
||||
* auto b = xt::diagonal(a); // => {1, 5, 9}
|
||||
* \endcode
|
||||
*/
|
||||
template <class E>
|
||||
inline auto diagonal(E&& arr, int offset = 0, std::size_t axis_1 = 0, std::size_t axis_2 = 1)
|
||||
{
|
||||
using CT = xclosure_t<E>;
|
||||
using shape_type = typename detail::diagonal_shape_type<typename std::decay_t<E>::shape_type>::type;
|
||||
|
||||
auto shape = arr.shape();
|
||||
auto dimension = arr.dimension();
|
||||
|
||||
// The following shape calculation code is an almost verbatim adaptation of numpy:
|
||||
// https://github.com/numpy/numpy/blob/2aabeafb97bea4e1bfa29d946fbf31e1104e7ae0/numpy/core/src/multiarray/item_selection.c#L1799
|
||||
auto ret_shape = xtl::make_sequence<shape_type>(dimension - 1, 0);
|
||||
int dim_1 = static_cast<int>(shape[axis_1]);
|
||||
int dim_2 = static_cast<int>(shape[axis_2]);
|
||||
|
||||
offset >= 0 ? dim_2 -= offset : dim_1 += offset;
|
||||
|
||||
auto diag_size = std::size_t(dim_2 < dim_1 ? dim_2 : dim_1);
|
||||
|
||||
std::size_t i = 0;
|
||||
for (std::size_t idim = 0; idim < dimension; ++idim)
|
||||
{
|
||||
if (idim != axis_1 && idim != axis_2)
|
||||
{
|
||||
ret_shape[i++] = shape[idim];
|
||||
}
|
||||
}
|
||||
|
||||
ret_shape.back() = diag_size;
|
||||
|
||||
return detail::make_xgenerator(detail::fn_impl<detail::diagonal_fn<CT>>(detail::diagonal_fn<CT>(std::forward<E>(arr), offset, axis_1, axis_2)),
|
||||
ret_shape);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief xexpression with values of arr on the diagonal, zeroes otherwise
|
||||
*
|
||||
* @param arr the 1D input array of length n
|
||||
* @param k the offset of the considered diagonal
|
||||
* @returns xexpression function with shape n x n and arr on the diagonal
|
||||
*
|
||||
* \code{.cpp}
|
||||
* xt::xarray<double> a = {1, 5, 9};
|
||||
* auto b = xt::diag(a); // => {{1, 0, 0},
|
||||
* // {0, 5, 0},
|
||||
* // {0, 0, 9}}
|
||||
* \endcode
|
||||
*/
|
||||
template <class E>
|
||||
inline auto diag(E&& arr, int k = 0)
|
||||
{
|
||||
using CT = xclosure_t<E>;
|
||||
std::size_t sk = std::size_t(std::abs(k));
|
||||
std::size_t s = arr.shape()[0] + sk;
|
||||
return detail::make_xgenerator(detail::fn_impl<detail::diag_fn<CT>>(detail::diag_fn<CT>(std::forward<E>(arr), k)),
|
||||
{s, s});
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Extract lower triangular matrix from xexpression. The parameter k selects the
|
||||
* offset of the diagonal.
|
||||
*
|
||||
* @param arr the input array
|
||||
* @param k the diagonal above which to zero elements. 0 (default) selects the main diagonal,
|
||||
* k < 0 is below the main diagonal, k > 0 above.
|
||||
* @returns xexpression containing lower triangle from arr, 0 otherwise
|
||||
*/
|
||||
template <class E>
|
||||
inline auto tril(E&& arr, int k = 0)
|
||||
{
|
||||
using CT = xclosure_t<E>;
|
||||
auto shape = arr.shape();
|
||||
return detail::make_xgenerator(detail::fn_impl<detail::trilu_fn<CT, std::greater_equal<long int>>>(
|
||||
detail::trilu_fn<CT, std::greater_equal<long int>>(std::forward<E>(arr), k, std::greater_equal<long int>())),
|
||||
shape);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Extract upper triangular matrix from xexpression. The parameter k selects the
|
||||
* offset of the diagonal.
|
||||
*
|
||||
* @param arr the input array
|
||||
* @param k the diagonal below which to zero elements. 0 (default) selects the main diagonal,
|
||||
* k < 0 is below the main diagonal, k > 0 above.
|
||||
* @returns xexpression containing lower triangle from arr, 0 otherwise
|
||||
*/
|
||||
template <class E>
|
||||
inline auto triu(E&& arr, int k = 0)
|
||||
{
|
||||
using CT = xclosure_t<E>;
|
||||
auto shape = arr.shape();
|
||||
return detail::make_xgenerator(detail::fn_impl<detail::trilu_fn<CT, std::less_equal<long int>>>(
|
||||
detail::trilu_fn<CT, std::less_equal<long int>>(std::forward<E>(arr), k, std::less_equal<long int>())),
|
||||
shape);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
251
vendor/xtensor/include/xtensor/xcomplex.hpp
vendored
Normal file
251
vendor/xtensor/include/xtensor/xcomplex.hpp
vendored
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTENSOR_COMPLEX_HPP
|
||||
#define XTENSOR_COMPLEX_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include <xtl/xcomplex.hpp>
|
||||
|
||||
#include "xtensor/xbuilder.hpp"
|
||||
#include "xtensor/xexpression.hpp"
|
||||
#include "xtensor/xoffset_view.hpp"
|
||||
|
||||
namespace xt
|
||||
{
|
||||
|
||||
/******************************
|
||||
* real and imag declarations *
|
||||
******************************/
|
||||
|
||||
template <class E>
|
||||
decltype(auto) real(E&& e) noexcept;
|
||||
|
||||
template <class E>
|
||||
decltype(auto) imag(E&& e) noexcept;
|
||||
|
||||
/********************************
|
||||
* real and imag implementation *
|
||||
********************************/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <bool iscomplex = true>
|
||||
struct complex_helper
|
||||
{
|
||||
template <class E>
|
||||
static inline auto real(E&& e) noexcept
|
||||
{
|
||||
using real_type = typename std::decay_t<E>::value_type::value_type;
|
||||
return xoffset_view<xclosure_t<E>, real_type, 0>(std::forward<E>(e));
|
||||
}
|
||||
|
||||
template <class E>
|
||||
static inline auto imag(E&& e) noexcept
|
||||
{
|
||||
using real_type = typename std::decay_t<E>::value_type::value_type;
|
||||
return xoffset_view<xclosure_t<E>, real_type, sizeof(real_type)>(std::forward<E>(e));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct complex_helper<false>
|
||||
{
|
||||
template <class E>
|
||||
static inline decltype(auto) real(E&& e) noexcept
|
||||
{
|
||||
return e;
|
||||
}
|
||||
|
||||
template <class E>
|
||||
static inline auto imag(E&& e) noexcept
|
||||
{
|
||||
return zeros<typename std::decay_t<E>::value_type>(e.shape());
|
||||
}
|
||||
};
|
||||
|
||||
template <bool isexpression = true>
|
||||
struct complex_expression_helper
|
||||
{
|
||||
template <class E>
|
||||
static inline auto real(E&& e) noexcept
|
||||
{
|
||||
return detail::complex_helper<xtl::is_complex<typename std::decay_t<E>::value_type>::value>::real(e);
|
||||
}
|
||||
|
||||
template <class E>
|
||||
static inline auto imag(E&& e) noexcept
|
||||
{
|
||||
return detail::complex_helper<xtl::is_complex<typename std::decay_t<E>::value_type>::value>::imag(e);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct complex_expression_helper<false>
|
||||
{
|
||||
template <class E>
|
||||
static inline decltype(auto) real(E&& e) noexcept
|
||||
{
|
||||
return xtl::forward_real(std::forward<E>(e));
|
||||
}
|
||||
|
||||
template <class E>
|
||||
static inline decltype(auto) imag(E&& e) noexcept
|
||||
{
|
||||
return xtl::forward_imag(std::forward<E>(e));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns an \ref xexpression representing the real part of the given expression.
|
||||
*
|
||||
* @tparam e the \ref xexpression
|
||||
*
|
||||
* The returned expression either hold a const reference to \p e or a copy
|
||||
* depending on whether \p e is an lvalue or an rvalue.
|
||||
*/
|
||||
template <class E>
|
||||
inline decltype(auto) real(E&& e) noexcept
|
||||
{
|
||||
return detail::complex_expression_helper<is_xexpression<std::decay_t<E>>::value>::real(std::forward<E>(e));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns an \ref xexpression representing the imaginary part of the given expression.
|
||||
*
|
||||
* @tparam e the \ref xexpression
|
||||
*
|
||||
* The returned expression either hold a const reference to \p e or a copy
|
||||
* depending on whether \p e is an lvalue or an rvalue.
|
||||
*/
|
||||
template <class E>
|
||||
inline decltype(auto) imag(E&& e) noexcept
|
||||
{
|
||||
return detail::complex_expression_helper<is_xexpression<std::decay_t<E>>::value>::imag(std::forward<E>(e));
|
||||
}
|
||||
|
||||
#define UNARY_COMPLEX_FUNCTOR(NAME) \
|
||||
template <class T> \
|
||||
struct NAME##_fun \
|
||||
{ \
|
||||
using argument_type = T; \
|
||||
using result_type = decltype(std::NAME(std::declval<T>())); \
|
||||
constexpr result_type operator()(const T& t) const \
|
||||
{ \
|
||||
using std::NAME; \
|
||||
return NAME(t); \
|
||||
} \
|
||||
}
|
||||
|
||||
namespace math
|
||||
{
|
||||
UNARY_COMPLEX_FUNCTOR(norm);
|
||||
UNARY_COMPLEX_FUNCTOR(arg);
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// libc++ (OSX) conj is unfortunately broken and returns
|
||||
// std::complex<T> instead of T.
|
||||
template <class T>
|
||||
constexpr T conj(const T& c)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
constexpr std::complex<T> conj(const std::complex<T>& c)
|
||||
{
|
||||
return std::complex<T>(c.real(), -c.imag());
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct conj_fun
|
||||
{
|
||||
using argument_type = T;
|
||||
using result_type = decltype(detail::conj(std::declval<T>()));
|
||||
using simd_value_type = xsimd::simd_type<T>;
|
||||
constexpr result_type operator()(const T& t) const
|
||||
{
|
||||
return detail::conj(t);
|
||||
}
|
||||
constexpr simd_value_type simd_apply(const simd_value_type& t) const
|
||||
{
|
||||
return detail::conj(t);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#undef UNARY_COMPLEX_FUNCTOR
|
||||
|
||||
/**
|
||||
* @brief Returns an \ref xfunction evaluating to the complex conjugate of the given expression.
|
||||
*
|
||||
* @param e the \ref xexpression
|
||||
*/
|
||||
template <class E>
|
||||
inline auto conj(E&& e) noexcept
|
||||
{
|
||||
using value_type = typename std::decay_t<E>::value_type;
|
||||
using functor = math::conj_fun<value_type>;
|
||||
using result_type = typename functor::result_type;
|
||||
using type = xfunction<functor, result_type, const_xclosure_t<E>>;
|
||||
return type(functor(), std::forward<E>(e));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculates the phase angle (in radians) elementwise for the complex numbers in e.
|
||||
* @param e the \ref xexpression
|
||||
*/
|
||||
template <class E>
|
||||
inline auto arg(E&& e) noexcept
|
||||
{
|
||||
using value_type = typename std::decay_t<E>::value_type;
|
||||
using functor = math::arg_fun<value_type>;
|
||||
using result_type = typename functor::result_type;
|
||||
using type = xfunction<functor, result_type, const_xclosure_t<E>>;
|
||||
return type(functor(), std::forward<E>(e));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Calculates the phase angle elementwise for the complex numbers in e.
|
||||
* Note that this function might be slightly less perfomant than \ref arg.
|
||||
* @param e the \ref xexpression
|
||||
* @param deg calculate angle in degrees instead of radians
|
||||
*/
|
||||
template <class E>
|
||||
inline auto angle(E&& e, bool deg = false) noexcept
|
||||
{
|
||||
using value_type = xtl::complex_value_type_t<typename std::decay_t<E>::value_type>;
|
||||
value_type multiplier = 1.0;
|
||||
if (deg)
|
||||
{
|
||||
multiplier = value_type(180) / numeric_constants<value_type>::PI;
|
||||
}
|
||||
return arg(std::forward<E>(e)) * std::move(multiplier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the squared magnitude elementwise for the complex numbers in e.
|
||||
* Equivalent to pow(real(e), 2) + pow(imag(e), 2).
|
||||
* @param e the \ref xexpression
|
||||
*/
|
||||
template <class E>
|
||||
inline auto norm(E&& e) noexcept
|
||||
{
|
||||
using value_type = typename std::decay_t<E>::value_type;
|
||||
using functor = math::norm_fun<value_type>;
|
||||
using result_type = typename functor::result_type;
|
||||
using type = xfunction<functor, result_type, const_xclosure_t<E>>;
|
||||
return type(functor(), std::forward<E>(e));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
113
vendor/xtensor/include/xtensor/xconcepts.hpp
vendored
Normal file
113
vendor/xtensor/include/xtensor/xconcepts.hpp
vendored
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2017, Ullrich Koethe *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTENSOR_CONCEPTS_HPP
|
||||
#define XTENSOR_CONCEPTS_HPP
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
/*****************************************************
|
||||
* concept checking and type inference functionality *
|
||||
*****************************************************/
|
||||
|
||||
namespace xt
|
||||
{
|
||||
|
||||
/******************************************
|
||||
* XTENSOR_REQUIRE concept checking macro *
|
||||
******************************************/
|
||||
|
||||
struct concept_check_successful
|
||||
{
|
||||
};
|
||||
|
||||
template <bool CONCEPTS>
|
||||
using concept_check = typename std::enable_if<CONCEPTS, concept_check_successful>::type;
|
||||
|
||||
/** @brief Concept checking macro (more readable than sfinae).
|
||||
|
||||
The macro is used as the last argument in a template declaration.
|
||||
It must be followed by a static boolean expression in angle brackets.
|
||||
The template will only be included in overload resolution when
|
||||
this expression evaluates to 'true'.
|
||||
|
||||
Example:
|
||||
\code
|
||||
template <class T,
|
||||
XTENSOR_REQUIRE<std::is_arithmetic<T>::value>>
|
||||
T foo(T t)
|
||||
{...}
|
||||
\endcode
|
||||
*/
|
||||
#define XTENSOR_REQUIRE typename = concept_check
|
||||
|
||||
/********************
|
||||
* iterator_concept *
|
||||
********************/
|
||||
|
||||
/** @brief Traits class to check if a type is an iterator.
|
||||
|
||||
This is useful in concept checking to make sure that a given template
|
||||
is only instantiated when the argument is an iterator.
|
||||
Currently, we apply the simple rule that class @tparam T
|
||||
is either a pointer or a C-array or has an embedded typedef
|
||||
'iterator_category'. More sophisticated checks can easily
|
||||
be added when needed.
|
||||
|
||||
If @tparam T is indeed an iterator, the class' <tt>value</tt> member
|
||||
is <tt>true</tt>:
|
||||
\code
|
||||
template <class T,
|
||||
XTENSOR_REQUIRE<iterator_concept<T>::value>>
|
||||
T foo(T t)
|
||||
{...}
|
||||
\endcode
|
||||
*/
|
||||
template <class T>
|
||||
struct iterator_concept
|
||||
{
|
||||
using V = std::decay_t<T>;
|
||||
|
||||
static char test(...);
|
||||
|
||||
template <class U>
|
||||
static int test(U*, typename U::iterator_category* = 0);
|
||||
|
||||
static const bool value =
|
||||
std::is_array<T>::value ||
|
||||
std::is_pointer<T>::value ||
|
||||
std::is_same<decltype(test(std::declval<V*>())), int>::value;
|
||||
};
|
||||
|
||||
/** @brief Check if a conversion may loose information.
|
||||
|
||||
@tparam FROM source type
|
||||
@tparam TO target type
|
||||
|
||||
When data is converted from a big type (e.g. <tt>int64_t</tt> or <tt>double</tt>)
|
||||
to a smaller type (e.g. <tt>int32_t</tt>), most compilers issue a 'possible loss of data'
|
||||
warning. This metafunction allows you to detect these situations and take appropriate
|
||||
actions.
|
||||
|
||||
If loss of data may occur, member <tt>is_narrowing_conversion::value</tt> is true. Currently,
|
||||
the check is only implemented for built-in types, i.e. types where <tt>std::is_arithmetic</tt>
|
||||
is true.
|
||||
*/
|
||||
template <class FROM, class TO>
|
||||
struct is_narrowing_conversion
|
||||
{
|
||||
using argument_type = std::decay_t<FROM>;
|
||||
using result_type = std::decay_t<TO>;
|
||||
|
||||
static const bool value = std::is_arithmetic<result_type>::value &&
|
||||
(sizeof(result_type) < sizeof(argument_type) ||
|
||||
(std::is_integral<result_type>::value && std::is_floating_point<argument_type>::value));
|
||||
};
|
||||
} // namespace xt
|
||||
|
||||
#endif // XCONCEPTS_HPP
|
||||
1418
vendor/xtensor/include/xtensor/xcontainer.hpp
vendored
Normal file
1418
vendor/xtensor/include/xtensor/xcontainer.hpp
vendored
Normal file
File diff suppressed because it is too large
Load diff
169
vendor/xtensor/include/xtensor/xcsv.hpp
vendored
Normal file
169
vendor/xtensor/include/xtensor/xcsv.hpp
vendored
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTENSOR_CSV_HPP
|
||||
#define XTENSOR_CSV_HPP
|
||||
|
||||
#include <exception>
|
||||
#include <istream>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "xtensor.hpp"
|
||||
|
||||
namespace xt
|
||||
{
|
||||
|
||||
/**************************************
|
||||
* load_csv and dump_csv declarations *
|
||||
**************************************/
|
||||
|
||||
template <class T, class A = std::allocator<T>>
|
||||
using xcsv_tensor = xtensor_container<std::vector<T, A>, 2, layout_type::row_major>;
|
||||
|
||||
template <class T, class A = std::allocator<T>>
|
||||
xcsv_tensor<T, A> load_csv(std::istream& stream);
|
||||
|
||||
template <class E>
|
||||
void dump_csv(std::ostream& stream, const xexpression<E>& e);
|
||||
|
||||
/*****************************************
|
||||
* load_csv and dump_csv implementations *
|
||||
*****************************************/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
inline T lexical_cast(const std::string& cell)
|
||||
{
|
||||
T res;
|
||||
std::istringstream iss(cell);
|
||||
iss >> res;
|
||||
return res;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline float lexical_cast<float>(const std::string& cell) { return std::stof(cell); }
|
||||
|
||||
template <>
|
||||
inline double lexical_cast<double>(const std::string& cell) { return std::stod(cell); }
|
||||
|
||||
template <>
|
||||
inline long double lexical_cast<long double>(const std::string& cell) { return std::stold(cell); }
|
||||
|
||||
template <>
|
||||
inline int lexical_cast<int>(const std::string& cell) { return std::stoi(cell); }
|
||||
|
||||
template <>
|
||||
inline long lexical_cast<long>(const std::string& cell) { return std::stol(cell); }
|
||||
|
||||
template <>
|
||||
inline long long lexical_cast<long long>(const std::string& cell) { return std::stoll(cell); }
|
||||
|
||||
template <>
|
||||
inline unsigned int lexical_cast<unsigned int>(const std::string& cell) { return static_cast<unsigned int>(std::stoul(cell)); }
|
||||
|
||||
template <>
|
||||
inline unsigned long lexical_cast<unsigned long>(const std::string& cell) { return std::stoul(cell); }
|
||||
|
||||
template <>
|
||||
inline unsigned long long lexical_cast<unsigned long long>(const std::string& cell) { return std::stoull(cell); }
|
||||
|
||||
template <class ST, class T, class OI>
|
||||
ST load_csv_row(std::istream& row_stream, OI output, std::string cell)
|
||||
{
|
||||
ST length = 0;
|
||||
while (std::getline(row_stream, cell, ','))
|
||||
{
|
||||
*output++ = lexical_cast<T>(cell);
|
||||
++length;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Load tensor from CSV.
|
||||
*
|
||||
* Returns an \ref xexpression for the parsed CSV
|
||||
* @param stream the input stream containing the CSV encoded values
|
||||
*/
|
||||
template <class T, class A>
|
||||
xcsv_tensor<T, A> load_csv(std::istream& stream)
|
||||
{
|
||||
using tensor_type = xcsv_tensor<T, A>;
|
||||
using storage_type = typename tensor_type::storage_type;
|
||||
using size_type = typename tensor_type::size_type;
|
||||
using inner_shape_type = typename tensor_type::inner_shape_type;
|
||||
using inner_strides_type = typename tensor_type::inner_strides_type;
|
||||
using output_iterator = std::back_insert_iterator<storage_type>;
|
||||
|
||||
storage_type data;
|
||||
size_type nbrow = 0, nbcol = 0;
|
||||
{
|
||||
output_iterator output(data);
|
||||
std::string row, cell;
|
||||
while (std::getline(stream, row))
|
||||
{
|
||||
std::stringstream row_stream(row);
|
||||
nbcol = detail::load_csv_row<size_type, T, output_iterator>(row_stream, output, cell);
|
||||
++nbrow;
|
||||
}
|
||||
}
|
||||
inner_shape_type shape = {nbrow, nbcol};
|
||||
inner_strides_type strides; // no need for initializer list for stack-allocated strides_type
|
||||
size_type data_size = compute_strides(shape, layout_type::row_major, strides);
|
||||
// Sanity check for data size.
|
||||
if (data.size() != data_size)
|
||||
{
|
||||
throw std::runtime_error("Inconsistent row lengths in CSV");
|
||||
}
|
||||
return tensor_type(std::move(data), std::move(shape), std::move(strides));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Dump tensor to CSV.
|
||||
*
|
||||
* @param stream the output stream to write the CSV encoded values
|
||||
* @param e the tensor expression to serialize
|
||||
*/
|
||||
template <class E>
|
||||
void dump_csv(std::ostream& stream, const xexpression<E>& e)
|
||||
{
|
||||
using size_type = typename E::size_type;
|
||||
const E& ex = e.derived_cast();
|
||||
if (ex.dimension() != 2)
|
||||
{
|
||||
throw std::runtime_error("Only 2-D expressions can be serialized to CSV");
|
||||
}
|
||||
size_type nbrows = ex.shape()[0], nbcols = ex.shape()[1];
|
||||
auto st = ex.stepper_begin(ex.shape());
|
||||
for (size_type r = 0; r != nbrows; ++r)
|
||||
{
|
||||
for (size_type c = 0; c != nbcols; ++c)
|
||||
{
|
||||
stream << *st;
|
||||
if (c != nbcols - 1)
|
||||
{
|
||||
st.step(1);
|
||||
stream << ',';
|
||||
}
|
||||
else
|
||||
{
|
||||
st.reset(1);
|
||||
st.step(0);
|
||||
stream << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
57
vendor/xtensor/include/xtensor/xeval.hpp
vendored
Normal file
57
vendor/xtensor/include/xtensor/xeval.hpp
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTENSOR_EVAL_HPP
|
||||
#define XTENSOR_EVAL_HPP
|
||||
|
||||
#include "xtensor_forward.hpp"
|
||||
|
||||
namespace xt
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class T>
|
||||
using is_container = std::is_base_of<xcontainer<std::remove_const_t<T>>, T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force evaluation of xexpression.
|
||||
* @return xarray or xtensor depending on shape type
|
||||
*
|
||||
* \code{.cpp}
|
||||
* xarray<double> a = {1,2,3,4};
|
||||
* auto&& b = xt::eval(a); // b is a reference to a, no copy!
|
||||
* auto&& c = xt::eval(a + b); // c is xarray<double>, not an xexpression
|
||||
* \endcode
|
||||
*/
|
||||
template <class T>
|
||||
inline auto eval(T&& t)
|
||||
-> std::enable_if_t<detail::is_container<std::decay_t<T>>::value, T&&>
|
||||
{
|
||||
return std::forward<T>(t);
|
||||
}
|
||||
|
||||
/// @cond DOXYGEN_INCLUDE_SFINAE
|
||||
template <class T, class I = std::decay_t<T>>
|
||||
inline auto eval(T&& t)
|
||||
-> std::enable_if_t<!detail::is_container<I>::value && detail::is_array<typename I::shape_type>::value, xtensor<typename I::value_type, std::tuple_size<typename I::shape_type>::value>>
|
||||
{
|
||||
return xtensor<typename I::value_type, std::tuple_size<typename I::shape_type>::value>(std::forward<T>(t));
|
||||
}
|
||||
|
||||
template <class T, class I = std::decay_t<T>>
|
||||
inline auto eval(T&& t)
|
||||
-> std::enable_if_t<!detail::is_container<I>::value && !detail::is_array<typename I::shape_type>::value, xt::xarray<typename I::value_type>>
|
||||
{
|
||||
return xarray<typename I::value_type>(std::forward<T>(t));
|
||||
}
|
||||
/// @endcond
|
||||
}
|
||||
|
||||
#endif
|
||||
219
vendor/xtensor/include/xtensor/xexception.hpp
vendored
Normal file
219
vendor/xtensor/include/xtensor/xexception.hpp
vendored
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTENSOR_EXCEPTION_HPP
|
||||
#define XTENSOR_EXCEPTION_HPP
|
||||
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace xt
|
||||
{
|
||||
|
||||
/*******************
|
||||
* broadcast_error *
|
||||
*******************/
|
||||
|
||||
class broadcast_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
|
||||
explicit broadcast_error(const char* msg)
|
||||
: std::runtime_error(msg)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template <class S1, class S2>
|
||||
[[noreturn]] void throw_broadcast_error(const S1& lhs, const S2& rhs);
|
||||
|
||||
/**********************************
|
||||
* broadcast_error implementation *
|
||||
**********************************/
|
||||
|
||||
#ifdef NDEBUG
|
||||
// Do not inline this function
|
||||
template <class S1, class S2>
|
||||
[[noreturn]] void throw_broadcast_error(const S1&, const S2&)
|
||||
{
|
||||
throw broadcast_error("Incompatible dimension of arrays, compile in DEBUG for more info");
|
||||
}
|
||||
#else
|
||||
template <class S1, class S2>
|
||||
[[noreturn]] void throw_broadcast_error(const S1& lhs, const S2& rhs)
|
||||
{
|
||||
std::ostringstream buf("Incompatible dimension of arrays:", std::ios_base::ate);
|
||||
|
||||
buf << "\n LHS shape = (";
|
||||
using size_type1 = typename S1::value_type;
|
||||
std::ostream_iterator<size_type1> iter1(buf, ", ");
|
||||
std::copy(lhs.cbegin(), lhs.cend(), iter1);
|
||||
|
||||
buf << ")\n RHS shape = (";
|
||||
using size_type2 = typename S2::value_type;
|
||||
std::ostream_iterator<size_type2> iter2(buf, ", ");
|
||||
std::copy(rhs.cbegin(), rhs.cend(), iter2);
|
||||
buf << ")";
|
||||
|
||||
throw broadcast_error(buf.str().c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************
|
||||
* transpose_error *
|
||||
*******************/
|
||||
|
||||
class transpose_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
|
||||
explicit transpose_error(const char* msg)
|
||||
: std::runtime_error(msg)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/***************
|
||||
* check_index *
|
||||
***************/
|
||||
|
||||
template <class S, class... Args>
|
||||
void check_index(const S& shape, Args... args);
|
||||
|
||||
template <class S, class It>
|
||||
void check_element_index(const S& shape, It first, It last);
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class S, std::size_t dim>
|
||||
inline void check_index_impl(const S&)
|
||||
{
|
||||
}
|
||||
|
||||
template <class S, std::size_t dim, class... Args>
|
||||
inline void check_index_impl(const S& shape, std::size_t arg, Args... args)
|
||||
{
|
||||
if (sizeof...(Args) + 1 > shape.size())
|
||||
{
|
||||
check_index_impl<S, dim>(shape, args...);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (arg >= std::size_t(shape[dim]) && shape[dim] != 1)
|
||||
{
|
||||
throw std::out_of_range("index " + std::to_string(arg) + " is out of bounds for axis "
|
||||
+ std::to_string(dim) + " with size " + std::to_string(shape[dim]));
|
||||
}
|
||||
check_index_impl<S, dim + 1>(shape, args...);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class S, class... Args>
|
||||
inline void check_index(const S& shape, Args... args)
|
||||
{
|
||||
using value_type = typename S::value_type;
|
||||
detail::check_index_impl<S, 0>(shape, static_cast<value_type>(args)...);
|
||||
}
|
||||
|
||||
template <class S, class It>
|
||||
inline void check_element_index(const S& shape, It first, It last)
|
||||
{
|
||||
using value_type = typename std::iterator_traits<It>::value_type;
|
||||
auto dst = static_cast<typename S::size_type>(last - first);
|
||||
It efirst = last - static_cast<std::ptrdiff_t>((std::min)(shape.size(), dst));
|
||||
std::size_t axis = 0;
|
||||
while (efirst != last)
|
||||
{
|
||||
if (*efirst >= value_type(shape[axis]) && shape[axis] != 1)
|
||||
{
|
||||
throw std::out_of_range("index " + std::to_string(*efirst) + " is out of bounds for axis "
|
||||
+ std::to_string(axis) + " with size " + std::to_string(shape[axis]));
|
||||
}
|
||||
++efirst, ++axis;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************
|
||||
* check_dimension *
|
||||
*******************/
|
||||
|
||||
template <class S, class... Args>
|
||||
inline void check_dimension(const S& shape, Args...)
|
||||
{
|
||||
if (sizeof...(Args) > shape.size())
|
||||
{
|
||||
throw std::out_of_range("Number of arguments (" + std::to_string(sizeof...(Args)) + ") us greater "
|
||||
+ "than the number of dimensions (" + std::to_string(shape.size()) + ")");
|
||||
}
|
||||
}
|
||||
|
||||
/****************
|
||||
* check_access *
|
||||
****************/
|
||||
|
||||
template <class S, class... Args>
|
||||
inline void check_access(const S& shape, Args... args)
|
||||
{
|
||||
check_dimension(shape, args...);
|
||||
check_index(shape, args...);
|
||||
}
|
||||
|
||||
#ifdef XTENSOR_ENABLE_ASSERT
|
||||
#define XTENSOR_TRY(expr) XTENSOR_TRY_IMPL(expr, __FILE__, __LINE__)
|
||||
#define XTENSOR_TRY_IMPL(expr, file, line) \
|
||||
try \
|
||||
{ \
|
||||
expr; \
|
||||
} \
|
||||
catch (std::exception& e) \
|
||||
{ \
|
||||
throw std::runtime_error(std::string(file) + ':' + std::to_string(line) + ": check failed\n\t" + std::string(e.what())); \
|
||||
}
|
||||
#else
|
||||
#define XTENSOR_TRY(expr)
|
||||
#endif
|
||||
|
||||
#ifdef XTENSOR_ENABLE_ASSERT
|
||||
#define XTENSOR_ASSERT(expr) XTENSOR_ASSERT_IMPL(expr, __FILE__, __LINE__)
|
||||
#define XTENSOR_ASSERT_IMPL(expr, file, line) \
|
||||
if (!(expr)) \
|
||||
{ \
|
||||
throw std::runtime_error(std::string(file) + ':' + std::to_string(line) + ": assertion failed (" #expr ") \n\t"); \
|
||||
}
|
||||
#else
|
||||
#define XTENSOR_ASSERT(expr)
|
||||
#endif
|
||||
|
||||
#ifdef XTENSOR_ENABLE_CHECK_DIMENSION
|
||||
#define XTENSOR_CHECK_DIMENSION(S, ARGS) XTENSOR_TRY(check_dimension(S, ARGS))
|
||||
#else
|
||||
#define XTENSOR_CHECK_DIMENSION(S, ARGS)
|
||||
#endif
|
||||
|
||||
#ifdef XTENSOR_ENABLE_ASSERT
|
||||
#define XTENSOR_ASSERT_MSG(expr, msg) \
|
||||
if (!(expr)) \
|
||||
{ \
|
||||
throw std::runtime_error(std::string("Assertion error!\n") + msg + \
|
||||
"\n " + __FILE__ + '(' + std::to_string(__LINE__) + ")\n"); \
|
||||
}
|
||||
#else
|
||||
#define XTENSOR_ASSERT_MSG(expr, msg)
|
||||
#endif
|
||||
|
||||
#define XTENSOR_PRECONDITION(expr, msg) \
|
||||
if (!(expr)) \
|
||||
{ \
|
||||
throw std::runtime_error(std::string("Precondition violation!\n") + msg + \
|
||||
"\n " + __FILE__ + '(' + std::to_string(__LINE__) + ")\n"); \
|
||||
}
|
||||
}
|
||||
#endif // XEXCEPTION_HPP
|
||||
307
vendor/xtensor/include/xtensor/xexpression.hpp
vendored
Normal file
307
vendor/xtensor/include/xtensor/xexpression.hpp
vendored
Normal file
|
|
@ -0,0 +1,307 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTENSOR_EXPRESSION_HPP
|
||||
#define XTENSOR_EXPRESSION_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include <xtl/xclosure.hpp>
|
||||
#include <xtl/xtype_traits.hpp>
|
||||
|
||||
#include "xshape.hpp"
|
||||
#include "xutils.hpp"
|
||||
|
||||
namespace xt
|
||||
{
|
||||
|
||||
/***************************
|
||||
* xexpression declaration *
|
||||
***************************/
|
||||
|
||||
/**
|
||||
* @class xexpression
|
||||
* @brief Base class for xexpressions
|
||||
*
|
||||
* The xexpression class is the base class for all classes representing an expression
|
||||
* that can be evaluated to a multidimensional container with tensor semantic.
|
||||
* Functions that can apply to any xexpression regardless of its specific type should take a
|
||||
* xexpression argument.
|
||||
*
|
||||
* \tparam E The derived type.
|
||||
*
|
||||
*/
|
||||
template <class D>
|
||||
class xexpression
|
||||
{
|
||||
public:
|
||||
|
||||
using derived_type = D;
|
||||
|
||||
derived_type& derived_cast() & noexcept;
|
||||
const derived_type& derived_cast() const & noexcept;
|
||||
derived_type derived_cast() && noexcept;
|
||||
|
||||
protected:
|
||||
|
||||
xexpression() = default;
|
||||
~xexpression() = default;
|
||||
|
||||
xexpression(const xexpression&) = default;
|
||||
xexpression& operator=(const xexpression&) = default;
|
||||
|
||||
xexpression(xexpression&&) = default;
|
||||
xexpression& operator=(xexpression&&) = default;
|
||||
};
|
||||
|
||||
/******************************
|
||||
* xexpression implementation *
|
||||
******************************/
|
||||
|
||||
/**
|
||||
* @name Downcast functions
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* Returns a reference to the actual derived type of the xexpression.
|
||||
*/
|
||||
template <class D>
|
||||
inline auto xexpression<D>::derived_cast() & noexcept -> derived_type&
|
||||
{
|
||||
return *static_cast<derived_type*>(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a constant reference to the actual derived type of the xexpression.
|
||||
*/
|
||||
template <class D>
|
||||
inline auto xexpression<D>::derived_cast() const & noexcept -> const derived_type&
|
||||
{
|
||||
return *static_cast<const derived_type*>(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a constant reference to the actual derived type of the xexpression.
|
||||
*/
|
||||
template <class D>
|
||||
inline auto xexpression<D>::derived_cast() && noexcept -> derived_type
|
||||
{
|
||||
return *static_cast<derived_type*>(this);
|
||||
}
|
||||
//@}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class E>
|
||||
struct is_xexpression_impl : std::is_base_of<xexpression<std::decay_t<E>>, std::decay_t<E>>
|
||||
{
|
||||
};
|
||||
|
||||
template <class E>
|
||||
struct is_xexpression_impl<xexpression<E>> : std::true_type
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
template <class E>
|
||||
using is_xexpression = detail::is_xexpression_impl<E>;
|
||||
|
||||
template <class E, class R = void>
|
||||
using enable_xexpression = typename std::enable_if<is_xexpression<E>::value, R>::type;
|
||||
|
||||
template <class E, class R = void>
|
||||
using disable_xexpression = typename std::enable_if<!is_xexpression<E>::value, R>::type;
|
||||
|
||||
template <class... E>
|
||||
using has_xexpression = xtl::disjunction<is_xexpression<E>...>;
|
||||
|
||||
/************
|
||||
* xclosure *
|
||||
************/
|
||||
|
||||
template <class T>
|
||||
class xscalar;
|
||||
|
||||
template <class E, class EN = void>
|
||||
struct xclosure
|
||||
{
|
||||
using type = xtl::closure_type_t<E>;
|
||||
};
|
||||
|
||||
template <class E>
|
||||
struct xclosure<E, disable_xexpression<std::decay_t<E>>>
|
||||
{
|
||||
using type = xscalar<xtl::closure_type_t<E>>;
|
||||
};
|
||||
|
||||
template <class E>
|
||||
using xclosure_t = typename xclosure<E>::type;
|
||||
|
||||
template <class E, class EN = void>
|
||||
struct const_xclosure
|
||||
{
|
||||
using type = xtl::const_closure_type_t<E>;
|
||||
};
|
||||
|
||||
template <class E>
|
||||
struct const_xclosure<E, disable_xexpression<std::decay_t<E>>>
|
||||
{
|
||||
using type = xscalar<xtl::const_closure_type_t<E>>;
|
||||
};
|
||||
|
||||
template <class E>
|
||||
using const_xclosure_t = typename const_xclosure<E>::type;
|
||||
|
||||
/***************
|
||||
* xvalue_type *
|
||||
***************/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class E, class enable = void>
|
||||
struct xvalue_type_impl
|
||||
{
|
||||
using type = E;
|
||||
};
|
||||
|
||||
template <class E>
|
||||
struct xvalue_type_impl<E, std::enable_if_t<is_xexpression<E>::value>>
|
||||
{
|
||||
using type = typename E::value_type;
|
||||
};
|
||||
}
|
||||
|
||||
template <class E>
|
||||
using xvalue_type = detail::xvalue_type_impl<E>;
|
||||
|
||||
template <class E>
|
||||
using xvalue_type_t = typename xvalue_type<E>::type;
|
||||
|
||||
/*************************
|
||||
* expression tag system *
|
||||
*************************/
|
||||
|
||||
struct xscalar_expression_tag
|
||||
{
|
||||
};
|
||||
|
||||
struct xtensor_expression_tag
|
||||
{
|
||||
};
|
||||
|
||||
struct xoptional_expression_tag
|
||||
{
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class E, class = void_t<int>>
|
||||
struct get_expression_tag
|
||||
{
|
||||
using type = xtensor_expression_tag;
|
||||
};
|
||||
|
||||
template <class E>
|
||||
struct get_expression_tag<E, void_t<typename std::decay_t<E>::expression_tag>>
|
||||
{
|
||||
using type = typename std::decay_t<E>::expression_tag;
|
||||
};
|
||||
|
||||
template <class E>
|
||||
using get_expression_tag_t = typename get_expression_tag<E>::type;
|
||||
|
||||
template <class... T>
|
||||
struct expression_tag_and;
|
||||
|
||||
template <class T>
|
||||
struct expression_tag_and<T>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct expression_tag_and<T, T>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct expression_tag_and<xscalar_expression_tag, xscalar_expression_tag>
|
||||
{
|
||||
using type = xscalar_expression_tag;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct expression_tag_and<xscalar_expression_tag, T>
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct expression_tag_and<T, xscalar_expression_tag>
|
||||
: expression_tag_and<xscalar_expression_tag, T>
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct expression_tag_and<xtensor_expression_tag, xoptional_expression_tag>
|
||||
{
|
||||
using type = xoptional_expression_tag;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct expression_tag_and<xoptional_expression_tag, xtensor_expression_tag>
|
||||
: expression_tag_and<xtensor_expression_tag, xoptional_expression_tag>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T1, class... T>
|
||||
struct expression_tag_and<T1, T...>
|
||||
: expression_tag_and<T1, typename expression_tag_and<T...>::type>
|
||||
{
|
||||
};
|
||||
|
||||
template <class... T>
|
||||
using expression_tag_and_t = typename expression_tag_and<T...>::type;
|
||||
}
|
||||
|
||||
template <class... T>
|
||||
struct xexpression_tag
|
||||
{
|
||||
using type = detail::expression_tag_and_t<detail::get_expression_tag_t<std::decay_t<const_xclosure_t<T>>>...>;
|
||||
};
|
||||
|
||||
template <class... T>
|
||||
using xexpression_tag_t = typename xexpression_tag<T...>::type;
|
||||
|
||||
template <class E>
|
||||
struct is_xtensor_expression : std::is_same<xexpression_tag_t<E>, xtensor_expression_tag>
|
||||
{
|
||||
};
|
||||
|
||||
template <class E>
|
||||
struct is_xoptional_expression : std::is_same<xexpression_tag_t<E>, xoptional_expression_tag>
|
||||
{
|
||||
};
|
||||
|
||||
/********************************
|
||||
* xoptional_comparable concept *
|
||||
********************************/
|
||||
|
||||
template <class... E>
|
||||
struct xoptional_comparable : xtl::conjunction<xtl::disjunction<is_xtensor_expression<E>,
|
||||
is_xoptional_expression<E>
|
||||
>...
|
||||
>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
818
vendor/xtensor/include/xtensor/xfixed.hpp
vendored
Normal file
818
vendor/xtensor/include/xtensor/xfixed.hpp
vendored
Normal file
|
|
@ -0,0 +1,818 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTENSOR_FIXED_HPP
|
||||
#define XTENSOR_FIXED_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "xcontainer.hpp"
|
||||
#include "xstrides.hpp"
|
||||
#include "xstorage.hpp"
|
||||
#include "xsemantic.hpp"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define XTENSOR_CONSTEXPR_ENHANCED const
|
||||
#define XTENSOR_CONSTEXPR_ENHANCED_STATIC const
|
||||
#define XTENSOR_CONSTEXPR_RETURN
|
||||
#else
|
||||
#define XTENSOR_CONSTEXPR_ENHANCED constexpr
|
||||
#define XTENSOR_CONSTEXPR_RETURN constexpr
|
||||
#define XTENSOR_CONSTEXPR_ENHANCED_STATIC constexpr static
|
||||
#define XTENSOR_HAS_CONSTEXPR_ENHANCED
|
||||
#endif
|
||||
|
||||
namespace xt
|
||||
{
|
||||
/**
|
||||
* @class fixed_shape
|
||||
* Fixed shape implementation for compile time defined arrays.
|
||||
* @sa xshape
|
||||
*/
|
||||
template <std::size_t... X>
|
||||
class fixed_shape
|
||||
{
|
||||
public:
|
||||
|
||||
using cast_type = const_array<std::size_t, sizeof...(X)>;
|
||||
|
||||
constexpr static std::size_t size()
|
||||
{
|
||||
return sizeof...(X);
|
||||
}
|
||||
|
||||
constexpr fixed_shape()
|
||||
{
|
||||
}
|
||||
|
||||
constexpr operator cast_type() const
|
||||
{
|
||||
return {{X...}};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <class T, size_t N>
|
||||
class tuple_size<xt::const_array<T, N>> :
|
||||
public integral_constant<size_t, N>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
namespace xtl
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template <class T, std::size_t N>
|
||||
struct sequence_builder<xt::const_array<T, N>>
|
||||
{
|
||||
using sequence_type = xt::const_array<T, N>;
|
||||
using value_type = typename sequence_type::value_type;
|
||||
using size_type = typename sequence_type::size_type;
|
||||
|
||||
inline static sequence_type make(size_type /*size*/, value_type /*v*/)
|
||||
{
|
||||
return sequence_type();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
namespace xt
|
||||
{
|
||||
|
||||
/**********************
|
||||
* xfixed declaration *
|
||||
**********************/
|
||||
|
||||
template <class ET, class S, layout_type L, class Tag>
|
||||
class xfixed_container;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
/**************************************************************************************
|
||||
The following is something we can currently only dream about -- for when we drop
|
||||
support for a lot of the old compilers (e.g. GCC 4.9, MSVC 2017 ;)
|
||||
|
||||
template <class T>
|
||||
constexpr std::size_t calculate_stride(T& shape, std::size_t idx, layout_type L)
|
||||
{
|
||||
if (shape[idx] == 1)
|
||||
{
|
||||
return std::size_t(0);
|
||||
}
|
||||
|
||||
std::size_t data_size = 1;
|
||||
std::size_t stride = 1;
|
||||
if (L == layout_type::row_major)
|
||||
{
|
||||
// because we have a integer sequence that counts
|
||||
// from 0 to sz - 1, we need to "invert" idx here
|
||||
idx = shape.size() - idx;
|
||||
for (std::size_t i = idx; i != 0; --i)
|
||||
{
|
||||
stride = data_size;
|
||||
data_size = stride * shape[i - 1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (std::size_t i = 0; i < idx + 1; ++i)
|
||||
{
|
||||
stride = data_size;
|
||||
data_size = stride * shape[i];
|
||||
}
|
||||
}
|
||||
return stride;
|
||||
}
|
||||
|
||||
*****************************************************************************************/
|
||||
|
||||
template <std::size_t IDX, std::size_t... X>
|
||||
struct at
|
||||
{
|
||||
constexpr static std::size_t arr[sizeof...(X)] = {X...};
|
||||
constexpr static std::size_t value = arr[IDX];
|
||||
};
|
||||
|
||||
template <layout_type L, std::size_t I, std::size_t... X>
|
||||
struct calculate_stride;
|
||||
|
||||
template <std::size_t I, std::size_t Y, std::size_t... X>
|
||||
struct calculate_stride<layout_type::column_major, I, Y, X...>
|
||||
{
|
||||
constexpr static std::size_t value = Y * calculate_stride<layout_type::column_major, I - 1, X...>::value;
|
||||
};
|
||||
|
||||
template <std::size_t Y, std::size_t... X>
|
||||
struct calculate_stride<layout_type::column_major, 0, Y, X...>
|
||||
{
|
||||
constexpr static std::size_t value = 1;
|
||||
};
|
||||
|
||||
template <std::size_t I, std::size_t... X>
|
||||
struct calculate_stride_row_major
|
||||
{
|
||||
constexpr static std::size_t value = at<sizeof...(X) - I, X...>::value * calculate_stride_row_major<I - 1, X...>::value;
|
||||
};
|
||||
|
||||
template <std::size_t... X>
|
||||
struct calculate_stride_row_major<0, X...>
|
||||
{
|
||||
constexpr static std::size_t value = 1;
|
||||
};
|
||||
|
||||
template <std::size_t I, std::size_t... X>
|
||||
struct calculate_stride<layout_type::row_major, I, X...>
|
||||
{
|
||||
constexpr static std::size_t value = calculate_stride_row_major<sizeof...(X) - I - 1, X...>::value;
|
||||
};
|
||||
|
||||
template <layout_type L, std::size_t... X, std::size_t... I>
|
||||
constexpr const_array<std::size_t, sizeof...(X)>
|
||||
get_strides_impl(const xt::fixed_shape<X...>& /*shape*/, std::index_sequence<I...>)
|
||||
{
|
||||
static_assert((L == layout_type::row_major) || (L == layout_type::column_major),
|
||||
"Layout not supported for fixed array");
|
||||
return {{at<I, X...>::value == 1 ? 0 : calculate_stride<L, I, X...>::value...}};
|
||||
}
|
||||
|
||||
template <class T, std::size_t... I>
|
||||
constexpr T get_backstrides_impl(const T& shape, const T& strides, std::index_sequence<I...>)
|
||||
{
|
||||
return {{(strides[I] * (shape[I] - 1))...}};
|
||||
}
|
||||
|
||||
template <std::size_t... X>
|
||||
struct compute_size_impl;
|
||||
|
||||
template <std::size_t Y, std::size_t... X>
|
||||
struct compute_size_impl<Y, X...>
|
||||
{
|
||||
constexpr static std::size_t value = Y * compute_size_impl<X...>::value;
|
||||
};
|
||||
|
||||
template <std::size_t X>
|
||||
struct compute_size_impl<X>
|
||||
{
|
||||
constexpr static std::size_t value = X;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct compute_size_impl<>
|
||||
{
|
||||
// support for 0D xtensor fixed (empty shape = xshape<>)
|
||||
constexpr static std::size_t value = 1;
|
||||
};
|
||||
|
||||
// TODO unify with constexpr compute_size when dropping MSVC 2015
|
||||
template <class T>
|
||||
struct fixed_compute_size;
|
||||
|
||||
template <std::size_t... X>
|
||||
struct fixed_compute_size<xt::fixed_shape<X...>>
|
||||
{
|
||||
constexpr static std::size_t value = compute_size_impl<X...>::value;
|
||||
};
|
||||
|
||||
template <class V, std::size_t... X>
|
||||
struct get_init_type_impl;
|
||||
|
||||
template <class V, std::size_t Y>
|
||||
struct get_init_type_impl<V, Y>
|
||||
{
|
||||
using type = V[Y];
|
||||
};
|
||||
|
||||
template <class V>
|
||||
struct get_init_type_impl<V>
|
||||
{
|
||||
using type = V[1];
|
||||
};
|
||||
|
||||
template <class V, std::size_t Y, std::size_t... X>
|
||||
struct get_init_type_impl<V, Y, X...>
|
||||
{
|
||||
using tmp_type = typename get_init_type_impl<V, X...>::type;
|
||||
using type = tmp_type[Y];
|
||||
};
|
||||
}
|
||||
|
||||
template <layout_type L, std::size_t... X>
|
||||
constexpr const_array<std::size_t, sizeof...(X)> get_strides(const fixed_shape<X...>& shape) noexcept
|
||||
{
|
||||
return detail::get_strides_impl<L>(shape, std::make_index_sequence<sizeof...(X)>{});
|
||||
}
|
||||
|
||||
template <class T>
|
||||
constexpr T get_backstrides(const T& shape, const T& strides) noexcept
|
||||
{
|
||||
return detail::get_backstrides_impl(shape, strides,
|
||||
std::make_index_sequence<std::tuple_size<T>::value>{});
|
||||
}
|
||||
|
||||
template <class V, class S>
|
||||
struct get_init_type;
|
||||
|
||||
template <class V, std::size_t... X>
|
||||
struct get_init_type<V, fixed_shape<X...>>
|
||||
{
|
||||
using type = typename detail::get_init_type_impl<V, X...>::type;
|
||||
};
|
||||
|
||||
template <class V, class S>
|
||||
using get_init_type_t = typename get_init_type<V, S>::type;
|
||||
|
||||
template <class ET, class S, layout_type L, class Tag>
|
||||
struct xcontainer_inner_types<xfixed_container<ET, S, L, Tag>>
|
||||
{
|
||||
using inner_shape_type = typename S::cast_type;
|
||||
using inner_strides_type = inner_shape_type;
|
||||
using backstrides_type = inner_shape_type;
|
||||
using inner_backstrides_type = backstrides_type;
|
||||
using shape_type = std::array<typename inner_shape_type::value_type,
|
||||
std::tuple_size<inner_shape_type>::value>;
|
||||
using strides_type = shape_type;
|
||||
using storage_type = aligned_array<ET, detail::fixed_compute_size<S>::value>;
|
||||
using temporary_type = xfixed_container<ET, S, L, Tag>;
|
||||
static constexpr layout_type layout = L;
|
||||
};
|
||||
|
||||
template <class ET, class S, layout_type L, class Tag>
|
||||
struct xiterable_inner_types<xfixed_container<ET, S, L, Tag>>
|
||||
: xcontainer_iterable_types<xfixed_container<ET, S, L, Tag>>
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* @class xfixed_container
|
||||
* @brief Dense multidimensional container with tensor semantic and fixed
|
||||
* dimension.
|
||||
*
|
||||
* The xfixed_container class implements a dense multidimensional container
|
||||
* with tensor semantic and fixed dimension
|
||||
*
|
||||
* @tparam ET The type of the elements.
|
||||
* @tparam S The xshape template paramter of the container.
|
||||
* @tparam L The layout_type of the tensor.
|
||||
* @tparam Tag The expression tag.
|
||||
* @sa xtensor_fixed
|
||||
*/
|
||||
template <class ET, class S, layout_type L, class Tag>
|
||||
class xfixed_container : public xcontainer<xfixed_container<ET, S, L, Tag>>,
|
||||
public xcontainer_semantic<xfixed_container<ET, S, L, Tag>>
|
||||
{
|
||||
public:
|
||||
|
||||
using self_type = xfixed_container<ET, S, L, Tag>;
|
||||
using base_type = xcontainer<self_type>;
|
||||
using semantic_base = xcontainer_semantic<self_type>;
|
||||
|
||||
using storage_type = typename base_type::storage_type;
|
||||
using value_type = typename base_type::value_type;
|
||||
using reference = typename base_type::reference;
|
||||
using const_reference = typename base_type::const_reference;
|
||||
using pointer = typename base_type::pointer;
|
||||
using const_pointer = typename base_type::const_pointer;
|
||||
using shape_type = typename base_type::shape_type;
|
||||
using inner_shape_type = typename base_type::inner_shape_type;
|
||||
using strides_type = typename base_type::strides_type;
|
||||
using backstrides_type = typename base_type::backstrides_type;
|
||||
using inner_backstrides_type = typename base_type::inner_backstrides_type;
|
||||
using inner_strides_type = typename base_type::inner_strides_type;
|
||||
using temporary_type = typename semantic_base::temporary_type;
|
||||
using expression_tag = Tag;
|
||||
|
||||
constexpr static std::size_t N = std::tuple_size<shape_type>::value;
|
||||
|
||||
xfixed_container();
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1910
|
||||
explicit xfixed_container(value_type v);
|
||||
#else
|
||||
[[deprecated]] explicit xfixed_container(value_type v);
|
||||
#endif
|
||||
explicit xfixed_container(const inner_shape_type& shape, layout_type l = L);
|
||||
explicit xfixed_container(const inner_shape_type& shape, value_type v, layout_type l = L);
|
||||
|
||||
#ifndef X_OLD_CLANG
|
||||
xfixed_container(const get_init_type_t<value_type, S>& init);
|
||||
#else
|
||||
// remove this enable_if when removing the other value_type constructor
|
||||
template <class IX = std::integral_constant<std::size_t, N>, class EN = std::enable_if_t<IX::value != 0, int>>
|
||||
xfixed_container(nested_initializer_list_t<value_type, N> t);
|
||||
#endif
|
||||
|
||||
~xfixed_container() = default;
|
||||
|
||||
xfixed_container(const xfixed_container&) = default;
|
||||
xfixed_container& operator=(const xfixed_container&) = default;
|
||||
|
||||
xfixed_container(xfixed_container&&) = default;
|
||||
xfixed_container& operator=(xfixed_container&&) = default;
|
||||
|
||||
template <class E>
|
||||
xfixed_container(const xexpression<E>& e);
|
||||
|
||||
template <class E>
|
||||
xfixed_container& operator=(const xexpression<E>& e);
|
||||
|
||||
template <class ST = shape_type>
|
||||
void resize(ST&& shape, bool force = false) const;
|
||||
|
||||
template <class ST = shape_type>
|
||||
void reshape(ST&& shape, layout_type layout = L) const;
|
||||
|
||||
template <class ST>
|
||||
bool broadcast_shape(ST& s, bool reuse_cache = false) const;
|
||||
|
||||
constexpr layout_type layout() const noexcept;
|
||||
|
||||
private:
|
||||
|
||||
storage_type m_storage;
|
||||
|
||||
XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_shape_type m_shape = S();
|
||||
XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_strides_type m_strides = get_strides<L>(S());
|
||||
XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_backstrides_type m_backstrides = get_backstrides(m_shape, m_strides);
|
||||
|
||||
storage_type& storage_impl() noexcept;
|
||||
const storage_type& storage_impl() const noexcept;
|
||||
|
||||
XTENSOR_CONSTEXPR_RETURN const inner_shape_type& shape_impl() const noexcept;
|
||||
XTENSOR_CONSTEXPR_RETURN const inner_strides_type& strides_impl() const noexcept;
|
||||
XTENSOR_CONSTEXPR_RETURN const inner_backstrides_type& backstrides_impl() const noexcept;
|
||||
|
||||
friend class xcontainer<xfixed_container<ET, S, L, Tag>>;
|
||||
};
|
||||
|
||||
#ifdef XTENSOR_HAS_CONSTEXPR_ENHANCED
|
||||
// Out of line definitions to prevent linker errors prior to C++17
|
||||
template <class ET, class S, layout_type L, class Tag>
|
||||
constexpr typename xfixed_container<ET, S, L, Tag>::inner_shape_type xfixed_container<ET, S, L, Tag>::m_shape;
|
||||
|
||||
template <class ET, class S, layout_type L, class Tag>
|
||||
constexpr typename xfixed_container<ET, S, L, Tag>::inner_strides_type xfixed_container<ET, S, L, Tag>::m_strides;
|
||||
|
||||
template <class ET, class S, layout_type L, class Tag>
|
||||
constexpr typename xfixed_container<ET, S, L, Tag>::inner_backstrides_type xfixed_container<ET, S, L, Tag>::m_backstrides;
|
||||
#endif
|
||||
|
||||
/****************************************
|
||||
* xfixed_container_adaptor declaration *
|
||||
****************************************/
|
||||
|
||||
template <class EC, class S, layout_type L, class Tag>
|
||||
class xfixed_adaptor;
|
||||
|
||||
template <class EC, class S, layout_type L, class Tag>
|
||||
struct xcontainer_inner_types<xfixed_adaptor<EC, S, L, Tag>>
|
||||
{
|
||||
using storage_type = std::remove_reference_t<EC>;
|
||||
using inner_shape_type = typename S::cast_type;
|
||||
using inner_strides_type = inner_shape_type;
|
||||
using backstrides_type = inner_shape_type;
|
||||
using inner_backstrides_type = backstrides_type;
|
||||
using shape_type = std::array<typename inner_shape_type::value_type,
|
||||
std::tuple_size<inner_shape_type>::value>;
|
||||
using strides_type = shape_type;
|
||||
using temporary_type = xfixed_container<typename storage_type::value_type, S, L, Tag>;
|
||||
static constexpr layout_type layout = L;
|
||||
};
|
||||
|
||||
template <class EC, class S, layout_type L, class Tag>
|
||||
struct xiterable_inner_types<xfixed_adaptor<EC, S, L, Tag>>
|
||||
: xcontainer_iterable_types<xfixed_adaptor<EC, S, L, Tag>>
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* @class xfixed_adaptor
|
||||
* @brief Dense multidimensional container adaptor with tensor semantic
|
||||
* and fixed dimension.
|
||||
*
|
||||
* The xfixed_adaptor class implements a dense multidimensional
|
||||
* container adaptor with tensor semantic and fixed dimension. It
|
||||
* is used to provide a multidimensional container semantic and a
|
||||
* tensor semantic to stl-like containers.
|
||||
*
|
||||
* @tparam EC The closure for the container type to adapt.
|
||||
* @tparam S The xshape template parameter for the fixed shape of the adaptor
|
||||
* @tparam L The layout_type of the adaptor.
|
||||
* @tparam Tag The expression tag.
|
||||
*/
|
||||
template <class EC, class S, layout_type L, class Tag>
|
||||
class xfixed_adaptor : public xcontainer<xfixed_adaptor<EC, S, L, Tag>>,
|
||||
public xcontainer_semantic<xfixed_adaptor<EC, S, L, Tag>>
|
||||
{
|
||||
public:
|
||||
|
||||
using container_closure_type = EC;
|
||||
|
||||
using self_type = xfixed_adaptor<EC, S, L, Tag>;
|
||||
using base_type = xcontainer<self_type>;
|
||||
using semantic_base = xcontainer_semantic<self_type>;
|
||||
using storage_type = typename base_type::storage_type;
|
||||
using shape_type = typename base_type::shape_type;
|
||||
using strides_type = typename base_type::strides_type;
|
||||
using backstrides_type = typename base_type::backstrides_type;
|
||||
using inner_shape_type = typename base_type::inner_shape_type;
|
||||
using inner_strides_type = typename base_type::inner_strides_type;
|
||||
using inner_backstrides_type = typename base_type::inner_backstrides_type;
|
||||
using temporary_type = typename semantic_base::temporary_type;
|
||||
using expression_tag = Tag;
|
||||
|
||||
xfixed_adaptor(storage_type&& data);
|
||||
xfixed_adaptor(const storage_type& data);
|
||||
|
||||
template <class D>
|
||||
xfixed_adaptor(D&& data);
|
||||
|
||||
~xfixed_adaptor() = default;
|
||||
|
||||
xfixed_adaptor(const xfixed_adaptor&) = default;
|
||||
xfixed_adaptor& operator=(const xfixed_adaptor&);
|
||||
|
||||
xfixed_adaptor(xfixed_adaptor&&) = default;
|
||||
xfixed_adaptor& operator=(xfixed_adaptor&&);
|
||||
xfixed_adaptor& operator=(temporary_type&&);
|
||||
|
||||
template <class E>
|
||||
xfixed_adaptor& operator=(const xexpression<E>& e);
|
||||
|
||||
constexpr layout_type layout() const noexcept;
|
||||
|
||||
private:
|
||||
|
||||
container_closure_type m_storage;
|
||||
|
||||
XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_shape_type m_shape = S();
|
||||
XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_strides_type m_strides = get_strides<L>(S());
|
||||
XTENSOR_CONSTEXPR_ENHANCED_STATIC inner_backstrides_type m_backstrides = get_backstrides(m_shape, m_strides);
|
||||
|
||||
storage_type& storage_impl() noexcept;
|
||||
const storage_type& storage_impl() const noexcept;
|
||||
|
||||
XTENSOR_CONSTEXPR_RETURN const inner_shape_type& shape_impl() const noexcept;
|
||||
XTENSOR_CONSTEXPR_RETURN const inner_strides_type& strides_impl() const noexcept;
|
||||
XTENSOR_CONSTEXPR_RETURN const inner_backstrides_type& backstrides_impl() const noexcept;
|
||||
|
||||
friend class xcontainer<xfixed_adaptor<EC, S, L, Tag>>;
|
||||
};
|
||||
|
||||
#ifdef XTENSOR_HAS_CONSTEXPR_ENHANCED
|
||||
// Out of line definitions to prevent linker errors prior to C++17
|
||||
template <class EC, class S, layout_type L, class Tag>
|
||||
constexpr typename xfixed_adaptor<EC, S, L, Tag>::inner_shape_type xfixed_adaptor<EC, S, L, Tag>::m_shape;
|
||||
|
||||
template <class EC, class S, layout_type L, class Tag>
|
||||
constexpr typename xfixed_adaptor<EC, S, L, Tag>::inner_strides_type xfixed_adaptor<EC, S, L, Tag>::m_strides;
|
||||
|
||||
template <class EC, class S, layout_type L, class Tag>
|
||||
constexpr typename xfixed_adaptor<EC, S, L, Tag>::inner_backstrides_type xfixed_adaptor<EC, S, L, Tag>::m_backstrides;
|
||||
#endif
|
||||
|
||||
/************************************
|
||||
* xfixed_container implementation *
|
||||
************************************/
|
||||
|
||||
/**
|
||||
* @name Constructors
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* Create an uninitialized xfixed_container according to the shape template parameter.
|
||||
*/
|
||||
template <class ET, class S, layout_type L, class Tag>
|
||||
inline xfixed_container<ET, S, L, Tag>::xfixed_container()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an xfixed_container, and initialize with the value of v.
|
||||
*
|
||||
* @param v the fill value
|
||||
*/
|
||||
template <class ET, class S, layout_type L, class Tag>
|
||||
inline xfixed_container<ET, S, L, Tag>::xfixed_container(value_type v)
|
||||
{
|
||||
std::fill(this->begin(), this->end(), v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an uninitialized xfixed_container.
|
||||
* Note this function is only provided for homogenity, and the shape & layout argument is
|
||||
* disregarded (the template shape is always used).
|
||||
*
|
||||
* @param shape the shape of the xfixed_container (unused!)
|
||||
* @param l the layout_type of the xfixed_container (unused!)
|
||||
*/
|
||||
template <class ET, class S, layout_type L, class Tag>
|
||||
inline xfixed_container<ET, S, L, Tag>::xfixed_container(const inner_shape_type& /*shape*/, layout_type /*l*/)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an xfixed_container, and initialize with the value of v.
|
||||
* Note, the shape argument to this function is only provided for homogenity,
|
||||
* and the shape argument is disregarded (the template shape is always used).
|
||||
*
|
||||
* @param shape the shape of the xfixed_container (unused!)
|
||||
* @param v the fill value
|
||||
* @param l the layout_type of the xfixed_container (unused!)
|
||||
*/
|
||||
template <class ET, class S, layout_type L, class Tag>
|
||||
inline xfixed_container<ET, S, L, Tag>::xfixed_container(const inner_shape_type& /*shape*/, value_type v, layout_type /*l*/)
|
||||
: xfixed_container(v)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates an xfixed_container with shape S with values from a C array.
|
||||
* The type returned by get_init_type_t is raw C array ``value_type[X][Y][Z]`` for ``xt::xshape<X, Y, Z>``.
|
||||
* C arrays can be initialized with the initializer list syntax, but the size is checked at compile
|
||||
* time to prevent errors.
|
||||
* Note: for clang < 3.8 this is an initializer_list and the size is not checked at compile-or runtime.
|
||||
*/
|
||||
#ifndef X_OLD_CLANG
|
||||
template <class ET, class S, layout_type L, class Tag>
|
||||
inline xfixed_container<ET, S, L, Tag>::xfixed_container(const get_init_type_t<value_type, S>& init)
|
||||
{
|
||||
std::copy(reinterpret_cast<const_pointer>(&init), reinterpret_cast<const_pointer>(&init) + this->size(),
|
||||
this->template begin<layout_type::row_major>());
|
||||
}
|
||||
#else
|
||||
template <class ET, class S, layout_type L, class Tag>
|
||||
template <class IX, class EN>
|
||||
inline xfixed_container<ET, S, L, Tag>::xfixed_container(nested_initializer_list_t<value_type, N> t)
|
||||
{
|
||||
L == layout_type::row_major ? nested_copy(m_storage.begin(), t) : nested_copy(this->template begin<layout_type::row_major>(), t);
|
||||
}
|
||||
#endif
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @name Extended copy semantic
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* The extended copy constructor.
|
||||
*/
|
||||
template <class ET, class S, layout_type L, class Tag>
|
||||
template <class E>
|
||||
inline xfixed_container<ET, S, L, Tag>::xfixed_container(const xexpression<E>& e)
|
||||
{
|
||||
semantic_base::assign(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* The extended assignment operator.
|
||||
*/
|
||||
template <class ET, class S, layout_type L, class Tag>
|
||||
template <class E>
|
||||
inline auto xfixed_container<ET, S, L, Tag>::operator=(const xexpression<E>& e) -> self_type&
|
||||
{
|
||||
return semantic_base::operator=(e);
|
||||
}
|
||||
//@}
|
||||
|
||||
/**
|
||||
* Note that the xfixed_container **cannot** be resized. Attempting to resize with a different
|
||||
* size throws an assert in debug mode.
|
||||
*/
|
||||
template <class ET, class S, layout_type L, class Tag>
|
||||
template <class ST>
|
||||
inline void xfixed_container<ET, S, L, Tag>::resize(ST&& shape, bool) const
|
||||
{
|
||||
(void)(shape); // remove unused parameter warning if XTENSOR_ASSERT undefined
|
||||
XTENSOR_ASSERT(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Note that the xfixed_container **cannot** be reshaped to a shape different from ``S``.
|
||||
*/
|
||||
template <class ET, class S, layout_type L, class Tag>
|
||||
template <class ST>
|
||||
inline void xfixed_container<ET, S, L, Tag>::reshape(ST&& shape, layout_type layout) const
|
||||
{
|
||||
if (!(std::equal(shape.begin(), shape.end(), m_shape.begin()) && shape.size() == m_shape.size() && layout == L))
|
||||
{
|
||||
throw std::runtime_error("Trying to reshape xtensor_fixed with different shape or layout.");
|
||||
}
|
||||
}
|
||||
|
||||
template <class ET, class S, layout_type L, class Tag>
|
||||
template <class ST>
|
||||
inline bool xfixed_container<ET, S, L, Tag>::broadcast_shape(ST& shape, bool) const
|
||||
{
|
||||
return xt::broadcast_shape(m_shape, shape);
|
||||
}
|
||||
|
||||
template <class ET, class S, layout_type L, class Tag>
|
||||
constexpr layout_type xfixed_container<ET, S, L, Tag>::layout() const noexcept
|
||||
{
|
||||
return base_type::static_layout;
|
||||
}
|
||||
|
||||
template <class ET, class S, layout_type L, class Tag>
|
||||
inline auto xfixed_container<ET, S, L, Tag>::storage_impl() noexcept -> storage_type&
|
||||
{
|
||||
return m_storage;
|
||||
}
|
||||
|
||||
template <class ET, class S, layout_type L, class Tag>
|
||||
inline auto xfixed_container<ET, S, L, Tag>::storage_impl() const noexcept -> const storage_type&
|
||||
{
|
||||
return m_storage;
|
||||
}
|
||||
|
||||
template <class ET, class S, layout_type L, class Tag>
|
||||
XTENSOR_CONSTEXPR_RETURN auto xfixed_container<ET, S, L, Tag>::shape_impl() const noexcept -> const inner_shape_type&
|
||||
{
|
||||
return m_shape;
|
||||
}
|
||||
|
||||
template <class ET, class S, layout_type L, class Tag>
|
||||
XTENSOR_CONSTEXPR_RETURN auto xfixed_container<ET, S, L, Tag>::strides_impl() const noexcept -> const inner_strides_type&
|
||||
{
|
||||
return m_strides;
|
||||
}
|
||||
|
||||
template <class ET, class S, layout_type L, class Tag>
|
||||
XTENSOR_CONSTEXPR_RETURN auto xfixed_container<ET, S, L, Tag>::backstrides_impl() const noexcept -> const inner_backstrides_type&
|
||||
{
|
||||
return m_backstrides;
|
||||
}
|
||||
|
||||
/*******************
|
||||
* xfixed_adaptor *
|
||||
*******************/
|
||||
|
||||
/**
|
||||
* @name Constructors
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* Constructs an xfixed_adaptor of the given stl-like container.
|
||||
* @param data the container to adapt
|
||||
*/
|
||||
template <class EC, class S, layout_type L, class Tag>
|
||||
inline xfixed_adaptor<EC, S, L, Tag>::xfixed_adaptor(storage_type&& data)
|
||||
: base_type(), m_storage(std::move(data))
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an xfixed_adaptor of the given stl-like container.
|
||||
* @param data the container to adapt
|
||||
*/
|
||||
template <class EC, class S, layout_type L, class Tag>
|
||||
inline xfixed_adaptor<EC, S, L, Tag>::xfixed_adaptor(const storage_type& data)
|
||||
: base_type(), m_storage(data)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an xfixed_adaptor of the given stl-like container,
|
||||
* with the specified shape and layout_type.
|
||||
* @param data the container to adapt
|
||||
*/
|
||||
template <class EC, class S, layout_type L, class Tag>
|
||||
template <class D>
|
||||
inline xfixed_adaptor<EC, S, L, Tag>::xfixed_adaptor(D&& data)
|
||||
: base_type(), m_storage(std::forward<D>(data))
|
||||
{
|
||||
}
|
||||
//@}
|
||||
|
||||
template <class EC, class S, layout_type L, class Tag>
|
||||
inline auto xfixed_adaptor<EC, S, L, Tag>::operator=(const xfixed_adaptor& rhs) -> self_type&
|
||||
{
|
||||
base_type::operator=(rhs);
|
||||
m_storage = rhs.m_storage;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class EC, class S, layout_type L, class Tag>
|
||||
inline auto xfixed_adaptor<EC, S, L, Tag>::operator=(xfixed_adaptor&& rhs) -> self_type&
|
||||
{
|
||||
base_type::operator=(std::move(rhs));
|
||||
m_storage = rhs.m_storage;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class EC, class S, layout_type L, class Tag>
|
||||
inline auto xfixed_adaptor<EC, S, L, Tag>::operator=(temporary_type&& rhs) -> self_type&
|
||||
{
|
||||
m_storage = xtl::forward_sequence<storage_type>(std::move(rhs.storage()));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @name Extended copy semantic
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* The extended assignment operator.
|
||||
*/
|
||||
template <class EC, class S, layout_type L, class Tag>
|
||||
template <class E>
|
||||
inline auto xfixed_adaptor<EC, S, L, Tag>::operator=(const xexpression<E>& e) -> self_type&
|
||||
{
|
||||
return semantic_base::operator=(e);
|
||||
}
|
||||
//@}
|
||||
|
||||
template <class EC, class S, layout_type L, class Tag>
|
||||
inline auto xfixed_adaptor<EC, S, L, Tag>::storage_impl() noexcept -> storage_type&
|
||||
{
|
||||
return m_storage;
|
||||
}
|
||||
|
||||
template <class EC, class S, layout_type L, class Tag>
|
||||
inline auto xfixed_adaptor<EC, S, L, Tag>::storage_impl() const noexcept -> const storage_type&
|
||||
{
|
||||
return m_storage;
|
||||
}
|
||||
|
||||
template <class EC, class S, layout_type L, class Tag>
|
||||
constexpr layout_type xfixed_adaptor<EC, S, L, Tag>::layout() const noexcept
|
||||
{
|
||||
return base_type::static_layout;
|
||||
}
|
||||
|
||||
template <class EC, class S, layout_type L, class Tag>
|
||||
XTENSOR_CONSTEXPR_RETURN auto xfixed_adaptor<EC, S, L, Tag>::shape_impl() const noexcept -> const inner_shape_type&
|
||||
{
|
||||
return m_shape;
|
||||
}
|
||||
|
||||
template <class EC, class S, layout_type L, class Tag>
|
||||
XTENSOR_CONSTEXPR_RETURN auto xfixed_adaptor<EC, S, L, Tag>::strides_impl() const noexcept -> const inner_strides_type&
|
||||
{
|
||||
return m_strides;
|
||||
}
|
||||
|
||||
template <class EC, class S, layout_type L, class Tag>
|
||||
XTENSOR_CONSTEXPR_RETURN auto xfixed_adaptor<EC, S, L, Tag>::backstrides_impl() const noexcept -> const inner_backstrides_type&
|
||||
{
|
||||
return m_backstrides;
|
||||
}
|
||||
}
|
||||
|
||||
#undef XTENSOR_CONSTEXPR_ENHANCED
|
||||
#undef XTENSOR_CONSTEXPR_RETURN
|
||||
#undef XTENSOR_CONSTEXPR_ENHANCED_STATIC
|
||||
#undef XTENSOR_HAS_CONSTEXPR_ENHANCED
|
||||
|
||||
#endif
|
||||
1184
vendor/xtensor/include/xtensor/xfunction.hpp
vendored
Normal file
1184
vendor/xtensor/include/xtensor/xfunction.hpp
vendored
Normal file
File diff suppressed because it is too large
Load diff
1349
vendor/xtensor/include/xtensor/xfunctor_view.hpp
vendored
Normal file
1349
vendor/xtensor/include/xtensor/xfunctor_view.hpp
vendored
Normal file
File diff suppressed because it is too large
Load diff
401
vendor/xtensor/include/xtensor/xgenerator.hpp
vendored
Normal file
401
vendor/xtensor/include/xtensor/xgenerator.hpp
vendored
Normal file
|
|
@ -0,0 +1,401 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTENSOR_GENERATOR_HPP
|
||||
#define XTENSOR_GENERATOR_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <numeric>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include <xtl/xsequence.hpp>
|
||||
|
||||
#include "xexpression.hpp"
|
||||
#include "xiterable.hpp"
|
||||
#include "xstrides.hpp"
|
||||
#include "xutils.hpp"
|
||||
|
||||
namespace xt
|
||||
{
|
||||
|
||||
/**************
|
||||
* xgenerator *
|
||||
**************/
|
||||
|
||||
template <class F, class R, class S>
|
||||
class xgenerator;
|
||||
|
||||
template <class C, class R, class S>
|
||||
struct xiterable_inner_types<xgenerator<C, R, S>>
|
||||
{
|
||||
using inner_shape_type = S;
|
||||
using const_stepper = xindexed_stepper<xgenerator<C, R, S>, true>;
|
||||
using stepper = const_stepper;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class xgenerator
|
||||
* @brief Multidimensional function operating on indices.
|
||||
*
|
||||
* The xgenerator class implements a multidimensional function,
|
||||
* generating a value from the supplied indices.
|
||||
*
|
||||
* @tparam F the function type
|
||||
* @tparam R the return type of the function
|
||||
* @tparam S the shape type of the generator
|
||||
*/
|
||||
template <class F, class R, class S>
|
||||
class xgenerator : public xexpression<xgenerator<F, R, S>>,
|
||||
public xconst_iterable<xgenerator<F, R, S>>
|
||||
{
|
||||
public:
|
||||
|
||||
using self_type = xgenerator<F, R, S>;
|
||||
using functor_type = typename std::remove_reference<F>::type;
|
||||
|
||||
using value_type = R;
|
||||
using reference = value_type;
|
||||
using const_reference = value_type;
|
||||
using pointer = value_type*;
|
||||
using const_pointer = const value_type*;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
using iterable_base = xconst_iterable<self_type>;
|
||||
using inner_shape_type = typename iterable_base::inner_shape_type;
|
||||
using shape_type = inner_shape_type;
|
||||
using strides_type = S;
|
||||
|
||||
using stepper = typename iterable_base::stepper;
|
||||
using const_stepper = typename iterable_base::const_stepper;
|
||||
|
||||
static constexpr layout_type static_layout = layout_type::any;
|
||||
static constexpr bool contiguous_layout = false;
|
||||
|
||||
template <class Func>
|
||||
xgenerator(Func&& f, const S& shape) noexcept;
|
||||
|
||||
size_type size() const noexcept;
|
||||
size_type dimension() const noexcept;
|
||||
const inner_shape_type& shape() const noexcept;
|
||||
layout_type layout() const noexcept;
|
||||
|
||||
template <class... Args>
|
||||
const_reference operator()(Args... args) const;
|
||||
template <class... Args>
|
||||
const_reference at(Args... args) const;
|
||||
template <class... Args>
|
||||
const_reference unchecked(Args... args) const;
|
||||
template <class OS>
|
||||
disable_integral_t<OS, const_reference> operator[](const OS& index) const;
|
||||
template <class I>
|
||||
const_reference operator[](std::initializer_list<I> index) const;
|
||||
const_reference operator[](size_type i) const;
|
||||
|
||||
template <class It>
|
||||
const_reference element(It first, It last) const;
|
||||
|
||||
template <class O>
|
||||
bool broadcast_shape(O& shape, bool reuse_cache = false) const;
|
||||
|
||||
template <class O>
|
||||
bool is_trivial_broadcast(const O& /*strides*/) const noexcept;
|
||||
|
||||
template <class O>
|
||||
const_stepper stepper_begin(const O& shape) const noexcept;
|
||||
template <class O>
|
||||
const_stepper stepper_end(const O& shape, layout_type) const noexcept;
|
||||
|
||||
template <class E, class FE = F, class = std::enable_if_t<has_assign_to<E, FE>::value>>
|
||||
void assign_to(xexpression<E>& e) const noexcept;
|
||||
|
||||
private:
|
||||
|
||||
template <std::size_t dim>
|
||||
void adapt_index() const;
|
||||
|
||||
template <std::size_t dim, class I, class... Args>
|
||||
void adapt_index(I& arg, Args&... args) const;
|
||||
|
||||
functor_type m_f;
|
||||
inner_shape_type m_shape;
|
||||
};
|
||||
|
||||
/*****************************
|
||||
* xgenerator implementation *
|
||||
*****************************/
|
||||
|
||||
/**
|
||||
* @name Constructor
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* Constructs an xgenerator applying the specified function over the
|
||||
* given shape.
|
||||
* @param f the function to apply
|
||||
* @param shape the shape of the xgenerator
|
||||
*/
|
||||
template <class F, class R, class S>
|
||||
template <class Func>
|
||||
inline xgenerator<F, R, S>::xgenerator(Func&& f, const S& shape) noexcept
|
||||
: m_f(std::forward<Func>(f)), m_shape(shape)
|
||||
{
|
||||
}
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @name Size and shape
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* Returns the size of the expression.
|
||||
*/
|
||||
template <class F, class R, class S>
|
||||
inline auto xgenerator<F, R, S>::size() const noexcept -> size_type
|
||||
{
|
||||
return compute_size(shape());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of dimensions of the function.
|
||||
*/
|
||||
template <class F, class R, class S>
|
||||
inline auto xgenerator<F, R, S>::dimension() const noexcept -> size_type
|
||||
{
|
||||
return m_shape.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the shape of the xgenerator.
|
||||
*/
|
||||
template <class F, class R, class S>
|
||||
inline auto xgenerator<F, R, S>::shape() const noexcept -> const inner_shape_type&
|
||||
{
|
||||
return m_shape;
|
||||
}
|
||||
|
||||
template <class F, class R, class S>
|
||||
inline layout_type xgenerator<F, R, S>::layout() const noexcept
|
||||
{
|
||||
return static_layout;
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @name Data
|
||||
*/
|
||||
/**
|
||||
* Returns the evaluated element at the specified position in the function.
|
||||
* @param args a list of indices specifying the position in the function. Indices
|
||||
* must be unsigned integers, the number of indices should be equal or greater than
|
||||
* the number of dimensions of the function.
|
||||
*/
|
||||
template <class F, class R, class S>
|
||||
template <class... Args>
|
||||
inline auto xgenerator<F, R, S>::operator()(Args... args) const -> const_reference
|
||||
{
|
||||
XTENSOR_TRY(check_index(shape(), args...));
|
||||
adapt_index<0>(args...);
|
||||
return m_f(args...);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a constant reference to the element at the specified position in the expression,
|
||||
* after dimension and bounds checking.
|
||||
* @param args a list of indices specifying the position in the function. Indices
|
||||
* must be unsigned integers, the number of indices should be equal to the number of dimensions
|
||||
* of the expression.
|
||||
* @exception std::out_of_range if the number of argument is greater than the number of dimensions
|
||||
* or if indices are out of bounds.
|
||||
*/
|
||||
template <class F, class R, class S>
|
||||
template <class... Args>
|
||||
inline auto xgenerator<F, R, S>::at(Args... args) const -> const_reference
|
||||
{
|
||||
check_access(shape(), args...);
|
||||
return this->operator()(args...);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a constant reference to the element at the specified position in the expression.
|
||||
* @param args a list of indices specifying the position in the expression. Indices
|
||||
* must be unsigned integers, the number of indices must be equal to the number of
|
||||
* dimensions of the expression, else the behavior is undefined.
|
||||
*
|
||||
* @warning This method is meant for performance, for expressions with a dynamic
|
||||
* number of dimensions (i.e. not known at compile time). Since it may have
|
||||
* undefined behavior (see parameters), operator() should be prefered whenever
|
||||
* it is possible.
|
||||
* @warning This method is NOT compatible with broadcasting, meaning the following
|
||||
* code has undefined behavior:
|
||||
* \code{.cpp}
|
||||
* xt::xarray<double> a = {{0, 1}, {2, 3}};
|
||||
* xt::xarray<double> b = {0, 1};
|
||||
* auto fd = a + b;
|
||||
* double res = fd.uncheked(0, 1);
|
||||
* \endcode
|
||||
*/
|
||||
template <class F, class R, class S>
|
||||
template <class... Args>
|
||||
inline auto xgenerator<F, R, S>::unchecked(Args... args) const -> const_reference
|
||||
{
|
||||
return m_f(args...);
|
||||
}
|
||||
|
||||
template <class F, class R, class S>
|
||||
template <class OS>
|
||||
inline auto xgenerator<F, R, S>::operator[](const OS& index) const
|
||||
-> disable_integral_t<OS, const_reference>
|
||||
{
|
||||
return element(index.cbegin(), index.cend());
|
||||
}
|
||||
|
||||
template <class F, class R, class S>
|
||||
template <class I>
|
||||
inline auto xgenerator<F, R, S>::operator[](std::initializer_list<I> index) const
|
||||
-> const_reference
|
||||
{
|
||||
return element(index.begin(), index.end());
|
||||
}
|
||||
|
||||
template <class F, class R, class S>
|
||||
inline auto xgenerator<F, R, S>::operator[](size_type i) const -> const_reference
|
||||
{
|
||||
return operator()(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a constant reference to the element at the specified position in the function.
|
||||
* @param first iterator starting the sequence of indices
|
||||
* @param last iterator ending the sequence of indices
|
||||
* The number of indices in the sequence should be equal to or greater
|
||||
* than the number of dimensions of the container.
|
||||
*/
|
||||
template <class F, class R, class S>
|
||||
template <class It>
|
||||
inline auto xgenerator<F, R, S>::element(It first, It last) const -> const_reference
|
||||
{
|
||||
using bounded_iterator = xbounded_iterator<It, typename shape_type::const_iterator>;
|
||||
XTENSOR_TRY(check_element_index(shape(), first, last));
|
||||
return m_f.element(bounded_iterator(first, shape().cbegin()), bounded_iterator(last, shape().cend()));
|
||||
}
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @name Broadcasting
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* Broadcast the shape of the function to the specified parameter.
|
||||
* @param shape the result shape
|
||||
* @param reuse_cache parameter for internal optimization
|
||||
* @return a boolean indicating whether the broadcasting is trivial
|
||||
*/
|
||||
template <class F, class R, class S>
|
||||
template <class O>
|
||||
inline bool xgenerator<F, R, S>::broadcast_shape(O& shape, bool) const
|
||||
{
|
||||
return xt::broadcast_shape(m_shape, shape);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the specified strides with those of the container to see whether
|
||||
* the broadcasting is trivial.
|
||||
* @return a boolean indicating whether the broadcasting is trivial
|
||||
*/
|
||||
template <class F, class R, class S>
|
||||
template <class O>
|
||||
inline bool xgenerator<F, R, S>::is_trivial_broadcast(const O& /*strides*/) const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//@}
|
||||
|
||||
template <class F, class R, class S>
|
||||
template <class O>
|
||||
inline auto xgenerator<F, R, S>::stepper_begin(const O& shape) const noexcept -> const_stepper
|
||||
{
|
||||
size_type offset = shape.size() - dimension();
|
||||
return const_stepper(this, offset);
|
||||
}
|
||||
|
||||
template <class F, class R, class S>
|
||||
template <class O>
|
||||
inline auto xgenerator<F, R, S>::stepper_end(const O& shape, layout_type) const noexcept -> const_stepper
|
||||
{
|
||||
size_type offset = shape.size() - dimension();
|
||||
return const_stepper(this, offset, true);
|
||||
}
|
||||
|
||||
template <class F, class R, class S>
|
||||
template <class E, class, class>
|
||||
inline void xgenerator<F, R, S>::assign_to(xexpression<E>& e) const noexcept
|
||||
{
|
||||
e.derived_cast().resize(m_shape);
|
||||
m_f.assign_to(e);
|
||||
}
|
||||
|
||||
template <class F, class R, class S>
|
||||
template <std::size_t dim>
|
||||
inline void xgenerator<F, R, S>::adapt_index() const
|
||||
{
|
||||
}
|
||||
|
||||
template <class F, class R, class S>
|
||||
template <std::size_t dim, class I, class... Args>
|
||||
inline void xgenerator<F, R, S>::adapt_index(I& arg, Args&... args) const
|
||||
{
|
||||
using value_type = typename decltype(m_shape)::value_type;
|
||||
if (sizeof...(Args) + 1 > m_shape.size())
|
||||
{
|
||||
adapt_index<dim>(args...);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (static_cast<value_type>(arg) >= m_shape[dim] && m_shape[dim] == 1)
|
||||
{
|
||||
arg = 0;
|
||||
}
|
||||
adapt_index<dim + 1>(args...);
|
||||
}
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
#ifdef X_OLD_CLANG
|
||||
template <class Functor, class I>
|
||||
inline auto make_xgenerator(Functor&& f, std::initializer_list<I> shape) noexcept
|
||||
{
|
||||
using shape_type = std::vector<std::size_t>;
|
||||
using type = xgenerator<Functor, typename Functor::value_type, shape_type>;
|
||||
return type(std::forward<Functor>(f), xtl::forward_sequence<shape_type>(shape));
|
||||
}
|
||||
#else
|
||||
template <class Functor, class I, std::size_t L>
|
||||
inline auto make_xgenerator(Functor&& f, const I (&shape)[L]) noexcept
|
||||
{
|
||||
using shape_type = std::array<std::size_t, L>;
|
||||
using type = xgenerator<Functor, typename Functor::value_type, shape_type>;
|
||||
return type(std::forward<Functor>(f), xtl::forward_sequence<shape_type>(shape));
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class Functor, class S>
|
||||
inline auto make_xgenerator(Functor&& f, S&& shape) noexcept
|
||||
{
|
||||
using type = xgenerator<Functor, typename Functor::value_type, std::decay_t<S>>;
|
||||
return type(std::forward<Functor>(f), std::forward<S>(shape));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
745
vendor/xtensor/include/xtensor/xindex_view.hpp
vendored
Normal file
745
vendor/xtensor/include/xtensor/xindex_view.hpp
vendored
Normal file
|
|
@ -0,0 +1,745 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTENSOR_INDEX_VIEW_HPP
|
||||
#define XTENSOR_INDEX_VIEW_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "xexpression.hpp"
|
||||
#include "xiterable.hpp"
|
||||
#include "xstrides.hpp"
|
||||
#include "xutils.hpp"
|
||||
|
||||
namespace xt
|
||||
{
|
||||
|
||||
template <class CT, class I>
|
||||
class xindex_view;
|
||||
|
||||
template <class CT, class I>
|
||||
struct xcontainer_inner_types<xindex_view<CT, I>>
|
||||
{
|
||||
using xexpression_type = std::decay_t<CT>;
|
||||
using temporary_type = xarray<typename xexpression_type::value_type, xexpression_type::static_layout>;
|
||||
};
|
||||
|
||||
template <class CT, class I>
|
||||
struct xiterable_inner_types<xindex_view<CT, I>>
|
||||
{
|
||||
using inner_shape_type = std::array<std::size_t, 1>;
|
||||
using const_stepper = xindexed_stepper<xindex_view<CT, I>, true>;
|
||||
using stepper = xindexed_stepper<xindex_view<CT, I>, false>;
|
||||
};
|
||||
|
||||
/***************
|
||||
* xindex_view *
|
||||
***************/
|
||||
|
||||
/**
|
||||
* @class xindex_view
|
||||
* @brief View of an xexpression from vector of indices.
|
||||
*
|
||||
* The xindex_view class implements a flat (1D) view into a multidimensional
|
||||
* xexpression yielding the values at the indices of the index array.
|
||||
* xindex_view is not meant to be used directly, but only with the \ref index_view
|
||||
* and \ref filter helper functions.
|
||||
*
|
||||
* @tparam CT the closure type of the \ref xexpression type underlying this view
|
||||
* @tparam I the index array type of the view
|
||||
*
|
||||
* @sa index_view, filter
|
||||
*/
|
||||
template <class CT, class I>
|
||||
class xindex_view : public xview_semantic<xindex_view<CT, I>>,
|
||||
public xiterable<xindex_view<CT, I>>
|
||||
{
|
||||
public:
|
||||
|
||||
using self_type = xindex_view<CT, I>;
|
||||
using xexpression_type = std::decay_t<CT>;
|
||||
using semantic_base = xview_semantic<self_type>;
|
||||
|
||||
using value_type = typename xexpression_type::value_type;
|
||||
using reference = typename xexpression_type::reference;
|
||||
using const_reference = typename xexpression_type::const_reference;
|
||||
using pointer = typename xexpression_type::pointer;
|
||||
using const_pointer = typename xexpression_type::const_pointer;
|
||||
using size_type = typename xexpression_type::size_type;
|
||||
using difference_type = typename xexpression_type::difference_type;
|
||||
|
||||
using iterable_base = xiterable<self_type>;
|
||||
using inner_shape_type = typename iterable_base::inner_shape_type;
|
||||
using shape_type = inner_shape_type;
|
||||
using strides_type = shape_type;
|
||||
|
||||
using indices_type = I;
|
||||
|
||||
using stepper = typename iterable_base::stepper;
|
||||
using const_stepper = typename iterable_base::const_stepper;
|
||||
|
||||
using temporary_type = typename xcontainer_inner_types<self_type>::temporary_type;
|
||||
using base_index_type = xindex_type_t<shape_type>;
|
||||
|
||||
static constexpr layout_type static_layout = layout_type::dynamic;
|
||||
static constexpr bool contiguous_layout = false;
|
||||
|
||||
template <class CTA, class I2>
|
||||
xindex_view(CTA&& e, I2&& indices) noexcept;
|
||||
|
||||
template <class E>
|
||||
self_type& operator=(const xexpression<E>& e);
|
||||
|
||||
template <class E>
|
||||
disable_xexpression<E, self_type>& operator=(const E& e);
|
||||
|
||||
size_type size() const noexcept;
|
||||
size_type dimension() const noexcept;
|
||||
const inner_shape_type& shape() const noexcept;
|
||||
layout_type layout() const noexcept;
|
||||
|
||||
template <class T>
|
||||
void fill(const T& value);
|
||||
|
||||
reference operator()(size_type idx = size_type(0));
|
||||
template <class... Args>
|
||||
reference operator()(size_type idx0, size_type idx1, Args... args);
|
||||
reference unchecked(size_type idx);
|
||||
template <class S>
|
||||
disable_integral_t<S, reference> operator[](const S& index);
|
||||
template <class OI>
|
||||
reference operator[](std::initializer_list<OI> index);
|
||||
reference operator[](size_type i);
|
||||
|
||||
template <class It>
|
||||
reference element(It first, It last);
|
||||
|
||||
const_reference operator()(size_type idx = size_type(0)) const;
|
||||
template <class... Args>
|
||||
const_reference operator()(size_type idx0, size_type idx1, Args... args) const;
|
||||
const_reference unchecked(size_type idx) const;
|
||||
template <class S>
|
||||
disable_integral_t<S, const_reference> operator[](const S& index) const;
|
||||
template <class OI>
|
||||
const_reference operator[](std::initializer_list<OI> index) const;
|
||||
const_reference operator[](size_type i) const;
|
||||
|
||||
template <class It>
|
||||
const_reference element(It first, It last) const;
|
||||
|
||||
template <class O>
|
||||
bool broadcast_shape(O& shape, bool reuse_cache = false) const;
|
||||
|
||||
template <class O>
|
||||
bool is_trivial_broadcast(const O& /*strides*/) const noexcept;
|
||||
|
||||
template <class ST>
|
||||
stepper stepper_begin(const ST& shape);
|
||||
template <class ST>
|
||||
stepper stepper_end(const ST& shape, layout_type);
|
||||
|
||||
template <class ST>
|
||||
const_stepper stepper_begin(const ST& shape) const;
|
||||
template <class ST>
|
||||
const_stepper stepper_end(const ST& shape, layout_type) const;
|
||||
|
||||
private:
|
||||
|
||||
CT m_e;
|
||||
const indices_type m_indices;
|
||||
const inner_shape_type m_shape;
|
||||
|
||||
void assign_temporary_impl(temporary_type&& tmp);
|
||||
|
||||
friend class xview_semantic<xindex_view<CT, I>>;
|
||||
};
|
||||
|
||||
/***************
|
||||
* xfiltration *
|
||||
***************/
|
||||
|
||||
/**
|
||||
* @class xfiltration
|
||||
* @brief Filter of a xexpression for fast scalar assign.
|
||||
*
|
||||
* The xfiltration class implements a lazy filtration of a multidimentional
|
||||
* \ref xexpression, optimized for scalar and computed scalar assignments.
|
||||
* Actually, the \ref xfiltration class IS NOT an \ref xexpression and the
|
||||
* scalar and computed scalar assignments are the only method it provides.
|
||||
* The filtering condition is not evaluated until the filtration is assigned.
|
||||
*
|
||||
* xfiltration is not meant to be used directly, but only with the \ref filtration
|
||||
* helper function.
|
||||
*
|
||||
* @tparam ECT the closure type of the \ref xexpression type underlying this filtration
|
||||
* @tparam CCR the closure type of the filtering \ref xexpression type
|
||||
*
|
||||
* @sa filtration
|
||||
*/
|
||||
template <class ECT, class CCT>
|
||||
class xfiltration
|
||||
{
|
||||
public:
|
||||
|
||||
using self_type = xfiltration<ECT, CCT>;
|
||||
using xexpression_type = std::decay_t<ECT>;
|
||||
using const_reference = typename xexpression_type::const_reference;
|
||||
|
||||
template <class ECTA, class CCTA>
|
||||
xfiltration(ECTA&& e, CCTA&& condition);
|
||||
|
||||
template <class E>
|
||||
disable_xexpression<E, self_type&> operator=(const E&);
|
||||
|
||||
template <class E>
|
||||
disable_xexpression<E, self_type&> operator+=(const E&);
|
||||
|
||||
template <class E>
|
||||
disable_xexpression<E, self_type&> operator-=(const E&);
|
||||
|
||||
template <class E>
|
||||
disable_xexpression<E, self_type&> operator*=(const E&);
|
||||
|
||||
template <class E>
|
||||
disable_xexpression<E, self_type&> operator/=(const E&);
|
||||
|
||||
template <class E>
|
||||
disable_xexpression<E, self_type&> operator%=(const E&);
|
||||
|
||||
private:
|
||||
|
||||
template <class F>
|
||||
self_type& apply(F&& func);
|
||||
|
||||
ECT m_e;
|
||||
CCT m_condition;
|
||||
};
|
||||
|
||||
/******************************
|
||||
* xindex_view implementation *
|
||||
******************************/
|
||||
|
||||
/**
|
||||
* @name Constructor
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* Constructs an xindex_view, selecting the indices specified by \a indices.
|
||||
* The resulting xexpression has a 1D shape with a length of n for n indices.
|
||||
*
|
||||
* @param e the underlying xexpression for this view
|
||||
* @param indices the indices to select
|
||||
*/
|
||||
template <class CT, class I>
|
||||
template <class CTA, class I2>
|
||||
inline xindex_view<CT, I>::xindex_view(CTA&& e, I2&& indices) noexcept
|
||||
: m_e(std::forward<CTA>(e)), m_indices(std::forward<I2>(indices)), m_shape({ m_indices.size() })
|
||||
{
|
||||
}
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @name Extended copy semantic
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* The extended assignment operator.
|
||||
*/
|
||||
template <class CT, class I>
|
||||
template <class E>
|
||||
inline auto xindex_view<CT, I>::operator=(const xexpression<E>& e) -> self_type&
|
||||
{
|
||||
return semantic_base::operator=(e);
|
||||
}
|
||||
//@}
|
||||
|
||||
template <class CT, class I>
|
||||
template <class E>
|
||||
inline auto xindex_view<CT, I>::operator=(const E& e) -> disable_xexpression<E, self_type>&
|
||||
{
|
||||
std::fill(this->begin(), this->end(), e);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class CT, class I>
|
||||
inline void xindex_view<CT, I>::assign_temporary_impl(temporary_type&& tmp)
|
||||
{
|
||||
std::copy(tmp.cbegin(), tmp.cend(), this->begin());
|
||||
}
|
||||
|
||||
/**
|
||||
* @name Size and shape
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* Returns the size of the xindex_view.
|
||||
*/
|
||||
template <class CT, class I>
|
||||
inline auto xindex_view<CT, I>::size() const noexcept -> size_type
|
||||
{
|
||||
return compute_size(shape());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of dimensions of the xindex_view.
|
||||
*/
|
||||
template <class CT, class I>
|
||||
inline auto xindex_view<CT, I>::dimension() const noexcept -> size_type
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the shape of the xindex_view.
|
||||
*/
|
||||
template <class CT, class I>
|
||||
inline auto xindex_view<CT, I>::shape() const noexcept -> const inner_shape_type&
|
||||
{
|
||||
return m_shape;
|
||||
}
|
||||
|
||||
template <class CT, class I>
|
||||
inline layout_type xindex_view<CT, I>::layout() const noexcept
|
||||
{
|
||||
return static_layout;
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @name Data
|
||||
*/
|
||||
//@{
|
||||
|
||||
/**
|
||||
* Fills the view with the given value.
|
||||
* @param value the value to fill the view with.
|
||||
*/
|
||||
template <class CT, class I>
|
||||
template <class T>
|
||||
inline void xindex_view<CT, I>::fill(const T& value)
|
||||
{
|
||||
std::fill(this->storage_begin(), this->storage_end(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the element at the specified position in the xindex_view.
|
||||
* @param idx index specifying the position in the index_view. More indices may be provided,
|
||||
* only the last one will be used.
|
||||
*/
|
||||
template <class CT, class I>
|
||||
inline auto xindex_view<CT, I>::operator()(size_type idx) -> reference
|
||||
{
|
||||
return m_e[m_indices[idx]];
|
||||
}
|
||||
|
||||
template <class CT, class I>
|
||||
template <class... Args>
|
||||
inline auto xindex_view<CT, I>::operator()(size_type, size_type idx1, Args... args) -> reference
|
||||
{
|
||||
return this->operator()(idx1, static_cast<size_type>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the element at the specified position in the xindex_view.
|
||||
* @param idx index specifying the position in the index_view.
|
||||
*/
|
||||
template <class CT, class I>
|
||||
inline auto xindex_view<CT, I>::unchecked(size_type idx) -> reference
|
||||
{
|
||||
return this->operator()(idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a constant reference to the element at the specified position in the xindex_view.
|
||||
* @param idx index specifying the position in the index_view. More indices may be provided,
|
||||
* only the last one will be used.
|
||||
*/
|
||||
template <class CT, class I>
|
||||
inline auto xindex_view<CT, I>::operator()(size_type idx) const -> const_reference
|
||||
{
|
||||
return m_e[m_indices[idx]];
|
||||
}
|
||||
|
||||
template <class CT, class I>
|
||||
template <class... Args>
|
||||
inline auto xindex_view<CT, I>::operator()(size_type, size_type idx1, Args... args) const -> const_reference
|
||||
{
|
||||
return this->operator()(idx1, args...);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a constant reference to the element at the specified position in the xindex_view.
|
||||
* @param idx index specifying the position in the index_view.
|
||||
*/
|
||||
template <class CT, class I>
|
||||
inline auto xindex_view<CT, I>::unchecked(size_type idx) const -> const_reference
|
||||
{
|
||||
return this->operator()(idx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the element at the specified position in the container.
|
||||
* @param index a sequence of indices specifying the position in the container. Indices
|
||||
* must be unsigned integers, the number of indices in the list should be equal or greater
|
||||
* than the number of dimensions of the container.
|
||||
*/
|
||||
template <class CT, class I>
|
||||
template <class S>
|
||||
inline auto xindex_view<CT, I>::operator[](const S& index)
|
||||
-> disable_integral_t<S, reference>
|
||||
{
|
||||
return m_e[m_indices[index[0]]];
|
||||
}
|
||||
|
||||
template <class CT, class I>
|
||||
template <class OI>
|
||||
inline auto xindex_view<CT, I>::operator[](std::initializer_list<OI> index)
|
||||
-> reference
|
||||
{
|
||||
return m_e[m_indices[*(index.begin())]];
|
||||
}
|
||||
|
||||
template <class CT, class I>
|
||||
inline auto xindex_view<CT, I>::operator[](size_type i) -> reference
|
||||
{
|
||||
return operator()(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a constant reference to the element at the specified position in the container.
|
||||
* @param index a sequence of indices specifying the position in the container. Indices
|
||||
* must be unsigned integers, the number of indices in the list should be equal or greater
|
||||
* than the number of dimensions of the container.
|
||||
*/
|
||||
template <class CT, class I>
|
||||
template <class S>
|
||||
inline auto xindex_view<CT, I>::operator[](const S& index) const
|
||||
-> disable_integral_t<S, const_reference>
|
||||
{
|
||||
return m_e[m_indices[index[0]]];
|
||||
}
|
||||
|
||||
template <class CT, class I>
|
||||
template <class OI>
|
||||
inline auto xindex_view<CT, I>::operator[](std::initializer_list<OI> index) const
|
||||
-> const_reference
|
||||
{
|
||||
return m_e[m_indices[*(index.begin())]];
|
||||
}
|
||||
|
||||
template <class CT, class I>
|
||||
inline auto xindex_view<CT, I>::operator[](size_type i) const -> const_reference
|
||||
{
|
||||
return operator()(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the element at the specified position in the xindex_view.
|
||||
* @param first iterator starting the sequence of indices
|
||||
* The number of indices in the sequence should be equal to or greater 1.
|
||||
*/
|
||||
template <class CT, class I>
|
||||
template <class It>
|
||||
inline auto xindex_view<CT, I>::element(It first, It /*last*/) -> reference
|
||||
{
|
||||
return m_e[m_indices[(*first)]];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the element at the specified position in the xindex_view.
|
||||
* @param first iterator starting the sequence of indices
|
||||
* The number of indices in the sequence should be equal to or greater 1.
|
||||
*/
|
||||
template <class CT, class I>
|
||||
template <class It>
|
||||
inline auto xindex_view<CT, I>::element(It first, It /*last*/) const -> const_reference
|
||||
{
|
||||
return m_e[m_indices[(*first)]];
|
||||
}
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @name Broadcasting
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* Broadcast the shape of the xindex_view to the specified parameter.
|
||||
* @param shape the result shape
|
||||
* @param reuse_cache parameter for internal optimization
|
||||
* @return a boolean indicating whether the broadcasting is trivial
|
||||
*/
|
||||
template <class CT, class I>
|
||||
template <class O>
|
||||
inline bool xindex_view<CT, I>::broadcast_shape(O& shape, bool) const
|
||||
{
|
||||
return xt::broadcast_shape(m_shape, shape);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the specified strides with those of the container to see whether
|
||||
* the broadcasting is trivial.
|
||||
* @return a boolean indicating whether the broadcasting is trivial
|
||||
*/
|
||||
template <class CT, class I>
|
||||
template <class O>
|
||||
inline bool xindex_view<CT, I>::is_trivial_broadcast(const O& /*strides*/) const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
//@}
|
||||
|
||||
/***************
|
||||
* stepper api *
|
||||
***************/
|
||||
|
||||
template <class CT, class I>
|
||||
template <class ST>
|
||||
inline auto xindex_view<CT, I>::stepper_begin(const ST& shape) -> stepper
|
||||
{
|
||||
size_type offset = shape.size() - dimension();
|
||||
return stepper(this, offset);
|
||||
}
|
||||
|
||||
template <class CT, class I>
|
||||
template <class ST>
|
||||
inline auto xindex_view<CT, I>::stepper_end(const ST& shape, layout_type) -> stepper
|
||||
{
|
||||
size_type offset = shape.size() - dimension();
|
||||
return stepper(this, offset, true);
|
||||
}
|
||||
|
||||
template <class CT, class I>
|
||||
template <class ST>
|
||||
inline auto xindex_view<CT, I>::stepper_begin(const ST& shape) const -> const_stepper
|
||||
{
|
||||
size_type offset = shape.size() - dimension();
|
||||
return const_stepper(this, offset);
|
||||
}
|
||||
|
||||
template <class CT, class I>
|
||||
template <class ST>
|
||||
inline auto xindex_view<CT, I>::stepper_end(const ST& shape, layout_type) const -> const_stepper
|
||||
{
|
||||
size_type offset = shape.size() - dimension();
|
||||
return const_stepper(this, offset, true);
|
||||
}
|
||||
|
||||
/******************************
|
||||
* xfiltration implementation *
|
||||
******************************/
|
||||
|
||||
/**
|
||||
* @name Constructor
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* Constructs a xfiltration on the given expression \c e, selecting
|
||||
* the elements matching the specified \c condition.
|
||||
*
|
||||
* @param e the \ref xexpression to filter.
|
||||
* @param condition the filtering \ref xexpression to apply.
|
||||
*/
|
||||
template <class ECT, class CCT>
|
||||
template <class ECTA, class CCTA>
|
||||
inline xfiltration<ECT, CCT>::xfiltration(ECTA&& e, CCTA&& condition)
|
||||
: m_e(std::forward<ECTA>(e)), m_condition(std::forward<CCTA>(condition))
|
||||
{
|
||||
}
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @name Extended copy semantic
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* Assigns the scalar \c e to \c *this.
|
||||
* @param e the scalar to assign.
|
||||
* @return a reference to \ *this.
|
||||
*/
|
||||
template <class ECT, class CCT>
|
||||
template <class E>
|
||||
inline auto xfiltration<ECT, CCT>::operator=(const E& e) -> disable_xexpression<E, self_type&>
|
||||
{
|
||||
return apply([this, &e](const_reference v, bool cond) { return cond ? e : v; });
|
||||
}
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @name Computed assignement
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* Adds the scalar \c e to \c *this.
|
||||
* @param e the scalar to add.
|
||||
* @return a reference to \c *this.
|
||||
*/
|
||||
template <class ECT, class CCT>
|
||||
template <class E>
|
||||
inline auto xfiltration<ECT, CCT>::operator+=(const E& e) -> disable_xexpression<E, self_type&>
|
||||
{
|
||||
return apply([this, &e](const_reference v, bool cond) { return cond ? v + e : v; });
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtracts the scalar \c e from \c *this.
|
||||
* @param e the scalar to subtract.
|
||||
* @return a reference to \c *this.
|
||||
*/
|
||||
template <class ECT, class CCT>
|
||||
template <class E>
|
||||
inline auto xfiltration<ECT, CCT>::operator-=(const E& e) -> disable_xexpression<E, self_type&>
|
||||
{
|
||||
return apply([this, &e](const_reference v, bool cond) { return cond ? v - e : v; });
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies \c *this with the scalar \c e.
|
||||
* @param e the scalar involved in the operation.
|
||||
* @return a reference to \c *this.
|
||||
*/
|
||||
template <class ECT, class CCT>
|
||||
template <class E>
|
||||
inline auto xfiltration<ECT, CCT>::operator*=(const E& e) -> disable_xexpression<E, self_type&>
|
||||
{
|
||||
return apply([this, &e](const_reference v, bool cond) { return cond ? v * e : v; });
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides \c *this by the scalar \c e.
|
||||
* @param e the scalar involved in the operation.
|
||||
* @return a reference to \c *this.
|
||||
*/
|
||||
template <class ECT, class CCT>
|
||||
template <class E>
|
||||
inline auto xfiltration<ECT, CCT>::operator/=(const E& e) -> disable_xexpression<E, self_type&>
|
||||
{
|
||||
return apply([this, &e](const_reference v, bool cond) { return cond ? v / e : v; });
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the remainder of \c *this after division by the scalar \c e.
|
||||
* @param e the scalar involved in the operation.
|
||||
* @return a reference to \c *this.
|
||||
*/
|
||||
template <class ECT, class CCT>
|
||||
template <class E>
|
||||
inline auto xfiltration<ECT, CCT>::operator%=(const E& e) -> disable_xexpression<E, self_type&>
|
||||
{
|
||||
return apply([this, &e](const_reference v, bool cond) { return cond ? v % e : v; });
|
||||
}
|
||||
|
||||
template <class ECT, class CCT>
|
||||
template <class F>
|
||||
inline auto xfiltration<ECT, CCT>::apply(F&& func) -> self_type&
|
||||
{
|
||||
std::transform(m_e.cbegin(), m_e.cend(), m_condition.cbegin(), m_e.begin(), func);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief creates an indexview from a container of indices.
|
||||
*
|
||||
* Returns a 1D view with the elements at \a indices selected.
|
||||
*
|
||||
* @param e the underlying xexpression
|
||||
* @param indices the indices to select
|
||||
*
|
||||
* \code{.cpp}
|
||||
* xarray<double> a = {{1,5,3}, {4,5,6}};
|
||||
* b = index_view(a, {{0, 0}, {1, 0}, {1, 1}});
|
||||
* std::cout << b << std::endl; // {1, 4, 5}
|
||||
* b += 100;
|
||||
* std::cout << a << std::endl; // {{101, 5, 3}, {104, 105, 6}}
|
||||
* \endcode
|
||||
*/
|
||||
template <class E, class I>
|
||||
inline auto index_view(E&& e, I&& indices) noexcept
|
||||
{
|
||||
using view_type = xindex_view<xclosure_t<E>, std::decay_t<I>>;
|
||||
return view_type(std::forward<E>(e), std::forward<I>(indices));
|
||||
}
|
||||
#ifdef X_OLD_CLANG
|
||||
template <class E, class I>
|
||||
inline auto index_view(E&& e, std::initializer_list<std::initializer_list<I>> indices) noexcept
|
||||
{
|
||||
std::vector<xindex> idx;
|
||||
for (auto it = indices.begin(); it != indices.end(); ++it)
|
||||
{
|
||||
idx.emplace_back(xindex(it->begin(), it->end()));
|
||||
}
|
||||
using view_type = xindex_view<xclosure_t<E>, std::vector<xindex>>;
|
||||
return view_type(std::forward<E>(e), std::move(idx));
|
||||
}
|
||||
#else
|
||||
template <class E, std::size_t L>
|
||||
inline auto index_view(E&& e, const xindex (&indices)[L]) noexcept
|
||||
{
|
||||
using view_type = xindex_view<xclosure_t<E>, std::array<xindex, L>>;
|
||||
return view_type(std::forward<E>(e), to_array(indices));
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief creates a view into \a e filtered by \a condition.
|
||||
*
|
||||
* Returns a 1D view with the elements selected where \a condition evaluates to \em true.
|
||||
* This is equivalent to \verbatim{index_view(e, where(condition));}\endverbatim
|
||||
* The returned view is not optimal if you just want to assign a scalar to the filtered
|
||||
* elements. In that case, you should consider using the \ref filtration function
|
||||
* instead.
|
||||
*
|
||||
* @param e the underlying xexpression
|
||||
* @param condition xexpression with shape of \a e which selects indices
|
||||
*
|
||||
* \code{.cpp}
|
||||
* xarray<double> a = {{1,5,3}, {4,5,6}};
|
||||
* b = filter(a, a >= 5);
|
||||
* std::cout << b << std::endl; // {5, 5, 6}
|
||||
* \endcode
|
||||
*
|
||||
* \sa filtration
|
||||
*/
|
||||
template <class E, class O>
|
||||
inline auto filter(E&& e, O&& condition) noexcept
|
||||
{
|
||||
auto indices = where(std::forward<O>(condition));
|
||||
using view_type = xindex_view<xclosure_t<E>, decltype(indices)>;
|
||||
return view_type(std::forward<E>(e), std::move(indices));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief creates a filtration of \c e filtered by \a condition.
|
||||
*
|
||||
* Returns a lazy filtration optimized for scalar assignment.
|
||||
* Actually, scalar assignment and computed scalar assignments
|
||||
* are the only available methods of the filtration, the filtration
|
||||
* IS NOT an \ref xexpression.
|
||||
*
|
||||
* @param e the \ref xexpression to filter
|
||||
* @param condition the filtering \ref xexpression
|
||||
*
|
||||
* \code{.cpp}
|
||||
* xarray<double> a = {{1,5,3}, {4,5,6}};
|
||||
* filtration(a, a >= 5) += 2;
|
||||
* std::cout << a << std::endl; // {{1, 7, 3}, {4, 7, 8}}
|
||||
* \endcode
|
||||
*/
|
||||
template <class E, class C>
|
||||
inline auto filtration(E&& e, C&& condition) noexcept
|
||||
{
|
||||
using filtration_type = xfiltration<xclosure_t<E>, xclosure_t<C>>;
|
||||
return filtration_type(std::forward<E>(e), std::forward<C>(condition));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
139
vendor/xtensor/include/xtensor/xinfo.hpp
vendored
Normal file
139
vendor/xtensor/include/xtensor/xinfo.hpp
vendored
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTENSOR_INFO_HPP
|
||||
#define XTENSOR_INFO_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
# if __cplusplus < 201103
|
||||
# define CONSTEXPR11_TN
|
||||
# define CONSTEXPR14_TN
|
||||
# define NOEXCEPT_TN
|
||||
# elif __cplusplus < 201402
|
||||
# define CONSTEXPR11_TN constexpr
|
||||
# define CONSTEXPR14_TN
|
||||
# define NOEXCEPT_TN noexcept
|
||||
# else
|
||||
# define CONSTEXPR11_TN constexpr
|
||||
# define CONSTEXPR14_TN constexpr
|
||||
# define NOEXCEPT_TN noexcept
|
||||
# endif
|
||||
#else // _MSC_VER
|
||||
# if _MSC_VER < 1900
|
||||
# define CONSTEXPR11_TN
|
||||
# define CONSTEXPR14_TN
|
||||
# define NOEXCEPT_TN
|
||||
# elif _MSC_VER < 2000
|
||||
# define CONSTEXPR11_TN constexpr
|
||||
# define CONSTEXPR14_TN
|
||||
# define NOEXCEPT_TN noexcept
|
||||
# else
|
||||
# define CONSTEXPR11_TN constexpr
|
||||
# define CONSTEXPR14_TN constexpr
|
||||
# define NOEXCEPT_TN noexcept
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace xt
|
||||
{
|
||||
// see http://stackoverflow.com/a/20170989
|
||||
struct static_string
|
||||
{
|
||||
template <std::size_t N>
|
||||
explicit CONSTEXPR11_TN static_string(const char (&a)[N]) NOEXCEPT_TN
|
||||
: data(a), size(N - 1)
|
||||
{
|
||||
}
|
||||
|
||||
CONSTEXPR11_TN static_string(const char* a, const std::size_t sz) NOEXCEPT_TN
|
||||
: data(a), size(sz)
|
||||
{
|
||||
}
|
||||
|
||||
const char* const data;
|
||||
const std::size_t size;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
CONSTEXPR14_TN static_string type_name()
|
||||
{
|
||||
#ifdef __clang__
|
||||
static_string p(__PRETTY_FUNCTION__);
|
||||
return static_string(p.data + 39, p.size - 39 - 1);
|
||||
#elif defined(__GNUC__)
|
||||
static_string p(__PRETTY_FUNCTION__);
|
||||
#if __cplusplus < 201402
|
||||
return static_string(p.data + 36, p.size - 36 - 1);
|
||||
#else
|
||||
return static_string(p.data + 54, p.size - 54 - 1);
|
||||
#endif
|
||||
#elif defined(_MSC_VER)
|
||||
static const static_string p(__FUNCSIG__);
|
||||
return static_string(p.data + 47, p.size - 47 - 7);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::string type_to_string()
|
||||
{
|
||||
static_string static_name = type_name<T>();
|
||||
return std::string(static_name.data, static_name.size);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
std::string info(const T& t)
|
||||
{
|
||||
std::string s;
|
||||
s += "\nValue type: " + type_to_string<typename T::value_type>();
|
||||
s += "\nLayout: ";
|
||||
if (t.layout() == layout_type::row_major)
|
||||
{
|
||||
s += "row_major";
|
||||
}
|
||||
else if (t.layout() == layout_type::column_major)
|
||||
{
|
||||
s += "column_major";
|
||||
}
|
||||
else if (t.layout() == layout_type::dynamic)
|
||||
{
|
||||
s += "dynamic";
|
||||
}
|
||||
else
|
||||
{
|
||||
s += "any";
|
||||
}
|
||||
s += "\nShape: (";
|
||||
bool first = true;
|
||||
for (const auto& el : t.shape())
|
||||
{
|
||||
if (!first)
|
||||
{
|
||||
s += ", ";
|
||||
}
|
||||
first = false;
|
||||
s += std::to_string(el);
|
||||
}
|
||||
s += ")\nStrides: (";
|
||||
first = true;
|
||||
for (const auto& el : t.strides())
|
||||
{
|
||||
if (!first)
|
||||
{
|
||||
s += ", ";
|
||||
}
|
||||
first = false;
|
||||
s += std::to_string(el);
|
||||
}
|
||||
s += ")\nSize: " + std::to_string(t.size()) + "\n";
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
634
vendor/xtensor/include/xtensor/xio.hpp
vendored
Normal file
634
vendor/xtensor/include/xtensor/xio.hpp
vendored
Normal file
|
|
@ -0,0 +1,634 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTENSOR_IO_HPP
|
||||
#define XTENSOR_IO_HPP
|
||||
|
||||
#include <complex>
|
||||
#include <cstddef>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <numeric>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "xexpression.hpp"
|
||||
#include "xmath.hpp"
|
||||
#include "xstrided_view.hpp"
|
||||
|
||||
namespace xt
|
||||
{
|
||||
|
||||
template <class E>
|
||||
inline std::ostream& operator<<(std::ostream& out, const xexpression<E>& e);
|
||||
|
||||
namespace print_options
|
||||
{
|
||||
struct print_options_impl
|
||||
{
|
||||
std::size_t edgeitems = 3;
|
||||
std::size_t line_width = 75;
|
||||
std::size_t threshold = 1000;
|
||||
std::streamsize precision = -1; // default precision
|
||||
};
|
||||
|
||||
inline print_options_impl& print_options()
|
||||
{
|
||||
static print_options_impl po;
|
||||
return po;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the line width. After \a line_width chars,
|
||||
* a new line is added.
|
||||
*
|
||||
* @param line_width The line width
|
||||
*/
|
||||
inline void set_line_width(std::size_t line_width)
|
||||
{
|
||||
print_options().line_width = line_width;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the threshold after which summarization is triggered (default: 1000).
|
||||
*
|
||||
* @param threshold The number of elements in the xexpression that triggers
|
||||
* summarization in the output
|
||||
*/
|
||||
inline void set_threshold(std::size_t threshold)
|
||||
{
|
||||
print_options().threshold = threshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the number of edge items. If the summarization is
|
||||
* triggered, this value defines how many items of each dimension
|
||||
* are printed.
|
||||
*
|
||||
* @param edgeitems The number of edge items
|
||||
*/
|
||||
inline void set_edgeitems(std::size_t edgeitems)
|
||||
{
|
||||
print_options().edgeitems = edgeitems;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the precision for printing floating point values.
|
||||
*
|
||||
* @param precision The number of digits for floating point output
|
||||
*/
|
||||
inline void set_precision(std::streamsize precision)
|
||||
{
|
||||
print_options().precision = precision;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************
|
||||
* xexpression ostream implementation *
|
||||
**************************************/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class E, class F>
|
||||
std::ostream& xoutput(std::ostream& out, const E& e,
|
||||
xstrided_slice_vector& slices, F& printer, std::size_t blanks,
|
||||
std::streamsize element_width, std::size_t edgeitems, std::size_t line_width)
|
||||
{
|
||||
using size_type = typename E::size_type;
|
||||
|
||||
const auto view = xt::strided_view(e, slices);
|
||||
if (view.dimension() == 0)
|
||||
{
|
||||
printer.print_next(out);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string indents(blanks, ' ');
|
||||
|
||||
size_type i = 0;
|
||||
size_type elems_on_line = 0;
|
||||
size_type ewp2 = static_cast<size_type>(element_width) + size_type(2);
|
||||
size_type line_lim = static_cast<size_type>(std::floor(line_width / ewp2));
|
||||
|
||||
out << '{';
|
||||
for (; i != size_type(view.shape()[0] - 1); ++i)
|
||||
{
|
||||
if (edgeitems && size_type(view.shape()[0]) > (edgeitems * 2) && i == edgeitems)
|
||||
{
|
||||
out << "..., ";
|
||||
if (view.dimension() > 1)
|
||||
{
|
||||
elems_on_line = 0;
|
||||
out << std::endl
|
||||
<< indents;
|
||||
}
|
||||
i = size_type(view.shape()[0]) - edgeitems;
|
||||
}
|
||||
if (view.dimension() == 1 && line_lim != 0 && elems_on_line >= line_lim)
|
||||
{
|
||||
out << std::endl
|
||||
<< indents;
|
||||
elems_on_line = 0;
|
||||
}
|
||||
slices.push_back(static_cast<int>(i));
|
||||
xoutput(out, e, slices, printer, blanks + 1, element_width, edgeitems, line_width) << ',';
|
||||
slices.pop_back();
|
||||
elems_on_line++;
|
||||
|
||||
if (view.dimension() == 1)
|
||||
{
|
||||
out << ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
out << std::endl
|
||||
<< indents;
|
||||
}
|
||||
}
|
||||
if (view.dimension() == 1 && line_lim != 0 && elems_on_line >= line_lim)
|
||||
{
|
||||
out << std::endl
|
||||
<< indents;
|
||||
}
|
||||
slices.push_back(static_cast<int>(i));
|
||||
xoutput(out, e, slices, printer, blanks + 1, element_width, edgeitems, line_width) << '}';
|
||||
slices.pop_back();
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
template <class F, class E>
|
||||
static void recurser_run(F& fn, const E& e, xstrided_slice_vector& slices, std::size_t lim = 0)
|
||||
{
|
||||
using size_type = typename E::size_type;
|
||||
const auto view = strided_view(e, slices);
|
||||
if (view.dimension() == 0)
|
||||
{
|
||||
fn.update(view());
|
||||
}
|
||||
else
|
||||
{
|
||||
size_type i = 0;
|
||||
for (; i != static_cast<size_type>(view.shape()[0] - 1); ++i)
|
||||
{
|
||||
if (lim && size_type(view.shape()[0]) > (lim * 2) && i == lim)
|
||||
{
|
||||
i = static_cast<size_type>(view.shape()[0]) - lim;
|
||||
}
|
||||
slices.push_back(static_cast<int>(i));
|
||||
recurser_run(fn, e, slices, lim);
|
||||
slices.pop_back();
|
||||
}
|
||||
slices.push_back(static_cast<int>(i));
|
||||
recurser_run(fn, e, slices, lim);
|
||||
slices.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class E = void>
|
||||
struct printer;
|
||||
|
||||
template <class T>
|
||||
struct printer<T, std::enable_if_t<std::is_floating_point<typename T::value_type>::value>>
|
||||
{
|
||||
using value_type = std::decay_t<typename T::value_type>;
|
||||
using cache_type = std::vector<value_type>;
|
||||
using cache_iterator = typename cache_type::const_iterator;
|
||||
|
||||
explicit printer(std::streamsize precision)
|
||||
: m_precision(precision)
|
||||
{
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
m_precision = m_required_precision < m_precision ? m_required_precision : m_precision;
|
||||
m_it = m_cache.cbegin();
|
||||
if (m_scientific)
|
||||
{
|
||||
// 3 = sign, number and dot and 4 = "e+00"
|
||||
m_width = m_precision + 7;
|
||||
if (m_large_exponent)
|
||||
{
|
||||
// = e+000 (additional number)
|
||||
m_width += 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::streamsize decimals = 1; // print a leading 0
|
||||
if (std::floor(m_max) != 0)
|
||||
{
|
||||
decimals += std::streamsize(std::log10(std::floor(m_max)));
|
||||
}
|
||||
// 2 => sign and dot
|
||||
m_width = 2 + decimals + m_precision;
|
||||
}
|
||||
if (!m_required_precision)
|
||||
{
|
||||
--m_width;
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& print_next(std::ostream& out)
|
||||
{
|
||||
if (!m_scientific)
|
||||
{
|
||||
std::stringstream buf;
|
||||
buf.width(m_width);
|
||||
buf << std::fixed;
|
||||
buf.precision(m_precision);
|
||||
buf << (*m_it);
|
||||
if (!m_required_precision)
|
||||
{
|
||||
buf << '.';
|
||||
}
|
||||
std::string res = buf.str();
|
||||
auto sit = res.rbegin();
|
||||
while (*sit == '0')
|
||||
{
|
||||
*sit = ' ';
|
||||
++sit;
|
||||
}
|
||||
out << res;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!m_large_exponent)
|
||||
{
|
||||
out << std::scientific;
|
||||
out.width(m_width);
|
||||
out << (*m_it);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::stringstream buf;
|
||||
buf.width(m_width);
|
||||
buf << std::scientific;
|
||||
buf.precision(m_precision);
|
||||
buf << (*m_it);
|
||||
std::string res = buf.str();
|
||||
|
||||
if (res[res.size() - 4] == 'e')
|
||||
{
|
||||
res.erase(0, 1);
|
||||
res.insert(res.size() - 2, "0");
|
||||
}
|
||||
out << res;
|
||||
}
|
||||
}
|
||||
++m_it;
|
||||
return out;
|
||||
}
|
||||
|
||||
void update(const value_type& val)
|
||||
{
|
||||
if (val != 0 && !std::isinf(val) && !std::isnan(val))
|
||||
{
|
||||
if (!m_scientific || !m_large_exponent)
|
||||
{
|
||||
int exponent = 1 + int(std::log10(math::abs(val)));
|
||||
if (exponent <= -5 || exponent > 7)
|
||||
{
|
||||
m_scientific = true;
|
||||
m_required_precision = m_precision;
|
||||
if (exponent <= -100 || exponent >= 100)
|
||||
{
|
||||
m_large_exponent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (math::abs(val) > m_max)
|
||||
{
|
||||
m_max = math::abs(val);
|
||||
}
|
||||
if (m_required_precision < m_precision)
|
||||
{
|
||||
while (std::floor(val * std::pow(10, m_required_precision)) != val * std::pow(10, m_required_precision))
|
||||
{
|
||||
m_required_precision++;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_cache.push_back(val);
|
||||
}
|
||||
|
||||
std::streamsize width()
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
bool m_large_exponent = false;
|
||||
bool m_scientific = false;
|
||||
std::streamsize m_width = 9;
|
||||
std::streamsize m_precision;
|
||||
std::streamsize m_required_precision = 0;
|
||||
value_type m_max = 0;
|
||||
|
||||
cache_type m_cache;
|
||||
cache_iterator m_it;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct printer<T, std::enable_if_t<std::is_integral<typename T::value_type>::value && !std::is_same<typename T::value_type, bool>::value>>
|
||||
{
|
||||
using value_type = std::decay_t<typename T::value_type>;
|
||||
using cache_type = std::vector<value_type>;
|
||||
using cache_iterator = typename cache_type::const_iterator;
|
||||
|
||||
explicit printer(std::streamsize)
|
||||
{
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
m_it = m_cache.cbegin();
|
||||
m_width = 1 + std::streamsize(std::log10(m_max)) + m_sign;
|
||||
}
|
||||
|
||||
std::ostream& print_next(std::ostream& out)
|
||||
{
|
||||
// + enables printing of chars etc. as numbers
|
||||
// TODO should chars be printed as numbers?
|
||||
out.width(m_width);
|
||||
out << +(*m_it);
|
||||
++m_it;
|
||||
return out;
|
||||
}
|
||||
|
||||
void update(const value_type& val)
|
||||
{
|
||||
if (math::abs(val) > m_max)
|
||||
{
|
||||
m_max = math::abs(val);
|
||||
}
|
||||
if (std::is_signed<value_type>::value && val < 0)
|
||||
{
|
||||
m_sign = true;
|
||||
}
|
||||
m_cache.push_back(val);
|
||||
}
|
||||
|
||||
std::streamsize width()
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::streamsize m_width;
|
||||
bool m_sign = false;
|
||||
value_type m_max = 0;
|
||||
|
||||
cache_type m_cache;
|
||||
cache_iterator m_it;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct printer<T, std::enable_if_t<std::is_same<typename T::value_type, bool>::value>>
|
||||
{
|
||||
using value_type = bool;
|
||||
using cache_type = std::vector<bool>;
|
||||
using cache_iterator = typename cache_type::const_iterator;
|
||||
|
||||
explicit printer(std::streamsize)
|
||||
{
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
m_it = m_cache.cbegin();
|
||||
}
|
||||
|
||||
std::ostream& print_next(std::ostream& out)
|
||||
{
|
||||
if (*m_it)
|
||||
{
|
||||
out << " true";
|
||||
}
|
||||
else
|
||||
{
|
||||
out << "false";
|
||||
}
|
||||
// TODO: the following std::setw(5) isn't working correctly on OSX.
|
||||
//out << std::boolalpha << std::setw(m_width) << (*m_it);
|
||||
++m_it;
|
||||
return out;
|
||||
}
|
||||
|
||||
void update(const value_type& val)
|
||||
{
|
||||
m_cache.push_back(val);
|
||||
}
|
||||
|
||||
std::streamsize width()
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::streamsize m_width = 5;
|
||||
|
||||
cache_type m_cache;
|
||||
cache_iterator m_it;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct printer<T, std::enable_if_t<xtl::is_complex<typename T::value_type>::value>>
|
||||
{
|
||||
using value_type = std::decay_t<typename T::value_type>;
|
||||
using cache_type = std::vector<bool>;
|
||||
using cache_iterator = typename cache_type::const_iterator;
|
||||
|
||||
explicit printer(std::streamsize precision)
|
||||
: real_printer(precision), imag_printer(precision)
|
||||
{
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
real_printer.init();
|
||||
imag_printer.init();
|
||||
m_it = m_signs.cbegin();
|
||||
}
|
||||
|
||||
std::ostream& print_next(std::ostream& out)
|
||||
{
|
||||
real_printer.print_next(out);
|
||||
if (*m_it)
|
||||
{
|
||||
out << "-";
|
||||
}
|
||||
else
|
||||
{
|
||||
out << "+";
|
||||
}
|
||||
std::stringstream buf;
|
||||
imag_printer.print_next(buf);
|
||||
std::string s = buf.str();
|
||||
if (s[0] == ' ')
|
||||
{
|
||||
s.erase(0, 1); // erase space for +/-
|
||||
}
|
||||
// insert j at end of number
|
||||
std::size_t idx = s.find_last_not_of(" ");
|
||||
s.insert(idx + 1, "i");
|
||||
out << s;
|
||||
++m_it;
|
||||
return out;
|
||||
}
|
||||
|
||||
void update(const value_type& val)
|
||||
{
|
||||
real_printer.update(val.real());
|
||||
imag_printer.update(std::abs(val.imag()));
|
||||
m_signs.push_back(std::signbit(val.imag()));
|
||||
}
|
||||
|
||||
std::streamsize width()
|
||||
{
|
||||
return real_printer.width() + imag_printer.width() + 2;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
printer<value_type> real_printer, imag_printer;
|
||||
cache_type m_signs;
|
||||
cache_iterator m_it;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct printer<T, std::enable_if_t<!std::is_fundamental<typename T::value_type>::value && !xtl::is_complex<typename T::value_type>::value>>
|
||||
{
|
||||
using value_type = std::decay_t<typename T::value_type>;
|
||||
using cache_type = std::vector<std::string>;
|
||||
using cache_iterator = typename cache_type::const_iterator;
|
||||
|
||||
explicit printer(std::streamsize)
|
||||
{
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
m_it = m_cache.cbegin();
|
||||
if (m_width > 20)
|
||||
{
|
||||
m_width = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& print_next(std::ostream& out)
|
||||
{
|
||||
out.width(m_width);
|
||||
out << *m_it;
|
||||
++m_it;
|
||||
return out;
|
||||
}
|
||||
|
||||
void update(const value_type& val)
|
||||
{
|
||||
std::stringstream buf;
|
||||
buf << val;
|
||||
std::string s = buf.str();
|
||||
if (int(s.size()) > m_width)
|
||||
{
|
||||
m_width = std::streamsize(s.size());
|
||||
}
|
||||
m_cache.push_back(s);
|
||||
}
|
||||
|
||||
std::streamsize width()
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::streamsize m_width = 0;
|
||||
cache_type m_cache;
|
||||
cache_iterator m_it;
|
||||
};
|
||||
|
||||
template <class E>
|
||||
struct custom_formatter
|
||||
{
|
||||
using value_type = std::decay_t<typename E::value_type>;
|
||||
|
||||
template <class F>
|
||||
custom_formatter(F&& func)
|
||||
: m_func(func)
|
||||
{
|
||||
}
|
||||
|
||||
std::string operator()(const value_type& val) const
|
||||
{
|
||||
return m_func(val);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::function<std::string(const value_type&)> m_func;
|
||||
};
|
||||
}
|
||||
|
||||
template <class E, class F>
|
||||
std::ostream& pretty_print(const xexpression<E>& e, F&& func, std::ostream& out = std::cout)
|
||||
{
|
||||
xfunction<detail::custom_formatter<E>, std::string, const_xclosure_t<E>> print_fun(detail::custom_formatter<E>(std::forward<F>(func)), e);
|
||||
return pretty_print(print_fun, out);
|
||||
}
|
||||
|
||||
template <class E>
|
||||
std::ostream& pretty_print(const xexpression<E>& e, std::ostream& out = std::cout)
|
||||
{
|
||||
const E& d = e.derived_cast();
|
||||
|
||||
size_t lim = 0;
|
||||
std::size_t sz = compute_size(d.shape());
|
||||
if (sz > print_options::print_options().threshold)
|
||||
{
|
||||
lim = print_options::print_options().edgeitems;
|
||||
}
|
||||
if (sz == 0)
|
||||
{
|
||||
out << "{}";
|
||||
return out;
|
||||
}
|
||||
|
||||
auto temp_precision = out.precision();
|
||||
auto precision = temp_precision;
|
||||
if (print_options::print_options().precision != -1)
|
||||
{
|
||||
out.precision(print_options::print_options().precision);
|
||||
precision = print_options::print_options().precision;
|
||||
}
|
||||
|
||||
detail::printer<E> p(precision);
|
||||
|
||||
xstrided_slice_vector sv;
|
||||
detail::recurser_run(p, d, sv, lim);
|
||||
p.init();
|
||||
sv.clear();
|
||||
xoutput(out, d, sv, p, 1, p.width(), lim, print_options::print_options().line_width);
|
||||
|
||||
out.precision(temp_precision); // restore precision
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
template <class E>
|
||||
inline std::ostream& operator<<(std::ostream& out, const xexpression<E>& e)
|
||||
{
|
||||
return pretty_print(e, out);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
824
vendor/xtensor/include/xtensor/xiterable.hpp
vendored
Normal file
824
vendor/xtensor/include/xtensor/xiterable.hpp
vendored
Normal file
|
|
@ -0,0 +1,824 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTENSOR_ITERABLE_HPP
|
||||
#define XTENSOR_ITERABLE_HPP
|
||||
|
||||
#include "xiterator.hpp"
|
||||
|
||||
namespace xt
|
||||
{
|
||||
|
||||
/*******************
|
||||
* xconst_iterable *
|
||||
*******************/
|
||||
|
||||
template <class D>
|
||||
struct xiterable_inner_types;
|
||||
|
||||
#define DL XTENSOR_DEFAULT_LAYOUT
|
||||
|
||||
/**
|
||||
* @class xconst_iterable
|
||||
* @brief Base class for multidimensional iterable constant expressions
|
||||
*
|
||||
* The xconst_iterable class defines the interface for multidimensional
|
||||
* constant expressions that can be iterated.
|
||||
*
|
||||
* @tparam D The derived type, i.e. the inheriting class for which xconst_iterable
|
||||
* provides the interface.
|
||||
*/
|
||||
template <class D>
|
||||
class xconst_iterable
|
||||
{
|
||||
public:
|
||||
|
||||
using derived_type = D;
|
||||
|
||||
using iterable_types = xiterable_inner_types<D>;
|
||||
using inner_shape_type = typename iterable_types::inner_shape_type;
|
||||
|
||||
using stepper = typename iterable_types::stepper;
|
||||
using const_stepper = typename iterable_types::const_stepper;
|
||||
|
||||
template <layout_type L>
|
||||
using layout_iterator = xiterator<stepper, inner_shape_type*, L>;
|
||||
template <layout_type L>
|
||||
using const_layout_iterator = xiterator<const_stepper, inner_shape_type*, L>;
|
||||
template <layout_type L>
|
||||
using reverse_layout_iterator = std::reverse_iterator<layout_iterator<L>>;
|
||||
template <layout_type L>
|
||||
using const_reverse_layout_iterator = std::reverse_iterator<const_layout_iterator<L>>;
|
||||
|
||||
template <class S, layout_type L>
|
||||
using broadcast_iterator = xiterator<stepper, S, L>;
|
||||
template <class S, layout_type L>
|
||||
using const_broadcast_iterator = xiterator<const_stepper, S, L>;
|
||||
template <class S, layout_type L>
|
||||
using reverse_broadcast_iterator = std::reverse_iterator<broadcast_iterator<S, L>>;
|
||||
template <class S, layout_type L>
|
||||
using const_reverse_broadcast_iterator = std::reverse_iterator<const_broadcast_iterator<S, L>>;
|
||||
|
||||
using storage_iterator = layout_iterator<DL>;
|
||||
using const_storage_iterator = const_layout_iterator<DL>;
|
||||
using reverse_storage_iterator = reverse_layout_iterator<DL>;
|
||||
using const_reverse_storage_iterator = const_reverse_layout_iterator<DL>;
|
||||
|
||||
using iterator = layout_iterator<DL>;
|
||||
using const_iterator = const_layout_iterator<DL>;
|
||||
using reverse_iterator = reverse_layout_iterator<DL>;
|
||||
using const_reverse_iterator = const_reverse_layout_iterator<DL>;
|
||||
|
||||
template <layout_type L = DL>
|
||||
const_layout_iterator<L> begin() const noexcept;
|
||||
template <layout_type L = DL>
|
||||
const_layout_iterator<L> end() const noexcept;
|
||||
template <layout_type L = DL>
|
||||
const_layout_iterator<L> cbegin() const noexcept;
|
||||
template <layout_type L = DL>
|
||||
const_layout_iterator<L> cend() const noexcept;
|
||||
|
||||
template <layout_type L = DL>
|
||||
const_reverse_layout_iterator<L> rbegin() const noexcept;
|
||||
template <layout_type L = DL>
|
||||
const_reverse_layout_iterator<L> rend() const noexcept;
|
||||
template <layout_type L = DL>
|
||||
const_reverse_layout_iterator<L> crbegin() const noexcept;
|
||||
template <layout_type L = DL>
|
||||
const_reverse_layout_iterator<L> crend() const noexcept;
|
||||
|
||||
template <class S, layout_type L = DL>
|
||||
const_broadcast_iterator<S, L> begin(const S& shape) const noexcept;
|
||||
template <class S, layout_type L = DL>
|
||||
const_broadcast_iterator<S, L> end(const S& shape) const noexcept;
|
||||
template <class S, layout_type L = DL>
|
||||
const_broadcast_iterator<S, L> cbegin(const S& shape) const noexcept;
|
||||
template <class S, layout_type L = DL>
|
||||
const_broadcast_iterator<S, L> cend(const S& shape) const noexcept;
|
||||
|
||||
template <class S, layout_type L = DL>
|
||||
const_reverse_broadcast_iterator<S, L> rbegin(const S& shape) const noexcept;
|
||||
template <class S, layout_type L = DL>
|
||||
const_reverse_broadcast_iterator<S, L> rend(const S& shape) const noexcept;
|
||||
template <class S, layout_type L = DL>
|
||||
const_reverse_broadcast_iterator<S, L> crbegin(const S& shape) const noexcept;
|
||||
template <class S, layout_type L = DL>
|
||||
const_reverse_broadcast_iterator<S, L> crend(const S& shape) const noexcept;
|
||||
|
||||
template <layout_type L = DL>
|
||||
const_layout_iterator<L> storage_begin() const noexcept;
|
||||
template <layout_type L = DL>
|
||||
const_layout_iterator<L> storage_end() const noexcept;
|
||||
template <layout_type L = DL>
|
||||
const_layout_iterator<L> storage_cbegin() const noexcept;
|
||||
template <layout_type L = DL>
|
||||
const_layout_iterator<L> storage_cend() const noexcept;
|
||||
|
||||
template <layout_type L = DL>
|
||||
const_reverse_layout_iterator<L> storage_rbegin() const noexcept;
|
||||
template <layout_type L = DL>
|
||||
const_reverse_layout_iterator<L> storage_rend() const noexcept;
|
||||
template <layout_type L = DL>
|
||||
const_reverse_layout_iterator<L> storage_crbegin() const noexcept;
|
||||
template <layout_type L = DL>
|
||||
const_reverse_layout_iterator<L> storage_crend() const noexcept;
|
||||
|
||||
protected:
|
||||
|
||||
const inner_shape_type& get_shape() const;
|
||||
|
||||
private:
|
||||
|
||||
template <layout_type L>
|
||||
const_layout_iterator<L> get_cbegin(bool end_index) const noexcept;
|
||||
template <layout_type L>
|
||||
const_layout_iterator<L> get_cend(bool end_index) const noexcept;
|
||||
|
||||
template <class S, layout_type L>
|
||||
const_broadcast_iterator<S, L> get_cbegin(const S& shape, bool end_index) const noexcept;
|
||||
template <class S, layout_type L>
|
||||
const_broadcast_iterator<S, L> get_cend(const S& shape, bool end_index) const noexcept;
|
||||
|
||||
template <class S>
|
||||
const_stepper get_stepper_begin(const S& shape) const noexcept;
|
||||
template <class S>
|
||||
const_stepper get_stepper_end(const S& shape, layout_type l) const noexcept;
|
||||
|
||||
const derived_type& derived_cast() const;
|
||||
};
|
||||
|
||||
/*************
|
||||
* xiterable *
|
||||
*************/
|
||||
|
||||
/**
|
||||
* @class xiterable
|
||||
* @brief Base class for multidimensional iterable expressions
|
||||
*
|
||||
* The xiterable class defines the interface for multidimensional
|
||||
* expressions that can be iterated.
|
||||
*
|
||||
* @tparam D The derived type, i.e. the inheriting class for which xiterable
|
||||
* provides the interface.
|
||||
*/
|
||||
template <class D>
|
||||
class xiterable : public xconst_iterable<D>
|
||||
{
|
||||
public:
|
||||
|
||||
using derived_type = D;
|
||||
|
||||
using base_type = xconst_iterable<D>;
|
||||
using inner_shape_type = typename base_type::inner_shape_type;
|
||||
|
||||
using stepper = typename base_type::stepper;
|
||||
using const_stepper = typename base_type::const_stepper;
|
||||
|
||||
template <layout_type L>
|
||||
using layout_iterator = typename base_type::template layout_iterator<L>;
|
||||
template <layout_type L>
|
||||
using const_layout_iterator = typename base_type::template const_layout_iterator<L>;
|
||||
template <layout_type L>
|
||||
using reverse_layout_iterator = typename base_type::template reverse_layout_iterator<L>;
|
||||
template <layout_type L>
|
||||
using const_reverse_layout_iterator = typename base_type::template const_reverse_layout_iterator<L>;
|
||||
|
||||
template <class S, layout_type L>
|
||||
using broadcast_iterator = typename base_type::template broadcast_iterator<S, L>;
|
||||
template <class S, layout_type L>
|
||||
using const_broadcast_iterator = typename base_type::template const_broadcast_iterator<S, L>;
|
||||
template <class S, layout_type L>
|
||||
using reverse_broadcast_iterator = typename base_type::template reverse_broadcast_iterator<S, L>;
|
||||
template <class S, layout_type L>
|
||||
using const_reverse_broadcast_iterator = typename base_type::template const_reverse_broadcast_iterator<S, L>;
|
||||
|
||||
using iterator = typename base_type::iterator;
|
||||
using const_iterator = typename base_type::const_iterator;
|
||||
using reverse_iterator = typename base_type::reverse_iterator;
|
||||
using const_reverse_iterator = typename base_type::const_reverse_iterator;
|
||||
|
||||
using base_type::begin;
|
||||
using base_type::end;
|
||||
using base_type::rbegin;
|
||||
using base_type::rend;
|
||||
using base_type::storage_begin;
|
||||
using base_type::storage_end;
|
||||
|
||||
template <layout_type L = DL>
|
||||
layout_iterator<L> begin() noexcept;
|
||||
template <layout_type L = DL>
|
||||
layout_iterator<L> end() noexcept;
|
||||
|
||||
template <layout_type L = DL>
|
||||
reverse_layout_iterator<L> rbegin() noexcept;
|
||||
template <layout_type L = DL>
|
||||
reverse_layout_iterator<L> rend() noexcept;
|
||||
|
||||
template <class S, layout_type L = DL>
|
||||
broadcast_iterator<S, L> begin(const S& shape) noexcept;
|
||||
template <class S, layout_type L = DL>
|
||||
broadcast_iterator<S, L> end(const S& shape) noexcept;
|
||||
|
||||
template <class S, layout_type L = DL>
|
||||
reverse_broadcast_iterator<S, L> rbegin(const S& shape) noexcept;
|
||||
template <class S, layout_type L = DL>
|
||||
reverse_broadcast_iterator<S, L> rend(const S& shape) noexcept;
|
||||
|
||||
template <layout_type L = DL>
|
||||
layout_iterator<L> storage_begin() noexcept;
|
||||
template <layout_type L = DL>
|
||||
layout_iterator<L> storage_end() noexcept;
|
||||
|
||||
template <layout_type L = DL>
|
||||
reverse_layout_iterator<L> storage_rbegin() noexcept;
|
||||
template <layout_type L = DL>
|
||||
reverse_layout_iterator<L> storage_rend() noexcept;
|
||||
|
||||
private:
|
||||
|
||||
template <layout_type L>
|
||||
layout_iterator<L> get_begin(bool end_index) noexcept;
|
||||
template <layout_type L>
|
||||
layout_iterator<L> get_end(bool end_index) noexcept;
|
||||
|
||||
template <class S, layout_type L>
|
||||
broadcast_iterator<S, L> get_begin(const S& shape, bool end_index) noexcept;
|
||||
template <class S, layout_type L>
|
||||
broadcast_iterator<S, L> get_end(const S& shape, bool end_index) noexcept;
|
||||
|
||||
template <class S>
|
||||
stepper get_stepper_begin(const S& shape) noexcept;
|
||||
template <class S>
|
||||
stepper get_stepper_end(const S& shape, layout_type l) noexcept;
|
||||
|
||||
template <class S>
|
||||
const_stepper get_stepper_begin(const S& shape) const noexcept;
|
||||
template <class S>
|
||||
const_stepper get_stepper_end(const S& shape, layout_type l) const noexcept;
|
||||
|
||||
derived_type& derived_cast();
|
||||
};
|
||||
|
||||
#undef DL
|
||||
|
||||
/**********************************
|
||||
* xconst_iterable implementation *
|
||||
**********************************/
|
||||
|
||||
/**
|
||||
* @name Constant iterators
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* Returns a constant iterator to the first element of the expression.
|
||||
* @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT.
|
||||
*/
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xconst_iterable<D>::begin() const noexcept -> const_layout_iterator<L>
|
||||
{
|
||||
return this->template cbegin<L>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a constant iterator to the element following the last element
|
||||
* of the expression.
|
||||
* @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT.
|
||||
*/
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xconst_iterable<D>::end() const noexcept -> const_layout_iterator<L>
|
||||
{
|
||||
return this->template cend<L>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a constant iterator to the first element of the expression.
|
||||
* @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT.
|
||||
*/
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xconst_iterable<D>::cbegin() const noexcept -> const_layout_iterator<L>
|
||||
{
|
||||
return this->template get_cbegin<L>(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a constant iterator to the element following the last element
|
||||
* of the expression.
|
||||
* @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT.
|
||||
*/
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xconst_iterable<D>::cend() const noexcept -> const_layout_iterator<L>
|
||||
{
|
||||
return this->template get_cend<L>(true);
|
||||
}
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @name Constant reverse iterators
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* Returns a constant iterator to the first element of the reversed expression.
|
||||
* @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT.
|
||||
*/
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xconst_iterable<D>::rbegin() const noexcept -> const_reverse_layout_iterator<L>
|
||||
{
|
||||
return this->template crbegin<L>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a constant iterator to the element following the last element
|
||||
* of the reversed expression.
|
||||
* @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT.
|
||||
*/
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xconst_iterable<D>::rend() const noexcept -> const_reverse_layout_iterator<L>
|
||||
{
|
||||
return this->template crend<L>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a constant iterator to the first element of the reversed expression.
|
||||
* @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT.
|
||||
*/
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xconst_iterable<D>::crbegin() const noexcept -> const_reverse_layout_iterator<L>
|
||||
{
|
||||
return const_reverse_layout_iterator<L>(get_cend<L>(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a constant iterator to the element following the last element
|
||||
* of the reversed expression.
|
||||
* @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT.
|
||||
*/
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xconst_iterable<D>::crend() const noexcept -> const_reverse_layout_iterator<L>
|
||||
{
|
||||
return const_reverse_layout_iterator<L>(get_cbegin<L>(false));
|
||||
}
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @name Constant broadcast iterators
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* Returns a constant iterator to the first element of the expression. The
|
||||
* iteration is broadcasted to the specified shape.
|
||||
* @param shape the shape used for broadcasting
|
||||
* @tparam S type of the \c shape parameter.
|
||||
* @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT.
|
||||
*/
|
||||
template <class D>
|
||||
template <class S, layout_type L>
|
||||
inline auto xconst_iterable<D>::begin(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
|
||||
{
|
||||
return cbegin<S, L>(shape);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a constant iterator to the element following the last element of the
|
||||
* expression. The iteration is broadcasted to the specified shape.
|
||||
* @param shape the shape used for broadcasting
|
||||
* @tparam S type of the \c shape parameter.
|
||||
* @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT.
|
||||
*/
|
||||
template <class D>
|
||||
template <class S, layout_type L>
|
||||
inline auto xconst_iterable<D>::end(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
|
||||
{
|
||||
return cend<S, L>(shape);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a constant iterator to the first element of the expression. The
|
||||
* iteration is broadcasted to the specified shape.
|
||||
* @param shape the shape used for broadcasting
|
||||
* @tparam S type of the \c shape parameter.
|
||||
* @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT.
|
||||
*/
|
||||
template <class D>
|
||||
template <class S, layout_type L>
|
||||
inline auto xconst_iterable<D>::cbegin(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
|
||||
{
|
||||
return get_cbegin<S, L>(shape, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a constant iterator to the element following the last element of the
|
||||
* expression. The iteration is broadcasted to the specified shape.
|
||||
* @param shape the shape used for broadcasting
|
||||
* @tparam S type of the \c shape parameter.
|
||||
* @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT.
|
||||
*/
|
||||
template <class D>
|
||||
template <class S, layout_type L>
|
||||
inline auto xconst_iterable<D>::cend(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
|
||||
{
|
||||
return get_cend<S, L>(shape, true);
|
||||
}
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @name Constant reverse broadcast iterators
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* Returns a constant iterator to the first element of the reversed expression.
|
||||
* The iteration is broadcasted to the specified shape.
|
||||
* @param shape the shape used for broadcasting
|
||||
* @tparam S type of the \c shape parameter.
|
||||
* @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT.
|
||||
*/
|
||||
template <class D>
|
||||
template <class S, layout_type L>
|
||||
inline auto xconst_iterable<D>::rbegin(const S& shape) const noexcept -> const_reverse_broadcast_iterator<S, L>
|
||||
{
|
||||
return crbegin<S, L>(shape);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a constant iterator to the element following the last element of the
|
||||
* reversed expression. The iteration is broadcasted to the specified shape.
|
||||
* @param shape the shape used for broadcasting
|
||||
* @tparam S type of the \c shape parameter.
|
||||
* @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT.
|
||||
*/
|
||||
template <class D>
|
||||
template <class S, layout_type L>
|
||||
inline auto xconst_iterable<D>::rend(const S& shape) const noexcept -> const_reverse_broadcast_iterator<S, L>
|
||||
{
|
||||
return crend<S, L>(shape);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a constant iterator to the first element of the reversed expression.
|
||||
* The iteration is broadcasted to the specified shape.
|
||||
* @param shape the shape used for broadcasting
|
||||
* @tparam S type of the \c shape parameter.
|
||||
* @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT.
|
||||
*/
|
||||
template <class D>
|
||||
template <class S, layout_type L>
|
||||
inline auto xconst_iterable<D>::crbegin(const S& shape) const noexcept -> const_reverse_broadcast_iterator<S, L>
|
||||
{
|
||||
return const_reverse_broadcast_iterator<S, L>(get_cend<S, L>(shape, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a constant iterator to the element following the last element of the
|
||||
* reversed expression. The iteration is broadcasted to the specified shape.
|
||||
* @param shape the shape used for broadcasting
|
||||
* @tparam S type of the \c shape parameter.
|
||||
* @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT.
|
||||
*/
|
||||
template <class D>
|
||||
template <class S, layout_type L>
|
||||
inline auto xconst_iterable<D>::crend(const S& shape) const noexcept -> const_reverse_broadcast_iterator<S, L>
|
||||
{
|
||||
return const_reverse_broadcast_iterator<S, L>(get_cbegin<S, L>(shape, false));
|
||||
}
|
||||
//@}
|
||||
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xconst_iterable<D>::storage_begin() const noexcept -> const_layout_iterator<L>
|
||||
{
|
||||
return this->template cbegin<L>();
|
||||
}
|
||||
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xconst_iterable<D>::storage_end() const noexcept -> const_layout_iterator<L>
|
||||
{
|
||||
return this->template cend<L>();
|
||||
}
|
||||
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xconst_iterable<D>::storage_cbegin() const noexcept -> const_layout_iterator<L>
|
||||
{
|
||||
return this->template cbegin<L>();
|
||||
}
|
||||
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xconst_iterable<D>::storage_cend() const noexcept -> const_layout_iterator<L>
|
||||
{
|
||||
return this->template cend<L>();
|
||||
}
|
||||
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xconst_iterable<D>::storage_rbegin() const noexcept -> const_reverse_layout_iterator<L>
|
||||
{
|
||||
return this->template crbegin<L>();
|
||||
}
|
||||
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xconst_iterable<D>::storage_rend() const noexcept -> const_reverse_layout_iterator<L>
|
||||
{
|
||||
return this->template crend<L>();
|
||||
}
|
||||
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xconst_iterable<D>::storage_crbegin() const noexcept -> const_reverse_layout_iterator<L>
|
||||
{
|
||||
return this->template crbegin<L>();
|
||||
}
|
||||
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xconst_iterable<D>::storage_crend() const noexcept -> const_reverse_layout_iterator<L>
|
||||
{
|
||||
return this->template crend<L>();
|
||||
}
|
||||
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xconst_iterable<D>::get_cbegin(bool end_index) const noexcept -> const_layout_iterator<L>
|
||||
{
|
||||
return const_layout_iterator<L>(get_stepper_begin(get_shape()), &get_shape(), end_index);
|
||||
}
|
||||
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xconst_iterable<D>::get_cend(bool end_index) const noexcept -> const_layout_iterator<L>
|
||||
{
|
||||
return const_layout_iterator<L>(get_stepper_end(get_shape(), L), &get_shape(), end_index);
|
||||
}
|
||||
|
||||
template <class D>
|
||||
template <class S, layout_type L>
|
||||
inline auto xconst_iterable<D>::get_cbegin(const S& shape, bool end_index) const noexcept -> const_broadcast_iterator<S, L>
|
||||
{
|
||||
return const_broadcast_iterator<S, L>(get_stepper_begin(shape), shape, end_index);
|
||||
}
|
||||
|
||||
template <class D>
|
||||
template <class S, layout_type L>
|
||||
inline auto xconst_iterable<D>::get_cend(const S& shape, bool end_index) const noexcept -> const_broadcast_iterator<S, L>
|
||||
{
|
||||
return const_broadcast_iterator<S, L>(get_stepper_end(shape, L), shape, end_index);
|
||||
}
|
||||
|
||||
template <class D>
|
||||
template <class S>
|
||||
inline auto xconst_iterable<D>::get_stepper_begin(const S& shape) const noexcept -> const_stepper
|
||||
{
|
||||
return derived_cast().stepper_begin(shape);
|
||||
}
|
||||
|
||||
template <class D>
|
||||
template <class S>
|
||||
inline auto xconst_iterable<D>::get_stepper_end(const S& shape, layout_type l) const noexcept -> const_stepper
|
||||
{
|
||||
return derived_cast().stepper_end(shape, l);
|
||||
}
|
||||
|
||||
template <class D>
|
||||
inline auto xconst_iterable<D>::get_shape() const -> const inner_shape_type&
|
||||
{
|
||||
return derived_cast().shape();
|
||||
}
|
||||
|
||||
template <class D>
|
||||
inline auto xconst_iterable<D>::derived_cast() const -> const derived_type&
|
||||
{
|
||||
return *static_cast<const derived_type*>(this);
|
||||
}
|
||||
|
||||
/****************************
|
||||
* xiterable implementation *
|
||||
****************************/
|
||||
|
||||
/**
|
||||
* @name Iterators
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* Returns an iterator to the first element of the expression.
|
||||
* @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT.
|
||||
*/
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xiterable<D>::begin() noexcept -> layout_iterator<L>
|
||||
{
|
||||
return get_begin<L>(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator to the element following the last element
|
||||
* of the expression.
|
||||
* @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT.
|
||||
*/
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xiterable<D>::end() noexcept -> layout_iterator<L>
|
||||
{
|
||||
return get_end<L>(true);
|
||||
}
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @name Reverse iterators
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* Returns an iterator to the first element of the reversed expression.
|
||||
* @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT.
|
||||
*/
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xiterable<D>::rbegin() noexcept -> reverse_layout_iterator<L>
|
||||
{
|
||||
return reverse_layout_iterator<L>(get_end<L>(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator to the element following the last element
|
||||
* of the reversed expression.
|
||||
* @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT.
|
||||
*/
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xiterable<D>::rend() noexcept -> reverse_layout_iterator<L>
|
||||
{
|
||||
return reverse_layout_iterator<L>(get_begin<L>(false));
|
||||
}
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @name Broadcast iterators
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* Returns an iterator to the first element of the expression. The
|
||||
* iteration is broadcasted to the specified shape.
|
||||
* @param shape the shape used for broadcasting
|
||||
* @tparam S type of the \c shape parameter.
|
||||
* @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT.
|
||||
*/
|
||||
template <class D>
|
||||
template <class S, layout_type L>
|
||||
inline auto xiterable<D>::begin(const S& shape) noexcept -> broadcast_iterator<S, L>
|
||||
{
|
||||
return get_begin<S, L>(shape, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator to the element following the last element of the
|
||||
* expression. The iteration is broadcasted to the specified shape.
|
||||
* @param shape the shape used for broadcasting
|
||||
* @tparam S type of the \c shape parameter.
|
||||
* @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT.
|
||||
*/
|
||||
template <class D>
|
||||
template <class S, layout_type L>
|
||||
inline auto xiterable<D>::end(const S& shape) noexcept -> broadcast_iterator<S, L>
|
||||
{
|
||||
return get_end<S, L>(shape, true);
|
||||
}
|
||||
//@}
|
||||
|
||||
/**
|
||||
* @name Reverse broadcast iterators
|
||||
*/
|
||||
//@{
|
||||
/**
|
||||
* Returns an iterator to the first element of the reversed expression. The
|
||||
* iteration is broadcasted to the specified shape.
|
||||
* @param shape the shape used for broadcasting
|
||||
* @tparam S type of the \c shape parameter.
|
||||
* @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT.
|
||||
*/
|
||||
template <class D>
|
||||
template <class S, layout_type L>
|
||||
inline auto xiterable<D>::rbegin(const S& shape) noexcept -> reverse_broadcast_iterator<S, L>
|
||||
{
|
||||
return reverse_broadcast_iterator<S, L>(get_end<S, L>(shape, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator to the element following the last element of the
|
||||
* reversed expression. The iteration is broadcasted to the specified shape.
|
||||
* @param shape the shape used for broadcasting
|
||||
* @tparam S type of the \c shape parameter.
|
||||
* @tparam L layout used for the traversal. Default value is \c XTENSOR_DEFAULT_LAYOUT.
|
||||
*/
|
||||
template <class D>
|
||||
template <class S, layout_type L>
|
||||
inline auto xiterable<D>::rend(const S& shape) noexcept -> reverse_broadcast_iterator<S, L>
|
||||
{
|
||||
return reverse_broadcast_iterator<S, L>(get_begin<S, L>(shape, false));
|
||||
}
|
||||
//@}
|
||||
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xiterable<D>::storage_begin() noexcept -> layout_iterator<L>
|
||||
{
|
||||
return this->template begin<L>();
|
||||
}
|
||||
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xiterable<D>::storage_end() noexcept -> layout_iterator<L>
|
||||
{
|
||||
return this->template end<L>();
|
||||
}
|
||||
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xiterable<D>::storage_rbegin() noexcept -> reverse_layout_iterator<L>
|
||||
{
|
||||
return this->template rbegin<L>();
|
||||
}
|
||||
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xiterable<D>::storage_rend() noexcept -> reverse_layout_iterator<L>
|
||||
{
|
||||
return this->template rend<L>();
|
||||
}
|
||||
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xiterable<D>::get_begin(bool end_index) noexcept -> layout_iterator<L>
|
||||
{
|
||||
return layout_iterator<L>(get_stepper_begin(this->get_shape()), &(this->get_shape()), end_index);
|
||||
}
|
||||
|
||||
template <class D>
|
||||
template <layout_type L>
|
||||
inline auto xiterable<D>::get_end(bool end_index) noexcept -> layout_iterator<L>
|
||||
{
|
||||
return layout_iterator<L>(get_stepper_end(this->get_shape(), L), &(this->get_shape()), end_index);
|
||||
}
|
||||
|
||||
template <class D>
|
||||
template <class S, layout_type L>
|
||||
inline auto xiterable<D>::get_begin(const S& shape, bool end_index) noexcept -> broadcast_iterator<S, L>
|
||||
{
|
||||
return broadcast_iterator<S, L>(get_stepper_begin(shape), shape, end_index);
|
||||
}
|
||||
|
||||
template <class D>
|
||||
template <class S, layout_type L>
|
||||
inline auto xiterable<D>::get_end(const S& shape, bool end_index) noexcept -> broadcast_iterator<S, L>
|
||||
{
|
||||
return broadcast_iterator<S, L>(get_stepper_end(shape, L), shape, end_index);
|
||||
}
|
||||
|
||||
template <class D>
|
||||
template <class S>
|
||||
inline auto xiterable<D>::get_stepper_begin(const S& shape) noexcept -> stepper
|
||||
{
|
||||
return derived_cast().stepper_begin(shape);
|
||||
}
|
||||
|
||||
template <class D>
|
||||
template <class S>
|
||||
inline auto xiterable<D>::get_stepper_end(const S& shape, layout_type l) noexcept -> stepper
|
||||
{
|
||||
return derived_cast().stepper_end(shape, l);
|
||||
}
|
||||
|
||||
template <class D>
|
||||
template <class S>
|
||||
inline auto xiterable<D>::get_stepper_begin(const S& shape) const noexcept -> const_stepper
|
||||
{
|
||||
return derived_cast().stepper_begin(shape);
|
||||
}
|
||||
|
||||
template <class D>
|
||||
template <class S>
|
||||
inline auto xiterable<D>::get_stepper_end(const S& shape, layout_type l) const noexcept -> const_stepper
|
||||
{
|
||||
return derived_cast().stepper_end(shape, l);
|
||||
}
|
||||
|
||||
template <class D>
|
||||
inline auto xiterable<D>::derived_cast() -> derived_type&
|
||||
{
|
||||
return *static_cast<derived_type*>(this);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
1123
vendor/xtensor/include/xtensor/xiterator.hpp
vendored
Normal file
1123
vendor/xtensor/include/xtensor/xiterator.hpp
vendored
Normal file
File diff suppressed because it is too large
Load diff
183
vendor/xtensor/include/xtensor/xjson.hpp
vendored
Normal file
183
vendor/xtensor/include/xtensor/xjson.hpp
vendored
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTENSOR_JSON_HPP
|
||||
#define XTENSOR_JSON_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "xstrided_view.hpp"
|
||||
|
||||
namespace xt
|
||||
{
|
||||
/*************************************
|
||||
* to_json and from_json declaration *
|
||||
*************************************/
|
||||
|
||||
template <class E>
|
||||
enable_xexpression<E> to_json(nlohmann::json&, const E&);
|
||||
|
||||
template <class E>
|
||||
enable_xcontainer_semantics<E> from_json(const nlohmann::json&, E&);
|
||||
|
||||
/// @cond DOXYGEN_INCLUDE_SFINAE
|
||||
template <class E>
|
||||
enable_xview_semantics<E> from_json(const nlohmann::json&, E&);
|
||||
/// @endcond
|
||||
|
||||
/****************************************
|
||||
* to_json and from_json implementation *
|
||||
****************************************/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <class D>
|
||||
void to_json_impl(nlohmann::json& j, const xexpression<D>& e, xstrided_slice_vector& slices)
|
||||
{
|
||||
const auto view = strided_view(e.derived_cast(), slices);
|
||||
if (view.dimension() == 0)
|
||||
{
|
||||
j = view();
|
||||
}
|
||||
else
|
||||
{
|
||||
j = nlohmann::json::array();
|
||||
using size_type = typename D::size_type;
|
||||
size_type nrows = view.shape()[0];
|
||||
for (size_type i = 0; i != nrows; ++i)
|
||||
{
|
||||
slices.push_back(i);
|
||||
nlohmann::json k;
|
||||
to_json_impl(k, e, slices);
|
||||
j.push_back(std::move(k));
|
||||
slices.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class D>
|
||||
inline void from_json_impl(const nlohmann::json& j, xexpression<D>& e, xstrided_slice_vector& slices)
|
||||
{
|
||||
auto view = strided_view(e.derived_cast(), slices);
|
||||
|
||||
if (view.dimension() == 0)
|
||||
{
|
||||
view() = j;
|
||||
}
|
||||
else
|
||||
{
|
||||
using size_type = typename D::size_type;
|
||||
size_type nrows = view.shape()[0];
|
||||
for (size_type i = 0; i != nrows; ++i)
|
||||
{
|
||||
slices.push_back(i);
|
||||
const nlohmann::json& k = j[i];
|
||||
from_json_impl(k, e, slices);
|
||||
slices.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline unsigned int json_dimension(const nlohmann::json& j)
|
||||
{
|
||||
if (j.is_array() && j.size())
|
||||
{
|
||||
return 1 + json_dimension(j[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <class S>
|
||||
inline void json_shape(const nlohmann::json& j, S& s, std::size_t pos = 0)
|
||||
{
|
||||
if (j.is_array())
|
||||
{
|
||||
auto size = j.size();
|
||||
s[pos] = size;
|
||||
if (size)
|
||||
{
|
||||
json_shape(j[0], s, pos + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief JSON serialization of an xtensor expression.
|
||||
*
|
||||
* The to_json method is used by the nlohmann_json package for automatic
|
||||
* serialization of user-defined types. The method is picked up by
|
||||
* argument-dependent lookup.
|
||||
*
|
||||
* @param j a JSON object
|
||||
* @param e a const \ref xexpression
|
||||
*/
|
||||
template <class E>
|
||||
inline enable_xexpression<E> to_json(nlohmann::json& j, const E& e)
|
||||
{
|
||||
auto sv = xstrided_slice_vector();
|
||||
detail::to_json_impl(j, e, sv);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief JSON deserialization of a xtensor expression with a container or
|
||||
* a view semantics.
|
||||
*
|
||||
* The from_json method is used by the nlohmann_json library for automatic
|
||||
* serialization of user-defined types. The method is picked up by
|
||||
* argument-dependent lookup.
|
||||
*
|
||||
* Note: for converting a JSON object to a value, nlohmann_json requiress
|
||||
* the value type to be default constructible, which is typically not the
|
||||
* case for expressions with a view semantics. In this case, from_json can
|
||||
* be called directly.
|
||||
*
|
||||
* @param j a const JSON object
|
||||
* @param e an \ref xexpression
|
||||
*/
|
||||
template <class E>
|
||||
inline enable_xcontainer_semantics<E> from_json(const nlohmann::json& j, E& e)
|
||||
{
|
||||
auto dimension = detail::json_dimension(j);
|
||||
auto s = xtl::make_sequence<typename E::shape_type>(dimension);
|
||||
detail::json_shape(j, s);
|
||||
|
||||
// In the case of a container, we resize the container.
|
||||
e.resize(s);
|
||||
|
||||
auto sv = xstrided_slice_vector();
|
||||
detail::from_json_impl(j, e, sv);
|
||||
}
|
||||
|
||||
/// @cond DOXYGEN_INCLUDE_SFINAE
|
||||
template <class E>
|
||||
inline enable_xview_semantics<E> from_json(const nlohmann::json& j, E& e)
|
||||
{
|
||||
typename E::shape_type s;
|
||||
detail::json_shape(j, s);
|
||||
|
||||
// In the case of a view, we check the size of the container.
|
||||
if (!std::equal(s.cbegin(), s.cend(), e.shape().cbegin()))
|
||||
{
|
||||
throw std::runtime_error("Shape mismatch when deserializing JSON to view");
|
||||
}
|
||||
|
||||
auto sv = xstrided_slice_vector();
|
||||
detail::from_json_impl(j, e, sv);
|
||||
}
|
||||
/// @endcond
|
||||
}
|
||||
|
||||
#endif
|
||||
93
vendor/xtensor/include/xtensor/xlayout.hpp
vendored
Normal file
93
vendor/xtensor/include/xtensor/xlayout.hpp
vendored
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTENSOR_LAYOUT_HPP
|
||||
#define XTENSOR_LAYOUT_HPP
|
||||
|
||||
#include "xtensor_config.hpp"
|
||||
|
||||
namespace xt
|
||||
{
|
||||
/*! layout_type enum for xcontainer based xexpressions */
|
||||
enum class layout_type
|
||||
{
|
||||
/*! dynamic layout_type: you can resize to row major, column major, or use custom strides */
|
||||
dynamic = 0x00,
|
||||
/*! layout_type compatible with all others */
|
||||
any = 0xFF,
|
||||
/*! row major layout_type */
|
||||
row_major = 0x01,
|
||||
/*! column major layout_type */
|
||||
column_major = 0x02
|
||||
};
|
||||
|
||||
/**
|
||||
* Implementation of the following logical table:
|
||||
*
|
||||
* @verbatim
|
||||
| d | a | r | c |
|
||||
--+---+---+---+---+
|
||||
d | d | d | d | d |
|
||||
a | d | a | r | c |
|
||||
r | d | r | r | d |
|
||||
c | d | c | d | c |
|
||||
d = dynamic, a = any, r = row_major, c = column_major.
|
||||
@endverbatim
|
||||
* Using bitmasks to avoid nested if-else statements.
|
||||
*
|
||||
* @param args the input layouts.
|
||||
* @return the output layout, computed with the previous logical table.
|
||||
*/
|
||||
template <class... Args>
|
||||
constexpr layout_type compute_layout(Args... args) noexcept;
|
||||
|
||||
constexpr layout_type default_assignable_layout(layout_type l) noexcept;
|
||||
|
||||
/******************
|
||||
* Implementation *
|
||||
******************/
|
||||
|
||||
namespace detail
|
||||
{
|
||||
constexpr layout_type compute_layout_impl() noexcept
|
||||
{
|
||||
return layout_type::any;
|
||||
}
|
||||
|
||||
constexpr layout_type compute_layout_impl(layout_type l) noexcept
|
||||
{
|
||||
return l;
|
||||
}
|
||||
|
||||
constexpr layout_type compute_layout_impl(layout_type lhs, layout_type rhs) noexcept
|
||||
{
|
||||
using type = std::underlying_type_t<layout_type>;
|
||||
return layout_type(static_cast<type>(lhs) & static_cast<type>(rhs));
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
constexpr layout_type compute_layout_impl(layout_type lhs, Args... args) noexcept
|
||||
{
|
||||
return compute_layout_impl(lhs, compute_layout_impl(args...));
|
||||
}
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
constexpr layout_type compute_layout(Args... args) noexcept
|
||||
{
|
||||
return detail::compute_layout_impl(args...);
|
||||
}
|
||||
|
||||
constexpr layout_type default_assignable_layout(layout_type l) noexcept
|
||||
{
|
||||
return (l == layout_type::row_major || l == layout_type::column_major) ?
|
||||
l : XTENSOR_DEFAULT_LAYOUT;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
2146
vendor/xtensor/include/xtensor/xmath.hpp
vendored
Normal file
2146
vendor/xtensor/include/xtensor/xmath.hpp
vendored
Normal file
File diff suppressed because it is too large
Load diff
110
vendor/xtensor/include/xtensor/xnoalias.hpp
vendored
Normal file
110
vendor/xtensor/include/xtensor/xnoalias.hpp
vendored
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTENSOR_NOALIAS_HPP
|
||||
#define XTENSOR_NOALIAS_HPP
|
||||
|
||||
#include "xsemantic.hpp"
|
||||
|
||||
namespace xt
|
||||
{
|
||||
|
||||
template <class A>
|
||||
class noalias_proxy
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
noalias_proxy(A& a) noexcept;
|
||||
|
||||
template <class E>
|
||||
A& operator=(const xexpression<E>& e);
|
||||
|
||||
template <class E>
|
||||
A& operator+=(const xexpression<E>& e);
|
||||
|
||||
template <class E>
|
||||
A& operator-=(const xexpression<E>& e);
|
||||
|
||||
template <class E>
|
||||
A& operator*=(const xexpression<E>& e);
|
||||
|
||||
template <class E>
|
||||
A& operator/=(const xexpression<E>& e);
|
||||
|
||||
template <class E>
|
||||
A& operator%=(const xexpression<E>& e);
|
||||
|
||||
private:
|
||||
|
||||
A& m_array;
|
||||
};
|
||||
|
||||
template <class A>
|
||||
noalias_proxy<A> noalias(A& a) noexcept;
|
||||
|
||||
/********************************
|
||||
* noalias_proxy implementation *
|
||||
********************************/
|
||||
|
||||
template <class A>
|
||||
inline noalias_proxy<A>::noalias_proxy(A& a) noexcept
|
||||
: m_array(a)
|
||||
{
|
||||
}
|
||||
|
||||
template <class A>
|
||||
template <class E>
|
||||
inline A& noalias_proxy<A>::operator=(const xexpression<E>& e)
|
||||
{
|
||||
return m_array.assign(e);
|
||||
}
|
||||
|
||||
template <class A>
|
||||
template <class E>
|
||||
inline A& noalias_proxy<A>::operator+=(const xexpression<E>& e)
|
||||
{
|
||||
return m_array.plus_assign(e);
|
||||
}
|
||||
|
||||
template <class A>
|
||||
template <class E>
|
||||
inline A& noalias_proxy<A>::operator-=(const xexpression<E>& e)
|
||||
{
|
||||
return m_array.minus_assign(e);
|
||||
}
|
||||
|
||||
template <class A>
|
||||
template <class E>
|
||||
inline A& noalias_proxy<A>::operator*=(const xexpression<E>& e)
|
||||
{
|
||||
return m_array.multiplies_assign(e);
|
||||
}
|
||||
|
||||
template <class A>
|
||||
template <class E>
|
||||
inline A& noalias_proxy<A>::operator/=(const xexpression<E>& e)
|
||||
{
|
||||
return m_array.divides_assign(e);
|
||||
}
|
||||
|
||||
template <class A>
|
||||
template <class E>
|
||||
inline A& noalias_proxy<A>::operator%=(const xexpression<E>& e)
|
||||
{
|
||||
return m_array.modulus_assign(e);
|
||||
}
|
||||
|
||||
template <class A>
|
||||
inline noalias_proxy<A> noalias(A& a) noexcept
|
||||
{
|
||||
return noalias_proxy<A>(a);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
477
vendor/xtensor/include/xtensor/xnorm.hpp
vendored
Normal file
477
vendor/xtensor/include/xtensor/xnorm.hpp
vendored
Normal file
|
|
@ -0,0 +1,477 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2017, Ullrich Koethe *
|
||||
* *
|
||||
* Distributed under the terms of the BSD 3-Clause License. *
|
||||
* *
|
||||
* The full license is in the file LICENSE, distributed with this software. *
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef XTENSOR_NORM_HPP
|
||||
#define XTENSOR_NORM_HPP
|
||||
|
||||
#include <cmath>
|
||||
// std::abs(int) prior to C++ 17
|
||||
#include <complex>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "xconcepts.hpp"
|
||||
#include "xmath.hpp"
|
||||
#include "xoperation.hpp"
|
||||
#include "xutils.hpp"
|
||||
|
||||
namespace xt
|
||||
{
|
||||
template <class X>
|
||||
using disable_evaluation_strategy = std::enable_if_t<!std::is_base_of<evaluation_strategy::base, std::decay_t<X>>::value, int>;
|
||||
|
||||
/*************************************
|
||||
* norm functions for built-in types *
|
||||
*************************************/
|
||||
|
||||
///@cond DOXYGEN_INCLUDE_SFINAE
|
||||
#define XTENSOR_DEFINE_SIGNED_NORMS(T) \
|
||||
inline auto \
|
||||
norm_lp(T t, double p) noexcept \
|
||||
{ \
|
||||
using rt = decltype(std::abs(t)); \
|
||||
return p == 0.0 \
|
||||
? static_cast<rt>(t != 0) \
|
||||
: std::abs(t); \
|
||||
} \
|
||||
inline auto \
|
||||
norm_lp_to_p(T t, double p) noexcept \
|
||||
{ \
|
||||
using rt = real_promote_type_t<T>; \
|
||||
return p == 0.0 \
|
||||
? static_cast<rt>(t != 0) \
|
||||
: std::pow(static_cast<rt>(std::abs(t)), \
|
||||
static_cast<rt>(p)); \
|
||||
} \
|
||||
inline size_t norm_l0(T t) noexcept { return (t != 0); } \
|
||||
inline auto norm_l1(T t) noexcept { return std::abs(t); } \
|
||||
inline auto norm_l2(T t) noexcept { return std::abs(t); } \
|
||||
inline auto norm_linf(T t) noexcept { return std::abs(t); } \
|
||||
inline auto norm_sq(T t) noexcept { return t * t; }
|
||||
|
||||
XTENSOR_DEFINE_SIGNED_NORMS(signed char)
|
||||
XTENSOR_DEFINE_SIGNED_NORMS(short)
|
||||
XTENSOR_DEFINE_SIGNED_NORMS(int)
|
||||
XTENSOR_DEFINE_SIGNED_NORMS(long)
|
||||
XTENSOR_DEFINE_SIGNED_NORMS(long long)
|
||||
XTENSOR_DEFINE_SIGNED_NORMS(float)
|
||||
XTENSOR_DEFINE_SIGNED_NORMS(double)
|
||||
XTENSOR_DEFINE_SIGNED_NORMS(long double)
|
||||
|
||||
#undef XTENSOR_DEFINE_SIGNED_NORMS
|
||||
|
||||
#define XTENSOR_DEFINE_UNSIGNED_NORMS(T) \
|
||||
inline T norm_lp(T t, double p) noexcept \
|
||||
{ \
|
||||
return p == 0.0 \
|
||||
? (t != 0) \
|
||||
: t; \
|
||||
} \
|
||||
inline auto \
|
||||
norm_lp_to_p(T t, double p) noexcept \
|
||||
{ \
|
||||
using rt = real_promote_type_t<T>; \
|
||||
return p == 0.0 \
|
||||
? static_cast<rt>(t != 0) \
|
||||
: std::pow(static_cast<rt>(t), \
|
||||
static_cast<rt>(p)); \
|
||||
} \
|
||||
inline T norm_l0(T t) noexcept { return t != 0 ? 1 : 0; } \
|
||||
inline T norm_l1(T t) noexcept { return t; } \
|
||||
inline T norm_l2(T t) noexcept { return t; } \
|
||||
inline T norm_linf(T t) noexcept { return t; } \
|
||||
inline auto norm_sq(T t) noexcept { return t * t; }
|
||||
|
||||
XTENSOR_DEFINE_UNSIGNED_NORMS(unsigned char)
|
||||
XTENSOR_DEFINE_UNSIGNED_NORMS(unsigned short)
|
||||
XTENSOR_DEFINE_UNSIGNED_NORMS(unsigned int)
|
||||
XTENSOR_DEFINE_UNSIGNED_NORMS(unsigned long)
|
||||
XTENSOR_DEFINE_UNSIGNED_NORMS(unsigned long long)
|
||||
|
||||
#undef XTENSOR_DEFINE_UNSIGNED_NORMS
|
||||
|
||||
/***********************************
|
||||
* norm functions for std::complex *
|
||||
***********************************/
|
||||
|
||||
/**
|
||||
* \brief L0 pseudo-norm of a complex number.
|
||||
* Equivalent to <tt>t != 0</tt>.
|
||||
*/
|
||||
template <class T>
|
||||
inline uint64_t norm_l0(const std::complex<T>& t) noexcept
|
||||
{
|
||||
return t.real() != 0 || t.imag() != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief L1 norm of a complex number.
|
||||
*/
|
||||
template <class T>
|
||||
inline auto norm_l1(const std::complex<T>& t) noexcept
|
||||
{
|
||||
return std::abs(t.real()) + std::abs(t.imag());
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief L2 norm of a complex number.
|
||||
* Equivalent to <tt>std::abs(t)</tt>.
|
||||
*/
|
||||
template <class T>
|
||||
inline auto norm_l2(const std::complex<T>& t) noexcept
|
||||
{
|
||||
return std::abs(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Squared norm of a complex number.
|
||||
* Equivalent to <tt>std::norm(t)</tt> (yes, the C++ standard really defines
|
||||
* <tt>norm()</tt> to compute the squared norm).
|
||||
*/
|
||||
template <class T>
|
||||
inline auto norm_sq(const std::complex<T>& t) noexcept
|
||||
{
|
||||
return std::norm(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief L-infinity norm of a complex number.
|
||||
*/
|
||||
template <class T>
|
||||
inline auto norm_linf(const std::complex<T>& t) noexcept
|
||||
{
|
||||
return (std::max)(std::abs(t.real()), std::abs(t.imag()));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief p-th power of the Lp norm of a complex number.
|
||||
*/
|
||||
template <class T>
|
||||
inline auto norm_lp_to_p(const std::complex<T>& t, double p) noexcept
|
||||
{
|
||||
using rt = decltype(std::pow(std::abs(t.real()), static_cast<T>(p)));
|
||||
return p == 0
|
||||
? static_cast<rt>(t.real() != 0 || t.imag() != 0)
|
||||
: std::pow(std::abs(t.real()), static_cast<T>(p)) +
|
||||
std::pow(std::abs(t.imag()), static_cast<T>(p));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Lp norm of a complex number.
|
||||
*/
|
||||
template <class T>
|
||||
inline auto norm_lp(const std::complex<T>& t, double p) noexcept
|
||||
{
|
||||
return p == 0
|
||||
? norm_lp_to_p(t, p)
|
||||
: std::pow(norm_lp_to_p(t, p), 1.0 / p);
|
||||
}
|
||||
|
||||
/***********************************
|
||||
* norm functions for xexpressions *
|
||||
***********************************/
|
||||
|
||||
#ifdef X_OLD_CLANG
|
||||
#define XTENSOR_NORM_FUNCTION_AXES(NAME) \
|
||||
template <class E, class I, class EVS = DEFAULT_STRATEGY_REDUCERS> \
|
||||
inline auto NAME(E&& e, std::initializer_list<I> axes, EVS es = EVS()) noexcept \
|
||||
{ \
|
||||
using axes_type = std::vector<typename std::decay_t<E>::size_type>; \
|
||||
return NAME(std::forward<E>(e), xtl::forward_sequence<axes_type>(axes), es); \
|
||||
}
|
||||
|
||||
#else
|
||||
#define XTENSOR_NORM_FUNCTION_AXES(NAME) \
|
||||
template <class E, class I, std::size_t N, class EVS = DEFAULT_STRATEGY_REDUCERS> \
|
||||
inline auto NAME(E&& e, const I(&axes)[N], EVS es = EVS()) noexcept \
|
||||
{ \
|
||||
using axes_type = std::array<typename std::decay_t<E>::size_type, N>; \
|
||||
return NAME(std::forward<E>(e), xtl::forward_sequence<axes_type>(axes), es); \
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#define XTENSOR_EMPTY
|
||||
#define XTENSOR_COMMA ,
|
||||
#define XTENSOR_NORM_FUNCTION(NAME, RESULT_TYPE, REDUCE_EXPR, REDUCE_OP, MERGE_FUNC) \
|
||||
template <class E, class X, class EVS = DEFAULT_STRATEGY_REDUCERS, \
|
||||
class = disable_evaluation_strategy<X>> \
|
||||
inline auto NAME(E&& e, X&& axes, EVS es = EVS()) noexcept \
|
||||
{ \
|
||||
using value_type = typename std::decay_t<E>::value_type; \
|
||||
using result_type = RESULT_TYPE; \
|
||||
\
|
||||
auto reduce_func = [](result_type const& r, value_type const& v) { \
|
||||
return REDUCE_EXPR(r REDUCE_OP NAME(v)); \
|
||||
}; \
|
||||
auto init_func = [](value_type const& v) { \
|
||||
return NAME(v); \
|
||||
}; \
|
||||
return reduce(make_xreducer_functor(std::move(reduce_func), \
|
||||
std::move(init_func), \
|
||||
MERGE_FUNC<result_type>()), \
|
||||
std::forward<E>(e), std::forward<X>(axes), es); \
|
||||
} \
|
||||
\
|
||||
template <class E, class EVS = DEFAULT_STRATEGY_REDUCERS, \
|
||||
XTENSOR_REQUIRE<is_xexpression<E>::value>> \
|
||||
inline auto NAME(E&& e, EVS es = EVS()) noexcept \
|
||||
{ \
|
||||
return NAME(std::forward<E>(e), arange(e.dimension()), es); \
|
||||
} \
|
||||
XTENSOR_NORM_FUNCTION_AXES(NAME)
|
||||
|
||||
XTENSOR_NORM_FUNCTION(norm_l0, unsigned long long, XTENSOR_EMPTY, +, std::plus)
|
||||
XTENSOR_NORM_FUNCTION(norm_l1, big_promote_type_t<value_type>, XTENSOR_EMPTY, +, std::plus)
|
||||
XTENSOR_NORM_FUNCTION(norm_sq, big_promote_type_t<value_type>, XTENSOR_EMPTY, +, std::plus)
|
||||
XTENSOR_NORM_FUNCTION(norm_linf, decltype(norm_linf(std::declval<value_type>())), (std::max<result_type>), XTENSOR_COMMA, math::maximum)
|
||||
|
||||
#undef XTENSOR_EMPTY
|
||||
#undef XTENSOR_COMMA
|
||||
#undef XTENSOR_NORM_FUNCTION
|
||||
#undef XTENSOR_NORM_FUNCTION_AXES
|
||||
/// @endcond
|
||||
/**
|
||||
* @ingroup red_functions
|
||||
* @brief L0 (count) pseudo-norm of an array-like argument over given axes.
|
||||
*
|
||||
* Returns an \ref xreducer for the L0 pseudo-norm of the elements across given \em axes.
|
||||
* @param e an \ref xexpression
|
||||
* @param axes the axes along which the norm is computed (optional)
|
||||
* @param es evaluation strategy to use (lazy (default), or immediate)
|
||||
* @return an \ref xreducer (or xcontainer, depending on evaluation strategy)
|
||||
* When no axes are provided, the norm is calculated over the entire array. In this case,
|
||||
* the reducer represents a scalar result, otherwise an array of appropriate dimension.
|
||||
*/
|
||||
template <class E, class X, class EVS, class>
|
||||
auto norm_l0(E&& e, X&& axes, EVS es) noexcept;
|
||||
|
||||
/**
|
||||
* @ingroup red_functions
|
||||
* @brief L1 norm of an array-like argument over given axes.
|
||||
*
|
||||
* Returns an \ref xreducer for the L1 norm of the elements across given \em axes.
|
||||
* @param e an \ref xexpression
|
||||
* @param axes the axes along which the norm is computed (optional)
|
||||
* @param es evaluation strategy to use (lazy (default), or immediate)
|
||||
* @return an \ref xreducer (or xcontainer, depending on evaluation strategy)
|
||||
* When no axes are provided, the norm is calculated over the entire array. In this case,
|
||||
* the reducer represents a scalar result, otherwise an array of appropriate dimension.
|
||||
*/
|
||||
template <class E, class X, class EVS, class>
|
||||
auto norm_l1(E&& e, X&& axes, EVS es) noexcept;
|
||||
|
||||
/**
|
||||
* @ingroup red_functions
|
||||
* @brief Squared L2 norm of an array-like argument over given axes.
|
||||
*
|
||||
* Returns an \ref xreducer for the squared L2 norm of the elements across given \em axes.
|
||||
* @param e an \ref xexpression
|
||||
* @param axes the axes along which the norm is computed (optional)
|
||||
* @param es evaluation strategy to use (lazy (default), or immediate)
|
||||
* @return an \ref xreducer (or xcontainer, depending on evaluation strategy)
|
||||
* When no axes are provided, the norm is calculated over the entire array. In this case,
|
||||
* the reducer represents a scalar result, otherwise an array of appropriate dimension.
|
||||
*/
|
||||
template <class E, class X, class EVS, class>
|
||||
auto norm_sq(E&& e, X&& axes, EVS es) noexcept;
|
||||
|
||||
/**
|
||||
* @ingroup red_functions
|
||||
* @brief L2 norm of a scalar or array-like argument.
|
||||
* @param e an xexpression
|
||||
* @param es evaluation strategy to use (lazy (default), or immediate)
|
||||
* For scalar types: implemented as <tt>abs(t)</tt><br>
|
||||
* otherwise: implemented as <tt>sqrt(norm_sq(t))</tt>.
|
||||
*/
|
||||
template <class E, class EVS = DEFAULT_STRATEGY_REDUCERS, XTENSOR_REQUIRE<is_xexpression<E>::value>>
|
||||
inline auto norm_l2(E&& e, EVS es = EVS()) noexcept
|
||||
{
|
||||
using std::sqrt;
|
||||
return sqrt(norm_sq(std::forward<E>(e), es));
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup red_functions
|
||||
* @brief L2 norm of an array-like argument over given axes.
|
||||
*
|
||||
* Returns an \ref xreducer for the L2 norm of the elements across given \em axes.
|
||||
* @param e an \ref xexpression
|
||||
* @param es evaluation strategy to use (lazy (default), or immediate)
|
||||
* @param axes the axes along which the norm is computed
|
||||
* @return an \ref xreducer (specifically: <tt>sqrt(norm_sq(e, axes))</tt>) (or xcontainer, depending on evaluation strategy)
|
||||
*/
|
||||
template <class E, class X, class EVS = DEFAULT_STRATEGY_REDUCERS,
|
||||
XTENSOR_REQUIRE<is_xexpression<E>::value>, class = disable_evaluation_strategy<X>>
|
||||
inline auto norm_l2(E&& e, X&& axes, EVS es = EVS()) noexcept
|
||||
{
|
||||
return sqrt(norm_sq(std::forward<E>(e), std::forward<X>(axes), es));
|
||||
}
|
||||
|
||||
#ifdef X_OLD_CLANG
|
||||
template <class E, class I, class EVS = DEFAULT_STRATEGY_REDUCERS>
|
||||
inline auto norm_l2(E&& e, std::initializer_list<I> axes, EVS es = EVS()) noexcept
|
||||
{
|
||||
using axes_type = std::vector<typename std::decay_t<E>::size_type>;
|
||||
return sqrt(norm_sq(std::forward<E>(e), xtl::forward_sequence<axes_type>(axes), es));
|
||||
}
|
||||
#else
|
||||
template <class E, class I, std::size_t N, class EVS = DEFAULT_STRATEGY_REDUCERS>
|
||||
inline auto norm_l2(E&& e, const I (&axes)[N], EVS es = EVS()) noexcept
|
||||
{
|
||||
using axes_type = std::array<typename std::decay_t<E>::size_type, N>;
|
||||
return sqrt(norm_sq(std::forward<E>(e), xtl::forward_sequence<axes_type>(axes), es));
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @ingroup red_functions
|
||||
* @brief Infinity (maximum) norm of an array-like argument over given axes.
|
||||
*
|
||||
* Returns an \ref xreducer for the infinity norm of the elements across given \em axes.
|
||||
* @param e an \ref xexpression
|
||||
* @param axes the axes along which the norm is computed (optional)
|
||||
* @param es evaluation strategy to use (lazy (default), or immediate)
|
||||
* @return an \ref xreducer (or xcontainer, depending on evaluation strategy)
|
||||
* When no axes are provided, the norm is calculated over the entire array. In this case,
|
||||
* the reducer represents a scalar result, otherwise an array of appropriate dimension.
|
||||
*/
|
||||
template <class E, class X, class EVS, class>
|
||||
auto norm_linf(E&& e, X&& axes, EVS es) noexcept;
|
||||
|
||||
/**
|
||||
* @ingroup red_functions
|
||||
* @brief p-th power of the Lp norm of an array-like argument over given axes.
|
||||
*
|
||||
* Returns an \ref xreducer for the p-th power of the Lp norm of the elements across given \em axes.
|
||||
* @param e an \ref xexpression
|
||||
* @param p
|
||||
* @param axes the axes along which the norm is computed (optional)
|
||||
* @param es evaluation strategy to use (lazy (default), or immediate)
|
||||
* @return an \ref xreducer (or xcontainer, depending on evaluation strategy)
|
||||
* When no axes are provided, the norm is calculated over the entire array. In this case,
|
||||
* the reducer represents a scalar result, otherwise an array of appropriate dimension.
|
||||
*/
|
||||
template <class E, class X, class EVS = DEFAULT_STRATEGY_REDUCERS, class = disable_evaluation_strategy<X>>
|
||||
inline auto norm_lp_to_p(E&& e, double p, X&& axes, EVS es = EVS()) noexcept
|
||||
{
|
||||
using value_type = typename std::decay_t<E>::value_type;
|
||||
using result_type = norm_type_t<std::decay_t<E>>;
|
||||
|
||||
auto reduce_func = [p](result_type const& r, value_type const& v) {
|
||||
return r + norm_lp_to_p(v, p);
|
||||
};
|
||||
|
||||
auto init_func = [p](value_type const& v) {
|
||||
return norm_lp_to_p(v, p);
|
||||
};
|
||||
return reduce(make_xreducer_functor(std::move(reduce_func), std::move(init_func), std::plus<result_type>()),
|
||||
std::forward<E>(e), std::forward<X>(axes), es);
|
||||
}
|
||||
|
||||
template <class E, XTENSOR_REQUIRE<is_xexpression<E>::value>, class EVS = DEFAULT_STRATEGY_REDUCERS>
|
||||
inline auto norm_lp_to_p(E&& e, double p, EVS es = EVS()) noexcept
|
||||
{
|
||||
return norm_lp_to_p(std::forward<E>(e), p, arange(e.dimension()), es);
|
||||
}
|
||||
|
||||
#ifdef X_OLD_CLANG
|
||||
template <class E, class I, class EVS = DEFAULT_STRATEGY_REDUCERS>
|
||||
inline auto norm_lp_to_p(E&& e, double p, std::initializer_list<I> axes, EVS es = EVS()) noexcept
|
||||
{
|
||||
using axes_type = std::vector<typename std::decay_t<E>::size_type>;
|
||||
return norm_lp_to_p(std::forward<E>(e), p, xtl::forward_sequence<axes_type>(axes), es);
|
||||
}
|
||||
#else
|
||||
template <class E, class I, std::size_t N, class EVS = DEFAULT_STRATEGY_REDUCERS>
|
||||
inline auto norm_lp_to_p(E&& e, double p, const I (&axes)[N], EVS es = EVS()) noexcept
|
||||
{
|
||||
using axes_type = std::array<typename std::decay_t<E>::size_type, N>;
|
||||
return norm_lp_to_p(std::forward<E>(e), p, xtl::forward_sequence<axes_type>(axes), es);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @ingroup red_functions
|
||||
* @brief Lp norm of an array-like argument over given axes.
|
||||
*
|
||||
* Returns an \ref xreducer for the Lp norm (p != 0) of the elements across given \em axes.
|
||||
* @param e an \ref xexpression
|
||||
* @param p
|
||||
* @param axes the axes along which the norm is computed (optional)
|
||||
* @param es evaluation strategy to use (lazy (default), or immediate)
|
||||
* @return an \ref xreducer (or xcontainer, depending on evaluation strategy)
|
||||
* When no axes are provided, the norm is calculated over the entire array. In this case,
|
||||
* the reducer represents a scalar result, otherwise an array of appropriate dimension.
|
||||
*/
|
||||
template <class E, class X, class EVS = DEFAULT_STRATEGY_REDUCERS, class = disable_evaluation_strategy<X>>
|
||||
inline auto norm_lp(E&& e, double p, X&& axes, EVS es = EVS())
|
||||
{
|
||||
XTENSOR_PRECONDITION(p != 0,
|
||||
"norm_lp(): p must be nonzero, use norm_l0() instead.");
|
||||
return pow(norm_lp_to_p(std::forward<E>(e), p, std::forward<X>(axes), es), 1.0 / p);
|
||||
}
|
||||
|
||||
template <class E, XTENSOR_REQUIRE<is_xexpression<E>::value>, class EVS = DEFAULT_STRATEGY_REDUCERS>
|
||||
inline auto norm_lp(E&& e, double p, EVS es = EVS())
|
||||
{
|
||||
return norm_lp(std::forward<E>(e), p, arange(e.dimension()), es);
|
||||
}
|
||||
|
||||
#ifdef X_OLD_CLANG
|
||||
template <class E, class I, class EVS = DEFAULT_STRATEGY_REDUCERS>
|
||||
inline auto norm_lp(E&& e, double p, std::initializer_list<I> axes, EVS es = EVS())
|
||||
{
|
||||
using axes_type = std::vector<typename std::decay_t<E>::size_type>;
|
||||
return norm_lp(std::forward<E>(e), p, xtl::forward_sequence<axes_type>(axes), es);
|
||||
}
|
||||
#else
|
||||
template <class E, class I, std::size_t N, class EVS = DEFAULT_STRATEGY_REDUCERS>
|
||||
inline auto norm_lp(E&& e, double p, const I (&axes)[N], EVS es = EVS())
|
||||
{
|
||||
using axes_type = std::array<typename std::decay_t<E>::size_type, N>;
|
||||
return norm_lp(std::forward<E>(e), p, xtl::forward_sequence<axes_type>(axes), es);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @ingroup red_functions
|
||||
* @brief Induced L1 norm of a matrix.
|
||||
*
|
||||
* Returns an \ref xreducer for the induced L1 norm (i.e. the maximum of the L1 norms of e's columns).
|
||||
* @param e a 2D \ref xexpression
|
||||
* @param es evaluation strategy to use (lazy (default), or immediate)
|
||||
* @return an \ref xreducer (or xcontainer, depending on evaluation strategy)
|
||||
*/
|
||||
template <class E, class EVS = DEFAULT_STRATEGY_REDUCERS, XTENSOR_REQUIRE<is_xexpression<E>::value>>
|
||||
inline auto norm_induced_l1(E&& e, EVS es = EVS())
|
||||
{
|
||||
XTENSOR_PRECONDITION(e.dimension() == 2,
|
||||
"norm_induced_l1(): only applicable to matrices (e.dimension() must be 2).");
|
||||
return norm_linf(norm_l1(std::forward<E>(e), {0}, es), es);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup red_functions
|
||||
* @brief Induced L-infinity norm of a matrix.
|
||||
*
|
||||
* Returns an \ref xreducer for the induced L-infinity norm (i.e. the maximum of the L1 norms of e's rows).
|
||||
* @param e a 2D \ref xexpression
|
||||
* @param es evaluation strategy to use (lazy (default), or immediate)
|
||||
* @return an \ref xreducer (or xcontainer, depending on evaluation strategy)
|
||||
*/
|
||||
template <class E, class EVS = DEFAULT_STRATEGY_REDUCERS, XTENSOR_REQUIRE<is_xexpression<E>::value>>
|
||||
inline auto norm_induced_linf(E&& e, EVS es = EVS())
|
||||
{
|
||||
XTENSOR_PRECONDITION(e.dimension() == 2,
|
||||
"norm_induced_linf(): only applicable to matrices (e.dimension() must be 2).");
|
||||
return norm_linf(norm_l1(std::forward<E>(e), {1}, es), es);
|
||||
}
|
||||
|
||||
} // namespace xt
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue