=================================================================== RCS file: /home/cvs/OpenXM_contrib2/asir2000/engine/nd.c,v retrieving revision 1.94 retrieving revision 1.97 diff -u -p -r1.94 -r1.97 --- OpenXM_contrib2/asir2000/engine/nd.c 2004/03/15 07:30:44 1.94 +++ OpenXM_contrib2/asir2000/engine/nd.c 2004/03/25 01:31:03 1.97 @@ -1,4 +1,4 @@ -/* $OpenXM: OpenXM_contrib2/asir2000/engine/nd.c,v 1.93 2004/03/13 07:48:30 noro Exp $ */ +/* $OpenXM: OpenXM_contrib2/asir2000/engine/nd.c,v 1.96 2004/03/17 08:16:24 noro Exp $ */ #include "nd.h" @@ -29,9 +29,12 @@ static NDV *nd_ps; static NDV *nd_ps_trace; static RHist *nd_psh; static int nd_psn,nd_pslen; - static RHist *nd_red; - +static int *nd_work_vector; +static int **nd_matrix; +static int nd_matrix_len; +static struct weight_or_block *nd_worb; +static int nd_worb_len; static int nd_found,nd_create,nd_notfirst; static int nmv_adv; static int nd_demand; @@ -422,6 +425,84 @@ int ndl_block_compare(UINT *d1,UINT *d2) return 0; } +int ndl_matrix_compare(UINT *d1,UINT *d2) +{ + int i,j,s; + int *v; + + for ( j = 0; j < nd_nvar; j++ ) + nd_work_vector[j] = GET_EXP(d1,j)-GET_EXP(d2,j); + for ( i = 0; i < nd_matrix_len; i++ ) { + v = nd_matrix[i]; + for ( j = 0, s = 0; j < nd_nvar; j++ ) + s += v[j]*nd_work_vector[j]; + if ( s > 0 ) return 1; + else if ( s < 0 ) return -1; + } + return 0; +} + +int ndl_composite_compare(UINT *d1,UINT *d2) +{ + int i,j,s,start,end,len,o; + int *v; + struct sparse_weight *sw; + + for ( j = 0; j < nd_nvar; j++ ) + nd_work_vector[j] = GET_EXP(d1,j)-GET_EXP(d2,j); + for ( i = 0; i < nd_worb_len; i++ ) { + len = nd_worb[i].length; + switch ( nd_worb[i].type ) { + case IS_DENSE_WEIGHT: + v = nd_worb[i].body.dense_weight; + for ( j = 0, s = 0; j < len; j++ ) + s += v[j]*nd_work_vector[j]; + if ( s > 0 ) return 1; + else if ( s < 0 ) return -1; + break; + case IS_SPARSE_WEIGHT: + sw = nd_worb[i].body.sparse_weight; + for ( j = 0, s = 0; j < len; j++ ) + s += sw[j].value*nd_work_vector[sw[j].pos]; + if ( s > 0 ) return 1; + else if ( s < 0 ) return -1; + break; + case IS_BLOCK: + o = nd_worb[i].body.block.order; + start = nd_worb[i].body.block.start; + switch ( o ) { + case 0: + end = start+len; + for ( j = start, s = 0; j < end; j++ ) + s += MUL_WEIGHT(nd_work_vector[j],j); + if ( s > 0 ) return 1; + else if ( s < 0 ) return -1; + for ( j = end-1; j >= start; j-- ) + if ( nd_work_vector[j] < 0 ) return 1; + else if ( nd_work_vector[j] > 0 ) return -1; + break; + case 1: + end = start+len; + for ( j = start, s = 0; j < end; j++ ) + s += MUL_WEIGHT(nd_work_vector[j],j); + if ( s > 0 ) return 1; + else if ( s < 0 ) return -1; + for ( j = start; j < end; j++ ) + if ( nd_work_vector[j] > 0 ) return 1; + else if ( nd_work_vector[j] < 0 ) return -1; + break; + case 2: + for ( j = start; j < end; j++ ) + if ( nd_work_vector[j] > 0 ) return 1; + else if ( nd_work_vector[j] < 0 ) return -1; + break; + } + break; + } + } + return 0; +} + /* TDH -> WW -> TD-> RL */ int ndl_ww_lex_compare(UINT *d1,UINT *d2) @@ -873,6 +954,79 @@ ND nd_add(int mod,ND p1,ND p2) } } +/* XXX on opteron, the inlined manipulation of destructive additon of + * two NM seems to make gcc optimizer get confused, so the part is + * done in a function. + */ + +int nm_destructive_add_q(NM *m1,NM *m2,NM *mr0,NM *mr) +{ + NM s; + Q t; + int can; + + addq(CQ(*m1),CQ(*m2),&t); + s = *m1; *m1 = NEXT(*m1); + if ( t ) { + can = 1; NEXTNM2(*mr0,*mr,s); CQ(*mr) = (t); + } else { + can = 2; FREENM(s); + } + s = *m2; *m2 = NEXT(*m2); FREENM(s); + return can; +} + +ND nd_add_q(ND p1,ND p2) +{ + int n,c,can; + ND r; + NM m1,m2,mr0,mr,s; + Q t; + + if ( !p1 ) return p2; + else if ( !p2 ) return p1; + else { + can = 0; + for ( n = NV(p1), m1 = BDY(p1), m2 = BDY(p2), mr0 = 0; m1 && m2; ) { + c = DL_COMPARE(DL(m1),DL(m2)); + switch ( c ) { + case 0: +#if defined(__x86_64__) + can += nm_destructive_add_q(&m1,&m2,&mr0,&mr); +#else + addq(CQ(m1),CQ(m2),&t); + s = m1; m1 = NEXT(m1); + if ( t ) { + can++; NEXTNM2(mr0,mr,s); CQ(mr) = (t); + } else { + can += 2; FREENM(s); + } + s = m2; m2 = NEXT(m2); FREENM(s); +#endif + break; + case 1: + s = m1; m1 = NEXT(m1); NEXTNM2(mr0,mr,s); + break; + case -1: + s = m2; m2 = NEXT(m2); NEXTNM2(mr0,mr,s); + break; + } + } + if ( !mr0 ) + if ( m1 ) mr0 = m1; + else if ( m2 ) mr0 = m2; + else return 0; + else if ( m1 ) NEXT(mr) = m1; + else if ( m2 ) NEXT(mr) = m2; + else NEXT(mr) = 0; + BDY(p1) = mr0; + SG(p1) = MAX(SG(p1),SG(p2)); + LEN(p1) = LEN(p1)+LEN(p2)-can; + FREEND(p2); + return p1; + } +} + ND nd_add_sf(ND p1,ND p2) { int n,c,can; @@ -2551,14 +2705,14 @@ UINT *ndv_compute_bound(NDV p) int nd_get_exporigin(struct order_spec *ord) { switch ( ord->id ) { - case 0: + case 0: case 2: return 1; case 1: /* block order */ /* d[0]:weight d[1]:w0,...,d[nd_exporigin-1]:w(n-1) */ return ord->ord.block.length+1; - case 2: - error("nd_get_exporigin : matrix order is not supported yet."); + case 3: + error("nd_get_exporigin : composite order is not supported yet."); } } @@ -2603,6 +2757,7 @@ void nd_setup_parameters(int nvar,int max) { nmv_adv = ROUND_FOR_ALIGN(sizeof(struct oNMV)+(nd_wpd-1)*sizeof(UINT)); nd_epos = nd_create_epos(nd_ord); nd_blockmask = nd_create_blockmask(nd_ord); + nd_work_vector = (int *)REALLOC(nd_work_vector,nd_nvar*sizeof(int)); } ND_pairs nd_reconstruct(int mod,int trace,ND_pairs d) @@ -3354,14 +3509,29 @@ void nd_init_ord(struct order_spec *ord) } break; case 1: + /* block order */ /* XXX */ nd_dcomp = -1; nd_isrlex = 0; ndl_compare_function = ndl_block_compare; break; case 2: - error("nd_init_ord : matrix order is not supported yet."); + /* matrix order */ + /* XXX */ + nd_dcomp = -1; + nd_isrlex = 0; + nd_matrix_len = ord->ord.matrix.row; + nd_matrix = ord->ord.matrix.matrix; + ndl_compare_function = ndl_matrix_compare; break; + case 3: + /* composite order */ + nd_dcomp = -1; + nd_isrlex = 0; + nd_worb_len = ord->ord.composite.length; + nd_worb = ord->ord.composite.w_or_b; + ndl_compare_function = ndl_composite_compare; + break; } nd_ord = ord; } @@ -3372,7 +3542,8 @@ BlockMask nd_create_blockmask(struct order_spec *ord) UINT *t; BlockMask bm; - if ( !ord->id ) + /* we only create mask table for block order */ + if ( ord->id != 1 ) return 0; n = ord->ord.block.length; bm = (BlockMask)MALLOC(sizeof(struct oBlockMask)); @@ -3430,7 +3601,14 @@ EPOS nd_create_epos(struct order_spec *ord) } break; case 2: - error("nd_create_epos : matrix order is not supported yet."); + /* matrix order */ + case 3: + /* composite order */ + for ( i = 0; i < nd_nvar; i++ ) { + epos[i].i = nd_exporigin + i/nd_epw; + epos[i].s = (nd_epw-(i%nd_epw)-1)*nd_bpe; + } + break; } return epos; }