home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / mesch12a.zip / memory.c < prev    next >
C/C++ Source or Header  |  1994-01-13  |  21KB  |  1,008 lines

  1.  
  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.  
  26.  
  27. /* memory.c 1.3 11/25/87 */
  28.  
  29. #include     "matrix.h"
  30.  
  31.  
  32. static    char    rcsid[] = "$Id: memory.c,v 1.11 1994/01/13 05:32:32 des Exp $";
  33.  
  34. /* m_get -- gets an mxn matrix (in MAT form) by dynamic memory allocation */
  35. MAT    *m_get(m,n)
  36. int    m,n;
  37. {
  38.    MAT    *matrix;
  39.    int    i;
  40.    
  41.    if (m < 0 || n < 0)
  42.      error(E_NEG,"m_get");
  43.  
  44.    if ((matrix=NEW(MAT)) == (MAT *)NULL )
  45.      error(E_MEM,"m_get");
  46.    else if (mem_info_is_on()) {
  47.       mem_bytes(TYPE_MAT,0,sizeof(MAT));
  48.       mem_numvar(TYPE_MAT,1);
  49.    }
  50.    
  51.    matrix->m = m;        matrix->n = matrix->max_n = n;
  52.    matrix->max_m = m;    matrix->max_size = m*n;
  53. #ifndef SEGMENTED
  54.    if ((matrix->base = NEW_A(m*n,Real)) == (Real *)NULL )
  55.    {
  56.       free(matrix);
  57.       error(E_MEM,"m_get");
  58.    }
  59.    else if (mem_info_is_on()) {
  60.       mem_bytes(TYPE_MAT,0,m*n*sizeof(Real));
  61.    }
  62. #else
  63.    matrix->base = (Real *)NULL;
  64. #endif
  65.    if ((matrix->me = (Real **)calloc(m,sizeof(Real *))) == 
  66.        (Real **)NULL )
  67.    {    free(matrix);    free(matrix->base);
  68.     error(E_MEM,"m_get");
  69.      }
  70.    else if (mem_info_is_on()) {
  71.       mem_bytes(TYPE_MAT,0,m*sizeof(Real *));
  72.    }
  73.    
  74. #ifndef SEGMENTED
  75.    /* set up pointers */
  76.    for ( i=0; i<m; i++ )
  77.      matrix->me[i] = &(matrix->base[i*n]);
  78. #else
  79.    for ( i = 0; i < m; i++ )
  80.      if ( (matrix->me[i]=NEW_A(n,Real)) == (Real *)NULL )
  81.        error(E_MEM,"m_get");
  82.      else if (mem_info_is_on()) {
  83.     mem_bytes(TYPE_MAT,0,n*sizeof(Real));
  84.        }
  85. #endif
  86.    
  87.    return (matrix);
  88. }
  89.  
  90.  
  91. /* px_get -- gets a PERM of given 'size' by dynamic memory allocation
  92.    -- Note: initialized to the identity permutation */
  93. PERM    *px_get(size)
  94. int    size;
  95. {
  96.    PERM    *permute;
  97.    int    i;
  98.  
  99.    if (size < 0)
  100.      error(E_NEG,"px_get");
  101.  
  102.    if ((permute=NEW(PERM)) == (PERM *)NULL )
  103.      error(E_MEM,"px_get");
  104.    else if (mem_info_is_on()) {
  105.       mem_bytes(TYPE_PERM,0,sizeof(PERM));
  106.       mem_numvar(TYPE_PERM,1);
  107.    }
  108.    
  109.    permute->size = permute->max_size = size;
  110.    if ((permute->pe = NEW_A(size,u_int)) == (u_int *)NULL )
  111.      error(E_MEM,"px_get");
  112.    else if (mem_info_is_on()) {
  113.       mem_bytes(TYPE_PERM,0,size*sizeof(u_int));
  114.    }
  115.    
  116.    for ( i=0; i<size; i++ )
  117.      permute->pe[i] = i;
  118.    
  119.    return (permute);
  120. }
  121.  
  122. /* v_get -- gets a VEC of dimension 'dim'
  123.    -- Note: initialized to zero */
  124. VEC    *v_get(size)
  125. int    size;
  126. {
  127.    VEC    *vector;
  128.    
  129.    if (size < 0)
  130.      error(E_NEG,"v_get");
  131.  
  132.    if ((vector=NEW(VEC)) == (VEC *)NULL )
  133.      error(E_MEM,"v_get");
  134.    else if (mem_info_is_on()) {
  135.       mem_bytes(TYPE_VEC,0,sizeof(VEC));
  136.       mem_numvar(TYPE_VEC,1);
  137.    }
  138.    
  139.    vector->dim = vector->max_dim = size;
  140.    if ((vector->ve=NEW_A(size,Real)) == (Real *)NULL )
  141.    {
  142.       free(vector);
  143.       error(E_MEM,"v_get");
  144.    }
  145.    else if (mem_info_is_on()) {
  146.       mem_bytes(TYPE_VEC,0,size*sizeof(Real));
  147.    }
  148.    
  149.    return (vector);
  150. }
  151.  
  152. /* m_free -- returns MAT & asoociated memory back to memory heap */
  153. int    m_free(mat)
  154. MAT    *mat;
  155. {
  156. #ifdef SEGMENTED
  157.    int    i;
  158. #endif
  159.    
  160.    if ( mat==(MAT *)NULL || (int)(mat->m) < 0 ||
  161.        (int)(mat->n) < 0 )
  162.      /* don't trust it */
  163.      return (-1);
  164.    
  165. #ifndef SEGMENTED
  166.    if ( mat->base != (Real *)NULL ) {
  167.       if (mem_info_is_on()) {
  168.      mem_bytes(TYPE_MAT,mat->max_m*mat->max_n*sizeof(Real),0);
  169.       }
  170.       free((char *)(mat->base));
  171.    }
  172. #else
  173.    for ( i = 0; i < mat->m; i++ )
  174.      if ( mat->me[i] != (Real *)NULL ) {
  175.     if (mem_info_is_on()) {
  176.        mem_bytes(TYPE_MAT,mat->max_n*sizeof(Real),0);
  177.     }
  178.     free((char *)(mat->me[i]));
  179.      }
  180. #endif
  181.    if ( mat->me != (Real **)NULL ) {
  182.       if (mem_info_is_on()) {
  183.      mem_bytes(TYPE_MAT,mat->max_m*sizeof(Real *),0);
  184.       }
  185.       free((char *)(mat->me));
  186.    }
  187.    
  188.    if (mem_info_is_on()) {
  189.       mem_bytes(TYPE_MAT,sizeof(MAT),0);
  190.       mem_numvar(TYPE_MAT,-1);
  191.    }
  192.    free((char *)mat);
  193.    
  194.    return (0);
  195. }
  196.  
  197.  
  198.  
  199. /* px_free -- returns PERM & asoociated memory back to memory heap */
  200. int    px_free(px)
  201. PERM    *px;
  202. {
  203.    if ( px==(PERM *)NULL || (int)(px->size) < 0 )
  204.      /* don't trust it */
  205.      return (-1);
  206.    
  207.    if ( px->pe == (u_int *)NULL ) {
  208.       if (mem_info_is_on()) {
  209.      mem_bytes(TYPE_PERM,sizeof(PERM),0);
  210.      mem_numvar(TYPE_PERM,-1);
  211.       }      
  212.       free((char *)px);
  213.    }
  214.    else
  215.    {
  216.       if (mem_info_is_on()) {
  217.      mem_bytes(TYPE_PERM,sizeof(PERM)+px->max_size*sizeof(u_int),0);
  218.      mem_numvar(TYPE_PERM,-1);
  219.       }
  220.       free((char *)px->pe);
  221.       free((char *)px);
  222.    }
  223.    
  224.    return (0);
  225. }
  226.  
  227.  
  228.  
  229. /* v_free -- returns VEC & asoociated memory back to memory heap */
  230. int    v_free(vec)
  231. VEC    *vec;
  232. {
  233.    if ( vec==(VEC *)NULL || (int)(vec->dim) < 0 )
  234.      /* don't trust it */
  235.      return (-1);
  236.    
  237.    if ( vec->ve == (Real *)NULL ) {
  238.       if (mem_info_is_on()) {
  239.      mem_bytes(TYPE_VEC,sizeof(VEC),0);
  240.      mem_numvar(TYPE_VEC,-1);
  241.       }
  242.       free((char *)vec);
  243.    }
  244.    else
  245.    {
  246.       if (mem_info_is_on()) {
  247.      mem_bytes(TYPE_VEC,sizeof(VEC)+vec->max_dim*sizeof(Real),0);
  248.      mem_numvar(TYPE_VEC,-1);
  249.       }
  250.       free((char *)vec->ve);
  251.       free((char *)vec);
  252.    }
  253.    
  254.    return (0);
  255. }
  256.  
  257.  
  258.  
  259. /* m_resize -- returns the matrix A of size new_m x new_n; A is zeroed
  260.    -- if A == NULL on entry then the effect is equivalent to m_get() */
  261. MAT    *m_resize(A,new_m,new_n)
  262. MAT    *A;
  263. int    new_m, new_n;
  264. {
  265.    int    i;
  266.    int    new_max_m, new_max_n, new_size, old_m, old_n;
  267.    extern    MAT *m_zero();
  268.    
  269.    if (new_m < 0 || new_n < 0)
  270.      error(E_NEG,"m_resize");
  271.  
  272.    if ( ! A )
  273.      return m_get(new_m,new_n);
  274.  
  275.    /* nothing was changed */
  276.    if (new_m == A->m && new_n == A->n)
  277.      return A;
  278.  
  279.    old_m = A->m;    old_n = A->n;
  280.    if ( new_m > A->max_m )
  281.    {    /* re-allocate A->me */
  282.       if (mem_info_is_on()) {
  283.      mem_bytes(TYPE_MAT,A->max_m*sizeof(Real *),
  284.               new_m*sizeof(Real *));
  285.       }
  286.  
  287.       A->me = RENEW(A->me,new_m,Real *);
  288.       if ( ! A->me )
  289.     error(E_MEM,"m_resize");
  290.    }
  291.    new_max_m = max(new_m,A->max_m);
  292.    new_max_n = max(new_n,A->max_n);
  293.    
  294. #ifndef SEGMENTED
  295.    new_size = new_max_m*new_max_n;
  296.    if ( new_size > A->max_size )
  297.    {    /* re-allocate A->base */
  298.       if (mem_info_is_on()) {
  299.      mem_bytes(TYPE_MAT,A->max_m*A->max_n*sizeof(Real),
  300.               new_size*sizeof(Real));
  301.       }
  302.  
  303.       A->base = RENEW(A->base,new_size,Real);
  304.       if ( ! A->base )
  305.     error(E_MEM,"m_resize");
  306.       A->max_size = new_size;
  307.    }
  308.    
  309.    /* now set up A->me[i] */
  310.    for ( i = 0; i < new_m; i++ )
  311.      A->me[i] = &(A->base[i*new_n]);
  312.    
  313.    /* now shift data in matrix */
  314.    if ( old_n > new_n )
  315.    {
  316.       for ( i = 1; i < min(old_m,new_m); i++ )
  317.     MEM_COPY((char *)&(A->base[i*old_n]),
  318.          (char *)&(A->base[i*new_n]),
  319.          sizeof(Real)*new_n);
  320.    }
  321.    else if ( old_n < new_n )
  322.    {
  323.       for ( i = (int)(min(old_m,new_m))-1; i > 0; i-- )
  324.       {   /* copy & then zero extra space */
  325.      MEM_COPY((char *)&(A->base[i*old_n]),
  326.           (char *)&(A->base[i*new_n]),
  327.           sizeof(Real)*old_n);
  328.      __zero__(&(A->base[i*new_n+old_n]),(new_n-old_n));
  329.       }
  330.       __zero__(&(A->base[old_n]),(new_n-old_n));
  331.       A->max_n = new_n;
  332.    }
  333.    /* zero out the new rows.. */
  334.    for ( i = old_m; i < new_m; i++ )
  335.      __zero__(&(A->base[i*new_n]),new_n);
  336. #else
  337.    if ( A->max_n < new_n )
  338.    {
  339.       Real    *tmp;
  340.       
  341.       for ( i = 0; i < A->max_m; i++ )
  342.       {
  343.      if (mem_info_is_on()) {
  344.         mem_bytes(TYPE_MAT,A->max_n*sizeof(Real),
  345.              new_max_n*sizeof(Real));
  346.      }    
  347.  
  348.      if ( (tmp = RENEW(A->me[i],new_max_n,Real)) == NULL )
  349.        error(E_MEM,"m_resize");
  350.      else {    
  351.         A->me[i] = tmp;
  352.      }
  353.       }
  354.       for ( i = A->max_m; i < new_max_m; i++ )
  355.       {
  356.      if ( (tmp = NEW_A(new_max_n,Real)) == NULL )
  357.        error(E_MEM,"m_resize");
  358.      else {
  359.         A->me[i] = tmp;
  360.  
  361.         if (mem_info_is_on()) {
  362.            mem_bytes(TYPE_MAT,0,new_max_n*sizeof(Real));
  363.         }        
  364.      }
  365.       }
  366.    }
  367.    
  368.    if ( A->max_m < new_m )
  369.    {
  370.       for ( i = A->max_m; i < new_m; i++ ) 
  371.     if ( (A->me[i] = NEW_A(new_max_n,Real)) == NULL )
  372.       error(E_MEM,"m_resize");
  373.     else if (mem_info_is_on()) {
  374.        mem_bytes(TYPE_MAT,0,new_max_n*sizeof(Real));
  375.     }
  376.       
  377.    }
  378.    
  379.    if ( old_n < new_n )
  380.    {
  381.       for ( i = 0; i < old_m; i++ )
  382.     __zero__(&(A->me[i][old_n]),new_n-old_n);
  383.    }
  384.    
  385.    /* zero out the new rows.. */
  386.    for ( i = old_m; i < new_m; i++ )
  387.      __zero__(A->me[i],new_n);
  388. #endif
  389.    
  390.    A->max_m = new_max_m;
  391.    A->max_n = new_max_n;
  392.    A->max_size = A->max_m*A->max_n;
  393.    A->m = new_m;    A->n = new_n;
  394.    
  395.    return A;
  396. }
  397.  
  398. /* px_resize -- returns the permutation px with size new_size
  399.    -- px is set to the identity permutation */
  400. PERM    *px_resize(px,new_size)
  401. PERM    *px;
  402. int    new_size;
  403. {
  404.    extern PERM *px_ident();
  405.    int    i;
  406.    
  407.    if (new_size < 0)
  408.      error(E_NEG,"px_resize");
  409.  
  410.    if ( ! px )
  411.      return px_get(new_size);
  412.    
  413.    /* nothing is changed */
  414.    if (new_size == px->size)
  415.      return px;
  416.  
  417.    if ( new_size > px->max_size )
  418.    {
  419.       if (mem_info_is_on()) {
  420.      mem_bytes(TYPE_PERM,px->max_size*sizeof(u_int),
  421.               new_size*sizeof(u_int));
  422.       }
  423.       px->pe = RENEW(px->pe,new_size,u_int);
  424.       if ( ! px->pe )
  425.     error(E_MEM,"px_resize");
  426.       px->max_size = new_size;
  427.    }
  428.    if ( px->size <= new_size )
  429.      /* extend permutation */
  430.      for ( i = px->size; i < new_size; i++ )
  431.        px->pe[i] = i;
  432.    else
  433.      for ( i = 0; i < new_size; i++ )
  434.        px->pe[i] = i;
  435.    
  436.    px->size = new_size;
  437.    
  438.    return px;
  439. }
  440.  
  441. /* v_resize -- returns the vector x with dim new_dim
  442.    -- x is set to the zero vector */
  443. VEC    *v_resize(x,new_dim)
  444. VEC    *x;
  445. int    new_dim;
  446. {
  447.    extern VEC *v_zero();
  448.    
  449.    if (new_dim < 0)
  450.      error(E_NEG,"v_resize");
  451.  
  452.    if ( ! x )
  453.      return v_get(new_dim);
  454.  
  455.    /* nothing is changed */
  456.    if (new_dim == x->dim)
  457.      return x;
  458.  
  459.    if ( x->max_dim == 0 )    /* assume that it's from sub_vec */
  460.      return v_get(new_dim);
  461.    
  462.    if ( new_dim > x->max_dim )
  463.    {
  464.       if (mem_info_is_on()) { 
  465.      mem_bytes(TYPE_VEC,x->max_dim*sizeof(Real),
  466.              new_dim*sizeof(Real));
  467.       }
  468.  
  469.       x->ve = RENEW(x->ve,new_dim,Real);
  470.       if ( ! x->ve )
  471.     error(E_MEM,"v_resize");
  472.       x->max_dim = new_dim;
  473.    }
  474.    
  475.    if ( new_dim > x->dim )
  476.      __zero__(&(x->ve[x->dim]),new_dim - x->dim);
  477.    x->dim = new_dim;
  478.    
  479.    return x;
  480. }
  481.  
  482.  
  483.  
  484.  
  485. /* Varying number of arguments */
  486. /* other functions of this type are in sparse.c and zmemory.c */
  487.  
  488.  
  489.  
  490. #ifdef ANSI_C
  491.  
  492.  
  493. /* To allocate memory to many arguments. 
  494.    The function should be called:
  495.    v_get_vars(dim,&x,&y,&z,...,NULL);
  496.    where 
  497.      int dim;
  498.      VEC *x, *y, *z,...;
  499.      The last argument should be NULL ! 
  500.      dim is the length of vectors x,y,z,...
  501.      returned value is equal to the number of allocated variables
  502.      Other gec_... functions are similar.
  503. */
  504.  
  505. int v_get_vars(int dim,...) 
  506. {
  507.    va_list ap;
  508.    int i=0;
  509.    VEC **par;
  510.    
  511.    va_start(ap, dim);
  512.    while (par = va_arg(ap,VEC **)) {   /* NULL ends the list*/
  513.       *par = v_get(dim);
  514.       i++;
  515.    } 
  516.  
  517.    va_end(ap);
  518.    return i;
  519. }
  520.  
  521.  
  522. int iv_get_vars(int dim,...) 
  523. {
  524.    va_list ap;
  525.    int i=0;
  526.    IVEC **par;
  527.    
  528.    va_start(ap, dim);
  529.    while (par = va_arg(ap,IVEC **)) {   /* NULL ends the list*/
  530.       *par = iv_get(dim);
  531.       i++;
  532.    } 
  533.  
  534.    va_end(ap);
  535.    return i;
  536. }
  537.  
  538. int m_get_vars(int m,int n,...) 
  539. {
  540.    va_list ap;
  541.    int i=0;
  542.    MAT **par;
  543.    
  544.    va_start(ap, n);
  545.    while (par = va_arg(ap,MAT **)) {   /* NULL ends the list*/
  546.       *par = m_get(m,n);
  547.       i++;
  548.    } 
  549.  
  550.    va_end(ap);
  551.    return i;
  552. }
  553.  
  554. int px_get_vars(int dim,...) 
  555. {
  556.    va_list ap;
  557.    int i=0;
  558.    PERM **par;
  559.    
  560.    va_start(ap, dim);
  561.    while (par = va_arg(ap,PERM **)) {   /* NULL ends the list*/
  562.       *par = px_get(dim);
  563.       i++;
  564.    } 
  565.  
  566.    va_end(ap);
  567.    return i;
  568. }
  569.  
  570.  
  571.  
  572. /* To resize memory for many arguments. 
  573.    The function should be called:
  574.    v_resize_vars(new_dim,&x,&y,&z,...,NULL);
  575.    where 
  576.      int new_dim;
  577.      VEC *x, *y, *z,...;
  578.      The last argument should be NULL ! 
  579.      rdim is the resized length of vectors x,y,z,...
  580.      returned value is equal to the number of allocated variables.
  581.      If one of x,y,z,.. arguments is NULL then memory is allocated to this 
  582.      argument. 
  583.      Other *_resize_list() functions are similar.
  584. */
  585.  
  586. int v_resize_vars(int new_dim,...)
  587. {
  588.    va_list ap;
  589.    int i=0;
  590.    VEC **par;
  591.    
  592.    va_start(ap, new_dim);
  593.    while (par = va_arg(ap,VEC **)) {   /* NULL ends the list*/
  594.       *par = v_resize(*par,new_dim);
  595.       i++;
  596.    } 
  597.  
  598.    va_end(ap);
  599.    return i;
  600. }
  601.  
  602.  
  603.  
  604. int iv_resize_vars(int new_dim,...) 
  605. {
  606.    va_list ap;
  607.    int i=0;
  608.    IVEC **par;
  609.    
  610.    va_start(ap, new_dim);
  611.    while (par = va_arg(ap,IVEC **)) {   /* NULL ends the list*/
  612.       *par = iv_resize(*par,new_dim);
  613.       i++;
  614.    } 
  615.  
  616.    va_end(ap);
  617.    return i;
  618. }
  619.  
  620. int m_resize_vars(int m,int n,...) 
  621. {
  622.    va_list ap;
  623.    int i=0;
  624.    MAT **par;
  625.    
  626.    va_start(ap, n);
  627.    while (par = va_arg(ap,MAT **)) {   /* NULL ends the list*/
  628.       *par = m_resize(*par,m,n);
  629.       i++;
  630.    } 
  631.  
  632.    va_end(ap);
  633.    return i;
  634. }
  635.  
  636.  
  637. int px_resize_vars(int new_dim,...) 
  638. {
  639.    va_list ap;
  640.    int i=0;
  641.    PERM **par;
  642.    
  643.    va_start(ap, new_dim);
  644.    while (par = va_arg(ap,PERM **)) {   /* NULL ends the list*/
  645.       *par = px_resize(*par,new_dim);
  646.       i++;
  647.    } 
  648.  
  649.    va_end(ap);
  650.    return i;
  651. }
  652.  
  653. /* To deallocate memory for many arguments. 
  654.    The function should be called:
  655.    v_free_vars(&x,&y,&z,...,NULL);
  656.    where 
  657.      VEC *x, *y, *z,...;
  658.      The last argument should be NULL ! 
  659.      There must be at least one not NULL argument.
  660.      returned value is equal to the number of allocated variables.
  661.      Returned value of x,y,z,.. is VNULL.
  662.      Other *_free_list() functions are similar.
  663. */
  664.  
  665.  
  666. int v_free_vars(VEC **pv,...)
  667. {
  668.    va_list ap;
  669.    int i=1;
  670.    VEC **par;
  671.    
  672.    v_free(*pv);
  673.    *pv = VNULL;
  674.    va_start(ap, pv);
  675.    while (par = va_arg(ap,VEC **)) {   /* NULL ends the list*/
  676.       v_free(*par); 
  677.       *par = VNULL;
  678.       i++;
  679.    } 
  680.  
  681.    va_end(ap);
  682.    return i;
  683. }
  684.  
  685.  
  686. int iv_free_vars(IVEC **ipv,...)
  687. {
  688.    va_list ap;
  689.    int i=1;
  690.    IVEC **par;
  691.    
  692.    iv_free(*ipv);
  693.    *ipv = IVNULL;
  694.    va_start(ap, ipv);
  695.    while (par = va_arg(ap,IVEC **)) {   /* NULL ends the list*/
  696.       iv_free(*par); 
  697.       *par = IVNULL;
  698.       i++;
  699.    } 
  700.  
  701.    va_end(ap);
  702.    return i;
  703. }
  704.  
  705.  
  706. int px_free_vars(PERM **vpx,...)
  707. {
  708.    va_list ap;
  709.    int i=1;
  710.    PERM **par;
  711.    
  712.    px_free(*vpx);
  713.    *vpx = PNULL;
  714.    va_start(ap, vpx);
  715.    while (par = va_arg(ap,PERM **)) {   /* NULL ends the list*/
  716.       px_free(*par); 
  717.       *par = PNULL;
  718.       i++;
  719.    } 
  720.  
  721.    va_end(ap);
  722.    return i;
  723. }
  724.  
  725. int m_free_vars(MAT **va,...)
  726. {
  727.    va_list ap;
  728.    int i=1;
  729.    MAT **par;
  730.    
  731.    m_free(*va);
  732.    *va = MNULL;
  733.    va_start(ap, va);
  734.    while (par = va_arg(ap,MAT **)) {   /* NULL ends the list*/
  735.       m_free(*par); 
  736.       *par = MNULL;
  737.       i++;
  738.    } 
  739.  
  740.    va_end(ap);
  741.    return i;
  742. }
  743.  
  744.  
  745. #elif VARARGS
  746. /* old varargs is used */
  747.  
  748.  
  749.  
  750. /* To allocate memory to many arguments. 
  751.    The function should be called:
  752.    v_get_vars(dim,&x,&y,&z,...,VNULL);
  753.    where 
  754.      int dim;
  755.      VEC *x, *y, *z,...;
  756.      The last argument should be VNULL ! 
  757.      dim is the length of vectors x,y,z,...
  758. */
  759.  
  760. int v_get_vars(va_alist) va_dcl
  761. {
  762.    va_list ap;
  763.    int dim,i=0;
  764.    VEC **par;
  765.    
  766.    va_start(ap);
  767.    dim = va_arg(ap,int);
  768.    while (par = va_arg(ap,VEC **)) {   /* NULL ends the list*/
  769.       *par = v_get(dim);
  770.       i++;
  771.    } 
  772.  
  773.    va_end(ap);
  774.    return i;
  775. }
  776.  
  777.  
  778. int iv_get_vars(va_alist) va_dcl
  779. {
  780.    va_list ap;
  781.    int i=0, dim;
  782.    IVEC **par;
  783.    
  784.    va_start(ap);
  785.    dim = va_arg(ap,int);
  786.    while (par = va_arg(ap,IVEC **)) {   /* NULL ends the list*/
  787.       *par = iv_get(dim);
  788.       i++;
  789.    } 
  790.  
  791.    va_end(ap);
  792.    return i;
  793. }
  794.  
  795. int m_get_vars(va_alist) va_dcl
  796. {
  797.    va_list ap;
  798.    int i=0, n, m;
  799.    MAT **par;
  800.    
  801.    va_start(ap);
  802.    m = va_arg(ap,int);
  803.    n = va_arg(ap,int);
  804.    while (par = va_arg(ap,MAT **)) {   /* NULL ends the list*/
  805.       *par = m_get(m,n);
  806.       i++;
  807.    } 
  808.  
  809.    va_end(ap);
  810.    return i;
  811. }
  812.  
  813.  
  814.  
  815. int px_get_vars(va_alist) va_dcl
  816. {
  817.    va_list ap;
  818.    int i=0, dim;
  819.    PERM **par;
  820.    
  821.    va_start(ap);
  822.    dim = va_arg(ap,int);
  823.    while (par = va_arg(ap,PERM **)) {   /* NULL ends the list*/
  824.       *par = px_get(dim);
  825.       i++;
  826.    } 
  827.  
  828.    va_end(ap);
  829.    return i;
  830. }
  831.  
  832.  
  833.  
  834. /* To resize memory for many arguments. 
  835.    The function should be called:
  836.    v_resize_vars(new_dim,&x,&y,&z,...,NULL);
  837.    where 
  838.      int new_dim;
  839.      VEC *x, *y, *z,...;
  840.      The last argument should be NULL ! 
  841.      rdim is the resized length of vectors x,y,z,...
  842.      returned value is equal to the number of allocated variables.
  843.      If one of x,y,z,.. arguments is NULL then memory is allocated to this 
  844.      argument. 
  845.      Other *_resize_list() functions are similar.
  846. */
  847.  
  848. int v_resize_vars(va_alist) va_dcl
  849. {
  850.    va_list ap;
  851.    int i=0, new_dim;
  852.    VEC **par;
  853.    
  854.    va_start(ap);
  855.    new_dim = va_arg(ap,int);
  856.    while (par = va_arg(ap,VEC **)) {   /* NULL ends the list*/
  857.       *par = v_resize(*par,new_dim);
  858.       i++;
  859.    } 
  860.  
  861.    va_end(ap);
  862.    return i;
  863. }
  864.  
  865.  
  866.  
  867. int iv_resize_vars(va_alist) va_dcl
  868. {
  869.    va_list ap;
  870.    int i=0, new_dim;
  871.    IVEC **par;
  872.    
  873.    va_start(ap);
  874.    new_dim = va_arg(ap,int);
  875.    while (par = va_arg(ap,IVEC **)) {   /* NULL ends the list*/
  876.       *par = iv_resize(*par,new_dim);
  877.       i++;
  878.    } 
  879.  
  880.    va_end(ap);
  881.    return i;
  882. }
  883.  
  884. int m_resize_vars(va_alist) va_dcl
  885. {
  886.    va_list ap;
  887.    int i=0, m, n;
  888.    MAT **par;
  889.    
  890.    va_start(ap);
  891.    m = va_arg(ap,int);
  892.    n = va_arg(ap,int);
  893.    while (par = va_arg(ap,MAT **)) {   /* NULL ends the list*/
  894.       *par = m_resize(*par,m,n);
  895.       i++;
  896.    } 
  897.  
  898.    va_end(ap);
  899.    return i;
  900. }
  901.  
  902. int px_resize_vars(va_alist) va_dcl
  903. {
  904.    va_list ap;
  905.    int i=0, new_dim;
  906.    PERM **par;
  907.    
  908.    va_start(ap);
  909.    new_dim = va_arg(ap,int);
  910.    while (par = va_arg(ap,PERM **)) {   /* NULL ends the list*/
  911.       *par = px_resize(*par,new_dim);
  912.       i++;
  913.    } 
  914.  
  915.    va_end(ap);
  916.    return i;
  917. }
  918.  
  919.  
  920. /* To deallocate memory for many arguments. 
  921.    The function should be called:
  922.    v_free_vars(&x,&y,&z,...,NULL);
  923.    where 
  924.      VEC *x, *y, *z,...;
  925.      The last argument should be NULL ! 
  926.      returned value is equal to the number of allocated variables.
  927.      Returned value of x,y,z,.. is VNULL.
  928.      Other *_free_list() functions are similar.
  929. */
  930.  
  931.  
  932. int v_free_vars(va_alist) va_dcl
  933. {
  934.    va_list ap;
  935.    int i=0;
  936.    VEC **par;
  937.    
  938.    va_start(ap);
  939.    while (par = va_arg(ap,VEC **)) {   /* NULL ends the list*/
  940.       v_free(*par); 
  941.       *par = VNULL;
  942.       i++;
  943.    } 
  944.  
  945.    va_end(ap);
  946.    return i;
  947. }
  948.  
  949.  
  950.  
  951. int iv_free_vars(va_alist) va_dcl
  952. {
  953.    va_list ap;
  954.    int i=0;
  955.    IVEC **par;
  956.    
  957.    va_start(ap);
  958.    while (par = va_arg(ap,IVEC **)) {   /* NULL ends the list*/
  959.       iv_free(*par); 
  960.       *par = IVNULL;
  961.       i++;
  962.    } 
  963.  
  964.    va_end(ap);
  965.    return i;
  966. }
  967.  
  968.  
  969. int px_free_vars(va_alist) va_dcl
  970. {
  971.    va_list ap;
  972.    int i=0;
  973.    PERM **par;
  974.    
  975.    va_start(ap);
  976.    while (par = va_arg(ap,PERM **)) {   /* NULL ends the list*/
  977.       px_free(*par); 
  978.       *par = PNULL;
  979.       i++;
  980.    } 
  981.  
  982.    va_end(ap);
  983.    return i;
  984. }
  985.  
  986. int m_free_vars(va_alist) va_dcl
  987. {
  988.    va_list ap;
  989.    int i=0;
  990.    MAT **par;
  991.    
  992.    va_start(ap);
  993.    while (par = va_arg(ap,MAT **)) {   /* NULL ends the list*/
  994.       m_free(*par); 
  995.       *par = MNULL;
  996.       i++;
  997.    } 
  998.  
  999.    va_end(ap);
  1000.    return i;
  1001. }
  1002.  
  1003.  
  1004.  
  1005. #endif /* VARARGS */
  1006.   
  1007.  
  1008.