int free_desc( struct HOST_DESC * desc, int freedescfilename, struct CONN * conn ) /* frees the host descriptor and closes the file */ { struct FRAGMENT * tmp; if( desc->file ) { fclose( desc->file ); if (flags.writer.type == UNIQUE) desc->oth->file = NULL; struct timeval t[2] = { conn->firsttime, conn->firsttime }; utimes( desc->filename, t ); } if( desc->filename && freedescfilename ) { S_free( desc->filename ); desc->filename = NULL; } if( desc->lockfilename ) { unlink( desc->lockfilename ); S_free( desc->lockfilename ); desc->lockfilename = NULL; } while( desc->unack ) { /* FIXME: desc->unack should be just NULL when closes! * I should check it! */ S_free( desc->unack->payload ); desc->unack->payload = NULL; tmp = desc->unack; desc->unack = desc->unack->next; S_free( tmp ); } }
void StringPair_free(StringPair* p) { S_free(p->key); S_free(p->value); cx_free(p); }
int display_status( FILE * out, struct CONN * conn, enum STATUS status ) /* display a "status banner" */ { char *client_name; char *server_name; char *s_time; char *status_string; if ( flags.notstatus ) { /* FIXME: sucks! and what if out will be a file? */ return 0; } client_name=(char *)lookup(conn->client.ip); s_time = (char *)S_calloc( 128, 1 ); if( time_ascii( s_time ) ) color( c_TIME, out,"%-16s ",s_time ); /* FIXME: check */ color( c_NUMBERING, out,"%-6d ",conn->num ); S_free ( s_time ); status_string = status2str( status ); color( _STATUS_COLOR(status), out,"%-14s",status_string ); S_free( status_string ); color( c_CLIENTNAME_STATUS, out, " %s:%s ", client_name, getportname(conn->client.port) ); color( _STATUS_COLOR(status), out,"> " ); server_name=(char *)lookup(conn->server.ip); color( c_SERVERNAME_STATUS, out,"%s", server_name ); fprintf( out,":" ); color( c_SERVICE, out,"%s", getportname(conn->server.port) ); fprintf( out, "\n" ); fflush( out ); }
int rmconn( struct CONN * prev_ring ) /* removes from the linked-list and deallocates a connection * prev_ring */ { struct CONN * curr = prev_ring->next; struct CONN * conn; prev_ring->next = curr->next; if( curr->next == NULL ) last_conn = prev_ring; free_desc( &(curr->client), 1, curr); if (flags.writer.type == UNIQUE) free_desc( &(curr->server), 0, curr); else free_desc( &(curr->server), 1, curr); S_free( curr ); conn = first_conn; if( flags.exitclosed ) { if( flags.exitclosed_first ) { /* -Ef */ while( conn->num > flags.exitclosed ) { if(! (conn->next) ) exit( EXIT_SUCCESS ); conn = conn->next; } } else { /* -E */ --flags.exitclosed; if( flags.exitclosed == 0) exit( EXIT_SUCCESS ); } } if( flags.trackonly && (! flags.trackonly_first) ) count_opened--; }
int main(int argc, char* argv[]) { int c; int n, t; stable_t *S; /* * default values for args */ while ( (c=getopt(argc, argv,"ha:N:T:"))>=0 ) { switch ( c ) { case 'a': if ( !optarg || sscanf(optarg,"%f",&apar)!=1 ) yaps_quit("Need a valid 'a' argument\n"); break; case 'N': if ( !optarg || sscanf(optarg,"%d",&N)!=1 ) yaps_quit("Need a valid 'N' argument\n"); break; case 'T': if ( !optarg || sscanf(optarg,"%d",&T)!=1 ) yaps_quit("Need a valid 'T' argument\n"); break; case 'h': usage(); exit(0); } } if ( T>N ) T = N; if ( !(S=S_make(N+1,T,2*N,2*T,apar,S_UVTABLE|S_STABLE|S_VERBOSE)) ) yaps_quit("S_make failed\n"); S_report(S, stdout); #if 1 /* * list various values */ printf("S(%d,%d) = %10.6lg, V=n/a U=%lg\n", N, 1, S_S(S,N,1), S_U(S,N,1)); for (t=2; t<=T; t++) printf("S(%d,%d) = %10.6lg, V=%lg U=%lg\n", N, t, S_S(S,N,t), S_V(S,N,t), S_U(S,N,t)); printf("\nS(%d,%d) = %10.6lg, V=n/a U=%lg\n", N+10, 1, S_S(S,N+10,1), S_U(S,N+10,1)); for (t=2; t<=2*T+10; t++) printf("S(%d,%d) = %10.6lg, V=%lg U=%lg\n", N+10, t, S_S(S,N+10,t), S_V(S,N+10,t), S_U(S,N+10,t)); for (n=T+1; n<=2*N; n++) printf("S(%d,%d..) = %10.6lg %10.6lg\n", n, T, S_S(S,n,T), S_S(S,n,T+1)); for (n=2; n<8; n++ ) { printf("S(%d,%d) = %10.6lg ", n, 1, S_S(S,n,1)); for (t=2; t<=n; t++) printf(" %10.6lg", S_S(S,n,t)); printf("\n"); } for (n=2; n<8; n++ ) { printf("V(%d,%d) = %10.6lg", n, 2, S_V(S,n,2)); for (t=3; t<=n; t++) printf(" %10.6lg", S_V(S,n,t)); printf("\n"); } for (n=2; n<8; n++ ) { printf("U(%d,%d) = %10.6lg", n, 2, S_U(S,n,2)); for (t=3; t<=n; t++) printf(" %10.6lg", S_U(S,n,t)); printf("\n"); } #else { /* * Sample a partition of size T of N by Chinese Rest. distribution * start by sampling the last entry from (1,2,...,N-T+1); * see p(m | CRD, apr, N, T) on page 4 of "doc/alpha.pdf" */ double *prob = malloc(sizeof(*prob)*N); double probtot = 1.0; prob[1] = 1.0; for (t=2; t<=N-T+1; t++) probtot += prob[t] = (N-t+1)*(t-apar) / S_U(S,N-t,T-1)/(t-1) * prob[t-1]; for (t=1; t<=N-T+1; t++) printf("p(m=%d) = %lg\n", t, prob[t]/probtot ); } #endif S_report(S, stdout); S_free(S); return 0; }
/* * use prior a is uniform */ double samplea2(double mya, stable_t *S, int I, int *K, scnt_int *T, scnt_int **n, stcnt_int **t, void (*getval)(scnt_int *n, stcnt_int *t, unsigned i, unsigned k), double *bpar, rngp_t rng, int loops, int verbose) { double inita[3] = {A_MIN,1,A_MAX}; int i, k; ALData ald; stcnt_int *mp; int n_m = 0; inita[1] = mya; if ( fabs(inita[1]-A_MAX)/A_MAX<0.00001 ) { inita[1] = A_MAX*0.999 + A_MIN*0.001; } if ( fabs(inita[1]-A_MIN)/A_MIN<0.00001 ) { inita[1] = A_MIN*0.999 + A_MAX*0.001; } #ifdef SQUEEZEA /* * bound current move to be less than SQEEZEA */ if ( inita[1]-SQUEEZEA>A_MIN ) inita[0] = inita[1]-SQUEEZEA; if ( inita[1]+SQUEEZEA<A_MAX ) inita[2] = inita[1]+SQUEEZEA; #endif ald.T = T; ald.n = n; ald.t = t; ald.I = I; ald.K = K; ald.val = getval; ald.bpar = bpar; ald.verbose = verbose; ald.maxt = 1; ald.maxn = 1; ald.S = NULL; n_m = 0; for (i=0; i<I; i++) for (k=0; k<K[i]; k++) { if ( t[i][k]>1 && t[i][k]<n[i][k]) n_m += t[i][k]-1 ; } ald.m = malloc(sizeof(*ald.m)*n_m); if ( !ald.m ) { fprintf(stderr,"Out of memory for samplea()\n"); exit(1); } // fprintf(stderr,"m[%d][%d] tabl space = %d\n", I, K[0], n_m); mp = ald.m; for (i=0; i<I; i++) for (k=0; k<K[i]; k++) { if ( t[i][k]>1 && t[i][k]<n[i][k]) { int N = n[i][k]; double ptot = S_S(S,N,t[i][k]); double rem = ptot + log(rng_unit(rng)); int M; // fprintf(stderr,"Sampling[%d][%d] n=%d, t=%d: ", i,k, N, t[i][k]); for (M=t[i][k]-1; M>=1; M--) { // each round instantiates another count int l; double fact = 0.0; for (l=1; l<=N-M; l++) { double term; if ( l>1 ) fact += log((l-mya)*(N-l+1)/(l-1)); term = fact+S_S(S,N-l,M)-ptot; if ( term>= rem ) break; rem = logminus(rem, term); } if ( l>N-M ) l = N-M; mp[M-1] = l; N -= l; assert(N>=1); // fprintf(stderr," %d", l); } // fprintf(stderr," %d\n", N); mp += t[i][k]-1; } } #ifdef PSAMPLE_ARS arms_simple(3, inita, inita+2, aterms2, NULL, 0, inita+1, &mya); if ( mya<inita[0] || mya>inita[2] ) { fprintf(stderr,"Arms_simple(apar) returned value out of bounds\n"); exit(1); } #else inita[1] = A_MAX; if ( SliceSimple(&mya, aterms2, inita, rng, loops, &ald) ) { fprintf(stderr,"SliceSimple error\n"); exit(1); } #endif if ( ald.S ) S_free(ald.S); return mya; }
/* * use prior a is uniform */ double samplea(double mya, int I, int *K, scnt_int *T, scnt_int **n, stcnt_int **t, void (*getval)(scnt_int *n, stcnt_int *t, unsigned i, unsigned k), double *bpar, rngp_t rng, int loops, int verbose) { double inita[3] = {A_MIN,1,A_MAX}; int i, k; ALData ald; inita[1] = mya; if ( fabs(inita[1]-A_MAX)/A_MAX<0.00001 ) { inita[1] = A_MAX*0.999 + A_MIN*0.001; } if ( fabs(inita[1]-A_MIN)/A_MIN<0.00001 ) { inita[1] = A_MIN*0.999 + A_MAX*0.001; } #ifdef SQUEEZEA /* * bound current move to be less than SQEEZEA */ if ( inita[1]-SQUEEZEA>A_MIN ) inita[0] = inita[1]-SQUEEZEA; if ( inita[1]+SQUEEZEA<A_MAX ) inita[2] = inita[1]+SQUEEZEA; #endif ald.T = T; ald.n = n; ald.t = t; ald.I = I; ald.K = K; ald.val = getval; ald.bpar = bpar; ald.verbose = verbose; ald.maxt = 1; ald.maxn = 1; ald.S = NULL; if ( getval ) { for (i=0; i<I; i++) for (k=0; k<K[i]; k++) { scnt_int myn; stcnt_int myt; getval(&myn, &myt, i, k); if ( myt>=ald.maxt ) ald.maxt = myt+1; if ( myn>=ald.maxn ) ald.maxn = myn+1; } } else { for (i=0; i<I; i++) for (k=0; k<K[i]; k++) { if ( t[i][k]>=ald.maxt ) ald.maxt = t[i][k]+1; if ( n[i][k]>=ald.maxn ) ald.maxn = n[i][k]+1; } } #ifdef PSAMPLE_ARS arms_simple(3, inita, inita+2, aterms, &ald, 0, inita+1, &mya); if ( mya<inita[0] || mya>inita[2] ) { fprintf(stderr,"Arms_simple(apar) returned value out of bounds\n"); exit(1); } #else inita[1] = A_MAX; if ( SliceSimple(&mya, aterms, inita, rng, loops, &ald) ) { fprintf(stderr,"SliceSimple error\n"); exit(1); } #endif if ( ald.S ) S_free(ald.S); return mya; }
int main(int argc, char* argv[]) { int i, j, c, iter, ITER=200; unsigned long int seed=0; int bcycle = 0; float bstart = 0; int acycle = 0; float astart = 0; int burnin = 0; stable_t *ST = NULL; int useN = DIM*2; MAXN = 1; MAXT = MAXSTAB; /* * default values for args */ while ( (c=getopt(argc, argv,"a:b:B:C:I:hH:I:N:P:S:s:T:v"))>=0 ) { switch ( c ) { case 'h': usage(burnin?burnin:ITER/2, ITER, useN); exit(0); case 'b': if ( !optarg || sscanf(optarg,"%f,%f",&bpar, &bstart)<1 ) yaps_quit("Need a valid 'b' argument\n"); break; case 'a': if ( !optarg || sscanf(optarg,"%f,%f",&apar,&astart)<1 ) yaps_quit("Need a valid 'a' argument\n"); break; case 'H': if ( !optarg || sscanf(optarg,"%d",&bcycle)!=1 ) yaps_quit("Need a valid 'G' argument\n"); break; case 'T': if ( !optarg || sscanf(optarg,"%d",&MAXT)!=1 ) yaps_quit("Need a valid 'T' argument\n"); break; case 'I': if ( !optarg || sscanf(optarg,"%d",&acycle)!=1 ) yaps_quit("Need a valid 'H' argument\n"); break; case 'N': if ( !optarg || sscanf(optarg,"%d",&useN)!=1 ) yaps_quit("Need a valid 'N' argument\n"); break; case 'C': if ( !optarg || sscanf(optarg,"%d",&ITER)!=1 ) yaps_quit("Need a valid 'C' argument\n"); break; case 'B': if ( !optarg || sscanf(optarg,"%d",&burnin)!=1 ) yaps_quit("Need a valid 'B' argument\n"); break; case 's': if ( !optarg || sscanf(optarg,"%lu",&seed)!=1 ) yaps_quit("Need a valid 's' argument\n"); break; case 'v': verbose++; break; #ifdef S_USE_THREADS case 'P': if ( !optarg || sscanf(optarg,"%u",&threads)!=1 ) yaps_quit("Need a valid 'P' argument\n"); break; #endif default: yaps_message("Bad command line argument\n\n"); usage(burnin?burnin:ITER/2, ITER, useN); exit(0); } } if ( useN>=MAXDATA ) yaps_quit("N too large\n"); if ( burnin==0 ) burnin = ITER/2; else if ( burnin>=ITER-1 ) yaps_quit("Burnin %d too large for cycles %d\n", burnin, ITER); yaps_message("Configuration details\n"); yaps_message("=====================\n"); /* * set random number generator */ if ( seed ) { rng_seed(rng,seed); } else { rng_time(rng,&seed); } yaps_message("Setting seed for data = %lu\n", seed); if ( acycle && apar==0 ) apar = 0.5; yaps_message("Setting a=%f, b=%f, N=%d, D=%d\n", apar, bpar, useN, NUMMN); yaps_message(" burnin=%d,", burnin); yaps_message(" cycles=%d\n", ITER); /* * fix pointers */ for (j=0; j<NUMMN; j++) { n[j] = &n_data[j*DIM]; t[j] = &t_data[j*DIM]; tave[j] = &tave_data[j*DIM]; } /* * initialise everything */ for (j=0; j<NUMMN; j++) { N[j] = useN; T[j] = 0; Tave[j] = 0; for (i=0; i<DIM; i++) { n[j][i] = 0; t[j][i] = 0; tave[j][i] = 0; } } /* * fix base distribution, uniform */ { for (i=0; i<DIM; i++) { H[i] = 1.0/DIM; } } /* * create data using a CRP to get initialisation for n[] */ c = 0; for (j=0; j<NUMMN; j++) { int cc; i = sampleH(); data[c++] = i; // first entry always adds a table n[j][i]++; t[j][i]++; T[j]++; for (cc=1; cc<N[j]; cc++) { float val = (cc+bpar)*rng_unit(rng); val -= T[j]*apar+bpar; if ( val<=0 ) { // new table i = sampleH(); t[j][i]++; T[j]++; } else { for (i=0; i<DIM; i++) { val -= n[j][i] - t[j][i]*apar; if ( val<0 ) break; } } assert(i<DIM); n[j][i]++; data[c++] = i; } } binit = bpar; /* * record maximum entries in data * do this where possible so that one can get the table * sizes right * */ MAXN = n[0][0]+1; MAXT = 1; for (j=0; j<NUMMN; j++) { for (i=0; i<DIM; i++) { if ( MAXN<=n[j][i] ) MAXN = n[j][i]+1; if ( MAXT<t[j][i] ) MAXT = t[j][i]*1.1+1; } } if ( MAXT>MAXN ) MAXT = MAXN; yaps_message("Making S for N=%d M=%d a=%lf\n", MAXN,MAXT,apar); ST = S_make(MAXN, MAXT, MAXN, MAXTAB, apar, S_STABLE | S_UVTABLE); if ( ST==NULL ) yaps_quit("Making S failed!\n"); S_report(ST,stdout); /* * the seed only sets the data/sample, * the seed for the simulation/Gibbs is always random */ rng_free(rng); rng_time(rng,&seed); //yaps_message("Resetting seed = %lu\n", seed); /* * report on initial data statistics */ yaps_message("\nData sampled\n"); yaps_message("============\n"); for (j=0; j<NUMMN; j++) { yaps_message("n[%d] =", j); for (i=0; i<DIM; i++) yaps_message(" %d", n[j][i]); yaps_message(" = %d\n", N[j]); yaps_message("t[%d] =",j); for (i=0; i<DIM; i++) yaps_message(" %d", t[j][i]); yaps_message(" = %d\n", T[j]); } /* * set the hyperparameters used in Gibbs, * can be different to data */ if ( bstart==0 ) bstart = bpar; if ( astart==0 ) astart = apar; // initialise latent stats and reporting info for (j=0; j<NUMMN; j++) { T[j] = 0; Tave[j] = 0; } tcnt = 0; bave = 0; bcnt = 0; aave = 0; acnt = 0; bpar = bstart; if ( verbose && bcycle!=0 ) yaps_message("Starting with initial b=%f\n", bpar); apar = astart; if ( verbose && acycle!=0 ) yaps_message("Starting with initial a=%f\n", apar); for (j=0; j<NUMMN; j++) { for (i=0; i<DIM; i++) { tave[j][i] = 0; t[j][i] = 0; if ( n[j][i]>0 ) { /* * initialise to a single table */ t[j][i] = 1; T[j]++; } } } for ( iter=0; iter<ITER; iter++) { /* * sampling with table indicators */ c = 0; for (j=0; j<NUMMN; j++) { int cc; for (cc=0; cc<N[j]; cc++) { float one; i = data[c++]; assert(n[j][i]); if ( n[j][i]==1 ) // this indicator must always be 1, no sampling continue; // sample whether it contributes to a table if ( t[j][i]>1 && (n[j][i]-1)*rng_unit(rng)<(t[j][i]-1) ) { t[j][i]--; T[j]--; } assert(t[j][i]<n[j][i]); // sample new table indicator one = H[i] * (bpar + T[j]*apar) * (t[j][i]) / (n[j][i]-t[j][i]+1) * S_V(ST, n[j][i],t[j][i]+1); if ( rng_unit(rng) < one/(one+1.0) ) { t[j][i]++; T[j]++; } } } /* * one major cycle of Gibbs sampler finished */ if ( verbose>1 ) { for (j=0; j<NUMMN; j++) { for (i=0; i<DIM; i++) printf(" %d", t[j][i]); printf(" = %d\n", T[j]); } } /* * sample & record b */ if ( bcycle!=0 && iter%bcycle==0 ) { // Gibbs on bpar (concentration par) too if ( bcycle<0 ) { int bc = -bcycle; for (bc-- ; bc>0; bc--) bpar = sampleb(bpar, 1, PB_shape, PB_scale, N, T, apar, rng, 1, 1); } bpar = sampleb(bpar, 1, PB_shape, PB_scale, N, T, apar, rng, 1, 1); if ( iter>=burnin ) { bave += bpar; bcnt ++; } } /* * sample & record a */ if ( acycle!=0 && iter%acycle==0 ) { int dimI[NUMMN]; double dimb[NUMMN]; for (j=0; j<NUMMN; j++) { dimI[j] = DIM; dimb[j] = bpar; } // Gibbs on apar (discount par) too if ( acycle<0 ) { int bc = -acycle; for (bc-- ; bc>0; bc--) apar = samplea(apar, NUMMN, dimI, T, n, t, NULL, dimb, rng, 1, 1); } apar = samplea(apar, NUMMN, dimI, T, n, t, NULL, dimb, rng, 1, 1); if ( iter>=burnin ) { aave += apar; acnt ++; } if ( verbose>1 ) yaps_message("Extending S for a=%lf\n", apar); if ( S_remake(ST,apar) ) yaps_message("Extending S failed\n"); } /* * full statistics collection */ if ( iter>=burnin ) { for (j=0; j<NUMMN; j++) { for (i=0; i<DIM; i++) { tave[j][i] += t[j][i]; } Tave[j] += T[j]; } tcnt ++; } } /* * report for this experiment */ yaps_message("\nEstimates\n"); yaps_message("=========\n"); for (j=0; j<NUMMN; j++) { yaps_message("t[%d] = ", j); for (i=0; i<DIM; i++) yaps_message(" %.2f", tave[j][i]/tcnt); yaps_message("\nT[%d]=%.2f\n", j, Tave[j]/tcnt); } if ( bcycle!=0 && bcnt>0 ) yaps_message("\nb=%.2f", bave/bcnt); if ( acycle!=0 && acnt>0 ) yaps_message("\na=%.3f", aave/acnt); yaps_message("\n"); S_free(ST); rng_free(rng); return 0; }
char * time_ascii(char * ret) { struct timeval *tp; struct timezone *tzp; struct tm * brokentime; if(flags.displaytime == NOTHING_TIME) goto retNULL; tp = (struct timeval * ) S_malloc( sizeof(struct timeval) ); tzp = (struct timezone * ) S_malloc( sizeof(struct timezone) ); memset(tp, 0, sizeof(struct timeval)); memset(tzp, 0, sizeof(struct timeval)); if(gettimeofday(tp, tzp)) { perror("gettimeofday returned not 0!"); goto retNULL; } else { brokentime = localtime(&(tp->tv_sec)); switch (flags.displaytime) { case ONLYTIME: sprintf(ret,"%2.2d:%2.2d:%2.2d.%6.6d", brokentime->tm_hour, brokentime->tm_min, brokentime->tm_sec, tp->tv_usec ); break; case TIMEDATE: sprintf(ret, "%2.2d-%2.2d-%2.2d " /* date */ "%2.2d:%2.2d:%2.2d.%6.6d", /* time */ /* date */ brokentime->tm_mday, brokentime->tm_mon + 1, brokentime->tm_year > 100 ? brokentime->tm_year - 100 : brokentime->tm_year, /* time */ brokentime->tm_hour, brokentime->tm_min, brokentime->tm_sec, tp->tv_usec ); break; default: #ifdef TCPICK_DEBUG suicide("time_ascii", "unimplemented feature required."); #endif goto retNULL; } } S_free ( tp ); S_free ( tzp ); return ret; retNULL: sprintf(ret,""); return NULL; }
/* * assume tables filled to usedN,usedM; * request (N,M) table value; * fiddle maxM, maxN to make it non-trivial * create extra space first; * then remake table values; * return non-zero on error */ static int S_extend(stable_t *sp, int N, int M) { int n; int result = 0; // int Nin = N, Min = M; N++; M++; /* * N shouldn't be too big or small */ #ifdef S_USE_THREADS if ( (sp->flags&S_THREADS) ) pthread_mutex_lock(&sp->mutex); #endif if ( N<sp->usedN && M<sp->usedM ) /* * someone did the change before we got here! */ goto SE_result; if ( N<sp->usedN ) N = sp->usedN; if ( N>sp->maxN ) N = sp->maxN; /* * N increase should not be trivial */ if ( N>sp->usedN ) { if ( N<sp->usedN*1.1 ) N = sp->usedN*1.1; if ( N<sp->usedN+50 ) N = sp->usedN+50; /* * reset if made too big */ if ( N>sp->maxN ) { N = sp->maxN; } } /* * M shouldn't be too big or small */ if ( M<sp->usedM ) M = sp->usedM; if ( N<M ) M = N; if ( M>sp->maxM ) M = sp->maxM; /* * M increase should not be trivial */ if ( M>sp->usedM ) { if ( M<sp->usedM*1.1 ) M = sp->usedM*1.1; if ( M<sp->usedM+50 ) M = sp->usedM+50; /* * reset if made too big */ if ( M>sp->maxM ) { M = sp->maxM; } if ( M>sp->usedN ) { M = sp->usedN; } } /* * N and M values now set */ if ( M>sp->usedM ) { /* * extend size of existing vectors; * note S/Sf/V/Vf are triangular up to n=usedM, so ignore that */ for (n=sp->usedM+1; n<=sp->usedN; n++) { if ( sp->flags&S_STABLE ) { if ( (sp->flags&S_FLOAT)==0 ) { myrealloc(sp->S[n-3],sizeof(sp->S[0][0])*(M-1)); if ( !sp->S[n-3] ) { S_free(sp); result = 1; goto SE_result; } } else { myrealloc(sp->Sf[n-3],sizeof(sp->Sf[0][0])*(M-1)); if ( !sp->Sf[n-3] ) { S_free(sp); result = 1; goto SE_result; } } } if ( sp->flags&S_UVTABLE ) { if ( (sp->flags&S_FLOAT)==0 ) { myrealloc(sp->V[n-2],sizeof(sp->V[0][0])*(M-1)); if ( !sp->V[n-2] ) { S_free(sp); result = 1; goto SE_result; } } else { myrealloc(sp->Vf[n-2],sizeof(sp->Vf[0][0])*(M-1)); if ( !sp->Vf[n-2] ) { S_free(sp); result = 1; goto SE_result; } } } } if ( sp->flags&S_STABLE && sp->flags&S_FLOAT ) { myrealloc(sp->SfrontN,sizeof(sp->SfrontN[0])*(M-1)); if ( !sp->SfrontN ) { S_free(sp); result = 1; goto SE_result; } } if ( sp->flags&S_UVTABLE && sp->flags&S_FLOAT ) { myrealloc(sp->VfrontN,sizeof(sp->VfrontN[0])*(M-1)); if ( !sp->VfrontN ) { S_free(sp); result = 1; goto SE_result; } } } /* * now create new vectors in S/Sf/V/Vf */ if ( N>sp->usedN ) { /* * extend size of S/Sf/SfrontN */ if ( sp->flags&S_STABLE ) { myrealloc(sp->S1,sizeof(sp->S1[0])*N); if ( !sp->S1 ) { S_free(sp); result = 1; goto SE_result; } if ( (sp->flags&S_FLOAT)==0 ) { myrealloc(sp->S,sizeof(sp->S[0])*N); if ( !sp->S ) { S_free(sp); result = 1; goto SE_result; } } else { myrealloc(sp->Sf,sizeof(sp->Sf[0])*N); if ( !sp->Sf ) { S_free(sp); result = 1; goto SE_result; } myrealloc(sp->SfrontM,sizeof(sp->SfrontM[0])*(N-M)); if ( !sp->SfrontM ) { S_free(sp); result = 1; goto SE_result; } } } } /* * extend size of V/Vf/VfrontN+M */ if ( sp->flags&S_UVTABLE ) { if ( (sp->flags&S_FLOAT)==0 ) { myrealloc(sp->V,sizeof(sp->V[0])*N); if ( !sp->V ) { S_free(sp); result = 1; goto SE_result; } } else { myrealloc(sp->Vf,sizeof(sp->Vf[0])*N); if ( !sp->Vf ) { S_free(sp); result = 1; goto SE_result; } if ( N-M > sp->usedN-sp->usedM ) { /* * stores *last* values, so cannot shrink or loose a few */ myrealloc(sp->VfrontM,sizeof(sp->VfrontM[0])*(N-M+1)); if ( !sp->VfrontM ) { S_free(sp); result = 1; goto SE_result; } } } } /* * now create new vectors */ for (n=sp->usedN+1; n<=N; n++) { if ( sp->flags&S_STABLE ) { if ( (sp->flags&S_FLOAT)==0 ) { sp->S[n-3] = mymalloc(sizeof(sp->S[0][0])*(M-1)); if ( !sp->S[n-3] ) { S_free(sp); result = 1; goto SE_result; } } else { sp->Sf[n-3] = mymalloc(sizeof(sp->Sf[0][0])*(M-1)); if ( !sp->Sf[n-3] ) { S_free(sp); result = 1; goto SE_result; } } } if ( sp->flags&S_UVTABLE ) { if ( (sp->flags&S_FLOAT)==0 ) { sp->V[n-2] = mymalloc(sizeof(sp->V[0][0])*(M-1)); if ( !sp->V[n-2] ) { S_free(sp); result = 1; goto SE_result; } } else { sp->Vf[n-2] = mymalloc(sizeof(sp->Vf[0][0])*(M-1)); if ( !sp->Vf[n-2] ) { S_free(sp); result = 1; goto SE_result; } } } } { int oldN, oldM; oldN = sp->usedN; oldM = sp->usedM; result = S_remake_part(sp,sp->a, oldN, oldM, N, M, sp->usedN1); } SE_result: #ifdef S_USE_THREADS if ( (sp->flags&S_THREADS) ) { // yaps_message("Extended %s under lock: in=%d,%d set=%d,%d used=%d,%d\n", // sp->tag, Nin, Min, N, M, sp->usedN, sp->usedM); pthread_mutex_unlock(&sp->mutex); } #endif return result; }
stable_t *S_make(unsigned initN, unsigned initM, unsigned maxN, unsigned maxM, double a, uint32_t flags) { int N; stable_t *sp = NULL; sp = mymalloc(sizeof(stable_t)); if ( !sp ) return NULL; if ( maxM<10 ) maxM = 10; if ( maxN<maxM ) maxN = maxM; if ( initM<10 ) initM = 10; if ( initN<initM ) initN = initM; if ( initN>maxN ) initN = maxM; if ( initN>maxN ) initN = maxN; if ( (flags&S_STABLE)==0 && (flags&S_UVTABLE)==0 ) return NULL; sp->tag = NULL; sp->memalloced = 0; sp->flags = flags; sp->maxN = maxN; sp->maxM = maxM; sp->usedN = initN; sp->usedM = initM; sp->usedN1 = initN; sp->startM = initM; sp->S = NULL; sp->SfrontN = sp->SfrontM = sp->S1 = NULL; sp->V = NULL; sp->VfrontN = sp->VfrontM = NULL; sp->Sf = sp->Vf = NULL; #ifdef S_USE_THREADS if ( (flags&S_THREADS) ) { // yaps_message("Initialised mutex \n"); pthread_mutex_init(&sp->mutex, NULL); } #endif sp->S1 = mymalloc(sizeof(sp->S1[0])*(initN)); if ( !sp->S1 ) { myfree(sp); return NULL; } if ( flags&S_STABLE ) { if ( flags&S_FLOAT ) { /* * allocate frontier */ sp->SfrontN = mymalloc(sizeof(sp->SfrontN[0])*(initM-1)); if ( !sp->SfrontN ) { S_free(sp); return NULL; } /* * sets diagonal entry of S since the loop writing * SfrontN never does the diagnal itself */ memset(sp->SfrontN,0,sizeof(sp->SfrontN[0])*(initM-1)); sp->SfrontM = mymalloc(sizeof(sp->SfrontM[0])*(initN-initM+1)); if ( !sp->SfrontM ) { S_free(sp); return NULL; } /* * allocate sp->Sf[] as vector of vectors */ sp->Sf = mymalloc(sizeof(sp->Sf[0])*(sp->usedN-2)); if ( !sp->Sf ) { S_free(sp); return NULL; } memset(sp->Sf,0,sizeof(sp->Sf[0])*(sp->usedN-2)); /* * allocate sp->Sf[0][.] to sp->Sf[startM-3][.] in one block */ sp->Sf[0] = mymalloc(sizeof(sp->Sf[0][0])*(sp->startM-1)*(sp->startM-2)/2); if ( !sp->Sf[0] ) { S_free(sp); return NULL; } for (N=1; N<=sp->startM-3; N++) sp->Sf[N] = sp->Sf[N-1] + N; /* * allocate remaining sp->Sf[N][.] as vectors */ assert(sp->startM-2+sp->Sf[sp->startM-3]-sp->Sf[0]== (sp->startM-1)*(sp->startM-2)/2); for (N=sp->startM-2; N<=sp->usedN-3; N++) { sp->Sf[N] = mymalloc(sizeof(sp->Sf[0][0])*(sp->usedM-1)); if ( !sp->Sf[N] ) { S_free(sp); return NULL; } } } else { sp->S = mymalloc(sizeof(sp->S[0])*sp->usedN); if ( !sp->S ) { S_free(sp); return NULL; } /* * allocate sp->S[0][.] to sp->S[startM-3][.] in one block */ sp->S[0] = mymalloc(sizeof(sp->S[0][0])*(sp->startM-1)*(sp->startM-2)/2); if ( !sp->S[0] ) { S_free(sp); return NULL; } for (N=1; N<=sp->startM-3; N++) sp->S[N] = sp->S[N-1] + N; /* * allocate remaining sp->S[N][.] as vectors for N>=usedM+1 * which store values M=2,...,usedM, so need (usedM-1) space */ assert(sp->startM-2+sp->S[sp->startM-3]-sp->S[0]== (sp->startM-1)*(sp->startM-2)/2); for (N=sp->startM-2; N<=sp->usedN-3; N++) { sp->S[N] = mymalloc(sizeof(sp->S[0][0])*(sp->usedM-1)); if ( !sp->S[N] ) { S_free(sp); return NULL; } } } } if ( flags&S_UVTABLE ) { if ( flags&S_FLOAT ) { /* * allocate frontier */ sp->VfrontN = mymalloc(sizeof(sp->VfrontN[0])*(initM-1)); if ( !sp->VfrontN ) { S_free(sp); return NULL; } /* * sets diagonal entry of V since the loop writing * VfrontN never does the diagnal itself */ memset(sp->VfrontN,0,sizeof(sp->VfrontN[0])*(initM-1)); sp->VfrontM = mymalloc(sizeof(sp->VfrontM[0])*(initN-initM+1)); if ( !sp->VfrontM ) { S_free(sp); return NULL; } sp->Vf = mymalloc(sizeof(sp->Vf[0])*sp->usedN); if ( !sp->Vf ) { S_free(sp); return NULL; } /* * allocate sp->Vf[0][.] to sp->Vf[startM-2][.] in one block */ sp->Vf[0] = mymalloc(sizeof(sp->Vf[0][0])*(sp->startM-1)*(sp->startM)/2); if ( !sp->Vf[0] ) { S_free(sp); return NULL; } for (N=1; N<=sp->startM-2; N++) sp->Vf[N] = sp->Vf[N-1] + N; /* * allocate remaining sp->Vf[N][.] as vectors for N>=usedM+1 * which store values M=2,...,usedM, so need (usedM-1) space */ assert(sp->startM-1+sp->Vf[sp->startM-2]-sp->Vf[0]== (sp->startM-1)*(sp->startM)/2); for (N=sp->startM-1; N<=sp->usedN-2; N++) { sp->Vf[N] = mymalloc(sizeof(sp->Vf[0][0])*(sp->usedM-1)); if ( !sp->Vf[N] ) { S_free(sp); return NULL; } } } else { sp->V = mymalloc(sizeof(sp->V[0])*sp->usedN); if ( !sp->V ) { S_free(sp); return NULL; } /* * allocate sp->V[0][.] to sp->V[startM-2][.] in one block */ sp->V[0] = mymalloc(sizeof(sp->V[0][0])*(sp->startM-1)*(sp->startM)/2); if ( !sp->V[0] ) { S_free(sp); return NULL; } for (N=1; N<=sp->startM-2; N++) sp->V[N] = sp->V[N-1] + N; /* * allocate remaining sp->V[N][.] as vectors for N>=usedM+1 * which store values M=2,...,usedM, so need (usedM-1) space */ assert(sp->startM-1+sp->V[sp->startM-2]-sp->V[0]== (sp->startM-1)*(sp->startM)/2); for (N=sp->startM-1; N<=sp->usedN-2; N++) { sp->V[N] = mymalloc(sizeof(sp->V[0][0])*(sp->usedM-1)); if ( !sp->V[N] ) { S_free(sp); return NULL; } } } } /* * this is where we actually build the Stirling numbers */ S_remake(sp,a); return sp; }