#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 ;
}
syntax highlighted by Code2HTML, v. 0.9.1