Skip to content

Commit 11b10b9

Browse files
committed
Better MSVC support (III)
1 parent 4f8af54 commit 11b10b9

1 file changed

Lines changed: 85 additions & 32 deletions

File tree

src/miniexpr.c

Lines changed: 85 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -154,13 +154,18 @@ static inline _Dcomplex div_c128(_Dcomplex a, _Dcomplex b) {
154154
#define FROM_TYPE_c128(x) (double)creal(x)
155155
#define IS_NONZERO_c64(x) (crealf(x) != 0.0f || cimagf(x) != 0.0f)
156156
#define IS_NONZERO_c128(x) (creal(x) != 0.0 || cimag(x) != 0.0)
157+
158+
/* Helper macros for complex-to-complex conversions */
159+
#define CONV_c64_to_c128(x) _Cbuild((double)crealf(x), (double)cimagf(x))
160+
#define TO_TYPE_c128_from_c64(x) CONV_c64_to_c128(x)
157161
#else
158-
#define TO_TYPE_c64(x) (float complex)(x)
159-
#define TO_TYPE_c128(x) (double complex)(x)
162+
#define TO_TYPE_c64(x) (float_complex)(x)
163+
#define TO_TYPE_c128(x) (double_complex)(x)
160164
#define FROM_TYPE_c64(x) (double)(x)
161165
#define FROM_TYPE_c128(x) (double)(x)
162166
#define IS_NONZERO_c64(x) ((x) != 0)
163167
#define IS_NONZERO_c128(x) ((x) != 0)
168+
#define TO_TYPE_c128_from_c64(x) (double_complex)(x)
164169
#endif
165170

166171
#include <assert.h>
@@ -1946,6 +1951,16 @@ static void vec_mul_scalar_c64(const float_complex *a, float_complex b, float_co
19461951
for (i = 0; i < n; i++) out[i] = mul_c64(a[i], b);
19471952
}
19481953

1954+
#if defined(_MSC_VER) && !defined(__clang__)
1955+
// MSVC complex functions in C take struct by value and return struct by value,
1956+
// but they might need specific headers or have different calling conventions.
1957+
// The errors suggest 'too few arguments' which is weird for cpow(a, b).
1958+
// Maybe it's because it's expecting _Dcomplex but getting something else?
1959+
// Actually, MSVC's cpow is defined in complex.h as:
1960+
// _Dcomplex cpow(_Dcomplex _Left, _Dcomplex _Right);
1961+
// The error "too few arguments for call" often happens if it's misidentified.
1962+
#endif
1963+
19491964
static void vec_pow_c64(const float_complex *a, const float_complex *b, float_complex *out, int n) {
19501965
int i;
19511966
IVDEP
@@ -2067,6 +2082,12 @@ static void vec_convert_##FROM_SUFFIX##_to_##TO_SUFFIX(const FROM_TYPE *in, TO_T
20672082
for (i = 0; i < n; i++) out[i] = TO_TYPE_##TO_SUFFIX(in[i]); \
20682083
}
20692084

2085+
static void vec_convert_c64_to_c128(const float_complex *in, double_complex *out, int n) {
2086+
int i;
2087+
IVDEP
2088+
for (i = 0; i < n; i++) out[i] = TO_TYPE_c128_from_c64(in[i]);
2089+
}
2090+
20702091
/* Generate all conversion functions */
20712092
/* Conversions FROM bool TO other types */
20722093
DEFINE_VEC_CONVERT(bool, i8, bool, int8_t)
@@ -2138,7 +2159,8 @@ DEFINE_VEC_CONVERT(f32, c128, float, double_complex)
21382159

21392160
DEFINE_VEC_CONVERT(f64, c128, double, double_complex)
21402161

2141-
DEFINE_VEC_CONVERT(c64, c128, float_complex, double_complex)
2162+
/* Special case for complex to complex conversion to avoid cast to double on MSVC */
2163+
// DEFINE_VEC_CONVERT(c64, c128, float_complex, double_complex) is handled above manually
21422164

21432165
/* Function to get conversion function pointer */
21442166
typedef void (*convert_func_t)(const void *, void *, int);
@@ -2246,7 +2268,7 @@ static void me_eval_##SUFFIX(const me_expr *n) { \
22462268
switch(TYPE_MASK(n->type)) { \
22472269
case ME_CONSTANT: \
22482270
{ \
2249-
TYPE val = (TYPE)n->value; \
2271+
TYPE val = TO_TYPE_##SUFFIX(n->value); \
22502272
for (i = 0; i < n->nitems; i++) { \
22512273
output[i] = val; \
22522274
} \
@@ -2293,9 +2315,9 @@ static void me_eval_##SUFFIX(const me_expr *n) { \
22932315
if (ldata && rdata) { \
22942316
VEC_ADD(ldata, rdata, output, n->nitems); \
22952317
} else if (ldata && right->type == ME_CONSTANT) { \
2296-
VEC_ADD_SCALAR(ldata, (TYPE)right->value, output, n->nitems); \
2318+
VEC_ADD_SCALAR(ldata, TO_TYPE_##SUFFIX(right->value), output, n->nitems); \
22972319
} else if (left->type == ME_CONSTANT && rdata) { \
2298-
VEC_ADD_SCALAR(rdata, (TYPE)left->value, output, n->nitems); \
2320+
VEC_ADD_SCALAR(rdata, TO_TYPE_##SUFFIX(left->value), output, n->nitems); \
22992321
} else { \
23002322
goto general_case_binary_##SUFFIX; \
23012323
} \
@@ -2309,9 +2331,9 @@ static void me_eval_##SUFFIX(const me_expr *n) { \
23092331
if (ldata && rdata) { \
23102332
VEC_MUL(ldata, rdata, output, n->nitems); \
23112333
} else if (ldata && right->type == ME_CONSTANT) { \
2312-
VEC_MUL_SCALAR(ldata, (TYPE)right->value, output, n->nitems); \
2334+
VEC_MUL_SCALAR(ldata, TO_TYPE_##SUFFIX(right->value), output, n->nitems); \
23132335
} else if (left->type == ME_CONSTANT && rdata) { \
2314-
VEC_MUL_SCALAR(rdata, (TYPE)left->value, output, n->nitems); \
2336+
VEC_MUL_SCALAR(rdata, TO_TYPE_##SUFFIX(left->value), output, n->nitems); \
23152337
} else { \
23162338
goto general_case_binary_##SUFFIX; \
23172339
} \
@@ -2325,18 +2347,18 @@ static void me_eval_##SUFFIX(const me_expr *n) { \
23252347
if (ldata && rdata) { \
23262348
VEC_POW(ldata, rdata, output, n->nitems); \
23272349
} else if (ldata && right->type == ME_CONSTANT) { \
2328-
VEC_POW_SCALAR(ldata, (TYPE)right->value, output, n->nitems); \
2350+
VEC_POW_SCALAR(ldata, TO_TYPE_##SUFFIX(right->value), output, n->nitems); \
23292351
} else { \
23302352
goto general_case_binary_##SUFFIX; \
23312353
} \
23322354
} else { \
23332355
general_case_binary_##SUFFIX: \
23342356
for (i = 0; i < n->nitems; i++) { \
23352357
double a = (left->type == ME_CONSTANT) ? left->value : \
2336-
(left->type == ME_VARIABLE) ? (double)ldata[i] : (double)ldata[i]; \
2358+
FROM_TYPE_##SUFFIX(ldata[i]); \
23372359
double b = (right->type == ME_CONSTANT) ? right->value : \
2338-
(right->type == ME_VARIABLE) ? (double)rdata[i] : (double)rdata[i]; \
2339-
output[i] = (TYPE)func(a, b); \
2360+
FROM_TYPE_##SUFFIX(rdata[i]); \
2361+
output[i] = TO_TYPE_##SUFFIX(func(a, b)); \
23402362
} \
23412363
} \
23422364
} else if (arity == 3 && IS_FUNCTION(n->type) && n->function == (void*)where_scalar) { \
@@ -2350,7 +2372,7 @@ static void me_eval_##SUFFIX(const me_expr *n) { \
23502372
const TYPE *ydata = (const TYPE*)((yexpr->type == ME_VARIABLE) ? yexpr->bound : yexpr->output); \
23512373
\
23522374
for (i = 0; i < n->nitems; i++) { \
2353-
output[i] = (cdata[i] != (TYPE)0) ? xdata[i] : ydata[i]; \
2375+
output[i] = (IS_NONZERO_##SUFFIX(cdata[i])) ? xdata[i] : ydata[i]; \
23542376
} \
23552377
} \
23562378
else if (arity == 1 && IS_FUNCTION(n->type)) { \
@@ -2373,7 +2395,7 @@ static void me_eval_##SUFFIX(const me_expr *n) { \
23732395
/* NumPy semantics: imag(real) == 0 with same dtype */ \
23742396
if (adata) { \
23752397
for (i = 0; i < n->nitems; i++) { \
2376-
output[i] = (TYPE)0; \
2398+
output[i] = TO_TYPE_##SUFFIX(0); \
23772399
} \
23782400
} \
23792401
} else if (func_ptr == (void*)real_wrapper) { \
@@ -2388,13 +2410,13 @@ static void me_eval_##SUFFIX(const me_expr *n) { \
23882410
} else { \
23892411
me_fun1 func = (me_fun1)func_ptr; \
23902412
if (arg->type == ME_CONSTANT) { \
2391-
TYPE val = (TYPE)func(arg->value); \
2413+
TYPE val = TO_TYPE_##SUFFIX(func(arg->value)); \
23922414
for (i = 0; i < n->nitems; i++) { \
23932415
output[i] = val; \
23942416
} \
23952417
} else { \
23962418
for (i = 0; i < n->nitems; i++) { \
2397-
output[i] = (TYPE)func((double)adata[i]); \
2419+
output[i] = TO_TYPE_##SUFFIX(func(FROM_TYPE_##SUFFIX(adata[i]))); \
23982420
} \
23992421
} \
24002422
} \
@@ -2409,30 +2431,30 @@ static void me_eval_##SUFFIX(const me_expr *n) { \
24092431
if (param->type == ME_CONSTANT) { \
24102432
args[j] = param->value; \
24112433
} else { \
2412-
args[j] = (double)pdata[i]; \
2434+
args[j] = FROM_TYPE_##SUFFIX(pdata[i]); \
24132435
} \
24142436
} \
24152437
\
24162438
if (IS_FUNCTION(n->type)) { \
24172439
switch(arity) { \
2418-
case 0: output[i] = (TYPE)((double(*)(void))n->function)(); break; \
2419-
case 3: output[i] = (TYPE)((double(*)(double,double,double))n->function)(args[0], args[1], args[2]); break; \
2420-
case 4: output[i] = (TYPE)((double(*)(double,double,double,double))n->function)(args[0], args[1], args[2], args[3]); break; \
2421-
case 5: output[i] = (TYPE)((double(*)(double,double,double,double,double))n->function)(args[0], args[1], args[2], args[3], args[4]); break; \
2422-
case 6: output[i] = (TYPE)((double(*)(double,double,double,double,double,double))n->function)(args[0], args[1], args[2], args[3], args[4], args[5]); break; \
2423-
case 7: output[i] = (TYPE)((double(*)(double,double,double,double,double,double,double))n->function)(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); break; \
2440+
case 0: output[i] = TO_TYPE_##SUFFIX(((double(*)(void))n->function)()); break; \
2441+
case 3: output[i] = TO_TYPE_##SUFFIX(((double(*)(double,double,double))n->function)(args[0], args[1], args[2])); break; \
2442+
case 4: output[i] = TO_TYPE_##SUFFIX(((double(*)(double,double,double,double))n->function)(args[0], args[1], args[2], args[3])); break; \
2443+
case 5: output[i] = TO_TYPE_##SUFFIX(((double(*)(double,double,double,double,double))n->function)(args[0], args[1], args[2], args[3], args[4])); break; \
2444+
case 6: output[i] = TO_TYPE_##SUFFIX(((double(*)(double,double,double,double,double,double))n->function)(args[0], args[1], args[2], args[3], args[4], args[5])); break; \
2445+
case 7: output[i] = TO_TYPE_##SUFFIX(((double(*)(double,double,double,double,double,double,double))n->function)(args[0], args[1], args[2], args[3], args[4], args[5], args[6])); break; \
24242446
} \
24252447
} else if (IS_CLOSURE(n->type)) { \
24262448
void *context = n->parameters[arity]; \
24272449
switch(arity) { \
2428-
case 0: output[i] = (TYPE)((double(*)(void*))n->function)(context); break; \
2429-
case 1: output[i] = (TYPE)((double(*)(void*,double))n->function)(context, args[0]); break; \
2430-
case 2: output[i] = (TYPE)((double(*)(void*,double,double))n->function)(context, args[0], args[1]); break; \
2431-
case 3: output[i] = (TYPE)((double(*)(void*,double,double,double))n->function)(context, args[0], args[1], args[2]); break; \
2432-
case 4: output[i] = (TYPE)((double(*)(void*,double,double,double,double))n->function)(context, args[0], args[1], args[2], args[3]); break; \
2433-
case 5: output[i] = (TYPE)((double(*)(void*,double,double,double,double,double))n->function)(context, args[0], args[1], args[2], args[3], args[4]); break; \
2434-
case 6: output[i] = (TYPE)((double(*)(void*,double,double,double,double,double,double))n->function)(context, args[0], args[1], args[2], args[3], args[4], args[5]); break; \
2435-
case 7: output[i] = (TYPE)((double(*)(void*,double,double,double,double,double,double,double))n->function)(context, args[0], args[1], args[2], args[3], args[4], args[5], args[6]); break; \
2450+
case 0: output[i] = TO_TYPE_##SUFFIX(((double(*)(void*))n->function)(context)); break; \
2451+
case 1: output[i] = TO_TYPE_##SUFFIX(((double(*)(void*,double))n->function)(context, args[0])); break; \
2452+
case 2: output[i] = TO_TYPE_##SUFFIX(((double(*)(void*,double,double))n->function)(context, args[0], args[1])); break; \
2453+
case 3: output[i] = TO_TYPE_##SUFFIX(((double(*)(void*,double,double,double))n->function)(context, args[0], args[1], args[2])); break; \
2454+
case 4: output[i] = TO_TYPE_##SUFFIX(((double(*)(void*,double,double,double,double))n->function)(context, args[0], args[1], args[2], args[3])); break; \
2455+
case 5: output[i] = TO_TYPE_##SUFFIX(((double(*)(void*,double,double,double,double,double))n->function)(context, args[0], args[1], args[2], args[3], args[4])); break; \
2456+
case 6: output[i] = TO_TYPE_##SUFFIX(((double(*)(void*,double,double,double,double,double,double))n->function)(context, args[0], args[1], args[2], args[3], args[4], args[5])); break; \
2457+
case 7: output[i] = TO_TYPE_##SUFFIX(((double(*)(void*,double,double,double,double,double,double,double))n->function)(context, args[0], args[1], args[2], args[3], args[4], args[5], args[6])); break; \
24362458
} \
24372459
} \
24382460
} \
@@ -2441,7 +2463,7 @@ static void me_eval_##SUFFIX(const me_expr *n) { \
24412463
\
24422464
default: \
24432465
for (i = 0; i < n->nitems; i++) { \
2444-
output[i] = (TYPE)NAN; \
2466+
output[i] = TO_TYPE_##SUFFIX(NAN); \
24452467
} \
24462468
break; \
24472469
} \
@@ -2563,6 +2585,36 @@ static void me_eval_##SUFFIX(const me_expr *n) { \
25632585
#define vec_sqrt_u64(a, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = (uint64_t)sqrt((a)[_i]); } while(0)
25642586
#define vec_negame_u64(a, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = -(a)[_i]; } while(0)
25652587

2588+
#if defined(_MSC_VER) && !defined(__clang__)
2589+
#define vec_add_c64(a, b, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = add_c64((a)[_i], (b)[_i]); } while(0)
2590+
#define vec_sub_c64(a, b, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = sub_c64((a)[_i], (b)[_i]); } while(0)
2591+
#define vec_mul_c64(a, b, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = mul_c64((a)[_i], (b)[_i]); } while(0)
2592+
#define vec_div_c64(a, b, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = div_c64((a)[_i], (b)[_i]); } while(0)
2593+
#define vec_pow_c64(a, b, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = cpowf((a)[_i], (b)[_i]); } while(0)
2594+
#define vec_add_scalar_c64(a, b, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = add_c64((a)[_i], (b)); } while(0)
2595+
#define vec_mul_scalar_c64(a, b, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = mul_c64((a)[_i], (b)); } while(0)
2596+
#define vec_pow_scalar_c64(a, b, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = cpowf((a)[_i], (b)); } while(0)
2597+
#define vec_sqrt_c64(a, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = csqrtf((a)[_i]); } while(0)
2598+
#define vec_negame_c64(a, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = neg_c64((a)[_i]); } while(0)
2599+
#define vec_conj_c64(a, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = conjf((a)[_i]); } while(0)
2600+
#define vec_imag_c64(a, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = cimagf((a)[_i]); } while(0)
2601+
#define vec_real_c64(a, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = crealf((a)[_i]); } while(0)
2602+
#define vec_conj_noop(a, out, n) do { (void)(a); (void)(out); (void)(n); } while(0)
2603+
2604+
#define vec_add_c128(a, b, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = add_c128((a)[_i], (b)[_i]); } while(0)
2605+
#define vec_sub_c128(a, b, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = sub_c128((a)[_i], (b)[_i]); } while(0)
2606+
#define vec_mul_c128(a, b, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = mul_c128((a)[_i], (b)[_i]); } while(0)
2607+
#define vec_div_c128(a, b, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = div_c128((a)[_i], (b)[_i]); } while(0)
2608+
#define vec_pow_c128(a, b, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = cpow((a)[_i], (b)[_i]); } while(0)
2609+
#define vec_add_scalar_c128(a, b, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = add_c128((a)[_i], (b)); } while(0)
2610+
#define vec_mul_scalar_c128(a, b, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = mul_c128((a)[_i], (b)); } while(0)
2611+
#define vec_pow_scalar_c128(a, b, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = cpow((a)[_i], (b)); } while(0)
2612+
#define vec_sqrt_c128(a, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = csqrt((a)[_i]); } while(0)
2613+
#define vec_negame_c128(a, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = neg_c128((a)[_i]); } while(0)
2614+
#define vec_conj_c128(a, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = conj((a)[_i]); } while(0)
2615+
#define vec_imag_c128(a, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = cimag((a)[_i]); } while(0)
2616+
#define vec_real_c128(a, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = creal((a)[_i]); } while(0)
2617+
#else
25662618
#define vec_add_c64(a, b, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = (a)[_i] + (b)[_i]; } while(0)
25672619
#define vec_sub_c64(a, b, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = (a)[_i] - (b)[_i]; } while(0)
25682620
#define vec_mul_c64(a, b, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = (a)[_i] * (b)[_i]; } while(0)
@@ -2591,6 +2643,7 @@ static void me_eval_##SUFFIX(const me_expr *n) { \
25912643
#define vec_conj_c128(a, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = conj((a)[_i]); } while(0)
25922644
#define vec_imag_c128(a, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = cimag((a)[_i]); } while(0)
25932645
#define vec_real_c128(a, out, n) do { for (int _i = 0; _i < (n); _i++) (out)[_i] = creal((a)[_i]); } while(0)
2646+
#endif
25942647

25952648
/* Generate float32 evaluator */
25962649
DEFINE_ME_EVAL(f32, float,

0 commit comments

Comments
 (0)