PageRenderTime 53ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/libsrc/veclib/vec_call.c

https://gitlab.com/oytunistrator/QuIP
C | 1027 lines | 663 code | 111 blank | 253 comment | 270 complexity | d9c6d9d2f82e82defbbcf65a90304f6e MD5 | raw file
  1. #include "quip_config.h"
  2. #include <string.h>
  3. #include "quip_prot.h"
  4. #include "nvf.h"
  5. /* BUG - this is only correct when the order of words in this table corresponds
  6. * to the ordering of the corresponding constants. Better to have a software initialization
  7. * of the table.
  8. */
  9. const char *argset_type_name[N_ARGSET_TYPES]={
  10. "unknown",
  11. "real",
  12. "complex",
  13. "mixed (complex/real)",
  14. "quaternion",
  15. "mixed (quaternion/real)"
  16. };
  17. static void shape_error(QSP_ARG_DECL Vector_Function *vfp, Data_Obj *dp)
  18. {
  19. sprintf(ERROR_STRING,"shape_error: Vector function %s: argument %s has unknown shape!?",
  20. VF_NAME(vfp),OBJ_NAME(dp));
  21. WARN(ERROR_STRING);
  22. }
  23. static int chk_uk(QSP_ARG_DECL Vector_Function *vfp, Vec_Obj_Args *oap)
  24. {
  25. int i;
  26. if( OA_DEST(oap) != NO_OBJ && UNKNOWN_OBJ_SHAPE(OA_DEST(oap)) ){
  27. shape_error(QSP_ARG vfp,OA_DEST(oap) );
  28. return(-1);
  29. }
  30. for(i=0;i<MAX_N_ARGS;i++){
  31. if( OA_SRC_OBJ(oap,i) != NO_OBJ && UNKNOWN_OBJ_SHAPE( OA_SRC_OBJ(oap,i) ) ){
  32. shape_error(QSP_ARG vfp,OA_SRC_OBJ(oap,i));
  33. return(-1);
  34. }
  35. }
  36. if( OA_SBM(oap) != NO_OBJ && UNKNOWN_OBJ_SHAPE(OA_SBM(oap)) ){
  37. shape_error(QSP_ARG vfp,OA_SBM(oap) );
  38. return(-1);
  39. }
  40. /* BUG check the scalar objects too? */
  41. return(0);
  42. }
  43. static const char *name_for_type(Data_Obj *dp)
  44. {
  45. if( IS_REAL(dp) ) return("real");
  46. else if( IS_COMPLEX(dp) ) return("complex");
  47. else if( IS_QUAT(dp) ) return("quaternion");
  48. //#ifdef CAUTIOUS
  49. else {
  50. // sprintf(DEFAULT_ERROR_STRING,"CAUTIOUS: name_for_type: type of object %s is unknown",OBJ_NAME(dp) );
  51. // NWARN(DEFAULT_ERROR_STRING);
  52. // return("unknown");
  53. assert( AERROR("name_for_type: unexpected type code!?") );
  54. }
  55. //#endif /* CAUTIOUS */
  56. }
  57. /* The "type" is real, complex, quaternion, or mixed...
  58. * independent of "precision" (byte/short/float etc)
  59. */
  60. static int chktyp(QSP_ARG_DECL Vector_Function *vfp,Vec_Obj_Args *oap)
  61. {
  62. SET_OA_ARGSTYPE(oap, UNKNOWN_ARGS);
  63. /* Set the type based on the destination vector */
  64. /* destv is highest numbered arg */
  65. if( IS_REAL(OA_DEST(oap) ) ){
  66. if( OA_SRC2(oap) != NO_OBJ ){ /* two source operands */
  67. if( IS_REAL( OA_SRC1(oap) ) ){
  68. if( IS_REAL(OA_SRC2(oap) ) ){
  69. SET_OA_ARGSTYPE(oap, REAL_ARGS);
  70. } else if( IS_COMPLEX(OA_SRC2(oap) ) ){
  71. SET_OA_ARGSTYPE(oap, MIXED_ARGS);
  72. } else if( IS_QUAT(OA_SRC2(oap) ) ){
  73. SET_OA_ARGSTYPE(oap, QMIXED_ARGS);
  74. } else {
  75. /* error - type mismatch */
  76. goto type_mismatch23;
  77. }
  78. } else if( IS_COMPLEX( OA_SRC1(oap) ) ){
  79. if( IS_REAL(OA_SRC2(oap) ) ){
  80. SET_OA_ARGSTYPE(oap, MIXED_ARGS);
  81. } else if( IS_COMPLEX(OA_SRC2(oap) ) ){
  82. SET_OA_ARGSTYPE(oap, MIXED_ARGS);
  83. } else {
  84. /* error - type mismatch */
  85. goto type_mismatch23;
  86. }
  87. } else if( IS_QUAT( OA_SRC1(oap) ) ){
  88. if( IS_REAL(OA_SRC2(oap) ) ){
  89. SET_OA_ARGSTYPE(oap, QMIXED_ARGS);
  90. } else if( IS_QUAT(OA_SRC2(oap) ) ){
  91. SET_OA_ARGSTYPE(oap, QMIXED_ARGS);
  92. } else {
  93. /* error - type mismatch */
  94. goto type_mismatch23;
  95. }
  96. }
  97. //#ifdef CAUTIOUS
  98. // Why was this CAUTIOUS when other goto's to type_mismatch13 are not???
  99. else {
  100. /* OA_SRC1 is not real or complex, must be a type mismatch */
  101. goto type_mismatch13;
  102. }
  103. //#endif /* CAUTIOUS */
  104. } else if( OA_SRC1(oap) != NO_OBJ ){ /* one source operand */
  105. if( IS_REAL( OA_SRC1(oap) ) ){
  106. SET_OA_ARGSTYPE(oap, REAL_ARGS);
  107. } else if( IS_COMPLEX( OA_SRC1(oap) ) ){
  108. SET_OA_ARGSTYPE(oap, MIXED_ARGS);
  109. } else if( IS_QUAT( OA_SRC1(oap) ) ){
  110. SET_OA_ARGSTYPE(oap, QMIXED_ARGS);
  111. } else {
  112. /* OA_SRC1 is not real or complex, must be a type mismatch */
  113. goto type_mismatch01;
  114. }
  115. } else { /* only 1 operand */
  116. SET_OA_ARGSTYPE(oap, REAL_ARGS);
  117. }
  118. } else if( IS_COMPLEX(OA_DEST(oap) ) ){
  119. if( OA_SRC2(oap) != NO_OBJ ){ /* two source operands */
  120. if( IS_COMPLEX( OA_SRC1(oap) ) ){
  121. if( IS_COMPLEX( OA_SRC2(oap) ) ){
  122. SET_OA_ARGSTYPE(oap, COMPLEX_ARGS);
  123. } else if( IS_REAL( OA_SRC2(oap) ) ){
  124. SET_OA_ARGSTYPE(oap, MIXED_ARGS);
  125. } else {
  126. /* error - type mismatch */
  127. goto type_mismatch23;
  128. }
  129. } else if( IS_REAL( OA_SRC1(oap) ) ){
  130. if( IS_COMPLEX( OA_SRC2(oap) ) ){
  131. SET_OA_ARGSTYPE(oap, MIXED_ARGS);
  132. /* Should we check for real-real with complex result??? */
  133. } else {
  134. /* error - type mismatch */
  135. goto type_mismatch23;
  136. }
  137. } else {
  138. /* OA_SRC1 is not real or complex, must be a type mismatch */
  139. goto type_mismatch13;
  140. }
  141. } else if( OA_SRC1(oap) != NO_OBJ ){ /* one source operand */
  142. if( IS_COMPLEX( OA_SRC1(oap) ) ){
  143. SET_OA_ARGSTYPE(oap, COMPLEX_ARGS);
  144. } else if( IS_REAL( OA_SRC1(oap) ) ){
  145. SET_OA_ARGSTYPE(oap, MIXED_ARGS);
  146. } else {
  147. /* OA_SRC1 is not real or complex, must be a type mismatch */
  148. goto type_mismatch01;
  149. }
  150. } else { /* only 1 operand */
  151. SET_OA_ARGSTYPE(oap, COMPLEX_ARGS);
  152. }
  153. } else if( IS_QUAT(OA_DEST(oap) ) ){
  154. if( OA_SRC2(oap) != NO_OBJ ){ /* two source operands */
  155. if( IS_QUAT( OA_SRC1(oap) ) ){
  156. if( IS_QUAT( OA_SRC2(oap) ) ){
  157. SET_OA_ARGSTYPE(oap, QUATERNION_ARGS);
  158. } else if( IS_REAL( OA_SRC2(oap) ) ){
  159. SET_OA_ARGSTYPE(oap, QMIXED_ARGS);
  160. } else {
  161. /* error - type mismatch */
  162. goto type_mismatch23;
  163. }
  164. } else if( IS_REAL( OA_SRC1(oap) ) ){
  165. if( IS_QUAT( OA_SRC2(oap) ) ){
  166. SET_OA_ARGSTYPE(oap, QMIXED_ARGS);
  167. /* Should we check for real-real with complex result??? */
  168. } else {
  169. /* error - type mismatch */
  170. goto type_mismatch23;
  171. }
  172. } else {
  173. /* OA_SRC1 is not real or complex, must be a type mismatch */
  174. goto type_mismatch13;
  175. }
  176. } else if( OA_SRC1(oap) != NO_OBJ ){ /* one source operand */
  177. if( IS_QUAT( OA_SRC1(oap) ) ){
  178. SET_OA_ARGSTYPE(oap, QUATERNION_ARGS);
  179. } else if( IS_REAL( OA_SRC1(oap) ) ){
  180. SET_OA_ARGSTYPE(oap, QMIXED_ARGS);
  181. } else {
  182. /* OA_SRC1 is not real or complex, must be a type mismatch */
  183. goto type_mismatch01;
  184. }
  185. } else { /* only 1 operand */
  186. SET_OA_ARGSTYPE(oap, QUATERNION_ARGS);
  187. }
  188. } else {
  189. sprintf(ERROR_STRING,"chktyp: can't categorize destination object %s!?",OBJ_NAME(OA_DEST(oap) ) );
  190. WARN(ERROR_STRING);
  191. }
  192. /* now the type field has been set - make sure it's legal */
  193. /* But first check a couple of special cases */
  194. /* make sure that function doesn't require mixed types */
  195. if( VF_FLAGS(vfp) & CPX_2_REAL ){
  196. //#ifdef CAUTIOUS
  197. // // quiet compiler
  198. // if( OA_SRC1(oap) == NULL ){
  199. // WARN("CAUITOUS: get_scal: Unexpected null source operand!?");
  200. // return -1;
  201. // }
  202. //#endif // CAUTIOUS
  203. assert( OA_SRC1(oap) != NULL );
  204. if( ! IS_COMPLEX( OA_SRC1(oap) ) ){
  205. sprintf(ERROR_STRING,"source vector %s (%s) must be complex with function %s",
  206. OBJ_NAME( OA_SRC1(oap) ) ,OBJ_PREC_NAME( OA_DEST(oap) ),VF_NAME(vfp) );
  207. WARN(ERROR_STRING);
  208. list_dobj(QSP_ARG OA_SRC1(oap) );
  209. return(-1);
  210. }
  211. if( ! IS_REAL(OA_DEST(oap) ) ){
  212. sprintf(ERROR_STRING,"destination vector %s (%s) must be real with function %s",
  213. OBJ_NAME(OA_DEST(oap) ) ,OBJ_PREC_NAME( OA_DEST(oap) ),VF_NAME(vfp) );
  214. WARN(ERROR_STRING);
  215. list_dobj(QSP_ARG OA_DEST(oap) );
  216. return(-1);
  217. }
  218. SET_OA_ARGSTYPE(oap, REAL_ARGS);
  219. return(0);
  220. }
  221. if( VF_CODE(vfp) == FVFFT ){
  222. /* source vector can be real or complex */
  223. if( !IS_COMPLEX(OA_DEST(oap) ) ){
  224. WARN("destination must be complex for fft");
  225. return(-1);
  226. }
  227. //#ifdef CAUTIOUS
  228. // // quiet analyzer
  229. // if( OA_SRC1(oap) == NULL ){
  230. // WARN("CAUTIOUS: Unexpected null src1 with fft!?");
  231. // return -1;
  232. // }
  233. //#endif // CAUTIOUS
  234. assert( OA_SRC1(oap) != NULL );
  235. if( IS_COMPLEX( OA_SRC1(oap) ) )
  236. SET_OA_ARGSTYPE(oap,COMPLEX_ARGS);
  237. else if( IS_QUAT( OA_SRC1(oap) ) ){
  238. WARN("Can't compute FFT of a quaternion input");
  239. return(-1);
  240. } else
  241. SET_OA_ARGSTYPE(oap,REAL_ARGS);
  242. return(0);
  243. }
  244. if( VF_CODE(vfp) == FVIFT ){
  245. //#ifdef CAUTIOUS
  246. // // quiet analyzer
  247. // if( OA_SRC1(oap) == NULL ){
  248. // WARN("CAUTIOUS: Unexpected null src1 with fft!?");
  249. // return -1;
  250. // }
  251. //#endif // CAUTIOUS
  252. assert( OA_SRC1(oap) != NULL );
  253. /* destination vector can be real or complex */
  254. if( !IS_COMPLEX( OA_SRC1(oap) ) ){
  255. WARN("source must be complex for inverse fft");
  256. return(-1);
  257. }
  258. if( IS_COMPLEX(OA_DEST(oap) ) )
  259. SET_OA_ARGSTYPE(oap,COMPLEX_ARGS);
  260. else if( IS_QUAT(OA_DEST(oap) ) ){
  261. WARN("Can't compute inverse FFT to a quaternion target");
  262. return(-1);
  263. } else
  264. SET_OA_ARGSTYPE(oap,REAL_ARGS);
  265. return(0);
  266. }
  267. /* now the type field has been set - make sure it's legal */
  268. if( (VF_TYPEMASK(vfp) & VL_TYPE_MASK(OA_ARGSTYPE(oap) ) )==0 ){
  269. sprintf(ERROR_STRING,
  270. "chktyp: Arguments of type %s are not permitted with function %s",
  271. argset_type_name[OA_ARGSTYPE(oap) ],VF_NAME(vfp) );
  272. WARN(ERROR_STRING);
  273. return(-1);
  274. }
  275. /*
  276. sprintf(ERROR_STRING,"function %s: oa_argstype = %s",VF_NAME(vfp) ,argset_type_name[OA_ARGSTYPE(oap) ]);
  277. ADVISE(ERROR_STRING);
  278. */
  279. /* if we get to here then it wasn't a special function */
  280. /* should be a function which allows same type or mixed */
  281. /* the first and second stuff is reversed
  282. * because the interpreter prompts for them
  283. * in the opposite order that they're passed
  284. */
  285. /* most legal mixed functions have one real and one complex operand, and
  286. * a complex target... But with the addition of quaternions, we also
  287. * can have quaternions mixed with real...
  288. */
  289. if( HAS_MIXED_ARGS(oap) && ! IS_COMPLEX(OA_DEST(oap)) ){
  290. sprintf(ERROR_STRING,"chktyp: destination vector %s must be complex when mixing types with function %s",
  291. OBJ_NAME(OA_DEST(oap) ) ,VF_NAME(vfp) );
  292. WARN(ERROR_STRING);
  293. return(-1);
  294. }
  295. if( HAS_QMIXED_ARGS(oap) && ! IS_QUAT(OA_DEST(oap) ) ){
  296. sprintf(ERROR_STRING,"chktyp: destination vector %s must be quaternion when mixing types with function %s",
  297. OBJ_NAME(OA_DEST(oap) ) ,VF_NAME(vfp) );
  298. WARN(ERROR_STRING);
  299. return(-1);
  300. }
  301. #define USES_REAL_SCALAR(code) \
  302. \
  303. ( code == FVSMUL || code == FVSADD || \
  304. code == FVSDIV || code == FVSSUB )
  305. #define USES_COMPLEX_SCALAR(code) \
  306. \
  307. ( code == FVCSMUL || code == FVCSADD || \
  308. code == FVCSDIV || code == FVCSSUB )
  309. #define USES_QUAT_SCALAR(code) \
  310. \
  311. ( code == FVQSMUL || code == FVQSADD || \
  312. code == FVQSDIV || code == FVQSSUB )
  313. /* BUG for things like vmul, it would be nice if the code
  314. * could just figure out which is real and which is complex
  315. * and swap around accordingly!
  316. */
  317. if( HAS_MIXED_ARGS(oap) ){
  318. #ifdef FOOBAR
  319. if( USES_REAL_SCALAR(VF_CODE(vfp)) ){
  320. if( ! IS_COMPLEX( OA_SRC2(oap) ) ){
  321. WARN("destination vector must be complex when mixing types with vsmul");
  322. return(-1);
  323. }
  324. if( ! IS_REAL( OA_SRC1(oap) ) ){
  325. WARN("source vector must be real when mixing types with vsmul");
  326. return(-1);
  327. }
  328. } else if( USES_COMPLEX_SCALAR(VF_CODE(vfp)) ){
  329. if( ! IS_COMPLEX( OA_SRC2(oap) ) ){
  330. WARN("destination vector must be complex when mixing types with vcsmul");
  331. return(-1);
  332. }
  333. if( ! IS_REAL( OA_SRC1(oap) ) ){
  334. WARN("source vector must be real when mixing types with vcsmul");
  335. return(-1);
  336. }
  337. } else if( USES_QUAT_SCALAR(VF_CODE(vfp)) ){
  338. if( ! IS_QUAT( OA_SRC2(oap) ) ){
  339. WARN("destination vector must be quaternion when mixing types with vqsmul");
  340. return(-1);
  341. }
  342. if( ! IS_REAL( OA_SRC1(oap) ) ){
  343. WARN("source vector must be real when mixing types with vqsmul");
  344. return(-1);
  345. }
  346. }
  347. #endif /* FOOBAR */
  348. /*
  349. show_obj_args(oap);
  350. sprintf(ERROR_STRING,"Function %s.",VF_NAME(vfp) );
  351. ADVISE(ERROR_STRING);
  352. ERROR1("chktyp: Sorry, not sure how to deal with this situation...");
  353. */
  354. if( ! IS_COMPLEX( OA_SRC1(oap) ) ){
  355. sprintf(ERROR_STRING,
  356. "first source vector (%s,%s) must be complex when mixing types with function %s",
  357. OBJ_NAME( OA_SRC1(oap) ) ,
  358. name_for_type( OA_SRC1(oap) ),
  359. VF_NAME(vfp) );
  360. WARN(ERROR_STRING);
  361. return(-1);
  362. }
  363. // Mixed-arg fuctions have to have two sources, but the analyzer
  364. // doesn't know that...
  365. //#ifdef CAUTIOUS
  366. // if( OA_SRC2(oap) == NULL ){
  367. // WARN("CAUTIOUS: Null src2 with mixed-arg function!?");
  368. // return -1;
  369. // }
  370. //#endif // CAUTIOUS
  371. assert( OA_SRC2(oap) != NULL );
  372. if( ! IS_REAL(OA_SRC2(oap) ) ){
  373. sprintf(ERROR_STRING,
  374. "second source vector (%s,%s) must be real when mixing types with function %s",
  375. OBJ_NAME(OA_SRC2(oap) ) ,
  376. name_for_type(OA_SRC2(oap) ),
  377. VF_NAME(vfp) );
  378. WARN(ERROR_STRING);
  379. return(-1);
  380. }
  381. /* Should the destination be complex??? */
  382. } else if( HAS_QMIXED_ARGS(oap) ){
  383. ERROR1("FIXME: need to add code for quaternions, vec_call.c");
  384. /* BUG add the same check as above for quaternions */
  385. return -1;
  386. }
  387. return(0);
  388. type_mismatch13:
  389. sprintf(ERROR_STRING,"Type mismatch between objects %s (%s) and %s (%s), function %s",
  390. OBJ_NAME( OA_SRC1(oap) ) ,name_for_type( OA_SRC1(oap) ),
  391. OBJ_NAME( OA_SRC3(oap) ) ,name_for_type( OA_SRC3(oap) ),
  392. VF_NAME(vfp) );
  393. WARN(ERROR_STRING);
  394. return(-1);
  395. type_mismatch01:
  396. sprintf(ERROR_STRING,"Type mismatch between objects %s (%s) and %s (%s), function %s",
  397. OBJ_NAME( OA_SRC1(oap) ) ,name_for_type( OA_SRC1(oap) ),
  398. OBJ_NAME(OA_DEST(oap) ) ,name_for_type(OA_DEST(oap) ),
  399. VF_NAME(vfp) );
  400. WARN(ERROR_STRING);
  401. return(-1);
  402. type_mismatch23:
  403. sprintf(ERROR_STRING,"Type mismatch between objects %s (%s) and %s (%s), function %s",
  404. OBJ_NAME(OA_SRC2(oap) ) ,name_for_type(OA_SRC2(oap) ),
  405. OBJ_NAME( OA_SRC3(oap) ) ,name_for_type( OA_SRC3(oap) ),
  406. VF_NAME(vfp) );
  407. WARN(ERROR_STRING);
  408. return(-1);
  409. } /* end chktyp() */
  410. static void show_legal_precisions(uint32_t mask)
  411. {
  412. uint32_t bit=1;
  413. prec_t prec;
  414. NADVISE("legal precisions are:");
  415. for( prec = 0; prec < 32 ; prec ++ ){
  416. bit = 1 << prec ;
  417. if( mask & bit ){
  418. sprintf(DEFAULT_ERROR_STRING,"\t%s",NAME_FOR_PREC_CODE(prec));
  419. NADVISE(DEFAULT_ERROR_STRING);
  420. }
  421. }
  422. }
  423. #define NEW_PREC_ERROR_MSG( prec ) \
  424. \
  425. sprintf(ERROR_STRING, \
  426. "chkprec: %s: input %s (%s) should have %s or %s precision with target %s (%s)", \
  427. VF_NAME(vfp) ,OBJ_NAME( OA_SRC1(oap) ) ,OBJ_PREC_NAME( OA_SRC1(oap) ), \
  428. NAME_FOR_PREC_CODE( prec ),NAME_FOR_PREC_CODE(dst_prec), \
  429. OBJ_NAME(OA_DEST(oap) ) ,OBJ_PREC_NAME( OA_DEST(oap) )); \
  430. WARN(ERROR_STRING); \
  431. return(-1);
  432. /* chkprec sets two flags:
  433. * oa_argsprec (tells machine prec),
  434. * and argstype (real/complex etc)
  435. *
  436. * But isn't argstype set by chktyp???
  437. *
  438. * The conditional operators don't have the same requirements
  439. * for matching... That is, they *shouldn't*, but because we have
  440. * different function calls for each operand type, it would not be practical
  441. * to have all different types...
  442. */
  443. /* end chkprec */
  444. static int chkprec(QSP_ARG_DECL Vector_Function *vfp,Vec_Obj_Args *oap)
  445. {
  446. prec_t srcp1,srcp2,dst_prec;
  447. int n_srcs=0;
  448. if( IS_NEW_CONVERSION(vfp) ){
  449. // New conversions specify the destination precision
  450. // e.g. vconv2by, and have sub-functions for all possible source precs
  451. // We should have a check here to insure that the destination prec
  452. // is appropriate for each function code.
  453. // No support for bitmaps yet
  454. return(0);
  455. }
  456. if( IS_CONVERSION(vfp) ){
  457. /* Conversions support all the rpecisions, so the checks
  458. * after this block are irrelevant.
  459. */
  460. /* the default function type is set using OA_SRC1 (the source),
  461. * but if the target is a bitmap we want to set it to bitmap...
  462. */
  463. if( IS_BITMAP(OA_DEST(oap) ) ){
  464. /*
  465. ADVISE("chkprec: Setting argstype to R_BIT_ARGS!?");
  466. SET_OA_ARGSTYPE(oap, R_BIT_ARGS);
  467. */
  468. /* R_BIT_ARGS was a functype - not an argset type??? */
  469. SET_OA_ARGSPREC(oap, BIT_ARGS);
  470. } else if( IS_BITMAP( OA_SRC1(oap) ) ){
  471. /* this is necessary because bitmaps handled with kludgy hacks */
  472. SET_OA_SBM(oap,OA_SRC1(oap) );
  473. }
  474. return(0);
  475. }
  476. dst_prec=OBJ_MACH_PREC(OA_DEST(oap) );
  477. /* BUG? could be bitmap destination??? */
  478. /* need to find out which prec to test... */
  479. /* First we make sure that all arg precisions
  480. * are legal with this function
  481. */
  482. if( ( VF_PRECMASK(vfp) & (1<<dst_prec)) == 0 ){
  483. sprintf(ERROR_STRING,
  484. "chkprec: dest. precision %s (obj %s) cannot be used with function %s",
  485. NAME_FOR_PREC_CODE(dst_prec),OBJ_NAME(OA_DEST(oap) ) ,VF_NAME(vfp) );
  486. WARN(ERROR_STRING);
  487. show_legal_precisions( VF_PRECMASK(vfp));
  488. return(-1);
  489. }
  490. if( OA_SRC1(oap) != NO_OBJ ){
  491. srcp1=OBJ_MACH_PREC( OA_SRC1(oap) );
  492. if( ( VF_PRECMASK(vfp) & (1<<srcp1)) == 0 ){
  493. sprintf(ERROR_STRING,
  494. "chkprec: src precision %s (obj %s) cannot be used with function %s",
  495. NAME_FOR_PREC_CODE(srcp1),OBJ_NAME( OA_SRC1(oap) ) ,VF_NAME(vfp) );
  496. WARN(ERROR_STRING);
  497. show_legal_precisions( VF_PRECMASK(vfp));
  498. return(-1);
  499. }
  500. n_srcs++;
  501. if( OA_SRC2(oap) != NO_OBJ ){
  502. srcp2=OBJ_MACH_PREC(OA_SRC2(oap) );
  503. if( ( VF_PRECMASK(vfp) & (1<<srcp2)) == 0 ){
  504. sprintf(ERROR_STRING,
  505. "chkprec: src precision %s (obj %s) cannot be used with function %s",
  506. NAME_FOR_PREC_CODE(srcp2),OBJ_NAME(OA_SRC2(oap) ) ,VF_NAME(vfp) );
  507. WARN(ERROR_STRING);
  508. show_legal_precisions( VF_PRECMASK(vfp));
  509. return(-1);
  510. }
  511. n_srcs++;
  512. }
  513. // Can there be more than 3 sources???
  514. }
  515. /* Figure out what type of function to call based on the arguments... */
  516. if( n_srcs == 0 ){
  517. /* oa_argstype is Function_Type...
  518. * is this right? just a null setting?
  519. */
  520. /* we used to use dst_prec here, but that
  521. * is only the machine precision!?
  522. */
  523. SET_OA_ARGSPREC(oap, ARGSET_PREC(OBJ_PREC( OA_DEST(oap) ) ));
  524. return(0);
  525. } else if( n_srcs == 2 ){
  526. /* First make sure that the two source operands match */
  527. if( srcp1 != srcp2 ) {
  528. source_mismatch_error:
  529. sprintf(ERROR_STRING,
  530. "chkprec: %s operands %s (%s) and %s (%s) should have the same precision",
  531. VF_NAME(vfp) ,OBJ_NAME( OA_SRC1(oap) ) ,
  532. OBJ_PREC_NAME( OA_SRC1(oap) ),
  533. OBJ_NAME(OA_SRC2(oap) ) ,
  534. OBJ_PREC_NAME( OA_SRC2(oap) ) );
  535. WARN(ERROR_STRING);
  536. return(-1);
  537. }
  538. /* if the precision is long, make sure that
  539. * none (or all) are bitmaps
  540. */
  541. if( srcp1 == BITMAP_MACH_PREC ){
  542. if( (IS_BITMAP( OA_SRC1(oap) ) && ! IS_BITMAP(OA_SRC2(oap) )) ||
  543. ( ! IS_BITMAP( OA_SRC1(oap) ) && IS_BITMAP(OA_SRC2(oap) )) )
  544. goto source_mismatch_error;
  545. }
  546. }
  547. /* Now we know that there are 1 or 2 inputs in addition to the target,
  548. * and that if there are two they match. Therefore we only have to
  549. * consider the first one.
  550. * dst_prec is the machine precision of the destination -
  551. * but doesn't include the pseudo-precision for bitmaps?
  552. */
  553. /* This test can succeed when the input is the same as bitmap_word */
  554. if( srcp1 == dst_prec ){
  555. if( srcp1 == BITMAP_MACH_PREC ){
  556. if( IS_BITMAP(OA_DEST(oap) ) && !IS_BITMAP( OA_SRC1(oap) ) )
  557. goto next1;
  558. if( IS_BITMAP( OA_SRC1(oap) ) && !IS_BITMAP(OA_DEST(oap) ) )
  559. goto next1;
  560. }
  561. /* Can't use dst_prec here because might be bitmap */
  562. SET_OA_ARGSPREC(oap, ARGSET_PREC(OBJ_PREC( OA_DEST(oap) ) ));
  563. return(0);
  564. }
  565. next1:
  566. /* Now we know that this is a mixed precision case.
  567. * Make sure it is one of the legal ones.
  568. * First we check the special cases (bitmaps, indices).
  569. */
  570. if( VF_FLAGS(vfp) & BITMAP_DST ){ /* vcmp, vcmpm */
  571. /* Is dest vector set too??? */
  572. if( OBJ_PREC( OA_DEST(oap) ) != PREC_BIT ){
  573. sprintf(ERROR_STRING,
  574. "%s: result vector %s (%s) should have %s precision",
  575. VF_NAME(vfp) ,OBJ_NAME(OA_DEST(oap) ) ,
  576. OBJ_PREC_NAME( OA_DEST(oap) ),
  577. NAME_FOR_PREC_CODE(PREC_BIT));
  578. WARN(ERROR_STRING);
  579. return(-1);
  580. }
  581. /* use the precision from the source */
  582. SET_OA_ARGSPREC(oap, ARGSET_PREC( OBJ_PREC( OA_SRC1(oap) ) ));
  583. return(0);
  584. }
  585. if( VF_FLAGS(vfp) == V_SCALRET2 ){ /* vmaxg etc */
  586. /* We assme that this is an index array and
  587. * not a bitmap.
  588. */
  589. if( OBJ_PREC( OA_DEST(oap) ) != PREC_DI ){
  590. sprintf(ERROR_STRING,
  591. "chkprec: %s: destination vector %s (%s) should have %s precision",
  592. VF_NAME(vfp) ,OBJ_NAME(OA_DEST(oap) ) ,
  593. OBJ_PREC_NAME( OA_DEST(oap) ),
  594. NAME_FOR_PREC_CODE(PREC_DI) );
  595. WARN(ERROR_STRING);
  596. return(-1);
  597. }
  598. /* If the destination is long, don't worry about
  599. * a match with the arg...
  600. */
  601. return(0);
  602. }
  603. /* don't insist on a precision match if result is an index */
  604. if( VF_FLAGS(vfp) & INDEX_RESULT ){
  605. /* We assume that we check the result precision elsewhere? */
  606. return(0);
  607. }
  608. switch( dst_prec ){
  609. case PREC_IN:
  610. if( srcp1==PREC_UBY ){
  611. SET_OA_ARGSPREC(oap, BYIN_ARGS);
  612. return(0);
  613. }
  614. NEW_PREC_ERROR_MSG(PREC_UBY);
  615. break;
  616. case PREC_DP:
  617. if( srcp1==PREC_SP ){
  618. SET_OA_ARGSPREC(oap, SPDP_ARGS);
  619. return(0);
  620. }
  621. NEW_PREC_ERROR_MSG(PREC_SP);
  622. break;
  623. case PREC_DI:
  624. if( srcp1==PREC_UIN ){
  625. SET_OA_ARGSPREC(oap, INDI_ARGS);
  626. return(0);
  627. }
  628. NEW_PREC_ERROR_MSG(PREC_UIN);
  629. break;
  630. case PREC_BY:
  631. if( srcp1==PREC_IN ){
  632. SET_OA_ARGSPREC(oap, INBY_ARGS);
  633. return(0);
  634. }
  635. NEW_PREC_ERROR_MSG(PREC_IN);
  636. break;
  637. default:
  638. sprintf(ERROR_STRING,
  639. "chkprec: %s: target %s (%s) cannot be used with mixed prec source %s (%s)",
  640. VF_NAME(vfp) ,OBJ_NAME(OA_DEST(oap) ) ,
  641. OBJ_PREC_NAME( OA_DEST(oap) ),
  642. OBJ_NAME( OA_SRC1(oap) ) ,NAME_FOR_PREC_CODE(srcp1));
  643. WARN(ERROR_STRING);
  644. return(-1);
  645. }
  646. SET_OA_FUNCTYPE( oap, FUNCTYPE_FOR( OA_ARGSPREC(oap) ,OA_ARGSTYPE(oap) ) );
  647. //TELL_FUNCTYPE( OA_ARGSPREC(oap) ,OA_ARGSTYPE(oap) )
  648. } /* end chkprec() */
  649. static int chksiz(QSP_ARG_DECL Vector_Function *vfp,Vec_Obj_Args *oap) /* check for argument size match */
  650. {
  651. int status=0;
  652. /* If the operation has a bitmap, then check the bitmap against the first source
  653. * (if bitmap is destination), or the destination (if bitmap is a source).
  654. *
  655. * An exception is conversion routines, where the bitmap *is* the first source...
  656. * The conversion routines do not have the BITMAP flag set...
  657. *
  658. * We should allow the bitmap to have additional dimensions above what the source
  659. * has, like a projection loop...
  660. */
  661. if( OA_SBM(oap) != NO_OBJ ){
  662. if( VF_FLAGS(vfp) & BITMAP_SRC ){ // redundant?
  663. /* We used to require that the bitmap size matched the destination,
  664. * but that is not necessary...
  665. */
  666. /*
  667. if( (status=old_cksiz(VF_FLAGS(vfp),OA_SBM(oap) ,OA_DEST(oap) ))
  668. == (-1) )
  669. */
  670. if( (status=cksiz(QSP_ARG VF_FLAGS(vfp),OA_SBM(oap) ,OA_DEST(oap) ))
  671. == (-1) )
  672. {
  673. sprintf(ERROR_STRING,
  674. "chksiz: bitmap arg func size error, function %s",VF_NAME(vfp) );
  675. ADVISE(ERROR_STRING);
  676. return(-1);
  677. }
  678. }
  679. //#ifdef CAUTIOUS
  680. // else if( ! IS_CONVERSION(vfp) && VF_CODE(vfp) != FVMOV ){
  681. // sprintf(ERROR_STRING,
  682. // "CAUTIOUS: chksiz %s: obj args bitmap is non-null, but function has no bitmap flag!?",
  683. // VF_NAME(vfp) );
  684. // ERROR1(ERROR_STRING);
  685. // }
  686. else {
  687. assert( IS_CONVERSION(vfp) || VF_CODE(vfp) == FVMOV );
  688. }
  689. // if( status != 0 ){
  690. // sprintf(ERROR_STRING,"CAUTIOUS: chksiz %s: old_cksiz returned status=%d!?",VF_NAME(vfp) ,status);
  691. // NWARN(ERROR_STRING);
  692. // }
  693. //#endif /* CAUTIOUS */
  694. assert( status == 0 );
  695. }
  696. if( OA_SRC1(oap) == NO_OBJ ){
  697. /* nothing to check!? */
  698. return(0);
  699. }
  700. #ifdef QUIP_DEBUG
  701. if( debug & veclib_debug ){
  702. sprintf(ERROR_STRING,"chksiz: destv %s (%s) arg1 %s (%s)",
  703. OBJ_NAME(OA_DEST(oap) ), AREA_NAME(OBJ_AREA(OA_DEST(oap))),
  704. OBJ_NAME( OA_SRC1(oap) ), AREA_NAME(OBJ_AREA(OA_SRC1(oap))) );
  705. ADVISE(ERROR_STRING);
  706. }
  707. #endif /* QUIP_DEBUG */
  708. /* We check the sizes of the args against the destination object - but in the case of ops like vdot,
  709. * (or any other scalar-returning projection op like vmax etc)
  710. * this may not match...
  711. */
  712. if( VF_CODE(vfp) == FVDOT ){
  713. if( (status=cksiz(QSP_ARG VF_FLAGS(vfp), OA_SRC1(oap) ,OA_SRC2(oap) )) == (-1) ){
  714. sprintf(ERROR_STRING,"chksiz: Size mismatch between arg1 (%s) and arg2 (%s), function %s",
  715. OBJ_NAME( OA_SRC1(oap) ) ,OBJ_NAME(OA_SRC2(oap) ) ,VF_NAME(vfp) );
  716. ADVISE(ERROR_STRING);
  717. return(-1);
  718. }
  719. return(0);
  720. }
  721. if( (status=cksiz(QSP_ARG VF_FLAGS(vfp), OA_SRC1(oap) ,OA_DEST(oap) )) == (-1) ){
  722. sprintf(ERROR_STRING,"chksiz: Size mismatch between arg1 (%s) and destination (%s), function %s",
  723. OBJ_NAME( OA_SRC1(oap) ) ,OBJ_NAME(OA_DEST(oap) ) ,VF_NAME(vfp) );
  724. ADVISE(ERROR_STRING);
  725. return(-1);
  726. }
  727. //#ifdef CAUTIOUS
  728. // if( status != 0 ){
  729. // sprintf(ERROR_STRING,"CAUTIOUS: chksiz %s: cksiz returned status=%d!?",VF_NAME(vfp) ,status);
  730. // NWARN(ERROR_STRING);
  731. // }
  732. //#endif /* CAUTIOUS */
  733. assert( status == 0 );
  734. if( OA_SRC2(oap) == NO_OBJ ) return(0);
  735. #ifdef QUIP_DEBUG
  736. if( debug & veclib_debug ){
  737. sprintf(ERROR_STRING,"chksiz: destv %s (%s) arg2 %s (%s)",
  738. OBJ_NAME(OA_DEST(oap) ), AREA_NAME(OBJ_AREA(OA_DEST(oap))),
  739. OBJ_NAME(OA_SRC2(oap) ), AREA_NAME(OBJ_AREA(OA_SRC2(oap))) );
  740. ADVISE(ERROR_STRING);
  741. }
  742. #endif /* QUIP_DEBUG */
  743. if( (status=cksiz(QSP_ARG VF_FLAGS(vfp),OA_SRC2(oap) ,OA_DEST(oap) )) == (-1) ){
  744. sprintf(ERROR_STRING,"chksiz: Size mismatch between arg2 (%s) and destination (%s), function %s",
  745. OBJ_NAME(OA_SRC2(oap) ) ,OBJ_NAME(OA_DEST(oap) ) ,VF_NAME(vfp) );
  746. ADVISE(ERROR_STRING);
  747. return(-1);
  748. }
  749. //#ifdef CAUTIOUS
  750. // if( status != 0 ){
  751. // sprintf(ERROR_STRING,"CAUTIOUS: chksiz %s: cksiz returned status=%d!?",VF_NAME(vfp) ,status);
  752. // NWARN(ERROR_STRING);
  753. // return(-1);
  754. // }
  755. //#endif /* CAUTIOUS */
  756. assert( status == 0 );
  757. /* BUG what about bitmaps?? */
  758. return(0);
  759. } /* end chksiz() */
  760. /* check that all of the arguments match (when they should) */
  761. static int chkargs( QSP_ARG_DECL Vector_Function *vfp, Vec_Obj_Args *oap)
  762. {
  763. //#ifdef CAUTIOUS
  764. // if( OA_DEST(oap) == NO_OBJ && VF_FLAGS(vfp) & BITMAP_DST ){
  765. //// OA_DEST(oap) = OA_BMAP(oap) ;
  766. // ERROR1("CAUTIOUS: chkargs: OA_DEST is null, expected a bitmap!?");
  767. // }
  768. //#endif // CAUTIOUS
  769. assert( OA_DEST(oap) != NO_OBJ || (VF_FLAGS(vfp) & BITMAP_DST)==0 );
  770. if( chk_uk(QSP_ARG vfp,oap) == (-1) ) return(-1);
  771. if( chktyp(QSP_ARG vfp,oap) == (-1) ) return(-1);
  772. if( chkprec(QSP_ARG vfp,oap) == (-1) ) return(-1);
  773. if( chksiz(QSP_ARG vfp,oap) == (-1) ) return(-1);
  774. /* Now we have to set the function type */
  775. return(0);
  776. }
  777. /* chkprec() now has the job of figuring out mixed precision op's */
  778. /* Instead of using the prec_mask from the table, we can figure out what
  779. * function we want and see if it is not equal to nullf...
  780. *
  781. */
  782. #define PREC_ERROR_MSG( prec ) \
  783. \
  784. sprintf(ERROR_STRING, \
  785. "chkprec: %s: input %s (%s) should have %s or %s precision with target %s (%s)", \
  786. VF_NAME(vfp) ,OBJ_NAME( OA_SRC1(oap) ) ,OBJ_PREC_NAME( OA_SRC1(oap) ), \
  787. NAME_FOR_PREC_CODE( prec ),NAME_FOR_PREC_CODE(dst_prec), \
  788. OBJ_NAME(OA_DEST(oap) ) ,OBJ_PREC_NAME( OA_DEST(oap) )); \
  789. WARN(ERROR_STRING); \
  790. return(-1);
  791. #ifdef FOOBAR
  792. int cktype(Data_Obj *dp1,Data_Obj *dp2)
  793. {
  794. if( dp1->dt_tdim != dp2->dt_tdim ) return(-1);
  795. else return(0);
  796. }
  797. void wacky_arg(Data_Obj *dp)
  798. {
  799. sprintf(ERROR_STRING, "%s: inc = %d, cols = %d",
  800. OBJ_NAME(dp) , dp->dt_inc, dp->dt_cols );
  801. NWARN(ERROR_STRING);
  802. list_dobj(QSP_ARG dp);
  803. ERROR1("wacky_arg: can't happen #1");
  804. }
  805. static char *remove_brackets(char *name)
  806. {
  807. static char clean_name[LLEN];
  808. char *s,*t;
  809. /* if the name has no brackets, we don't need to do anything */
  810. if( strstr(name,"[") == NULL && strstr(name,"{") == NULL ) return(name);
  811. /* BUG we don't check for the name overflowing LLEN */
  812. s=name;
  813. t=clean_name;
  814. while( *s ){
  815. if( *s == '[' ){
  816. *t++ = 'S';
  817. *t++ = 'O';
  818. } else if( *s == ']' ){
  819. *t++ = 'S';
  820. *t++ = 'C';
  821. } else if( *s == '{' ){
  822. *t++ = 'C';
  823. *t++ = 'O';
  824. } else if( *s == '}' ){
  825. *t++ = 'C';
  826. *t++ = 'C';
  827. } else {
  828. *t++ = *s;
  829. }
  830. s++;
  831. }
  832. *t=0;
  833. return(clean_name);
  834. }
  835. #endif /* FOOBAR */
  836. #ifdef FOOBAR
  837. static int make_arg_evenly_spaced(Vec_Obj_Args *oap,int index)
  838. {
  839. Data_Obj *new_dp,*arg_dp;
  840. char tmp_name[LLEN];
  841. arg_dp = OA_SRC_OBJ(oap,index) ;
  842. if( arg_dp == NO_OBJ ) return(0);
  843. if( IS_EVENLY_SPACED(arg_dp) ) return(0);
  844. /* If the object is subscripted, the brackets will break the name */
  845. sprintf(tmp_name,"%s.dup",remove_brackets(OBJ_NAME(arg_dp) ));
  846. new_dp = dup_obj(arg_dp,tmp_name);
  847. dp_copy(new_dp,arg_dp); /* BUG use vmov */
  848. if( OA_DEST(oap) == arg_dp )
  849. OA_DEST(oap) = new_dp;
  850. SET_OA_SRC_OBJ(oap,index) = new_dp;
  851. return(1);
  852. }
  853. #endif /* FOOBAR */
  854. int perf_vfunc(QSP_ARG_DECL Vec_Func_Code code, Vec_Obj_Args *oap)
  855. {
  856. return( call_vfunc(QSP_ARG FIND_VEC_FUNC(code), oap) );
  857. }
  858. #ifdef HAVE_ANY_GPU
  859. // BUG??? is this redundant now that we have platforms?
  860. static int default_gpu_dispatch(Vector_Function *vfp, Vec_Obj_Args *oap)
  861. {
  862. sprintf(DEFAULT_ERROR_STRING,"No GPU dispatch function specified, can't call %s",VF_NAME(vfp) );
  863. NWARN(DEFAULT_ERROR_STRING);
  864. NADVISE("Please call set_gpu_dispatch_func().");
  865. return(-1);
  866. }
  867. static int (*gpu_dispatch_func)(Vector_Function *vfp, Vec_Obj_Args *oap)=default_gpu_dispatch;
  868. void set_gpu_dispatch_func( int (*func)(Vector_Function *vfp, Vec_Obj_Args *oap) )
  869. {
  870. //sprintf(ERROR_STRING,"Setting gpu dispatch func (0x%lx)",(int_for_addr)func);
  871. //ADVISE(ERROR_STRING);
  872. gpu_dispatch_func = func;
  873. }
  874. #endif /* HAVE_ANY_GPU */
  875. int call_vfunc( QSP_ARG_DECL Vector_Function *vfp, Vec_Obj_Args *oap )
  876. {
  877. /* Set the default function type.
  878. * Why do we use src1 in preference to oa_dest?
  879. *
  880. * One answer is bitmap result functions...
  881. */
  882. if( OA_SRC1(oap) != NO_OBJ ){
  883. SET_OA_ARGSPREC(oap, ARGSET_PREC( OBJ_PREC( OA_SRC1(oap) ) ));
  884. } else if( OA_DEST(oap) != NO_OBJ ){
  885. SET_OA_ARGSPREC(oap, ARGSET_PREC( OBJ_PREC( OA_DEST(oap) ) ));
  886. } else {
  887. sprintf(ERROR_STRING,"call_vfunc %s:",VF_NAME(vfp) );
  888. ADVISE(ERROR_STRING);
  889. ERROR1("call_vfunc: no prototype vector!?");
  890. }
  891. //sprintf(ERROR_STRING,"call_vfunc: function %s",VF_NAME(vfp));
  892. //advise(ERROR_STRING);
  893. //show_obj_args(QSP_ARG oap);
  894. /* If we are performing a conversion, we assume that the proper
  895. * conversion function has already been selected.
  896. * We want to do this efficiently...
  897. */
  898. /* if( IS_CONVERSION(vfp) ) return(0); */
  899. /* check for precision, type, size matches */
  900. if( chkargs(QSP_ARG vfp,oap) == (-1) ) return(-1); /* make set vslct_fake */
  901. /* argstype has been set from within chkargs */
  902. SET_OA_FUNCTYPE( oap, FUNCTYPE_FOR( OA_ARGSPREC(oap) ,OA_ARGSTYPE(oap) ) );
  903. //TELL_FUNCTYPE( OA_ARGSPREC(oap) ,OA_ARGSTYPE(oap) )
  904. /* We don't worry here about vectorization on CUDA... */
  905. // Here we should call the platform-specific dispatch function...
  906. if( check_obj_devices(oap) < 0 )
  907. return -1;
  908. assert( OA_PFDEV(oap) != NULL );
  909. /*
  910. fprintf(stderr,"call_vfunc: oap = 0x%lx vfp = 0x%lx\n",
  911. (long)oap,(long)vfp );
  912. fprintf(stderr,"call_vfunc: func at 0x%lx\n",(long)OA_DISPATCH_FUNC(oap));
  913. */
  914. //return (* OA_DISPATCH_FUNC( oap ) )(QSP_ARG vfp,oap);
  915. return platform_dispatch( QSP_ARG PFDEV_PLATFORM(OA_PFDEV(oap)), vfp,oap);
  916. } // call_vfunc