Next: Display objects
Up: Function and Class
Previous: Utility functions
The following objects are useful utility objects used throughout the
program. Items which have a specific section listed for them are
explained in detail in that section.
Table 6.1: VMD
utility objects.
A template class implementing a doubly linked list. This can be used to
provide an arbitrary linked list of any type, which also has a built-in
iterator.
- listItems -- number of items in this linked list
- DLink<T> *head, *tail, *curr -- pointers to the positions
in the linked list
- int num(void) -- return number of items in the list.
- int is_current(void) -- returns a flag indicating if there
is a current item, or if the current item is 'undefined'.
- append(const T&) -- appends the given item to the end of
the list. A copy of the item of type T is made.
- remove(void) -- removes the current item (does nothing if
there is no current item).
- T current(void) -- returns a copy of the current item.
- T item(int) -- returns a copy of the Nth item.
- T get(void) -- returns a copy of the current item, and
advances the current item pointer to the next item.
- next(void) -- advance the current item pointer.
- prev(void) -- move back the current item pointer.
- set(int) -- make the Nth item the current item.
- int find(const T&) -- change the current item to be the first
one which matches the argument, or does nothing if no items match. Returns
TRUE if a match was found.
- reset(void) -- set the current item to be the first one.
- clear(void) -- set the current item pointer to be NULL, i.e.
so that is_current() will return FALSE.
This is a template, so a new linked list is created as follows:
DLinkList<int> intLinkedList;
Once created, new items can be added or removed, and the list may
be iterated through by the use of reset, get, next, and prev routines.
A streams-like utility object used to format messages for display at
the console or other selectable ostream object. Messages are
given to an Inform
object via insertion operators ( <<),
and the messages are printed out to a provided ostream device,
prefixed by a certain string. A special manipulator `sendmsg' is
used to signal when a mesage should be printed.
Each Inform
object has a current `message level', which is also
indicated when the messages are printed out. Routines are provided to
set the current level of the Inform
object, so that only messages
with a level smaller than or equal to the current output level are
printed. Levels range from 1 (most likely to be printed) to 10 (very
unlikely to be printed). The main use of this feature in VMD
is
in conjunction with debugging messages, where the level of debugging
information can be changed via text commands.
There are four global instances of Inform
which are available
to the entire program (as long as they include the file Inform.h):
- msgInfo -- Generally informative messages.
- msgWarn -- Special warning messages, which do not signal
an error but warn of some possible problem with the current state.
- msgErr -- Error messages.
- msgDebug -- Debugging messages. The macro MSGDEBUG()
exists which should be used when printing messages to msgDebug; if the
macro VMDDEBUG is set during compilation, the debugging messages
will be included in the executable. An example of use:
MSGDEBUG("This is a debug message" << sendmsg)
- Inform::(char *name, int ison=1)
The name argument is the name of the instance of this object; when
messages are printed out they are profixed with the name, the
message level, and a right paren, i.e.
Info 1) Info message.
The `ison' argument determines if messages should be printed or
not at the start. Besides the message levels, each Inform object can
be on or off. When off, message are not printed, otherwise they are if
the message level is set properly.
Inform
contains several manipulators used to determine how the
message is printed or to do actions. They are:
- sendmsg -- used to signal that the message is complete, and
should be printed. So, this should be that last item inserted into the
Inform
stream.
- level1 ... level10 -- sets the output level of the current
message to X, where X is the digit at the end of this name (1 ... 10).
- char *name -- name of the instance. Used to print message
prefix.
- ostrstream *msg -- character stream used to hold the message
string to be printed.
- ostream *msgDest -- destination stream, where the message will
be printed. This could be the console (cout), or also a file.
- int On -- whether the object should print out its messages.
- int needNewline -- before the message is actually printed,
sometimes a newline must be printed, and sometimes not. This flag tells
whether to print a newline. Once a message is printed, this flag is
cleared. The member function need_newline may be used to set
this flag.
- int outputLevel -- the current output message level of the
instance. This level is compared with the level of the message currently
being requested to be printed; if the level of the message is less than
or equal to the current message level of the Inform
object, then
the message is printed, otherwise it is just ignored.
- int msgLevel -- the current output level of the message that
is to be printed. This may be changed anytime during the construction of
the message; the level at the time when the request to print the message
is made is the one used.
- void on(int) -- set the object to be on or off.
- int on(void) -- return the current on/off status.
- output_level(int) -- set the current output level.
- int output_level(void) -- return current output level of the
Inform
object.
- msg_level(int) -- set the current level of the next message
to be printed.
- int msg_level(void) -- return the current message output level.
- void need_newline(int) -- set the current flag for whether a
newline is needed or not.
- int need_newline(void) -- return current newline print status.
- void destination(ostream *) -- give the provided destination
stream to the Inform
object as a place where to print messages.
- ostream *destination(void) -- return destination to where
messages will be printed.
- send(void) -- prints the contents of the current message buffer
to the destination stream, if necessary.
- operator<<(various types) -- overloaded insertion operators
which are used to put data into the current message buffer. These are
used just like regular stream insertion operators, and when the message
is complete, either the routine send should be called, or else
the sendmsg manipulator should be inserted into the stream. Newline
characters may be put in the stream, Inform
will print out each
newline-separated line with the proper prefix.
As stated, there are four global instances of Inform
which should be
used for printing all messages in VMD
. They are used just like a stream,
except the manipulator sendmsg is used instead of endl to
signal that the string should be printed. An example:
msgWarn << level3 << "This is a level-3 warning." << sendmsg;
In this case, if msgWarn is on, and it's output level is greater than
or equal to 3, then this message will be printed, otherwise it will be
ignored.
For debugging messages (printed to msgDebug), make sure to use the
MSGDEBUG macro, so that these debugging messages can be conditionally
excluded from the executable.
Right now, only the debug Inform
object takes advantage of the
message level facility, all other messages (information, warning, or error)
are all level-1 messages. More messages should be printed out by VMD
,
but at different levels of verbosity and content, and text commands should
be put in to control the current output level of msgInfo, msgWarn,
and msgErr.
Text commands should be added to allow the message text to be sent to a
file, or to the console (right now, they are always sent to the console).
This would not be very difficult, a new text command would need to be
added which would open a file, and call the destination routine with
the respective ostream pointer.
This is a template class which implements a simple associative array.
A NameList
consists of N items, where each item has a name, an index,
and an associated data value (the type of which is determined by the type
given to the template).
- ResizeArray<char *> names -- the array of names, each of which
has a data value associated with it.
- ResizeArray<T> Data -- the data associated with each name. The
size of this array is the same as the size of names.
- ResizeArray<int> sortedOrder -- an array of integers which
indicates the sorted order for the names array. It is the same
length as names and Data.
- int Num -- the number of items in these lists.
- int num(void) -- return number of items in the NameList
.
- int add_name(char *, const T&) -- adds a new name to the
list, with the given data of type T associated with it. This returns the
index (also called typecode) of the name in the list. If the name
already exists in the list, this just returns to index of the existing
name, and does not change the data stored.
- char *name(int) -- return the name of the Nth item.
- char *sort_name(int) -- return the name of the Nth sorted item,
i.e. the Nth highest name when they are put in sorted order.
- int typecode(char *, int = -1) -- return the index for the given
name. If the second argument is greater than 0, it is used as the max
length of the names to check for a match. If it is negative, an exact
match must be found. If no match is found, this returns -1.
- int sort_typecode(int) -- return the actual index of the Nth
sorted item.
- T data(char *, int = -1) -- return a copy of the data for
the given name, in the same way as for typecode(char *, int).
- T data(int) -- return the data for the Nth item.
- void set_data(int, const T&) -- changes the data value
associated with the Nth name to the given value.
This is a template used to associate sets of data of any type with character
strings (names). Names and data are added with add_name, and
the other routines are used to query info about these names. Many objects
in VMD
use NameList
s, for example the colors are all stored this way.
A template class which implements a dynamically-growing, automatically
resizing array of data of a given type. Elements in the array may be
accessed via the [] operator. When new data is added to the end of an
array, the size of the array is automatically increased if necessary.
A ResizeArray
has two sizes that are important:
- The internal size, which is currently allocated size of the
array. This is almost always larger than the total number of items
stored in the array. A larger-than-necessary buffer is kept so that
data may be easily put at the end of the array without having to always
reallocate and copy the existing array storage.
- The external size, which is the largest index in the array
which has been accessed by the user (either by reading from that index,
or writing a value at that index. This is what the user would consider
the `size' of the array.
- ResizeArray::(int = 10, float = 2.0)
The first argument is the initial internal size of the array, i.e. the
initial number of elements for which to allocate memory (although the
initial external size of the array will be zero). The second argument
is the resizing factor: when an element of the array beyond the
size the internal array is accessed, the array will be made larger by
multiplying the current internal size by the rescaling factor. This
must be larger than 1.
- T *data -- the current array of data, which will be made
larger as the array grows.
- int sz -- the internal size of the array.
- float resizeFactor -- factor by which the number of elements
in data is increased when the array grows too large. sz will be
made larger by sz *= resizeFactor.
- int currSize -- the external size of the array, that is, the
largest index into data which has been accessed. This is always
less than or equal to sz.
- int num(void) -- return the external size of the array.
- T& item(int N) -- return (as an lvalue) the Nth item in the
array. If N is larger than the internal size of the array, the size of
the array will be automatically increased by the current resize factor.
- T& operator[](int N) -- same as item, just a nicer
form (this really makes it look like a regular array. In fact, you can
have 2D and 3D resizing arrays by using this operator, and declaring
a template of a template).
- int append(const T&) -- append the given data at the end of
the array, resizing it if necessary. Returns the index of the item.
- int insert_after(int, const T&) -- inserts the given data in
the location following the given index. If the given index is less than
0, this puts the item at the beginning of the array. If the given index
is larger than the external size, this puts the item at the end of the
array. Returns the index of the item.
- int insert_before(int, const T&) -- inserts the given data in
the location just before the given index. If the given index is less than
0, this puts the item at the beginning of the array. If the given index
is larger than the external size, this puts the item at the end of the
array. Returns the index of the item.
- void remove(int M= -1, int N= -1) -- removes the items with
index M ... N, with all items in array positions below this region moved
up to fill the resulting hole. If both arguments are negative, this
removes ALL the array items. If the second argument is negative, only
item M is removed.
- int find(const T&) -- scans the array for an element which
matches the given argument, and returns the index of the first matching
item found. If no match is found, this returns -1.
A ResizeArray
is created by specifying the type of data to store, i.e.
ResizeArray<char *> stringArray;
Once created, it looks just like an array, and you can use the [] operator
to get and set data. For example:
stringArray[3] = "Some text.";
or
cout << stringArray[3] << endl;
A template class which implements a simple stack of arbitrary data.
Items are pushed onto and popped off of the stack, or may just be
copied from the stack.
- Stack::(int s)
The argument s is the maximum size of the stack.
- T *data -- array storing the actual data in the stack.
- T *curr -- pointer to the current 'top' item in the stack.
- int sz -- maximum number of items which the stack can hold.
- int items -- current number of items on the stack.
- int stack_size(void) -- return number of items on the stack.
- int num(void) -- same as stack_size().
- push(const T&) -- copies the given item onto the top of the
stack, moving all other items down one.
- push(void) -- moves all items down one, keeping a copy of the
previous top item on the top of the stack.
- T& pop(void) -- returns the top item on the stack, while also
removing it and moving all the other items up one.
- t& top(void) -- returns a reference to the top of the stack,
but does not change anything.
You instantiate a stack by telling it how large it can grow, and then just
push and pop data on/off the stack. If the stack gets too large or small,
warning messagea are printed.
The Timer
class is used for timing various aspects of VMD
. It is
modeled after the CMMD_node_timers implemented on the CM5.
Each Timer
object is an accumulator that accumulates time whenever
started. A Timer
can be started and stopped multiple times, accumulating
the total time from each cycle. Timer
's can also be cleared to
set the accumulated time to zero. Each Timer
tracks clock time,
user cpu time, system cpu time, and total cpu time.
On the HPs and SGIs, these functions are based on the library routines
times() and gettimeofday().
- void start() -- Start the Timer
accumulating time.
- void stop() -- Stop the Timer
from accumulating time.
- void clear() -- Clear the accumulated time for the Timer
.
- float clock_time() -- Get the accumulated clock time for
the Timer
.
- float user_time() -- Get the accumulated user CPU time.
- float system_time() -- Get the accumulated system CPU time.
- float cpu_time() -- Get the accumulated CPU time.
This is user_time() + system_time().
The functions start(), stop(), and clear()
are used to start, stop and clear a Timer
. The functions
clock_time(), cpu_time(), user_time(),
and system_time() are used to report the current values
of a Timer
.
As example, to time both the total time to complete a loop and
each iteration of the loop, the following code could be used:
Timer total_time;
Timer iter_time;
total_time.start();
while ( . . .)
{
iter_time.start();
. . .
iter_time.stop();
printf("ITERATION TOOK %f secondsn", iter_time.clock_time());
iter_time.clear();
}
total_time.stop();
printf("TOTAL TIME %f secondsn", total_time.clock_time());
Next: Display objects
Up: Function and Class
Previous: Utility functions
Andrew Dalke
Wed May 15 02:25:03 CDT 1996