Home My Page Projects Code Snippets Project Openings diderot
Summary Activity Tracker Tasks SCM

SCM Repository

[diderot] View of /branches/vis12/src/lib/common/dyn-seq.c
ViewVC logotype

View of /branches/vis12/src/lib/common/dyn-seq.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1979 - (download) (as text) (annotate)
Sat Jul 21 16:25:51 2012 UTC (7 years, 1 month ago) by jhr
File size: 9440 byte(s)
  Fix a few type errors, etc.
/*! \file dyn-seq.c
 *
 * \author John Reppy
 *
 * An implementation of dynamic sequences.
 */

/*
 * COPYRIGHT (c) 2012 The Diderot Project (http://diderot-language.cs.uchicago.edu)
 * All rights reserved.
 */

#include "Diderot/diderot.h"
#include <teem/nrrd.h>

// compute the address of the i'th element in the sequence
STATIC_INLINE void* ElemAddr(void *base, size_t elemSz, unsigned int i)
{
    return (void *)((char *)base + i*elemSz);
}

//! append an element to a sequence
Diderot_DynSeq_t *Diderot_DynSeqAppend (size_t elemSz, Diderot_DynSeq_t *seq, void *item)
{
    if (seq->nElems == seq->size) {
      // grow the data array
	unsigned int newSize = (seq->size < 64) ? seq->size + 8 : seq->size + 64;
	void *newData = CheckedAlloc (elemSz * newSize);
	Diderot_DynSeqCopy (elemSz, newData, seq);
	seq->size = newSize;
	seq->base = 0;
	FREE(seq->data);
	seq->data = newData;
    }
    unsigned int i = (seq->base + seq->nElems) % seq->size;
    seq->nElems++;
    memcpy(ElemAddr(seq->data, elemSz, i), item, elemSz);
    return seq;
}

//! prepend an element to a sequence
//Diderot_DynSeq_t *Diderot_DynSeqPrepend (size_t elemSz, void *, Diderot_DynSeq_t *);

//! concatenate two sequences
//Diderot_DynSeq_t *Diderot_DynSeqConcat (size_t elemSz, Diderot_DynSeq_t *, Diderot_DynSeq_t *);

//! \brief copy the elements of a sequence to an array
//! \param elemSz the size of the sequence elements in bytes
//! \param dst the destination array
//! \param seq the source sequence
//! \return the address of the element that follows the array
void *Diderot_DynSeqCopy (size_t elemSz, void *dst, Diderot_DynSeq_t *seq)
{
    unsigned int n = seq->nElems;
    if (seq->base + n > seq->size) {
      // sequence wraps around, so we need to copy it in two steps
	n = seq->size - seq->base;
	memcpy (dst, ElemAddr(seq->data, elemSz, seq->base), n*elemSz);
	dst = (void *)((char *)dst + n*elemSz);
	n = seq->nElems - n;
	memcpy (dst, ElemAddr(seq->data, elemSz, 0), n*elemSz);
	return (void *)((char *)dst + n*elemSz);
    }
    else {
	size_t cpySz = n*elemSz;
	memcpy (dst, ElemAddr(seq->data, elemSz, seq->base), cpySz);
	return (void *)((char *)dst + cpySz);
    }
}

static struct {
    bool isFloat;
    unsigned int sizeb;
} NrrdTypeInfo[nrrdTypeLast] = {
	[nrrdTypeDefault] = {false, 0},		/*  0: signifies "determine output type for me" */
	[nrrdTypeChar] = {false, 1},		/*  1:   signed 1-byte integer */
	[nrrdTypeUChar] = {false, 1},		/*  2: unsigned 1-byte integer */
	[nrrdTypeShort] = {false, 2},		/*  3:   signed 2-byte integer */
	[nrrdTypeUShort] = {false, 2},		/*  4: unsigned 2-byte integer */
	[nrrdTypeInt] = {false, 4},		/*  5:   signed 4-byte integer */
	[nrrdTypeUInt] = {false, 4},		/*  6: unsigned 4-byte integer */
	[nrrdTypeLLong] = {false, 8},		/*  7:   signed 8-byte integer */
	[nrrdTypeULLong] = {false, 8},		/*  8: unsigned 8-byte integer */
	[nrrdTypeFloat] = {true, 4},		/*  9:          4-byte floating point */
	[nrrdTypeDouble] = {true, 8},		/* 10:          8-byte floating point */
	[nrrdTypeBlock] = {false, 0},		/* 11: size user defined at run time; MUST BE LAST */
    };

//! Check that a nrrd has the expected structure for loading into a dynamic sequence
//! \param wrld the world; used to report errors
//! \param nin the nrrd to check
//! \param nDims the number of dimensions in the sequence elements
//! \param dims the array of sequence element dimensions
//! \return the number of values per element, or zero on error
static unsigned int CheckNrrd (
    WorldPrefix_t *wrld,
    Nrrd *nin,
    unsigned int nDims,
    unsigned int *dims)
{

  // compute the expected number of values per sequence element
    unsigned int nValuesPerElem = 1;
    for (unsigned int i = 0;  i < nDims;  i++) {
	nValuesPerElem *= dims[i];
    }

  // check the structure of the nrrd file
    if (nin->spaceDim != 1) {
	Diderot_Error (wrld, "unexpected number of axes in nrrd; expected 1, found %d\n",
	    nin->spaceDim);
	return 0;
    }
    if (nin->dim - 1 != nDims) {
	Diderot_Error (wrld, "unexpected nrrd dimension; expected %d, found %d\n",
	    nDims, nin->dim-1);
	return 0;
    }
    for (unsigned int i = 0;  i < nDims;  i++) {
	if (dims[i] != nin->axis[i+1].size) {
	    Diderot_Error (wrld, "nrrd shape does not match expected structure\n");
	    return 0;
	}
    }
    if (NrrdTypeInfo[nin->type].sizeb == 0) {
	Diderot_Error (wrld, "bogus element type %d in nrrd\n", nin->type);
	return 0;
    }

    return nValuesPerElem;
}

//! load a dynamic sequence from a Nrrd file, where the sequence elements have real ground type.
//! \param wrld the world; used to report errors
//! \param nin the nrrd to check
//! \param nDims the number of dimensions in the sequence elements
//! \param dims the array of sequence element dimensions
//! \return the dynamic sequence, or zero on error
Diderot_DynSeq_t *Diderot_DynSeqLoadReal (
    WorldPrefix_t *wrld,
    Nrrd *nin,
    unsigned int nDims,
    unsigned int *dims)
{
    unsigned int nValuesPerElem = CheckNrrd(wrld, nin, nDims, dims);
    size_t elemSz = SIZEOF_DIDEROT_REAL * nValuesPerElem;

    if (nValuesPerElem == 0)
	return (Diderot_DynSeq_t *)0;

  // get the number of elements
    size_t nElems = nin->axis[0].size;

  // allocate the dynamic sequence
    Diderot_DynSeq_t *seq = Diderot_DynSeqAlloc(elemSz, nElems);

  // initialize the sequence from the nrrd
    if (! NrrdTypeInfo[nin->type].isFloat || (NrrdTypeInfo[nin->type].sizeb != SIZEOF_DIDEROT_REAL)) {
      // this is the slow path; we have to convert values as they are copied from the nrrd
#if defined(DIDEROT_DOUBLE_PRECISION)
	double (*loadFn)(const void *) = nrrdDLoad[nin->type];
#else
	float (*loadFn)(const void *) = nrrdFLoad[nin->type];
#endif
	Diderot_real_t *dst = (Diderot_real_t *)seq->data;
	char *src = (char *)nin->data;
	size_t srcElemSz = NrrdTypeInfo[nin->type].sizeb;
	for (size_t i = 0;  i < nElems * nValuesPerElem;  i++) {
	    *dst++ = loadFn(src);
	    src += srcElemSz;
	}
    }
    else {
      // this is the fast path, where we can just do a bulk memcpy
	memcpy (seq->data, nin->data, nElems * elemSz);
    }

    return seq;

}


//! load a dynamic sequence from a Nrrd file, where the sequence elements have int ground type.
//! \param wrld the world; used to report errors
//! \param nin the nrrd to check
//! \param nDims the number of dimensions in the sequence elements
//! \param dims the array of sequence element dimensions
//! \return the dynamic sequence, or zero on error
Diderot_DynSeq_t *Diderot_DynSeqLoadInt (
    WorldPrefix_t *wrld,
    Nrrd *nin,
    unsigned int nDims,
    unsigned int *dims)
{
    unsigned int nValuesPerElem = CheckNrrd(wrld, nin, nDims, dims);
    size_t elemSz = SIZEOF_DIDEROT_INT * nValuesPerElem;

    if (nValuesPerElem == 0)
	return (Diderot_DynSeq_t *)0;

    if (NrrdTypeInfo[nin->type].isFloat) {
	Diderot_Error (wrld, "expected integer element type for int sequence, but found %d\n", nin->type);
	return 0;
    }

  // get the number of elements
    size_t nElems = nin->axis[0].size;

  // allocate the dynamic sequence
    Diderot_DynSeq_t *seq = Diderot_DynSeqAlloc(elemSz, nElems);

  // initialize the sequence from the nrrd
    if (NrrdTypeInfo[nin->type].sizeb != SIZEOF_DIDEROT_INT) {
      // this is the slow path; we have to convert values as they are copied from the nrrd
	int (*loadFn)(const void *) = nrrdILoad[nin->type];
	Diderot_int_t *dst = (Diderot_int_t *)seq->data;
	char *src = (char *)nin->data;
	size_t srcElemSz = NrrdTypeInfo[nin->type].sizeb;
	for (size_t i = 0;  i < nElems * nValuesPerElem;  i++) {
	    *dst++ = loadFn(src);
	    src += srcElemSz;
	}
    }
    else {
      // this is the fast path, where we can just do a bulk memcpy
	memcpy (seq->data, nin->data, nElems * elemSz);
    }

    return seq;

}


//! load a dynamic sequence from a Nrrd file, where the sequence elements have bool ground type.
//! \param wrld the world; used to report errors
//! \param nin the nrrd to check
//! \param nDims the number of dimensions in the sequence elements
//! \param dims the array of sequence element dimensions
//! \return the dynamic sequence, or zero on error
Diderot_DynSeq_t *Diderot_DynSeqLoadBool (
    WorldPrefix_t *wrld,
    Nrrd *nin,
    unsigned int nDims,
    unsigned int *dims)
{
    unsigned int nValuesPerElem = CheckNrrd(wrld, nin, nDims, dims);
    size_t elemSz = sizeof(bool) * nValuesPerElem;

    if (nValuesPerElem == 0)
	return (Diderot_DynSeq_t *)0;

    if (NrrdTypeInfo[nin->type].isFloat) {
	Diderot_Error (wrld, "expected integer element type for bool sequence, but found %d\n", nin->type);
	return 0;
    }

  // get the number of elements
    size_t nElems = nin->axis[0].size;

  // allocate the dynamic sequence
    Diderot_DynSeq_t *seq = Diderot_DynSeqAlloc(elemSz, nElems);

  // initialize the sequence from the nrrd
    if (NrrdTypeInfo[nin->type].sizeb != sizeof(bool)) {
      // this is the slow path; we have to convert values as they are copied from the nrrd
	int (*loadFn)(const void *) = nrrdILoad[nin->type];
	bool *dst = (bool *)seq->data;
	char *src = (char *)nin->data;
	size_t srcElemSz = NrrdTypeInfo[nin->type].sizeb;
	for (size_t i = 0;  i < nElems * nValuesPerElem;  i++) {
	    *dst++ = loadFn(src) ? true : false;
	    src += srcElemSz;
	}
    }
    else {
      // this is the fast path, where we can just do a bulk memcpy
	memcpy (seq->data, nin->data, nElems * elemSz);
    }

    return seq;

}

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0