#include "niml_private.h" /*-----------------------------------------------------------*/ /* This macro copies the basic elements of a struct, from struct qold to struct qnew. Of course, the new struct gets a new idcode. This macro may be used after creating a new struct with NI_new(), for example. -------------------------------------------------------------*/ #undef COPY_BASIC_STRUCT #define COPY_BASIC_STRUCT(qnew,qold) \ do{ (qnew)->type = (qold)->type ; \ (qnew)->nref = 1 ; \ (qnew)->idcode = UNIQ_idcode() ; \ NI_register_struct( (qnew) ) ; \ (qnew)->name = NI_strdup((qold)->name) ; \ } while(0) /*-----------------------------------------------------------*/ /*! Transpose a dataset, so that rows are columns and vice- versa. - Requires that all vectors (columns) have the same type - Requires that all vectors do NOT have statistical distribution types attached. - Returns pointer to a new dataset (NULL for errors). -------------------------------------------------------------*/ void * NI_dataset_transpose( void *ndd ) { NI_dataset *ndnew , *nd = (NI_dataset *)ndd ; NI_index_t ii,jj , nvec_old,nvec_new , len_old,len_new ; int tt , lt ; if( nd == NULL || nd->type != NI_DATASET_TYPE || nd->vec == NULL ) return NULL ; /* bad input */ /* check if all columns have same type, etc. */ nvec_old = NI_dataset_vecnum(nd) ; len_old = NI_dataset_veclen(nd) ; if( nvec_old <= 0 || len_old <= 0 ) return NULL ; if( nd->vec[0] == NULL ) return NULL ; if( nd->vec[0]->statistic != NULL ) return NULL ; tt = nd->vec[0]->vec_typ ; lt = NI_datatype_size(tt) ; for( ii=1 ; ii < nvec_old ; ii++ ){ if( nd->vec[ii] == NULL ) return NULL ; if( nd->vec[ii]->vec_typ != tt ) return NULL ; if( nd->vec[ii]->statistic != NULL ) return NULL ; } /* create output struct */ ndnew = NI_new(NI_dataset) ; COPY_BASIC_STRUCT(ndnew,nd) ; ndnew->num_node = nd->num_node ; ndnew->num_val = nd->num_val ; ndnew->order = NI_opposite_order(nd->order) ; /* flipped */ ndnew->domain = (NI_struct *)NI_pointto_struct(nd->domain) ; /* same domain */ /* create new vectors */ nvec_new = NI_dataset_vecnum(ndnew) ; len_new = NI_dataset_veclen(ndnew) ; ndnew->vec = NI_malloc(NI_vector*, sizeof(NI_vector *) * nvec_new ) ; for( ii=0 ; ii < nvec_new ; ii++ ) ndnew->vec[ii] = (NI_vector *)NI_new_vector( tt , len_new ) ; /* copy data from old vectors to new vectors */ if( tt != NI_STRING ){ /* copy fixed length content */ char *vnew , *vold ; for( ii=0 ; ii < nvec_new ; ii++ ){ vnew = (char *)ndnew->vec[ii]->vec ; for( jj=0 ; jj < nvec_old ; jj++ ){ vold = (char *)nd->vec[jj]->vec ; memcpy( vnew+lt*jj , vold+lt*ii , lt ) ; } } for( ii=0 ; ii < nvec_new ; ii++ ) NI_set_vector_range( ndnew->vec[ii] ) ; } else { /* duplicate strings */ char **vnew , **vold ; for( ii=0 ; ii < nvec_new ; ii++ ){ vnew = (char **)ndnew->vec[ii]->vec ; for( jj=0 ; jj < nvec_old ; jj++ ){ vold = (char **)nd->vec[jj]->vec ; vnew[jj] = NI_strdup( vold[ii] ) ; } } } /** done **/ return (void *)ndnew ; }