10. Examples

This chapter contains example CEETRON SAM programs. The source code for all examples resides in CeetronSAM/src/sam/base/exam.

10.1. Example 1, Demonstration of Object Collections

This example provides some simple illustrations of the use the HashTable, VHashTable, IntVHash, List, Stack and Dictionary collection modules. In general the collection objects store pointers (CEETRON SAM type Vobject). In CEETRON SAM these pointers are the pointers to other CEETRON SAM objects. The type Vobject* is the C language type void*, so that any void* type may be stored in collection objects. In this example pointers to strings as well as simple integers cast to pointer type are used for illustration.

#include <stdio.h>
#include "sam/base/base.h"
#include "sam/base/license.h"
#include "sam/CEETRON_SAM_license.h"

static void
test_hashtable(void);
static void
test_vhashtable(void);
static void
test_intvhash(void);
static void
test_list(void);
static void
test_stack(void);
static void
test_dictionary(void);
static void
print_integer(Vint* n);

/*----------------------------------------------------------------------
                      Test and demonstrate collection objects
----------------------------------------------------------------------*/
int
main()
{
    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    test_hashtable();
    test_vhashtable();
    test_intvhash();
    test_list();
    test_stack();
    test_dictionary();
    return 0;
}

/*----------------------------------------------------------------------
                      HashTable
----------------------------------------------------------------------*/
static void
test_hashtable(void)
{
    Vint i;
    vsy_HashTable* htab;
    Vint num, count, key, keys[10];
    Vchar* str;

    printf("\nHashTable test\n");

    /* instance HashTable object */
    htab = vsy_HashTableBegin();
    /* set initial allocation to two objects */
    vsy_HashTableDef(htab, 2);
    /* inquire and count */
    vsy_HashTableInq(htab, &num);
    vsy_HashTableCount(htab, &count);
    printf("num = %d, count = %d\n", num, count);

    /* insert some simple "string" objects */
    vsy_HashTableInsert(htab, 3, (Vobject*)"three");
    vsy_HashTableInsert(htab, 0, (Vobject*)"zero");
    vsy_HashTableInsert(htab, 2, (Vobject*)"two");
    vsy_HashTableInsert(htab, 1, (Vobject*)"one");

    /* count and find maximum key */
    vsy_HashTableCount(htab, &count);
    vsy_HashTableMaxKey(htab, &key);
    printf("count= %d, max key= %d\n", count, key);

    /* get all keys */
    vsy_HashTableAllKeys(htab, keys);
    for (i = 0; i < count; i++) {
        printf("key = %d\n", keys[i]);
    }
    /* remove a couple */
    vsy_HashTableRemove(htab, 2);
    vsy_HashTableRemove(htab, 0);
    /* add some */
    vsy_HashTableInsert(htab, 4, (Vobject*)"four");
    vsy_HashTableInsert(htab, 15, (Vobject*)"fifteen");

    /* now inquire and count */
    vsy_HashTableInq(htab, &num);
    vsy_HashTableCount(htab, &count);
    printf("num = %d, count = %d\n", num, count);

    /* InitIter,NextIter traversal */
    vsy_HashTableInitIter(htab);
    while (vsy_HashTableNextIter(htab, &key, (Vobject**)&str), str != NULL) {
        printf("key = %d, string = %s\n", key, str);
    }
    /* delete object */
    vsy_HashTableEnd(htab);
}

/*----------------------------------------------------------------------
                      VHashTable
----------------------------------------------------------------------*/
static void
test_vhashtable(void)
{
    vsy_VHashTable* htab;
    Vint size, num, count, key[3];
    Vchar* str;

    printf("\nVHashTable test\n");

    /* instance HashTable object */
    htab = vsy_VHashTableBegin();
    /* set initial allocation to three keys and two objects */
    vsy_VHashTableDef(htab, 3, 2);
    /* inquire and count */
    vsy_VHashTableInq(htab, &size, &num);
    vsy_VHashTableCount(htab, &count);
    printf("size = %d, num = %d, count = %d\n", size, num, count);

    /* insert some simple "string" objects */
    key[0] = 1;
    key[1] = 2;

    key[2] = 3;
    vsy_VHashTableInsert(htab, key, (Vobject*)"three");
    key[2] = 0;
    vsy_VHashTableInsert(htab, key, (Vobject*)"zero");
    key[2] = 2;
    vsy_VHashTableInsert(htab, key, (Vobject*)"two");
    key[2] = 1;
    vsy_VHashTableInsert(htab, key, (Vobject*)"one");

    /* count */
    vsy_VHashTableCount(htab, &count);
    printf("count= %d\n", count);

    /* remove a couple */
    key[2] = 2;
    vsy_VHashTableRemove(htab, key);
    key[2] = 0;
    vsy_VHashTableRemove(htab, key);
    /* add some */
    key[2] = 4;
    vsy_VHashTableInsert(htab, key, (Vobject*)"four");
    key[2] = 15;
    vsy_VHashTableInsert(htab, key, (Vobject*)"fifteen");

    /* now inquire and count */
    vsy_VHashTableInq(htab, &size, &num);
    vsy_VHashTableCount(htab, &count);
    printf("size = %d, num = %d, count = %d\n", size, num, count);

    /* InitIter,NextIter traversal */
    vsy_VHashTableInitIter(htab);
    while (vsy_VHashTableNextIter(htab, key, (Vobject**)&str), str != NULL) {
        printf("key = %d %d %d, string = %s\n", key[0], key[1], key[2], str);
    }
    /* delete object */
    vsy_VHashTableEnd(htab);
}

/*----------------------------------------------------------------------
                      IntVHash
----------------------------------------------------------------------*/
static void
test_intvhash(void)
{
    vsy_IntVHash* ivhash;
    Vint size, num, count, key[3], ival;

    printf("\nIntVHash test\n");

    /* instance IntVHash object */
    ivhash = vsy_IntVHashBegin();
    /* set initial allocation to three keys and two objects */
    vsy_IntVHashDef(ivhash, 3, 2);
    /* inquire and count */
    vsy_IntVHashInq(ivhash, &size, &num);
    vsy_IntVHashCount(ivhash, &count);
    printf("size = %d, num = %d, count = %d\n", size, num, count);

    /* insert some simple "string" objects */
    key[0] = 1;
    key[1] = 2;

    key[2] = 3;
    vsy_IntVHashInsert(ivhash, key, 3);
    key[2] = 2;
    vsy_IntVHashInsert(ivhash, key, 2);
    key[2] = 1;
    vsy_IntVHashInsert(ivhash, key, 1);

    /* count */
    vsy_IntVHashCount(ivhash, &count);
    printf("count= %d\n", count);

    /* remove a couple */
    key[2] = 2;
    vsy_IntVHashRemove(ivhash, key);
    key[2] = 0;
    vsy_IntVHashRemove(ivhash, key);
    /* add some */
    key[2] = 4;
    vsy_IntVHashInsert(ivhash, key, 4);
    key[2] = 15;
    vsy_IntVHashInsert(ivhash, key, 15);

    /* now inquire and count */
    vsy_IntVHashInq(ivhash, &size, &num);
    vsy_IntVHashCount(ivhash, &count);
    printf("size = %d, num = %d, count = %d\n", size, num, count);

    /* InitIter,NextIter traversal */
    vsy_IntVHashInitIter(ivhash);
    while (vsy_IntVHashNextIter(ivhash, key, &ival), ival != 0) {
        printf("key = %d %d %d, ival = %d\n", key[0], key[1], key[2], ival);
    }
    /* delete object */
    vsy_IntVHashEnd(ivhash);
}

/*----------------------------------------------------------------------
                      List
----------------------------------------------------------------------*/
static void
test_list(void)
{
    vsy_List* list;
    Vint values[3] = {1, 10, 20};

    printf("\nList test\n");
    /* instance object */
    list = vsy_ListBegin();
    /* insert some numbers */
    vsy_ListInsert(list, values[0], (Vobject*)&values[0]);
    vsy_ListInsert(list, values[1], (Vobject*)&values[1]);
    vsy_ListInsert(list, values[2], (Vobject*)&values[2]);
    /* ForEach facility to list contents */
    vsy_ListForEach(list, (Vfunc1*)print_integer);
    printf("\n");
    /* remove an object and list contents again */
    vsy_ListRemove(list, values[1]);
    vsy_ListForEach(list, (Vfunc1*)print_integer);
    printf("\n");
    /* delete object */
    vsy_ListEnd(list);
}

/*----------------------------------------------------------------------
                      Stack
----------------------------------------------------------------------*/
static void
test_stack(void)
{
    vsy_Stack* stack;
    Vint values[3] = {1, 10, 20};

    printf("\nStack test\n");
    /* instance object */
    stack = vsy_StackBegin();

    /* push some numbers */
    vsy_StackPush(stack, (Vobject*)&values[0]);
    vsy_StackPush(stack, (Vobject*)&values[1]);
    vsy_StackPush(stack, (Vobject*)&values[2]);
    /* ForEach facility to list contents */
    vsy_StackForEach(stack, (Vfunc1*)print_integer);
    printf("\n");
    /* pop an object off and list contents again*/
    vsy_StackPop(stack);
    vsy_StackForEach(stack, (Vfunc1*)print_integer);
    printf("\n");
    /* delete object */
    vsy_StackEnd(stack);
}

/*----------------------------------------------------------------------
                      Dictionary
----------------------------------------------------------------------*/
static void
test_dictionary(void)
{
    vsy_Dictionary* dict;
    Vint num, count;
    Vchar* name;
    Vchar* str;

    printf("\nDictionary test\n");

    /* instance Dictionary object */
    dict = vsy_DictionaryBegin();
    /* set initial allocation to two objects */
    vsy_DictionaryDef(dict, 2);
    /* inquire and count */
    vsy_DictionaryInq(dict, &num);
    vsy_DictionaryCount(dict, &count);
    printf("num = %d, count = %d\n", num, count);

    /* insert some simple "string" objects */
    vsy_DictionaryInsert(dict, "Three", (Vobject*)"three");
    vsy_DictionaryInsert(dict, "Zero", (Vobject*)"zero");
    vsy_DictionaryInsert(dict, "Two", (Vobject*)"two");
    vsy_DictionaryInsert(dict, "One", (Vobject*)"one");
    /* remove a couple */
    vsy_DictionaryRemove(dict, "Two");
    vsy_DictionaryRemove(dict, "Zero");
    /* add some */
    vsy_DictionaryInsert(dict, "Four", (Vobject*)"four");
    vsy_DictionaryInsert(dict, "Fifteen", (Vobject*)"fifteen");

    /* now inquire and count */
    vsy_DictionaryInq(dict, &num);
    vsy_DictionaryCount(dict, &count);
    printf("num = %d, count = %d\n", num, count);

    /* InitIter,NextIter traversal */
    vsy_DictionaryInitIter(dict);
    while (vsy_DictionaryNextIter(dict, &name, (Vobject**)&str), str != NULL) {
        printf("name = %s, string = %s\n", name, str);
    }
    /* reinsert name and lookup */
    vsy_DictionaryInsert(dict, "Three", (Vobject*)"3");
    vsy_DictionaryLookup(dict, "Three", (Vobject**)&str);
    printf("name = %s, string = %s\n", "Three", str);

    /* delete object */
    vsy_DictionaryEnd(dict);
}

/*----------------------------------------------------------------------
                      print utility
----------------------------------------------------------------------*/
static void
print_integer(Vint* n)
{
    printf("%d ", *n);
}

10.2. Example 2, Demonstration of Numeric Type Collections

This example illustrates the use of the BitVec, DblVec, IntVec, IntDict, IntHash and IntQue numeric type collection modules. These modules are designed to store individual bit vales, double precision value, and integer values. A simple indexed vector representation is available for bits, doubles and integers. Hashtable, queue and dictionary storage are available for integers.

Three BitVec objects are instanced and various operations are performed on the bit vectors. The results of these operations are printed. Initially a bit vector X is instanced and the bits are set to one for indices 1,3 and 5 using vsy_BitVecSet().. Any unreferenced intermediate bit indices are initially set to zero. Two additional bit vectors, Y and Z are instanced and various Boolean operations are performed. Note that by default the lowest bit index is zero. The function vsy_BitVecSetParami() is used to exclude the zero bit index in bit vector Y.

The DblVec and IntVec modules are identical except for the numeric data types which they store. Note that any unset value will be returned as a zero. The IntDict and IntHash modules are dictionary and hashtable storage for integer values which are very similar to the Dictionary and HashTable storage for objects. The IntQue module is a first-in, first-out access mechanism for integers.

#include <stdio.h>
#include "sam/base/base.h"
#include "sam/base/license.h"
#include "sam/CEETRON_SAM_license.h"

static void
test_bitvec(void);
static void
test_dblvec(void);
static void
test_intvec(void);
static void
test_inthash(void);
static void
test_intdict(void);
static void
test_intstack(void);
static void
test_intque(void);
static void
print_bitvector(vsy_BitVec* bitvec, Vchar* stg);

/*----------------------------------------------------------------------
                      Demonstration of Numeric Type Collections
----------------------------------------------------------------------*/
int
main()
{
    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    test_bitvec();
    test_dblvec();
    test_intvec();
    test_intdict();
    test_intstack();
    test_inthash();
    test_intque();
    return 0;
}

/*----------------------------------------------------------------------
                      BitVec
----------------------------------------------------------------------*/
static void
test_bitvec(void)
{
    vsy_BitVec *bitvecx, *bitvecy, *bitvecz;
    Vint index, maxindex, flag, count;

    printf("\nBitVec test\n");

    /* instance object */
    bitvecx = vsy_BitVecBegin();

    /* set some indices */
    vsy_BitVecSet(bitvecx, 1, 1);
    vsy_BitVecSet(bitvecx, 3, 1);
    vsy_BitVecSet(bitvecx, 5, 1);

    /* get max index referenced */
    vsy_BitVecInq(bitvecx, &maxindex);
    printf("maximum index = %d\n", maxindex);

    /* test get */
    for (index = 0; index <= maxindex; index++) {
        vsy_BitVecGet(bitvecx, index, &flag);
        printf("index %d = %d\n", index, flag);
    }
    /* count flags */
    vsy_BitVecCount(bitvecx, &count);
    printf("number of flags = %d\n", count);

    /* test iteration with print */
    print_bitvector(bitvecx, (Vchar*)"X");

    /* boolean operations */
    bitvecy = vsy_BitVecBegin();
    bitvecz = vsy_BitVecBegin();

    /* copy the bit vector to bit vector x */
    vsy_BitVecBoolean(bitvecy, BITVEC_SET, bitvecx);
    vsy_BitVecSet(bitvecy, 5, 0);
    print_bitvector(bitvecy, (Vchar*)"Y is a copy of X with index 5 set to zero");

    vsy_BitVecBoolean(bitvecz, BITVEC_SET, bitvecy);
    vsy_BitVecBoolean(bitvecz, BITVEC_AND, bitvecx);
    print_bitvector(bitvecz, (Vchar*)"Z is X AND Y");

    vsy_BitVecBoolean(bitvecz, BITVEC_SET, bitvecy);
    vsy_BitVecBoolean(bitvecz, BITVEC_OR, bitvecx);
    print_bitvector(bitvecz, (Vchar*)"Z is X OR Y");

    vsy_BitVecBoolean(bitvecz, BITVEC_SET, bitvecy);
    vsy_BitVecBoolean(bitvecz, BITVEC_XOR, bitvecx);
    print_bitvector(bitvecz, (Vchar*)"Z is X XOR Y");

    vsy_BitVecComplement(bitvecy);
    print_bitvector(bitvecy, (Vchar*)"Y is NOT Y");

    vsy_BitVecSetParami(bitvecy, VSY_INCLUDEZERO, SYS_OFF);
    print_bitvector(bitvecy, (Vchar*)"exclude index zero from Y");

    /* delete object */
    vsy_BitVecEnd(bitvecx);
    vsy_BitVecEnd(bitvecy);
    vsy_BitVecEnd(bitvecz);
}

/*----------------------------------------------------------------------
                      print utility
----------------------------------------------------------------------*/
static void
print_bitvector(vsy_BitVec* bitvec, Vchar* stg)
{
    Vint index;

    /* print a title */
    printf("\n%s\n", stg);
    /* print indices of all one bits */
    vsy_BitVecInitIter(bitvec);
    while (vsy_BitVecNextIter(bitvec, &index), index >= 0) {
        printf("index = %d\n", index);
    }
}

/*----------------------------------------------------------------------
                      DblVec
----------------------------------------------------------------------*/
static void
test_dblvec(void)
{
    vsy_DblVec* dblvec;
    Vint num, count;
    Vint index;
    Vdouble val, *ptr;

    printf("\nDblVec test\n");

    /* instance DblVec object */
    dblvec = vsy_DblVecBegin();
    /* set initial allocation to two integers */
    vsy_DblVecDef(dblvec, 2);
    /* inquire and count */
    vsy_DblVecInq(dblvec, &num);
    vsy_DblVecCount(dblvec, &count);
    printf("num = %d, count = %d\n", num, count);

    /* insert some integers */
    vsy_DblVecSet(dblvec, 5, 105.);
    vsy_DblVecSet(dblvec, 3, 103.);
    vsy_DblVecSet(dblvec, 7, 107.);
    vsy_DblVecSet(dblvec, 2, 102.);
    vsy_DblVecSet(dblvec, 1, 101.);

    /* get a set value */
    vsy_DblVecGet(dblvec, 5, &val);
    printf("value = %f\n", val);
    /* get an unset value */
    vsy_DblVecGet(dblvec, 6, &val);
    printf("value = %f\n", val);

    /* get pointer, index starts from 1 */
    vsy_DblVecGetPtr(dblvec, &ptr);
    vsy_DblVecInq(dblvec, &num);
    for (index = 1; index <= num; index++) {
        printf("index= %d, value= %f\n", index, ptr[index - 1]);
    }
    /* InitIter,NextIter traversal */
    vsy_DblVecInitIter(dblvec);
    while (vsy_DblVecNextIter(dblvec, &index, &val), index != -1) {
        printf("index = %d, value = %f\n", index, val);
    }
    /* clear */
    vsy_DblVecClear(dblvec);
    /* inquire and count */
    vsy_DblVecInq(dblvec, &num);
    vsy_DblVecCount(dblvec, &count);
    printf("num = %d, count = %d\n", num, count);

    /* delete object */
    vsy_DblVecEnd(dblvec);
}

/*----------------------------------------------------------------------
                      IntVec
----------------------------------------------------------------------*/
static void
test_intvec(void)
{
    vsy_IntVec* intvec;
    Vint num, count;
    Vint index;
    Vint val, *ptr;

    printf("\nIntVec test\n");

    /* instance IntVec object */
    intvec = vsy_IntVecBegin();
    /* set initial allocation to two integers */
    vsy_IntVecDef(intvec, 2);
    /* inquire and count */
    vsy_IntVecInq(intvec, &num);
    vsy_IntVecCount(intvec, &count);
    printf("num = %d, count = %d\n", num, count);

    /* insert some integers */
    vsy_IntVecSet(intvec, 5, 105);
    vsy_IntVecSet(intvec, 3, 103);
    vsy_IntVecSet(intvec, 7, 107);
    vsy_IntVecSet(intvec, 2, 102);
    vsy_IntVecSet(intvec, 1, 101);

    /* get a set value */
    vsy_IntVecGet(intvec, 5, &val);
    printf("value = %d\n", val);
    /* get an unset value */
    vsy_IntVecGet(intvec, 6, &val);
    printf("value = %d\n", val);

    /* get pointer, index starts from 1 */
    vsy_IntVecGetPtr(intvec, &ptr);
    vsy_IntVecInq(intvec, &num);
    for (index = 1; index <= num; index++) {
        printf("index= %d, value= %d\n", index, ptr[index - 1]);
    }
    /* InitIter,NextIter traversal */
    vsy_IntVecInitIter(intvec);
    while (vsy_IntVecNextIter(intvec, &index, &val), index != -1) {
        printf("index = %d, value = %d\n", index, val);
    }
    /* clear */
    vsy_IntVecClear(intvec);
    /* inquire and count */
    vsy_IntVecInq(intvec, &num);
    vsy_IntVecCount(intvec, &count);
    printf("num = %d, count = %d\n", num, count);

    /* delete object */
    vsy_IntVecEnd(intvec);
}

/*----------------------------------------------------------------------
                      IntDict
----------------------------------------------------------------------*/
static void
test_intdict(void)
{
    vsy_IntDict* intdict;
    Vint num, count;
    Vchar* name;
    Vint val;

    printf("\nIntDict test\n");

    /* instance IntDict object */
    intdict = vsy_IntDictBegin();
    /* set initial allocation to two integers */
    vsy_IntDictDef(intdict, 2);
    /* inquire and count */
    vsy_IntDictInq(intdict, &num);
    vsy_IntDictCount(intdict, &count);
    printf("num = %d, count = %d\n", num, count);

    /* insert some integers */
    vsy_IntDictInsert(intdict, "105", 105);
    vsy_IntDictInsert(intdict, "103", 103);
    vsy_IntDictInsert(intdict, "100", 100);
    vsy_IntDictInsert(intdict, "102", 102);
    vsy_IntDictInsert(intdict, "101", 101);

    /* lookup a legal value */
    vsy_IntDictLookup(intdict, "101", &val);
    printf("value = %d\n", val);
    /* lookup a illegal value */
    vsy_IntDictLookup(intdict, "104", &val);
    printf("value = %d\n", val);

    /* now inquire and count */
    vsy_IntDictInq(intdict, &num);
    vsy_IntDictCount(intdict, &count);
    printf("num = %d, count = %d\n", num, count);

    /* InitIter,NextIter traversal */
    vsy_IntDictInitIter(intdict);
    while (vsy_IntDictNextIter(intdict, &name, &val), name != NULL) {
        printf("name = %s, value = %d\n", name, val);
    }
    /* clear */
    vsy_IntDictClear(intdict);
    /* inquire and count */
    vsy_IntDictInq(intdict, &num);
    vsy_IntDictCount(intdict, &count);
    printf("num = %d, count = %d\n", num, count);

    /* delete object */
    vsy_IntDictEnd(intdict);
}

/*----------------------------------------------------------------------
                      IntStack
----------------------------------------------------------------------*/
static void
test_intstack(void)
{
    vsy_IntStack* intstack;
    Vint id, num;

    printf("\nIntStack test\n");

    /* instance IntStack object */
    intstack = vsy_IntStackBegin();
    /* set initial allocation to 20 integers */
    vsy_IntStackDef(intstack, 20);

    /* push some integers */
    vsy_IntStackPush(intstack, 105);
    vsy_IntStackPush(intstack, 103);
    vsy_IntStackPush(intstack, 100);
    vsy_IntStackPush(intstack, 102);
    vsy_IntStackPush(intstack, 101);

    vsy_IntStackPrint(intstack);

    vsy_IntStackPush(intstack, 101);
    vsy_IntStackPrint(intstack);

    /* pop */
    vsy_IntStackPop(intstack, &id);
    printf("id = %d\n", id);
    vsy_IntStackPrint(intstack);

    /* clear */
    vsy_IntStackClear(intstack);
    vsy_IntStackPrint(intstack);

    vsy_IntStackCount(intstack, &num);
    printf("num = %d\n", num);

    /* delete object */
    vsy_IntStackEnd(intstack);
}

/*----------------------------------------------------------------------
                      IntHash
----------------------------------------------------------------------*/
static void
test_inthash(void)
{
    vsy_IntHash* inthash;
    Vint num, count, key;
    Vint val;

    printf("\nIntHash test\n");

    /* instance IntHash object */
    inthash = vsy_IntHashBegin();
    /* set initial allocation to two integers */
    vsy_IntHashDef(inthash, 2);
    /* inquire and count */
    vsy_IntHashInq(inthash, &num);
    vsy_IntHashCount(inthash, &count);
    printf("num = %d, count = %d\n", num, count);

    /* insert some integers */
    vsy_IntHashInsert(inthash, 5, 105);
    vsy_IntHashInsert(inthash, 3, 103);
    vsy_IntHashInsert(inthash, 0, 100);
    vsy_IntHashInsert(inthash, 2, 102);
    vsy_IntHashInsert(inthash, 1, 101);

    /* lookup a legal value */
    vsy_IntHashLookup(inthash, 1, &val);
    printf("value = %d\n", val);
    /* lookup a illegal value */
    vsy_IntHashLookup(inthash, 4, &val);
    printf("value = %d\n", val);

    /* now inquire and count */
    vsy_IntHashInq(inthash, &num);
    vsy_IntHashCount(inthash, &count);
    printf("num = %d, count = %d\n", num, count);

    /* InitIter,NextIter traversal */
    vsy_IntHashInitIter(inthash);
    while (vsy_IntHashNextIter(inthash, &key, &val), val != 0) {
        printf("key = %d, value = %d\n", key, val);
    }
    /* delete object */
    vsy_IntHashEnd(inthash);
}

/*----------------------------------------------------------------------
                      IntQue
----------------------------------------------------------------------*/
static void
test_intque(void)
{
    vsy_IntQue* intque;
    Vint num, count;
    Vint val;

    printf("\nIntQue test\n");

    /* instance IntQue object */
    intque = vsy_IntQueBegin();
    /* set initial allocation to two integers */
    vsy_IntQueDef(intque, 2);
    /* inquire and count */
    vsy_IntQueInq(intque, &num);
    vsy_IntQueCount(intque, &count);
    printf("num = %d, count = %d\n", num, count);

    /* put some integers */
    vsy_IntQuePut(intque, 105);
    vsy_IntQuePut(intque, 103);
    vsy_IntQuePut(intque, 100);
    vsy_IntQuePut(intque, 102);
    vsy_IntQuePut(intque, 101);

    /* reference */
    vsy_IntQueRef(intque, &val);
    printf("value = %d\n", val);

    /* get */
    vsy_IntQueGet(intque, &val);
    printf("value = %d\n", val);

    /* now inquire and count */
    vsy_IntQueInq(intque, &num);
    vsy_IntQueCount(intque, &count);
    printf("num = %d, count = %d\n", num, count);

    /* delete object */
    vsy_IntQueEnd(intque);
}

10.3. Example 3, Demonstration of Property Sets

This example illustrates the use of the PropSet property set module. A single PropSet object is instanced and a number of property types are inserted. Note that the PropSet object makes a copy of all the inserted properties. The total number of defined properties is counted. Finally all the properties inserted in the PropSet object are printed.

#include <stdio.h>
#include "sam/base/base.h"
#include "sam/base/license.h"
#include "sam/CEETRON_SAM_license.h"

static void
print_propset(vsy_PropSet* propset, Vchar* stg);

/*----------------------------------------------------------------------
                      Test and demonstrate property sets
----------------------------------------------------------------------*/
int
main()
{
    vsy_PropSet* propset;
    Vint ivalue[16];
    Vdouble dvalue[16];
    Vobject* pvalue[16];
    Vint count;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    printf("\nPropSet test\n");

    /* instance object */
    propset = vsy_PropSetBegin();

    /* insert some properties */
    vsy_PropSetInserti(propset, "integer", 1);
    vsy_PropSetInsertf(propset, "float", 2.);
    ivalue[0] = 10;
    ivalue[1] = 11;
    ivalue[2] = 12;
    vsy_PropSetInsertiv(propset, "integer vector", 3, ivalue);
    vsy_PropSetInsertc(propset, "string", (Vchar*)"Test and demonstrate property set");
    dvalue[0] = 100.;
    dvalue[1] = 101.;
    vsy_PropSetInsertdv(propset, "double vector", 2, dvalue);
    pvalue[0] = (void*)1;
    pvalue[1] = (void*)2;
    vsy_PropSetInsertpv(propset, "object vector", 2, pvalue);

    vsy_PropSetCount(propset, &count);
    printf("number of properties = %d\n", count);

    print_propset(propset, (Vchar*)"Property Set");

    /* delete object */
    vsy_PropSetEnd(propset);
    return 0;
}

/*----------------------------------------------------------------------
                      print utility
----------------------------------------------------------------------*/
static void
print_propset(vsy_PropSet* propset, Vchar* stg)
{
    Vchar* name;
    Vint type, num, size;
    Vint i;
    Vint ivalue[16];
    Vfloat fvalue[16];
    Vdouble dvalue[16];
    Vobject* pvalue[16];
    Vchar cvalue[256];

    /* print a title */
    printf("\n%s\n", stg);

    /* print values of all entries */
    vsy_PropSetInitIter(propset);
    while (vsy_PropSetNextIter(propset, &name), name != NULL) {
        vsy_PropSetLookup(propset, name, &type, &num, &size);
        printf("\nProperty name = %s\n", name);
        printf(" type         = %d\n", type);
        printf(" num          = %d\n", num);
        printf(" size         = %d\n", size);
        if (type == SYS_INTEGER) {
            vsy_PropSetLookupInteger(propset, name, ivalue);
            for (i = 0; i < num; i++) {
                printf("  prop[%2d]    = %d\n", i, ivalue[i]);
            }
        }
        else if (type == SYS_FLOAT) {
            vsy_PropSetLookupFloat(propset, name, fvalue);
            for (i = 0; i < num; i++) {
                printf("  prop[%2d]    = %f\n", i, fvalue[i]);
            }
        }
        else if (type == SYS_DOUBLE) {
            vsy_PropSetLookupDouble(propset, name, dvalue);
            for (i = 0; i < num; i++) {
                printf("  prop[%2d]    = %f\n", i, dvalue[i]);
            }
        }
        else if (type == SYS_OBJECT) {
            vsy_PropSetLookupObject(propset, name, pvalue);
            for (i = 0; i < num; i++) {
                printf("  prop[%2d]    = %p\n", i, pvalue[i]);
            }
        }
        else if (type == SYS_STRING) {
            vsy_PropSetLookupString(propset, name, cvalue);
            printf("  prop        = %s\n", cvalue);
        }
    }
}

10.4. Example 4, Demonstration of Random Number Generation

This example illustrates the use of the Random random number module. A single Random object is instanced and 10 random numbers are generated and printed using the default seed. Then a user specified seed is set using vsy_RandomInit() and 10 more random numbers are generated. Note that Random will generate an identical sequence of random numbers from the same seed.

#include <stdio.h>
#include "sam/base/base.h"
#include "sam/base/license.h"
#include "sam/CEETRON_SAM_license.h"

/*----------------------------------------------------------------------
                      test and demonstrate random object
----------------------------------------------------------------------*/
int
main()
{
    int i;
    Vint ir;
    Vfloat fr;
    vsy_Random* random;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* instance Random object */
    random = vsy_RandomBegin();

    /* generate and print 10 random numbers */
    printf("Default seed\n");
    for (i = 0; i < 10; i++) {
        vsy_RandomNumber(random, &fr);
        printf("i,fr %d %f\n", i, fr);
    }
    /* set a seed and generate 10 more random numbers */
    printf("User seed\n");
    vsy_RandomInit(random, 70946);
    for (i = 0; i < 10; i++) {
        vsy_RandomNumber(random, &fr);
        printf("i,fr %d %f\n", i, fr);
    }
    for (i = 0; i < 10; i++) {
        vsy_RandomInteger(random, &ir);
        printf("i,ir %d %d\n", i, ir);
    }
    /* destroy Random object */
    vsy_RandomEnd(random);
    return 0;
}

10.5. Example 5, Creating a Derived Class in C++ Using a Base Random Class

This example is an extension of Example 4 and illustrates creating a derived class, der_Random, in C++ using Random as a public base class. The derived class extends the base class by adding the function, Boolean, to return random boolean values (an integer 0 or 1).

#include <stdio.h>
#include "sam/base/base.h"

class der_Random: public vsy_Random {
  public:
    void
    Boolean(Vint*);
};

void
der_Random::Boolean(Vint* boolean)
{
    Vfloat r;

    vsy_Random::Number(&r);
    if (r < .5) {
        *boolean = 0;
    }
    else {
        *boolean = 1;
    }
}

/*----------------------------------------------------------------------
                      demonstrate derived der_Random object
----------------------------------------------------------------------*/
int
main()
{
    int i;
    Vfloat f;
    Vint b;
    der_Random* random;

    /* instance derived Random object */
    random = new der_Random();

    /* generate and print 10 random numbers */
    printf("Default seed\n");
    for (i = 0; i < 10; i++) {
        random->Number(&f);
        printf("i,f %d %f\n", i, f);
    }
    /* set a seed and generate 10 more random numbers */
    printf("User seed\n");
    random->Init(70946);
    for (i = 0; i < 10; i++) {
        random->Number(&f);
        printf("i,f %d %f\n", i, f);
    }
    /* generate 10 random Booleans */
    printf("Added function Boolean\n");
    for (i = 0; i < 10; i++) {
        random->Boolean(&b);
        printf("i,b %d %d\n", i, b);
    }
    /* destroy derived Random object */
    delete random;
    return 0;
}

10.6. Example 6, Install User Error Handler and Memory Management

This example illustrates the procedure for installing a user error handler and user memory management functions. The user error handler is installed using vut_ErrorSetHandler(). When installed it acts as the error handler for all objects. The user error handler in this example prints the data passed in the argument list and uses the vut_ErrorString() function to interpret the errorflag argument. The user memory management functions are set using vut_MemorySetFunctions() and like the user error handler act as the memory management system for all objects.

A simple List object is instanced and vsy_ListInsert() is called with an improper argument to generate an error. The user error handler is invoked at this point. The default error handler is reinstalled by calling vut_ErrorSetHandler() with a NULL argument, vsy_ListInsert() is called again with an improper argument and the default handler is invoked. Notice the printed output of the user defined memory management functions. User defined memory management functions should only be installed once before any objects are instanced and should remain in effect until all objects are destroyed.

#include <stdlib.h>
#include "sam/base/base.h"
#include "sam/base/license.h"
#include "sam/CEETRON_SAM_license.h"

/* list of system error types */
static Vint errortable[SYS_ERROR_MAX] = {SYS_ERROR_VALUE,      SYS_ERROR_ENUM,      SYS_ERROR_OBJECTTYPE, SYS_ERROR_MEMORY,
                                         SYS_ERROR_NULLOBJECT, SYS_ERROR_FILE,      SYS_ERROR_COMPUTE,    SYS_ERROR_OPERATION,
                                         SYS_ERROR_OVERFLOW,   SYS_ERROR_UNDERFLOW, SYS_ERROR_UNKNOWN,    SYS_ERROR_FORMAT,
                                         SYS_ERROR_SEVERE};

static const Vchar* errorname[SYS_ERROR_MAX] = {
"SYS_ERROR_VALUE",   "SYS_ERROR_ENUM",    "SYS_ERROR_OBJECTTYPE", "SYS_ERROR_MEMORY",   "SYS_ERROR_NULLOBJECT",
"SYS_ERROR_FILE",    "SYS_ERROR_COMPUTE", "SYS_ERROR_OPERATION",  "SYS_ERROR_OVERFLOW", "SYS_ERROR_UNDERFLOW",
"SYS_ERROR_UNKNOWN", "SYS_ERROR_FORMAT",  "SYS_ERROR_SEVERE"};

static void
user_ErrorHandler(const Vchar* funcname, Vint errorflag, const Vchar* message)
{
    printf("\n");
    if (funcname) {
        printf("function : %s\n", funcname);
    }
    if (errorflag > 0 && errorflag <= SYS_ERROR_MAX) {
        printf("error    : %s\n", vut_ErrorString(errorflag));
    }
    if (strlen(message)) {
        printf("message  : %s\n", message);
    }
}

static void*
user_malloc(size_t siz)
{
    printf("\n");
    printf("malloc %lu bytes\n", (unsigned long)siz);
    return (malloc(siz));
}

static void*
user_realloc(void* ptr, size_t siz)
{
    printf("\n");
    printf("realloc %p ptr, %lu bytes\n", ptr, (unsigned long)siz);
    return (realloc(ptr, siz));
}

static void
user_free(void* ptr)
{
    printf("\n");
    printf("free %p ptr\n", ptr);
    free(ptr);
}

/*----------------------------------------------------------------------
                      Install user error handler and memory management
----------------------------------------------------------------------*/
int
main()
{
    Vint i;
    vsy_List* list;
    Vint num;
    Vint ierr;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* print DevTools version string */
    printf("version= %s\n", vut_Name(NAME_VERSION, 0));

    /* install user error handler */
    vut_ErrorSetHandler(user_ErrorHandler);

    /* install user memory management */
    vut_MemorySetFunctions(user_malloc, user_realloc, user_free);

    /* instance object */
    list = vsy_ListBegin();
    /* insert some numbers */
    /* index= -1 produces an error */
    vsy_ListInsert(list, -1, (void*)1);
    vsy_ListInsert(list, 10, (void*)10);
    vsy_ListInsert(list, 20, (void*)20);

    /* count objects */
    vsy_ListCount(list, &num);
    printf("\n");
    printf("num= %d\n", num);
    printf("\n");

    /* reinstall default error handler */
    vut_ErrorSetHandler(NULL);

    /* insert an object */
    /* index= -2 produces an error */
    vsy_ListInsert(list, -2, (void*)2);
    /* query object for error and search */
    ierr = vsy_ListError(list);
    /* in general, errors are non-zero */
    if (ierr) {
        for (i = 0; i < SYS_ERROR_MAX; i++) {
            if (ierr == errortable[i]) {
                printf("\nError, ierr= %d, name= %s\n", ierr, errorname[i]);
                break;
            }
        }
    }
    /* delete object */
    vsy_ListEnd(list);
    return 0;
}

10.7. Example 7, Test and Demonstrate Concatenated Storage

This example illustrates using the Concat module for storing a series of data records efficiently without the need for many small individual memory allocations for each record. After the Concat object is instanced, 10000 small data records, lm, containing 4 integers each are added to the concatenation. Each call to vsy_ConcatAdd() copies the contents of the integer lm vector to the concatenation. The number of bytes currently stored in the concatenation and the number of records added are returned and printed. Then each data record is visited sequentially using the iterator functions. The contents of each record are printed.

#include <stdlib.h>
#include "sam/base/base.h"
#include "sam/base/license.h"
#include "sam/CEETRON_SAM_license.h"

/*----------------------------------------------------------------------
                      Test and demonstrate concatenation storage
----------------------------------------------------------------------*/
int
main()
{
    Vint i;
    vsy_Concat* concat;
    Vint lm[4];
    Vint num;
    Vlong siz;
    Vint nbytes;
    Vint* lmptr;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* instance object */
    concat = vsy_ConcatBegin();
    /* insert some arrays */
    for (i = 0; i < 10000; i++) {
        lm[0] = i;
        lm[1] = i + 1;
        lm[2] = i + 2;
        lm[3] = i + 3;
        vsy_ConcatAdd(concat, 4 * sizeof(Vint), lm);
        /* get the pointer to the last data entered for i == 100 */
        if (i == 100) {
            vsy_ConcatRef(concat, (void**)&lmptr);
            printf("ith = %d, lm[] = %d %d %d %d\n", i, lmptr[0], lmptr[1], lmptr[2], lmptr[3]);
        }
    }
    /* count objects */
    vsy_ConcatInq(concat, &siz);
    vsy_ConcatCount(concat, &num);
    printf("\n");
    printf("siz= %lld\n", siz);
    printf("num= %d\n", num);
    printf("\n");
    /* iterate through records printing every 100th */
    i = 0;
    vsy_ConcatInitIter(concat);
    while (vsy_ConcatNextIter(concat, &nbytes, (void**)&lmptr), lmptr != NULL) {
        if (i % 100 == 0) {
            printf("ith = %d, nbytes = %d, lm[] = %d %d %d %d\n", i, nbytes, lmptr[0], lmptr[1], lmptr[2], lmptr[3]);
        }
        i++;
    }
    /* delete object */
    vsy_ConcatEnd(concat);
    return 0;
}

10.8. Example 8, Test and Demonstrate a Data Table

This example demonstrates the use of the DataTable module. The DataTable module is designed to hold pointers to vectors of double precision data at associated values of a double precision independent variable. Each vector is assumed to be a constant length specified by the vsy_DataTableDef() function. In this example four vectors of data of length three are inserted at values -50., 50., 100., and 200. of the independent variable using function vsy_DataTableInsert(). These vectors might represent, for example, values of material properties as a function of temperature. This function does not copy the vector data only the pointer to the vector. The order in which the values are entered is immaterial, the DataTable object always sorts the vectors as a function of increasing value of the independent variable. The function vsy_DataTableLookup() is used to return the pointer to the vector at a previously input value. The function vsy_DataTableEval() is used to evaluate the vector data at some arbitrary value of the independent variable. The function vsy_DataTableSetParami() is called to enable linear extrapolation. The function vsy_DataTableForEach() is be used in this example to free all the vector memory objects.

#include <stdlib.h>
#include "sam/base/base.h"
#include "sam/base/license.h"
#include "sam/CEETRON_SAM_license.h"

/*----------------------------------------------------------------------
                      Test and demonstrate data table
----------------------------------------------------------------------*/
int
main()
{
    Vint num;
    vsy_DataTable* datatable;
    Vdouble v, *d, deval[3];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* instance object */
    datatable = vsy_DataTableBegin();

    /* configure to hold 3-component data objects */
    vsy_DataTableDef(datatable, 0, 3);

    d = (Vdouble*)malloc(3 * sizeof(Vdouble));
    d[0] = 20000000.;
    d[1] = .3;
    d[2] = .0020;
    vsy_DataTableInsert(datatable, 200., d);

    d = (Vdouble*)malloc(3 * sizeof(Vdouble));
    d[0] = 10000000.;
    d[1] = .3;
    d[2] = .0015;
    vsy_DataTableInsert(datatable, 100., d);

    d = (Vdouble*)malloc(3 * sizeof(Vdouble));
    d[0] = 8000000.;
    d[1] = .3;
    d[2] = .0010;
    vsy_DataTableInsert(datatable, 50., d);

    d = (Vdouble*)malloc(3 * sizeof(Vdouble));
    d[0] = 6000000.;
    d[1] = .3;
    d[2] = .0008;
    vsy_DataTableInsert(datatable, -50., d);

    /* count objects */
    vsy_DataTableCount(datatable, &num);
    printf("\n");
    printf("num= %d\n\n", num);

    /* lookup */
    vsy_DataTableLookup(datatable, 200., &d);
    if (d != NULL) {
        printf("Lookup v= 200. d = %f %f %f\n\n", d[0], d[1], d[2]);
    }
    /* evaluate */
    vsy_DataTableSetParami(datatable, DATATABLE_EXTRAPOLATE, DATATABLE_LINEAR);
    vsy_DataTableEval(datatable, 150., deval);
    printf("Eval   v= 150. d = %f %f %f\n\n", deval[0], deval[1], deval[2]);
    vsy_DataTableEval(datatable, 400., deval);
    printf("Eval   v= 400. d = %f %f %f\n\n", deval[0], deval[1], deval[2]);

    /* iterate through objects */
    vsy_DataTableInitIter(datatable);
    while (vsy_DataTableNextIter(datatable, &v, (Vdouble**)&d), d != NULL) {
        printf("v = %f, d = %f %f %f\n", v, d[0], d[1], d[2]);
    }
    /* free data objects */
    vsy_DataTableForEach(datatable, (void (*)(void*))free);

    /* delete object */
    vsy_DataTableEnd(datatable);
    return 0;
}

10.9. Example 9, Test and Demonstrate a PQueue Object

This example demonstrates the use of the PQueue module. The PQueue module is designed to hold integer indices and associated priority values. In this example priority values representing angles in degrees are stored. A priority queue of this type may represent the minimum angle in a triangle. The dynamic range of the priority values is set to (0.,60.). Any angles larger than 60. degrees will be placed in the accumulator associated with angles within the priority queue precision of 60. degrees. The priority queue precision is 60./1024. in this case. Several indices with associated priority values are inserted using vsy_PQueueInsert(). Note that the priority value of index 6 is redefined. The index with the minimum angle is queried using vsy_PQueueMinMax() and removed using vsy_PQueueRemove(). The next minimum is then queried and printed but not removed. A new index is inserted with an angle which is a new minimum. A subsequent query for the current minimum retrieves this index. Unlike standard priority queues based upon heap data structures, the PQueue module allows queries for either minimum or maximum value. Finally the priority queue is cleared and a subsequent check for a maximum value returns an index of zero.

#include <stdlib.h>
#include "sam/base/base.h"
#include "sam/base/license.h"
#include "sam/CEETRON_SAM_license.h"

/*----------------------------------------------------------------------
                      Test and Demonstrate PQueue object
----------------------------------------------------------------------*/
int
main()
{
    vsy_PQueue* pqueue;
    Vint id;
    Vdouble val;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* instance object */
    pqueue = vsy_PQueueBegin();

    /* configure to degrees from 0. to 60. */
    vsy_PQueueDef(pqueue, 0, 1024);
    vsy_PQueueRange(pqueue, 0., 60.);

    vsy_PQueueInsert(pqueue, 1, 20.);
    vsy_PQueueInsert(pqueue, 3, 30.);
    vsy_PQueueInsert(pqueue, 6, 10.);
    vsy_PQueueInsert(pqueue, 7, 10.001);

    /* redefine index 6 */
    vsy_PQueueInsert(pqueue, 6, 40.001);

    /* query for minimum and remove */
    vsy_PQueueMinMax(pqueue, 0, &id, &val);
    vsy_PQueueRemove(pqueue, id);
    printf("\n");
    printf("minimum id= %d, val= %e\n", id, val);

    /* query for minimum */
    vsy_PQueueMinMax(pqueue, 0, &id, &val);
    printf("\n");
    printf("minimum id= %d, val= %e\n", id, val);

    /* insert new minimum */
    vsy_PQueueInsert(pqueue, 2, 5.);
    vsy_PQueueMinMax(pqueue, 0, &id, &val);
    printf("\n");
    printf("minimum id= %d, val= %e\n", id, val);

    /* query for maximum */
    vsy_PQueueMinMax(pqueue, 1, &id, &val);
    printf("\n");
    printf("maximum id= %d, val= %e\n", id, val);

    /* clear */
    vsy_PQueueClear(pqueue);

    /* check */
    vsy_PQueueMinMax(pqueue, 1, &id, &val);
    printf("maximum id= %d\n", id);

    /* delete object */
    vsy_PQueueEnd(pqueue);
    return 0;
}

10.10. Example 9a, Test and Demonstrate a Heap Object

This example demonstrates the use of the Heap module. Like the PQueue module, the Heap module is designed to hold integer indices and associated priority values. The Heap module maintains a precise priority queue while the PQueue module is approximate. The Heap is set up to maintain a minimum priority queue.

Several indices with associated priority values are inserted using vsy_HeapInsert(). Note that the priority value of index 6 is redefined. The index with the minimum value is queried and removed using vsy_HeapRefRemove(). The next minimum is then queried and printed but not removed. A new index is inserted with a value which is a new minimum. A subsequent query for the current minimum retrieves this index. Index 1 is removed even though it does not contain the minimum value. Finally the priority queue is cleared and a subsequent check for a minimum value returns an index of zero.

#include <stdlib.h>
#include "sam/base/base.h"
#include "sam/base/license.h"
#include "sam/CEETRON_SAM_license.h"

/*----------------------------------------------------------------------
                      Test and Demonstrate Heap object
----------------------------------------------------------------------*/
int
main()
{
    vsy_Heap* heap;
    Vint id;
    Vdouble val;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* instance object */
    heap = vsy_HeapBegin();

    /* set up heap to return minimum */
    vsy_HeapDef(heap, 10, 0);

    vsy_HeapInsert(heap, 1, 20.);
    vsy_HeapInsert(heap, 3, 30.);
    vsy_HeapInsert(heap, 6, 10.);
    vsy_HeapInsert(heap, 7, 10.001);

    /* redefine index 6 */
    vsy_HeapInsert(heap, 6, 40.001);

    /* query for minimum and remove */
    vsy_HeapRefRemove(heap, &id, &val);
    printf("\n");
    printf("minimum id= %d, val= %e\n", id, val);

    /* query for minimum */
    vsy_HeapRef(heap, &id, &val);
    printf("\n");
    printf("minimum id= %d, val= %e\n", id, val);

    /* insert new minimum */
    vsy_HeapInsert(heap, 2, 5.);
    vsy_HeapRef(heap, &id, &val);
    printf("\n");
    printf("minimum id= %d, val= %e\n", id, val);

    /* remove index 1 */
    vsy_HeapRemove(heap, 1);
    /* remove two, if 1 has been removed the 3 is new min */
    vsy_HeapRefRemove(heap, &id, &val);
    vsy_HeapRefRemove(heap, &id, &val);
    printf("\n");
    printf("minimum id= %d, val= %e\n", id, val);

    /* clear */
    vsy_HeapClear(heap);

    /* check */
    vsy_HeapRef(heap, &id, &val);
    printf("minimum id= %d\n", id);

    /* delete object */
    vsy_HeapEnd(heap);
    return 0;
}

10.11. Example 10, Test and Demonstrate a TriCon Object

This example demonstrates the use of the TriCon module. The TriCon module is designed to hold triangle connectivity and support triangle stripping, connectivity and adjacency queries. In this example two separate sets of triangles are processed, the first contains 4 triangles, the second 9 triangles. An estimated number of triangles, in this case the exact number contained in the first set, is defined with vsy_TriConDef(). Each triangle is entered using vsy_TriConAppend(), and triangle indices are assigned to each triangle starting with 1. Once all triangles are entered, the function vsy_TriConProcess() is called to generate adjacency and strip information. The number of triangle strips and maximum number of points in any strip are returned. A loop over the number of strips is performed and vsy_TriConStrip() is called to return the point connectivity of each strip. The function vsy_TriConNum() may be used to conveniently query the number of defined triangles.

In order to process another triangle set the function vsy_TriConClear() must be called. The triangles for the second set are then appended in a manner similar to the procedure used for the first set. Indices are assigned starting with 1. This second set of triangles is processed and the resulting strips queried and printed.

#include <stdio.h>
#include "sam/base/base.h"
#include "sam/base/license.h"
#include "sam/CEETRON_SAM_license.h"

/*
        3
       / \
      6---5
     / \ / \
    1---4---2
*/
Vint tri4[4][3] = {{1, 4, 6}, {4, 5, 6}, {4, 2, 5}, {6, 5, 3}};

/*
          10
         / \
        8---9
       / \ / \
      5---6---7
     / \ / \ / \
    1---2---3---4
*/
Vint tri9[9][3] = {{1, 2, 5}, {2, 6, 5}, {2, 3, 6}, {3, 7, 6}, {3, 4, 7}, {5, 6, 8}, {6, 9, 8}, {6, 7, 9}, {8, 9, 10}};

/*----------------------------------------------------------------------
                      test and demonstrate TriCon object
----------------------------------------------------------------------*/
int
main()
{
    Vint i;
    vsy_TriCon* tricon;
    Vint numstrips, maxlength, istrip;
    Vint ntris;
    Vint ns, ie[9], is[11];
    Vint ix[3];
    Vint numtri;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* do 4 element triangular mesh */
    ntris = 4;
    /* instance TriCon object */
    tricon = vsy_TriConBegin();
    vsy_TriConDef(tricon, ntris);

    /* insert triangles */
    for (i = 0; i < ntris; i++) {
        vsy_TriConAppend(tricon, tri4[i]);
    }
    /* process */
    vsy_TriConProcess(tricon, &numstrips, &maxlength);
    printf(" numstrips= %d, maxlength= %d\n", numstrips, maxlength);

    /* access triangle strips */
    for (istrip = 1; istrip <= numstrips; istrip++) {
        vsy_TriConStrip(tricon, istrip, &ns, ie, is);
        printf("strip= %d, ns= %d\n", istrip, ns);
        for (i = 0; i < ns; i++) {
            printf(" %d", is[i]);
        }
        printf("\n");
    }
    /* find out how many triangles there are */
    vsy_TriConNum(tricon, &numtri);
    printf("Current number of triangles= %d\n", numtri);

    /* access input triangle connections */
    for (i = 1; i <= numtri; i++) {
        vsy_TriConRef(tricon, i, ix);
        printf("tri[%d]= %d %d %d\n", i, ix[0], ix[1], ix[2]);
    }

    /* now do 9 element triangular mesh */
    vsy_TriConClear(tricon);
    ntris = 9;

    for (i = 0; i < ntris; i++) {
        vsy_TriConAppend(tricon, tri9[i]);
    }

    vsy_TriConProcess(tricon, &numstrips, &maxlength);
    printf(" numstrips= %d, maxlength= %d\n", numstrips, maxlength);
    for (istrip = 1; istrip <= numstrips; istrip++) {
        vsy_TriConStrip(tricon, istrip, &ns, ie, is);
        printf("strip= %d, ns= %d\n", istrip, ns);
        for (i = 0; i < ns; i++) {
            printf(" %d", is[i]);
        }
        printf("\n");
    }
    /* destroy TriCon object */
    vsy_TriConEnd(tricon);
    return 0;
}

10.12. Example 11, Test and Demonstrate a VertLoc Object

This example demonstrates the use of the VertLoc module. The VertLoc module is designed to hold point coordinates and associated attributes and support point colocation queries. In this example 4 points are defined in the x,y plane. Points 2 and 4 are colocated at (1.,0.,0.) and are assigned identical color and normal attributes. The points are inserted at the specified coordinate locations and their attributes are set. The functions vsy_VertLocSetColor() and vsy_VertLocSetNormal() are called before the call to vsy_VertLocInsert() is made to define the point location. This ensures that the current attributes are set to the point attributes when the insertion is made. The colocated points are determined with the call to vsy_VertLocMerge(). The number of unique point locations and the maximum number of colocated points is returned. Since two of the four points are colocated, then the number of unique sets is 3 and the maximum number of colocated points is 2. If the attributes for points 2 and 4 were not identical they would not have been identified as colocated points. All attributes are stored internally with an 8-bit representation and all attribute comparisons are done at this resolution. Note that this fact also affects the attribute values returned by vsy_VertLocColor() and vsy_VertLocNormal(). There will be round off errors due to this 8-bit representation.

A loop over the number of uniques sets is performed and vsy_VertLocUnique() is called to return the point indices contained in each set. The function vsy_VertLocLowest() is useful for finding the lowest point index coincident with any given point index. The function vsy_VertLocNum() may be used to conveniently query the number of defined points.

#include <stdio.h>
#include "sam/base/base.h"
#include "sam/base/license.h"
#include "sam/CEETRON_SAM_license.h"

Vfloat vert[4][3] = {{0.f, 0.f, 0.f}, {1.f, 0.f, 0.f}, {0.f, 1.f, 0.f}, {1.f, 0.f, 0.f}};
Vfloat ct[4][3] = {{0.f, 0.f, 0.f}, {0.f, 1.f, 0.f}, {0.f, 0.f, 1.f}, {0.f, 1.f, 0.f}};
Vfloat vn[4][3] = {{1.f, 0.f, 0.f}, {.7071f, .7071f, 0.f}, {0.f, 0.f, -1.f}, {.7071f, .7071f, 0.f}};

/*----------------------------------------------------------------------
                      test and demonstrate VertLoc object
----------------------------------------------------------------------*/
int
main()
{
    Vint i;
    vsy_VertLoc* vertloc;
    Vint numunique, maxlocate, iunique, lowestid;
    Vint nverts;
    Vfloat x[3];
    Vfloat c[3], v[3];
    Vint nu, iu[10];
    Vint numvert;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    nverts = 4;

    /* instance VertLoc object */
    vertloc = vsy_VertLocBegin();
    vsy_VertLocDef(vertloc, nverts);

    /* insert vertices */
    for (i = 1; i <= nverts; i++) {
        vsy_VertLocSetColor(vertloc, ct[i - 1]);
        vsy_VertLocSetNormal(vertloc, vn[i - 1]);
        vsy_VertLocInsert(vertloc, i, vert[i - 1]);
    }

    /* merge */
    vsy_VertLocMerge(vertloc, &numunique, &maxlocate);
    printf(" numunique= %d, maxlocate= %d\n", numunique, maxlocate);

    /* query for unique clusters of vertices */
    for (iunique = 1; iunique <= numunique; iunique++) {
        vsy_VertLocUnique(vertloc, iunique, &nu, iu);
        printf("unique vertex cluster= %d, nu= %d\n", iunique, nu);
        for (i = 0; i < nu; i++) {
            printf(" %d", iu[i]);
        }
        printf("\n");
    }
    /* access lowest id */
    for (i = 1; i <= nverts; i++) {
        vsy_VertLocLowest(vertloc, i, &iunique, &lowestid);
        printf("vert[%d], iunique= %d, lowestid= %d\n", i, iunique, lowestid);
    }
    /* find out how many points there are */
    vsy_VertLocNum(vertloc, &numvert);
    printf("Current number of points= %d\n", numvert);

    /* access input vertex locations */
    for (i = 1; i <= numvert; i++) {
        vsy_VertLocRef(vertloc, i, x);
        printf("vert[%d]= %e %e %e\n", i, x[0], x[1], x[2]);
        vsy_VertLocColor(vertloc, i, c);
        printf("color[%d]= %e %e %e\n", i, c[0], c[1], c[2]);
        vsy_VertLocNormal(vertloc, i, v);
        printf("normal[%d]= %e %e %e\n", i, v[0], v[1], v[2]);
    }

    /* destroy VertLoc object */
    vsy_VertLocEnd(vertloc);
    return 0;
}

10.13. Example 12, Test and Demonstrate a LineCon Object

This example demonstrates the use of the LineCon module. The LineCon module is designed to hold line connectivity and support line stripping and connectivity queries. In this example two separate sets of lines are processed, the first contains 9 lines outlining a mesh of 4 triangles, the contains 11 lines incompletely outlining a mesh of 9 triangles. An estimated number of lines, in this case the exact number contained in the first set, is defined with vsy_LineConDef(). Each line is entered using vsy_LineConAppend(), and line indices are assigned to each line starting with 1. Once all lines are entered, the function vsy_LineConProcess() is called to generate strip information. The number of line strips and maximum number of points in any strip are returned. A loop over the number of strips is performed and vsy_LineConStrip() is called to return the point connectivity of each strip. The function vsy_LineConNum() may be used to conveniently query the number of defined lines.

In order to process another line set the function vsy_LineConClear() must be called. The lines for the second set are then appended in a manner similar to the procedure used for the first set. Indices are assigned starting with 1. This second set of lines is processed and the resulting strips queried and printed. In each case LineCon is able to connect the line sets with a single line strip.

#include <stdio.h>
#include "sam/base/base.h"
#include "sam/base/license.h"
#include "sam/CEETRON_SAM_license.h"

/*
        3
       / \
      6---5
     / \ / \
    1---4---2
*/
Vint line9[9][2] = {{1, 4}, {4, 2}, {1, 6}, {4, 6}, {4, 5}, {2, 5}, {6, 5}, {6, 3}, {5, 3}};
/*
          10
         / \
        8   9
       /     \
      5---6---7
     /         \
    1---2---3---4
*/
Vint line11[11][2] = {{1, 2}, {2, 3}, {3, 4}, {1, 5}, {4, 7}, {5, 6}, {6, 7}, {5, 8}, {7, 9}, {8, 10}, {9, 10}};

/*----------------------------------------------------------------------
                      test and demonstrate LineCon object
----------------------------------------------------------------------*/
int
main()
{
    Vint i;
    vsy_LineCon* linecon;
    Vint numstrips, maxlength, istrip;
    Vint nlines;
    Vint ns, ie[11], is[12];
    Vint ix[2];
    Vint numline;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* do 4 element triangular mesh, with 9 lines */
    nlines = 9;
    /* instance LineCon object */
    linecon = vsy_LineConBegin();
    vsy_LineConDef(linecon, nlines);

    /* insert lines */
    for (i = 0; i < nlines; i++) {
        vsy_LineConAppend(linecon, line9[i]);
    }
    /* process */
    vsy_LineConProcess(linecon, &numstrips, &maxlength);
    printf(" numstrips= %d, maxlength= %d\n", numstrips, maxlength);

    /* access line strips */
    for (istrip = 1; istrip <= numstrips; istrip++) {
        vsy_LineConStrip(linecon, istrip, &ns, ie, is);
        printf("strip= %d, ns= %d\n", istrip, ns);
        printf("lines=");
        for (i = 0; i < ns - 1; i++) {
            printf(" %d", ie[i]);
        }
        printf("\n");
        printf("nodes=");
        for (i = 0; i < ns; i++) {
            printf(" %d", is[i]);
        }
        printf("\n");
    }
    /* find out how many lines there are */
    vsy_LineConNum(linecon, &numline);
    printf("Current number of lines= %d\n", numline);

    /* access input lines connections */
    for (i = 1; i <= numline; i++) {
        vsy_LineConRef(linecon, i, ix);
        printf("line[%d]= %d %d\n", i, ix[0], ix[1]);
    }

    /* now do a 10 point mesh incompletely connected */
    vsy_LineConClear(linecon);
    nlines = 11;

    for (i = 0; i < nlines; i++) {
        vsy_LineConAppend(linecon, line11[i]);
    }
    vsy_LineConProcess(linecon, &numstrips, &maxlength);
    printf(" numstrips= %d, maxlength= %d\n", numstrips, maxlength);

    for (istrip = 1; istrip <= numstrips; istrip++) {
        vsy_LineConStrip(linecon, istrip, &ns, ie, is);
        printf("strip= %d, ns= %d\n", istrip, ns);
        printf("lines=");
        for (i = 0; i < ns - 1; i++) {
            printf(" %d", ie[i]);
        }
        printf("\n");
        printf("nodes=");
        for (i = 0; i < ns; i++) {
            printf(" %d", is[i]);
        }
        printf("\n");
    }
    /* destroy LineCon object */
    vsy_LineConEnd(linecon);
    return 0;
}

10.14. Example 13, Test and Demonstrate a Timer Object

This example demonstrates the use of the Timer module. A single Timer object can be used to accumulate timing information for several timed sections. In this example two timing sections, PlusOne and Multiply are created. First the timing interval for PlusOne is started using vsy_TimerStart(). Since this is the first reference to this timed section it is created by this call. After the addition loop the timing interval is stopped using vsy_TimerStop(). The contents of Timer are printed using vsy_TimerInitIter(), vsy_TimerNextIter() and vsy_TimerEval(). Then a timing interval for timed section, Multiply is performed for a multiplication loop. Note that timing information can be retrieved using vsy_TimerEval() inside or outside a timing interval.

The functions vsy_TimerInit(), vsy_TimerRemove() and vsy_TimerClear() are called illustrating their effects on the timed sections in Timer.

#include <stdio.h>
#include "sam/base/base.h"
#include "sam/base/license.h"
#include "sam/CEETRON_SAM_license.h"

static void
print_time(vsy_Timer* timer);

/*----------------------------------------------------------------------
                      Test and demonstrate Timer
----------------------------------------------------------------------*/
int
main()
{
    Vint i;
    Vdouble a;
    vsy_Timer* timer;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    printf("\nTimer test\n");

    /* instance object */
    timer = vsy_TimerBegin();

    /* start timing addition */
    vsy_TimerStart(timer, "PlusOne");
    a = 0;
    for (i = 0; i < 10000000; i++) {
        a += 1.;
    }
    /* stop and print */
    vsy_TimerStop(timer, "PlusOne");
    print_time(timer);

    /* start timing multiplication */
    vsy_TimerStart(timer, "Multiply");
    a = 1;
    for (i = 0; i < 10000000; i++) {
        a *= 1.0000001;
    }
    /* stop and print */
    vsy_TimerStop(timer, "Multiply");
    print_time(timer);

    /* restart timing addition */
    vsy_TimerStart(timer, "PlusOne");
    a = 0;
    for (i = 0; i < 20000000; i++) {
        a += 1.;
    }
    /* print before stopping */
    print_time(timer);

    /* stop and print */
    vsy_TimerStop(timer, "PlusOne");
    print_time(timer);

    /* initialize and print */
    vsy_TimerInit(timer, "PlusOne");
    print_time(timer);

    /* remove and print */
    vsy_TimerRemove(timer, "Multiply");
    print_time(timer);

    /* clear all */
    vsy_TimerClear(timer);
    print_time(timer);

    /* delete object */
    vsy_TimerEnd(timer);
    return 0;
}

/*----------------------------------------------------------------------
                      print utility
----------------------------------------------------------------------*/
static void
print_time(vsy_Timer* timer)
{
    Vchar* name;
    Vint num, run;
    Vfloat usr, sys, ela;

    printf("Current timer state\n");
    /* iterate through all times */
    vsy_TimerInitIter(timer);
    while (vsy_TimerNextIter(timer, &name), name) {
        vsy_TimerEval(timer, name, &num, &run, &usr, &sys, &ela);
        printf(" name: %s, num= %d, run= %d, cpu= %f, sys= %f, ela= %f\n", name, num, run, usr, sys, ela);
    }
}

10.15. Example 14, Test and Demonstrate the MachInfo Module

This example demonstrates querying the MachInfo object for the machine information such as system name, host name, number of processors, processor MFlop rate and total physical memory. The status flag returned by each machine information call indicates whether the query is supported or not. Certain compiled options such as VKI_LIBAPI_SOCKETS may also be queried. The returned status flag indicates whether MachInfo has been compiled with the respective compile options.

#include <stdio.h>
#include "sam/base/base.h"
#include "sam/base/license.h"
#include "sam/CEETRON_SAM_license.h"

/*----------------------------------------------------------------------
                      Test and demonstrate MachInfo
----------------------------------------------------------------------*/
int
main()
{
    Vint flag;
    Vint numproc;
    Vint totalmem;
    Vint usedmem;
    Vint objectsize;
    Vint filepossize;
    Vint endian;
    Vdouble machprec;
    Vchar sysname[256];
    Vchar hostname[256];
    Vchar username[256];
    Vchar datestg[SYS_MAXDATENAME] = {0};
    Vchar timestg[SYS_MAXTIMENAME] = {0};
    Vchar vlongstg[33];
    Vint day, mon, year;
    Vint sec, min, hour;
    Vlong vli;
    Vfloat cpuusr, cpusys;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    printf("\nMachInfo test\n");

    /* query for system name */
    vut_MachInfoSystemName(&flag, sysname);
    if (flag) {
        printf("System name = %s\n", sysname);
    }
    else {
        printf("System name query unsupported\n");
    }
    /* query for host name */
    vut_MachInfoHostName(&flag, hostname);
    if (flag) {
        printf("Host name = %s\n", hostname);
    }
    else {
        printf("Host name query unsupported\n");
    }
    /* query for user name */
    vut_MachInfoUserName(&flag, username);
    if (flag) {
        printf("User name = %s\n", username);
    }
    else {
        printf("User name query unsupported\n");
    }

    /* query for number of processors */
    vut_MachInfoNumProc(&flag, &numproc);
    if (flag) {
        printf("Number of processors = %d\n", numproc);
    }
    else {
        printf("Number of processors query unsupported\n");
    }

    /* query for machine precision */
    vut_MachInfoPrec(&flag, &machprec);
    if (flag) {
        printf("Machine precision = %e\n", machprec);
    }
    else {
        printf("Machine precision query unsupported\n");
    }

    /* query for total physical memory */
    vut_MachInfoTotalMem(&flag, &totalmem);
    if (flag) {
        printf("Total memory (MBytes)= %d\n", totalmem);
    }
    else {
        printf("Total memory (MBytes) query unsupported\n");
    }

    /* query for used physical memory */
    vut_MachInfoUsedMem(&flag, &usedmem);
    if (flag) {
        printf("Used memory (MBytes)= %d\n", usedmem);
    }
    else {
        printf("Used memory (MBytes) query unsupported\n");
    }

    /* query for object size */
    vut_MachInfoObjectSize(&flag, &objectsize);
    if (flag) {
        printf("Object size sizeof(size_t)= %d\n", objectsize);
    }
    else {
        printf("Object size query unsupported\n");
    }

    /* query for file position size */
    vut_MachInfoFilePosSize(&flag, &filepossize);
    if (flag) {
        printf("File position size sizeof(long)= %d\n", filepossize);
    }
    else {
        printf("File position size query unsupported\n");
    }

    /* query for endian */
    /* the flag is always 1 */
    vut_MachInfoEndian(&flag, &endian);
    if (endian == 0) {
        printf("Endian= big\n");
    }
    else {
        printf("Endian= little\n");
    }
    /* date and time strings */
    /* the flag is always 1 */
    vut_MachInfoDateString(&flag, datestg);
    printf("Date: %s\n", datestg);
    vut_MachInfoTimeString(&flag, timestg);
    printf("Time: %s\n", timestg);

    /* date and time integers */
    vut_MachInfoDateInteger(&flag, &day, &mon, &year);
    printf("Date: day= %d, mon= %d, year= %d\n", day, mon, year);
    vut_MachInfoTimeInteger(&flag, &sec, &min, &hour);
    printf("Time: sec= %d, min= %d, hour= %d\n", sec, min, hour);

    /* cpu times, user and system */
    vut_MachInfoCpuTimes(&flag, &cpuusr, &cpusys);
    printf("CpuTimes: usr= %e, sys= %e\n", cpuusr, cpusys);

    /* Vlong string */
    vli = 1234567;
    vut_MachInfoVlongString(vli, vlongstg);
    printf("long int(Vlong)= %s\n", vlongstg);

    /* query for compiled options */
    vut_MachInfoLIBAPI_SOCKETS(&flag);
    if (flag) {
        printf("VKI_LIBAPI_SOCKETS compiled\n");
    }
    else {
        printf("VKI_LIBAPI_SOCKETS not compiled\n");
    }
    return 0;
}

10.16. Example 15, Test and Demonstrate a PTask Object

This example illustrates using a PTask object to compute a dot product using threads. On a multiprocessor computer the objective is to utilize all machine processors by dividing the computation into equalized tasks and performing the dot product in parallel. In this example 2 processors are assumed and the dot product is carried out on two vectors of length 1000000 doubles containing all ones. A computing task which is to be executed on a thread must be posed as a call to a function with a single argument of type pointer to void. The function in this case is pdot and its argument is a pointer to a structure, ptdot, which has been designed to perform a dot product on a subset of entries in the two vectors. Each thread structure contains the number of entries to process, pointers to the starting addresses in the global vectors and a single double, s, containing the dot product of the subset. Note that each structure is allocated from the heap with an additional CACHEPAD number of bytes. This is done to ensure that the accumulators, s, are separated in memory by more than the size of a cache line. This effectively eliminates cache line invalidation caused by writing to the individual accumulators by more than one processor. After the individual ptdot structures are initialized the threads are created and executed using vsy_PTaskExec(). Once execution is complete, the accumulators for each task are added and printed.

#include "stdio.h"
#include "stdlib.h"
#include "sam/base/base.h"
#include "sam/base/license.h"
#include "sam/CEETRON_SAM_license.h"

typedef struct ptdot ptdot;
struct ptdot {
    int n;
    double* a;
    double* b;
    double s;
};

void
pdot(ptdot* p);

#define NUMPROC  2
#define NUMVEC   1000000
#define CACHEPAD 1024

/*----------------------------------------------------------------------
                      Test and Demonstrate PTask
----------------------------------------------------------------------*/
int
main()
{
    int i, j;
    int num, rem;
    int np, nt;
    double *at, *bt;
    double st;
    vsy_PTask* ptask;
    ptdot* pt[NUMPROC];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* instance PTask object */
    ptask = vsy_PTaskBegin();

    /* allocate vectors */
    at = (double*)malloc(NUMVEC * sizeof(double));
    bt = (double*)malloc(NUMVEC * sizeof(double));

    /* initialize with ones */
    for (j = 0; j < NUMVEC; j++) {
        at[j] = 1.;
        bt[j] = 1.;
    }
    /* partition dot product */
    num = NUMVEC / NUMPROC;
    rem = (NUMVEC % NUMPROC);
    nt = 0;
    for (i = 0; i < NUMPROC; i++) {
        pt[i] = (ptdot*)malloc(sizeof(ptdot) + CACHEPAD);
        if (i < NUMPROC - 1) {
            np = num;
        }
        else {
            np = num + rem;
        }
        pt[i]->n = np;
        pt[i]->a = &at[nt];
        pt[i]->b = &bt[nt];
        nt += np;
    }
    /* execute over NUMPROC threads */
    vsy_PTaskDef(ptask, NUMPROC, PTASK_EXEC);
    vsy_PTaskExec(ptask, NUMPROC, (void (*)(void*))pdot, (Vobject**)pt);

    /* add results of each thread */
    st = 0.;
    for (i = 0; i < NUMPROC; i++) {
        st += pt[i]->s;
        free(pt[i]);
    }
    printf("st= %e\n", st);

    /* free vectors */
    free(at);
    free(bt);
    /* delete PTask */
    vsy_PTaskEnd(ptask);
    return 0;
}

void
pdot(ptdot* p)
{
    int i;
    /* perform dot product */
    p->s = 0.;
    for (i = 0; i < p->n; i++) {
        p->s += p->a[i] * p->b[i];
    }
}

10.17. Example 16, Test and Demonstrate Text Processing and Formatting

This example illustrates using the text processing and formatting modules. Three formatting objects are used, HTMLText for HTML formatting, PlainText for plain text formatting and LaTeXText for LaTeX formatting. A TextTee object is used to direct the text content to all three formatters simultaneously. It requires three TextFun abstract interfaces (tf0, tf1 and tf2) to link the three formatters to the TextTee object and a single abstract interface (tf) to the TextTee object. All text content is written to the interface to the TextTee object and it propagates to the three formatters. Each of the three formatters writes to a file and the files exam16.htm, exam16.txt and exam16.tex are generated by this application. These files may be viewed/processed by a HTML browser, any text editor and the LaTeX text processing system. The following content is generated.

  • Title

  • Heading

  • Horizontal rule

  • Basic text

  • Itemized list

  • Table

  • Graphics image

  • Preformatted text

The function vsy_TextFunSetMode() can be used to enable and disable text formatting modes such as italics, bold, centering, etc. Note the use of vsy_TextFunTextColor() and vsy_TextFunTableColor() to control the color of text and the color of the table cells. Finally the files are closed using vsy_TextFunCloseFile().

#include "sam/base/base.h"
#include "sam/base/license.h"
#include "sam/CEETRON_SAM_license.h"

/* define some colors */
static Vfloat red[3] = {1.f, 0.f, 0.f};
static Vfloat grn[3] = {0.f, 1.f, 0.f};
static Vfloat blu[3] = {0.f, 0.f, 1.f};
static Vfloat blk[3] = {0.f, 0.f, 0.f};
static Vfloat wht[3] = {1.f, 1.f, 1.f};
static Vfloat back[3] = {0.733333f, 0.866666f, 1.0f};
static Vfloat offwht[3] = {0.8f, 0.8f, 0.8f};
static Vfloat altwht[3] = {0.9f, 0.9f, 0.9f};

/*----------------------------------------------------------------------
                      Test and demonstrate TextFun objects
----------------------------------------------------------------------*/
int
main()
{
    vsy_HTMLText* htmltext;
    vsy_PlainText* plaintext;
    vsy_LaTeXText* latextext;
    vsy_TextTee* texttee;
    vsy_TextFun *tf0, *tf1, *tf2, *tf;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* set HTML output */
    htmltext = vsy_HTMLTextBegin();
    tf0 = vsy_TextFunBegin();
    vsy_HTMLTextTextFun(htmltext, tf0);
    vsy_TextFunOpenFile(tf0, (Vchar*)"exam16.htm");

    /* set plain text output */
    plaintext = vsy_PlainTextBegin();
    tf1 = vsy_TextFunBegin();
    vsy_PlainTextTextFun(plaintext, tf1);
    vsy_TextFunOpenFile(tf1, (Vchar*)"exam16.txt");

    /* set LaTeX output */
    latextext = vsy_LaTeXTextBegin();
    tf2 = vsy_TextFunBegin();
    vsy_LaTeXTextTextFun(latextext, tf2);
    vsy_TextFunOpenFile(tf2, (Vchar*)"exam16.tex");

    /* create a tee to write to all formats */
    texttee = vsy_TextTeeBegin();
    vsy_TextTeeSetObject(texttee, VSY_TEXTFUN, tf0);
    vsy_TextTeeSetObject(texttee, VSY_TEXTFUN_1, tf1);
    vsy_TextTeeSetObject(texttee, VSY_TEXTFUN_2, tf2);
    tf = vsy_TextFunBegin();
    vsy_TextTeeTextFun(texttee, tf);

    /* title */
    vsy_TextFunFormInit(tf, SYS_TEXT_TITLE);
    vsy_TextFunString(tf, "This is the title");
    vsy_TextFunFormTerm(tf, SYS_TEXT_TITLE);

    /* level 1 heading */
    vsy_TextFunHeadingLevel(tf, 1);
    vsy_TextFunFormInit(tf, SYS_TEXT_HEADING);
    vsy_TextFunString(tf, "This is a heading 1 test");
    vsy_TextFunFormTerm(tf, SYS_TEXT_HEADING);

    /* horizontal rule */
    vsy_TextFunHorizontalRule(tf);

    /* level 2 heading */
    vsy_TextFunHeadingLevel(tf, 2);
    vsy_TextFunFormInit(tf, SYS_TEXT_HEADING);
    vsy_TextFunString(tf, "This is a heading 2 test");
    vsy_TextFunFormTerm(tf, SYS_TEXT_HEADING);

    /* basic text */
    vsy_TextFunTextColor(tf, wht);
    vsy_TextFunString(tf, "This is white-colored text.");
    vsy_TextFunTextColor(tf, red);
    vsy_TextFunString(tf, "This is red-colored text.");
    vsy_TextFunTextColor(tf, grn);
    vsy_TextFunString(tf, "This is green-colored text.");
    vsy_TextFunTextColor(tf, blu);
    vsy_TextFunString(tf, "This is blue-colored text.");
    vsy_TextFunTextColor(tf, blk);
    vsy_TextFunString(tf, "And now back to black-colored text.");

    /* list */
    vsy_TextFunListType(tf, SYS_TEXT_ORDERED);
    vsy_TextFunFormInit(tf, SYS_TEXT_LIST);
    vsy_TextFunFormInit(tf, SYS_TEXT_ITEM);
    vsy_TextFunSetMode(tf, SYS_TEXT_BOLD, SYS_ON);
    vsy_TextFunString(tf, "This is item 1 in a list in bold font");
    vsy_TextFunSetMode(tf, SYS_TEXT_BOLD, SYS_OFF);
    vsy_TextFunFormTerm(tf, SYS_TEXT_ITEM);
    vsy_TextFunFormInit(tf, SYS_TEXT_ITEM);
    vsy_TextFunSetMode(tf, SYS_TEXT_ITALICS, SYS_ON);
    vsy_TextFunString(tf, "This is item 2 in a list in italics font");
    vsy_TextFunSetMode(tf, SYS_TEXT_ITALICS, SYS_OFF);
    vsy_TextFunFormTerm(tf, SYS_TEXT_ITEM);
    vsy_TextFunFormInit(tf, SYS_TEXT_ITEM);
    vsy_TextFunSetMode(tf, SYS_TEXT_TYPEWRITER, SYS_ON);
    vsy_TextFunString(tf, "This is item 3 in a list in typewriter font");
    vsy_TextFunSetMode(tf, SYS_TEXT_TYPEWRITER, SYS_OFF);
    vsy_TextFunFormTerm(tf, SYS_TEXT_ITEM);
    vsy_TextFunFormTerm(tf, SYS_TEXT_LIST);

    /* table */
    vsy_TextFunSetMode(tf, SYS_TEXT_CENTER, SYS_ON);
    vsy_TextFunTableWidth(tf, 60);
    vsy_TextFunBorderWidth(tf, 4);
    vsy_TextFunFormInit(tf, SYS_TEXT_TABLE);

    /* row 1 */
    vsy_TextFunFormInit(tf, SYS_TEXT_ROW);
    vsy_TextFunColumnAlign(tf, SYS_TEXT_LEFT);
    vsy_TextFunTableColor(tf, red);
    vsy_TextFunFormInit(tf, SYS_TEXT_COLUMN);
    vsy_TextFunSpace(tf, 3);
    vsy_TextFunString(tf, "Aligned left");
    vsy_TextFunSpace(tf, 3);
    vsy_TextFunFormTerm(tf, SYS_TEXT_COLUMN);
    vsy_TextFunColumnAlign(tf, SYS_TEXT_MIDDLE);
    vsy_TextFunTableColor(tf, grn);
    vsy_TextFunFormInit(tf, SYS_TEXT_COLUMN);
    vsy_TextFunSpace(tf, 3);
    vsy_TextFunString(tf, "Aligned middle");
    vsy_TextFunSpace(tf, 3);
    vsy_TextFunFormTerm(tf, SYS_TEXT_COLUMN);
    vsy_TextFunColumnAlign(tf, SYS_TEXT_RIGHT);
    vsy_TextFunTableColor(tf, blu);
    vsy_TextFunFormInit(tf, SYS_TEXT_COLUMN);
    vsy_TextFunSpace(tf, 3);
    vsy_TextFunString(tf, "Aligned right");
    vsy_TextFunSpace(tf, 3);
    vsy_TextFunFormTerm(tf, SYS_TEXT_COLUMN);
    vsy_TextFunFormTerm(tf, SYS_TEXT_ROW);

    /* row 2 */
    vsy_TextFunTableColor(tf, offwht);
    vsy_TextFunFormInit(tf, SYS_TEXT_ROW);
    vsy_TextFunFormInit(tf, SYS_TEXT_COLUMN);
    vsy_TextFunSpace(tf, 3);
    vsy_TextFunString(tf, "row 2 col 1");
    vsy_TextFunSpace(tf, 3);
    vsy_TextFunFormTerm(tf, SYS_TEXT_COLUMN);
    vsy_TextFunFormInit(tf, SYS_TEXT_COLUMN);
    vsy_TextFunSpace(tf, 3);
    vsy_TextFunString(tf, "row 2 col 2");
    vsy_TextFunSpace(tf, 3);
    vsy_TextFunFormTerm(tf, SYS_TEXT_COLUMN);
    vsy_TextFunFormInit(tf, SYS_TEXT_COLUMN);
    vsy_TextFunSpace(tf, 3);
    vsy_TextFunString(tf, "row 2 col 3");
    vsy_TextFunSpace(tf, 3);
    vsy_TextFunFormTerm(tf, SYS_TEXT_COLUMN);
    vsy_TextFunFormTerm(tf, SYS_TEXT_ROW);

    /* row 3 */
    vsy_TextFunTableColor(tf, altwht);
    vsy_TextFunFormInit(tf, SYS_TEXT_ROW);
    vsy_TextFunFormInit(tf, SYS_TEXT_COLUMN);
    vsy_TextFunSpace(tf, 3);
    vsy_TextFunString(tf, "row 3 col 1");
    vsy_TextFunSpace(tf, 3);
    vsy_TextFunFormTerm(tf, SYS_TEXT_COLUMN);
    vsy_TextFunFormInit(tf, SYS_TEXT_COLUMN);
    vsy_TextFunSpace(tf, 3);
    vsy_TextFunString(tf, "row 3 col 2");
    vsy_TextFunSpace(tf, 3);
    vsy_TextFunFormTerm(tf, SYS_TEXT_COLUMN);
    vsy_TextFunFormInit(tf, SYS_TEXT_COLUMN);
    vsy_TextFunSpace(tf, 3);
    vsy_TextFunString(tf, "row 3 col 3");
    vsy_TextFunSpace(tf, 3);
    vsy_TextFunFormTerm(tf, SYS_TEXT_COLUMN);
    vsy_TextFunFormTerm(tf, SYS_TEXT_ROW);
    vsy_TextFunTableColor(tf, back);

    vsy_TextFunFormTerm(tf, SYS_TEXT_TABLE);

    /* image file */
    vsy_TextFunFormAction(tf, SYS_TEXT_LINEBREAK);
    vsy_TextFunImageFile(tf, (Vchar*)"../../vgl/exam/earth.gif");
    vsy_TextFunSetMode(tf, SYS_TEXT_CENTER, SYS_OFF);
    vsy_TextFunFormAction(tf, SYS_TEXT_LINEBREAK);

    /* pre-formatted text */
    vsy_TextFunHeadingLevel(tf, 2);
    vsy_TextFunFormInit(tf, SYS_TEXT_HEADING);
    vsy_TextFunString(tf, "Pre-formatted text");
    vsy_TextFunFormTerm(tf, SYS_TEXT_HEADING);
    vsy_TextFunSetMode(tf, SYS_TEXT_PREFORMATTED, SYS_ON);
    vsy_TextFunString(tf, "j = 0;\n");
    vsy_TextFunString(tf, "for(i = 0; i < 3; i++) {\n");
    vsy_TextFunTextColor(tf, red);
    vsy_TextFunString(tf, "   j += i;\n");
    vsy_TextFunTextColor(tf, blk);
    vsy_TextFunString(tf, "}\n");
    vsy_TextFunSetMode(tf, SYS_TEXT_PREFORMATTED, SYS_OFF);

    /* close files */
    vsy_TextFunCloseFile(tf);

    /* delete objects */
    vsy_HTMLTextEnd(htmltext);
    vsy_PlainTextEnd(plaintext);
    vsy_LaTeXTextEnd(latextext);
    vsy_TextTeeEnd(texttee);
    vsy_TextFunEnd(tf0);
    vsy_TextFunEnd(tf1);
    vsy_TextFunEnd(tf2);
    vsy_TextFunEnd(tf);
    return 0;
}

10.19. Example 18, Test and Demonstrate the ADTree object

This example illustrates using an ADTree object to perform geometric searches. An alternating digital tree may contain either discrete point entities or geometric entities with extent, such as lines, triangles or tetrahedra. This example illustrates both types of trees. First a point tree is setup to contain 5 points within a unit cube. Each point is given a user defined key and inserted using vsy_ADTreeInsertPoint(). Then a tolerance bound of .26 is specified and a point search is performed for all entities which are contained within the coordinate extent of + or - .26 centered about .5,.5.0. The search in initiated and performed using vsy_ADTreeRefPointInit(). Each point entity contained with the specified extent about the input point is returned using successive calls to vsy_ADTreeRefPointNext(). Then point 3 is removed using vsy_ADTreeRemove() and the search is repeated. The tolerance is changed to .36 and the searches are repeated with point 2 removed.

The tree is redefined to an extent tree using vsy_ADTreeDef() and three geometric entities defined by extent are inserted using vsy_ADTreeInsertExtent(). The function vsy_ADTreeDef() will remove any previous defined entities from the tree. Then both a search about a point and a search within an extent are performed. Any extent entity in the tree which overlaps the input extent is returned by the search.

#include <stdio.h>
#include "sam/base/base.h"
#include "sam/base/license.h"
#include "sam/CEETRON_SAM_license.h"

/*----------------------------------------------------------------------
                      Test and demonstrate ADTree
----------------------------------------------------------------------*/
int
main()
{
    Vint key;
    Vint nhits;
    vsy_ADTree* adtree;
    Vdouble xmin[3], xmax[3];
    Vdouble x[3], tol;
    Vdouble xn[3], xx[3];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    printf("\nADTree test\n");

    /* instance ADTree object */
    adtree = vsy_ADTreeBegin();

    /* set up POINT ADTree within unit square */
    /* set initial allocation to five objects */
    printf("\nPOINT ADTree\n");
    xmin[0] = 0.;
    xmin[1] = 0.;
    xmin[2] = 0.;
    xmax[0] = 1.;
    xmax[1] = 1.;
    xmax[2] = 1.;
    vsy_ADTreeDef(adtree, ADTREE_POINT, xmin, xmax);

    /* insert 5 points */
    x[0] = .25;
    x[1] = .75;
    x[2] = 0.;
    vsy_ADTreeInsertPoint(adtree, 1, x);
    x[0] = .75;
    x[1] = .75;
    x[2] = 0.;
    vsy_ADTreeInsertPoint(adtree, 2, x);
    x[0] = .65;
    x[1] = .65;
    x[2] = 0.;
    vsy_ADTreeInsertPoint(adtree, 3, x);
    x[0] = .05;
    x[1] = .65;
    x[2] = 0.;
    vsy_ADTreeInsertPoint(adtree, 4, x);
    x[0] = .65;
    x[1] = .15;
    x[2] = 0.;
    vsy_ADTreeInsertPoint(adtree, 5, x);

    /* search with .26 tolerace box about point .5,.5 */
    tol = .26;
    vsy_ADTreeSetParamd(adtree, ADTREE_TOLERANCE, tol);
    x[0] = .5;
    x[1] = .5;
    x[2] = 0.;
    printf("search point= %f, %f, %f,  tolerance= %f\n", x[0], x[1], x[2], tol);
    vsy_ADTreeRefPointInit(adtree, x);
    while (vsy_ADTreeRefPointNext(adtree, &key), key) {
        printf(" find key= %d\n", key);
    }
    /* remove point 3 and search again */
    printf("remove point 3\n");
    vsy_ADTreeRemove(adtree, 3);
    printf("search point= %f, %f, %f,  tolerance= %f\n", x[0], x[1], x[2], tol);
    vsy_ADTreeRefPointInit(adtree, x);
    while (vsy_ADTreeRefPointNext(adtree, &key), key) {
        printf(" find key= %d\n", key);
    }

    /* search */
    tol = .36;
    vsy_ADTreeSetParamd(adtree, ADTREE_TOLERANCE, tol);
    printf("search point= %f, %f, %f,  tolerance= %f\n", x[0], x[1], x[2], tol);
    vsy_ADTreeRefPointInit(adtree, x);
    while (vsy_ADTreeRefPointNext(adtree, &key), key) {
        printf(" find key= %d\n", key);
    }
    /* remove and search */
    printf("remove point 2\n");
    vsy_ADTreeRemove(adtree, 2);
    printf("search point= %f, %f, %f,  tolerance= %f\n", x[0], x[1], x[2], tol);
    vsy_ADTreeRefPointInit(adtree, x);
    while (vsy_ADTreeRefPointNext(adtree, &key), key) {
        printf(" find key= %d\n", key);
    }

    /* now do objects with EXTENT */
    printf("\nEXTENT ADTree\n");
    vsy_ADTreeDef(adtree, ADTREE_EXTENT, xmin, xmax);

    /* insert 3 extent boxes */
    xn[0] = .25;
    xn[1] = .25;
    xn[2] = 0.;
    xx[0] = .5;
    xx[1] = .5;
    xx[2] = 0.;
    vsy_ADTreeInsertExtent(adtree, 1, xn, xx);
    xn[0] = .6;
    xn[1] = .5;
    xn[2] = 0.;
    xx[0] = .7;
    xx[1] = .8;
    xx[2] = 0.;
    vsy_ADTreeInsertExtent(adtree, 2, xn, xx);
    xn[0] = .8;
    xn[1] = .1;
    xn[2] = 0.;
    xx[0] = .9;
    xx[1] = .9;
    xx[2] = 0.;
    vsy_ADTreeInsertExtent(adtree, 3, xn, xx);

    /* point search */
    x[0] = .5;
    x[1] = .5;
    x[2] = 0.;
    tol = .1000;
    vsy_ADTreeSetParamd(adtree, ADTREE_TOLERANCE, tol);
    printf("search point= %f, %f, %f,  tolerance= %f\n", x[0], x[1], x[2], tol);
    vsy_ADTreeRefPointInit(adtree, x);
    vsy_ADTreeGetInteger(adtree, ADTREE_NUMHITS, &nhits);
    printf(" number of hits= %d\n", nhits);
    while (vsy_ADTreeRefPointNext(adtree, &key), key) {
        printf(" find key= %d\n", key);
    }
    /* extent search */
    xn[0] = .6;
    xn[1] = .55;
    xn[2] = 0.;
    xx[0] = .9;
    xx[1] = .55;
    xx[2] = 0.;
    tol = .05;
    printf("search extent, min= %f, %f, %f\n", xn[0], xn[1], xn[2]);
    printf("               max= %f, %f, %f\n", xx[0], xx[1], xx[2]);
    printf("               tolerance= %f\n", tol);
    vsy_ADTreeSetParamd(adtree, ADTREE_TOLERANCE, tol);
    vsy_ADTreeRefExtentInit(adtree, xn, xx);
    vsy_ADTreeGetInteger(adtree, ADTREE_NUMHITS, &nhits);
    printf(" number of hits= %d\n", nhits);
    while (vsy_ADTreeRefExtentNext(adtree, &key), key) {
        printf(" find key= %d\n", key);
    }

    /* delete object */
    vsy_ADTreeEnd(adtree);
    return 0;
}

10.20. Example 21, Purposefully left blank

10.21. Example 22, Test and Demonstrate the VSocket object

This example illustrates using a VSocket object to establish a TCP/IP communication socket between two processes, referred to as the server and the client. The socket requires that a hostname and a port number be specified.

The program shows how a server is made ready to accept client connections, and how the communication between client and server for each connection is made through a separate thread. The program spawns three other processes: two simple clients that send strings and numeric data to the server - main_client - and a client that instructs the server to shut itself down - main_stop.

Once the connection is defined with vsy_VSocketDef(), and then established with vsy_VSocketOpen(), the server starts an infinite loop where it attempts to establish new client connections with vsy_VSocketAccept(). Once a connection is established memory is allocated from the heap to store information associated with the connection and a thread is started to execute the server function. This function exchanges messages with the client using vsy_VSocketWriteString(), vsy_VSocketWrite(), vsy_VSocketReadString(), and vsy_VSocketRead(). The string-specific functions are an indication that character strings are being sent so the data need not be swapped even if the binary representation of integers, floats, and doubles is different between the server and the client. The thread terminates whenever the client sends the bye command. When a stop command is received by the server the server breaks from the infinite loop and waits for the running threads to terminate by using vsy_PTaskJoin(). Once the thread terminates all heap data associated with this connection is deallocated.

The main_client function sends commands to be displayed by the server who then sends an acknowledgement.

The main_stop function sends a single “stop” command to the server; once all clients terminate their communication with the server the server shuts itself down.

#include <stdio.h>
#include "sam/base/base.h"
#include "sam/base/license.h"
#include "sam/CEETRON_SAM_license.h"
#ifdef VKI_ARCH_WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif

#define BUFSIZE 256

static const Vchar* commands[2][5] = {{"client1", "int", "float", "double", "bye"}, {"client2", "int", "float", "double", "bye"}};

static Vint icval[2] = {27, -2};
static Vfloat fcval[2] = {-0.001f, 3.e-5f};
static Vdouble dcval[2] = {0.33, -2.56};

typedef struct {
    vsy_VSocket* vsocket;
    Vint cid;
    Vchar firstbuf[BUFSIZE];
} exam22struct;

/* terminate thread */
static void
exam22term(exam22struct* inst)
{
    free(inst);
}

static void
server(Vobject* obj)
{
    exam22struct* inst = (exam22struct*)obj;
    Vint size, iterm;
    Vint ival, n;
    Vfloat fval;
    Vdouble dval;
    Vchar buffer[BUFSIZE];

    iterm = 0;
    /* Infinite loop to receive commands from client */
    for (n = 0;; ++n) {
        /* Read first command from struct; otherwise, from socket */
        if (n == 0) {
            strcpy(buffer, inst->firstbuf);
        }
        else {
            vsy_VSocketReadString(inst->vsocket, inst->cid, BUFSIZE, buffer, &size);
            if (vsy_VSocketError(inst->vsocket))
                return;
        }

        /* echo command */
        printf("SERVER: client %d- %s", inst->cid, buffer);

        /* Termination: set flag to quit later */
        if (strstr(buffer, "bye")) {
            iterm = 1;

            /* int: read integer from socket and print */
        }
        else if (strstr(buffer, "int")) {
            vsy_VSocketRead(inst->vsocket, inst->cid, sizeof(Vint), (Vchar*)&ival);
            if (vsy_VSocketError(inst->vsocket))
                return;

            printf(" %d", ival);

            /* float: read float from socket and print */
        }
        else if (strstr(buffer, "float")) {
            vsy_VSocketRead(inst->vsocket, inst->cid, sizeof(Vfloat), (Vchar*)&fval);
            if (vsy_VSocketError(inst->vsocket))
                return;

            printf(" %e", fval);

            /* double: read double from socket and print */
        }
        else if (strstr(buffer, "double")) {
            vsy_VSocketRead(inst->vsocket, inst->cid, sizeof(Vdouble), (Vchar*)&dval);
            if (vsy_VSocketError(inst->vsocket))
                return;

            printf(" %e", dval);
        }
        printf("\n");

        /* acknowledge receipt to client */
        vsy_VSocketWriteString(inst->vsocket, inst->cid, (Vchar*)"ok");
        if (vsy_VSocketError(inst->vsocket))
            return;

        /* bye: quit */
        if (iterm == 1) {
            vsy_VSocketClose(inst->vsocket, inst->cid);
            break;
        }
    }
}

static void
main_server()
{
    vsy_VSocket* vsocket;
    vsy_List* list;
    Vchar hostname[BUFSIZE], buffer[BUFSIZE];
    Vint flag, cid, i, size;
    exam22struct* inst;

    /* Get info about this host */
    vut_MachInfoHostName(&flag, hostname);
    if (flag == 0) {
        printf("SERVER: Unable to retrieve host name\n");
        return;
    }
    /* Instance and set up VSocket */
    vsocket = vsy_VSocketBegin();
    vsy_VSocketSetParami(vsocket, VSOCKET_WAITTIME, 10);
    vsy_VSocketSetParami(vsocket, VSOCKET_MAXCONNECTIONS, 1);
    vsy_VSocketDef(vsocket, VSOCKET_SERVER, VSOCKET_NET);
    vsy_VSocketSetNet(vsocket, 10000, hostname);
    vsy_VSocketOpen(vsocket);
    if (vsy_VSocketError(vsocket)) {
        printf("SERVER: Unable to Open\n");
        return;
    }
    /* Instance list to store client instances */
    list = vsy_ListBegin();

    for (i = 0; i < 5; ++i) {
        vsy_VSocketAccept(vsocket, &cid);
        if (cid == 0)
            break;

        vsy_VSocketReadString(vsocket, cid, BUFSIZE, buffer, &size);

        /* check for stop server command */
        if (strstr(buffer, "stop")) {
            vsy_VSocketClose(vsocket, cid);
            break;
        }

        /* establish new connection in thread */
        inst = (exam22struct*)malloc(sizeof(exam22struct));
        vsy_ListInsert(list, cid, (Vobject*)inst);
        inst->vsocket = vsocket;
        inst->cid = cid;
        strcpy(inst->firstbuf, buffer);
        server((Vobject*)inst);
    }

    /* Close connection and cleanup */
    vsy_VSocketSetParami(vsocket, VSOCKET_WAITTIME, 1);
    vsy_ListForEach(list, (Vfunc1*)exam22term);
    vsy_VSocketClose(vsocket, 0);
    vsy_ListEnd(list);
    vsy_VSocketEnd(vsocket);
    return;
}

static void
client(vsy_VSocket* vsocket, Vint id)
{
    Vint iterm = 0, size = 0, n = 0;
    Vchar buffer[BUFSIZE] = {0};

    /* start command loop */
    for (n = 0; n < 5; n++) {
        /* send command to server */
        vsy_VSocketWriteString(vsocket, 0, (Vchar*)commands[id - 1][n]);
        if (vsy_VSocketError(vsocket))
            return;

        /* set termination flag */
        if (strcmp(commands[id - 1][n], "bye") == 0) {
            iterm = 1;

            /* read and send int as binary */
        }
        else if (strcmp(commands[id - 1][n], "int") == 0) {
            vsy_VSocketWrite(vsocket, 0, sizeof(Vint), (Vchar*)&icval[id - 1]);
            if (vsy_VSocketError(vsocket))
                return;

            /* read and send float as binary */
        }
        else if (strcmp(commands[id - 1][n], "float") == 0) {
            vsy_VSocketWrite(vsocket, 0, sizeof(Vfloat), (Vchar*)&fcval[id - 1]);
            if (vsy_VSocketError(vsocket))
                return;

            /* read and send double as binary */
        }
        else if (strcmp(commands[id - 1][n], "double") == 0) {
            vsy_VSocketWrite(vsocket, 0, sizeof(Vdouble), (Vchar*)&dcval[id - 1]);
            if (vsy_VSocketError(vsocket))
                return;
        }
        /* read receipt acknowledgement from server */
        vsy_VSocketReadString(vsocket, 0, BUFSIZE, buffer, &size);
        if (vsy_VSocketError(vsocket))
            return;
        if (strcmp(buffer, "ok") == 0) {
            printf("CLIENT %d: ...information received by server from client\n", id);
        }

        /* terminate thread if "bye" */
        if (iterm == 1)
            break;
    }
}

static void
main_client(Vint id)
{
    vsy_VSocket* vsocket;
    Vchar hostname[BUFSIZE];
    Vint flag;

    /* Get info about this host */
    vut_MachInfoHostName(&flag, hostname);
    if (flag == 0) {
        printf("CLIENT %d: Unable to retrieve host name in client\n", id);
        return;
    }
    /* Instance and set up VSocket */
    vsocket = vsy_VSocketBegin();
    vsy_VSocketSetParami(vsocket, VSOCKET_WAITTIME, 1000);
    vsy_VSocketDef(vsocket, VSOCKET_CLIENT, VSOCKET_NET);
    vsy_VSocketSetNet(vsocket, 10000, hostname);
    vsy_VSocketOpen(vsocket);
    if (vsy_VSocketError(vsocket)) {
        vsy_VSocketEnd(vsocket);
        return;
    }
    /* Exchange information with server */
    client(vsocket, id);
    /* Close connection and cleanup */
    vsy_VSocketClose(vsocket, 0);
    vsy_VSocketEnd(vsocket);
    return;
}

static void
main_stop()
{
    vsy_VSocket* vsocket;
    Vchar hostname[BUFSIZE];
    Vint flag;

    /* Get info about this host */
    vut_MachInfoHostName(&flag, hostname);
    if (flag == 0) {
        printf("STOP: Unable to retrieve host name\n");
        return;
    }
    /* Instance and set up VSocket */
    vsocket = vsy_VSocketBegin();
    vsy_VSocketDef(vsocket, VSOCKET_CLIENT, VSOCKET_NET);
    vsy_VSocketSetNet(vsocket, 10000, hostname);
    vsy_VSocketOpen(vsocket);

    /* Send command to server to stop itself */
    printf("STOP: sending stop command to server\n");
    vsy_VSocketWriteString(vsocket, 0, (Vchar*)"stop");

    /* Close connection and cleanup */
    vsy_VSocketClose(vsocket, 0);
    vsy_VSocketEnd(vsocket);
    return;
}

/*----------------------------------------------------------------------
                      Test and Demonstrate VSocket Object

                      Byte-swapping may need to be added for
                      heterogeneous machines with different
                      byte representation
----------------------------------------------------------------------*/
int
main(int argc, char* argv[])
{
    Vchar sys[BUFSIZE];
    Vint n;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

#ifdef VKI_ARCH_WIN32
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
#endif
    /* Check input */
    if (argc == 1) {
        for (n = 1; n <= 3; n++) {
#ifdef VKI_ARCH_WIN32
            sprintf(sys, "%s %d", argv[0], n);
            ZeroMemory(&si, sizeof(si));
            si.cb = sizeof(si);
            ZeroMemory(&pi, sizeof(pi));
            if (!CreateProcess(NULL, sys, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
                printf("SERVER: Unable to start child process %d\n", n);
                exit(0);
            }
#else
            sprintf(sys, "%s %d &", argv[0], n);
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
#endif
            system(sys);
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
#endif
        }
        main_server();
    }
    else if (argc == 2) {
        sscanf(argv[1], "%d", &n);
        if (n == 1 || n == 2) {
            main_client(n);
        }
        else {
            /* Wait 10 seconds before stopping server */
            printf("SERVER: Waiting 10 seconds to launch stop server...\n");
#ifdef VKI_ARCH_WIN32
            Sleep(10000);
#else
            sleep(10);
#endif
            main_stop();
        }
    }
    return 0;
}

10.22. Example 23, Test and Demonstrate Quadruple Precision VQuad

This example illustrates the available methods to operate on quadruple precision variables of type VQuad. Load and store operations are shown using vut_VQuadLoad() and vut_VQuadStore().

Comparison functions are demonstrated with vut_VQuadEQ(), vut_VQuadGE(), vut_VQuadGT(), vut_VQuadLE(), and vut_VQuadLT(). All these functions return 1 for TRUE values or 0, for FALSE values.

Basic arithmetic operations are shown with vut_VQuadAdd(), vut_VQuadSub(), vut_VQuadMult(), and vut_VQuadDiv(). For convenience these functions’ return value is the result of the arithmetic operation.

Unary operations are given by vut_VQuadAbs(), vut_VQuadHalf(), vut_VQuadNeg(), and vut_VQuadSqrt().

Three-component vector operations are shown with vut_VQuadMag3(), vut_VQuadDot3(), vut_VQuadCross3(), and vut_VQuadUnit3().

Finally, quadruple precision variables can be printed to a string with vut_VQuadSPrintf().

#include <stdio.h>
#include <math.h>
#include "sam/base/base.h"
#include "sam/base/license.h"
#include "sam/CEETRON_SAM_license.h"

/*----------------------------------------------------------------------
                      Test and Demonstrate Quadruple Precision
----------------------------------------------------------------------*/
int
main()
{
    Vdouble da, db;
    Vquad qa, qb, qc, va[3], vb[3], vc[3];
    Vint ierr;
    Vchar bufa[256], bufb[256], bufc[256];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* load and store operations */
    da = 1.23;
    db = -0.9;
    printf("Double precision numbers:\n");
    printf("da= %21.14e, db= %21.14e\n\n", da, db);
    printf("sizeof(Vquad)= %d\n", (int)sizeof(Vquad));
    qa = vut_VQuadLoad(da);
    qb = vut_VQuadLoad(db);
    vut_VQuadSPrintf(qa, 41, 1, bufa, &ierr);
    vut_VQuadSPrintf(qb, 41, 1, bufb, &ierr);
    printf("Quadruple precision numbers:\n");
    printf("qa= %s, qb= %s\n\n", bufa, bufb);

    printf("Double precision numbers:\n");
    da = vut_VQuadStore(qa, &ierr);
    db = vut_VQuadStore(qb, &ierr);
    printf("da= %21.14e, db= %21.14e\n\n", da, db);

    /* comparisons */
    printf("Comparisons:\n");
    if (vut_VQuadEQ(qa, qb)) {
        printf("%s == %s\n", bufa, bufb);
    }
    else {
        printf("%s != %s\n", bufa, bufb);
    }

    if (vut_VQuadGE(qa, qb)) {
        printf("%s >= %s\n", bufa, bufb);
    }
    else {
        printf("%s <  %s\n", bufa, bufb);
    }

    if (vut_VQuadGT(qa, qb)) {
        printf("%s >  %s\n", bufa, bufb);
    }
    else {
        printf("%s <= %s\n", bufa, bufb);
    }

    if (vut_VQuadLE(qa, qb)) {
        printf("%s <= %s\n", bufa, bufb);
    }
    else {
        printf("%s >  %s\n", bufa, bufb);
    }

    if (vut_VQuadLT(qa, qb)) {
        printf("%s <  %s\n", bufa, bufb);
    }
    else {
        printf("%s >= %s\n\n", bufa, bufb);
    }

    /* arithmetic operation */
    printf("Arithmetic operations:\n");
    qc = vut_VQuadSub(qa, qb, &ierr);
    vut_VQuadSPrintf(qc, 41, 1, bufc, &ierr);
    printf("%s - %s = %s\n", bufa, bufb, bufc);

    qc = vut_VQuadMult(qa, qb, &ierr);
    vut_VQuadSPrintf(qc, 41, 1, bufc, &ierr);
    printf("%s * %s = %s\n", bufa, bufb, bufc);

    qc = vut_VQuadDiv(qa, qb, &ierr);
    vut_VQuadSPrintf(qc, 41, 1, bufc, &ierr);
    printf("%s / %s = %s\n", bufa, bufb, bufc);

    qa = vut_VQuadLoad(2.0);
    vut_VQuadSPrintf(qa, 41, 1, bufa, &ierr);
    qb = vut_VQuadSqrt(qa, &ierr);
    vut_VQuadSPrintf(qb, 41, 1, bufb, &ierr);
    printf("sqrt(%s) = %s\n", bufa, bufb);
    qc = vut_VQuadMult(qb, qb, &ierr);
    vut_VQuadSPrintf(qc, 41, 1, bufc, &ierr);
    printf("%s * %s = %s\n\n", bufb, bufb, bufc);

    qc = vut_VQuadNeg(qa);
    vut_VQuadSPrintf(qc, 41, 1, bufc, &ierr);
    printf("-(%s) = %s\n", bufa, bufc);

    qa = vut_VQuadLoad(-2.0);
    vut_VQuadSPrintf(qa, 41, 1, bufa, &ierr);
    qb = vut_VQuadAbs(qc);
    vut_VQuadSPrintf(qb, 41, 1, bufb, &ierr);
    printf("abs(%s) = %s\n", bufc, bufb);

    /* vector operation */
    printf("Vector operations:\n");
    va[0] = vut_VQuadLoad(0.);
    va[1] = vut_VQuadLoad(3.);
    va[2] = vut_VQuadLoad(4.);
    vut_VQuadSPrintf(va[0], 41, 1, bufa, &ierr);
    vut_VQuadSPrintf(va[1], 41, 1, bufb, &ierr);
    vut_VQuadSPrintf(va[2], 41, 1, bufc, &ierr);
    printf("va= %s\n    %s\n    %s\n", bufa, bufb, bufc);

    vb[0] = vut_VQuadLoad(2.);
    vb[1] = vut_VQuadLoad(3.);
    vb[2] = vut_VQuadLoad(4.);
    vut_VQuadSPrintf(vb[0], 41, 1, bufa, &ierr);
    vut_VQuadSPrintf(vb[1], 41, 1, bufb, &ierr);
    vut_VQuadSPrintf(vb[2], 41, 1, bufc, &ierr);
    printf("va= %s\n    %s\n    %s\n", bufa, bufb, bufc);

    qa = vut_VQuadDot3(va, va, &ierr);
    vut_VQuadSPrintf(qa, 41, 1, bufa, &ierr);
    printf("Dot3(va,va) = %s\n", bufa);

    qa = vut_VQuadMag3(va, &ierr);
    vut_VQuadSPrintf(qa, 41, 1, bufa, &ierr);
    printf("Mag3(va) = %s\n", bufa);

    vut_VQuadCross3(va, vb, vc, &ierr);
    vut_VQuadSPrintf(vc[0], 41, 1, bufa, &ierr);
    vut_VQuadSPrintf(vc[1], 41, 1, bufb, &ierr);
    vut_VQuadSPrintf(vc[2], 41, 1, bufc, &ierr);
    printf("va X vb = %s\n          %s\n          %s\n", bufa, bufb, bufc);

    vut_VQuadUnit3(va, &ierr);
    vut_VQuadSPrintf(va[0], 41, 1, bufa, &ierr);
    vut_VQuadSPrintf(va[1], 41, 1, bufb, &ierr);
    vut_VQuadSPrintf(va[2], 41, 1, bufc, &ierr);
    printf("Unit3(va)= %s\n           %s\n           %s\n", bufa, bufb, bufc);
    return 0;
}

10.23. Example 23cc, C++ Operator Overloading for Quadruple Precision VQuad

This example illustrates the overloading of basic arithmetic and comparison operations in C++. A new C++ class Vcquad is created and the basic methods are defined using the VQuad functions illustrated in Example 23. Once these operators are defined users can perform simple arithmetic calculations by treating a Vcquad variable just like a Vdouble or Vfloat, using the +, -, /, or * operators.

#include <stdio.h>
#include <math.h>
#include "sam/base/base.h"

class Vcquad {
  public:
    Vcquad(): a(vut_VQuadLoad(0.)) {}
    Vcquad
    operator=(Vdouble b);
    Vcquad
    operator+(Vcquad b);
    Vcquad
    operator-(Vcquad b);
    Vcquad
    operator-();
    Vcquad
    operator*(Vcquad b);
    Vcquad
    operator+=(Vcquad b);
    Vcquad
    operator-=(Vcquad b);
    Vcquad
    operator*=(Vcquad b);
    Vcquad
    operator/=(Vcquad b);
    Vcquad
    operator/(Vcquad b);
    Vint
    operator<(Vcquad b);
    Vint
    operator<=(Vcquad b);
    Vint
    operator>(Vcquad b);
    Vint
    operator>=(Vcquad b);
    Vint
    operator==(Vcquad b);
    Vcquad
    sqrt();
    void
    Printf();

  private:
    Vquad a;
};

Vcquad
Vcquad::operator=(Vdouble b)
{
    Vcquad x;

    a = vut_VQuadLoad(b);
    return *this;
}

Vcquad
Vcquad::operator+(Vcquad b)
{
    Vcquad x;
    Vint ierr;

    x.a = vut_VQuadAdd(a, b.a, &ierr);
    return x;
}

Vcquad
Vcquad::operator-(Vcquad b)
{
    Vcquad x;
    Vint ierr;

    x.a = vut_VQuadSub(a, b.a, &ierr);
    return x;
}

Vcquad
Vcquad::operator-()
{
    Vcquad x;

    x.a = vut_VQuadNeg(a);
    return x;
}

Vcquad
Vcquad::operator*(Vcquad b)
{
    Vcquad x;
    Vint ierr;

    x.a = vut_VQuadMult(a, b.a, &ierr);
    return x;
}

Vcquad
Vcquad::operator+=(Vcquad b)
{
    Vint ierr;

    a = vut_VQuadAdd(a, b.a, &ierr);
    return *this;
}

Vcquad
Vcquad::operator-=(Vcquad b)
{
    Vint ierr;

    a = vut_VQuadSub(a, b.a, &ierr);
    return *this;
}

Vcquad
Vcquad::operator*=(Vcquad b)
{
    Vint ierr;

    a = vut_VQuadMult(a, b.a, &ierr);
    return *this;
}

Vcquad
Vcquad::operator/=(Vcquad b)
{
    Vint ierr;

    a = vut_VQuadDiv(a, b.a, &ierr);
    return *this;
}

Vcquad
Vcquad::operator/(Vcquad b)
{
    Vcquad x;
    Vint ierr;

    x.a = vut_VQuadDiv(a, b.a, &ierr);
    return x;
}

Vint
Vcquad::operator<(Vcquad b)
{
    return vut_VQuadLT(a, b.a);
}

Vint
Vcquad::operator>(Vcquad b)
{
    return vut_VQuadGT(a, b.a);
}

Vint
Vcquad::operator>=(Vcquad b)
{
    return vut_VQuadGE(a, b.a);
}

Vint
Vcquad::operator==(Vcquad b)
{
    return vut_VQuadEQ(a, b.a);
}

Vcquad
Vcquad::sqrt()
{
    Vcquad x;
    Vint ierr;

    x.a = vut_VQuadSqrt(a, &ierr);
    return x;
}

void
Vcquad::Printf()
{
    Vint ierr;

    vut_VQuadPrintf(a, 41, 1, &ierr);
}

/*----------------------------------------------------------------------
                      C++ Operator Overloading for Quadruple Precision
----------------------------------------------------------------------*/
int
main()
{
    Vcquad ca, cb, cc, v[3];

    /* load and store operations */
    ca = 1.23;
    cb = 2.;
    printf("ca = ");
    ca.Printf();
    printf("\n");
    printf("cb = ");
    cb.Printf();
    printf("\n\n");

    /* arithmetic operation */
    cc = ca + cb;
    printf("ca + cb = ");
    cc.Printf();
    printf("\n\n");
    cc = ca - cb;
    printf("ca - cb = ");
    cc.Printf();
    printf("\n\n");
    cc = ca * cb;
    printf("ca * cb = ");
    cc.Printf();
    printf("\n\n");
    cc = ca / cb;
    printf("ca / cb = ");
    cc.Printf();
    printf("\n\n");

    cc = ca.sqrt();
    printf("sqrt(ca)= ");
    cc.Printf();
    printf("\n\n");

    cc = -ca;
    printf("-ca= ");
    cc.Printf();
    printf("\n\n");

    cc = ca;
    cc += cb;
    printf("ca + cb = ");
    cc.Printf();
    printf("\n\n");

    cc = ca;
    cc -= cb;
    printf("ca - cb = ");
    cc.Printf();
    printf("\n\n");

    cc = ca;
    cc *= cb;
    printf("ca * cb = ");
    cc.Printf();
    printf("\n\n");

    cc = ca;
    cc /= cb;
    printf("ca / cb = ");
    cc.Printf();
    printf("\n\n");

    /* comparisons */
    if (ca < cb) {
        printf("ca < cb\n");
    }
    else {
        printf("ca >= cb\n");
    }
    if (cb < ca) {
        printf("cb < ca\n");
    }
    else {
        printf("cb >= ca\n");
    }
    if (ca == ca) {
        printf("ca = ca\n");
    }
    /* vector operation */
    v[0] = 3.;
    v[1] = 4.;
    v[2] = 5.;
    cc = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
    printf("v . v = ");
    cc.Printf();
    printf("\n\n");
    return 0;
}

10.24. Example 24, Test and demonstrate Tree

This example demonstrates the use of the Tree module. The Tree module is designed to hold pointers (CEETRON SAM type Vobject) in a tree structure. Nodes are added to a parent node in the tree using vsy_TreeAddNode(). The parent node 0 specifically sets the root node. A node index is returned by vsy_TreeAddNode(), use vsy_TreeSetValue() to assign a pointer to the node index.

Trees lend themselves to recursive traversal. Use vsy_TreeFirstChild() to initialize access to all children of a parent node, then use vsy_TreeNextChild() to access each child. A child node identifier of zero is returned when all children have been accessed.

#include <stdio.h>
#include "sam/base/base.h"
#include "sam/base/license.h"
#include "sam/CEETRON_SAM_license.h"

static void
print_id(Vobject* obj)
{
    Vint* val;

    val = (Vint*)obj;
    printf("parent= %d, value= %d\n", val[1], val[0]);
}

static void
print_tree(vsy_Tree* tree, Vint node)
{
    Vobject* obj;
    Vint child;

    vsy_TreeGetValue(tree, node, &obj);
    print_id(obj);

    vsy_TreeFirstChild(tree, node, &child);
    while (child != 0) {
        print_tree(tree, child);
        vsy_TreeNextChild(tree, child, &child);
    }
}

/*----------------------------------------------------------------------
                      Test and demonstrate Tree
----------------------------------------------------------------------*/
int
main()
{
    vsy_Tree* tree;
    Vint root, c[3], child, g2_1, g2_2;
    Vint value[1000][2];

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* instance object */
    tree = vsy_TreeBegin();

    /* extract root node */
    vsy_TreeAddNode(tree, 0, &root);
    value[root][0] = root;
    value[root][1] = 0;
    vsy_TreeSetValue(tree, root, (Vobject*)&value[root]);

    /* add 3 children to root */
    vsy_TreeAddNode(tree, root, &c[0]);
    value[c[0]][0] = c[0];
    value[c[0]][1] = root;
    vsy_TreeSetValue(tree, c[0], (Vobject*)&value[c[0]]);

    vsy_TreeAddNode(tree, root, &c[1]);
    value[c[1]][0] = c[1];
    value[c[1]][1] = root;
    vsy_TreeSetValue(tree, c[1], (Vobject*)&value[c[1]]);

    vsy_TreeAddNode(tree, root, &c[2]);
    value[c[2]][0] = c[2];
    value[c[2]][1] = root;
    vsy_TreeSetValue(tree, c[2], (Vobject*)&value[c[2]]);

    /* add a child to c[2] */
    vsy_TreeAddNode(tree, c[2], &child);
    value[child][0] = child;
    value[child][1] = c[2];
    vsy_TreeSetValue(tree, child, (Vobject*)&value[child]);

    /* add 2 grandchildren to c[2] */
    vsy_TreeAddNode(tree, child, &g2_1);
    value[g2_1][0] = g2_1;
    value[g2_1][1] = child;
    vsy_TreeSetValue(tree, g2_1, (Vobject*)&value[g2_1]);

    vsy_TreeAddNode(tree, child, &g2_2);
    value[g2_2][0] = g2_2;
    value[g2_2][1] = child;
    vsy_TreeSetValue(tree, g2_2, (Vobject*)&value[g2_2]);

    /* list all children recursively */
    printf("Tree after all insertions:\n");
    vsy_TreeForEach(tree, print_id);

    /* remove one node */
    vsy_TreeDelNode(tree, child);

    /* list all children recursively */
    printf("\nTree after removing node %d:\n", child);
    print_tree(tree, root);

    /* re-insert a child to c[2] */
    vsy_TreeAddNode(tree, c[2], &child);
    value[child][0] = child;
    value[child][1] = c[2];
    vsy_TreeSetValue(tree, child, (Vobject*)&value[child]);

    /* re-insert 2 grandchildren to c[2] */
    vsy_TreeAddNode(tree, child, &g2_1);
    value[g2_1][0] = g2_1;
    value[g2_1][1] = child;
    vsy_TreeSetValue(tree, g2_1, (Vobject*)&value[g2_1]);

    vsy_TreeAddNode(tree, child, &g2_2);
    value[g2_2][0] = g2_2;
    value[g2_2][1] = child;
    vsy_TreeSetValue(tree, g2_2, (Vobject*)&value[g2_2]);

    printf("\nTree after reinsertion of children:\n");
    vsy_TreeForEach(tree, print_id);

    vsy_TreeEnd(tree);
    return 0;
}

10.25. Example 25, Test and demonstrate Pred

This example demonstrates the use of the Pred module to accurately determine whether triangles and tetrahedra are proper, degenerate, or inverted; and whether a point lies inside, outside, or on a circle defined by three points or a sphere defined by four points.

#include <stdio.h>
#include <math.h>
#include "sam/base/base.h"
#include "sam/base/license.h"
#include "sam/CEETRON_SAM_license.h"

/*----------------------------------------------------------------------
                      Test and demonstrate Pred
----------------------------------------------------------------------*/
int
main()
{
    Vdouble x[4][3], e[3], xt[3][3], xl[2][3], xl0[2][2], xl1[2][2];
    vsy_Pred* pred;
    Vdouble retval;
    Vint pass;
    Vint code, ient, ierr;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    /* instance object */
    pred = vsy_PredBegin();
    /* push FPU control words */
    vsy_PredPushFPU(pred);
    /* check to see if Pred is exact */
    vsy_PredExact(pred, &pass);
    if (pass == 0) {
        printf("Pred is unable to do exact arithmetic, check compiler options\n");
    }
    else {
        printf("Pred is able to do exact arithmetic\n");
    }
    /* set tetrahedron vertices for right tetrahedron */
    /* first node at origin */
    x[0][0] = 0.;
    x[0][1] = 0.;
    x[0][2] = 0.;
    /* second node on x-axis */
    x[1][0] = 1.;
    x[1][1] = 0.;
    x[1][2] = 0.;
    /* third node on y-axis */
    x[2][0] = 0.;
    x[2][1] = 1.;
    x[2][2] = 0.;
    /* fourth node on z-axis */
    x[3][0] = 0.;
    x[3][1] = 0.;
    x[3][2] = 1.;
    /* test point for insphere */
    e[0] = 20.;
    e[1] = .25;
    e[2] = .25;
    retval = vsy_PredInsphere(pred, x[0], x[1], x[2], x[3], e);
    printf("Point outside sphere: retval= %e\n", retval);

    e[0] = .2;
    e[1] = .25;
    e[2] = .25;
    retval = vsy_PredInsphere(pred, x[0], x[1], x[2], x[3], e);
    printf("Point inside sphere: retval= %e\n", retval);

    e[0] = 0.;
    e[1] = 0.;
    e[2] = 0.;
    retval = vsy_PredInsphere(pred, x[0], x[1], x[2], x[3], e);
    printf("Point on sphere: retval= %e\n", retval);

    /* compute orientation */
    /* return value should be positive */
    retval = vsy_PredOrient3d(pred, x[0], x[1], x[2], x[3]);
    printf("Proper tetrahedron: retval= %e\n", retval);

    /* move second point close to plane of 1,3 and 4th points */
    /* return value should be positive */
    x[1][0] = 1.e-100;
    x[1][1] = 0.5;
    x[1][2] = 0.5;
    retval = vsy_PredOrient3d(pred, x[0], x[1], x[2], x[3]);
    printf("Proper tetrahedron: retval= %e\n", retval);
    /* move second point to plane of 1,3 and 4th points */
    /* return value should be zero */
    x[1][0] = 0.;
    x[1][1] = 0.5;
    x[1][2] = 0.5;
    retval = vsy_PredOrient3d(pred, x[0], x[1], x[2], x[3]);
    printf("Degenerate tetrahedron: retval= %e\n", retval);
    /* move second point beyond plane of 1,3 and 4th points */
    /* return value should be negative */
    x[1][0] = -1.e-100;
    x[1][1] = 0.5;
    x[1][2] = 0.5;
    retval = vsy_PredOrient3d(pred, x[0], x[1], x[2], x[3]);
    printf("Inverted tetrahedron: retval= %e\n", retval);

    /* compute line tri intersection status */
    xt[0][0] = 0.;
    xt[0][1] = 0.;
    xt[0][2] = 0.;
    /* second node on x-axis */
    xt[1][0] = 1.;
    xt[1][1] = 0.;
    xt[1][2] = 0.;
    /* third node on y-axis */
    xt[2][0] = 0.;
    xt[2][1] = 1.;
    xt[2][2] = 0.;
    /* line endpoints */
    xl[0][0] = -1.;
    xl[0][1] = 0.;
    xl[0][2] = 0.;
    xl[1][0] = 0.;
    xl[1][1] = 2.;
    xl[1][2] = 0.;
    vsy_PredIntersectLineTri(pred, xt, xl, &code, &ient, &ierr);
    printf("Line Tri no intersection, code= %d\n", code);
    /* line end point in triangle interior */
    xl[1][0] = .25;
    xl[1][1] = .25;
    xl[1][2] = 0.;
    vsy_PredIntersectLineTri(pred, xt, xl, &code, &ient, &ierr);
    printf("Line Tri coplanar intersection, code= %d\n", code);
    /* line spans triangle */
    xl[1][0] = .75;
    xl[1][1] = .75;
    xl[1][2] = 0.;
    vsy_PredIntersectLineTri(pred, xt, xl, &code, &ient, &ierr);
    printf("Line Tri coplanar intersection, code= %d\n", code);

    /* two-dimension tests */
    /* set circle points */
    x[0][0] = -1.;
    x[0][1] = 0.;
    x[1][0] = 1.;
    x[1][1] = 0.;
    x[2][0] = 0.;
    x[2][1] = 1.;

    /* check point inside circle */
    e[0] = 0.;
    e[1] = 0.;
    retval = vsy_PredIncircle(pred, x[0], x[1], x[2], e);
    printf("Point inside circle: retval= %e\n", retval);

    /* check point outside circle */
    e[0] = 2.;
    e[1] = 0.;
    retval = vsy_PredIncircle(pred, x[0], x[1], x[2], e);
    printf("Point outside circle: retval= %e\n", retval);

    /* check point on circle */
    e[0] = 0.;
    e[1] = -1.;
    retval = vsy_PredIncircle(pred, x[0], x[1], x[2], e);
    printf("Point on circle: retval= %e\n", retval);

    /* check properly defined triangle */
    x[0][0] = 0.;
    x[0][1] = 0.;
    x[1][0] = 1.;
    x[1][1] = 0.;
    x[2][0] = 0.;
    x[2][1] = 1.;
    retval = vsy_PredOrient2d(pred, x[0], x[1], x[2]);
    printf("Proper triangle: retval= %e\n", retval);

    /* check degenerate triangle */
    x[0][0] = 0.;
    x[0][1] = 0.;
    x[1][0] = 1.;
    x[1][1] = 0.;
    x[2][0] = 0.5;
    x[2][1] = 0.;
    retval = vsy_PredOrient2d(pred, x[0], x[1], x[2]);
    printf("Degenerate triangle: retval= %e\n", retval);

    /* check inverted triangle */
    x[0][0] = 0.;
    x[0][1] = 0.;
    x[1][0] = 1.;
    x[1][1] = 0.;
    x[2][0] = 0.;
    x[2][1] = -1.;
    retval = vsy_PredOrient2d(pred, x[0], x[1], x[2]);
    printf("Inverted triangle: retval= %e\n", retval);

    /* compute line line intersection status */
    xl0[0][0] = 0.;
    xl0[0][1] = 0.;
    xl0[1][0] = 1.;
    xl0[1][1] = 0.;
    xl1[0][0] = -1.;
    xl1[0][1] = 0.;
    xl1[1][0] = 2.;
    xl1[1][1] = 0.;
    vsy_PredIntersectLineLine(pred, xl0, xl1, &code, &ient, &ierr);
    printf("Line Line intersection, code= %d, ient= %d\n", code, ient);

    /* pop (restore) FPU control words */
    vsy_PredPopFPU(pred);

    vsy_PredEnd(pred);
    return 0;
}

10.26. Example 26, Test and demonstrate StrUtil

This example demonstrates the use of the StrUtil module to convert wide character strings to UTF-8 encoding and back again.

#include <stdio.h>
#include <wchar.h>
#include "sam/base/base.h"
#include "sam/base/license.h"
#include "sam/CEETRON_SAM_license.h"

/*----------------------------------------------------------------------
                      Test and demonstrate StrUtil
----------------------------------------------------------------------*/
int
main()
{
    wchar_t euro[] = {L'U', L'n', L'i', L'c', L'o', L'd', L'e', L' ', L'E', L'u', L'r', L'o', L'=', L' ', 0x20ac, L'\0'};
    Vchar str[256];
    wchar_t wstr[256];
    Vint numchar;

    vsy_LicenseValidate(CEETRON_SAM_LICENSE);

    printf("\nStrUtil test\n");

    /* convert wide char to utf8 */
    vut_StrUtilToUTF8(euro, 256, str);

    numchar = vut_StrUtilLenUTF8(str);
    printf("number of characters= %d\n", numchar);
    printf("%s\n", str);
    /* convert back to wide char */
    vut_StrUtilFromUTF8(str, 256, wstr);
    /* test */
    if (wcscmp(wstr, euro)) {
        printf("string comparison fails\n");
    }
    else {
        printf("string comparison succeeds\n");
    }

    return 0;
}