The preceding example module, MakeX, manipulates regular (compactly encoded) positions less efficiently than it might. Note that the first call to DXGetArrayData in the file makex.c expands the compact coding of regular positions. MakeXEfficient eliminates this expansion.
MakeXEfficient has the same two inputs as MakeX: data, is of type field and has no default value; addend, is of type size, and has a default value of 1.
MakeXEfficient has the same output as MakeX: result is of type field.
Repeat Steps (1) through (5) of the preceding example (see 6.1 , "MakeX Module Example--Create New Positions"), using the file name "makexeff" in place of "makex." Step (5) will produce files makexeff.c, makexeff.mdf, and makexeff.make.
(6) Implement the MakeXEfficient function. MakeXEfficient uses Array-handling routines like those described in "Array Handling". But the main differences from MakeX are a handle for manipulating the input-positions Array, and a scratch buffer to hold the coordinates of a single position (three floating-point numbers in this example). Note that there is no call to DXGetArrayData for a pointer to the input-positions Array, thereby avoiding inefficiencies by not expanding regular positions.
Edit the makexeff.c file and replace the line
p_positions = (float*) DXGetArrayData(array)with the following:
if (!(handle = DXCreateArrayHandle(array))) goto error; scratch = DXAllocate(3*sizeof(float)); if (!scratch) goto error;
Another necessary code change is one inside the loop labeled "Now "draw" the x's" in the .c file--a call to the DXIterateArray routine to access the current position. Add the following pair of lines after the comment in the loop:
in_ptr = (float *)DXIterateArray(handle, i, in_ptr, scratch); inpoint = DXPt(in_ptr[0], in_ptr[1], in_ptr[2]);
Of course, the handle and the scratch buffer have to be freed at some point. Add the following lines before the MakeXEfficient_worker code near the end of the file:
/* Delete scratch and handle */ DXFree((Pointer)scratch); DXFreeArrayHandle(handle); /* return */ return OK; error: /* Delete scratch and handle */ DXFree((Pointer)scratch); DXFreeArrayHandle(handle); return ERROR;
Add the following lines after the first block of code in the doLeaf routine:
/* User-added declarations */ float *scratch, *in_ptr, size; Point inpoint, *out_pos_ptr; ArrayHandle handle; Array connections; Line *conn_ptr;
The file /usr/local/dx/samples/program_guide/makexeff.c contains a completed version of this program.
(7) To create a version of Data Explorer that includes the MakeXEfficient module, enter the command:
make -f makexeff.make dxexec
(You have now created an executable that contains the MakeX module.)
(8) To invoke this version, enter:
dx -mdf ./makexeff.mdf -exec ./dxexec
This command starts Data Explorer (the makexeff.mdf file tells the graphical user interface about MakeX and its inputs and outputs). The executable dxexec invoked here is the one created in Step 6.
(9) With this version of Data Explorer you can now run any visual program that uses the MakeXEfficient module. One such program is /usr/local/dx/samples/program_guide/makex_efficient.net