@@ -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+
19491964static 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 */
20722093DEFINE_VEC_CONVERT (bool , i8 , bool , int8_t )
@@ -2138,7 +2159,8 @@ DEFINE_VEC_CONVERT(f32, c128, float, double_complex)
21382159
21392160DEFINE_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 */
21442166typedef 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 */
25962649DEFINE_ME_EVAL (f32 , float ,
0 commit comments