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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/**
* @file ops_binary.h
* @brief Binary tensor operations header
*
* Declares all element-wise binary operations for tensors including:
* - Arithmetic operations (add, sub, mul, div, pow, maximum, minimum)
* - Logical operations (logical_and, logical_or, logical_xor)
* - Comparison operations (eq, ne, lt, le, gt, ge)
*
* All operations support multiple data types and handle both contiguous
* and strided tensor layouts efficiently.
*/
#ifndef HODU_CPU_KERNELS_OPS_BINARY_H
#define HODU_CPU_KERNELS_OPS_BINARY_H
#include "utils.h"
#ifdef __cplusplus
extern "C" {
#endif
// ============================================================================
// BINARY OPERATION FUNCTION SIGNATURES
// ============================================================================
//
// All binary operations follow a consistent signature:
// void op_type(const void *lhs, const void *rhs, void *output, const size_t *metadata)
//
// Parameters:
// lhs - Pointer to left-hand side tensor data
// rhs - Pointer to right-hand side tensor data
// output - Pointer to output buffer (pre-allocated)
// metadata - Array describing tensor layout (see below)
//
// Metadata layout:
// - metadata[0]: num_els (total number of elements)
// - metadata[1]: num_dims (number of dimensions)
// - metadata[2..2+num_dims]: lhs_shape
// - metadata[2+num_dims..2+2*num_dims]: rhs_shape
// - metadata[2+2*num_dims..2+3*num_dims]: lhs_strides
// - metadata[2+3*num_dims..2+4*num_dims]: rhs_strides
// - metadata[2+4*num_dims]: lhs_offset
// - metadata[2+4*num_dims+1]: rhs_offset
//
// Note: Broadcasting must be handled by the caller; these functions assume
// compatible shapes and perform element-wise operations only.
/// Macro to declare arithmetic binary operations for a given type
/// Declares: add, sub, mul, div, pow, maximum, minimum
#define DECLARE_BINARY_OP(TYPE_SUFFIX) \
void add_##TYPE_SUFFIX(const void *lhs, const void *rhs, void *output, \
const size_t *metadata); \
void sub_##TYPE_SUFFIX(const void *lhs, const void *rhs, void *output, \
const size_t *metadata); \
void mul_##TYPE_SUFFIX(const void *lhs, const void *rhs, void *output, \
const size_t *metadata); \
void div_##TYPE_SUFFIX(const void *lhs, const void *rhs, void *output, \
const size_t *metadata); \
void pow_##TYPE_SUFFIX(const void *lhs, const void *rhs, void *output, \
const size_t *metadata); \
void maximum_##TYPE_SUFFIX(const void *lhs, const void *rhs, void *output, \
const size_t *metadata); \
void minimum_##TYPE_SUFFIX(const void *lhs, const void *rhs, void *output, \
const size_t *metadata);
/// Macro to declare logical binary operations for a given type
/// Declares: logical_and, logical_or, logical_xor
/// All return boolean results (uint8_t: 0 for false, 1 for true)
#define DECLARE_BINARY_LOGICAL(TYPE_SUFFIX) \
void logical_and_##TYPE_SUFFIX(const void *lhs, const void *rhs, void *output, \
const size_t *metadata); \
void logical_or_##TYPE_SUFFIX(const void *lhs, const void *rhs, void *output, \
const size_t *metadata); \
void logical_xor_##TYPE_SUFFIX(const void *lhs, const void *rhs, void *output, \
const size_t *metadata);
/// Macro to declare comparison binary operations for a given type
/// Declares: eq, ne, lt, le, gt, ge
/// All return boolean results (uint8_t: 0 for false, 1 for true)
#define DECLARE_BINARY_CMP(TYPE_SUFFIX) \
void eq_##TYPE_SUFFIX(const void *lhs, const void *rhs, void *output, const size_t *metadata); \
void ne_##TYPE_SUFFIX(const void *lhs, const void *rhs, void *output, const size_t *metadata); \
void lt_##TYPE_SUFFIX(const void *lhs, const void *rhs, void *output, const size_t *metadata); \
void le_##TYPE_SUFFIX(const void *lhs, const void *rhs, void *output, const size_t *metadata); \
void gt_##TYPE_SUFFIX(const void *lhs, const void *rhs, void *output, const size_t *metadata); \
void ge_##TYPE_SUFFIX(const void *lhs, const void *rhs, void *output, const size_t *metadata);
// Bool type
DECLARE_BINARY_OP(bool)
DECLARE_BINARY_LOGICAL(bool)
DECLARE_BINARY_CMP(bool)
// Float types (f8e4m3, f8e5m2, bf16, f16, f32, f64)
DECLARE_BINARY_OP(f8e4m3)
DECLARE_BINARY_LOGICAL(f8e4m3)
DECLARE_BINARY_CMP(f8e4m3)
DECLARE_BINARY_OP(f8e5m2)
DECLARE_BINARY_LOGICAL(f8e5m2)
DECLARE_BINARY_CMP(f8e5m2)
DECLARE_BINARY_OP(bf16)
DECLARE_BINARY_LOGICAL(bf16)
DECLARE_BINARY_CMP(bf16)
DECLARE_BINARY_OP(f16)
DECLARE_BINARY_LOGICAL(f16)
DECLARE_BINARY_CMP(f16)
DECLARE_BINARY_OP(f32)
DECLARE_BINARY_LOGICAL(f32)
DECLARE_BINARY_CMP(f32)
DECLARE_BINARY_OP(f64)
DECLARE_BINARY_LOGICAL(f64)
DECLARE_BINARY_CMP(f64)
// Integer types (u8, u16, u32, u64, i8, i16, i32, i64)
DECLARE_BINARY_OP(u8)
DECLARE_BINARY_LOGICAL(u8)
DECLARE_BINARY_CMP(u8)
DECLARE_BINARY_OP(u16)
DECLARE_BINARY_LOGICAL(u16)
DECLARE_BINARY_CMP(u16)
DECLARE_BINARY_OP(u32)
DECLARE_BINARY_LOGICAL(u32)
DECLARE_BINARY_CMP(u32)
DECLARE_BINARY_OP(u64)
DECLARE_BINARY_LOGICAL(u64)
DECLARE_BINARY_CMP(u64)
DECLARE_BINARY_OP(i8)
DECLARE_BINARY_LOGICAL(i8)
DECLARE_BINARY_CMP(i8)
DECLARE_BINARY_OP(i16)
DECLARE_BINARY_LOGICAL(i16)
DECLARE_BINARY_CMP(i16)
DECLARE_BINARY_OP(i32)
DECLARE_BINARY_LOGICAL(i32)
DECLARE_BINARY_CMP(i32)
DECLARE_BINARY_OP(i64)
DECLARE_BINARY_LOGICAL(i64)
DECLARE_BINARY_CMP(i64)
#ifdef __cplusplus
}
#endif
#endif // HODU_CPU_KERNELS_OPS_BINARY_H