PageRenderTime 281ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/ifm-5.1/vars/src/vars-vector.c

#
C | 614 lines | 343 code | 122 blank | 149 comment | 60 complexity | 5dec51477d0d0cd07a2466a943885b26 MD5 | raw file
Possible License(s): GPL-2.0, 0BSD, LGPL-2.1
  1. /*
  2. * This file is part of the Vars library, copyright (C) Glenn
  3. * Hutchings 1996-2003.
  4. *
  5. * The Vars library comes with ABSOLUTELY NO WARRANTY. This is free
  6. * software, and you are welcome to redistribute it under certain
  7. * conditions; see the file COPYING for details.
  8. */
  9. /*!
  10. @defgroup vector Vectors
  11. @ingroup types
  12. A vector is an ordered list of floats. Once a vector is created, its
  13. size (which must be greater than zero) cannot change. Vector elements
  14. are numbered from zero.
  15. */
  16. /*!
  17. @defgroup vector_create Creating and destroying vectors
  18. @ingroup vector
  19. */
  20. /*!
  21. @defgroup vector_access Accessing vector elements
  22. @ingroup vector
  23. */
  24. /*!
  25. @defgroup vector_modify Modifying vector elements
  26. @ingroup vector
  27. */
  28. /*!
  29. @defgroup vector_misc Other vector functions
  30. @ingroup vector
  31. */
  32. #include <stdio.h>
  33. #include <string.h>
  34. #include <stdlib.h>
  35. #include <stdarg.h>
  36. #include "vars-config.h"
  37. #include "vars-macros.h"
  38. #include "vars-memory.h"
  39. #include "vars-vector.h"
  40. #define ALLOCSIZE 10
  41. /* Type definition */
  42. struct v_vector {
  43. struct v_header id; /* Type marker */
  44. unsigned int size; /* Size */
  45. float *data; /* Values */
  46. };
  47. /* Type variable */
  48. vtype *vvector_type = NULL;
  49. /* Vector freeze format */
  50. static char *freeze_format = "%g";
  51. /* No. of elements per freeze line */
  52. static int freeze_linesize = 5;
  53. /* Vector print format */
  54. static char *print_format = "%g";
  55. /* No. of elements per print line */
  56. static int print_linesize = 5;
  57. /* Internal functions */
  58. static int vv_sortpoints(const void *v1, const void *v2);
  59. /*!
  60. @brief Return a copy of a vector.
  61. @ingroup vector_create
  62. @param v Vector.
  63. @return Copy.
  64. */
  65. vvector *
  66. vv_copy(vvector *v)
  67. {
  68. vvector *copy;
  69. VV_CHECK(v);
  70. copy = vv_create_from_values(v->size, v->data);
  71. if (V_DEBUG(V_DBG_INFO))
  72. v_info("Copied %s to 0x%p", v_vinfo(v), copy);
  73. return copy;
  74. }
  75. /*!
  76. @brief Create a zeroised vector.
  77. @ingroup vector_create
  78. @param size Length of vector.
  79. @return Vector.
  80. */
  81. vvector *
  82. vv_create(unsigned int size)
  83. {
  84. return vv_create_from_values(size, NULL);
  85. }
  86. /*!
  87. @brief Create a vector from explicit values.
  88. @ingroup vector_create
  89. @param size Length of vector.
  90. @return Vector.
  91. There must be exactly \c size remaining arguments, which are the values
  92. of the vector elements.
  93. */
  94. vvector *
  95. vv_create_vector(unsigned int size, ...)
  96. {
  97. float *values;
  98. va_list ap;
  99. int i;
  100. if (size != 0)
  101. values = V_ALLOC(float, size);
  102. else
  103. v_fatal("vv_create_vector(): zero size vector");
  104. va_start(ap, size);
  105. for (i = 0; i < size; i++)
  106. values[i] = va_arg(ap, double);
  107. return vv_create_with_values(size, values);
  108. }
  109. /*!
  110. @brief Create a vector from a list.
  111. @ingroup vector_create
  112. @param list List of values.
  113. @return Vector.
  114. The vector size is the length of the list, and each element is the float
  115. value of the corresponding list element. The list must have at least one
  116. element.
  117. */
  118. vvector *
  119. vv_create_from_list(vlist *list)
  120. {
  121. unsigned int i, size;
  122. vvector *v;
  123. VL_CHECK(list);
  124. if ((size = vl_length(list)) == 0)
  125. v_fatal("vv_create_from_list(): zero length list");
  126. v = vv_create_with_values(size, NULL);
  127. for (i = 0; i < size; i++)
  128. v->data[i] = vl_fget(list, i);
  129. return v;
  130. }
  131. /*!
  132. @brief Create a vector by copying the given values.
  133. @ingroup vector_create
  134. @param size No. of values.
  135. @param values List of values.
  136. @return Vector.
  137. */
  138. vvector *
  139. vv_create_from_values(unsigned int size, float *values)
  140. {
  141. vvector *v;
  142. int i;
  143. if (size == 0)
  144. v_fatal("vv_create_from_values(): zero size vector");
  145. v = vv_create_with_values(size, NULL);
  146. for (i = 0; i < size; i++)
  147. v->data[i] = (values == NULL ? 0.0 : values[i]);
  148. return v;
  149. }
  150. /*!
  151. @brief Create a new vector using the given values.
  152. @ingroup vector_create
  153. @param size No. of values.
  154. @param values List of values (deallocated along with the vector).
  155. @return Vector.
  156. */
  157. vvector *
  158. vv_create_with_values(unsigned int size, float *values)
  159. {
  160. static vheader *id = NULL;
  161. vvector *v;
  162. if (size == 0)
  163. v_fatal("vv_create_with_values(): zero size vector");
  164. if (id == NULL) {
  165. vv_declare();
  166. id = vt_header(vvector_type);
  167. }
  168. v = V_ALLOC(vvector, 1);
  169. v->id = *id;
  170. v->size = size;
  171. if (values != NULL)
  172. v->data = values;
  173. else
  174. v->data = V_ALLOC(float, size);
  175. if (V_DEBUG(V_DBG_INFO))
  176. v_info("Created %s", v_vinfo(v));
  177. return v;
  178. }
  179. /* Declare vector type */
  180. vtype *
  181. vv_declare(void)
  182. {
  183. if (vvector_type == NULL) {
  184. vvector_type = vt_create("VECTOR", "V");
  185. vt_copy_with(vvector_type, (void *(*)()) vv_copy);
  186. vt_read_with(vvector_type, (void *(*)()) vv_fread);
  187. vt_write_with(vvector_type, vv_fwrite);
  188. vt_freeze_with(vvector_type, vv_freeze);
  189. vt_thaw_with(vvector_type, (void *(*)()) vv_thaw);
  190. vt_print_with(vvector_type, vv_print);
  191. vt_destroy_with(vvector_type, vv_destroy);
  192. vt_traverse_with(vvector_type, vv_traverse);
  193. }
  194. return vvector_type;
  195. }
  196. /*!
  197. @brief Deallocate a vector.
  198. @ingroup vector_create
  199. @param v Vector.
  200. */
  201. void
  202. vv_destroy(vvector *v)
  203. {
  204. VV_CHECK(v);
  205. if (V_DEBUG(V_DBG_INFO))
  206. v_info("Destroyed %s", v_vinfo(v));
  207. V_DEALLOC(v->data);
  208. V_DEALLOC(v);
  209. }
  210. /* Read vector from a stream */
  211. vvector *
  212. vv_fread(FILE *fp)
  213. {
  214. vvector *v;
  215. int size;
  216. /* No. of elements */
  217. if (!v_read_long(&size, fp))
  218. return NULL;
  219. /* List of floats */
  220. v = vv_create_with_values((unsigned int) size, NULL);
  221. if (!v_read_float_list(v->data, (int) size, fp)) {
  222. vv_destroy(v);
  223. return NULL;
  224. }
  225. if (V_DEBUG(V_DBG_IO))
  226. v_info("Read %s", v_vinfo(v));
  227. return v;
  228. }
  229. /* Freeze vector to a stream */
  230. int
  231. vv_freeze(vvector *v, FILE *fp)
  232. {
  233. int from = 0, to, i;
  234. VV_CHECK(v);
  235. if (V_DEBUG(V_DBG_IO))
  236. v_info("Freezing %s", v_vinfo(v));
  237. v_freeze_start(fp);
  238. fputs("{\n", fp);
  239. v_push_indent();
  240. while (from < v->size) {
  241. to = V_MIN(from + freeze_linesize, v->size);
  242. v_indent(fp);
  243. for (i = from; i < to; i++) {
  244. fprintf(fp, freeze_format, v->data[i]);
  245. fputc(',', fp);
  246. if (i < to - 1)
  247. fputc(' ', fp);
  248. else
  249. fputc('\n', fp);
  250. }
  251. from += freeze_linesize;
  252. }
  253. v_pop_indent();
  254. v_indent(fp);
  255. fputc('}', fp);
  256. v_freeze_finish(fp);
  257. return 1;
  258. }
  259. /* Set vector freeze format string */
  260. void
  261. vv_freeze_format(char *string)
  262. {
  263. freeze_format = string;
  264. }
  265. /* Set no. of elements per vector freeze line */
  266. void
  267. vv_freeze_linesize(int size)
  268. {
  269. freeze_linesize = size;
  270. }
  271. /* Write vector to a stream */
  272. int
  273. vv_fwrite(vvector *v, FILE *fp)
  274. {
  275. VV_CHECK(v);
  276. if (V_DEBUG(V_DBG_IO))
  277. v_info("Writing %s", v_vinfo(v));
  278. /* No. of elements */
  279. if (!v_write_long(v->size, fp))
  280. return 0;
  281. /* List of floats */
  282. if (!v_write_float_list(v->data, v->size, fp))
  283. return 0;
  284. return 1;
  285. }
  286. /*!
  287. @brief Get element of a vector.
  288. @ingroup vector_access
  289. @param v Vector.
  290. @param num Index entry.
  291. @return Value.
  292. */
  293. float
  294. vv_get(vvector *v, int num)
  295. {
  296. VV_CHECK(v);
  297. if (num < 0 || num >= v->size) {
  298. v_exception("vv_get(): attempt to reference invalid element (%d)",
  299. num);
  300. return 0.0;
  301. }
  302. return v->data[num];
  303. }
  304. /*!
  305. @brief Return a pointer to the values in a vector.
  306. @ingroup vector_access
  307. @param v Vector.
  308. @return List of values (don't deallocate it).
  309. */
  310. float *
  311. vv_get_values(vvector *v)
  312. {
  313. VV_CHECK(v);
  314. return v->data;
  315. }
  316. /*!
  317. @brief Return a copy of the values in a vector.
  318. @ingroup vector_access
  319. @param v Vector.
  320. @return Copy of the values.
  321. */
  322. float *
  323. vv_get_values_copy(vvector *v)
  324. {
  325. float *values;
  326. int i;
  327. VV_CHECK(v);
  328. values = V_ALLOC(float, v->size);
  329. for (i = 0; i < v->size; i++)
  330. values[i] = v->data[i];
  331. return values;
  332. }
  333. /*!
  334. @brief Return length of a vector.
  335. @ingroup vector_misc
  336. @param v Vector.
  337. @return Length.
  338. */
  339. int
  340. vv_length(vvector *v)
  341. {
  342. VV_CHECK(v);
  343. return v->size;
  344. }
  345. /* Print contents of a vector */
  346. void
  347. vv_print(vvector *v, FILE *fp)
  348. {
  349. int from = 0, to, i;
  350. VV_CHECK(v);
  351. v_print_start();
  352. v_push_indent();
  353. v_print_type(vvector_type, v, fp);
  354. while (from < v->size) {
  355. to = V_MIN(from + print_linesize, v->size);
  356. v_indent(fp);
  357. for (i = from; i < to; i++) {
  358. fprintf(fp, print_format, v->data[i]);
  359. if (i < to - 1)
  360. fputc(' ', fp);
  361. else
  362. fputc('\n', fp);
  363. }
  364. from += print_linesize;
  365. }
  366. v_pop_indent();
  367. v_print_finish();
  368. }
  369. /* Set vector print format string */
  370. void
  371. vv_print_format(char *string)
  372. {
  373. print_format = string;
  374. }
  375. /* Set no. of elements per vector print line */
  376. void
  377. vv_print_linesize(int size)
  378. {
  379. print_linesize = size;
  380. }
  381. /*!
  382. @brief Sort vector values in ascending order.
  383. @ingroup vector_misc
  384. @param v Vector.
  385. */
  386. void
  387. vv_sort(vvector *v)
  388. {
  389. if (v->size > 1)
  390. qsort(v->data, v->size, sizeof(float), vv_sortpoints);
  391. }
  392. /* Point sorting function */
  393. static int
  394. vv_sortpoints(const void *v1, const void *v2)
  395. {
  396. float *p1 = (float *) v1;
  397. float *p2 = (float *) v2;
  398. /* Sort on X values */
  399. return ((*p1) < (*p2)) ? -1 : 1;
  400. }
  401. /*!
  402. @brief Set vector element to a given value.
  403. @ingroup vector_modify
  404. @param v Vector
  405. @param num Index entry.
  406. @param val Value to set.
  407. */
  408. void
  409. vv_store(vvector *v, int num, float val)
  410. {
  411. VV_CHECK(v);
  412. if (num < 0 || num >= v->size) {
  413. v_exception("vv_store(): attempt to reference invalid element (%d)",
  414. num);
  415. return;
  416. }
  417. v->data[num] = val;
  418. }
  419. /*!
  420. @brief Set all vector elements to the given values.
  421. @ingroup vector_modify
  422. @param v Vector.
  423. @param values List of values to set.
  424. */
  425. void
  426. vv_store_values(vvector *v, float *values)
  427. {
  428. int i;
  429. VV_CHECK(v);
  430. for (i = 0; i < v->size; i++)
  431. v->data[i] = (values == NULL ? 0.0 : values[i]);
  432. }
  433. /* Thaw vector from a stream */
  434. vvector *
  435. vv_thaw(FILE *fp)
  436. {
  437. static int allocsize = ALLOCSIZE;
  438. static float *values = NULL;
  439. int token, count = 0;
  440. double value;
  441. vvector *v;
  442. v_thaw_start();
  443. if (!v_thaw_follow(fp, '{', "open-brace"))
  444. goto fail;
  445. if (values == NULL)
  446. values = V_ALLOC(float, allocsize);
  447. while (1) {
  448. if (v_thaw_peek(fp) == '}') {
  449. v_thaw_token(fp);
  450. break;
  451. }
  452. if (!v_thaw_double(fp, &value))
  453. goto fail;
  454. values[count] = value;
  455. if (++count == allocsize) {
  456. allocsize *= 2;
  457. values = V_REALLOC(values, float, allocsize);
  458. }
  459. if ((token = v_thaw_token(fp)) == '}') {
  460. break;
  461. } else if (token != ',') {
  462. v_thaw_expected("comma or close-brace");
  463. goto fail;
  464. }
  465. }
  466. v_thaw_finish();
  467. if (count == 0) {
  468. v_thaw_err("vector has no elements");
  469. goto fail;
  470. }
  471. v = vv_create_from_values(count, values);
  472. if (V_DEBUG(V_DBG_IO))
  473. v_info("Thawed %s", v_vinfo(v));
  474. return v;
  475. fail:
  476. v_thaw_finish();
  477. return NULL;
  478. }
  479. /* Traverse a vector */
  480. int
  481. vv_traverse(vvector *v, int (*func)())
  482. {
  483. VV_CHECK(v);
  484. if ((*func)(v))
  485. return 1;
  486. v_push_traverse(v);
  487. v_pop_traverse();
  488. return 0;
  489. }