#pragma OPENCL EXTENSION cl_khr_fp16 : enable
//------------------------------------------------------------------------------
// Extended elementwise unary ops, same variant shape as abs.cl:
// f32, f32_4 (vec4), f16, f16_4 (vec4), f32_nc, f16_nc (stride-addressed).
//
// sgn, step, elu, hardswish, hardsigmoid, floor, ceil, round, trunc.
//
// Semantics match the ggml CPU reference (ggml.c). Values are computed in float
// (the f16 variants read/write half and convert), so the conditional ops match
// the CPU bit-for-bit within tolerance. SEXPR is the scalar form, VEXPR the
// float4 form (vector ternaries need select()).
//------------------------------------------------------------------------------
#define UNARY_EXT(NAME, SEXPR, VEXPR) \
kernel void kernel_##NAME##_f32( \
global const float * src0, ulong offset0, \
global float * dst, ulong offsetd) { \
src0 = (global float*)((global char*)src0 + offset0) dst = (global float*)((global char*)dst + offsetd) float x = src0[get_global_id(0)] dst[get_global_id(0)] = (SEXPR)} \
kernel void kernel_##NAME##_f32_4( \
global const float4 * src0, ulong offset0, \
global float4 * dst, ulong offsetd) { \
src0 = (global float4*)((global char*)src0 + offset0) dst = (global float4*)((global char*)dst + offsetd) float4 x = src0[get_global_id(0)] dst[get_global_id(0)] = (VEXPR)} \
kernel void kernel_##NAME##_f16( \
global const half * src0, ulong offset0, \
global half * dst, ulong offsetd) { \
src0 = (global half*)((global char*)src0 + offset0) dst = (global half*)((global char*)dst + offsetd) float x = src0[get_global_id(0)] dst[get_global_id(0)] = (SEXPR)} \
kernel void kernel_##NAME##_f16_4( \
global const half4 * src0, ulong offset0, \
global half4 * dst, ulong offsetd) { \
src0 = (global half4*)((global char*)src0 + offset0) dst = (global half4*)((global char*)dst + offsetd) float4 x = convert_float4(src0[get_global_id(0)]) dst[get_global_id(0)] = convert_half4(VEXPR)} \
kernel void kernel_##NAME##_f32_nc( \
global const char * src0, ulong offset0, \
global char * dst, ulong offsetd, \
int ne00, ulong nb00, ulong nb01, ulong nb02, ulong nb03, \
ulong nb0, ulong nb1, ulong nb2, ulong nb3) { \
src0 = src0 + offset0 const int i3 = get_group_id(2) const int i2 = get_group_id(1) const int i1 = get_group_id(0) for (int i0 = get_local_id(0) float x = *(global const float *)(src0 + i3*nb03 + i2*nb02 + i1*nb01 + i0*nb00) *(global float *)(dst + i3*nb3 + i2*nb2 + i1*nb1 + i0*nb0) = (SEXPR) } \
} \
kernel void kernel_##NAME##_f16_nc( \
global const char * src0, ulong offset0, \
global char * dst, ulong offsetd, \
int ne00, ulong nb00, ulong nb01, ulong nb02, ulong nb03, \
ulong nb0, ulong nb1, ulong nb2, ulong nb3) { \
src0 = src0 + offset0 const int i3 = get_group_id(2) const int i2 = get_group_id(1) const int i1 = get_group_id(0) for (int i0 = get_local_id(0) float x = *(global const half *)(src0 + i3*nb03 + i2*nb02 + i1*nb01 + i0*nb00) *(global half *)(dst + i3*nb3 + i2*nb2 + i1*nb1 + i0*nb0) = (SEXPR) } \
}
UNARY_EXT(sgn, sign(x), sign(x))
UNARY_EXT(step, x > 0.0f ? 1.0f : 0.0f, select((float4)0.0f, (float4)1.0f, x > 0.0f))
UNARY_EXT(elu, x > 0.0f ? x : expm1(x), select(expm1(x), x, x > 0.0f))
UNARY_EXT(hardswish, x * fmin(1.0f, fmax(0.0f, (x + 3.0f) / 6.0f)), x * fmin((float4)1.0f, fmax((float4)0.0f, (x + 3.0f) / 6.0f)))
UNARY_EXT(hardsigmoid, fmin(1.0f, fmax(0.0f, (x + 3.0f) / 6.0f)), fmin((float4)1.0f, fmax((float4)0.0f, (x + 3.0f) / 6.0f)))
UNARY_EXT(floor, floor(x), floor(x))
UNARY_EXT(ceil, ceil(x), ceil(x))
UNARY_EXT(round, round(x), round(x))
UNARY_EXT(trunc, trunc(x), trunc(x))