/*
 *     Copyright (c) 2022, NVIDIA CORPORATION.  All rights reserved.
 *
 * NVIDIA CORPORATION and its licensors retain all intellectual property
 * and proprietary rights in and to this software, related documentation
 * and any modifications thereto.  Any use, reproduction, disclosure or
 * distribution of this software and related documentation without an express
 * license agreement from NVIDIA CORPORATION is strictly prohibited.
 *
 */

#ifndef __NVHPC_COMMON_H
#define __NVHPC_COMMON_H

#ifdef __cplusplus
#define __C "C"
#else
#define __C
#endif
#define __EXTERN extern __C

/*
 * We need to first undef `__forceinline__` because it is possible
 * that it is defined already in some CUDA headers.
 */
#undef __forceinline__
#define __forceinline__ __attribute__((always_inline))

/*
 * Macros for setting the attributes to all functions in the bitcode
 * files.
 */

/* Clang Attributes
 * We need to differentiate the function attributes between the nonvvm
 * and the nvvm case.
 */
#if !defined(PGI_COMPILE_BITCODE) // nonvvm
#define __ATTRIBUTES __device__ static inline
#define __ATTRIBUTES_NORETURN __device__ __attribute__((noinline)) __attribute__((noreturn)) static
#elif defined(__clang__)
#define __ATTRIBUTES __forceinline__
#define __ATTRIBUTES_NORETURN __attribute__((noinline)) __attribute__((noreturn)) static
#else
#define __ATTRIBUTES __device__
#define __ATTRIBUTES_NORETURN __device__ __attribute__((noinline)) __attribute__((noreturn))
#endif

/* NVCC attributes */
#define __DEVICE __EXTERN __device__
#define __CONST_PURE __attribute__((const)) /* function does not access or change any mutable state visible to caller */

// Clang defines `__nv_pure__` as ` __location__(nv_pure)`, causing compilation errors
#if defined(__clang__) || !defined(__nv_pure__)
#define __PURE __attribute__((pure))
#else
#define __PURE __nv_pure__                  /* function does not change any mutable state visible to caller */
#endif

#define SIZE_OF_FLOAT 4
#define SIZE_OF_DOUBLE 8

#define WARP_SIZE 32

#include "nvhpc_cuda_complex.h"

#endif /* __NVHPC_COMMON_H */
