Skip to content

Instantly share code, notes, and snippets.

@insertinterestingnamehere
Created April 7, 2016 23:45
Show Gist options
  • Save insertinterestingnamehere/c4d7e440b754b190be1e97d02dba2c85 to your computer and use it in GitHub Desktop.
Save insertinterestingnamehere/c4d7e440b754b190be1e97d02dba2c85 to your computer and use it in GitHub Desktop.
Demonstrates a bug in MSVC 2015 Update 2
#include <map>
#include <memory>
#include <vector>
#include <limits>
#include <cstdint>
#include <iostream>
#include <atomic>
#include <sstream>
#include <algorithm>
#include <array>
#include <complex>
#include <unordered_set>
#include <list>
#include <bitset>
class disable_invalid_parameter_handler {
_invalid_parameter_handler m_saved;
disable_invalid_parameter_handler(const disable_invalid_parameter_handler &);
disable_invalid_parameter_handler &operator=(const disable_invalid_parameter_handler &);
static void nop_parameter_handler(const wchar_t *, const wchar_t *, const wchar_t *, unsigned int, uintptr_t) {}
public:
disable_invalid_parameter_handler() { m_saved = _set_invalid_parameter_handler(&nop_parameter_handler); }
~disable_invalid_parameter_handler() { _set_invalid_parameter_handler(m_saved); }
};
namespace dynd {
template <typename T>
struct front;
template <typename T>
struct back;
template <typename T>
struct second_back;
template <typename I, size_t J>
struct at;
template <typename I, size_t J>
struct from;
template <typename I, size_t J>
struct to;
template <typename I, typename J>
struct join;
template <typename I, typename J>
struct take;
template <typename T, T... I>
struct integer_sequence {
enum { size = sizeof...(I) };
typedef T value_type;
static constexpr size_t size2() { return sizeof...(I); }
};
namespace detail {
template <typename SequenceType>
struct i2a;
template <typename T, T... I>
struct i2a<integer_sequence<T, I...>> {
static const std::array<T, sizeof...(I)> value;
};
template <typename T, T... I>
const std::array<T, sizeof...(I)> i2a<integer_sequence<T, I...>>::value = {{I...}};
}
template <typename SequenceType>
const std::array<typename SequenceType::value_type, SequenceType::size> &i2a() {
return detail::i2a<SequenceType>::value;
}
template <typename T>
struct is_integer_sequence {
static const bool value = false;
};
template <typename T, T... I>
struct is_integer_sequence<integer_sequence<T, I...>> {
static const bool value = true;
};
template <std::size_t... I>
using index_sequence = integer_sequence<size_t, I...>;
template <typename T>
struct is_index_sequence {
static const bool value = false;
};
template <std::size_t... I>
struct is_index_sequence<index_sequence<I...>> {
static const bool value = true;
};
template <typename T, T I0, T... I>
struct at<integer_sequence<T, I0, I...>, 0> {
enum { value = I0 };
};
template <typename T, T I0, T... I, size_t J>
struct at<integer_sequence<T, I0, I...>, J> {
enum { value = at<integer_sequence<T, I...>, J - 1>::value };
};
template <typename T, T... I, T... J>
struct join<integer_sequence<T, I...>, integer_sequence<T, J...>> {
typedef integer_sequence<T, I..., J...> type;
};
namespace detail {
template <int flags, typename T, T...>
struct make_integer_sequence;
template <int flags, typename T, T stop>
struct make_integer_sequence<flags, T, stop> : make_integer_sequence<flags, T, 0, stop> {};
template <int flags, typename T, T start, T stop>
struct make_integer_sequence<flags, T, start, stop> : make_integer_sequence<flags, T, start, stop, 1> {};
template <typename T, T start, T stop, T step>
struct make_integer_sequence<-1, T, start, stop, step> : make_integer_sequence<(start < stop), T, start, stop, step> {
};
template <typename T, T start, T stop, T step>
struct make_integer_sequence<0, T, start, stop, step> {
typedef integer_sequence<T> type;
};
template <typename T, T start, T stop, T step>
struct make_integer_sequence<1, T, start, stop, step> {
enum { next = start + step };
typedef typename join < integer_sequence<T, start>,
typename make_integer_sequence<next<stop, T, next, stop, step>::type>::type type;
};
}
template <typename T, T... I>
using make_integer_sequence = typename detail::make_integer_sequence<-1, T, I...>::type;
template <size_t... I>
using make_index_sequence = typename detail::make_integer_sequence<-1, size_t, I...>::type;
template <typename T, T I0, T... I>
struct front<integer_sequence<T, I0, I...>> {
static const T value = I0;
};
template <typename T, T I0>
struct back<integer_sequence<T, I0>> {
static const T value = I0;
};
template <typename T, T I0, T... I>
struct back<integer_sequence<T, I0, I...>> {
static const T value = back<integer_sequence<T, I...>>::value;
};
template <typename T, T I0, T... I>
struct from<integer_sequence<T, I0, I...>, 0> {
typedef integer_sequence<T, I0, I...> type;
};
template <typename T>
struct from<integer_sequence<T>, 0> {
typedef integer_sequence<T> type;
};
template <typename T, T I0, T... I>
struct from<integer_sequence<T, I0, I...>, 1> {
typedef integer_sequence<T, I...> type;
};
template <typename T, T I0, T... I, size_t J>
struct from<integer_sequence<T, I0, I...>, J> {
typedef typename from<integer_sequence<T, I...>, J - 1>::type type;
};
template <typename T, T I0, T... I>
struct to<integer_sequence<T, I0, I...>, 0> {
typedef integer_sequence<T> type;
};
template <typename T>
struct to<integer_sequence<T>, 0> {
typedef integer_sequence<T> type;
};
template <typename T, T I0, T... I>
struct to<integer_sequence<T, I0, I...>, 1> {
typedef integer_sequence<T, I0> type;
};
template <typename T, T I0, T... I, size_t J>
struct to<integer_sequence<T, I0, I...>, J> {
typedef typename join<integer_sequence<T, I0>, typename to<integer_sequence<T, I...>, J - 1>::type>::type type;
};
template <typename... T>
struct type_sequence {
enum { size = sizeof...(T) };
static constexpr size_t size2() { return sizeof...(T); }
};
template <typename T>
struct is_type_sequence {
static const bool value = false;
};
template <typename... T>
struct is_type_sequence<type_sequence<T...>> {
static const bool value = true;
};
template <typename T>
struct back<type_sequence<T>> {
typedef T type;
};
template <typename T0, typename... T>
struct back<type_sequence<T0, T...>> {
typedef typename back<type_sequence<T...>>::type type;
};
template <typename S, typename T>
struct second_back<type_sequence<S, T>> {
typedef S type;
};
template <typename T0, typename T1, typename... T>
struct second_back<type_sequence<T0, T1, T...>> {
typedef typename second_back<type_sequence<T1, T...>>::type type;
};
template <typename T0, typename... T>
struct front<type_sequence<T0, T...>> {
typedef T0 type;
};
template <typename T0, typename... T>
struct at<type_sequence<T0, T...>, 0> {
typedef T0 type;
};
template <size_t I, typename T0, typename... T>
struct at<type_sequence<T0, T...>, I> {
typedef typename at<type_sequence<T...>, I - 1>::type type;
};
template <typename T0, typename... T>
struct from<type_sequence<T0, T...>, 0> {
typedef type_sequence<T0, T...> type;
};
template <>
struct from<type_sequence<>, 0> {
typedef type_sequence<> type;
};
template <typename T0, typename... T>
struct from<type_sequence<T0, T...>, 1> {
typedef type_sequence<T...> type;
};
template <typename T0, typename... T, size_t I>
struct from<type_sequence<T0, T...>, I> {
typedef typename from<type_sequence<T...>, I - 1>::type type;
};
template <typename T0, typename... T>
struct to<type_sequence<T0, T...>, 0> {
typedef type_sequence<> type;
};
template <>
struct to<type_sequence<>, 0> {
typedef type_sequence<> type;
};
template <typename T0, typename... T>
struct to<type_sequence<T0, T...>, 1> {
typedef type_sequence<T0> type;
};
template <typename T0, typename... T, size_t I>
struct to<type_sequence<T0, T...>, I> {
typedef typename join<type_sequence<T0>, typename to<type_sequence<T...>, I - 1>::type>::type type;
};
template <typename... T, typename... U>
struct join<type_sequence<T...>, type_sequence<U...>> {
typedef type_sequence<T..., U...> type;
};
template <typename... T, size_t... I>
struct take<type_sequence<T...>, index_sequence<I...>> {
typedef type_sequence<typename at<type_sequence<T...>, I>::type...> type;
};
template <typename T>
struct pop_front {
typedef typename from<T, 1>::type type;
};
template <typename... S>
struct outer;
template <typename T0, T0 I0, typename T1, T1 I1>
struct outer<integer_sequence<T0, I0>, integer_sequence<T1, I1>> {
typedef type_sequence<integer_sequence<typename std::common_type<T0, T1>::type, I0, I1>> type;
};
template <typename T0, T0 I0, typename T1, T1 I, T1... I1>
struct outer<integer_sequence<T0, I0>, integer_sequence<T1, I, I1...>> {
typedef typename join<type_sequence<integer_sequence<typename std::common_type<T0, T1>::type, I0, I>>,
typename outer<integer_sequence<T0, I0>, integer_sequence<T1, I1...>>::type>::type type;
};
template <typename T0, T0... I0, typename T1, T1 I1>
struct outer<type_sequence<integer_sequence<T0, I0...>>, integer_sequence<T1, I1>> {
typedef type_sequence<integer_sequence<typename std::common_type<T0, T1>::type, I0..., I1>> type;
};
template <typename T0, T0... I0, typename T1, T1 I, T1... I1>
struct outer<type_sequence<integer_sequence<T0, I0...>>, integer_sequence<T1, I, I1...>> {
typedef
typename join<type_sequence<integer_sequence<typename std::common_type<T0, T1>::type, I0..., I>>,
typename outer<type_sequence<integer_sequence<T0, I0...>>, integer_sequence<T1, I1...>>::type>::type
type;
};
template <typename T0, typename... T1>
struct outer<type_sequence<T0>, type_sequence<T1...>> {
typedef type_sequence<type_sequence<T0, T1>...> type;
};
template <typename... T0, typename... T1>
struct outer<type_sequence<type_sequence<T0...>>, type_sequence<T1...>> {
typedef type_sequence<type_sequence<T0..., T1>...> type;
};
template <typename S0, typename S1>
struct outer<S0, S1> {
typedef typename join<typename outer<typename to<S0, 1>::type, S1>::type,
typename outer<typename pop_front<S0>::type, S1>::type>::type type;
};
template <typename S0, typename S1, typename... S>
struct outer<S0, S1, S...> {
typedef typename outer<typename outer<S0, S1>::type, S...>::type type;
};
template <typename S, typename A0, typename... A>
typename std::enable_if<S::size == 1 && is_integer_sequence<S>::value, void>::type for_each(A0 &&a0, A &&... a) {
a0.template on_each<front<S>::value>(std::forward<A>(a)...);
}
template <typename S, typename A0, typename... A>
typename std::enable_if<S::size == 1 && is_type_sequence<S>::value, void>::type for_each(A0 &&a0, A &&... a) {
a0.template on_each<typename front<S>::type>(std::forward<A>(a)...);
}
template <typename S, typename... A>
typename std::enable_if<(S::size2() > 1), void>::type for_each(A &&... a) {
for_each<typename to<S, 1>::type>(std::forward<A>(a)...);
for_each<typename pop_front<S>::type>(std::forward<A>(a)...);
}
}
namespace dynd {
template <typename T, typename U, typename V>
struct is_common_type_of : std::conditional<std::is_same<T, typename std::common_type<U, V>::type>::value,
std::true_type, std::false_type>::type {
};
template <bool Value, template <typename...> class T, template <typename...> class U, typename... As>
struct conditional_make;
template <template <typename...> class T, template <typename...> class U, typename... As>
struct conditional_make<true, T, U, As...> {
typedef T<As...> type;
};
template <template <typename...> class T, template <typename...> class U, typename... As>
struct conditional_make<false, T, U, As...> {
typedef U<As...> type;
};
template <typename T>
struct is_function_pointer {
static const bool value =
std::is_pointer<T>::value ? std::is_function<typename std::remove_pointer<T>::type>::value : false;
};
template <typename T>
struct is_vector : std::false_type {
};
template <typename T>
struct is_vector<std::vector<T>> : std::true_type {
};
template <typename T>
long intrusive_ptr_use_count(T *ptr);
template <typename T>
void intrusive_ptr_retain(T *ptr);
template <typename T>
void intrusive_ptr_release(T *ptr);
template <typename T>
class intrusive_ptr {
protected:
T *m_ptr;
public:
intrusive_ptr() : m_ptr(0) {}
explicit intrusive_ptr(T *ptr, bool add_ref = true) : m_ptr(ptr)
{
if (m_ptr != 0 && add_ref) {
intrusive_ptr_retain(m_ptr);
}
}
intrusive_ptr(const intrusive_ptr &other) : m_ptr(other.m_ptr)
{
if (m_ptr != 0) {
intrusive_ptr_retain(m_ptr);
}
}
intrusive_ptr(intrusive_ptr &&other) : m_ptr(other.m_ptr) { other.m_ptr = 0; }
~intrusive_ptr()
{
if (m_ptr != 0) {
intrusive_ptr_release(m_ptr);
}
}
intptr_t use_count() const { return intrusive_ptr_use_count(m_ptr); }
explicit operator bool() const { return m_ptr != 0; }
T *operator->() const { return m_ptr; }
intrusive_ptr &operator=(const intrusive_ptr &rhs)
{
if (m_ptr != 0) {
intrusive_ptr_release(m_ptr);
}
if (rhs.m_ptr != 0) {
m_ptr = rhs.m_ptr;
intrusive_ptr_retain(m_ptr);
}
else {
m_ptr = 0;
}
return *this;
}
intrusive_ptr &operator=(intrusive_ptr &&rhs)
{
if (m_ptr != 0) {
intrusive_ptr_release(m_ptr);
}
m_ptr = rhs.m_ptr;
rhs.m_ptr = 0;
return *this;
}
intrusive_ptr &operator=(T *rhs)
{
if (m_ptr != nullptr) {
intrusive_ptr_release(m_ptr);
}
m_ptr = rhs;
if (m_ptr != nullptr) {
intrusive_ptr_retain(m_ptr);
}
return *this;
}
bool unique() const { return intrusive_ptr_use_count(m_ptr) <= 1; }
T *get() const { return m_ptr; }
T *release()
{
T *result = m_ptr;
m_ptr = 0;
return result;
}
void swap(intrusive_ptr &rhs)
{
T *tmp = m_ptr;
m_ptr = rhs.m_ptr;
rhs.m_ptr = tmp;
}
};
template <typename T>
bool operator==(const intrusive_ptr<T> &lhs, const intrusive_ptr<T> &rhs)
{
return lhs.get() == rhs.get();
}
template <typename T>
bool operator!=(const intrusive_ptr<T> &lhs, const intrusive_ptr<T> &rhs)
{
return lhs.get() == rhs.get();
}
template <template <typename...> class T, typename U>
struct is_instance {
static const bool value = false;
};
template <template <typename...> class T, typename... A>
struct is_instance<T, T<A...>> {
static const bool value = true;
};
template <typename T, typename U>
T alias_cast(U value)
{
union {
U tmp;
T res;
};
tmp = value;
return res;
}
template <typename T>
struct is_char_string_param {
static const bool value = false;
};
template <>
struct is_char_string_param<const char *> {
static const bool value = true;
};
template <>
struct is_char_string_param<char *> {
static const bool value = true;
};
template <int N>
struct is_char_string_param<const char(&)[N]> {
static const bool value = true;
};
template <int N>
struct is_char_string_param<const char(&&)[N]> {
static const bool value = true;
};
template <typename... T>
struct all_char_string_params {
static const bool value = false;
};
template <>
struct all_char_string_params<> {
static const bool value = true;
};
template <typename T0>
struct all_char_string_params<T0> {
static const bool value = is_char_string_param<T0>::value;
};
template <typename... T, typename T0>
struct all_char_string_params<T0, T...> {
static const bool value = is_char_string_param<T0>::value && all_char_string_params<T...>::value;
};
template <typename T>
struct remove_all_pointers {
typedef T type;
};
template <typename T>
struct remove_reference_then_cv {
typedef typename std::remove_cv<typename std::remove_reference<T>::type>::type type;
};
template <typename T>
struct remove_all_pointers<T *> {
typedef typename remove_all_pointers<typename std::remove_cv<T>::type>::type type;
};
namespace detail {
template <typename func_type, typename... B>
struct funcproto {
typedef typename funcproto<decltype(&func_type::operator()), B...>::type type;
};
template <typename R, typename... A, typename... B>
struct funcproto<R(A...), B...> {
typedef R(type)(A..., B...);
};
template <typename R, typename... A, typename... B>
struct funcproto<R (*)(A...), B...> {
typedef typename funcproto<R(A...), B...>::type type;
};
template <typename T, typename R, typename... A, typename... B>
struct funcproto<R (T::*)(A...), B...> {
typedef typename funcproto<R(A...), B...>::type type;
};
template <typename T, typename R, typename... A, typename... B>
struct funcproto<R (T::*)(A...) const, B...> {
typedef typename funcproto<R(A...), B...>::type type;
};
}
template <typename func_type, typename... B>
struct funcproto_of {
typedef typename detail::funcproto<func_type, B...>::type type;
};
template <typename func_type, typename... B>
struct funcproto_of<func_type *, B...> {
typedef typename funcproto_of<func_type, B...>::type type;
};
template <typename func_type>
struct return_of {
typedef typename return_of<typename funcproto_of<func_type>::type>::type type;
};
template <typename R, typename... A>
struct return_of<R(A...)> {
typedef R type;
};
template <typename func_type>
struct args_of {
typedef typename args_of<typename funcproto_of<func_type>::type>::type type;
};
template <typename R, typename... A>
struct args_of<R(A...)> {
typedef type_sequence<A...> type;
};
template <typename func_type>
struct arity_of {
static const size_t value = arity_of<typename funcproto_of<func_type>::type>::value;
};
template <typename R, typename... A>
struct arity_of<R(A...)> {
static const size_t value = sizeof...(A);
};
template <typename func_type, int I>
struct arg_at {
typedef typename at<typename args_of<func_type>::type, I>::type type;
};
}
namespace dynd {
inline int libdynd_init() { return 0; }
inline void libdynd_cleanup() {}
bool built_with_cuda();
}
namespace dynd {
class bool1;
typedef std::int8_t int8;
typedef std::int16_t int16;
typedef std::int32_t int32;
typedef std::int64_t int64;
class int128;
typedef std::uint8_t uint8;
typedef std::uint16_t uint16;
typedef std::uint32_t uint32;
typedef std::uint64_t uint64;
class uint128;
class float16;
typedef float float32;
typedef double float64;
class float128;
template <typename T>
struct is_boolean {
static const bool value = false;
};
template <>
struct is_boolean<bool> {
static const bool value = true;
};
template <>
struct is_boolean<bool1> {
static const bool value = true;
};
template <typename T>
struct is_integral : std::is_integral<T> {
};
template <typename T>
struct is_floating_point : std::is_floating_point<T> {
};
template <typename T>
struct is_complex : std::false_type {
};
template <typename T>
struct is_arithmetic : std::integral_constant<bool, is_integral<T>::value || is_floating_point<T>::value> {
};
template <typename T>
struct is_numeric : std::integral_constant<bool, is_arithmetic<T>::value || is_complex<T>::value> {
};
template <typename T, typename U>
struct is_mixed_arithmetic : std::integral_constant<bool, is_arithmetic<T>::value && is_arithmetic<U>::value> {
};
template <typename T>
struct is_mixed_arithmetic<T, T> : std::false_type {
};
template <typename... Ts>
using true_t = std::true_type;
template <typename... Ts>
using false_t = std::false_type;
template <typename T>
using not_t = std::integral_constant<bool, !T::value>;
template <typename T, typename U>
struct is_lcast_arithmetic : not_t<typename conditional_make<is_arithmetic<T>::value && is_arithmetic<U>::value,
is_common_type_of, true_t, T, T, U>::type> {
};
template <typename T, typename U>
struct is_rcast_arithmetic : not_t<typename conditional_make<is_arithmetic<T>::value && is_arithmetic<U>::value,
is_common_type_of, true_t, U, T, U>::type> {
};
template <typename T>
struct is_signed {
static const bool value = std::is_signed<T>::value || std::is_same<T, int128>::value;
};
template <typename T>
struct is_unsigned {
static const bool value = std::is_unsigned<T>::value || std::is_same<T, uint128>::value;
};
template <typename T>
T strto(const char *begin, char **end);
template <>
inline float strto(const char *begin, char **end)
{
return std::strtof(begin, end);
}
template <>
inline double strto(const char *begin, char **end)
{
return std::strtod(begin, end);
}
template <typename T>
T floor(T value)
{
return std::floor(value);
}
enum assign_error_mode {
assign_error_nocheck,
assign_error_overflow,
assign_error_fractional,
assign_error_inexact,
assign_error_default
};
struct overflow_check_t {
};
inline std::ostream &operator<<(std::ostream &o, assign_error_mode errmode)
{
switch (errmode) {
case assign_error_nocheck:
o << "nocheck";
break;
case assign_error_overflow:
o << "overflow";
break;
case assign_error_fractional:
o << "fractional";
break;
case assign_error_inexact:
o << "inexact";
break;
case assign_error_default:
o << "default";
break;
default:
o << "invalid error mode(" << (int)errmode << ")";
break;
}
return o;
}
namespace detail {
template <typename T, typename... Types>
struct TypeSetCheckInternal : std::is_same<T, Types>... {
};
template <typename T, typename... Types>
struct TypeSetCheck : std::is_base_of<std::true_type, TypeSetCheckInternal<T, Types...>>::type {
};
template <typename T, typename... Types>
struct enable_for : std::enable_if<TypeSetCheck<T, Types...>::value, int> {
};
}
}
namespace dynd {
class __declspec(dllexport) bool1 {
char m_value;
public:
bool1() = default;
explicit bool1(bool value) : m_value(value) {}
operator bool() const { return m_value != 0; }
bool1 &operator=(bool rhs)
{
m_value = rhs;
return *this;
}
bool1 operator+() const { return *this; }
bool1 operator-() const { return *this; }
bool1 operator!() const { return bool1(m_value == 0); }
bool1 operator~() const { return bool1(m_value == 0); }
bool1 operator&&(bool1 &rhs) { return bool1(m_value && rhs.m_value); }
bool1 operator||(bool1 &rhs) { return bool1(m_value || rhs.m_value); }
bool1 &operator+=(bool1 rhs)
{
m_value += rhs.m_value;
return *this;
}
bool1 &operator-=(bool1 rhs)
{
m_value -= rhs.m_value;
return *this;
}
bool1 &operator*=(bool1 rhs)
{
m_value *= rhs.m_value;
return *this;
}
bool1 &operator/=(bool1 rhs)
{
m_value /= rhs.m_value;
return *this;
}
friend int operator+(bool1 lhs, bool1 rhs);
friend int operator-(bool1 lhs, bool1 rhs);
friend int operator*(bool1 lhs, bool1 rhs);
friend int operator/(bool1 lhs, bool1 rhs);
};
template <>
struct is_integral<bool1> : std::true_type {
};
inline int operator+(bool1 lhs, bool1 rhs) { return lhs.m_value + rhs.m_value; }
inline int operator-(bool1 lhs, bool1 rhs) { return lhs.m_value - rhs.m_value; }
inline int operator*(bool1 lhs, bool1 rhs) { return lhs.m_value * rhs.m_value; }
inline int operator/(bool1 lhs, bool1 rhs) { return lhs.m_value / rhs.m_value; }
}
namespace std {
template <>
struct common_type<dynd::bool1, bool> : common_type<char, bool> {
};
template <>
struct common_type<dynd::bool1, dynd::bool1> {
typedef dynd::bool1 type;
};
template <>
struct common_type<dynd::bool1, char> : common_type<char, char> {
};
template <>
struct common_type<dynd::bool1, signed char> : common_type<char, signed char> {
};
template <>
struct common_type<dynd::bool1, unsigned char> : common_type<char, unsigned char> {
};
template <>
struct common_type<dynd::bool1, short> : common_type<char, short> {
};
template <>
struct common_type<dynd::bool1, unsigned short> : common_type<char, unsigned short> {
};
template <>
struct common_type<dynd::bool1, int> : common_type<char, int> {
};
template <>
struct common_type<dynd::bool1, unsigned int> : common_type<char, unsigned int> {
};
template <>
struct common_type<dynd::bool1, long> : common_type<char, long> {
};
template <>
struct common_type<dynd::bool1, unsigned long> : common_type<char, unsigned long> {
};
template <>
struct common_type<dynd::bool1, long long> : common_type<char, long long> {
};
template <>
struct common_type<dynd::bool1, unsigned long long> : common_type<char, unsigned long long> {
};
template <>
struct common_type<dynd::bool1, float> : common_type<char, float> {
};
template <>
struct common_type<dynd::bool1, double> : common_type<char, double> {
};
template <typename T>
struct common_type<T, dynd::bool1> : common_type<dynd::bool1, T> {
};
}
namespace dynd {
inline bool operator<(bool1 lhs, bool1 rhs) { return static_cast<bool>(lhs) < static_cast<bool>(rhs); }
template <typename T>
typename std::enable_if<std::is_arithmetic<T>::value, bool>::type operator<(bool1 lhs, T rhs)
{
return static_cast<T>(lhs) < rhs;
}
template <typename T>
typename std::enable_if<std::is_arithmetic<T>::value, bool>::type operator<(T lhs, bool1 rhs)
{
return lhs < static_cast<T>(rhs);
}
inline bool operator<=(bool1 lhs, bool1 rhs) { return static_cast<bool>(lhs) <= static_cast<bool>(rhs); }
template <typename T>
typename std::enable_if<std::is_arithmetic<T>::value, bool>::type operator<=(bool1 lhs, T rhs)
{
return static_cast<T>(lhs) <= rhs;
}
template <typename T>
typename std::enable_if<std::is_arithmetic<T>::value, bool>::type operator<=(T lhs, bool1 rhs)
{
return lhs <= static_cast<T>(rhs);
}
inline bool operator==(bool1 lhs, bool1 rhs) { return static_cast<bool>(lhs) == static_cast<bool>(rhs); }
template <typename T>
typename std::enable_if<std::is_arithmetic<T>::value, bool>::type operator==(bool1 lhs, T rhs)
{
return static_cast<T>(lhs) == rhs;
}
template <typename T>
typename std::enable_if<std::is_arithmetic<T>::value, bool>::type operator==(T lhs, bool1 rhs)
{
return lhs == static_cast<T>(rhs);
}
inline bool operator!=(bool1 lhs, bool1 rhs) { return static_cast<bool>(lhs) != static_cast<bool>(rhs); }
template <typename T>
typename std::enable_if<std::is_arithmetic<T>::value, bool>::type operator!=(bool1 lhs, T rhs)
{
return static_cast<T>(lhs) != rhs;
}
template <typename T>
typename std::enable_if<std::is_arithmetic<T>::value, bool>::type operator!=(T lhs, bool1 rhs)
{
return lhs != static_cast<T>(rhs);
}
inline bool operator>=(bool1 lhs, bool1 rhs) { return static_cast<bool>(lhs) >= static_cast<bool>(rhs); }
template <typename T>
typename std::enable_if<std::is_arithmetic<T>::value, bool>::type operator>=(bool1 lhs, T rhs)
{
return static_cast<T>(lhs) >= rhs;
}
template <typename T>
typename std::enable_if<std::is_arithmetic<T>::value, bool>::type operator>=(T lhs, bool1 rhs)
{
return lhs >= static_cast<T>(rhs);
}
inline bool operator>(bool1 lhs, bool1 rhs) { return static_cast<bool>(lhs) > static_cast<bool>(rhs); }
template <typename T>
typename std::enable_if<std::is_arithmetic<T>::value, bool>::type operator>(bool1 lhs, T rhs)
{
return static_cast<T>(lhs) > rhs;
}
template <typename T>
typename std::enable_if<std::is_arithmetic<T>::value, bool>::type operator>(T lhs, bool1 rhs)
{
return lhs > static_cast<T>(rhs);
}
inline std::ostream &operator<<(std::ostream &o, const bool1 &rhs) { return o << static_cast<bool>(rhs); }
}
namespace dynd {
class __declspec(dllimport) int128 {
public:
uint64_t m_lo, m_hi;
int128() {}
int128(uint64_t hi, uint64_t lo) : m_lo(lo), m_hi(hi) {}
int128(bool1) { throw std::runtime_error("int128(bool1) is not implemented"); }
int128(char value) : m_lo((int64_t)value), m_hi(value < 0 ? 0xffffffffffffffffULL : 0ULL) {}
int128(signed char value) : m_lo((int64_t)value), m_hi(value < 0 ? 0xffffffffffffffffULL : 0ULL) {}
int128(unsigned char value) : m_lo(value), m_hi(0ULL) {}
int128(short value) : m_lo((int64_t)value), m_hi(value < 0 ? 0xffffffffffffffffULL : 0ULL) {}
int128(unsigned short value) : m_lo(value), m_hi(0ULL) {}
int128(int value) : m_lo((int64_t)value), m_hi(value < 0 ? 0xffffffffffffffffULL : 0ULL) {}
int128(unsigned int value) : m_lo(value), m_hi(0ULL) {}
int128(long value) : m_lo((int64_t)value), m_hi(value < 0 ? 0xffffffffffffffffULL : 0ULL) {}
int128(unsigned long value) : m_lo(value), m_hi(0ULL) {}
int128(long long value) : m_lo((int64_t)value), m_hi(value < 0 ? 0xffffffffffffffffULL : 0ULL) {}
int128(unsigned long long value) : m_lo(value), m_hi(0ULL) {}
int128(float value);
int128(double value);
int128(const uint128 &value);
int128(const float16 &value);
int128(const float128 &value);
int128 operator+() const { return *this; }
bool operator!() const { return !(this->m_hi) && !(this->m_lo); }
int128 operator~() const { return int128(~m_hi, ~m_lo); }
bool operator==(const int128 &rhs) const { return m_lo == rhs.m_lo && m_hi == rhs.m_hi; }
bool operator==(int rhs) const
{
return static_cast<int64_t>(m_lo) == static_cast<int64_t>(rhs) && m_hi == (rhs >= 0 ? 0ULL : 0xffffffffffffffffULL);
}
bool operator!=(const int128 &rhs) const { return m_lo != rhs.m_lo || m_hi != rhs.m_hi; }
bool operator!=(int rhs) const
{
return static_cast<int64_t>(m_lo) != static_cast<int64_t>(rhs) || m_hi != (rhs >= 0 ? 0ULL : 0xffffffffffffffffULL);
}
bool operator<(float rhs) const { return double(*this) < rhs; }
bool operator<(double rhs) const { return double(*this) < rhs; }
bool operator<(const int128 &rhs) const
{
return (int64_t)m_hi < (int64_t)rhs.m_hi || (m_hi == rhs.m_hi && m_lo < rhs.m_lo);
}
bool operator<=(const int128 &rhs) const
{
return (int64_t)m_hi < (int64_t)rhs.m_hi || (m_hi == rhs.m_hi && m_lo <= rhs.m_lo);
}
bool operator>(const int128 &rhs) const { return rhs.operator<(*this); }
bool operator>=(const int128 &rhs) const { return rhs.operator<=(*this); }
bool is_negative() const { return (m_hi & 0x8000000000000000ULL) != 0; }
void negate()
{
uint64_t lo = ~m_lo, hi = ~m_hi;
uint64_t lo_p1 = lo + 1;
m_hi = hi + (lo_p1 < lo);
m_lo = lo_p1;
}
int128 &operator+=(const int128 &rhs)
{
uint64_t lo = m_lo + rhs.m_lo;
*this = int128(m_hi + ~rhs.m_hi + (lo < m_lo), lo);
return *this;
}
int128 operator-() const
{
uint64_t lo = ~m_lo, hi = ~m_hi;
uint64_t lo_p1 = lo + 1;
return int128(hi + (lo_p1 < lo), lo_p1);
}
int128 operator+(const int128 &rhs) const
{
uint64_t lo = m_lo + rhs.m_lo;
return int128(m_hi + rhs.m_hi + (lo < m_lo), lo);
}
int128 operator-(const int128 &rhs) const
{
uint64_t lo = m_lo + ~rhs.m_lo + 1;
return int128(m_hi + ~rhs.m_hi + (lo < m_lo), lo);
}
int128 operator*(uint32_t rhs) const;
int128 &operator/=(int128 ) { throw std::runtime_error("operator/= is not implemented for int128"); }
operator float() const
{
if (*this < int128(0)) {
int128 tmp = -(*this);
return tmp.m_lo + tmp.m_hi * 18446744073709551616.f;
}
else {
return m_lo + m_hi * 18446744073709551616.f;
}
}
operator double() const
{
if (*this < int128(0)) {
int128 tmp = -(*this);
return tmp.m_lo + tmp.m_hi * 18446744073709551616.0;
}
else {
return m_lo + m_hi * 18446744073709551616.0;
}
}
explicit operator bool() const { return m_lo || m_hi; }
explicit operator char() const { return (char)m_lo; }
explicit operator signed char() const { return (signed char)m_lo; }
explicit operator unsigned char() const { return (unsigned char)m_lo; }
explicit operator short() const { return (short)m_lo; }
explicit operator unsigned short() const { return (unsigned short)m_lo; }
explicit operator int() const { return (int)m_lo; }
explicit operator unsigned int() const { return (unsigned int)m_lo; }
explicit operator long() const { return (long)m_lo; }
explicit operator unsigned long() const { return (unsigned long)m_lo; }
explicit operator long long() const { return (long long)m_lo; }
explicit operator unsigned long long() const { return (unsigned long long)m_lo; }
};
template <>
struct is_integral<int128> : std::true_type {
};
}
namespace std {
template <>
struct common_type<dynd::int128, bool> {
typedef dynd::int128 type;
};
template <>
struct common_type<dynd::int128, dynd::bool1> {
typedef dynd::int128 type;
};
template <>
struct common_type<dynd::int128, char> {
typedef dynd::int128 type;
};
template <>
struct common_type<dynd::int128, signed char> {
typedef dynd::int128 type;
};
template <>
struct common_type<dynd::int128, unsigned char> {
typedef dynd::int128 type;
};
template <>
struct common_type<dynd::int128, short> {
typedef dynd::int128 type;
};
template <>
struct common_type<dynd::int128, unsigned short> {
typedef dynd::int128 type;
};
template <>
struct common_type<dynd::int128, int> {
typedef dynd::int128 type;
};
template <>
struct common_type<dynd::int128, unsigned int> {
typedef dynd::int128 type;
};
template <>
struct common_type<dynd::int128, long> {
typedef dynd::int128 type;
};
template <>
struct common_type<dynd::int128, unsigned long> {
typedef dynd::int128 type;
};
template <>
struct common_type<dynd::int128, long long> {
typedef dynd::int128 type;
};
template <>
struct common_type<dynd::int128, unsigned long long> {
typedef dynd::int128 type;
};
template <>
struct common_type<dynd::int128, dynd::int128> {
typedef dynd::int128 type;
};
template <>
struct common_type<dynd::int128, float> {
typedef float type;
};
template <>
struct common_type<dynd::int128, double> {
typedef double type;
};
template <typename T>
struct common_type<T, dynd::int128> : common_type<dynd::int128, T> {
};
}
namespace dynd {
inline int128 operator/(int128 , int128 )
{
throw std::runtime_error("operator/ is not implemented for int128");
}
inline bool operator==(int lhs, const int128 &rhs) { return rhs == lhs; }
inline bool operator!=(int lhs, const int128 &rhs) { return rhs != lhs; }
inline bool operator<(const int128 &lhs, int rhs) { return lhs < int128(rhs); }
inline bool operator>(const int128 &lhs, int rhs) { return lhs > int128(rhs); }
inline bool operator<(float lhs, const int128 &rhs) { return lhs < double(rhs); }
inline bool operator<(double lhs, const int128 &rhs) { return lhs < double(rhs); }
inline bool operator<(signed char lhs, const int128 &rhs) { return int128(lhs) < rhs; }
inline bool operator<(unsigned char lhs, const int128 &rhs) { return int128(lhs) < rhs; }
inline bool operator<(short lhs, const int128 &rhs) { return int128(lhs) < rhs; }
inline bool operator<(unsigned short lhs, const int128 &rhs) { return int128(lhs) < rhs; }
inline bool operator<(int lhs, const int128 &rhs) { return int128(lhs) < rhs; }
inline bool operator<(unsigned int lhs, const int128 &rhs) { return int128(lhs) < rhs; }
inline bool operator<(long long lhs, const int128 &rhs) { return int128(lhs) < rhs; }
inline bool operator<(unsigned long long lhs, const int128 &rhs) { return int128(lhs) < rhs; }
inline bool operator>(float lhs, const int128 &rhs) { return lhs > double(rhs); }
inline bool operator>(double lhs, const int128 &rhs) { return lhs > double(rhs); }
inline bool operator>(signed char lhs, const int128 &rhs) { return int128(lhs) > rhs; }
inline bool operator>(unsigned char lhs, const int128 &rhs) { return int128(lhs) > rhs; }
inline bool operator>(short lhs, const int128 &rhs) { return int128(lhs) > rhs; }
inline bool operator>(unsigned short lhs, const int128 &rhs) { return int128(lhs) > rhs; }
inline bool operator>(int lhs, const int128 &rhs) { return int128(lhs) > rhs; }
inline bool operator>(unsigned int lhs, const int128 &rhs) { return int128(lhs) > rhs; }
inline bool operator>(long long lhs, const int128 &rhs) { return int128(lhs) > rhs; }
inline bool operator>(unsigned long long lhs, const int128 &rhs) { return int128(lhs) > rhs; }
__declspec(dllimport) std::ostream &operator<<(std::ostream &out, const int128 &val);
}
namespace std {
template <>
class numeric_limits<dynd::int128> {
public:
static const bool is_specialized = true;
static dynd::int128(min)() throw() { return dynd::int128(0x8000000000000000ULL, 0ULL); }
static dynd::int128(max)() throw() { return dynd::int128(0x7fffffffffffffffULL, 0xffffffffffffffffULL); }
static const int digits = 0;
static const int digits10 = 0;
static const bool is_signed = true;
static const bool is_integer = true;
static const bool is_exact = true;
static const int radix = 2;
static dynd::int128 epsilon() throw() { return dynd::int128(0ULL, 1ULL); }
static dynd::int128 round_error() throw() { return dynd::int128(0ULL, 1ULL); }
static const int min_exponent = 0;
static const int min_exponent10 = 0;
static const int max_exponent = 0;
static const int max_exponent10 = 0;
static const bool has_infinity = false;
static const bool has_quiet_NaN = false;
static const bool has_signaling_NaN = false;
static const float_denorm_style has_denorm = denorm_absent;
static const bool has_denorm_loss = false;
static dynd::int128 infinity() throw();
static dynd::int128 quiet_NaN() throw();
static dynd::int128 signaling_NaN() throw();
static dynd::int128 denorm_min() throw();
static const bool is_iec559 = false;
static const bool is_bounded = false;
static const bool is_modulo = false;
static const bool traps = false;
static const bool tinyness_before = false;
static const float_round_style round_style = round_toward_zero;
};
}
namespace dynd {
class int128;
class __declspec(dllimport) uint128 {
public:
uint64_t m_lo, m_hi;
uint128() {}
uint128(uint64_t hi, uint64_t lo) : m_lo(lo), m_hi(hi) {}
uint128(bool1) { throw std::runtime_error("uint128(bool1) is not implemented"); }
uint128(char value) : m_lo(value), m_hi(0ULL) {}
uint128(signed char value) : m_lo(value), m_hi(0ULL) {}
uint128(unsigned char value) : m_lo(value), m_hi(0ULL) {}
uint128(short value) : m_lo(value), m_hi(0ULL) {}
uint128(unsigned short value) : m_lo(value), m_hi(0ULL) {}
uint128(int value) : m_lo(value), m_hi(0ULL) {}
uint128(unsigned int value) : m_lo(value), m_hi(0ULL) {}
uint128(long value) : m_lo(value), m_hi(0ULL) {}
uint128(unsigned long value) : m_lo(value), m_hi(0ULL) {}
uint128(long long value) : m_lo(value), m_hi(0ULL) {}
uint128(unsigned long long value) : m_lo(value), m_hi(0ULL) {}
uint128(float value);
uint128(double value);
uint128(const int128 &value);
uint128(const float16 &value);
uint128(const float128 &value);
bool operator==(const uint128 &rhs) const { return m_hi == rhs.m_hi && m_lo == rhs.m_lo; }
bool operator==(uint64_t rhs) const { return m_hi == 0 && m_lo == rhs; }
bool operator==(int rhs) const { return rhs >= 0 && m_hi == 0u && m_lo == static_cast<unsigned int>(rhs); }
bool operator==(unsigned int rhs) const { return m_hi == 0u && m_lo == rhs; }
uint128 operator+() const { return *this; }
uint128 operator-() const
{
__pragma(warning(push)) __pragma(warning(disable : 4146))
if (this->m_lo != 0) {
return uint128(!this->m_hi, -this->m_lo);
}
else {
return uint128(-this->m_hi, 0);
}
__pragma(warning(pop))
}
bool operator!() const { return (m_hi != 0) && (m_lo != 0); }
uint128 operator~() const { return uint128(~m_hi, ~m_lo); }
bool operator!=(const uint128 &rhs) const { return m_hi != rhs.m_hi || m_lo != rhs.m_lo; }
bool operator!=(uint64_t rhs) const { return m_hi != 0 || m_lo != rhs; }
bool operator!=(int rhs) const { return rhs < 0 || m_hi != 0u || m_lo != static_cast<unsigned int>(rhs); }
bool operator!=(unsigned int rhs) const { return m_hi != 0u || m_lo != rhs; }
bool operator<(float rhs) const { return double(*this) < rhs; }
bool operator<(double rhs) const { return double(*this) < rhs; }
bool operator<(const uint128 &rhs) const { return m_hi < rhs.m_hi || (m_hi == rhs.m_hi && m_lo < rhs.m_lo); }
bool operator<=(const uint128 &rhs) const { return m_hi < rhs.m_hi || (m_hi == rhs.m_hi && m_lo <= rhs.m_lo); }
bool operator>(const uint128 &rhs) const { return rhs.operator<(*this); }
bool operator>=(const uint128 &rhs) const { return rhs.operator<=(*this); }
uint128 operator+(const uint128 &rhs) const
{
uint64_t lo = m_lo + rhs.m_lo;
return uint128(m_hi + rhs.m_hi + (lo < m_lo), lo);
}
uint128 operator+(uint64_t rhs) const
{
uint64_t lo = m_lo + rhs;
return uint128(m_hi + (lo < m_lo), lo);
}
uint128 operator+(uint32_t rhs) const
{
uint64_t lo = m_lo + static_cast<uint64_t>(rhs);
return uint128(m_hi + (lo < m_lo), lo);
}
uint128 operator-(const uint128 &rhs) const
{
uint64_t lo = m_lo + ~rhs.m_lo + 1;
return uint128(m_hi + ~rhs.m_hi + (lo < m_lo), lo);
}
uint128 operator-(uint64_t rhs) const
{
uint64_t lo = m_lo + ~rhs + 1;
return uint128(m_hi + 0xffffffffffffffffULL + (lo < m_lo), lo);
}
uint128 operator*(uint32_t rhs) const;
uint128 operator/(uint32_t rhs) const;
void divrem(uint32_t rhs, uint32_t &out_rem);
uint128 &operator/=(uint128 )
{
throw std::runtime_error("operator/= is not implemented for uint128");
}
explicit operator bool() const { return m_lo || m_hi; }
operator float() const { return m_lo + m_hi * 18446744073709551616.f; }
operator double() const { return m_lo + m_hi * 18446744073709551616.0; }
operator char() const { return static_cast<char>(m_lo); }
operator signed char() const { return static_cast<signed char>(m_lo); }
operator unsigned char() const { return static_cast<unsigned char>(m_lo); }
operator short() const { return static_cast<short>(m_lo); }
operator unsigned short() const { return static_cast<unsigned short>(m_lo); }
operator int() const { return static_cast<int>(m_lo); }
operator unsigned int() const { return static_cast<unsigned int>(m_lo); }
operator long() const { return static_cast<long>(m_lo); }
operator unsigned long() const { return static_cast<unsigned long>(m_lo); }
operator long long() const { return static_cast<long long>(m_lo); }
operator unsigned long long() const { return static_cast<unsigned long long>(m_lo); }
};
template <>
struct is_integral<uint128> : std::true_type {
};
inline uint128 operator/(uint128 , uint128 )
{
throw std::runtime_error("operator/ is not implemented for int128");
}
}
namespace std {
template <>
struct common_type<dynd::uint128, bool> {
typedef dynd::uint128 type;
};
template <>
struct common_type<dynd::uint128, dynd::bool1> {
typedef dynd::uint128 type;
};
template <>
struct common_type<dynd::uint128, char> {
typedef dynd::uint128 type;
};
template <>
struct common_type<dynd::uint128, signed char> {
typedef dynd::uint128 type;
};
template <>
struct common_type<dynd::uint128, unsigned char> {
typedef dynd::uint128 type;
};
template <>
struct common_type<dynd::uint128, short> {
typedef dynd::uint128 type;
};
template <>
struct common_type<dynd::uint128, unsigned short> {
typedef dynd::uint128 type;
};
template <>
struct common_type<dynd::uint128, int> {
typedef dynd::uint128 type;
};
template <>
struct common_type<dynd::uint128, unsigned int> {
typedef dynd::uint128 type;
};
template <>
struct common_type<dynd::uint128, long> {
typedef dynd::uint128 type;
};
template <>
struct common_type<dynd::uint128, unsigned long> {
typedef dynd::uint128 type;
};
template <>
struct common_type<dynd::uint128, long long> {
typedef dynd::uint128 type;
};
template <>
struct common_type<dynd::uint128, unsigned long long> {
typedef dynd::uint128 type;
};
template <>
struct common_type<dynd::uint128, dynd::int128> {
typedef dynd::uint128 type;
};
template <>
struct common_type<dynd::uint128, dynd::uint128> {
typedef dynd::uint128 type;
};
template <>
struct common_type<dynd::uint128, float> {
typedef float type;
};
template <>
struct common_type<dynd::uint128, double> {
typedef double type;
};
template <typename T>
struct common_type<T, dynd::uint128> : common_type<dynd::uint128, T> {
};
}
namespace dynd {
inline bool operator==(unsigned int lhs, const uint128 &rhs) { return rhs.m_hi == 0u && lhs == rhs.m_lo; }
inline bool operator!=(unsigned int lhs, const uint128 &rhs) { return rhs.m_hi != 0u || lhs != rhs.m_lo; }
inline bool operator<(float lhs, const uint128 &rhs) { return lhs < double(rhs); }
inline bool operator<(double lhs, const uint128 &rhs) { return lhs < double(rhs); }
inline bool operator<(signed char lhs, const uint128 &rhs) { return lhs < 0 || uint128(lhs) < rhs; }
inline bool operator<(unsigned char lhs, const uint128 &rhs) { return uint128(lhs) < rhs; }
inline bool operator<(short lhs, const uint128 &rhs) { return lhs < 0 || uint128(lhs) < rhs; }
inline bool operator<(unsigned short lhs, const uint128 &rhs) { return uint128(lhs) < rhs; }
inline bool operator<(int lhs, const uint128 &rhs) { return lhs < 0 || uint128(lhs) < rhs; }
inline bool operator<(unsigned int lhs, const uint128 &rhs) { return uint128(lhs) < rhs; }
inline bool operator<(long lhs, const uint128 &rhs) { return lhs < 0 || uint128(lhs) < rhs; }
inline bool operator<(unsigned long lhs, const uint128 &rhs) { return uint128(lhs) < rhs; }
inline bool operator<(long long lhs, const uint128 &rhs) { return lhs < 0 || uint128(lhs) < rhs; }
inline bool operator<(unsigned long long lhs, const uint128 &rhs) { return uint128(lhs) < rhs; }
template <typename T, typename dynd::detail::enable_for<T, unsigned char, unsigned short, unsigned int, unsigned long,
unsigned long long>::type = 0>
inline void operator+=(uint128 , T )
{
throw std::runtime_error("operator += is not implemented for uint128");
}
__declspec(dllimport) std::ostream &operator<<(std::ostream &out, const uint128 &val);
}
namespace std {
template <>
class numeric_limits<dynd::uint128> {
public:
static const bool is_specialized = true;
static dynd::uint128(min)() throw() { return dynd::uint128(0ULL, 0ULL); }
static dynd::uint128(max)() throw() { return dynd::uint128(0xffffffffffffffffULL, 0xffffffffffffffffULL); }
static const int digits = 0;
static const int digits10 = 0;
static const bool is_signed = true;
static const bool is_integer = true;
static const bool is_exact = true;
static const int radix = 2;
static dynd::uint128 epsilon() throw() { return dynd::uint128(0ULL, 1ULL); }
static dynd::uint128 round_error() throw() { return dynd::uint128(0ULL, 1ULL); }
static const int min_exponent = 0;
static const int min_exponent10 = 0;
static const int max_exponent = 0;
static const int max_exponent10 = 0;
static const bool has_infinity = false;
static const bool has_quiet_NaN = false;
static const bool has_signaling_NaN = false;
static const float_denorm_style has_denorm = denorm_absent;
static const bool has_denorm_loss = false;
static dynd::uint128 infinity() throw();
static dynd::uint128 quiet_NaN() throw();
static dynd::uint128 signaling_NaN() throw();
static dynd::uint128 denorm_min() throw();
static const bool is_iec559 = false;
static const bool is_bounded = false;
static const bool is_modulo = false;
static const bool traps = false;
static const bool tinyness_before = false;
static const float_round_style round_style = round_toward_zero;
};
}
namespace dynd {
__declspec(dllimport) uint16_t float_to_halfbits(float value);
__declspec(dllimport) uint16_t double_to_halfbits(double value);
__declspec(dllimport) float halfbits_to_float(uint16_t value);
__declspec(dllimport) double halfbits_to_double(uint16_t value);
class __declspec(dllimport) float16 {
uint16_t m_bits;
public:
class raw_bits_tag {
};
explicit float16(uint16_t bits, raw_bits_tag) : m_bits(bits) {}
float16() {}
explicit float16(bool1 rhs) : m_bits(rhs ? (0x3c00u) : (0x0000u)) {}
explicit float16(bool rhs) : m_bits(rhs ? (0x3c00u) : (0x0000u)) {}
explicit float16(int8 value) : float16(static_cast<float32>(value)) {}
explicit float16(int16 value) : float16(static_cast<float32>(value)) {}
explicit float16(int32 value) : float16(static_cast<float32>(value)) {}
explicit float16(int64 value) : float16(static_cast<float32>(value)) {}
explicit float16(int128 value);
explicit float16(uint16 value) : float16(static_cast<float32>(value)) {}
explicit float16(uint32 value) : float16(static_cast<float32>(value)) {}
explicit float16(uint64 value) : float16(static_cast<float32>(value)) {}
explicit float16(uint128 value);
explicit float16(float f) : m_bits(float_to_halfbits(f)) {}
explicit float16(double d) : m_bits(double_to_halfbits(d)) {}
explicit float16(const float128 &value);
float16(const float16 &rhs) : m_bits(rhs.m_bits) {}
explicit operator int8() const { return static_cast<int8>(halfbits_to_float(m_bits)); }
explicit operator int16() const
{
return static_cast<int16>(halfbits_to_float(m_bits));
}
explicit operator int32() const { return static_cast<int32>(halfbits_to_float(m_bits)); }
explicit operator int64() const { return static_cast<int64>(halfbits_to_float(m_bits)); }
explicit operator int128() const;
explicit operator uint8() const { return static_cast<uint8>(halfbits_to_float(m_bits)); }
explicit operator uint16() const { return static_cast<uint16>(halfbits_to_float(m_bits)); }
explicit operator uint32() const { return static_cast<uint32>(halfbits_to_float(m_bits)); }
explicit operator uint64() const { return static_cast<uint64>(halfbits_to_float(m_bits)); }
explicit operator uint128() const;
operator float32() const
{
return halfbits_to_float(m_bits);
}
explicit operator float64() const { return halfbits_to_double(m_bits); }
explicit operator float128() const;
uint16_t bits() const { return m_bits; }
bool iszero() const { return (m_bits & 0x7fff) == 0; }
bool signbit_() const { return (m_bits & 0x8000u) != 0; }
bool isnan_() const { return ((m_bits & 0x7c00u) == 0x7c00u) && ((m_bits & 0x03ffu) != 0x0000u); }
bool isinf_() const { return ((m_bits & 0x7fffu) == 0x7c00u); }
bool isfinite_() const { return ((m_bits & 0x7c00u) != 0x7c00u); }
bool less_nonan(const float16 &rhs) const
{
if (signbit_()) {
if (rhs.signbit_()) {
return m_bits > rhs.m_bits;
}
else {
return (m_bits != 0x8000u) || (rhs.m_bits != 0x0000u);
}
}
else {
if (rhs.signbit_()) {
return false;
}
else {
return m_bits < rhs.m_bits;
}
}
}
bool less_equal_nonan(const float16 &rhs) const
{
if (signbit_()) {
if (rhs.signbit_()) {
return m_bits >= rhs.m_bits;
}
else {
return true;
}
}
else {
if (rhs.signbit_()) {
return (m_bits == 0x0000u) && (rhs.m_bits == 0x8000u);
}
else {
return m_bits <= rhs.m_bits;
}
}
}
friend float16 float16_from_bits(uint16_t bits);
float16 operator+() const { return *this; }
float16 operator-() const { return float16(-static_cast<float>(*this)); }
bool operator!() const { return (0x7fffu | m_bits) == 0; }
explicit operator bool() const { return (0x7ffu | m_bits) != 0; }
};
inline float16 operator+(const float16 &, const float16 &)
{
throw std::runtime_error("+ is not implemented for float16");
}
inline bool operator<(const float16 &lhs, const float16 &rhs)
{
return static_cast<double>(lhs) < static_cast<double>(rhs);
}
template <typename T>
typename std::enable_if<is_arithmetic<T>::value && !std::is_same<T, float128>::value, bool>::type
operator<(const float16 &lhs, const T &rhs)
{
return static_cast<double>(lhs) < static_cast<double>(rhs);
}
template <typename T>
typename std::enable_if<is_arithmetic<T>::value && !std::is_same<T, float128>::value, bool>::type
operator<(const T &lhs, const float16 &rhs)
{
return static_cast<double>(lhs) < static_cast<double>(rhs);
}
inline bool operator<=(const float16 &lhs, const float16 &rhs)
{
return static_cast<double>(lhs) <= static_cast<double>(rhs);
}
template <typename T>
typename std::enable_if<is_arithmetic<T>::value, bool>::type operator<=(const float16 &lhs, const T &rhs)
{
return static_cast<double>(lhs) <= static_cast<double>(rhs);
}
template <typename T>
typename std::enable_if<is_arithmetic<T>::value, bool>::type operator<=(const T &lhs, const float16 &rhs)
{
return static_cast<double>(lhs) <= static_cast<double>(rhs);
}
inline bool operator==(const float16 &lhs, const float16 &rhs)
{
return static_cast<double>(lhs) == static_cast<double>(rhs);
}
template <typename T>
typename std::enable_if<is_arithmetic<T>::value && !std::is_same<T, float128>::value, bool>::type
operator==(const float16 &lhs, const T &rhs)
{
return static_cast<double>(lhs) == static_cast<double>(rhs);
}
template <typename T>
typename std::enable_if<is_arithmetic<T>::value && !std::is_same<T, float128>::value, bool>::type
operator==(const T &lhs, const float16 &rhs)
{
return static_cast<double>(lhs) == static_cast<double>(rhs);
}
inline bool operator!=(const float16 &lhs, const float16 &rhs)
{
return static_cast<double>(lhs) != static_cast<double>(rhs);
}
template <typename T>
typename std::enable_if<is_arithmetic<T>::value && !std::is_same<T, float128>::value, bool>::type
operator!=(const float16 &lhs, const T &rhs)
{
return static_cast<double>(lhs) != static_cast<double>(rhs);
}
template <typename T>
typename std::enable_if<is_arithmetic<T>::value && !std::is_same<T, float128>::value, bool>::type
operator!=(const T &lhs, const float16 &rhs)
{
return static_cast<double>(lhs) != static_cast<double>(rhs);
}
inline bool operator>=(const float16 &lhs, const float16 &rhs)
{
return static_cast<double>(lhs) >= static_cast<double>(rhs);
}
template <typename T>
typename std::enable_if<is_arithmetic<T>::value, bool>::type operator>=(const float16 &lhs, const T &rhs)
{
return static_cast<double>(lhs) >= static_cast<double>(rhs);
}
template <typename T>
typename std::enable_if<is_arithmetic<T>::value, bool>::type operator>=(const T &lhs, const float16 &rhs)
{
return static_cast<double>(lhs) >= static_cast<double>(rhs);
}
inline bool operator>(const float16 &lhs, const float16 &rhs)
{
return static_cast<double>(lhs) > static_cast<double>(rhs);
}
template <typename T>
typename std::enable_if<is_arithmetic<T>::value && !std::is_same<T, float128>::value, bool>::type
operator>(const float16 &lhs, const T &rhs)
{
return static_cast<double>(lhs) > static_cast<double>(rhs);
}
template <typename T>
typename std::enable_if<is_arithmetic<T>::value && !std::is_same<T, float128>::value, bool>::type
operator>(const T &lhs, const float16 &rhs)
{
return static_cast<double>(lhs) > static_cast<double>(rhs);
}
inline float16 float16_from_bits(uint16_t bits) { return float16(bits, float16::raw_bits_tag()); }
inline float16 floor(float16 value) { return float16(std::floor(static_cast<float>(value))); }
inline std::ostream &operator<<(std::ostream &o, const float16 &)
{
return (o << "<float16 printing unimplemented>");
}
}
namespace dynd {
class __declspec(dllimport) float128 {
public:
uint64_t m_lo, m_hi;
float128() {}
float128(uint64_t hi, uint64_t lo) : m_lo(lo), m_hi(hi) {}
float128(bool1) {}
float128(signed char value);
float128(unsigned char value);
float128(short value);
float128(unsigned short value);
float128(int value);
float128(unsigned int value);
float128(long value) { *this = float128((long long)value); }
float128(unsigned long value) { *this = float128((unsigned long long)value); }
float128(long long value);
float128(unsigned long long value);
float128(double value);
float128(const int128 &value);
float128(const uint128 &value);
float128(const float16 &value);
float128 &operator/=(float128 )
{
throw std::runtime_error("operator/= is not implemented for float128");
}
operator signed char() const
{
throw std::runtime_error("float128 conversions are not completed");
}
operator unsigned char() const
{
throw std::runtime_error("float128 conversions are not completed");
}
operator short() const
{
throw std::runtime_error("float128 conversions are not completed");
}
operator unsigned short() const
{
throw std::runtime_error("float128 conversions are not completed");
}
operator int() const
{
throw std::runtime_error("float128 conversions are not completed");
}
operator unsigned int() const
{
throw std::runtime_error("float128 conversions are not completed");
}
operator long() const
{
throw std::runtime_error("float128 conversions are not completed");
}
operator unsigned long() const
{
throw std::runtime_error("float128 conversions are not completed");
}
operator long long() const
{
throw std::runtime_error("float128 conversions are not completed");
}
operator unsigned long long() const
{
throw std::runtime_error("float128 conversions are not completed");
}
operator float() const
{
throw std::runtime_error("float128 conversions are not completed");
}
operator double() const
{
throw std::runtime_error("float128 conversions are not completed");
}
explicit float128(const bool &rhs) : m_lo(0ULL), m_hi(rhs ? 0x3fff000000000000ULL : 0ULL) {}
bool iszero() const { return (m_hi & 0x7fffffffffffffffULL) == 0 && m_lo == 0; }
bool signbit_() const { return (m_hi & 0x8000000000000000ULL) != 0; }
bool isnan_() const
{
return (m_hi & 0x7fff000000000000ULL) == 0x7fff000000000000ULL &&
((m_hi & 0x0000ffffffffffffULL) != 0ULL || m_lo != 0ULL);
}
bool isinf_() const { return (m_hi & 0x7fffffffffffffffULL) == 0x7fff000000000000ULL && (m_lo == 0ULL); }
bool isfinite_() const { return (m_hi & 0x7fff000000000000ULL) != 0x7fff000000000000ULL; }
bool less_nonan(const float128 &rhs) const
{
if (signbit_()) {
if (rhs.signbit_()) {
return m_hi > rhs.m_hi || (m_hi == rhs.m_hi && m_lo > rhs.m_lo);
}
else {
return (m_hi != 0x8000000000000000ULL) || (m_lo != 0LL) || (rhs.m_hi != 0LL) || rhs.m_lo != 0LL;
}
}
else {
if (rhs.signbit_()) {
return false;
}
else {
return m_hi < rhs.m_hi || (m_hi == rhs.m_hi && m_lo < rhs.m_lo);
}
}
}
bool less_equal_nonan(const float128 &rhs) const
{
if (signbit_()) {
if (rhs.signbit_()) {
return m_hi > rhs.m_hi || (m_hi == rhs.m_hi && m_lo >= rhs.m_lo);
}
else {
return true;
}
}
else {
if (rhs.signbit_()) {
return (m_hi == 0x8000000000000000ULL) && (m_lo == 0LL) && (rhs.m_hi == 0LL) && rhs.m_lo == 0LL;
}
else {
return m_hi < rhs.m_hi || (m_hi == rhs.m_hi && m_lo <= rhs.m_lo);
}
}
}
float128 operator+() const { return *this; }
float128 operator-() const { return float128(-static_cast<double>(*this)); }
bool operator!() const { return ((0x7fffffffffffffffULL | m_hi) == 0) && (m_lo == 0); }
explicit operator bool() const { return (m_lo != 0) || ((0x7fffffffffffffffULL | m_hi) != 0); }
};
template <>
struct is_floating_point<float128> : std::true_type {
};
inline float128 operator+(const float128 &, const float128 &)
{
throw std::runtime_error("addition for float128 is not implemented");
}
inline float128 operator*(float128 , float128 )
{
throw std::runtime_error("operator* for float128 is not implemented");
}
inline float128 operator/(float128 , float128 )
{
throw std::runtime_error("operator/ for float128 is not implemented");
}
inline bool operator<(const float128 &lhs, const float128 &rhs)
{
return static_cast<double>(lhs) < static_cast<double>(rhs);
}
template <typename T>
typename std::enable_if<is_arithmetic<T>::value, bool>::type operator<(const float128 &lhs, const T &rhs)
{
return static_cast<double>(lhs) < static_cast<double>(rhs);
}
template <typename T>
typename std::enable_if<is_arithmetic<T>::value, bool>::type operator<(const T &lhs, const float128 &rhs)
{
return static_cast<double>(lhs) < static_cast<double>(rhs);
}
inline bool operator<=(const float128 &lhs, const float128 &rhs)
{
return static_cast<double>(lhs) <= static_cast<double>(rhs);
}
template <typename T>
typename std::enable_if<is_arithmetic<T>::value, bool>::type operator<=(const float128 &lhs, const T &rhs)
{
return static_cast<double>(lhs) <= static_cast<double>(rhs);
}
template <typename T>
typename std::enable_if<is_arithmetic<T>::value, bool>::type operator<=(const T &lhs, const float128 &rhs)
{
return static_cast<double>(lhs) <= static_cast<double>(rhs);
}
inline bool operator==(const float128 &lhs, const float128 &rhs)
{
return static_cast<double>(lhs) == static_cast<double>(rhs);
}
template <typename T>
typename std::enable_if<is_arithmetic<T>::value, bool>::type operator==(const float128 &lhs, const T &rhs)
{
return static_cast<double>(lhs) == static_cast<double>(rhs);
}
template <typename T>
typename std::enable_if<is_arithmetic<T>::value, bool>::type operator==(const T &lhs, const float128 &rhs)
{
return static_cast<double>(lhs) == static_cast<double>(rhs);
}
inline bool operator!=(const float128 &lhs, const float128 &rhs)
{
return static_cast<double>(lhs) != static_cast<double>(rhs);
}
template <typename T>
typename std::enable_if<is_arithmetic<T>::value, bool>::type operator!=(const float128 &lhs, const T &rhs)
{
return static_cast<double>(lhs) != static_cast<double>(rhs);
}
template <typename T>
typename std::enable_if<is_arithmetic<T>::value, bool>::type operator!=(const T &lhs, const float128 &rhs)
{
return static_cast<double>(lhs) != static_cast<double>(rhs);
}
inline bool operator>=(const float128 &lhs, const float128 &rhs)
{
return static_cast<double>(lhs) >= static_cast<double>(rhs);
}
template <typename T>
typename std::enable_if<is_arithmetic<T>::value, bool>::type operator>=(const float128 &lhs, const T &rhs)
{
return static_cast<double>(lhs) >= static_cast<double>(rhs);
}
template <typename T>
typename std::enable_if<is_arithmetic<T>::value, bool>::type operator>=(const T &lhs, const float128 &rhs)
{
return static_cast<double>(lhs) >= static_cast<double>(rhs);
}
inline bool operator>(const float128 &lhs, const float128 &rhs)
{
return static_cast<double>(lhs) > static_cast<double>(rhs);
}
template <typename T>
typename std::enable_if<is_arithmetic<T>::value, bool>::type operator>(const float128 &lhs, const T &rhs)
{
return static_cast<double>(lhs) > static_cast<double>(rhs);
}
template <typename T>
typename std::enable_if<is_arithmetic<T>::value, bool>::type operator>(const T &lhs, const float128 &rhs)
{
return static_cast<double>(lhs) > static_cast<double>(rhs);
}
inline std::ostream &operator<<(std::ostream &o, const float128 &)
{
return (o << "<float128 printing unimplemented>");
}
inline float128 floor(float128 value) { return static_cast<double>(value); }
}
namespace std {
template <>
struct common_type<dynd::float128, bool> {
typedef dynd::float128 type;
};
template <>
struct common_type<dynd::float128, dynd::bool1> {
typedef dynd::float128 type;
};
template <>
struct common_type<dynd::float128, char> {
typedef dynd::float128 type;
};
template <>
struct common_type<dynd::float128, signed char> {
typedef dynd::float128 type;
};
template <>
struct common_type<dynd::float128, unsigned char> {
typedef dynd::float128 type;
};
template <>
struct common_type<dynd::float128, short> {
typedef dynd::float128 type;
};
template <>
struct common_type<dynd::float128, unsigned short> {
typedef dynd::float128 type;
};
template <>
struct common_type<dynd::float128, int> {
typedef dynd::float128 type;
};
template <>
struct common_type<dynd::float128, unsigned int> {
typedef dynd::float128 type;
};
template <>
struct common_type<dynd::float128, long> {
typedef dynd::float128 type;
};
template <>
struct common_type<dynd::float128, unsigned long> {
typedef dynd::float128 type;
};
template <>
struct common_type<dynd::float128, long long> {
typedef dynd::float128 type;
};
template <>
struct common_type<dynd::float128, unsigned long long> {
typedef dynd::float128 type;
};
template <>
struct common_type<dynd::float128, dynd::int128> {
typedef dynd::float128 type;
};
template <>
struct common_type<dynd::float128, dynd::uint128> {
typedef dynd::float128 type;
};
template <>
struct common_type<dynd::float128, float> {
typedef dynd::float128 type;
};
template <>
struct common_type<dynd::float128, double> {
typedef dynd::float128 type;
};
template <>
struct common_type<dynd::float128, dynd::float128> {
typedef dynd::float128 type;
};
template <typename T>
struct common_type<T, dynd::float128> : common_type<dynd::float128, T> {
};
}
namespace dynd {
template <typename T>
class complex {
public:
T m_real, m_imag;
typedef T value_type;
complex(const T &re = 0.0, const T &im = 0.0) : m_real(re), m_imag(im) {}
template <typename U>
complex(const complex<U> &rhs)
: m_real(static_cast<T>(rhs.m_real)), m_imag(static_cast<T>(rhs.m_imag))
{
}
complex(const std::complex<T> &rhs) : m_real(rhs.real()), m_imag(rhs.imag()) {}
T real() const { return m_real; }
T imag() const { return m_imag; }
complex<T> &operator=(const complex<T> &rhs)
{
m_real = rhs.m_real;
m_imag = rhs.m_imag;
return *this;
}
complex<T> &operator+=(const complex<T> &rhs)
{
m_real += rhs.m_real;
m_imag += rhs.m_imag;
return *this;
}
complex<T> &operator+=(const T &rhs)
{
m_real += rhs;
return *this;
}
complex<T> &operator-=(const complex<T> &rhs)
{
m_real -= rhs.m_real;
m_imag -= rhs.m_imag;
return *this;
}
complex<T> &operator-=(const T &rhs)
{
m_real -= rhs;
return *this;
}
complex<T> operator*=(const complex<T> &rhs)
{
new (this) complex<T>(m_real * rhs.m_real - m_imag * rhs.m_imag, m_real * rhs.m_imag + rhs.m_real * m_imag);
return *this;
}
complex<T> operator*=(const T &rhs)
{
m_real *= rhs;
m_imag *= rhs;
return *this;
}
complex<T> &operator/=(const complex<T> &rhs)
{
T denom = rhs.m_real * rhs.m_real + rhs.m_imag * rhs.m_imag;
new (this) complex<T>((m_real * rhs.m_real + m_imag * rhs.m_imag) / denom,
(rhs.m_real * m_imag - m_real * rhs.m_imag) / denom);
return *this;
}
complex<T> &operator/=(const T &rhs)
{
m_real /= rhs;
m_imag /= rhs;
return *this;
}
explicit operator bool() const { return m_real || m_imag; }
explicit operator T() const { return m_real; }
template <typename U,
typename = typename std::enable_if<is_mixed_arithmetic<T, U>::value && !std::is_same<U, bool>::value>::type>
explicit operator U() const
{
return static_cast<U>(m_real);
}
operator std::complex<T>() const { return std::complex<T>(m_real, m_imag); }
};
template <typename T>
struct is_complex<complex<T>> : std::true_type {
};
}
namespace std {
template <typename T>
struct common_type<dynd::complex<T>, bool> {
typedef dynd::complex<T> type;
};
template <typename T>
struct common_type<dynd::complex<T>, dynd::bool1> {
typedef dynd::complex<T> type;
};
template <typename T>
struct common_type<dynd::complex<T>, char> {
typedef char type;
};
template <typename T>
struct common_type<dynd::complex<T>, signed char> {
typedef dynd::complex<T> type;
};
template <typename T>
struct common_type<dynd::complex<T>, unsigned char> {
typedef dynd::complex<T> type;
};
template <typename T>
struct common_type<dynd::complex<T>, short> {
typedef dynd::complex<T> type;
};
template <typename T>
struct common_type<dynd::complex<T>, unsigned short> {
typedef dynd::complex<T> type;
};
template <typename T>
struct common_type<dynd::complex<T>, int> {
typedef dynd::complex<T> type;
};
template <typename T>
struct common_type<dynd::complex<T>, unsigned int> {
typedef dynd::int128 type;
};
template <typename T>
struct common_type<dynd::complex<T>, long> {
typedef dynd::complex<T> type;
};
template <typename T>
struct common_type<dynd::complex<T>, unsigned long> {
typedef dynd::complex<T> type;
};
template <typename T>
struct common_type<dynd::complex<T>, long long> {
typedef dynd::complex<T> type;
};
template <typename T>
struct common_type<dynd::complex<T>, unsigned long long> {
typedef dynd::complex<T> type;
};
template <typename T>
struct common_type<dynd::complex<T>, dynd::int128> {
typedef dynd::complex<T> type;
};
template <typename T>
struct common_type<dynd::complex<T>, dynd::uint128> {
typedef dynd::complex<T> type;
};
template <typename T>
struct common_type<dynd::complex<T>, float> {
typedef dynd::complex<typename common_type<T, float>::type> type;
};
template <typename T>
struct common_type<dynd::complex<T>, double> {
typedef dynd::complex<typename common_type<T, double>::type> type;
};
template <typename T>
struct common_type<dynd::complex<T>, dynd::float128> {
typedef dynd::complex<typename common_type<T, dynd::float128>::type> type;
};
template <typename T, typename U>
struct common_type<dynd::complex<T>, dynd::complex<U>> {
typedef dynd::complex<typename common_type<T, U>::type> type;
};
template <typename T, typename U>
struct common_type<T, dynd::complex<U>> : common_type<dynd::complex<U>, T> {
};
}
namespace dynd {
typedef complex<float32> complex64;
typedef complex<float64> complex128;
template <typename T, typename U>
bool operator==(complex<T> lhs, complex<U> rhs)
{
return (lhs.m_real == rhs.m_real) && (lhs.m_imag == rhs.m_imag);
}
template <typename T, typename U>
typename std::enable_if<std::is_integral<U>::value || std::is_floating_point<U>::value, bool>::type
operator==(complex<T> lhs, U rhs)
{
return (lhs.m_real == rhs) && !lhs.m_imag;
}
template <typename T, typename U>
typename std::enable_if<std::is_integral<T>::value || std::is_floating_point<T>::value, bool>::type
operator==(T lhs, complex<U> rhs)
{
return rhs == lhs;
}
template <typename T>
bool operator==(complex<T> lhs, std::complex<T> rhs)
{
return (lhs.m_real == rhs.real()) && (lhs.m_imag == rhs.imag());
}
template <typename T>
bool operator==(std::complex<T> lhs, complex<T> rhs)
{
return rhs == lhs;
}
template <typename T, typename U>
bool operator!=(complex<T> lhs, complex<U> rhs)
{
return !(lhs == rhs);
}
template <typename T, typename U>
bool operator!=(complex<T> lhs, U rhs)
{
return lhs.m_real == rhs && !lhs.m_imag;
}
template <typename T>
complex<T> operator+(const complex<T> &rhs)
{
return complex<T>(+rhs.m_real, +rhs.m_imag);
}
template <typename T>
complex<T> operator-(const complex<T> &rhs)
{
return complex<T>(-rhs.m_real, -rhs.m_imag);
}
template <typename T>
complex<T> operator!(const complex<T> &rhs)
{
return (!rhs.m_real && !rhs.m_imag);
}
template <typename T>
complex<T> operator+(complex<T> lhs, complex<T> rhs)
{
return lhs += rhs;
}
template <typename T, typename U>
complex<typename std::common_type<T, U>::type> operator+(complex<T> lhs, complex<U> rhs)
{
return static_cast<complex<typename std::common_type<T, U>::type>>(lhs) +
static_cast<complex<typename std::common_type<T, U>::type>>(rhs);
}
template <typename T>
complex<T> operator+(complex<T> lhs, T rhs)
{
return lhs += rhs;
}
template <typename T, typename U>
typename std::enable_if<std::is_integral<U>::value || std::is_floating_point<U>::value,
complex<typename std::common_type<T, U>::type>>::type
operator+(complex<T> lhs, U rhs)
{
return static_cast<complex<typename std::common_type<T, U>::type>>(lhs) +
static_cast<typename std::common_type<T, U>::type>(rhs);
}
template <typename T>
complex<T> operator+(T lhs, complex<T> rhs)
{
return complex<T>(lhs + rhs.m_real, rhs.m_imag);
}
template <typename T, typename U>
typename std::enable_if<std::is_integral<T>::value || std::is_floating_point<T>::value,
complex<typename std::common_type<T, U>::type>>::type
operator+(T lhs, complex<U> rhs)
{
return static_cast<typename std::common_type<T, U>::type>(lhs) +
static_cast<complex<typename std::common_type<T, U>::type>>(rhs);
}
template <typename T>
complex<T> operator-(complex<T> lhs, complex<T> rhs)
{
return lhs -= rhs;
}
template <typename T, typename U>
complex<typename std::common_type<T, U>::type> operator-(complex<T> lhs, complex<U> rhs)
{
return static_cast<complex<typename std::common_type<T, U>::type>>(lhs) -
static_cast<complex<typename std::common_type<T, U>::type>>(rhs);
}
template <typename T>
complex<T> operator-(complex<T> lhs, T rhs)
{
return lhs -= rhs;
}
template <typename T, typename U>
typename std::enable_if<std::is_integral<U>::value || std::is_floating_point<U>::value,
complex<typename std::common_type<T, U>::type>>::type
operator-(complex<T> lhs, U rhs)
{
return static_cast<complex<typename std::common_type<T, U>::type>>(lhs) -
static_cast<typename std::common_type<T, U>::type>(rhs);
}
template <typename T>
complex<T> operator-(T lhs, complex<T> rhs)
{
return complex<T>(lhs - rhs.m_real, -rhs.m_imag);
}
template <typename T, typename U>
typename std::enable_if<std::is_integral<T>::value || std::is_floating_point<T>::value,
complex<typename std::common_type<T, U>::type>>::type
operator-(T lhs, complex<U> rhs)
{
return static_cast<typename std::common_type<T, U>::type>(lhs) -
static_cast<complex<typename std::common_type<T, U>::type>>(rhs);
}
template <typename T>
complex<T> operator*(complex<T> lhs, complex<T> rhs)
{
return lhs *= rhs;
}
template <typename T, typename U>
complex<typename std::common_type<T, U>::type> operator*(complex<T> lhs, complex<U> rhs)
{
return static_cast<complex<typename std::common_type<T, U>::type>>(lhs) *
static_cast<complex<typename std::common_type<T, U>::type>>(rhs);
}
template <typename T>
complex<T> operator*(complex<T> lhs, T rhs)
{
return lhs *= rhs;
}
template <typename T, typename U>
typename std::enable_if<std::is_integral<U>::value || std::is_floating_point<U>::value,
complex<typename std::common_type<T, U>::type>>::type
operator*(complex<T> lhs, U rhs)
{
return static_cast<complex<typename std::common_type<T, U>::type>>(lhs) *
static_cast<typename std::common_type<T, U>::type>(rhs);
}
template <typename T>
complex<T> operator*(T lhs, complex<T> rhs)
{
return complex<T>(lhs * rhs.m_real, lhs * rhs.m_imag);
}
template <typename T, typename U>
typename std::enable_if<std::is_integral<T>::value || std::is_floating_point<T>::value,
complex<typename std::common_type<T, U>::type>>::type
operator*(T lhs, complex<U> rhs)
{
return static_cast<typename std::common_type<T, U>::type>(lhs) *
static_cast<complex<typename std::common_type<T, U>::type>>(rhs);
}
template <typename T>
complex<T> operator/(complex<T> lhs, complex<T> rhs)
{
return lhs /= rhs;
}
template <typename T, typename U>
complex<typename std::common_type<T, U>::type> operator/(complex<T> lhs, complex<U> rhs)
{
return static_cast<complex<typename std::common_type<T, U>::type>>(lhs) /
static_cast<complex<typename std::common_type<T, U>::type>>(rhs);
}
template <typename T>
complex<T> operator/(complex<T> lhs, T rhs)
{
return lhs /= rhs;
}
template <typename T>
complex<T> operator/(T lhs, complex<T> rhs)
{
T denom = rhs.m_real * rhs.m_real + rhs.m_imag * rhs.m_imag;
return complex<T>(lhs * rhs.m_real / denom, -lhs * rhs.m_imag / denom);
}
template <typename T>
std::ostream &operator<<(std::ostream &out, const complex<T> &val)
{
return (out << "(" << val.m_real << " + " << val.m_imag << "j)");
}
template <typename T>
complex<T> _i();
template <>
inline complex<float> _i<float>()
{
return complex<float>(0.0f, 1.0f);
}
template <>
inline complex<double> _i<double>()
{
return complex<double>(0.0, 1.0);
}
template <typename T>
complex<T> conj(const complex<T> &z)
{
return complex<T>(z.real(), -z.imag());
}
}
namespace dynd {
template <typename T, typename U>
struct operator_if_only_lcast_arithmetic
: std::enable_if<!std::is_same<T, U>::value && !(std::is_arithmetic<T>::value && std::is_arithmetic<U>::value) &&
is_lcast_arithmetic<T, U>::value && !is_rcast_arithmetic<T, U>::value,
U> {
};
template <typename T, typename U>
struct operator_if_only_rcast_arithmetic
: std::enable_if<!std::is_same<T, U>::value && !(std::is_arithmetic<T>::value && std::is_arithmetic<U>::value) &&
!is_lcast_arithmetic<T, U>::value && is_rcast_arithmetic<T, U>::value,
T> {
};
template <typename... T>
struct make_void {
typedef void type;
};
template <typename T, typename U>
struct operator_if_lrcast_arithmetic
: std::enable_if<!std::is_same<T, U>::value && !(std::is_arithmetic<T>::value && std::is_arithmetic<U>::value) &&
is_lcast_arithmetic<T, U>::value && is_rcast_arithmetic<T, U>::value,
typename conditional_make<is_arithmetic<T>::value && is_arithmetic<U>::value, std::common_type,
make_void, T, U>::type::type> {
};
template <typename T, typename U>
typename operator_if_only_rcast_arithmetic<T, U>::type operator+(T lhs, U rhs)
{
return lhs + static_cast<T>(rhs);
}
template <typename T, typename U>
typename operator_if_only_lcast_arithmetic<T, U>::type operator+(T lhs, U rhs)
{
return static_cast<U>(lhs) + rhs;
}
template <typename T, typename U>
typename operator_if_lrcast_arithmetic<T, U>::type operator+(T lhs, U rhs)
{
return static_cast<typename std::common_type<T, U>::type>(lhs) +
static_cast<typename std::common_type<T, U>::type>(rhs);
}
template <typename T, typename U>
typename operator_if_only_rcast_arithmetic<T, U>::type operator/(T lhs, U rhs)
{
return lhs / static_cast<T>(rhs);
}
template <typename T, typename U>
typename operator_if_only_lcast_arithmetic<T, U>::type operator/(T lhs, U rhs)
{
return static_cast<U>(lhs) / rhs;
}
template <typename T, typename U>
typename operator_if_lrcast_arithmetic<T, U>::type operator/(T lhs, U rhs)
{
return static_cast<typename std::common_type<T, U>::type>(lhs) /
static_cast<typename std::common_type<T, U>::type>(rhs);
}
template <typename T, typename U>
typename std::enable_if<is_mixed_arithmetic<T, U>::value, complex<typename std::common_type<T, U>::type>>::type
operator/(complex<T> lhs, U rhs)
{
return static_cast<complex<typename std::common_type<T, U>::type>>(lhs) /
static_cast<typename std::common_type<T, U>::type>(rhs);
}
template <typename T, typename U>
typename std::enable_if<is_mixed_arithmetic<T, U>::value, complex<typename std::common_type<T, U>::type>>::type
operator/(T lhs, complex<U> rhs)
{
return static_cast<typename std::common_type<T, U>::type>(lhs) /
static_cast<complex<typename std::common_type<T, U>::type>>(rhs);
}
template <typename T, typename U>
typename std::enable_if<std::is_floating_point<T>::value && is_integral<U>::value, T &>::type operator/=(T &lhs, U rhs)
{
return lhs /= static_cast<T>(rhs);
}
}
namespace dynd {
using std::cos;
using std::sin;
using std::tan;
using std::atan2;
using std::cosh;
using std::sinh;
using std::exp;
using std::log;
using std::pow;
using std::sqrt;
using std::cbrt;
using std::hypot;
using std::abs;
using std::isfinite;
using std::isinf;
using std::isnan;
namespace ndt {
class type;
}
namespace nd {
class array;
class callable;
}
}
namespace dynd {
inline bool any_diagnostics_enabled()
{
return ((0 != 0) || (0 != 0));
}
inline std::string which_diagnostics_enabled()
{
return "";
}
}
namespace dynd {
template <typename T, typename DerivedType>
class storagebuf {
protected:
char *m_data;
intptr_t m_capacity;
intptr_t m_size;
char m_static_data[16 * 8];
bool using_static_data() const { return m_data == &m_static_data[0]; }
public:
storagebuf() : m_data(m_static_data), m_capacity(sizeof(m_static_data)), m_size(0) {
set(m_static_data, 0, sizeof(m_static_data));
}
~storagebuf() {
if (!using_static_data() && m_data != 0) {
free(m_data);
}
}
size_t size() const { return m_size; }
size_t capacity() const { return m_capacity; }
void reserve(intptr_t requested_capacity) {
if (m_capacity < requested_capacity) {
intptr_t grown_capacity = m_capacity * 3 / 2;
if (requested_capacity < grown_capacity) {
requested_capacity = grown_capacity;
}
char *new_data = reinterpret_cast<char *>(realloc(m_data, m_capacity, requested_capacity));
if (new_data == 0) {
reinterpret_cast<DerivedType *>(this)->destroy();
m_data = 0;
throw std::bad_alloc();
}
set(reinterpret_cast<char *>(new_data) + m_capacity, 0, requested_capacity - m_capacity);
m_data = new_data;
m_capacity = requested_capacity;
}
}
void *alloc(size_t size) { return std::malloc(size); }
void *realloc(void *ptr, size_t old_size, size_t new_size) {
if (using_static_data()) {
void *new_data = alloc(new_size);
if (new_data != 0) {
copy(new_data, ptr, old_size);
}
return new_data;
} else {
return std::realloc(ptr, new_size);
}
}
void free(void *ptr) {
if (!using_static_data()) {
std::free(ptr);
}
}
void *copy(void *dst, const void *src, size_t size) { return std::memcpy(dst, src, size); }
void *set(void *dst, int value, size_t size) { return std::memset(dst, value, size); }
T *get() const { return reinterpret_cast<T *>(m_data); }
template <typename U>
U *get_at(size_t offset) {
return reinterpret_cast<U *>(m_data + offset);
}
static constexpr size_t aligned_size(size_t size) {
return (size + static_cast<size_t>(7)) & ~static_cast<size_t>(7);
}
template <typename KernelType, typename... ArgTypes>
void emplace_back(ArgTypes &&... args) {
static_assert(alignof(KernelType) <= 8, "kernel types require alignment to be at most 8 bytes");
size_t offset = m_size;
m_size += aligned_size(sizeof(KernelType));
reserve(m_size);
KernelType::init(this->get_at<KernelType>(offset), std::forward<ArgTypes>(args)...);
}
void emplace_back(size_t size) {
m_size += aligned_size(size);
reserve(m_size);
}
};
}
namespace dynd {
static constexpr size_t aligned_size(size_t size) { return (size + static_cast<size_t>(7)) & ~static_cast<size_t>(7); }
typedef uint32_t kernel_request_t;
namespace nd {
class kernel_builder;
struct call_node {
typedef void (*instantiate_type_t)(call_node *node, kernel_builder *ckb, kernel_request_t kernreq,
const char *dst_arrmeta, size_t nsrc, const char *const *src_arrmeta);
typedef void (*destroy_type_t)(call_node *node);
destroy_type_t destroy;
instantiate_type_t instantiate;
size_t aligned_size;
call_node(instantiate_type_t instantiate)
: instantiate(instantiate), aligned_size(dynd::aligned_size(sizeof(call_node))) {}
call_node(instantiate_type_t instantiate, destroy_type_t destroy, size_t data_size)
: destroy(destroy), instantiate(instantiate), aligned_size(dynd::aligned_size(data_size)) {}
template <typename... ArgTypes>
static void init(call_node *self, ArgTypes &&... args) {
new (self) call_node(std::forward<ArgTypes>(args)...);
}
};
}
}
namespace dynd {
namespace nd {
struct kernel_prefix;
class kernel_builder : public storagebuf<kernel_prefix, kernel_builder> {
call_node *m_call;
public:
kernel_builder(call_node *call = nullptr) : m_call(call) {}
__declspec(dllexport) void destroy();
~kernel_builder() { destroy(); }
template <typename KernelType, typename... ArgTypes>
void emplace_back(ArgTypes &&... args) {
storagebuf<kernel_prefix, kernel_builder>::emplace_back<KernelType>(std::forward<ArgTypes>(args)...);
m_call = reinterpret_cast<call_node *>(reinterpret_cast<char *>(m_call) + m_call->aligned_size);
}
void emplace_back(size_t size) { storagebuf<kernel_prefix, kernel_builder>::emplace_back(size); }
void operator()(kernel_request_t kr, const char *res_metadata, size_t narg, const char *const *arg_metadata) {
m_call->instantiate(m_call, this, kr, res_metadata, narg, arg_metadata);
}
};
}
}
namespace dynd {
typedef void (*kernel_call_t)(nd::kernel_prefix *self, const nd::array *dst, const nd::array *src);
typedef void (*kernel_single_t)(nd::kernel_prefix *self, char *dst, char *const *src);
typedef void (*kernel_strided_t)(nd::kernel_prefix *self, char *dst, intptr_t dst_stride, char *const *src,
const intptr_t *src_stride, size_t count);
enum {
kernel_request_host = 0x00000000,
kernel_request_call = 0x00000000,
kernel_request_single = 0x00000001,
kernel_request_strided = 0x00000003,
kernel_request_data_only = 0x00000001
};
typedef uint32_t kernel_request_t;
namespace nd {
struct __declspec(dllexport) kernel_prefix {
typedef void (*destructor_fn_t)(kernel_prefix *);
void (*destructor)(kernel_prefix *self);
void *function;
template <typename T>
T get_function() const
{
return reinterpret_cast<T>(function);
}
void destroy()
{
if (destructor != 0) {
destructor(this);
}
}
void single(char *dst, char *const *src) { (*reinterpret_cast<kernel_single_t>(function))(this, dst, src); }
void strided(char *dst, intptr_t dst_stride, char *const *src, const intptr_t *src_stride, size_t count)
{
(*reinterpret_cast<kernel_strided_t>(function))(this, dst, dst_stride, src, src_stride, count);
}
kernel_prefix *get_child(intptr_t offset)
{
return reinterpret_cast<kernel_prefix *>(reinterpret_cast<char *>(this) + kernel_builder::aligned_size(offset));
}
size_t *get_offsets() { return reinterpret_cast<size_t *>(this + 1); }
static kernel_prefix *init(kernel_prefix *self, void *func)
{
self->function = func;
self->destructor = 0;
return self;
}
};
}
}
namespace dynd {
class __declspec(dllimport) bytes {
protected:
char *m_data;
size_t m_size;
public:
bytes() : m_data(0), m_size(0) {}
bytes(const char *data, size_t size) : m_data(new char[size]), m_size(size) { memcpy(m_data, data, size); }
template <size_t N>
bytes(const char (&data)[N]) : bytes(data, N - 1)
{
}
bytes(const bytes &other) : m_data(new char[other.m_size]), m_size(other.m_size)
{
memcpy(m_data, other.m_data, other.m_size);
}
~bytes() { delete[] m_data; }
bool empty() const { return m_size == 0; }
char *data() { return m_data; }
const char *data() const { return m_data; }
size_t size() const { return m_size; }
bytes &append(const char *data, size_t size)
{
char *old_data = m_data;
size_t old_size = m_size;
m_data = new char[m_size + size];
m_size += size;
memcpy(m_data, old_data, old_size);
memcpy(m_data + old_size, data, size);
delete[] old_data;
return *this;
}
bytes &assign(const char *data, size_t size)
{
if (size != m_size) {
delete[] m_data;
m_data = new char[size];
m_size = size;
}
memcpy(m_data, data, m_size);
return *this;
}
void clear()
{
if (m_size != 0) {
delete[] m_data;
m_data = nullptr;
m_size = 0;
}
}
void resize(size_t size)
{
if (size != m_size) {
char *data = new char[size];
memcpy(data, m_data, std::min(size, m_size));
delete[] m_data;
m_data = data;
m_size = size;
}
}
char *begin() { return m_data; }
const char *begin() const { return m_data; }
char *end() { return m_data + m_size; }
const char *end() const { return m_data + m_size; }
bytes &operator=(const bytes &rhs) { return assign(rhs.m_data, rhs.m_size); }
bool operator==(const bytes &rhs) const
{
return m_size == rhs.m_size && std::memcmp(m_data, rhs.m_data, m_size) == 0;
}
bool operator!=(const bytes &rhs) const
{
return m_size != rhs.m_size || std::memcmp(m_data, rhs.m_data, m_size) != 0;
}
const bytes operator+(const bytes &rhs)
{
bytes result;
result.resize(size() + rhs.size());
std::memcpy(result.begin(), begin(), size());
std::memcpy(result.begin() + size(), rhs.begin(), rhs.size());
return result;
}
bytes &operator+=(const bytes &rhs)
{
size_t orig_size = size();
resize(size() + rhs.size());
std::memcpy(begin() + orig_size, rhs.begin(), rhs.size());
return *this;
}
};
namespace detail {
class value_bytes {
protected:
char *m_data;
size_t m_size;
value_bytes(char *data, size_t size) : m_data(data), m_size(size) {}
public:
value_bytes() : m_data(0), m_size(0) {}
value_bytes(const value_bytes &other) : m_data(new char[other.m_size]), m_size(other.m_size)
{
memcpy(m_data, other.m_data, m_size);
}
~value_bytes() { delete[] m_data; }
operator char *() { return m_data; }
operator const char *() const { return m_data; }
value_bytes &operator=(const value_bytes &rhs)
{
memcpy(m_data, rhs.m_data, m_size);
return *this;
}
};
}
class strided_iterator : public detail::value_bytes,
public std::iterator<std::random_access_iterator_tag, detail::value_bytes> {
intptr_t m_stride;
public:
strided_iterator() : m_stride(0){};
strided_iterator(char *data, size_t size, intptr_t stride) : value_bytes(data, size), m_stride(stride) {}
strided_iterator(const strided_iterator &other) : value_bytes(other.m_data, other.m_size), m_stride(other.m_stride) {}
~strided_iterator()
{
m_data = 0;
m_size = 0;
}
intptr_t stride() const { return m_stride; }
value_bytes &operator*() { return *this; }
strided_iterator &operator++()
{
m_data += m_stride;
return *this;
}
strided_iterator operator++(int)
{
strided_iterator tmp(*this);
operator++();
return tmp;
}
strided_iterator &operator+=(std::ptrdiff_t i)
{
m_data += i * m_stride;
return *this;
}
strided_iterator &operator--()
{
m_data -= m_stride;
return *this;
}
strided_iterator operator--(int)
{
strided_iterator tmp(*this);
operator--();
return tmp;
}
strided_iterator &operator-=(std::ptrdiff_t i)
{
m_data -= i * m_stride;
return *this;
}
bool operator<(const strided_iterator &rhs) const { return m_data < rhs.m_data; }
bool operator<=(const strided_iterator &rhs) const { return m_data <= rhs.m_data; }
bool operator==(const strided_iterator &rhs) const { return m_data == rhs.m_data; }
bool operator!=(const strided_iterator &rhs) const { return m_data != rhs.m_data; }
bool operator>=(const strided_iterator &rhs) const { return m_data >= rhs.m_data; }
bool operator>(const strided_iterator &rhs) const { return m_data > rhs.m_data; }
std::ptrdiff_t operator-(strided_iterator rhs) { return (m_data - rhs.m_data) / m_stride; }
strided_iterator &operator=(const strided_iterator &other)
{
m_data = other.m_data;
m_size = other.m_size;
return *this;
}
friend strided_iterator operator+(strided_iterator lhs, std::ptrdiff_t rhs);
friend strided_iterator operator-(strided_iterator lhs, std::ptrdiff_t rhs);
};
inline strided_iterator operator+(strided_iterator lhs, std::ptrdiff_t rhs)
{
return strided_iterator(lhs.m_data + rhs * lhs.m_stride, lhs.m_size, lhs.m_stride);
}
inline strided_iterator operator-(strided_iterator lhs, std::ptrdiff_t rhs)
{
return strided_iterator(lhs.m_data - rhs * lhs.m_stride, lhs.m_size, lhs.m_stride);
}
}
namespace dynd {
class irange {
intptr_t m_start, m_finish, m_step;
public:
inline irange()
: m_start(std::numeric_limits<intptr_t>::min()), m_finish(std::numeric_limits<intptr_t>::max()), m_step(1)
{
}
inline irange(intptr_t idx) : m_start(idx), m_finish(idx), m_step(0) {}
inline irange(intptr_t start, intptr_t finish, intptr_t step = 1)
: m_start(start), m_finish(finish), m_step(step)
{
}
inline const intptr_t &start() const { return m_start; }
inline const intptr_t &finish() const { return m_finish; }
inline const intptr_t &step() const { return m_step; }
inline void set_start(intptr_t value) { m_start = value; }
inline void set_finish(intptr_t value) { m_finish = value; }
inline void set_step(intptr_t value) { m_step = value; }
inline bool is_nop() const
{
return m_start == std::numeric_limits<intptr_t>::min() && m_finish == std::numeric_limits<intptr_t>::max() &&
m_step == 1;
}
irange by(intptr_t step) const { return irange(m_start, m_finish, step); }
irange operator<(intptr_t finish) const { return irange(m_start, finish, m_step); }
irange operator<=(intptr_t last) const
{
return irange(m_start, (last != -1) ? (last + 1) : std::numeric_limits<intptr_t>::max(), m_step);
}
irange operator>(intptr_t finish) const { return irange(m_start, finish, m_step); }
irange operator>=(intptr_t last) const
{
return irange(m_start, (last != 0) ? (last - 1) : std::numeric_limits<intptr_t>::max(), m_step);
}
friend irange operator<(intptr_t start_minus_one, const irange &i);
friend irange operator<=(intptr_t start, const irange &i);
friend irange operator>(intptr_t start_plus_one, const irange &i);
friend irange operator>=(intptr_t start, const irange &i);
};
inline irange operator<(intptr_t start_minus_one, const irange &i)
{
return irange(start_minus_one + 1, i.m_finish, i.m_step);
}
inline irange operator<=(intptr_t start, const irange &i) { return irange(start, i.m_finish, i.m_step); }
inline irange operator>(intptr_t start_plus_one, const irange &i)
{
return irange(start_plus_one - 1, i.m_finish, i.m_step);
}
inline irange operator>=(intptr_t start, const irange &i) { return irange(start, i.m_finish, i.m_step); }
}
namespace dynd {
namespace eval {
struct __declspec(dllimport) eval_context {
assign_error_mode errmode;
eval_context() : errmode(assign_error_fractional) {}
};
extern __declspec(dllimport) eval_context default_eval_context;
}
}
namespace dynd {
enum memory_block_type_t {
array_memory_block_type,
external_memory_block_type,
fixed_size_pod_memory_block_type,
pod_memory_block_type,
zeroinit_memory_block_type,
objectarray_memory_block_type,
memmap_memory_block_type
};
__declspec(dllimport) std::ostream &operator<<(std::ostream &o, memory_block_type_t mbt);
struct __declspec(dllimport) memory_block_data {
struct __declspec(dllimport) api {
char *(*allocate)(memory_block_data *self, size_t count);
char *(*resize)(memory_block_data *self, char *previous_allocated, size_t count);
void (*finalize)(memory_block_data *self);
void (*reset)(memory_block_data *self);
};
std::atomic_long m_use_count;
uint32_t m_type;
explicit memory_block_data(long use_count, memory_block_type_t type) : m_use_count(use_count), m_type(type)
{
}
char *alloc(size_t count) { return get_api()->allocate(this, count); }
char *resize(char *previous_allocated, size_t count) { return get_api()->resize(this, previous_allocated, count); }
void finalize() { get_api()->finalize(this); }
void reset() { get_api()->reset(this); }
private:
api *get_api();
};
namespace detail {
__declspec(dllimport) void memory_block_free(memory_block_data *memblock);
}
inline long intrusive_ptr_use_count(memory_block_data *ptr) { return ptr->m_use_count; }
inline void intrusive_ptr_retain(memory_block_data *ptr) { ++ptr->m_use_count; }
inline void intrusive_ptr_release(memory_block_data *ptr)
{
if (--ptr->m_use_count == 0) {
detail::memory_block_free(ptr);
}
}
__declspec(dllimport) void memory_block_debug_print(const memory_block_data *memblock, std::ostream &o,
const std::string &indent = "");
}
namespace dynd {
class bytes;
class string;
enum type_id_t {
uninitialized_id,
any_kind_id,
scalar_kind_id,
bool_kind_id,
bool_id,
int_kind_id,
int8_id,
int16_id,
int32_id,
int64_id,
int128_id,
uint_kind_id,
uint8_id,
uint16_id,
uint32_id,
uint64_id,
uint128_id,
float_kind_id,
float16_id,
float32_id,
float64_id,
float128_id,
complex_kind_id,
complex_float32_id,
complex_float64_id,
void_id,
dim_kind_id,
bytes_kind_id,
fixed_bytes_id,
bytes_id,
string_kind_id,
fixed_string_id,
char_id,
string_id,
tuple_id,
struct_id,
fixed_dim_kind_id,
fixed_dim_id,
var_dim_id,
categorical_id,
option_id,
pointer_id,
memory_id,
type_id,
array_id,
callable_id,
expr_kind_id,
adapt_id,
expr_id,
cuda_host_id,
cuda_device_id,
kind_sym_id,
int_sym_id,
typevar_id,
typevar_dim_id,
typevar_constructed_id,
pow_dimsym_id,
ellipsis_dim_id,
dim_fragment_id,
};
template <type_id_t Value>
using id_constant = std::integral_constant<type_id_t, Value>;
template <type_id_t... I>
using type_id_sequence = integer_sequence<type_id_t, I...>;
typedef type_id_sequence<int8_id, int16_id, int32_id, int64_id, int128_id> int_ids;
typedef type_id_sequence<bool_id, uint8_id, uint16_id, uint32_id, uint64_id, uint128_id> uint_ids;
typedef type_id_sequence<float16_id, float32_id, float64_id, float128_id> float_ids;
typedef type_id_sequence<complex_float32_id, complex_float64_id> complex_ids;
typedef join<int_ids, uint_ids>::type integral_ids;
typedef join<integral_ids, join<float_ids, complex_ids>::type>::type arithmetic_ids;
typedef type_id_sequence<fixed_dim_id, var_dim_id> dim_ids;
enum type_flags_t {
type_flag_none = 0x00000000,
type_flag_zeroinit = 0x00000001,
type_flag_construct = 0x00000002,
type_flag_blockref = 0x00000004,
type_flag_destructor = 0x00000008,
type_flag_not_host_readable = 0x00000010,
type_flag_symbolic = 0x00000020,
type_flag_variadic = 0x00000040,
type_flag_indexable = 0x00000080,
};
enum axis_order_classification_t {
axis_order_none,
axis_order_neither,
axis_order_f,
axis_order_c
};
enum {
type_flags_operand_inherited = type_flag_zeroinit | type_flag_blockref | type_flag_construct | type_flag_destructor |
type_flag_not_host_readable | type_flag_symbolic,
type_flags_value_inherited = type_flag_symbolic | type_flag_variadic
};
__declspec(dllimport) std::ostream &operator<<(std::ostream &o, type_id_t tid);
namespace ndt {
class base_type;
}
inline bool is_builtin_type(const ndt::base_type *dt)
{
switch (reinterpret_cast<uintptr_t>(dt)) {
case uninitialized_id:
case bool_id:
case int8_id:
case int16_id:
case int32_id:
case int64_id:
case int128_id:
case uint8_id:
case uint16_id:
case uint32_id:
case uint64_id:
case uint128_id:
case float16_id:
case float32_id:
case float64_id:
case float128_id:
case complex_float32_id:
case complex_float64_id:
case void_id:
return true;
default:
return false;
}
}
namespace detail {
template <int I>
struct log2_x;
template <>
struct log2_x<1> {
enum { value = 0 };
};
template <>
struct log2_x<2> {
enum { value = 1 };
};
template <>
struct log2_x<4> {
enum { value = 2 };
};
template <>
struct log2_x<8> {
enum { value = 3 };
};
}
template <typename T>
struct type_id_of;
template <typename T>
struct type_id_of<const T> {
static const type_id_t value = type_id_of<T>::value;
};
template <>
struct type_id_of<bool1> {
static const type_id_t value = bool_id;
};
template <>
struct type_id_of<char> {
static const type_id_t value = ((char)-1) < 0 ? int8_id : uint8_id;
};
template <>
struct type_id_of<signed char> {
static const type_id_t value = int8_id;
};
template <>
struct type_id_of<short> {
static const type_id_t value = int16_id;
};
template <>
struct type_id_of<int> {
static const type_id_t value = int32_id;
};
template <>
struct type_id_of<long> {
static const type_id_t value = static_cast<type_id_t>(int8_id + detail::log2_x<sizeof(long)>::value);
};
template <>
struct type_id_of<long long> {
static const type_id_t value = int64_id;
};
template <>
struct type_id_of<int128> {
static const type_id_t value = int128_id;
};
template <>
struct type_id_of<uint8_t> {
static const type_id_t value = uint8_id;
};
template <>
struct type_id_of<uint16_t> {
static const type_id_t value = uint16_id;
};
template <>
struct type_id_of<unsigned int> {
static const type_id_t value = uint32_id;
};
template <>
struct type_id_of<unsigned long> {
static const type_id_t value = static_cast<type_id_t>(uint8_id + detail::log2_x<sizeof(unsigned long)>::value);
};
template <>
struct type_id_of<unsigned long long> {
static const type_id_t value = uint64_id;
};
template <>
struct type_id_of<uint128> {
static const type_id_t value = uint128_id;
};
template <>
struct type_id_of<float16> {
static const type_id_t value = float16_id;
};
template <>
struct type_id_of<float32> {
static const type_id_t value = float32_id;
};
template <>
struct type_id_of<float64> {
static const type_id_t value = float64_id;
};
template <>
struct type_id_of<float128> {
static const type_id_t value = float128_id;
};
template <>
struct type_id_of<complex64> {
static const type_id_t value = complex_float32_id;
};
template <>
struct type_id_of<complex128> {
static const type_id_t value = complex_float64_id;
};
template <>
struct type_id_of<void> {
static const type_id_t value = void_id;
};
template <>
struct type_id_of<ndt::type> {
static const type_id_t value = type_id;
};
template <>
struct type_id_of<std::complex<float>> {
static const type_id_t value = complex_float32_id;
};
template <>
struct type_id_of<std::complex<double>> {
static const type_id_t value = complex_float64_id;
};
template <type_id_t TypeID>
struct type_of;
template <>
struct type_of<bool_id> {
typedef bool1 type;
};
template <>
struct type_of<int8_id> {
typedef int8 type;
};
template <>
struct type_of<int16_id> {
typedef int16 type;
};
template <>
struct type_of<int32_id> {
typedef int32 type;
};
template <>
struct type_of<int64_id> {
typedef int64 type;
};
template <>
struct type_of<int128_id> {
typedef int128 type;
};
template <>
struct type_of<uint8_id> {
typedef uint8 type;
};
template <>
struct type_of<uint16_id> {
typedef uint16 type;
};
template <>
struct type_of<uint32_id> {
typedef uint32 type;
};
template <>
struct type_of<uint64_id> {
typedef uint64 type;
};
template <>
struct type_of<uint128_id> {
typedef uint128 type;
};
template <>
struct type_of<float16_id> {
typedef float16 type;
};
template <>
struct type_of<float32_id> {
typedef float32 type;
};
template <>
struct type_of<float64_id> {
typedef float64 type;
};
template <>
struct type_of<float128_id> {
typedef float128 type;
};
template <>
struct type_of<complex_float32_id> {
typedef complex64 type;
};
template <>
struct type_of<complex_float64_id> {
typedef complex128 type;
};
template <>
struct type_of<bytes_id> {
typedef bytes type;
};
template <>
struct type_of<string_id> {
typedef string type;
};
template <>
struct type_of<type_id> {
typedef ndt::type type;
};
template <type_id_t ID>
struct base_id_of;
template <>
struct base_id_of<scalar_kind_id> : id_constant<any_kind_id> {
};
template <>
struct base_id_of<bool_kind_id> : id_constant<scalar_kind_id> {
};
template <>
struct base_id_of<bool_id> : id_constant<bool_kind_id> {
};
template <>
struct base_id_of<int_kind_id> : id_constant<scalar_kind_id> {
};
template <>
struct base_id_of<int8_id> : id_constant<int_kind_id> {
};
template <>
struct base_id_of<int16_id> : id_constant<int_kind_id> {
};
template <>
struct base_id_of<int32_id> : id_constant<int_kind_id> {
};
template <>
struct base_id_of<int64_id> : id_constant<int_kind_id> {
};
template <>
struct base_id_of<int128_id> : id_constant<int_kind_id> {
};
template <>
struct base_id_of<uint_kind_id> : id_constant<scalar_kind_id> {
};
template <>
struct base_id_of<uint8_id> : id_constant<uint_kind_id> {
};
template <>
struct base_id_of<uint16_id> : id_constant<uint_kind_id> {
};
template <>
struct base_id_of<uint32_id> : id_constant<uint_kind_id> {
};
template <>
struct base_id_of<uint64_id> : id_constant<uint_kind_id> {
};
template <>
struct base_id_of<uint128_id> : id_constant<uint_kind_id> {
};
template <>
struct base_id_of<float_kind_id> : id_constant<scalar_kind_id> {
};
template <>
struct base_id_of<float16_id> : id_constant<float_kind_id> {
};
template <>
struct base_id_of<float32_id> : id_constant<float_kind_id> {
};
template <>
struct base_id_of<float64_id> : id_constant<float_kind_id> {
};
template <>
struct base_id_of<float128_id> : id_constant<float_kind_id> {
};
template <>
struct base_id_of<complex_kind_id> : id_constant<scalar_kind_id> {
};
template <>
struct base_id_of<complex_float32_id> : id_constant<complex_kind_id> {
};
template <>
struct base_id_of<complex_float64_id> : id_constant<complex_kind_id> {
};
template <>
struct base_id_of<void_id> : id_constant<any_kind_id> {
};
template <>
struct base_id_of<bytes_kind_id> : id_constant<scalar_kind_id> {
};
template <>
struct base_id_of<fixed_bytes_id> : id_constant<bytes_kind_id> {
};
template <>
struct base_id_of<bytes_id> : id_constant<bytes_kind_id> {
};
template <>
struct base_id_of<string_kind_id> : id_constant<scalar_kind_id> {
};
template <>
struct base_id_of<char_id> : id_constant<string_kind_id> {
};
template <>
struct base_id_of<fixed_string_id> : id_constant<string_kind_id> {
};
template <>
struct base_id_of<string_id> : id_constant<string_kind_id> {
};
template <>
struct base_id_of<fixed_dim_kind_id> : id_constant<dim_kind_id> {
};
template <>
struct base_id_of<fixed_dim_id> : id_constant<fixed_dim_kind_id> {
};
template <>
struct base_id_of<var_dim_id> : id_constant<dim_kind_id> {
};
template <>
struct base_id_of<pointer_id> : id_constant<any_kind_id> {
};
template <>
struct base_id_of<memory_id> : id_constant<any_kind_id> {
};
template <>
struct base_id_of<expr_kind_id> : id_constant<any_kind_id> {
};
template <>
struct base_id_of<adapt_id> : id_constant<expr_kind_id> {
};
template <>
struct base_id_of<tuple_id> : id_constant<scalar_kind_id> {
};
template <>
struct base_id_of<struct_id> : id_constant<tuple_id> {
};
template <>
struct base_id_of<option_id> : id_constant<any_kind_id> {
};
template <>
struct base_id_of<categorical_id> : id_constant<any_kind_id> {
};
template <>
struct base_id_of<expr_id> : id_constant<any_kind_id> {
};
template <>
struct base_id_of<type_id> : id_constant<scalar_kind_id> {
};
template <>
struct base_id_of<callable_id> : id_constant<scalar_kind_id> {
};
template <>
struct base_id_of<array_id> : id_constant<scalar_kind_id> {
};
template <>
struct base_id_of<dim_kind_id> : id_constant<any_kind_id> {
};
template <>
struct base_id_of<typevar_id> : id_constant<scalar_kind_id> {
};
namespace detail {
template <type_id_t DstTypeID, type_id_t DstBaseID, type_id_t SrcTypeID, type_id_t SrcBaseID>
struct is_lossless_assignable {
static const bool value = false;
};
template <type_id_t DstTypeID, type_id_t SrcTypeID>
struct is_lossless_assignable<DstTypeID, float_kind_id, SrcTypeID, int_kind_id> {
static const bool value = true;
};
template <type_id_t DstTypeID, type_id_t SrcTypeID>
struct is_lossless_assignable<DstTypeID, float_kind_id, SrcTypeID, uint_kind_id> {
static const bool value = true;
};
template <type_id_t DstTypeID, type_id_t SrcTypeID>
struct is_lossless_assignable<DstTypeID, complex_kind_id, SrcTypeID, bool_kind_id> {
static const bool value = true;
};
template <type_id_t DstTypeID, type_id_t SrcTypeID>
struct is_lossless_assignable<DstTypeID, complex_kind_id, SrcTypeID, int_kind_id> {
static const bool value = false;
};
template <type_id_t DstTypeID, type_id_t SrcTypeID>
struct is_lossless_assignable<DstTypeID, complex_kind_id, SrcTypeID, uint_kind_id> {
static const bool value = false;
};
template <type_id_t DstTypeID, type_id_t SrcTypeID>
struct is_lossless_assignable<DstTypeID, complex_kind_id, SrcTypeID, float_kind_id> {
static const bool value = (sizeof(typename type_of<DstTypeID>::type) / 2) >
sizeof(typename type_of<SrcTypeID>::type);
};
template <type_id_t DstTypeID, type_id_t SrcTypeID, type_id_t BaseTypeID>
struct is_lossless_assignable<DstTypeID, BaseTypeID, SrcTypeID, BaseTypeID> {
static const bool value = sizeof(typename type_of<DstTypeID>::type) > sizeof(typename type_of<SrcTypeID>::type);
};
}
template <type_id_t DstTypeID, type_id_t Src0TypeID>
struct is_lossless_assignable : detail::is_lossless_assignable<DstTypeID, base_id_of<DstTypeID>::value, Src0TypeID,
base_id_of<Src0TypeID>::value> {
};
template <typename T>
struct is_dynd_scalar {
enum { value = false };
};
template <>
struct is_dynd_scalar<bool> {
enum { value = true };
};
template <>
struct is_dynd_scalar<bool1> {
enum { value = true };
};
template <>
struct is_dynd_scalar<char> {
enum { value = true };
};
template <>
struct is_dynd_scalar<signed char> {
enum { value = true };
};
template <>
struct is_dynd_scalar<short> {
enum { value = true };
};
template <>
struct is_dynd_scalar<int> {
enum { value = true };
};
template <>
struct is_dynd_scalar<long> {
enum { value = true };
};
template <>
struct is_dynd_scalar<long long> {
enum { value = true };
};
template <>
struct is_dynd_scalar<int128> {
enum { value = true };
};
template <>
struct is_dynd_scalar<unsigned char> {
enum { value = true };
};
template <>
struct is_dynd_scalar<unsigned short> {
enum { value = true };
};
template <>
struct is_dynd_scalar<unsigned int> {
enum { value = true };
};
template <>
struct is_dynd_scalar<unsigned long> {
enum { value = true };
};
template <>
struct is_dynd_scalar<unsigned long long> {
enum { value = true };
};
template <>
struct is_dynd_scalar<uint128> {
enum { value = true };
};
template <>
struct is_dynd_scalar<float16> {
enum { value = true };
};
template <>
struct is_dynd_scalar<float32> {
enum { value = true };
};
template <>
struct is_dynd_scalar<float64> {
enum { value = true };
};
template <>
struct is_dynd_scalar<float128> {
enum { value = true };
};
template <>
struct is_dynd_scalar<complex64> {
enum { value = true };
};
template <>
struct is_dynd_scalar<complex128> {
enum { value = true };
};
template <>
struct is_dynd_scalar<std::complex<float>> {
enum { value = true };
};
template <>
struct is_dynd_scalar<std::complex<double>> {
enum { value = true };
};
template <typename T>
struct property_type_id_of {
static const type_id_t value = type_id_of<T>::value;
};
template <>
struct property_type_id_of<std::string> {
static const type_id_t value = string_id;
};
}
namespace dynd {
namespace ndt {
class type;
}
struct iterdata_common;
typedef void (*foreach_fn_t)(const ndt::type &dt, const char *arrmeta, char *data, void *callback_data);
typedef char *(*iterdata_increment_fn_t)(iterdata_common *iterdata, intptr_t level);
typedef char *(*iterdata_advance_fn_t)(iterdata_common *iterdata, intptr_t level, intptr_t i);
typedef char *(*iterdata_reset_fn_t)(iterdata_common *iterdata, char *data, intptr_t ndim);
typedef void (*type_transform_fn_t)(const ndt::type &dt, intptr_t arrmeta_offset, void *extra,
ndt::type &out_transformed_type, bool &out_was_transformed);
struct __declspec(dllimport) iterdata_common {
iterdata_increment_fn_t incr;
iterdata_advance_fn_t adv;
iterdata_reset_fn_t reset;
};
namespace ndt {
class __declspec(dllimport) base_type {
mutable std::atomic_long m_use_count;
protected:
type_id_t m_id;
size_t m_metadata_size;
size_t m_data_size;
size_t m_data_alignment;
uint32_t flags;
intptr_t m_ndim;
intptr_t m_fixed_ndim;
public:
base_type(type_id_t id, size_t data_size, size_t data_alignment, uint32_t flags, size_t arrmeta_size, size_t ndim,
size_t strided_ndim)
: m_use_count(1), m_id(id), m_metadata_size(arrmeta_size), m_data_size(data_size),
m_data_alignment(data_alignment), flags(flags), m_ndim(ndim), m_fixed_ndim(strided_ndim)
{
}
virtual ~base_type();
int32_t get_use_count() const { return m_use_count; }
type_id_t get_id() const { return m_id; }
size_t get_arrmeta_size() const { return m_metadata_size; }
size_t get_data_size() const { return m_data_size; }
size_t get_data_alignment() const { return m_data_alignment; }
intptr_t get_ndim() const { return m_ndim; }
intptr_t get_strided_ndim() const { return m_fixed_ndim; }
uint32_t get_flags() const { return flags; }
virtual size_t get_default_data_size() const;
virtual void print_type(std::ostream &o) const = 0;
virtual void print_data(std::ostream &o, const char *arrmeta, const char *data) const;
inline bool is_indexable() const { return (flags & type_flag_indexable) != 0; }
bool is_scalar() const { return m_ndim == 0 && (flags & type_flag_variadic) == 0; }
virtual bool is_type_subarray(const ndt::type &subarray_tp) const;
virtual bool is_expression() const;
virtual bool is_unique_data_owner(const char *arrmeta) const;
virtual void transform_child_types(type_transform_fn_t transform_fn, intptr_t arrmeta_offset, void *extra,
ndt::type &out_transformed_type, bool &out_was_transformed) const;
virtual ndt::type get_canonical_type() const;
virtual void set_from_utf8_string(const char *arrmeta, char *data, const char *utf8_begin, const char *utf8_end,
const eval::eval_context *ectx) const;
inline void set_from_utf8_string(const char *arrmeta, char *data, const std::string &utf8_str,
const eval::eval_context *ectx) const
{
this->set_from_utf8_string(arrmeta, data, utf8_str.data(), utf8_str.data() + utf8_str.size(), ectx);
}
virtual ndt::type apply_linear_index(intptr_t nindices, const irange *indices, size_t current_i,
const ndt::type &root_tp, bool leading_dimension) const;
virtual intptr_t apply_linear_index(intptr_t nindices, const irange *indices, const char *arrmeta,
const ndt::type &result_type, char *out_arrmeta,
const intrusive_ptr<memory_block_data> &embedded_reference, size_t current_i,
const ndt::type &root_tp, bool leading_dimension, char **inout_data,
intrusive_ptr<memory_block_data> &inout_dataref) const;
virtual ndt::type at_single(intptr_t i0, const char **inout_arrmeta, const char **inout_data) const;
virtual ndt::type get_type_at_dimension(char **inout_arrmeta, intptr_t i, intptr_t total_ndim = 0) const;
virtual void get_shape(intptr_t ndim, intptr_t i, intptr_t *out_shape, const char *arrmeta, const char *data) const;
virtual void get_strides(size_t i, intptr_t *out_strides, const char *arrmeta) const;
virtual bool is_c_contiguous(const char *arrmeta) const;
bool is_symbolic() const { return (flags & type_flag_symbolic) != 0; }
virtual axis_order_classification_t classify_axis_order(const char *arrmeta) const;
virtual bool is_lossless_assignment(const ndt::type &dst_tp, const ndt::type &src_tp) const;
virtual bool operator==(const base_type &rhs) const = 0;
virtual void arrmeta_default_construct(char *arrmeta, bool blockref_alloc) const;
virtual void arrmeta_copy_construct(char *dst_arrmeta, const char *src_arrmeta,
const intrusive_ptr<memory_block_data> &embedded_reference) const;
virtual void arrmeta_destruct(char *arrmeta) const;
virtual void arrmeta_reset_buffers(char *arrmeta) const;
virtual void arrmeta_finalize_buffers(char *arrmeta) const;
virtual void arrmeta_debug_print(const char *arrmeta, std::ostream &o, const std::string &indent) const;
virtual void data_construct(const char *arrmeta, char *data) const;
virtual void data_destruct(const char *arrmeta, char *data) const;
virtual void data_destruct_strided(const char *arrmeta, char *data, intptr_t stride, size_t count) const;
virtual size_t get_iterdata_size(intptr_t ndim) const;
virtual size_t iterdata_construct(iterdata_common *iterdata, const char **inout_arrmeta, intptr_t ndim,
const intptr_t *shape, ndt::type &out_uniform_tp) const;
virtual size_t iterdata_destruct(iterdata_common *iterdata, intptr_t ndim) const;
virtual bool match(const ndt::type &candidate_tp, std::map<std::string, ndt::type> &tp_vars) const;
virtual void foreach_leading(const char *arrmeta, char *data, foreach_fn_t callback, void *callback_data) const;
virtual void get_vars(std::unordered_set<std::string> &) const {}
virtual std::map<std::string, std::pair<ndt::type, const char *>> get_dynamic_type_properties() const;
friend void intrusive_ptr_retain(const base_type *ptr);
friend void intrusive_ptr_release(const base_type *ptr);
friend long intrusive_ptr_use_count(const base_type *ptr);
friend type make_dynamic_type(type_id_t tp_id);
};
inline void intrusive_ptr_retain(const base_type *ptr)
{
if (!is_builtin_type(ptr)) {
++ptr->m_use_count;
}
}
inline void intrusive_ptr_release(const base_type *ptr)
{
if (!is_builtin_type(ptr)) {
if (--ptr->m_use_count == 0) {
delete ptr;
}
}
}
inline long intrusive_ptr_use_count(const base_type *ptr) { return ptr->m_use_count; }
}
struct __declspec(dllimport) size_stride_t {
intptr_t dim_size;
intptr_t stride;
};
}
namespace dynd {
namespace ndt {
class __declspec(dllimport) base_expr_type : public base_type {
public:
base_expr_type(type_id_t type_id, size_t data_size, size_t alignment, uint32_t flags, size_t arrmeta_size,
size_t ndim = 0);
virtual const type &get_value_type() const = 0;
virtual const type &get_operand_type() const = 0;
virtual const type &get_storage_type() const
{
throw std::runtime_error("get_storage_type is not implemented for this type");
}
static inline uint32_t inherited_flags(uint32_t value_flags, uint32_t operand_flags)
{
return (value_flags & type_flags_value_inherited) | (operand_flags & type_flags_operand_inherited);
}
virtual type with_replaced_storage_type(const type &replacement_type) const = 0;
bool is_expression() const;
type get_canonical_type() const;
void arrmeta_default_construct(char *arrmeta, bool blockref_alloc) const;
void arrmeta_copy_construct(char *dst_arrmeta, const char *src_arrmeta,
const intrusive_ptr<memory_block_data> &embedded_reference) const;
void arrmeta_destruct(char *arrmeta) const;
void arrmeta_debug_print(const char *arrmeta, std::ostream &o, const std::string &indent) const;
size_t get_iterdata_size(intptr_t ndim) const;
};
}
}
namespace dynd {
namespace ndt {
class type;
}
enum string_encoding_t : uint32_t {
string_encoding_ascii,
string_encoding_ucs_2,
string_encoding_utf_8,
string_encoding_utf_16,
string_encoding_utf_32,
string_encoding_invalid
};
extern __declspec(dllimport) int string_encoding_char_size_table[6];
inline bool is_variable_length_string_encoding(string_encoding_t encoding)
{
return encoding == string_encoding_utf_8 || encoding == string_encoding_utf_16;
}
inline const char *encoding_as_string(string_encoding_t encoding)
{
switch (encoding) {
case string_encoding_ascii:
return "ascii";
case string_encoding_ucs_2:
return "ucs2";
case string_encoding_utf_8:
return "utf8";
case string_encoding_utf_16:
return "utf16";
case string_encoding_utf_32:
return "utf32";
default:
return "unknown string encoding";
}
}
inline std::ostream &operator<<(std::ostream &o, string_encoding_t encoding)
{
o << encoding_as_string(encoding);
return o;
}
typedef uint32_t (*next_unicode_codepoint_t)(const char *&it, const char *end);
typedef void (*append_unicode_codepoint_t)(uint32_t cp, char *&it, char *end);
__declspec(dllimport) next_unicode_codepoint_t
get_next_unicode_codepoint_function(string_encoding_t encoding, assign_error_mode errmode);
__declspec(dllimport) append_unicode_codepoint_t
get_append_unicode_codepoint_function(string_encoding_t encoding, assign_error_mode errmode);
__declspec(dllimport) std::string string_range_as_utf8_string(string_encoding_t encoding, const char *begin, const char *end,
assign_error_mode errmode);
__declspec(dllimport) void print_escaped_unicode_codepoint(std::ostream &o, uint32_t cp, bool single_quote);
__declspec(dllimport) void print_escaped_utf8_string(std::ostream &o, const char *str_begin, const char *str_end,
bool single_quote = false);
inline void print_escaped_utf8_string(std::ostream &o, const std::string &str, bool single_quote = false)
{
print_escaped_utf8_string(o, str.data(), str.data() + str.size(), single_quote);
}
__declspec(dllimport) void append_utf8_codepoint(uint32_t cp, std::string &out_str);
__declspec(dllimport) ndt::type char_type_of_encoding(string_encoding_t encoding);
}
namespace dynd {
namespace ndt {
class __declspec(dllimport) base_string_type : public base_type {
private:
const string_encoding_t m_encoding{string_encoding_ascii};
const std::string m_encoding_repr{encoding_as_string(string_encoding_ascii)};
public:
base_string_type(type_id_t type_id, size_t data_size, size_t alignment, uint32_t flags, size_t arrmeta_size)
: base_type(type_id, data_size, alignment, flags, arrmeta_size, 0, 0)
{
}
virtual string_encoding_t get_encoding() const { return m_encoding; }
virtual void get_string_range(const char **out_begin, const char **out_end, const char *arrmeta,
const char *data) const = 0;
std::string get_utf8_string(const char *arrmeta, const char *data, assign_error_mode errmode) const;
size_t get_iterdata_size(intptr_t ndim) const;
std::map<std::string, std::pair<ndt::type, const char *>> get_dynamic_type_properties() const;
};
}
}
namespace dynd {
namespace ndt {
class type;
}
namespace nd {
class array;
}
class __declspec(dllimport) dynd_exception {
protected:
std::string m_message, m_what;
public:
dynd_exception() {}
dynd_exception(const char *exception_name, const std::string &msg)
: m_message(msg), m_what(std::string() + exception_name + ": " + msg)
{
}
virtual const char *message() const throw();
virtual const char *what() const throw();
virtual ~dynd_exception() throw();
};
class __declspec(dllimport) too_many_indices : public dynd_exception {
public:
too_many_indices(const ndt::type &dt, intptr_t nindices, intptr_t ndim);
virtual ~too_many_indices() throw();
};
class __declspec(dllimport) index_out_of_bounds : public dynd_exception {
public:
index_out_of_bounds(intptr_t i, size_t axis, intptr_t ndim, const intptr_t *shape);
index_out_of_bounds(intptr_t i, size_t axis, const std::vector<intptr_t> &shape);
index_out_of_bounds(intptr_t i, intptr_t dimension_size);
virtual ~index_out_of_bounds() throw();
};
class __declspec(dllimport) axis_out_of_bounds : public dynd_exception {
public:
axis_out_of_bounds(size_t i, intptr_t ndim);
virtual ~axis_out_of_bounds() throw();
};
class __declspec(dllimport) irange_out_of_bounds : public dynd_exception {
public:
irange_out_of_bounds(const irange &i, size_t axis, intptr_t ndim, const intptr_t *shape);
irange_out_of_bounds(const irange &i, size_t axis, const std::vector<intptr_t> &shape);
irange_out_of_bounds(const irange &i, intptr_t dimension_size);
virtual ~irange_out_of_bounds() throw();
};
class __declspec(dllimport) zero_division_error : public dynd_exception {
public:
zero_division_error(const std::string &msg) : dynd_exception("zero division error", msg) {}
virtual ~zero_division_error() throw();
};
class __declspec(dllimport) type_error : public dynd_exception {
public:
type_error(const char *exception_name, const std::string &msg) : dynd_exception(exception_name, msg) {}
type_error(const std::string &msg) : dynd_exception("type error", msg) {}
virtual ~type_error() throw();
};
class __declspec(dllimport) invalid_id : public type_error {
public:
invalid_id(int type_id);
virtual ~invalid_id() throw();
};
class __declspec(dllimport) string_decode_error : public dynd_exception {
std::string m_bytes;
string_encoding_t m_encoding;
public:
string_decode_error(const char *begin, const char *end, string_encoding_t encoding);
virtual ~string_decode_error() throw();
const std::string &bytes() const;
string_encoding_t encoding() const;
};
class __declspec(dllimport) string_encode_error : public dynd_exception {
uint32_t m_cp;
string_encoding_t m_encoding;
public:
string_encode_error(uint32_t cp, string_encoding_t encoding);
virtual ~string_encode_error() throw();
uint32_t cp() const;
string_encoding_t encoding() const;
};
enum comparison_type_t {
comparison_type_sorting_less,
comparison_type_less,
comparison_type_less_equal,
comparison_type_equal,
comparison_type_not_equal,
comparison_type_greater_equal,
comparison_type_greater
};
class __declspec(dllimport) not_comparable_error : public dynd_exception {
public:
not_comparable_error(const ndt::type &lhs, const ndt::type &rhs, comparison_type_t comptype);
virtual ~not_comparable_error() throw();
};
}
namespace dynd {
namespace detail {
template <typename ValueType, int NDim>
class scalar_wrapper_iterator;
template <typename ValueType>
class scalar_wrapper {
protected:
const char *m_metadata;
char *m_data;
public:
typedef ValueType data_type;
static const intptr_t ndim = 0;
template <int NDim>
class iterator_type : public scalar_wrapper_iterator<ValueType, NDim> {
public:
iterator_type(const char *metadata, char *data) : scalar_wrapper_iterator<ValueType, NDim>(metadata, data) {}
};
scalar_wrapper(const char *metadata, char *data) : m_metadata(metadata), m_data(data) {}
data_type &operator()(const char *, char *data)
{
return *reinterpret_cast<data_type *>(data);
}
};
template <typename ValueType>
class scalar_wrapper_iterator<ValueType, 0> {
protected:
char *m_data;
public:
scalar_wrapper_iterator(const char *, char *data) : m_data(data) {}
ValueType &operator*() { return *reinterpret_cast<ValueType *>(m_data); }
bool operator==(const scalar_wrapper_iterator &rhs) const { return m_data == rhs.m_data; }
bool operator!=(const scalar_wrapper_iterator &rhs) const { return m_data != rhs.m_data; }
};
}
template <typename T>
using identity_t = T;
template <typename T>
using as_t = typename conditional_make<!std::is_fundamental<typename std::remove_cv<T>::type>::value &&
!std::is_same<typename std::remove_cv<T>::type, ndt::type>::value,
identity_t, detail::scalar_wrapper, T>::type;
inline size_t inc_to_alignment(size_t offset, size_t alignment)
{
return (offset + alignment - 1) & (std::size_t)(-(std::ptrdiff_t)alignment);
}
inline char *inc_to_alignment(char *ptr, size_t alignment)
{
return reinterpret_cast<char *>((reinterpret_cast<std::size_t>(ptr) + alignment - 1) &
(std::size_t)(-(std::ptrdiff_t)alignment));
}
inline void *inc_to_alignment(void *ptr, size_t alignment)
{
return reinterpret_cast<char *>((reinterpret_cast<std::size_t>(ptr) + alignment - 1) &
(size_t)(-(std::ptrdiff_t)alignment));
}
inline bool offset_is_aligned(size_t offset, size_t alignment) { return (offset & (alignment - 1)) == 0; }
void __declspec(dllimport) print_builtin_scalar(type_id_t type_id, std::ostream &o, const char *data);
struct __declspec(dllimport) iterdata_broadcasting_terminator {
iterdata_common common;
char *data;
};
__declspec(dllimport) char *iterdata_broadcasting_terminator_incr(iterdata_common *iterdata, intptr_t level);
__declspec(dllimport) char *iterdata_broadcasting_terminator_adv(iterdata_common *iterdata, intptr_t level, intptr_t i);
__declspec(dllimport) char *iterdata_broadcasting_terminator_reset(iterdata_common *iterdata, char *data, intptr_t level);
namespace ndt {
typedef type (*type_make_t)(type_id_t tp_id, const nd::array &args);
__declspec(dllimport) type make_fixed_dim(size_t dim_size, const type &element_tp);
inline type make_var_dim(const type &element_tp);
template <typename T>
struct traits {
~traits() = delete;
};
template <typename T>
struct has_traits {
static const bool value = std::is_destructible<traits<T>>::value;
};
class __declspec(dllimport) type : public intrusive_ptr<const base_type> {
private:
template <typename T, typename C = typename T::value_type>
std::enable_if_t<is_vector<T>::value, const T> &property(const char *name) const
{
const std::pair<ndt::type, const char *> pair = get_properties()[name];
const ndt::type &dt = pair.first.get_dtype();
if (pair.first.get_id() != fixed_dim_id) {
throw std::runtime_error("unsupported type for property access");
}
if (dt.get_id() == property_type_id_of<C>::value) {
return *reinterpret_cast<const T *>(pair.second);
}
throw std::runtime_error("type mismatch or unsupported type in property access");
}
template <typename T>
std::enable_if_t<!is_vector<T>::value, const T> &property(const char *name) const
{
const std::pair<ndt::type, const char *> pair = get_properties()[name];
if (pair.first.get_id() == property_type_id_of<T>::value) {
return *reinterpret_cast<const T *>(pair.second);
}
throw std::runtime_error("type mismatch in property access");
}
public:
using intrusive_ptr<const base_type>::intrusive_ptr;
type() = default;
type(type_id_t tp_id);
explicit type(const std::string &rep);
type(const char *rep_begin, const char *rep_end);
bool operator==(const type &rhs) const
{
return m_ptr == rhs.m_ptr || (!is_builtin() && !rhs.is_builtin() && *m_ptr == *rhs.m_ptr);
}
bool operator!=(const type &rhs) const { return !(operator==(rhs)); }
bool is_null() const { return m_ptr == 0; }
bool is_builtin() const { return is_builtin_type(m_ptr); }
type at_array(int nindices, const irange *indices) const;
type at_single(intptr_t i0, const char **inout_arrmeta = 0, const char **inout_data = 0) const
{
if (!is_builtin()) {
return m_ptr->at_single(i0, inout_arrmeta, inout_data);
}
else {
throw too_many_indices(*this, 1, 0);
}
}
type at(const irange &i0) const { return at_array(1, &i0); }
type at(const irange &i0, const irange &i1) const
{
irange i[2] = {i0, i1};
return at_array(2, i);
}
type at(const irange &i0, const irange &i1, const irange &i2) const
{
irange i[3] = {i0, i1, i2};
return at_array(3, i);
}
type at(const irange &i0, const irange &i1, const irange &i2, const irange &i3) const
{
irange i[4] = {i0, i1, i2, i3};
return at_array(4, i);
}
bool match(const ndt::type &candidate_tp, std::map<std::string, ndt::type> &tp_vars) const;
bool match(const type &other) const
{
std::map<std::string, type> tp_vars;
return match(other, tp_vars);
}
template <typename T>
const T &p(const char *name) const
{
return property<T>(name);
}
template <typename T>
const T &p(const std::string &name) const
{
return property<T>(name.c_str());
}
type apply_linear_index(intptr_t nindices, const irange *indices, size_t current_i, const type &root_tp,
bool leading_dimension) const;
const type &value_type() const;
const type &storage_type() const;
type_id_t get_id() const
{
if (is_builtin()) {
return static_cast<type_id_t>(reinterpret_cast<intptr_t>(m_ptr));
}
else {
return m_ptr->get_id();
}
}
type_id_t unchecked_get_builtin_id() const { return static_cast<type_id_t>(reinterpret_cast<intptr_t>(m_ptr)); }
type_id_t get_base_id() const;
size_t get_data_alignment() const;
size_t get_data_size() const;
size_t get_default_data_size() const;
size_t get_arrmeta_size() const
{
if (is_builtin()) {
return 0;
}
else {
return m_ptr->get_arrmeta_size();
}
}
bool data_layout_compatible_with(const type &rhs) const;
bool is_type_subarray(const ndt::type &subarray_tp) const
{
if (is_builtin()) {
return *this == subarray_tp;
}
else {
return m_ptr->is_type_subarray(subarray_tp);
}
}
bool is_pod() const
{
if (is_builtin()) {
return true;
}
else {
return m_ptr->get_data_size() > 0 && (m_ptr->get_flags() & (type_flag_blockref | type_flag_destructor)) == 0;
}
}
bool is_c_contiguous(const char *arrmeta) const
{
if (is_builtin()) {
return true;
}
return m_ptr->is_c_contiguous(arrmeta);
}
bool is_indexable() const { return !is_builtin() && m_ptr->is_indexable(); }
bool is_scalar() const { return is_builtin() || m_ptr->is_scalar(); }
bool is_expression() const
{
if (is_builtin()) {
return false;
}
else {
return m_ptr->is_expression();
}
}
bool is_symbolic() const { return !is_builtin() && m_ptr->is_symbolic(); }
bool is_variadic() const { return !is_builtin() && (m_ptr->get_flags() & type_flag_variadic); }
type with_replaced_scalar_types(const type &scalar_type) const;
type with_replaced_dtype(const type &replacement_tp, intptr_t replace_ndim = 0) const;
type without_memory_type() const;
type with_new_axis(intptr_t i, intptr_t new_ndim = 1) const;
type get_canonical_type() const
{
if (is_builtin()) {
return *this;
}
else {
return m_ptr->get_canonical_type();
}
}
uint32_t get_flags() const
{
if (is_builtin()) {
return type_flag_none;
}
else {
return m_ptr->get_flags();
}
}
intptr_t get_ndim() const
{
if (is_builtin()) {
return 0;
}
else {
return m_ptr->get_ndim();
}
}
intptr_t get_strided_ndim() const
{
if (is_builtin()) {
return 0;
}
else {
return m_ptr->get_strided_ndim();
}
}
type get_dtype(size_t include_ndim = 0, char **inout_arrmeta = 0) const
{
size_t ndim = get_ndim();
if (ndim == include_ndim) {
return *this;
}
else if (ndim > include_ndim) {
return m_ptr->get_type_at_dimension(inout_arrmeta, ndim - include_ndim);
}
else {
std::stringstream ss;
ss << "Cannot use " << include_ndim << " array ";
ss << "dimensions from dynd type " << *this;
ss << ", it only has " << ndim;
throw dynd::type_error(ss.str());
}
}
type get_dtype(size_t include_ndim, const char **inout_arrmeta) const
{
return get_dtype(include_ndim, const_cast<char **>(inout_arrmeta));
}
intptr_t get_dim_size(const char *arrmeta, const char *data) const;
intptr_t get_size(const char *arrmeta) const;
type get_type_at_dimension(char **inout_arrmeta, intptr_t i, intptr_t total_ndim = 0) const
{
if (!is_builtin()) {
return m_ptr->get_type_at_dimension(inout_arrmeta, i, total_ndim);
}
else if (i == 0) {
return *this;
}
else {
throw too_many_indices(*this, total_ndim + i, total_ndim);
}
}
void get_vars(std::unordered_set<std::string> &vars) const
{
if (!is_builtin()) {
m_ptr->get_vars(vars);
}
}
std::unordered_set<std::string> get_vars() const
{
std::unordered_set<std::string> vars;
get_vars(vars);
return vars;
}
std::map<std::string, std::pair<ndt::type, const char *>> get_properties() const;
const base_type *extended() const { return m_ptr; }
template <class T>
const T *extended() const
{
return static_cast<const T *>(m_ptr);
}
bool get_as_strided(const char *arrmeta, intptr_t *out_dim_size, intptr_t *out_stride, ndt::type *out_el_tp,
const char **out_el_arrmeta) const;
bool get_as_strided(const char *arrmeta, intptr_t ndim, const size_stride_t **out_size_stride, ndt::type *out_el_tp,
const char **out_el_arrmeta) const;
size_t get_iterdata_size(intptr_t ndim) const
{
if (is_builtin()) {
return 0;
}
else {
return m_ptr->get_iterdata_size(ndim);
}
}
void iterdata_construct(iterdata_common *iterdata, const char **inout_arrmeta, intptr_t ndim, const intptr_t *shape,
type &out_uniform_type) const
{
if (!is_builtin()) {
m_ptr->iterdata_construct(iterdata, inout_arrmeta, ndim, shape, out_uniform_type);
}
}
void iterdata_destruct(iterdata_common *iterdata, intptr_t ndim) const
{
if (!is_builtin()) {
m_ptr->iterdata_destruct(iterdata, ndim);
}
}
size_t get_broadcasted_iterdata_size(intptr_t ndim) const
{
if (is_builtin()) {
return sizeof(iterdata_broadcasting_terminator);
}
else {
return m_ptr->get_iterdata_size(ndim) + sizeof(iterdata_broadcasting_terminator);
}
}
void broadcasted_iterdata_construct(iterdata_common *iterdata, const char **inout_arrmeta, intptr_t ndim,
const intptr_t *shape, type &out_uniform_tp) const
{
size_t size;
if (is_builtin()) {
size = 0;
}
else {
size = m_ptr->iterdata_construct(iterdata, inout_arrmeta, ndim, shape, out_uniform_tp);
}
iterdata_broadcasting_terminator *id =
reinterpret_cast<iterdata_broadcasting_terminator *>(reinterpret_cast<char *>(iterdata) + size);
id->common.incr = &iterdata_broadcasting_terminator_incr;
id->common.adv = &iterdata_broadcasting_terminator_adv;
id->common.reset = &iterdata_broadcasting_terminator_reset;
}
void print_data(std::ostream &o, const char *arrmeta, const char *data) const;
std::string str() const
{
std::stringstream ss;
ss << *this;
return ss.str();
}
static type make(type_id_t tp_id, const nd::array &args);
friend __declspec(dllimport) std::ostream &operator<<(std::ostream &o, const type &rhs);
};
template <>
struct traits<void> {
static const size_t ndim = 0;
static const bool is_same_layout = false;
static type equivalent() { return type(type_id_of<void>::value); }
};
namespace detail {
template <typename T, typename... ArgTypes>
auto _make_type(int, ArgTypes &&... args) -> decltype(traits<T>::equivalent(std::forward<ArgTypes>(args)...))
{
return traits<T>::equivalent(std::forward<ArgTypes>(args)...);
}
template <typename T, typename... ArgTypes>
auto _make_type(char, ArgTypes &&... ) -> decltype(traits<T>::equivalent())
{
return traits<T>::equivalent();
}
}
template <typename T, typename... ArgTypes>
auto make_type(ArgTypes &&... args) -> decltype(detail::_make_type<T>(0, std::forward<ArgTypes>(args)...))
{
return detail::_make_type<T>(0, std::forward<ArgTypes>(args)...);
}
template <typename ValueType>
type type_for(const ValueType &value)
{
return make_type<ValueType>(value);
}
template <typename ValueType>
type type_for(const std::initializer_list<ValueType> &values)
{
return make_type<std::initializer_list<ValueType>>(values);
}
template <typename ValueType>
type type_for(const std::initializer_list<std::initializer_list<ValueType>> &values)
{
return make_type<std::initializer_list<std::initializer_list<ValueType>>>(values);
}
template <typename ValueType>
type type_for(const std::initializer_list<std::initializer_list<std::initializer_list<ValueType>>> &values)
{
return make_type<std::initializer_list<std::initializer_list<std::initializer_list<ValueType>>>>(values);
}
template <typename T, typename... ArgTypes>
std::enable_if_t<std::is_base_of<base_type, T>::value, type> make_type(ArgTypes &&... args)
{
return type(new T(std::forward<ArgTypes>(args)...), false);
}
template <>
struct traits<bool1> {
static const size_t ndim = 0;
static const bool is_same_layout = true;
static type equivalent() { return type(type_id_of<bool1>::value); }
};
template <>
struct traits<bool> {
static const size_t ndim = 0;
static const bool is_same_layout = false;
static type equivalent() { return traits<bool1>::equivalent(); }
};
template <>
struct traits<signed char> {
static const size_t ndim = 0;
static const bool is_same_layout = true;
static type equivalent() { return type(type_id_of<signed char>::value); }
static signed char na() { return std::numeric_limits<signed char>::min(); }
};
template <>
struct traits<short> {
static const size_t ndim = 0;
static const bool is_same_layout = true;
static type equivalent() { return type(type_id_of<short>::value); }
};
template <>
struct traits<int> {
static const size_t ndim = 0;
static const bool is_same_layout = true;
static type equivalent() { return type(type_id_of<int>::value); }
static int na() { return std::numeric_limits<int>::min(); }
};
template <>
struct traits<long> {
static const size_t ndim = 0;
static const bool is_same_layout = true;
static type equivalent() { return type(type_id_of<long>::value); }
};
template <>
struct traits<long long> {
static const size_t ndim = 0;
static const bool is_same_layout = true;
static type equivalent() { return type(type_id_of<long long>::value); }
};
template <>
struct traits<int128> {
static const size_t ndim = 0;
static const bool is_same_layout = true;
static type equivalent() { return type(type_id_of<int128>::value); }
};
template <>
struct traits<unsigned char> {
static const size_t ndim = 0;
static const bool is_same_layout = true;
static type equivalent() { return type(type_id_of<unsigned char>::value); }
};
template <>
struct traits<unsigned short> {
static const size_t ndim = 0;
static const bool is_same_layout = true;
static type equivalent() { return type(type_id_of<unsigned short>::value); }
};
template <>
struct traits<unsigned int> {
static const size_t ndim = 0;
static const bool is_same_layout = true;
static type equivalent() { return type(type_id_of<unsigned int>::value); }
static unsigned int na() { return std::numeric_limits<unsigned int>::max(); }
};
template <>
struct traits<unsigned long> {
static const size_t ndim = 0;
static const bool is_same_layout = true;
static type equivalent() { return type(type_id_of<unsigned long>::value); }
};
template <>
struct traits<unsigned long long> {
static const size_t ndim = 0;
static const bool is_same_layout = true;
static type equivalent() { return type(type_id_of<unsigned long long>::value); }
};
template <>
struct traits<uint128> {
static const size_t ndim = 0;
static const bool is_same_layout = true;
static type equivalent() { return type(type_id_of<uint128>::value); }
};
template <>
struct traits<char> {
static const size_t ndim = 0;
static const bool is_same_layout = true;
static type equivalent() { return type(type_id_of<char>::value); }
};
template <>
struct traits<float16> {
static const size_t ndim = 0;
static const bool is_same_layout = true;
static type equivalent() { return type(type_id_of<float16>::value); }
};
template <>
struct traits<float> {
static const size_t ndim = 0;
static const bool is_same_layout = true;
static type equivalent() { return type(type_id_of<float>::value); }
};
template <>
struct traits<double> {
static const size_t ndim = 0;
static const bool is_same_layout = true;
static type equivalent() { return type(type_id_of<double>::value); }
};
template <>
struct traits<float128> {
static const size_t ndim = 0;
static const bool is_same_layout = true;
static type equivalent() { return type(type_id_of<float128>::value); }
};
template <typename T>
struct traits<complex<T>> {
static const size_t ndim = 0;
static const bool is_same_layout = true;
static type equivalent() { return type(type_id_of<complex<T>>::value); }
};
template <typename T>
struct traits<std::complex<T>> {
static const size_t ndim = 0;
static const bool is_same_layout = true;
static type equivalent() { return type(type_id_of<std::complex<T>>::value); }
};
template <>
struct traits<const char *> {
static const size_t ndim = 0;
static const bool is_same_layout = false;
static type equivalent() { return type(string_id); }
};
template <size_t N>
struct traits<char[N]> {
static const size_t ndim = 0;
static const bool is_same_layout = false;
static type equivalent() { return type(string_id); }
};
template <size_t N>
struct traits<const char[N]> {
static const size_t ndim = 0;
static const bool is_same_layout = false;
static type equivalent() { return type(string_id); }
};
template <>
struct traits<type> {
static const size_t ndim = 0;
static const bool is_same_layout = true;
static type equivalent() { return type(type_id); }
};
template <typename T>
struct traits<const T> {
static const size_t ndim = traits<T>::ndim;
static const bool is_same_layout = traits<T>::is_same_layout;
static type equivalent() { return traits<T>::equivalent(); }
};
template <typename T>
struct traits<T &> {
static const size_t ndim = traits<T>::ndim;
static const bool is_same_layout = traits<T>::is_same_layout;
static type equivalent() { return traits<T>::equivalent(); }
};
template <typename T>
struct traits<T &&> {
static const size_t ndim = traits<T>::ndim;
static const bool is_same_layout = traits<T>::is_same_layout;
static type equivalent() { return traits<T>::equivalent(); }
};
template <typename T, size_t N>
struct traits<T[N]> {
static const size_t ndim = traits<T>::ndim + 1;
static const bool is_same_layout = traits<T>::is_same_layout;
static type equivalent() { return make_fixed_dim(N, make_type<T>()); }
};
template <>
struct traits<assign_error_mode> {
static const size_t ndim = 0;
static const bool is_same_layout = true;
static type equivalent() { return make_type<typename std::underlying_type<assign_error_mode>::type>(); }
static assign_error_mode na()
{
return static_cast<assign_error_mode>(traits<typename std::underlying_type<assign_error_mode>::type>::na());
}
};
template <typename T, size_t N>
struct traits<const T[N]> {
static const size_t ndim = traits<T[N]>::ndim;
static const bool is_same_layout = traits<T[N]>::is_same_layout;
static type equivalent() { return make_type<T[N]>(); }
};
template <typename ContainerType, size_t NDim>
struct container_traits {
static const size_t ndim = NDim;
static const bool is_same_layout = false;
static type equivalent(const ContainerType &values)
{
intptr_t shape[ndim];
container_traits::shape(shape, values);
type tp = value_type();
for (intptr_t i = ndim - 1; i >= 0; --i) {
if (shape[i] == -1) {
tp = make_var_dim(tp);
}
else {
tp = make_fixed_dim(shape[i], tp);
}
}
return tp;
}
static void shape(intptr_t *res, const ContainerType &values)
{
res[0] = values.size();
auto iter = values.begin();
ndt::traits<typename ContainerType::value_type>::shape(res + 1, *iter);
while (++iter != values.end()) {
intptr_t next_shape[ndim - 1];
ndt::traits<typename ContainerType::value_type>::shape(next_shape, *iter);
for (size_t i = 1; i < ndim; ++i) {
if (res[i] != next_shape[i - 1]) {
res[i] = -1;
}
}
}
}
static type value_type() { return container_traits<typename ContainerType::value_type, ndim - 1>::value_type(); }
};
template <typename ContainerType>
struct container_traits<ContainerType, 1> {
static const size_t ndim = 1;
static const bool is_same_layout = false;
static type equivalent(const ContainerType &values)
{
intptr_t size;
shape(&size, values);
return make_fixed_dim(size, value_type());
}
static void shape(intptr_t *res, const ContainerType &values) { res[0] = values.size(); }
static type value_type() { return traits<typename ContainerType::value_type>::equivalent(); }
};
template <typename ValueType>
struct traits<std::initializer_list<ValueType>>
: container_traits<std::initializer_list<ValueType>, traits<ValueType>::ndim + 1> {
};
template <typename ValueType>
struct traits<std::vector<ValueType>> : container_traits<std::vector<ValueType>, traits<ValueType>::ndim + 1> {
};
__declspec(dllimport) extern class common_type {
typedef type (*child_type)(const type &, const type &);
struct init;
static std::map<std::array<type_id_t, 2>, child_type> children;
public:
common_type();
__declspec(dllimport) ndt::type operator()(const ndt::type &tp0, const ndt::type &tp1) const;
} common_type;
__declspec(dllimport) type make_type(intptr_t ndim, const intptr_t *shape, const ndt::type &dtype);
template <int N>
inline type make_type(intptr_t ndim, const intptr_t *shape, const char(&dtype)[N])
{
return make_type(ndim, shape, ndt::type(dtype));
}
__declspec(dllimport) type make_type(intptr_t ndim, const intptr_t *shape, const ndt::type &dtype, bool &out_any_var);
__declspec(dllimport) std::ostream &operator<<(std::ostream &o, const type &rhs);
struct reg_info_t {
type tp;
};
namespace detail {
__declspec(dllimport) std::map<type_id_t, reg_info_t> &infos();
}
__declspec(dllimport) void reg(type_id_t id, const ndt::type &tp);
}
__declspec(dllimport) void hexadecimal_print(std::ostream &o, char value);
__declspec(dllimport) void hexadecimal_print(std::ostream &o, unsigned char value);
__declspec(dllimport) void hexadecimal_print(std::ostream &o, unsigned short value);
__declspec(dllimport) void hexadecimal_print(std::ostream &o, unsigned int value);
__declspec(dllimport) void hexadecimal_print(std::ostream &o, unsigned long value);
__declspec(dllimport) void hexadecimal_print(std::ostream &o, unsigned long long value);
__declspec(dllimport) void hexadecimal_print(std::ostream &o, const char *data, intptr_t element_size);
__declspec(dllimport) void hexadecimal_print_summarized(std::ostream &o, const char *data, intptr_t element_size,
intptr_t summary_size);
__declspec(dllimport) void strided_array_summarized(std::ostream &o, const ndt::type &tp, const char *arrmeta, const char *data,
intptr_t dim_size, intptr_t stride);
__declspec(dllimport) void print_indented(std::ostream &o, const std::string &indent, const std::string &s,
bool skipfirstline = false);
__declspec(dllimport) bool is_lossless_assignment(const ndt::type &dst_tp, const ndt::type &src_tp);
}
namespace dynd {
class __declspec(dllimport) string : public bytes {
public:
string() {}
string(const char *data, size_t size) : bytes(data, size) {}
string(const std::string &other) : string(other.data(), other.size()) {}
bool operator<(const string &rhs) const
{
return std::lexicographical_compare(begin(), end(), rhs.begin(), rhs.end());
}
bool operator<=(const string &rhs) const
{
return !std::lexicographical_compare(rhs.begin(), rhs.end(), begin(), end());
}
bool operator>=(const string &rhs) const
{
return !std::lexicographical_compare(begin(), end(), rhs.begin(), rhs.end());
}
bool operator>(const string &rhs) const
{
return std::lexicographical_compare(rhs.begin(), rhs.end(), begin(), end());
}
const string operator+(const string &rhs)
{
string result;
result.resize(size() + rhs.size());
std::memcpy(result.begin(), begin(), size());
std::memcpy(result.begin() + size(), rhs.begin(), rhs.size());
return result;
}
};
namespace ndt {
class __declspec(dllimport) string_type : public base_string_type {
private:
const string_encoding_t m_encoding{string_encoding_utf_8};
const std::string m_encoding_repr{encoding_as_string(string_encoding_utf_8)};
public:
typedef string data_type;
string_type();
string_encoding_t get_encoding() const { return m_encoding; }
size_t get_target_alignment() const { return string_encoding_char_size_table[string_encoding_utf_8]; }
void get_string_range(const char **out_begin, const char **out_end, const char *arrmeta, const char *data) const;
void set_from_utf8_string(const char *arrmeta, char *dst, const char *utf8_begin, const char *utf8_end,
const eval::eval_context *ectx) const;
void print_data(std::ostream &o, const char *arrmeta, const char *data) const;
void print_type(std::ostream &o) const;
bool is_unique_data_owner(const char *arrmeta) const;
type get_canonical_type() const;
void get_shape(intptr_t ndim, intptr_t i, intptr_t *out_shape, const char *arrmeta, const char *data) const;
std::map<std::string, std::pair<ndt::type, const char *>> get_dynamic_type_properties() const;
bool is_lossless_assignment(const type &dst_tp, const type &src_tp) const;
bool operator==(const base_type &rhs) const;
void data_destruct(const char *arrmeta, char *data) const;
void data_destruct_strided(const char *arrmeta, char *data, intptr_t stride, size_t count) const;
};
template <>
struct traits<string> {
static const size_t ndim = 0;
static const bool is_same_layout = true;
static type equivalent() { return type(string_id); }
static string na() { return string(); }
};
template <>
struct traits<std::string> {
static const size_t ndim = 0;
static const bool is_same_layout = false;
static type equivalent() { return make_type<string>(); }
};
}
}
namespace dynd {
namespace ndt {
class __declspec(dllimport) base_dim_type : public base_type {
protected:
type m_element_tp;
size_t m_element_arrmeta_offset;
public:
base_dim_type(type_id_t tp_id, const type &element_tp, size_t data_size, size_t data_alignment,
size_t element_arrmeta_offset, uint32_t flags, bool strided);
const type &get_element_type() const { return m_element_tp; }
void get_element_types(std::size_t ndim, const type **element_tp) const;
std::vector<const type *> get_element_types(std::size_t ndim) const
{
std::vector<const type *> element_tp(ndim);
get_element_types(ndim, element_tp.data());
return element_tp;
}
bool is_type_subarray(const type &subarray_tp) const
{
intptr_t this_ndim = get_ndim(), stp_ndim = subarray_tp.get_ndim();
if (this_ndim > stp_ndim) {
return get_element_type().is_type_subarray(subarray_tp);
}
else if (this_ndim == stp_ndim) {
return (*this) == (*subarray_tp.extended());
}
else {
return false;
}
}
size_t get_element_arrmeta_offset() const { return m_element_arrmeta_offset; }
virtual intptr_t get_dim_size(const char *arrmeta = 0, const char *data = 0) const = 0;
intptr_t get_size(const char *arrmeta) const
{
std::intptr_t dim_size = get_dim_size(arrmeta, 0);
if (dim_size == -1) {
return -1;
}
return dim_size * m_element_tp.get_size(0);
}
virtual void get_vars(std::unordered_set<std::string> &vars) const { m_element_tp.get_vars(vars); }
virtual size_t arrmeta_copy_construct_onedim(char *dst_arrmeta, const char *src_arrmeta,
const intrusive_ptr<memory_block_data> &embedded_reference) const = 0;
virtual bool match(const type &candidate_tp, std::map<std::string, type> &tp_vars) const;
virtual type with_element_type(const type &element_tp) const = 0;
};
}
}
namespace dynd {
namespace ndt {
class __declspec(dllimport) var_dim_type : public base_dim_type {
public:
struct metadata_type {
intrusive_ptr<memory_block_data> blockref;
intptr_t stride;
intptr_t offset;
};
struct data_type {
char *begin;
size_t size;
};
var_dim_type(const type &element_tp);
size_t get_default_data_size() const { return sizeof(data_type); }
size_t get_target_alignment() const { return m_element_tp.get_data_alignment(); }
void print_data(std::ostream &o, const char *arrmeta, const char *data) const;
void print_type(std::ostream &o) const;
bool is_expression() const;
bool is_unique_data_owner(const char *arrmeta) const;
void transform_child_types(type_transform_fn_t transform_fn, intptr_t arrmeta_offset, void *extra,
type &out_transformed_tp, bool &out_was_transformed) const;
type get_canonical_type() const;
type apply_linear_index(intptr_t nindices, const irange *indices, size_t current_i, const type &root_tp,
bool leading_dimension) const;
intptr_t apply_linear_index(intptr_t nindices, const irange *indices, const char *arrmeta, const type &result_tp,
char *out_arrmeta, const intrusive_ptr<memory_block_data> &embedded_reference,
size_t current_i, const type &root_tp, bool leading_dimension, char **inout_data,
intrusive_ptr<memory_block_data> &inout_dataref) const;
type at_single(intptr_t i0, const char **inout_arrmeta, const char **inout_data) const;
type get_type_at_dimension(char **inout_arrmeta, intptr_t i, intptr_t total_ndim = 0) const;
intptr_t get_dim_size(const char *arrmeta, const char *data) const;
void get_shape(intptr_t ndim, intptr_t i, intptr_t *out_shape, const char *arrmeta, const char *data) const;
void get_strides(size_t i, intptr_t *out_strides, const char *arrmeta) const;
axis_order_classification_t classify_axis_order(const char *arrmeta) const;
bool is_lossless_assignment(const type &dst_tp, const type &src_tp) const;
bool operator==(const base_type &rhs) const;
void arrmeta_default_construct(char *arrmeta, bool blockref_alloc) const;
void arrmeta_copy_construct(char *dst_arrmeta, const char *src_arrmeta,
const intrusive_ptr<memory_block_data> &embedded_reference) const;
void arrmeta_reset_buffers(char *arrmeta) const;
void arrmeta_finalize_buffers(char *arrmeta) const;
void arrmeta_destruct(char *arrmeta) const;
void arrmeta_debug_print(const char *arrmeta, std::ostream &o, const std::string &indent) const;
size_t arrmeta_copy_construct_onedim(char *dst_arrmeta, const char *src_arrmeta,
const intrusive_ptr<memory_block_data> &embedded_reference) const;
void data_destruct(const char *arrmeta, char *data) const;
void data_destruct_strided(const char *arrmeta, char *data, intptr_t stride, size_t count) const;
size_t get_iterdata_size(intptr_t ndim) const;
size_t iterdata_construct(iterdata_common *iterdata, const char **inout_arrmeta, intptr_t ndim,
const intptr_t *shape, type &out_uniform_tp) const;
size_t iterdata_destruct(iterdata_common *iterdata, intptr_t ndim) const;
void foreach_leading(const char *arrmeta, char *data, foreach_fn_t callback, void *callback_data) const;
std::map<std::string, std::pair<ndt::type, const char *>> get_dynamic_type_properties() const;
virtual type with_element_type(const type &element_tp) const;
static type make(const type &element_tp) { return type(new var_dim_type(element_tp), false); }
static type make(const type &element_tp, intptr_t ndim)
{
type result = element_tp;
for (intptr_t i = 0; i < ndim; ++i) {
result = make(result);
}
return result;
}
};
inline type make_var_dim(const type &element_tp) { return var_dim_type::make(element_tp); }
}
}
namespace dynd {
namespace nd {
template <typename ValueType>
struct init {
init(const ndt::type &, const char *) {}
void single(char *data, const ValueType &value) const { *reinterpret_cast<ValueType *>(data) = value; }
void contiguous(char *data, const ValueType *values, size_t size) const
{
for (size_t i = 0; i < size; ++i) {
single(data, values[i]);
data += sizeof(ValueType);
}
}
};
template <>
struct init<bool> {
init(const ndt::type &, const char *) {}
void single(char *data, bool value) const { *reinterpret_cast<bool1 *>(data) = value; }
void contiguous(char *data, const bool *values, size_t size) const
{
for (size_t i = 0; i < size; ++i) {
single(data, values[i]);
data += sizeof(bool1);
}
}
};
template <>
struct init<bytes> {
init(const ndt::type &, const char *) {}
void single(char *data, const bytes &value) const
{
reinterpret_cast<bytes *>(data)->assign(value.data(), value.size());
}
void contiguous(char *data, const bytes *values, size_t size) const
{
for (size_t i = 0; i < size; ++i) {
single(data, values[i]);
data += sizeof(bytes);
}
}
};
template <>
struct init<std::string> {
init(const ndt::type &, const char *) {}
void single(char *data, const std::string &value) const
{
reinterpret_cast<string *>(data)->assign(value.data(), value.size());
}
void contiguous(char *data, const std::string *values, size_t size) const
{
for (size_t i = 0; i < size; ++i) {
single(data, values[i]);
data += sizeof(string);
}
}
};
template <>
struct init<const char *> {
init(const ndt::type &, const char *) {}
void single(char *data, const char *value) const { reinterpret_cast<string *>(data)->assign(value, strlen(value)); }
void contiguous(char *data, const char *const *values, size_t size) const
{
for (size_t i = 0; i < size; ++i) {
single(data, values[i]);
data += sizeof(string);
}
}
};
template <size_t N>
struct init<char[N]> {
init(const ndt::type &, const char *) {}
void single(char *data, const char *value) const { reinterpret_cast<string *>(data)->assign(value, N - 1); }
void contiguous(char *data, const char *const *values, size_t size) const
{
for (size_t i = 0; i < size; ++i) {
single(data, values[i]);
data += sizeof(string);
}
}
};
template <size_t N>
struct init<const char[N]> {
init(const ndt::type &, const char *) {}
void single(char *data, const char *value) const { reinterpret_cast<string *>(data)->assign(value, N - 1); }
void contiguous(char *data, const char *const *values, size_t size) const
{
for (size_t i = 0; i < size; ++i) {
single(data, values[i]);
data += sizeof(string);
}
}
};
template <typename ContainerType, size_t Rank>
struct container_init {
typedef void (*closure_type)(const container_init *, char *, const ContainerType &);
typedef typename ContainerType::value_type value_type;
intptr_t stride;
closure_type closure;
init<value_type> child;
container_init(const ndt::type &tp, const char *metadata)
: child(tp.extended<ndt::base_dim_type>()->get_element_type(),
metadata + tp.extended<ndt::base_dim_type>()->get_element_arrmeta_offset())
{
switch (tp.get_id()) {
case fixed_dim_id:
stride = reinterpret_cast<const size_stride_t *>(metadata)->stride;
closure = [](const container_init *self, char *data, const ContainerType &values) {
for (const value_type &value : values) {
self->child.single(data, value);
data += self->stride;
}
};
break;
default:
throw std::runtime_error("unsupported");
}
}
void single(char *data, const ContainerType &values) const { closure(this, data, values); }
};
template <typename ValueType>
struct container_init<std::initializer_list<ValueType>, 1> {
typedef void (*closure_type)(const container_init *, char *, const std::initializer_list<ValueType> &);
typedef ValueType value_type;
intrusive_ptr<memory_block_data> memblock;
closure_type closure;
init<value_type> child;
container_init(const ndt::type &tp, const char *metadata)
: child(tp.extended<ndt::base_dim_type>()->get_element_type(), metadata + sizeof(size_stride_t))
{
switch (tp.get_id()) {
case fixed_dim_id:
closure = [](const container_init *self, char *data, const std::initializer_list<ValueType> &values) {
self->child.contiguous(data, values.begin(), values.size());
};
break;
case var_dim_id:
memblock = reinterpret_cast<const ndt::var_dim_type::metadata_type *>(metadata)->blockref;
closure = [](const container_init *self, char *data, const std::initializer_list<ValueType> &values) {
reinterpret_cast<ndt::var_dim_type::data_type *>(data)->begin = self->memblock->alloc(values.size());
reinterpret_cast<ndt::var_dim_type::data_type *>(data)->size = values.size();
self->child.contiguous(reinterpret_cast<ndt::var_dim_type::data_type *>(data)->begin, values.begin(),
values.size());
};
break;
default:
throw std::runtime_error("unexpected type id");
}
}
void single(char *data, const std::initializer_list<ValueType> &values) const { closure(this, data, values); }
};
template <typename ContainerType>
struct container_init<ContainerType, 1> {
typedef typename ContainerType::value_type value_type;
void (*func)(const container_init *, char *, const ContainerType &);
init<value_type> child;
container_init(const ndt::type &tp, const char *metadata)
: child(tp.extended<ndt::base_dim_type>()->get_element_type(), metadata + sizeof(size_stride_t))
{
}
void single(char *data, const ContainerType &values) const { child.contiguous(data, values.data(), values.size()); }
};
template <typename T>
struct init<std::initializer_list<T>> : container_init<std::initializer_list<T>, ndt::traits<T>::ndim + 1> {
using container_init<std::initializer_list<T>, ndt::traits<T>::ndim + 1>::container_init;
};
template <typename T>
struct init<std::vector<T>> : container_init<std::vector<T>, ndt::traits<T>::ndim + 1> {
using container_init<std::vector<T>, ndt::traits<T>::ndim + 1>::container_init;
};
}
}
namespace dynd {
namespace ndt {
class __declspec(dllimport) base_memory_type : public base_type {
protected:
type m_element_tp;
size_t m_storage_arrmeta_offset;
public:
base_memory_type(type_id_t type_id, const type &element_tp, size_t data_size, size_t alignment,
size_t storage_arrmeta_offset, uint32_t flags);
const type &get_element_type() const { return m_element_tp; }
virtual size_t get_default_data_size() const;
virtual void get_vars(std::unordered_set<std::string> &vars) const;
virtual void print_data(std::ostream &o, const char *arrmeta, const char *data) const;
void get_shape(intptr_t ndim, intptr_t i, intptr_t *out_shape, const char *arrmeta, const char *data) const;
void get_strides(size_t i, intptr_t *out_strides, const char *arrmeta) const;
type apply_linear_index(intptr_t nindices, const irange *indices, size_t current_i, const type &root_tp,
bool leading_dimension) const;
intptr_t apply_linear_index(intptr_t nindices, const irange *indices, const char *arrmeta, const type &result_type,
char *out_arrmeta, const intrusive_ptr<memory_block_data> &embedded_reference,
size_t current_i, const type &root_tp, bool leading_dimension, char **inout_data,
intrusive_ptr<memory_block_data> &inout_dataref) const;
type at_single(intptr_t i0, const char **inout_arrmeta, const char **inout_data) const;
type get_type_at_dimension(char **inout_arrmeta, intptr_t i, intptr_t total_ndim = 0) const;
virtual bool is_lossless_assignment(const type &dst_tp, const type &src_tp) const;
virtual bool operator==(const base_type &rhs) const = 0;
inline bool is_type_subarray(const type &subarray_tp) const
{
return (!subarray_tp.is_builtin() && (*this) == (*subarray_tp.extended())) ||
m_element_tp.is_type_subarray(subarray_tp);
}
virtual void transform_child_types(type_transform_fn_t transform_fn, intptr_t arrmeta_offset, void *extra,
type &out_transformed_tp, bool &out_was_transformed) const;
virtual type get_canonical_type() const;
virtual type with_replaced_storage_type(const type &storage_tp) const = 0;
virtual void arrmeta_default_construct(char *arrmeta, bool blockref_alloc) const;
virtual void arrmeta_copy_construct(char *dst_arrmeta, const char *src_arrmeta,
const intrusive_ptr<memory_block_data> &embedded_reference) const;
virtual void arrmeta_destruct(char *arrmeta) const;
virtual void data_alloc(char **data, size_t size) const = 0;
virtual void data_zeroinit(char *data, size_t size) const = 0;
virtual void data_free(char *data) const = 0;
virtual bool match(const type &candidate_tp, std::map<std::string, type> &tp_vars) const;
virtual std::map<std::string, std::pair<ndt::type, const char *>> get_dynamic_type_properties() const;
};
}
}
namespace dynd {
struct __declspec(dllimport) array_preamble : memory_block_data {
ndt::type tp;
uint64_t flags;
char *data;
intrusive_ptr<memory_block_data> owner;
~array_preamble()
{
if (!tp.is_builtin()) {
char *arrmeta = reinterpret_cast<char *>(this + 1);
if (!owner) {
if (!tp->is_expression() && (tp->get_flags() & type_flag_destructor) != 0) {
tp->data_destruct(arrmeta, data);
}
if (!tp->is_expression()) {
const ndt::type &dtp = tp->get_type_at_dimension(0, tp->get_ndim());
if (dtp.get_base_id() == memory_id) {
dtp.extended<ndt::base_memory_type>()->data_free(data);
}
}
}
tp->arrmeta_destruct(arrmeta);
}
}
char *metadata() { return reinterpret_cast<char *>(this + 1); }
const char *metadata() const { return reinterpret_cast<const char *>(this + 1); }
};
__declspec(dllimport) intrusive_ptr<memory_block_data> make_array_memory_block(size_t arrmeta_size);
__declspec(dllimport) intrusive_ptr<memory_block_data> make_array_memory_block(size_t arrmeta_size, size_t extra_size,
size_t extra_alignment, char **out_extra_ptr);
__declspec(dllimport) intrusive_ptr<memory_block_data> shallow_copy_array_memory_block(const intrusive_ptr<memory_block_data> &ndo);
__declspec(dllimport) void array_memory_block_debug_print(const memory_block_data *memblock, std::ostream &o,
const std::string &indent);
inline long intrusive_ptr_use_count(array_preamble *ptr) { return ptr->m_use_count; }
inline void intrusive_ptr_retain(array_preamble *ptr) { ++ptr->m_use_count; }
inline void intrusive_ptr_release(array_preamble *ptr)
{
if (--ptr->m_use_count == 0) {
detail::memory_block_free(ptr);
}
}
}
namespace dynd {
template<class T, int staticN = 3>
class shortvector {
T *m_data;
T m_shortdata[staticN];
shortvector(const shortvector& rhs);
shortvector& operator=(const shortvector& rhs);
public:
shortvector()
: m_data(m_shortdata) {
}
void init(size_t size) {
if (m_data != m_shortdata) {
delete[] m_data;
}
if (size <= staticN) {
m_data = m_shortdata;
} else {
m_data = new T[size];
}
}
void init(size_t size, const T *data) {
init(size);
memcpy(m_data, data, size * sizeof(T));
}
explicit shortvector(size_t size)
: m_data((size <= staticN) ? m_shortdata : new T[size])
{
}
shortvector(size_t size, const shortvector& rhs)
: m_data((size <= staticN) ? m_shortdata : new T[size])
{
std::memcpy(m_data, rhs.m_data, size * sizeof(T));
}
shortvector(size_t size, const T* data)
: m_data((size <= staticN) ? m_shortdata : new T[size])
{
std::memcpy(m_data, data, size * sizeof(T));
}
shortvector(shortvector&& rhs) {
if (rhs.m_data == rhs.m_shortdata) {
std::memcpy(m_shortdata, rhs.m_shortdata, staticN * sizeof(T));
m_data = m_shortdata;
} else {
m_data = rhs.m_data;
rhs.m_data = rhs.m_shortdata;
}
}
shortvector& operator=(shortvector&& rhs) {
if (this != &rhs) {
if (m_data != m_shortdata) {
delete[] m_data;
}
if (rhs.m_data == rhs.m_shortdata) {
std::memcpy(m_shortdata, rhs.m_shortdata, staticN * sizeof(T));
m_data = m_shortdata;
} else {
m_data = rhs.m_data;
rhs.m_data = rhs.m_shortdata;
}
}
return *this;
}
~shortvector() {
if (m_data != m_shortdata) {
delete[] m_data;
}
}
void swap(shortvector& rhs) {
std::swap(m_data, rhs.m_data);
if (m_data == rhs.m_shortdata) {
m_data = m_shortdata;
if (rhs.m_data == m_shortdata) {
T tmp[staticN];
rhs.m_data = rhs.m_shortdata;
std::memcpy(tmp, m_shortdata, staticN * sizeof(T));
std::memcpy(m_shortdata, rhs.m_shortdata, staticN * sizeof(T));
std::memcpy(rhs.m_shortdata, tmp, staticN * sizeof(T));
} else {
std::memcpy(m_shortdata, rhs.m_shortdata, staticN * sizeof(T));
}
} else if (rhs.m_data == m_shortdata) {
rhs.m_data = rhs.m_shortdata;
std::memcpy(rhs.m_shortdata, m_shortdata, staticN * sizeof(T));
}
}
const T* get() const {
return m_data;
}
T* get() {
return m_data;
}
const T& operator[](size_t i) const {
return m_data[i];
}
T& operator[](size_t i) {
return m_data[i];
}
};
template<class T, int M, int staticN = 3>
class multi_shortvector {
T *m_shortvectors[M];
T m_static_data[staticN * M];
T *m_alloc_data;
void internal_init(int n) {
if (n <= staticN) {
if (n == 0) {
n = 1;
}
for (int i = 0; i < M; ++i) {
m_shortvectors[i] = &m_static_data[i*n];
}
} else {
m_alloc_data = new T[n * M];
for (int i = 0; i < M; ++i) {
m_shortvectors[i] = m_alloc_data + i*n;
}
}
}
multi_shortvector(const multi_shortvector&);
multi_shortvector& operator=(const multi_shortvector&);
public:
multi_shortvector()
: m_alloc_data(0) {
}
multi_shortvector(int n)
: m_alloc_data(0) {
internal_init(n);
}
~multi_shortvector() {
delete[] m_alloc_data;
}
void init(int n) {
if (m_alloc_data != 0) {
delete[] m_alloc_data;
}
internal_init(n);
}
T **get_all() {
return m_shortvectors;
}
const T * const*get_all() const {
return m_shortvectors;
}
T *get(int i) {
return m_shortvectors[i];
}
const T *get(int i) const {
return m_shortvectors[i];
}
T& get(int i, int j) {
return m_shortvectors[i][j];
}
const T& get(int i, int j) const {
return m_shortvectors[i][j];
}
};
typedef shortvector<intptr_t> dimvector;
}
namespace dynd {
namespace ndt {
class __declspec(dllimport) base_bytes_type : public base_type {
public:
base_bytes_type(type_id_t type_id, size_t data_size, size_t alignment, uint32_t flags, size_t arrmeta_size)
: base_type(type_id, data_size, alignment, flags, arrmeta_size, 0, 0)
{
}
virtual void get_bytes_range(const char **out_begin, const char **out_end, const char *arrmeta,
const char *data) const = 0;
size_t get_iterdata_size(intptr_t ndim) const;
};
}
}
namespace dynd {
namespace ndt {
class __declspec(dllimport) bytes_type : public base_bytes_type {
size_t m_alignment;
public:
typedef bytes data_type;
bytes_type(size_t alignment);
size_t get_target_alignment() const { return m_alignment; }
void print_data(std::ostream &o, const char *arrmeta, const char *data) const;
void print_type(std::ostream &o) const;
void get_bytes_range(const char **out_begin, const char **out_end, const char *arrmeta, const char *data) const;
void set_bytes_data(const char *arrmeta, char *data, const char *bytes_begin, const char *bytes_end) const;
bool is_unique_data_owner(const char *arrmeta) const;
type get_canonical_type() const;
void get_shape(intptr_t ndim, intptr_t i, intptr_t *out_shape, const char *arrmeta, const char *data) const;
bool is_lossless_assignment(const type &dst_tp, const type &src_tp) const;
bool operator==(const base_type &rhs) const;
void data_destruct(const char *arrmeta, char *data) const;
void data_destruct_strided(const char *arrmeta, char *data, intptr_t stride, size_t count) const;
std::map<std::string, std::pair<ndt::type, const char *>> get_dynamic_type_properties() const;
static const type &make()
{
static const type bytes_tp(new bytes_type(1), false);
return *reinterpret_cast<const type *>(&bytes_tp);
}
static type make(size_t alignment) { return type(new bytes_type(alignment), false); }
};
template <>
struct traits<bytes> {
static const size_t ndim = 0;
static const bool is_same_layout = true;
static type equivalent() { return type(bytes_id); }
static bytes na() { return bytes(); }
};
}
}
namespace dynd {
struct __declspec(dllimport) pointer_type_arrmeta {
intrusive_ptr<memory_block_data> blockref;
intptr_t offset;
};
namespace ndt {
class __declspec(dllimport) pointer_type : public base_type {
type m_target_tp;
public:
pointer_type(const type &target_tp);
const type &get_value_type() const { return m_target_tp.value_type(); }
const type &get_operand_type() const;
const type &get_target_type() const { return m_target_tp; }
void print_data(std::ostream &o, const char *arrmeta, const char *data) const;
void print_type(std::ostream &o) const;
inline bool is_type_subarray(const type &subarray_tp) const
{
return (!subarray_tp.is_builtin() && (*this) == (*subarray_tp.extended())) ||
m_target_tp.is_type_subarray(subarray_tp);
}
bool is_unique_data_owner(const char *arrmeta) const;
void transform_child_types(type_transform_fn_t transform_fn, intptr_t arrmeta_offset, void *extra,
type &out_transformed_tp, bool &out_was_transformed) const;
type get_canonical_type() const;
type apply_linear_index(intptr_t nindices, const irange *indices, size_t current_i, const type &root_tp,
bool leading_dimension) const;
intptr_t apply_linear_index(intptr_t nindices, const irange *indices, const char *arrmeta, const type &result_tp,
char *out_arrmeta, const intrusive_ptr<memory_block_data> &embedded_reference,
size_t current_i, const type &root_tp, bool leading_dimension, char **inout_data,
intrusive_ptr<memory_block_data> &inout_dataref) const;
type at_single(intptr_t i0, const char **inout_arrmeta, const char **inout_data) const;
type get_type_at_dimension(char **inout_arrmeta, intptr_t i, intptr_t total_ndim = 0) const;
void get_shape(intptr_t ndim, intptr_t i, intptr_t *out_shape, const char *arrmeta, const char *data) const;
axis_order_classification_t classify_axis_order(const char *arrmeta) const;
bool is_lossless_assignment(const type &dst_tp, const type &src_tp) const;
bool operator==(const base_type &rhs) const;
type with_replaced_storage_type(const type &replacement_type) const;
void arrmeta_default_construct(char *arrmeta, bool blockref_alloc) const;
void arrmeta_copy_construct(char *dst_arrmeta, const char *src_arrmeta,
const intrusive_ptr<memory_block_data> &embedded_reference) const;
void arrmeta_reset_buffers(char *arrmeta) const;
void arrmeta_finalize_buffers(char *arrmeta) const;
void arrmeta_destruct(char *arrmeta) const;
void arrmeta_debug_print(const char *arrmeta, std::ostream &o, const std::string &indent) const;
bool match(const type &candidate_tp, std::map<std::string, type> &tp_vars) const;
std::map<std::string, std::pair<ndt::type, const char *>> get_dynamic_type_properties() const;
static type make(const type &target_tp);
};
template <typename T>
struct traits<T *> {
static const size_t ndim = 0;
static const bool is_same_layout = true;
static type equivalent() { return pointer_type::make(make_type<T>()); }
};
inline type make_pointer_type(const type &target_tp) { return pointer_type::make(target_tp); }
}
}
namespace dynd {
namespace ndt {
class __declspec(dllimport) type_type : public base_type {
type m_pattern_tp;
public:
typedef type data_type;
type_type();
type_type(const type &pattern_tp);
const type &get_pattern_type() const { return m_pattern_tp; }
void print_data(std::ostream &o, const char *arrmeta, const char *data) const;
void print_type(std::ostream &o) const;
bool operator==(const base_type &rhs) const;
void arrmeta_default_construct(char *arrmeta, bool blockref_alloc) const;
void arrmeta_copy_construct(char *dst_arrmeta, const char *src_arrmeta,
const intrusive_ptr<memory_block_data> &embedded_reference) const;
void arrmeta_reset_buffers(char *arrmeta) const;
void arrmeta_finalize_buffers(char *arrmeta) const;
void arrmeta_destruct(char *arrmeta) const;
void arrmeta_debug_print(const char *, std::ostream &,
const std::string &) const
{
}
void data_destruct(const char *arrmeta, char *data) const;
void data_destruct_strided(const char *arrmeta, char *data, intptr_t stride, size_t count) const;
};
}
}
namespace dynd {
namespace ndt {
__declspec(dllimport) type make_fixed_dim(size_t dim_size, const type &element_tp);
}
namespace nd {
class callable;
__declspec(dllexport) callable &reg(const std::string &name);
class __declspec(dllexport) array;
__declspec(dllexport) array empty(const ndt::type &tp);
enum array_access_flags {
read_access_flag = 0x01,
write_access_flag = 0x02,
immutable_access_flag = 0x04
};
enum {
readwrite_access_flags = read_access_flag | write_access_flag,
default_access_flags = read_access_flag | write_access_flag,
};
__declspec(dllexport) std::ostream &operator<<(std::ostream &o, const array &rhs);
class array_vals;
class array_vals_at;
namespace detail {
template <typename CArrayType, bool IsTriviallyCopyable>
struct init_from_c_array;
template <typename ValueType, size_t Size>
struct init_from_c_array<ValueType[Size], true> {
nd::init<ValueType> child;
intptr_t stride;
init_from_c_array(const ndt::type &tp, const char *metadata)
: child(tp.extended<ndt::base_dim_type>()->get_element_type(), metadata + sizeof(size_stride_t)),
stride(reinterpret_cast<const size_stride_t *>(metadata)->stride)
{
}
void single(char *data, const ValueType (&values)[Size]) const
{
for (const ValueType &value : values) {
child.single(data, value);
data += stride;
}
}
};
template <typename ValueType, size_t Size>
struct init_from_c_array<ValueType[Size], false> {
nd::init<ValueType> child;
intptr_t stride;
init_from_c_array(const ndt::type &tp, const char *metadata)
: child(tp.extended<ndt::base_dim_type>()->get_element_type(), metadata + sizeof(size_stride_t)),
stride(reinterpret_cast<const size_stride_t *>(metadata)->stride)
{
}
void single(char *data, const ValueType (&values)[Size]) const
{
for (const ValueType &value : values) {
child.single(data, value);
data += stride;
}
}
};
}
template <typename ValueType, size_t Size>
struct init<ValueType[Size]>
: detail::init_from_c_array<ValueType[Size],
std::is_pod<ValueType>::value && ndt::traits<ValueType>::is_same_layout> {
using detail::init_from_c_array<ValueType[Size], std::is_pod<ValueType>::value &&
ndt::traits<ValueType>::is_same_layout>::init_from_c_array;
};
template <typename ValueType>
struct as {
void single(ValueType &value, char *data) const { value = *reinterpret_cast<ValueType *>(data); }
};
template <>
struct as<std::string> {
void single(std::string &value, char *data) const
{
value.assign(reinterpret_cast<string *>(data)->data(), reinterpret_cast<string *>(data)->size());
}
};
class __declspec(dllexport) array : public intrusive_ptr<array_preamble> {
template <typename T>
void init(T &&value)
{
nd::init<typename remove_reference_then_cv<T>::type> init(get()->tp, get()->metadata());
init.single(get()->data, std::forward<T>(value));
get()->flags =
(get()->tp.get_ndim() == 0) ? (nd::read_access_flag | nd::immutable_access_flag) : nd::readwrite_access_flags;
}
template <typename ValueType>
void init(const ValueType *values, size_t size)
{
nd::init<ValueType> init(get()->tp, get()->metadata());
init.contiguous(get()->data, values, size);
get()->flags =
(get()->tp.get_ndim() == 0) ? (nd::read_access_flag | nd::immutable_access_flag) : nd::readwrite_access_flags;
}
public:
using intrusive_ptr<array_preamble>::intrusive_ptr;
array() = default;
template <typename T,
typename = std::enable_if_t<ndt::has_traits<typename remove_reference_then_cv<T>::type>::value>>
array(T &&value) : intrusive_ptr<array_preamble>(empty(ndt::type_for(value)))
{
init(std::forward<T>(value));
}
template <typename ValueType>
array(const std::initializer_list<ValueType> &values) : intrusive_ptr<array_preamble>(empty(ndt::type_for(values)))
{
init(values);
}
template <typename ValueType>
array(const std::initializer_list<std::initializer_list<ValueType>> &values)
: intrusive_ptr<array_preamble>(empty(ndt::type_for(values)))
{
init(values);
}
template <typename ValueType>
array(const std::initializer_list<std::initializer_list<std::initializer_list<ValueType>>> &values)
: intrusive_ptr<array_preamble>(empty(ndt::type_for(values)))
{
init(values);
}
template <typename ValueType>
array(const ValueType *values, size_t size)
: intrusive_ptr<array_preamble>(empty(ndt::make_fixed_dim(size, ndt::make_type<ValueType>())))
{
init(values, size);
}
inline bool is_null() const { return intrusive_ptr<array_preamble>::get() == 0; }
char *data() const
{
if (get()->flags & write_access_flag) {
return get()->data;
}
throw std::runtime_error("tried to write to a dynd array that is not writable");
}
const char *cdata() const { return get()->data; }
inline uint32_t get_access_flags() const
{
return get()->flags & (immutable_access_flag | read_access_flag | write_access_flag);
}
inline bool is_immutable() const { return (get()->flags & immutable_access_flag) != 0; }
inline bool is_scalar() const { return get_type().is_scalar(); }
const ndt::type &get_type() const { return *reinterpret_cast<const ndt::type *>(&get()->tp); }
inline intptr_t get_ndim() const
{
if (get()->tp.is_builtin()) {
return 0;
}
else {
return get()->tp->get_ndim();
}
}
inline ndt::type get_dtype() const
{
size_t ndim = get()->tp.get_ndim();
if (ndim == 0) {
return get()->tp;
}
return get()->tp->get_type_at_dimension(0, ndim);
}
inline ndt::type get_dtype(size_t include_ndim) const
{
if (get()->tp.is_builtin()) {
if (include_ndim > 0) {
throw too_many_indices(get_type(), include_ndim, 0);
}
return ndt::type(get()->tp.get_id());
}
else {
size_t ndim = get()->tp->get_ndim();
if (ndim < include_ndim) {
throw too_many_indices(get_type(), include_ndim, ndim);
}
ndim -= include_ndim;
if (ndim == 0) {
return get()->tp;
}
else {
return get()->tp->get_type_at_dimension(0, ndim);
}
}
}
void flag_as_immutable();
inline uint64_t get_flags() const { return get()->flags; }
inline std::vector<intptr_t> get_shape() const
{
std::vector<intptr_t> result(get_ndim());
get_shape(&result[0]);
return result;
}
inline void get_shape(intptr_t *out_shape) const
{
if (!get()->tp.is_builtin() && get()->tp->get_ndim() > 0) {
get()->tp->get_shape(get()->tp->get_ndim(), 0, out_shape, get()->metadata(), get()->data);
}
}
inline intptr_t get_dim_size() const { return get_type().get_dim_size(get()->metadata(), get()->data); }
inline intptr_t get_dim_size(intptr_t i) const
{
if (0 <= i && i < get_type().get_strided_ndim()) {
const size_stride_t *ss = reinterpret_cast<const size_stride_t *>(get()->metadata());
return ss[i].dim_size;
}
else if (0 <= i && i < get_ndim()) {
dimvector shape(i + 1);
get()->tp->get_shape(i + 1, 0, shape.get(), get()->metadata(), get()->data);
return shape[i];
}
else {
std::stringstream ss;
ss << "Not enough dimensions in array, tried to access axis " << i << " for type " << get_type();
throw std::invalid_argument(ss.str());
}
}
std::vector<intptr_t> get_strides() const
{
std::vector<intptr_t> result(get_ndim());
get_strides(&result[0]);
return result;
}
inline void get_strides(intptr_t *out_strides) const
{
if (!get()->tp.is_builtin()) {
get()->tp->get_strides(0, out_strides, get()->metadata());
}
}
inline intrusive_ptr<memory_block_data> get_data_memblock() const
{
if (get()->owner) {
return get()->owner;
}
else {
return intrusive_ptr<memory_block_data>(get(), true);
}
}
array p(const char *name) const;
array p(const std::string &name) const;
static nd::array from_type_property(const std::pair<ndt::type, const char *> &pair);
template <typename... ArgTypes>
array f(const char *name, ArgTypes &&... args) const
{
callable &f = reg(name);
return f(*this, std::forward<ArgTypes>(args)...);
}
array &operator+=(const array &rhs);
array &operator-=(const array &rhs);
array &operator*=(const array &rhs);
array &operator/=(const array &rhs);
array_vals vals() const;
array_vals_at vals_at(const irange &i0) const;
array_vals_at vals_at(const irange &i0, const irange &i1) const;
array_vals_at vals_at(const irange &i0, const irange &i1, const irange &i2) const;
array_vals_at vals_at(const irange &i0, const irange &i1, const irange &i2, const irange &i3) const;
array eval() const;
array eval_immutable() const;
array eval_copy(uint32_t access_flags = 0) const;
array storage() const;
array at_array(intptr_t nindices, const irange *indices, bool collapse_leading = true) const;
array operator()(const irange &i0) const { return at_array(1, &i0); }
array operator()(const irange &i0, const irange &i1) const
{
irange i[2] = {i0, i1};
return at_array(2, i);
}
array operator()(const irange &i0, const irange &i1, const irange &i2) const
{
irange i[3] = {i0, i1, i2};
return at_array(3, i);
}
array operator()(const irange &i0, const irange &i1, const irange &i2, const irange &i3) const
{
irange i[4] = {i0, i1, i2, i3};
return at_array(4, i);
}
array operator()(const irange &i0, const irange &i1, const irange &i2, const irange &i3, const irange &i4) const
{
irange i[5] = {i0, i1, i2, i3, i4};
return at_array(5, i);
}
array at(const irange &i0) const { return at_array(1, &i0); }
array assign(const array &rhs, assign_error_mode error_mode = assign_error_fractional) const;
array assign_na() const;
array cast(const ndt::type &tp) const;
array ucast(const ndt::type &uniform_dt, intptr_t replace_ndim = 0) const;
template <class T>
inline array ucast(intptr_t replace_ndim = 0) const
{
return ucast(ndt::make_type<T>(), replace_ndim);
}
array view(const ndt::type &tp) const;
template <int N>
inline array view(const char (&rhs)[N])
{
return view(ndt::type(rhs));
}
template <typename T>
typename std::enable_if<ndt::traits<T>::is_same_layout, T>::type view() const
{
return *reinterpret_cast<const T *>(cdata());
}
template <typename T>
typename std::enable_if<!ndt::traits<T>::is_same_layout, T>::type view()
{
return T(get()->metadata(), data());
}
array uview(const ndt::type &uniform_dt, intptr_t replace_ndim) const;
array permute(intptr_t ndim, const intptr_t *axes) const;
array rotate(intptr_t to, intptr_t from = 0) const;
array rotate(intptr_t from = 0) const { return rotate(get_ndim() - 1, from); }
array transpose() const;
array view_scalars(const ndt::type &scalar_tp) const;
array replace_dtype(const ndt::type &replacement_tp, intptr_t replace_ndim = 0) const;
array new_axis(intptr_t i, intptr_t new_ndim = 1) const;
template <class T>
array view_scalars() const
{
return view_scalars(ndt::make_type<T>());
}
template <typename ValueType>
ValueType as(assign_error_mode error_mode = assign_error_fractional) const
{
ValueType value;
nd::as<ValueType> as;
ndt::type tp = ndt::make_type<ValueType>();
if (tp == get()->tp) {
as.single(value, get()->data);
}
else {
array a = empty(tp);
a.assign(*this, error_mode);
as.single(value, a.get()->data);
}
return value;
}
array to_host() const;
bool is_na() const;
bool equals_exact(const array &rhs) const;
void debug_print(std::ostream &o, const std::string &indent = "") const;
friend __declspec(dllexport) std::ostream &operator<<(std::ostream &o, const array &rhs);
friend class array_vals;
friend class array_vals_at;
};
__declspec(dllexport) array as_struct(size_t size, const std::pair<const char *, array> *pairs);
inline array as_struct(const std::initializer_list<std::pair<const char *, array>> &pairs)
{
return as_struct(pairs.size(), pairs.begin());
}
__declspec(dllexport) array operator+(const array &a0);
__declspec(dllexport) array operator-(const array &a0);
__declspec(dllexport) array operator!(const array &a0);
__declspec(dllexport) array operator~(const array &a0);
__declspec(dllexport) array operator+(const array &op0, const array &op1);
__declspec(dllexport) array operator-(const array &op0, const array &op1);
__declspec(dllexport) array operator/(const array &op0, const array &op1);
__declspec(dllexport) array operator*(const array &op0, const array &op1);
__declspec(dllexport) array operator&&(const array &a0, const array &a1);
__declspec(dllexport) array operator||(const array &a0, const array &a1);
__declspec(dllexport) array operator<(const array &a0, const array &a1);
__declspec(dllexport) array operator<=(const array &a0, const array &a1);
__declspec(dllexport) array operator==(const array &a0, const array &a1);
__declspec(dllexport) array operator!=(const array &a0, const array &a1);
__declspec(dllexport) array operator>=(const array &a0, const array &a1);
__declspec(dllexport) array operator>(const array &a0, const array &a1);
class __declspec(dllexport) array_vals {
const array &m_arr;
array_vals(const array &arr) : m_arr(arr) {}
array_vals(const array_vals &);
array_vals &operator=(const array_vals &);
public:
array_vals &operator=(const array &rhs)
{
m_arr.assign(rhs);
return *this;
}
template <class T>
typename std::enable_if<is_dynd_scalar<T>::value, array_vals &>::type operator=(const T &rhs)
{
m_arr.assign(rhs);
return *this;
}
friend class array;
friend array_vals array::vals() const;
};
class __declspec(dllexport) array_vals_at {
array m_arr;
array_vals_at(const array &arr) : m_arr(arr) {}
array_vals_at(array &&arr) : m_arr(std::move(arr)) {}
array_vals_at(const array_vals &);
array_vals_at &operator=(const array_vals_at &);
public:
array_vals_at &operator=(const array &rhs)
{
m_arr.assign(rhs);
return *this;
}
template <class T>
typename std::enable_if<is_dynd_scalar<T>::value, array_vals_at &>::type operator=(const T &rhs)
{
m_arr.assign(rhs);
return *this;
}
friend class array;
friend array_vals_at array::vals_at(const irange &) const;
friend array_vals_at array::vals_at(const irange &, const irange &) const;
friend array_vals_at array::vals_at(const irange &, const irange &, const irange &) const;
friend array_vals_at array::vals_at(const irange &, const irange &, const irange &, const irange &) const;
};
__declspec(dllexport) array make_strided_array_from_data(const ndt::type &uniform_dtype, intptr_t ndim, const intptr_t *shape,
const intptr_t *strides, int64_t access_flags, char *data_ptr,
const intrusive_ptr<memory_block_data> &data_reference,
char **out_uniform_arrmeta = 0);
inline array_vals array::vals() const { return array_vals(*this); }
inline array_vals_at array::vals_at(const irange &i0) const { return array_vals_at(at_array(1, &i0, false)); }
inline array_vals_at array::vals_at(const irange &i0, const irange &i1) const
{
irange i[2] = {i0, i1};
return array_vals_at(at_array(2, i, false));
}
inline array_vals_at array::vals_at(const irange &i0, const irange &i1, const irange &i2) const
{
irange i[3] = {i0, i1, i2};
return array_vals_at(at_array(3, i, false));
}
inline array_vals_at array::vals_at(const irange &i0, const irange &i1, const irange &i2, const irange &i3) const
{
irange i[4] = {i0, i1, i2, i3};
return array_vals_at(at_array(4, i, false));
}
__declspec(dllexport) array empty_shell(const ndt::type &tp);
inline array dtyped_empty(intptr_t ndim, const intptr_t *shape, const ndt::type &tp)
{
if (ndim > 0) {
intptr_t i = ndim - 1;
ndt::type rtp = shape[i] >= 0 ? ndt::make_fixed_dim(shape[i], tp) : ndt::var_dim_type::make(tp);
while (i-- > 0) {
rtp = shape[i] >= 0 ? ndt::make_fixed_dim(shape[i], rtp) : ndt::var_dim_type::make(rtp);
}
return empty(rtp);
}
else {
return empty(tp);
}
}
inline array dtyped_empty(const std::vector<intptr_t> &shape, const ndt::type &tp)
{
return dtyped_empty(shape.size(), shape.empty() ? 0 : &shape[0], tp);
}
template <int N>
inline array empty(const char (&dshape)[N])
{
return nd::empty(ndt::type(dshape, dshape + N - 1));
}
inline array empty(intptr_t dim0, const ndt::type &tp)
{
return nd::empty(dim0 >= 0 ? ndt::make_fixed_dim(dim0, tp) : ndt::var_dim_type::make(tp));
}
template <int N>
inline array empty(intptr_t dim0, const char (&dshape)[N])
{
return empty(dim0, ndt::type(dshape, dshape + N - 1));
}
inline array empty(intptr_t dim0, intptr_t dim1, const ndt::type &tp)
{
ndt::type rtp = (dim1 >= 0) ? ndt::make_fixed_dim(dim1, tp) : ndt::var_dim_type::make(tp);
rtp = (dim0 >= 0) ? ndt::make_fixed_dim(dim0, rtp) : ndt::var_dim_type::make(rtp);
return nd::empty(rtp);
}
template <int N>
inline array empty(intptr_t dim0, intptr_t dim1, const char (&dshape)[N])
{
return empty(dim0, dim1, ndt::type(dshape, dshape + N - 1));
}
inline array empty(intptr_t dim0, intptr_t dim1, intptr_t dim2, const ndt::type &tp)
{
ndt::type rtp = (dim2 >= 0) ? ndt::make_fixed_dim(dim2, tp) : ndt::var_dim_type::make(tp);
rtp = (dim1 >= 0) ? ndt::make_fixed_dim(dim1, rtp) : ndt::var_dim_type::make(rtp);
rtp = (dim0 >= 0) ? ndt::make_fixed_dim(dim0, rtp) : ndt::var_dim_type::make(rtp);
return empty(rtp);
}
template <int N>
inline array empty(intptr_t dim0, intptr_t dim1, intptr_t dim2, const char (&dshape)[N])
{
return empty(dim0, dim1, dim2, ndt::type(dshape, dshape + N - 1));
}
__declspec(dllexport) array empty_like(const array &rhs, const ndt::type &uniform_dtype);
__declspec(dllexport) array empty_like(const array &rhs);
inline array dtyped_zeros(intptr_t ndim, const intptr_t *shape, const ndt::type &tp)
{
nd::array res = dtyped_empty(ndim, shape, tp);
res.assign(0);
return res;
}
inline array zeros(intptr_t dim0, const ndt::type &tp)
{
intptr_t shape[1] = {dim0};
return dtyped_zeros(1, shape, tp);
}
inline array zeros(intptr_t dim0, intptr_t dim1, const ndt::type &tp)
{
intptr_t shape[2] = {dim0, dim1};
return dtyped_zeros(2, shape, tp);
}
__declspec(dllexport) array typed_ones(intptr_t ndim, const intptr_t *shape, const ndt::type &tp);
inline array ones(const std::vector<intptr_t> &shape, const ndt::type &tp)
{
return typed_ones(shape.size(), shape.empty() ? 0 : &shape[0], tp);
}
inline array dtyped_ones(intptr_t ndim, const intptr_t *shape, const ndt::type &tp)
{
nd::array res = dtyped_empty(ndim, shape, tp);
res.assign(1);
return res;
}
inline array ones(intptr_t dim0, const ndt::type &tp)
{
intptr_t shape[1] = {dim0};
return dtyped_ones(1, shape, tp);
}
inline array ones(intptr_t dim0, intptr_t dim1, const ndt::type &tp)
{
intptr_t shape[2] = {dim0, dim1};
return dtyped_ones(2, shape, tp);
}
__declspec(dllexport) array concatenate(const nd::array &x, const nd::array &y);
__declspec(dllexport) array reshape(const array &a, const array &shape);
inline array reshape(const array &a, intptr_t ndim, const intptr_t *shape)
{
return reshape(a, nd::array(shape, ndim));
}
__declspec(dllexport) array memmap(const std::string &filename, intptr_t begin = 0,
intptr_t end = std::numeric_limits<intptr_t>::max(), uint32_t access = default_access_flags);
__declspec(dllexport) array combine_into_tuple(size_t field_count, const array *field_values);
}
namespace ndt {
template <typename T>
inline const T &unchecked_fixed_dim_get(const nd::array &a, intptr_t i)
{
const size_stride_t *md = reinterpret_cast<const size_stride_t *>(a.get()->metadata());
return *reinterpret_cast<const T *>(a.cdata() + i * md->stride);
}
template <typename T>
inline T &unchecked_fixed_dim_get_rw(const nd::array &a, intptr_t i)
{
const size_stride_t *md = reinterpret_cast<const size_stride_t *>(a.get()->metadata());
return *reinterpret_cast<T *>(a.data() + i * md->stride);
}
}
__declspec(dllexport) void broadcast_input_shapes(intptr_t ninputs, const nd::array *inputs, intptr_t &out_undim,
dimvector &out_shape, shortvector<int> &out_axis_perm);
class __declspec(dllexport) broadcast_error : public dynd_exception {
public:
broadcast_error(const std::string &m);
broadcast_error(intptr_t dst_ndim, const intptr_t *dst_shape, intptr_t src_ndim, const intptr_t *src_shape);
broadcast_error(const nd::array &dst, const nd::array &src);
broadcast_error(intptr_t ninputs, const nd::array *inputs);
broadcast_error(const ndt::type &dst_tp, const char *dst_arrmeta, const ndt::type &src_tp, const char *src_arrmeta);
broadcast_error(const ndt::type &dst_tp, const char *dst_arrmeta, const char *src_name);
broadcast_error(intptr_t dst_size, intptr_t src_size, const char *dst_name, const char *src_name);
virtual ~broadcast_error() throw();
};
__declspec(dllexport) void broadcast_to_shape(intptr_t ndim, const intptr_t *shape, intptr_t src_ndim, const intptr_t *src_shape,
const intptr_t *src_strides, intptr_t *out_strides);
__declspec(dllexport) void incremental_broadcast(intptr_t out_undim, intptr_t *out_shape, intptr_t undim, const intptr_t *shape);
}
namespace dynd {
namespace ndt {
namespace detail {
__declspec(dllexport) ndt::type internal_substitute(const ndt::type &pattern, const std::map<std::string, ndt::type> &typevars,
bool concrete);
}
inline ndt::type substitute(const ndt::type &pattern, const std::map<std::string, ndt::type> &typevars, bool concrete)
{
if (!pattern.is_symbolic() && pattern.get_id() != callable_id) {
return pattern;
}
else {
return detail::internal_substitute(pattern, typevars, concrete);
}
}
}
}
namespace dynd {
namespace ndt {
class __declspec(dllimport) base_fixed_dim_type : public base_dim_type {
public:
using base_dim_type::base_dim_type;
base_fixed_dim_type(const type &element_tp);
size_t get_default_data_size() const;
void print_data(std::ostream &o, const char *arrmeta, const char *data) const;
void print_type(std::ostream &o) const;
bool is_expression() const;
bool is_unique_data_owner(const char *arrmeta) const;
void transform_child_types(type_transform_fn_t transform_fn, intptr_t arrmeta_offset, void *extra,
type &out_transformed_tp, bool &out_was_transformed) const;
type get_canonical_type() const;
type at_single(intptr_t i0, const char **inout_arrmeta, const char **inout_data) const;
type get_type_at_dimension(char **inout_arrmeta, intptr_t i, intptr_t total_ndim = 0) const;
intptr_t get_dim_size(const char *arrmeta, const char *data) const;
void get_shape(intptr_t ndim, intptr_t i, intptr_t *out_shape, const char *arrmeta, const char *data) const;
bool is_lossless_assignment(const type &dst_tp, const type &src_tp) const;
virtual bool is_sized() const { return false; }
bool operator==(const base_type &rhs) const;
void arrmeta_default_construct(char *arrmeta, bool blockref_alloc) const;
void arrmeta_copy_construct(char *dst_arrmeta, const char *src_arrmeta,
const intrusive_ptr<memory_block_data> &embedded_reference) const;
void arrmeta_reset_buffers(char *arrmeta) const;
void arrmeta_finalize_buffers(char *arrmeta) const;
void arrmeta_destruct(char *arrmeta) const;
void arrmeta_debug_print(const char *arrmeta, std::ostream &o, const std::string &indent) const;
size_t arrmeta_copy_construct_onedim(char *dst_arrmeta, const char *src_arrmeta,
const intrusive_ptr<memory_block_data> &embedded_reference) const;
void data_destruct(const char *arrmeta, char *data) const;
void data_destruct_strided(const char *arrmeta, char *data, intptr_t stride, size_t count) const;
bool match(const type &candidate_tp, std::map<std::string, type> &tp_vars) const;
std::map<std::string, std::pair<ndt::type, const char *>> get_dynamic_type_properties() const;
virtual type with_element_type(const type &element_tp) const;
static type make(const type &element_tp) { return type(new base_fixed_dim_type(element_tp), false); }
static type make(const type &element_tp, intptr_t ndim)
{
if (ndim > 0) {
type result = make(element_tp);
for (intptr_t i = 1; i < ndim; ++i) {
result = make(result);
}
return result;
}
else {
return element_tp;
}
}
};
__declspec(dllimport) type make_fixed_dim_kind(const type &element_tp);
inline type make_fixed_dim_kind(const type &uniform_tp, intptr_t ndim)
{
return base_fixed_dim_type::make(uniform_tp, ndim);
}
template <typename T>
struct traits<T[]> {
static type equivalent() { return base_fixed_dim_type::make(make_type<T>()); }
};
template <typename T>
struct traits<const T[]> {
static type equivalent() { return make_type<T[]>(); }
};
}
}
namespace dynd {
typedef size_stride_t fixed_dim_type_arrmeta;
struct __declspec(dllimport) fixed_dim_type_iterdata {
iterdata_common common;
char *data;
intptr_t stride;
};
template <typename ElementType, int NDim>
class fixed_dim_iterator;
template <typename ElementType>
class fixed_dim : public as_t<ElementType> {
protected:
fixed_dim operator()(const char *metadata, char *data) { return fixed_dim(metadata, data); }
template <typename Index0Type, typename... IndexType>
decltype(auto) operator()(const char *metadata, char *data, Index0Type index0, IndexType... index)
{
return as_t<ElementType>::operator()(
metadata + sizeof(fixed_dim_type_arrmeta),
data + index0 * reinterpret_cast<const fixed_dim_type_arrmeta *>(metadata)->stride, index...);
}
public:
static const intptr_t ndim = as_t<ElementType>::ndim + 1;
typedef typename as_t<ElementType>::data_type data_type;
template <int NDim>
class iterator_type : public fixed_dim_iterator<ElementType, NDim> {
public:
iterator_type(const char *metadata, char *data) : fixed_dim_iterator<ElementType, NDim>(metadata, data) {}
};
fixed_dim(const char *metadata, char *data) : as_t<ElementType>(metadata, data) {}
size_t size() const { return reinterpret_cast<const fixed_dim_type_arrmeta *>(this->m_metadata)->dim_size; }
void set_data(char *data) { this->m_data = data; }
template <typename... IndexType>
decltype(auto) operator()(IndexType... index)
{
static_assert(sizeof...(IndexType) <= ndim, "too many indices");
return (*this)(this->m_metadata, this->m_data, index...);
}
template <int NDim = 1>
iterator_type<NDim> begin()
{
return iterator_type<NDim>(this->m_metadata, this->m_data);
}
template <int NDim = 1>
iterator_type<NDim> end()
{
return iterator_type<NDim>(this->m_metadata,
this->m_data +
reinterpret_cast<const fixed_dim_type_arrmeta *>(this->m_metadata)->dim_size *
reinterpret_cast<const fixed_dim_type_arrmeta *>(this->m_metadata)->stride);
}
};
template <typename ElementType>
class fixed_dim_iterator<ElementType, 0> {
protected:
const char *m_metadata;
char *m_data;
public:
fixed_dim_iterator(const char *metadata, char *data) : m_metadata(metadata), m_data(data) {}
fixed_dim<ElementType> operator*() { return fixed_dim<ElementType>(m_metadata, m_data); }
bool operator==(const fixed_dim_iterator &rhs) const { return m_data == rhs.m_data; }
bool operator!=(const fixed_dim_iterator &rhs) const { return m_data != rhs.m_data; }
};
template <typename ElementType, int NDim>
class fixed_dim_iterator : public as_t<ElementType>::template iterator_type<NDim - 1> {
intptr_t m_stride;
public:
fixed_dim_iterator(const char *metadata, char *data)
: as_t<ElementType>::template iterator_type<NDim - 1>(metadata + sizeof(fixed_dim_type_arrmeta), data),
m_stride(reinterpret_cast<const fixed_dim_type_arrmeta *>(metadata)->stride)
{
}
fixed_dim_iterator &operator++()
{
this->m_data += m_stride;
return *this;
}
fixed_dim_iterator operator++(int)
{
fixed_dim_iterator tmp(*this);
operator++();
return tmp;
}
};
namespace ndt {
class __declspec(dllimport) fixed_dim_type : public base_fixed_dim_type {
intptr_t m_dim_size;
public:
typedef size_stride_t metadata_type;
fixed_dim_type(intptr_t dim_size, const type &element_tp);
size_t get_default_data_size() const;
intptr_t get_fixed_dim_size() const { return m_dim_size; }
intptr_t get_fixed_stride(const char *arrmeta) const
{
return reinterpret_cast<const size_stride_t *>(arrmeta)->stride;
}
void print_data(std::ostream &o, const char *arrmeta, const char *data) const;
void print_type(std::ostream &o) const;
bool is_c_contiguous(const char *arrmeta) const;
bool is_expression() const;
bool is_unique_data_owner(const char *arrmeta) const;
void transform_child_types(type_transform_fn_t transform_fn, intptr_t arrmeta_offset, void *extra,
type &out_transformed_tp, bool &out_was_transformed) const;
type get_canonical_type() const;
type apply_linear_index(intptr_t nindices, const irange *indices, size_t current_i, const type &root_tp,
bool leading_dimension) const;
intptr_t apply_linear_index(intptr_t nindices, const irange *indices, const char *arrmeta, const type &result_tp,
char *out_arrmeta, const intrusive_ptr<memory_block_data> &embedded_reference,
size_t current_i, const type &root_tp, bool leading_dimension, char **inout_data,
intrusive_ptr<memory_block_data> &inout_dataref) const;
type at_single(intptr_t i0, const char **inout_arrmeta, const char **inout_data) const;
type get_type_at_dimension(char **inout_arrmeta, intptr_t i, intptr_t total_ndim = 0) const;
intptr_t get_dim_size(const char *arrmeta, const char *data) const;
void get_shape(intptr_t ndim, intptr_t i, intptr_t *out_shape, const char *arrmeta, const char *data) const;
void get_strides(size_t i, intptr_t *out_strides, const char *arrmeta) const;
bool is_sized() const { return true; }
axis_order_classification_t classify_axis_order(const char *arrmeta) const;
bool is_lossless_assignment(const type &dst_tp, const type &src_tp) const;
bool operator==(const base_type &rhs) const;
void arrmeta_default_construct(char *arrmeta, bool blockref_alloc) const;
void arrmeta_copy_construct(char *dst_arrmeta, const char *src_arrmeta,
const intrusive_ptr<memory_block_data> &embedded_reference) const;
void arrmeta_reset_buffers(char *arrmeta) const;
void arrmeta_finalize_buffers(char *arrmeta) const;
void arrmeta_destruct(char *arrmeta) const;
void arrmeta_debug_print(const char *arrmeta, std::ostream &o, const std::string &indent) const;
size_t arrmeta_copy_construct_onedim(char *dst_arrmeta, const char *src_arrmeta,
const intrusive_ptr<memory_block_data> &embedded_reference) const;
size_t get_iterdata_size(intptr_t ndim) const;
size_t iterdata_construct(iterdata_common *iterdata, const char **inout_arrmeta, intptr_t ndim,
const intptr_t *shape, type &out_uniform_tp) const;
size_t iterdata_destruct(iterdata_common *iterdata, intptr_t ndim) const;
void data_destruct(const char *arrmeta, char *data) const;
void data_destruct_strided(const char *arrmeta, char *data, intptr_t stride, size_t count) const;
void foreach_leading(const char *arrmeta, char *data, foreach_fn_t callback, void *callback_data) const;
void reorder_default_constructed_strides(char *dst_arrmeta, const type &src_tp, const char *src_arrmeta) const;
bool match(const type &candidate_tp, std::map<std::string, type> &tp_vars) const;
std::map<std::string, std::pair<ndt::type, const char *>> get_dynamic_type_properties() const;
virtual type with_element_type(const type &element_tp) const;
};
__declspec(dllimport) type make_fixed_dim(size_t dim_size, const type &element_tp);
__declspec(dllimport) type make_fixed_dim(intptr_t ndim, const intptr_t *shape, const type &dtp);
inline type make_fixed_dim(size_t dim_size, const type &element_tp, intptr_t ndim)
{
type result = element_tp;
for (intptr_t i = 0; i < ndim; ++i) {
result = make_fixed_dim(dim_size, result);
}
return result;
}
template <typename ElementType>
struct traits<fixed_dim<ElementType>> {
static const bool is_same_layout = false;
static type equivalent() { return base_fixed_dim_type::make(make_type<ElementType>()); }
};
}
}
namespace dynd {
namespace ndt {
class __declspec(dllimport) tuple_type : public base_type {
protected:
intptr_t m_field_count;
const std::vector<type> m_field_types;
std::vector<uintptr_t> m_arrmeta_offsets;
bool m_variadic;
tuple_type(type_id_t type_id, const std::vector<type> &field_types, uint32_t flags, bool layout_in_arrmeta,
bool variadic);
uintptr_t *get_arrmeta_data_offsets(char *arrmeta) const { return reinterpret_cast<uintptr_t *>(arrmeta); }
public:
tuple_type(const std::vector<type> &field_types, bool variadic);
inline const uintptr_t *get_data_offsets(const char *arrmeta) const
{
return reinterpret_cast<const uintptr_t *>(arrmeta);
}
intptr_t get_field_count() const { return m_field_count; }
const ndt::type get_type() const { return ndt::type_for(m_field_types); }
const std::vector<type> &get_field_types() const { return m_field_types; }
const type *get_field_types_raw() const { return m_field_types.data(); }
const std::vector<uintptr_t> &get_arrmeta_offsets() const { return m_arrmeta_offsets; }
const uintptr_t *get_arrmeta_offsets_raw() const { return m_arrmeta_offsets.data(); }
const type &get_field_type(intptr_t i) const { return m_field_types[i]; }
uintptr_t get_arrmeta_offset(intptr_t i) const { return m_arrmeta_offsets[i]; }
bool is_variadic() const { return m_variadic; }
virtual void get_vars(std::unordered_set<std::string> &vars) const;
void print_data(std::ostream &o, const char *arrmeta, const char *data) const;
bool is_expression() const;
bool is_unique_data_owner(const char *arrmeta) const;
size_t get_default_data_size() const;
void get_shape(intptr_t ndim, intptr_t i, intptr_t *out_shape, const char *arrmeta, const char *data) const;
type apply_linear_index(intptr_t nindices, const irange *indices, size_t current_i, const type &root_tp,
bool leading_dimension) const;
intptr_t apply_linear_index(intptr_t nindices, const irange *indices, const char *arrmeta, const type &result_tp,
char *out_arrmeta, const intrusive_ptr<memory_block_data> &embedded_reference,
size_t current_i, const type &root_tp, bool leading_dimension, char **inout_data,
intrusive_ptr<memory_block_data> &inout_dataref) const;
void print_type(std::ostream &o) const;
void transform_child_types(type_transform_fn_t transform_fn, intptr_t arrmeta_offset, void *extra,
type &out_transformed_tp, bool &out_was_transformed) const;
type get_canonical_type() const;
bool is_lossless_assignment(const type &dst_tp, const type &src_tp) const;
bool operator==(const base_type &rhs) const;
void arrmeta_default_construct(char *arrmeta, bool blockref_alloc) const;
void arrmeta_copy_construct(char *dst_arrmeta, const char *src_arrmeta,
const intrusive_ptr<memory_block_data> &embedded_reference) const;
void arrmeta_reset_buffers(char *arrmeta) const;
void arrmeta_finalize_buffers(char *arrmeta) const;
void arrmeta_destruct(char *arrmeta) const;
void data_destruct(const char *arrmeta, char *data) const;
void data_destruct_strided(const char *arrmeta, char *data, intptr_t stride, size_t count) const;
void foreach_leading(const char *arrmeta, char *data, foreach_fn_t callback, void *callback_data) const;
void arrmeta_debug_print(const char *arrmeta, std::ostream &o, const std::string &indent) const;
virtual bool match(const type &candidate_tp, std::map<std::string, type> &tp_vars) const;
std::map<std::string, std::pair<ndt::type, const char *>> get_dynamic_type_properties() const;
static void fill_default_data_offsets(intptr_t nfields, const type *field_tps, uintptr_t *out_data_offsets)
{
if (nfields > 0) {
out_data_offsets[0] = 0;
size_t offs = 0;
for (intptr_t i = 1; i < nfields; ++i) {
offs += field_tps[i - 1].get_default_data_size();
offs = inc_to_alignment(offs, field_tps[i].get_data_alignment());
out_data_offsets[i] = offs;
}
}
}
static type make(const std::vector<type> &field_types, bool variadic = false)
{
return type(new tuple_type(field_types, variadic), false);
}
static type make(bool variadic = false) { return make(std::vector<type>(), variadic); }
};
}
}
namespace dynd {
namespace ndt {
class __declspec(dllimport) struct_type : public tuple_type {
const std::vector<std::string> m_field_names;
protected:
uintptr_t *get_arrmeta_data_offsets(char *arrmeta) const { return reinterpret_cast<uintptr_t *>(arrmeta); }
public:
struct_type(const std::vector<std::string> &field_names, const std::vector<type> &field_types,
bool variadic = false);
const std::vector<std::string> &get_field_names() const { return m_field_names; }
const std::string &get_field_name(intptr_t i) const { return m_field_names[i]; }
intptr_t get_field_index(const std::string &field_name) const;
const type &get_field_type(const std::string &field_name) const;
const type &get_field_type(intptr_t i) const;
inline const uintptr_t *get_data_offsets(const char *arrmeta) const
{
return reinterpret_cast<const uintptr_t *>(arrmeta);
}
uintptr_t get_data_offset(const char *arrmeta, const std::string &field_name) const;
void print_type(std::ostream &o) const;
void transform_child_types(type_transform_fn_t transform_fn, intptr_t arrmeta_offset, void *extra,
type &out_transformed_tp, bool &out_was_transformed) const;
type get_canonical_type() const;
type at_single(intptr_t i0, const char **inout_arrmeta, const char **inout_data) const;
bool is_lossless_assignment(const type &dst_tp, const type &src_tp) const;
bool operator==(const base_type &rhs) const;
void arrmeta_debug_print(const char *arrmeta, std::ostream &o, const std::string &indent) const;
type apply_linear_index(intptr_t nindices, const irange *indices, size_t current_i, const type &root_tp,
bool leading_dimension) const;
intptr_t apply_linear_index(intptr_t nindices, const irange *indices, const char *arrmeta, const type &result_tp,
char *out_arrmeta, const intrusive_ptr<memory_block_data> &embedded_reference,
size_t current_i, const type &root_tp, bool leading_dimension, char **inout_data,
intrusive_ptr<memory_block_data> &inout_dataref) const;
std::map<std::string, std::pair<ndt::type, const char *>> get_dynamic_type_properties() const;
virtual bool match(const type &candidate_tp, std::map<std::string, type> &tp_vars) const;
static type make(const std::vector<std::string> &field_names, const std::vector<type> &field_types,
bool variadic = false)
{
return type(new struct_type(field_names, field_types, variadic), false);
}
static type make(bool variadic = false) { return make(std::vector<std::string>(), std::vector<type>(), variadic); }
};
}
}
namespace dynd {
namespace ndt {
class __declspec(dllimport) callable_type : public base_type {
type m_return_type;
type m_pos_tuple;
type m_kwd_struct;
std::vector<intptr_t> m_opt_kwd_indices;
struct get_pos_types_kernel;
public:
typedef nd::callable data_type;
callable_type(const type &ret_type, const type &pos_types, const type &kwd_types);
const type &get_return_type() const { return m_return_type; }
const type &get_pos_tuple() const { return m_pos_tuple; }
const std::vector<type> &get_pos_types() const { return m_pos_tuple.extended<tuple_type>()->get_field_types(); }
bool is_pos_variadic() const { return m_pos_tuple.extended<tuple_type>()->is_variadic(); }
bool is_kwd_variadic() const { return m_kwd_struct.extended<struct_type>()->is_variadic(); }
const type &get_kwd_struct() const { return m_kwd_struct; }
const std::vector<type> &get_kwd_types() const { return m_kwd_struct.extended<struct_type>()->get_field_types(); }
const std::vector<std::string> &get_kwd_names() const
{
return m_kwd_struct.extended<struct_type>()->get_field_names();
}
const type &get_pos_type(intptr_t i) const
{
if (i == -1) {
return get_return_type();
}
return m_pos_tuple.extended<tuple_type>()->get_field_type(i);
}
const type &get_kwd_type(intptr_t i) const { return m_kwd_struct.extended<struct_type>()->get_field_type(i); }
std::string get_kwd_name(intptr_t i) const { return m_kwd_struct.extended<struct_type>()->get_field_name(i); }
intptr_t get_kwd_index(const std::string &arg_name) const
{
return m_kwd_struct.extended<struct_type>()->get_field_index(arg_name);
}
void get_vars(std::unordered_set<std::string> &vars) const;
bool has_kwd(const std::string &name) const { return get_kwd_index(name) != -1; }
const std::vector<intptr_t> &get_option_kwd_indices() const { return m_opt_kwd_indices; }
intptr_t get_narg() const { return get_npos() + get_nkwd(); }
intptr_t get_npos() const { return m_pos_tuple.extended<tuple_type>()->get_field_count(); }
intptr_t get_nkwd() const { return m_kwd_struct.extended<tuple_type>()->get_field_count(); }
intptr_t get_nopt() const { return m_opt_kwd_indices.size(); }
void print_data(std::ostream &o, const char *arrmeta, const char *data) const;
void print_type(std::ostream &o) const;
void transform_child_types(type_transform_fn_t transform_fn, intptr_t arrmeta_offset, void *extra,
type &out_transformed_tp, bool &out_was_transformed) const;
type get_canonical_type() const;
type apply_linear_index(intptr_t nindices, const irange *indices, size_t current_i, const type &root_tp,
bool leading_dimension) const;
intptr_t apply_linear_index(intptr_t nindices, const irange *indices, const char *arrmeta, const type &result_tp,
char *out_arrmeta, const intrusive_ptr<memory_block_data> &embedded_reference,
size_t current_i, const type &root_tp, bool leading_dimension, char **inout_data,
intrusive_ptr<memory_block_data> &inout_dataref) const;
bool is_lossless_assignment(const type &dst_tp, const type &src_tp) const;
bool operator==(const base_type &rhs) const;
void arrmeta_default_construct(char *arrmeta, bool blockref_alloc) const;
void arrmeta_copy_construct(char *dst_arrmeta, const char *src_arrmeta,
const intrusive_ptr<memory_block_data> &embedded_reference) const;
void arrmeta_reset_buffers(char *arrmeta) const;
void arrmeta_finalize_buffers(char *arrmeta) const;
void arrmeta_destruct(char *arrmeta) const;
void data_destruct(const char *arrmeta, char *data) const;
void data_destruct_strided(const char *arrmeta, char *data, intptr_t stride, size_t count) const;
bool match(const type &candidate_tp, std::map<std::string, type> &tp_vars) const;
std::map<std::string, std::pair<ndt::type, const char *>> get_dynamic_type_properties() const;
static type make(const type &ret_tp, const type &tuple_tp, const type &struct_tp)
{
return type(new callable_type(ret_tp, tuple_tp, struct_tp), false);
}
static type make(const type &ret_tp, const std::vector<type> &pos_tp, const std::vector<std::string> &kwd_names,
const std::vector<type> &kwd_tp)
{
return make(ret_tp, tuple_type::make(pos_tp), struct_type::make(kwd_names, kwd_tp));
}
static type make(const type &ret_tp, const type &tuple_tp)
{
if (tuple_tp.get_id() != tuple_id) {
return make(ret_tp, tuple_type::make({tuple_tp}), struct_type::make());
}
return make(ret_tp, tuple_tp, struct_type::make(tuple_tp.extended<tuple_type>()->is_variadic()));
}
static type make(const type &ret_tp, const std::vector<type> &pos_tp)
{
return make(ret_tp, tuple_type::make(pos_tp), struct_type::make());
}
static type make(const type &ret_tp) { return make(ret_tp, tuple_type::make(), struct_type::make()); }
};
template <typename R>
struct traits<R()> {
static type equivalent() { return callable_type::make(make_type<R>()); }
};
template <typename R, typename A0, typename... A>
struct traits<R(A0, A...)> {
static type equivalent() { return callable_type::make(make_type<R>(), {make_type<A0>(), make_type<A>()...}); }
template <typename... T>
static type equivalent(const T &... names)
{
size_t num_pos = 1 + sizeof...(A) - sizeof...(T);
const std::vector<type> tp{make_type<A0>(), make_type<A>()...};
const std::vector<type> pos(tp.begin(), tp.begin() + num_pos);
const std::vector<type> kwargs(tp.begin() + num_pos, tp.end());
return callable_type::make(make_type<R>(), pos, {names...}, kwargs);
}
};
template <typename R, typename T, typename... A>
struct traits<R (T::*)(A...)> {
static type equivalent() { return make_type<typename funcproto_of<R (T::*)(A...)>::type>(); }
};
__declspec(dllimport) type make_generic_funcproto(intptr_t nargs);
}
}
namespace dynd {
namespace nd {
template <typename ClosureType>
struct closure_call : call_node {
ClosureType closure;
closure_call(ClosureType closure)
: call_node(instantiate_wrapper, destructor_wrapper, sizeof(closure_call)), closure(closure) {}
template <typename... ArgTypes>
static void init(closure_call *self, ArgTypes &&... args) {
new (self) closure_call(std::forward<ArgTypes>(args)...);
}
static void destructor_wrapper(call_node *self) { reinterpret_cast<closure_call *>(self)->~closure_call(); }
static void instantiate_wrapper(call_node *self, kernel_builder *kb, kernel_request_t kernreq,
const char *dst_arrmeta, size_t nsrc, const char *const *src_arrmeta) {
reinterpret_cast<closure_call *>(self)->closure(*kb, kernreq, dst_arrmeta, nsrc, src_arrmeta);
}
};
}
}
namespace dynd {
namespace nd {
class call_graph : public storagebuf<call_node, call_graph> {
public:
__declspec(dllexport) void destroy() {}
~call_graph() {
intptr_t offset = 0;
while (offset != m_size) {
call_node *node = get_at<call_node>(offset);
offset += node->aligned_size;
node->destroy(node);
}
}
template <typename ClosureType>
void emplace_back(ClosureType closure) {
storagebuf<call_node, call_graph>::emplace_back<closure_call<ClosureType>>(closure);
}
};
}
}
namespace dynd {
namespace nd {
class call_graph;
enum callable_property {
none = 0x00000000,
left_associative = 0x00000001,
right_associative = 0x00000002,
commutative = 0x00000004
};
inline callable_property operator|(callable_property a, callable_property b) {
return static_cast<callable_property>(static_cast<int>(a) | static_cast<int>(b));
}
enum callable_flags_t {
callable_flag_none = 0x00000000,
callable_flag_abstract = 0x00000001,
};
class __declspec(dllexport) base_callable {
protected:
std::atomic_long m_use_count;
ndt::type m_tp;
public:
base_callable(const ndt::type &tp) : m_use_count(0), m_tp(tp) {}
base_callable(const base_callable &) = delete;
virtual ~base_callable();
const ndt::type &get_type() const { return m_tp; }
const ndt::type &get_return_type() const { return m_tp.extended<ndt::callable_type>()->get_return_type(); }
std::intptr_t get_narg() const { return m_tp.extended<ndt::callable_type>()->get_npos(); }
const ndt::type &get_arg_type(std::intptr_t i) const {
return m_tp.extended<ndt::callable_type>()->get_pos_type(i);
}
const std::vector<ndt::type> &get_argument_types() const {
return m_tp.extended<ndt::callable_type>()->get_pos_types();
}
virtual ndt::type resolve(base_callable *caller, char *data, call_graph &cg, const ndt::type &res_tp, size_t narg,
const ndt::type *arg_tp, size_t nkwd, const array *kwds,
const std::map<std::string, ndt::type> &tp_vars) = 0;
virtual array alloc(const ndt::type *dst_tp) const { return empty(*dst_tp); }
virtual void overload(const ndt::type &, intptr_t ,
const ndt::type *, const callable &) {
throw std::runtime_error("callable is not overloadable");
}
virtual const callable &specialize(const ndt::type &, intptr_t ,
const ndt::type *) {
throw std::runtime_error("callable is not specializable");
}
array call(ndt::type &dst_tp, size_t nsrc, const ndt::type *src_tp, const char *const *src_arrmeta,
char *const *src_data, size_t nkwd, const array *kwds, const std::map<std::string, ndt::type> &tp_vars);
array call(ndt::type &dst_tp, size_t nsrc, const ndt::type *src_tp, const char *const *src_arrmeta,
const array *src_data, size_t nkwd, const array *kwds, const std::map<std::string, ndt::type> &tp_vars);
void call(const ndt::type &dst_tp, const char *dst_arrmeta, array *dst_data, size_t nsrc, const ndt::type *src_tp,
const char *const *src_arrmeta, const array *src_data, size_t nkwd, const array *kwds,
const std::map<std::string, ndt::type> &tp_vars);
void call(const ndt::type &dst_tp, const char *dst_arrmeta, char *dst_data, size_t nsrc, const ndt::type *src_tp,
const char *const *src_arrmeta, char *const *src_data, size_t nkwd, const array *kwds,
const std::map<std::string, ndt::type> &tp_vars);
friend void intrusive_ptr_retain(base_callable *ptr);
friend void intrusive_ptr_release(base_callable *ptr);
friend long intrusive_ptr_use_count(base_callable *ptr);
};
inline void intrusive_ptr_retain(base_callable *ptr) { ++ptr->m_use_count; }
inline void intrusive_ptr_release(base_callable *ptr) {
if (--ptr->m_use_count == 0) {
delete ptr;
}
}
inline long intrusive_ptr_use_count(base_callable *ptr) { return ptr->m_use_count; }
}
}
namespace dynd {
namespace nd {
template <typename KernelType>
class default_instantiable_callable : public base_callable {
protected:
using base_callable::base_callable;
public:
default_instantiable_callable(const ndt::type &tp) : base_callable(tp) {}
ndt::type resolve(base_callable *, char *, call_graph &cg,
const ndt::type &dst_tp, size_t , const ndt::type *,
size_t , const array *,
const std::map<std::string, ndt::type> &) {
cg.emplace_back([](kernel_builder &kb, kernel_request_t kernreq, const char *,
size_t ,
const char *const *) { kb.emplace_back<KernelType>(kernreq); });
return dst_tp;
}
};
}
}
namespace dynd {
namespace nd {
template <typename...>
struct base_kernel;
template <typename PrefixType, typename SelfType>
struct base_kernel<PrefixType, SelfType> : PrefixType {
kernel_prefix *get_child(intptr_t offset) { return kernel_prefix::get_child(kernel_builder::aligned_size(offset)); }
kernel_prefix *get_child() { return kernel_prefix::get_child(reinterpret_cast<SelfType *>(this)->size()); }
template <size_t I>
std::enable_if_t<I == 0, kernel_prefix *> get_child()
{
return get_child();
}
template <size_t I>
std::enable_if_t<(I > 0), kernel_prefix *> get_child()
{
const size_t *offsets = this->get_offsets();
return kernel_prefix::get_child(offsets[I - 1]);
}
constexpr size_t size() const { return sizeof(SelfType); }
template <typename... ArgTypes>
static void init(SelfType *self, kernel_request_t kernreq, ArgTypes &&... args)
{
new (self) SelfType(std::forward<ArgTypes>(args)...);
self->destructor = SelfType::destruct;
switch (kernreq) {
case kernel_request_call:
self->function = reinterpret_cast<void *>(SelfType::call_wrapper);
break;
case kernel_request_single:
self->function = reinterpret_cast<void *>(SelfType::single_wrapper);
break;
default:
throw std::invalid_argument("expr ckernel init: unrecognized ckernel request " + std::to_string(kernreq));
}
}
static void destruct(kernel_prefix *self) { reinterpret_cast<SelfType *>(self)->~SelfType(); }
void call(array *, const array *)
{
std::stringstream ss;
ss << "void call(array *dst, const array *src) is not implemented in " << typeid(SelfType).name();
throw std::runtime_error(ss.str());
}
static void call_wrapper(kernel_prefix *self, array *dst, const array *src)
{
reinterpret_cast<SelfType *>(self)->call(dst, src);
}
void single(char *, char *const *)
{
std::stringstream ss;
ss << "void single(char *dst, char *const *src) is not implemented in " << typeid(SelfType).name();
throw std::runtime_error(ss.str());
}
static void single_wrapper(kernel_prefix *self, char *dst, char *const *src)
{
reinterpret_cast<SelfType *>(self)->single(dst, src);
}
static const volatile char *ir;
};
template <typename PrefixType, typename SelfType>
const volatile char *(base_kernel<PrefixType, SelfType>::ir) = 0;
template <typename SelfType>
struct base_kernel<SelfType> : base_kernel<kernel_prefix, SelfType> {
};
}
}
namespace dynd {
namespace nd {
namespace functional {
template <typename A, size_t I>
struct apply_arg {
typedef typename std::remove_cv<typename std::remove_reference<A>::type>::type D;
apply_arg(const char *, const nd::array *) {}
D &get(char *data) { return *reinterpret_cast<D *>(data); }
};
template <typename ElementType, size_t I>
struct apply_arg<fixed_dim<ElementType>, I> {
fixed_dim<ElementType> value;
apply_arg(const char *arrmeta, const nd::array *) : value(arrmeta, 0) {}
fixed_dim<ElementType> &get(char *data)
{
value.set_data(data);
return value;
}
};
template <typename func_type, int N = args_of<typename funcproto_of<func_type>::type>::type::size>
using as_apply_arg_sequence = typename to<typename args_of<typename funcproto_of<func_type>::type>::type, N>::type;
template <typename A, typename I = make_index_sequence<A::size>>
struct apply_args;
template <typename... A, size_t... I>
struct apply_args<type_sequence<A...>, index_sequence<I...>> : apply_arg<A, I>... {
apply_args(const char *const *src_arrmeta, const nd::array *kwds)
: apply_arg<A, I>(src_arrmeta[I], kwds)...
{
}
};
template <typename T, size_t I>
struct apply_kwd {
T m_val;
apply_kwd(nd::array val) : m_val(val.as<T>()) {}
T get() { return m_val; }
};
template <typename K, typename J = make_index_sequence<K::size>>
struct apply_kwds;
template <>
struct apply_kwds<type_sequence<>, index_sequence<>> {
apply_kwds(intptr_t , const nd::array *) {}
};
template <typename... K, size_t... J>
struct apply_kwds<type_sequence<K...>, index_sequence<J...>> : apply_kwd<K, J>... {
apply_kwds(intptr_t , const nd::array *kwds) : apply_kwd<K, J>(kwds[J])... {}
};
template <typename func_type, int N>
using as_apply_kwd_sequence =
typename from<typename args_of<typename funcproto_of<func_type>::type>::type, N>::type;
}
}
}
namespace dynd {
namespace nd {
template <typename SelfType, size_t... N>
struct base_strided_kernel;
template <typename SelfType>
struct base_strided_kernel<SelfType> : base_kernel<SelfType> {
static void strided_wrapper(kernel_prefix *self, char *dst, intptr_t dst_stride, char *const *src,
const intptr_t *src_stride, size_t count)
{
reinterpret_cast<SelfType *>(self)->strided(dst, dst_stride, src, src_stride, count);
}
template <typename... ArgTypes>
static void init(SelfType *self, kernel_request_t kernreq, ArgTypes &&... args)
{
new (self) SelfType(std::forward<ArgTypes>(args)...);
self->destructor = SelfType::destruct;
switch (kernreq) {
case kernel_request_call:
self->function = reinterpret_cast<void *>(SelfType::call_wrapper);
break;
case kernel_request_single:
self->function = reinterpret_cast<void *>(SelfType::single_wrapper);
break;
case kernel_request_strided:
self->function = reinterpret_cast<void *>(SelfType::strided_wrapper);
break;
default:
throw std::invalid_argument("expr ckernel init: unrecognized ckernel request " + std::to_string(kernreq));
}
}
};
template <typename SelfType, size_t N>
struct base_strided_kernel<SelfType, N> : base_strided_kernel<SelfType> {
void call(array *dst, const array *src)
{
char *src_data[N];
for (size_t i = 0; i < N; ++i) {
src_data[i] = const_cast<char *>(src[i].cdata());
}
reinterpret_cast<SelfType *>(this)->single(const_cast<char *>(dst->cdata()), src_data);
}
void strided(char *dst, intptr_t dst_stride, char *const *src, const intptr_t *src_stride, size_t count)
{
char *src_copy[N];
memcpy(src_copy, src, sizeof(src_copy));
for (size_t i = 0; i != count; ++i) {
reinterpret_cast<SelfType *>(this)->single(dst, src_copy);
dst += dst_stride;
for (size_t j = 0; j < N; ++j) {
src_copy[j] += src_stride[j];
}
}
}
};
template <typename SelfType>
struct base_strided_kernel<SelfType, 0> : base_strided_kernel<SelfType> {
void call(array *dst, const array *)
{
reinterpret_cast<SelfType *>(this)->single(const_cast<char *>(dst->cdata()), nullptr);
}
void strided(char *dst, intptr_t dst_stride, char *const *, const intptr_t *,
size_t count)
{
for (size_t i = 0; i != count; ++i) {
reinterpret_cast<SelfType *>(this)->single(dst, 0);
dst += dst_stride;
}
}
};
}
}
namespace dynd {
namespace nd {
namespace functional {
namespace detail {
template <typename func_type, func_type func, typename R, typename A, typename I, typename K, typename J>
struct apply_function_kernel;
template <typename func_type, func_type func, typename R, typename... A, size_t... I, typename... K, size_t... J>
struct apply_function_kernel<func_type, func, R, type_sequence<A...>, index_sequence<I...>, type_sequence<K...>,
index_sequence<J...>>
: base_strided_kernel<apply_function_kernel<func_type, func, R, type_sequence<A...>, index_sequence<I...>,
type_sequence<K...>, index_sequence<J...>>,
sizeof...(A)>,
apply_args<type_sequence<A...>, index_sequence<I...>>,
apply_kwds<type_sequence<K...>, index_sequence<J...>> {
typedef apply_args<type_sequence<A...>, index_sequence<I...>> args_type;
typedef apply_kwds<type_sequence<K...>, index_sequence<J...>> kwds_type;
apply_function_kernel(args_type args, kwds_type kwds) : args_type(args), kwds_type(kwds) {}
void single(char *dst, char *const *src)
{
*reinterpret_cast<R *>(dst) = func(apply_arg<A, I>::get(src[I])..., apply_kwd<K, J>::get()...);
}
};
template <typename func_type, func_type func, typename... A, size_t... I, typename... K, size_t... J>
struct apply_function_kernel<func_type, func, void, type_sequence<A...>, index_sequence<I...>,
type_sequence<K...>, index_sequence<J...>>
: base_strided_kernel<apply_function_kernel<func_type, func, void, type_sequence<A...>, index_sequence<I...>,
type_sequence<K...>, index_sequence<J...>>,
sizeof...(A)>,
apply_args<type_sequence<A...>, index_sequence<I...>>,
apply_kwds<type_sequence<K...>, index_sequence<J...>> {
typedef apply_args<type_sequence<A...>, index_sequence<I...>> args_type;
typedef apply_kwds<type_sequence<K...>, index_sequence<J...>> kwds_type;
apply_function_kernel(args_type args, kwds_type kwds) : args_type(args), kwds_type(kwds) {}
void single(char *, char *const *src)
{
func(apply_arg<A, I>::get(src[I])..., apply_kwd<K, J>::get()...);
}
};
}
template <typename func_type, func_type func, int N = arity_of<func_type>::value>
using apply_function_kernel =
detail::apply_function_kernel<func_type, func, typename return_of<func_type>::type,
as_apply_arg_sequence<func_type, N>, make_index_sequence<N>,
as_apply_kwd_sequence<func_type, N>,
make_index_sequence<arity_of<func_type>::value - N>>;
}
}
}
namespace dynd {
namespace nd {
namespace functional {
namespace detail {
template <typename T, typename mem_func_type, typename R, typename A, typename I, typename K, typename J>
struct apply_member_function_kernel;
template <typename T, typename mem_func_type, typename R, typename... A, size_t... I, typename... K, size_t... J>
struct apply_member_function_kernel<T *, mem_func_type, R, type_sequence<A...>, index_sequence<I...>,
type_sequence<K...>, index_sequence<J...>>
: base_strided_kernel<
apply_member_function_kernel<T *, mem_func_type, R, type_sequence<A...>, index_sequence<I...>,
type_sequence<K...>, index_sequence<J...>>,
sizeof...(A)>,
apply_args<type_sequence<A...>, index_sequence<I...>>,
apply_kwds<type_sequence<K...>, index_sequence<J...>> {
typedef apply_args<type_sequence<A...>, index_sequence<I...>> args_type;
typedef apply_kwds<type_sequence<K...>, index_sequence<J...>> kwds_type;
typedef std::pair<T *, mem_func_type> data_type;
T *obj;
mem_func_type mem_func;
apply_member_function_kernel(T *obj, mem_func_type mem_func, args_type args, kwds_type kwds)
: args_type(args), kwds_type(kwds), obj(obj), mem_func(mem_func)
{
}
void single(char *dst, char *const *src)
{
*reinterpret_cast<R *>(dst) = (obj->*mem_func)(apply_arg<A, I>::get(src[I])..., apply_kwd<K, J>::get()...);
}
};
template <typename T, typename mem_func_type, typename... A, size_t... I, typename... K, size_t... J>
struct apply_member_function_kernel<T *, mem_func_type, void, type_sequence<A...>, index_sequence<I...>,
type_sequence<K...>, index_sequence<J...>>
: base_strided_kernel<
apply_member_function_kernel<T *, mem_func_type, void, type_sequence<A...>, index_sequence<I...>,
type_sequence<K...>, index_sequence<J...>>,
sizeof...(A)>,
apply_args<type_sequence<A...>, index_sequence<I...>>,
apply_kwds<type_sequence<K...>, index_sequence<J...>> {
typedef apply_args<type_sequence<A...>, index_sequence<I...>> args_type;
typedef apply_kwds<type_sequence<K...>, index_sequence<J...>> kwds_type;
typedef std::pair<T *, mem_func_type> data_type;
T *obj;
mem_func_type mem_func;
apply_member_function_kernel(T *obj, mem_func_type mem_func, args_type args, kwds_type kwds)
: args_type(args), kwds_type(kwds), obj(obj), mem_func(mem_func)
{
}
void single(char *, char *const *src)
{
(obj->*mem_func)(apply_arg<A, I>::get(src[I])..., apply_kwd<K, J>::get()...);
}
};
}
template <typename T, typename mem_func_type, int N>
using apply_member_function_kernel =
detail::apply_member_function_kernel<T, mem_func_type, typename return_of<mem_func_type>::type,
as_apply_arg_sequence<mem_func_type, N>, make_index_sequence<N>,
as_apply_kwd_sequence<mem_func_type, N>,
make_index_sequence<arity_of<mem_func_type>::value - N>>;
}
}
}
namespace dynd {
namespace nd {
namespace functional {
namespace detail {
template <typename func_type, typename R, typename A, typename I, typename K, typename J>
struct construct_then_apply_callable_kernel;
template <typename func_type, typename R, typename... A, size_t... I, typename... K, size_t... J> struct construct_then_apply_callable_kernel<func_type, R, type_sequence<A...>, index_sequence<I...>, type_sequence<K...>, index_sequence<J...>> : base_strided_kernel< construct_then_apply_callable_kernel<func_type, R, type_sequence<A...>, index_sequence<I...>, type_sequence<K...>, index_sequence<J...>>, sizeof...(A)>, apply_args<type_sequence<A...>, index_sequence<I...>> { typedef apply_args<type_sequence<A...>, index_sequence<I...>> args_type; typedef apply_kwds<type_sequence<K...>, index_sequence<J...>> kwds_type; func_type func; construct_then_apply_callable_kernel(args_type args, kwds_type kwds) : args_type(args), func(kwds.apply_kwd<K, J>::get()...) { } void single(char *dst, char *const *src) { *reinterpret_cast<R *>(dst) = func(apply_arg<A, I>::get(src[I])...); } }; template <typename func_type, typename... A, size_t... I, typename... K, size_t... J> struct construct_then_apply_callable_kernel<func_type, void, type_sequence<A...>, index_sequence<I...>, type_sequence<K...>, index_sequence<J...>> : base_strided_kernel< construct_then_apply_callable_kernel<func_type, void, type_sequence<A...>, index_sequence<I...>, type_sequence<K...>, index_sequence<J...>>, sizeof...(A)>, apply_args<type_sequence<A...>, index_sequence<I...>> { typedef apply_args<type_sequence<A...>, index_sequence<I...>> args_type; typedef apply_kwds<type_sequence<K...>, index_sequence<J...>> kwds_type; func_type func; construct_then_apply_callable_kernel(args_type args, kwds_type kwds) : args_type(args), func(kwds.apply_kwd<K, J>::get()...) { } void single(char *, char *const *src) { func(apply_arg<A, I>::get(src[I])...); } };
}
template <typename func_type, typename... K>
using construct_then_apply_callable_kernel = detail::construct_then_apply_callable_kernel<
func_type, typename return_of<func_type>::type, as_apply_arg_sequence<func_type, arity_of<func_type>::value>,
make_index_sequence<arity_of<func_type>::value>, type_sequence<K...>, make_index_sequence<sizeof...(K)>>;
}
}
}
namespace dynd {
namespace nd {
namespace functional {
namespace detail {
template <typename func_type, typename R, typename A, typename I, typename K, typename J>
struct apply_callable_kernel;
template <typename func_type, typename R, typename... A, size_t... I, typename... K, size_t... J>
struct apply_callable_kernel<func_type, R, type_sequence<A...>, index_sequence<I...>, type_sequence<K...>,
index_sequence<J...>>
: base_strided_kernel<apply_callable_kernel<func_type, R, type_sequence<A...>, index_sequence<I...>,
type_sequence<K...>, index_sequence<J...>>,
sizeof...(A)>,
apply_args<type_sequence<A...>, index_sequence<I...>>,
apply_kwds<type_sequence<K...>, index_sequence<J...>> {
typedef apply_args<type_sequence<A...>, index_sequence<I...>> args_type;
typedef apply_kwds<type_sequence<K...>, index_sequence<J...>> kwds_type;
func_type func;
apply_callable_kernel(func_type func, args_type args, kwds_type kwds)
: args_type(args), kwds_type(kwds), func(func)
{
}
void single(char *dst, char *const *src)
{
*reinterpret_cast<R *>(dst) = func(apply_arg<A, I>::get(src[I])..., apply_kwd<K, J>::get()...);
}
};
template <typename func_type, typename... A, size_t... I, typename... K, size_t... J>
struct apply_callable_kernel<func_type, void, type_sequence<A...>, index_sequence<I...>, type_sequence<K...>,
index_sequence<J...>>
: base_strided_kernel<apply_callable_kernel<func_type, void, type_sequence<A...>, index_sequence<I...>,
type_sequence<K...>, index_sequence<J...>>,
sizeof...(A)>,
apply_args<type_sequence<A...>, index_sequence<I...>>,
apply_kwds<type_sequence<K...>, index_sequence<J...>> {
typedef apply_args<type_sequence<A...>, index_sequence<I...>> args_type;
typedef apply_kwds<type_sequence<K...>, index_sequence<J...>> kwds_type;
func_type func;
apply_callable_kernel(func_type func, args_type args, kwds_type kwds)
: args_type(args), kwds_type(kwds), func(func)
{
}
void single(char *, char *const *src)
{
func(apply_arg<A, I>::get(src[I])..., apply_kwd<K, J>::get()...);
}
};
template <typename func_type, typename R, typename... A, size_t... I, typename... K, size_t... J>
struct apply_callable_kernel<func_type *, R, type_sequence<A...>, index_sequence<I...>, type_sequence<K...>,
index_sequence<J...>>
: base_strided_kernel<apply_callable_kernel<func_type *, R, type_sequence<A...>, index_sequence<I...>,
type_sequence<K...>, index_sequence<J...>>,
sizeof...(A)>,
apply_args<type_sequence<A...>, index_sequence<I...>>,
apply_kwds<type_sequence<K...>, index_sequence<J...>> {
typedef apply_args<type_sequence<A...>, index_sequence<I...>> args_type;
typedef apply_kwds<type_sequence<K...>, index_sequence<J...>> kwds_type;
func_type *func;
apply_callable_kernel(func_type *func, args_type args, kwds_type kwds)
: args_type(args), kwds_type(kwds), func(func)
{
}
void single(char *dst, char *const *src)
{
*reinterpret_cast<R *>(dst) = (*func)(apply_arg<A, I>::get(src[I])..., apply_kwd<K, J>::get()...);
}
};
template <typename func_type, typename... A, size_t... I, typename... K, size_t... J>
struct apply_callable_kernel<func_type *, void, type_sequence<A...>, index_sequence<I...>, type_sequence<K...>,
index_sequence<J...>>
: base_strided_kernel<apply_callable_kernel<func_type *, void, type_sequence<A...>, index_sequence<I...>,
type_sequence<K...>, index_sequence<J...>>,
sizeof...(A)>,
apply_args<type_sequence<A...>, index_sequence<I...>>,
apply_kwds<type_sequence<K...>, index_sequence<J...>> {
typedef apply_args<type_sequence<A...>, index_sequence<I...>> args_type;
typedef apply_kwds<type_sequence<K...>, index_sequence<J...>> kwds_type;
func_type *func;
apply_callable_kernel(func_type *func, args_type args, kwds_type kwds)
: args_type(args), kwds_type(kwds), func(func)
{
}
void single(char *, char *const *src)
{
(*func)(apply_arg<A, I>::get(src[I])..., apply_kwd<K, J>::get()...);
}
};
}
template <typename func_type, int N>
using apply_callable_kernel = detail::apply_callable_kernel<
func_type, typename return_of<func_type>::type, as_apply_arg_sequence<func_type, N>, make_index_sequence<N>,
as_apply_kwd_sequence<func_type, N>, make_index_sequence<arity_of<func_type>::value - N>>;
}
}
}
namespace dynd {
namespace nd {
namespace functional {
template <typename func_type, int N>
class apply_callable_callable : public base_callable {
func_type m_func;
public:
template <typename... T>
apply_callable_callable(func_type func, T &&... names)
: base_callable(ndt::make_type<typename funcproto_of<func_type>::type>(std::forward<T>(names)...)),
m_func(func) {}
ndt::type resolve(base_callable *, char *, call_graph &cg,
const ndt::type &dst_tp, size_t , const ndt::type *,
size_t nkwd, const array *kwds, const std::map<std::string, ndt::type> &) {
typedef apply_callable_kernel<func_type, N> kernel_type;
cg.emplace_back([ func = m_func, kwds = typename kernel_type::kwds_type(nkwd, kwds) ](
kernel_builder & kb, kernel_request_t kernreq, const char *,
size_t , const char *const *src_arrmeta) {
kb.emplace_back<kernel_type>(kernreq, func, typename kernel_type::args_type(src_arrmeta, nullptr), kwds);
});
return dst_tp;
}
};
}
}
}
namespace dynd {
struct id_info {
std::string name;
std::vector<type_id_t> base_ids;
std::vector<char> is_base_id;
id_info() = default;
id_info(const char *name, type_id_t id, const std::vector<type_id_t> &base_ids)
: name(name), base_ids(base_ids), is_base_id(128)
{
is_base_id[id] = true;
for (type_id_t base_id : base_ids) {
is_base_id[base_id] = true;
}
}
};
namespace detail {
extern __declspec(dllimport) std::vector<id_info> &infos();
}
__declspec(dllimport) type_id_t new_id(const char *name, type_id_t base_id);
inline type_id_t min_id() { return static_cast<type_id_t>(1); }
inline type_id_t max_id()
{
const std::vector<id_info> &infos = detail::infos();
return static_cast<type_id_t>(infos.size() - 1);
}
inline type_id_t base_id(type_id_t id)
{
const std::vector<id_info> &infos = detail::infos();
return infos[id].base_ids.front();
}
template <type_id_t ID>
std::enable_if_t<ID == any_kind_id, std::vector<type_id_t>> base_ids()
{
return {};
}
template <type_id_t ID>
std::enable_if_t<ID != any_kind_id, std::vector<type_id_t>> base_ids()
{
std::vector<type_id_t> res{base_id_of<ID>::value};
for (type_id_t base_id : base_ids<base_id_of<ID>::value>()) {
res.push_back(base_id);
}
return res;
}
inline const std::vector<type_id_t> &base_ids(type_id_t id)
{
const std::vector<id_info> &infos = detail::infos();
return infos[id].base_ids;
}
inline bool is_base_id_of(type_id_t base_id, type_id_t id)
{
const std::vector<id_info> &infos = detail::infos();
return infos[id].is_base_id[base_id] != 0;
}
}
namespace dynd {
inline bool consistent(const std::vector<type_id_t> &lhs, const std::vector<type_id_t> &rhs)
{
if (lhs.size() != rhs.size()) {
return false;
}
for (size_t i = 0; i < lhs.size(); ++i) {
if (!is_base_id_of(lhs[i], rhs[i]) && !is_base_id_of(rhs[i], lhs[i])) {
return false;
}
}
return true;
}
inline bool supercedes(const std::vector<type_id_t> &lhs, const std::vector<type_id_t> &rhs)
{
if (lhs.size() != rhs.size()) {
return false;
}
for (size_t i = 0; i < lhs.size(); ++i) {
if (!is_base_id_of(rhs[i], lhs[i])) {
return false;
}
}
return true;
}
inline bool ambiguous(const std::vector<type_id_t> &lhs, const std::vector<type_id_t> &rhs)
{
return consistent(lhs, rhs) && !(supercedes(lhs, rhs) || supercedes(rhs, lhs));
}
template <size_t N>
bool supercedes(const type_id_t (&lhs)[N], const std::vector<type_id_t> &rhs)
{
if (rhs.size() != N) {
return false;
}
for (size_t i = 0; i < N; ++i) {
if (!is_base_id_of(rhs[i], lhs[i])) {
return false;
}
}
return true;
}
inline bool supercedes(size_t N, const type_id_t *lhs, const std::vector<type_id_t> &rhs)
{
if (rhs.size() != N) {
return false;
}
for (size_t i = 0; i < N; ++i) {
if (!is_base_id_of(rhs[i], lhs[i])) {
return false;
}
}
return true;
}
namespace detail {
class topological_sort_marker {
char m_mark;
public:
topological_sort_marker() : m_mark(0) {}
void temporarily_mark() { m_mark = 1; }
void mark() { m_mark = 2; }
bool is_temporarily_marked() { return m_mark == 1; }
bool is_marked() { return m_mark == 2; }
};
template <typename VertexIterator, typename EdgeIterator, typename MarkerIterator, typename Iterator>
void topological_sort_visit(size_t i, VertexIterator vertices, EdgeIterator edges, MarkerIterator markers,
Iterator &res)
{
if (markers[i].is_temporarily_marked()) {
throw std::runtime_error("not a dag");
}
if (!markers[i].is_marked()) {
markers[i].temporarily_mark();
for (auto j : edges[i]) {
topological_sort_visit(j, vertices, edges, markers, res);
}
markers[i].mark();
*res = vertices[i];
--res;
}
}
}
template <typename VertexIterator, typename EdgeIterator, typename Iterator>
void topological_sort(VertexIterator begin, VertexIterator end, EdgeIterator edges, Iterator res)
{
size_t size = end - begin;
res += size - 1;
std::unique_ptr<detail::topological_sort_marker[]> markers =
std::make_unique<detail::topological_sort_marker[]>(size);
for (size_t i = 0; i < size; ++i) {
detail::topological_sort_visit(i, begin, edges, markers.get(), res);
}
}
template <typename VertexType, typename Iterator>
void topological_sort(std::initializer_list<VertexType> vertices,
std::initializer_list<std::initializer_list<size_t>> edges, Iterator res)
{
topological_sort(vertices.begin(), vertices.end(), edges.begin(), res);
}
inline std::ostream &print_ids(std::ostream &o, size_t nids, const type_id_t *ids)
{
o << "(" << ids[0];
for (size_t i = 1; i < nids; ++i) {
o << ", " << ids[i];
}
o << ")";
return o;
}
template <typename T, typename Map = std::map<size_t, T>>
class dispatcher {
public:
typedef T value_type;
typedef std::pair<std::vector<type_id_t>, value_type> pair_type;
typedef Map map_type;
typedef typename std::vector<pair_type>::iterator iterator;
typedef typename std::vector<pair_type>::const_iterator const_iterator;
private:
std::vector<pair_type> m_pairs;
map_type m_map;
static size_t hash_combine(size_t seed, type_id_t id) { return seed ^ (id + (seed << 6) + (seed >> 2)); }
template <typename... IDTypes>
static size_t hash_combine(size_t seed, type_id_t id0, IDTypes... ids)
{
return hash_combine(hash_combine(seed, id0), ids...);
}
public:
dispatcher() = default;
dispatcher(const dispatcher &other) : m_pairs(other.m_pairs), m_map(other.m_map) {}
template <typename Iterator>
dispatcher(Iterator begin, Iterator end, const map_type &map = map_type()) : m_map(map)
{
assign(begin, end);
}
dispatcher(std::initializer_list<pair_type> pairs, const map_type &map = map_type())
: dispatcher(pairs.begin(), pairs.end(), map)
{
}
template <typename Iterator>
void assign(Iterator begin, Iterator end)
{
m_pairs.resize(end - begin);
std::vector<std::vector<size_t>> edges(m_pairs.size());
for (size_t i = 0; i < edges.size(); ++i) {
for (size_t j = i + 1; j < edges.size(); ++j) {
if (ambiguous(begin[i].first, begin[j].first)) {
bool ok = false;
for (size_t k = 0; k < edges.size(); ++k) {
if (supercedes(begin[k].first, begin[i].first) && supercedes(begin[k].first, begin[j].first)) {
ok = true;
}
}
if (!ok) {
std::stringstream ss;
print_ids(ss, begin[i].first.size(), begin[i].first.data());
ss << " and ";
print_ids(ss, begin[j].first.size(), begin[j].first.data());
ss << " are ambiguous";
throw std::runtime_error(ss.str());
}
}
if (edge(begin[i].first, begin[j].first)) {
edges[i].push_back(j);
}
else if (edge(begin[j].first, begin[i].first)) {
edges[j].push_back(i);
}
}
}
topological_sort(begin, end, edges, m_pairs.begin());
m_map.clear();
}
void assign(std::initializer_list<pair_type> pairs) { assign(pairs.begin(), pairs.end()); }
template <typename Iterator>
void insert(Iterator begin, Iterator end)
{
std::vector<pair_type> vertices = m_pairs;
vertices.insert(vertices.end(), begin, end);
assign(vertices.begin(), vertices.end());
}
void insert(const pair_type &pair) { insert(&pair, &pair + 1); }
void insert(std::initializer_list<pair_type> pairs) { insert(pairs.begin(), pairs.end()); }
iterator begin() { return m_pairs.begin(); }
const_iterator begin() const { return m_pairs.begin(); }
const_iterator cbegin() const { return m_pairs.cbegin(); }
iterator end() { return m_pairs.end(); }
const_iterator end() const { return m_pairs.end(); }
const_iterator cend() const { return m_pairs.cend(); }
template <typename... IDTypes>
const value_type &operator()(IDTypes... ids)
{
size_t key = hash(ids...);
const auto &it = m_map.find(key);
if (it != m_map.end()) {
return it->second;
}
for (const pair_type &pair : m_pairs) {
if (supercedes({ids...}, pair.first)) {
return m_map[key] = pair.second;
}
}
throw std::out_of_range("signature not found");
}
const value_type &operator()(size_t nids, const type_id_t *ids)
{
size_t key = static_cast<size_t>(ids[0]);
for (size_t i = 1; i < nids; ++i) {
key = hash_combine(key, ids[i]);
}
const auto &it = m_map.find(key);
if (it != m_map.end()) {
return it->second;
}
for (const pair_type &pair : m_pairs) {
if (supercedes(nids, ids, pair.first)) {
return m_map[key] = pair.second;
}
}
throw std::out_of_range("signature not found");
}
const value_type &operator()(std::initializer_list<type_id_t> ids) { return operator()(ids.size(), ids.begin()); }
static bool edge(const std::vector<type_id_t> &u, const std::vector<type_id_t> &v)
{
if (supercedes(u, v)) {
if (supercedes(v, u)) {
return false;
}
else {
return true;
}
}
return false;
}
static size_t hash(type_id_t id) { return static_cast<size_t>(id); }
template <typename... IDTypes>
static size_t hash(type_id_t id0, IDTypes... ids)
{
return hash_combine(hash(id0), ids...);
}
};
}
namespace dynd {
namespace nd {
namespace detail {
__declspec(dllexport) std::map<std::string, callable> &get_regfunctions();
inline bool is_special_kwd(const ndt::callable_type *, array &dst, const std::string &name,
const nd::array &value) {
if (name == "dst_tp") {
dst = nd::empty(value.as<ndt::type>());
return true;
} else if (name == "dst") {
dst = value;
return true;
}
return false;
}
__declspec(dllexport) void check_narg(const ndt::callable_type *af_tp, intptr_t narg);
__declspec(dllexport) void check_arg(const ndt::callable_type *af_tp, intptr_t i, const ndt::type &actual_tp,
const char *actual_arrmeta, std::map<std::string, ndt::type> &tp_vars);
template <template <type_id_t...> class KernelType>
struct make_all;
template <template <type_id_t...> class KernelType>
struct new_make_all;
template <template <type_id_t...> class KernelType, template <type_id_t...> class Condition>
struct make_all_if;
}
typedef array callable_arg_t;
typedef std::pair<const char *, array> callable_kwd_t;
class __declspec(dllexport) callable : public intrusive_ptr<base_callable> {
public:
using intrusive_ptr<base_callable>::intrusive_ptr;
callable() = default;
template <typename CallableType, typename... T, typename = std::enable_if_t<all_char_string_params<T...>::value>>
callable(CallableType f, T &&... names)
: callable(new functional::apply_callable_callable<CallableType, arity_of<CallableType>::value - sizeof...(T)>(
f, std::forward<T>(names)...),
true) {}
bool is_null() const { return get() == 0; }
callable_property get_flags() const { return right_associative; }
const ndt::callable_type *get_type() const {
if (get() == 0) {
return 0;
}
return m_ptr->get_type().extended<ndt::callable_type>();
}
ndt::type resolve(const ndt::type &dst_tp, size_t nsrc, const ndt::type *src_tp, size_t nkwd, const array *kwds) {
std::map<std::string, ndt::type> tp_vars;
call_graph cg;
return m_ptr->resolve(nullptr, nullptr, cg, dst_tp, nsrc, src_tp, nkwd, kwds, tp_vars);
}
ndt::type resolve(const ndt::type &dst_tp, std::initializer_list<ndt::type> src_tp,
std::initializer_list<array> kwds) {
return resolve(dst_tp, src_tp.size(), src_tp.begin(), kwds.size(), kwds.begin());
}
ndt::type resolve(std::initializer_list<ndt::type> src_tp, std::initializer_list<array> kwds) {
return resolve(get_type()->get_return_type(), src_tp.size(), src_tp.begin(), kwds.size(), kwds.begin());
}
const ndt::type &get_array_type() const { return m_ptr->get_type(); }
const ndt::type &get_ret_type() const { return get_type()->get_return_type(); }
std::intptr_t get_narg() const { return get_type()->get_npos(); }
const ndt::type &get_arg_type(std::intptr_t i) const { return get_type()->get_pos_type(i); }
const std::vector<ndt::type> &get_arg_types() const { return get_type()->get_pos_types(); }
void overload(const ndt::type &ret_tp, intptr_t narg, const ndt::type *arg_tp, const callable &value) {
get()->overload(ret_tp, narg, arg_tp, value);
}
void overload(const ndt::type &ret_tp, const std::initializer_list<ndt::type> &arg_tp, const callable &value) {
overload(ret_tp, arg_tp.size(), arg_tp.begin(), value);
}
const callable &specialize(const ndt::type &ret_tp, intptr_t narg, const ndt::type *arg_tp) const {
return get()->specialize(ret_tp, narg, arg_tp);
}
const callable &specialize(const ndt::type &ret_tp, const std::initializer_list<ndt::type> &arg_tp) const {
return specialize(ret_tp, arg_tp.size(), arg_tp.begin());
}
array call(size_t args_size, const array *args_values, size_t kwds_size,
const std::pair<const char *, array> *kwds_values) const;
template <typename... ArgTypes>
array operator()(ArgTypes &&... args) const {
array tmp[sizeof...(ArgTypes)] = {std::forward<ArgTypes>(args)...};
return call(sizeof...(ArgTypes), tmp, 0, nullptr);
}
array operator()() const { return call(0, nullptr, 0, nullptr); }
array operator()(const std::initializer_list<array> &args,
const std::initializer_list<std::pair<const char *, array>> &kwds) const {
return call(args.size(), args.begin(), kwds.size(), kwds.begin());
}
template <template <type_id_t> class KernelType, typename I0, typename... A>
static dispatcher<callable> new_make_all(A &&... a) {
std::vector<std::pair<std::vector<type_id_t>, callable>> callables;
for_each<I0>(detail::new_make_all<KernelType>(), callables, std::forward<A>(a)...);
return dispatcher<callable>(callables.begin(), callables.end());
}
template <template <type_id_t> class KernelType, typename I0, typename... A>
static std::map<type_id_t, callable> make_all(A &&... a) {
std::map<type_id_t, callable> callables;
for_each<I0>(detail::make_all<KernelType>(), callables, std::forward<A>(a)...);
return callables;
}
template <template <type_id_t, type_id_t, type_id_t...> class KernelType, typename I0, typename I1, typename... I,
typename... A>
static std::map<std::array<type_id_t, 2 + sizeof...(I)>, callable> make_all(A &&... a) {
std::map<std::array<type_id_t, 2 + sizeof...(I)>, callable> callables;
for_each<typename outer<I0, I1, I...>::type>(detail::make_all<KernelType>(), callables, std::forward<A>(a)...);
return callables;
}
template <template <type_id_t, type_id_t, type_id_t...> class KernelType, typename I0, typename I1, typename... I,
typename... A>
static dispatcher<callable> new_make_all(A &&... a) {
std::vector<std::pair<std::vector<type_id_t>, callable>> callables;
for_each<typename outer<I0, I1, I...>::type>(detail::new_make_all<KernelType>(), callables,
std::forward<A>(a)...);
return dispatcher<callable>(callables.begin(), callables.end());
}
template <template <type_id_t> class KernelType, template <type_id_t> class Condition, typename I0, typename... A>
static dispatcher<callable> make_all_if(A &&... a) {
std::vector<std::pair<std::vector<type_id_t>, callable>> callables;
for_each<I0>(detail::make_all_if<KernelType, Condition>(), callables, std::forward<A>(a)...);
return dispatcher<callable>(callables.begin(), callables.end());
}
template <template <type_id_t, type_id_t, type_id_t...> class KernelType,
template <type_id_t, type_id_t, type_id_t...> class Condition, typename I0, typename I1, typename... I,
typename... A>
static dispatcher<callable> make_all_if(A &&... a) {
std::vector<std::pair<std::vector<type_id_t>, callable>> callables;
for_each<typename outer<I0, I1, I...>::type>(detail::make_all_if<KernelType, Condition>(), callables,
std::forward<A>(a)...);
return dispatcher<callable>(callables.begin(), callables.end());
}
};
template <typename CallableType, typename... ArgTypes>
std::enable_if_t<std::is_base_of<base_callable, CallableType>::value, callable> make_callable(ArgTypes &&... args) {
return callable(new CallableType(std::forward<ArgTypes>(args)...), true);
}
template <typename KernelType, typename... ArgTypes>
std::enable_if_t<std::is_base_of<base_kernel<KernelType>, KernelType>::value, callable>
make_callable(const ndt::type &tp) {
return make_callable<default_instantiable_callable<KernelType>>(tp);
}
inline std::ostream &operator<<(std::ostream &o, const callable &rhs) {
return o << "<callable <" << rhs->get_type() << "> at " << reinterpret_cast<const void *>(rhs.get()) << ">";
}
namespace detail {
template <template <type_id_t...> class KernelType, typename S>
struct apply;
template <template <type_id_t...> class KernelType, type_id_t... I>
struct apply<KernelType, type_id_sequence<I...>> {
typedef KernelType<I...> type;
};
template <template <type_id_t...> class KernelType>
struct make_all {
template <type_id_t TypeID, typename... A>
void on_each(std::map<type_id_t, callable> &callables, A &&... a) const {
callables[TypeID] = make_callable<KernelType<TypeID>>(std::forward<A>(a)...);
}
template <typename TypeIDSequence, typename... A>
void on_each(std::map<std::array<type_id_t, TypeIDSequence::size2()>, callable> &callables, A &&... a) const {
callables[i2a<TypeIDSequence>()] =
make_callable<typename apply<KernelType, TypeIDSequence>::type>(std::forward<A>(a)...);
}
};
template <template <type_id_t...> class KernelType>
struct new_make_all {
template <type_id_t TypeID, typename... A>
void on_each(std::vector<std::pair<std::vector<type_id_t>, callable>> &callables, A &&... a) const {
callables.push_back({{TypeID}, make_callable<KernelType<TypeID>>(std::forward<A>(a)...)});
}
template <typename TypeIDSequence, typename... A>
void on_each(std::vector<std::pair<std::vector<type_id_t>, callable>> &callables, A &&... a) const {
auto arr = i2a<TypeIDSequence>();
std::vector<type_id_t> v(arr.size());
for (size_t i = 0; i < arr.size(); ++i) {
v[i] = arr[i];
}
callables.push_back(
{{v}, make_callable<typename apply<KernelType, TypeIDSequence>::type>(std::forward<A>(a)...)});
}
};
template <template <type_id_t...> class KernelType, template <type_id_t...> class Condition>
struct make_all_if {
template <type_id_t TypeID, typename... A>
void on_each(std::vector<std::pair<std::vector<type_id_t>, callable>> &callables, A &&... a) const {
if (Condition<TypeID>::value) {
callables.push_back({{TypeID}, make_callable<KernelType<TypeID>>(std::forward<A>(a)...)});
}
}
template <typename TypeIDSequence, typename... A>
void on_each(std::vector<std::pair<std::vector<type_id_t>, callable>> &callables, A &&... a) const {
if (apply<Condition, TypeIDSequence>::type::value) {
auto arr = i2a<TypeIDSequence>();
std::vector<type_id_t> v;
for (size_t i = 0; i < arr.size(); ++i) {
v.push_back(arr[i]);
}
callables.push_back(
{{v}, make_callable<typename apply<KernelType, TypeIDSequence>::type>(std::forward<A>(a)...)});
}
}
};
}
__declspec(dllexport) std::map<std::string, callable> &callables();
}
__declspec(dllexport) nd::callable make_callable_from_assignment(const ndt::type &dst_tp, const ndt::type &src_tp,
assign_error_mode errmode);
}
namespace dynd {
namespace nd {
extern __declspec(dllexport) callable plus;
extern __declspec(dllexport) callable minus;
extern __declspec(dllexport) callable logical_not;
extern __declspec(dllexport) callable bitwise_not;
extern __declspec(dllexport) callable add;
extern __declspec(dllexport) callable subtract;
extern __declspec(dllexport) callable multiply;
extern __declspec(dllexport) callable divide;
extern __declspec(dllexport) callable logical_and;
extern __declspec(dllexport) callable logical_or;
extern __declspec(dllexport) callable compound_add;
extern __declspec(dllexport) callable compound_div;
extern __declspec(dllexport) callable sum;
}
}
namespace dynd {
namespace nd {
namespace functional {
template <typename func_type, func_type func, int N = arity_of<func_type>::value>
class apply_function_callable : public base_callable {
public:
template <typename... T>
apply_function_callable(T &&... names)
: base_callable(ndt::make_type<typename funcproto_of<func_type>::type>(std::forward<T>(names)...)) {}
ndt::type resolve(base_callable *, char *, call_graph &cg,
const ndt::type &dst_tp, size_t , const ndt::type *,
size_t nkwd, const array *kwds, const std::map<std::string, ndt::type> &) {
typedef apply_function_kernel<func_type, func, N> kernel_type;
cg.emplace_back([kwds = typename kernel_type::kwds_type(nkwd, kwds)](
kernel_builder & kb, kernel_request_t kernreq, const char *,
size_t , const char *const *src_arrmeta) {
kb.emplace_back<kernel_type>(kernreq, typename kernel_type::args_type(src_arrmeta, nullptr), kwds);
});
return dst_tp;
}
};
}
}
}
namespace dynd {
namespace detail {
template <typename>
struct sfinae_true : std::true_type {};
template <typename T> static auto plus_isdef_test(int )->sfinae_true<decltype(+ std::declval<T>())>; template <typename> static auto plus_isdef_test(long)->std::false_type; template <type_id_t Src0TypeID> struct isdef_plus : decltype(plus_isdef_test<typename type_of<Src0TypeID>::type>(0)) {};
__pragma(warning(push)) __pragma(warning(disable : 4146))
template <typename T> static auto minus_isdef_test(int )->sfinae_true<decltype(- std::declval<T>())>; template <typename> static auto minus_isdef_test(long)->std::false_type; template <type_id_t Src0TypeID> struct isdef_minus : decltype(minus_isdef_test<typename type_of<Src0TypeID>::type>(0)) {};
__pragma(warning(pop))
template <typename T> static auto logical_not_isdef_test(int )->sfinae_true<decltype(! std::declval<T>())>; template <typename> static auto logical_not_isdef_test(long)->std::false_type; template <type_id_t Src0TypeID> struct isdef_logical_not : decltype(logical_not_isdef_test<typename type_of<Src0TypeID>::type>(0)) {};
template <typename T> static auto bitwise_not_isdef_test(int )->sfinae_true<decltype(~ std::declval<T>())>; template <typename> static auto bitwise_not_isdef_test(long)->std::false_type; template <type_id_t Src0TypeID> struct isdef_bitwise_not : decltype(bitwise_not_isdef_test<typename type_of<Src0TypeID>::type>(0)) {};
template <typename T, typename U> static auto add_isdef_test(int )->sfinae_true<decltype(std::declval<T>() + std::declval<U>())>; template <typename, typename> static auto add_isdef_test(long)->std::false_type; template <type_id_t Src0TypeID, type_id_t Src1TypeID> struct isdef_add : decltype(add_isdef_test<typename type_of<Src0TypeID>::type, typename type_of<Src1TypeID>::type>(0)) {};
template <typename T, typename U> static auto subtract_isdef_test(int )->sfinae_true<decltype(std::declval<T>() - std::declval<U>())>; template <typename, typename> static auto subtract_isdef_test(long)->std::false_type; template <type_id_t Src0TypeID, type_id_t Src1TypeID> struct isdef_subtract : decltype(subtract_isdef_test<typename type_of<Src0TypeID>::type, typename type_of<Src1TypeID>::type>(0)) {};
template <typename T, typename U> static auto multiply_isdef_test(int )->sfinae_true<decltype(std::declval<T>() * std::declval<U>())>; template <typename, typename> static auto multiply_isdef_test(long)->std::false_type; template <type_id_t Src0TypeID, type_id_t Src1TypeID> struct isdef_multiply : decltype(multiply_isdef_test<typename type_of<Src0TypeID>::type, typename type_of<Src1TypeID>::type>(0)) {};
template <typename T, typename U> static auto divide_isdef_test(int )->sfinae_true<decltype(std::declval<T>() / std::declval<U>())>; template <typename, typename> static auto divide_isdef_test(long)->std::false_type; template <type_id_t Src0TypeID, type_id_t Src1TypeID> struct isdef_divide : decltype(divide_isdef_test<typename type_of<Src0TypeID>::type, typename type_of<Src1TypeID>::type>(0)) {};
template <typename T, typename U> static auto mod_isdef_test(int )->sfinae_true<decltype(std::declval<T>() % std::declval<U>())>; template <typename, typename> static auto mod_isdef_test(long)->std::false_type; template <type_id_t Src0TypeID, type_id_t Src1TypeID> struct isdef_mod : decltype(mod_isdef_test<typename type_of<Src0TypeID>::type, typename type_of<Src1TypeID>::type>(0)) {};
template <typename T, typename U> static auto bitwise_and_isdef_test(int )->sfinae_true<decltype(std::declval<T>() & std::declval<U>())>; template <typename, typename> static auto bitwise_and_isdef_test(long)->std::false_type; template <type_id_t Src0TypeID, type_id_t Src1TypeID> struct isdef_bitwise_and : decltype(bitwise_and_isdef_test<typename type_of<Src0TypeID>::type, typename type_of<Src1TypeID>::type>(0)) {};
template <typename T, typename U> static auto logical_and_isdef_test(int )->sfinae_true<decltype(std::declval<T>() && std::declval<U>())>; template <typename, typename> static auto logical_and_isdef_test(long)->std::false_type; template <type_id_t Src0TypeID, type_id_t Src1TypeID> struct isdef_logical_and : decltype(logical_and_isdef_test<typename type_of<Src0TypeID>::type, typename type_of<Src1TypeID>::type>(0)) {};
template <typename T, typename U> static auto bitwise_or_isdef_test(int )->sfinae_true<decltype(std::declval<T>() | std::declval<U>())>; template <typename, typename> static auto bitwise_or_isdef_test(long)->std::false_type; template <type_id_t Src0TypeID, type_id_t Src1TypeID> struct isdef_bitwise_or : decltype(bitwise_or_isdef_test<typename type_of<Src0TypeID>::type, typename type_of<Src1TypeID>::type>(0)) {};
template <typename T, typename U> static auto logical_or_isdef_test(int )->sfinae_true<decltype(std::declval<T>() || std::declval<U>())>; template <typename, typename> static auto logical_or_isdef_test(long)->std::false_type; template <type_id_t Src0TypeID, type_id_t Src1TypeID> struct isdef_logical_or : decltype(logical_or_isdef_test<typename type_of<Src0TypeID>::type, typename type_of<Src1TypeID>::type>(0)) {};
template <typename T, typename U> static auto bitwise_xor_isdef_test(int )->sfinae_true<decltype(std::declval<T>() ^ std::declval<U>())>; template <typename, typename> static auto bitwise_xor_isdef_test(long)->std::false_type; template <type_id_t Src0TypeID, type_id_t Src1TypeID> struct isdef_bitwise_xor : decltype(bitwise_xor_isdef_test<typename type_of<Src0TypeID>::type, typename type_of<Src1TypeID>::type>(0)) {};
template <typename T, typename U> static auto left_shift_isdef_test(int )->sfinae_true<decltype(std::declval<T>() << std::declval<U>())>; template <typename, typename> static auto left_shift_isdef_test(long)->std::false_type; template <type_id_t Src0TypeID, type_id_t Src1TypeID> struct isdef_left_shift : decltype(left_shift_isdef_test<typename type_of<Src0TypeID>::type, typename type_of<Src1TypeID>::type>(0)) {};
template <typename T, typename U> static auto right_shift_isdef_test(int )->sfinae_true<decltype(std::declval<T>() >> std::declval<U>())>; template <typename, typename> static auto right_shift_isdef_test(long)->std::false_type; template <type_id_t Src0TypeID, type_id_t Src1TypeID> struct isdef_right_shift : decltype(right_shift_isdef_test<typename type_of<Src0TypeID>::type, typename type_of<Src1TypeID>::type>(0)) {};
}
namespace nd {
namespace detail { template <type_id_t Src0TypeID> struct inline_plus { static auto f(typename type_of<Src0TypeID>::type a) { return + a; } }; }
__pragma(warning(push)) __pragma(warning(disable : 4146))
namespace detail { template <type_id_t Src0TypeID> struct inline_minus { static auto f(typename type_of<Src0TypeID>::type a) { return - a; } }; }
__pragma(warning(pop))
namespace detail { template <type_id_t Src0TypeID> struct inline_logical_not { static auto f(typename type_of<Src0TypeID>::type a) { return ! a; } }; }
namespace detail { template <type_id_t Src0TypeID> struct inline_bitwise_not { static auto f(typename type_of<Src0TypeID>::type a) { return ~ a; } }; }
namespace detail { template <type_id_t Src0TypeID, type_id_t Src1TypeID> struct inline_add { static auto f(typename type_of<Src0TypeID>::type a, typename type_of<Src1TypeID>::type b) { return a + b; } }; }
namespace detail { template <type_id_t Src0TypeID, type_id_t Src1TypeID> struct inline_subtract { static auto f(typename type_of<Src0TypeID>::type a, typename type_of<Src1TypeID>::type b) { return a - b; } }; }
namespace detail { template <type_id_t Src0TypeID, type_id_t Src1TypeID> struct inline_multiply { static auto f(typename type_of<Src0TypeID>::type a, typename type_of<Src1TypeID>::type b) { return a * b; } }; }
namespace detail { template <type_id_t Src0TypeID, type_id_t Src1TypeID> struct inline_bitwise_and { static auto f(typename type_of<Src0TypeID>::type a, typename type_of<Src1TypeID>::type b) { return a & b; } }; }
namespace detail { template <type_id_t Src0TypeID, type_id_t Src1TypeID> struct inline_logical_and { static auto f(typename type_of<Src0TypeID>::type a, typename type_of<Src1TypeID>::type b) { return a && b; } }; }
namespace detail { template <type_id_t Src0TypeID, type_id_t Src1TypeID> struct inline_bitwise_or { static auto f(typename type_of<Src0TypeID>::type a, typename type_of<Src1TypeID>::type b) { return a | b; } }; }
namespace detail { template <type_id_t Src0TypeID, type_id_t Src1TypeID> struct inline_logical_or { static auto f(typename type_of<Src0TypeID>::type a, typename type_of<Src1TypeID>::type b) { return a || b; } }; }
namespace detail { template <type_id_t Src0TypeID, type_id_t Src1TypeID> struct inline_bitwise_xor { static auto f(typename type_of<Src0TypeID>::type a, typename type_of<Src1TypeID>::type b) { return a ^ b; } }; }
namespace detail { template <type_id_t Src0TypeID, type_id_t Src1TypeID> struct inline_left_shift { static auto f(typename type_of<Src0TypeID>::type a, typename type_of<Src1TypeID>::type b) { return a << b; } }; }
namespace detail { template <type_id_t Src0TypeID, type_id_t Src1TypeID> struct inline_right_shift { static auto f(typename type_of<Src0TypeID>::type a, typename type_of<Src1TypeID>::type b) { return a >> b; } }; }
namespace detail {
template <type_id_t Src0TypeID, type_id_t Src1TypeID>
struct inline_logical_xor {
static auto f(typename type_of<Src0TypeID>::type a, typename type_of<Src1TypeID>::type b) { return (!a) ^ (!b); }
};
}
namespace detail {
template <type_id_t Src0TypeID, type_id_t Src1TypeID>
constexpr bool needs_zero_check() {
using Base0 = base_id_of<Src0TypeID>;
using Base1 = base_id_of<Src1TypeID>;
return ((Base0::value == bool_kind_id) || (Base0::value == int_kind_id) || (Base0::value == uint_kind_id)) &&
((Base1::value == bool_kind_id) || (Base1::value == int_kind_id) || (Base1::value == uint_kind_id));
}
}
namespace detail { template <type_id_t Src0TypeID, type_id_t Src1TypeID, bool check> struct inline_divide_base; template <type_id_t Src0TypeID, type_id_t Src1TypeID> struct inline_divide_base<Src0TypeID, Src1TypeID, true> { static auto f(typename type_of<Src0TypeID>::type a, typename type_of<Src1TypeID>::type b) { if (b == 0) { throw dynd::zero_division_error("Integer division or modulo by zero."); } return a / b; } }; template <type_id_t Src0TypeID, type_id_t Src1TypeID> struct inline_divide_base<Src0TypeID, Src1TypeID, false> { static auto f(typename type_of<Src0TypeID>::type a, typename type_of<Src1TypeID>::type b) { return a / b; } }; template <type_id_t Src0TypeID, type_id_t Src1TypeID> using inline_divide = inline_divide_base<Src0TypeID, Src1TypeID, needs_zero_check<Src0TypeID, Src1TypeID>()>; }
namespace detail { template <type_id_t Src0TypeID, type_id_t Src1TypeID, bool check> struct inline_mod_base; template <type_id_t Src0TypeID, type_id_t Src1TypeID> struct inline_mod_base<Src0TypeID, Src1TypeID, true> { static auto f(typename type_of<Src0TypeID>::type a, typename type_of<Src1TypeID>::type b) { if (b == 0) { throw dynd::zero_division_error("Integer division or modulo by zero."); } return a % b; } }; template <type_id_t Src0TypeID, type_id_t Src1TypeID> struct inline_mod_base<Src0TypeID, Src1TypeID, false> { static auto f(typename type_of<Src0TypeID>::type a, typename type_of<Src1TypeID>::type b) { return a % b; } }; template <type_id_t Src0TypeID, type_id_t Src1TypeID> using inline_mod = inline_mod_base<Src0TypeID, Src1TypeID, needs_zero_check<Src0TypeID, Src1TypeID>()>; }
}
namespace ndt {
__pragma(warning(push)) __pragma(warning(disable : 4146))
__pragma(warning(pop))
}
}
namespace dynd {
namespace nd {
template <type_id_t Src0TypeID, type_id_t Src1TypeID>
using add_callable = functional::apply_function_callable<decltype(&detail::inline_add<Src0TypeID, Src1TypeID>::f),
&detail::inline_add<Src0TypeID, Src1TypeID>::f>;
}
}
namespace dynd {
namespace nd {
class base_dispatch_callable : public base_callable {
public:
using base_callable::base_callable;
ndt::type resolve(base_callable *, char *, call_graph &cg,
const ndt::type &dst_tp, size_t nsrc, const ndt::type *src_tp, size_t nkwd, const array *kwds,
const std::map<std::string, ndt::type> &tp_vars) {
const callable &child = specialize(dst_tp, nsrc, src_tp);
return child->resolve(this, nullptr, cg, dst_tp.is_symbolic() ? child.get_ret_type() : dst_tp, nsrc, src_tp, nkwd,
kwds, tp_vars);
}
};
}
}
namespace dynd {
namespace nd {
template <size_t N>
class arithmetic_dispatch_callable;
template <>
class arithmetic_dispatch_callable<1> : public base_dispatch_callable {
dispatcher<callable> m_dispatcher;
public:
arithmetic_dispatch_callable(const ndt::type &tp, const dispatcher<callable> &dispatcher)
: base_dispatch_callable(tp), m_dispatcher(dispatcher)
{
}
void overload(const ndt::type &, intptr_t , const ndt::type *src_tp,
const callable &value)
{
m_dispatcher.insert({{src_tp[0].get_id()}, value});
}
const callable &specialize(const ndt::type &, intptr_t ,
const ndt::type *src_tp)
{
return m_dispatcher(src_tp[0].get_id());
}
};
template <>
class arithmetic_dispatch_callable<2> : public base_dispatch_callable {
dispatcher<callable> m_dispatcher;
public:
arithmetic_dispatch_callable(const ndt::type &tp, const dispatcher<callable> &dispatcher)
: base_dispatch_callable(tp), m_dispatcher(dispatcher)
{
}
void overload(const ndt::type &, intptr_t , const ndt::type *src_tp,
const callable &value)
{
m_dispatcher.insert({{src_tp[0].get_id(), src_tp[1].get_id()}, value});
}
const callable &specialize(const ndt::type &, intptr_t ,
const ndt::type *src_tp)
{
return m_dispatcher(src_tp[0].get_id(), src_tp[1].get_id());
}
};
}
}
namespace dynd {
namespace nd {
template <type_id_t Src0TypeID, type_id_t Src1TypeID>
using bitwise_and_callable =
functional::apply_function_callable<decltype(&detail::inline_bitwise_and<Src0TypeID, Src1TypeID>::f),
&detail::inline_bitwise_and<Src0TypeID, Src1TypeID>::f>;
}
}
namespace dynd {
namespace nd {
template <type_id_t Arg0ID>
using bitwise_not_callable = functional::apply_function_callable<decltype(&detail::inline_bitwise_not<Arg0ID>::f),
&detail::inline_bitwise_not<Arg0ID>::f>;
}
}
namespace dynd {
namespace nd {
template <type_id_t Src0TypeID, type_id_t Src1TypeID>
using bitwise_or_callable =
functional::apply_function_callable<decltype(&detail::inline_bitwise_or<Src0TypeID, Src1TypeID>::f),
&detail::inline_bitwise_or<Src0TypeID, Src1TypeID>::f>;
}
}
namespace dynd {
namespace nd {
template <type_id_t Src0TypeID, type_id_t Src1TypeID>
using bitwise_xor_callable =
functional::apply_function_callable<decltype(&detail::inline_bitwise_xor<Src0TypeID, Src1TypeID>::f),
&detail::inline_bitwise_xor<Src0TypeID, Src1TypeID>::f>;
}
}
namespace dynd {
namespace nd {
template <typename DstType, typename Src0Type, bool UseBinaryOperator>
struct compound_add_kernel;
template <typename DstType, typename Src0Type>
struct compound_add_kernel<DstType, Src0Type, false>
: base_strided_kernel<compound_add_kernel<DstType, Src0Type, false>, 1> {
typedef DstType dst_type;
typedef Src0Type src0_type;
void single(char *dst, char *const *src)
{
*reinterpret_cast<dst_type *>(dst) += *reinterpret_cast<src0_type *>(src[0]);
}
void strided(char *dst, std::intptr_t dst_stride, char *const *src, const std::intptr_t *src_stride,
std::size_t count)
{
char *src0 = src[0];
std::intptr_t src0_stride = src_stride[0];
for (std::size_t i = 0; i < count; ++i) {
*reinterpret_cast<dst_type *>(dst) += *reinterpret_cast<src0_type *>(src0);
dst += dst_stride;
src0 += src0_stride;
}
}
};
template <typename DstType, typename Src0Type>
struct compound_add_kernel<DstType, Src0Type, true>
: base_strided_kernel<compound_add_kernel<DstType, Src0Type, true>, 1> {
typedef DstType dst_type;
typedef Src0Type src0_type;
void single(char *dst, char *const *src)
{
*reinterpret_cast<dst_type *>(dst) =
static_cast<dst_type>(*reinterpret_cast<dst_type *>(dst) + *reinterpret_cast<src0_type *>(src[0]));
}
void strided(char *dst, std::intptr_t dst_stride, char *const *src, const std::intptr_t *src_stride,
std::size_t count)
{
char *src0 = src[0];
std::intptr_t src0_stride = src_stride[0];
for (std::size_t i = 0; i < count; ++i) {
*reinterpret_cast<dst_type *>(dst) =
static_cast<dst_type>(*reinterpret_cast<dst_type *>(dst) + *reinterpret_cast<src0_type *>(src0));
dst += dst_stride;
src0 += src0_stride;
}
}
};
template <typename Src0Type>
struct compound_add_kernel<bool1, Src0Type, true>
: base_strided_kernel<compound_add_kernel<bool1, Src0Type, true>, 1> {
typedef bool1 dst_type;
typedef Src0Type src0_type;
void single(char *dst, char *const *src)
{
*reinterpret_cast<dst_type *>(dst) =
*reinterpret_cast<dst_type *>(dst) + *reinterpret_cast<src0_type *>(src[0]) ? true : false;
}
void strided(char *dst, std::intptr_t dst_stride, char *const *src, const std::intptr_t *src_stride,
std::size_t count)
{
char *src0 = src[0];
std::intptr_t src0_stride = src_stride[0];
for (std::size_t i = 0; i < count; ++i) {
*reinterpret_cast<dst_type *>(dst) =
*reinterpret_cast<dst_type *>(dst) + *reinterpret_cast<src0_type *>(src0) ? true : false;
dst += dst_stride;
src0 += src0_stride;
}
}
};
template <type_id_t DstTypeID, type_id_t Src0TypeID>
struct compound_add_kernel_t
: compound_add_kernel<typename type_of<DstTypeID>::type, typename type_of<Src0TypeID>::type,
!is_lossless_assignable<DstTypeID, Src0TypeID>::value> {
};
}
}
namespace dynd {
namespace nd {
template <type_id_t DstTypeID, type_id_t Src0TypeID>
class compound_add_callable : public default_instantiable_callable<compound_add_kernel_t<DstTypeID, Src0TypeID>> {
public:
compound_add_callable()
: default_instantiable_callable<compound_add_kernel_t<DstTypeID, Src0TypeID>>(
ndt::callable_type::make(ndt::type(DstTypeID), ndt::type(Src0TypeID)))
{
}
};
}
}
namespace dynd {
namespace nd {
class compound_arithmetic_dispatch_callable : public base_dispatch_callable {
dispatcher<callable> m_dispatcher;
public:
compound_arithmetic_dispatch_callable(const ndt::type &tp, const dispatcher<callable> &dispatcher)
: base_dispatch_callable(tp), m_dispatcher(dispatcher)
{
}
void overload(const ndt::type &dst_tp, intptr_t , const ndt::type *src_tp, const callable &value)
{
m_dispatcher.insert({{dst_tp.get_id(), src_tp[0].get_id()}, value});
}
const callable &specialize(const ndt::type &dst_tp, intptr_t , const ndt::type *src_tp)
{
return m_dispatcher(dst_tp.get_id(), src_tp[0].get_id());
}
};
}
}
namespace dynd {
namespace nd {
template <typename DstType, typename Src0Type, bool UseBinaryOperator>
struct compound_div_kernel;
template <typename DstType, typename Src0Type>
struct compound_div_kernel<DstType, Src0Type, false>
: base_strided_kernel<compound_div_kernel<DstType, Src0Type, false>, 1> {
typedef DstType dst_type;
typedef Src0Type src0_type;
void single(char *dst, char *const *src)
{
*reinterpret_cast<dst_type *>(dst) /= *reinterpret_cast<src0_type *>(src[0]);
}
void strided(char *dst, std::intptr_t dst_stride, char *const *src, const std::intptr_t *src_stride,
std::size_t count)
{
char *src0 = src[0];
std::intptr_t src0_stride = src_stride[0];
for (std::size_t i = 0; i < count; ++i) {
*reinterpret_cast<dst_type *>(dst) /= *reinterpret_cast<src0_type *>(src0);
dst += dst_stride;
src0 += src0_stride;
}
}
};
template <typename DstType, typename Src0Type>
struct compound_div_kernel<DstType, Src0Type, true>
: base_strided_kernel<compound_div_kernel<DstType, Src0Type, true>, 1> {
typedef DstType dst_type;
typedef Src0Type src0_type;
void single(char *dst, char *const *src)
{
*reinterpret_cast<dst_type *>(dst) =
static_cast<dst_type>(*reinterpret_cast<dst_type *>(dst) / *reinterpret_cast<src0_type *>(src[0]));
}
void strided(char *dst, std::intptr_t dst_stride, char *const *src, const std::intptr_t *src_stride,
std::size_t count)
{
char *src0 = src[0];
std::intptr_t src0_stride = src_stride[0];
for (std::size_t i = 0; i < count; ++i) {
*reinterpret_cast<dst_type *>(dst) =
static_cast<dst_type>(*reinterpret_cast<dst_type *>(dst) / *reinterpret_cast<src0_type *>(src0));
dst += dst_stride;
src0 += src0_stride;
}
}
};
template <typename Src0Type>
struct compound_div_kernel<bool1, Src0Type, true>
: base_strided_kernel<compound_div_kernel<bool1, Src0Type, true>, 1> {
typedef bool1 dst_type;
typedef Src0Type src0_type;
void single(char *dst, char *const *src)
{
*reinterpret_cast<dst_type *>(dst) =
*reinterpret_cast<dst_type *>(dst) / *reinterpret_cast<src0_type *>(src[0]) ? true : false;
}
void strided(char *dst, std::intptr_t dst_stride, char *const *src, const std::intptr_t *src_stride,
std::size_t count)
{
char *src0 = src[0];
std::intptr_t src0_stride = src_stride[0];
for (std::size_t i = 0; i < count; ++i) {
*reinterpret_cast<dst_type *>(dst) =
*reinterpret_cast<dst_type *>(dst) / *reinterpret_cast<src0_type *>(src0) ? true : false;
dst += dst_stride;
src0 += src0_stride;
}
}
};
template <type_id_t DstTypeID, type_id_t Src0TypeID>
struct compound_div_kernel_t
: compound_div_kernel<typename type_of<DstTypeID>::type, typename type_of<Src0TypeID>::type,
!is_lossless_assignable<DstTypeID, Src0TypeID>::value> {
};
}
}
namespace dynd {
namespace nd {
template <type_id_t DstTypeID, type_id_t Src0TypeID>
class compound_div_callable : public default_instantiable_callable<compound_div_kernel_t<DstTypeID, Src0TypeID>> {
public:
compound_div_callable()
: default_instantiable_callable<compound_div_kernel_t<DstTypeID, Src0TypeID>>(
ndt::callable_type::make(ndt::type(DstTypeID), ndt::type(Src0TypeID)))
{
}
};
}
}
namespace dynd {
namespace nd {
template <type_id_t Arg0ID, type_id_t Arg1ID>
using divide_callable = functional::apply_function_callable<decltype(&detail::inline_divide<Arg0ID, Arg1ID>::f),
&detail::inline_divide<Arg0ID, Arg1ID>::f>;
}
}
namespace dynd {
namespace nd {
template <type_id_t Src0TypeID, type_id_t Src1TypeID>
using left_shift_callable =
functional::apply_function_callable<decltype(&detail::inline_left_shift<Src0TypeID, Src1TypeID>::f),
&detail::inline_left_shift<Src0TypeID, Src1TypeID>::f>;
}
}
namespace dynd {
namespace nd {
template <type_id_t Src0TypeID, type_id_t Src1TypeID>
using logical_and_callable =
functional::apply_function_callable<decltype(&detail::inline_logical_and<Src0TypeID, Src1TypeID>::f),
&detail::inline_logical_and<Src0TypeID, Src1TypeID>::f>;
}
}
namespace dynd {
namespace nd {
template <type_id_t Arg0ID>
using logical_not_callable = functional::apply_function_callable<decltype(&detail::inline_logical_not<Arg0ID>::f),
&detail::inline_logical_not<Arg0ID>::f>;
}
}
namespace dynd {
namespace nd {
template <type_id_t Src0TypeID, type_id_t Src1TypeID>
using logical_or_callable =
functional::apply_function_callable<decltype(&detail::inline_logical_or<Src0TypeID, Src1TypeID>::f),
&detail::inline_logical_or<Src0TypeID, Src1TypeID>::f>;
}
}
namespace dynd {
namespace nd {
template <type_id_t Src0TypeID, type_id_t Src1TypeID>
using logical_xor_callable =
functional::apply_function_callable<decltype(&detail::inline_logical_xor<Src0TypeID, Src1TypeID>::f),
&detail::inline_logical_xor<Src0TypeID, Src1TypeID>::f>;
}
}
namespace dynd {
namespace nd {
template <type_id_t Arg0ID, type_id_t Arg1ID>
using mod_callable = functional::apply_function_callable<decltype(&detail::inline_mod<Arg0ID, Arg1ID>::f),
&detail::inline_mod<Arg0ID, Arg1ID>::f>;
}
}
namespace dynd {
namespace nd {
template <type_id_t Arg0ID>
using minus_callable =
functional::apply_function_callable<decltype(&detail::inline_minus<Arg0ID>::f), &detail::inline_minus<Arg0ID>::f>;
}
}
namespace dynd {
namespace nd {
template <type_id_t Src0TypeID, type_id_t Src1TypeID>
using multiply_callable =
functional::apply_function_callable<decltype(&detail::inline_multiply<Src0TypeID, Src1TypeID>::f),
&detail::inline_multiply<Src0TypeID, Src1TypeID>::f>;
}
}
namespace dynd {
namespace nd {
template <type_id_t Arg0ID>
using plus_callable =
functional::apply_function_callable<decltype(&detail::inline_plus<Arg0ID>::f), &detail::inline_plus<Arg0ID>::f>;
}
}
namespace dynd {
namespace nd {
template <type_id_t Src0TypeID, type_id_t Src1TypeID>
using right_shift_callable =
functional::apply_function_callable<decltype(&detail::inline_right_shift<Src0TypeID, Src1TypeID>::f),
&detail::inline_right_shift<Src0TypeID, Src1TypeID>::f>;
}
}
namespace dynd {
namespace nd {
template <type_id_t Src0TypeID, type_id_t Src1TypeID>
using subtract_callable =
functional::apply_function_callable<decltype(&detail::inline_subtract<Src0TypeID, Src1TypeID>::f),
&detail::inline_subtract<Src0TypeID, Src1TypeID>::f>;
}
}
namespace dynd {
namespace nd {
template <type_id_t Src0TypeID>
struct __declspec(dllexport) sum_kernel : base_strided_kernel<sum_kernel<Src0TypeID>, 1> {
typedef typename type_of<Src0TypeID>::type src0_type;
typedef src0_type dst_type;
void single(char *dst, char *const *src)
{
*reinterpret_cast<dst_type *>(dst) = *reinterpret_cast<dst_type *>(dst) + *reinterpret_cast<src0_type *>(src[0]);
}
void strided(char *dst, intptr_t dst_stride, char *const *src, const intptr_t *src_stride, size_t count)
{
char *src0 = src[0];
intptr_t src0_stride = src_stride[0];
for (size_t i = 0; i < count; ++i) {
*reinterpret_cast<dst_type *>(dst) = *reinterpret_cast<dst_type *>(dst) + *reinterpret_cast<src0_type *>(src0);
dst += dst_stride;
src0 += src0_stride;
}
}
};
}
}
namespace dynd {
namespace nd {
template <type_id_t Arg0ID>
class sum_callable : public default_instantiable_callable<sum_kernel<Arg0ID>> {
public:
sum_callable()
: default_instantiable_callable<sum_kernel<Arg0ID>>(
ndt::callable_type::make(ndt::make_type<typename nd::sum_kernel<Arg0ID>::dst_type>(), ndt::type(Arg0ID)))
{
}
};
}
}
namespace dynd {
namespace nd {
class sum_dispatch_callable : public base_dispatch_callable {
dispatcher<callable> m_dispatcher;
public:
sum_dispatch_callable(const ndt::type &tp, const dispatcher<callable> &dispatcher)
: base_dispatch_callable(tp), m_dispatcher(dispatcher)
{
}
void overload(const ndt::type &, intptr_t , const ndt::type *src_tp,
const callable &value)
{
m_dispatcher.insert({{src_tp[0].get_dtype().get_id()}, value});
}
const callable &specialize(const ndt::type &, intptr_t ,
const ndt::type *src_tp)
{
return m_dispatcher(src_tp[0].get_dtype().get_id());
}
};
}
}
namespace dynd {
namespace nd {
namespace functional {
template <typename T, typename mem_func_type, int N>
class apply_member_function_callable : public base_callable {
T m_obj;
mem_func_type m_mem_func;
public:
template <typename... S>
apply_member_function_callable(T obj, mem_func_type mem_func, S &&... names)
: base_callable(ndt::make_type<mem_func_type>(std::forward<S>(names)...)), m_obj(obj), m_mem_func(mem_func) {}
ndt::type resolve(base_callable *, char *, call_graph &cg,
const ndt::type &dst_tp, size_t , const ndt::type *,
size_t nkwd, const array *kwds, const std::map<std::string, ndt::type> &) {
typedef apply_member_function_kernel<T, mem_func_type, N> kernel_type;
cg.emplace_back([ obj = m_obj, mem_func = m_mem_func, kwds = typename kernel_type::kwds_type(nkwd, kwds) ](
kernel_builder &kb, kernel_request_t kernreq, const char *,
size_t , const char *const *src_arrmeta) {
kb.emplace_back<kernel_type>(kernreq, obj, mem_func, typename kernel_type::args_type(src_arrmeta, nullptr),
kwds);
});
return dst_tp;
}
};
}
}
}
namespace dynd {
namespace nd {
namespace functional {
template <typename func_type, typename... KwdTypes>
class construct_then_apply_callable_callable : public base_callable {
public:
template <typename... T>
construct_then_apply_callable_callable(T &&... names)
: base_callable(
ndt::make_type<typename funcproto_of<func_type, KwdTypes...>::type>(std::forward<T>(names)...)) {}
ndt::type resolve(base_callable *, char *, call_graph &cg,
const ndt::type &dst_tp, size_t , const ndt::type *,
size_t nkwd, const array *kwds, const std::map<std::string, ndt::type> &) {
typedef construct_then_apply_callable_kernel<func_type, KwdTypes...> kernel_type;
cg.emplace_back([kwds = typename kernel_type::kwds_type(nkwd, kwds)](
kernel_builder &kb, kernel_request_t kernreq, const char *,
size_t , const char *const *src_arrmeta) {
kb.emplace_back<kernel_type>(kernreq, typename kernel_type::args_type(src_arrmeta, nullptr), kwds);
});
return dst_tp;
}
};
}
}
}
namespace dynd {
template <typename ValueType>
struct option {
ValueType value;
option() : value(ndt::traits<ValueType>::na()) {}
option(ValueType value) : value(value) {}
};
template <typename ValueType>
option<ValueType> opt()
{
return option<ValueType>();
}
template <typename ValueType>
option<ValueType> opt(ValueType value)
{
return option<ValueType>(value);
}
__declspec(dllimport) void assign_na_builtin(type_id_t value_id, char *data);
__declspec(dllimport) bool is_avail_builtin(type_id_t value_id, const char *data);
namespace ndt {
class __declspec(dllimport) option_type : public base_type {
type m_value_tp;
public:
option_type(const type &value_tp);
size_t get_default_data_size() const { return m_value_tp.get_default_data_size(); }
void get_vars(std::unordered_set<std::string> &vars) const;
const type &get_value_type() const { return m_value_tp.value_type(); }
void print_type(std::ostream &o) const;
void print_data(std::ostream &o, const char *arrmeta, const char *data) const;
bool is_expression() const;
bool is_unique_data_owner(const char *arrmeta) const;
void transform_child_types(type_transform_fn_t transform_fn, intptr_t arrmeta_offset, void *extra,
type &out_transformed_tp, bool &out_was_transformed) const;
type get_canonical_type() const;
type get_type_at_dimension(char **inout_arrmeta, intptr_t i, intptr_t total_ndim = 0) const;
bool is_lossless_assignment(const type &dst_tp, const type &src_tp) const;
bool operator==(const base_type &rhs) const;
void arrmeta_default_construct(char *arrmeta, bool blockref_alloc) const;
void arrmeta_copy_construct(char *dst_arrmeta, const char *src_arrmeta,
const intrusive_ptr<memory_block_data> &embedded_reference) const;
void arrmeta_reset_buffers(char *arrmeta) const;
void arrmeta_finalize_buffers(char *arrmeta) const;
void arrmeta_destruct(char *arrmeta) const;
void arrmeta_debug_print(const char *arrmeta, std::ostream &o, const std::string &indent) const;
void data_destruct(const char *arrmeta, char *data) const;
void data_destruct_strided(const char *arrmeta, char *data, intptr_t stride, size_t count) const;
bool match(const type &candidate_tp, std::map<std::string, type> &tp_vars) const;
std::map<std::string, std::pair<ndt::type, const char *>> get_dynamic_type_properties() const;
};
template <typename ValueType>
struct traits<option<ValueType>> {
static const bool is_same_layout = true;
static type equivalent() { return make_type<option_type>(make_type<ValueType>()); }
};
}
}
namespace dynd {
namespace nd {
extern __declspec(dllexport) callable assign_na;
extern __declspec(dllexport) callable is_na;
__declspec(dllexport) void old_assign_na(const ndt::type &option_tp, const char *arrmeta, char *data);
__declspec(dllexport) bool old_is_avail(const ndt::type &option_tp, const char *arrmeta, const char *data);
__declspec(dllexport) void set_option_from_utf8_string(const ndt::type &option_tp, const char *arrmeta, char *data,
const char *utf8_begin, const char *utf8_end,
const eval::eval_context *ectx);
inline void set_option_from_utf8_string(const ndt::type &option_tp, const char *arrmeta, char *data,
const std::string &utf8_str, const eval::eval_context *ectx)
{
set_option_from_utf8_string(option_tp, arrmeta, data, utf8_str.data(), utf8_str.data() + utf8_str.size(), ectx);
}
}
}
namespace dynd {
namespace nd {
template <intptr_t... I>
struct forward_na_kernel : base_strided_kernel<forward_na_kernel<I...>, 2> {
size_t is_na_offset[2];
size_t assign_na_offset;
void single(char *res, char *const *args) {
// Next non-comment line builds if replaced with:
// for (intptr_t i : std::array<intptr_t, sizeof...(I)>({I...})) {
for (intptr_t i : {I...}) {
bool1 is_na;
this->get_child(is_na_offset[i])->single(reinterpret_cast<char *>(&is_na), args + i);
if (is_na) {
return this->get_child(assign_na_offset)->single(res, nullptr);
}
}
this->get_child()->single(res, args);
}
};
}
}
namespace dynd {
namespace nd {
typedef intptr_t index_t;
template <index_t... I>
class forward_na_callable : public base_callable {
callable m_child;
public:
forward_na_callable(const ndt::type &tp, const callable &child) : base_callable(tp), m_child(child) {}
ndt::type resolve(base_callable *caller, char *, call_graph &cg, const ndt::type &dst_tp,
size_t , const ndt::type *src_tp, size_t nkwd, const array *kwds,
const std::map<std::string, ndt::type> &tp_vars) {
cg.emplace_back([](kernel_builder &kb, kernel_request_t kernreq, const char *dst_arrmeta, size_t nsrc,
const char *const *src_arrmeta) {
size_t self_offset = kb.size();
kb.emplace_back<forward_na_kernel<I...>>(kernreq);
kb(kernel_request_single, dst_arrmeta, nsrc, src_arrmeta);
for (intptr_t i : std::array<index_t, sizeof...(I)>({I...})) {
size_t is_na_offset = kb.size() - self_offset;
kb(kernel_request_single, nullptr, 1, src_arrmeta + i);
kb.get_at<forward_na_kernel<I...>>(self_offset)->is_na_offset[i] = is_na_offset;
}
size_t assign_na_offset = kb.size() - self_offset;
kb(kernel_request_single, nullptr, 0, nullptr);
kb.get_at<forward_na_kernel<I...>>(self_offset)->assign_na_offset = assign_na_offset;
});
ndt::type src_value_tp[2];
for (intptr_t i = 0; i < 2; ++i) {
src_value_tp[i] = src_tp[i];
}
for (intptr_t i : std::array<index_t, sizeof...(I)>({I...})) {
src_value_tp[i] = src_value_tp[i].extended<ndt::option_type>()->get_value_type();
}
base_callable *child;
if (m_child.is_null()) {
child = caller;
} else {
child = m_child.get();
}
ndt::type res_value_tp =
child->resolve(this, nullptr, cg, dst_tp.is_symbolic() ? child->get_return_type() : dst_tp, 2, src_value_tp,
nkwd, kwds, tp_vars);
for (index_t i : std::array<index_t, sizeof...(I)>({I...})) {
is_na->resolve(this, nullptr, cg, ndt::make_type<bool>(), 1, src_tp + i, 0, nullptr, tp_vars);
}
return assign_na->resolve(this, nullptr, cg, ndt::make_type<ndt::option_type>(res_value_tp), 0, nullptr, nkwd,
kwds, tp_vars);
}
};
}
}
namespace dynd {
namespace nd {
namespace functional {
__declspec(dllexport) callable adapt(const ndt::type &value_tp, const callable &forward);
template <typename func_type, func_type func, typename... T>
callable apply(T &&... names) {
return make_callable<apply_function_callable<func_type, func, arity_of<func_type>::value - sizeof...(T)>>(
std::forward<T>(names)...);
}
template <typename func_type, typename... T>
typename std::enable_if<!is_function_pointer<func_type>::value, callable>::type apply(func_type func,
T &&... names) {
static_assert(all_char_string_params<T...>::value, "All the names must be strings");
return make_callable<apply_callable_callable<func_type, arity_of<func_type>::value - sizeof...(T)>>(
func, std::forward<T>(names)...);
}
template <typename func_type, typename... T>
callable apply(func_type *func, T &&... names) {
return make_callable<apply_callable_callable<func_type *, arity_of<func_type>::value - sizeof...(T)>>(
func, std::forward<T>(names)...);
}
template <typename func_type, typename... KwdTypes, typename... T>
callable apply(T &&... names) {
return make_callable<construct_then_apply_callable_callable<func_type, KwdTypes...>>(std::forward<T>(names)...);
}
template <typename T, typename R, typename... A, typename... S>
callable apply(T *obj, R (T::*mem_func)(A...), S &&... names) {
return make_callable<apply_member_function_callable<T *, R (T::*)(A...), sizeof...(A) - sizeof...(S)>>(
obj, mem_func, std::forward<S>(names)...);
}
__declspec(dllexport) callable compose(const callable &first, const callable &second, const ndt::type &buf_tp = ndt::type());
__declspec(dllexport) callable constant(const array &val);
__declspec(dllexport) callable left_compound(const callable &child);
__declspec(dllexport) callable right_compound(const callable &child);
__declspec(dllexport) callable elwise(const callable &child);
__declspec(dllexport) callable elwise(const ndt::type &tp);
__declspec(dllexport) callable elwise(const ndt::type &self_tp, const callable &child);
__declspec(dllexport) ndt::type elwise_make_type(const ndt::callable_type *child_tp);
template <int... I>
callable forward_na(const ndt::type &ret_tp) {
ndt::type tp =
ndt::callable_type::make(ndt::make_type<ndt::option_type>(ret_tp), {ndt::type("Any"), ndt::type("Any")});
return make_callable<forward_na_callable<I...>>(tp, callable());
}
template <int... I>
callable forward_na(const callable &child) {
ndt::type tp = ndt::callable_type::make(ndt::make_type<ndt::option_type>(child.get_ret_type()),
{ndt::type("Any"), ndt::type("Any")});
return make_callable<forward_na_callable<I...>>(tp, child);
}
__declspec(dllexport) callable outer(const callable &child);
__declspec(dllexport) ndt::type outer_make_type(const ndt::callable_type *child_tp);
__declspec(dllexport) callable neighborhood(const callable &child, const callable &boundary_child = callable());
__declspec(dllexport) callable reduction(const callable &child);
__declspec(dllexport) callable reduction(const callable &child,
const std::initializer_list<std::pair<const char *, array>> &kwds);
}
}
}
namespace dynd {
namespace ndt {
class __declspec(dllimport) scalar_kind_type : public base_type {
public:
scalar_kind_type();
bool operator==(const base_type &rhs) const;
bool match(const type &candidate_tp, std::map<std::string, type> &tp_vars) const;
void print_type(std::ostream &o) const;
static type make() { return type(new scalar_kind_type(), false); }
};
}
}
using namespace std;
using namespace dynd;
namespace {
typedef type_id_sequence<uint8_id, uint16_id, uint32_id, uint64_id, int8_id, int16_id, int32_id, int64_id, float32_id,
float64_id, complex_float32_id, complex_float64_id>
binop_ids;
typedef type_id_sequence<uint8_id, uint16_id, uint32_id, uint64_id, int8_id, int16_id, int32_id, int64_id, float32_id,
float64_id>
binop_real_ids;
template <template <type_id_t> class CallableType, template <type_id_t> class Condition, typename TypeIDSequence>
nd::callable make_unary_arithmetic() {
dispatcher<nd::callable> dispatcher = nd::callable::make_all_if<CallableType, Condition, TypeIDSequence>();
const ndt::type &tp = ndt::type("(Any) -> Any");
for (type_id_t i0 : i2a<dim_ids>()) {
dispatcher.insert({{i0}, nd::functional::elwise(tp)});
}
return nd::make_callable<nd::arithmetic_dispatch_callable<1>>(tp, dispatcher);
}
template <template <type_id_t, type_id_t> class KernelType, template <type_id_t, type_id_t> class Condition,
typename TypeIDSequence>
nd::callable make_binary_arithmetic() {
const ndt::type &tp = ndt::type("(Any, Any) -> Any");
auto dispatcher = nd::callable::make_all_if<KernelType, Condition, TypeIDSequence, TypeIDSequence>();
dispatcher.insert({{{option_id, any_kind_id}, nd::functional::forward_na<0>(ndt::type("Any"))},
{{any_kind_id, option_id}, nd::functional::forward_na<1>(ndt::type("Any"))},
{{option_id, option_id}, nd::functional::forward_na<0, 1>(ndt::type("Any"))},
{{dim_kind_id, scalar_kind_id}, nd::functional::elwise(tp)},
{{scalar_kind_id, dim_kind_id}, nd::functional::elwise(tp)},
{{dim_kind_id, dim_kind_id}, nd::functional::elwise(tp)}});
return nd::make_callable<nd::arithmetic_dispatch_callable<2>>(tp, dispatcher);
}
template <template <type_id_t, type_id_t> class KernelType, typename TypeIDSequence>
nd::callable make_compound_arithmetic() {
const ndt::type &tp = ndt::type("(Any, Any) -> Any");
auto dispatcher = nd::callable::new_make_all<KernelType, TypeIDSequence, TypeIDSequence>();
for (type_id_t i0 : i2a<TypeIDSequence>()) {
for (type_id_t i1 : i2a<dim_ids>()) {
dispatcher.insert({{i0, i1}, nd::functional::elwise(tp)});
}
}
for (type_id_t i0 : i2a<dim_ids>()) {
typedef typename join<TypeIDSequence, dim_ids>::type broadcast_ids;
for (type_id_t i1 : i2a<broadcast_ids>()) {
dispatcher.insert({{i0, i1}, nd::functional::elwise(tp)});
}
}
return nd::make_callable<nd::compound_arithmetic_dispatch_callable>(tp, dispatcher);
}
}
__declspec(dllexport) nd::callable nd::plus = make_unary_arithmetic<nd::plus_callable, dynd::detail::isdef_plus, arithmetic_ids>();
__declspec(dllexport) nd::callable nd::minus =
make_unary_arithmetic<nd::minus_callable, dynd::detail::isdef_minus, arithmetic_ids>();
__declspec(dllexport) nd::callable nd::logical_not =
make_unary_arithmetic<nd::logical_not_callable, dynd::detail::isdef_logical_not, arithmetic_ids>();
__declspec(dllexport) nd::callable nd::bitwise_not =
make_unary_arithmetic<nd::bitwise_not_callable, dynd::detail::isdef_bitwise_not, integral_ids>();
__declspec(dllexport) nd::callable nd::add = make_binary_arithmetic<nd::add_callable, dynd::detail::isdef_add, binop_ids>();
__declspec(dllexport) nd::callable nd::subtract =
make_binary_arithmetic<nd::subtract_callable, dynd::detail::isdef_subtract, binop_ids>();
__declspec(dllexport) nd::callable nd::multiply =
make_binary_arithmetic<nd::multiply_callable, dynd::detail::isdef_multiply, binop_ids>();
__declspec(dllexport) nd::callable nd::divide = make_binary_arithmetic<nd::divide_callable, dynd::detail::isdef_divide, binop_ids>();
__declspec(dllexport) nd::callable nd::logical_and =
make_binary_arithmetic<nd::logical_and_callable, dynd::detail::isdef_logical_and, binop_real_ids>();
__declspec(dllexport) nd::callable nd::logical_or =
make_binary_arithmetic<nd::logical_or_callable, dynd::detail::isdef_logical_or, binop_real_ids>();
__declspec(dllexport) nd::callable nd::compound_add = make_compound_arithmetic<nd::compound_add_callable, binop_ids>();
__declspec(dllexport) nd::callable nd::compound_div = make_compound_arithmetic<nd::compound_div_callable, binop_ids>();
__declspec(dllexport) nd::callable nd::sum = nd::functional::reduction(nd::make_callable<nd::sum_dispatch_callable>(
ndt::callable_type::make(ndt::scalar_kind_type::make(), ndt::scalar_kind_type::make()),
nd::callable::new_make_all<
nd::sum_callable,
type_id_sequence<int8_id, int16_id, int32_id, int64_id, uint8_id, uint16_id, uint32_id, uint64_id, float16_id,
float32_id, float64_id, complex_float32_id, complex_float64_id>>()));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment