/dx-4.4.4/src/exec/libdx/lbextract.c

# · C · 1185 lines · 816 code · 237 blank · 132 comment · 200 complexity · 95a46cf3b93d40dadc0418c319897fcd MD5 · raw file

  1. /***********************************************************************/
  2. /* Open Visualization Data Explorer */
  3. /* (C) Copyright IBM Corp. 1989,1999 */
  4. /* ALL RIGHTS RESERVED */
  5. /* This code licensed under the */
  6. /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */
  7. /***********************************************************************/
  8. #include <dxconfig.h>
  9. #include <string.h>
  10. #include <dx/dx.h>
  11. /*
  12. * simple routines for common cases
  13. */
  14. Object DXExtractInteger(Object o, int *ip)
  15. {
  16. return DXExtractParameter(o, TYPE_INT, 0, 1, (Pointer)ip);
  17. }
  18. Object DXExtractFloat(Object o, float *fp)
  19. {
  20. return DXExtractParameter(o, TYPE_FLOAT, 0, 1, (Pointer)fp);
  21. }
  22. /* slightly different - it returns a pointer to the start of the string.
  23. * the caller doesn't need to allocate space for it.
  24. */
  25. Object DXExtractString(Object o, char **cp)
  26. {
  27. char *c;
  28. int len;
  29. Type t;
  30. /* this does the checking to be sure it is either a String object,
  31. * or a TYPE_STRING array.
  32. */
  33. if(!DXQueryParameter(o, TYPE_STRING, 1, NULL))
  34. return NULL;
  35. if(DXGetObjectClass(o) == CLASS_STRING) {
  36. if (cp)
  37. *cp = DXGetString((String)o);
  38. return o;
  39. }
  40. DXGetArrayInfo((Array) o, &len, &t, NULL, NULL, NULL);
  41. if (t == TYPE_STRING) {
  42. if (len > 1)
  43. return NULL;
  44. if (cp)
  45. *cp = (char *)DXGetArrayData((Array)o);
  46. return o;
  47. }
  48. /* for backwards compatibility - TYPE_UBYTE */
  49. c = (char *)DXGetArrayData((Array)o);
  50. while (--len > 0) {
  51. if (*c++) /* fail if there are imbedded NULLs... */
  52. continue;
  53. return NULL;
  54. }
  55. if (*c) /* ...or if there isn't a trailing NULL */
  56. return NULL;
  57. if (cp)
  58. *cp = (char *)DXGetArrayData((Array)o);
  59. return o;
  60. }
  61. Object DXExtractNthString (Object o, int n, char **cp)
  62. {
  63. char *c, *cs;
  64. int len;
  65. Type type;
  66. int shape;
  67. if (n < 0)
  68. return (NULL);
  69. /* only returns ok if object class String or Array TYPE_STRING or UBYTE */
  70. if (! DXQueryParameter (o, TYPE_STRING, 1, NULL))
  71. return (NULL);
  72. if (DXGetObjectClass(o) == CLASS_STRING) {
  73. /* String objects are 1 string, so asking for any string
  74. * but the 0th is bad.
  75. */
  76. if (n)
  77. return (NULL);
  78. if (cp)
  79. *cp = DXGetString ((String) o);
  80. return (o);
  81. }
  82. DXGetArrayInfo ((Array) o, &len, &type, NULL, NULL, NULL);
  83. if (type == TYPE_STRING) {
  84. /* len is number of strings in array */
  85. if (n >= len)
  86. return NULL;
  87. /* the Query call above made sure this is rank 1,
  88. * so shape is safe here
  89. */
  90. DXGetArrayInfo ((Array) o, NULL, NULL, NULL, NULL, &shape);
  91. cs = (char *) DXGetArrayData ((Array) o);
  92. if (cp)
  93. *cp = cs + (n * shape);
  94. return o;
  95. }
  96. /* here for backward compatibility -
  97. * null separated chars in a UBYTE array
  98. */
  99. cs = (char *) DXGetArrayData ((Array) o);
  100. for (c=cs; len--; ) {
  101. if (*c++)
  102. continue;
  103. if (n == 0) {
  104. if (cp)
  105. *cp = cs;
  106. return (o);
  107. }
  108. n--;
  109. cs = c;
  110. }
  111. return (NULL);
  112. }
  113. /* new code */
  114. #define CONVTYPE(from, to) \
  115. static Error \
  116. from##2##to(int count, from *fp, to *tp) \
  117. { \
  118. int i; \
  119. \
  120. for (i=0; i<count; i++) \
  121. *tp++ = (to) *fp++; \
  122. \
  123. return OK; \
  124. }
  125. CONVTYPE(byte, short)
  126. CONVTYPE(byte, int)
  127. CONVTYPE(byte, float)
  128. CONVTYPE(byte, double)
  129. CONVTYPE(ubyte, short )
  130. CONVTYPE(ubyte, ushort)
  131. CONVTYPE(ubyte, int)
  132. CONVTYPE(ubyte, uint)
  133. CONVTYPE(ubyte, float)
  134. CONVTYPE(ubyte, double)
  135. CONVTYPE(short, int)
  136. CONVTYPE(short, float)
  137. CONVTYPE(short, double)
  138. CONVTYPE(ushort, int)
  139. CONVTYPE(ushort, uint)
  140. CONVTYPE(ushort, float)
  141. CONVTYPE(ushort, double)
  142. CONVTYPE(int, float)
  143. CONVTYPE(int, double)
  144. CONVTYPE(uint, float)
  145. CONVTYPE(uint, double)
  146. CONVTYPE(float, double)
  147. struct convtable {
  148. int conversion; /* convert flags */
  149. Error (*convfunc)(); /* convert routine */
  150. /* parms are: (int count, Pointer from, Pointer to); */
  151. int hascommon; /* has common representation? */
  152. Type commontype; /* smallest common representation */
  153. };
  154. /* conversion flags */
  155. #define CONV_ILLEGAL 0 /* types don't convert without truncation */
  156. #define CONV_ALLOWED 1 /* conversion allowed */
  157. #define CONV_EQUAL 2 /* types already same */
  158. #define CONV_NOTIMPL 3 /* type not implemented */
  159. #define CONV_LOSSY 4 /* conversion may lose precision (not supported) */
  160. /* table indices for conversion function table */
  161. #define NUM_TYPES 11
  162. #define C_BYTE 0
  163. #define C_UBYTE 1
  164. #define C_SHORT 2
  165. #define C_USHORT 3
  166. #define C_INT 4
  167. #define C_UINT 5
  168. #define C_HYPER 6 /* currently unsupported */
  169. #define C_UHYPER 7 /* currently unsupported */
  170. #define C_FLOAT 8
  171. #define C_DOUBLE 9
  172. #define C_LDOUBLE 10 /* currently unsupported */
  173. #define TYPE_XXXX TYPE_BYTE /* fill in value for unimplemented types */
  174. /* hascommon flags */
  175. #define NO_COMMON 0
  176. #define HAS_COMMON 1
  177. static char *typename(Type t)
  178. {
  179. switch (t) {
  180. case TYPE_BYTE: return "byte";
  181. case TYPE_UBYTE: return "ubyte";
  182. case TYPE_SHORT: return "short";
  183. case TYPE_USHORT: return "ushort";
  184. case TYPE_INT: return "int";
  185. case TYPE_UINT: return "uint";
  186. case TYPE_HYPER: return "hyper";
  187. /* case TYPE_UHYPER: return "uhyper"; */
  188. case TYPE_FLOAT: return "float";
  189. case TYPE_DOUBLE: return "double";
  190. /* case TYPE_LDOUBLE: return "ldouble"; */
  191. default: return "unknown";
  192. }
  193. /* notreached */
  194. }
  195. static int typeindex(Type t)
  196. {
  197. switch (t) {
  198. case TYPE_BYTE: return C_BYTE;
  199. case TYPE_UBYTE: return C_UBYTE;
  200. case TYPE_SHORT: return C_SHORT;
  201. case TYPE_USHORT: return C_USHORT;
  202. case TYPE_INT: return C_INT;
  203. case TYPE_UINT: return C_UINT;
  204. case TYPE_HYPER: return C_HYPER;
  205. /* case TYPE_UHYPER: return C_UHYPER; */
  206. case TYPE_FLOAT: return C_FLOAT;
  207. case TYPE_DOUBLE: return C_DOUBLE;
  208. /* case TYPE_LDOUBLE: return C_LDOUBLE; */
  209. default: return -1;
  210. }
  211. /* notreached */
  212. }
  213. static struct convtable typetable[NUM_TYPES][NUM_TYPES] =
  214. {
  215. /* from BYTE */ /* to ... */
  216. { { CONV_EQUAL, NULL, HAS_COMMON, TYPE_BYTE }, /* BYTE */
  217. { CONV_ILLEGAL, NULL, NO_COMMON, TYPE_BYTE }, /* UBYTE */
  218. { CONV_ALLOWED, byte2short, HAS_COMMON, TYPE_SHORT }, /* SHORT */
  219. { CONV_ILLEGAL, NULL, NO_COMMON, TYPE_BYTE }, /* USHORT */
  220. { CONV_ALLOWED, byte2int, HAS_COMMON, TYPE_INT }, /* INT */
  221. { CONV_ILLEGAL, NULL, NO_COMMON, TYPE_BYTE }, /* UINT */
  222. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* HYPER */
  223. { CONV_NOTIMPL, NULL, NO_COMMON, TYPE_BYTE }, /* UHYPER */
  224. { CONV_ALLOWED, byte2float, HAS_COMMON, TYPE_FLOAT }, /* FLOAT */
  225. { CONV_ALLOWED, byte2double, HAS_COMMON, TYPE_DOUBLE }, /* DOUBLE */
  226. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, }, /* LDOUBLE */
  227. /* from UBYTE */ /* to ... */
  228. { { CONV_ILLEGAL, NULL, NO_COMMON, TYPE_BYTE }, /* BYTE */
  229. { CONV_EQUAL, NULL, HAS_COMMON, TYPE_UBYTE }, /* UBYTE */
  230. { CONV_ALLOWED, ubyte2short, HAS_COMMON, TYPE_SHORT }, /* SHORT */
  231. { CONV_ALLOWED, ubyte2ushort, HAS_COMMON, TYPE_USHORT }, /* USHORT */
  232. { CONV_ALLOWED, ubyte2int, HAS_COMMON, TYPE_INT }, /* INT */
  233. { CONV_ALLOWED, ubyte2uint, HAS_COMMON, TYPE_UINT }, /* UINT */
  234. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* HYPER */
  235. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, /* UHYPER */
  236. { CONV_ALLOWED, ubyte2float, HAS_COMMON, TYPE_FLOAT }, /* FLOAT */
  237. { CONV_ALLOWED, ubyte2double, HAS_COMMON, TYPE_DOUBLE }, /* DOUBLE */
  238. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, }, /* LDOUBLE */
  239. /* from SHORT */ /* to ... */
  240. { { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_SHORT }, /* BYTE */
  241. { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_SHORT }, /* UBYTE */
  242. { CONV_EQUAL, NULL, HAS_COMMON, TYPE_SHORT }, /* SHORT */
  243. { CONV_ILLEGAL, NULL, NO_COMMON, TYPE_BYTE }, /* USHORT */
  244. { CONV_ALLOWED, short2int, HAS_COMMON, TYPE_INT }, /* INT */
  245. { CONV_ILLEGAL, NULL, NO_COMMON, TYPE_BYTE }, /* UINT */
  246. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* HYPER */
  247. { CONV_NOTIMPL, NULL, NO_COMMON, TYPE_BYTE }, /* UHYPER */
  248. { CONV_ALLOWED, short2float, HAS_COMMON, TYPE_FLOAT }, /* FLOAT */
  249. { CONV_ALLOWED, short2double, HAS_COMMON, TYPE_DOUBLE }, /* DOUBLE */
  250. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, }, /* LDOUBLE */
  251. /* from USHORT */ /* to ... */
  252. { { CONV_ILLEGAL, NULL, NO_COMMON, TYPE_BYTE }, /* BYTE */
  253. { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_USHORT }, /* UBYTE */
  254. { CONV_ILLEGAL, NULL, NO_COMMON, TYPE_BYTE }, /* SHORT */
  255. { CONV_EQUAL, NULL, HAS_COMMON, TYPE_USHORT }, /* USHORT */
  256. { CONV_ALLOWED, ushort2int, HAS_COMMON, TYPE_INT }, /* INT */
  257. { CONV_ALLOWED, ushort2uint, HAS_COMMON, TYPE_UINT }, /* UINT */
  258. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* HYPER */
  259. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, /* UHYPER */
  260. { CONV_ALLOWED, ushort2float, HAS_COMMON, TYPE_FLOAT }, /* FLOAT */
  261. { CONV_ALLOWED, ushort2double, HAS_COMMON, TYPE_DOUBLE }, /* DOUBLE */
  262. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, }, /* LDOUBLE */
  263. /* from INT */ /* to ... */
  264. { { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_INT }, /* BYTE */
  265. { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_INT }, /* UBYTE */
  266. { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_INT }, /* SHORT */
  267. { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_INT }, /* USHORT */
  268. { CONV_EQUAL, NULL, HAS_COMMON, TYPE_INT }, /* INT */
  269. { CONV_ILLEGAL, NULL, NO_COMMON, TYPE_BYTE }, /* UINT */
  270. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* HYPER */
  271. { CONV_NOTIMPL, NULL, NO_COMMON, TYPE_BYTE }, /* UHYPER */
  272. { CONV_ALLOWED, int2float, HAS_COMMON, TYPE_FLOAT }, /* FLOAT */
  273. { CONV_ALLOWED, int2double, HAS_COMMON, TYPE_DOUBLE }, /* DOUBLE */
  274. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, }, /* LDOUBLE */
  275. /* from UINT */ /* to ... */
  276. { { CONV_ILLEGAL, NULL, NO_COMMON, TYPE_BYTE }, /* BYTE */
  277. { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_UBYTE }, /* UBYTE */
  278. { CONV_ILLEGAL, NULL, NO_COMMON, TYPE_BYTE }, /* SHORT */
  279. { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_USHORT }, /* USHORT */
  280. { CONV_ILLEGAL, NULL, NO_COMMON, TYPE_BYTE }, /* INT */
  281. { CONV_EQUAL, NULL, HAS_COMMON, TYPE_UINT }, /* UINT */
  282. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* HYPER */
  283. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, /* UHYPER */
  284. { CONV_ALLOWED, uint2float, HAS_COMMON, TYPE_FLOAT }, /* FLOAT */
  285. { CONV_ALLOWED, uint2double, HAS_COMMON, TYPE_DOUBLE }, /* DOUBLE */
  286. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, }, /* LDOUBLE */
  287. /* from HYPER */ /* to ... */
  288. { { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* BYTE */
  289. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* UBYTE */
  290. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* SHORT */
  291. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* USHORT */
  292. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* INT */
  293. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* UINT */
  294. { CONV_EQUAL, NULL, HAS_COMMON, TYPE_HYPER }, /* HYPER */
  295. { CONV_NOTIMPL, NULL, NO_COMMON, TYPE_BYTE }, /* UHYPER */
  296. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_FLOAT }, /* FLOAT */
  297. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_DOUBLE }, /* DOUBLE */
  298. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, }, /* LDOUBLE */
  299. /* from UHYPER */ /* to ... */
  300. { { CONV_NOTIMPL, NULL, NO_COMMON, TYPE_BYTE }, /* BYTE */
  301. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* UBYTE */
  302. { CONV_NOTIMPL, NULL, NO_COMMON, TYPE_BYTE }, /* SHORT */
  303. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* USHORT */
  304. { CONV_NOTIMPL, NULL, NO_COMMON, TYPE_BYTE }, /* INT */
  305. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_HYPER }, /* UINT */
  306. { CONV_NOTIMPL, NULL, NO_COMMON, TYPE_BYTE }, /* HYPER */
  307. { CONV_EQUAL, NULL, HAS_COMMON, TYPE_XXXX }, /* UHYPER */
  308. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_FLOAT }, /* FLOAT */
  309. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_DOUBLE }, /* DOUBLE */
  310. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, }, /* LDOUBLE */
  311. /* from FLOAT */ /* to ... */
  312. { { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_FLOAT }, /* BYTE */
  313. { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_FLOAT }, /* UBYTE */
  314. { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_FLOAT }, /* SHORT */
  315. { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_FLOAT }, /* USHORT */
  316. { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_FLOAT }, /* INT */
  317. { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_FLOAT }, /* UINT */
  318. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_FLOAT }, /* HYPER */
  319. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_FLOAT }, /* UHYPER */
  320. { CONV_EQUAL, NULL, HAS_COMMON, TYPE_FLOAT }, /* FLOAT */
  321. { CONV_ALLOWED, float2double, HAS_COMMON, TYPE_DOUBLE }, /* DOUBLE */
  322. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, }, /* LDOUBLE */
  323. /* from DOUBLE */ /* to ... */
  324. { { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_DOUBLE }, /* BYTE */
  325. { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_DOUBLE }, /* UBYTE */
  326. { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_DOUBLE }, /* SHORT */
  327. { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_DOUBLE }, /* USHORT */
  328. { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_DOUBLE }, /* INT */
  329. { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_DOUBLE }, /* UINT */
  330. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_DOUBLE }, /* HYPER */
  331. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_DOUBLE }, /* UHYPER */
  332. { CONV_ILLEGAL, NULL, HAS_COMMON, TYPE_DOUBLE }, /* FLOAT */
  333. { CONV_EQUAL, NULL, HAS_COMMON, TYPE_DOUBLE }, /* DOUBLE */
  334. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, }, /* LDOUBLE */
  335. /* from LDOUBLE */ /* to ... */
  336. { { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, /* BYTE */
  337. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, /* UBYTE */
  338. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, /* SHORT */
  339. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, /* USHORT */
  340. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, /* INT */
  341. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, /* UINT */
  342. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, /* HYPER */
  343. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, /* UHYPER */
  344. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, /* FLOAT */
  345. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, /* DOUBLE */
  346. { CONV_NOTIMPL, NULL, HAS_COMMON, TYPE_XXXX }, }, /* LDOUBLE */
  347. };
  348. /* these could probably be macro-ized somehow */
  349. /* THESE MUST WORK INPLACE!!! */
  350. #define INC(ptr, size) (Pointer)((long)(ptr) + (size))
  351. #define DEC(ptr, size) (Pointer)((long)(ptr) - (size))
  352. /* conversion is: a -> a + 0i */
  353. static Error real2complex(int count, Pointer from, Pointer to, int itemsize)
  354. {
  355. int i;
  356. Pointer efrom, eto;
  357. efrom = INC(from, itemsize * (count-1));
  358. eto = INC(to, 2 * itemsize * (count-1));
  359. for (i=count; i>0; i--) {
  360. memset(eto, '\0', itemsize);
  361. eto = DEC(to, itemsize);
  362. memcpy(efrom, eto, itemsize);
  363. efrom = DEC(from, itemsize);
  364. eto = DEC(to, itemsize);
  365. }
  366. return OK;
  367. }
  368. /* conversion is: a -> a + 0i + 0j + 0k */
  369. static Error real2quatern(int count, Pointer from, Pointer to, int itemsize)
  370. {
  371. int i;
  372. /*efrom = INC(from, itemsize * (count-1));*/
  373. /*eto = INC(to, 4 * itemsize * (count-1));*/
  374. for (i=count; i>0; i--) {
  375. memset(to, '\0', 3 * itemsize);
  376. to = DEC(to, 3 * itemsize);
  377. memcpy(from, to, itemsize);
  378. from = DEC(from, itemsize);
  379. to = DEC(to, itemsize);
  380. }
  381. return OK;
  382. }
  383. /* conversion is: a + bi -> a + bi + 0j + 0k */
  384. static Error complex2quatern(int count, Pointer from, Pointer to, int itemsize)
  385. {
  386. int i;
  387. /*efrom = INC(from, itemsize * (count-1));*/
  388. /*eto = INC(from, 2 * itemsize * (count-1));*/
  389. for (i=count; i>0; i--) {
  390. memset(to, '\0', itemsize);
  391. to = DEC(to, itemsize);
  392. memcpy(from, to, itemsize);
  393. from = DEC(from, itemsize);
  394. to = DEC(to, itemsize);
  395. }
  396. return OK;
  397. }
  398. struct convtable2 {
  399. int conversion;
  400. Error (*convfunc)(int count, Pointer from, Pointer to, int itemsize);
  401. int hascommon;
  402. Category commoncat;
  403. };
  404. /* (uses same conversion flags as above) */
  405. #define NUM_CATS 3
  406. #define C_REAL 0
  407. #define C_COMPLEX 1
  408. #define C_QUATERN 2
  409. static char *catname(Category c)
  410. {
  411. switch (c) {
  412. case CATEGORY_REAL: return "real";
  413. case CATEGORY_COMPLEX: return "complex";
  414. case CATEGORY_QUATERNION: return "quaternion";
  415. default: return "unknown";
  416. }
  417. /* notreached */
  418. }
  419. static int catindex(Category c)
  420. {
  421. switch (c) {
  422. case CATEGORY_REAL: return C_REAL;
  423. case CATEGORY_COMPLEX: return C_COMPLEX;
  424. case CATEGORY_QUATERNION: return C_QUATERN;
  425. default: return -1;
  426. }
  427. /* notreached */
  428. }
  429. static struct convtable2 cattable[NUM_CATS][NUM_CATS] =
  430. {
  431. /* from REAL */ /* to ... */
  432. { { CONV_EQUAL, NULL, HAS_COMMON, CATEGORY_REAL }, /* REAL */
  433. { CONV_ALLOWED, real2complex, HAS_COMMON, CATEGORY_COMPLEX }, /* COMPLEX */
  434. { CONV_ALLOWED, real2quatern, HAS_COMMON, CATEGORY_QUATERNION }, }, /* QUATERN */
  435. /* from COMPLEX */ /* to ... */
  436. { { CONV_ILLEGAL, NULL, HAS_COMMON, CATEGORY_COMPLEX }, /* REAL */
  437. { CONV_EQUAL, NULL, HAS_COMMON, CATEGORY_COMPLEX }, /* COMPLEX */
  438. { CONV_ALLOWED, complex2quatern, HAS_COMMON, CATEGORY_QUATERNION }, }, /* QUATERN */
  439. /* from QUATERN */ /* to ... */
  440. { { CONV_ILLEGAL, NULL, HAS_COMMON, CATEGORY_QUATERNION }, /* REAL */
  441. { CONV_ILLEGAL, NULL, HAS_COMMON, CATEGORY_QUATERNION }, /* COMPLEX */
  442. { CONV_EQUAL, NULL, HAS_COMMON, CATEGORY_QUATERNION }, }, /* QUATERN */
  443. };
  444. /* this modifies shape in place to squeeze out shapes of 1
  445. * (e.g. rank 3, shape 3 1 4 -> rank 2 shape 3 4)
  446. */
  447. static void SqueezeShape(int *rank, int *shape)
  448. {
  449. int i, j;
  450. i = 0;
  451. while (i < *rank) {
  452. if (shape[i] > 1)
  453. i++;
  454. else {
  455. (*rank)--;
  456. for (j=i; j<*rank; j++)
  457. shape[j] = shape[j+1];
  458. }
  459. }
  460. }
  461. /* this checks to see if it can squeeze the first rank/shape pair
  462. * to match the second, and if it can, it modifies them in place
  463. * and returns OK. otherwise it leaves them alone and returns ERROR
  464. * and sets the error code.
  465. * if it has to expand to match, it adds shape 1 at the end of the list.
  466. *
  467. * this routine isn't done yet.
  468. */
  469. #if 0
  470. static Error SqueezeToShape(int *rank, int *shape, int trank, int *tshape)
  471. {
  472. int i, j;
  473. i = 0;
  474. while (i < *rank) {
  475. if (shape[i] > 1)
  476. i++;
  477. else {
  478. (*rank)--;
  479. for (j=i; j<*rank; j++)
  480. shape[j] = shape[j+1];
  481. }
  482. }
  483. return ERROR;
  484. }
  485. #endif
  486. static Error
  487. ConvertArrayContents(Array from, Array to, int squeeze)
  488. {
  489. int i;
  490. int fi, ti;
  491. Pointer fromdp, todp;
  492. int count;
  493. int fromcount, tocount;
  494. Type fromtype, totype;
  495. Category fromcat, tocat;
  496. int fromrank, torank;
  497. int fromshape[100], toshape[100];
  498. DXGetArrayInfo(from, &fromcount, &fromtype, &fromcat, &fromrank, fromshape);
  499. DXGetArrayInfo(to, &tocount, &totype, &tocat, &torank, toshape);
  500. if (fromcount != tocount)
  501. DXErrorReturn(ERROR_DATA_INVALID, "array sizes don't match");
  502. /* squeeze out shapes of 1 from both and make sure they match. */
  503. if (squeeze) {
  504. SqueezeShape(&fromrank, fromshape);
  505. SqueezeShape(&torank, toshape);
  506. }
  507. if (fromrank != torank) {
  508. if (squeeze)
  509. DXErrorReturn(ERROR_DATA_INVALID, "data ranks don't match");
  510. return ConvertArrayContents(from, to, 1);
  511. }
  512. for (i=0; i<fromrank; i++)
  513. if (fromshape[i] != toshape[i]) {
  514. if (squeeze)
  515. DXErrorReturn(ERROR_DATA_INVALID, "data shapes don't match");
  516. return ConvertArrayContents(from, to, 1);
  517. }
  518. if (((fi = typeindex(fromtype)) < 0) || ((ti = typeindex(totype)) < 0))
  519. DXErrorReturn(ERROR_NOT_IMPLEMENTED, "unsupported data type");
  520. fromdp = DXGetArrayData(from);
  521. todp = DXGetArrayData(to);
  522. switch (typetable[fi][ti].conversion) {
  523. case CONV_EQUAL:
  524. memcpy(todp, fromdp, fromcount * DXGetItemSize(from));
  525. break;
  526. case CONV_ALLOWED:
  527. count = fromcount * (DXGetItemSize(from) / DXTypeSize(fromtype));
  528. if ((typetable[fi][ti].convfunc)(count, fromdp, todp) == ERROR)
  529. DXErrorReturn(ERROR_DATA_INVALID, "type conversion failed");
  530. break;
  531. case CONV_NOTIMPL:
  532. default:
  533. DXErrorReturn(ERROR_NOT_IMPLEMENTED, "unsupported data type");
  534. case CONV_ILLEGAL:
  535. case CONV_LOSSY:
  536. DXSetError(ERROR_DATA_INVALID, "cannot convert %s to %s",
  537. typename(fromtype), typename(totype));
  538. return ERROR;
  539. }
  540. if (((fi = catindex(fromcat)) < 0) || ((ti = catindex(tocat)) < 0))
  541. DXErrorReturn(ERROR_NOT_IMPLEMENTED, "unsupported data category");
  542. switch (cattable[fi][ti].conversion) {
  543. case CONV_EQUAL:
  544. break;
  545. case CONV_ALLOWED:
  546. count = fromcount * (DXGetItemSize(from) / DXCategorySize(fromcat));
  547. if ((cattable[fi][ti].convfunc)(count, todp, todp,
  548. DXGetItemSize(from)) == ERROR)
  549. DXErrorReturn(ERROR_DATA_INVALID, "category conversion failed");
  550. break;
  551. case CONV_NOTIMPL:
  552. default:
  553. DXErrorReturn(ERROR_NOT_IMPLEMENTED, "unsupported data category");
  554. case CONV_ILLEGAL:
  555. case CONV_LOSSY:
  556. DXSetError(ERROR_NOT_IMPLEMENTED, "cannot convert %s to %s",
  557. catname(fromcat), catname(tocat));
  558. return ERROR;
  559. }
  560. return OK;
  561. }
  562. static Array
  563. ArrayConvert(Array a, Type t, Category c, int rank, int *shape)
  564. {
  565. int i;
  566. Array out;
  567. ASSERT(rank<100);
  568. out = DXNewArrayV(t, c, rank, shape);
  569. DXGetArrayInfo(a, &i, NULL, NULL, NULL, NULL);
  570. if (!DXAddArrayData(out, 0, i, NULL))
  571. return NULL;
  572. if (!ConvertArrayContents(a, out, 0)) {
  573. DXDelete((Object)out);
  574. return NULL;
  575. }
  576. return out;
  577. }
  578. Array
  579. DXArrayConvert(Array a, Type t, Category c, int rank, ... )
  580. {
  581. int i;
  582. int shape[100];
  583. va_list arg;
  584. ASSERT(rank<100);
  585. /* collect args */
  586. va_start(arg,rank); /* no spaces allowed - this is a weird macro */
  587. for (i=0; i<rank; i++)
  588. shape[i] = va_arg(arg, int);
  589. va_end(arg);
  590. /* common code with V version. */
  591. return ArrayConvert(a, t, c, rank, shape);
  592. }
  593. Array
  594. DXArrayConvertV(Array a, Type t, Category c, int rank, int *shape)
  595. {
  596. return ArrayConvert(a, t, c, rank, shape);
  597. }
  598. /* sees if there is a common format and returns it. otherwise returns
  599. * NULL but and sets error code.
  600. */
  601. static Error
  602. QueryArrayCommon(Type *t, Category *c, int *rank, int *shape, int n,
  603. Array *a, int squeeze)
  604. {
  605. int i, j;
  606. int ni, cti, cci;
  607. Type nextt, comt;
  608. Category nextc, comc;
  609. int nextrank, comrank;
  610. int nextshape[100], comshape[100];
  611. ASSERT(n<100);
  612. if (n <= 0) {
  613. DXSetError(ERROR_DATA_INVALID,
  614. "array list count must be a positive integer");
  615. return ERROR;
  616. }
  617. if (!DXGetArrayInfo(a[0], NULL, &comt, &comc, &comrank, comshape))
  618. return ERROR;
  619. if (squeeze)
  620. SqueezeShape(&comrank, comshape);
  621. /* if the values don't match, see if they are compatible, and use
  622. * the minimum necessary changes.
  623. */
  624. for (i=1; i<n; i++) {
  625. if (!DXGetArrayInfo(a[i], NULL, &nextt, &nextc, &nextrank, nextshape))
  626. return ERROR;
  627. /* data type */
  628. if (comt != nextt) {
  629. if ((cti = typeindex(comt)) < 0)
  630. DXErrorReturn(ERROR_NOT_IMPLEMENTED, "unsupported data type");
  631. if ((ni = typeindex(nextt)) < 0)
  632. DXErrorReturn(ERROR_NOT_IMPLEMENTED, "unsupported data type");
  633. switch (typetable[cti][ni].hascommon) {
  634. case HAS_COMMON:
  635. comt = typetable[cti][ni].commontype;
  636. break;
  637. case NO_COMMON:
  638. DXSetError(ERROR_DATA_INVALID, "no common format for %s and %s",
  639. typename(comt), typename(nextt));
  640. return ERROR;
  641. }
  642. }
  643. /* data category */
  644. if (comc != nextc) {
  645. if ((cci = catindex(comc)) < 0)
  646. DXErrorReturn(ERROR_NOT_IMPLEMENTED, "unsupported data category");
  647. if ((ni = catindex(nextc)) < 0)
  648. DXErrorReturn(ERROR_NOT_IMPLEMENTED, "unsupported data category");
  649. switch (cattable[cci][ni].hascommon) {
  650. case HAS_COMMON:
  651. comc = cattable[cci][ni].commoncat;
  652. break;
  653. case NO_COMMON:
  654. DXSetError(ERROR_DATA_INVALID, "no common format for %s and %s",
  655. catname(comc), catname(nextc));
  656. return ERROR;
  657. }
  658. }
  659. /* data rank - squeeze out shapes of 1 */
  660. if (squeeze)
  661. SqueezeShape(&nextrank, nextshape);
  662. if (comrank != nextrank) {
  663. if (squeeze) {
  664. DXSetError(ERROR_DATA_INVALID,
  665. "data rank does not match (%d != %d)",
  666. comrank, nextrank);
  667. return ERROR;
  668. }
  669. return QueryArrayCommon(t, c, rank, shape, n, a, 1);
  670. }
  671. for (j=0; j<comrank; j++) {
  672. if (comshape[j] != nextshape[j]) {
  673. if (squeeze) {
  674. DXSetError(ERROR_DATA_INVALID,
  675. "data shape %d does not match (%d != %d)",
  676. j, comshape[j], nextshape[j]);
  677. return ERROR;
  678. }
  679. return QueryArrayCommon(t, c, rank, shape, n, a, 1);
  680. }
  681. }
  682. }
  683. /* ok - finally. return the results */
  684. if (t)
  685. *t = comt;
  686. if (c)
  687. *c = comc;
  688. if (rank)
  689. *rank = comrank;
  690. if (shape) {
  691. for (i=0; i<comrank; i++)
  692. shape[i] = comshape[i];
  693. }
  694. return OK;
  695. }
  696. Error
  697. DXQueryArrayCommon(Type *t, Category *c, int *rank, int *shape,
  698. int n, Array a, ...)
  699. {
  700. int i;
  701. Array alist[100];
  702. va_list arg;
  703. ASSERT(n<100);
  704. /* collect args */
  705. va_start(arg,a); /* no spaces allowed - this is a weird macro */
  706. for (i=0; i<n; i++)
  707. alist[i] = va_arg(arg, Array);
  708. va_end(arg);
  709. /* common code with V version. */
  710. return QueryArrayCommon(t, c, rank, shape, n, alist, 0);
  711. }
  712. Error
  713. DXQueryArrayCommonV(Type *t, Category *c, int *rank, int *shape,
  714. int n, Array *alist)
  715. {
  716. return QueryArrayCommon(t, c, rank, shape, n, alist, 0);
  717. }
  718. /* sees if the array can be converted to the requested format.
  719. * should this set the error code?? (it does right now)
  720. */
  721. static Error
  722. QueryArrayConvert(Array a, Type t, Category c, int rank, int *shape, int squeeze)
  723. {
  724. int i;
  725. int ai, rti, rci;
  726. Type at;
  727. Category ac;
  728. int arank;
  729. int ashape[100], rshape[100];
  730. if (!DXGetArrayInfo(a, NULL, &at, &ac, &arank, ashape))
  731. return ERROR;
  732. /* data type */
  733. if (at != t) {
  734. if ((rti = typeindex(t)) < 0)
  735. DXErrorReturn(ERROR_NOT_IMPLEMENTED, "unsupported data type");
  736. if ((ai = typeindex(at)) < 0)
  737. DXErrorReturn(ERROR_NOT_IMPLEMENTED, "unsupported data type");
  738. switch (typetable[ai][rti].conversion) {
  739. case CONV_EQUAL:
  740. case CONV_ALLOWED:
  741. break;
  742. default:
  743. DXSetError(ERROR_DATA_INVALID, "cannot convert type %s into %s",
  744. typename(at), typename(t));
  745. return ERROR;
  746. }
  747. }
  748. /* data category */
  749. if (ac != c) {
  750. if ((rci = catindex(c)) < 0)
  751. DXErrorReturn(ERROR_NOT_IMPLEMENTED, "unsupported data category");
  752. if ((ai = catindex(ac)) < 0)
  753. DXErrorReturn(ERROR_NOT_IMPLEMENTED, "unsupported data category");
  754. switch (cattable[ai][rci].conversion) {
  755. case CONV_EQUAL:
  756. case CONV_ALLOWED:
  757. break;
  758. default:
  759. DXSetError(ERROR_DATA_INVALID, "cannot convert category %s into %s",
  760. catname(ac), catname(c));
  761. return ERROR;
  762. }
  763. }
  764. /* get rid of 1's */
  765. if (squeeze) {
  766. SqueezeShape(&arank, ashape);
  767. for (i=0; i<rank; i++)
  768. rshape[i] = shape[i];
  769. SqueezeShape(&rank, rshape);
  770. }
  771. if (arank != rank) {
  772. if (squeeze) {
  773. DXSetError(ERROR_DATA_INVALID, "data rank does not match (%d > %d)",
  774. arank, rank);
  775. return ERROR;
  776. }
  777. return QueryArrayConvert(a, t, c, rank, shape, 1);
  778. }
  779. /* data rank and shape */
  780. for (i=0; i<rank; i++)
  781. if (shape[i] != rshape[i]) {
  782. if (squeeze) {
  783. DXSetError(ERROR_DATA_INVALID,
  784. "data shape does not match (%d != %d)",
  785. shape[i], ashape[i]);
  786. return ERROR;
  787. }
  788. return QueryArrayConvert(a, t, c, rank, shape, 1);
  789. }
  790. return OK;
  791. }
  792. Error
  793. DXQueryArrayConvert(Array a, Type t, Category c, int rank, ...)
  794. {
  795. int i;
  796. int shape[100];
  797. va_list arg;
  798. ASSERT(rank<100);
  799. /* collect args */
  800. va_start(arg,rank); /* no spaces allowed - this is a weird macro */
  801. for (i=0; i<rank; i++)
  802. shape[i] = va_arg(arg, int);
  803. va_end(arg);
  804. /* common code with V version. */
  805. return QueryArrayConvert(a, t, c, rank, shape, 0);
  806. }
  807. Error
  808. DXQueryArrayConvertV(Array a, Type t, Category c, int rank, int *shape)
  809. {
  810. return QueryArrayConvert(a, t, c, rank, shape, 0);
  811. }
  812. #define MAXDIM 32
  813. /* type check an object, and return the number if a list.
  814. */
  815. Object DXQueryParameter(Object o, Type t, int dim, int *count)
  816. {
  817. int nitems;
  818. Type at;
  819. Category ac;
  820. int ar, as[MAXDIM];
  821. /* assume the worst */
  822. if(count)
  823. *count = 0;
  824. if(!o)
  825. return NULL;
  826. /* slightly special case for char arrays, which might come in
  827. * as string objects.
  828. */
  829. if ((t == TYPE_STRING) && (DXGetObjectClass(o) == CLASS_STRING)) {
  830. char *cp = DXGetString((String)o);
  831. if(!cp || dim > 1)
  832. return NULL;
  833. if(dim == 0 && strlen(cp) > 1)
  834. return NULL;
  835. if(count)
  836. *count = strlen(cp);
  837. return o;
  838. }
  839. /* check general characteristics first, before worrying about
  840. * specific data types
  841. */
  842. if( DXGetObjectClass(o) != CLASS_ARRAY
  843. || !DXGetArrayInfo((Array)o, &nitems, &at, &ac, &ar, as)
  844. || ac != CATEGORY_REAL
  845. || ar > 1
  846. || nitems == 0)
  847. return NULL;
  848. /* don't do these checks for strings */
  849. if (at != TYPE_STRING) {
  850. /* if dim > 1, rank must be 1 and shape must match dim.
  851. * dim 0 or 1 both match rank 1 shape 1 and rank 0
  852. */
  853. if(dim > 1) {
  854. if(ar != 1 || as[0] != dim)
  855. return NULL;
  856. } else {
  857. if(ar > 1 || (ar == 1 && as[0] != 1))
  858. return NULL;
  859. }
  860. }
  861. if(count)
  862. *count = nitems;
  863. /* if types match exactly, you're done */
  864. if(at == t)
  865. return o;
  866. /* see if the types could be promoted ok. 'at' is the actual
  867. * array type, 't' is what they want.
  868. */
  869. if (dim == 0) {
  870. if (DXQueryArrayConvert((Array)o, t, CATEGORY_REAL, 0) == OK)
  871. return o;
  872. } else {
  873. if (DXQueryArrayConvert((Array)o, t, CATEGORY_REAL, 1, dim) == OK)
  874. return o;
  875. }
  876. DXResetError();
  877. return NULL;
  878. }
  879. /* given an object, and a caller-allocated buffer, copy the input
  880. * to the buffer, converting type if necessary.
  881. */
  882. Object DXExtractParameter(Object o, Type t, int dim, int count, Pointer p)
  883. {
  884. Array na;
  885. char *sp;
  886. int nitems;
  887. Type at;
  888. Category ac;
  889. int ar, as[MAXDIM];
  890. if(!o)
  891. return NULL;
  892. /* slightly special case for string arrays, which might come in
  893. * as string objects.
  894. */
  895. if(t == TYPE_STRING && DXGetObjectClass(o) == CLASS_STRING) {
  896. sp = DXGetString((String)o);
  897. if(!sp || dim > 1)
  898. return NULL;
  899. if(dim == 0 && strlen(sp) > 1)
  900. return NULL;
  901. if(count != strlen(sp))
  902. return NULL;
  903. if (p)
  904. strcpy((char *)p, sp);
  905. return o;
  906. }
  907. /* check general characteristics first, before worrying about
  908. * specific data types
  909. */
  910. if( DXGetObjectClass(o) != CLASS_ARRAY
  911. || !DXGetArrayInfo((Array)o, &nitems, &at, &ac, &ar, as)
  912. || ac != CATEGORY_REAL
  913. || ar > 1
  914. || nitems == 0
  915. || nitems != count)
  916. return NULL;
  917. /* if dim > 1, rank must be 1 and shape must match dim.
  918. * dim 0 or 1 both match rank 1 shape 1 and rank 0
  919. */
  920. if(dim > 1) {
  921. if(ar != 1 || as[0] != dim)
  922. return NULL;
  923. } else {
  924. if(ar > 1 || (ar == 1 && as[0] != 1))
  925. return NULL;
  926. }
  927. /* if types match exactly, just memcpy the number of bytes and return */
  928. if(at == t) {
  929. if (p)
  930. memcpy(p, DXGetArrayData((Array)o),
  931. nitems * DXGetItemSize((Array)o));
  932. return o;
  933. }
  934. /* types don't match exactly, so see if they can be converted.
  935. */
  936. if (dim == 0)
  937. na = DXArrayConvert((Array)o, t, CATEGORY_REAL, 0);
  938. else
  939. na = DXArrayConvert((Array)o, t, CATEGORY_REAL, 1, dim);
  940. if (!na) {
  941. DXResetError();
  942. return NULL;
  943. }
  944. if (p)
  945. memcpy(p, DXGetArrayData(na), nitems * DXGetItemSize(na));
  946. DXDelete((Object)na);
  947. return o;
  948. }