Skip to content

Commit

Permalink
Temporary handling for 1-D backing arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
cpiker committed Mar 16, 2020
1 parent 99ff7ce commit eac6bc0
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 15 deletions.
7 changes: 6 additions & 1 deletion src/das2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ static IDL_MEMINT g_aShape8[2];
#include "das2c_vars.c"
#include "das2c_props.c"
#include "das2c_data.c"
/*#include "das2c_convert.c"*/
#include "das2c_free.c"
#include "das2c_readhttp.c"

Expand Down Expand Up @@ -133,7 +134,11 @@ int IDL_Load(void){
{(IDL_SYSRTN_GENERIC)das2c_api_data}, "DAS2C_DATA",
D2C_DATA_MINA, D2C_DATA_MAXA, D2C_DATA_FLAG, NULL
},
{
/* {
{(IDL_SYSRTN_GENERIC)das2c_api_convert}, "DAS2C_CONVERT",
D2C_CONVERT_MINA, D2C_CONVERT_MAXA, D2C_CONVERT_FLAG, NULL
},
*/ {
{(IDL_SYSRTN_GENERIC)das2c_api_free}, "DAS2C_FREE",
D2C_FREE_MINA, D2C_FREE_MAXA, D2C_FREE_FLAG, NULL
},
Expand Down
50 changes: 50 additions & 0 deletions src/das2c_convert.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,57 @@

static IDL_VPTR das2c_api_convert(int argc, IDL_VPTR* argv)
{

DasVar* pVar = das2c_arg_to_var(argc, argv, 0, NULL, NULL, NULL, NULL);

/* Get new units */
if(argc < 2)
das2c_IdlMsgExit("Units not given in for argument 2");

if(argv[1]->type != IDL_TYP_STRING)
das2c_IdlMsgExit("Units string exected for argument 2");

const char* sNewUnits = IDL_VarGetString(argv[1]);
if(*sNewUnits == '\0') das2c_IdlMsgExit("Units string is empty");

das_units new_units = Units_fromStr(sNewUnits);
if(new_units == UNIT_INVALID)
das2c_error2idl();

if(! Units_canConvert(pVar->units, new_units) )
das2c_IdlMsgExit(
"Data in units of %s can't be converted to units of %s",
Units_toStr(pVar->units), sNewUnits
);

/* See if this variable has an array, if not there's no need to run
conversions here. */
if(pVar->vartype != D2V_ARRAY)
das2c_IdlMsgError(
"Unit conversions for virtual variables and sequences is not yet supported."
);

DasAry* pAry = DasVarAry_getArray(pVar);
if(pAry == NULL) das2c_IdlMsgError("das2C logic error in DasVarAry_getArray()");

/* get a pointer to the top of the variable and get it's length, ignore the
shape, we don't care for this operation. */
size_t u = 0, uVals = 0;
const byte* pSrc = DasAry_getIn(pAry, pVar-vt, DIM0, &uVals);

/* For time units we just have to run the function on everything (slow)
for non-time units we can get a factor and convert in a loop (fast) */
if(Units_haveCalRep(new_units)){
/* TODO: Update das2C to provide a function to get the factor and
the displacement so that times can be converted in a loop as well */


}
else{
double rFactor = Units_convertTo(

}


}

120 changes: 106 additions & 14 deletions src/das2c_data.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,46 @@ int das2c_vtype_2_idlcode(das_val_type vt)
}
}

/* ************************************************************************* */
/* Helper, a memset that handles multi-byte items, from das2C */

/* Use memcpy because the amount of data written in each call goes up
* exponentially and memcpy is freaking fast, much faster than a linear
* write loop for large arrays.
*/
byte* das2c_memset(byte* pDest, const byte* pSrc, size_t uElemSz, size_t uCount)
{
if(uCount == 0) return pDest; /* Successfully did nothing */
if(uElemSz == 0) das2c_IdlMsgExit("Invalid element size");
if(pDest == NULL) das2c_IdlMsgExit("Invalid destination");
if(pDest == NULL) das2c_IdlMsgExit("Invalid source");

size_t uDone = 0, uWrite = 0;

memcpy(pDest, pSrc, uElemSz);
uDone = 1;

byte* pWrite = pDest;
while(uDone < uCount){

if(uDone > (uCount - uDone))
uWrite = uCount - uDone;
else
uWrite = uDone;

pWrite += uDone*uElemSz;

/* write from ourselves so that the amount of data written each time
goes as the square of the number of loops */
memcpy(pWrite, pDest, uElemSz*uWrite);

uDone += uWrite;
}

return pDest;
}


/* ************************************************************************* */
/* API Function, careful with changes! */

Expand Down Expand Up @@ -194,59 +234,111 @@ static IDL_VPTR das2c_api_data(int argc, IDL_VPTR* argv)

/* Safety cast to const usage */
const DasDs* pDs = (const DasDs*)pvDs;
const DasDim* pDim = (const DasDim*)pvDim;
/* const DasDim* pDim = (const DasDim*)pvDim; */
const DasVar* pVar = (const DasVar*)pvVar;

ptrdiff_t aDsShape[DASIDX_MAX] = DASIDX_INIT_UNUSED;
int nDsRank = DasDs_shape(pDs, aDsShape);

ptrdiff_t aReqShape[DASIDX_MAX] = DASIDX_INIT_UNUSED; /* requested shape */
int nReqRank = -1;
/* ptrdiff_t aReqShape[DASIDX_MAX] = DASIDX_INIT_UNUSED; */ /* requested shape */
/* int nReqRank = -1; */

ptrdiff_t aVarShape[DASIDX_MAX] = DASIDX_INIT_UNUSED;
int nVarRank = DasVar_shape(pVar, aVarShape);

if(argc < 2){
/* Easy, requested shape is just the ds shape */
/*if(argc < 2){
/ * Easy, requested shape is just the ds shape * /
memcpy(aReqShape, aDsShape, nDsRank*sizeof(ptrdiff_t));
nReqRank = nDsRank;
}
else{
else{*/
if(argc > 1)
/* Hard, now we have to parse a slice structure */
das2c_IdlMsgExit("TODO: Handle slice structures.");

}

/* Grab the array if it exists */
DasAry* pvAry;
if( (pvAry = DasVarAry_getArray(pvVar)) == NULL){
das2c_IdlMsgExit("TODO: Handle virtual variables.");
}

/* Just wrap the top level array now as a test of index layout */
IDL_VPTR pRet = NULL;

/* low level byte pointer to head */
size_t uVals = 0;
size_t uValSz = 0;
size_t uBytes = 0;

/* Going to copy out data for now. Can change this if needed. */
/* Having IDL reach deep into protected buffers seems like a */
/* recipe for disaster */
const byte* pSrc = DasAry_getIn(pvAry, pVar->vt, DIM0, &uVals);
uValSz = DasAry_valSize(pvAry);
uBytes = uVals * uValSz;

/* just quick and dirty for today */

uBytes = uVals*DasAry_valSize(pvAry);
IDL_MEMINT dim[IDL_MAX_ARRAY_DIM];

/* Quick an dirty test for 'electric' with no slice */
IDL_MEMINT dim[2]; dim[0] = aReqShape[1]; dim[1] = aReqShape[0];
size_t u;
for(u = 0; u < nDsRank; ++u)
dim[u] = aDsShape[(nDsRank - 1) - u];

char* pDest = IDL_MakeTempArray(
das2c_vtype_2_idlcode(pVar->vt),
nReqRank,
nDsRank,
dim,
IDL_ARR_INI_NOP,
&pRet
);

/* Staying with quick and dirty. Here's the memcopys, thinking
* in C array layout...
*
* nReqRank == nVarRank -> nothing to do (for now)
* nReqRank > nVarRank
*
* if aVarShape [-3, N] repeated mem copy in a loop I times
* if aVarShape [N, -3] repeated mem set in a loop J times
*/

size_t I = 0;
size_t uSlowestBytes = 0;

if(nDsRank == nVarRank){
memcpy(pDest, pSrc, uBytes);
}
else{
if(nDsRank != 2) das2c_IdlMsgExit("Logic error 1 in das2c_data()");

/* Memcpy over the data block */
memcpy(pDest, pSrc, uBytes);
if(aVarShape[0] == DASIDX_UNUSED){

if(aVarShape[1] != aDsShape[1]) das2c_IdlMsgExit("Logic error 2 in das2c_data()");

/* for each I, copy a single run of J values */
for(I = 0; I < aDsShape[0]; ++I)
memcpy(pDest + (I*uBytes), pSrc, uBytes);
}
else{
if(aVarShape[1] == DASIDX_UNUSED){

if(aVarShape[0] != aDsShape[0]) das2c_IdlMsgExit("Logic error 3 in das2c_data()");

uSlowestBytes = aDsShape[0] * uValSz;

/* for each I, fill with a single I value J times */
for(I = 0; I < aDsShape[0]; ++I)
das2c_memset(
(byte*)(pDest + (I*uSlowestBytes)), pSrc + I*uValSz, uValSz, aDsShape[1]
);

}
else{
das2c_IdlMsgExit("Logic error 4 in das2c_data()");
}
}
}

return pRet;
}
Expand Down

0 comments on commit eac6bc0

Please sign in to comment.