OSDN Git Service

Please enter the commit message for your changes. Lines starting
[eos/base.git] / util / src / TclTk / blt2.5 / generic / bltVecObjCmd.c
diff --git a/util/src/TclTk/blt2.5/generic/bltVecObjCmd.c b/util/src/TclTk/blt2.5/generic/bltVecObjCmd.c
deleted file mode 100644 (file)
index b6cba9e..0000000
+++ /dev/null
@@ -1,3219 +0,0 @@
-
-/*
- * bltVecCmd.c --
- *
- *     This module implements vector data objects.
- *
- * Copyright 1995-1998 Lucent Technologies, Inc.
- *
- * Permission to use, copy, modify, and distribute this software and
- * its documentation for any purpose and without fee is hereby
- * granted, provided that the above copyright notice appear in all
- * copies and that both that the copyright notice and warranty
- * disclaimer appear in supporting documentation, and that the names
- * of Lucent Technologies any of their entities not be used in
- * advertising or publicity pertaining to distribution of the software
- * without specific, written prior permission.
- *
- * Lucent Technologies disclaims all warranties with regard to this
- * software, including all implied warranties of merchantability and
- * fitness.  In no event shall Lucent Technologies be liable for any
- * special, indirect or consequential damages or any damages
- * whatsoever resulting from loss of use, data or profits, whether in
- * an action of contract, negligence or other tortuous action, arising
- * out of or in connection with the use or performance of this
- * software.
- */
-
-/*
- * TODO:
- *     o Add H. Kirsch's vector binary read operation
- *             x binread file0
- *             x binread -file file0
- *
- *     o Add ASCII/binary file reader
- *             x read fileName
- *
- *     o Allow Tcl-based client notifications.
- *             vector x
- *             x notify call Display
- *             x notify delete Display
- *             x notify reorder #1 #2
- */
-
-#include "bltVecInt.h"
-
-#if (TCL_MAJOR_VERSION > 7) 
-
-static 
-int GetDouble(interp, objPtr, valuePtr)
-    Tcl_Interp *interp;
-    Tcl_Obj *objPtr;
-    double *valuePtr;
-{
-    /* First try to extract the value as a double precision number. */
-    if (Tcl_GetDoubleFromObj(interp, objPtr, valuePtr) == TCL_OK) {
-       return TCL_OK;
-    }
-    Tcl_ResetResult(interp);
-
-    /* Then try to parse it as an expression. */
-    if (Tcl_ExprDouble(interp, Tcl_GetString(objPtr), valuePtr) == TCL_OK) {
-       return TCL_OK;
-    }
-    return TCL_ERROR;
-}
-
-static Tcl_Obj *
-GetValues(VectorObject *vPtr, int first, int last)
-{ 
-    register int i; 
-    Tcl_Obj *listObjPtr;
-
-    listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
-    for (i = first; i <= last; i++) { 
-       Tcl_ListObjAppendElement(vPtr->interp, listObjPtr, 
-                                Tcl_NewDoubleObj(vPtr->valueArr[i]));
-    } 
-    return listObjPtr;
-}
-
-static void
-ReplicateValue(vPtr, first, last, value) 
-    VectorObject *vPtr;
-    int first, last;
-    double value;
-{ 
-    register int i;
-    for (i = first; i <= last; i++) { 
-       vPtr->valueArr[i] = value; 
-    } 
-    vPtr->notifyFlags |= UPDATE_RANGE; 
-}
-
-static int
-CopyList(vPtr, objc, objv)
-    VectorObject *vPtr;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    register int i;
-    double value;
-
-    if (Blt_VectorChangeLength(vPtr, objc) != TCL_OK) {
-       return TCL_ERROR;
-    }
-    for (i = 0; i < objc; i++) {
-       if (GetDouble(vPtr->interp, objv[i], &value) != TCL_OK) {
-           Blt_VectorChangeLength(vPtr, i);
-           return TCL_ERROR;
-       }
-       vPtr->valueArr[i] = value;
-    }
-    return TCL_OK;
-}
-
-static int
-AppendVector(destPtr, srcPtr)
-    VectorObject *destPtr, *srcPtr;
-{
-    int nBytes;
-    int oldSize, newSize;
-
-    oldSize = destPtr->length;
-    newSize = oldSize + srcPtr->last - srcPtr->first + 1;
-    if (Blt_VectorChangeLength(destPtr, newSize) != TCL_OK) {
-       return TCL_ERROR;
-    }
-    nBytes = (newSize - oldSize) * sizeof(double);
-    memcpy((char *)(destPtr->valueArr + oldSize),
-       (srcPtr->valueArr + srcPtr->first), nBytes);
-    destPtr->notifyFlags |= UPDATE_RANGE;
-    return TCL_OK;
-}
-
-static int
-InsertList(vPtr, objc, objv, idx)
-    VectorObject *vPtr;
-    int objc;
-    Tcl_Obj *CONST *objv;
-    int idx;
-{
-    int count;
-    register int i;
-    double value;
-    int oldSize, newSize;
-
-    oldSize = vPtr->length;
-    newSize = vPtr->length + objc;
-    if (Blt_VectorChangeLength(vPtr, newSize) != TCL_OK) {
-       return -1;
-    }
-    memmove((char *)(vPtr->valueArr + idx + objc),
-        (char *)(vPtr->valueArr + idx), sizeof(double)*(oldSize-idx));
-    count = oldSize;
-    for (i = 0; i < objc; i++) {
-       if (GetDouble(vPtr->interp, objv[i], &value) != TCL_OK) {
-           Blt_VectorChangeLength(vPtr, count);
-           return TCL_ERROR;
-       }
-       vPtr->valueArr[idx++] = value;
-    }
-    vPtr->notifyFlags |= UPDATE_RANGE;
-    return (newSize-oldSize);
-}
-static int
-InsertVector(destPtr, srcPtr, idx)
-    VectorObject *destPtr, *srcPtr;
-    int idx;
-{
-    int nBytes;
-    int oldSize, newSize, dif;
-
-    oldSize = destPtr->length;
-    newSize = oldSize + srcPtr->last - srcPtr->first + 1;
-    if (Blt_VectorChangeLength(destPtr, newSize) != TCL_OK) {
-       return -1;
-    }
-    nBytes = (newSize - oldSize) * sizeof(double);
-    dif = (newSize-oldSize);
-    memmove((char *)(srcPtr->valueArr + idx + dif),
-        (char *)(srcPtr->valueArr + idx), sizeof(double)*(oldSize-idx));
-    memcpy((char *)(destPtr->valueArr + oldSize),
-       (srcPtr->valueArr + srcPtr->first), nBytes);
-    destPtr->notifyFlags |= UPDATE_RANGE;
-    return dif;
-}
-
-static int
-AppendList(vPtr, objc, objv)
-    VectorObject *vPtr;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    int count;
-    register int i;
-    double value;
-    int oldSize;
-
-    oldSize = vPtr->length;
-    if (Blt_VectorChangeLength(vPtr, vPtr->length + objc) != TCL_OK) {
-       return TCL_ERROR;
-    }
-    count = oldSize;
-    for (i = 0; i < objc; i++) {
-       if (GetDouble(vPtr->interp, objv[i], &value) != TCL_OK) {
-           Blt_VectorChangeLength(vPtr, count);
-           return TCL_ERROR;
-       }
-       vPtr->valueArr[count++] = value;
-    }
-    vPtr->notifyFlags |= UPDATE_RANGE;
-    return TCL_OK;
-}
-
-/* Vector instance option commands */
-
-/*
- * -----------------------------------------------------------------------
- *
- * AppendOp --
- *
- *     Appends one of more Tcl lists of values, or vector objects
- *     onto the end of the current vector object.
- *
- * Results:
- *     A standard Tcl result.  If a current vector can't be created,
- *      resized, any of the named vectors can't be found, or one of
- *     lists of values is invalid, TCL_ERROR is returned.
- *
- * Side Effects:
- *     Clients of current vector will be notified of the change.
- *
- * -----------------------------------------------------------------------
- */
-static int
-AppendOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    register int i;
-    int result;
-    VectorObject *v2Ptr;
-
-    for (i = 2; i < objc; i++) {
-       v2Ptr = Blt_VectorParseElement((Tcl_Interp *)NULL, vPtr->dataPtr, 
-              Tcl_GetString(objv[i]), (char **)NULL, NS_SEARCH_BOTH);
-       if (v2Ptr != NULL) {
-           result = AppendVector(vPtr, v2Ptr);
-       } else {
-           int nElem;
-           Tcl_Obj **elemObjArr;
-
-           if (Tcl_ListObjGetElements(interp, objv[i], &nElem, &elemObjArr) 
-               != TCL_OK) {
-               return TCL_ERROR;
-           }
-           result = AppendList(vPtr, nElem, elemObjArr);
-       }
-       if (result != TCL_OK) {
-           return TCL_ERROR;
-       }
-    }
-    if (vPtr->numcols && (vPtr->length%vPtr->numcols)) {
-        Tcl_Obj *str = Tcl_NewStringObj("0", -1);
-        int add = (vPtr->numcols-(vPtr->length%vPtr->numcols));
-        Tcl_IncrRefCount(str);
-        for (i=0; i<add; i++) {
-            AppendList(vPtr, 1, &str);
-        }
-        Tcl_DecrRefCount(str);
-    }
-    if (objc > 2) {
-       if (vPtr->flush) {
-           Blt_VectorFlushCache(vPtr);
-       }
-       Blt_VectorUpdateClients(vPtr);
-    }
-    return TCL_OK;
-}
-/*
-* -----------------------------------------------------------------------
-*
-* InsertOp --
-*
-*      Insert one of more Tcl lists of values at index.
-*
-* Results:
-*      A standard Tcl result.  If a current vector can't be created,
-*      resized, any of the named vectors can't be found, or one of
-*      lists of values is invalid, TCL_ERROR is returned.
-*
-* Side Effects:
-*      Clients of current vector will be notified of the change.
-*
-* -----------------------------------------------------------------------
-*/
-static int
-InsertOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    register int i;
-    int result, idx, cnt;
-    VectorObject *v2Ptr;
-
-    if (Blt_VectorGetIndex(interp, vPtr, Tcl_GetString(objv[2]), &idx, 
-        INDEX_CHECK, (Blt_VectorIndexProc **) NULL) != TCL_OK) {
-            return TCL_ERROR;
-    }
-
-    for (i = 3; i < objc; i++) {
-        v2Ptr = Blt_VectorParseElement((Tcl_Interp *)NULL, vPtr->dataPtr, 
-        Tcl_GetString(objv[i]), (char **)NULL, NS_SEARCH_BOTH);
-        result = TCL_OK;
-        if (v2Ptr != NULL) {
-            if (v2Ptr->length>0) {
-                cnt = InsertVector(vPtr, v2Ptr, idx);
-                if (cnt<0) {
-                    result = TCL_ERROR;
-                } else {
-                    idx += cnt;
-                }
-            }
-        } else {
-            int nElem;
-            Tcl_Obj **elemObjArr;
-
-            if (Tcl_ListObjGetElements(interp, objv[i], &nElem, &elemObjArr) 
-                != TCL_OK) {
-                return TCL_ERROR;
-            }
-            cnt = InsertList(vPtr, nElem, elemObjArr, idx);
-            if (cnt<0) {
-                result = TCL_ERROR;
-            } else {
-                idx += cnt;
-            }
-        }
-        if (result != TCL_OK) {
-            return TCL_ERROR;
-        }
-    }
-    if (vPtr->numcols && (vPtr->length%vPtr->numcols)) {
-        Tcl_Obj *str = Tcl_NewStringObj("0", -1);
-        int add = (vPtr->numcols-(vPtr->length%vPtr->numcols));
-        Tcl_IncrRefCount(str);
-        for (i=0; i<add; i++) {
-            InsertList(vPtr, 1, &str, idx);
-        }
-        Tcl_DecrRefCount(str);
-    }
-    if (objc > 2) {
-        if (vPtr->flush) {
-            Blt_VectorFlushCache(vPtr);
-        }
-        Blt_VectorUpdateClients(vPtr);
-    }
-    return TCL_OK;
-}
-
-/*
- * -----------------------------------------------------------------------
- *
- * ClearOp --
- *
- *     Deletes all the accumulated array indices for the Tcl array
- *     associated will the vector.  This routine can be used to
- *     free excess memory from a large vector.
- *      Call with arg to change auto-flush option.
- *
- * Results:
- *     Always returns TCL_OK.
- *
- * Side Effects:
- *     Memory used for the entries of the Tcl array variable is freed.
- *
- * -----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-ClearOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;                  
-    Tcl_Obj *CONST *objv;      
-{
-    if (objc>2) {
-        if (Tcl_GetBooleanFromObj(interp, objv[2], &vPtr->flush) != TCL_OK) {
-            return TCL_ERROR;
-        }
-    }
-    Blt_VectorFlushCache(vPtr);
-    Blt_VectorUpdateClients(vPtr);
-    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(vPtr->flush));
-    return TCL_OK;
-}
-
-/*
- * -----------------------------------------------------------------------
- *
- * DeleteOp --
- *
- *     Deletes the given indices from the vector.  If no indices are
- *     provided the entire vector is deleted.
- *
- * Results:
- *     A standard Tcl result.  If any of the given indices is invalid,
- *     interp->result will an error message and TCL_ERROR is returned.
- *
- * Side Effects:
- *     The clients of the vector will be notified of the vector
- *     deletions.
- *
- * -----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-DeleteOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    unsigned char *unsetArr;
-    register int i, j;
-    register int count;
-    char *string;
-
-    /* FIXME: Don't delete vector with no indices.  */
-    if (objc == 2) {
-       Blt_VectorFree(vPtr);
-       return TCL_OK;
-    }
-    /*
-     * Allocate an "unset" bitmap the size of the vector.  
-     */
-    unsetArr = Blt_Calloc(sizeof(unsigned char), (vPtr->length + 7) / 8);
-    assert(unsetArr);
-
-#define SetBit(i) \
-    unsetArr[(i) >> 3] |= (1 << ((i) & 0x07))
-#define GetBit(i) \
-    (unsetArr[(i) >> 3] & (1 << ((i) & 0x07)))
-
-    for (i = 2; i < objc; i++) {
-       string = Tcl_GetString(objv[i]);
-       if (Blt_VectorGetIndexRange(interp, vPtr, string, 
-               (INDEX_COLON | INDEX_CHECK), (Blt_VectorIndexProc **) NULL) 
-               != TCL_OK) {
-           Blt_Free(unsetArr);
-           return TCL_ERROR;
-       }
-       for (j = vPtr->first; j <= vPtr->last; j++) {
-           SetBit(j);          /* Mark the range of elements for deletion. */
-       }
-    }
-    count = 0;
-    for (i = 0; i < vPtr->length; i++) {
-       if (GetBit(i)) {
-           continue;           /* Skip elements marked for deletion. */
-       }
-       if (count < i) {
-           vPtr->valueArr[count] = vPtr->valueArr[i];
-       }
-       count++;
-    }
-    Blt_Free(unsetArr);
-    vPtr->length = count;
-    if (vPtr->flush) {
-       Blt_VectorFlushCache(vPtr);
-    }
-    Blt_VectorUpdateClients(vPtr);
-    return TCL_OK;
-}
-
-/*
- * -----------------------------------------------------------------------
- *
- * DupOp --
- *
- *     Creates one or more duplicates of the vector object.
- *
- * Results:
- *     A standard Tcl result.  If a new vector can't be created,
- *      or and existing vector resized, TCL_ERROR is returned.
- *
- * Side Effects:
- *     Clients of existing vectors will be notified of the change.
- *
- * -----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-DupOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;                /* Not used. */
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    VectorObject *v2Ptr;
-    int isNew;
-    register int i;
-    char *string;
-
-    for (i = 2; i < objc; i++) {
-       string = Tcl_GetString(objv[i]);
-       v2Ptr = Blt_VectorCreate(vPtr->dataPtr, string, string, string,&isNew);
-       if (v2Ptr == NULL) {
-           return TCL_ERROR;
-       }
-       if (v2Ptr == vPtr) {
-           continue;
-       }
-       if (Blt_VectorDuplicate(v2Ptr, vPtr) != TCL_OK) {
-           return TCL_ERROR;
-       }
-       if (!isNew) {
-           if (v2Ptr->flush) {
-               Blt_VectorFlushCache(v2Ptr);
-           }
-           Blt_VectorUpdateClients(v2Ptr);
-       }
-    }
-    return TCL_OK;
-}
-
-/*
- * -----------------------------------------------------------------------
- *
- * IndexOp --
- *
- *     Sets or reads the value of the index.  This simulates what the
- *     vector's variable does.
- *
- * Results:
- *     A standard Tcl result.  If the index is invalid,
- *     interp->result will an error message and TCL_ERROR is returned.
- *     Otherwise interp->result will contain the values.
- *
- * -----------------------------------------------------------------------
- */
-static int
-IndexOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    int first, last;
-    char *string;
-
-    string = Tcl_GetString(objv[2]);
-    if (Blt_VectorGetIndexRange(interp, vPtr, string, INDEX_ALL_FLAGS, 
-               (Blt_VectorIndexProc **) NULL) != TCL_OK) {
-       return TCL_ERROR;
-    }
-    first = vPtr->first, last = vPtr->last;
-    if (objc == 3) {
-       Tcl_Obj *listObjPtr;
-
-       if (first == vPtr->length) {
-           Tcl_AppendResult(interp, "can't get index \"", string, "\"",
-               (char *)NULL);
-           return TCL_ERROR;   /* Can't read from index "++end" */
-       }
-       listObjPtr = GetValues(vPtr, first, last);
-       Tcl_SetObjResult(interp, listObjPtr);
-    } else {
-       double value;
-
-       /* FIXME: huh? Why set values here?.  */
-       if (first == SPECIAL_INDEX) {
-           Tcl_AppendResult(interp, "can't set index \"", string, "\"",
-               (char *)NULL);
-           return TCL_ERROR;   /* Tried to set "min" or "max" */
-       }
-       if (GetDouble(vPtr->interp, objv[3], &value) != TCL_OK) {
-           return TCL_ERROR;
-       }
-       if (first == vPtr->length) {
-           if (Blt_VectorChangeLength(vPtr, vPtr->length + 1) != TCL_OK) {
-               return TCL_ERROR;
-           }
-       }
-       ReplicateValue(vPtr, first, last, value);
-       Tcl_SetObjResult(interp, objv[3]);
-       if (vPtr->flush) {
-           Blt_VectorFlushCache(vPtr);
-       }
-       Blt_VectorUpdateClients(vPtr);
-    }
-    return TCL_OK;
-}
-
-/* Get an int or expression. */
-static int
-GetIntObj(interp, obj, iPtr)
-    Tcl_Interp *interp;
-    Tcl_Obj *obj;
-    int *iPtr;
-{
-    if (Tcl_GetIntFromObj(interp, obj, iPtr) != TCL_OK) {
-        long l;
-        Tcl_ResetResult(interp);
-        if (Tcl_ExprLongObj(interp, obj, &l) != TCL_OK) {
-            return TCL_ERROR;
-        }
-        *iPtr = (int)l;
-    }
-    return TCL_OK;
-}
-
-
-/*
- * -----------------------------------------------------------------------
- *
- * LengthOp --
- *
- *     Returns the length of the vector.  If a new size is given, the
- *     vector is resized to the new vector.
- *
- * Results:
- *     A standard Tcl result.  If the new length is invalid,
- *     interp->result will an error message and TCL_ERROR is returned.
- *     Otherwise interp->result will contain the length of the vector.
- *
- * -----------------------------------------------------------------------
- */
-static int
-LengthOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    if (objc == 3) {
-       int size;
-
-       if (GetIntObj(interp, objv[2], &size) != TCL_OK) {
-           return TCL_ERROR;
-       }
-       if (size < 0) {
-           Tcl_AppendResult(interp, "bad vector size \"", 
-               Tcl_GetString(objv[2]), "\"", (char *)NULL);
-           return TCL_ERROR;
-       }
-       if (size%vPtr->numcols) {
-             Tcl_AppendResult(interp, "size not multiple of columns \"", 
-                 Tcl_GetString(objv[2]), "\"", (char *)NULL);
-             return TCL_ERROR;
-        }
-       if (Blt_VectorChangeLength(vPtr, size) != TCL_OK) {
-           return TCL_ERROR;
-       }
-       if (vPtr->flush) {
-           Blt_VectorFlushCache(vPtr);
-       }
-       Blt_VectorUpdateClients(vPtr);
-    }
-    Tcl_SetObjResult(interp, Tcl_NewIntObj(vPtr->length));
-    return TCL_OK;
-}
-
-/*
- * -----------------------------------------------------------------------
- *
- * VariableOp --
- *
- *     Queries or sets the offset of the array index from the base
- *     address of the data array of values.
- *
- * Results:
- *     A standard Tcl result.  If the source vector doesn't exist
- *     or the source list is not a valid list of numbers, TCL_ERROR
- *     returned.  Otherwise TCL_OK is returned.
- *
- * -----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-VariableOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;                  /* Not used. */
-    Tcl_Obj *CONST *objv;
-{
-    if (objc > 2) {
-       if (Blt_VectorMapVariable(interp, vPtr, Tcl_GetString(objv[2])) 
-           != TCL_OK) {
-           return TCL_ERROR;
-       }
-    }
-    if (vPtr->arrayName != NULL) {
-       Tcl_SetResult(interp, vPtr->arrayName, TCL_VOLATILE);
-    }
-    return TCL_OK;
-}
-
-/*
- * -----------------------------------------------------------------------
- *
- * MergeOp --
- *
- *     Merges the values from the given vectors to the current vector.
- *
- * Results:
- *     A standard Tcl result.  If any of the given vectors differ in size,
- *     TCL_ERROR is returned.  Otherwise TCL_OK is returned and the
- *     vector data will contain merged values of the given vectors.
- *
- * -----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-MergeOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    VectorObject *v2Ptr;
-    VectorObject **vecArr;
-    register VectorObject **vPtrPtr;
-    int refSize, length, nElem;
-    register int i;
-    double *valuePtr, *valueArr;
-    
-    /* Allocate an array of vector pointers of each vector to be
-     * merged in the current vector.  */
-    vecArr = Blt_Malloc(sizeof(VectorObject *) * objc);
-    assert(vecArr);
-    vPtrPtr = vecArr;
-
-    refSize = -1;
-    nElem = 0;
-    for (i = 2; i < objc; i++) {
-       if (Blt_VectorLookupName(vPtr->dataPtr, Tcl_GetString(objv[i]), &v2Ptr)
-               != TCL_OK) {
-           Blt_Free(vecArr);
-           return TCL_ERROR;
-       }
-       /* Check that all the vectors are the same length */
-       length = v2Ptr->last - v2Ptr->first + 1;
-       if (refSize < 0) {
-           refSize = length;
-       } else if (length != refSize) {
-           Tcl_AppendResult(vPtr->interp, "vectors \"", vPtr->name,
-               "\" and \"", v2Ptr->name, "\" differ in length",
-               (char *)NULL);
-           Blt_Free(vecArr);
-           return TCL_ERROR;
-       }
-       *vPtrPtr++ = v2Ptr;
-       nElem += refSize;
-    }
-    *vPtrPtr = NULL;
-
-    valueArr = Blt_Malloc(sizeof(double) * nElem);
-    if (valueArr == NULL) {
-       Tcl_AppendResult(vPtr->interp, "not enough memory to allocate ", 
-                Blt_Itoa(nElem), " vector elements", (char *)NULL);
-       return TCL_ERROR;
-    }
-    /* Merge the values from each of the vectors into the current vector */
-    valuePtr = valueArr;
-    for (i = 0; i < refSize; i++) {
-       for (vPtrPtr = vecArr; *vPtrPtr != NULL; vPtrPtr++) {
-           *valuePtr++ = (*vPtrPtr)->valueArr[i + (*vPtrPtr)->first];
-       }
-    }
-    Blt_Free(vecArr);
-    Blt_VectorReset(vPtr, valueArr, nElem, nElem, TCL_DYNAMIC);
-    return TCL_OK;
-}
-
-/*
- * -----------------------------------------------------------------------
- *
- * NormalizeOp --
- *
- *     Normalizes the vector.
- *
- * Results:
- *     A standard Tcl result.  If the density is invalid, TCL_ERROR
- *     is returned.  Otherwise TCL_OK is returned.
- *
- * -----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-NormalizeOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    register int i;
-    double range;
-
-    Blt_VectorUpdateRange(vPtr);
-    range = vPtr->max - vPtr->min;
-    if (objc > 2) {
-       VectorObject *v2Ptr;
-       int isNew;
-       char *string;
-
-       string = Tcl_GetString(objv[2]);
-       v2Ptr = Blt_VectorCreate(vPtr->dataPtr, string, string, string, 
-                                &isNew);
-       if (v2Ptr == NULL) {
-           return TCL_ERROR;
-       }
-       if (Blt_VectorChangeLength(v2Ptr, vPtr->length) != TCL_OK) {
-           return TCL_ERROR;
-       }
-       for (i = 0; i < vPtr->length; i++) {
-           v2Ptr->valueArr[i] = (vPtr->valueArr[i] - vPtr->min) / range;
-       }
-       Blt_VectorUpdateRange(v2Ptr);
-       if (!isNew) {
-           if (v2Ptr->flush) {
-               Blt_VectorFlushCache(v2Ptr);
-           }
-           Blt_VectorUpdateClients(v2Ptr);
-       }
-    } else {
-       double norm;
-       Tcl_Obj *listObjPtr;
-
-       listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
-       for (i = 0; i < vPtr->length; i++) {
-           norm = (vPtr->valueArr[i] - vPtr->min) / range;
-           Tcl_ListObjAppendElement(interp, listObjPtr, 
-               Tcl_NewDoubleObj(norm));
-       }
-       Tcl_SetObjResult(interp, listObjPtr);
-    }
-    return TCL_OK;
-}
-
-/*
- * -----------------------------------------------------------------------
- *
- * NotifyOp --
- *
- *     Notify clients of changes to vector.
- *
- * Results:
- *     A standard Tcl result.
- *
- *  x vector notify now
- *  x vector notify always
- *  x vector notify whenidle
- *
- * -----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-NotifyOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    int option;
-    int bool;
-    char *string;
-    enum optionIndices {
-       OPTION_ALWAYS, OPTION_NEVER, OPTION_WHENIDLE, 
-       OPTION_NOW, OPTION_CANCEL, OPTION_PENDING,
-       OPTION_CALLBACK
-    };
-    static char *optionArr[] = {
-       "always", "never", "whenidle", "now", "cancel", "pending", "callback", NULL
-    };
-    if (objc == 2) {
-        if (vPtr->notifyFlags&NOTIFY_WHENIDLE) {
-            Tcl_AppendResult(interp, "whenidle", 0);
-        } else if (vPtr->notifyFlags&NOTIFY_NEVER) {
-            Tcl_AppendResult(interp, "never", 0);
-        } else if (vPtr->notifyFlags&NOTIFY_ALWAYS) {
-            Tcl_AppendResult(interp, "always", 0);
-        }
-        return TCL_OK;
-    }
-    if (Tcl_GetIndexFromObj(interp, objv[2], optionArr, "qualifier", TCL_EXACT,
-           &option) != TCL_OK) {
-       return TCL_OK;
-    }
-    if (option != OPTION_CALLBACK && objc != 3) {
-        Tcl_AppendResult(interp, "only callback takes args", 0);
-        return TCL_ERROR;
-    }
-    switch (option) {
-    case OPTION_ALWAYS:
-       vPtr->notifyFlags &= ~NOTIFY_WHEN_MASK;
-       vPtr->notifyFlags |= NOTIFY_ALWAYS;
-       break;
-    case OPTION_NEVER:
-       vPtr->notifyFlags &= ~NOTIFY_WHEN_MASK;
-       vPtr->notifyFlags |= NOTIFY_NEVER;
-       break;
-    case OPTION_WHENIDLE:
-       vPtr->notifyFlags &= ~NOTIFY_WHEN_MASK;
-       vPtr->notifyFlags |= NOTIFY_WHENIDLE;
-       break;
-    case OPTION_NOW:
-       /* FIXME: How does this play when an update is pending? */
-       Blt_VectorNotifyClients(vPtr);
-       break;
-    case OPTION_CANCEL:
-       if (vPtr->notifyFlags & NOTIFY_PENDING) {
-           vPtr->notifyFlags &= ~NOTIFY_PENDING;
-           Tcl_CancelIdleCall(Blt_VectorNotifyClients, (ClientData)vPtr);
-       }
-       break;
-    case OPTION_PENDING:
-       bool = (vPtr->notifyFlags & NOTIFY_PENDING);
-       Tcl_SetObjResult(interp, Tcl_NewBooleanObj(bool));
-       break;
-    case OPTION_CALLBACK:
-        if (objc == 3) {
-            if (vPtr->callback != NULL) {
-                Tcl_SetObjResult(interp, vPtr->callback);
-            }
-        } else {
-            string = Tcl_GetString(objv[3]);
-            if (string && string[0]) {
-                Tcl_IncrRefCount(objv[3]);
-            }
-            if (vPtr->callback) {
-                Tcl_DecrRefCount(vPtr->callback);
-            }
-            if (string && string[0]) {
-                vPtr->callback = objv[3];
-            } else {
-                vPtr->callback = NULL;
-            }
-        }
-        break;
-    }
-    return TCL_OK;
-}
-
-/*
- * -----------------------------------------------------------------------
- *
- * PopulateOp --
- *
- *     Creates or resizes a new vector based upon the density specified.
- *
- * Results:
- *     A standard Tcl result.  If the density is invalid, TCL_ERROR
- *     is returned.  Otherwise TCL_OK is returned.
- *
- * -----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-PopulateOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    VectorObject *v2Ptr;
-    int size, density;
-    int isNew;
-    register int i, j;
-    double slice, range;
-    register double *valuePtr;
-    int count;
-    char *string;
-
-    string = Tcl_GetString(objv[2]);
-    v2Ptr = Blt_VectorCreate(vPtr->dataPtr, string, string, string, &isNew);
-    if (v2Ptr == NULL) {
-       return TCL_ERROR;
-    }
-    if (vPtr->length == 0) {
-       return TCL_OK;          /* Source vector is empty. */
-    }
-    if (GetIntObj(interp, objv[3], &density) != TCL_OK) {
-       return TCL_ERROR;
-    }
-    if (density < 1) {
-       Tcl_AppendResult(interp, "bad density \"", Tcl_GetString(objv[3]), 
-               "\"", (char *)NULL);
-       return TCL_ERROR;
-    }
-    size = (vPtr->length - 1) * (density + 1) + 1;
-    if (Blt_VectorChangeLength(v2Ptr, size) != TCL_OK) {
-       return TCL_ERROR;
-    }
-    count = 0;
-    valuePtr = v2Ptr->valueArr;
-    for (i = 0; i < (vPtr->length - 1); i++) {
-       range = vPtr->valueArr[i + 1] - vPtr->valueArr[i];
-       slice = range / (double)(density + 1);
-       for (j = 0; j <= density; j++) {
-           *valuePtr = vPtr->valueArr[i] + (slice * (double)j);
-           valuePtr++;
-           count++;
-       }
-    }
-    count++;
-    *valuePtr = vPtr->valueArr[i];
-    assert(count == v2Ptr->length);
-    if (!isNew) {
-       if (v2Ptr->flush) {
-           Blt_VectorFlushCache(v2Ptr);
-       }
-       Blt_VectorUpdateClients(v2Ptr);
-    }
-    return TCL_OK;
-}
-
-/*
- * -----------------------------------------------------------------------
- *
- * RangeOp --
- *
- *     Returns a Tcl list of the range of vector values specified.
- *
- * Results:
- *     A standard Tcl result.  If the given range is invalid, TCL_ERROR
- *     is returned.  Otherwise TCL_OK is returned and interp->result
- *     will contain the list of values.
- *
- * -----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-RangeOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;                  /* Not used. */
-    Tcl_Obj *CONST *objv;
-{
-    Tcl_Obj *listObjPtr;
-    int first, last;
-    register int i;
-
-    if ((Blt_VectorGetIndex(interp, vPtr, Tcl_GetString(objv[2]), &first, 
-               INDEX_CHECK, (Blt_VectorIndexProc **) NULL) != TCL_OK) ||
-       (Blt_VectorGetIndex(interp, vPtr, Tcl_GetString(objv[3]), &last, 
-               INDEX_CHECK, (Blt_VectorIndexProc **) NULL) != TCL_OK)) {
-       return TCL_ERROR;
-    }
-    listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
-    if (first > last) {
-       /* Return the list reversed */
-       for (i = last; i <= first; i++) {
-           Tcl_ListObjAppendElement(interp, listObjPtr, 
-               Tcl_NewDoubleObj(vPtr->valueArr[i]));
-       }
-    } else {
-       for (i = first; i <= last; i++) {
-           Tcl_ListObjAppendElement(interp, listObjPtr, 
-               Tcl_NewDoubleObj(vPtr->valueArr[i]));
-       }
-    }
-    Tcl_SetObjResult(interp, listObjPtr);
-    return TCL_OK;
-}
-
-/*
- * ----------------------------------------------------------------------
- *
- * InRange --
- *
- *     Determines if a value lies within a given range.
- *
- *     The value is normalized and compared against the interval
- *     [0..1], where 0.0 is the minimum and 1.0 is the maximum.
- *     DBL_EPSILON is the smallest number that can be represented
- *     on the host machine, such that (1.0 + epsilon) != 1.0.
- *
- *     Please note, min cannot be greater than max.
- *
- * Results:
- *     If the value is within of the interval [min..max], 1 is 
- *     returned; 0 otherwise.
- *
- * ----------------------------------------------------------------------
- */
-INLINE static int
-InRange(value, min, max)
-    double value, min, max;
-{
-    double range;
-
-    range = max - min;
-    if (range < DBL_EPSILON) {
-       return (FABS(max - value) < DBL_EPSILON);
-    } else {
-       double norm;
-
-       norm = (value - min) / range;
-       return ((norm >= -DBL_EPSILON) && ((norm - 1.0) < DBL_EPSILON));
-    }
-}
-
-enum NativeFormats {
-    FMT_UNKNOWN = -1,
-    FMT_UCHAR, FMT_CHAR,
-    FMT_USHORT, FMT_SHORT,
-    FMT_UINT, FMT_INT,
-    FMT_ULONG, FMT_LONG,
-    FMT_FLOAT, FMT_DOUBLE
-};
-
-/*
- * -----------------------------------------------------------------------
- *
- * GetBinaryFormat
- *
- *      Translates a format string into a native type.  Formats may be
- *     as follows.
- *
- *             signed          i1, i2, i4, i8
- *             unsigned        u1, u2, u4, u8
- *             real            r4, r8, r16
- *
- *     But there must be a corresponding native type.  For example,
- *     this for reading 2-byte binary integers from an instrument and
- *     converting them to unsigned shorts or ints.
- *
- * -----------------------------------------------------------------------
- */
-static enum NativeFormats
-GetBinaryFormat(interp, string, sizePtr)
-    Tcl_Interp *interp;
-    char *string;
-    int *sizePtr;
-{
-    char c;
-
-    c = tolower(string[0]);
-    if (Tcl_GetInt(interp, string + 1, sizePtr) != TCL_OK) {
-       Tcl_AppendResult(interp, "unknown binary format \"", string,
-           "\": incorrect byte size", (char *)NULL);
-       return FMT_UNKNOWN;
-    }
-    switch (c) {
-    case 'r':
-       if (*sizePtr == sizeof(double)) {
-           return FMT_DOUBLE;
-       } else if (*sizePtr == sizeof(float)) {
-           return FMT_FLOAT;
-       }
-       break;
-
-    case 'i':
-       if (*sizePtr == sizeof(char)) {
-           return FMT_CHAR;
-       } else if (*sizePtr == sizeof(int)) {
-           return FMT_INT;
-       } else if (*sizePtr == sizeof(long)) {
-           return FMT_LONG;
-       } else if (*sizePtr == sizeof(short)) {
-           return FMT_SHORT;
-       }
-       break;
-
-    case 'u':
-       if (*sizePtr == sizeof(unsigned char)) {
-           return FMT_UCHAR;
-       } else if (*sizePtr == sizeof(unsigned int)) {
-           return FMT_UINT;
-       } else if (*sizePtr == sizeof(unsigned long)) {
-           return FMT_ULONG;
-       } else if (*sizePtr == sizeof(unsigned short)) {
-           return FMT_USHORT;
-       }
-       break;
-
-    default:
-       Tcl_AppendResult(interp, "unknown binary format \"", string,
-           "\": should be either i#, r#, u# (where # is size in bytes)",
-           (char *)NULL);
-       return FMT_UNKNOWN;
-    }
-    Tcl_AppendResult(interp, "can't handle format \"", string, "\"", 
-                    (char *)NULL);
-    return FMT_UNKNOWN;
-}
-
-static int
-CopyValues(vPtr, byteArr, fmt, size, length, swap, indexPtr)
-    VectorObject *vPtr;
-    char *byteArr;
-    enum NativeFormats fmt;
-    int size;
-    int length;
-    int swap;
-    int *indexPtr;
-{
-    register int i, n;
-    int newSize;
-
-    if ((swap) && (size > 1)) {
-       int nBytes = size * length;
-       register unsigned char *p;
-       register int left, right;
-
-       for (i = 0; i < nBytes; i += size) {
-           p = (unsigned char *)(byteArr + i);
-           for (left = 0, right = size - 1; left < right; left++, right--) {
-               p[left] ^= p[right];
-               p[right] ^= p[left];
-               p[left] ^= p[right];
-           }
-
-       }
-    }
-    newSize = *indexPtr + length;
-    if (newSize > vPtr->length) {
-       if (Blt_VectorChangeLength(vPtr, newSize) != TCL_OK) {
-           return TCL_ERROR;
-       }
-    }
-#define CopyArrayToVector(vPtr, arr) \
-    for (i = 0, n = *indexPtr; i < length; i++, n++) { \
-       (vPtr)->valueArr[n] = (double)(arr)[i]; \
-    }
-
-    switch (fmt) {
-    case FMT_CHAR:
-       CopyArrayToVector(vPtr, (char *)byteArr);
-       break;
-
-    case FMT_UCHAR:
-       CopyArrayToVector(vPtr, (unsigned char *)byteArr);
-       break;
-
-    case FMT_INT:
-       CopyArrayToVector(vPtr, (int *)byteArr);
-       break;
-
-    case FMT_UINT:
-       CopyArrayToVector(vPtr, (unsigned int *)byteArr);
-       break;
-
-    case FMT_LONG:
-       CopyArrayToVector(vPtr, (long *)byteArr);
-       break;
-
-    case FMT_ULONG:
-       CopyArrayToVector(vPtr, (unsigned long *)byteArr);
-       break;
-
-    case FMT_SHORT:
-       CopyArrayToVector(vPtr, (short int *)byteArr);
-       break;
-
-    case FMT_USHORT:
-       CopyArrayToVector(vPtr, (unsigned short int *)byteArr);
-       break;
-
-    case FMT_FLOAT:
-       CopyArrayToVector(vPtr, (float *)byteArr);
-       break;
-
-    case FMT_DOUBLE:
-       CopyArrayToVector(vPtr, (double *)byteArr);
-       break;
-
-    case FMT_UNKNOWN:
-       break;
-    }
-    *indexPtr += length;
-    return TCL_OK;
-}
-
-/*
- * -----------------------------------------------------------------------
- *
- * BinreadOp --
- *
- *     Reads binary values from a Tcl channel. Values are either appended
- *     to the end of the vector or placed at a given index (using the
- *     "-at" option), overwriting existing values.  Data is read until EOF
- *     is found on the channel or a specified number of values are read.
- *     (note that this is not necessarily the same as the number of bytes).
- *
- *     The following flags are supported:
- *             -swap           Swap bytes
- *             -at index       Start writing data at the index.
- *             -format fmt     Specifies the format of the data.
- *
- *     This binary reader was created by Harald Kirsch (kir@iitb.fhg.de).
- *     Anything that's wrong is due to my munging of his code.
- *
- * Results:
- *     Returns a standard Tcl result. The interpreter result will contain
- *     the number of values (not the number of bytes) read.
- *
- * Caveats:
- *     Channel reads must end on an element boundary.
- *
- * -----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-BinreadOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    Tcl_Channel channel;
-    char *byteArr;
-    char *string;
-    enum NativeFormats fmt;
-    int arraySize, bytesRead;
-    int count, total;
-    int first;
-    int size, length, mode;
-    int swap;
-    register int i;
-
-    string = Tcl_GetString(objv[2]);
-    channel = Tcl_GetChannel(interp, string, &mode);
-    if (channel == NULL) {
-       return TCL_ERROR;
-    }
-    if ((mode & TCL_READABLE) == 0) {
-       Tcl_AppendResult(interp, "channel \"", string,
-           "\" wasn't opened for reading", (char *)NULL);
-       return TCL_ERROR;
-    }
-    first = vPtr->length;
-    fmt = FMT_DOUBLE;
-    size = sizeof(double);
-    swap = FALSE;
-    count = 0;
-
-    if (objc > 3) {
-       string = Tcl_GetString(objv[3]);
-       if (string[0] != '-') {
-           long int value;
-           /* Get the number of values to read.  */
-           if (Tcl_GetLongFromObj(interp, objv[3], &value) != TCL_OK) {
-               return TCL_ERROR;
-           }
-           if (value < 0) {
-               Tcl_AppendResult(interp, "count can't be negative", 
-                                (char *)NULL);
-               return TCL_ERROR;
-           }
-           count = (int)value;
-           objc--, objv++;
-       }
-    }
-    /* Process any option-value pairs that remain.  */
-    for (i = 3; i < objc; i++) {
-       string = Tcl_GetString(objv[i]);
-       if (strcmp(string, "-swap") == 0) {
-           swap = TRUE;
-       } else if (strcmp(string, "-format") == 0) {
-           i++;
-           if (i >= objc) {
-               Tcl_AppendResult(interp, "missing arg after \"", string,
-                   "\"", (char *)NULL);
-               return TCL_ERROR;
-           }
-           string = Tcl_GetString(objv[i]);
-           fmt = GetBinaryFormat(interp, string, &size);
-           if (fmt == FMT_UNKNOWN) {
-               return TCL_ERROR;
-           }
-       } else if (strcmp(string, "-at") == 0) {
-           i++;
-           if (i >= objc) {
-               Tcl_AppendResult(interp, "missing arg after \"", string,
-                   "\"", (char *)NULL);
-               return TCL_ERROR;
-           }
-           string = Tcl_GetString(objv[i]);
-           if (Blt_VectorGetIndex(interp, vPtr, string, &first, 0, 
-                        (Blt_VectorIndexProc **)NULL) != TCL_OK) {
-               return TCL_ERROR;
-           }
-           if (first > vPtr->length) {
-               Tcl_AppendResult(interp, "index \"", string,
-                   "\" is out of range", (char *)NULL);
-               return TCL_ERROR;
-           }
-       }
-    }
-
-#define BUFFER_SIZE 1024
-    if (count == 0) {
-       arraySize = BUFFER_SIZE * size;
-    } else {
-       arraySize = count * size;
-    }
-
-    byteArr = Blt_Malloc(arraySize);
-    assert(byteArr);
-
-    /* FIXME: restore old channel translation later? */
-    if (Tcl_SetChannelOption(interp, channel, "-translation",
-           "binary") != TCL_OK) {
-       return TCL_ERROR;
-    }
-    total = 0;
-    while (!Tcl_Eof(channel)) {
-       bytesRead = Tcl_Read(channel, byteArr, arraySize);
-       if (bytesRead < 0) {
-           Tcl_AppendResult(interp, "error reading channel: ",
-               Tcl_PosixError(interp), (char *)NULL);
-           return TCL_ERROR;
-       }
-       if ((bytesRead % size) != 0) {
-           Tcl_AppendResult(interp, "error reading channel: short read",
-               (char *)NULL);
-           return TCL_ERROR;
-       }
-       length = bytesRead / size;
-       if (CopyValues(vPtr, byteArr, fmt, size, length, swap, &first)
-           != TCL_OK) {
-           return TCL_ERROR;
-       }
-       total += length;
-       if (count > 0) {
-           break;
-       }
-    }
-    Blt_Free(byteArr);
-
-    if (vPtr->flush) {
-       Blt_VectorFlushCache(vPtr);
-    }
-    Blt_VectorUpdateClients(vPtr);
-
-    /* Set the result as the number of values read.  */
-    Tcl_SetObjResult(interp, Tcl_NewIntObj(total));
-    return TCL_OK;
-}
-
-static int
-BinwriteOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    Tcl_Channel channel;
-    char *string;
-    int bytesWrite;
-    int count, total;
-    int first;
-    int  mode;
-    register int i;
-
-    string = Tcl_GetString(objv[2]);
-    channel = Tcl_GetChannel(interp, string, &mode);
-    if (channel == NULL) {
-       return TCL_ERROR;
-    }
-    if ((mode & TCL_WRITABLE) == 0) {
-       Tcl_AppendResult(interp, "channel \"", string,
-           "\" wasn't opened for writing", (char *)NULL);
-       return TCL_ERROR;
-    }
-    first = 0;
-    count = vPtr->length;
-
-    if (objc > 3) {
-       string = Tcl_GetString(objv[3]);
-       if (string[0] != '-') {
-           long int value;
-           /* Get the number of values to write.  */
-           if (Tcl_GetLongFromObj(interp, objv[3], &value) != TCL_OK) {
-               return TCL_ERROR;
-           }
-           if (value < 0) {
-               Tcl_AppendResult(interp, "count can't be negative", 
-                                (char *)NULL);
-               return TCL_ERROR;
-           }
-           count = (int)value;
-           objc--, objv++;
-       }
-    }
-    /* Process any option-value pairs that remain.  */
-    for (i = 3; i < objc; i++) {
-       string = Tcl_GetString(objv[i]);
-         if (strcmp(string, "-at") == 0) {
-           i++;
-           if (i >= objc) {
-               Tcl_AppendResult(interp, "missing arg after \"", string,
-                   "\"", (char *)NULL);
-               return TCL_ERROR;
-           }
-           string = Tcl_GetString(objv[i]);
-           if (Blt_VectorGetIndex(interp, vPtr, string, &first, 0, 
-                        (Blt_VectorIndexProc **)NULL) != TCL_OK) {
-               return TCL_ERROR;
-           }
-           if ((first+count) > vPtr->length) {
-               Tcl_AppendResult(interp, "index \"", string,
-                   "\" is out of range", (char *)NULL);
-               return TCL_ERROR;
-           }
-       }
-    }
-
-    /* FIXME: restore old channel translation later? */
-    if (Tcl_SetChannelOption(interp, channel, "-translation",
-           "binary") != TCL_OK) {
-       return TCL_ERROR;
-    }
-    total = sizeof(double)*first;
-    count = sizeof(double)*count;
-    while (!Tcl_Eof(channel)) {
-        bytesWrite = BUFSIZ;
-        if (bytesWrite > (count-total)) {
-            bytesWrite = (count-total);
-        }
-       bytesWrite = Tcl_Write(channel, ((char*)vPtr->valueArr)+total, bytesWrite);
-       if (bytesWrite <= 0) {
-           Tcl_AppendResult(interp, "error writing channel: ",
-               Tcl_PosixError(interp), (char *)NULL);
-           return TCL_ERROR;
-       }
-       total += bytesWrite;
-       if (total >= count) {
-           break;
-       }
-    }
-
-    /* Set the result as the number of values written.  */
-    Tcl_SetObjResult(interp, Tcl_NewIntObj(total/sizeof(double)));
-    return TCL_OK;
-}
-
-/*
- * -----------------------------------------------------------------------
- *
- * SearchOp --
- *
- *     Searchs for a value in the vector. Returns the indices of all
- *     vector elements matching a particular value.
- *
- * Results:
- *     Always returns TCL_OK.  interp->result will contain a list of
- *     the indices of array elements matching value. If no elements
- *     match, interp->result will contain the empty string.
- *
- * -----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-SearchOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    double min, max;
-    register int i;
-    int wantValue;
-    char *string;
-    Tcl_Obj *listObjPtr;
-
-    wantValue = FALSE;
-    string = Tcl_GetString(objv[2]);
-    if ((string[0] == '-') && (strcmp(string, "-value") == 0)) {
-       wantValue = TRUE;
-       objv++, objc--;
-    }
-    if (GetDouble(interp, objv[2], &min) != TCL_OK) {
-       return TCL_ERROR;
-    }
-    max = min;
-    if ((objc > 3) && (GetDouble(interp, objv[3], &max) != TCL_OK)) {
-       return TCL_ERROR;
-    }
-    if ((min - max) >= DBL_EPSILON) {
-       return TCL_OK;          /* Bogus range. Don't bother looking. */
-    }
-    listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
-    if (wantValue) {
-       for (i = 0; i < vPtr->length; i++) {
-           if (InRange(vPtr->valueArr[i], min, max)) {
-               Tcl_ListObjAppendElement(interp, listObjPtr, 
-                       Tcl_NewDoubleObj(vPtr->valueArr[i]));
-           }
-       }
-    } else {
-       for (i = 0; i < vPtr->length; i++) {
-           if (InRange(vPtr->valueArr[i], min, max)) {
-               Tcl_ListObjAppendElement(interp, listObjPtr,
-                        Tcl_NewIntObj(i + vPtr->offset));
-           }
-       }
-    }
-    Tcl_SetObjResult(interp, listObjPtr);
-    return TCL_OK;
-}
-
-/*
- * -----------------------------------------------------------------------
- *
- * OffsetOp --
- *
- *     Queries or sets the offset of the array index from the base
- *     address of the data array of values.
- *
- * Results:
- *     A standard Tcl result.  If the source vector doesn't exist
- *     or the source list is not a valid list of numbers, TCL_ERROR
- *     returned.  Otherwise TCL_OK is returned.
- *     Clients of the vector are notified.
- *     Any cached array indices are flushed.
- *
- * -----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-OffsetOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    if (objc == 3) {
-       int newOffset;
-
-       if (GetIntObj(interp, objv[2], &newOffset) != TCL_OK) {
-           return TCL_ERROR;
-       }
-        if (vPtr->numcols>1 && newOffset && newOffset%vPtr->numcols) {
-            /* newOffset += (vPtr->numcols-(newOffset%vPtr->numcols)); */
-            Tcl_AppendResult(interp, "offset must be a multiple of numcols", 0);
-            return TCL_ERROR;
-        }
-
-       vPtr->offset = newOffset;
-        if (vPtr->flush) {
-            Blt_VectorFlushCache(vPtr);
-        }
-        Blt_VectorUpdateClients(vPtr);
-    }
-    Tcl_SetObjResult(interp, Tcl_NewIntObj(vPtr->offset));
-    return TCL_OK;
-}
-
-/*
- * -----------------------------------------------------------------------
- *
- * RandomOp --
- *
- *     Generates random values for the length of the vector.
- *
- * Results:
- *     A standard Tcl result.
- *
- * -----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-RandomOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;                  /* Not used. */
-    Tcl_Obj *CONST *objv;              /* Not used. */
-{
-#ifdef HAVE_DRAND48
-    register int i;
-
-    for (i = 0; i < vPtr->length; i++) {
-       vPtr->valueArr[i] = drand48();
-    }
-#endif /* HAVE_DRAND48 */
-    if (vPtr->flush) {
-       Blt_VectorFlushCache(vPtr);
-    }
-    Blt_VectorUpdateClients(vPtr);
-    return TCL_OK;
-}
-
-/*
- * -----------------------------------------------------------------------
- *
- * SeqOp --
- *
- *     Generates a sequence of values in the vector.
- *
- * Results:
- *     A standard Tcl result.
- *
- * -----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-SeqOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;                  /* Not used. */
-    Tcl_Obj *CONST *objv;
-{
-    register int i;
-    double start, finish, step;
-    int fillVector;
-    int nSteps;
-    char *string;
-
-    if (GetDouble(interp, objv[2], &start) != TCL_OK) {
-       return TCL_ERROR;
-    }
-    fillVector = FALSE;
-    string = Tcl_GetString(objv[3]);
-    if ((string[0] == 'e') && (strcmp(string, "end") == 0)) {
-       fillVector = TRUE;
-    } else if (GetDouble(interp, objv[3], &finish) != TCL_OK) {
-       return TCL_ERROR;
-    }
-    step = 1.0;
-    if ((objc > 4) && (GetDouble(interp, objv[4], &step) != TCL_OK)) {
-       return TCL_ERROR;
-    }
-    if (fillVector) {
-       nSteps = vPtr->length;
-    } else {
-       nSteps = (int)((finish - start) / step) + 1;
-    }
-    if (nSteps > 0) {
-       if (Blt_VectorChangeLength(vPtr, nSteps) != TCL_OK) {
-           return TCL_ERROR;
-       }
-       for (i = 0; i < nSteps; i++) {
-           vPtr->valueArr[i] = start + (step * (double)i);
-       }
-       if (vPtr->flush) {
-           Blt_VectorFlushCache(vPtr);
-       }
-       Blt_VectorUpdateClients(vPtr);
-    }
-    return TCL_OK;
-}
-
-/*
- * -----------------------------------------------------------------------
- *
- * SetOp --
- *
- *     Sets the data of the vector object from a list of values.
- *
- * Results:
- *     A standard Tcl result.  If the source vector doesn't exist
- *     or the source list is not a valid list of numbers, TCL_ERROR
- *     returned.  Otherwise TCL_OK is returned.
- *
- * Side Effects:
- *     The vector data is reset.  Clients of the vector are notified.
- *     Any cached array indices are flushed.
- *
- * -----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-SetOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;                  /* Not used. */
-    Tcl_Obj *CONST *objv;
-{
-    int result;
-    VectorObject *v2Ptr;
-    int nElem;
-    Tcl_Obj **elemObjArr;
-
-    /* The source can be either a list of numbers or another vector.  */
-
-    v2Ptr = Blt_VectorParseElement((Tcl_Interp *)NULL, vPtr->dataPtr, 
-          Tcl_GetString(objv[2]), (char **)NULL, NS_SEARCH_BOTH);
-    if (v2Ptr != NULL) {
-       if (vPtr == v2Ptr) {
-           VectorObject *tmpPtr;
-           /* 
-            * Source and destination vectors are the same.  Copy the
-            * source first into a temporary vector to avoid memory
-            * overlaps. 
-            */
-           tmpPtr = Blt_VectorNew(vPtr->dataPtr);
-           result = Blt_VectorDuplicate(tmpPtr, v2Ptr);
-           if (result == TCL_OK) {
-               result = Blt_VectorDuplicate(vPtr, tmpPtr);
-           }
-           Blt_VectorFree(tmpPtr);
-       } else {
-           result = Blt_VectorDuplicate(vPtr, v2Ptr);
-       }
-    } else if (Tcl_ListObjGetElements(interp, objv[2], &nElem, &elemObjArr) 
-              == TCL_OK) {
-       result = CopyList(vPtr, nElem, elemObjArr);
-    } else {
-       return TCL_ERROR;
-    }
-
-    if (result == TCL_OK) {
-       /*
-        * The vector has changed; so flush the array indices (they're
-        * wrong now), find the new range of the data, and notify
-        * the vector's clients that it's been modified.
-        */
-       if (vPtr->flush) {
-           Blt_VectorFlushCache(vPtr);
-       }
-       Blt_VectorUpdateClients(vPtr);
-    }
-    return result;
-}
-
-/*
- * -----------------------------------------------------------------------
- *
- * SplitOp --
- *
- *     Copies the values from the vector evens into one of more
- *     vectors.
- *
- * Results:
- *     A standard Tcl result.  
- *
- * -----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-SplitOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    int nVectors;
-
-    nVectors = objc - 2;
-    if (nVectors == 0 || (vPtr->length % nVectors) != 0) {
-       Tcl_AppendResult(interp, "can't split vector \"", vPtr->name, 
-          "\" into ", Blt_Itoa(nVectors), " even parts.", (char *)NULL);
-       return TCL_ERROR;
-    }
-    if (nVectors > 0) {
-       VectorObject *v2Ptr;
-       char *string;           /* Name of vector. */
-       int i, j, k;
-       int oldSize, newSize, extra, isNew;
-
-       extra = vPtr->length / nVectors;
-       for (i = 0; i < nVectors; i++) {
-           string = Tcl_GetString(objv[i+2]);
-           v2Ptr = Blt_VectorCreate(vPtr->dataPtr, string, string, string,
-               &isNew);
-           oldSize = v2Ptr->length;
-           newSize = oldSize + extra;
-           if (Blt_VectorChangeLength(v2Ptr, newSize) != TCL_OK) {
-               return TCL_ERROR;
-           }
-           for (j = i, k = oldSize; j < vPtr->length; j += nVectors, k++) {
-               v2Ptr->valueArr[k] = vPtr->valueArr[j];
-           }
-           Blt_VectorUpdateClients(v2Ptr);
-           if (v2Ptr->flush) {
-               Blt_VectorFlushCache(v2Ptr);
-           }
-       }
-    }
-    return TCL_OK;
-}
-
-
-static VectorObject **sortVectorArr; /* Pointer to the array of values
-                                     * currently being sorted. */
-static int nSortVectors;
-static int reverse;            /* Indicates the ordering of the sort. If
-                                * non-zero, the vectors are sorted in
-                                * decreasing order */
-
-static int
-CompareVectors(a, b)
-    void *a;
-    void *b;
-{
-    double delta;
-    int i;
-    int sign;
-    register VectorObject *vPtr;
-
-    sign = (reverse) ? -1 : 1;
-    for (i = 0; i < nSortVectors; i++) {
-       vPtr = sortVectorArr[i];
-       delta = vPtr->valueArr[*(int *)a] - vPtr->valueArr[*(int *)b];
-       if (delta < 0.0) {
-           return (-1 * sign);
-       } else if (delta > 0.0) {
-           return (1 * sign);
-       }
-    }
-    return 0;
-}
-
-int *
-Blt_VectorSortIndex(vPtrPtr, nVectors)
-    VectorObject **vPtrPtr;
-    int nVectors;
-{
-    int *indexArr;
-    register int i;
-    VectorObject *vPtr = *vPtrPtr;
-    int length;
-
-    length = vPtr->last - vPtr->first + 1;
-    indexArr = Blt_Malloc(sizeof(int) * length);
-    assert(indexArr);
-    for (i = vPtr->first; i <= vPtr->last; i++) {
-       indexArr[i] = i;
-    }
-    sortVectorArr = vPtrPtr;
-    nSortVectors = nVectors;
-    qsort((char *)indexArr, length, sizeof(int), 
-         (QSortCompareProc *)CompareVectors);
-    return indexArr;
-}
-
-static int *
-SortVectors(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    VectorObject **vPtrArray, *v2Ptr;
-    int *iArr;
-    register int i;
-
-    vPtrArray = Blt_Malloc(sizeof(VectorObject *) * (objc + 1));
-    assert(vPtrArray);
-    vPtrArray[0] = vPtr;
-    iArr = NULL;
-    for (i = 0; i < objc; i++) {
-       if (Blt_VectorLookupName(vPtr->dataPtr, Tcl_GetString(objv[i]), &v2Ptr)
-           != TCL_OK) {
-           goto error;
-       }
-       if (v2Ptr->length != vPtr->length) {
-           Tcl_AppendResult(interp, "vector \"", v2Ptr->name,
-               "\" is not the same size as \"", vPtr->name, "\"",
-               (char *)NULL);
-           goto error;
-       }
-       vPtrArray[i + 1] = v2Ptr;
-    }
-    iArr = Blt_VectorSortIndex(vPtrArray, objc + 1);
-  error:
-    Blt_Free(vPtrArray);
-    return iArr;
-}
-
-
-/*
- * -----------------------------------------------------------------------
- *
- * SortOp --
- *
- *     Sorts the vector object and any other vectors according to
- *     sorting order of the vector object.
- *
- * Results:
- *     A standard Tcl result.  If any of the auxiliary vectors are
- *     a different size than the sorted vector object, TCL_ERROR is
- *     returned.  Otherwise TCL_OK is returned.
- *
- * Side Effects:
- *     The vectors are sorted.
- *
- * -----------------------------------------------------------------------
- */
-
-static int
-SortOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    VectorObject *v2Ptr;
-    char *string;
-    double *mergeArr;
-    int *iArr;
-    int refSize, nBytes;
-    int result;
-    register int i, n;
-
-    reverse = FALSE;
-    if (objc > 2) {
-       int length;
-
-       string = Tcl_GetStringFromObj(objv[2], &length);
-       if (string[0] == '-') {
-           if ((length > 1) && (strncmp(string, "-reverse", length) == 0)) {
-               reverse = TRUE;
-           } else {
-               Tcl_AppendResult(interp, "unknown flag \"", string,
-                        "\": should be \"-reverse\"", (char *)NULL);
-               return TCL_ERROR;
-           }
-           objc--, objv++;
-       }
-    }
-    if (objc > 2) {
-       iArr = SortVectors(vPtr, interp, objc - 2, objv + 2);
-    } else {
-       iArr = Blt_VectorSortIndex(&vPtr, 1);
-    }
-    if (iArr == NULL) {
-       return TCL_ERROR;
-    }
-    refSize = vPtr->length;
-
-    /*
-     * Create an array to store a copy of the current values of the
-     * vector. We'll merge the values back into the vector based upon
-     * the indices found in the index array.
-     */
-    nBytes = sizeof(double) * refSize;
-    mergeArr = Blt_Malloc(nBytes);
-    assert(mergeArr);
-    memcpy((char *)mergeArr, (char *)vPtr->valueArr, nBytes);
-    for (n = 0; n < refSize; n++) {
-       vPtr->valueArr[n] = mergeArr[iArr[n]];
-    }
-    if (vPtr->flush) {
-       Blt_VectorFlushCache(vPtr);
-    }
-    Blt_VectorUpdateClients(vPtr);
-
-    /* Now sort any other vectors in the same fashion.  The vectors
-     * must be the same size as the iArr though.  */
-    result = TCL_ERROR;
-    for (i = 2; i < objc; i++) {
-       if (Blt_VectorLookupName(vPtr->dataPtr, Tcl_GetString(objv[i]), &v2Ptr)
-           != TCL_OK) {
-           goto error;
-       }
-       if (v2Ptr->length != refSize) {
-           Tcl_AppendResult(interp, "vector \"", v2Ptr->name,
-               "\" is not the same size as \"", vPtr->name, "\"",
-               (char *)NULL);
-           goto error;
-       }
-       memcpy((char *)mergeArr, (char *)v2Ptr->valueArr, nBytes);
-       for (n = 0; n < refSize; n++) {
-           v2Ptr->valueArr[n] = mergeArr[iArr[n]];
-       }
-       Blt_VectorUpdateClients(v2Ptr);
-       if (v2Ptr->flush) {
-           Blt_VectorFlushCache(v2Ptr);
-       }
-    }
-    result = TCL_OK;
-  error:
-    Blt_Free(mergeArr);
-    Blt_Free(iArr);
-    return result;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * InstExprOp --
- *
- *     Computes the result of the expression which may be
- *     either a scalar (single value) or vector (list of values).
- *
- * Results:
- *     A standard Tcl result.
- *
- *----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-InstExprOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-
-    if (Blt_ExprVector(interp, Tcl_GetString(objv[2]), (Blt_Vector *) vPtr) 
-       != TCL_OK) {
-       return TCL_ERROR;
-    }
-    if (vPtr->flush) {
-       Blt_VectorFlushCache(vPtr);
-    }
-    Blt_VectorUpdateClients(vPtr);
-    return TCL_OK;
-}
-
-/*
- * -----------------------------------------------------------------------
- *
- * ArithOp --
- *
- * Results:
- *     A standard Tcl result.  If the source vector doesn't exist
- *     or the source list is not a valid list of numbers, TCL_ERROR
- *     returned.  Otherwise TCL_OK is returned.
- *
- * Side Effects:
- *     The vector data is reset.  Clients of the vector are notified.
- *     Any cached array indices are flushed.
- *
- * -----------------------------------------------------------------------
- */
-/*ARGSUSED*/
-static int
-ArithOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;                  /* Not used. */
-    Tcl_Obj *CONST *objv;
-{
-    register double value;
-    register int i;
-    VectorObject *v2Ptr;
-    double scalar;
-    Tcl_Obj *listObjPtr;
-    char *string;
-
-    v2Ptr = Blt_VectorParseElement((Tcl_Interp *)NULL, vPtr->dataPtr, 
-               Tcl_GetString(objv[2]), (char **)NULL, NS_SEARCH_BOTH);
-    if (v2Ptr != NULL) {
-       register int j;
-       int length;
-
-       length = v2Ptr->last - v2Ptr->first + 1;
-       if (length != vPtr->length) {
-           Tcl_AppendResult(interp, "vectors \"", Tcl_GetString(objv[0]), 
-               "\" and \"", Tcl_GetString(objv[2]), 
-               "\" are not the same length", (char *)NULL);
-           return TCL_ERROR;
-       }
-       string = Tcl_GetString(objv[1]);
-       listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
-       switch (string[0]) {
-       case '*':
-           for (i = 0, j = v2Ptr->first; i < vPtr->length; i++, j++) {
-               value = vPtr->valueArr[i] * v2Ptr->valueArr[j];
-               Tcl_ListObjAppendElement(interp, listObjPtr,
-                        Tcl_NewDoubleObj(value));
-           }
-           break;
-
-       case '/':
-           for (i = 0, j = v2Ptr->first; i < vPtr->length; i++, j++) {
-               value = vPtr->valueArr[i] / v2Ptr->valueArr[j];
-               Tcl_ListObjAppendElement(interp, listObjPtr,
-                        Tcl_NewDoubleObj(value));
-           }
-           break;
-
-       case '-':
-           for (i = 0, j = v2Ptr->first; i < vPtr->length; i++, j++) {
-               value = vPtr->valueArr[i] - v2Ptr->valueArr[j];
-               Tcl_ListObjAppendElement(interp, listObjPtr,
-                        Tcl_NewDoubleObj(value));
-           }
-           break;
-
-       case '+':
-           for (i = 0, j = v2Ptr->first; i < vPtr->length; i++, j++) {
-               value = vPtr->valueArr[i] + v2Ptr->valueArr[j];
-               Tcl_ListObjAppendElement(interp, listObjPtr,
-                        Tcl_NewDoubleObj(value));
-           }
-           break;
-       }
-       Tcl_SetObjResult(interp, listObjPtr);
-
-    } else if (GetDouble(interp, objv[2], &scalar) == TCL_OK) {
-       listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
-       string = Tcl_GetString(objv[1]);
-       switch (string[0]) {
-       case '*':
-           for (i = 0; i < vPtr->length; i++) {
-               value = vPtr->valueArr[i] * scalar;
-               Tcl_ListObjAppendElement(interp, listObjPtr,
-                        Tcl_NewDoubleObj(value));
-           }
-           break;
-
-       case '/':
-           for (i = 0; i < vPtr->length; i++) {
-               value = vPtr->valueArr[i] / scalar;
-               Tcl_ListObjAppendElement(interp, listObjPtr,
-                        Tcl_NewDoubleObj(value));
-           }
-           break;
-
-       case '-':
-           for (i = 0; i < vPtr->length; i++) {
-               value = vPtr->valueArr[i] - scalar;
-               Tcl_ListObjAppendElement(interp, listObjPtr,
-                        Tcl_NewDoubleObj(value));
-           }
-           break;
-
-       case '+':
-           for (i = 0; i < vPtr->length; i++) {
-               value = vPtr->valueArr[i] + scalar;
-               Tcl_ListObjAppendElement(interp, listObjPtr,
-                        Tcl_NewDoubleObj(value));
-           }
-           break;
-       }
-       Tcl_SetObjResult(interp, listObjPtr);
-    } else {
-       return TCL_ERROR;
-    }
-    return TCL_OK;
-}
-
-/* 
-
- * Set the numcols used in matrix math.
- *
- *   $vec matrix numcols ?n?
- */
-
-static int
-MatrixNumcolsObjOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    int i;
-
-    if (objc == 3) {
-        Tcl_SetObjResult(interp, Tcl_NewIntObj(vPtr->numcols));
-        return TCL_OK;
-    }
-    if (GetIntObj(vPtr->interp, objv[3], &i) != TCL_OK) {
-        return TCL_ERROR;
-    }
-    if (i<=0) {
-        Tcl_AppendResult(interp, "value must >= 1", 0);
-        return TCL_ERROR;
-    }
-    vPtr->numcols = i;
-    if (vPtr->length%i) {
-        Blt_VectorChangeLength(vPtr, vPtr->length);
-    }
-    if (vPtr->offset && vPtr->offset%i) {
-        vPtr->offset += (i-(i%vPtr->offset));
-    }
-    vPtr->notifyFlags |= UPDATE_RANGE;
-    if (vPtr->flush) {
-        Blt_VectorFlushCache(vPtr);
-    }
-    Blt_VectorUpdateClients(vPtr);
-    return TCL_OK;
-}
-
-/* 
- * Set the numcols used in matrix math.
- *
- *   $vec matrix numrows ?n?
- */
-
-static int
-MatrixNumrowsObjOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    int i, newSize;
-
-    if (vPtr->numcols<=0) {
-        Tcl_AppendResult(interp, "must set matrix numcols", 0);
-        return TCL_ERROR;
-    }
-    if (objc <= 3) {
-        Tcl_SetObjResult(interp, Tcl_NewIntObj(vPtr->length/vPtr->numcols));
-        return TCL_OK;
-    }
-    if (GetIntObj(vPtr->interp, objv[3], &i) != TCL_OK) {
-        return TCL_ERROR;
-    }
-    if (i == (vPtr->length/vPtr->numcols)) {
-        return TCL_OK;
-    }
-    newSize = (vPtr->numcols*i);
-    if (Blt_VectorChangeLength(vPtr, newSize) != TCL_OK) {
-        return TCL_ERROR;
-    }
-    vPtr->notifyFlags |= UPDATE_RANGE;
-    if (vPtr->flush) {
-        Blt_VectorFlushCache(vPtr);
-    }
-    Blt_VectorUpdateClients(vPtr);
-    return TCL_OK;
-}
-
-static int
-MatrixTransposeObjOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    int cols, rows, r, c, src, dst, bytes;
-    double *v, *n;
-
-    cols = vPtr->numcols;
-    if ((vPtr->length)%cols) {
-        Tcl_AppendResult(interp, "numcols must be set to MOD the array size", 0);
-        return TCL_ERROR;
-    }
-    rows = (vPtr->length/cols);
-    v = vPtr->valueArr;
-    bytes = sizeof(double)*vPtr->length;
-    n = Blt_Calloc(1, bytes);
-    
-    for (r=0; r<rows; r++) {
-        for (c=0; c<cols; c++) {
-            src = (r*cols)+c;
-            dst = (c*rows)+r;
-            n[dst] = v[src];
-        }
-    }
-    memcpy(vPtr->valueArr, n, bytes);
-    Blt_Free(n);
-    vPtr->numcols = rows;
-    vPtr->notifyFlags |= UPDATE_RANGE;
-    if (vPtr->flush) {
-        Blt_VectorFlushCache(vPtr);
-    }
-    Blt_VectorUpdateClients(vPtr);
-    return TCL_OK;
-}
-
-/*
-* -----------------------------------------------------------------------
-*
-* SortOp --
-*
-*      Sorts the vector by column. eg.
-*
-*          vecName matrix sort 1 -reverse
-*
-* Results:
-*      A standard Tcl result.
-*
-* Side Effects:
-*      The vector is sorted.
-*
-* -----------------------------------------------------------------------
-*/
-
-static int
-MatrixSortObjOp(vPtr, interp, objc, objv)
-VectorObject *vPtr;
-Tcl_Interp *interp;
-int objc;
-Tcl_Obj *CONST *objv;
-{
-    char *string;
-    double *mergeArr;
-    int *iArr;
-    int refSize, nBytes;
-    register int i, n;
-    int column, ncols, nrows;
-    double *v;
-
-    if (!strcmp("end", Tcl_GetString(objv[3]))) {
-        column = vPtr->numcols-1;
-    } else if (GetIntObj(interp, objv[3], &column) != TCL_OK) {    
-        return TCL_ERROR;
-    }
-    ncols = vPtr->numcols;
-    if (column<0 || column>=ncols) {
-        Tcl_AppendResult(interp, "bad column", 0);
-        return TCL_ERROR;
-    }
-    reverse = FALSE;
-    if (objc > 4) {
-        int length;
-
-        string = Tcl_GetStringFromObj(objv[4], &length);
-        if ((length > 1) && (strncmp(string, "-reverse", length) == 0)) {
-            reverse = TRUE;
-        } else {
-            Tcl_AppendResult(interp, "unknown flag \"", string,
-            "\": should be \"-reverse\"", (char *)NULL);
-            return TCL_ERROR;
-        }
-    }
-    nrows = vPtr->length/ncols;
-    iArr = Blt_Malloc(sizeof(int) * nrows);
-    assert(iArr);
-    for (n = 0, i = column; i < vPtr->length; n++, i+=ncols) {
-        iArr[n] = i;
-    }
-    sortVectorArr = &vPtr;
-    nSortVectors = 1;
-    qsort((char *)iArr, nrows, sizeof(int), 
-        (QSortCompareProc *)CompareVectors);
-
-    refSize = vPtr->length;
-    nBytes = sizeof(double) * refSize;
-    mergeArr = Blt_Malloc(nBytes);
-    assert(mergeArr);
-    memcpy((char *)mergeArr, (char *)vPtr->valueArr, nBytes);
-    v = vPtr->valueArr;
-    for (n = 0; n < nrows; n++) {
-        int cind;
-        cind = iArr[n] - column;
-        for (i=0; i<ncols; i++) {
-            v[n*ncols+i] = mergeArr[cind+i];
-        }
-    }
-    Blt_Free(mergeArr);
-    Blt_Free(iArr);
-    if (vPtr->flush) {
-        Blt_VectorFlushCache(vPtr);
-    }
-    Blt_VectorUpdateClients(vPtr);
-
-    return TCL_OK;
-}
-
-/* 
- * Delete a column from a matrix vector..
- *
- *   vector matrix insert $vec ?offset?
- */
-
-static int
-MatrixDeleteObjOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    int i, j, offset = 0, newSize, numrows, rsz;
-    double *v;
-
-    if (objc > 3) {
-        if (!strcmp("end", Tcl_GetString(objv[3]))) {
-            offset = vPtr->numcols-1;
-        } else if (GetIntObj(interp, objv[3], &offset) != TCL_OK) {    
-            return TCL_ERROR;
-        }
-    }
-    if (offset<0 || offset>=(vPtr->numcols) || vPtr->numcols<=1) {
-        Tcl_AppendResult(interp, "value must be < numcols", 0);
-        return TCL_ERROR;
-    }
-    numrows = vPtr->length/vPtr->numcols;
-    newSize = numrows*(vPtr->numcols-1);
-    rsz = vPtr->numcols;
-
-    v = vPtr->valueArr;
-    for (i=0; i<numrows; i++) {
-        int in, io;
-        in = i*(rsz-1);
-        io = i*(rsz);
-        if (offset == (rsz-1)) {
-            for (j=0; j<(rsz-1); j++) {
-                v[in+j] = v[io+j];
-            }
-        } else if (offset == 0) {
-            for (j=0; j<(rsz-1); j++) {
-                v[in+j] = v[io+j+1];
-            }
-        } else {
-            for (j=0; j<offset; j++) {
-                v[in+j] = v[io+j];
-            }
-            for (j=offset+1; j<(rsz-1); j++) {
-                v[in+j-1] = v[io+j];
-            }
-        }
-    }
-    if (Blt_VectorChangeLength(vPtr, newSize) != TCL_OK) {
-        return TCL_ERROR;
-    }
-    vPtr->numcols = rsz-1;
-    vPtr->notifyFlags |= UPDATE_RANGE;
-    if (vPtr->flush) {
-        Blt_VectorFlushCache(vPtr);
-    }
-    Blt_VectorUpdateClients(vPtr);
-    
-    return TCL_OK;
-}
-
-/* 
- * Insert a column into a matrix vector..
- *
- *   vector matrix insert $vec ?offset? ?initValue?
- *
- * TODO: support insert from another matrix.
- */
-
-static int
-MatrixInsertObjOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    int i, j, offset = 0, newSize, numrows, rsz;
-    double initValue = 0.0, *v;
-
-    if (objc > 3) {
-        if (!strcmp("end", Tcl_GetString(objv[3]))) {
-            offset = vPtr->numcols;
-        } else if (GetIntObj(interp, objv[3], &offset) != TCL_OK) {    
-            return TCL_ERROR;
-        }
-    }
-    if (objc > 4 && GetDouble(interp, objv[4], &initValue) != TCL_OK) {
-        return TCL_ERROR;
-    }
-    if (offset<0 || offset>vPtr->numcols || vPtr->numcols<=0) {
-        Tcl_AppendResult(interp, "value must be <= numcols", 0);
-        return TCL_ERROR;
-    }
-    numrows = vPtr->length/vPtr->numcols;
-    newSize = numrows*(vPtr->numcols+1);
-    rsz = vPtr->numcols;
-    if (Blt_VectorChangeLength(vPtr, newSize) != TCL_OK) {
-        return TCL_ERROR;
-    }
-    v = vPtr->valueArr;
-
-    for (i=numrows-1; i>=0; i--) {
-        int in, io;
-        in = i*(rsz+1);
-        io = i*(rsz);
-        if (offset == rsz) {
-            for (j=rsz-1; j>=0; j--) {
-                v[in+j] = v[io+j];
-            }
-            v[in+rsz] = initValue;
-        } else if (offset == 0) {
-            for (j=rsz-1; j>=0; j--) {
-                v[in+j+1] = v[io+j];
-            }
-            v[in] = initValue;
-        } else {
-            for (j=rsz-1; j>=offset; j--) {
-                v[in+j+1] = v[io+j];
-            }
-            for (; j>=0; j--) {
-                v[in+j] = v[io+j];
-            }
-            v[in+offset] = initValue;
-        }
-    }
-    vPtr->numcols = rsz+1;
-    vPtr->notifyFlags |= UPDATE_RANGE;
-    if (vPtr->flush) {
-        Blt_VectorFlushCache(vPtr);
-    }
-    Blt_VectorUpdateClients(vPtr);
-    
-    return TCL_OK;
-}
-
-/* 
- * Set a column to a value.
- *
- *   vecName matrix set $vec ?column? ?valuelist?
- *
- */
-
-static int
-MatrixSetObjOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    int i, offset = 0, numrows, rsz;
-    double initValue = 0.0, *v;
-    int nElem = 0, eInd = 0;
-    Tcl_Obj **elemObjArr;
-
-
-    if (objc > 3) {
-        if (!strcmp("end", Tcl_GetString(objv[3]))) {
-            offset = vPtr->numcols-1;
-        } else if (GetIntObj(interp, objv[3], &offset) != TCL_OK) {    
-            return TCL_ERROR;
-        }
-    }
-    if (objc > 4) {
-        if (GetDouble(interp, objv[4], &initValue) != TCL_OK) {
-            if (Tcl_ListObjGetElements(interp, objv[4], &nElem, &elemObjArr) 
-                != TCL_OK) {
-                return TCL_ERROR;
-            }
-            if (nElem<1 || GetDouble(interp, elemObjArr[0],
-                &initValue) != TCL_OK) {
-                Tcl_AppendResult( interp, "list must have >=1 value", 0);
-                return TCL_ERROR;
-            }
-            eInd = 1;
-        }
-    }
-    if (offset<0 || offset>=vPtr->numcols || vPtr->numcols<=0) {
-        Tcl_AppendResult(interp, "column offset must be <= numcols", 0);
-        return TCL_ERROR;
-    }
-    numrows = vPtr->length/vPtr->numcols;
-    rsz = vPtr->numcols;
-    v = vPtr->valueArr;
-
-    for (i=0; i<numrows; i++) {
-        if (eInd && i>0 && i<nElem) {
-            if (GetDouble(interp, elemObjArr[i], &initValue)
-                != TCL_OK) {
-                return TCL_ERROR;
-            }
-        }
-        v[i*rsz+offset] = initValue;
-    }
-    Tcl_ResetResult(interp);
-    vPtr->notifyFlags |= UPDATE_RANGE;
-    if (vPtr->flush) {
-        Blt_VectorFlushCache(vPtr);
-    }
-    Blt_VectorUpdateClients(vPtr);
-    return TCL_OK;
-}
-
-/* 
- * Get column values.
- *
- *   vecName matrix get $vec ?coloffset? 
- *
- */
-
-static int
-MatrixGetObjOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    int i, offset = 0, numrows, rsz;
-    double  *v, *v3;
-    Tcl_Obj *lPtr;
-
-    if (objc > 3) {
-        if (!strcmp("end", Tcl_GetString(objv[3]))) {
-            offset = vPtr->numcols-1;
-        } else if (GetIntObj(interp, objv[3], &offset) != TCL_OK) {    
-            return TCL_ERROR;
-        }
-    }
-    if (offset<0 || offset>=vPtr->numcols || vPtr->numcols<=0) {
-        Tcl_AppendResult(interp, "column offset must be <= numcols", 0);
-        return TCL_ERROR;
-    }
-    numrows = vPtr->length/vPtr->numcols;
-    rsz = vPtr->numcols;
-    v = vPtr->valueArr;
-
-    if (objc>4) {
-        int isNew, newSize;
-        VectorObject *v3Ptr;
-        char *string = Tcl_GetString(objv[4]);
-        
-        v3Ptr = Blt_VectorCreate(vPtr->dataPtr, string, string, string,&isNew);
-        if (v3Ptr == NULL) {
-            return TCL_ERROR;
-        }
-        newSize = numrows;
-        if (Blt_VectorChangeLength(v3Ptr, newSize) != TCL_OK) {
-            return TCL_ERROR;
-        }
-        v3Ptr->numcols = 1;
-        v3 = v3Ptr->valueArr;
-        for (i=0; i<numrows; i++) {
-            v3[i] = v[i*rsz+offset];
-        }
-        if (!isNew) {
-            v3Ptr->notifyFlags |= UPDATE_RANGE;
-            if (v3Ptr->flush) {
-                Blt_VectorFlushCache(v3Ptr);
-            }
-            Blt_VectorUpdateClients(v3Ptr);
-        }
-    } else {
-        lPtr = Tcl_NewListObj(0,0);
-        for (i=0; i<numrows; i++) {
-            Tcl_ListObjAppendElement(interp, lPtr, Tcl_NewDoubleObj(v[i*rsz+offset]));
-        }
-        Tcl_SetObjResult(interp, lPtr);
-    }
-    return TCL_OK;
-}
-
-/* 
-* Copy columns
- *
- *   vecName matrix copy $vec srcVec ?dstcoloffset? ?srccoloffset?
- *
- */
-
-static int
-MatrixCopyObjOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    int i, offset = 0, srcoffset = 0, numrows, numrows2, rsz, rsz2;
-    double *v, *v2;
-    VectorObject *v2Ptr = vPtr;
-
-
-    if (objc > 3) {
-        if (!strcmp("end", Tcl_GetString(objv[3]))) {
-            offset = vPtr->numcols-1;
-        } else if (GetIntObj(interp, objv[3], &offset) != TCL_OK) {    
-            return TCL_ERROR;
-        }
-    }
-    if (objc > 4) {
-        if (!strcmp("end", Tcl_GetString(objv[4]))) {
-            srcoffset = v2Ptr->numcols-1;
-        } else if (GetIntObj(interp, objv[4], &srcoffset) != TCL_OK) {    
-            return TCL_ERROR;
-        }
-    }
-    if (objc>5 && Blt_VectorLookupName(vPtr->dataPtr, Tcl_GetString(objv[5]),
-        &v2Ptr) != TCL_OK) {
-        return TCL_ERROR;
-    }
-
-    if (vPtr == v2Ptr && srcoffset == offset) {
-        Tcl_AppendResult(interp, "column offsets must be different", 0);
-        return TCL_ERROR;
-    }
-    if (offset<0 || offset>=vPtr->numcols || vPtr->numcols<=0) {
-        Tcl_AppendResult(interp, "column offset must be <= numcols", 0);
-        return TCL_ERROR;
-    }
-    if (srcoffset<0 || srcoffset>=v2Ptr->numcols || v2Ptr->numcols<=0) {
-        Tcl_AppendResult(interp, "src column offset must be <= numcols", 0);
-        return TCL_ERROR;
-    }
-    numrows = vPtr->length/vPtr->numcols;
-    numrows2 = v2Ptr->length/v2Ptr->numcols;
-    rsz = vPtr->numcols;
-    rsz2 = v2Ptr->numcols;
-    
-    if (numrows2>numrows) {
-        int newSize = numrows2*(vPtr->numcols+1);
-        if (Blt_VectorChangeLength(vPtr, newSize) != TCL_OK) {
-            return TCL_ERROR;
-        }
-    }
-    v = vPtr->valueArr;
-    v2 = v2Ptr->valueArr;
-
-    for (i=0; i<numrows2; i++) {
-        v[i*rsz+offset] = v2[i*rsz2+srcoffset];
-    }
-    vPtr->notifyFlags |= UPDATE_RANGE;
-    if (vPtr->flush) {
-        Blt_VectorFlushCache(vPtr);
-    }
-    Blt_VectorUpdateClients(vPtr);
-    
-    return TCL_OK;
-}
-
-/* 
- * Shift values down or up within a column.
- *
- *   $vec matrix shift  column ?amount? ?start?
- *
- *   $vec matrix shift 1 5
- *
- */
-
-static int
-MatrixShiftObjOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    int i, offset = 0, amount = 1, numrows, rsz, start=vPtr->first;
-    double *v;
-    
-    if (!strcmp("end", Tcl_GetString(objv[3]))) {
-        offset = vPtr->numcols-1;
-    } else if (GetIntObj(interp, objv[3], &offset) != TCL_OK) {    
-        return TCL_ERROR;
-    }
-    if (objc > 4) {
-        if (GetIntObj(interp, objv[4], &amount) != TCL_OK) {    
-            return TCL_ERROR;
-        }
-    }
-    if (objc > 5) {
-        if (GetIntObj(interp, objv[5], &start) != TCL_OK) {    
-            return TCL_ERROR;
-        }
-    }
-    if (offset<0 || offset>=vPtr->numcols || vPtr->numcols<=0) {
-        Tcl_AppendResult(interp, "column offset must be < numcols", 0);
-        return TCL_ERROR;
-    }
-    start -= vPtr->first;
-    rsz = vPtr->numcols;
-    numrows = vPtr->length/rsz;
-    if (amount==0) return TCL_OK;
-    v = vPtr->valueArr;
-    if (amount>numrows || amount<-numrows)  {
-        for (i=start; i<numrows; i++) {
-            v[i*rsz+offset] = 0;
-        }
-    } else {    
-        if (amount < 0) {
-            for (i=start; i<numrows; i++) {
-                if ((i-amount)>= numrows) {
-                    v[i*rsz+offset] = 0;
-                } else {
-                    v[i*rsz+offset] = v[(i-amount)*rsz+offset];
-                }
-            }
-        } else {
-            for (i=numrows-1; i>=start; i--) {
-                if ((i-amount) < 0) {
-                    v[i*rsz+offset] = 0;
-                } else {
-                    v[i*rsz+offset] = v[(i-amount)*rsz+offset];
-                }
-            }
-        }
-    }
-    vPtr->notifyFlags |= UPDATE_RANGE;
-    if (vPtr->flush) {
-        Blt_VectorFlushCache(vPtr);
-    }
-    Blt_VectorUpdateClients(vPtr);
-    
-    return TCL_OK;
-}
-
-/* 
-* Perform matrix multiplication.
-*
-*   $vec matrix multiply vecName
-*
-*/
-
-static int
-MatrixMultiplyObjOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    VectorObject *v2Ptr;
-    int nc1, nc2, nr1, nr2, i, mr, mc, len, result = TCL_OK;
-    double *v1, *v2, *v, vStatic[256];
-    char *str;
-    Tcl_Obj *lPtr;
-    
-    if (Blt_VectorLookupName(vPtr->dataPtr, str=Tcl_GetString(objv[3]),
-        &v2Ptr) != TCL_OK) {
-            return TCL_ERROR;
-    }
-    
-    nc1=vPtr->numcols;
-    nc2=v2Ptr->numcols;
-    nr1 = (vPtr->length/nc1);
-    nr2 = (v2Ptr->length/nc2);
-    if (v2Ptr->length<=0 || vPtr->length<=0) {
-        Tcl_AppendResult(interp, "vectors must not be empty", 0);
-        return TCL_ERROR;
-    }
-    if (nc1 != nr2) {
-        Tcl_AppendResult(interp, "numcols != numrows of ", str, 0);
-        return TCL_ERROR;
-    }
-    v1 = vPtr->valueArr;
-    v2 = v2Ptr->valueArr;
-    len = nr1*nc2;
-    if (len<=256) {
-        v = vStatic;
-        memset(v, 0,sizeof(vStatic));
-    } else {
-        v = (double*)Blt_Calloc(sizeof(double), len);
-    }
-    for (mc=0; mc<nc2; mc++) {
-        for (mr=0; mr<nr1; mr++) {
-            for (i=0; i<nc1; i++) {
-                v[mr*nc2+mc] += v1[mr*nc1+i]*v2[i*nc2+mc];
-            }
-        }
-    }
-    if (objc>4) {
-        int isNew, newSize;
-        VectorObject *v3Ptr;
-        char *string = Tcl_GetString(objv[4]);
-        
-        v3Ptr = Blt_VectorCreate(vPtr->dataPtr, string, string, string,&isNew);
-        if (v3Ptr == NULL) {
-            result = TCL_ERROR;
-            goto cleanup;
-        }
-        newSize = len;
-        if (Blt_VectorChangeLength(v3Ptr, newSize) != TCL_OK) {
-            result = TCL_ERROR;
-            goto cleanup;
-        }
-        memcpy(v3Ptr->valueArr, v, sizeof(double)*newSize);
-        v3Ptr->numcols = nc2;
-        if (!isNew) {
-            v3Ptr->notifyFlags |= UPDATE_RANGE;
-            if (v3Ptr->flush) {
-                Blt_VectorFlushCache(v3Ptr);
-            }
-            Blt_VectorUpdateClients(v3Ptr);
-        }
-    } else {
-
-        lPtr = Tcl_NewListObj(0,0);
-        for (i=0; i<len; i++) {
-            Tcl_ListObjAppendElement(interp, lPtr, Tcl_NewDoubleObj(v[i]));
-        }
-        Tcl_SetObjResult(interp, lPtr);
-    }
-cleanup:
-    if (v != vStatic) {
-        Blt_Free((char*)v);
-    }
-    
-    return result;
-}
-
-static Blt_OpSpec matrixCmdOps[] =
-{
-    {"copy",     1, (Blt_Op)MatrixCopyObjOp, 5, 6, "dstcolumn srccolumn ?srcVec?",},
-    {"delete",   1, (Blt_Op)MatrixDeleteObjOp, 4, 4, "column",},
-    {"get",      1, (Blt_Op)MatrixGetObjOp, 4, 5, "column ?dstVec?",},
-    {"insert",   1, (Blt_Op)MatrixInsertObjOp, 4, 5, "column ?inititem?",},
-    {"multiply", 1, (Blt_Op)MatrixMultiplyObjOp, 4, 5, "vecName ?dstVec?",},
-    {"numcols",  2, (Blt_Op)MatrixNumcolsObjOp, 3, 4, "?newsize?",},
-    {"numrows",  2, (Blt_Op)MatrixNumrowsObjOp, 3, 4, "?newsize?",},
-    {"shift",    2, (Blt_Op)MatrixShiftObjOp, 5, 6, "column offset ?start?",},
-    {"set",      2, (Blt_Op)MatrixSetObjOp, 4, 5, "column ?valuelist?",},
-    {"sort",     2, (Blt_Op)MatrixSortObjOp, 4, 5, "column ?-reverse?",},
-    {"transpose", 1, (Blt_Op)MatrixTransposeObjOp, 3, 3, "",},
-};
-
-static int nMatrixOps = sizeof(matrixCmdOps) / sizeof(Blt_OpSpec);
-
-static int
-MatrixOp(vPtr, interp, objc, objv)
-    VectorObject *vPtr;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    int result = TCL_OK;
-    Blt_Op proc;
-    
-    proc = Blt_GetOpFromObj(interp, nMatrixOps, matrixCmdOps, BLT_OP_ARG2, objc, objv, 0);
-    if (proc == NULL) {
-        return TCL_ERROR;
-    }
-    return (*proc) (vPtr, interp, objc, objv);
-    
-    return result;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * VectorInstCmd --
- *
- *     Parses and invokes the appropriate vector instance command
- *     option.
- *
- * Results:
- *     A standard Tcl result.
- *
- *----------------------------------------------------------------------
- */
-static Blt_OpSpec vectorInstOps[] =
-{
-    {"*", 1, (Blt_Op)ArithOp, 3, 3, "item",},  /*Deprecated*/
-    {"+", 1, (Blt_Op)ArithOp, 3, 3, "item",},  /*Deprecated*/
-    {"-", 1, (Blt_Op)ArithOp, 3, 3, "item",},  /*Deprecated*/
-    {"/", 1, (Blt_Op)ArithOp, 3, 3, "item",},  /*Deprecated*/
-    {"append", 1, (Blt_Op)AppendOp, 3, 0, "item ?item...?",},
-    {"binread", 4, (Blt_Op)BinreadOp, 3, 0, "channel ?numValues? ?flags?",},
-    {"binwrite", 4, (Blt_Op)BinwriteOp, 3, 0, "channel ?numValues? ?flags?",},
-    {"clear", 1, (Blt_Op)ClearOp, 2, 3, "?autoflush?",},
-    {"delete", 2, (Blt_Op)DeleteOp, 2, 0, "index ?index...?",},
-    {"dup", 2, (Blt_Op)DupOp, 3, 0, "vecName",},
-    {"expr", 1, (Blt_Op)InstExprOp, 3, 3, "expression",},
-    {"index", 3, (Blt_Op)IndexOp, 3, 4, "index ?value?",},
-    {"insert", 3, (Blt_Op)InsertOp, 3, 0, "index value ?value...?",},
-    {"length", 1, (Blt_Op)LengthOp, 2, 3, "?newSize?",},
-    {"matrix", 2, (Blt_Op)MatrixOp, 3, 0, "op ...",},
-    {"merge", 2, (Blt_Op)MergeOp, 3, 0, "vecName ?vecName...?",},
-    {"normalize", 3, (Blt_Op)NormalizeOp, 2, 3, "?vecName?",}, /*Deprecated*/
-    {"notify", 3, (Blt_Op)NotifyOp, 2, 4, "?keyword? ?callback?",},
-    {"offset", 2, (Blt_Op)OffsetOp, 2, 3, "?offset?",},
-    {"populate", 1, (Blt_Op)PopulateOp, 4, 4, "vecName density",},
-    {"random", 4, (Blt_Op)RandomOp, 2, 2, "",},        /*Deprecated*/
-    {"range", 4, (Blt_Op)RangeOp, 4, 4, "first last",},
-    {"search", 3, (Blt_Op)SearchOp, 3, 4, "?-value? value ?value?",},
-    {"seq", 3, (Blt_Op)SeqOp, 4, 5, "start end ?step?",},
-    {"set", 3, (Blt_Op)SetOp, 3, 3, "list",},
-    {"sort", 2, (Blt_Op)SortOp, 2, 0, "?-reverse? ?vecName...?",},
-    {"split", 2, (Blt_Op)SplitOp, 2, 0, "?vecName...?",},
-    {"variable", 1, (Blt_Op)VariableOp, 2, 3, "?varName?",},
-};
-
-static int nInstOps = sizeof(vectorInstOps) / sizeof(Blt_OpSpec);
-
-int
-Blt_VectorInstCmd(clientData, interp, objc, objv)
-    ClientData clientData;
-    Tcl_Interp *interp;
-    int objc;
-    Tcl_Obj *CONST *objv;
-{
-    Blt_Op proc;
-    VectorObject *vPtr = clientData;
-
-    vPtr->first = 0;
-    vPtr->last = vPtr->length - 1;
-    proc = Blt_GetOpFromObj(interp, nInstOps, vectorInstOps, BLT_OP_ARG1, objc,
-       objv, 0);
-    if (proc == NULL) {
-       return TCL_ERROR;
-    }
-    return (*proc) (vPtr, interp, objc, objv);
-}
-
-\f
-/*
- * ----------------------------------------------------------------------
- *
- * Blt_VectorVarTrace --
- *
- * Results:
- *     Returns NULL on success.  Only called from a variable trace.
- *
- * Side effects:
- *
- * ----------------------------------------------------------------------
- */
-char *
-Blt_VectorVarTrace(clientData, interp, part1, part2, flags)
-    ClientData clientData;     /* Vector object. */
-    Tcl_Interp *interp;
-    char *part1, *part2;
-    int flags;
-{
-    Blt_VectorIndexProc *indexProc;
-    VectorObject *vPtr = clientData;
-    int first, last;
-    int varFlags;
-#define MAX_ERR_MSG    1023
-    static char message[MAX_ERR_MSG + 1];
-
-    if (part2 == NULL) {
-       if (flags & TCL_TRACE_UNSETS) {
-           Blt_Free(vPtr->arrayName);
-           vPtr->arrayName = NULL;
-           vPtr->varNsPtr = NULL;
-           if (vPtr->freeOnUnset) {
-               Blt_VectorFree(vPtr);
-           }
-       }
-       return NULL;
-    }
-    if (Blt_VectorGetIndexRange(interp, vPtr, part2,
-        INDEX_ALL_FLAGS|INDEX_VAR_TRACE, &indexProc) != TCL_OK) {
-            if (strcmp(part2, "active") == 0 || !strcmp(part2, "#TEST KEY#")) {
-            /* TkTable stores these cells. */
-            return TCL_OK;
-        }                    
-       goto error;
-    }
-    first = vPtr->first, last = vPtr->last;
-    varFlags = TCL_LEAVE_ERR_MSG | (TCL_GLOBAL_ONLY & flags);
-    if (flags & TCL_TRACE_WRITES) {
-       double value;
-       Tcl_Obj *objPtr;
-
-       if (first == SPECIAL_INDEX) { /* Tried to set "min" or "max" */
-           if (indexProc != NULL) {
-                return "read-only index";
-            } else {
-                return TCL_OK;
-            }
-       }
-       objPtr = Tcl_GetVar2Ex(interp, part1, part2, varFlags);
-       if (objPtr == NULL) {
-           goto error;
-       }
-       if (!strlen(Tcl_GetString(objPtr))) {
-           value = 0.0;
-       } else if (GetDouble(interp, objPtr, &value) != TCL_OK) {
-           if ((last == first) && (first >= 0)) {
-               /* Single numeric index. Reset the array element to
-                * its old value on errors */
-               Tcl_SetVar2Ex(interp, part1, part2, objPtr, varFlags);
-           }
-           goto error;
-       }
-       if (first == vPtr->length) {
-           if (Blt_VectorChangeLength(vPtr, vPtr->length + 1) != TCL_OK) {
-               return "error resizing vector";
-           }
-       }
-       /* Set possibly an entire range of values */
-       ReplicateValue(vPtr, first, last, value);
-    } else if (flags & TCL_TRACE_READS) {
-       double value;
-       Tcl_Obj *objPtr;
-
-       if (first == SPECIAL_INDEX && indexProc == NULL) {
-             return TCL_OK;
-       }
-       if (vPtr->length == 0) {
-           if (Tcl_SetVar2(interp, part1, part2, "", varFlags) == NULL) {
-               goto error;
-           }
-           return NULL;
-       }
-       if  (first == vPtr->length) {
-           return "write-only index";
-       }
-       if (first == last) {
-           if (first >= 0) {
-               value = vPtr->valueArr[first];
-           } else {
-               vPtr->first = 0, vPtr->last = vPtr->length - 1;
-               value = (*indexProc) ((Blt_Vector *) vPtr);
-           }
-           objPtr = Tcl_NewDoubleObj(value);
-           if (Tcl_SetVar2Ex(interp, part1, part2, objPtr, varFlags) == NULL) {
-               Tcl_DecrRefCount(objPtr);
-               goto error;
-           }
-       } else {
-           objPtr = GetValues(vPtr, first, last);
-           if (Tcl_SetVar2Ex(interp, part1, part2, objPtr, varFlags) == NULL) {
-               Tcl_DecrRefCount(objPtr);
-               goto error;
-           }
-       }
-    } else if (flags & TCL_TRACE_UNSETS) {
-       register int i, j;
-
-       if ((first == vPtr->length) || (first == SPECIAL_INDEX)) {
-           return "special vector index";
-       }
-         if (vPtr->numcols>1) {
-             return NULL;
-         } else {
-             /*
-             * Collapse the vector from the point of the first unset element.
-             * Also flush any array variable entries so that the shift is
-             * reflected when the array variable is read.
-             */
-             for (i = first, j = last + 1; j < vPtr->length; i++, j++) {
-                 vPtr->valueArr[i] = vPtr->valueArr[j];
-             }
-             vPtr->length -= ((last - first) + 1);
-             if (vPtr->flush) {
-                 Blt_VectorFlushCache(vPtr);
-             }
-       }
-    } else {
-       return "unknown variable trace flag";
-    }
-    if (flags & (TCL_TRACE_UNSETS | TCL_TRACE_WRITES)) {
-       Blt_VectorUpdateClients(vPtr);
-    }
-    Tcl_ResetResult(interp);
-    return NULL;
-
- error: 
-    strncpy(message, Tcl_GetStringResult(interp), MAX_ERR_MSG);
-    message[MAX_ERR_MSG] = '\0';
-    return message;
-}
-
-#endif /* TCL_MAJOR_VERSION > 7 */