chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:47:05 +08:00
commit 4f3b7da785
7394 changed files with 2005594 additions and 0 deletions
@@ -0,0 +1,40 @@
/* ******************************************************************************
*
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
******************************************************************************/
//
// @author raver119@gmail.com
//
#ifndef SAMEDIFF_BLASVERSIONHELPER_H
#define SAMEDIFF_BLASVERSIONHELPER_H
#include <system/common.h>
namespace sd {
class SD_LIB_EXPORT BlasVersionHelper {
public:
int _blasMajorVersion = 0;
int _blasMinorVersion = 0;
int _blasPatchVersion = 0;
BlasVersionHelper();
~BlasVersionHelper() = default;
};
} // namespace sd
#endif // DEV_TESTS_BLASVERSIONHELPER_H
+40
View File
@@ -0,0 +1,40 @@
//
// Created by agibsonccc on 4/11/25.
//
/* ******************************************************************************
*
* Copyright (c) 2024 Konduit K.K.
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
******************************************************************************/
//
// @author Adam Gibson
//
#ifndef LIBND4J_CUDALIMITTYPE_H
#define LIBND4J_CUDALIMITTYPE_H
#ifndef __JAVACPP_HACK__
enum CudaLimitType {
CUDA_LIMIT_STACK_SIZE = 0,
CUDA_LIMIT_MALLOC_HEAP_SIZE = 1,
CUDA_LIMIT_PRINTF_FIFO_SIZE = 2,
CUDA_LIMIT_DEV_RUNTIME_SYNC_DEPTH = 3,
CUDA_LIMIT_DEV_RUNTIME_PENDING_LAUNCH_COUNT = 4,
CUDA_LIMIT_MAX_L2_FETCH_GRANULARITY = 5,
CUDA_LIMIT_PERSISTING_L2_CACHE_SIZE = 6
};
#endif
#endif // LIBND4J_CUDALIMITTYPE_H
+364
View File
@@ -0,0 +1,364 @@
/* ******************************************************************************
*
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
******************************************************************************/
//
// Created by raver119 on 06.10.2017.
//
#ifndef LIBND4J_ENVIRONMENT_H
#define LIBND4J_ENVIRONMENT_H
#include <array/DataType.h>
#include <types/pair.h>
#include <atomic>
#include <stdexcept>
#include <vector>
#include <config.h>
#ifdef SD_CUDA
#include <cuda.h>
#include <cuda_runtime.h>
#include "CudaLimitType.h"
#endif
namespace sd {
class SD_LIB_EXPORT Environment {
private:
std::atomic<int> _tadThreshold;
std::atomic<int> _elementThreshold;
std::atomic<bool> _verbose;
std::atomic<bool> _debug;
std::atomic<bool> _leaks;
std::atomic<bool> _profile;
std::atomic<sd::DataType> _dataType;
std::atomic<bool> _precBoost;
std::atomic<bool> _useONEDNN{true};
std::atomic<bool> _allowHelpers{true};
std::atomic<bool> funcTracePrintDeallocate;
std::atomic<bool> funcTracePrintAllocate;
// NDArray lifecycle tracking fields
// Prevents backward-cpp crashes during early JVM initialization
// Can be enabled via SD_LIFECYCLE_TRACKING=1 env var after JVM is ready
std::atomic<bool> _lifecycleTracking{false};
std::atomic<bool> _trackViews{true};
std::atomic<bool> _trackDeletions{true};
std::atomic<int> _stackDepth{32};
std::atomic<int> _reportInterval{300};
std::atomic<size_t> _maxDeletionHistory{10000};
std::atomic<bool> _snapshotFiles{false}; // Default off - only write snapshots on demand
std::atomic<bool> _trackOperations{false}; // Default off - operation tracking adds overhead
std::atomic<int> _maxThreads;
std::atomic<int> _maxMasterThreads;
std::atomic<bool> deleteSpecial{true};
std::atomic<bool> deletePrimary{true};
std::atomic<bool> deleteShapeInfo{true};
std::atomic<bool> _checkInputChange{false};
std::atomic<bool> _checkOutputChange{false};
std::atomic<bool> _logNDArrayEvenuts{false};
std::atomic<bool> _logNativeNDArrayCreation{false};
// these fields hold defaults
std::atomic<int64_t> _maxTotalPrimaryMemory{-1};
std::atomic<int64_t> _maxTotalSpecialMemory{-1};
std::atomic<int64_t> _maxDeviceMemory{-1};
bool _blasFallback = false;
std::atomic<bool> _enableBlasFall{true};
#ifdef SD_EXPERIMENTAL_ENABLED
const bool _experimental = true;
#else
const bool _experimental = false;
#endif
// device compute capability for CUDA
std::vector<Pair> _capabilities;
// CUDA specific environment configurations
std::atomic<int> _cudaDeviceCount{0};
std::atomic<int> _cudaCurrentDevice{0};
std::atomic<bool> _cudaMemoryPinned{false};
std::atomic<bool> _cudaUseManagedMemory{false};
std::atomic<int> _cudaMemoryPoolSize{0}; // in MB
std::atomic<bool> _cudaForceP2P{false};
std::atomic<bool> _cudaAllocatorEnabled{true};
std::atomic<int> _cudaMaxBlocks{0};
std::atomic<int> _cudaMaxThreadsPerBlock{0};
std::atomic<bool> _cudaAsyncExecution{true};
std::atomic<int> _cudaStreamLimit{4};
std::atomic<bool> _cudaUseDeviceHost{false};
std::atomic<int> _cudaEventLimit{4};
std::atomic<int> _cudaCachingAllocatorLimit{0}; // in MB
std::atomic<bool> _cudaUseUnifiedMemory{false};
std::atomic<int> _cudaPrefetchSize{0}; // in MB
std::atomic<bool> _cudaGraphOptimization{false};
std::atomic<bool> _cudaTensorCoreEnabled{true};
std::atomic<int> _cudaBlockingSync{0};
std::atomic<int> _cudaDeviceSchedule{0}; // 0: default, 1: spin, 2: yield, 3: block
// CUDA Device Limit configurations
std::atomic<size_t> _cudaStackSize{0}; // cudaLimitStackSize
std::atomic<size_t> _cudaMallocHeapSize{0}; // cudaLimitMallocHeapSize
std::atomic<size_t> _cudaPrintfFifoSize{0}; // cudaLimitPrintfFifoSize
std::atomic<size_t> _cudaDevRuntimeSyncDepth{0}; // cudaLimitDevRuntimeSyncDepth
std::atomic<size_t> _cudaDevRuntimePendingLaunchCount{0}; // cudaLimitDevRuntimePendingLaunchCount
std::atomic<size_t> _cudaMaxL2FetchGranularity{0}; // cudaLimitMaxL2FetchGranularity
std::atomic<size_t> _cudaPersistingL2CacheSize{0}; // cudaLimitPersistingL2CacheSize
Environment();
public:
~Environment();
/**
* These 3 fields are mostly for CUDA/cuBLAS version tracking
*/
int _blasMajorVersion = 0;
int _blasMinorVersion = 0;
int _blasPatchVersion = 0;
static Environment& getInstance();
bool isEnableBlas() {
return _enableBlasFall.load();
}
void setEnableBlas(bool reallyEnable) {
_enableBlasFall.store(reallyEnable);
}
/**
* When log ndarray evens is true in c++
* certain features of ndarray logging will trigger such as what ndarray constructors are being called.
* A great use case for this is for detecting subtle changes in ndarrays like move constructor calls
* which can cause the underlying data to change.
* @return
*/
bool isLogNativeNDArrayCreation();
void setLogNativeNDArrayCreation(bool logNativeNDArrayCreation);
/**
* This is mostly a java feature. We can use this to build a framework
* for logging ndarray events from c++ later.
* @return
*/
bool isLogNDArrayEvents();
void setLogNDArrayEvents(bool logNDArrayEvents);
/**
* This is mainly for debugging. This toggles
* deletion of shape info descriptors.
* This can be used to isolate potential issues with shape info
* memory management.
* The next concern is why have this at all?
* Historically, we had issues with shape descriptors and shape info
* buffers being deallocated when they shouldn't be due to stack based deallocation.
* By controlling everything with normal heap allocation, manual deletes and configurable behavior
* we can keep memory management consistent and predictable.
*/
bool isDeleteSpecial();
void setDeleteSpecial(bool reallyDelete);
bool isDeletePrimary();
void setDeletePrimary(bool reallyDelete);
/**
* Checks whether the outputs of the op have changed
* by duplicating them before and after the op runs
* if it doesn't change it throws an exception.
* @return
*/
bool isCheckOutputChange();
void setCheckOutputChange(bool reallyCheck);
/**
* Checks whether immutable ops changed their inputs by
* duplicating each input and ensuring they're still equal after the op runs.
* @return
*/
bool isCheckInputChange();
void setCheckInputChange(bool reallyCheck);
bool isVerbose();
void setVerbose(bool reallyVerbose);
bool isDebug();
bool isProfiling();
bool isDetectingLeaks();
bool isDebugAndVerbose();
void setDebug(bool reallyDebug);
void setProfiling(bool reallyProfile);
void setLeaksDetector(bool reallyDetect);
bool helpersAllowed();
void allowHelpers(bool reallyAllow);
bool blasFallback();
int tadThreshold();
void setTadThreshold(int threshold);
int elementwiseThreshold();
void setElementwiseThreshold(int threshold);
int maxThreads();
void setMaxThreads(int max);
int maxMasterThreads();
void setMaxMasterThreads(int max);
/*
* Legacy memory limits API, still used in new API as simplified version
*/
void setMaxPrimaryMemory(uint64_t maxBytes);
void setMaxSpecialyMemory(uint64_t maxBytes);
void setMaxDeviceMemory(uint64_t maxBytes);
uint64_t maxPrimaryMemory();
uint64_t maxSpecialMemory();
////////////////////////
/*
* Methods for memory limits/counters
*/
void setGroupLimit(int group, sd::LongType numBytes);
void setDeviceLimit(int deviceId, sd::LongType numBytes);
sd::LongType getGroupLimit(int group);
sd::LongType getDeviceLimit(int deviceId);
sd::LongType getGroupCounter(int group);
sd::LongType getDeviceCounter(int deviceId);
////////////////////////
bool isUseONEDNN() { return _useONEDNN.load(); }
void setUseONEDNN(bool useMKLDNN) { _useONEDNN.store(useMKLDNN); }
sd::DataType defaultFloatDataType();
void setDefaultFloatDataType(sd::DataType dtype);
bool precisionBoostAllowed();
void allowPrecisionBoost(bool reallyAllow);
bool isExperimentalBuild();
bool isCPU();
int blasMajorVersion();
int blasMinorVersion();
int blasPatchVersion();
std::vector<Pair>& capabilities();
bool isFuncTracePrintDeallocate();
void setFuncTracePrintDeallocate(bool reallyPrint);
bool isFuncTracePrintAllocate();
void setFuncTracePrintAllocate(bool reallyPrint);
// NDArray lifecycle tracking methods
bool isLifecycleTracking();
void setLifecycleTracking(bool enabled);
bool isTrackViews();
void setTrackViews(bool track);
bool isTrackDeletions();
void setTrackDeletions(bool track);
int getStackDepth();
void setStackDepth(int depth);
int getReportInterval();
void setReportInterval(int seconds);
size_t getMaxDeletionHistory();
void setMaxDeletionHistory(size_t max);
bool isSnapshotFiles();
void setSnapshotFiles(bool enabled);
bool isTrackOperations();
void setTrackOperations(bool enabled);
bool isDeleteShapeInfo();
void setDeleteShapeInfo(bool deleteShapeInfo);
// CUDA specific getters/setters
int cudaDeviceCount() { return _cudaDeviceCount.load(); }
int cudaCurrentDevice() { return _cudaCurrentDevice.load(); }
void setCudaCurrentDevice(int device);
bool cudaMemoryPinned() { return _cudaMemoryPinned.load(); }
void setCudaMemoryPinned(bool pinned);
bool cudaUseManagedMemory() { return _cudaUseManagedMemory.load(); }
void setCudaUseManagedMemory(bool managed);
int cudaMemoryPoolSize() { return _cudaMemoryPoolSize.load(); }
void setCudaMemoryPoolSize(int sizeInMB);
bool cudaForceP2P() { return _cudaForceP2P.load(); }
void setCudaForceP2P(bool forceP2P);
bool cudaAllocatorEnabled() { return _cudaAllocatorEnabled.load(); }
void setCudaAllocatorEnabled(bool enabled);
int cudaMaxBlocks() { return _cudaMaxBlocks.load(); }
void setCudaMaxBlocks(int blocks);
int cudaMaxThreadsPerBlock() { return _cudaMaxThreadsPerBlock.load(); }
void setCudaMaxThreadsPerBlock(int threads);
bool cudaAsyncExecution() { return _cudaAsyncExecution.load(); }
void setCudaAsyncExecution(bool async);
int cudaStreamLimit() { return _cudaStreamLimit.load(); }
void setCudaStreamLimit(int limit);
bool cudaUseDeviceHost() { return _cudaUseDeviceHost.load(); }
void setCudaUseDeviceHost(bool useDeviceHost);
int cudaEventLimit() { return _cudaEventLimit.load(); }
void setCudaEventLimit(int limit);
int cudaCachingAllocatorLimit() { return _cudaCachingAllocatorLimit.load(); }
void setCudaCachingAllocatorLimit(int limitInMB);
bool cudaUseUnifiedMemory() { return _cudaUseUnifiedMemory.load(); }
void setCudaUseUnifiedMemory(bool unified);
int cudaPrefetchSize() { return _cudaPrefetchSize.load(); }
void setCudaPrefetchSize(int sizeInMB);
bool cudaGraphOptimization() { return _cudaGraphOptimization.load(); }
void setCudaGraphOptimization(bool enabled);
bool cudaTensorCoreEnabled() { return _cudaTensorCoreEnabled.load(); }
void setCudaTensorCoreEnabled(bool enabled);
int cudaBlockingSync() { return _cudaBlockingSync.load(); }
void setCudaBlockingSync(int mode);
int cudaDeviceSchedule() { return _cudaDeviceSchedule.load(); }
void setCudaDeviceSchedule(int schedule);
// CUDA Device Limit getters/setters
size_t cudaStackSize() { return _cudaStackSize.load(); }
void setCudaStackSize(size_t size);
size_t cudaMallocHeapSize() { return _cudaMallocHeapSize.load(); }
void setCudaMallocHeapSize(size_t size);
size_t cudaPrintfFifoSize() { return _cudaPrintfFifoSize.load(); }
void setCudaPrintfFifoSize(size_t size);
size_t cudaDevRuntimeSyncDepth() { return _cudaDevRuntimeSyncDepth.load(); }
void setCudaDevRuntimeSyncDepth(size_t depth);
size_t cudaDevRuntimePendingLaunchCount() { return _cudaDevRuntimePendingLaunchCount.load(); }
void setCudaDevRuntimePendingLaunchCount(size_t count);
size_t cudaMaxL2FetchGranularity() { return _cudaMaxL2FetchGranularity.load(); }
void setCudaMaxL2FetchGranularity(size_t size);
size_t cudaPersistingL2CacheSize() { return _cudaPersistingL2CacheSize.load(); }
void setCudaPersistingL2CacheSize(size_t size);
bool setCudaDeviceLimit(int limitType, size_t value);
// Initialize CUDA environment settings from environment variables
void initCudaEnvironment();
// Initialize CUDA device limits from environment variables
void initCudaDeviceLimits();
};
} // namespace sd
#endif // LIBND4J_ENVIRONMENT_H
+415
View File
@@ -0,0 +1,415 @@
/* ******************************************************************************
*
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
******************************************************************************/
#ifndef LIBND4J_REQUIREMENTSHELPER_H
#define LIBND4J_REQUIREMENTSHELPER_H
#include <ConstMessages.h>
#include <helpers/ShapeUtils.h>
#include <helpers/logger.h>
#include <system/Environment.h>
#include <system/op_boilerplate.h>
#include <exception>
#include <iostream>
#include <type_traits>
namespace sd {
inline std::ostream& operator<<(std::ostream& o, DataType type) {
o << DataTypeUtils::asString(type);
return o;
}
template <class T, std::size_t N>
SD_LIB_HIDDEN std::ostream& operator<<(std::ostream& o, const std::array<T, N>& arr) {
o << '[';
for (auto& x : arr) {
o << x << ", ";
}
o << ']';
return o;
}
template <class T>
SD_LIB_HIDDEN std::ostream& operator<<(std::ostream& o, const std::initializer_list<T>& arr) {
for (auto& x : arr) {
o << x << ", ";
}
return o;
}
template <typename T>
using remove_cvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
// https://stackoverflow.com/questions/15393938/find-out-whether-a-c-object-is-callable
template <typename T>
using remove_cvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
template <typename T>
using remove_ref_t = typename std::remove_reference<T>::type;
template <typename T>
using remove_refptr_t = typename std::remove_pointer<remove_ref_t<T>>::type;
template <typename T>
using is_function_t = typename std::is_function<remove_refptr_t<T>>::type;
template <bool isObject, typename T>
struct is_callable_impl : public is_function_t<T> {};
template <typename T>
struct is_callable_impl<true, T> {
private:
struct Fallback {
void operator()();
};
struct Derived : T, Fallback {};
template <typename U, U>
struct Check;
template <typename>
static std::true_type test(...);
template <typename C>
static std::false_type test(Check<void (Fallback::*)(), &C::operator()>*);
public:
typedef decltype(test<Derived>(nullptr)) type;
};
template <typename T>
using is_callable = typename is_callable_impl<std::is_class<remove_ref_t<T>>::value, remove_ref_t<T>>::type;
template <typename S, typename T>
class is_streamable {
template <typename SS, typename TT>
static auto test(int) -> decltype(std::declval<SS&>() << std::declval<TT>(), std::true_type());
template <typename, typename>
static auto test(...) -> std::false_type;
public:
static const bool value = decltype(test<S, T>(0))::value;
};
template <typename T>
class has_getMsg {
template <typename TT>
static auto test(int) -> decltype(std::declval<TT&>().getMsg(), std::true_type());
template <typename>
static auto test(...) -> std::false_type;
public:
static const bool value = decltype(test<T>(0))::value;
};
template <typename T>
class has_getValue {
template <typename TT>
static auto test(int) -> decltype(std::declval<TT&>().getValue(), std::true_type());
template <typename>
static auto test(...) -> std::false_type;
public:
static const bool value = decltype(test<T>(0))::value;
};
template <typename T>
class has_getValueStr {
template <typename TT>
static auto test(int) -> decltype(std::declval<TT&>().getValueStr(), std::true_type());
template <typename>
static auto test(...) -> std::false_type;
public:
static const bool value = decltype(test<T>(0))::value;
};
template <typename T, typename Enable = void>
struct Underline {
using type = T;
};
template <typename T>
struct Underline<T, typename std::enable_if<has_getValue<T>::value>::type> {
using type = remove_cvref_t<decltype(std::declval<T&>().getValue())>;
};
template <typename T, typename Enable = void>
struct UnderlineMsg {
using type = T;
};
template <typename T>
struct UnderlineMsg<T, typename std::enable_if<has_getMsg<T>::value>::type> {
using type = decltype(std::declval<T&>().getMsg());
};
template <typename T>
using UnderlineType = typename Underline<T>::type;
template <typename T>
using UnderlineMsgType = typename UnderlineMsg<T>::type;
template <typename T>
typename std::enable_if<(!has_getMsg<T>::value ||
(has_getMsg<T>::value && !is_streamable<std::stringstream, UnderlineMsgType<T>>::value)),
const char*>::type
getMsg(T x) {
return "";
}
template <typename T>
typename std::enable_if<(has_getMsg<T>::value && is_streamable<std::stringstream, UnderlineMsgType<T>>::value),
UnderlineMsgType<T>>::type
getMsg(const T& x) {
return x.getMsg();
}
template <typename T>
typename std::enable_if<!has_getValue<T>::value, T>::type getValue(const T& x) {
return x;
}
template <typename T>
typename std::enable_if<has_getValue<T>::value, decltype(std::declval<T&>().getValue())>::type getValue(const T& x) {
return x.getValue();
}
template <typename T>
typename std::enable_if<!has_getValueStr<T>::value && !std::is_same<remove_cvref_t<UnderlineType<T>>, bool>::value &&
is_streamable<std::stringstream, UnderlineType<T>>::value,
UnderlineType<T>>::type
getStreamValue(const T& x) {
return getValue(x);
}
template <typename T>
typename std::enable_if<!has_getValueStr<T>::value && !is_streamable<std::stringstream, UnderlineType<T>>::value,
std::string>::type
getStreamValue(T x) {
return "{//system can not stringify the variable}";
}
template <typename T>
typename std::enable_if<has_getValueStr<T>::value, std::string>::type getStreamValue(const T& x) {
return x.getValueStr();
}
template <typename T>
typename std::enable_if<!has_getValueStr<T>::value && std::is_same<remove_cvref_t<UnderlineType<T>>, bool>::value,
const char*>::type
getStreamValue(const T& x) {
return getValue(x) ? "True" : "False";
}
/**
* @brief Requirements helper is used to replace plain checks for making them output informative messages
* @see https://github.com/eclipse/deeplearning4j/blob/master/libnd4j/Helpers.md
*/
class Requirements {
public:
Requirements(const char* prefix_msg = "") : prefix(prefix_msg), ok(true) {
#if defined(ENABLE_LOG_TO_TEST)
sd::Environment::getInstance().setDebug(true);
sd::Environment::getInstance().setVerbose(true);
#endif
};
// Requirements is implicitly converted to bool.
// Note: this way you can use short circuit operators && to chain requirements
// req.expect && req.expect && ...
// This way you will get the shortcircuit that will not evaluate the later
// it is better than using calls chaining like: req.expect( ).expect
operator bool() { return this->ok; }
// sets the prefix message
Requirements& setPrefix(const char* prefix_msg) {
prefix = prefix_msg;
return *this;
}
// Compares two values with comparison
// Note: to achive full lazy evaluation of the obtained values or messages
// you should wrap them and use getValue getMsg functions
template <typename T, typename T1, typename Op>
Requirements& expect(const T& expVar, const T1& reqVar, Op comparision, const char* first_half = "") {
if (!this->ok) return *this;
bool cmp = comparision(getValue(expVar), getValue(reqVar));
if (!cmp && sd::Environment::getInstance().isDebug() && sd::Environment::getInstance().isVerbose()) {
std::stringstream stream;
stream << prefix << ": " << getMsg(expVar) << " {" << getStreamValue(expVar) << "} " << first_half << ' '
<< getMsg(reqVar) << ' ' << getStreamValue(reqVar);
sd::Logger::info("%s\n", stream.str().c_str());
}
this->ok = this->ok && cmp;
return *this;
}
template <typename T, typename T1>
Requirements& expectEq(const T& exp, const T1& req) {
return expect(exp, req, std::equal_to<UnderlineType<T1>>{}, EXPECTED_EQ_MSG);
}
template <typename T, typename T1>
Requirements& expectNotEq(const T& exp, const T1& req) {
return expect(exp, req, std::not_equal_to<UnderlineType<T1>>{}, EXPECTED_NE_MSG);
}
template <typename T, typename T1>
Requirements& expectLess(const T& exp, const T1& req) {
return expect(exp, req, std::less<UnderlineType<T1>>{}, EXPECTED_LT_MSG);
}
template <typename T, typename T1>
Requirements& expectLessEq(const T& exp, const T1& req) {
return expect(exp, req, std::less_equal<UnderlineType<T1>>{}, EXPECTED_LE_MSG);
}
template <typename T, typename T1>
Requirements& expectGreater(T exp, T1 req) {
return expect(exp, req, std::greater<UnderlineType<T1>>{}, EXPECTED_GT_MSG);
}
template <typename T, typename T1>
Requirements& expectGreaterEq(const T& exp, const T1& req) {
return expect(exp, req, std::greater_equal<UnderlineType<T1>>{}, EXPECTED_GE_MSG);
}
// throws. use this if you want to throw an exception if there is any failure
void throws() {
if (!this->ok) THROW_EXCEPTION(OP_VALIDATION_FAIL_MSG);
}
template <typename T>
Requirements& expectTrue(const T& expVar, const char* msg = EXPECTED_TRUE) {
if (!this->ok) return *this;
bool cmp = static_cast<bool>(getValue(expVar));
if (!cmp && sd::Environment::getInstance().isDebug() && sd::Environment::getInstance().isVerbose()) {
std::stringstream stream;
stream << prefix << ": " << getMsg(expVar) << " {" << getStreamValue(expVar) << "} " << msg;
sd::Logger::info("%s\n", stream.str().c_str());
}
this->ok = this->ok && cmp;
return *this;
}
template <typename T>
Requirements& expectFalse(const T& expVar, const char* msg = EXPECTED_FALSE) {
if (!this->ok) return *this;
bool cmp = static_cast<bool>(getValue(expVar));
if (cmp && sd::Environment::getInstance().isDebug() && sd::Environment::getInstance().isVerbose()) {
std::stringstream stream;
stream << prefix << ": " << getMsg(expVar) << " {" << getStreamValue(expVar) << "} " << msg;
sd::Logger::info("%s\n", stream.str().c_str());
}
this->ok = this->ok && !cmp;
return *this;
}
template <typename T, typename T2>
Requirements expectIn(const T& expVar, std::initializer_list<T2> vals) {
if (!ok) return *this;
auto val = getValue(expVar);
for (const auto& r_i : vals) {
if (val == r_i) return *this;
}
if (sd::Environment::getInstance().isDebug() && sd::Environment::getInstance().isVerbose()) {
std::stringstream stream;
stream << prefix << ": " << getMsg(expVar) << '{' << getStreamValue(expVar) << "} " << EXPECTED_IN << " {"
<< getStreamValue(vals) << "}\n";
sd::Logger::info("%s", stream.str().c_str());
}
ok = false;
return *this;
}
// Logs the Successfull cases to know if the requiremets met the conditions
void logTheSuccess() {
if (this->ok && sd::Environment::getInstance().isDebug() && sd::Environment::getInstance().isVerbose()) {
sd::Logger::info("%s: %s\n", prefix, REQUIREMENTS_MEETS_MSG);
}
}
private:
// the prefix used to add messages in each log
const char* prefix;
// bool value used for the Requirements to mimick bool
bool ok;
};
// Generic wrapper where variable and info can be lazy evaluated using the lambda
template <typename T1, typename T2>
struct InfoVariable {
T1 value_or_op;
T2 message_or_op;
InfoVariable(T1 valOrOp, T2 msgOrOp) : value_or_op(valOrOp), message_or_op(msgOrOp) {}
template <typename U = T1, typename std::enable_if<!is_callable<U>::value, int>::type = 0>
U getValue() const {
return value_or_op;
}
template <typename U = T1, typename std::enable_if<is_callable<U>::value, int>::type = 0>
auto getValue() const -> decltype(std::declval<U&>()()) {
return value_or_op();
}
template <typename U = T2, typename std::enable_if<!is_callable<U>::value, int>::type = 0>
U getMsg() const {
return message_or_op;
}
template <typename U = T2, typename std::enable_if<is_callable<U>::value, int>::type = 0>
auto getMsg() const -> decltype(std::declval<U&>()()) {
return message_or_op();
}
};
template <typename T1, typename T2>
SD_LIB_HIDDEN InfoVariable<T1, T2> makeInfoVariable(T1&& v1, T2&& v2) {
return InfoVariable<T1, T2>(std::forward<T1>(v1), std::forward<T2>(v2));
}
template <typename T>
struct ShapeInfoVariable {
explicit ShapeInfoVariable(const T& val, const char* msg = "") : value(val), message(msg) {}
const T& value;
const char* message;
const char* getMsg() const { return message; }
const T& getValue() const { return value; }
std::string getValueStr() const { return ShapeUtils::shapeAsString(value); }
};
template <typename T>
ShapeInfoVariable<T> makeShapeInfoVariable(T&& v, const char* msg) {
return ShapeInfoVariable<T>(std::forward<T>(v), msg);
}
} // namespace sd
#endif // LIBND4J_REQUIREMENTSHELPER_H
+252
View File
@@ -0,0 +1,252 @@
/* ******************************************************************************
*
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
******************************************************************************/
/*
* buffer.h
*
* Created on: Dec 24, 2015
* Author: agibsonccc
*/
#ifndef BUFFER_H_
#define BUFFER_H_
#include <helpers/DebugHelper.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <system/common.h>
// Question: Should the indexes here really be int? Isn't size_t or sd::LongType more appropriate?
namespace sd {
namespace buffer {
/**
* Represents both a cpu and gpu
* buffer - mainly used for testing
*/
template <typename T>
struct Buffer {
int length = 0;
int allocatedOnGpu = 0;
T *data = nullptr;
T *gData = nullptr;
T one, two;
public:
~Buffer() {
delete[] data;
delete[] gData;
}
void assign(T *val) { data = val; }
T &operator=(T x) {
one = x;
return x;
}
class Proxy {
Buffer<T> &a;
int idx;
public:
Proxy(Buffer &a, int idx) : a(a), idx(idx) {}
T &operator=(T x) {
a.two = x;
a.data[idx] = x;
return a.data[idx];
}
};
Proxy operator[](int index) { return Proxy(*this, index); }
};
/**
* Returns the size of the buffer
* in bytes
* @param buffer the buffer to get the size of
* @return the size of the buffer in bytes
*/
template <typename T>
SD_HOST_DEVICE int bufferSize(Buffer<T> *buffer);
/**
* Copies data to the gpu
* @param buffer the buffer to copy
*/
#ifdef __CUDACC__
template <typename T>
SD_HOST void copyDataToGpu(Buffer<T> **buffer, cudaStream_t stream);
#endif
/**
* Copies data from the gpu
* @param buffer the buffer to copy
*/
#ifdef __CUDACC__
template <typename T>
SD_HOST void copyDataFromGpu(Buffer<T> **buffer, cudaStream_t stream);
#endif
/**
* Allocate buffer of the given
* length on the cpu and gpu.
*/
template <typename T>
SD_HOST void allocBuffer(Buffer<T> **buffer, int length);
/**
* Frees the given buffer
* (gpu and cpu
*/
template <typename T>
SD_HOST void freeBuffer(Buffer<T> **buffer);
/**
* Creates a buffer
* based on the data
* and also synchronizes
* the data on the gpu.
*/
template <typename T>
SD_HOST Buffer<T> *createBuffer(T *data, int length);
/**
* Print the buffer on the host
* @param buff
*/
template <typename T>
SD_HOST void printArr(Buffer<T> *buff);
/**
*
* @param buffer
* @return
*/
template <typename T>
SD_HOST_DEVICE int bufferSize(Buffer<T> *buffer) {
return sizeof(T) * buffer->length;
}
#ifdef __CUDACC__
/**
*
* @param buffer
*/
template <typename T>
SD_HOST void copyDataToGpu(Buffer<T> **buffer, cudaStream_t stream) {
Buffer<T> *bufferRef = *buffer;
checkCudaErrors(
cudaMemcpyAsync(bufferRef->gData, bufferRef->data, bufferSize(bufferRef), cudaMemcpyHostToDevice, stream));
checkCudaErrors(cudaStreamSynchronize(stream));
}
/**
*
* @param buffer
*/
template <typename T>
SD_HOST void copyDataFromGpu(Buffer<T> **buffer, cudaStream_t stream) {
Buffer<T> *bufferRef = *buffer;
int bufferTotalSize = bufferSize(bufferRef);
checkCudaErrors(cudaMemcpyAsync(bufferRef->data, bufferRef->gData, bufferTotalSize, cudaMemcpyDeviceToHost, stream));
checkCudaErrors(cudaStreamSynchronize(stream));
}
#endif
/**
* Allocate buffer of the given
* length on the cpu and gpu.
*/
template <typename T>
SD_HOST void allocBuffer(Buffer<T> **buffer, int length) {
Buffer<T> *bufferRef = *buffer;
bufferRef->length = length;
bufferRef->data = reinterpret_cast<T *>(malloc(sizeof(T) * length));
CHECK_ALLOC(bufferRef->data, "Failed to allocate new buffer", sizeof(T) * length);
#ifdef __CUDACC__
checkCudaErrors(cudaMalloc(&bufferRef->gData, sizeof(T) * length));
#endif
}
/**
* Frees the given buffer
* (gpu and cpu
*/
template <typename T>
SD_HOST void freeBuffer(Buffer<T> *buffer) {
#ifdef __CUDACC__
if (buffer->gData != nullptr) checkCudaErrors(cudaFree(buffer->gData));
#endif
delete buffer;
}
/**
* Creates a buffer
* based on the data
* and also synchronizes
* the data on the gpu.
*/
template <typename T>
SD_HOST Buffer<T> *createBuffer(T *data, int length) {
Buffer<T> *ret = new Buffer<T>;
T *buffData = new T[length];
for (int i = 0; i < length; i++) buffData[i] = data[i];
ret->data = buffData;
ret->length = length;
return ret;
}
#ifdef __CUDACC__
template <typename T>
SD_HOST Buffer<T> *createBuffer(T *data, int length, cudaStream_t stream) {
Buffer<T> *ret = createBuffer(data, length);
T *gData;
T **gDataRef = &(gData);
checkCudaErrors(cudaMalloc(reinterpret_cast<void **>(gDataRef), sizeof(T) * length));
ret->gData = gData;
checkCudaErrors(cudaMemcpyAsync(ret->gData, ret->data, sizeof(T) * length, cudaMemcpyHostToDevice, stream));
return ret;
}
#endif
} // namespace buffer
} // namespace sd
#ifdef __CUDACC__
template <typename T>
SD_HOST void printArr(sd::buffer::Buffer<T> *buff) {
for (int i = 0; i < buff->length; i++) {
printf("Buffer[%d] was %f\n", i, buff->data[i]);
}
}
#endif
#endif /* BUFFER_H_ */
+367
View File
@@ -0,0 +1,367 @@
/* ******************************************************************************
*
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
******************************************************************************/
#ifndef SD_SYSTEM_COMMON_H
#define SD_SYSTEM_COMMON_H
#include <cstdint>
#define STRINGIZE2(x) #x
#define STRINGIZE(x) STRINGIZE2(x)
#define COMMA ,
#if defined(_MSC_VER)
#pragma warning(disable : 4244)
#pragma warning(disable : 4267)
#pragma warning(disable : 4251)
#pragma warning(disable : 4101)
#pragma warning(disable : 4305)
#pragma warning(disable : 4309)
#pragma warning(disable : 4333)
#pragma warning(disable : 4146)
#pragma warning(disable : 4018)
// we're ignoring warning about non-exportable parent class, since std::runtime_error is a part of Standard C++ Library
#pragma warning(disable : 4275)
#pragma warning(disable : 4297)
#endif
#if defined _WIN32 || defined __CYGWIN__
#ifdef __GNUC__
#define SD_LIB_EXPORT __attribute__((dllexport))
#else
#define SD_LIB_EXPORT __declspec(dllexport)
#endif
#define SD_LIB_HIDDEN
#else
#if __GNUC__ >= 4
#define SD_LIB_EXPORT __attribute__((visibility("default")))
#define SD_LIB_HIDDEN __attribute__((visibility("hidden")))
#else
#define SD_LIB_EXPORT
#define SD_LIB_HIDDEN
#endif
#endif
// Cross-platform compiler attributes
#if defined(__GNUC__)
#define SD_NO_INSTRUMENT __attribute__((no_instrument_function))
#elif defined(_MSC_VER)
#define SD_NO_INSTRUMENT __declspec(noinline)
#else
#define SD_NO_INSTRUMENT
#endif
#ifdef __clang__
#include <unordered_map>
#define SD_MAP_IMPL std::unordered_map
#define SD_LOOPS_INLINED
#define SD_INLINE inline
#elif _MSC_VER
#include <map>
#define SD_MAP_IMPL std::map
#define SD_INLINE __forceinline
#elif __GNUC__
#include <unordered_map>
#define SD_MAP_IMPL std::unordered_map
#define SD_LOOPS_INLINED
#define SD_INLINE inline
#elif __CUDACC__
#include <unordered_map>
#define SD_MAP_IMPL std::unordered_map
#define SD_INLINE __forceinline__ inline
#else
#include <unordered_map>
#define SD_MAP_IMPL std::unordered_map
#define SD_INLINE inline
#endif
#ifdef __CUDACC__
#define SD_HOST __host__
#define SD_DEVICE __device__
#define SD_KERNEL __global__
#define SD_HOST_DEVICE __host__ __device__
#else
#define SD_HOST
#define SD_DEVICE
#define SD_KERNEL
#define SD_HOST_DEVICE
#endif // CUDACC
#if defined(_ISOC11_SOURCE) && defined(__AVX2__)
#define SD_DESIRED_ALIGNMENT 32
#define SD_ALIGNED_ALLOC 1
#endif
#if defined(__GNUC__)
#define SD_ALIGN32 __attribute__((aligned(32)))
#elif defined(_MSC_VER)
#define SD_ALIGN32 __declspec(align(32))
#else
#define SD_ALIGN32
#endif
#ifdef __CUDACC__
// 610 is for tests only
// 600 is Tesla P100
// 530 is Tegra
#if __CUDA_ARCH__ == 600 || __CUDA_ARCH__ == 530 || __CUDA_ARCH__ == 700 || __CUDA_ARCH__ == 720 || __CUDA_ARCH__ == 750
#define NATIVE_HALFS
#endif
#endif
// Include openmp_pragmas.h AFTER SD_INLINE is defined
#include <system/openmp_pragmas.h>
#ifdef __CUDACC__
#define SD_META_DEF SD_INLINE SD_HOST
#define SD_OP_DEF SD_INLINE SD_HOST_DEVICE
#elif __JAVACPP_HACK__
#define SD_META_DEF
#define SD_OP_DEF
#else
// Proper fix: Use SIMD but handle the float16/bfloat16 issue with template specializations
#define SD_META_DEF PRAGMA_OMP_DECLARE_SIMD SD_INLINE
#define SD_OP_DEF PRAGMA_OMP_DECLARE_SIMD SD_INLINE
// Alternative macro for problematic template instantiations
#define SD_OP_DEF_NO_SIMD SD_INLINE
#endif
#define SD_MIN_V 1e-12
#define SD_MAX_FLOAT 1e37
#define SD_MIN_FLOAT 1e-37
#define SD_MAX_INT 2147483647
#define SD_MIN_CUTFOFF -3.79297773665f
#define SD_MAX_CUTFOFF 3.79297773665f
#define SD_FLOAT_MIN_NORMAL 1.17549435e-38
#define SD_EPSILON 1e-5
#define SD_DOUBLE_PI_T T(2.0 * 3.14159265358979323846)
#define SD_DOUBLE_PI_X X(2.0 * 3.14159265358979323846)
#include <cstdarg>
#include <cstdio>
#include <string>
namespace sd {
using Pointer = void*;
using LongType = int64_t;
using UnsignedLong = uint64_t;
using Unsigned = uint32_t;
enum class Status : int {
OK = 0,
BAD_INPUT = 1,
BAD_SHAPE = 2,
BAD_RANK = 3,
BAD_PARAMS = 4,
BAD_OUTPUT = 5,
BAD_RNG = 6,
BAD_EPSILON = 7,
BAD_GRADIENTS = 8,
BAD_BIAS = 9,
VALIDATION = 20,
BAD_GRAPH = 30,
BAD_LENGTH = 31,
BAD_DIMENSIONS = 32,
BAD_ORDER = 33,
BAD_ARGUMENTS = 34,
DOUBLE_WRITE = 40,
DOUBLE_READ = 45,
KERNEL_FAILURE = 50,
EQ_TRUE = 100,
EQ_FALSE = 101,
MAYBE = 119
};
struct ErrorResult {
sd::Status status;
std::string message;
};
} // namespace sd
#define SD_MAX_DIMENSION 0x7fffffff
#define SD_MAX_NUM_THREADS 1024
#define SD_MAX_RANK 32
#define SD_MAX_SHAPEINFOLENGTH 2 * SD_MAX_RANK + 4
#define SD_MAX_COORD 3
#define SD_PREALLOC_SIZE 33554432
#ifdef __CUDACC__
#include <cuda.h>
#include <cuda_device_runtime_api.h>
#include <cuda_runtime.h>
#include <cuda_runtime_api.h>
#endif
#define SD_CUDA_BLOCK_SIZE 256
#if !defined(_OPENMP)
#define omp_get_thread_num() 0
#define omp_get_num_threads() 1
#define omp_get_max_threads() 1
#define omp_set_num_threads(threads)
#else
#include <omp.h>
#endif
#ifndef __JAVACPP_HACK__
#if defined(SD_GCC_FUNCTRACE)
#include <exceptions/backward.hpp>
using namespace backward;
#endif
// Exception handling functions (exported for JavaCPP visibility)
SD_LIB_EXPORT void throwException(const char* exceptionMessage);
SD_LIB_EXPORT void safeSetErrorContext(int errorCode, const char* errorMessage);
#define THROW_EXCEPTION(exceptionMessage) throwException(exceptionMessage);
#endif
#define CONCAT2(A, B) A##B
#define CONCAT3_IMPL(a, b, c) a##b##c
#define CONCAT3(a, b, c) CONCAT3_IMPL(a, b, c)
#define MIX2(A, B) A##_##B
#define MIX3(A, B, C) A##_##B##_##C
#define MIX4(A, B, C, D) A##_##B##_##C##_##D
#define EMPTY()
#define DEFER(id) id EMPTY()
#define CONCAT_IMPL(a, b) a##b
#define CONCAT(a, b) CONCAT_IMPL(a, b)
#define CONCAT4(a, b, c, d) a##b##c##d
#define CONCAT5_IMPL(a, b, c, d, e) a##b##c##d##e
#define CONCAT5(a, b, c, d, e) CONCAT5_IMPL(a, b, c, d, e)
#define CONCAT6_IMPL(a, b, c, d, e, f) a##b##c##d##e##f
#define CONCAT6(a, b, c, d, e, f) CONCAT6_IMPL(a, b, c, d, e, f)
#define CONCAT7_IMPL(a, b, c, d, e, f, g) a##b##c##d##e##f##g
#define CONCAT7(a, b, c, d, e, f, g) CONCAT7_IMPL(a, b, c, d, e, f, g)
#define CONCAT8_IMPL(a, b, c, d, e, f, g, h) a##b##c##d##e##f##g##h
#define UNDERSCORE _
#define COMMA_MATH ,
#define TUPLE_TO_ARGS(x) TUPLE_TO_ARGS_IMPL x
#define TUPLE_TO_ARGS_IMPL(first, second) first, second
#define EXPAND(...) __VA_ARGS__
#define EXPAND2(...) __VA_ARGS__
#define EXPAND3(...) __VA_ARGS__
#define EXTRACT(...) EXTRACT __VA_ARGS__
#define NOTHING_EXTRACT
#define PASTE(x, ...) x##__VA_ARGS__
#define PASTE2(x, ...) x##__VA_ARGS__
#define PASTE3(x, ...) x##__VA_ARGS__
#define EVALUATING_PASTE(x, ...) PASTE(x, __VA_ARGS__)
#define EVALUATING_PASTE2(x, ...) PASTE2(x, __VA_ARGS__)
#define EVALUATING_PASTE3(x, ...) PASTE3(x, __VA_ARGS__)
#define UNPAREN(x) EVALUATING_PASTE(NOTHING_, EXTRACT x)
#define UNPAREN2(x) EVALUATING_PASTE2(NOTHING_, EXTRACT x)
#define UNPAREN3(x) EVALUATING_PASTE3(NOTHING_, EXTRACT x)
#define EVAL(...) EVAL0(__VA_ARGS__)
#define EVALX(x) x
#define EVAL0(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__)))
#define EVAL1(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__)))
#define EVAL2(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__)))
#define EVAL3(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__)))
#define EVAL4(...) EVAL5(EVAL5(EVAL5(__VA_ARGS__)))
#define EVAL5(...) __VA_ARGS__
#define EXPAND(...) __VA_ARGS__
#define CAT(a, b) CAT_IMPL(a, b)
#define CAT_IMPL(a, b) a##b
#define PP_NARGS(...) PP_NARGS_IMPL(__VA_ARGS__, PP_RSEQ_N())
#define PP_NARGS_IMPL(...) PP_ARG_N(__VA_ARGS__)
#define PP_ARG_N(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,N,...) N
#define PP_RSEQ_N() 28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
#define GET(n, list) CAT(GET_, n) list
#define GET_0(t1, ...) t1
#define GET_1(t1, t2, ...) t2
#define GET_2(t1, t2, t3, ...) t3
#define GET_3(t1, t2, t3, t4, ...) t4
#define GET_4(t1, t2, t3, t4, t5, ...) t5
#define GET_5(t1, t2, t3, t4, t5, t6, ...) t6
#define GET_6(t1, t2, t3, t4, t5, t6, t7, ...) t7
#define GET_7(t1, t2, t3, t4, t5, t6, t7, t8, ...) t8
#define GET_8(t1, t2, t3, t4, t5, t6, t7, t8, t9, ...) t9
#define GET_9(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, ...) t10
#define GET_10(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, ...) t11
#define GET_11(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, ...) t12
#define GET_12(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, ...) t13
#define GET_13(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, ...) t14
#define GET_14(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, ...) t15
#define GET_15(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, ...) t16
#define GET_16(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, ...) t17
#define GET_17(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, ...) t18
#define GET_18(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, ...) t19
#define GET_19(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, t20, ...) t20
#define GET_20(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, t20, t21, ...) t21
#define GET_21(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, t20, t21, t22, ...) t22
#define GET_22(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, t20, t21, t22, t23, ...) t23
#define GET_23(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, t20, t21, t22, t23, t24, ...) t24
#define GET_24(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, t20, t21, t22, t23, t24, t25, ...) t25
#define GET_25(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, t20, t21, t22, t23, t24, t25, t26, ...) t26
#define GET_26(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, t20, t21, t22, t23, t24, t25, t26, t27, ...) t27
#define GET_27(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, t20, t21, t22, t23, t24, t25, t26, t27, t28, ...) t28
#define GET_28(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, t20, t21, t22, t23, t24, t25, t26, t27, t28, t29, ...) t29
#define GET_FIRST_IMPL(a, b) a
#define GET_FIRST(tuple) GET_FIRST_IMPL tuple
#define GET_SECOND_IMPL(a, b) b
#define GET_SECOND(tuple) GET_SECOND_IMPL tuple
template <class T>
inline constexpr bool is_my_string_v =
std::is_same_v<std::decay_t<T>, std::string> ||
std::is_same_v<std::decay_t<T>, std::u16string> ||
std::is_same_v<std::decay_t<T>, std::u32string>;
template <class... Ts>
inline constexpr bool any_my_string_v = (... || is_my_string_v<Ts>);
#endif
+152
View File
@@ -0,0 +1,152 @@
/* ******************************************************************************
*
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
******************************************************************************/
//
// @author raver119@gmail.com
//
#ifndef LIBND4J_ENUM_BOILERPLATE_H
#define LIBND4J_ENUM_BOILERPLATE_H
#include <system/type_boilerplate.h>
#define EN_1(WHAT, OP_PAIR) WHAT(OP_PAIR)
#define EN_2(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_1(WHAT, __VA_ARGS__))
#define EN_3(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_2(WHAT, __VA_ARGS__))
#define EN_4(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_3(WHAT, __VA_ARGS__))
#define EN_5(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_4(WHAT, __VA_ARGS__))
#define EN_6(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_5(WHAT, __VA_ARGS__))
#define EN_7(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_6(WHAT, __VA_ARGS__))
#define EN_8(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_7(WHAT, __VA_ARGS__))
#define EN_9(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_8(WHAT, __VA_ARGS__))
#define EN_10(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_9(WHAT, __VA_ARGS__))
#define EN_11(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_10(WHAT, __VA_ARGS__))
#define EN_12(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_11(WHAT, __VA_ARGS__))
#define EN_13(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_12(WHAT, __VA_ARGS__))
#define EN_14(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_13(WHAT, __VA_ARGS__))
#define EN_15(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_14(WHAT, __VA_ARGS__))
#define EN_16(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_15(WHAT, __VA_ARGS__))
#define EN_17(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_16(WHAT, __VA_ARGS__))
#define EN_18(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_17(WHAT, __VA_ARGS__))
#define EN_19(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_18(WHAT, __VA_ARGS__))
#define EN_20(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_19(WHAT, __VA_ARGS__))
#define EN_21(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_20(WHAT, __VA_ARGS__))
#define EN_22(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_21(WHAT, __VA_ARGS__))
#define EN_23(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_22(WHAT, __VA_ARGS__))
#define EN_24(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_23(WHAT, __VA_ARGS__))
#define EN_25(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_24(WHAT, __VA_ARGS__))
#define EN_26(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_25(WHAT, __VA_ARGS__))
#define EN_27(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_26(WHAT, __VA_ARGS__))
#define EN_28(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_27(WHAT, __VA_ARGS__))
#define EN_29(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_28(WHAT, __VA_ARGS__))
#define EN_30(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_29(WHAT, __VA_ARGS__))
#define EN_31(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_30(WHAT, __VA_ARGS__))
#define EN_32(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_31(WHAT, __VA_ARGS__))
#define EN_33(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_32(WHAT, __VA_ARGS__))
#define EN_34(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_33(WHAT, __VA_ARGS__))
#define EN_35(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_34(WHAT, __VA_ARGS__))
#define EN_36(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_35(WHAT, __VA_ARGS__))
#define EN_37(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_36(WHAT, __VA_ARGS__))
#define EN_38(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_37(WHAT, __VA_ARGS__))
#define EN_39(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_38(WHAT, __VA_ARGS__))
#define EN_40(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_39(WHAT, __VA_ARGS__))
#define EN_41(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_40(WHAT, __VA_ARGS__))
#define EN_42(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_41(WHAT, __VA_ARGS__))
#define EN_43(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_42(WHAT, __VA_ARGS__))
#define EN_44(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_43(WHAT, __VA_ARGS__))
#define EN_45(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_44(WHAT, __VA_ARGS__))
#define EN_46(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_45(WHAT, __VA_ARGS__))
#define EN_47(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_46(WHAT, __VA_ARGS__))
#define EN_48(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_47(WHAT, __VA_ARGS__))
#define EN_49(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_48(WHAT, __VA_ARGS__))
#define EN_50(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_49(WHAT, __VA_ARGS__))
#define EN_51(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_50(WHAT, __VA_ARGS__))
#define EN_52(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_51(WHAT, __VA_ARGS__))
#define EN_53(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_52(WHAT, __VA_ARGS__))
#define EN_54(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_53(WHAT, __VA_ARGS__))
#define EN_55(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_54(WHAT, __VA_ARGS__))
#define EN_56(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_55(WHAT, __VA_ARGS__))
#define EN_57(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_56(WHAT, __VA_ARGS__))
#define EN_58(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_57(WHAT, __VA_ARGS__))
#define EN_59(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_58(WHAT, __VA_ARGS__))
#define EN_60(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_59(WHAT, __VA_ARGS__))
#define EN_61(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_60(WHAT, __VA_ARGS__))
#define EN_62(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_61(WHAT, __VA_ARGS__))
#define EN_63(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_62(WHAT, __VA_ARGS__))
#define EN_64(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_63(WHAT, __VA_ARGS__))
#define EN_65(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_64(WHAT, __VA_ARGS__))
#define EN_66(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_65(WHAT, __VA_ARGS__))
#define EN_67(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_66(WHAT, __VA_ARGS__))
#define EN_68(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_67(WHAT, __VA_ARGS__))
#define EN_69(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_68(WHAT, __VA_ARGS__))
#define EN_70(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_69(WHAT, __VA_ARGS__))
#define EN_71(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_70(WHAT, __VA_ARGS__))
#define EN_72(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_71(WHAT, __VA_ARGS__))
#define EN_73(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_72(WHAT, __VA_ARGS__))
#define EN_74(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_73(WHAT, __VA_ARGS__))
#define EN_75(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_74(WHAT, __VA_ARGS__))
#define EN_76(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_75(WHAT, __VA_ARGS__))
#define EN_77(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_76(WHAT, __VA_ARGS__))
#define EN_78(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_77(WHAT, __VA_ARGS__))
#define EN_79(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_78(WHAT, __VA_ARGS__))
#define EN_80(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_79(WHAT, __VA_ARGS__))
#define EN_81(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_80(WHAT, __VA_ARGS__))
#define EN_82(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_81(WHAT, __VA_ARGS__))
#define EN_83(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_82(WHAT, __VA_ARGS__))
#define EN_84(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_83(WHAT, __VA_ARGS__))
#define EN_85(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_84(WHAT, __VA_ARGS__))
#define EN_86(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_85(WHAT, __VA_ARGS__))
#define EN_87(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_86(WHAT, __VA_ARGS__))
#define EN_88(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_87(WHAT, __VA_ARGS__))
#define EN_89(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_88(WHAT, __VA_ARGS__))
#define EN_90(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_89(WHAT, __VA_ARGS__))
#define EN_91(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_90(WHAT, __VA_ARGS__))
#define EN_92(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_91(WHAT, __VA_ARGS__))
#define EN_93(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_92(WHAT, __VA_ARGS__))
#define EN_94(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_93(WHAT, __VA_ARGS__))
#define EN_95(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_94(WHAT, __VA_ARGS__))
#define EN_96(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_95(WHAT, __VA_ARGS__))
#define EN_97(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_96(WHAT, __VA_ARGS__))
#define EN_98(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_97(WHAT, __VA_ARGS__))
#define EN_99(WHAT, OP_PAIR, ...) WHAT(OP_PAIR) EVAL(EN_98(WHAT, __VA_ARGS__))
#define __EXPAND_ENUM(NUM, CLASS) CLASS = NUM,
#define _EXPAND_ENUM(OP_PAIR) EVALUATING_PASTE(__EXPAND, _ENUM(UNPAREN(OP_PAIR)))
#define GET_MACROS_ENUM(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \
_21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, \
_40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, \
_59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, \
_78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, \
_97, _98, _99, NAME, ...) \
NAME
#define FOR_EACH_ENUM(WHAT, ...) \
EXPAND(GET_MACROS_ENUM(__VA_ARGS__, EN_99, EN_98, EN_97, EN_96, EN_95, EN_94, EN_93, EN_92, EN_91, EN_90, EN_89, \
EN_88, EN_87, EN_86, EN_85, EN_84, EN_83, EN_82, EN_81, EN_80, EN_79, EN_78, EN_77, EN_76, \
EN_75, EN_74, EN_73, EN_72, EN_71, EN_70, EN_69, EN_68, EN_67, EN_66, EN_65, EN_64, EN_63, \
EN_62, EN_61, EN_60, EN_59, EN_58, EN_57, EN_56, EN_55, EN_54, EN_53, EN_52, EN_51, EN_50, \
EN_49, EN_48, EN_47, EN_46, EN_45, EN_44, EN_43, EN_42, EN_41, EN_40, EN_39, EN_38, EN_37, \
EN_36, EN_35, EN_34, EN_33, EN_32, EN_31, EN_30, EN_29, EN_28, EN_27, EN_26, EN_25, EN_24, \
EN_23, EN_22, EN_21, EN_20, EN_19, EN_18, EN_17, EN_16, EN_15, EN_14, EN_13, EN_12, EN_11, \
EN_10, EN_9, EN_8, EN_7, EN_6, EN_5, EN_4, EN_3, EN_2, EN_1)(WHAT, __VA_ARGS__))
#define _EXEC_ENUM(WHAT, ...) EVAL(FOR_EACH_ENUM(WHAT, __VA_ARGS__))
#define EXEC_ENUMERATOR(...) EXPAND(_EXEC_ENUM(_EXPAND_ENUM, __VA_ARGS__))
#define BUILD_ENUMERATION(OPS) EVAL(EXEC_ENUMERATOR(OPS))
#endif
File diff suppressed because it is too large Load Diff
+109
View File
@@ -0,0 +1,109 @@
/* ******************************************************************************
*
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
******************************************************************************/
//
// @author raver119@gmail.com
//
#ifndef LIBND4J_OP_ENUMS_H
#define LIBND4J_OP_ENUMS_H
#include <loops/legacy_ops.h>
#include <system/enum_boilerplate.h>
#include <system/type_boilerplate.h>
namespace sd {
namespace random {
enum Ops { BUILD_ENUMERATION(RANDOM_OPS) };
}
namespace transform {
enum FloatOps { BUILD_ENUMERATION(TRANSFORM_FLOAT_OPS) };
enum SameOps { BUILD_ENUMERATION(TRANSFORM_SAME_OPS) };
enum BoolOps { BUILD_ENUMERATION(TRANSFORM_BOOL_OPS) };
enum AnyOps { BUILD_ENUMERATION(TRANSFORM_ANY_OPS) };
enum StrictOps { BUILD_ENUMERATION(TRANSFORM_STRICT_OPS) };
} // namespace transform
namespace pairwise {
enum Ops { BUILD_ENUMERATION(PAIRWISE_TRANSFORM_OPS) };
enum BoolOps { BUILD_ENUMERATION(PAIRWISE_BOOL_OPS) };
enum IntOps { BUILD_ENUMERATION(PAIRWISE_INT_OPS) };
} // namespace pairwise
namespace scalar {
enum Ops { BUILD_ENUMERATION(SCALAR_OPS) };
enum BoolOps { BUILD_ENUMERATION(SCALAR_BOOL_OPS) };
enum IntOps { BUILD_ENUMERATION(SCALAR_INT_OPS) };
} // namespace scalar
namespace reduce {
enum FloatOps { BUILD_ENUMERATION(REDUCE_FLOAT_OPS) };
enum SameOps { BUILD_ENUMERATION(REDUCE_SAME_OPS) };
enum BoolOps { BUILD_ENUMERATION(REDUCE_BOOL_OPS) };
enum LongOps { BUILD_ENUMERATION(REDUCE_LONG_OPS) };
} // namespace reduce
namespace reduce3 {
enum Ops { BUILD_ENUMERATION(REDUCE3_OPS) };
}
namespace indexreduce {
enum Ops { BUILD_ENUMERATION(INDEX_REDUCE_OPS) };
}
namespace broadcast {
enum Ops { BUILD_ENUMERATION(BROADCAST_OPS) };
enum BoolOps { BUILD_ENUMERATION(BROADCAST_BOOL_OPS) };
enum IntOps { BUILD_ENUMERATION(BROADCAST_INT_OPS) };
} // namespace broadcast
namespace variance {
enum Ops { BUILD_ENUMERATION(SUMMARY_STATS_OPS) };
}
namespace logic {
enum Ops {
While = 0,
Scope = 10,
Conditional = 20,
Switch = 30,
Return = 40,
Expose = 50,
Merge = 60,
LoopCond = 70,
NextIteration = 80,
Exit = 90,
Enter = 100,
};
}
} // namespace sd
#endif
+226
View File
@@ -0,0 +1,226 @@
/* ******************************************************************************
*
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
******************************************************************************/
#ifndef DEV_TESTS_OPENMP_PRAGMAS_H
#define DEV_TESTS_OPENMP_PRAGMAS_H
#include <cfloat>
#include <climits>
#include <cstdint>
#include <limits>
#include <system/type_boilerplate.h> // For sd::LongType and other types
// Add compiler-specific SIMD handling for problematic types
#if defined(__GNUC__) && !defined(__clang__)
// GCC-specific: Disable SIMD warnings for unsupported types
#define PRAGMA_OMP_DECLARE_SIMD_SAFE \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wattributes\"") \
_Pragma("omp declare simd") \
_Pragma("GCC diagnostic pop")
#elif defined(__clang__)
// Clang-specific: Similar approach
#define PRAGMA_OMP_DECLARE_SIMD_SAFE \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wignored-attributes\"") \
_Pragma("omp declare simd") \
_Pragma("clang diagnostic pop")
#elif defined(_MSC_VER)
// MSVC: No SIMD pragma, just inline
#define PRAGMA_OMP_DECLARE_SIMD_SAFE
#else
// Default fallback
#define PRAGMA_OMP_DECLARE_SIMD_SAFE _Pragma("omp declare simd")
#endif
#if defined(_MSC_VER)
#define OMP_STRINGIFY_HELPER(args) #args
#define OMP_STRINGIFY(args) OMP_STRINGIFY_HELPER(args)
#define OMP_IF(args)
#define OMP_SCHEDULE(args)
#define PRAGMA_OMP_ATOMIC
#define PRAGMA_OMP_ATOMIC_ARGS(args)
#define PRAGMA_OMP_CRITICAL
#define PRAGMA_OMP_DECLARE_SIMD
#define PRAGMA_OMP_SIMD __pragma(omp simd)
#define PRAGMA_OMP_SIMD_ARGS(args)
#define PRAGMA_OMP_DECLARE_REDUCTION(OP_NAME, TYPE, OPERATOR, INIT)
#define PRAGMA_OMP_PARALLEL
#define PRAGMA_OMP_PARALLEL_REDUCTION(args)
#define PRAGMA_OMP_PARALLEL_ARGS(args)
#define PRAGMA_OMP_PARALLEL_THREADS(args)
#define PRAGMA_OMP_PARALLEL_THREADS_IF(threads, condition)
#define PRAGMA_OMP_PARALLEL_FOR
#define PRAGMA_OMP_PARALLEL_FOR_ARGS(args)
#define PRAGMA_OMP_PARALLEL_FOR_IF(args)
#define PRAGMA_OMP_PARALLEL_FOR_COLLAPSE(loops)
#define PRAGMA_OMP_PARALLEL_FOR_REDUCTION(args)
#define PRAGMA_OMP_PARALLEL_FOR_THREADS(args)
#define PRAGMA_OMP_PARALLEL_FOR_SIMD
#define PRAGMA_OMP_PARALLEL_FOR_SIMD_ARGS(args)
#define PRAGMA_OMP_PARALLEL_FOR_SIMD_COLLAPSE(loops)
#define PRAGMA_OMP_PARALLEL_FOR_SIMD_REDUCTION(args)
#define PRAGMA_OMP_PARALLEL_FOR_SIMD_THREADS(args)
#define PRAGMA_OMP_PARALLEL_FOR_SIMD_THREADS_COLLAPSE(threads, loops)
#define PRAGMA_OMP_PARALLEL_SECTIONS
#define PRAGMA_OMP_SECTION
#define PRAGMA_OMP_SINGLE
#define PRAGMA_OMP_SINGLE_ARGS(args)
#define PRAGMA_OMP_TASK
#else
#define OMP_STRINGIFY_HELPER(args) #args
#define OMP_STRINGIFY(args) OMP_STRINGIFY_HELPER(args)
#define OMP_IF(args) if (args)
#define OMP_SCHEDULE(args) schedule(args)
#define PRAGMA_OMP_ATOMIC _Pragma(OMP_STRINGIFY(omp atomic))
#define PRAGMA_OMP_ATOMIC_ARGS(args) _Pragma(OMP_STRINGIFY(omp atomic args))
#define PRAGMA_OMP_CRITICAL _Pragma(OMP_STRINGIFY(omp critical))
#define PRAGMA_OMP_DECLARE_SIMD _Pragma("omp declare simd")
#define PRAGMA_OMP_SIMD _Pragma(OMP_STRINGIFY(omp simd))
#define PRAGMA_OMP_SIMD_ARGS(args) _Pragma(OMP_STRINGIFY(omp simd args))
#define PRAGMA_OMP_DECLARE_REDUCTION(OP_NAME, TYPE, OPERATOR, INIT) \
_Pragma(OMP_STRINGIFY(omp declare reduction(OP_NAME : TYPE : omp_out OPERATOR omp_in) \
initializer(omp_priv = INIT)))
#define PRAGMA_OMP_PARALLEL _Pragma(OMP_STRINGIFY(omp parallel default(shared)))
#define PRAGMA_OMP_PARALLEL_REDUCTION(...) \
_Pragma(OMP_STRINGIFY(omp parallel reduction(__VA_ARGS__) default(shared)))
#define PRAGMA_OMP_PARALLEL_ARGS(...) \
_Pragma(OMP_STRINGIFY(omp parallel __VA_ARGS__ default(shared)))
#define PRAGMA_OMP_PARALLEL_THREADS(args) \
_Pragma(OMP_STRINGIFY(omp parallel num_threads(args) if (args > 1) default(shared)))
#define PRAGMA_OMP_PARALLEL_THREADS_IF(threads, condition) \
_Pragma(OMP_STRINGIFY(omp parallel num_threads(threads) if (condition) default(shared)))
#define PRAGMA_OMP_PARALLEL_FOR \
_Pragma(OMP_STRINGIFY(omp parallel for default(shared)))
#define PRAGMA_OMP_PARALLEL_FOR_REDUCTION(...) \
_Pragma(OMP_STRINGIFY(omp parallel for reduction(__VA_ARGS__) default(shared)))
#define PRAGMA_OMP_PARALLEL_FOR_ARGS(...) \
_Pragma(OMP_STRINGIFY(omp parallel for __VA_ARGS__ default(shared)))
#define PRAGMA_OMP_PARALLEL_FOR_IF(args) \
_Pragma(OMP_STRINGIFY(omp parallel for if(args) default(shared)))
#define PRAGMA_OMP_PARALLEL_FOR_COLLAPSE(loops) \
_Pragma(OMP_STRINGIFY(omp parallel for default(shared) collapse(loops)))
#define PRAGMA_OMP_PARALLEL_FOR_THREADS(args) \
_Pragma(OMP_STRINGIFY(omp parallel for num_threads(args) if(args > 1) default(shared)))
#define PRAGMA_OMP_PARALLEL_FOR_SIMD \
_Pragma(OMP_STRINGIFY(omp parallel for simd default(shared)))
#define PRAGMA_OMP_PARALLEL_FOR_SIMD_ARGS(...) \
_Pragma(OMP_STRINGIFY(omp parallel for simd __VA_ARGS__ default(shared)))
#define PRAGMA_OMP_PARALLEL_FOR_SIMD_COLLAPSE(loops) \
_Pragma(OMP_STRINGIFY(omp parallel for simd default(shared) collapse(loops)))
#define PRAGMA_OMP_PARALLEL_FOR_SIMD_REDUCTION(...) \
_Pragma(OMP_STRINGIFY(omp parallel for simd reduction(__VA_ARGS__) default(shared)))
#define PRAGMA_OMP_PARALLEL_FOR_SIMD_THREADS(args) \
_Pragma(OMP_STRINGIFY(omp parallel for simd num_threads(args) if(args > 1) default(shared)))
#define PRAGMA_OMP_PARALLEL_FOR_SIMD_THREADS_COLLAPSE(threads, loops) \
_Pragma(OMP_STRINGIFY(omp parallel for simd num_threads(threads) if(threads > 1) default(shared) collapse(loops)))
#define PRAGMA_OMP_PARALLEL_SECTIONS \
_Pragma(OMP_STRINGIFY(omp parallel sections))
#define PRAGMA_OMP_SECTION \
_Pragma(OMP_STRINGIFY(omp section))
#define PRAGMA_OMP_SINGLE \
_Pragma(OMP_STRINGIFY(omp single))
#define PRAGMA_OMP_SINGLE_ARGS(...) \
_Pragma(OMP_STRINGIFY(omp single __VA_ARGS__))
#define PRAGMA_OMP_TASK \
_Pragma(OMP_STRINGIFY(omp task))
#endif
// Reduction function templates
#define FUNC_RL std::function<int64_t(sd::LongType, sd::LongType, sd::LongType, sd::LongType)>
#define FUNC_AL std::function<sd::LongType(sd::LongType, sd::LongType)>
// Aggregation functions
#define FUNC_RD std::function<double(sd::LongType, sd::LongType, sd::LongType, sd::LongType)>
#define FUNC_AD std::function<double(double, double)>
// Parallel block
#define FUNC_DO std::function<void(sd::LongType, sd::LongType)>
// Parallel_for block
#define FUNC_1D std::function<void(sd::LongType, sd::LongType, sd::LongType, sd::LongType)>
#define FUNC_2D \
std::function<void(sd::LongType, sd::LongType, sd::LongType, sd::LongType, \
sd::LongType, sd::LongType, sd::LongType)>
#define FUNC_3D \
std::function<void(sd::LongType, sd::LongType, sd::LongType, sd::LongType, \
sd::LongType, sd::LongType, sd::LongType, sd::LongType, \
sd::LongType, sd::LongType)>
// Aggregation lambda
#define LAMBDA_AL [&](sd::LongType _old, sd::LongType _new) -> sd::LongType
#define LAMBDA_AD [&](double _old, double _new) -> double
#define LAMBDA_SUML \
LAMBDA_AL { return _old + _new; }
#define LAMBDA_SUMD \
LAMBDA_AD { return _old + _new; }
// Reduction lambda
#define PRAGMA_REDUCE_LONG \
[&](sd::LongType thread_id, sd::LongType start, sd::LongType stop, sd::LongType increment) \
mutable -> sd::LongType
#define PRAGMA_REDUCE_DOUBLE \
[&](sd::LongType thread_id, sd::LongType start, sd::LongType stop, sd::LongType increment) \
mutable -> double
// Parallel block lambda
#define PRAGMA_THREADS_DO \
[&](sd::LongType thread_id, sd::LongType numThreads) -> void
// Parallel_for lambdas
#define PRAGMA_THREADS_FOR \
[&](sd::LongType thread_id, sd::LongType start, sd::LongType stop, sd::LongType increment) \
-> void
#define PRAGMA_THREADS_FOR_2D \
[&](sd::LongType thread_id, sd::LongType start_x, sd::LongType stop_x, sd::LongType inc_x, \
sd::LongType start_y, sd::LongType stop_y, sd::LongType inc_y) -> void
#define PRAGMA_THREADS_FOR_3D \
[&](sd::LongType thread_id, sd::LongType start_x, sd::LongType stop_x, sd::LongType inc_x, \
sd::LongType start_y, sd::LongType stop_y, sd::LongType inc_y, \
sd::LongType start_z, sd::LongType stop_z, sd::LongType inc_z) -> void
// OpenMP reduction declarations
#if !defined(_MSC_VER)
// Declare custom reductions using the '+' operator for custom types
#if defined(HAS_FLOAT16)
#pragma omp declare reduction(+: float16 : omp_out += omp_in) \
initializer(omp_priv = float16(0.0f))
#endif
#if defined(HAS_BFLOAT16)
#pragma omp declare reduction(+: bfloat16 : omp_out += omp_in) \
initializer(omp_priv = bfloat16(0.0f))
#endif
// For other custom types, declare similar reductions using the '+' operator
#endif // !defined(_MSC_VER)
#endif // DEV_TESTS_OPENMP_PRAGMAS_H
+33
View File
@@ -0,0 +1,33 @@
/* ******************************************************************************
*
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
******************************************************************************/
#pragma once
// TODO convert this into an enum class
// might break JNI though...
typedef int OpType;
#if defined(_MSC_VER) && (_MSC_VER < 1900)
#define constexpr
#endif
namespace op_type {
constexpr OpType Variance = 0;
constexpr OpType StandardDeviation = 1;
} // namespace op_type
@@ -0,0 +1,99 @@
/* ******************************************************************************
*
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
******************************************************************************/
//
// @author raver119@gmail.com
//
#ifndef SD_PLATFORM_BOILERPLATE_H
#define SD_PLATFORM_BOILERPLATE_H
#include <ConstMessages.h>
#include <execution/Engine.h>
#define CONCATP(A, B) A##_##B
#define DECLARE_PLATFORM_F(NAME, ENGINE, CNAME) \
class SD_LIB_EXPORT PLATFORM_##CNAME : public PlatformHelper { \
public: \
PLATFORM_##CNAME() : PlatformHelper(#NAME, samediff::Engine::ENGINE) {} \
bool isUsable(graph::Context &context) override; \
sd::Status invokeHelper(graph::Context &context) override; \
};
#define DECLARE_PLATFORM(NAME, ENGINE) DECLARE_PLATFORM_F(NAME, ENGINE, NAME##_##ENGINE)
#define PLATFORM_IMPL_F(NAME, ENGINE, CNAME) \
struct SD_LIB_EXPORT __registratorPlatformHelper_##CNAME { \
__registratorPlatformHelper_##CNAME() { \
auto helper = new PLATFORM_##CNAME(); \
OpRegistrator::getInstance().registerHelper(helper); \
} \
}; \
static __registratorPlatformHelper_##CNAME platformHelper_##CNAME; \
sd::Status PLATFORM_##CNAME::invokeHelper(sd::graph::Context &block)
#define PLATFORM_IMPL(NAME, ENGINE) PLATFORM_IMPL_F(NAME, ENGINE, NAME##_##ENGINE)
#define PLATFORM_CHECK_F(NAME, ENGINE, CNAME) bool PLATFORM_##CNAME::isUsable(graph::Context &block)
#define PLATFORM_CHECK(NAME, ENGINE) PLATFORM_CHECK_F(NAME, ENGINE, NAME##_##ENGINE)
#define DECLARE_PLATFORM_LEGACY_F(PREFIX, OPNUM, ENGINE, CNAME) \
class SD_LIB_EXPORT PLATFORM_LEGACY_##CNAME : public PlatformHelperLegacy { \
public: \
PLATFORM_LEGACY_##CNAME() : PlatformHelperLegacy(PREFIX, OPNUM, samediff::Engine::ENGINE) {} \
bool isUsable(void *extraParams, const sd::LongType *outShapeInfo, const sd::LongType *inArg0ShapeInfo, \
const sd::LongType *inArg1ShapeInfo) override; \
sd::Status invokeHelper(void *extraParams, const sd::LongType *outShapeInfo, sd::InteropDataBuffer *outputBuffer, \
const sd::LongType *inArg0ShapeInfo, const sd::InteropDataBuffer *inArg0Buffer, \
const sd::LongType *inArg1ShapeInfo, const sd::InteropDataBuffer *inArg1Buffer) override; \
};
#define PLATFORM_LEGACY_IMPL_F(CNAME) \
struct SD_LIB_EXPORT __registratorPlatformHelper_##CNAME { \
__registratorPlatformHelper_##CNAME() { \
auto helper = new PLATFORM_LEGACY_##CNAME(); \
OpRegistrator::getInstance().registerHelperLegacy(helper); \
} \
}; \
static __registratorPlatformHelper_##CNAME platformHelper_##CNAME; \
sd::Status PLATFORM_LEGACY_##CNAME::invokeHelper( \
void *extraParams, const sd::LongType *outShapeInfo, sd::InteropDataBuffer *outputBuffer, \
const sd::LongType *inArg0ShapeInfo, const sd::InteropDataBuffer *inArg0Buffer, \
const sd::LongType *inArg1ShapeInfo, const sd::InteropDataBuffer *inArg1Buffer)
#define PLATFORM_LEGACY_CHECK_F(CNAME) \
bool PLATFORM_LEGACY_##CNAME::isUsable(void *extraParams, const sd::LongType *outShapeInfo, \
const sd::LongType *inArg0ShapeInfo, const sd::LongType *inArg1ShapeInfo)
#define DECLARE_PLATFORM_TRANSFORM_STRICT(OP_ENUM_ENTRY, ENGINE) \
DECLARE_PLATFORM_LEGACY_F(UNIQUE_TRANSFORM_STRICT_PREFIX, transform::StrictOps::OP_ENUM_ENTRY, ENGINE, \
TRANSFORM_STRICT##_##OP_ENUM_ENTRY##_##ENGINE)
#define PLATFORM_TRANSFORM_STRICT_IMPL(OP_ENUM_ENTRY, ENGINE) \
PLATFORM_LEGACY_IMPL_F(TRANSFORM_STRICT##_##OP_ENUM_ENTRY##_##ENGINE)
#define PLATFORM_TRANSFORM_STRICT_CHECK(OP_ENUM_ENTRY, ENGINE) \
PLATFORM_LEGACY_CHECK_F(TRANSFORM_STRICT##_##OP_ENUM_ENTRY##_##ENGINE)
#define DECLARE_PLATFORM_SCALAR_OP(OP_ENUM_ENTRY, ENGINE) \
DECLARE_PLATFORM_LEGACY_F(UNIQUE_SCALAROP_PREFIX, scalar::Ops::OP_ENUM_ENTRY, ENGINE, \
SCALAR_OP##_##OP_ENUM_ENTRY##_##ENGINE)
#define PLATFORM_SCALAR_OP_IMPL(OP_ENUM_ENTRY, ENGINE) \
PLATFORM_LEGACY_IMPL_F(SCALAR_OP##_##OP_ENUM_ENTRY##_##ENGINE)
#define PLATFORM_SCALAR_OP_CHECK(OP_ENUM_ENTRY, ENGINE) \
PLATFORM_LEGACY_CHECK_F(SCALAR_OP##_##OP_ENUM_ENTRY##_##ENGINE)
#endif // SD_PLATFORM_BOILERPLATE_H
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,884 @@
//
// Created by agibsonccc on 8/6/25.
//
/* ******************************************************************************
*
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
******************************************************************************/
#ifndef LIBND4J_TYPE_INSTANTIATE_BOILERPLATE_H
#define LIBND4J_TYPE_INSTANTIATE_BOILERPLATE_H
#include <system/selective_rendering.h>
// ===========================================================================
// TEMPLATE INSTANTIATION MACROS - Used for declaring template instantiations
// ===========================================================================
// Single type template instantiation using aliases only
#define SD_INSTANTIATE_SINGLE_DECL(TEMPLATE_NAME, SIGNATURE, TYPE_ALIAS, TYPE) \
SD_IF_SINGLE_ALIAS_COMPILED(TYPE_ALIAS, \
TEMPLATE_NAME<TYPE> SIGNATURE; \
)
// Double type template instantiation using aliases only
#define SD_INSTANTIATE_DOUBLE_DECL(TEMPLATE_NAME, SIGNATURE, TYPE_A_ALIAS, TYPE_A, TYPE_B_ALIAS, TYPE_B) \
SD_IF_PAIR_ALIAS_COMPILED(TYPE_A_ALIAS, TYPE_B_ALIAS, \
template TEMPLATE_NAME<TYPE_A, TYPE_B> SIGNATURE; \
)
// Triple type template instantiation using aliases only
#define SD_INSTANTIATE_TRIPLE_DECL(TEMPLATE_NAME, SIGNATURE, TYPE_A_ALIAS, TYPE_A, TYPE_B_ALIAS, TYPE_B, TYPE_C_ALIAS, TYPE_C) \
SD_IF_TRIPLE_ALIAS_COMPILED(TYPE_A_ALIAS, TYPE_B_ALIAS, TYPE_C_ALIAS, \
TEMPLATE_NAME<TYPE_A, TYPE_B, TYPE_C> SIGNATURE; \
)
// Template instantiation with same type used twice using aliases only
#define SD_INSTANTIATE_SINGLE_TWICE_DECL(TEMPLATE_NAME, SIGNATURE, TYPE_ALIAS, TYPE) \
SD_IF_PAIR_ALIAS_COMPILED(TYPE_ALIAS, TYPE_ALIAS, \
TEMPLATE_NAME<TYPE, TYPE> SIGNATURE; \
)
// Template instantiation with same type used three times using aliases only
#define SD_INSTANTIATE_SINGLE_THRICE_DECL(TEMPLATE_NAME, SIGNATURE, TYPE_ALIAS, TYPE) \
SD_IF_TRIPLE_ALIAS_COMPILED(TYPE_ALIAS, TYPE_ALIAS, TYPE_ALIAS, \
TEMPLATE_NAME<TYPE, TYPE, TYPE> SIGNATURE; \
)
// Unchained single type instantiation using aliases only
#define SD_INSTANTIATE_UNCHAINED_SINGLE_DECL(TEMPLATE_NAME, SIGNATURE, TYPE_ALIAS, TYPE) \
SD_IF_SINGLE_ALIAS_COMPILED(TYPE_ALIAS, \
TEMPLATE_NAME TYPE SIGNATURE; \
)
// Partial single type instantiation using aliases only
#define SD_INSTANTIATE_PARTIAL_SINGLE_DECL(TEMPLATE_NAME, SIGNATURE, TYPE_ALIAS, TYPE) \
SD_IF_SINGLE_ALIAS_COMPILED(TYPE_ALIAS, \
TEMPLATE_NAME TYPE, UNPAREN2(SIGNATURE); \
)
// Triple partial instantiation using aliases only
#define SD_INSTANTIATE_TRIPLE_PARTIAL_DECL(TEMPLATE_NAME, SIGNATURE, TYPE_A, TYPE_B, TYPE_C_ALIAS, TYPE_C) \
SD_IF_SINGLE_ALIAS_COMPILED(TYPE_C_ALIAS, \
TEMPLATE_NAME<TYPE_A, TYPE_B, TYPE_C> SIGNATURE; \
)
// Special case for triple with types only (used by pairwise)
#define SD_INSTANTIATE_TRIPLE_TYPES_ONLY_DECL(TEMPLATE_NAME, TYPE_B, SIGNATURE, TYPE_A, TYPE_C) \
TEMPLATE_NAME<TYPE_A, TYPE_B, TYPE_C> SIGNATURE;
// ===========================================================================
// FUNCTION CALL MACROS - Used for calling templated functions in selectors
// ===========================================================================
// Single type function call - for use in switch cases
#define SD_INSTANTIATE_SINGLE(NAME, SIGNATURE, TYPE_ALIAS, TYPE) \
NAME<TYPE> SIGNATURE;
// Double type function call
#define SD_INSTANTIATE_DOUBLE(TEMPLATE_NAME, SIGNATURE, TYPE_A_ALIAS, TYPE_A, TYPE_B_ALIAS, TYPE_B) \
TEMPLATE_NAME<TYPE_A, TYPE_B> SIGNATURE
// Triple type function call
#define SD_INSTANTIATE_TRIPLE(TEMPLATE_NAME, SIGNATURE, TYPE_A_ALIAS, TYPE_A, TYPE_B_ALIAS, TYPE_B, TYPE_C_ALIAS, TYPE_C) \
TEMPLATE_NAME<TYPE_A, TYPE_B, TYPE_C> SIGNATURE
// Function call with same type used twice
#define SD_INSTANTIATE_SINGLE_TWICE(TEMPLATE_NAME, SIGNATURE, TYPE_ALIAS, TYPE) \
TEMPLATE_NAME<TYPE, TYPE> SIGNATURE
// Function call with same type used three times
#define SD_INSTANTIATE_SINGLE_THRICE(TEMPLATE_NAME, SIGNATURE, TYPE_ALIAS, TYPE) \
TEMPLATE_NAME<TYPE, TYPE, TYPE> SIGNATURE
// Unchained single type function call
#define SD_INSTANTIATE_UNCHAINED_SINGLE(TEMPLATE_NAME, SIGNATURE, TYPE_ALIAS, TYPE) \
TEMPLATE_NAME TYPE SIGNATURE
// Partial single type function call
#define SD_INSTANTIATE_PARTIAL_SINGLE(TEMPLATE_NAME, SIGNATURE, TYPE_ALIAS, TYPE) \
TEMPLATE_NAME TYPE, UNPAREN2(SIGNATURE)
// Triple partial function call
#define SD_INSTANTIATE_TRIPLE_PARTIAL(TEMPLATE_NAME, SIGNATURE, TYPE_A, TYPE_B, TYPE_C_ALIAS, TYPE_C) \
TEMPLATE_NAME<TYPE_A, TYPE_B, TYPE_C> SIGNATURE
// Special case for triple with types only (used by pairwise)
#define SD_INSTANTIATE_TRIPLE_TYPES_ONLY(TEMPLATE_NAME, TYPE_B, SIGNATURE, TYPE_A, TYPE_C) \
TEMPLATE_NAME<TYPE_A, TYPE_B, TYPE_C> SIGNATURE
// ===========================================================================
// RAW TEMPLATE DECLARATION MACROS - Generate template syntax without conditionals
// For use inside conditional compilation wrappers
// ===========================================================================
// Raw single type template declaration
#define SD_RAW_SINGLE_TEMPLATE_DECL(TEMPLATE_NAME, SIGNATURE, TYPE) \
template TEMPLATE_NAME<TYPE> SIGNATURE;
// Raw double type template declaration
#define SD_RAW_DOUBLE_TEMPLATE_DECL(TEMPLATE_NAME, SIGNATURE, TYPE_A, TYPE_B) \
template SIGNATURE<TYPE_A, TYPE_B>;
// Raw triple type template declaration
#define SD_RAW_TRIPLE_TEMPLATE_DECL(TEMPLATE_NAME, SIGNATURE, TYPE_A, TYPE_B, TYPE_C) \
template TEMPLATE_NAME<TYPE_A, TYPE_B, TYPE_C> SIGNATURE;
// Raw template declaration with same type used twice
#define SD_RAW_SINGLE_TWICE_TEMPLATE_DECL(TEMPLATE_NAME, SIGNATURE, TYPE) \
template TEMPLATE_NAME<TYPE, TYPE> SIGNATURE;
// Raw template declaration with same type used three times
#define SD_RAW_SINGLE_THRICE_TEMPLATE_DECL(TEMPLATE_NAME, SIGNATURE, TYPE) \
template TEMPLATE_NAME<TYPE, TYPE, TYPE> SIGNATURE;
// Raw unchained single type template declaration
#define SD_RAW_UNCHAINED_SINGLE_TEMPLATE_DECL(TEMPLATE_NAME, SIGNATURE, TYPE) \
template TEMPLATE_NAME TYPE SIGNATURE;
// Raw partial single type template declaration
#define SD_RAW_PARTIAL_SINGLE_TEMPLATE_DECL(TEMPLATE_NAME, SIGNATURE, TYPE) \
template TEMPLATE_NAME TYPE, UNPAREN2(SIGNATURE);
// Raw triple partial template declaration
#define SD_RAW_TRIPLE_PARTIAL_TEMPLATE_DECL(TEMPLATE_NAME, SIGNATURE, TYPE_A, TYPE_B, TYPE_C) \
template TEMPLATE_NAME<TYPE_A, TYPE_B, TYPE_C> SIGNATURE;
// Raw triple with types only template declaration (used by pairwise)
#define SD_RAW_TRIPLE_TYPES_ONLY_TEMPLATE_DECL(TEMPLATE_NAME, TYPE_B, SIGNATURE, TYPE_A, TYPE_C) \
template TEMPLATE_NAME<TYPE_A, TYPE_B, TYPE_C> SIGNATURE;
// ============================================================================
// SECTION 3: CONDITIONAL EXPANSION PRIMITIVES (VARIADIC)
// ============================================================================
// Statement context expansions (for use in function bodies)
#define SD_IF_1(...) __VA_ARGS__
#define SD_IF_0(...) do {} while(0);
// Fallback for undefined _COMPILED flags (treated as 0/false)
#define SD_IF_(...) do {} while(0);
// Declaration context expansions (for use at file/namespace scope)
#define SD_IF_DECL_1(...) __VA_ARGS__
#define SD_IF_DECL_0(...) /* filtered out */
// Fallback for undefined _COMPILED flags (treated as 0/false)
#define SD_IF_DECL_(...) /* filtered out */
// Expression context expansions (for use in expressions)
#define SD_IF_EXPR_1(...) __VA_ARGS__
#define SD_IF_EXPR_0(...) ((void)0)
// Fallback for undefined _COMPILED flags (treated as 0/false)
#define SD_IF_EXPR_(...) ((void)0)
// Special whitespace-preserving helpers
#define SD_UNPAREN(...) SD_UNPAREN_IMPL __VA_ARGS__
#define SD_UNPAREN_IMPL(...) __VA_ARGS__
#define SD_IDENTITY(...) __VA_ARGS__
#define SD_EXPAND(...) __VA_ARGS__
// ============================================================================
// SECTION 4: TOKEN MANIPULATION HELPERS
// ============================================================================
// Basic concatenation macros
#define SD_CAT(a, b) SD_CAT_I(a, b)
#define SD_CAT_I(a, b) a ## b
// Three-token concatenation
#define SD_CAT3(a, b, c) SD_CAT3_I(a, b, c)
#define SD_CAT3_I(a, b, c) a ## b ## c
// Five-token concatenation
#define SD_CAT5(a, b, c, d, e) SD_CAT5_I(a, b, c, d, e)
#define SD_CAT5_I(a, b, c, d, e) a ## b ## c ## d ## e
// Seven-token concatenation
#define SD_CAT7(a, b, c, d, e, f, g) SD_CAT7_I(a, b, c, d, e, f, g)
#define SD_CAT7_I(a, b, c, d, e, f, g) a ## b ## c ## d ## e ## f ## g
// ============================================================================
// SECTION 5: COMPILATION CHECK MACROS
// ============================================================================
// Check if type combinations are compiled (returns 0 or 1)
#define SD_IS_SINGLE_COMPILED(NUM) \
SD_CAT3(SD_SINGLE_TYPE_, NUM, _COMPILED)
#define SD_IS_PAIR_COMPILED(NUM1, NUM2) \
SD_CAT5(SD_PAIR_TYPE_, NUM1, _, NUM2, _COMPILED)
#define SD_IS_TRIPLE_COMPILED(NUM1, NUM2, NUM3) \
SD_CAT7(SD_TRIPLE_TYPE_, NUM1, _, NUM2, _, NUM3, _COMPILED)
// ============================================================================
// SECTION 6: UNIFIED INTERFACE - NUMERIC (VARIADIC)
// ============================================================================
// Double-expansion pattern: force SD_*_TYPE_*_COMPILED to expand to its value before concatenation
#define SD_CAT_AFTER_EXPAND(a, b) SD_CAT(a, b)
// Intermediate macros that use CAT_AFTER_EXPAND to ensure flag value is expanded first
#define SD_IF_SINGLE_COMPILED_I(COMPILED_FLAG, ...) \
SD_CAT_AFTER_EXPAND(SD_IF_, COMPILED_FLAG)(__VA_ARGS__)
#define SD_IF_PAIR_COMPILED_I(COMPILED_FLAG, ...) \
SD_CAT_AFTER_EXPAND(SD_IF_, COMPILED_FLAG)(__VA_ARGS__)
#define SD_IF_TRIPLE_COMPILED_I(COMPILED_FLAG, ...) \
SD_CAT_AFTER_EXPAND(SD_IF_, COMPILED_FLAG)(__VA_ARGS__)
// Public interface
#define SD_IF_SINGLE_COMPILED(TYPE_NUM, ...) \
SD_IF_SINGLE_COMPILED_I(SD_IS_SINGLE_COMPILED(TYPE_NUM), __VA_ARGS__)
#define SD_IF_PAIR_COMPILED(TYPE1_NUM, TYPE2_NUM, ...) \
SD_IF_PAIR_COMPILED_I(SD_IS_PAIR_COMPILED(TYPE1_NUM, TYPE2_NUM), __VA_ARGS__)
#define SD_IF_TRIPLE_COMPILED(TYPE1_NUM, TYPE2_NUM, TYPE3_NUM, ...) \
SD_IF_TRIPLE_COMPILED_I(SD_IS_TRIPLE_COMPILED(TYPE1_NUM, TYPE2_NUM, TYPE3_NUM), __VA_ARGS__)
// Direct numeric type ID interfaces (declaration context)
// Use CAT_AFTER_EXPAND to ensure flag value is expanded before concatenation
#define SD_IF_SINGLE_COMPILED_DECL_I(COMPILED_FLAG, ...) \
SD_CAT_AFTER_EXPAND(SD_IF_DECL_, COMPILED_FLAG)(__VA_ARGS__)
#define SD_IF_PAIR_COMPILED_DECL_I(COMPILED_FLAG, ...) \
SD_CAT_AFTER_EXPAND(SD_IF_DECL_, COMPILED_FLAG)(__VA_ARGS__)
#define SD_IF_TRIPLE_COMPILED_DECL_I(COMPILED_FLAG, ...) \
SD_CAT_AFTER_EXPAND(SD_IF_DECL_, COMPILED_FLAG)(__VA_ARGS__)
// Public interface
#define SD_IF_SINGLE_COMPILED_DECL(TYPE_NUM, ...) \
SD_IF_SINGLE_COMPILED_DECL_I(SD_IS_SINGLE_COMPILED(TYPE_NUM), __VA_ARGS__)
#define SD_IF_PAIR_COMPILED_DECL(TYPE1_NUM, TYPE2_NUM, ...) \
SD_IF_PAIR_COMPILED_DECL_I(SD_IS_PAIR_COMPILED(TYPE1_NUM, TYPE2_NUM), __VA_ARGS__)
#define SD_IF_TRIPLE_COMPILED_DECL(TYPE1_NUM, TYPE2_NUM, TYPE3_NUM, ...) \
SD_IF_TRIPLE_COMPILED_DECL_I(SD_IS_TRIPLE_COMPILED(TYPE1_NUM, TYPE2_NUM, TYPE3_NUM), __VA_ARGS__)
// ============================================================================
// SECTION 7: UNIFIED INTERFACE - DATATYPE ENUM (VARIADIC)
// ============================================================================
// Helper macros for forcing evaluation through indirection
#define SD_EVAL_ENUM_TO_NUM_I(x) x
#define SD_EVAL_ENUM_TO_NUM(DTYPE) SD_EVAL_ENUM_TO_NUM_I(SD_CAT(SD_ENUM_TO_NUM_, DTYPE))
// DataType enum interfaces (statement context)
#define SD_IF_SINGLE_DATATYPE_COMPILED(DTYPE, ...) \
SD_IF_SINGLE_COMPILED(SD_EVAL_ENUM_TO_NUM(DTYPE), __VA_ARGS__)
#define SD_IF_PAIR_DATATYPE_COMPILED(DTYPE1, DTYPE2, ...) \
SD_IF_PAIR_COMPILED( \
SD_EVAL_ENUM_TO_NUM(DTYPE1), \
SD_EVAL_ENUM_TO_NUM(DTYPE2), \
__VA_ARGS__)
#define SD_IF_TRIPLE_DATATYPE_COMPILED(DTYPE1, DTYPE2, DTYPE3, ...) \
SD_IF_TRIPLE_COMPILED( \
SD_EVAL_ENUM_TO_NUM(DTYPE1), \
SD_EVAL_ENUM_TO_NUM(DTYPE2), \
SD_EVAL_ENUM_TO_NUM(DTYPE3), \
__VA_ARGS__)
// DataType enum interfaces (declaration context)
#define SD_IF_SINGLE_DATATYPE_COMPILED_DECL(DTYPE, ...) \
SD_IF_SINGLE_COMPILED_DECL(SD_EVAL_ENUM_TO_NUM(DTYPE), __VA_ARGS__)
#define SD_IF_PAIR_DATATYPE_COMPILED_DECL(DTYPE1, DTYPE2, ...) \
SD_IF_PAIR_COMPILED_DECL( \
SD_EVAL_ENUM_TO_NUM(DTYPE1), \
SD_EVAL_ENUM_TO_NUM(DTYPE2), \
__VA_ARGS__)
#define SD_IF_TRIPLE_DATATYPE_COMPILED_DECL(DTYPE1, DTYPE2, DTYPE3, ...) \
SD_IF_TRIPLE_COMPILED_DECL( \
SD_EVAL_ENUM_TO_NUM(DTYPE1), \
SD_EVAL_ENUM_TO_NUM(DTYPE2), \
SD_EVAL_ENUM_TO_NUM(DTYPE3), \
__VA_ARGS__)
// ============================================================================
// SECTION 8: UNIFIED INTERFACE - CONSTEXPR ALIASES (VARIADIC)
// ============================================================================
// Helper macros to force evaluation of SD_ALIAS_TO_NUM_* before passing to SD_IF_*_COMPILED
#define SD_EVAL_ALIAS_TO_NUM(ALIAS) SD_CAT(SD_ALIAS_TO_NUM_, ALIAS)
// Intermediate evaluation macros
#define SD_IF_SINGLE_ALIAS_COMPILED_I(TYPE_NUM, ...) \
SD_IF_SINGLE_COMPILED(TYPE_NUM, __VA_ARGS__)
#define SD_IF_PAIR_ALIAS_COMPILED_I(TYPE_NUM1, TYPE_NUM2, ...) \
SD_IF_PAIR_COMPILED(TYPE_NUM1, TYPE_NUM2, __VA_ARGS__)
#define SD_IF_TRIPLE_ALIAS_COMPILED_I(TYPE_NUM1, TYPE_NUM2, TYPE_NUM3, ...) \
SD_IF_TRIPLE_COMPILED(TYPE_NUM1, TYPE_NUM2, TYPE_NUM3, __VA_ARGS__)
// Constexpr alias interfaces (statement context)
#define SD_IF_SINGLE_ALIAS_COMPILED(ALIAS, ...) \
SD_IF_SINGLE_ALIAS_COMPILED_I(SD_EVAL_ALIAS_TO_NUM(ALIAS), __VA_ARGS__)
#define SD_IF_PAIR_ALIAS_COMPILED(ALIAS1, ALIAS2, ...) \
SD_IF_PAIR_ALIAS_COMPILED_I( \
SD_EVAL_ALIAS_TO_NUM(ALIAS1), \
SD_EVAL_ALIAS_TO_NUM(ALIAS2), \
__VA_ARGS__)
#define SD_IF_TRIPLE_ALIAS_COMPILED(ALIAS1, ALIAS2, ALIAS3, ...) \
SD_IF_TRIPLE_ALIAS_COMPILED_I( \
SD_EVAL_ALIAS_TO_NUM(ALIAS1), \
SD_EVAL_ALIAS_TO_NUM(ALIAS2), \
SD_EVAL_ALIAS_TO_NUM(ALIAS3), \
__VA_ARGS__)
// Intermediate evaluation macros for declaration context
#define SD_IF_SINGLE_ALIAS_COMPILED_DECL_I(TYPE_NUM, ...) \
SD_IF_SINGLE_COMPILED_DECL(TYPE_NUM, __VA_ARGS__)
#define SD_IF_PAIR_ALIAS_COMPILED_DECL_I(TYPE_NUM1, TYPE_NUM2, ...) \
SD_IF_PAIR_COMPILED_DECL(TYPE_NUM1, TYPE_NUM2, __VA_ARGS__)
#define SD_IF_TRIPLE_ALIAS_COMPILED_DECL_I(TYPE_NUM1, TYPE_NUM2, TYPE_NUM3, ...) \
SD_IF_TRIPLE_COMPILED_DECL(TYPE_NUM1, TYPE_NUM2, TYPE_NUM3, __VA_ARGS__)
// Constexpr alias interfaces (declaration context)
#define SD_IF_SINGLE_ALIAS_COMPILED_DECL(ALIAS, ...) \
SD_IF_SINGLE_ALIAS_COMPILED_DECL_I(SD_EVAL_ALIAS_TO_NUM(ALIAS), __VA_ARGS__)
#define SD_IF_PAIR_ALIAS_COMPILED_DECL(ALIAS1, ALIAS2, ...) \
SD_IF_PAIR_ALIAS_COMPILED_DECL_I( \
SD_EVAL_ALIAS_TO_NUM(ALIAS1), \
SD_EVAL_ALIAS_TO_NUM(ALIAS2), \
__VA_ARGS__)
#define SD_IF_TRIPLE_ALIAS_COMPILED_DECL(ALIAS1, ALIAS2, ALIAS3, ...) \
SD_IF_TRIPLE_ALIAS_COMPILED_DECL_I( \
SD_EVAL_ALIAS_TO_NUM(ALIAS1), \
SD_EVAL_ALIAS_TO_NUM(ALIAS2), \
SD_EVAL_ALIAS_TO_NUM(ALIAS3), \
__VA_ARGS__)
// ============================================================================
// SECTION 9: UNIFIED INTERFACE - C++ TYPE NAMES (VARIADIC)
// ============================================================================
// C++ type name interfaces (statement context)
#define SD_IF_SINGLE_TYPE_COMPILED(TYPE, ...) \
SD_IF_SINGLE_COMPILED(SD_CAT(SD_TYPE_TO_NUM_, TYPE), __VA_ARGS__)
#define SD_IF_PAIR_TYPE_COMPILED(TYPE1, TYPE2, ...) \
SD_IF_PAIR_COMPILED( \
SD_CAT(SD_TYPE_TO_NUM_, TYPE1), \
SD_CAT(SD_TYPE_TO_NUM_, TYPE2), \
__VA_ARGS__)
#define SD_IF_TRIPLE_TYPE_COMPILED(TYPE1, TYPE2, TYPE3, ...) \
SD_IF_TRIPLE_COMPILED( \
SD_CAT(SD_TYPE_TO_NUM_, TYPE1), \
SD_CAT(SD_TYPE_TO_NUM_, TYPE2), \
SD_CAT(SD_TYPE_TO_NUM_, TYPE3), \
__VA_ARGS__)
// C++ type name interfaces (declaration context)
#define SD_IF_SINGLE_TYPE_COMPILED_DECL(TYPE, ...) \
SD_IF_SINGLE_COMPILED_DECL(SD_CAT(SD_TYPE_TO_NUM_, TYPE), __VA_ARGS__)
#define SD_IF_PAIR_TYPE_COMPILED_DECL(TYPE1, TYPE2, ...) \
SD_IF_PAIR_COMPILED_DECL( \
SD_CAT(SD_TYPE_TO_NUM_, TYPE1), \
SD_CAT(SD_TYPE_TO_NUM_, TYPE2), \
__VA_ARGS__)
#define SD_IF_TRIPLE_TYPE_COMPILED_DECL(TYPE1, TYPE2, TYPE3, ...) \
SD_IF_TRIPLE_COMPILED_DECL( \
SD_CAT(SD_TYPE_TO_NUM_, TYPE1), \
SD_CAT(SD_TYPE_TO_NUM_, TYPE2), \
SD_CAT(SD_TYPE_TO_NUM_, TYPE3), \
__VA_ARGS__)
// Whitespace-preserving wrappers for BUILD_* macros
// These help preserve whitespace when selective rendering is used
#define SD_PRESERVE_WS(...) __VA_ARGS__
#define SD_PASS_THROUGH(...) __VA_ARGS__
// Helper for fixing parenthesized arguments
#define SD_FIX_PAREN(x) SD_FIX_PAREN_IMPL x
#define SD_FIX_PAREN_IMPL(...) __VA_ARGS__
#define SD_CHAR_IS_INT8 ((sizeof(char) == 1) && (CHAR_MIN < 0))
#define SD_CHAR_IS_UINT8 ((sizeof(char) == 1) && (CHAR_MIN >= 0))
#define SD_SHORT_IS_INT16 (sizeof(short) == 2)
#define SD_INT_IS_INT32 (sizeof(int) == 4)
#define SD_LONG_IS_INT32 (sizeof(long) == 4)
#define SD_LONG_IS_INT64 (sizeof(long) == 8)
#define SD_LONG_LONG_IS_INT64 (sizeof(long long) == 8)
// ============================================================================
// HELPER MACROS FOR SELECTOR VARIANTS
// ============================================================================
// ============================================================================
// HELPER MACROS FOR _SELECTOR_SINGLE
// ============================================================================
#define _EXPAND_SELECTOR_SINGLE_EQUIVALENTS(A, B, C, D) \
CONCAT(_EXPAND_SELECTOR_SINGLE_, D)(A, B, C)
// Type-specific expansions for SELECTOR_SINGLE
#define _EXPAND_SELECTOR_SINGLE_int8_t(A, B, C) \
EVAL(SD_IF_SINGLE_ALIAS_COMPILED(C, A<signed char> B;)) \
CONCAT(_EXPAND_SELECTOR_SINGLE_CHAR_IF_, SD_CHAR_IS_INT8)(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_uint8_t(A, B, C) \
EVAL(SD_IF_SINGLE_ALIAS_COMPILED(C, A<unsigned char> B;)) \
CONCAT(_EXPAND_SELECTOR_SINGLE_UCHAR_IF_, SD_CHAR_IS_UINT8)(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_int64_t(A, B, C) \
EVAL(SD_IF_SINGLE_ALIAS_COMPILED(C, A<long long> B;)) \
CONCAT(_EXPAND_SELECTOR_SINGLE_LONG_IF_, SD_LONG_IS_INT64)(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_LongType(A, B, C) \
EVAL(SD_IF_SINGLE_ALIAS_COMPILED(C, A<long long> B;)) \
CONCAT(_EXPAND_SELECTOR_SINGLE_LONG_IF_, SD_LONG_IS_INT64)(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_uint64_t(A, B, C) \
EVAL(SD_IF_SINGLE_ALIAS_COMPILED(C, A<unsigned long long> B;)) \
CONCAT(_EXPAND_SELECTOR_SINGLE_ULONG_IF_, SD_LONG_IS_INT64)(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_UnsignedLong(A, B, C) \
EVAL(SD_IF_SINGLE_ALIAS_COMPILED(C, A<unsigned long long> B;)) \
CONCAT(_EXPAND_SELECTOR_SINGLE_ULONG_IF_, SD_LONG_IS_INT64)(A, B, C)
// Conditional helpers
#define _EXPAND_SELECTOR_SINGLE_CHAR_IF_0(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_CHAR_IF_1(A, B, C) EVAL(SD_IF_SINGLE_ALIAS_COMPILED(C, A<char> B;))
#define _EXPAND_SELECTOR_SINGLE_UCHAR_IF_0(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_UCHAR_IF_1(A, B, C) EVAL(SD_IF_SINGLE_ALIAS_COMPILED(C, A<char> B;))
#define _EXPAND_SELECTOR_SINGLE_LONG_IF_0(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_LONG_IF_1(A, B, C) EVAL(SD_IF_SINGLE_ALIAS_COMPILED(C, A<long> B;))
#define _EXPAND_SELECTOR_SINGLE_ULONG_IF_0(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_ULONG_IF_1(A, B, C) EVAL(SD_IF_SINGLE_ALIAS_COMPILED(C, A<unsigned long> B;))
// Default - empty macro for types that don't need special handling
#define _EXPAND_SELECTOR_SINGLE_DEFAULT(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_(A, B, C) _EXPAND_SELECTOR_SINGLE_DEFAULT(A, B, C)
#if defined(HAS_FLOAT32)
#define _EXPAND_SELECTOR_SINGLE_float(A, B, C) _EXPAND_SELECTOR_SINGLE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_float(A, B, C)
#endif
#if defined(HAS_DOUBLE)
#define _EXPAND_SELECTOR_SINGLE_double(A, B, C) _EXPAND_SELECTOR_SINGLE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_double(A, B, C)
#endif
#if defined(HAS_FLOAT16)
#define _EXPAND_SELECTOR_SINGLE_float16(A, B, C) _EXPAND_SELECTOR_SINGLE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_float16(A, B, C)
#endif
#if defined(HAS_BFLOAT16)
#define _EXPAND_SELECTOR_SINGLE_bfloat16(A, B, C) _EXPAND_SELECTOR_SINGLE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_bfloat16(A, B, C)
#endif
#if defined(HAS_BOOL)
#define _EXPAND_SELECTOR_SINGLE_bool(A, B, C) _EXPAND_SELECTOR_SINGLE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_bool(A, B, C)
#endif
#if defined(HAS_INT16)
#define _EXPAND_SELECTOR_SINGLE_int16_t(A, B, C) _EXPAND_SELECTOR_SINGLE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_int16_t(A, B, C)
#endif
#if defined(HAS_UINT16)
#define _EXPAND_SELECTOR_SINGLE_uint16_t(A, B, C) _EXPAND_SELECTOR_SINGLE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_uint16_t(A, B, C)
#endif
#if defined(HAS_INT32)
#define _EXPAND_SELECTOR_SINGLE_int32_t(A, B, C) _EXPAND_SELECTOR_SINGLE_DEFAULT(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_Int32Type(A, B, C) _EXPAND_SELECTOR_SINGLE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_int32_t(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_Int32Type(A, B, C)
#endif
#if defined(HAS_UINT32)
#define _EXPAND_SELECTOR_SINGLE_uint32_t(A, B, C) _EXPAND_SELECTOR_SINGLE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_uint32_t(A, B, C)
#endif
#if defined(HAS_INT8)
#define _EXPAND_SELECTOR_SINGLE_SignedChar(A, B, C) _EXPAND_SELECTOR_SINGLE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_SignedChar(A, B, C)
#endif
#if defined(HAS_UINT8)
#define _EXPAND_SELECTOR_SINGLE_UnsignedChar(A, B, C) _EXPAND_SELECTOR_SINGLE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_UnsignedChar(A, B, C)
#endif
// ============================================================================
// HELPER MACROS FOR _SELECTOR_PARTIAL_SINGLE
// ============================================================================
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_EQUIVALENTS(A, B, C, D) \
CONCAT(_EXPAND_SELECTOR_PARTIAL_SINGLE_, D)(A, B, C)
// Type-specific expansions for SELECTOR_PARTIAL_SINGLE
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_int8_t(A, B, C) \
EVAL(SD_IF_SINGLE_ALIAS_COMPILED(C, A signed char, UNPAREN2(B);)) \
CONCAT(_EXPAND_SELECTOR_PARTIAL_SINGLE_CHAR_IF_, SD_CHAR_IS_INT8)(A, B, C)
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_uint8_t(A, B, C) \
EVAL(SD_IF_SINGLE_ALIAS_COMPILED(C, A unsigned char, UNPAREN2(B);)) \
CONCAT(_EXPAND_SELECTOR_PARTIAL_SINGLE_UCHAR_IF_, SD_CHAR_IS_UINT8)(A, B, C)
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_int64_t(A, B, C) \
EVAL(SD_IF_SINGLE_ALIAS_COMPILED(C, A long long, UNPAREN2(B);)) \
CONCAT(_EXPAND_SELECTOR_PARTIAL_SINGLE_LONG_IF_, SD_LONG_IS_INT64)(A, B, C)
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_LongType(A, B, C) \
EVAL(SD_IF_SINGLE_ALIAS_COMPILED(C, A long long, UNPAREN2(B);)) \
CONCAT(_EXPAND_SELECTOR_PARTIAL_SINGLE_LONG_IF_, SD_LONG_IS_INT64)(A, B, C)
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_uint64_t(A, B, C) \
EVAL(SD_IF_SINGLE_ALIAS_COMPILED(C, A unsigned long long, UNPAREN2(B);)) \
CONCAT(_EXPAND_SELECTOR_PARTIAL_SINGLE_ULONG_IF_, SD_LONG_IS_INT64)(A, B, C)
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_UnsignedLong(A, B, C) \
EVAL(SD_IF_SINGLE_ALIAS_COMPILED(C, A unsigned long long, UNPAREN2(B);)) \
CONCAT(_EXPAND_SELECTOR_PARTIAL_SINGLE_ULONG_IF_, SD_LONG_IS_INT64)(A, B, C)
// Conditional helpers
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_CHAR_IF_0(A, B, C)
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_CHAR_IF_1(A, B, C) EVAL(SD_IF_SINGLE_ALIAS_COMPILED(C, A char, UNPAREN2(B);))
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_UCHAR_IF_0(A, B, C)
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_UCHAR_IF_1(A, B, C) EVAL(SD_IF_SINGLE_ALIAS_COMPILED(C, A char, UNPAREN2(B);))
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_LONG_IF_0(A, B, C)
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_LONG_IF_1(A, B, C) EVAL(SD_IF_SINGLE_ALIAS_COMPILED(C, A long, UNPAREN2(B);))
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_ULONG_IF_0(A, B, C)
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_ULONG_IF_1(A, B, C) EVAL(SD_IF_SINGLE_ALIAS_COMPILED(C, A unsigned long, UNPAREN2(B);))
// Default
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_DEFAULT(A, B, C)
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_(A, B, C) _EXPAND_SELECTOR_PARTIAL_SINGLE_DEFAULT(A, B, C)
#if defined(HAS_FLOAT32)
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_float(A, B, C) _EXPAND_SELECTOR_PARTIAL_SINGLE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_float(A, B, C)
#endif
#if defined(HAS_DOUBLE)
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_double(A, B, C) _EXPAND_SELECTOR_PARTIAL_SINGLE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_double(A, B, C)
#endif
#if defined(HAS_FLOAT16)
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_float16(A, B, C) _EXPAND_SELECTOR_PARTIAL_SINGLE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_float16(A, B, C)
#endif
#if defined(HAS_BFLOAT16)
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_bfloat16(A, B, C) _EXPAND_SELECTOR_PARTIAL_SINGLE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_bfloat16(A, B, C)
#endif
#if defined(HAS_BOOL)
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_bool(A, B, C) _EXPAND_SELECTOR_PARTIAL_SINGLE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_bool(A, B, C)
#endif
#if defined(HAS_INT16)
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_int16_t(A, B, C) _EXPAND_SELECTOR_PARTIAL_SINGLE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_int16_t(A, B, C)
#endif
#if defined(HAS_UINT16)
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_uint16_t(A, B, C) _EXPAND_SELECTOR_PARTIAL_SINGLE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_uint16_t(A, B, C)
#endif
#if defined(HAS_INT32)
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_int32_t(A, B, C) _EXPAND_SELECTOR_PARTIAL_SINGLE_DEFAULT(A, B, C)
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_Int32Type(A, B, C) _EXPAND_SELECTOR_PARTIAL_SINGLE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_int32_t(A, B, C)
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_Int32Type(A, B, C)
#endif
#if defined(HAS_UINT32)
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_uint32_t(A, B, C) _EXPAND_SELECTOR_PARTIAL_SINGLE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_uint32_t(A, B, C)
#endif
#if defined(HAS_INT8)
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_SignedChar(A, B, C) _EXPAND_SELECTOR_PARTIAL_SINGLE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_SignedChar(A, B, C)
#endif
#if defined(HAS_UINT8)
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_UnsignedChar(A, B, C) _EXPAND_SELECTOR_PARTIAL_SINGLE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_PARTIAL_SINGLE_UnsignedChar(A, B, C)
#endif
// ============================================================================
// HELPER MACROS FOR _SELECTOR_SINGLE_TWICE
// ============================================================================
#define _EXPAND_SELECTOR_SINGLE_TWICE_EQUIVALENTS(A, B, C, D) \
CONCAT(_EXPAND_SELECTOR_SINGLE_TWICE_, D)(A, B, C)
// Type-specific expansions for SELECTOR_SINGLE_TWICE
#define _EXPAND_SELECTOR_SINGLE_TWICE_int64_t(A, B, C) \
EVAL(SD_IF_PAIR_ALIAS_COMPILED(C, C, A<long long, long long> B;)) \
CONCAT(_EXPAND_SELECTOR_SINGLE_TWICE_LONG_IF_, SD_LONG_IS_INT64)(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_TWICE_LongType(A, B, C) \
EVAL(SD_IF_PAIR_ALIAS_COMPILED(C, C, A<long long, long long> B;)) \
CONCAT(_EXPAND_SELECTOR_SINGLE_TWICE_LONG_IF_, SD_LONG_IS_INT64)(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_TWICE_uint64_t(A, B, C) \
EVAL(SD_IF_PAIR_ALIAS_COMPILED(C, C, A<unsigned long long, unsigned long long> B;)) \
CONCAT(_EXPAND_SELECTOR_SINGLE_TWICE_ULONG_IF_, SD_LONG_IS_INT64)(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_TWICE_UnsignedLong(A, B, C) \
EVAL(SD_IF_PAIR_ALIAS_COMPILED(C, C, A<unsigned long long, unsigned long long> B;)) \
CONCAT(_EXPAND_SELECTOR_SINGLE_TWICE_ULONG_IF_, SD_LONG_IS_INT64)(A, B, C)
// Conditional helpers
#define _EXPAND_SELECTOR_SINGLE_TWICE_LONG_IF_0(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_TWICE_LONG_IF_1(A, B, C) EVAL(SD_IF_PAIR_ALIAS_COMPILED(C, C, A<long, long> B;))
#define _EXPAND_SELECTOR_SINGLE_TWICE_ULONG_IF_0(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_TWICE_ULONG_IF_1(A, B, C) EVAL(SD_IF_PAIR_ALIAS_COMPILED(C, C, A<unsigned long, unsigned long> B;))
// Default
#define _EXPAND_SELECTOR_SINGLE_TWICE_DEFAULT(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_TWICE_(A, B, C) _EXPAND_SELECTOR_SINGLE_TWICE_DEFAULT(A, B, C)
#if defined(HAS_FLOAT32)
#define _EXPAND_SELECTOR_SINGLE_TWICE_float(A, B, C) _EXPAND_SELECTOR_SINGLE_TWICE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_TWICE_float(A, B, C)
#endif
#if defined(HAS_DOUBLE)
#define _EXPAND_SELECTOR_SINGLE_TWICE_double(A, B, C) _EXPAND_SELECTOR_SINGLE_TWICE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_TWICE_double(A, B, C)
#endif
#if defined(HAS_FLOAT16)
#define _EXPAND_SELECTOR_SINGLE_TWICE_float16(A, B, C) _EXPAND_SELECTOR_SINGLE_TWICE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_TWICE_float16(A, B, C)
#endif
#if defined(HAS_BFLOAT16)
#define _EXPAND_SELECTOR_SINGLE_TWICE_bfloat16(A, B, C) _EXPAND_SELECTOR_SINGLE_TWICE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_TWICE_bfloat16(A, B, C)
#endif
#if defined(HAS_BOOL)
#define _EXPAND_SELECTOR_SINGLE_TWICE_bool(A, B, C) _EXPAND_SELECTOR_SINGLE_TWICE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_TWICE_bool(A, B, C)
#endif
#if defined(HAS_INT8)
#define _EXPAND_SELECTOR_SINGLE_TWICE_int8_t(A, B, C) _EXPAND_SELECTOR_SINGLE_TWICE_DEFAULT(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_TWICE_SignedChar(A, B, C) _EXPAND_SELECTOR_SINGLE_TWICE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_TWICE_int8_t(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_TWICE_SignedChar(A, B, C)
#endif
#if defined(HAS_UINT8)
#define _EXPAND_SELECTOR_SINGLE_TWICE_uint8_t(A, B, C) _EXPAND_SELECTOR_SINGLE_TWICE_DEFAULT(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_TWICE_UnsignedChar(A, B, C) _EXPAND_SELECTOR_SINGLE_TWICE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_TWICE_uint8_t(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_TWICE_UnsignedChar(A, B, C)
#endif
#if defined(HAS_INT16)
#define _EXPAND_SELECTOR_SINGLE_TWICE_int16_t(A, B, C) _EXPAND_SELECTOR_SINGLE_TWICE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_TWICE_int16_t(A, B, C)
#endif
#if defined(HAS_UINT16)
#define _EXPAND_SELECTOR_SINGLE_TWICE_uint16_t(A, B, C) _EXPAND_SELECTOR_SINGLE_TWICE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_TWICE_uint16_t(A, B, C)
#endif
#if defined(HAS_INT32)
#define _EXPAND_SELECTOR_SINGLE_TWICE_int32_t(A, B, C) _EXPAND_SELECTOR_SINGLE_TWICE_DEFAULT(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_TWICE_Int32Type(A, B, C) _EXPAND_SELECTOR_SINGLE_TWICE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_TWICE_int32_t(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_TWICE_Int32Type(A, B, C)
#endif
#if defined(HAS_UINT32)
#define _EXPAND_SELECTOR_SINGLE_TWICE_uint32_t(A, B, C) _EXPAND_SELECTOR_SINGLE_TWICE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_TWICE_uint32_t(A, B, C)
#endif
// ============================================================================
// HELPER MACROS FOR _SELECTOR_SINGLE_THRICE
// ============================================================================
#define _EXPAND_SELECTOR_SINGLE_THRICE_EQUIVALENTS(A, B, C, D) \
CONCAT(_EXPAND_SELECTOR_SINGLE_THRICE_, D)(A, B, C)
// Type-specific expansions for SELECTOR_SINGLE_THRICE
#define _EXPAND_SELECTOR_SINGLE_THRICE_int64_t(A, B, C) \
EVAL(SD_IF_TRIPLE_ALIAS_COMPILED(C, C, C, A<long long, long long, long long> B;)) \
CONCAT(_EXPAND_SELECTOR_SINGLE_THRICE_LONG_IF_, SD_LONG_IS_INT64)(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_THRICE_LongType(A, B, C) \
EVAL(SD_IF_TRIPLE_ALIAS_COMPILED(C, C, C, A<long long, long long, long long> B;)) \
CONCAT(_EXPAND_SELECTOR_SINGLE_THRICE_LONG_IF_, SD_LONG_IS_INT64)(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_THRICE_uint64_t(A, B, C) \
EVAL(SD_IF_TRIPLE_ALIAS_COMPILED(C, C, C, A<unsigned long long, unsigned long long, unsigned long long> B;)) \
CONCAT(_EXPAND_SELECTOR_SINGLE_THRICE_ULONG_IF_, SD_LONG_IS_INT64)(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_THRICE_UnsignedLong(A, B, C) \
EVAL(SD_IF_TRIPLE_ALIAS_COMPILED(C, C, C, A<unsigned long long, unsigned long long, unsigned long long> B;)) \
CONCAT(_EXPAND_SELECTOR_SINGLE_THRICE_ULONG_IF_, SD_LONG_IS_INT64)(A, B, C)
// Conditional helpers
#define _EXPAND_SELECTOR_SINGLE_THRICE_LONG_IF_0(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_THRICE_LONG_IF_1(A, B, C) EVAL(SD_IF_TRIPLE_ALIAS_COMPILED(C, C, C, A<long, long, long> B;))
#define _EXPAND_SELECTOR_SINGLE_THRICE_ULONG_IF_0(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_THRICE_ULONG_IF_1(A, B, C) EVAL(SD_IF_TRIPLE_ALIAS_COMPILED(C, C, C, A<unsigned long, unsigned long, unsigned long> B;))
// Default
#define _EXPAND_SELECTOR_SINGLE_THRICE_DEFAULT(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_THRICE_(A, B, C) _EXPAND_SELECTOR_SINGLE_THRICE_DEFAULT(A, B, C)
#if defined(HAS_FLOAT32)
#define _EXPAND_SELECTOR_SINGLE_THRICE_float(A, B, C) _EXPAND_SELECTOR_SINGLE_THRICE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_THRICE_float(A, B, C)
#endif
#if defined(HAS_DOUBLE)
#define _EXPAND_SELECTOR_SINGLE_THRICE_double(A, B, C) _EXPAND_SELECTOR_SINGLE_THRICE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_THRICE_double(A, B, C)
#endif
#if defined(HAS_FLOAT16)
#define _EXPAND_SELECTOR_SINGLE_THRICE_float16(A, B, C) _EXPAND_SELECTOR_SINGLE_THRICE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_THRICE_float16(A, B, C)
#endif
#if defined(HAS_BFLOAT16)
#define _EXPAND_SELECTOR_SINGLE_THRICE_bfloat16(A, B, C) _EXPAND_SELECTOR_SINGLE_THRICE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_THRICE_bfloat16(A, B, C)
#endif
#if defined(HAS_BOOL)
#define _EXPAND_SELECTOR_SINGLE_THRICE_bool(A, B, C) _EXPAND_SELECTOR_SINGLE_THRICE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_THRICE_bool(A, B, C)
#endif
#if defined(HAS_INT8)
#define _EXPAND_SELECTOR_SINGLE_THRICE_int8_t(A, B, C) _EXPAND_SELECTOR_SINGLE_THRICE_DEFAULT(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_THRICE_SignedChar(A, B, C) _EXPAND_SELECTOR_SINGLE_THRICE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_THRICE_int8_t(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_THRICE_SignedChar(A, B, C)
#endif
#if defined(HAS_UINT8)
#define _EXPAND_SELECTOR_SINGLE_THRICE_uint8_t(A, B, C) _EXPAND_SELECTOR_SINGLE_THRICE_DEFAULT(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_THRICE_UnsignedChar(A, B, C) _EXPAND_SELECTOR_SINGLE_THRICE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_THRICE_uint8_t(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_THRICE_UnsignedChar(A, B, C)
#endif
#if defined(HAS_INT16)
#define _EXPAND_SELECTOR_SINGLE_THRICE_int16_t(A, B, C) _EXPAND_SELECTOR_SINGLE_THRICE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_THRICE_int16_t(A, B, C)
#endif
#if defined(HAS_UINT16)
#define _EXPAND_SELECTOR_SINGLE_THRICE_uint16_t(A, B, C) _EXPAND_SELECTOR_SINGLE_THRICE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_THRICE_uint16_t(A, B, C)
#endif
#if defined(HAS_INT32)
#define _EXPAND_SELECTOR_SINGLE_THRICE_int32_t(A, B, C) _EXPAND_SELECTOR_SINGLE_THRICE_DEFAULT(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_THRICE_Int32Type(A, B, C) _EXPAND_SELECTOR_SINGLE_THRICE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_THRICE_int32_t(A, B, C)
#define _EXPAND_SELECTOR_SINGLE_THRICE_Int32Type(A, B, C)
#endif
#if defined(HAS_UINT32)
#define _EXPAND_SELECTOR_SINGLE_THRICE_uint32_t(A, B, C) _EXPAND_SELECTOR_SINGLE_THRICE_DEFAULT(A, B, C)
#else
#define _EXPAND_SELECTOR_SINGLE_THRICE_uint32_t(A, B, C)
#endif
#endif // LIBND4J_TYPE_INSTANTIATE_BOILERPLATE_H
@@ -0,0 +1,106 @@
/* ******************************************************************************
*
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
******************************************************************************/
#ifndef SD_TYPE_INST_H
#define SD_TYPE_INST_H
#include <system/selective_rendering.h>
#include <type_traits>
#include "common.h"
// ============================================================================
// CONDITIONAL INSTANTIATION SYSTEM WITH ARGUMENT COUNT DISPATCH
// ============================================================================
// Count arguments
#define CONDITIONAL_INSTANTIATE_NARGS(...) \
CONDITIONAL_INSTANTIATE_NARGS_IMPL(__VA_ARGS__, 16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
#define CONDITIONAL_INSTANTIATE_NARGS_IMPL(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,N,...) N
// Main conditional instantiation macro
#define CONDITIONAL_INSTANTIATE(condition, ...) \
EVAL(CONDITIONAL_INSTANTIATE_DISPATCH(CONDITIONAL_INSTANTIATE_NARGS(__VA_ARGS__), condition, __VA_ARGS__))
#define CONDITIONAL_INSTANTIATE_DISPATCH(N, condition, ...) \
CONDITIONAL_INSTANTIATE_CAT(CONDITIONAL_INSTANTIATE_, N)(condition, __VA_ARGS__)
#define CONDITIONAL_INSTANTIATE_CAT(a, b) a ## b
// ============================================================================
// SOLUTION 9: FUNCTION-LIKE SELECTION - NO CONCATENATION WITH CONDITIONS
// ============================================================================
// Instead of concatenating condition results, use function-like selection
#define CONDITIONAL_INSTANTIATE_IF(condition) \
CONDITIONAL_INSTANTIATE_EXECUTE(SIMPLE_BOOL(condition))
// Convert any condition to exactly 0 or 1 - this handles complex expressions
#define SIMPLE_BOOL(x) \
SIMPLE_BOOL_HELPER(x, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
#define SIMPLE_BOOL_HELPER(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,...) a16
// Use the boolean result to select execution method - NO concatenation with complex expressions
#define CONDITIONAL_INSTANTIATE_EXECUTE(clean_bool) \
CONDITIONAL_INSTANTIATE_CAT(CONDITIONAL_INSTANTIATE_RUN_, clean_bool)
#define CONDITIONAL_INSTANTIATE_RUN_1
#define CONDITIONAL_INSTANTIATE_RUN_0 //
// Handlers for different argument counts
#define CONDITIONAL_INSTANTIATE_1(condition, arg1) \
CONDITIONAL_INSTANTIATE_IF(condition) arg1
#define CONDITIONAL_INSTANTIATE_2(condition, arg1, arg2) \
CONDITIONAL_INSTANTIATE_IF(condition) arg1 arg2
#define CONDITIONAL_INSTANTIATE_3(condition, arg1, arg2, arg3) \
CONDITIONAL_INSTANTIATE_IF(condition) arg1 arg2 arg3
#define CONDITIONAL_INSTANTIATE_4(condition, arg1, arg2, arg3, arg4) \
CONDITIONAL_INSTANTIATE_IF(condition) arg1 arg2 arg3 arg4
#define CONDITIONAL_INSTANTIATE_5(condition, arg1, arg2, arg3, arg4, arg5) \
CONDITIONAL_INSTANTIATE_IF(condition) arg1 arg2 arg3 arg4 arg5
#define CONDITIONAL_INSTANTIATE_6(condition, arg1, arg2, arg3, arg4, arg5, arg6) \
CONDITIONAL_INSTANTIATE_IF(condition) arg1 arg2 arg3 arg4 arg5 arg6
#define CONDITIONAL_INSTANTIATE_7(condition, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \
CONDITIONAL_INSTANTIATE_IF(condition) arg1 arg2 arg3 arg4 arg5 arg6 arg7
#define CONDITIONAL_INSTANTIATE_8(condition, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \
CONDITIONAL_INSTANTIATE_IF(condition) arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8
// ============================================================================
// COMMA MACRO FOR NESTED TEMPLATE ARGUMENTS
// ============================================================================
// ============================================================================
// TYPE CHECKING SYSTEM
// ============================================================================
#define EXPAND_AND_CHECK_TRIPLE(a1, b1, c1) SD_IS_TRIPLE_TYPE_COMPILED(GET_FIRST(a1),GET_FIRST(b1),GET_FIRST(c1))
#define EXPAND_AND_CHECK_PAIR(a1, b1) SD_IS_PAIR_TYPE_COMPILED(GET_FIRST(a1), GET_FIRST(b1))
#endif // SD_TYPE_INST_H