home *** CD-ROM | disk | FTP | other *** search
- return (-1);
-
- if ( px->pe == (u_int *)NULL ) {
- if (mem_info_is_on()) {
- mem_bytes(TYPE_PERM,sizeof(PERM),0);
- mem_numvar(TYPE_PERM,-1);
- }
- free((char *)px);
- }
- else
- {
- if (mem_info_is_on()) {
- mem_bytes(TYPE_PERM,sizeof(PERM)+px->max_size*sizeof(u_int),0);
- mem_numvar(TYPE_PERM,-1);
- }
- free((char *)px->pe);
- free((char *)px);
- }
-
- return (0);
- }
-
-
-
- /* v_free -- returns VEC & asoociated memory back to memory heap */
- int v_free(vec)
- VEC *vec;
- {
- if ( vec==(VEC *)NULL || (int)(vec->dim) < 0 )
- /* don't trust it */
- return (-1);
-
- if ( vec->ve == (Real *)NULL ) {
- if (mem_info_is_on()) {
- mem_bytes(TYPE_VEC,sizeof(VEC),0);
- mem_numvar(TYPE_VEC,-1);
- }
- free((char *)vec);
- }
- else
- {
- if (mem_info_is_on()) {
- mem_bytes(TYPE_VEC,sizeof(VEC)+vec->max_dim*sizeof(Real),0);
- mem_numvar(TYPE_VEC,-1);
- }
- free((char *)vec->ve);
- free((char *)vec);
- }
-
- return (0);
- }
-
-
-
- /* m_resize -- returns the matrix A of size new_m x new_n; A is zeroed
- -- if A == NULL on entry then the effect is equivalent to m_get() */
- MAT *m_resize(A,new_m,new_n)
- MAT *A;
- int new_m, new_n;
- {
- int i;
- int new_max_m, new_max_n, new_size, old_m, old_n;
-
- if (new_m < 0 || new_n < 0)
- error(E_NEG,"m_resize");
-
- if ( ! A )
- return m_get(new_m,new_n);
-
- /* nothing was changed */
- if (new_m == A->m && new_n == A->n)
- return A;
-
- old_m = A->m; old_n = A->n;
- if ( new_m > A->max_m )
- { /* re-allocate A->me */
- if (mem_info_is_on()) {
- mem_bytes(TYPE_MAT,A->max_m*sizeof(Real *),
- new_m*sizeof(Real *));
- }
-
- A->me = RENEW(A->me,new_m,Real *);
- if ( ! A->me )
- error(E_MEM,"m_resize");
- }
- new_max_m = max(new_m,A->max_m);
- new_max_n = max(new_n,A->max_n);
-
- #ifndef SEGMENTED
- new_size = new_max_m*new_max_n;
- if ( new_size > A->max_size )
- { /* re-allocate A->base */
- if (mem_info_is_on()) {
- mem_bytes(TYPE_MAT,A->max_m*A->max_n*sizeof(Real),
- new_size*sizeof(Real));
- }
-
- A->base = RENEW(A->base,new_size,Real);
- if ( ! A->base )
- error(E_MEM,"m_resize");
- A->max_size = new_size;
- }
-
- /* now set up A->me[i] */
- for ( i = 0; i < new_m; i++ )
- A->me[i] = &(A->base[i*new_n]);
-
- /* now shift data in matrix */
- if ( old_n > new_n )
- {
- for ( i = 1; i < min(old_m,new_m); i++ )
- MEM_COPY((char *)&(A->base[i*old_n]),
- (char *)&(A->base[i*new_n]),
- sizeof(Real)*new_n);
- }
- else if ( old_n < new_n )
- {
- for ( i = (int)(min(old_m,new_m))-1; i > 0; i-- )
- { /* copy & then zero extra space */
- MEM_COPY((char *)&(A->base[i*old_n]),
- (char *)&(A->base[i*new_n]),
- sizeof(Real)*old_n);
- __zero__(&(A->base[i*new_n+old_n]),(new_n-old_n));
- }
- __zero__(&(A->base[old_n]),(new_n-old_n));
- A->max_n = new_n;
- }
- /* zero out the new rows.. */
- for ( i = old_m; i < new_m; i++ )
- __zero__(&(A->base[i*new_n]),new_n);
- #else
- if ( A->max_n < new_n )
- {
- Real *tmp;
-
- for ( i = 0; i < A->max_m; i++ )
- {
- if (mem_info_ade approximation
- -- A is not changed
- -- q_out - degree of the Pade approximation (q_out,q_out)
- -- j_out - the power of 2 for scaling the matrix A
- such that ||A/2^j_out|| <= 0.5
- */
- MAT *_m_exp(A,eps,out,q_out,j_out)
- MAT *A,*out;
- double eps;
- int *q_out, *j_out;
- {
- static MAT *D = MNULL, *Apow = MNULL, *N = MNULL, *Y = MNULL;
- static VEC *c1 = VNULL, *tmp = VNULL;
- VEC y0, y1; /* additional structures */
- static PERM *pivot = PNULL;
- int j, k, l, q, r, s, j2max, t;
- double inf_norm, eqq, power2, c, sign;
-
- if ( ! A )
- error(E_SIZES,"_m_exp");
- if ( A->m != A->n )
- error(E_SIZES,"_m_exp");
- if ( A == out )
- error(E_INSITU,"_m_exp");
- if ( eps < 0.0 )
- error(E_RANGE,"_m_exp");
- else if (eps == 0.0)
- eps = MACHEPS;
-
- N = m_resize(N,A->m,A->n);
- D = m_resize(D,A->m,A->n);
- Apow = m_resize(Apow,A->m,A->n);
- out = m_resize(out,A->m,A->n);
-
- MEM_STAT_REG(N,TYPE_MAT);
- MEM_STAT_REG(D,TYPE_MAT);
- MEM_STAT_REG(Apow,TYPE_MAT);
-
- /* normalise A to have ||A||_inf <= 1 */
- inf_norm = m_norm_inf(A);
- if (inf_norm <= 0.0) {
- m_ident(out);
- *q_out = -1;
- *j_out = 0;
- return out;
- }
- else {
- j2max = floor(1+log(inf_norm)/log(2.0));
- j2max = max(0, j2max);
- }
-
- power2 = 1.0;
- for ( k = 1; k <= j2max; k++ )
- power2 *= 2;
- power2 = 1.0/power2;
- if ( j2max > 0 )
- sm_mlt(power2,A,A);
-
- /* compute order for polynomial approximation */
- eqq = 1.0/6.0;
- for ( q = 1; eqq > eps; q++ )
- eqq /= 16.0*(2.0*q+1.0)*(2.0*q+3.0);
-
- /* construct vector of coefficients */
- c1 = v_resize(c1,q+1);
- MEM_STAT_REG(c1,TYPE_VEC);
- c1->ve[0] = 1.0;
- for ( k = 1; k <= q; k++ )
- c1->ve[k] = c1->ve[k-1]*(q-k+1)/((2*q-k+1)*(double)k);
-
- tmp = v_resize(tmp,A->n);
- MEM_STAT_REG(tmp,TYPE_VEC);
-
- s = (int)floor(sqrt((double)q/2.0));
- if ( s <= 0 ) s = 1;
- _m_pow(A,s,out,Apow);
- r = q/s;
-
- Y = m_resize(Y,s,A->n);
- MEM_STAT_REG(Y,TYPE_MAT);
- /* y0 and y1 are pointers to rows of Y, N and D */
- y0.dim = y0.max_dim = A->n;
- y1.dim = y1.max_dim = A->n;
-
- m_zero(Y);
- m_zero(N);
- m_zero(D);
-
- for( j = 0; j < A->n; j++ )
- {
- if (j > 0)
- Y->me[0][j-1] = 0.0;
- y0.ve = Y->me[0];
- y0.ve[j] = 1.0;
- for ( k = 0; k < s-1; k++ )
- {
- y1.ve = Y->me[k+1];
- mv_mlt(A,&y0,&y1);
- y0.ve = y1.ve;
- }
-
- y0.ve = N->me[j];
- y1.ve = D->me[j];
- t = s*r;
- for ( l = 0; l <= q-t; l++ )
- {
- c = c1->ve[t+l];
- sign = ((t+l) & 1) ? -1.0 : 1.0;
- __mltadd__(y0.ve,Y->me[l],c, Y->n);
- __mltadd__(y1.ve,Y->me[l],c*sign,Y->n);
- }
-
- for (k=1; k <= r; k++)
- {
- v_copy(mv_mlt(Apow,&y0,tmp),&y0);
- v_copy(mv_mlt(Apow,&y1,tmp),&y1);
- t = s*(r-k);
- for (l=0; l < s; l++)
- {
- c = c1->ve[t+l];
- sign = ((t+l) & 1) ? -1.0 : 1.0;
- __mltadd__(y0.ve,Y->me[l],c, Y->n);
- __mltadd__(y1.ve,Y->me[l],c*sign,Y->n);
- }
- }
- }
-
- pivot = px_resize(pivot,A->m);
- MEM_STAT_REG(pivot,TYPE_PERM);
-
- /* note that N and D are transposed,
- therefore we use LUTsolve;
- out is saved row-wise, and must be transposed
- after this */
-
- LUfactor(D,pivot);
- for (k=0; k < A->n; k++)
- {
- y0.ve = N->me[k];
- y1.ve = out->me[k];
- LUTsolve(D,pivot,&y0,&y1);
- }
- m_transp(out,out);
-
-
- /* Use recursive squaring to turn the normalised exponential to the
- true exponential */
-
- #define Z(k) ((k) & 1 ? Apow : out)
-
- for( k = 1; k <= j2max; k++)
- m_mlt(Z(k-1),Z(k-1),Z(k));
-
- if (Z(k) == out)
- m_copy(Apow,out);
-
- /* output parameters */
- *j_out = j2max;
- *q_out = q;
-
- /* restore the matrix A */
- sm_mlt(1.0/power2,A,A);
- return out;
-
- #undef Z
- }
-
-
- /* simple interface for _m_exp */
- MAT *m_exp(A,eps,out)
- MAT *A,*out;
- double eps;
- {
- int q_out, j_out;
-
- return _m_exp(A,eps,out,&q_out,&j_out);
- }
-
-
- /*--------------------------------*/
-
- /* m_poly -- computes sum_i a[i].A^i, where i=0,1,...dim(a);
- -- uses C. Van Loan's fast and memory efficient method */
- MAT *m_poly(A,a,out)
- MAT *A,*out;
- VEC *a;
- {
- static MAT *Apow = MNULL, *Y = MNULL;
- static VEC *tmp;
- VEC y0, y1; /* additional vectors */
- int j, k, l, q, r, s, t;
-
- if ( ! A || ! a )
- error(E_NULL,"m_poly");
- if ( A->m != A->n )
- error(E_SIZES,"m_poly");
- if ( A == out )
- error(E_INSITU,"m_poly");
-
- out = m_resize(out,A->m,A->n);
- Apow = m_resize(Apow,A->m,A->n);
- MEM_STAT_REG(Apow,TYPE_MAT);
- tmp = v_resize(tmp,A->n);
- MEM_STAT_REG(tmp,TYPE_VEC);
-
- q = a->dim - 1;
- if ( q == 0 ) {
- m_zero(out);
- for (j=0; j < out->n; j++)
- out->me[j][j] = a->ve[0];
- return out;
- }
- else if ( q == 1) {
- sm_mlt(a->ve[1],A,out);
- for (j=0; j < out->n; j++)
- out->me[j][j] += a->ve[0];
- return out;
- }
-
- s = (int)floor(sqrt((double)q/2.0));
- if ( s <= 0 ) s = 1;
- _m_pow(A,s,out,Apow);
- r = q/s;
-
- Y = m_resize(Y,s,A->n);
- MEM_STAT_REG(Y,TYPE_MAT);
- /* pointers to rows of Y */
- y0.dim = y0.max_dim = A->n;
- y1.dim = y1.max_dim = A->n;
-
- m_zero(Y);
- m_zero(out);
-
- #define Z(k) ((k) & 1 ? tmp : &y0)
- #define ZZ(k) ((k) & 1 ? tmp->ve : y0.ve)
-
- for( j = 0; j < A->n; j++)
- {
- if( j > 0 )
- Y->me[0][j-1] = 0.0;
- Y->me[0][j] = 1.0;
-
- y0.ve = Y->me[0];
- for (k = 0; k < s-1; k++)
- {
- y1.ve = Y->me[k+1];
- mv_mlt(A,&y0,&y1);
- y0.ve = y1.ve;
- }
-
- y0.ve = out->me[j];
-
- t = s*r;
- for ( l = 0; l <= q-t; l++ )
- __mltadd__(y0.ve,Y->me[l],a->ve[t+l],Y->n);
-
- for (k=1; k <= r; k++)
- {
- mv_mlt(Apow,Z(k-1),Z(k));
- t = s*(r-k);
- for (l=0; l < s; l++)
- __mltadd__(ZZ(k),Y->me[l],a->ve[t+l],Y->n);
- }
- if (Z(k) == &y0) v_copy(tmp,&y0);
- }
-
- m_transp(out,out);
-
- return out;
- }
-
-
-