PageRenderTime 53ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/src/mesch/zmemory.c

https://bitbucket.org/nrnhines/nrn
C | 714 lines | 469 code | 130 blank | 115 comment | 114 complexity | a42b0b16b460c0356e8b9bcfd2df272c MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0
  1. #include <../../nrnconf.h>
  2. /**************************************************************************
  3. **
  4. ** Copyright (C) 1993 David E. Steward & Zbigniew Leyk, all rights reserved.
  5. **
  6. ** Meschach Library
  7. **
  8. ** This Meschach Library is provided "as is" without any express
  9. ** or implied warranty of any kind with respect to this software.
  10. ** In particular the authors shall not be liable for any direct,
  11. ** indirect, special, incidental or consequential damages arising
  12. ** in any way from use of the software.
  13. **
  14. ** Everyone is granted permission to copy, modify and redistribute this
  15. ** Meschach Library, provided:
  16. ** 1. All copies contain this copyright notice.
  17. ** 2. All modified copies shall carry a notice stating who
  18. ** made the last modification and the date of such modification.
  19. ** 3. No charge is made for this software or works derived from it.
  20. ** This clause shall not be construed as constraining other software
  21. ** distributed on the same medium as this software, nor is a
  22. ** distribution fee considered a charge.
  23. **
  24. ***************************************************************************/
  25. /* Memory allocation and de-allocation for complex matrices and vectors */
  26. #include <stdio.h>
  27. #include "zmatrix.h"
  28. static char rcsid[] = "zmemory.c,v 1.1 1997/12/04 17:56:13 hines Exp";
  29. /* zv_zero -- zeros all entries of a complex vector
  30. -- uses __zzero__() */
  31. ZVEC *zv_zero(x)
  32. ZVEC *x;
  33. {
  34. if ( ! x )
  35. error(E_NULL,"zv_zero");
  36. __zzero__(x->ve,x->dim);
  37. return x;
  38. }
  39. /* zm_zero -- zeros all entries of a complex matrix
  40. -- uses __zzero__() */
  41. ZMAT *zm_zero(A)
  42. ZMAT *A;
  43. {
  44. int i;
  45. if ( ! A )
  46. error(E_NULL,"zm_zero");
  47. for ( i = 0; i < A->m; i++ )
  48. __zzero__(A->me[i],A->n);
  49. return A;
  50. }
  51. /* zm_get -- gets an mxn complex matrix (in ZMAT form) */
  52. ZMAT *zm_get(m,n)
  53. int m,n;
  54. {
  55. ZMAT *matrix;
  56. u_int i;
  57. if (m < 0 || n < 0)
  58. error(E_NEG,"zm_get");
  59. if ((matrix=NEW(ZMAT)) == (ZMAT *)NULL )
  60. error(E_MEM,"zm_get");
  61. else if (mem_info_is_on()) {
  62. mem_bytes(TYPE_ZMAT,0,sizeof(ZMAT));
  63. mem_numvar(TYPE_ZMAT,1);
  64. }
  65. matrix->m = m; matrix->n = matrix->max_n = n;
  66. matrix->max_m = m; matrix->max_size = m*n;
  67. #ifndef SEGMENTED
  68. if ((matrix->base = NEW_A(m*n,complex)) == (complex *)NULL )
  69. {
  70. free(matrix);
  71. error(E_MEM,"zm_get");
  72. }
  73. else if (mem_info_is_on()) {
  74. mem_bytes(TYPE_ZMAT,0,m*n*sizeof(complex));
  75. }
  76. #else
  77. matrix->base = (complex *)NULL;
  78. #endif
  79. if ((matrix->me = (complex **)calloc(m,sizeof(complex *))) ==
  80. (complex **)NULL )
  81. { free(matrix->base); free(matrix);
  82. error(E_MEM,"zm_get");
  83. }
  84. else if (mem_info_is_on()) {
  85. mem_bytes(TYPE_ZMAT,0,m*sizeof(complex *));
  86. }
  87. #ifndef SEGMENTED
  88. /* set up pointers */
  89. for ( i=0; i<m; i++ )
  90. matrix->me[i] = &(matrix->base[i*n]);
  91. #else
  92. for ( i = 0; i < m; i++ )
  93. if ( (matrix->me[i]=NEW_A(n,complex)) == (complex *)NULL )
  94. error(E_MEM,"zm_get");
  95. else if (mem_info_is_on()) {
  96. mem_bytes(TYPE_ZMAT,0,n*sizeof(complex));
  97. }
  98. #endif
  99. return (matrix);
  100. }
  101. /* zv_get -- gets a ZVEC of dimension 'dim'
  102. -- Note: initialized to zero */
  103. ZVEC *zv_get(size)
  104. int size;
  105. {
  106. ZVEC *vector;
  107. if (size < 0)
  108. error(E_NEG,"zv_get");
  109. if ((vector=NEW(ZVEC)) == (ZVEC *)NULL )
  110. error(E_MEM,"zv_get");
  111. else if (mem_info_is_on()) {
  112. mem_bytes(TYPE_ZVEC,0,sizeof(ZVEC));
  113. mem_numvar(TYPE_ZVEC,1);
  114. }
  115. vector->dim = vector->max_dim = size;
  116. if ((vector->ve=NEW_A(size,complex)) == (complex *)NULL )
  117. {
  118. free(vector);
  119. error(E_MEM,"zv_get");
  120. }
  121. else if (mem_info_is_on()) {
  122. mem_bytes(TYPE_ZVEC,0,size*sizeof(complex));
  123. }
  124. return (vector);
  125. }
  126. /* zm_free -- returns ZMAT & asoociated memory back to memory heap */
  127. int zm_free(mat)
  128. ZMAT *mat;
  129. {
  130. #ifdef SEGMENTED
  131. int i;
  132. #endif
  133. if ( mat==(ZMAT *)NULL || (int)(mat->m) < 0 ||
  134. (int)(mat->n) < 0 )
  135. /* don't trust it */
  136. return (-1);
  137. #ifndef SEGMENTED
  138. if ( mat->base != (complex *)NULL ) {
  139. if (mem_info_is_on()) {
  140. mem_bytes(TYPE_ZMAT,mat->max_m*mat->max_n*sizeof(complex),0);
  141. }
  142. free((char *)(mat->base));
  143. }
  144. #else
  145. for ( i = 0; i < mat->max_m; i++ )
  146. if ( mat->me[i] != (complex *)NULL ) {
  147. if (mem_info_is_on()) {
  148. mem_bytes(TYPE_ZMAT,mat->max_n*sizeof(complex),0);
  149. }
  150. free((char *)(mat->me[i]));
  151. }
  152. #endif
  153. if ( mat->me != (complex **)NULL ) {
  154. if (mem_info_is_on()) {
  155. mem_bytes(TYPE_ZMAT,mat->max_m*sizeof(complex *),0);
  156. }
  157. free((char *)(mat->me));
  158. }
  159. if (mem_info_is_on()) {
  160. mem_bytes(TYPE_ZMAT,sizeof(ZMAT),0);
  161. mem_numvar(TYPE_ZMAT,-1);
  162. }
  163. free((char *)mat);
  164. return (0);
  165. }
  166. /* zv_free -- returns ZVEC & asoociated memory back to memory heap */
  167. int zv_free(vec)
  168. ZVEC *vec;
  169. {
  170. if ( vec==(ZVEC *)NULL || (int)(vec->dim) < 0 )
  171. /* don't trust it */
  172. return (-1);
  173. if ( vec->ve == (complex *)NULL ) {
  174. if (mem_info_is_on()) {
  175. mem_bytes(TYPE_ZVEC,sizeof(ZVEC),0);
  176. mem_numvar(TYPE_ZVEC,-1);
  177. }
  178. free((char *)vec);
  179. }
  180. else
  181. {
  182. if (mem_info_is_on()) {
  183. mem_bytes(TYPE_ZVEC,vec->max_dim*sizeof(complex)+
  184. sizeof(ZVEC),0);
  185. mem_numvar(TYPE_ZVEC,-1);
  186. }
  187. free((char *)vec->ve);
  188. free((char *)vec);
  189. }
  190. return (0);
  191. }
  192. /* zm_resize -- returns the matrix A of size new_m x new_n; A is zeroed
  193. -- if A == NULL on entry then the effect is equivalent to m_get() */
  194. ZMAT *zm_resize(A,new_m,new_n)
  195. ZMAT *A;
  196. int new_m, new_n;
  197. {
  198. u_int i, new_max_m, new_max_n, new_size, old_m, old_n;
  199. if (new_m < 0 || new_n < 0)
  200. error(E_NEG,"zm_resize");
  201. if ( ! A )
  202. return zm_get(new_m,new_n);
  203. if (new_m == A->m && new_n == A->n)
  204. return A;
  205. old_m = A->m; old_n = A->n;
  206. if ( new_m > A->max_m )
  207. { /* re-allocate A->me */
  208. if (mem_info_is_on()) {
  209. mem_bytes(TYPE_ZMAT,A->max_m*sizeof(complex *),
  210. new_m*sizeof(complex *));
  211. }
  212. A->me = RENEW(A->me,new_m,complex *);
  213. if ( ! A->me )
  214. error(E_MEM,"zm_resize");
  215. }
  216. new_max_m = max(new_m,A->max_m);
  217. new_max_n = max(new_n,A->max_n);
  218. #ifndef SEGMENTED
  219. new_size = new_max_m*new_max_n;
  220. if ( new_size > A->max_size )
  221. { /* re-allocate A->base */
  222. if (mem_info_is_on()) {
  223. mem_bytes(TYPE_ZMAT,A->max_m*A->max_n*sizeof(complex),
  224. new_size*sizeof(complex));
  225. }
  226. A->base = RENEW(A->base,new_size,complex);
  227. if ( ! A->base )
  228. error(E_MEM,"zm_resize");
  229. A->max_size = new_size;
  230. }
  231. /* now set up A->me[i] */
  232. for ( i = 0; i < new_m; i++ )
  233. A->me[i] = &(A->base[i*new_n]);
  234. /* now shift data in matrix */
  235. if ( old_n > new_n )
  236. {
  237. for ( i = 1; i < min(old_m,new_m); i++ )
  238. MEM_COPY((char *)&(A->base[i*old_n]),
  239. (char *)&(A->base[i*new_n]),
  240. sizeof(complex)*new_n);
  241. }
  242. else if ( old_n < new_n )
  243. {
  244. for ( i = min(old_m,new_m)-1; i > 0; i-- )
  245. { /* copy & then zero extra space */
  246. MEM_COPY((char *)&(A->base[i*old_n]),
  247. (char *)&(A->base[i*new_n]),
  248. sizeof(complex)*old_n);
  249. __zzero__(&(A->base[i*new_n+old_n]),(new_n-old_n));
  250. }
  251. __zzero__(&(A->base[old_n]),(new_n-old_n));
  252. A->max_n = new_n;
  253. }
  254. /* zero out the new rows.. */
  255. for ( i = old_m; i < new_m; i++ )
  256. __zzero__(&(A->base[i*new_n]),new_n);
  257. #else
  258. if ( A->max_n < new_n )
  259. {
  260. complex *tmp;
  261. for ( i = 0; i < A->max_m; i++ )
  262. {
  263. if (mem_info_is_on()) {
  264. mem_bytes(TYPE_ZMAT,A->max_n*sizeof(complex),
  265. new_max_n*sizeof(complex));
  266. }
  267. if ( (tmp = RENEW(A->me[i],new_max_n,complex)) == NULL )
  268. error(E_MEM,"zm_resize");
  269. else {
  270. A->me[i] = tmp;
  271. }
  272. }
  273. for ( i = A->max_m; i < new_max_m; i++ )
  274. {
  275. if ( (tmp = NEW_A(new_max_n,complex)) == NULL )
  276. error(E_MEM,"zm_resize");
  277. else {
  278. A->me[i] = tmp;
  279. if (mem_info_is_on()) {
  280. mem_bytes(TYPE_ZMAT,0,new_max_n*sizeof(complex));
  281. }
  282. }
  283. }
  284. }
  285. else if ( A->max_m < new_m )
  286. {
  287. for ( i = A->max_m; i < new_m; i++ )
  288. if ( (A->me[i] = NEW_A(new_max_n,complex)) == NULL )
  289. error(E_MEM,"zm_resize");
  290. else if (mem_info_is_on()) {
  291. mem_bytes(TYPE_ZMAT,0,new_max_n*sizeof(complex));
  292. }
  293. }
  294. if ( old_n < new_n )
  295. {
  296. for ( i = 0; i < old_m; i++ )
  297. __zzero__(&(A->me[i][old_n]),new_n-old_n);
  298. }
  299. /* zero out the new rows.. */
  300. for ( i = old_m; i < new_m; i++ )
  301. __zzero__(A->me[i],new_n);
  302. #endif
  303. A->max_m = new_max_m;
  304. A->max_n = new_max_n;
  305. A->max_size = A->max_m*A->max_n;
  306. A->m = new_m; A->n = new_n;
  307. return A;
  308. }
  309. /* zv_resize -- returns the (complex) vector x with dim new_dim
  310. -- x is set to the zero vector */
  311. ZVEC *zv_resize(x,new_dim)
  312. ZVEC *x;
  313. int new_dim;
  314. {
  315. if (new_dim < 0)
  316. error(E_NEG,"zv_resize");
  317. if ( ! x )
  318. return zv_get(new_dim);
  319. if (new_dim == x->dim)
  320. return x;
  321. if ( x->max_dim == 0 ) /* assume that it's from sub_zvec */
  322. return zv_get(new_dim);
  323. if ( new_dim > x->max_dim )
  324. {
  325. if (mem_info_is_on()) {
  326. mem_bytes(TYPE_ZVEC,x->max_dim*sizeof(complex),
  327. new_dim*sizeof(complex));
  328. }
  329. x->ve = RENEW(x->ve,new_dim,complex);
  330. if ( ! x->ve )
  331. error(E_MEM,"zv_resize");
  332. x->max_dim = new_dim;
  333. }
  334. if ( new_dim > x->dim )
  335. __zzero__(&(x->ve[x->dim]),new_dim - x->dim);
  336. x->dim = new_dim;
  337. return x;
  338. }
  339. /* varying arguments */
  340. #ifdef ANSI_C
  341. #include <stdarg.h>
  342. /* To allocate memory to many arguments.
  343. The function should be called:
  344. zv_get_vars(dim,&x,&y,&z,...,NULL);
  345. where
  346. int dim;
  347. ZVEC *x, *y, *z,...;
  348. The last argument should be NULL !
  349. dim is the length of vectors x,y,z,...
  350. returned value is equal to the number of allocated variables
  351. Other gec_... functions are similar.
  352. */
  353. int zv_get_vars(int dim,...)
  354. {
  355. va_list ap;
  356. int i=0;
  357. ZVEC **par;
  358. va_start(ap, dim);
  359. while ((par = va_arg(ap,ZVEC **))) { /* NULL ends the list*/
  360. *par = zv_get(dim);
  361. i++;
  362. }
  363. va_end(ap);
  364. return i;
  365. }
  366. int zm_get_vars(int m,int n,...)
  367. {
  368. va_list ap;
  369. int i=0;
  370. ZMAT **par;
  371. va_start(ap, n);
  372. while ((par = va_arg(ap,ZMAT **))) { /* NULL ends the list*/
  373. *par = zm_get(m,n);
  374. i++;
  375. }
  376. va_end(ap);
  377. return i;
  378. }
  379. /* To resize memory for many arguments.
  380. The function should be called:
  381. v_resize_vars(new_dim,&x,&y,&z,...,NULL);
  382. where
  383. int new_dim;
  384. ZVEC *x, *y, *z,...;
  385. The last argument should be NULL !
  386. rdim is the resized length of vectors x,y,z,...
  387. returned value is equal to the number of allocated variables.
  388. If one of x,y,z,.. arguments is NULL then memory is allocated to this
  389. argument.
  390. Other *_resize_list() functions are similar.
  391. */
  392. int zv_resize_vars(int new_dim,...)
  393. {
  394. va_list ap;
  395. int i=0;
  396. ZVEC **par;
  397. va_start(ap, new_dim);
  398. while ((par = va_arg(ap,ZVEC **))) { /* NULL ends the list*/
  399. *par = zv_resize(*par,new_dim);
  400. i++;
  401. }
  402. va_end(ap);
  403. return i;
  404. }
  405. int zm_resize_vars(int m,int n,...)
  406. {
  407. va_list ap;
  408. int i=0;
  409. ZMAT **par;
  410. va_start(ap, n);
  411. while ((par = va_arg(ap,ZMAT **))) { /* NULL ends the list*/
  412. *par = zm_resize(*par,m,n);
  413. i++;
  414. }
  415. va_end(ap);
  416. return i;
  417. }
  418. /* To deallocate memory for many arguments.
  419. The function should be called:
  420. v_free_vars(&x,&y,&z,...,NULL);
  421. where
  422. ZVEC *x, *y, *z,...;
  423. The last argument should be NULL !
  424. There must be at least one not NULL argument.
  425. returned value is equal to the number of allocated variables.
  426. Returned value of x,y,z,.. is VNULL.
  427. Other *_free_list() functions are similar.
  428. */
  429. int zv_free_vars(ZVEC **pv,...)
  430. {
  431. va_list ap;
  432. int i=1;
  433. ZVEC **par;
  434. zv_free(*pv);
  435. *pv = ZVNULL;
  436. va_start(ap, pv);
  437. while ((par = va_arg(ap,ZVEC **))) { /* NULL ends the list*/
  438. zv_free(*par);
  439. *par = ZVNULL;
  440. i++;
  441. }
  442. va_end(ap);
  443. return i;
  444. }
  445. int zm_free_vars(ZMAT **va,...)
  446. {
  447. va_list ap;
  448. int i=1;
  449. ZMAT **par;
  450. zm_free(*va);
  451. *va = ZMNULL;
  452. va_start(ap, va);
  453. while ((par = va_arg(ap,ZMAT **))) { /* NULL ends the list*/
  454. zm_free(*par);
  455. *par = ZMNULL;
  456. i++;
  457. }
  458. va_end(ap);
  459. return i;
  460. }
  461. #elif VARARGS
  462. #include <varargs.h>
  463. /* To allocate memory to many arguments.
  464. The function should be called:
  465. v_get_vars(dim,&x,&y,&z,...,NULL);
  466. where
  467. int dim;
  468. ZVEC *x, *y, *z,...;
  469. The last argument should be NULL !
  470. dim is the length of vectors x,y,z,...
  471. returned value is equal to the number of allocated variables
  472. Other gec_... functions are similar.
  473. */
  474. int zv_get_vars(va_alist) va_dcl
  475. {
  476. va_list ap;
  477. int dim,i=0;
  478. ZVEC **par;
  479. va_start(ap);
  480. dim = va_arg(ap,int);
  481. while ((par = va_arg(ap,ZVEC **))) { /* NULL ends the list*/
  482. *par = zv_get(dim);
  483. i++;
  484. }
  485. va_end(ap);
  486. return i;
  487. }
  488. int zm_get_vars(va_alist) va_dcl
  489. {
  490. va_list ap;
  491. int i=0, n, m;
  492. ZMAT **par;
  493. va_start(ap);
  494. m = va_arg(ap,int);
  495. n = va_arg(ap,int);
  496. while ((par = va_arg(ap,ZMAT **))) { /* NULL ends the list*/
  497. *par = zm_get(m,n);
  498. i++;
  499. }
  500. va_end(ap);
  501. return i;
  502. }
  503. /* To resize memory for many arguments.
  504. The function should be called:
  505. v_resize_vars(new_dim,&x,&y,&z,...,NULL);
  506. where
  507. int new_dim;
  508. ZVEC *x, *y, *z,...;
  509. The last argument should be NULL !
  510. rdim is the resized length of vectors x,y,z,...
  511. returned value is equal to the number of allocated variables.
  512. If one of x,y,z,.. arguments is NULL then memory is allocated to this
  513. argument.
  514. Other *_resize_list() functions are similar.
  515. */
  516. int zv_resize_vars(va_alist) va_dcl
  517. {
  518. va_list ap;
  519. int i=0, new_dim;
  520. ZVEC **par;
  521. va_start(ap);
  522. new_dim = va_arg(ap,int);
  523. while ((par = va_arg(ap,ZVEC **))) { /* NULL ends the list*/
  524. *par = zv_resize(*par,new_dim);
  525. i++;
  526. }
  527. va_end(ap);
  528. return i;
  529. }
  530. int zm_resize_vars(va_alist) va_dcl
  531. {
  532. va_list ap;
  533. int i=0, m, n;
  534. ZMAT **par;
  535. va_start(ap);
  536. m = va_arg(ap,int);
  537. n = va_arg(ap,int);
  538. while ((par = va_arg(ap,ZMAT **))) { /* NULL ends the list*/
  539. *par = zm_resize(*par,m,n);
  540. i++;
  541. }
  542. va_end(ap);
  543. return i;
  544. }
  545. /* To deallocate memory for many arguments.
  546. The function should be called:
  547. v_free_vars(&x,&y,&z,...,NULL);
  548. where
  549. ZVEC *x, *y, *z,...;
  550. The last argument should be NULL !
  551. There must be at least one not NULL argument.
  552. returned value is equal to the number of allocated variables.
  553. Returned value of x,y,z,.. is VNULL.
  554. Other *_free_list() functions are similar.
  555. */
  556. int zv_free_vars(va_alist) va_dcl
  557. {
  558. va_list ap;
  559. int i=0;
  560. ZVEC **par;
  561. va_start(ap);
  562. while ((par = va_arg(ap,ZVEC **))) { /* NULL ends the list*/
  563. zv_free(*par);
  564. *par = ZVNULL;
  565. i++;
  566. }
  567. va_end(ap);
  568. return i;
  569. }
  570. int zm_free_vars(va_alist) va_dcl
  571. {
  572. va_list ap;
  573. int i=0;
  574. ZMAT **par;
  575. va_start(ap);
  576. while ((par = va_arg(ap,ZMAT **))) { /* NULL ends the list*/
  577. zm_free(*par);
  578. *par = ZMNULL;
  579. i++;
  580. }
  581. va_end(ap);
  582. return i;
  583. }
  584. #endif